diff --git a/.circleci/config.yml b/.circleci/config.yml index e7916074b..d8ac4b995 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -25,6 +25,13 @@ jobs: - run: name: Add i386 arch command: dpkg --add-architecture i386 + - run: + name: Add STJr PPA + command: | + apt-get -qq update + apt-get -qq -y install dirmngr + apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 0B1702D71499D9C25F986507F240F4449D3B0EC6 + echo "deb http://ppa.launchpad.net/stjr/srb2/ubuntu trusty main" >> /etc/apt/sources.list - run: name: Update APT listing command: apt-get -qq update @@ -36,15 +43,15 @@ jobs: - v1-SRB2-APT - run: name: Install SDK - command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libcurl4-openssl-dev:i386 gettext ccache wget gcc-multilib upx openssh-client + command: apt-get -qq -y --no-install-recommends install git build-essential nasm libpng-dev:i386 libsdl2-mixer-dev:i386 libgme-dev:i386 libcurl4-openssl-dev:i386 libopenmpt-dev:i386 gettext ccache wget gcc-multilib upx openssh-client - save_cache: key: v1-SRB2-APT paths: - /var/cache/apt/archives - checkout - run: - name: Compile without network support and BLUA - command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1 NO_LUA=1 + name: Compile without network support + command: make -C src LINUX=1 ERRORMODE=1 -k NONET=1 - run: name: wipe build command: make -C src LINUX=1 cleandep diff --git a/.gitattributes b/.gitattributes index d45620912..7751149ac 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,12 @@ +#Source code +/src/*.c text=auto +/src/*.h text=auto +/src/*.s text=auto +/src/*.m text=auto +/src/*.xpm text=auto +/src/Makefile text=auto +/src/Make*.cfg text=auto +/src/CMakeLists.txt text=auto # Windows EOL *.cs -crlf -whitespace *.mk -crlf -whitespace diff --git a/.travis.yml b/.travis.yml index 663498901..9abe8ee2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,11 +18,14 @@ matrix: - os: linux addons: apt: + sources: + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-4.4 @@ -33,11 +36,14 @@ matrix: - os: linux addons: apt: + sources: + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-4.6 @@ -48,11 +54,14 @@ matrix: - os: linux addons: apt: + sources: + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-4.7 @@ -70,11 +79,13 @@ matrix: apt: sources: - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-4.8 @@ -87,11 +98,13 @@ matrix: apt: sources: - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-7 @@ -104,11 +117,13 @@ matrix: apt: sources: - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-8 @@ -125,11 +140,13 @@ matrix: apt: sources: - llvm-toolchain-precise-3.5 + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - clang-3.5 @@ -142,11 +159,13 @@ matrix: sources: - llvm-toolchain-precise-3.6 - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - clang-3.6 @@ -159,11 +178,13 @@ matrix: sources: - llvm-toolchain-precise-3.7 - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - clang-3.7 @@ -176,11 +197,13 @@ matrix: sources: - llvm-toolchain-precise-3.8 - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - clang-3.8 @@ -193,11 +216,13 @@ matrix: sources: - llvm-toolchain-precise-3.9 - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - clang-3.9 @@ -210,11 +235,13 @@ matrix: # sources: # - llvm-toolchain-precise-4.0 # - ubuntu-toolchain-r-test +# - sourceline: 'ppa:stjr/srb2' # packages: # - libsdl2-mixer-dev # - libpng-dev # - libgl1-mesa-dev # - libgme-dev +# - libopenmpt-dev # - p7zip-full # - clang-4.0 # compiler: clang-4.0 @@ -226,11 +253,13 @@ matrix: # sources: # - llvm-toolchain-precise-5.0 # - ubuntu-toolchain-r-test +# - sourceline: 'ppa:stjr/srb2' # packages: # - libsdl2-mixer-dev # - libpng-dev # - libgl1-mesa-dev # - libgme-dev +# - libopenmpt-dev # - p7zip-full # - clang-5.0 # compiler: clang-5.0 @@ -442,11 +471,15 @@ matrix: - os: linux addons: apt: + sources: + - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-4.8 @@ -457,20 +490,52 @@ matrix: AND env(DPL_TERMINATE_MAIN) != "1" env: - _DPL_JOB_ENABLED=1 - - _DPL_JOB_NAME=focal + - _DPL_JOB_NAME=eoan - _DPL_DPUT_TARGET=1 - _DPL_PACKAGE_SOURCE=1 - - PACKAGE_DISTRO=focal - - PACKAGE_SUBVERSION=~20.04focal + - PACKAGE_DISTRO=eoan + - PACKAGE_SUBVERSION=~19.10eoan #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 - os: linux addons: apt: + sources: + - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev + - libcurl4-openssl-dev + - p7zip-full + - gcc-4.8 + compiler: gcc-4.8 + dist: xenial + if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1") + AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1")) + AND env(DPL_TERMINATE_MAIN) != "1" + env: + - _DPL_JOB_ENABLED=1 + - _DPL_JOB_NAME=disco + - _DPL_DPUT_TARGET=1 + - _DPL_PACKAGE_SOURCE=1 + - PACKAGE_DISTRO=disco + - PACKAGE_SUBVERSION=~19.04disco + #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 + - os: linux + addons: + apt: + sources: + - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' + packages: + - libsdl2-mixer-dev + - libpng-dev + - libgl1-mesa-dev + - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-4.8 @@ -490,16 +555,20 @@ matrix: - os: linux addons: apt: + sources: + - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-4.8 compiler: gcc-4.8 - dist: xenial + dist: trusty if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1") AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1")) AND env(DPL_TERMINATE_MAIN) != "1" @@ -514,11 +583,15 @@ matrix: - os: linux addons: apt: + sources: + - ubuntu-toolchain-r-test + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full - gcc-4.8 @@ -535,30 +608,6 @@ matrix: - PACKAGE_DISTRO=trusty - PACKAGE_SUBVERSION=~14.04trusty #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 - - os: linux - addons: - apt: - packages: - - libsdl2-mixer-dev - - libpng-dev - - libgl1-mesa-dev - - libgme-dev - - libcurl4-openssl-dev - - p7zip-full - - gcc-4.8 - compiler: gcc-4.8 - dist: xenial - if: env(DPL_ENABLED) = "1" AND (env(_DPL_JOB_ENABLED) = "1" OR env(DPL_JOB_ENABLE_ALL) = "1") - AND (branch =~ /^.*deployer.*$/ OR (tag IS present AND env(DPL_TAG_ENABLED) = "1")) - AND env(DPL_TERMINATE_MAIN) != "1" - env: - - _DPL_JOB_ENABLED=1 - - _DPL_JOB_NAME=eoan - - _DPL_DPUT_TARGET=1 - - _DPL_PACKAGE_SOURCE=1 - - PACKAGE_DISTRO=eoan - - PACKAGE_SUBVERSION=~19.10eoan - #gcc-4.8 (Ubuntu 4.8.5-2ubuntu1~14.04.1) 4.8.5 allow_failures: - compiler: clang-3.5 - compiler: clang-3.6 @@ -578,12 +627,15 @@ cache: addons: apt: + sources: + - sourceline: 'ppa:stjr/srb2' packages: - libsdl2-mixer-dev - libpng-dev - libgl1-mesa-dev - libgme-dev - zlib1g-dev + - libopenmpt-dev - libcurl4-openssl-dev - p7zip-full homebrew: @@ -593,6 +645,7 @@ addons: - sdl2_mixer - game-music-emu - p7zip + - libopenmpt - cmake - curl update: true diff --git a/CMakeLists.txt b/CMakeLists.txt index 831db96c9..39ad80698 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,14 +1,34 @@ cmake_minimum_required(VERSION 3.0) + +# Enable CCache early +set(SRB2_USE_CCACHE OFF CACHE BOOL "Use CCache") +if (${SRB2_USE_CCACHE}) + find_program(CCACHE_PROGRAM ccache) + if(CCACHE_PROGRAM) + message(STATUS "Found CCache: ${CCACHE_PROGRAM}") + set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") + else() + message(WARNING "You have specified to use CCACHE but it was not found. Object files will not be cached.") + endif() +endif() + +file(STRINGS src/version.h SRB2_VERSION) +string(REGEX MATCH "[0-9]+\\.[0-9.]+" SRB2_VERSION ${SRB2_VERSION}) + # DO NOT CHANGE THIS SRB2 STRING! Some variable names depend on this string. # Version change is fine. project(SRB2 - VERSION 2.0 + VERSION ${SRB2_VERSION} LANGUAGES C) if(${PROJECT_SOURCE_DIR} MATCHES ${PROJECT_BINARY_DIR}) message(FATAL_ERROR "In-source builds will bring you a world of pain. Please make a separate directory to invoke CMake from.") endif() +if ((${SRB2_USE_CCACHE}) AND (${CMAKE_C_COMPILER} MATCHES "clang")) + message(WARNING "Using clang and CCache: You may want to set environment variable CCACHE_CPP2=yes to prevent include errors during compile.") +endif() + # Set up CMAKE path set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") @@ -95,7 +115,6 @@ set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") # Set EXE names so the assets CMakeLists can refer to its target set(SRB2_SDL2_EXE_NAME srb2kart CACHE STRING "Executable binary output name") -set(SRB2_WIN_EXE_NAME srb2kartdd CACHE STRING "Executable binary output name for DirectDraw build") include_directories(${CMAKE_CURRENT_BINARY_DIR}/src) @@ -114,16 +133,19 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in ${CMAKE_CURRENT_BINAR ##### PACKAGE CONFIGURATION ##### -if(${CMAKE_SYSTEM} MATCHES "Windows") - set(CPACK_GENERATOR "ZIP") -endif() -if(${CMAKE_SYSTEM} MATCHES "Linux") - set(CPACK_GENERATOR "TGZ") -endif() -if(${CMAKE_SYSTEM} MATCHES "Darwin") - set(CPACK_GENERATOR "DragNDrop") +set(SRB2_CPACK_GENERATOR "" CACHE STRING "Generator to use for making a package. E.g., ZIP, TGZ, DragNDrop (OSX only). Leave blank for default generator.") + +if("${SRB2_CPACK_GENERATOR}" STREQUAL "") + if(${CMAKE_SYSTEM} MATCHES "Windows") + set(SRB2_CPACK_GENERATOR "ZIP") + elseif(${CMAKE_SYSTEM} MATCHES "Linux") + set(SRB2_CPACK_GENERATOR "TGZ") + elseif(${CMAKE_SYSTEM} MATCHES "Darwin") + set(SRB2_CPACK_GENERATOR "TGZ") + endif() endif() +set(CPACK_GENERATOR ${SRB2_CPACK_GENERATOR}) set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Sonic Robo Blast 2 Kart" CACHE STRING "Program name for display purposes") set(CPACK_PACKAGE_VENDOR "Kart Krew" CACHE STRING "Vendor name for display purposes") #set(CPACK_PACKAGE_DESCRIPTION_FILE ) @@ -132,4 +154,5 @@ set(CPACK_PACKAGE_VERSION_MAJOR ${SRB2_VERSION_MAJOR}) set(CPACK_PACKAGE_VERSION_MINOR ${SRB2_VERSION_MINOR}) set(CPACK_PACKAGE_VERSION_PATCH ${SRB2_VERSION_PATCH}) set(CPACK_PACKAGE_INSTALL_DIRECTORY "CMake ${CMAKE_VERSION_MAJOR}.${CMAKE_VERSION_MINOR}") +SET(CPACK_OUTPUT_FILE_PREFIX package) include(CPack) diff --git a/Doxyfile b/Doxyfile index d11fa2bbc..eb8c6ae9e 100644 --- a/Doxyfile +++ b/Doxyfile @@ -109,13 +109,10 @@ FILE_PATTERNS = *.c \ *.mm \ *.dox RECURSIVE = YES -EXCLUDE = ./src/djgppdos/internal.h \ - ./src/djgppdos/setup.c \ - ./src/sdl/IMG_xpm.c \ +EXCLUDE = ./src/sdl/IMG_xpm.c \ ./src/sdl/SRB2DC/scramble.c EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = */src/hardware/*/* \ - */src/djgppdos/bcd.? \ */src/sdl/SDL_main/* \ */src/*/*_private.h \ */src/sdl/*/*help.? \ diff --git a/README.md b/README.md index 5a8c98329..7fe87ca71 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ - SDL2-Mixer (Linux/OS X only) - libupnp (Linux/OS X only) - libgme (Linux/OS X only) +- libopenmpt (Linux/OS X only) ## Compiling diff --git a/appveyor.yml b/appveyor.yml index 53a534c50..aa7a4c7cd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -72,7 +72,7 @@ install: configuration: - SDL -#- SDL64 +- SDL64 before_build: - set "Path=%MINGW_SDK%\bin;%Path%" @@ -110,8 +110,8 @@ after_build: - set BUILDSARCHIVE=%REPO%-%CONFIGURATION%.7z - cmd: 7z a %BUILD_ARCHIVE% %BUILD_PATH% -xr!.gitignore - appveyor PushArtifact %BUILD_ARCHIVE% -- cmd: copy %BUILD_ARCHIVE% %BUILDSARCHIVE% -- appveyor PushArtifact %BUILDSARCHIVE% +#- cmd: copy %BUILD_ARCHIVE% %BUILDSARCHIVE% +#- appveyor PushArtifact %BUILDSARCHIVE% ############################## # DEPLOYER SCRIPT ############################## diff --git a/assets/CMakeLists.txt b/assets/CMakeLists.txt index e5cfa5ca2..a8f4cac5c 100644 --- a/assets/CMakeLists.txt +++ b/assets/CMakeLists.txt @@ -12,6 +12,13 @@ ENDFUNCTION(PREPEND) set(SRB2_ASSET_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/installer" CACHE STRING "Path to directory that contains all asset files for the installer.") +set(SRB2_ASSET_INSTALL ON + CACHE BOOL "Insert asset files into the install directory or package.") + +#################### +# POST-V2.2 NOTE: Do not forget to add patch.pk3 to the end of this list! +#################### + set(SRB2_ASSET_HASHED "main.kart;\ gfx.pk3;\ @@ -26,7 +33,8 @@ set(SRB2_ASSET_DOCS "README.txt;\ HISTORY.txt;\ LICENSE.txt;\ -LICENSE-3RD-PARTY.txt" +LICENSE-3RD-PARTY.txt;\ +README-SDL.txt" CACHE STRING "Documentation filenames. In OS X, these are packaged separately from other assets. No spaces between entries!" ) @@ -41,20 +49,27 @@ endforeach() if(${CMAKE_SYSTEM} MATCHES Darwin) get_target_property(outname SRB2SDL2 OUTPUT_NAME) - install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/" - DESTINATION "${outname}.app/Contents/Resources" - ) + if(${SRB2_ASSET_INSTALL}) + install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/" + DESTINATION "${outname}.app/Contents/Resources" + ) + endif() + # Always install the doc files, even in non-asset packages. install(FILES ${SRB2_ASSET_DOCS} DESTINATION . OPTIONAL ) else() - install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/" - DESTINATION . - ) - # Docs are assumed to be located in SRB2_ASSET_DIRECTORY, so don't install again - #install(FILES ${SRB2_ASSET_DOCS} - # DESTINATION . - # OPTIONAL - #) + if(${SRB2_ASSET_INSTALL}) + install(DIRECTORY "${SRB2_ASSET_DIRECTORY}/" + DESTINATION . + ) + # Docs are assumed to be located in SRB2_ASSET_DIRECTORY, so don't install them in their own call. + else() + # Always install the doc files, even in non-asset packages. + install(FILES ${SRB2_ASSET_DOCS} + DESTINATION . + OPTIONAL + ) + endif() endif() diff --git a/assets/README.txt b/assets/README.txt index e8e21a842..678871725 100644 --- a/assets/README.txt +++ b/assets/README.txt @@ -46,12 +46,12 @@ SRB2 Message Board: https://mb.srb2.org SRB2 Official Discord: -https://discord.gg/pYDXzpX +https://discord.gg/pYDXzpX (13+) COPYRIGHT AND DISCLAIMER -Design and content on SRB2Kart is copyright 2018 by Kart Krew. -Design and content on SRB2 is copyright 1998-2018 by Sonic Team Junior. +Design and content on SRB2Kart is copyright 2020 by Kart Krew. +Design and content on SRB2 is copyright 1998-2020 by Sonic Team Junior. All non-original material on SRB2.ORG is copyrighted by their respective owners, and no copyright infringement is intended. The owner of the SRB2.ORG domain is only acting as an ISP, and is therefore not diff --git a/bin/DC/.gitignore b/bin/DC/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/DC/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/Dos/Debug/.gitignore b/bin/Dos/Debug/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/Dos/Debug/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/Dos/Release/.gitignore b/bin/Dos/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/Dos/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/PS3/Debug/.gitignore b/bin/PS3/Debug/.gitignore deleted file mode 100644 index c4dcd19e5..000000000 --- a/bin/PS3/Debug/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/*.elf -/*.self -/*.pkg -/*.BIN -/pkg diff --git a/bin/PS3/Release/.gitignore b/bin/PS3/Release/.gitignore deleted file mode 100644 index c4dcd19e5..000000000 --- a/bin/PS3/Release/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -/*.elf -/*.self -/*.pkg -/*.BIN -/pkg diff --git a/bin/PSP/Release/.gitignore b/bin/PSP/Release/.gitignore deleted file mode 100644 index 98d08e695..000000000 --- a/bin/PSP/Release/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/EBOOT.PBP -/PARAM.SFO -/SRB2PSP.PBP -/SRB2PSP.elf diff --git a/bin/Wii/Debug/.gitignore b/bin/Wii/Debug/.gitignore deleted file mode 100644 index 200eea51f..000000000 --- a/bin/Wii/Debug/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/*.elf -/*.dol -/apps diff --git a/bin/Wii/Release/.gitignore b/bin/Wii/Release/.gitignore deleted file mode 100644 index 200eea51f..000000000 --- a/bin/Wii/Release/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/*.elf -/*.dol -/apps diff --git a/bin/WinCE/ARMV4Dbg/.gitignore b/bin/WinCE/ARMV4Dbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/ARMV4Dbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/ARMV4IDbg/.gitignore b/bin/WinCE/ARMV4IDbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/ARMV4IDbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/ARMV4IRel/.gitignore b/bin/WinCE/ARMV4IRel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/ARMV4IRel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/ARMV4Rel/.gitignore b/bin/WinCE/ARMV4Rel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/ARMV4Rel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/ARMV4TDbg/.gitignore b/bin/WinCE/ARMV4TDbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/ARMV4TDbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/ARMV4TRel/.gitignore b/bin/WinCE/ARMV4TRel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/ARMV4TRel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPS16Dbg/.gitignore b/bin/WinCE/MIPS16Dbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPS16Dbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPS16Rel/.gitignore b/bin/WinCE/MIPS16Rel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPS16Rel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPSIIDbg/.gitignore b/bin/WinCE/MIPSIIDbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPSIIDbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPSIIRel/.gitignore b/bin/WinCE/MIPSIIRel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPSIIRel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPSII_FPDbg/.gitignore b/bin/WinCE/MIPSII_FPDbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPSII_FPDbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPSII_FPRel/.gitignore b/bin/WinCE/MIPSII_FPRel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPSII_FPRel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPSIVDbg/.gitignore b/bin/WinCE/MIPSIVDbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPSIVDbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPSIVRel/.gitignore b/bin/WinCE/MIPSIVRel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPSIVRel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPSIV_FPDbg/.gitignore b/bin/WinCE/MIPSIV_FPDbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPSIV_FPDbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/MIPSIV_FPRel/.gitignore b/bin/WinCE/MIPSIV_FPRel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/MIPSIV_FPRel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/Release/.gitignore b/bin/WinCE/Release/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/Release/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/SH3Dbg/.gitignore b/bin/WinCE/SH3Dbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/SH3Dbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/SH3Rel/.gitignore b/bin/WinCE/SH3Rel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/SH3Rel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/SH4Dbg/.gitignore b/bin/WinCE/SH4Dbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/SH4Dbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/SH4Rel/.gitignore b/bin/WinCE/SH4Rel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/SH4Rel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/X86Dbg/.gitignore b/bin/WinCE/X86Dbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/X86Dbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/X86Rel/.gitignore b/bin/WinCE/X86Rel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/X86Rel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/emulatorDbg/.gitignore b/bin/WinCE/emulatorDbg/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/emulatorDbg/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/WinCE/emulatorRel/.gitignore b/bin/WinCE/emulatorRel/.gitignore deleted file mode 100644 index 42c6dc2c6..000000000 --- a/bin/WinCE/emulatorRel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# DON'T REMOVE -# This keeps the folder from disappearing diff --git a/bin/nds/Debug/.gitignore b/bin/nds/Debug/.gitignore deleted file mode 100644 index 9bfc4a51d..000000000 --- a/bin/nds/Debug/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.arm9 -*.elf* -*.nds diff --git a/bin/nds/Release/.gitignore b/bin/nds/Release/.gitignore deleted file mode 100644 index 9bfc4a51d..000000000 --- a/bin/nds/Release/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -*.arm9 -*.elf* -*.nds diff --git a/cmake/Modules/FindDiscordRPC.cmake b/cmake/Modules/FindDiscordRPC.cmake new file mode 100644 index 000000000..e71762767 --- /dev/null +++ b/cmake/Modules/FindDiscordRPC.cmake @@ -0,0 +1,23 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(DISCORDRPC_PKGCONF DISCORDRPC) + +find_path(DISCORDRPC_INCLUDE_DIR + NAMES discord_rpc.h + PATHS + ${DISCORDRPC_PKGCONF_INCLUDE_DIRS} + "/usr/include" + "/usr/local/include" +) + +find_library(DISCORDRPC_LIBRARY + NAMES discord-rpc + PATHS + ${DISCORDRPC_PKGCONF_LIBRARY_DIRS} + "/usr/lib" + "/usr/local/lib" +) + +set(DISCORDRPC_PROCESS_INCLUDES DISCORDRPC_INCLUDE_DIR) +set(DISCORDRPC_PROCESS_LIBS DISCORDRPC_LIBRARY) +libfind_process(DISCORDRPC) diff --git a/cmake/Modules/FindOPENMPT.cmake b/cmake/Modules/FindOPENMPT.cmake new file mode 100644 index 000000000..2d334b6f0 --- /dev/null +++ b/cmake/Modules/FindOPENMPT.cmake @@ -0,0 +1,23 @@ +include(LibFindMacros) + +libfind_pkg_check_modules(OPENMPT_PKGCONF OPENMPT) + +find_path(OPENMPT_INCLUDE_DIR + NAMES libopenmpt.h + PATHS + ${OPENMPT_PKGCONF_INCLUDE_DIRS} + "/usr/include/libopenmpt" + "/usr/local/include/libopenmpt" +) + +find_library(OPENMPT_LIBRARY + NAMES openmpt + PATHS + ${OPENMPT_PKGCONF_LIBRARY_DIRS} + "/usr/lib" + "/usr/local/lib" +) + +set(OPENMPT_PROCESS_INCLUDES OPENMPT_INCLUDE_DIR) +set(OPENMPT_PROCESS_LIBS OPENMPT_LIBRARY) +libfind_process(OPENMPT) \ No newline at end of file diff --git a/cmake/launch-c.in b/cmake/launch-c.in new file mode 100644 index 000000000..c60558232 --- /dev/null +++ b/cmake/launch-c.in @@ -0,0 +1,3 @@ +#!/bin/sh +export CCACHE_CPP2=true +exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$@" diff --git a/cmake/launch-cxx.in b/cmake/launch-cxx.in new file mode 100644 index 000000000..c60558232 --- /dev/null +++ b/cmake/launch-cxx.in @@ -0,0 +1,3 @@ +#!/bin/sh +export CCACHE_CPP2=true +exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$@" diff --git a/debian-template/control b/debian-template/control index 4db1d8752..532d78abe 100644 --- a/debian-template/control +++ b/debian-template/control @@ -11,6 +11,7 @@ Build-Depends: debhelper (>= 7.0.50~), zlib1g-dev, libgme-dev, libcurl4-openssl-dev, + libopenmpt-dev, libglu1-dev | libglu-dev, libosmesa6-dev | libgl-dev, nasm [i386] @@ -26,6 +27,7 @@ Depends: ${SHLIBS_DEPENDS}, ${MISC_DEPENDS}, zlib1g, libgme0, libcurl4, + libopenmpt | libopenmpt0, libpng | libpng16-16 | libpng12-0 Description: A cross-platform 3D Sonic fangame Sonic Robo Blast 2 is a 3D open-source Sonic the Hedgehog diff --git a/deployer/travis/deployer_defaults.sh b/deployer/travis/deployer_defaults.sh index 9b853a80a..fd1d83cb2 100644 --- a/deployer/travis/deployer_defaults.sh +++ b/deployer/travis/deployer_defaults.sh @@ -29,8 +29,8 @@ # Asset File Parameters : ${ASSET_ARCHIVE_PATH:=https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-assets.7z} : ${ASSET_ARCHIVE_OPTIONAL_PATH:=https://github.com/mazmazz/Kart-Public/releases/download/kart_assets/srb2kart-v102-optional-assets.7z} -: ${ASSET_FILES_HASHED:=srb2.srb patch.kart gfx.kart textures.kart chars.kart maps.kart} -: ${ASSET_FILES_DOCS:=README.txt HISTORY.txt LICENSE.txt LICENSE-3RD-PARTY.txt} +: ${ASSET_FILES_HASHED:=main.kart chars.pk3 gfx.pk3 maps.pk3 textures.pk3 patch.pk3} +: ${ASSET_FILES_DOCS:=README.txt HISTORY.txt LICENSE.txt LICENSE-3RD-PARTY.txt README-SDL.txt} : ${ASSET_FILES_OPTIONAL_GET:=0} # FTP Parameters @@ -51,24 +51,24 @@ # Package Parameters : ${PACKAGE_NAME:=srb2kart} -: ${PACKAGE_VERSION:=1.0.2} +: ${PACKAGE_VERSION:=2.0} : ${PACKAGE_SUBVERSION} # Highly recommended to set this to reflect the distro series target (e.g., ~18.04bionic) : ${PACKAGE_REVISION} # Defaults to UTC timestamp : ${PACKAGE_INSTALL_PATH:=/usr/games/SRB2Kart} : ${PACKAGE_LINK_PATH:=/usr/games} : ${PACKAGE_DISTRO:=trusty} : ${PACKAGE_URGENCY:=high} -: ${PACKAGE_NAME_EMAIL:=Kart Krew } -: ${PACKAGE_GROUP_NAME_EMAIL:=Kart Krew } +: ${PACKAGE_NAME_EMAIL:=Kart Krew } +: ${PACKAGE_GROUP_NAME_EMAIL:=Kart Krew } : ${PACKAGE_WEBSITE:=} -: ${PACKAGE_ASSET_MINVERSION:=1.0.1} # Number this the version BEFORE the actual required version, because we do a > check -: ${PACKAGE_ASSET_MAXVERSION:=1.0.3} # Number this the version AFTER the actual required version, because we do a < check +: ${PACKAGE_ASSET_MINVERSION:=1.2} # Number this the version BEFORE the actual required version, because we do a > check +: ${PACKAGE_ASSET_MAXVERSION:=2.1} # Number this the version AFTER the actual required version, because we do a < check : ${PROGRAM_NAME:=Sonic Robo Blast 2 Kart} : ${PROGRAM_VENDOR:=Kart Krew} -: ${PROGRAM_VERSION:=1.0.2} -: ${PROGRAM_DESCRIPTION:=A kart racing mod based on the 3D Sonic the Hedgehog fangame Sonic Robo Blast 2.} +: ${PROGRAM_VERSION:=2.0} +: ${PROGRAM_DESCRIPTION:=Go go-karting with Dr. Eggman!} : ${PROGRAM_FILENAME:=srb2kart} : ${DPL_PGP_KEY_PRIVATE} # Base64-encoded private key file. Used to sign Debian packages diff --git a/extras/conf/SRB2Kart2.cfg b/extras/conf/SRB2Kart2.cfg new file mode 100644 index 000000000..3d715ada6 --- /dev/null +++ b/extras/conf/SRB2Kart2.cfg @@ -0,0 +1,6226 @@ +/*********************************************************\ + vim: ai + Zone Builder Game Configuration + For SRB2Kart Version 2.0 + Based on the Configuration for Sonic Robo Blast 2 Version 2.1 + Contributors (alphabetical): + * Foxboy + * JJames19119 + * Kalaron + * Kristos + * MascaraSnake + * Morpheus + * Neo Chaotikal + * Oogaland + * Rob + * Shadow Hog + * SRB2-Playah + * SSNTails + * ST218 + * toaster + * Viola +\*********************************************************/ + +// This is required to prevent accidental use of a different configuration +type = "Doom Builder 2 Game Configuration"; + +// This is the title to show for this game +game = "SRB2Jart v2.0"; + +//GZDB specific. Don't try to load lumps that don't exist. +basegame = 0; + +// This is the simplified game engine/sourceport name +engine = "zdoom"; + +// When this is set to true, sectors with the same tag will light up when a line is highlighted +linetagindicatesectors = true; + +// The format interface handles the map data format - DoomMapSetIO for SRB2DB2, SRB2MapSetIO for Zone Builder +formatinterface = "SRB2MapSetIO"; + +//Sky textures for vanilla maps +defaultskytextures +{ + SKY1 = "MAP42,MAPB2,MAPBL,MAPH6,MAPHE"; + SKY2 = "MAP11"; + SKY4 = "MAPB4"; + SKY6 = "MAP19,MAPBH"; + SKY8 = "MAP12,MAP22,MAP40,MAPBC,MAPH3,MAPH9,MAPHA"; + SKY11 = "MAP04"; + SKY12 = "MAP39"; + SKY13 = "MAP21"; + SKY17 = "MAP24"; + SKY21 = "MAPH8"; + SKY22 = "MAPBG"; + SKY28 = "MAP35"; + SKY30 = "MAP49,MAPH1"; + SKY31 = "MAP23"; + SKY40 = "MAP48"; + SKY41 = "MAP52,MAPBQ"; + SKY42 = "MAP51,MAPBN"; + SKY45 = "MAP55,MAPBO,MAPBP"; + SKY46 = "MAP53,MAPHD"; + SKY52 = "MAP03,MAPBD"; + SKY55 = "MAP17"; + SKY60 = "MAPB1"; + SKY61 = "MAP50"; + SKY70 = "MAP10"; + SKY71 = "MAP27"; + SKY72 = "MAPH2"; + SKY73 = "MAP34"; + SKY74 = "MAP33"; + SKY75 = "MAP25"; + SKY76 = "MAP20"; + SKY77 = "MAP28"; + SKY78 = "MAPH5"; + SKY87 = "MAPB8,MAPH0"; + SKY88 = "MAP01,MAP02,MAP07,MAP08,MAP09,MAP31,MAPB5,MAPBR,MAPBS"; + SKY91 = "MAP05,MAPB0,MAPBJ"; + SKY93 = "MAPBM"; + SKY117 = "MAP13,MAP32"; + SKY118 = "MAPB9"; + SKY190 = "MAP16,MAP18"; + SKY357 = "MAP46"; + SKY371 = "MAPHF"; + SKY700 = "MAP47"; + SKY714 = "MAP41"; + SKY715 = "MAP45"; + SKY821 = "MAP29,MAPBB"; + SKY1012 = "MAPBA"; + SKY1017 = "MAP14,MAP15"; + SKY1019 = "MAPHB"; + SKY2002 = "MAP44,MAPB3,MAPH4"; + SKY2432 = "MAPHC"; + SKY2517 = "MAP37"; + SKY3262 = "MAP38"; + SKY3388 = "MAP43"; + SKY3753 = "MAP26"; + SKY4733 = "MAPB7"; + SKY6343 = "MAP54"; + SKY7492 = "MAP06"; +} + +// Default lump name for new map +defaultlumpname = "MAP01"; + +// Default testing parameters +testparameters = "-file \"%AP\" \"%F\" -warp %L"; +testshortpaths = true; + +// Default nodebuilder configurations +defaultsavecompiler = "zennode_normal"; +defaulttestcompiler = "zennode_fast"; + +// Skill levels +skills +{ + 1 = "Normal"; +} + +// Skins +skins +{ + Sonic; + Tails; + Knuckles; + Amy; + Mighty; + Ray; + Eggman; + MetalSonic; + Fang; +} + +// Gametypes +gametypes +{ + -1 = "Single Player"; + 0 = "Race"; + 1 = "Battle"; +} + +// Special linedefs +soundlinedefflag = 64; // See linedefflags +singlesidedflag = 1; // See linedefflags +doublesidedflag = 4; // See linedefflags +impassableflag = 1; +upperunpeggedflag = 8; +lowerunpeggedflag = 16; +repeatmidtextureflag = 1024; +pegmidtextureflag = 256; + +// Generalized actions +generalizedlinedefs = false; +generalizedsectors = true; + +// Texture loading options +defaultwalltexture = "GFZROCK"; +defaultfloortexture = "GFZFLR01"; +defaultceilingtexture = "F_SKY1"; +mixtexturesflats = false; +defaulttexturescale = 1.0f; +defaultflatscale = 1.0f; + +// Thing number for start position in 3D Mode +start3dmode = 3328; + + + + +/* +TEXTURES AND FLAT SOURCES +This tells Doom Builder where to find the information for textures +and flats in the IWAD file, Addition WAD file and Map WAD file. + +Start and end lumps must be given in a structure (of which the +key name doesnt matter) and any textures or flats in between them +are loaded in either the textures category or flats category. + +For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. +Kalaron: and now TX_START +*/ + +// Texture sources +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +// Patch sources +patches +{ + standard1 + { + start = "P_START"; + end = "P_END"; + } + + standard2 + { + start = "PP_START"; + end = "PP_END"; + } +} + +// Sprite sources +sprites +{ + standard1 + { + start = "S_START"; + end = "S_END"; + } + + standard2 + { + start = "SS_START"; + end = "SS_END"; + } +} + +// Flat sources +flats +{ + standard1 + { + start = "F_START"; + end = "F_END"; + } + + standard2 + { + start = "FF_START"; + end = "FF_END"; + } + + standard3 + { + start = "FF_START"; + end = "F_END"; + } + + standard4 + { + start = "F_START"; + end = "FF_END"; + } +} + + +/* +GAME DETECT PATTERN +Used to guess the game for which a WAD file is made. + +1 = One of these lumps must exist +2 = None of these lumps must exist +3 = All of these lumps must exist +*/ + +gamedetect +{ + EXTENDED = 2; + + + BEHAVIOR = 2; + + E#M# = 2; + + MAP?? = 1; +} + + +/* +MAP LUMP NAMES +Map lumps are loaded with the map as long as they are right after each other. When the editor +meets a lump which is not defined in this list it will ignore the map if not satisfied. +The order of items defines the order in which lumps will be written to WAD file on save. +To indicate the map header lump, use ~MAP + +Legenda: +required = Lump is required to exist. +blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) +nodebuild = The nodebuilder generates this lump. +allowempty = The nodebuilder is allowed to leave this lump empty. +script = This lump is a text-based script. Specify the filename of the script configuration to use. +*/ + +maplumpnames +{ + ~MAP + { + required = true; + blindcopy = true; + nodebuild = false; + } + + THINGS + { + required = true; + nodebuild = true; + allowempty = true; + } + + LINEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + SIDEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + VERTEXES + { + required = true; + nodebuild = true; + allowempty = false; + } + + SEGS + { + required = false; + nodebuild = true; + allowempty = false; + } + + SSECTORS + { + required = false; + nodebuild = true; + allowempty = false; + } + + NODES + { + required = false; + nodebuild = true; + allowempty = false; + } + + SECTORS + { + required = true; + nodebuild = true; + allowempty = false; + } + + REJECT + { + required = false; + nodebuild = true; + allowempty = false; + } + + BLOCKMAP + { + required = false; + nodebuild = true; + allowempty = true; + } +} + +scriptlumpnames +{ + MAINCFG + { + script = "SOC.cfg"; + } + + OBJCTCFG + { + script = "SOC.cfg"; + } + + SOC_ + { + script = "SOC.cfg"; + isprefix = true; + } + + LUA_ + { + script = "Lua.cfg"; + isprefix = true; + } +} + +// DEFAULT SECTOR BRIGHTNESS LEVELS +sectorbrightness +{ + 255; + 248; + 240; + 232; + 224; + 216; + 208; + 200; + 192; + 184; + 176; + 168; + 160; + 152; + 144; + 136; + 128; + 120; + 112; + 104; + 96; + 88; + 80; + 72; + 64; + 56; + 48; + 40; + 32; + 24; + 16; + 8; + 0; +} + +// SECTOR TYPES----------------------------------------------------------------- +sectortypes +{ + 0 = "Normal"; + 1 = "Damage"; + 2 = "Offroad (Weak)"; + 3 = "Offroad"; + 4 = "Offroad (Strong)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + //9 = "Ring Drainer (Floor Touch)"; + //10 = "Ring Drainer (Anywhere in Sector)"; + //11 = "Special Stage Damage"; + 12 = "Wall Sector (no step-up/down)"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + //96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (Race Lap)"; + 128 = "Check for Linedef Executor on FOFs"; + //144 = "Egg Capsule"; + //160 = "Special Stage Time/Rings Parameters"; + 176 = "Custom Global Gravity"; + 192 = "Invert Encore Remap"; + 256 = "Spring Panel"; + 512 = "Wind/Current"; + 768 = "Spring Panel (Speed Capped)"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + //1536 = "Speed Pad (Spin)"; + 1792 = "Bustable Block Sprite Parameter (ROIA)"; + 2048 = "Bustable Block Sprite Parameter (ROIB)"; + 2304 = "Bustable Block Sprite Parameter (ROIC)"; + 2560 = "Bustable Block Sprite Parameter (ROID)"; + 2816 = "Bustable Block Sprite Parameter (ROIE)"; + 3072 = "Bustable Block Sprite Parameter (ROIF)"; + 3328 = "Bustable Block Sprite Parameter (ROIG)"; + 3584 = "Bustable Block Sprite Parameter (ROIH)"; + 3840 = "Bustable Block Sprite Parameter (ROII)"; + 4096 = "Star Post Activator"; + 8192 = "Exit Level"; + //12288 = "CTF Red Team Base"; + //16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Sneaker Panel"; + //28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line (Unused)"; + //45056 = "Rope Hang"; + //49152 = "Intangible to the Camera"; +} + + +// GENERALISED SECTOR TYPES----------------------------------------------------------------- +gen_sectortypes +{ + first + { + 0 = "Normal"; + 1 = "Damage"; + 2 = "Offroad (Weak)"; + 3 = "Offroad"; + 4 = "Offroad (Strong)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + //9 = "Ring Drainer (Floor Touch)"; + //10 = "Ring Drainer (Anywhere in Sector)"; + //11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 15 = "Bouncy FOF"; + } + + second + { + 0 = "Normal"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (Race Lap)"; + 128 = "Check for Linedef Executor on FOFs"; + //144 = "Egg Capsule"; + //160 = "Special Stage Time/Rings Parameters"; + 176 = "Custom Global Gravity"; + 192 = "Invert Encore Remap"; + } + + third + { + 0 = "Normal"; + 256 = "Spring Panel"; + 512 = "Wind/Current"; + 768 = "Spring Panel (Speed Capped)"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + //1536 = "Speed Pad (Spin)"; + 1792 = "Bustable Block Sprite Parameter (ROIA)"; + 2048 = "Bustable Block Sprite Parameter (ROIB)"; + 2304 = "Bustable Block Sprite Parameter (ROIC)"; + 2560 = "Bustable Block Sprite Parameter (ROID)"; + 2816 = "Bustable Block Sprite Parameter (ROIE)"; + 3072 = "Bustable Block Sprite Parameter (ROIF)"; + 3328 = "Bustable Block Sprite Parameter (ROIG)"; + 3584 = "Bustable Block Sprite Parameter (ROIH)"; + 3840 = "Bustable Block Sprite Parameter (ROII)"; + } + + fourth + { + 0 = "Normal"; + 4096 = "Star Post Activator"; + 8192 = "Exit Level"; + //12288 = "CTF Red Team Base"; + //16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Sneaker Panel"; + //28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line (Unused)"; + //45056 = "Rope Hang"; + //49152 = "Intangible to the Camera"; + } +} + +// LINEDEF FLAGS +linedefflags +{ + 1 = "[0] Impassable"; + 2 = "[1] Block Players"; + 4 = "[2] Double-Sided"; + 8 = "[3] Upper Unpegged"; + 16 = "[4] Lower Unpegged"; + 32 = "[5] Slope Skew (E1)"; + 64 = "[6] Not Climbable"; + 128 = "[7] No Midtexture Skew (E2)"; + 256 = "[8] Peg Midtexture (E3)"; + 512 = "[9] Solid Midtexture (E4)"; + 1024 = "[10] Repeat Midtexture (E5)"; + 2048 = "[11] No Sonic"; + 4096 = "[12] No Tails"; + 8192 = "[13] No Knuckles"; + 16384 = "[14] Bouncy Wall"; + 32768 = "[15] Transfer Line"; +} + +// Linedef flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +linedefflagstranslation +{ + 1 = "blocking"; + 2 = "blockmonsters"; + 4 = "twosided"; + 8 = "dontpegtop"; + 16 = "dontpegbottom"; + 32 = "secret"; + 64 = "blocksound"; + 128 = "dontdraw"; + 256 = "mapped"; +} + +// LINEDEF ACTIVATIONS +linedefactivations +{ +} + +// LINEDEF TYPES +linedeftypes +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + + 1 + { + title = "Per-Sector Gravity"; + prefix = "(1)"; + flags64text = "[6] Flip in reverse gravity"; + } + + 4 + { + title = "Speed Pad"; + prefix = "(4)"; + flags512text = "[9] No teleport to center"; + } + + 5 + { + title = "Camera Scanner"; + prefix = "(5)"; + } + + 6 + { + title = "Disable Linedef Effect on Level Load"; + prefix = "(6)"; + } + + 7 + { + title = "Sector Flat Alignment"; + prefix = "(7)"; + flags64text = "[6] Align only floor"; + flags2text = "[1] Align only ceiling"; + flags512text = "[9] Rotate flats"; + flags16384text = "[14] Rotate only floor"; + flags1024text = "[10] Rotate only ceiling"; + } + + 10 + { + title = "Culling Plane"; + prefix = "(10)"; + flags64text = "[6] Cull only while in sector"; + } + + 13 + { + title = "Heat Wave Effect"; + prefix = "(13)"; + } + + 40 + { + title = "Visual Portal Between Tagged Linedefs"; + prefix = "(40)"; + } + + 50 + { + title = "Instantly Lower Floor on Level Load"; + prefix = "(50)"; + } + + 51 + { + title = "Instantly Raise Ceiling on Level Load"; + prefix = "(51)"; + } + + 63 + { + title = "Fake Floor/Ceiling Planes"; + prefix = "(63)"; + } + + 80 + { + title = "Offset Tagged Things from Frontside FOF"; + prefix = "(80)"; + } + + 540 + { + title = "Floor Friction"; + prefix = "(540)"; + } + } + + parameters + { + title = "Parameters"; + + 2 + { + title = "Custom Exit"; + prefix = "(2)"; + flags2text = "[1] Check emeralds"; + flags64text = "[6] Skip score tally"; + } + + 3 + { + title = "Zoom Tube Parameters"; + prefix = "(3)"; + flags512text = "[9] Ignore player direction"; + } + + 8 + { + title = "Special Sector Properties"; + prefix = "(8)"; + flags64text = "[6] Touch only ceiling"; + flags256text = "[8] Touch sector edge"; + flags512text = "[9] Touch floor or ceiling"; + } + + 9 + { + title = "Chain Parameters"; + prefix = "(9)"; + flags64text = "[6] Fixed spinning direction"; + } + + 11 + { + title = "Rope Hang Parameters"; + prefix = "(11)"; + flags32text = "[5] Don't loop"; + flags64text = "[6] Static"; + } + + 12 + { + title = "Rock Spawner Parameters"; + prefix = "(12)"; + flags64text = "[6] Randomize speed"; + } + + 64 + { + title = "Continuously Appearing/Disappearing FOF"; + prefix = "(64)"; + flags2text = "[1] Use control sector tag"; + flags64text = "[6] No sound effect"; + } + + 65 + { + title = "Bridge Thinker "; + prefix = "(65)"; + } + } + + polyobject + { + title = "PolyObject"; + + 20 + { + title = "First Line"; + prefix = "(20)"; + flags64text = "[6] Trigger linedef executor"; + flags128text = "[7] Intangible"; + flags256text = "[8] Stopped by pushables"; + flags512text = "[9] Render flats"; + } + + 21 + { + title = "Explicitly Include Line"; + prefix = "(21)"; + } + + 22 + { + title = "Parameters"; + prefix = "(22)"; + } + + 30 + { + title = "Waving Flag"; + prefix = "(30)"; + } + + 31 + { + title = "Displacement by Front Sector"; + prefix = "(31)"; + } + } + + planemove + { + title = "Plane Movement"; + + 52 + { + title = "Continuously Falling Sector"; + prefix = "(52)"; + flags64text = "[6] Continuously rising"; + } + + 53 + { + title = "Continuous Floor/Ceiling Mover"; + prefix = "(53)"; + } + + 54 + { + title = "Continuous Floor Mover"; + prefix = "(54)"; + } + + 55 + { + title = "Continuous Ceiling Mover"; + prefix = "(55)"; + } + + 56 + { + title = "Continuous Two-Speed Floor/Ceiling Mover"; + prefix = "(56)"; + } + + 57 + { + title = "Continuous Two-Speed Floor Mover"; + prefix = "(57)"; + } + + 58 + { + title = "Continuous Two-Speed Ceiling Mover"; + prefix = "(58)"; + } + + 59 + { + title = "Activate Moving Platform"; + prefix = "(59)"; + flags64text = "[6] Move upwards at start"; + } + + 60 + { + title = "Activate Moving Platform (Adjustable Speed)"; + prefix = "(60)"; + flags64text = "[6] Move upwards at start"; + } + + 61 + { + title = "Crusher (Ceiling to Floor)"; + prefix = "(61)"; + flags512text = "[9] Double, constant speed"; + } + + 62 + { + title = "Crusher (Floor to Ceiling)"; + prefix = "(62)"; + flags512text = "[9] Double, constant speed"; + } + } + + fofsolid + { + title = "FOF (solid)"; + + 100 + { + title = "Solid, Opaque"; + prefix = "(100)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 101 + { + title = "Solid, Opaque, No Shadow"; + prefix = "(101)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 102 + { + title = "Solid, Translucent"; + prefix = "(102)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Render insides"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "195F"; + flags643dfloorflagsadd = "7C80"; + } + + 103 + { + title = "Solid, Sides Only"; + prefix = "(103)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1CF"; + } + + 104 + { + title = "Solid, No Sides"; + prefix = "(104)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1D7"; + flags643dfloorflagsremove = "40"; + } + + 105 + { + title = "Solid, Invisible"; + prefix = "(105)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 140 + { + title = "Intangible from Bottom, Opaque"; + prefix = "(140)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 141 + { + title = "Intangible from Bottom, Translucent"; + prefix = "(141)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "200191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 142 + { + title = "Intangible from Bottom, Translucent, No Sides"; + prefix = "(142)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "2001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 143 + { + title = "Intangible from Top, Opaque"; + prefix = "(143)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "400841F"; + flags643dfloorflagsadd = "40"; + } + + 144 + { + title = "Intangible from Top, Translucent"; + prefix = "(144)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "400191F"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 145 + { + title = "Intangible from Top, Translucent, No Sides"; + prefix = "(145)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Render insides/block non-plr"; + 3dfloor = true; + 3dfloorflags = "4001917"; + flags1283dfloorflagsadd = "7C80"; + flags643dfloorflagsadd = "40"; + } + + 146 + { + title = "Only Tangible from Sides"; + prefix = "(146)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "600800F"; + } + } + + fofintangible + { + title = "FOF (intangible)"; + + 120 + { + title = "Water, Opaque"; + prefix = "(120)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "8F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 121 + { + title = "Water, Translucent"; + prefix = "(121)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "9F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 122 + { + title = "Water, Opaque, No Sides"; + prefix = "(122)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 123 + { + title = "Water, Translucent, No Sides"; + prefix = "(123)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 124 + { + title = "Goo Water, Translucent"; + prefix = "(124)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "209F39"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 125 + { + title = "Goo Water, Translucent, No Sides"; + prefix = "(125)"; + flags64text = "[6] Use two light levels"; + flags512text = "[9] Use target light level"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "201F31"; + flags643dfloorflagsadd = "20000"; + flags5123dfloorflagsadd = "80000000"; + flags10243dfloorflagsadd = "40000000"; + } + + 220 + { + title = "Intangible, Opaque"; + prefix = "(220)"; + 3dfloor = true; + 3dfloorflags = "8F19"; + } + + 221 + { + title = "Intangible, Translucent"; + prefix = "(221)"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "1B59"; + flags643dfloorflagsremove = "40"; + } + + 222 + { + title = "Intangible, Sides Only"; + prefix = "(222)"; + flags64text = "[6] Cast shadow"; + 3dfloor = true; + 3dfloorflags = "8249"; + flags643dfloorflagsremove = "240"; + } + + 223 + { + title = "Intangible, Invisible"; + prefix = "(223)"; + 3dfloor = true; + 3dfloorflags = "41"; + } + } + + fofmoving + { + title = "FOF (moving)"; + + 150 + { + title = "Air Bobbing"; + prefix = "(150)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 151 + { + title = "Air Bobbing (Adjustable)"; + prefix = "(151)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 152 + { + title = "Reverse Air Bobbing (Adjustable)"; + prefix = "(152)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 160 + { + title = "Floating, Bobbing"; + prefix = "(160)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "4019F"; + } + + 190 + { + title = "Rising Platform, Solid, Opaque"; + prefix = "(190)"; + flags2text = "[1] Sink when stepped on"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 191 + { + title = "Rising Platform, Solid, Opaque, No Shadow"; + prefix = "(191)"; + flags2text = "[1] Sink when stepped on"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1DF"; + } + + 192 + { + title = "Rising Platform, Solid, Translucent"; + prefix = "(192)"; + flags2text = "[1] Sink when stepped on"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "195F"; + } + + 193 + { + title = "Rising Platform, Solid, Invisible"; + prefix = "(193)"; + flags2text = "[1] Sink when stepped on"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "47"; + } + + 194 + { + title = "Rising Platform, Intangible from Bottom, Opaque"; + prefix = "(194)"; + flags2text = "[1] Sink when stepped on"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "200841F"; + flags643dfloorflagsadd = "40"; + } + + 195 + { + title = "Rising Platform, Intangible from Bottom, Translucent"; + prefix = "(195)"; + flags2text = "[1] Sink when stepped on"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash, no shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "2009D1F"; + flags643dfloorflagsadd = "40"; + } + } + + fofcrumbling + { + title = "FOF (crumbling)"; + + 170 + { + title = "Crumbling, Respawn"; + prefix = "(170)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + + 171 + { + title = "Crumbling, No Respawn"; + prefix = "(171)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "80019F"; + } + + 172 + { + title = "Crumbling, Respawn, Intangible from Bottom"; + prefix = "(172)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210841F"; + flags643dfloorflagsadd = "40"; + } + + 173 + { + title = "Crumbling, No Respawn, Intangible from Bottom"; + prefix = "(173)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218841F"; + flags643dfloorflagsadd = "40"; + } + + 174 + { + title = "Crumbling, Respawn, Int. from Bottom, Translucent"; + prefix = "(174)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "210959F"; + flags643dfloorflagsadd = "40"; + } + + 175 + { + title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; + prefix = "(175)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Don't cast shadow"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "218959F"; + flags643dfloorflagsadd = "40"; + } + + 176 + { + title = "Crumbling, Respawn, Floating, Bobbing"; + prefix = "(176)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 177 + { + title = "Crumbling, No Respawn, Floating, Bobbing"; + prefix = "(177)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 178 + { + title = "Crumbling, Respawn, Floating"; + prefix = "(178)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "14019F"; + } + + 179 + { + title = "Crumbling, No Respawn, Floating"; + prefix = "(179)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "1C019F"; + } + + 180 + { + title = "Crumbling, Respawn, Air Bobbing"; + prefix = "(180)"; + flags32text = "[5] Only block player"; + flags64text = "[6] Spindash to move"; + flags128text = "[7] Only block non-players"; + 3dfloor = true; + 3dfloorflags = "10019F"; + } + } + + fofspecial + { + title = "FOF (special)"; + + 200 + { + title = "Light Block"; + prefix = "(200)"; + 3dfloor = true; + 3dfloorflags = "20201"; + } + + 201 + { + title = "Half Light Block"; + prefix = "(201)"; + 3dfloor = true; + 3dfloorflags = "201"; + } + + 202 + { + title = "Fog Block"; + prefix = "(202)"; + 3dfloor = true; + 3dfloorflags = "3EF19"; + } + + 250 + { + title = "Mario Block"; + prefix = "(250)"; + 3dfloor = true; + 3dfloorflags = "40019F"; + } + + 251 + { + title = "Thwomp Block"; + prefix = "(251)"; + flags512text = "[9] Custom crushing sound"; + flags1024text = "[10] Custom speed"; + 3dfloor = true; + 3dfloorflags = "19F"; + } + + 252 + { + title = "Shatter Block"; + prefix = "(252)"; + flags64text = "[6] Shatter only from below"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "8800019"; + flags643dfloorflagsadd = "200006"; + } + + 253 + { + title = "Shatter Block, Translucent"; + prefix = "(253)"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "8801019"; + } + + 254 + { + title = "Bustable Block"; + prefix = "(254)"; + flags64text = "[6] Only bustable by Knuckles"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "80001F"; + flags643dfloorflagsadd = "20000000"; + } + + 255 + { + title = "Spin-Bustable Block"; + prefix = "(255)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080001F"; + } + + 256 + { + title = "Spin-Bustable Block, Translucent"; + prefix = "(256)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorflags = "1080101F"; + } + + 257 + { + title = "Quicksand"; + prefix = "(257)"; + flags1024text = "[10] Ripple effect"; + 3dfloor = true; + 3dfloorflags = "1008219"; + flags10243dfloorflagsadd = "40000000"; + } + + 258 + { + title = "Laser"; + prefix = "(258)"; + flags32text = "[5] Don't damage bosses"; + 3dfloor = true; + 3dfloorflags = "959"; + } + + 259 + { + title = "Custom FOF"; + prefix = "(259)"; + flags32text = "[5] Only block player"; + flags128text = "[7] Only block non-players"; + flags512text = "[9] Shattered by pushables"; + flags1024text = "[10] Trigger linedef executor"; + 3dfloor = true; + 3dfloorcustom = true; + } + } + + linedeftrigger + { + title = "Linedef Executor Trigger"; + + 300 + { + title = "Continuous"; + prefix = "(300)"; + } + + 301 + { + title = "Each Time"; + prefix = "(301)"; + flags16384text = "[14] Also trigger on exit"; + } + + 302 + { + title = "Once"; + prefix = "(302)"; + } + + 303 + { + title = "Ring Count - Continuous"; + prefix = "(303)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + } + + 304 + { + title = "Ring Count - Once"; + prefix = "(304)"; + flags2text = "[1] Rings greater or equal"; + flags64text = "[6] Rings less or equal"; + flags512text = "[9] Consider all players"; + } + + 305 + { + title = "Character Ability - Continuous"; + prefix = "(305)"; + } + + 306 + { + title = "Character Ability - Each Time"; + prefix = "(306)"; + flags16384text = "[14] Also trigger on exit"; + } + + 307 + { + title = "Character Ability - Once"; + prefix = "(307)"; + } + + 308 + { + title = "Race Only - Once"; + prefix = "(308)"; + } + + 309 + { + title = "CTF Red Team - Continuous"; + prefix = "(309)"; + } + + 310 + { + title = "CTF Red Team - Each Time"; + prefix = "(310)"; + flags16384text = "[14] Also trigger on exit"; + } + + 311 + { + title = "CTF Blue Team - Continuous"; + prefix = "(311)"; + } + + 312 + { + title = "CTF Blue Team - Each Time"; + prefix = "(312)"; + flags16384text = "[14] Also trigger on exit"; + } + + 313 + { + title = "No More Enemies - Once"; + prefix = "(313)"; + } + + 314 + { + title = "Number of Pushables - Continuous"; + prefix = "(314)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + } + + 315 + { + title = "Number of Pushables - Once"; + prefix = "(315)"; + flags64text = "[6] Number greater or equal"; + flags512text = "[9] Number less"; + } + + 317 + { + title = "Condition Set Trigger - Continuous"; + prefix = "(317)"; + } + + 318 + { + title = "Condition Set Trigger - Once"; + prefix = "(318)"; + } + + 319 + { + title = "Unlockable - Continuous"; + prefix = "(319)"; + } + + 320 + { + title = "Unlockable - Once"; + prefix = "(320)"; + } + + 321 + { + title = "Trigger After X Calls - Continuous"; + prefix = "(321)"; + flags64text = "[6] Trigger more than once"; + + } + + 322 + { + title = "Trigger After X Calls - Each Time"; + prefix = "(322)"; + flags64text = "[6] Trigger more than once"; + } + + 399 + { + title = "Level Load"; + prefix = "(399)"; + } + } + + linedefexecsector + { + title = "Linedef Executor (sector)"; + + 400 + { + title = "Set Tagged Sector's Floor Height/Texture"; + prefix = "(400)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Keep floor flat"; + } + + 401 + { + title = "Set Tagged Sector's Ceiling Height/Texture"; + prefix = "(401)"; + flags8text = "[3] Set delay by backside sector"; + } + + 402 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(402)"; + flags8text = "[3] Set delay by backside sector"; + } + + 409 + { + title = "Change Tagged Sector's Tag"; + prefix = "(409)"; + flags8text = "[3] Set delay by backside sector"; + } + + 410 + { + title = "Change Front Sector's Tag"; + prefix = "(410)"; + flags8text = "[3] Set delay by backside sector"; + } + + 416 + { + title = "Start Adjustable Flickering Light"; + prefix = "(416)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 417 + { + title = "Start Adjustable Pulsating Light"; + prefix = "(417)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 418 + { + title = "Start Adjustable Blinking Light (unsynchronized)"; + prefix = "(418)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 419 + { + title = "Start Adjustable Blinking Light (synchronized)"; + prefix = "(419)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Second level from back"; + } + + 420 + { + title = "Fade Light Level"; + prefix = "(420)"; + flags8text = "[3] Set delay by backside sector"; + } + + 421 + { + title = "Stop Lighting Effect"; + prefix = "(421)"; + flags8text = "[3] Set delay by backside sector"; + } + + 435 + { + title = "Change Plane Scroller Direction"; + prefix = "(435)"; + flags8text = "[3] Set delay by backside sector"; + } + } + + linedefexecplane + { + title = "Linedef Executor (plane movement)"; + + 403 + { + title = "Move Tagged Sector's Floor"; + prefix = "(403)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change floor flat"; + } + + 404 + { + title = "Move Tagged Sector's Ceiling"; + prefix = "(404)"; + flags2text = "[1] Trigger linedef executor"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Change ceiling flat"; + } + + 405 + { + title = "Move Floor According to Front Texture Offsets"; + prefix = "(405)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 407 + { + title = "Move Ceiling According to Front Texture Offsets"; + prefix = "(407)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move instantly"; + } + + 411 + { + title = "Stop Plane Movement"; + prefix = "(411)"; + flags8text = "[3] Set delay by backside sector"; + } + + 428 + { + title = "Start Platform Movement"; + prefix = "(428)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Move upwards at start"; + } + + 429 + { + title = "Crush Ceiling Once"; + prefix = "(429)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + + 430 + { + title = "Crush Floor Once"; + prefix = "(430)"; + flags8text = "[3] Set delay by backside sector"; + } + + 431 + { + title = "Crush Floor and Ceiling Once"; + prefix = "(431)"; + flags8text = "[3] Set delay by backside sector"; + flags512text = "[9] Double, constant speed"; + } + } + + linedefexecplayer + { + title = "Linedef Executor (player/object)"; + + 412 + { + title = "Teleporter"; + prefix = "(412)"; + flags2text = "[1] Silent"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Retain angle"; + flags256text = "[8] Relative, silent"; + flags512text = "[9] Retain momentum"; + } + + 425 + { + title = "Change Object State"; + prefix = "(425)"; + flags8text = "[3] Set delay by backside sector"; + } + + 426 + { + title = "Stop Object"; + prefix = "(426)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Teleport to sector center"; + } + + 427 + { + title = "Award Score"; + prefix = "(427)"; + flags8text = "[3] Set delay by backside sector"; + } + + 432 + { + title = "Enable/Disable 2D Mode"; + prefix = "(432)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to 3D"; + } + + 433 + { + title = "Enable/Disable Gravity Flip"; + prefix = "(433)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Return to normal"; + } + + 434 + { + title = "Award Power-Up"; + prefix = "(434)"; + flags2text = "[1] Use back upper texture"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] No time limit"; + } + + 437 + { + title = "Disable Player Control"; + prefix = "(437)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Allow jumping"; + } + + 438 + { + title = "Change Object Size"; + prefix = "(438)"; + flags8text = "[3] Set delay by backside sector"; + } + + 442 + { + title = "Change Object Type State"; + prefix = "(442)"; + flags8text = "[3] Set delay by backside sector"; + } + } + + linedefexecmisc + { + title = "Linedef Executor (misc.)"; + + 413 + { + title = "Change Music"; + prefix = "(413)"; + flags2text = "[1] Keep after death"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + flags512text = "[9] Don't loop"; + } + + 414 + { + title = "Play Sound Effect"; + prefix = "(414)"; + flags2text = "[1] From sector center"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] From nowhere for triggerer"; + flags512text = "[9] For everyone"; + flags1024text = "[10] From tagged sectors"; + } + + 415 + { + title = "Run Script"; + prefix = "(415)"; + flags8text = "[3] Set delay by backside sector"; + } + + 422 + { + title = "Switch to Cut-Away View"; + prefix = "(422)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Adjust pitch"; + } + + 423 + { + title = "Change Sky"; + prefix = "(423)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 424 + { + title = "Change Weather"; + prefix = "(424)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] For everyone"; + } + + 436 + { + title = "Shatter FOF"; + prefix = "(436)"; + flags8text = "[3] Set delay by backside sector"; + } + + 439 + { + title = "Change Tagged Linedef's Textures"; + prefix = "(439)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only existing"; + } + + 440 + { + title = "Start Metal Sonic Race"; + prefix = "(440)"; + flags8text = "[3] Set delay by backside sector"; + } + + 441 + { + title = "Condition Set Trigger"; + prefix = "(441)"; + flags8text = "[3] Set delay by backside sector"; + } + + 443 + { + title = "Call Lua Function"; + prefix = "(443)"; + flags8text = "[3] Set delay by backside sector"; + } + + 444 + { + title = "Earthquake"; + prefix = "(444)"; + flags8text = "[3] Set delay by backside sector"; + } + + + 445 + { + title = "Make FOF Disappear/Reappear"; + prefix = "(445)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Reappear"; + } + + 450 + { + title = "Execute Linedef Executor (specific tag)"; + prefix = "(450)"; + flags8text = "[3] Set delay by backside sector"; + } + + 451 + { + title = "Execute Linedef Executor (random tag in range)"; + prefix = "(451)"; + flags8text = "[3] Set delay by backside sector"; + } + } + + linedefexecpoly + { + title = "Linedef Executor (polyobject)"; + + 480 + { + title = "Door Slide"; + prefix = "(480)"; + flags8text = "[3] Set delay by backside sector"; + } + + 481 + { + title = "Door Swing"; + prefix = "(481)"; + flags8text = "[3] Set delay by backside sector"; + } + + 482 + { + title = "Move"; + prefix = "(482)"; + flags8text = "[3] Set delay by backside sector"; + } + + 483 + { + title = "Move, Override"; + prefix = "(483)"; + flags8text = "[3] Set delay by backside sector"; + } + + 484 + { + title = "Rotate Right"; + prefix = "(484)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 485 + { + title = "Rotate Right, Override"; + prefix = "(485)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 486 + { + title = "Rotate Left"; + prefix = "(486)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 487 + { + title = "Rotate Left, Override"; + prefix = "(487)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Don't turn players"; + flags512text = "[9] Turn all objects"; + } + + 488 + { + title = "Move by Waypoints"; + prefix = "(488)"; + flags8text = "[3] Set delay by backside sector"; + flags32text = "[5] Reverse order"; + flags128text = "[7] There and back"; + flags256text = "[8] Return when done"; + flags512text = "[9] Loop movement"; + } + + 489 + { + title = "Turn Invisible, Intangible"; + prefix = "(489)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only invisible"; + } + + 490 + { + title = "Turn Visible, Tangible"; + prefix = "(490)"; + flags8text = "[3] Set delay by backside sector"; + flags64text = "[6] Only visible"; + } + + 491 + { + title = "Set Translucency"; + prefix = "(491)"; + flags8text = "[3] Set delay by backside sector"; + } + } + + wallscroll + { + title = "Wall Scrolling"; + + 500 + { + title = "Scroll Wall Front Side Left"; + prefix = "(500)"; + } + + 501 + { + title = "Scroll Wall Front Side Right"; + prefix = "(501)"; + } + + 502 + { + title = "Scroll Wall According to Linedef"; + prefix = "(502)"; + } + + 503 + { + title = "Scroll Wall According to Linedef (Accelerative)"; + prefix = "(503)"; + } + + 504 + { + title = "Scroll Wall According to Linedef (Displacement)"; + prefix = "(504)"; + } + + 505 + { + title = "Scroll Texture by Front Side Offsets"; + prefix = "(505)"; + } + + 506 + { + title = "Scroll Texture by Back Side Offsets"; + prefix = "(506)"; + } + + 507 + { + title = "Scroll Front and Back Textures by Offsets"; + prefix = "(507)"; + } + } + + planescroll + { + title = "Plane Scrolling"; + + 510 + { + title = "Scroll Floor Texture"; + prefix = "(510)"; + } + + 511 + { + title = "Scroll Floor Texture (Accelerative)"; + prefix = "(511)"; + } + + 512 + { + title = "Scroll Floor Texture (Displacement)"; + prefix = "(512)"; + } + + 513 + { + title = "Scroll Ceiling Texture"; + prefix = "(513)"; + } + + 514 + { + title = "Scroll Ceiling Texture (Accelerative)"; + prefix = "(514)"; + } + + 515 + { + title = "Scroll Ceiling Texture (Displacement)"; + prefix = "(515)"; + } + + 520 + { + title = "Carry Objects on Floor"; + prefix = "(520)"; + } + + 521 + { + title = "Carry Objects on Floor (Accelerative)"; + prefix = "(521)"; + flags64text = "[6] Even across edges"; + } + + 522 + { + title = "Carry Objects on Floor (Displacement)"; + prefix = "(522)"; + } + + 523 + { + title = "Carry Objects on Ceiling"; + prefix = "(523)"; + flags64text = "[6] Even across edges"; + } + + 524 + { + title = "Carry Objects on Ceiling (Accelerative)"; + prefix = "(524)"; + } + + 525 + { + title = "Carry Objects on Ceiling (Displacement)"; + prefix = "(525)"; + } + + 530 + { + title = "Scroll Floor Texture and Carry Objects"; + prefix = "(530)"; + flags64text = "[6] Even across edges"; + } + + 531 + { + title = "Scroll Floor Texture and Carry Objects (Accelerative)"; + prefix = "(531)"; + } + + 532 + { + title = "Scroll Floor Texture and Carry Objects (Displacement)"; + prefix = "(532)"; + } + + 533 + { + title = "Scroll Ceiling Texture and Carry Objects"; + prefix = "(533)"; + flags64text = "[6] Even across edges"; + } + + 534 + { + title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(534)"; + } + + 535 + { + title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(535)"; + } + } + + pusher + { + title = "Pusher"; + + 541 + { + title = "Wind"; + prefix = "(541)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 542 + { + title = "Upwards Wind"; + prefix = "(542)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 543 + { + title = "Downwards Wind"; + prefix = "(543)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 544 + { + title = "Current"; + prefix = "(544)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 545 + { + title = "Upwards Current"; + prefix = "(545)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 546 + { + title = "Downwards Current"; + prefix = "(546)"; + flags512text = "[9] Player slides"; + flags64text = "[6] Even across edges"; + } + + 547 + { + title = "Push/Pull"; + prefix = "(547)"; + } + } + + light + { + title = "Lighting"; + + 600 + { + title = "Floor Lighting"; + prefix = "(600)"; + } + + 601 + { + title = "Ceiling Lighting"; + prefix = "(601)"; + } + + 602 + { + title = "Adjustable Pulsating Light"; + prefix = "(602)"; + } + + 603 + { + title = "Adjustable Flickering Light"; + prefix = "(603)"; + } + + 604 + { + title = "Adjustable Blinking Light (unsynchronized)"; + prefix = "(604)"; + } + + 605 + { + title = "Adjustable Blinking Light (synchronized)"; + prefix = "(605)"; + } + + 606 + { + title = "Colormap"; + prefix = "(606)"; + } + } + + slope + { + title = "Slope"; + + 700 + { + title = "Slope Frontside Floor"; + prefix = "(700)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Not dynamic"; + slope = "regular"; + slopeargs = 1; + } + + 701 + { + title = "Slope Frontside Ceiling"; + prefix = "(701)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Not dynamic"; + slope = "regular"; + slopeargs = 2; + } + + 702 + { + title = "Slope Frontside Floor and Ceiling"; + prefix = "(702)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Not dynamic"; + slope = "regular"; + slopeargs = 3; + } + + 703 + { + title = "Slope Frontside Floor and Backside Ceiling"; + prefix = "(703)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Not dynamic"; + slope = "regular"; + slopeargs = 9; + } + + 704 + { + title = "Slope Frontside Floor by 3 Tagged Vertex Things"; + prefix = "(704)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 0; + } + + 705 + { + title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; + prefix = "(705)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 1; + } + + 710 + { + title = "Slope Backside Floor"; + prefix = "(710)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Not dynamic"; + slope = "regular"; + slopeargs = 4; + } + + 711 + { + title = "Slope Backside Ceiling"; + prefix = "(711)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Not dynamic"; + slope = "regular"; + slopeargs = 8; + } + + 712 + { + title = "Slope Backside Floor and Ceiling"; + prefix = "(712)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Not dynamic"; + slope = "regular"; + slopeargs = 12; + } + + 713 + { + title = "Slope Backside Floor and Frontside Ceiling"; + prefix = "(713)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Not dynamic"; + slope = "regular"; + slopeargs = 6; + } + + 714 + { + title = "Slope Backside Floor by 3 Tagged Vertex Things"; + prefix = "(714)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 2; + } + + 715 + { + title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; + prefix = "(715)"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Use tag and offsets"; + slope = "vertex"; + slopeargs = 3; + } + + 720 + { + title = "Copy Frontside Floor Slope from Line Tag"; + prefix = "(720)"; + slope = "copy"; + slopeargs = 1; + } + + 721 + { + title = "Copy Frontside Ceiling Slope from Line Tag"; + prefix = "(721)"; + slope = "copy"; + slopeargs = 2; + } + + 722 + { + title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; + prefix = "(722)"; + slope = "copy"; + slopeargs = 3; + } + + 777 + { + title = "Slope Floor by 3 Anchors"; + prefix = "(777)"; + flags64text = "[6] Use backside sector"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Mirror on ceiling"; + } + + 778 + { + title = "Slope Ceiling by 3 Anchors"; + prefix = "(778)"; + flags64text = "[6] Use backside sector"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + flags8192text = "[13] Mirror on floor"; + } + + 779 + { + title = "Slope Floor and Ceiling by 3 Anchors"; + prefix = "(779)"; + flags64text = "[6] Use backside sector"; + flags2048text = "[11] No physics"; + flags4096text = "[12] Dynamic"; + } + + 799 + { + title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; + prefix = "(799)"; + } + } + + transwall + { + title = "Translucent Wall"; + + 900 + { + title = "90% Opaque"; + prefix = "(900)"; + } + + 901 + { + title = "80% Opaque"; + prefix = "(901)"; + } + + 902 + { + title = "70% Opaque"; + prefix = "(902)"; + } + + 903 + { + title = "60% Opaque"; + prefix = "(903)"; + } + + 904 + { + title = "50% Opaque"; + prefix = "(904)"; + } + + 905 + { + title = "40% Opaque"; + prefix = "(905)"; + } + + 906 + { + title = "30% Opaque"; + prefix = "(906)"; + } + + 907 + { + title = "20% Opaque"; + prefix = "(907)"; + } + + 908 + { + title = "10% Opaque"; + prefix = "(908)"; + } + + 909 + { + title = "Fog Wall"; + prefix = "(909)"; + } + } + + derrlines + { + title = "SRB2Kart"; + + 2000 + { + title = "Waypoint Parameters"; + prefix = "(2000)"; + } + + 2001 + { + title = "Finish Line"; + prefix = "(2001)"; + flags64text = "[6] Use backside"; + } + } +} + + +// THING FLAGS +thingflags +{ + 1 = "[1] Extra"; + 2 = "[2] Flip"; + 4 = "[4] Special"; + 8 = "[8] Ambush"; +} + +// Thing flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +thingflagstranslation +{ + 1 = "skill1"; + 2 = "skill2"; + 4 = "skill3"; + 8 = "ambush"; +} + +// THING FLAGS ERROR MASK +// Mask for the thing flags which indicates the options +// that make the same thing appear in the same modes +thingflagsmask1 = 7; // 1 + 2 + 4 +thingflagsmask2 = 0; + + +// THING TYPES------------------------------------------------------------------ +// Color values: 1-Blue 2-Green 3-Cyan 4-Red 5-Magenta 6-Brown 7-Gray +// 8-Dark_Gray 9-Light_Blue 10-Light_Green 11-Light_Cyan 12-Light_Red 13-Pink +// 14-Yellow 15-White +thingtypes +{ + editor + { + color = 15; // White + arrow = 1; + title = ""; + error = -1; + width = 8; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; + } + + starts + { + color = 1; // Blue + arrow = 1; + title = "Player Starts"; + width = 16; + height = 56; + flags8text = "[8] Spawn on ceiling"; + sprite = "SIGNE0"; + + 1 + { + title = "Player 01 Start"; + sprite = "SIGNE0"; + } + 2 + { + title = "Player 02 Start"; + sprite = "SIGNE0"; + } + 3 + { + title = "Player 03 Start"; + sprite = "SIGNE0"; + } + 4 + { + title = "Player 04 Start"; + sprite = "SIGNE0"; + } + 5 + { + title = "Player 05 Start"; + sprite = "SIGNE0"; + } + 6 + { + title = "Player 06 Start"; + sprite = "SIGNE0"; + } + 7 + { + title = "Player 07 Start"; + sprite = "SIGNE0"; + } + 8 + { + title = "Player 08 Start"; + sprite = "SIGNE0"; + } + 9 + { + title = "Player 09 Start"; + sprite = "SIGNE0"; + } + 10 + { + title = "Player 10 Start"; + sprite = "SIGNE0"; + } + 11 + { + title = "Player 11 Start"; + sprite = "SIGNE0"; + } + 12 + { + title = "Player 12 Start"; + sprite = "SIGNE0"; + } + 13 + { + title = "Player 13 Start"; + sprite = "SIGNE0"; + } + 14 + { + title = "Player 14 Start"; + sprite = "SIGNE0"; + } + 15 + { + title = "Player 15 Start"; + sprite = "SIGNE0"; + } + 16 + { + title = "Player 16 Start"; + sprite = "SIGNE0"; + } + 33 + { + title = "Match Start"; + sprite = "SUPTG0"; + } + /*34 + { + title = "CTF Red Team Start"; + sprite = "SIGNF0"; + } + 35 + { + title = "CTF Blue Team Start"; + sprite = "SIGND0"; + }*/ + } + + enemies + { + color = 9; // Light_Blue + arrow = 1; + title = "Enemies"; + width = 24; + height = 32; + sprite = "POSSA1"; + + 100 + { + title = "Crawla (Blue)"; + sprite = "POSSA1"; + } + 101 + { + title = "Crawla (Red)"; + sprite = "SPOSA1"; + } + 102 + { + title = "Stupid Dumb Unnamed RoboFish"; + sprite = "FISHA0"; + width = 8; + height = 28; + angletext = "Jump strength"; + } + 103 + { + title = "Buzz (Gold)"; + sprite = "BUZZA1"; + width = 20; + height = 24; + flags8text = "[8] Cannot move"; + } + 104 + { + title = "Buzz (Red)"; + sprite = "RBUZA1"; + width = 20; + height = 24; + flags8text = "[8] Cannot move"; + } + 124 + { + title = "Buzz (Aqua)"; + sprite = "BBUZA1"; + width = 20; + height = 24; + } + 105 + { + title = "Jetty-Syn Bomber"; + sprite = "JETBB1"; + width = 20; + height = 48; + flags8text = "[8] Cannot move"; + } + 106 + { + title = "Jetty-Syn Gunner"; + sprite = "JETGB1"; + width = 20; + height = 48; + flags8text = "[8] Cannot move"; + } + 107 + { + title = "Crawla Commander"; + sprite = "CCOMA1"; + width = 16; + } + 108 + { + title = "Deton"; + sprite = "DETNA1"; + width = 20; + } + 109 + { + title = "Skim"; + sprite = "SKIMA1"; + width = 16; + height = 24; + } + 110 + { + title = "Turret"; + sprite = "TRETA1"; + width = 16; + height = 32; + } + 111 + { + title = "Pop-up Turret"; + sprite = "TURRI1"; + width = 12; + height = 64; + angletext = "Firing delay"; + } + 112 + { + title = "Sharp"; + sprite = "SHRPA1"; + width = 16; + height = 24; + } + 113 + { + title = "Jet Jaw"; + sprite = "JJAWA3A7"; + width = 12; + height = 20; + } + 114 + { + title = "Snailer"; + sprite = "SNLRA3A7"; + height = 48; + } + 115 + { + title = "Bird Aircraft Strike Hazard"; + sprite = "VLTRF1"; + width = 12; + height = 24; + } + 116 + { + title = "Pointy"; + sprite = "PNTYA1"; + width = 8; + height = 16; + } + 117 + { + title = "Robo-Hood"; + sprite = "ARCHA1"; + flags8text = "[8] Cannot jump"; + } + 118 + { + title = "CastleBot FaceStabber"; + sprite = "CBFSA1"; + width = 32; + height = 64; + } + 119 + { + title = "Egg Guard"; + sprite = "ESHIA1"; + width = 16; + height = 48; + flags8text = "[8] Double speed"; + } + 120 + { + title = "Green Snapper"; + sprite = "GSNPA1"; + height = 24; + } + 121 + { + title = "Minus"; + sprite = "MNUSA1"; + } + 122 + { + title = "Spring Shell (Green)"; + sprite = "SSHLA1"; + height = 40; + } + 125 + { + title = "Spring Shell (Yellow)"; + sprite = "SSHLI1"; + height = 40; + } + 123 + { + title = "Unidus"; + sprite = "UNIDA1"; + width = 18; + height = 36; + } + } + + bosses + { + color = 8; // Dark_Gray + arrow = 1; + title = "Bosses"; + width = 24; + height = 52; + sprite = "EGGMA1"; + + 200 + { + title = "Boss 1 - Egg Mobile"; + sprite = "EGGMA1"; + flags4text = "[4] End level on death"; + flags8text = "[8] Alternate laser attack"; + } + 201 + { + title = "Boss 2 - Egg Slimer"; + sprite = "EGGNA1"; + height = 48; + flags4text = "[4] End level on death"; + flags8text = "[8] Speed up when hit"; + } + 202 + { + title = "Boss 3 - Sea Egg"; + sprite = "EGGOA1"; + width = 32; + height = 80; + flags4text = "[4] End level on death"; + } + 203 + { + title = "Boss 4 - Eggscalibur"; + sprite = "EGGPA1"; + flags4text = "[4] End level on death"; + } + 207 + { + title = "Boss 5A - Metal Sonic (Race)"; + sprite = "METLI1"; + width = 16; + height = 48; + } + 208 + { + title = "Boss 5B - Metal Sonic (Battle)"; + sprite = "METLC1"; + width = 16; + height = 48; + flags4text = "[4] End level on death"; + } + 209 + { + title = "Boss 6 - Brak Eggman"; + sprite = "BRAK[1"; + width = 48; + height = 160; + flags4text = "[4] End level on death"; + flags8text = "[8] Electric barrier"; + } + 206 + { + title = "Boss ? - Brak Eggman (Old)"; + sprite = "BRAKB1"; + width = 48; + height = 160; + flags4text = "[4] End level on death"; + } + 290 + { + arrow = 0; + title = "Boss Escape Point"; + width = 8; + height = 16; + sprite = "internal:eggmanend"; + } + 291 + { + arrow = 0; + title = "Egg Capsule Center"; + width = 8; + height = 16; + sprite = "internal:capsule"; + } + 292 + { + arrow = 0; + title = "Boss Waypoint"; + width = 8; + height = 16; + flags8text = "[8] Sea Egg shooting point"; + sprite = "internal:eggmanway"; + angletext = "No. (Sea Egg)"; + flagsvaluetext = "No. (Brak)"; + parametertext = "Next"; + } + 293 + { + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + } + } + + rings + { + color = 14; // Yellow + title = "Rings and Weapon Panels"; + width = 24; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + sprite = "RINGA0"; + + 300 + { + title = "Ring"; + sprite = "RINGA0"; + width = 16; + } + 301 + { + title = "Bounce Ring"; + sprite = "internal:RNGBA0"; + } + 302 + { + title = "Rail Ring"; + sprite = "internal:RNGRA0"; + } + 303 + { + title = "Infinity Ring"; + sprite = "internal:RNGIA0"; + } + 304 + { + title = "Automatic Ring"; + sprite = "internal:RNGAA0"; + } + 305 + { + title = "Explosion Ring"; + sprite = "internal:RNGEA0"; + } + 306 + { + title = "Scatter Ring"; + sprite = "internal:RNGSA0"; + } + 307 + { + title = "Grenade Ring"; + sprite = "internal:RNGGA0"; + } + 308 + { + title = "CTF Team Ring (Red)"; + sprite = "internal:RRNGA0"; + width = 16; + } + 309 + { + title = "CTF Team Ring (Blue)"; + sprite = "internal:BRNGA0"; + width = 16; + } + 330 + { + title = "Bounce Ring Panel"; + sprite = "internal:PIKBA0"; + } + 331 + { + title = "Rail Ring Panel"; + sprite = "internal:PIKRA0"; + } + 332 + { + title = "Automatic Ring Panel"; + sprite = "internal:PIKAA0"; + } + 333 + { + title = "Explosion Ring Panel"; + sprite = "internal:PIKEA0"; + } + 334 + { + title = "Scatter Ring Panel"; + sprite = "internal:PIKSA0"; + } + 335 + { + title = "Grenade Ring Panel"; + sprite = "internal:PIKGA0"; + } + } + + collectibles + { + color = 10; // Light_Green + title = "Other Collectibles"; + width = 16; + height = 32; + sort = 1; + sprite = "CEMGA0"; + + 310 + { + title = "CTF Red Flag"; + sprite = "RFLGA0"; + width = 24; + height = 64; + } + 311 + { + title = "CTF Blue Flag"; + sprite = "BFLGA0"; + width = 24; + height = 64; + } + 312 + { + title = "Special Stage Token"; + sprite = "internal:token"; + width = 8; + height = 16; + flags8height = 24; + flags4text = "[4] Mario Block version"; + flags8text = "[8] Float"; + } + 313 + { + title = "Chaos Emerald 1 (Green)"; + sprite = "EMMYA0"; + } + 314 + { + title = "Chaos Emerald 2 (Purple)"; + sprite = "EMMYB0"; + } + 315 + { + title = "Chaos Emerald 3 (Blue)"; + sprite = "EMMYC0"; + } + 316 + { + title = "Chaos Emerald 4 (Cyan)"; + sprite = "EMMYD0"; + } + 317 + { + title = "Chaos Emerald 5 (Orange)"; + sprite = "EMMYE0"; + } + 318 + { + title = "Chaos Emerald 6 (Red)"; + sprite = "EMMYF0"; + } + 319 + { + title = "Chaos Emerald 7 (Gray)"; + sprite = "EMMYG0"; + } + 320 + { + title = "Emerald Hunt Location"; + sprite = "internal:hunt"; + } + 323 + { + title = "Match Chaos Emerald Spawn"; + sprite = "CEMGA0"; + width = 8; + height = 16; + flags8height = 24; + flags8text = "[8] Float"; + } + } + + boxes + { + color = 7; // Gray + blocking = 2; + title = "Monitors"; + width = 16; + height = 32; + flags4text = "[4] Random (Strong)"; + flags8text = "[8] Random (Weak)"; + sprite = "SRBXA0"; + + 400 + { + title = "Super Ring (10 Rings)"; + sprite = "SRBXA0"; + } + 401 + { + title = "Pity Shield"; + sprite = "GRTVA0"; + } + 402 + { + title = "Attraction Shield"; + sprite = "YLTVA0"; + } + 403 + { + title = "Force Shield"; + sprite = "BLTVA0"; + } + 404 + { + title = "Armageddon Shield"; + sprite = "BKTVA0"; + } + 405 + { + title = "Whirlwind Shield"; + sprite = "WHTVA0"; + } + 406 + { + title = "Elemental Shield"; + sprite = "ELTVA0"; + } + 407 + { + title = "Super Sneakers"; + sprite = "SHTVA0"; + } + 408 + { + title = "Invincibility"; + sprite = "PINVA0"; + } + 409 + { + title = "Extra Life"; + sprite = "PRUPA0"; + flags4text = "[4] Random (Strong) / 10k points"; + flags8text = "[8] Random (Weak) / 10k points"; + } + 410 + { + title = "Eggman"; + sprite = "EGGBA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 411 + { + title = "Teleporter"; + sprite = "MIXUA0"; + } + 412 + { + title = "Random"; + sprite = "QUESA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 413 + { + title = "Gravity Boots"; + sprite = "GBTVA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 414 + { + title = "CTF Team Ring Monitor (Red)"; + sprite = "RRBXA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 415 + { + title = "CTF Team Ring Monitor (Blue)"; + sprite = "BRBXA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 416 + { + title = "Recycler"; + sprite = "RECYA0"; + } + 418 + { + title = "Score (1,000 Points)"; + sprite = "PTTVA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 419 + { + title = "Score (10,000 Points)"; + sprite = "PTTVF0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + } + + miscellaneous + { + color = 11; // Light_Cyan + title = "Miscellaneous"; + width = 16; + height = 40; + sprite = "STPTA0"; + + 500 + { + title = "Air Bubble Patch"; + sprite = "BUBLA0"; + width = 8; + height = 16; + flags8text = "[8] No distance check"; + } + 501 + { + title = "Level End Sign"; + sprite = "SIGND0"; + width = 8; + height = 32; + } + 502 + { + arrow = 1; + title = "Star Post"; + sprite = "STPTA0"; + width = 64; + height = 80; + angletext = "Angle/Order"; + } + 526 + { + blocking = 2; + title = "Cannonball"; + sprite = "CBLLA0"; + width = 20; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1000 + { + arrow = 1; + blocking = 2; + title = "Gargoyle"; + sprite = "GARGA1"; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1102 + { + arrow = 1; + blocking = 2; + title = "Eggman Statue"; + sprite = "ESTAA1"; + width = 32; + height = 240; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1106 + { + arrow = 1; + title = "Chain (Swinging)"; + sprite = "internal:chain1"; + height = 32; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1107 + { + arrow = 1; + title = "Chain (Spinning)"; + sprite = "internal:chain2"; + height = 32; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1108 + { + arrow = 1; + title = "Chain (Hidden)"; + sprite = "internal:chain3"; + height = 32; + flags8text = "[8] Double size"; + } + 1200 + { + title = "Tumbleweed (Big)"; + sprite = "BTBLA0"; + width = 24; + height = 48; + flags8text = "[8] Moves perpetually"; + } + 1201 + { + title = "Tumbleweed (Small)"; + sprite = "STBLA0"; + width = 12; + height = 24; + flags8text = "[8] Moves perpetually"; + } + 1504 + { + title = "ATZ Target"; + sprite = "RCRYB0"; + width = 24; + height = 32; + } + 1852 + { + blocking = 2; + title = "Snowman"; + sprite = "XMS3A0"; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1876 + { + arrow = 1; + blocking = 2; + title = "Eggman Disco Statue"; + sprite = "ESTAB1"; + width = 20; + height = 96; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + } + + springs + { + color = 12; // Light_Red + title = "Springs and Fans"; + width = 48; + height = 32; + sprite = "RSPRD2"; + + 540 + { + title = "Fan"; + sprite = "FANSA0D0"; + width = 16; + height = 16; + flags4text = "[4] Invisible"; + flags8text = "[8] No distance check"; + angletext = "Lift height"; + } + 541 + { + title = "Gas Jet"; + sprite = "STEMD0"; + width = 32; + height = 16; + } + 550 + { + title = "Yellow Spring"; + sprite = "SPVYA0"; + } + 551 + { + title = "Red Spring"; + sprite = "SPVRA0"; + } + 552 + { + title = "Blue Spring"; + sprite = "SPVBA0"; + } + 553 + { + title = "Grey Spring"; + sprite = "SPVGA0"; + } + 554 + { + arrow = 1; + title = "Diagonal Yellow Spring"; + sprite = "SPDYA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 555 + { + arrow = 1; + title = "Diagonal Red Spring"; + sprite = "SPDRA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 556 + { + arrow = 1; + title = "Diagonal Blue Spring"; + sprite = "SPDBA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 557 + { + arrow = 1; + title = "Diagonal Grey Spring"; + sprite = "SPDGA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 558 + { + arrow = 1; + title = "Horizontal Yellow Spring"; + sprite = "SPHYA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 559 + { + arrow = 1; + title = "Horizontal Red Spring"; + sprite = "SPHRA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 560 + { + arrow = 1; + title = "Horizontal Blue Spring"; + sprite = "SPHBA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 561 + { + arrow = 1; + title = "Horizontal Grey Spring"; + sprite = "SPHGA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + } + + patterns + { + color = 5; // Magenta + arrow = 1; + title = "Special Placement Patterns"; + width = 16; + height = 384; + sprite = "RINGA0"; + + 600 + { + arrow = 0; + title = "5 Vertical Rings (Yellow Spring)"; + sprite = "RINGA0"; + } + 601 + { + arrow = 0; + title = "5 Vertical Rings (Red Spring)"; + sprite = "RINGA0"; + height = 1024; + } + 602 + { + title = "5 Diagonal Rings (Yellow Spring)"; + sprite = "RINGA0"; + height = 32; + } + 603 + { + title = "10 Diagonal Rings (Red Spring)"; + sprite = "RINGA0"; + height = 32; + } + 604 + { + title = "Circle of Rings"; + sprite = "RINGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 605 + { + title = "Circle of Rings (Big)"; + sprite = "RINGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 606 + { + title = "Circle of Wing Logos"; + sprite = "NWNGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 607 + { + title = "Circle of Wing Logos (Big)"; + sprite = "NWNGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 608 + { + title = "Circle of Rings and Wings"; + sprite = "NWNGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 609 + { + title = "Circle of Rings and Wings (Big)"; + sprite = "NWNGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + } + + invisible + { + color = 15; // White + title = "Misc. Invisible"; + width = 8; + height = 16; + sprite = "UNKNA0"; + + 700 + { + title = "Water Ambience A (Large)"; + sprite = "internal:ambiance"; + } + + 701 + { + title = "Water Ambience B (Large)"; + sprite = "internal:ambiance"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + sprite = "internal:ambiance"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + sprite = "internal:ambiance"; + } + + 704 + { + title = "Water Ambience E (Small)"; + sprite = "internal:ambiance"; + } + + 705 + { + title = "Water Ambience F (Small)"; + sprite = "internal:ambiance"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + sprite = "internal:ambiance"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + sprite = "internal:ambiance"; + } + + 708 + { + title = "Disco Ambience"; + sprite = "internal:ambiance"; + } + + 709 + { + title = "Volcano Ambience"; + sprite = "internal:ambiance"; + } + + 750 + { + title = "Slope Vertex"; + sprite = "internal:vertexslope"; + angletext = "Tag"; + } + + 751 + { + arrow = 1; + title = "Teleport Destination"; + sprite = "internal:tele"; + } + + 752 + { + arrow = 1; + title = "Alternate View Point"; + sprite = "internal:view"; + } + + 753 + { + title = "Zoom Tube Waypoint"; + sprite = "internal:zoom"; + angletext = "Order"; + } + + 754 + { + title = "Push Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Push using XYZ"; + sprite = "GWLGA0"; + angletext = "Radius"; + } + 755 + { + title = "Pull Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Pull using XYZ"; + sprite = "GWLRA0"; + angletext = "Radius"; + } + + 760 + { + title = "PolyObject Anchor"; + sprite = "internal:polyanchor"; + angletext = "ID"; + } + + 761 + { + title = "PolyObject Spawn Point"; + sprite = "internal:polycenter"; + angletext = "ID"; + } + + 762 + { + title = "PolyObject Spawn Point (Crush)"; + sprite = "internal:polycentercrush"; + angletext = "ID"; + } + + 777 + { + title = "Floor Slope Anchor"; + sprite = "internal:Vertex_Anchor_Floor.png"; + parametertext = "Level"; + } + + 778 + { + title = "Ceiling Slope Anchor"; + sprite = "internal:Ceiling_Anchor_Floor.png"; + parametertext = "Level"; + } + + 780 + { + title = "Skybox View Point"; + sprite = "internal:skyb"; + flags4text = "[4] In-map reference point"; + angletext = "View height"; + } + + } + + hazards + { + color = 4; // Red + title = "Hazards"; + width = 20; + height = 40; + + 521 + { + title = "Spikeball"; + sprite = "SPIKA0"; + width = 12; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 523 + { + title = "Spike"; + sprite = "USPKA0"; + width = 8; + height = 42; + flags4text = "[4] Retractable"; + flags8text = "[8] Solid"; + angletext = "Retraction interval"; + } + 524 + { + arrow = 1; + title = "Big Floating Mine"; + width = 16; + height = 32; + sprite = "BMNEA1"; + } + 527 + { + arrow = 1; + title = "Big Floating Mine (Air)"; + width = 16; + height = 32; + sprite = "BMNEA1"; + } + 525 + { + title = "Cannonball Launcher"; + sprite = "internal:cannonball"; + } + 1101 + { + title = "Torch"; + sprite = "FLAMA0"; + width = 8; + height = 32; + } + 1105 + { + title = "Mace (Swinging)"; + sprite = "internal:mace1"; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1104 + { + title = "Mace (Spinning)"; + sprite = "internal:mace2"; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1202 + { + arrow = 1; + title = "Rock Spawner"; + sprite = "ROIAA0"; + angletext = "Tag"; + } + 1300 + { + arrow = 1; + title = "Flame Jet (Horizontal)"; + sprite = "internal:flameh"; + width = 16; + flags8text = "[8] Waves vertically"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1301 + { + title = "Flame Jet (Vertical)"; + sprite = "internal:flamev"; + width = 16; + flags8text = "[8] Shoot downwards"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1500 + { + arrow = 1; + blocking = 2; + title = "Trapgoyle"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1501 + { + arrow = 1; + blocking = 2; + title = "Trapgoyle (Up)"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1502 + { + arrow = 1; + blocking = 2; + title = "Trapgoyle (Down)"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1503 + { + arrow = 1; + blocking = 2; + title = "Trapgoyle (Long)"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 3576 + { + title = "Spinning Flame Jet (Clockwise)"; + sprite = "internal:flame1"; + width = "16"; + } + 3575 + { + title = "Spinning Flame Jet (Counter-Clockwise)"; + sprite = "internal:flame2"; + width = "16"; + } + } + + decoration + { + color = 2; // Green + title = "Decoration"; + width = 16; + height = 40; + sprite = "FWR1A0"; + + 757 + { + title = "Fan Particle Generator"; + sprite = "PRTLA0"; + width = 8; + height = 16; + angletext = "Particle speed"; + parametertext = "Interval"; + } + 800 + { + title = "GFZ Flower"; + sprite = "FWR1A0"; + } + 801 + { + title = "Sunflower"; + sprite = "FWR2A0"; + height = 96; + } + 802 + { + title = "Budding Flower"; + sprite = "FWR3A0"; + width = 8; + height = 32; + } + 804 + { + title = "Berry Bush"; + sprite = "BUS1A0"; + height = 32; + } + 805 + { + title = "Bush"; + sprite = "BUS2A0"; + height = 32; + } + 900 + { + title = "THZ Flower"; + sprite = "THZPA0"; + width = 8; + height = 32; + } + 901 + { + title = "Alarm"; + sprite = "ALRMA0"; + width = 8; + height = 16; + hangs = 1; + } + 1001 + { + title = "Seaweed"; + sprite = "SEWEA0"; + width = 24; + height = 56; + } + 1002 + { + title = "Dripping Water"; + sprite = "DRIPD0"; + width = 8; + height = 16; + hangs = 1; + angletext = "Dripping interval"; + } + 1003 + { + title = "Coral (Green)"; + sprite = "CRL1A0"; + width = 8; + height = 16; + } + 1004 + { + title = "Coral (Red)"; + sprite = "CRL2A0"; + width = 8; + height = 16; + } + 1005 + { + title = "Coral (Orange)"; + sprite = "CRL3A0"; + width = 8; + height = 16; + } + 1006 + { + title = "Blue Crystal"; + sprite = "BCRYA1"; + width = 8; + height = 16; + } + 1100 + { + title = "Chain"; + sprite = "CHANA0"; + width = 8; + height = 128; + hangs = 1; + } + 1103 + { + title = "CEZ Flower"; + sprite = "FWR4A0"; + } + 1203 + { + title = "Cactus with Brown Flower"; + sprite = "CACTA0"; + height = 32; + } + 1204 + { + title = "Cactus with Brown Flower (Tall)"; + sprite = "CACTB0"; + height = 64; + } + 1205 + { + title = "Cactus with Blue Flower"; + sprite = "CACTC0"; + height = 32; + } + 1206 + { + title = "Cactus with Blue Flower (Tall)"; + sprite = "CACTD0"; + height = 80; + } + 1850 + { + title = "Christmas Pole"; + sprite = "XMS1A0"; + } + 1851 + { + title = "Candy Cane"; + sprite = "XMS2A0"; + width = 8; + height = 32; + } + 1875 + { + title = "Disco Ball"; + sprite = "DBALA0"; + height = 54; + hangs = 1; + } + 1900 + { + title = "Brown Stalagmite (Tall)"; + sprite = "STLGA0"; + } + 1901 + { + title = "Brown Stalagmite"; + sprite = "STLGB0"; + } + 1902 + { + title = "Orange Stalagmite (Tall)"; + sprite = "STLGC0"; + } + 1903 + { + title = "Orange Stalagmite"; + sprite = "STLGD0"; + } + 1904 + { + title = "Red Stalagmite (Tall)"; + sprite = "STLGE0"; + } + 1905 + { + title = "Red Stalagmite"; + sprite = "STLGF0"; + } + 1906 + { + title = "Gray Stalagmite (Tall)"; + sprite = "STLGG0"; + } + 1907 + { + title = "Gray Stalagmite"; + sprite = "STLGH0"; + } + 1908 + { + title = "Blue Stalagmite (Tall)"; + sprite = "STLGI0"; + } + 1909 + { + title = "Blue Stalagmite"; + sprite = "STLGJ0"; + } + } + + nights + { + color = 13; // Pink + title = "NiGHTS Items"; + width = 12; + height = 32; + sprite = "NWNGA0"; + + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + } + 1704 + { + arrow = 1; + title = "Bumper"; + sprite = "NBMPG3G7"; + width = 32; + height = 64; + unflippable = true; + flagsvaluetext = "Pitch"; + angletext = "Yaw"; + } + 1705 + { + arrow = 1; + title = "Hoop (Generic)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + flagsvaluetext = "Height"; + angletext = "Pitch/Yaw"; + } + 1706 + { + title = "Wing Logo"; + sprite = "NWNGA0"; + height = 24; + unflippable = true; + } + 1707 + { + title = "Super Paraloop"; + sprite = "NPRUA0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1708 + { + title = "Drill Refill"; + sprite = "NPRUB0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1709 + { + title = "Nightopian Helper"; + sprite = "NPRUC0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1711 + { + title = "Extra Time"; + sprite = "NPRUD0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1712 + { + title = "Link Freeze"; + sprite = "NPRUE0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1713 + { + arrow = 1; + title = "Hoop (Customizable)"; + flags1text = "[1] Radius +16"; + flags2text = "[2] Radius +32"; + flags4text = "[4] Radius +64"; + flags8text = "[8] Radius +128"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + } + } + + nightstrk + { + color = 13; // Pink + title = "NiGHTS Track"; + width = 8; + height = 4096; + sprite = "UNKNA0"; + + 1700 + { + title = "Axis"; + sprite = "internal:axis1"; + circle = 1; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + angletext = "Radius/Direction"; + parametertext = "Mare"; + } + 1701 + { + title = "Axis Transfer"; + sprite = "internal:axis2"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1702 + { + title = "Axis Transfer Line"; + sprite = "internal:axis3"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + angletext = "Rings"; + parametertext = "Mare"; + } + } + + mario + { + color = 6; // Brown + title = "Mario Items"; + width = 16; + height = 32; + sprite = "GOOMA0"; + + 1800 + { + title = "Coin"; + sprite = "COINA0"; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 1801 + { + arrow = 1; + title = "Goomba"; + sprite = "GOOMA0"; + width = 24; + } + 1802 + { + arrow = 1; + title = "Goomba (Blue)"; + sprite = "BGOMA0"; + width = 24; + } + 1803 + { + title = "Fire Flower"; + sprite = "FFWRB0"; + } + 1804 + { + title = "Koopa Shell"; + sprite = "SHLLA0"; + width = 8; + height = 16; + } + 1805 + { + title = "Puma (Jumping Fireball)"; + sprite = "PUMAA0"; + width = 8; + height = 16; + angletext = "Jump strength"; + } + 1806 + { + title = "King Bowser"; + sprite = "KOOPA0"; + height = 28; + } + 1807 + { + title = "Axe"; + sprite = "MAXEA0"; + width = 8; + height = 16; + } + 1808 + { + title = "Bush (Short)"; + sprite = "MUS1A0"; + } + 1809 + { + title = "Bush (Tall)"; + sprite = "MUS2A0"; + } + 1810 + { + title = "Toad"; + sprite = "TOADA0"; + width = 8; + } + } + + srb1 + { + color = 3; // Cyan + arrow = 1; + title = "SRB1 Remake"; + width = 20; + height = 32; + sprite = "SRBAA1"; + + 4000 + { + title = "SRB1 Crawla"; + sprite = "SRBAA1"; + height = 40; + } + 4001 + { + title = "GuardRobo"; + sprite = "SRBBA1"; + width = 17; + height = 40; + } + 4002 + { + title = "Pyrin"; + sprite = "SRBCB1"; + width = 22; + } + 4003 + { + title = "HotRobo"; + sprite = "SRBDA0"; + height = 40; + } + 4004 + { + title = "Pogminz"; + sprite = "SRBEA1"; + } + 4005 + { + title = "Pogminz (Water)"; + sprite = "SRBEA1"; + } + 4006 + { + title = "Pog-GX2"; + sprite = "SRBFA0"; + width = 10; + height = 34; + } + 4007 + { + title = "Pyrex"; + sprite = "SRBGA1"; + width = 24; + } + 4008 + { + title = "SRB1 Turret"; + sprite = "SRBHA0"; + width = 24; + hangs = 1; + } + 4009 + { + title = "SWAT Bot"; + sprite = "SRBIA1"; + width = 21; + height = 69; + } + 4010 + { + title = "SpyBot 2000"; + sprite = "SRBJA0"; + width = 36; + height = 62; + } + 4011 + { + title = "Buzz Bomber"; + sprite = "SRBKA0"; + width = 44; + height = 45; + } + 4012 + { + arrow = 0; + title = "RBZ Spike"; + sprite = "SRBLA0"; + width = 10; + height = 53; + } + 4013 + { + arrow = 0; + blocking = 2; + title = "Dumb Metal Sonic"; + sprite = "SRBMC0"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 4014 + { + title = "Super SWAT Bot"; + sprite = "SRBNA1"; + width = 21; + height = 69; + } + 4015 + { + title = "Genrex"; + sprite = "SRBOA1"; + width = 17; + height = 40; + } + } + + bsz + { + color = 2; // Green + title = "Botanic Serenity Items"; + width = 16; + height = 32; + sprite = "BSZ1A0"; + 1400 + { + title = "Tall Flower (Red)"; + sprite = "BSZ1A0"; + } + 1401 + { + title = "Tall Flower (Purple)"; + sprite = "BSZ1B0"; + } + 1402 + { + title = "Tall Flower (Blue)"; + sprite = "BSZ1C0"; + } + 1403 + { + title = "Tall Flower (Cyan)"; + sprite = "BSZ1D0"; + } + 1404 + { + title = "Tall Flower (Yellow)"; + sprite = "BSZ1E0"; + } + 1405 + { + title = "Tall Flower (Orange)"; + sprite = "BSZ1F0"; + } + 1410 + { + title = "Medium Flower (Red)"; + sprite = "BSZ2A0"; + } + 1411 + { + title = "Medium Flower (Purple)"; + sprite = "BSZ2B0"; + } + 1412 + { + title = "Medium Flower (Blue)"; + sprite = "BSZ2C0"; + } + 1413 + { + title = "Medium Flower (Cyan)"; + sprite = "BSZ2D0"; + } + 1414 + { + title = "Medium Flower (Yellow)"; + sprite = "BSZ2E0"; + } + 1415 + { + title = "Medium Flower (Orange)"; + sprite = "BSZ2F0"; + } + 1420 + { + title = "Short Flower (Red)"; + sprite = "BSZ3A0"; + } + 1421 + { + title = "Short Flower (Purple)"; + sprite = "BSZ3B0"; + } + 1422 + { + title = "Short Flower (Blue)"; + sprite = "BSZ3C0"; + } + 1423 + { + title = "Short Flower (Cyan)"; + sprite = "BSZ3D0"; + } + 1424 + { + title = "Short Flower (Yellow)"; + sprite = "BSZ3E0"; + } + 1425 + { + title = "Short Flower (Orange)"; + sprite = "BSZ3F0"; + } + 1430 + { + title = "Tulip (Red)"; + sprite = "BSZ4A0"; + } + 1431 + { + title = "Tulip (Purple)"; + sprite = "BSZ4B0"; + } + 1432 + { + title = "Tulip (Blue)"; + sprite = "BSZ4C0"; + } + 1433 + { + title = "Tulip (Cyan)"; + sprite = "BSZ4D0"; + } + 1434 + { + title = "Tulip (Yellow)"; + sprite = "BSZ4E0"; + } + 1435 + { + title = "Tulip (Orange)"; + sprite = "BSZ4F0"; + } + 1440 + { + title = "Cluster (Red)"; + sprite = "BSZ5A0"; + } + 1441 + { + title = "Cluster (Purple)"; + sprite = "BSZ5B0"; + } + 1442 + { + title = "Cluster (Blue)"; + sprite = "BSZ5C0"; + } + 1443 + { + title = "Cluster (Cyan)"; + sprite = "BSZ5D0"; + } + 1444 + { + title = "Cluster (Yellow)"; + sprite = "BSZ5E0"; + } + 1445 + { + title = "Cluster (Orange)"; + sprite = "BSZ5F0"; + } + 1450 + { + title = "Bush (Red)"; + sprite = "BSZ6A0"; + } + 1451 + { + title = "Bush (Purple)"; + sprite = "BSZ6B0"; + } + 1452 + { + title = "Bush (Blue)"; + sprite = "BSZ6C0"; + } + 1453 + { + title = "Bush (Cyan)"; + sprite = "BSZ6D0"; + } + 1454 + { + title = "Bush (Yellow)"; + sprite = "BSZ6E0"; + } + 1455 + { + title = "Bush (Orange)"; + sprite = "BSZ6F0"; + } + 1460 + { + title = "Vine (Red)"; + sprite = "BSZ7A0"; + } + 1461 + { + title = "Vine (Purple)"; + sprite = "BSZ7B0"; + } + 1462 + { + title = "Vine (Blue)"; + sprite = "BSZ7C0"; + } + 1463 + { + title = "Vine (Cyan)"; + sprite = "BSZ7D0"; + } + 1464 + { + title = "Vine (Yellow)"; + sprite = "BSZ7E0"; + } + 1465 + { + title = "Vine (Orange)"; + sprite = "BSZ7F0"; + } + 1470 + { + title = "BSZ Shrub"; + sprite = "BSZ8A0"; + } + 1471 + { + title = "BSZ Clover"; + sprite = "BSZ8B0"; + } + 1472 + { + title = "BSZ Fish"; + sprite = "BSZ8C0"; + } + 1473 + { + title = "BSZ Sunflower"; + sprite = "BSZ8D0"; + } + } + + derrobjs // sev: split these into multiple sections later + { + color = 4; // Red + arrow = 1; + title = "SRB2Kart Stuff"; + sprite = "ITEMALAR"; + width = 8; + height = 16; + + 2000 + { + title = "Random Item"; + sprite = "RNDMA0"; + width = 36; + height = 36; + } + 2333 + { + title = "Capsule"; + //sprite = "internal:kartcapsule"; + width = 28; + height = 112; + blocking = 2; + angletext = "Speed"; + parametertext = "Movement sequence"; + flags4text = "[4] Reverse movement"; + flags8text = "[8] Back and forth"; + } + 1488 + { + arrow = 1; + title = "Random Audience Member"; + sprite = "AUDIA2A8"; + width = 8; + height = 20; + } + 1479 + { + title = "Torch (no fullbright)"; + sprite = "FLAMA0"; + width = 8; + height = 32; + } + 1480 + { + blocking = 2; + arrow = 1; + title = "Devil Gargoyle"; + sprite = "DECOA1"; + width = 16; + height = 40; + } + 1481 + { + blocking = 2; + arrow = 1; + title = "Angel Gargoyle"; + sprite = "DECOB1"; + width = 16; + height = 40; + } + 1482 + { + title = "Generic Palmtree"; + sprite = "DECOC0"; + width = 16; + height = 189; + } + 1483 + { + title = "Peach's Castle Flag"; + sprite = "DECOD0"; + width = 16; + height = 40; + } + 1484 + { + title = "Sonic the Hedge (bust)"; + sprite = "DECOE0"; + width = 64; + height = 64; + } + 1485 + { + title = "Tall Bush"; + sprite = "DECOF0"; + width = 16; + height = 32; + } + 1486 + { + title = "Bush Tree"; + sprite = "DECOG0"; + width = 16; + height = 40; + } + 1487 + { + title = "Fire Hydrant"; + sprite = "DECOH0"; + width = 16; + height = 40; + } + 2400 + { + title = "Big Puma"; + sprite = "DECOI0"; + width = 24; + height = 48; + } + 2805 + { + title = "Autumn Bush"; + sprite = "DOODA0"; + width = 16; + height = 24; + } + 2800 + { + title = "Autumn Flower"; + sprite = "DOODB0"; + width = 16; + height = 40; + } + 2801 + { + title = "Autumn Sunflower"; + sprite = "DOODD0"; + width = 16; + height = 96; + } + 2802 + { + title = "Autumn Budding Flower"; + sprite = "DOODF0"; + width = 8; + height = 32; + } + 2809 + { + title = "Decorative MKSC Item"; + sprite = "DOODJ0"; + width = 16; + height = 32; + } + 2807 + { + title = "Decorative DKR Item"; + sprite = "DOODL0"; + width = 91; + height = 166; + } + 2808 + { + title = "Big Ring"; + sprite = "BRNGA0"; + width = 26; + height = 62; + } + 2301 + { + title = "SMK DP Bush 1"; + sprite = "SNESA0"; + width = 14; + height = 15; + } + 2302 + { + title = "SMK DP Bush 2"; + sprite = "SNESB0"; + width = 13; + height = 13; + } + 2303 + { + title = "SMK DP Bush 3"; + sprite = "SNESC0"; + width = 7; + height = 7; + } + /*379 + { + title = "MKSC Boo"; + sprite = "GBASA0"; + width = 16; + height = 56; + }*/ + 2015 + { + title = "Buzz Bomber"; + sprite = "BUZBA2A8"; + width = 24; + height = 24; + } + 2500 + { + title = "Chomper"; + sprite = "CHOMA2A8"; + width = 24; + height = 48; + } + 2016 + { + title = "SCZ Palmtree"; + sprite = "SACOA0"; + width = 16; + height = 96; + } + 3000 + { + title = "SCZ Blue Flower"; + sprite = "SACOB0"; + width = 16; + height = 40; + } + 3001 + { + title = "SCZ Blue Tulips"; + sprite = "SACOC0"; + width = 16; + height = 40; + } + 3002 + { + title = "SCZ Yellow Flower"; + sprite = "SACOD0"; + width = 16; + height = 40; + } + 3003 + { + title = "SCZ Yellow Tulips"; + sprite = "SACOE0"; + width = 16; + height = 40; + } + 4022 // Dupe + { + title = "SCZ Wall Plant"; + sprite = "SACOF0"; + width = 16; + height = 40; + } + 4024 + { + title = "SCZ Plant"; + sprite = "SACOG0"; + width = 16; + height = 40; + } + 4025 + { + title = "SCZ Bush"; + sprite = "SACOH0"; + width = 16; + height = 40; + } + 4026 + { + title = "CAZ Skull"; + sprite = "CRABA1"; + width = 16; + height = 40; + } + 4027 + { + title = "CAZ Phantom Tree"; + sprite = "CRABB0"; + width = 32; + height = 150; + } + 4028 + { + title = "CAZ Flying Gargoyle"; + sprite = "CRABI1"; + width = 20; + height = 170; + } + 4029 + { + title = "CAZ Lamppost"; + sprite = "CRABK0"; + width = 32; + height = 150; + } + 4030 + { + title = "CAZ Dead Tree"; + sprite = "CRABL0"; + width = 32; + height = 150; + } + 715 + { + title = "Sonic the Hedge"; + sprite = "SBUSA0"; + width = 192; + height = 922; + } + 1969 + { + title = "MZ Torch"; + sprite = "MARBA0"; + width = 12; + height = 45; + } + 1970 + { + title = "MZ Burner"; + sprite = "MARBJ0"; + width = 24; + height = 96; + } + 4050 + { + title = "CD SS1 UFO"; + sprite = "FUFOA0"; + width = 70; + height = 70; + } + 1988 + { + title = "RRZ Lamp"; + sprite = "RUSTA0"; + width = 12; + height = 45; + } + 1989 + { + title = "RRZ Chain"; + sprite = "RUSTB0"; + width = 12; + height = 45; + } + 462 + { + title = "SD2 BP Balloon"; + sprite = "BLONA0"; + width = 32; + height = 64; + angletext = "Color"; + } + 2018 + { + title = "PRZ Smoke Generator"; + sprite = "SMOKA0"; + width = 24; + height = 64; + flags4text = "[4] Spawn VVZ smoke"; + } + 1600 + { + title = "VVZ Smoke"; + sprite = "VAPEA0"; + width = 16; + height = 64; + } + 716 + { + title = "HTZ Pinetree"; + sprite = "HTZAA0"; + width = 5; + height = 204; + } + 717 + { + title = "HTZ Bush"; + sprite = "HTZBA0"; + width = 24; + height = 38; + } + 718 + { + title = "MKSC SG Vine 1"; + sprite = "SGVAA0"; + width = 32; + height = 256; + } + 719 + { + title = "MKSC SG Vine 2"; + sprite = "SGVBA0"; + width = 17; + height = 48; + } + 720 + { + title = "MKSC SG Vine 3"; + sprite = "SGVCA0"; + width = 17; + height = 48; + } + 711 + { + title = "MKDS PG Tree"; + sprite = "PGTRA0"; + width = 30; + height = 504; + } + 712 + { + title = "MKDS PG Flower 1"; + sprite = "PGF1A0"; + width = 17; + height = 48; + } + 713 + { + title = "MKDS PG Flower 2"; + sprite = "PGF2A0"; + width = 17; + height = 48; + } + 714 + { + title = "MKDS PG Flower 3"; + sprite = "PGF3A0"; + width = 17; + height = 48; + } + 715 + { + title = "MKDS PG Bush"; + sprite = "PGBHA0"; + width = 384; + height = 922; + } + 1960 + { + title = "SM SS3 Pillar"; + sprite = "DPLRA0"; + width = 58; + height = 256; + } + 3124 + { + title = "MC Spotlight"; + sprite = "SPTLA0"; + width = 8; + height = 16; + } + 3120 + { + title = "MC Random Shadow"; + sprite = "ENM1B2B8"; + width = 16; + height = 32; + } + 3121 + { + title = "MC Roaming Shadow"; + sprite = "ENM1C2C8"; + width = 16; + height = 32; + } + 3122 + { + title = "MC Sign"; + sprite = "MARRA0"; + width = 64; + height = 128; + flags1text = "[1] Flip Arrow"; + flags4text = "[4] Boost Warning"; + } + 3199 + { + title = "Mementos Reaper Waypoint"; + sprite = "ENM1B5"; + width = 64; + height = 128; + flags1text = "[1] Flip Arrow"; + flags4text = "[4] Boost Warning"; + } + 3202 + { + title = "Mementos Reaper"; + sprite = "REAPA0"; + width = 64; + height = 128; + } + 3201 + { + title = "Mementos Teleporter"; + sprite = "GARUA0"; + width = 512; + height = 16; + } + 1601 + { + title = "MCZ Jack in the Box"; + sprite = "JITBA0"; + width = 16; + height = 128; + } + 2499 + { + title = "3CD Moon"; + sprite = "CDMOA0"; + width = 30; + height = 60; + } + 2498 + { + title = "3CD Bush"; + sprite = "CDBUA0"; + width = 16; + height = 16; + } + 2496 + { + title = "3CD Tree 1"; + sprite = "CDBUB0"; + width = 20; + height = 20; + } + 2497 + { + title = "3CD Tree 2"; + sprite = "CDBUC0"; + width = 20; + height = 20; + } + 3204 + { + title = "DSZ Pinetree"; + sprite = "PINEC0"; + width = 32; + height = 192; + } + 2311 + { + title = "EZZ Propeller"; + sprite = "PPLRA0"; + width = 32; + height = 48; + } + 3742 + { + title = "DPZ Palmtree"; + sprite = "DPPTA0"; + width = 16; + height = 560; + } + 1950 + { + title = "AAZ Palmtree"; + sprite = "AATRC0"; + width = 160; + height = 256; + angletext = "Leaves"; + parametertext = "Height"; + } + 2005 + { + title = "BBZ Frogger"; + sprite = "FROGA2A8"; + width = 28; + height = 72; + } + 2006 + { + title = "BBZ Robra"; + sprite = "CBRAA2A8"; + width = 32; + height = 72; + } + 2007 + { + blocking = 2; + title = "BBZ Blue Robra"; + sprite = "BBRAA2A8"; + width = 32; + height = 72; + } + 2679 + { + title = "EGZ Fog Generator"; + sprite = "EGFGA0"; + } + 3970 + { + blocking = 2; + title = "SMK Pipe"; + sprite = "SMKPA1A5"; + width = 20; + height = 52; + flags8text = "[8] Orange"; + } + 3971 + { + title = "SMK DP Monty Mole"; + sprite = "MTYMA0"; + width = 28; + height = 32; + } + 3972 + { + blocking = 2; + title = "SMK Thwomp"; + sprite = "THWPA0"; + width = 22; + height = 52; + flags8text = "[8] Rainbow"; + } + 3745 + { + title = "SMK VL Snowball"; + sprite = "SNOBA0"; + width = 16; + height = 32; + } + 3203 + { + blocking = 2; + title = "SMK VL Ice Block"; + sprite = "ICEBARAL"; + width = 32; + height = 32; + } + 749 + { + title = "Blue Torch"; + sprite = "CNDLA0"; + width = 8; + height = 32; + } + 748 + { + title = "Green Torch"; + sprite = "CNDLE0"; + width = 8; + height = 32; + } + 744 + { + blocking = 2; + title = "CK RR Chest"; + sprite = "CHESA0"; + width = 48; + height = 64; + } + 743 + { + blocking = 2; + title = "CK RR Chimera Statue"; + sprite = "CHIMA0"; + width = 64; + height = 128; + } + 742 + { + blocking = 2; + title = "CK RR Dragon Statue"; + sprite = "DRGNA0"; + width = 64; + height = 128; + } + 741 + { + blocking = 2; + title = "CK RR Lizard Man Statue"; + sprite = "LZMNA0"; + width = 64; + height = 128; + } + 740 + { + blocking = 2; + title = "CK RR Pegasus Statue"; + sprite = "PGSSA0"; + width = 64; + height = 128; + } + 739 + { + title = "Small Purple Torch"; + sprite = "ZTCHA0"; + width = 8; + height = 32; + } + 747 + { + blocking = 2; + title = "KKR GD Thing"; + sprite = "DOCHA0"; + width = 16; + height = 64; + } + 746 + { + blocking = 2; + title = "KKR GD Duck"; + sprite = "DUCKA0"; + width = 16; + height = 64; + } + 745 + { + blocking = 2; + title = "KKR GD Tree"; + sprite = "GTREA0"; + width = 32; + height = 128; + } + 738 + { + title = "THH Monokuma"; + sprite = "MKMAA2"; + width = 16; + height = 64; + } + 737 + { + title = "Small Red Torch"; + sprite = "RTCHA0"; + width = 8; + height = 32; + } + 736 + { + title = "PC Bowling Pin"; + sprite = "BOWLA0"; + width = 16; + height = 64; + } + 735 + { + title = "PC Merry-Go-Round Ambience"; + sprite = "internal:ambiance"; + } + 734 + { + title = "Twinkle Cart Ambience"; + sprite = "internal:ambiance"; + } + 733 + { + title = "PC Exploding Barrel"; + sprite = "BRRLA0"; + width = 32; + height = 64; + } + 732 + { + blocking = 2; + title = "PC Merry-Go-Round Horse"; + sprite = "HRSEA0"; + width = 32; + height = 128; + } + 731 + { + blocking = 2; + title = "Chao Fruit (Blue)"; + sprite = "BFRTA0"; + width = 16; + height = 16; + } + 730 + { + blocking = 2; + title = "Chao Fruit (Orange)"; + sprite = "OFRTA0"; + width = 16; + height = 16; + } + 729 + { + blocking = 2; + title = "Chao Fruit (Red)"; + sprite = "RFRTA0"; + width = 16; + height = 16; + } + 728 + { + blocking = 2; + title = "Chao Fruit (Pink)"; + sprite = "OFRTA0"; + width = 16; + height = 16; + } + 727 + { + title = "RBA Spikeball 1"; + sprite = "ASPKA0"; + width = 64; + height = 32; + } + 726 + { + title = "RBA Spikeball 2"; + sprite = "ASPKA0"; + width = 64; + height = 32; + } + 725 + { + title = "RBA Spikeball 3"; + sprite = "ASPKA0"; + width = 64; + height = 32; + } + 724 + { + title = "RBA Boost Prompt"; + sprite = "HBSTA0"; + width = 64; + height = 64; + } + 724 + { + title = "RBA Boost OFF"; + sprite = "HBSFA0"; + width = 64; + height = 64; + } + 724 + { + title = "RBA Boost ON"; + sprite = "HBSOA0"; + width = 64; + height = 64; + } + 2200 + { + title = "AS Toad"; + sprite = "TOAHA0"; + width = 16; + height = 64; + } + 2201 + { + blocking = 2; + title = "FTZ Lizard Man Statue"; + sprite = "WBLZA0"; + width = 32; + height = 92; + } + 2202 + { + blocking = 2; + title = "FTZ Lion Man Statue"; + sprite = "WBLNA0"; + width = 32; + height = 92; + } + } + waypoints + { + color = 4; // Red + arrow = 1; + title = "Waypoints"; + sprite = "KBLNC0"; + width = 16; + height = 32; + + 2001 + { + title = "Waypoint (height = next waypoint ID)"; + sprite = "EMBMP0"; + angletext = "ID"; + flags1text = "[1] Disable"; + flags4text = "[4] Shortcut"; + flags8text = "[8] No respawn"; + heighttext = "Next"; + } + 2002 + { + title = "Waypoint Riser"; + sprite = "EMBMY0"; + angletext = "ID (if flag [4] set)"; + flags2text = "[2] Look for FOF above"; + flags4text = "[4] Require matching waypoint ID"; + flags8text = "[8] Copy exact height"; + } + 2003 + { + title = "Waypoint Anchor"; + sprite = "EMBMR0"; + angletext = "ID"; + } + 2004 + { + title = "Bot Hint"; + sprite = "EMBMA0"; + angletext = "Radius"; + flags8text = "[8] Avoid this area"; + parametertext = "Strength (default = 2)"; + } + } +} + +//Default things filters +thingsfilters +{ + + filter0 + { + name = "Player starts"; + category = "starts"; + type = -1; + } + + filter1 + { + name = "Track Waypoints"; + category = "derrobjs"; + type = -1; + + } + + filter2 + { + name = "Enemies"; + category = "enemies"; + type = -1; + + } + + + filter3 + { + name = "NiGHTS Track"; + category = "nightstrk"; + type = -1; + + } + + + filter4 + { + name = "Normal Gravity"; + category = ""; + type = -1; + + fields + { + 2 = false; + } + + } + + + filter5 + { + name = "Reverse Gravity"; + category = ""; + type = -1; + + fields + { + 2 = true; + } + + } + + filter6 + { + name = "Boss Waypoints"; + category = ""; + type = 292; + } +} + +texturesets +{ + + set0 + { + name = "Greenflower Zone"; + filter0 = "GFZ*"; + filter1 = "FWATER*"; + filter2 = "CFALL*"; + filter3 = "GFALL*"; + filter4 = "FLOOR0_4"; + filter5 = "FLOOR1_2"; + filter6 = "FLOOR1_3"; + filter7 = "BWATER*"; + filter8 = "FLOOR0_2"; + filter9 = "DEM1_5"; + filter10 = "OLDROCKW"; + filter11 = "ROCKY*"; + filter12 = "OWOODW"; + filter13 = "WOODFLR"; + } + + set1 + { + name = "Techno Hill Zone"; + filter0 = "TH*"; + filter1 = "CHEMG*"; + filter2 = "TFALL?"; + filter3 = "ALTBOX*"; + filter4 = "BOXWARN?"; + filter5 = "PIPE*"; + filter6 = "PISTON"; + filter7 = "WHZ*"; + filter8 = "BAR*"; + filter9 = "COMP?"; + filter10 = "INFOWAL?"; + filter11 = "SPECWLL?"; + filter12 = "SUPPORT?"; + filter13 = "LITE*"; + filter14 = "BLUEW?"; + filter15 = "GREYW?"; + filter16 = "RED?"; + filter17 = "YEL?"; + filter18 = "SLITE?"; + filter19 = "DOORTRK1"; + filter20 = "GOOP*"; + filter21 = "AFALL?"; + filter22 = "STEEL*"; + filter23 = "CONVEY?"; + } + + set2 + { + name = "Deep Sea Zone"; + filter0 = "DSZ*"; + filter1 = "LWATER*"; + filter2 = "LFALL?"; + filter3 = "BFALL?"; + filter4 = "DEEPSE*"; + filter5 = "WEB?"; + filter6 = "RUINS1_1"; + filter7 = "CLRWAL*"; + } + + set3 + { + name = "Castle Eggman Zone"; + filter0 = "CASTLE*"; + filter1 = "STONE*"; + filter2 = "DMA*"; + filter3 = "LIB*"; + filter4 = "CEZ*"; + filter5 = "CEFLAG*"; + filter6 = "TOMBST?"; + filter7 = "NCEZW?"; + filter8 = "DEM1_1"; + filter9 = "WEBB?"; + filter10 = "LFZ*"; + filter11 = "WEEDWALL"; + filter12 = "STORM1"; + filter13 = "STR_M1"; + } + + set4 + { + name = "Arid Canyon Zone"; + filter0 = "AC*"; + filter1 = "OIL*"; + filter2 = "SOLFALL?"; + } + + set5 + { + name = "Red Volcano Zone"; + filter0 = "RVZ*"; + filter1 = "D2LAVA"; + filter2 = "MM*"; + filter3 = "ROCKFLR*"; + filter4 = "ROCKWLL*"; + filter5 = "DLAVA?"; + filter6 = "LAVA?"; + filter7 = "RLAVA?"; + filter8 = "SFALL?"; + filter9 = "MINE*"; + filter10 = "LVASAND?"; + filter11 = "FLOOR6_2"; + filter12 = "TLITE6_1"; + filter13 = "ROCKBOIL"; + filter14 = "TLITE6_5"; + filter15 = "TLITE6_6"; + filter16 = "FLOOR6_1"; + } + + set6 + { + name = "Dark City Zone"; + filter0 = "DC*"; + filter1 = "SIDEWALK"; + filter2 = "BRICK*"; + filter3 = "CEMENT?"; + filter4 = "BRIDGE*"; + filter5 = "CATFLR02"; + filter6 = "LIFT*"; + } + + set7 + { + name = "Doomship Zone"; + filter0 = "DSHIP*"; + } + + set8 + { + name = "Egg Rock Zone"; + filter0 = "ER*"; + filter1 = "MEK*"; + filter2 = "VENT*"; + filter3 = "DOWN*"; + filter4 = "UP*"; + filter5 = "LITE*"; + filter6 = "BLUEW?"; + filter7 = "GREYW?"; + filter8 = "RED?"; + filter9 = "YEL?"; + filter10 = "EGRID*"; + filter11 = "CONVEY?"; + } + + set9 + { + name = "Mario"; + filter0 = "MARFLAG?"; + filter1 = "THWOMP*"; + filter2 = "PTZ*"; + filter3 = "MARIO*"; + filter4 = "MARROCK?"; + } + + set10 + { + name = "Special Stage"; + filter0 = "ASPEC*"; + filter1 = "CSPEC*"; + filter2 = "EMTEX?"; + filter3 = "GSPEC*"; + filter4 = "PSPEC*"; + filter5 = "RSPEC*"; + filter6 = "SFLR*"; + filter7 = "SPACE*"; + filter8 = "SPC*"; + filter9 = "SPEC*"; + filter10 = "VOID*"; + filter11 = "WSPEC*"; + filter12 = "YSPEC*"; + filter13 = "BSPEC*"; + } + + set11 + { + name = "Multiplayer levels"; + filter0 = "ALLYRING"; + filter1 = "BRAKCAT?"; + filter2 = "SANDWLL"; + filter3 = "LAKE*"; + filter4 = "AP*"; + filter5 = "ZIM*"; + filter6 = "RCZ*"; + } + + set12 + { + name = "Caves and Cliffs"; + filter0 = "CAVE*"; + filter1 = "ROCK?"; + filter2 = "ROCKF?"; + filter3 = "CLIFF*"; + filter4 = "SHAL*"; + filter5 = "MRNR*"; + } + + set13 + { + name = "Christmas"; + filter0 = "XM*"; + filter1 = "FROST*"; + filter2 = "GRSWALL3"; + filter3 = "GRSWALL4"; + } + + set14 + { + name = "Forts"; + filter0 = "2FORT*"; + } + + set15 + { + name = "Ice and Snow"; + filter0 = "ICE*"; + filter1 = "SNOW*"; + } + + set16 + { + name = "Jungle"; + filter0 = "GRSEDG?"; + filter1 = "JNG*"; + filter2 = "SHROOM*"; + } + + set17 + { + name = "Sand"; + filter0 = "SAND"; + filter1 = "SANDW"; + filter2 = "SANDFLR*"; + filter3 = "SND*"; + filter4 = "AGZ*"; + filter5 = "QUIK*"; + filter6 = "Q?FALL?"; + } + + set18 + { + name = "Forest"; + filter0 = "WOOD*"; + filter1 = "EC*"; + filter2 = "GRASS1*"; + filter3 = "VFZ*"; + filter4 = "OWOODW"; + filter5 = "DEM1_2"; + } + + set19 + { + name = "Generic"; + filter0 = "BUST*"; + filter1 = "CEIL3_1"; + filter2 = "CTFFLG*"; + filter3 = "DEM1_3"; + filter4 = "BIGX"; + filter5 = "ARROW?"; + filter6 = "HAZARD?"; + filter7 = "*PIT"; + filter8 = "SPIKE*"; + filter9 = "*CAUTN"; + filter10 = "TRAPFLR"; + filter11 = "EGGTRAP?"; + filter12 = "GLASS*"; + filter13 = "DIRT*"; + filter14 = "EGGOLD*"; + filter15 = "MARE*"; + filter16 = "BLUEFLR"; + filter17 = "BLUWALL"; + filter18 = "CYAN*"; + filter19 = "GOLD*"; + filter20 = "GREENFLR"; + filter21 = "GRNWALL"; + filter22 = "GREYFLR"; + filter23 = "GRYWALL"; + filter24 = "LIME*"; + filter25 = "NEOG*"; + filter26 = "ORGFLR"; + filter27 = "ORANGE"; + filter28 = "PUR*"; + filter29 = "REDFLR"; + filter30 = "REDWALL"; + filter31 = "VIO*"; + filter32 = "YELFLR"; + filter33 = "YELWALL"; + } + + set20 + { + name = "Unsorted"; + filter0 = "FLAT1_2"; + filter1 = "FOSSIL*"; + filter2 = "F_METAL?"; + filter3 = "GRASSY*"; + filter4 = "WATER?"; + filter5 = "SURF*"; + filter6 = "OFALL?"; + filter7 = "MFALL1"; + filter8 = "SCREEN01"; + filter9 = "TRCKWLL1"; + filter10 = "WINDOW"; + filter11 = "XTRMCHK*"; + filter12 = "CHAINFEN"; + filter13 = "SRB1*"; + filter14 = "DISCO*"; + filter15 = "DANCE?"; + filter16 = "RECORD"; + filter17 = "DFZ*"; + } + + set21 + { + name = "Classic levels"; + filter0 = "GHZ*"; + filter1 = "HPZ*"; + filter2 = "LBZ*"; + filter3 = "GRASS2"; + filter4 = "GRASS3"; + filter5 = "GRSWALL"; + filter6 = "GRNLITE1"; + filter7 = "GATE2"; + filter8 = "DEM1_6"; + } +} diff --git a/extras/conf/Srb2-20db.cfg b/extras/conf/Srb2-20db.cfg deleted file mode 100644 index 8dc18b6e8..000000000 --- a/extras/conf/Srb2-20db.cfg +++ /dev/null @@ -1,2276 +0,0 @@ -/******************************************************************************\ - - SRB2 Doom Builder - Game Configuration for SRB2 version 2.0. - - Contributors: - - Kristos - - Shadow Hog - - ST218 - - Foxboy - - JJames19119 - - SRB2-Playah - - Oogaland - - SSNTails - - DarkWarrior - - Neo - -\******************************************************************************/ - -// This is required to prevent accedential use of a different configuration. -type = "SRB2 Doom Builder Game Configuration"; - -// This is the title to show for this game. -game = "Sonic Robo Blast 2 v2.0"; - -// Map format determines the way the map will be loaded. -mapformat = 1; - -// Flags for changes in 2.0. -seceffectnybble = 1; - -// Default flags for first new thing. -defaulthingflags = 0; - -// Default lump name for new map. -defaultlumpname = "MAP01"; - -// Load textures/flats by default from this file. -texturesfile = ""; - -// Thing number for start position in 3D Mode. -start3dmode = 32000; - -// Thing number for control sector position hint. -ctrlsechint = 32001; - -// Zoom tube waypoint, for the wizard. -zoomtubewaypoint = 753; - -// No generalized types. -generalizedlinedefs = 0; -generalizedsectors = 0; - -/* TEXTURES AND FLAT SOURCES --------------------------------------------------- - -This tells Doom Builder where to find the information for textures and flats in -the IWAD file, Addition WAD file and Map WAD file. - -Start and end lumps must be given in a structure (of which the key name doesn't -matter) and any textures or flats in between them are loaded in either the -textures category or flats category. - -For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. - -*/ - -// Texture sources. -textures -{ -} - -// Flat sources. -flats -{ - standard1 - { - start = "F_START"; - end = "F_END"; - } - - standard2 - { - start = "FF_START"; - end = "FF_END"; - } - - standard3 - { - start = "FF_START"; - end = "F_END"; - } - - standard4 - { - start = "F_START"; - end = "FF_END"; - } -} - -/* TEXTURES AND FLATS FILTERING ------------------------------------------------ - -This allows you to filter textures and flats so that you only see the -textures/flats listed that you prefer to use. - -The key name doesn't matter here, only the values. - -Pattern-matching is performed on lump names. You can use the following wildcards -in values to specify ranges: - -? = Any character. -* = Zero or more characters. -# = Any numeric digit. -[abc...] = Any of these characters that are between brackets. -[!abc..] = Not any of these characters that are between brackets. - -*/ - -// List these textures... -texturesfilter -{ - all_textures = "*"; -} - -// But do not list these textures... -notexturesfilter -{ - none = ""; -} - -// List these flats... -flatsfilter -{ - all_flats = "*"; -} - -// But do not list these flats... -noflatsfilter -{ - none = ""; -} - -/* PSEUDO-FLATS AND TEXTURES --------------------------------------------------- - -Names of flats and textures that don't really exist, but shouldn't be identified -as invalid. - -Pattern-matching is performed on lump names. See above for syntax. - -*/ - -pseudoflats -{ - F_SKY1; -} - -pseudotextures -{ - [#]*; -} - -/* GAME DETECT PATTERN --------------------------------------------------------- - -Used to guess the game for which a WAD file is made. - -1 = One of these lumps must exist. -2 = None of these lumps must exist. -3 = All of these lumps must exist. - -Pattern-matching is performed on lump names. See above for syntax. - -*/ - -gamedetect -{ - EXTENDED = 2; - BEHAVIOR = 2; - E#M# = 2; - MAP?? = 1; -} - -/* MAP LUMP NAMES -------------------------------------------------------------- - -Map lumps are loaded with the map as long as they are right after each other. -When the editor meets a lump which is not defined in this list (or defined -as 0), it will stop loading right there. - -The order of items defines the order in which lumps will be written to WAD file -on save. The value (flags) of items determines what the editor should do with -it. You should never mess with value 4, because it may result in incorrect map -builds. - - 1 = Lump required. - 2 = Lump which must be respected. - 4 = Lump generated by node builder. - 8 = Lump allowed to be empty after nodebuilding. - 16 = Lump allowed to be missing after nodebuilding. - 4096 = Lump which can be edited as text. - 8192 = Lump which can be edited as DEHACKED. -12288 = Lump which can be edited as MAPINFO. -16384 = WAD-global. - -*/ - -maplumpnames -{ - THINGS = 13; - LINEDEFS = 5; - SIDEDEFS = 5; - VERTEXES = 5; - SEGS = 4; - SSECTORS = 4; - NODES = 4; - SECTORS = 5; - REJECT = 4; - BLOCKMAP = 20; - MAINCFG = 24576; -} - -// DEFAULT SECTOR BRIGHTNESS LEVELS -------------------------------------------- - -sectorbrightness -{ - 255; - 240; - 224; - 208; - 192; - 176; - 160; - 144; - 128; - 112; - 96; - 80; - 64; - 48; - 32; - 16; - 0; -} - -// SECTOR TYPES ---------------------------------------------------------------- - -sectortypes -{ - nybble0 - { - 0 = "(normal)"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Modifications)"; - 7 = "Death Pit (No Camera Modifications)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (No Floor Touch)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy Sector (FOF Control Only)"; - } - - nybble1 - { - 0 = "(normal)"; - 1 = "Trigger Line Ex. (Pushable Objects)"; - 2 = "Trigger Line Ex. (Anywhere, All Players)"; - 3 = "Trigger Line Ex. (Floor Touch, All Players)"; - 4 = "Trigger Line Ex. (Anywhere in Sector)"; - 5 = "Trigger Line Ex. (Floor Touch)"; - 6 = "Trigger Line Ex. (Emerald Check)"; - 7 = "Trigger Line Ex. (Nights Mare)"; - 8 = " Check for Line Exec. on FOFs"; - 9 = "Egg Trap Capsule"; - 10 = "Special Stage Time/Rings Parameters"; - 11 = "Custom Global Gravity"; - } - - nybble2 - { - 0 = "(normal)"; - 1 = "Ice/Sludge"; - 2 = "Wind/Current"; - 3 = "Ice/Sludge and Wind/Current"; - 4 = "Conveyor Belt"; - 5 = "Speed Pad (No Spin)"; - 6 = "Speed Pad (Spin)"; - 7 = "Bustable Block Sprite Parameter (ROIA)"; - 8 = "Bustable Block Sprite Parameter (ROIB)"; - 9 = "Bustable Block Sprite Parameter (ROIC)"; - 10 = "Bustable Block Sprite Parameter (ROID)"; - 11 = "Bustable Block Sprite Parameter (ROIE)"; - 12 = "Bustable Block Sprite Parameter (ROIF)"; - 13 = "Bustable Block Sprite Parameter (ROIG)"; - 14 = "Bustable Block Sprite Parameter (ROIH)"; - 15 = "Bustable Block Sprite Parameter (ROII)"; - } - - nybble3 - { - 0 = "(normal)"; - 1 = "Star Post Activator"; - 2 = "Exit/Special Stage Goal/Return Flag"; - 3 = "CTF: Red Team Base"; - 4 = "CTF: Blue Team Base"; - 5 = "Fan Sector"; - 6 = "Super Sonic Transform"; - 7 = "Spinner"; - 8 = "Zoom Tube Start"; - 9 = "Zoom Tube End"; - 10 = "Finish Line"; - 11 = "Rope Hang"; - } -} - -// LINEDEF FLAGS --------------------------------------------------------------- - -linedefflags -{ - 1 = "[0] Effect 6"; - 2 = "[1] Block Enemies"; - 4 = "[2] Double-Sided"; - 8 = "[3] Upper Unpegged"; - 16 = "[4] Lower Unpegged"; - 32 = "[5] Effect 1"; - 64 = "[6] Not Climbable"; - 128 = "[7] Effect 2"; - 256 = "[8] Effect 3"; - 512 = "[9] Effect 4"; - 1024 = "[10] Effect 5"; - 2048 = "[11] No Sonic"; - 4096 = "[12] No Tails"; - 8192 = "[13] No Knuckles"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - -// LINEDEF ACTIVATIONS --------------------------------------------------------- - -linedefactivations -{ -} - -/* FOF FLAGS ------------------------------------------------------------------- - -This is a hack. The FOF flag values have changed in 2.0, but the old 1.09.4 -values are hardcoded in the source for SRB2 Doom Builder. Until Oogaland fixes -this, I'm sticking some fake values in here to make 3D mode draw FOFs like it's -supposed to. --Neo - -Flags I've found relevant: - - 4 = Renders the walls. - 8 = Renders the planes. -32 = Doesn't cast a shadow. - -*/ - -fofs -{ - 100 = 12; - 101 = 44; - 102 = 44; - 103 = 36; - 104 = 40; - 105 = 32; - 120 = 12; - 121 = 12; - 122 = 8; - 123 = 8; - 140 = 12; - 141 = 12; - 142 = 8; - 143 = 12; - 144 = 12; - 145 = 8; - 146 = 4; - 150 = 12; - 151 = 12; - 152 = 12; - 160 = 12; - 170 = 12; - 171 = 12; - 172 = 12; - 173 = 12; - 174 = 12; - 175 = 12; - 176 = 12; - 177 = 12; - 178 = 12; - 179 = 12; - 180 = 12; - 190 = 12; - 191 = 44; - 192 = 44; - 193 = 32; - 194 = 12; - 195 = 12; - 200 = 0; - 201 = 0; - 202 = 0; - 220 = 12; - 221 = 44; - 222 = 36; - 223 = 32; - 250 = 12; - 251 = 12; - 252 = 12; - 253 = 12; - 254 = 12; - 255 = 12; - 256 = 12; - 257 = 12; - 258 = 44; - 259 = 12; -} - -// LINEDEF TYPES --------------------------------------------------------------- - -linedeftypes -{ - 0 = "Miscellaneous: (normal)"; - 1 = "Miscellaneous: Per-Sector Gravity"; - 2 = "Parameters: Custom Exit"; - 3 = "Parameters: Zoom Tube Parameters"; - 4 = "Miscellaneous: Speed Pad"; - 5 = "Miscellaneous: Camera Scanner"; - 6 = "Miscellaneous: Disable Linedef Effect On Level Load"; - 7 = "Miscellaneous: Sector Flat Alignment"; - 8 = "Parameters: Sector Special Parameters"; - 9 = "Parameters: Chain Parameters"; - 10 = "Miscellaneous: Culling Plane"; - 11 = "Parameters: Rope Hang Parameters"; - 12 = "Parameters: Rock Spawn Parameters"; - 13 = "Miscellaneous: Heat Wave Effect"; - 20 = "PolyObject: First Line"; - 21 = "PolyObject: Explicity Include Line"; - 22 = "PolyObject: Parameters"; - 30 = "PolyObject: Waving Flag"; - 50 = "Miscellaneous: Instantly Lower Floor On Level Load"; - 51 = "Miscellaneous: Instantly Raise Ceiling On Level Load"; - 52 = "Plane Movement: Continuously Falling Sector"; - 53 = "Plane Movement: Continuous Floor/Ceiling Mover"; - 54 = "Plane Movement: Continuous Floor Mover"; - 55 = "Plane Movement: Continuous Ceiling Mover"; - 56 = "Plane Movement: Continuous Two-Speed Floor/Ceiling Mover"; - 57 = "Plane Movement: Continuous Two-Speed Floor Mover"; - 58 = "Plane Movement: Continuous Two-Speed Ceiling Mover"; - 59 = "Plane Movement: Activate Moving Platform"; - 60 = "Plane Movement: Activate Moving Platform (Adjustable Speed)"; - 61 = "Plane Movement: Crusher (Ceiling to Floor)"; - 62 = "Plane Movement: Crusher (Floor to Ceiling)"; - 63 = "Miscellaneous: Fake Floor/Ceiling Planes"; - 64 = "Parameters: Appearing/Disappearing FOF"; - 65 = "Parameters: Bridge Thinker"; - 100 = "FOF (solid): Solid, Opaque"; - 101 = "FOF (solid): Solid, Opaque, No Shadow"; - 102 = "FOF (solid): Solid, Translucent"; - 103 = "FOF (solid): Solid, Sides Only"; - 104 = "FOF (solid): Solid, No Sides"; - 105 = "FOF (solid): Solid, Invisible"; - 120 = "FOF (intangible): Water, Opaque"; - 121 = "FOF (intangible): Water, Translucent"; - 122 = "FOF (intangible): Water, Opaque, No Sides"; - 123 = "FOF (intangible): Water, Translucent, No Sides"; - 140 = "FOF (solid): Intangible from Bottom, Opaque"; - 141 = "FOF (solid): Intangible from Bottom, Translucent"; - 142 = "FOF (solid): Intangible from Bottom, Translucent, No Sides"; - 143 = "FOF (solid): Intangible from Top, Opaque"; - 144 = "FOF (solid): Intangible from Top, Translucent"; - 145 = "FOF (solid): Intangible from Top, Translucent, No Sides"; - 146 = "FOF (solid): Only Tangible From Sides"; - 150 = "FOF (bobbing): Air Bobbing"; - 151 = "FOF (bobbing): Air Bobbing (Adjustable)"; - 152 = "FOF (bobbing): Reverse Air Bobbing (Adjustable)"; - 160 = "FOF (bobbing): Floating, Bobbing"; - 170 = "FOF (crumbling): Crumbling (Respawn)"; - 171 = "FOF (crumbling): Crumbling (No Respawn)"; - 172 = "FOF (crumbling): Crumbling (Respawn), Intangible from Bottom"; - 173 = "FOF (crumbling): Crumbling (No Respawn), Intangible from Bottom"; - 174 = "FOF (crumbling): Crumbling (Respawn), Int. from Bottom, Translucent"; - 175 = "FOF (crumbling): Crumbling (No Respawn), Int. from Bottom, Translucent"; - 176 = "FOF (crumbling): Crumbling (Respawn), Floating, Bobbing"; - 177 = "FOF (crumbling): Crumbling (No Respawn), Floating, Bobbing"; - 178 = "FOF (crumbling): Crumbling (Respawn), Floating"; - 179 = "FOF (crumbling): Crumbling (No Respawn), Floating"; - 180 = "FOF (crumbling): Crumbling (Respawn), Air Bobbing"; - 190 = "FOF (bobbing): Rising Platform, Solid, Opaque"; - 191 = "FOF (bobbing): Rising Platform, Solid, Opaque, No Shadow"; - 192 = "FOF (bobbing): Rising Platform, Solid, Translucent"; - 193 = "FOF (bobbing): Rising Platform, Solid, Invisible"; - 194 = "FOF (bobbing): Rising Platform, Intangible from Bottom, Opaque"; - 195 = "FOF (bobbing): Rising Platform, Intangible from Bottom, Translucent"; - 200 = "FOF (special): Light Block"; - 201 = "FOF (special): Half Light Block"; - 202 = "FOF (special): Fog Block"; - 220 = "FOF (intangible): Intangible, Opaque"; - 221 = "FOF (intangible): Intangible, Translucent"; - 222 = "FOF (intangible): Intangible, Sides Only"; - 223 = "FOF (intangible): Intangible, Invisible"; - 250 = "FOF (special): Mario Block"; - 251 = "FOF (special): Thwomp Block"; - 252 = "FOF (special): Shatter Block"; - 253 = "FOF (special): Shatter Block, Translucent"; - 254 = "FOF (special): Bustable Block"; - 255 = "FOF (special): Spin Bust Block"; - 256 = "FOF (special): Spin Bust Block, Translucent"; - 257 = "FOF (special): Quicksand"; - 258 = "FOF (special): Laser"; - 259 = "FOF (special): Custom FOF"; - 300 = "Linedef Executor Trigger: Continuous"; - 301 = "Linedef Executor Trigger: Each Time"; - 302 = "Linedef Executor Trigger: Once"; - 303 = "Linedef Executor Trigger: Ring Count - Continuous"; - 304 = "Linedef Executor Trigger: Ring Count - Once"; - 305 = "Linedef Executor Trigger: Character Ability - Once"; - 306 = "Linedef Executor Trigger: Character Ability - Each Time"; - 307 = "Linedef Executor Trigger: Character Ability - Continuous"; - 308 = "Linedef Executor Trigger: Race Only - Once"; - 309 = "Linedef Executor Trigger: CTF Red Team - Continuous"; - 310 = "Linedef Executor Trigger: CTF Red Team - Each Time"; - 311 = "Linedef Executor Trigger: CTF Blue Team - Continuous"; - 312 = "Linedef Executor Trigger: CTF Blue Team - Each Time"; - 313 = "Linedef Executor Trigger: No More Enemies - Once"; - 314 = "Linedef Executor Trigger: Number of Pushables - Continuous"; - 315 = "Linedef Executor Trigger: Number of Pushables - Once"; - 316 = "Linedef Executor Trigger: Land On PolyObject"; - 399 = "Linedef Executor Trigger: Level Load"; - 400 = "Linedef Executor (sector): Set Tagged Sector's Floor Height/Texture"; - 401 = "Linedef Executor (sector): Set Tagged Sector's Ceiling Height/Texture"; - 402 = "Linedef Executor (sector): Set Tagged Sector's Light Level"; - 403 = "Linedef Executor (plane movement): Move Tagged Sector's Floor"; - 404 = "Linedef Executor (plane movement): Move Tagged Sector's Ceiling"; - 405 = "Linedef Executor (plane movement): Lower Floor According to Linedef"; - 406 = "Linedef Executor (plane movement): Raise Floor According to Linedef"; - 407 = "Linedef Executor (plane movement): Lower Ceiling According to Linedef"; - 408 = "Linedef Executor (plane movement): Raise Ceiling According to Linedef"; - 409 = "Linedef Executor (sector): Change Tagged Sectors' Tag"; - 410 = "Linedef Executor (sector): Change Front Sector's Tag"; - 411 = "Linedef Executor (plane movement): Stop Plane Movement"; - 412 = "Linedef Executor (player/object): Teleporter"; - 413 = "Linedef Executor (misc.): Change Music"; - 414 = "Linedef Executor (misc.): Play Sound Effect"; - 415 = "Linedef Executor (misc.): Run Script"; - 416 = "Linedef Executor (sector): Start Adjustable Fire Flicker"; - 417 = "Linedef Executor (sector): Start Adjustable Glowing Light"; - 418 = "Linedef Executor (sector): Start Adjustable Blinking Light (unsynchronized)"; - 419 = "Linedef Executor (sector): Start Adjustable Blinking Light (synchronized)"; - 420 = "Linedef Executor (sector): Fade Light Level"; - 421 = "Linedef Executor (sector): Stop Lighting Effect"; - 422 = "Linedef Executor (misc.): Switch To Cut-Away View"; - 423 = "Linedef Executor (misc.): Change Sky"; - 424 = "Linedef Executor (misc.): Change Weather"; - 425 = "Linedef Executor (player/object): Change Object State"; - 426 = "Linedef Executor (player/object): Stop Object"; - 427 = "Linedef Executor (player/object): Award Score"; - 428 = "Linedef Executor (plane movement): Start Platform Movement"; - 429 = "Linedef Executor (plane movement): Crush Ceiling Once"; - 430 = "Linedef Executor (plane movement): Crush Floor Once"; - 431 = "Linedef Executor (plane movement): Crush Floor And Ceiling Once"; - 432 = "Linedef Executor (player/object): Enable 2D Mode"; - 433 = "Linedef Executor (player/object): Disable 2D Mode"; - 434 = "Linedef Executor (player/object): Award Power-Up"; - 435 = "Linedef Executor (sector): Change Plane Scroller Direction"; - 436 = "Linedef Executor (misc.): Shatter FOF"; - 437 = "Linedef Executor (player/object): Disable Player Control"; - 438 = "Linedef Executor (player/object): Change Object Size"; - 450 = "Linedef Executor (misc.): Execute Linedef Executor"; - 480 = "Linedef Executor (polyobject): Door Slide"; - 481 = "Linedef Executor (polyobject): Door Swing"; - 482 = "Linedef Executor (polyobject): Move"; - 483 = "Linedef Executor (polyobject): Move, Override"; - 484 = "Linedef Executor (polyobject): Rotate Right"; - 485 = "Linedef Executor (polyobject): Rotate Right, Override"; - 486 = "Linedef Executor (polyobject): Rotate Left"; - 487 = "Linedef Executor (polyobject): Rotate Left, Override"; - 488 = "Linedef Executor (polyobject): Move by Waypoints"; - 489 = "Linedef Executor (polyobject): Turn Invisible, Intangible"; - 490 = "Linedef Executor (polyobject): Turn Visible, Tangible"; - 491 = "Linedef Executor (polyobject): Set Translucency"; - 500 = "Wall Scrolling: Scroll Wall Front Side Left"; - 501 = "Wall Scrolling: Scroll Wall Front Side Right"; - 502 = "Wall Scrolling: Scroll Wall According to Linedef"; - 503 = "Wall Scrolling: Scroll Wall According to Linedef (Accelerative)"; - 504 = "Wall Scrolling: Scroll Wall According to Linedef (Displacement)"; - 505 = "Wall Scrolling: Scroll Texture by Front Side Offsets"; - 506 = "Wall Scrolling: Scroll Texture by Back Side Offsets"; - 510 = "Plane Scrolling: Scroll Floor Texture"; - 511 = "Plane Scrolling: Scroll Floor Texture (Accelerative)"; - 512 = "Plane Scrolling: Scroll Floor Texture (Displacement)"; - 513 = "Plane Scrolling: Scroll Ceiling Texture"; - 514 = "Plane Scrolling: Scroll Ceiling Texture (Accelerative)"; - 515 = "Plane Scrolling: Scroll Ceiling Texture (Displacement)"; - 520 = "Plane Scrolling: Carry Objects on Floor"; - 521 = "Plane Scrolling: Carry Objects on Floor (Accelerative)"; - 522 = "Plane Scrolling: Carry Objects on Floor (Displacement)"; - 523 = "Plane Scrolling: Carry Objects on Ceiling"; - 524 = "Plane Scrolling: Carry Objects on Ceiling (Accelerative)"; - 525 = "Plane Scrolling: Carry Objects on Ceiling (Displacement)"; - 530 = "Plane Scrolling: Scroll Floor Texture and Carry Objects"; - 531 = "Plane Scrolling: Scroll Floor Texture and Carry Objects (Accelerative)"; - 532 = "Plane Scrolling: Scroll Floor Texture and Carry Objects (Displacement)"; - 533 = "Plane Scrolling: Scroll Ceiling Texture and Carry Objects"; - 534 = "Plane Scrolling: Scroll Ceiling Texture and Carry Objects (Accelerative)"; - 535 = "Plane Scrolling: Scroll Ceiling Texture and Carry Objects (Displacement)"; - 540 = "Miscellaneous: Floor Friction"; - 541 = "Pusher: Wind"; - 542 = "Pusher: Upwards Wind"; - 543 = "Pusher: Downwards Wind"; - 544 = "Pusher: Current"; - 545 = "Pusher: Upwards Current"; - 546 = "Pusher: Downwards Current"; - 547 = "Pusher: Push/Pull"; - 600 = "Lighting: Floor Lighting"; - 601 = "Lighting: Ceiling Lighting"; - 602 = "Lighting: Adjustable Pulsating Light"; - 603 = "Lighting: Adjustable Flickering Light"; - 604 = "Lighting: Adjustable Blinking Light (unsynchronized)"; - 605 = "Lighting: Adjustable Blinking Light (synchronized)"; - 606 = "Lighting: Colormap"; - 900 = "Translucent Wall: 90% Opaque"; - 901 = "Translucent Wall: 80% Opaque"; - 902 = "Translucent Wall: 70% Opaque"; - 903 = "Translucent Wall: 60% Opaque"; - 904 = "Translucent Wall: 50% Opaque"; - 905 = "Translucent Wall: 40% Opaque"; - 906 = "Translucent Wall: 30% Opaque"; - 907 = "Translucent Wall: 20% Opaque"; - 908 = "Translucent Wall: 10% Opaque"; - 909 = "Translucent Wall: Fog Wall"; -} - -// THING FLAGS ----------------------------------------------------------------- - -thingflags -{ - 1 = "[0] Unused Flag"; - 2 = "[1] Object Flip"; - 4 = "[2] Object Special"; - 8 = "[3] Ambush"; - 16 = "(Used for Z offsets)"; -} - -/* THING TYPES ----------------------------------------------------------------- - -Color values: 1 = Blue 9 = Light_Blue - 2 = Green 10 = Light_Green - 3 = Cyan 11 = Light_Cyan - 4 = Red 12 = Light_Red - 5 = Magenta 13 = Pink - 6 = Brown 14 = Yellow - 7 = Gray 15 = White - 8 = Dark_Gray - -*/ - -thingtypes -{ - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 32000 = "3D Mode Start"; - 32001 - { - arrow = 0; - title = "Control Sector Position Hint"; - } - } - - starts - { - color = 1; // Blue - arrow = 1; - title = "Player Starts"; - width = 16; - height = 56; - zfactor = 32; - deaftext = "[3] Spawn On Ceiling"; - - 1 - { - title = "Player 01 Start"; - sprite = "SUPTD0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "SUPTD0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "SUPTD0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "SUPTD0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "SUPTD0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "SUPTD0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "SUPTD0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "SUPTD0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "SUPTD0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "SUPTD0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "SUPTD0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "SUPTD0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "SUPTD0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "SUPTD0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "SUPTD0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "SUPTD0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "SUPTD0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "SUPTD0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "SUPTD0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "SUPTD0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "SUPTD0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "SUPTD0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "SUPTD0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "SUPTD0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "SUPTD0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "SUPTD0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "SUPTD0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "SUPTD0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "SUPTD0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "SUPTD0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "SUPTD0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "SUPTD0"; - } - 33 - { - title = "Match Start"; - sprite = "SUPTI0"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - - enemies - { - color = 9; // Light_Blue - arrow = 1; - title = "Enemies"; - width = 24; - height = 32; - sort = 1; - - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 20; - height = 24; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 20; - height = 24; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - } - 111 - { - title = "Popup Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - } - 112 - { - title = "Sharp"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - height = 48; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - deaftext = "[3] Unknown Effect"; - } - 118 - { - title = "CastleBot FaceStabber"; - sprite = "CBFSA1"; - width = 32; - height = 64; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA1"; - } - 750 - { - title = " Chaos Enemy Spawn"; - sprite = "TFOGG0"; - width = 32; - height = 64; - } - } - - bosses - { - color = 8; // Dark_Gray - arrow = 1; - title = "Bosses"; - width = 24; - height = 52; - sort = 1; - zfactor = 32; - - 200 - { - title = "Boss 1 - Egg Mobile"; - sprite = "EGGMA1"; - deaftext = "[3] Rotating Spikeballs"; - } - 201 - { - title = "Boss 2 - Egg Slimer"; - sprite = "EGGNA1"; - height = 48; - deaftext = "[3] Speed Up When Hit"; - } - 202 - { - title = "Boss 3 - Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 80; - deaftext = "[3] Unknown Effect"; - } - 203 - { - title = " Boss 4 - Eggscalibur"; - sprite = "EGGPA1"; - } - 206 - { - title = "Boss 5 - Black Eggman"; - sprite = "BRAKB1"; - width = 48; - height = 160; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - zfactor = 16; - } - 291 - { - arrow = 0; - title = "Egg Trap Center"; - width = 8; - height = 16; - zfactor = 16; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - zfactor = 16; - } - } - - rings - { - color = 14; // Yellow - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "CPRKB0"; - } - 302 - { - title = "Rail Ring"; - sprite = "SPRKA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "TAUTA3A7"; - } - 305 - { - title = "Explosion Ring"; - sprite = "BMSLA1"; - } - 306 - { - title = "Scatter Ring"; - sprite = "TSCRA1A5"; - } - 307 - { - title = "Grenade Ring"; - sprite = "TGREA0"; - } - 339 - { - title = "Turbo Ring"; - sprite = "BMSLA1"; - } - 340 - { - title = "Mine Ring"; - sprite = "TSCRA1A5"; - } - 341 - { - title = "Bright Fluorescent Ring"; - sprite = "TGREA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "TRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "PIKGA0"; - } - 336 - { - title = "Turbo Ring Panel"; - sprite = "PIKEA0"; - } - 337 - { - title = "Mine Ring Panel"; - sprite = "PIKSA0"; - } - 338 - { - title = "Bright Fluorescent Ring Panel"; - sprite = "PIKGA0"; - } - } - - collectibles - { - color = 10; // Light_Green - title = "Other Collectibles"; - width = 16; - height = 32; - sort = 1; - - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Special Stage Token"; - sprite = "TOKEA0"; - width = 8; - height = 16; - deafheight = 32; - deaftext = "[3] Float"; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "EMMYA0"; - } - 314 - { - title = "Chaos Emerald 2 (Orange)"; - sprite = "EMMYB0"; - } - 315 - { - title = "Chaos Emerald 3 (Purple)"; - sprite = "EMMYC0"; - } - 316 - { - title = "Chaos Emerald 4 (Blue)"; - sprite = "EMMYD0"; - } - 317 - { - title = "Chaos Emerald 5 (Red)"; - sprite = "EMMYE0"; - } - 318 - { - title = "Chaos Emerald 6 (Light Blue)"; - sprite = "EMMYF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "EMMYG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "EMERA0"; - } - 323 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - width = 8; - height = 48; - deafheight = 32; - deaftext = "[3] Float"; - } - } - - boxes - { - color = 7; // Gray - blocking = 2; - title = "Item Boxes"; - width = 16; - height = 32; - deaftext = "[3] Random (Weak)"; - sort = 1; - - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "SRBXA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "YLTVA0"; - } - 403 - { - title = "Force Shield"; - sprite = "BLTVA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "BKTVA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "WHTVA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "GRTVA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "SHTVA0"; - } - 408 - { - title = "Invincibility"; - sprite = "PINVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "MTEXA0"; - } - 410 - { - title = "Eggman"; - sprite = "EGGBA0"; - } - 411 - { - title = "Teleporter"; - sprite = "MIXUA0"; - } - 412 - { - title = "Random"; - sprite = "QUESA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "GBTVA0"; - } - 414 - { - title = "CTF Team Ring Box (Red)"; - sprite = "RRBXA0"; - deaftext = "[3] Ambush"; - } - 415 - { - title = "CTF Team Ring Box (Blue)"; - sprite = "BRBXA0"; - deaftext = "[3] Ambush"; - } - 416 - { - title = "Recycler"; - sprite = "RECYA0"; - } - } - - miscellaneous - { - color = 11; // Light_Cyan - title = "Miscellaneous"; - width = 16; - height = 40; - sort = 1; - - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLA0"; - width = 8; - height = 16; - } - 501 - { - title = "End Level Sign"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0"; - width = 64; - height = 80; - } - 526 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - deaftext = "[3] Not Pushable"; - } - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - deaftext = "[3] Not Pushable"; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - deaftext = "[3] Not Pushable"; - } - 1106 - { - arrow = 1; - title = "Chain (Hang)"; - sprite = "SMCHA0"; - height = 32; - deaftext = "[3] Double Size"; - } - 1107 - { - arrow = 1; - title = "Chain (Spin)"; - sprite = "SMCHA0"; - height = 32; - } - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 48; - deaftext = "[3] Moves Perpetually"; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - deaftext = "[3] Moves Perpetually"; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - deaftext = "[3] Not Pushable"; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - deaftext = "[3] Not Pushable"; - } - } - - springs - { - color = 12; // Light_Red - title = "Springs and Fans"; - width = 20; - height = 16; - - 540 - { - title = "Fan"; - sprite = "FANSA0"; - width = 16; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - width = 32; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 553 - { - title = "Yellow Spring (Ceiling)"; - sprite = "SUDYA0"; - } - 554 - { - title = "Red Spring (Ceiling)"; - sprite = "SUDRA0"; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - 557 - { - arrow = 1; - title = "Diagonal Yellow Spring (Ceiling)"; - sprite = "YSUDE2"; - width = 16; - hangs = 1; - deaftext = "[3] Rotate 22.5° CCW"; - } - 558 - { - arrow = 1; - title = "Diagonal Red Spring (Ceiling)"; - sprite = "RSUDE2"; - width = 16; - hangs = 1; - deaftext = "[3] Rotate 22.5° CCW"; - } - } - - patterns - { - color = 5; // Magenta - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - } - 606 - { - title = "Circle of Wing Logos"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 607 - { - title = "Circle of Wing Logos (Big)"; - sprite = "NWNGA0"; - width = 192; - } - 608 - { - title = "Circle of Rings and Wings"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 609 - { - title = "Circle of Rings and Wings (Big)"; - sprite = "NWNGA0"; - width = 192; - } - } - - invisible - { - color = 15; // White - title = "Misc. Invisible"; - width = 8; - height = 16; - - 700 = "Water Ambience A (Large)"; - 701 = "Water Ambience B (Large)"; - 702 = "Water Ambience C (Medium)"; - 703 = "Water Ambience D (Medium)"; - 704 = "Water Ambience E (Small)"; - 705 = "Water Ambience F (Small)"; - 706 = "Water Ambience G (Extra Large)"; - 707 = "Water Ambience H (Extra Large)"; - 708 = "Disco Ambience"; - 709 = "Volcano Ambience"; - 751 - { - arrow = 1; - title = "Teleport Destination"; - } - 752 - { - arrow = 1; - title = "Alternate View Point"; - } - 753 = "Zoom Tube Waypoint"; - 754 - { - title = "Push Point"; - deaftext = "[3] Push Using XYZ"; - } - 755 - { - title = "Pull Point"; - deaftext = "[3] Pull Using XYZ"; - } - 760 = "PolyObject Anchor"; - 761 = "PolyObject Spawn Point"; - 762 = "PolyObject Spawn Point (Crush)"; - } - - hazards - { - color = 4; // Red - title = "Hazards"; - width = 20; - height = 40; - sort = 1; - - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 522 - { - blocking = 2; - title = "Spike (Ceiling)"; - sprite = "DSPKA0"; - width = 8; - height = 42; - hangs = 1; - } - 523 - { - title = "Spike (Floor)"; - sprite = "USPKA0"; - width = 8; - height = 42; - deaftext = "[3] Solid"; - } - 524 - { - arrow = 1; - title = "Big Floating Mine"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 527 - { - arrow = 1; - title = "Big Floating Mine (Air)"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 525 - { - title = "Cannonball Launcher"; - sprite = "CBLLA0"; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0"; - width = 8; - height = 32; - } - 1104 - { - title = "Mace (Spinning)"; - sprite = "SMCEA0"; - deaftext = "[3] Double Size"; - } - 1105 - { - title = "Mace (Swinging)"; - sprite = "SMCEA0"; - deaftext = "[3] Double Size"; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - } - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "FLMEB0"; - width = 16; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "FLMEB0"; - width = 16; - deaftext = "[3] Shoot Downwards"; - } - } - - decoration - { - color = 2; // Green - title = "Decoration"; - width = 16; - height = 40; - - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - } - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - height = 32; - } - 900 - { - title = "THZ Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CRL1A0"; - width = 8; - height = 16; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CRL2A0"; - width = 8; - height = 16; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CRL3A0"; - width = 8; - height = 16; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1100 - { - title = "Chain"; - sprite = "CHANA0"; - width = 8; - height = 128; - hangs = 1; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - } - 1203 - { - title = "Cactus with Brown Flower"; - sprite = "CACTA0"; - height = 32; - } - 1204 - { - title = "Cactus with Brown Flower (Tall)"; - sprite = "CACTB0"; - height = 64; - } - 1205 - { - title = "Cactus with Blue Flower"; - sprite = "CACTC0"; - height = 32; - } - 1206 - { - title = "Cactus with Blue Flower (Tall)"; - sprite = "CACTD0"; - height = 80; - } - 1850 - { - title = "Xmas Pole"; - sprite = "XMS1A0"; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - height = 54; - hangs = 1; - } - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STG0A0"; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STG1A0"; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STG2A0"; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STG3A0"; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STG4A0"; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STG5A0"; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STG6A0"; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STG7A0"; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STG8A0"; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STG9A0"; - } - } - - nights - { - color = 13; // Pink - title = "Nights Items"; - width = 12; - height = 32; - - 1700 - { - title = "Axis"; - width = 8; - height = 4096; - circle = 1; - } - 1701 - { - title = "Axis Transfer"; - width = 8; - height = 4096; - } - 1702 - { - title = "Axis Transfer Line"; - width = 8; - height = 4096; - } - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - deaftext = "[3] Die Upon Time Up"; - } - 1704 - { - arrow = 1; - title = "Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - } - 1705 - { - arrow = 1; - title = "Hoop"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1706 - { - title = "Wing Logo"; - sprite = "NWNGA0"; - height = 24; - } - 1707 - { - title = "Super Loop"; - sprite = "NPRAA0"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRBA0"; - } - 1709 - { - title = "Helper"; - sprite = "NPRCA0"; - } - 1710 - { - title = "Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - mario - { - color = 6; // Brown - title = "Mario Items"; - width = 16; - height = 32; - sort = 1; - - 1800 - { - title = "Coin"; - sprite = "COINA0"; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA0"; - width = 8; - height = 16; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - height = 28; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - } - } - - srb1 - { - color = 3; // Cyan - arrow = 1; - title = "SRB1 Remake Items"; - width = 20; - height = 32; - sort = 1; - - 4000 - { - title = "SRB1 Crawla"; - sprite = "SRBAA1"; - height = 40; - } - 4001 - { - title = "GuardRobo"; - sprite = "SRBBA1"; - width = 17; - height = 40; - } - 4002 - { - title = "Pyrin"; - sprite = "SRBCB1"; - width = 22; - } - 4003 - { - title = "HotRobo"; - sprite = "SRBDA0"; - height = 40; - } - 4004 - { - title = "Pogminz"; - sprite = "SRBEA1"; - } - 4005 - { - title = "Pogminz (Water)"; - sprite = "SRBEA1"; - } - 4006 - { - title = "Pog-GX2"; - sprite = "SRBFA0"; - width = 10; - height = 34; - } - 4007 - { - title = "Pyrex"; - sprite = "SRBGA1"; - width = 24; - } - 4008 - { - title = "UFO"; - sprite = "SRBHA0"; - width = 24; - hangs = 1; - } - 4009 - { - title = "SWAT Bot"; - sprite = "SRBIA1"; - width = 21; - height = 69; - } - 4010 - { - title = "SpyBot 2000"; - sprite = "SRBJA0"; - width = 36; - height = 62; - } - 4011 - { - title = "Buzz Bomber"; - sprite = "SRBKA0"; - width = 44; - height = 45; - } - 4012 - { - arrow = 0; - title = "RBZ Spike"; - sprite = "SRBLA0"; - width = 10; - height = 53; - } - 4013 - { - arrow = 0; - blocking = 2; - title = "Dumb Metal Sonic"; - sprite = "SRBMC0"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 4014 - { - title = "Super SWAT Bot"; - sprite = "SRBNA1"; - width = 21; - height = 69; - } - 4015 - { - title = "Genrex"; - sprite = "SRBOA1"; - width = 17; - height = 40; - } - } -} diff --git a/extras/conf/Srb2-20wb.cfg b/extras/conf/Srb2-20wb.cfg deleted file mode 100644 index d4ccd6971..000000000 --- a/extras/conf/Srb2-20wb.cfg +++ /dev/null @@ -1,2364 +0,0 @@ -/******************************************************************************\ - - SRB2 Workbench - Game Configuration for SRB2 version 2.0. - - Contributors: - - Kristos - - Shadow Hog - - ST218 - - Foxboy - - JJames19119 - - SRB2-Playah - - Oogaland - - SSNTails - - DarkWarrior - - Neo - -\******************************************************************************/ - -// This is required to prevent accedential use of a different configuration. -type = "SRB2 Workbench Game Configuration"; - -// This is the title to show for this game. -game = "Sonic Robo Blast 2 v2.0"; - -// This is used internally to refer to the game. -id = "srb2-20wb"; - -// Flags for changes in 2.0. -seceffectnybble = 1; -thingeffectnybble = 1; - -// Defaults for new thing. -defaultthingflags = 0; -defaultthing = 1; - -// Flags indicating which header features are supported. See -// ENUM_MAPHEADER_FLAGS in soc.h for values. -headerflags = 29360130; // Map Credits, Run SOC, Subtitle, Speed Music. - -// Thing numbers for Nights axes. -nights -{ - axistransfer = 1701; - axistransferline = 1702; -} - -// Wiki page names. -wiki -{ - seceffect = "Sector+Type+%d"; - ldeffect = "Linedef+Type+%d"; - thing = "Thing+Type+%d"; -} - -// Map-type flags for the TypeOfLevel header option. -leveltypes -{ - 1 = "Cooperative"; - 2 = "Race"; - 4 = "Match"; - 8 = "Tag"; - 16 = "Capture the Flag"; - 32 = " Chaos"; - 64 = "Nights"; - 128 = " Adventure"; - 256 = "Mario"; - 512 = "2D"; - 1024 = " Xmas"; - 2048 = "Egg Rock Zone 3"; - 4096 = "Single Player"; - 8192 = "SRB1 Remake"; -} - -// Weather types for use in the header-editor. -weather -{ - 0 = "None"; - 1 = "Storm"; - 2 = "Snow"; - 3 = "Rain"; - 4 = "Blank (precalculate)"; - 5 = "Storm (no rain)"; - 6 = "Storm (no strikes)"; - 7 = "Heat Wave"; -} - -/* PSEUDO-FLATS AND TEXTURES --------------------------------------------------- - -Names of flats and textures that don't really exist, but shouldn't be identified -as invalid. - -Pattern-matching is performed on lump names. You can use the following wildcards -in values to specify ranges: - -? = Any character. -* = Zero or more characters. -# = Any numeric digit. -[abc...] = Any of these characters that are between brackets. -[!abc..] = Not any of these characters that are between brackets. - -TODO: Not actually used yet! - -*/ - -pseudoflats -{ - F_SKY1; -} - -pseudotextures -{ - [#]*; -} - -// Sky flat, used to determine whether upper/lower textures are required. -sky = "F_SKY1"; - -/* MAP LUMP NAMES -------------------------------------------------------------- - -Map lumps are loaded with the map as long as they are right after each other. -When the editor meets a lump which is not defined in this list, it will stop -loading right there. - - 1 = Lump required. - 2 = Lump which must be respected. - 4 = Lump generated by node builder. - 8 = Lump allowed to be empty after nodebuilding. - 16 = Lump allowed to be missing after nodebuilding. - 4096 = Lump which can be edited as text. - 8192 = Lump which can be edited as DEHACKED. -12288 = Lump which can be edited as MAPINFO. -16384 = WAD-global. - -*/ - -maplumpnames -{ - THINGS = 13; - LINEDEFS = 5; - SIDEDEFS = 5; - VERTEXES = 5; - SEGS = 4; - SSECTORS = 4; - NODES = 4; - SECTORS = 5; - REJECT = 4; - BLOCKMAP = 20; -} - -// SECTOR TYPES ---------------------------------------------------------------- - -sectortypes -{ - nybble0 - { - 0 = "(normal)"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Modifications)"; - 7 = "Death Pit (No Camera Modifications)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (No Floor Touch)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy Sector (FOF Control Only)"; - } - - nybble1 - { - 0 = "(normal)"; - 1 = "Trigger Linedef Executor (Pushable Objects)"; - 2 = "Trigger Linedef Executor (Anywhere, All Players)"; - 3 = "Trigger Linedef Executor (Floor Touch, All Players)"; - 4 = "Trigger Linedef Executor (Anywhere in Sector)"; - 5 = "Trigger Linedef Executor (Floor Touch)"; - 6 = "Trigger Linedef Executor (Emerald Check)"; - 7 = "Trigger Linedef Executor (Nights Mare)"; - 8 = " Check for Linedef Executor on FOFs"; - 9 = "Egg Trap Capsule"; - 10 = "Special Stage Time/Rings Parameters"; - 11 = "Custom Global Gravity"; - } - - nybble2 - { - 0 = "(normal)"; - 1 = "Ice/Sludge"; - 2 = "Wind/Current"; - 3 = "Ice/Sludge and Wind/Current"; - 4 = "Conveyor Belt"; - 5 = "Speed Pad (No Spin)"; - 6 = "Speed Pad (Spin)"; - 7 = "Bustable Block Sprite Parameter (ROIA)"; - 8 = "Bustable Block Sprite Parameter (ROIB)"; - 9 = "Bustable Block Sprite Parameter (ROIC)"; - 10 = "Bustable Block Sprite Parameter (ROID)"; - 11 = "Bustable Block Sprite Parameter (ROIE)"; - 12 = "Bustable Block Sprite Parameter (ROIF)"; - 13 = "Bustable Block Sprite Parameter (ROIG)"; - 14 = "Bustable Block Sprite Parameter (ROIH)"; - 15 = "Bustable Block Sprite Parameter (ROII)"; - } - - nybble3 - { - 0 = "(normal)"; - 1 = "Star Post Activator"; - 2 = "Exit/Special Stage Goal/Return Flag"; - 3 = "CTF: Red Team Base"; - 4 = "CTF: Blue Team Base"; - 5 = "Fan Sector"; - 6 = "Super Sonic Transform"; - 7 = "Spinner"; - 8 = "Zoom Tube Start"; - 9 = "Zoom Tube End"; - 10 = "Finish Line"; - 11 = "Rope Hang"; - } -} - -// LINEDEF FLAGS --------------------------------------------------------------- - -linedefflags -{ - 1 = "[00] Effect 6"; - 2 = "[01] Block Enemies"; - 4 = "[02] Double-Sided"; - 8 = "[03] Upper Unpegged"; - 16 = "[04] Lower Unpegged"; - 32 = "[05] Effect 1"; - 64 = "[06] Not Climbable"; - 128 = "[07] Effect 2"; - 256 = "[08] Effect 3"; - 512 = "[09] Effect 4"; - 1024 = "[10] Effect 5"; - 2048 = "[11] No Sonic"; - 4096 = "[12] No Tails"; - 8192 = "[13] No Knuckles"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - -// FOF INFORMATION ------------------------------------------------------------- - -fofs -{ - default = 100; - colourmap = 606; - defaultcustom = 259; - - // The FOF linedef specials, together with their FOF flags and a few - // other fields. - specials - { - 100 {flags = 415;} - 101 {flags = 479;} - 102 {flags = 6495;} - 103 {flags = 463;} - 104 {flags = 471;} - 105 {flags = 71;} - 120 {flags = 36665;} - 121 {flags = 40761;} - 122 {flags = 3889;} - 123 {flags = 7985;} - 140 {flags = 33588255;} - 141 {flags = 33560863;} - 142 {flags = 33560855;} - 143 {flags = 67142687;} - 144 {flags = 67115295;} - 145 {flags = 67115287;} - 146 {flags = 100696079;} - 150 {flags = 415; airbob = 1;} - 151 {flags = 415; airbob = 1;} - 152 {flags = 415; airbob = 1;} - 160 {flags = 262559; airbob = 1;} - 170 {flags = 1048991;} - 171 {flags = 1573279;} - 172 {flags = 34636831;} - 173 {flags = 35161119;} - 174 {flags = 34641311;} - 175 {flags = 35165599;} - 176 {flags = 1311135; airbob = 1;} - 177 {flags = 1835423; airbob = 1;} - 178 {flags = 1311135;} - 179 {flags = 1835423;} - 180 {flags = 1048991;} - 190 {flags = 415; rising = 1;} - 191 {flags = 479; rising = 1;} - 192 {flags = 6495; rising = 1;} - 193 {flags = 71; rising = 1;} - 194 {flags = 33588255; rising = 1;} - 195 {flags = 33594655; rising = 1;} - 200 {flags = 131585;} - 201 {flags = 513;} - 202 {flags = 257817;} - 220 {flags = 36633;} - 221 {flags = 6937;} - 222 {flags = 32777;} - 223 {flags = 65;} - 250 {flags = 4194719;} - 251 {flags = 415;} - 252 {flags = 142606367;} - 253 {flags = 142610463;} - 254 {flags = 8388639;} - 255 {flags = 276824095;} - 256 {flags = 276828191;} - 257 {flags = 16810521;} - 258 {flags = 2393;} - 259 {custom = 1;} - } - - // The significance of the FOF flags. Some of these have special - // meanings to the editor; for those which don't, the subsection name is - // ignored, but an entry will still be added to the list of flags for - // custom FOFs. - flags - { - FF_EXISTS {value = 1; text = "Exists.";} - FF_BLOCKPLAYER {value = 2; text = "Solid to players.";} - FF_BLOCKOTHERS {value = 4; text = "Solid to everything else.";} -// FF_SOLID {value = 6; text = "Solid to all objects."} - FF_RENDERSIDES {value = 8; text = "Renders the walls.";} - FF_RENDERPLANES {value = 16; text = "Renders the planes.";} -// FF_RENDERALL {value = 24; text = "Renders everything.} - FF_SWIMMABLE {value = 32; text = "Water block.";} - FF_NOSHADE {value = 64; text = "Doesn't cast a shadow.";} - FF_CUTSOLIDS {value = 128; text = "Skips rendering pixels hidden behind the block.";} - FF_CUTEXTRA {value = 256; text = "Skips rendering blocks marked with FF_EXTRA hidden behind the block.";} -// FF_CUTLEVEL {value = 384; text = "Skips rendering everything hidden behind the block."} - FF_CUTSPRITES {value = 512; text = "Splits sprites halfway inside the block.";} - FF_BOTHPLANES {value = 1024; text = "Renders both inside and outside planes.";} - FF_EXTRA {value = 2048; text = "Not rendered when seen through a block marked with FF_CUTEXTRA.";} - FF_TRANSLUCENT {value = 4096; text = "Translucent.";} - FF_FOG {value = 8192; text = "Fog block.";} - FF_INVERTPLANES {value = 16384; text = "Renders the planes only when within the block.";} - FF_ALLSIDES {value = 32768; text = "Renders both inside and outside walls.";} - FF_INVERTSIDES {value = 65536; text = "Renders the walls only when within the block.";} - FF_DOUBLESHADOW {value = 131072; text = "Light level and colormap affect only the inside of the block.";} - FF_FLOATBOB {value = 262144; text = "Floats on water and bobs when stepped on.";} - FF_NORETURN {value = 524288; text = "(Use with FF_CRUMBLE) Doesn't respawn after crumbling.";} - FF_CRUMBLE {value = 1048576; text = "Crumbles two seconds after being stepped on.";} - FF_SHATTERBOTTOM {value = 2097152; text = "(Use with FF_BUSTUP) Breaks only when hit from below.";} - FF_MARIO {value = 4194304; text = "Mario item block.";} - FF_BUSTUP {value = 8388608; text = "Can be broken by a spin or Knuckles.";} - FF_QUICKSAND {value = 16777216; text = "Quicksand block.";} - FF_PLATFORM {value = 33554432; text = "Intangible from bottom.";} - FF_REVERSEPLATFORM {value = 67108864; text = "Intangible from top.";} -// FF_INTANGABLEFLATS {value = 100663296; text = "Only tangible from sides.";} - FF_SHATTER {value = 134217728; text = "(Use with FF_BUSTUP) Breaks on any contact.";} - FF_SPINBUST {value = 268435456; text = "(Use with FF_BUSTUP) Breaks only with a spin from above.";} - FF_ONLYKNUX {value = 536870912; text = "(Use with FF_BUSTUP) Can only be broken by Knuckles.";} - FF_RIPPLE {value = 1073741824; text = "Employs a visual ripple effect.";} -// FF_COLORMAPONLY {value = 2147483648; text = "Ignores the control sector's light level.";} - } -} - -// LINEDEF TYPES --------------------------------------------------------------- - -linedeftypes -{ - misc - { - title = "Miscellaneous"; - values - { - 0 = "(normal)"; - 1 = "Per-Sector Gravity"; - 4 = "Speed Pad"; - 5 = "Camera Scanner"; - 6 = "Disable Linedef Effect On Level Load"; - 7 = "Sector Flat Alignment"; - 10 = "Culling Plane"; - 13 = "Heat Wave Effect"; - 50 = "Instantly Lower Floor On Level Load"; - 51 = "Instantly Raise Ceiling On Level Load"; - 63 = "Fake Floor/Ceiling Planes"; - 540 = "Floor Friction"; - } - } - - parameters - { - title = "Parameters"; - values - { - 2 = "Custom Exit"; - 3 = "Zoom Tube Parameters"; - 8 = "Sector Special Parameters"; - 9 = "Chain Parameters"; - 11 = "Rope Hang Parameters"; - 12 = "Rock Spawn Parameters"; - 64 = "Appearing/Disappearing FOF"; - 65 = " Bridge Thinker"; - } - } - - polyobject - { - title = "PolyObject"; - values - { - 20 = "First Line"; - 21 = "Explicity Include Line"; - 22 = "Parameters"; - 30 = "Waving Flag"; - } - } - - movement - { - title = "Plane Movement"; - values - { - 52 = "Continuously Falling Sector"; - 53 = "Continuous Floor/Ceiling Mover"; - 54 = "Continuous Floor Mover"; - 55 = "Continuous Ceiling Mover"; - 56 = "Continuous Two-Speed Floor/Ceiling Mover"; - 57 = "Continuous Two-Speed Floor Mover"; - 58 = "Continuous Two-Speed Ceiling Mover"; - 59 = "Activate Moving Platform"; - 60 = "Activate Moving Platform (Adjustable Speed)"; - 61 = "Crusher (Ceiling to Floor)"; - 62 = "Crusher (Floor to Ceiling)"; - } - } - - fofsolid - { - title = "FOF (solid)"; - values - { - 100 = "Solid, Opaque"; - 101 = "Solid, Opaque, No Shadow"; - 102 = "Solid, Translucent"; - 103 = "Solid, Sides Only"; - 104 = "Solid, No Sides"; - 105 = "Solid, Invisible"; - 140 = "Intangible from Bottom, Opaque"; - 141 = "Intangible from Bottom, Translucent"; - 142 = "Intangible from Bottom, Translucent, No Sides"; - 143 = "Intangible from Top, Opaque"; - 144 = "Intangible from Top, Translucent"; - 145 = "Intangible from Top, Translucent, No Sides"; - 146 = "Only Tangible From Sides"; - } - } - - fofintangible - { - title = "FOF (intangible)"; - values - { - 120 = "Water, Opaque"; - 121 = "Water, Translucent"; - 122 = "Water, Opaque, No Sides"; - 123 = "Water, Translucent, No Sides"; - 220 = "Intangible, Opaque"; - 221 = "Intangible, Translucent"; - 222 = "Intangible, Sides Only"; - 223 = "Intangible, Invisible"; - } - } - - fofbobbing - { - title = "FOF (bobbing)"; - values - { - 150 = " Air Bobbing"; - 151 = " Air Bobbing (Adjustable)"; - 152 = " Reverse Air Bobbing (Adjustable)"; - 160 = "Floating, Bobbing"; - 190 = "Rising Platform, Solid, Opaque"; - 191 = "Rising Platform, Solid, Opaque, No Shadow"; - 192 = "Rising Platform, Solid, Translucent"; - 193 = "Rising Platform, Solid, Invisible"; - 194 = "Rising Platform, Intangible from Bottom, Opaque"; - 195 = "Rising Platform, Intangible from Bottom, Translucent"; - } - } - - fofcrumbling - { - title = "FOF (crumbling)"; - values - { - 170 = "Crumbling (Respawn)"; - 171 = "Crumbling (No Respawn)"; - 172 = "Crumbling (Respawn), Intangible from Bottom"; - 173 = "Crumbling (No Respawn), Intangible from Bottom"; - 174 = "Crumbling (Respawn), Int. from Bottom, Translucent"; - 175 = "Crumbling (No Respawn), Int. from Bottom, Translucent"; - 176 = "Crumbling (Respawn), Floating, Bobbing"; - 177 = "Crumbling (No Respawn), Floating, Bobbing"; - 178 = "Crumbling (Respawn), Floating"; - 179 = "Crumbling (No Respawn), Floating"; - 180 = "Crumbling (Respawn), Air Bobbing"; - } - } - - fofspecial - { - title = "FOF (special)"; - values - { - 200 = "Light Block"; - 201 = "Half Light Block"; - 202 = "Fog Block"; - 250 = "Mario Block"; - 251 = "Thwomp Block"; - 252 = "Shatter Block"; - 253 = "Shatter Block, Translucent"; - 254 = "Bustable Block"; - 255 = "Spin Bust Block"; - 256 = "Spin Bust Block, Translucent"; - 257 = "Quicksand"; - 258 = "Laser"; - 259 = "Custom FOF"; - } - } - - trigger - { - title = "Linedef Executor Trigger"; - values - { - 300 = "Continuous"; - 301 = "Each Time"; - 302 = "Once"; - 303 = "Ring Count - Continuous"; - 304 = "Ring Count - Once"; - 305 = "Character Ability - Once"; - 306 = "Character Ability - Each Time"; - 307 = "Character Ability - Continuous"; - 308 = "Race Only - Once"; - 309 = "CTF Red Team - Continuous"; - 310 = "CTF Red Team - Each Time"; - 311 = "CTF Blue Team - Continuous"; - 312 = "CTF Blue Team - Each Time"; - 313 = "No More Enemies - Once"; - 314 = "Number of Pushables - Continuous"; - 315 = "Number of Pushables - Once"; - 316 = "Land On PolyObject"; - 399 = "Level Load"; - } - } - - execsector - { - title = "Linedef Executor (sector)"; - values - { - 400 = "Set Tagged Sector's Floor Height/Texture"; - 401 = "Set Tagged Sector's Ceiling Height/Texture"; - 402 = "Set Tagged Sector's Light Level"; - 409 = "Change Tagged Sectors' Tag"; - 410 = "Change Front Sector's Tag"; - 416 = "Start Adjustable Fire Flicker"; - 417 = "Start Adjustable Glowing Light"; - 418 = "Start Adjustable Blinking Light (unsynchronized)"; - 419 = "Start Adjustable Blinking Light (synchronized)"; - 420 = "Fade Light Level"; - 421 = "Stop Lighting Effect"; - 435 = "Change Plane Scroller Direction"; - } - } - - execplane - { - title = "Linedef Executor (plane movement)"; - values - { - 403 = "Move Tagged Sector's Floor"; - 404 = "Move Tagged Sector's Ceiling"; - 405 = "Lower Floor According to Linedef"; - 406 = "Raise Floor According to Linedef"; - 407 = "Lower Ceiling According to Linedef"; - 408 = "Raise Ceiling According to Linedef"; - 411 = "Stop Plane Movement"; - 428 = "Start Platform Movement"; - 429 = "Crush Ceiling Once"; - 430 = "Crush Floor Once"; - 431 = "Crush Floor And Ceiling Once"; - } - } - - execplayer - { - title = "Linedef Executor (player/object)"; - values - { - 412 = "Teleporter"; - 425 = "Change Object State"; - 426 = "Stop Object"; - 427 = "Award Score"; - 432 = "Enable 2D Mode"; - 433 = "Disable 2D Mode"; - 434 = "Award Power-Up"; - 437 = "Disable Player Control"; - 438 = "Change Object Size"; - } - } - - execmisc - { - title = "Linedef Executor (misc.)"; - values - { - 413 = "Change Music"; - 414 = "Play Sound Effect"; - 415 = "Run Script"; - 422 = "Switch To Cut-Away View"; - 423 = "Change Sky"; - 424 = "Change Weather"; - 436 = "Shatter FOF"; - 450 = "Execute Linedef Executor"; - } - } - - execpoly - { - title = "Linedef Executor (polyobject)"; - values - { - 480 = "Door Slide"; - 481 = "Door Swing"; - 482 = "Move"; - 483 = "Move, Override"; - 484 = "Rotate Right"; - 485 = "Rotate Right, Override"; - 486 = "Rotate Left"; - 487 = "Rotate Left, Override"; - 488 = "Move by Waypoints"; - 489 = "Turn Invisible, Intangible"; - 490 = "Turn Visible, Tangible"; - 491 = "Set Translucency"; - } - } - - wall - { - title = "Wall Scrolling"; - values - { - 500 = "Scroll Wall Front Side Left"; - 501 = "Scroll Wall Front Side Right"; - 502 = "Scroll Wall According to Linedef"; - 503 = "Scroll Wall According to Linedef (Accelerative)"; - 504 = "Scroll Wall According to Linedef (Displacement)"; - 505 = "Scroll Texture by Front Side Offsets"; - 506 = "Scroll Texture by Back Side Offsets"; - } - } - - plane - { - title = "Plane Scrolling"; - values - { - 510 = "Scroll Floor Texture"; - 511 = "Scroll Floor Texture (Accelerative)"; - 512 = "Scroll Floor Texture (Displacement)"; - 513 = "Scroll Ceiling Texture"; - 514 = "Scroll Ceiling Texture (Accelerative)"; - 515 = "Scroll Ceiling Texture (Displacement)"; - 520 = "Carry Objects on Floor"; - 521 = "Carry Objects on Floor (Accelerative)"; - 522 = "Carry Objects on Floor (Displacement)"; - 523 = "Carry Objects on Ceiling"; - 524 = "Carry Objects on Ceiling (Accelerative)"; - 525 = "Carry Objects on Ceiling (Displacement)"; - 530 = "Scroll Floor Texture and Carry Objects"; - 531 = "Scroll Floor Texture and Carry Objects (Accelerative)"; - 532 = "Scroll Floor Texture and Carry Objects (Displacement)"; - 533 = "Scroll Ceiling Texture and Carry Objects"; - 534 = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; - 535 = "Scroll Ceiling Texture and Carry Objects (Displacement)"; - } - } - - pusher - { - title = "Pusher"; - values - { - 541 = "Wind"; - 542 = "Upwards Wind"; - 543 = "Downwards Wind"; - 544 = "Current"; - 545 = "Upwards Current"; - 546 = "Downwards Current"; - 547 = "Push/Pull"; - } - } - - lighting - { - title = "Lighting"; - values - { - 600 = "Floor Lighting"; - 601 = "Ceiling Lighting"; - 602 = "Adjustable Pulsating Light"; - 603 = "Adjustable Flickering Light"; - 604 = "Adjustable Blinking Light (unsynchronized)"; - 605 = "Adjustable Blinking Light (synchronized)"; - 606 = "Colormap"; - } - } - - transwall - { - title = "Translucent Wall"; - values - { - 900 = "90% Opaque"; - 901 = "80% Opaque"; - 902 = "70% Opaque"; - 903 = "60% Opaque"; - 904 = "50% Opaque"; - 905 = "40% Opaque"; - 906 = "30% Opaque"; - 907 = "20% Opaque"; - 908 = "10% Opaque"; - 909 = "Fog Wall"; - } - } -} - -// THING FLAGS ----------------------------------------------------------------- - -thingflags -{ - 1 = "[0] Unused Flag"; - 2 = "[1] Object Flip"; - 4 = "[2] Object Special"; - 8 = "[3] Ambush"; - 16 = "(Used for Z offsets)"; -} - -/* THING TYPES ----------------------------------------------------------------- - -Color values are 24-bit RGB colors in decimal. - -*/ - -thingtypes -{ - starts - { - color = 223; // Blue (0000DF) - arrow = 1; - title = "Player Starts"; - width = 16; - height = 56; - zfactor = 32; - deaftext = "[3] Spawn On Ceiling"; - values - { - 1 - { - title = "Player 01 Start"; - sprite = "SUPTD0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "SUPTD0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "SUPTD0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "SUPTD0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "SUPTD0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "SUPTD0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "SUPTD0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "SUPTD0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "SUPTD0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "SUPTD0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "SUPTD0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "SUPTD0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "SUPTD0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "SUPTD0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "SUPTD0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "SUPTD0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "SUPTD0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "SUPTD0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "SUPTD0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "SUPTD0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "SUPTD0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "SUPTD0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "SUPTD0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "SUPTD0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "SUPTD0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "SUPTD0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "SUPTD0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "SUPTD0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "SUPTD0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "SUPTD0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "SUPTD0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "SUPTD0"; - } - 33 - { - title = "Match Start"; - sprite = "SUPTI0"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - } - - enemies - { - color = 6250495; // Light blue (5F5FFF) - arrow = 1; - title = "Enemies"; - width = 24; - height = 32; - values - { - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 20; - height = 24; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 20; - height = 24; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - height = 32; - } - 111 - { - title = "Popup Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - } - 112 - { - title = "Sharp"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - height = 48; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - deaftext = "[3] Unknown Effect"; - } - 118 - { - title = "CastleBot FaceStabber"; - sprite = "CBFSA1"; - width = 32; - height = 64; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA1"; - } - 750 - { - title = " Chaos Enemy Spawn"; - sprite = "TFOGG0"; - width = 32; - height = 64; - } - } - } - - bosses - { - color = 6250335; // Grey (5F5F5F) - arrow = 1; - title = "Bosses"; - width = 24; - height = 52; - zfactor = 32; - values - { - 200 - { - title = "Boss 1 - Egg Mobile"; - sprite = "EGGMA1"; - spectext = "[2] End Level When Defeated"; - deaftext = "[3] Rotating Spikeballs"; - } - 201 - { - title = "Boss 2 - Egg Slimer"; - sprite = "EGGNA1"; - height = 48; - spectext = "[2] End Level When Defeated"; - deaftext = "[3] Speed Up When Hit"; - } - 202 - { - title = "Boss 3 - Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 80; - spectext = "[2] End Level When Defeated"; - deaftext = "[3] Unknown Effect"; - } - 203 - { - title = " Boss 4 - Eggscalibur"; - sprite = "EGGPA1"; - } - 206 - { - title = "Boss 5 - Black Eggman"; - sprite = "BRAKB1"; - width = 48; - height = 160; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - zfactor = 16; - } - 291 - { - arrow = 0; - title = "Egg Trap Center"; - width = 8; - height = 16; - zfactor = 16; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - zfactor = 16; - } - } - } - - rings - { - color = 12566272; // Yellow (BFBF00) - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - values - { - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "CPRKB0"; - } - 302 - { - title = "Rail Ring"; - sprite = "SPRKA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "TAUTA3A7"; - } - 305 - { - title = "Explosion Ring"; - sprite = "BMSLA1"; - } - 306 - { - title = "Scatter Ring"; - sprite = "TSCRA1A5"; - } - 307 - { - title = "Grenade Ring"; - sprite = "TGREA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "TRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "PIKGA0"; - } - } - } - - collectibles - { - color = 48896; // Green (00BF00) - title = "Other Collectibles"; - width = 16; - height = 32; - values - { - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Special Stage Token"; - sprite = "TOKEA0"; - width = 8; - height = 16; - deafheight = 32; - deaftext = "[3] Float"; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "EMMYA0"; - } - 314 - { - title = "Chaos Emerald 2 (Orange)"; - sprite = "EMMYB0"; - } - 315 - { - title = "Chaos Emerald 3 (Purple)"; - sprite = "EMMYC0"; - } - 316 - { - title = "Chaos Emerald 4 (Blue)"; - sprite = "EMMYD0"; - } - 317 - { - title = "Chaos Emerald 5 (Red)"; - sprite = "EMMYE0"; - } - 318 - { - title = "Chaos Emerald 6 (Light Blue)"; - sprite = "EMMYF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "EMMYG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "EMERA0"; - } - 323 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - width = 8; - height = 48; - deafheight = 32; - deaftext = "[3] Float"; - } - } - } - - boxes - { - color = 12566463; // Silver (BFBFBF) - blocking = 2; - title = "Item Boxes"; - width = 16; - height = 32; - spectext = "[2] Random (Strong)"; - deaftext = "[3] Random (Weak)"; - values - { - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "SRBXA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "YLTVA0"; - } - 403 - { - title = "Force Shield"; - sprite = "BLTVA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "BKTVA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "WHTVA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "GRTVA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "SHTVA0"; - } - 408 - { - title = "Invincibility"; - sprite = "PINVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "MTEXA0"; - } - 410 - { - title = "Eggman"; - sprite = "EGGBA0"; - } - 411 - { - title = "Teleporter"; - sprite = "MIXUA0"; - } - 412 - { - title = "Random"; - sprite = "QUESA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "GBTVA0"; - } - 414 - { - title = "CTF Team Ring Box (Red)"; - sprite = "RRBXA0"; - spectext = "[2] Object Special"; - deaftext = "[3] Ambush"; - } - 415 - { - title = "CTF Team Ring Box (Blue)"; - sprite = "BRBXA0"; - spectext = "[2] Object Special"; - deaftext = "[3] Ambush"; - } - 416 - { - title = "Recycler"; - sprite = "RECYA0"; - } - } - } - - miscellaneous - { - color = 49119; // Sky blue (00BFDF) - title = "Miscellaneous"; - width = 16; - height = 40; - values - { - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLA0"; - width = 8; - height = 16; - } - 501 - { - title = "End Level Sign"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0"; - width = 64; - height = 80; - } - 526 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - spectext = "[2] Light And Bouncy"; - deaftext = "[3] Not Pushable"; - } - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - spectext = "[2] Light And Bouncy"; - deaftext = "[3] Not Pushable"; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - spectext = "[2] Light And Bouncy"; - deaftext = "[3] Not Pushable"; - } - 1106 - { - arrow = 1; - title = "Chain (Hang)"; - sprite = "SMCHA0"; - height = 32; - deaftext = "[3] Double Size"; - } - 1107 - { - arrow = 1; - title = "Chain (Spin)"; - sprite = "SMCHA0"; - height = 32; - } - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 28; - deaftext = "[3] Moves Perpetually"; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - deaftext = "[3] Moves Perpetually"; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - spectext = "[2] Light And Bouncy"; - deaftext = "[3] Not Pushable"; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - spectext = "[2] Light And Bouncy"; - deaftext = "[3] Not Pushable"; - } - } - } - - springs - { - color = 14614528; // Red (DF0000) - title = "Springs and Fans"; - width = 20; - height = 16; - values - { - 540 - { - title = "Fan"; - sprite = "FANSA0"; - width = 16; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - width = 32; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 553 - { - title = "Yellow Spring (Ceiling)"; - sprite = "SUDYA0"; - hangs = 1; - } - 554 - { - title = "Red Spring (Ceiling)"; - sprite = "SUDRA0"; - hangs = 1; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - 557 - { - arrow = 1; - title = "Diagonal Yellow Spring (Ceiling)"; - sprite = "YSUDE2"; - width = 16; - hangs = 1; - deaftext = "[3] Rotate 22.5° CCW"; - } - 558 - { - arrow = 1; - title = "Diagonal Red Spring (Ceiling)"; - sprite = "RSUDE2"; - width = 16; - hangs = 1; - deaftext = "[3] Rotate 22.5° CCW"; - } - } - } - - patterns - { - color = 10420319; // Dark Rose (9F005F) - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - values - { - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - } - 606 - { - title = "Circle of Wing Logos"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 607 - { - title = "Circle of Wing Logos (Big)"; - sprite = "NWNGA0"; - width = 192; - } - 608 - { - title = "Circle of Rings and Wings"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 609 - { - title = "Circle of Rings and Wings (Big)"; - sprite = "NWNGA0"; - width = 192; - } - } - } - - invisible - { - color = 16777215; // White (FFFFFF) - title = "Misc. Invisible"; - width = 8; - height = 16; - values - { - 700 = "Water Ambience A (Large)"; - 701 = "Water Ambience B (Large)"; - 702 = "Water Ambience C (Medium)"; - 703 = "Water Ambience D (Medium)"; - 704 = "Water Ambience E (Small)"; - 705 = "Water Ambience F (Small)"; - 706 = "Water Ambience G (Extra Large)"; - 707 = "Water Ambience H (Extra Large)"; - 708 = "Disco Ambience"; - 709 = "Volcano Ambience"; - 751 - { - arrow = 1; - title = "Teleport Destination"; - } - 752 - { - arrow = 1; - title = "Alternate View Point"; - } - 753 = "Zoom Tube Waypoint"; - 754 - { - title = "Push Point"; - spectext = "[2] No Z Fade"; - deaftext = "[3] Push Using XYZ"; - } - 755 - { - title = "Pull Point"; - spectext = "[2] No Z Fade"; - deaftext = "[3] Pull Using XYZ"; - } - 760 = "PolyObject Anchor"; - 761 = "PolyObject Spawn Point"; - 762 = "PolyObject Spawn Point (Crush)"; - } - } - - hazards - { - color = 10420224; // Maroon (9F0000) - title = "Hazards"; - width = 20; - height = 40; - values - { - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 522 - { - blocking = 2; - title = "Spike (Ceiling)"; - sprite = "DSPKA0"; - width = 8; - height = 42; - hangs = 1; - } - 523 - { - title = "Spike (Floor)"; - sprite = "USPKA0"; - width = 8; - height = 42; - deaftext = "[3] Solid"; - } - 524 - { - arrow = 1; - title = "Big Floating Mine"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 527 - { - arrow = 1; - title = "Big Floating Mine (Air)"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 525 - { - title = "Cannonball Launcher"; - sprite = "CBLLA0"; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0"; - width = 8; - height = 32; - } - 1104 - { - title = "Mace (Spinning)"; - sprite = "SMCEA0"; - deaftext = "[3] Double Size"; - } - 1105 - { - title = "Mace (Swinging)"; - sprite = "SMCEA0"; - deaftext = "[3] Double Size"; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - } - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "FLMEB0"; - width = 16; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "FLMEB0"; - width = 16; - deaftext = "[3] Shoot Downwards"; - } - } - } - - decoration - { - color = 4153088; // Dark lime (3F5F00) - title = "Decoration"; - width = 16; - height = 40; - values - { - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - } - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - height = 32; - } - 900 - { - title = "THZ Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CRL1A0"; - width = 8; - height = 16; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CRL2A0"; - width = 8; - height = 16; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CRL3A0"; - width = 8; - height = 16; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1100 - { - title = "Chain"; - sprite = "CHANA0"; - width = 8; - height = 128; - hangs = 1; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - } - 1203 - { - title = "Cactus with Brown Flower"; - sprite = "CACTA0"; - height = 32; - } - 1204 - { - title = "Cactus with Brown Flower (Tall)"; - sprite = "CACTB0"; - height = 64; - } - 1205 - { - title = "Cactus with Blue Flower"; - sprite = "CACTC0"; - height = 32; - } - 1206 - { - title = "Cactus with Blue Flower (Tall)"; - sprite = "CACTD0"; - height = 80; - } - 1850 - { - title = "Xmas Pole"; - sprite = "XMS1A0"; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - height = 54; - hangs = 1; - } - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STG0A0"; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STG1A0"; - width = 16; - height = 40; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STG2A0"; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STG3A0"; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STG4A0"; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STG5A0"; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STG6A0"; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STG7A0"; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STG8A0"; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STG9A0"; - } - } - } - - nights - { - color = 12517599; // Violet (BF00DF) - title = "Nights Items"; - width = 12; - height = 32; - values - { - 1700 - { - title = "Axis"; - width = 8; - height = 2048; - circle = 1; - } - 1701 - { - title = "Axis Transfer"; - width = 8; - height = 2048; - } - 1702 - { - title = "Axis Transfer Line"; - width = 8; - height = 2048; - } - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - deaftext = "[3] Die Upon Time Up"; - } - 1704 - { - arrow = 1; - title = "Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - } - 1705 - { - arrow = 1; - title = "Hoop"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1706 - { - title = "Wing Logo"; - sprite = "NWNGA0"; - height = 24; - } - 1707 - { - title = "Super Loop"; - sprite = "NPRAA0"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRBA0"; - } - 1709 - { - title = "Helper"; - sprite = "NPRCA0"; - } - 1710 - { - title = "Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - mario - { - color = 14647040; // Orange (DF7F00) - title = "Mario Items"; - width = 16; - height = 32; - values - { - 1800 - { - title = "Coin"; - sprite = "COINA0"; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA0"; - width = 8; - height = 16; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - height = 48; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - } - } - } - - srb1 - { - color = 32607; // Teal (007F5F) - arrow = 1; - title = "SRB1 Remake Items"; - width = 20; - height = 32; - values - { - 4000 - { - title = "SRB1 Crawla"; - sprite = "SRBAA1"; - height = 40; - } - 4001 - { - title = "GuardRobo"; - sprite = "SRBBA1"; - width = 17; - height = 40; - } - 4002 - { - title = "Pyrin"; - sprite = "SRBCB1"; - width = 22; - } - 4003 - { - title = "HotRobo"; - sprite = "SRBDA0"; - height = 40; - } - 4004 - { - title = "Pogminz"; - sprite = "SRBEA1"; - } - 4005 - { - title = "Pogminz (Water)"; - sprite = "SRBEA1"; - } - 4006 - { - title = "Pog-GX2"; - sprite = "SRBFA0"; - width = 10; - height = 34; - } - 4007 - { - title = "Pyrex"; - sprite = "SRBGA1"; - width = 24; - } - 4008 - { - title = "UFO"; - sprite = "SRBHA0"; - width = 24; - hangs = 1; - } - 4009 - { - title = "SWAT Bot"; - sprite = "SRBIA1"; - width = 21; - height = 69; - } - 4010 - { - title = "SpyBot 2000"; - sprite = "SRBJA0"; - width = 36; - height = 62; - } - 4011 - { - title = "Buzz Bomber"; - sprite = "SRBKA0"; - width = 44; - height = 45; - } - 4012 - { - arrow = 0; - title = "RBZ Spike"; - sprite = "SRBLA0"; - width = 10; - height = 53; - } - 4013 - { - arrow = 0; - blocking = 2; - title = "Dumb Metal Sonic"; - sprite = "SRBMC0"; - width = 16; - height = 40; - spectext = "[2] Light And Bouncy"; - deaftext = "[3] Not Pushable"; - } - 4014 - { - title = "Super SWAT Bot"; - sprite = "SRBNA1"; - width = 21; - height = 69; - } - 4015 - { - title = "Genrex"; - sprite = "SRBOA1"; - width = 17; - height = 40; - } - } - } -} diff --git a/extras/conf/Srb2-21db.cfg b/extras/conf/Srb2-21db.cfg deleted file mode 100644 index a7c4dbf75..000000000 --- a/extras/conf/Srb2-21db.cfg +++ /dev/null @@ -1,2832 +0,0 @@ -/******************************************************************************\ - - SRB2 Doom Builder - Game Configuration for SRB2 version 2.1. - - Contributors: - - Kristos - - Shadow Hog - - ST218 - - Foxboy - - JJames19119 - - SRB2-Playah - - Oogaland - - SSNTails - - DarkWarrior - - Neo - - Morpheus - - Trinity - -\******************************************************************************/ - -// This is required to prevent accedential use of a different configuration. -type = "SRB2 Doom Builder Game Configuration"; - -// This is the title to show for this game. -game = "Sonic Robo Blast 2 v2.1"; - -// Map format determines the way the map will be loaded. -mapformat = 1; - -// Flags for changes in 2.0. -seceffectnybble = 1; - -// Default flags for first new thing. -defaulthingflags = 0; - -// Default lump name for new map. -defaultlumpname = "MAP01"; - -// Load textures/flats by default from this file. -texturesfile = ""; - -// Thing number for start position in 3D Mode. -start3dmode = 32000; - -// Thing number for control sector position hint. -ctrlsechint = 32001; - -// Zoom tube waypoint, for the wizard. -zoomtubewaypoint = 753; - -// No generalized types. -generalizedlinedefs = 0; -generalizedsectors = 0; - -/* TEXTURES AND FLAT SOURCES --------------------------------------------------- - -This tells Doom Builder where to find the information for textures and flats in -the IWAD file, Addition WAD file and Map WAD file. - -Start and end lumps must be given in a structure (of which the key name doesn't -matter) and any textures or flats in between them are loaded in either the -textures category or flats category. - -For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. - -*/ - -// Texture sources. -textures -{ - zdoom1 - { - start = "TX_START"; - end = "TX_END"; - } -} - -// Flat sources. -flats -{ - standard1 - { - start = "F_START"; - end = "F_END"; - } - - standard2 - { - start = "FF_START"; - end = "FF_END"; - } - - standard3 - { - start = "FF_START"; - end = "F_END"; - } - - standard4 - { - start = "F_START"; - end = "FF_END"; - } -} - -/* TEXTURES AND FLATS FILTERING ------------------------------------------------ - -This allows you to filter textures and flats so that you only see the -textures/flats listed that you prefer to use. - -The key name doesn't matter here, only the values. - -Pattern-matching is performed on lump names. You can use the following wildcards -in values to specify ranges: - -? = Any character. -* = Zero or more characters. -# = Any numeric digit. -[abc...] = Any of these characters that are between brackets. -[!abc..] = Not any of these characters that are between brackets. - -*/ - -// List these textures... -texturesfilter -{ - all_textures = "*"; -} - -// But do not list these textures... -notexturesfilter -{ - none = ""; -} - -// List these flats... -flatsfilter -{ - all_flats = "*"; -} - -// But do not list these flats... -noflatsfilter -{ - none = ""; -} - -/* PSEUDO-FLATS AND TEXTURES --------------------------------------------------- - -Names of flats and textures that don't really exist, but shouldn't be identified -as invalid. - -Pattern-matching is performed on lump names. See above for syntax. - -*/ - -pseudoflats -{ - F_SKY1; -} - -pseudotextures -{ - [#]*; -} - -/* GAME DETECT PATTERN --------------------------------------------------------- - -Used to guess the game for which a WAD file is made. - -1 = One of these lumps must exist. -2 = None of these lumps must exist. -3 = All of these lumps must exist. - -Pattern-matching is performed on lump names. See above for syntax. - -*/ - -gamedetect -{ - EXTENDED = 2; - BEHAVIOR = 2; - E#M# = 2; - MAP?? = 1; -} - -/* MAP LUMP NAMES -------------------------------------------------------------- - -Map lumps are loaded with the map as long as they are right after each other. -When the editor meets a lump which is not defined in this list (or defined -as 0), it will stop loading right there. - -The order of items defines the order in which lumps will be written to WAD file -on save. The value (flags) of items determines what the editor should do with -it. You should never mess with value 4, because it may result in incorrect map -builds. - - 1 = Lump required. - 2 = Lump which must be respected. - 4 = Lump generated by node builder. - 8 = Lump allowed to be empty after nodebuilding. - 16 = Lump allowed to be missing after nodebuilding. - 4096 = Lump which can be edited as text. - 8192 = Lump which can be edited as DEHACKED. -12288 = Lump which can be edited as MAPINFO. -16384 = WAD-global. - -*/ - -maplumpnames -{ - THINGS = 13; - LINEDEFS = 5; - SIDEDEFS = 5; - VERTEXES = 5; - SEGS = 4; - SSECTORS = 4; - NODES = 4; - SECTORS = 5; - REJECT = 4; - BLOCKMAP = 20; - MAINCFG = 24576; -} - -// DEFAULT SECTOR BRIGHTNESS LEVELS -------------------------------------------- - -sectorbrightness -{ - 255; - 240; - 224; - 208; - 192; - 176; - 160; - 144; - 128; - 112; - 96; - 80; - 64; - 48; - 32; - 16; - 0; -} - -// SECTOR TYPES ---------------------------------------------------------------- - -sectortypes -{ - nybble0 - { - 0 = "(normal)"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Modifications)"; - 7 = "Death Pit (No Camera Modifications)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (No Floor Touch)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy Sector (FOF Control Only)"; - } - - nybble1 - { - 0 = "(normal)"; - 1 = "Trigger Line Ex. (Pushable Objects)"; - 2 = "Trigger Line Ex. (Anywhere, All Players)"; - 3 = "Trigger Line Ex. (Floor Touch, All Players)"; - 4 = "Trigger Line Ex. (Anywhere in Sector)"; - 5 = "Trigger Line Ex. (Floor Touch)"; - 6 = "Trigger Line Ex. (Emerald Check)"; - 7 = "Trigger Line Ex. (Nights Mare)"; - 8 = " Check for Line Exec. on FOFs"; - 9 = "Egg Trap Capsule"; - 10 = "Special Stage Time/Rings Parameters"; - 11 = "Custom Global Gravity"; - } - - nybble2 - { - 0 = "(normal)"; - 1 = "Ice/Sludge"; - 2 = "Wind/Current"; - 3 = "Ice/Sludge and Wind/Current"; - 4 = "Conveyor Belt"; - 5 = "Speed Pad (No Spin)"; - 6 = "Speed Pad (Spin)"; - 7 = "Bustable Block Sprite Parameter (ROIA)"; - 8 = "Bustable Block Sprite Parameter (ROIB)"; - 9 = "Bustable Block Sprite Parameter (ROIC)"; - 10 = "Bustable Block Sprite Parameter (ROID)"; - 11 = "Bustable Block Sprite Parameter (ROIE)"; - 12 = "Bustable Block Sprite Parameter (ROIF)"; - 13 = "Bustable Block Sprite Parameter (ROIG)"; - 14 = "Bustable Block Sprite Parameter (ROIH)"; - 15 = "Bustable Block Sprite Parameter (ROII)"; - } - - nybble3 - { - 0 = "(normal)"; - 1 = "Star Post Activator"; - 2 = "Exit/Special Stage Goal/Return Flag"; - 3 = "CTF: Red Team Base"; - 4 = "CTF: Blue Team Base"; - 5 = "Fan Sector"; - 6 = "Super Sonic Transform"; - 7 = "Spinner"; - 8 = "Zoom Tube Start"; - 9 = "Zoom Tube End"; - 10 = "Finish Line"; - 11 = "Rope Hang"; - 12 = "Intangible to the Camera"; - } -} - -// LINEDEF FLAGS --------------------------------------------------------------- - -linedefflags -{ - 1 = "[0] Effect 6"; - 2 = "[1] Block Enemies"; - 4 = "[2] Double-Sided"; - 8 = "[3] Upper Unpegged"; - 16 = "[4] Lower Unpegged"; - 32 = "[5] Effect 1"; - 64 = "[6] Not Climbable"; - 128 = "[7] Effect 2"; - 256 = "[8] Effect 3"; - 512 = "[9] Effect 4"; - 1024 = "[10] Effect 5"; - 2048 = "[11] No Sonic"; - 4096 = "[12] No Tails"; - 8192 = "[13] No Knuckles"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - -// LINEDEF ACTIVATIONS --------------------------------------------------------- - -linedefactivations -{ -} - -/* FOF FLAGS ------------------------------------------------------------------- - -This is a hack. The FOF flag values have changed in 2.0, but the old 1.09.4 -values are hardcoded in the source for SRB2 Doom Builder. Until Oogaland fixes -this, I'm sticking some fake values in here to make 3D mode draw FOFs like it's -supposed to. --Neo - -Flags I've found relevant: - - 4 = Renders the walls. - 8 = Renders the planes. -32 = Doesn't cast a shadow. - -*/ - -fofs -{ - 100 = 12; - 101 = 44; - 102 = 44; - 103 = 36; - 104 = 40; - 105 = 32; - 120 = 12; - 121 = 12; - 122 = 8; - 123 = 8; - 124 = 12; - 125 = 8; - 140 = 12; - 141 = 12; - 142 = 8; - 143 = 12; - 144 = 12; - 145 = 8; - 146 = 4; - 150 = 12; - 151 = 12; - 152 = 12; - 160 = 12; - 170 = 12; - 171 = 12; - 172 = 12; - 173 = 12; - 174 = 12; - 175 = 12; - 176 = 12; - 177 = 12; - 178 = 12; - 179 = 12; - 180 = 12; - 190 = 12; - 191 = 44; - 192 = 44; - 193 = 32; - 194 = 12; - 195 = 12; - 200 = 0; - 201 = 0; - 202 = 0; - 220 = 12; - 221 = 44; - 222 = 36; - 223 = 32; - 250 = 12; - 251 = 12; - 252 = 12; - 253 = 12; - 254 = 12; - 255 = 12; - 256 = 12; - 257 = 12; - 258 = 44; - 259 = 12; -} - -// LINEDEF TYPES --------------------------------------------------------------- - -linedeftypes -{ - 0 = "Miscellaneous: (normal)"; - 1 = "Miscellaneous: Per-Sector Gravity"; - 2 = "Parameters: Custom Exit"; - 3 = "Parameters: Zoom Tube Parameters"; - 4 = "Miscellaneous: Speed Pad"; - 5 = "Miscellaneous: Camera Scanner"; - 6 = "Miscellaneous: Disable Linedef Effect On Level Load"; - 7 = "Miscellaneous: Sector Flat Alignment"; - 8 = "Parameters: Sector Special Parameters"; - 9 = "Parameters: Chain Parameters"; - 10 = "Miscellaneous: Culling Plane"; - 11 = "Parameters: Rope Hang Parameters"; - 12 = "Parameters: Rock Spawn Parameters"; - 13 = "Miscellaneous: Heat Wave Effect"; - 20 = "PolyObject: First Line"; - 21 = "PolyObject: Explicity Include Line"; - 22 = "PolyObject: Parameters"; - 30 = "PolyObject: Waving Flag"; - 50 = "Miscellaneous: Instantly Lower Floor On Level Load"; - 51 = "Miscellaneous: Instantly Raise Ceiling On Level Load"; - 52 = "Plane Movement: Continuously Falling Sector"; - 53 = "Plane Movement: Continuous Floor/Ceiling Mover"; - 54 = "Plane Movement: Continuous Floor Mover"; - 55 = "Plane Movement: Continuous Ceiling Mover"; - 56 = "Plane Movement: Continuous Two-Speed Floor/Ceiling Mover"; - 57 = "Plane Movement: Continuous Two-Speed Floor Mover"; - 58 = "Plane Movement: Continuous Two-Speed Ceiling Mover"; - 59 = "Plane Movement: Activate Moving Platform"; - 60 = "Plane Movement: Activate Moving Platform (Adjustable Speed)"; - 61 = "Plane Movement: Crusher (Ceiling to Floor)"; - 62 = "Plane Movement: Crusher (Floor to Ceiling)"; - 63 = "Miscellaneous: Fake Floor/Ceiling Planes"; - 64 = "Parameters: Appearing/Disappearing FOF"; - 65 = "Parameters: Bridge Thinker"; - 100 = "FOF (solid): Solid, Opaque"; - 101 = "FOF (solid): Solid, Opaque, No Shadow"; - 102 = "FOF (solid): Solid, Translucent"; - 103 = "FOF (solid): Solid, Sides Only"; - 104 = "FOF (solid): Solid, No Sides"; - 105 = "FOF (solid): Solid, Invisible"; - 120 = "FOF (intangible): Water, Opaque"; - 121 = "FOF (intangible): Water, Translucent"; - 122 = "FOF (intangible): Water, Opaque, No Sides"; - 123 = "FOF (intangible): Water, Translucent, No Sides"; - 124 = "FOF (intangible): Goo Water, Translucent"; - 125 = "FOF (intangible): Goo Water, Translucent, No Sides"; - 140 = "FOF (solid): Intangible from Bottom, Opaque"; - 141 = "FOF (solid): Intangible from Bottom, Translucent"; - 142 = "FOF (solid): Intangible from Bottom, Translucent, No Sides"; - 143 = "FOF (solid): Intangible from Top, Opaque"; - 144 = "FOF (solid): Intangible from Top, Translucent"; - 145 = "FOF (solid): Intangible from Top, Translucent, No Sides"; - 146 = "FOF (solid): Only Tangible From Sides"; - 150 = "FOF (bobbing): Air Bobbing"; - 151 = "FOF (bobbing): Air Bobbing (Adjustable)"; - 152 = "FOF (bobbing): Reverse Air Bobbing (Adjustable)"; - 160 = "FOF (bobbing): Floating, Bobbing"; - 170 = "FOF (crumbling): Crumbling (Respawn)"; - 171 = "FOF (crumbling): Crumbling (No Respawn)"; - 172 = "FOF (crumbling): Crumbling (Respawn), Intangible from Bottom"; - 173 = "FOF (crumbling): Crumbling (No Respawn), Intangible from Bottom"; - 174 = "FOF (crumbling): Crumbling (Respawn), Int. from Bottom, Translucent"; - 175 = "FOF (crumbling): Crumbling (No Respawn), Int. from Bottom, Translucent"; - 176 = "FOF (crumbling): Crumbling (Respawn), Floating, Bobbing"; - 177 = "FOF (crumbling): Crumbling (No Respawn), Floating, Bobbing"; - 178 = "FOF (crumbling): Crumbling (Respawn), Floating"; - 179 = "FOF (crumbling): Crumbling (No Respawn), Floating"; - 180 = "FOF (crumbling): Crumbling (Respawn), Air Bobbing"; - 190 = "FOF (bobbing): Rising Platform, Solid, Opaque"; - 191 = "FOF (bobbing): Rising Platform, Solid, Opaque, No Shadow"; - 192 = "FOF (bobbing): Rising Platform, Solid, Translucent"; - 193 = "FOF (bobbing): Rising Platform, Solid, Invisible"; - 194 = "FOF (bobbing): Rising Platform, Intangible from Bottom, Opaque"; - 195 = "FOF (bobbing): Rising Platform, Intangible from Bottom, Translucent"; - 200 = "FOF (special): Light Block"; - 201 = "FOF (special): Half Light Block"; - 202 = "FOF (special): Fog Block"; - 220 = "FOF (intangible): Intangible, Opaque"; - 221 = "FOF (intangible): Intangible, Translucent"; - 222 = "FOF (intangible): Intangible, Sides Only"; - 223 = "FOF (intangible): Intangible, Invisible"; - 250 = "FOF (special): Mario Block"; - 251 = "FOF (special): Thwomp Block"; - 252 = "FOF (special): Shatter Block"; - 253 = "FOF (special): Shatter Block, Translucent"; - 254 = "FOF (special): Bustable Block"; - 255 = "FOF (special): Spin Bust Block"; - 256 = "FOF (special): Spin Bust Block, Translucent"; - 257 = "FOF (special): Quicksand"; - 258 = "FOF (special): Laser"; - 259 = "FOF (special): Custom FOF"; - 300 = "Linedef Executor Trigger: Continuous"; - 301 = "Linedef Executor Trigger: Each Time"; - 302 = "Linedef Executor Trigger: Once"; - 303 = "Linedef Executor Trigger: Ring Count - Continuous"; - 304 = "Linedef Executor Trigger: Ring Count - Once"; - 305 = "Linedef Executor Trigger: Character Ability - Once"; - 306 = "Linedef Executor Trigger: Character Ability - Each Time"; - 307 = "Linedef Executor Trigger: Character Ability - Continuous"; - 308 = "Linedef Executor Trigger: Race Only - Once"; - 309 = "Linedef Executor Trigger: CTF Red Team - Continuous"; - 310 = "Linedef Executor Trigger: CTF Red Team - Each Time"; - 311 = "Linedef Executor Trigger: CTF Blue Team - Continuous"; - 312 = "Linedef Executor Trigger: CTF Blue Team - Each Time"; - 313 = "Linedef Executor Trigger: No More Enemies - Once"; - 314 = "Linedef Executor Trigger: Number of Pushables - Continuous"; - 315 = "Linedef Executor Trigger: Number of Pushables - Once"; - 316 = "Linedef Executor Trigger: Land On PolyObject"; - 317 = "Linedef Executor Trigger: Unlockable Trigger - Continuous"; - 318 = "Linedef Executor Trigger: Unlockable Trigger - Once"; - 399 = "Linedef Executor Trigger: Level Load"; - 400 = "Linedef Executor (sector): Set Tagged Sector's Floor Height/Texture"; - 401 = "Linedef Executor (sector): Set Tagged Sector's Ceiling Height/Texture"; - 402 = "Linedef Executor (sector): Set Tagged Sector's Light Level"; - 403 = "Linedef Executor (plane movement): Move Tagged Sector's Floor"; - 404 = "Linedef Executor (plane movement): Move Tagged Sector's Ceiling"; - 405 = "Linedef Executor (plane movement): Move Floor According to Front Texture Offsets"; - 407 = "Linedef Executor (plane movement): Move Ceiling According to Front Texture Offsets"; - 409 = "Linedef Executor (sector): Change Tagged Sectors' Tag"; - 410 = "Linedef Executor (sector): Change Front Sector's Tag"; - 411 = "Linedef Executor (plane movement): Stop Plane Movement"; - 412 = "Linedef Executor (player/object): Teleporter"; - 413 = "Linedef Executor (misc.): Change Music"; - 414 = "Linedef Executor (misc.): Play Sound Effect"; - 415 = "Linedef Executor (misc.): Run Script"; - 416 = "Linedef Executor (sector): Start Adjustable Fire Flicker"; - 417 = "Linedef Executor (sector): Start Adjustable Glowing Light"; - 418 = "Linedef Executor (sector): Start Adjustable Blinking Light (unsynchronized)"; - 419 = "Linedef Executor (sector): Start Adjustable Blinking Light (synchronized)"; - 420 = "Linedef Executor (sector): Fade Light Level"; - 421 = "Linedef Executor (sector): Stop Lighting Effect"; - 422 = "Linedef Executor (misc.): Switch To Cut-Away View"; - 423 = "Linedef Executor (misc.): Change Sky"; - 424 = "Linedef Executor (misc.): Change Weather"; - 425 = "Linedef Executor (player/object): Change Object State"; - 426 = "Linedef Executor (player/object): Stop Object"; - 427 = "Linedef Executor (player/object): Award Score"; - 428 = "Linedef Executor (plane movement): Start Platform Movement"; - 429 = "Linedef Executor (plane movement): Crush Ceiling Once"; - 430 = "Linedef Executor (plane movement): Crush Floor Once"; - 431 = "Linedef Executor (plane movement): Crush Floor And Ceiling Once"; - 432 = "Linedef Executor (player/object): Enable/Disable 2D Mode"; - 433 = "Linedef Executor (player/object): Enable/Disable Gravity Flip"; - 434 = "Linedef Executor (player/object): Award Power-Up"; - 435 = "Linedef Executor (sector): Change Plane Scroller Direction"; - 436 = "Linedef Executor (misc.): Shatter FOF"; - 437 = "Linedef Executor (player/object): Disable Player Control"; - 438 = "Linedef Executor (player/object): Change Object Size"; - 439 = "Linedef Executor (misc.): Change Tagged Linedef Textures"; - 440 = "Linedef Executor (misc.): Start Metal Sonic Race"; - 441 = "Linedef Executor (misc.): Unlockable Trigger"; - 442 = "Linedef Executor (player/object): Change Object Type State"; - 443 = "Linedef Executor (misc.): Call Lua Function"; - 444 = "Linedef Executor (misc.): Earthquake"; - 445 = "Linedef Executor (misc.): Force Block Disappear"; - 450 = "Linedef Executor (misc.): Execute Linedef Executor (from tag)"; - 451 = "Linedef Executor (misc.): Execute Linedef Executor (random range)"; - 480 = "Linedef Executor (polyobject): Door Slide"; - 481 = "Linedef Executor (polyobject): Door Swing"; - 482 = "Linedef Executor (polyobject): Move"; - 483 = "Linedef Executor (polyobject): Move, Override"; - 484 = "Linedef Executor (polyobject): Rotate Right"; - 485 = "Linedef Executor (polyobject): Rotate Right, Override"; - 486 = "Linedef Executor (polyobject): Rotate Left"; - 487 = "Linedef Executor (polyobject): Rotate Left, Override"; - 488 = "Linedef Executor (polyobject): Move by Waypoints"; - 489 = "Linedef Executor (polyobject): Turn Invisible, Intangible"; - 490 = "Linedef Executor (polyobject): Turn Visible, Tangible"; - 491 = "Linedef Executor (polyobject): Set Translucency"; - 500 = "Wall Scrolling: Scroll Wall Front Side Left"; - 501 = "Wall Scrolling: Scroll Wall Front Side Right"; - 502 = "Wall Scrolling: Scroll Wall According to Linedef"; - 503 = "Wall Scrolling: Scroll Wall According to Linedef (Accelerative)"; - 504 = "Wall Scrolling: Scroll Wall According to Linedef (Displacement)"; - 505 = "Wall Scrolling: Scroll Texture by Front Side Offsets"; - 506 = "Wall Scrolling: Scroll Texture by Back Side Offsets"; - 510 = "Plane Scrolling: Scroll Floor Texture"; - 511 = "Plane Scrolling: Scroll Floor Texture (Accelerative)"; - 512 = "Plane Scrolling: Scroll Floor Texture (Displacement)"; - 513 = "Plane Scrolling: Scroll Ceiling Texture"; - 514 = "Plane Scrolling: Scroll Ceiling Texture (Accelerative)"; - 515 = "Plane Scrolling: Scroll Ceiling Texture (Displacement)"; - 520 = "Plane Scrolling: Carry Objects on Floor"; - 521 = "Plane Scrolling: Carry Objects on Floor (Accelerative)"; - 522 = "Plane Scrolling: Carry Objects on Floor (Displacement)"; - 523 = "Plane Scrolling: Carry Objects on Ceiling"; - 524 = "Plane Scrolling: Carry Objects on Ceiling (Accelerative)"; - 525 = "Plane Scrolling: Carry Objects on Ceiling (Displacement)"; - 530 = "Plane Scrolling: Scroll Floor Texture and Carry Objects"; - 531 = "Plane Scrolling: Scroll Floor Texture and Carry Objects (Accelerative)"; - 532 = "Plane Scrolling: Scroll Floor Texture and Carry Objects (Displacement)"; - 533 = "Plane Scrolling: Scroll Ceiling Texture and Carry Objects"; - 534 = "Plane Scrolling: Scroll Ceiling Texture and Carry Objects (Accelerative)"; - 535 = "Plane Scrolling: Scroll Ceiling Texture and Carry Objects (Displacement)"; - 540 = "Miscellaneous: Floor Friction"; - 541 = "Pusher: Wind"; - 542 = "Pusher: Upwards Wind"; - 543 = "Pusher: Downwards Wind"; - 544 = "Pusher: Current"; - 545 = "Pusher: Upwards Current"; - 546 = "Pusher: Downwards Current"; - 547 = "Pusher: Push/Pull"; - 600 = "Lighting: Floor Lighting"; - 601 = "Lighting: Ceiling Lighting"; - 602 = "Lighting: Adjustable Pulsating Light"; - 603 = "Lighting: Adjustable Flickering Light"; - 604 = "Lighting: Adjustable Blinking Light (unsynchronized)"; - 605 = "Lighting: Adjustable Blinking Light (synchronized)"; - 606 = "Lighting: Colormap"; - 900 = "Translucent Wall: 90% Opaque"; - 901 = "Translucent Wall: 80% Opaque"; - 902 = "Translucent Wall: 70% Opaque"; - 903 = "Translucent Wall: 60% Opaque"; - 904 = "Translucent Wall: 50% Opaque"; - 905 = "Translucent Wall: 40% Opaque"; - 906 = "Translucent Wall: 30% Opaque"; - 907 = "Translucent Wall: 20% Opaque"; - 908 = "Translucent Wall: 10% Opaque"; - 909 = "Translucent Wall: Fog Wall"; -} - -// THING FLAGS ----------------------------------------------------------------- - -thingflags -{ - 1 = "[0] Unused Flag"; - 2 = "[1] Object Flip"; - 4 = "[2] Object Special"; - 8 = "[3] Ambush"; - 16 = "(Used for Z offsets)"; -} - -/* THING TYPES ----------------------------------------------------------------- - -Color values: 1 = Blue 9 = Light_Blue - 2 = Green 10 = Light_Green - 3 = Cyan 11 = Light_Cyan - 4 = Red 12 = Light_Red - 5 = Magenta 13 = Pink - 6 = Brown 14 = Yellow - 7 = Gray 15 = White - 8 = Dark_Gray - -*/ - -thingtypes -{ - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 32000 = "3D Mode Start"; - 32001 - { - arrow = 0; - title = "Control Sector Position Hint"; - } - } - - starts - { - color = 1; // Blue - arrow = 1; - title = "Player Starts"; - width = 16; - height = 56; - deaftext = "[3] Spawn On Ceiling"; - - 1 - { - title = "Player 01 Start"; - sprite = "SUPTD0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "SUPTD0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "SUPTD0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "SUPTD0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "SUPTD0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "SUPTD0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "SUPTD0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "SUPTD0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "SUPTD0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "SUPTD0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "SUPTD0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "SUPTD0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "SUPTD0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "SUPTD0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "SUPTD0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "SUPTD0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "SUPTD0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "SUPTD0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "SUPTD0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "SUPTD0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "SUPTD0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "SUPTD0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "SUPTD0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "SUPTD0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "SUPTD0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "SUPTD0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "SUPTD0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "SUPTD0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "SUPTD0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "SUPTD0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "SUPTD0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "SUPTD0"; - } - 33 - { - title = "Match Start"; - sprite = "SUPTI0"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - - enemies - { - color = 9; // Light_Blue - arrow = 1; - title = "Enemies"; - width = 24; - height = 32; - sort = 1; - - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 20; - height = 24; - deaftext = "[3] Cannot Move"; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 20; - height = 24; - deaftext = "[3] Cannot Move"; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - height = 48; - deaftext = "[3] Cannot Move"; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - height = 48; - deaftext = "[3] Cannot Move"; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - height = 32; - } - 111 - { - title = "Popup Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - } - 112 - { - title = "Sharp"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - height = 48; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - deaftext = "[3] Cannot Jump"; - } - 118 - { - title = "CastleBot FaceStabber"; - sprite = "CBFSA1"; - width = 32; - height = 64; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - deaftext = "[3] Double Speed"; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA1"; - } - 122 - { - title = "Spring Shell (Green)"; - sprite = "SSHLA1"; - height = 40; - } - 123 - { - title = "Unidus"; - sprite = "UNIDA1"; - width = 18; - height = 36; - } - 124 - { - title = "AquaBuzz"; - sprite = "BBUZA1"; - width = 20; - height = 24; - } - 125 - { - title = "Spring Shell (Yellow)"; - sprite = "YSHLA1"; - height = 40; - } - 750 - { - title = " Chaos Enemy Spawn"; - sprite = "TFOGG0"; - width = 32; - height = 64; - } - } - - bosses - { - color = 8; // Dark_Gray - arrow = 1; - title = "Bosses"; - width = 24; - height = 52; - sort = 1; - - 200 - { - title = "Boss 1 - Egg Mobile"; - sprite = "EGGMA1"; - deaftext = "[3] Rotating Spikeballs"; - } - 201 - { - title = "Boss 2 - Egg Slimer"; - sprite = "EGGNA1"; - height = 48; - deaftext = "[3] Speed Up When Hit"; - } - 202 - { - title = "Boss 3 - Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 80; - } - 203 - { - title = "Boss 4 - Eggscalibur"; - sprite = "EGGPA1"; - } - 206 - { - title = "Boss - Black Eggman (Old)"; - sprite = "BRAKB1"; - width = 48; - height = 160; - } - 207 - { - title = "Boss 5A - Metal Sonic Race Start"; - sprite = "METLI1"; - width = 16; - height = 48; - } - 208 - { - title = "Boss 5B - Metal Sonic Battle Start"; - sprite = "METLC1"; - width = 16; - height = 48; - } - 209 - { - title = "Boss 6 - Black Eggman (New)"; - sprite = "BRAK[1"; - width = 48; - height = 160; - deaftext = "[3] Electric Barrier"; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - } - 291 - { - arrow = 0; - title = "Egg Trap Center"; - width = 8; - height = 16; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - deaftext = "[3] Sea Egg Shooting Point"; - } - 293 = "Metal Sonic Waypoint"; - } - - rings - { - color = 14; // Yellow - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "CPRKB0"; - } - 302 - { - title = "Rail Ring"; - sprite = "SPRKA0"; - } - 303 - { - title = "Infinity Ring"; - sprite = "RNGIA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "TAUTA3A7"; - } - 305 - { - title = "Explosion Ring"; - sprite = "BMSLA1"; - } - 306 - { - title = "Scatter Ring"; - sprite = "TSCRA1A5"; - } - 307 - { - title = "Grenade Ring"; - sprite = "TGREA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "TRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "PIKGA0"; - } - } - - collectibles - { - color = 10; // Light_Green - title = "Other Collectibles"; - width = 16; - height = 32; - sort = 1; - - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Special Stage Token"; - sprite = "TOKEA0"; - width = 8; - height = 16; - deafheight = 32; - deaftext = "[3] Float"; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "EMMYA0"; - } - 314 - { - title = "Chaos Emerald 2 (Orange)"; - sprite = "EMMYB0"; - } - 315 - { - title = "Chaos Emerald 3 (Purple)"; - sprite = "EMMYC0"; - } - 316 - { - title = "Chaos Emerald 4 (Blue)"; - sprite = "EMMYD0"; - } - 317 - { - title = "Chaos Emerald 5 (Red)"; - sprite = "EMMYE0"; - } - 318 - { - title = "Chaos Emerald 6 (Light Blue)"; - sprite = "EMMYF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "EMMYG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "EMERA0"; - } - 323 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - width = 8; - height = 16; - deafheight = 32; - deaftext = "[3] Float"; - } - } - - boxes - { - color = 7; // Gray - blocking = 2; - title = "Item Boxes"; - width = 16; - height = 32; - deaftext = "[3] Random (Weak)"; - sort = 1; - - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "SRBXA0"; - } - 401 - { - title = "Pity / Basic Shield"; - sprite = "GRTVA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "YLTVA0"; - } - 403 - { - title = "Force Shield"; - sprite = "BLTVA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "BKTVA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "WHTVA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "ELTVA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "SHTVA0"; - } - 408 - { - title = "Invincibility"; - sprite = "PINVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "PRUPA0"; - deaftext = "[3] Random (Weak) / 10k points"; - } - 410 - { - title = "Eggman"; - sprite = "EGGBA0"; - } - 411 - { - title = "Teleporter"; - sprite = "MIXUA0"; - } - 412 - { - title = "Random"; - sprite = "QUESA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "GBTVA0"; - } - 414 - { - title = "CTF Team Ring Box (Red)"; - sprite = "RRBXA0"; - deaftext = "[3] Ambush"; - } - 415 - { - title = "CTF Team Ring Box (Blue)"; - sprite = "BRBXA0"; - deaftext = "[3] Ambush"; - } - 416 - { - title = "Recycler"; - sprite = "RECYA0"; - } - 418 - { - title = "1,000 Points"; - sprite = "PTTVA0"; - } - 419 - { - title = "10,000 Points"; - sprite = "PTTVF0"; - } - } - - miscellaneous - { - color = 11; // Light_Cyan - title = "Miscellaneous"; - width = 16; - height = 40; - sort = 1; - - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLA0"; - width = 8; - height = 16; - deaftext = "[3] No Distance Check"; - } - 501 - { - title = "End Level Sign"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0"; - width = 64; - height = 80; - } - 526 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - deaftext = "[3] Not Pushable"; - } - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - deaftext = "[3] Not Pushable"; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - deaftext = "[3] Not Pushable"; - } - 1106 - { - arrow = 1; - title = "Chain (Hang)"; - sprite = "SMCHA0"; - height = 32; - deaftext = "[3] Double Size"; - } - 1107 - { - arrow = 1; - title = "Chain (Spin)"; - sprite = "SMCHA0"; - height = 32; - } - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 48; - deaftext = "[3] Tossed On Spawn"; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - deaftext = "[3] Tossed On Spawn"; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - deaftext = "[3] Not Pushable"; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - deaftext = "[3] Not Pushable"; - } - 1504 - { - title = "ATZ Target"; - sprite = "RCRYB0"; - width = 24; - height = 32; - } - } - - springs - { - color = 12; // Light_Red - title = "Springs and Fans"; - width = 20; - height = 16; - - 540 - { - title = "Fan"; - sprite = "FANSA0D0"; - width = 16; - deaftext = "[3] No Distance Check"; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - width = 32; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - } - - patterns - { - color = 5; // Magenta - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - } - 606 - { - title = "Circle of Wing Logos"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 607 - { - title = "Circle of Wing Logos (Big)"; - sprite = "NWNGA0"; - width = 192; - } - 608 - { - title = "Circle of Rings and Wings"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 609 - { - title = "Circle of Rings and Wings (Big)"; - sprite = "NWNGA0"; - width = 192; - } - } - - invisible - { - color = 15; // White - title = "Misc. Invisible"; - width = 8; - height = 16; - - 700 = "Water Ambience A (Large)"; - 701 = "Water Ambience B (Large)"; - 702 = "Water Ambience C (Medium)"; - 703 = "Water Ambience D (Medium)"; - 704 = "Water Ambience E (Small)"; - 705 = "Water Ambience F (Small)"; - 706 = "Water Ambience G (Extra Large)"; - 707 = "Water Ambience H (Extra Large)"; - 708 = "Disco Ambience"; - 709 = "Volcano Ambience"; - 751 - { - arrow = 1; - title = "Teleport Destination"; - } - 752 - { - arrow = 1; - title = "Alternate View Point"; - } - 753 = "Zoom Tube Waypoint"; - 754 - { - title = "Push Point"; - deaftext = "[3] Push Using XYZ"; - } - 755 - { - title = "Pull Point"; - deaftext = "[3] Pull Using XYZ"; - } - 760 = "PolyObject Anchor"; - 761 = "PolyObject Spawn Point"; - 762 = "PolyObject Spawn Point (Crush)"; - 780 = "Skybox View Point"; - } - - hazards - { - color = 4; // Red - title = "Hazards"; - width = 20; - height = 40; - sort = 1; - - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 523 - { - title = "Spike (Floor)"; - sprite = "USPKA0"; - width = 8; - height = 42; - deaftext = "[3] Solid"; - } - 524 - { - arrow = 1; - title = "Big Floating Mine"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 527 - { - arrow = 1; - title = "Big Floating Mine (Air)"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 525 - { - title = "Cannonball Launcher"; - sprite = "CBLLA0"; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0"; - width = 8; - height = 32; - } - 1104 - { - title = "Mace (Spinning)"; - sprite = "SMCEA0"; - deaftext = "[3] Double Size"; - } - 1105 - { - title = "Mace (Swinging)"; - sprite = "SMCEA0"; - deaftext = "[3] Double Size"; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - } - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "FLMEB0"; - width = 16; - deaftext = "[3] Waves Vertically"; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "FLMEB0"; - width = 16; - deaftext = "[3] Shoot Downwards"; - } - 1500 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle"; - sprite = "GARGA1"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 1501 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Up)"; - sprite = "GARGA1"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 1502 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Down)"; - sprite = "GARGA1"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 1503 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Long)"; - sprite = "GARGA1"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 3575 - { - title = "Spinning Flame Jet (Counter-Clockwise)"; - sprite = "FLMEB0"; - width = "16"; - } - 3576 - { - title = "Spinning Flame Jet (Clockwise)"; - sprite = "FLMEB0"; - width = "16"; - } - } - - decoration - { - color = 2; // Green - title = "Decoration"; - width = 16; - height = 40; - - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - } - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - height = 32; - } - 900 - { - title = "THZ Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CRL1A0"; - width = 8; - height = 16; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CRL2A0"; - width = 8; - height = 16; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CRL3A0"; - width = 8; - height = 16; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1100 - { - title = "Chain"; - sprite = "CHANA0"; - width = 8; - height = 128; - hangs = 1; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - } - 1203 - { - title = "Cactus with Brown Flower"; - sprite = "CACTA0"; - height = 32; - } - 1204 - { - title = "Cactus with Brown Flower (Tall)"; - sprite = "CACTB0"; - height = 64; - } - 1205 - { - title = "Cactus with Blue Flower"; - sprite = "CACTC0"; - height = 32; - } - 1206 - { - title = "Cactus with Blue Flower (Tall)"; - sprite = "CACTD0"; - height = 80; - } - 1850 - { - title = "Xmas Pole"; - sprite = "XMS1A0"; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - height = 54; - hangs = 1; - } - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STLGA0"; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STLGB0"; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STLGC0"; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STLGD0"; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STLGE0"; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STLGF0"; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STLGG0"; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STLGH0"; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STLGI0"; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STLGJ0"; - } - } - - nights - { - color = 13; // Pink - title = "Nights Items"; - width = 12; - height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - deaftext = "[3] Die Upon Time Up"; - } - 1704 - { - arrow = 1; - title = "Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - } - 1705 - { - arrow = 1; - title = "Hoop (Generic)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1706 - { - title = "Wing Logo"; - sprite = "NWNGA0"; - height = 24; - } - 1707 - { - title = "Super Loop"; - sprite = "NPRUA0"; - deaftext = "[3] Spawn Immediately"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRUB0"; - deaftext = "[3] Spawn Immediately"; - } - 1709 - { - title = "Helper"; - sprite = "NPRUC0"; - deaftext = "[3] Spawn Immediately"; - } - 1711 - { - title = "Extra Time"; - sprite = "NPRUD0"; - deaftext = "[3] Spawn Immediately"; - } - 1712 - { - title = "Link Freeze"; - sprite = "NPRUE0"; - deaftext = "[3] Spawn Immediately"; - } - 1713 - { - arrow = 1; - title = "Hoop (Customizable)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - } - - nightstrk - { - color = 13; // Pink - title = "Nights Track"; - width = 8; - height = 4096; - - 1700 - { - title = "Axis"; - circle = 1; - } - 1701 - { - title = "Axis Transfer"; - } - 1702 - { - title = "Axis Transfer Line"; - } - 1710 - { - title = "Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk1 - { - color = 13; // Pink - title = "Nights Track (2nd Mare)"; - width = 8; - height = 4096; - - 5796 - { - title = "(Mare 2) Axis"; - circle = 1; - } - 5797 - { - title = "(Mare 2) Axis Transfer"; - } - 5798 - { - title = "(Mare 2) Axis Transfer Line"; - } - 5806 - { - title = "(Mare 2) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk2 - { - color = 13; // Pink - title = "Nights Track (3rd Mare)"; - width = 8; - height = 4096; - - 9892 - { - title = "(Mare 3) Axis"; - circle = 1; - } - 9893 - { - title = "(Mare 3) Axis Transfer"; - } - 9894 - { - title = "(Mare 3) Axis Transfer Line"; - } - 9902 - { - title = "(Mare 3) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk3 - { - color = 13; // Pink - title = "Nights Track (4th Mare)"; - width = 8; - height = 4096; - - 13988 - { - title = "(Mare 4) Axis"; - circle = 1; - } - 13989 - { - title = "(Mare 4) Axis Transfer"; - } - 13990 - { - title = "(Mare 4) Axis Transfer Line"; - } - 13998 - { - title = "(Mare 4) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk4 - { - color = 13; // Pink - title = "Nights Track (5th Mare)"; - width = 8; - height = 4096; - - 18084 - { - title = "(Mare 5) Axis"; - circle = 1; - } - 18085 - { - title = "(Mare 5) Axis Transfer"; - } - 18086 - { - title = "(Mare 5) Axis Transfer Line"; - } - 18094 - { - title = "(Mare 5) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk5 - { - color = 13; // Pink - title = "Nights Track (6th Mare)"; - width = 8; - height = 4096; - - 22180 - { - title = "(Mare 6) Axis"; - circle = 1; - } - 22181 - { - title = "(Mare 6) Axis Transfer"; - } - 22182 - { - title = "(Mare 6) Axis Transfer Line"; - } - 22190 - { - title = "(Mare 6) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk6 - { - color = 13; // Pink - title = "Nights Track (7th Mare)"; - width = 8; - height = 4096; - - 26276 - { - title = "(Mare 7) Axis"; - circle = 1; - } - 26277 - { - title = "(Mare 7) Axis Transfer"; - } - 26278 - { - title = "(Mare 7) Axis Transfer Line"; - } - 26286 - { - title = "(Mare 7) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk7 - { - color = 13; // Pink - title = "Nights Track (8th Mare)"; - width = 8; - height = 4096; - - 30372 - { - title = "(Mare 8) Axis"; - circle = 1; - } - 30373 - { - title = "(Mare 8) Axis Transfer"; - } - 30374 - { - title = "(Mare 8) Axis Transfer Line"; - } - 30382 - { - title = "(Mare 8) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - mario - { - color = 6; // Brown - title = "Mario Items"; - width = 16; - height = 32; - sort = 1; - - 1800 - { - title = "Coin"; - sprite = "COINA0"; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA0"; - width = 8; - height = 16; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - height = 28; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - } - } - - srb1 - { - color = 3; // Cyan - arrow = 1; - title = "SRB1 Remake Items"; - width = 20; - height = 32; - sort = 1; - - 4000 - { - title = "SRB1 Crawla"; - sprite = "SRBAA1"; - height = 40; - } - 4001 - { - title = "GuardRobo"; - sprite = "SRBBA1"; - width = 17; - height = 40; - } - 4002 - { - title = "Pyrin"; - sprite = "SRBCB1"; - width = 22; - } - 4003 - { - title = "HotRobo"; - sprite = "SRBDA0"; - height = 40; - } - 4004 - { - title = "Pogminz"; - sprite = "SRBEA1"; - } - 4005 - { - title = "Pogminz (Water)"; - sprite = "SRBEA1"; - } - 4006 - { - title = "Pog-GX2"; - sprite = "SRBFA0"; - width = 10; - height = 34; - } - 4007 - { - title = "Pyrex"; - sprite = "SRBGA1"; - width = 24; - } - 4008 - { - title = "UFO"; - sprite = "SRBHA0"; - width = 24; - hangs = 1; - } - 4009 - { - title = "SWAT Bot"; - sprite = "SRBIA1"; - width = 21; - height = 69; - } - 4010 - { - title = "SpyBot 2000"; - sprite = "SRBJA0"; - width = 36; - height = 62; - } - 4011 - { - title = "Buzz Bomber"; - sprite = "SRBKA0"; - width = 44; - height = 45; - } - 4012 - { - arrow = 0; - title = "RBZ Spike"; - sprite = "SRBLA0"; - width = 10; - height = 53; - } - 4013 - { - arrow = 0; - blocking = 2; - title = "Dumb Metal Sonic"; - sprite = "SRBMC0"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 4014 - { - title = "Super SWAT Bot"; - sprite = "SRBNA1"; - width = 21; - height = 69; - } - 4015 - { - title = "Genrex"; - sprite = "SRBOA1"; - width = 17; - height = 40; - } - } - - bsz - { - color = 2; // Green - title = "Botanic Serenity Items"; - width = 16; - height = 32; - 1400 - { - title = "Tall Flower (Red)"; - sprite = "BSZ1A0"; - } - 1401 - { - title = "Tall Flower (Purple)"; - sprite = "BSZ1B0"; - } - 1402 - { - title = "Tall Flower (Blue)"; - sprite = "BSZ1C0"; - } - 1403 - { - title = "Tall Flower (Cyan)"; - sprite = "BSZ1D0"; - } - 1404 - { - title = "Tall Flower (Yellow)"; - sprite = "BSZ1E0"; - } - 1405 - { - title = "Tall Flower (Orange)"; - sprite = "BSZ1F0"; - } - 1410 - { - title = "Medium Flower (Red)"; - sprite = "BSZ2A0"; - } - 1411 - { - title = "Medium Flower (Purple)"; - sprite = "BSZ2B0"; - } - 1412 - { - title = "Medium Flower (Blue)"; - sprite = "BSZ2C0"; - } - 1413 - { - title = "Medium Flower (Cyan)"; - sprite = "BSZ2D0"; - } - 1414 - { - title = "Medium Flower (Yellow)"; - sprite = "BSZ2E0"; - } - 1415 - { - title = "Medium Flower (Orange)"; - sprite = "BSZ2F0"; - } - 1420 - { - title = "Short Flower (Red)"; - sprite = "BSZ3A0"; - } - 1421 - { - title = "Short Flower (Purple)"; - sprite = "BSZ3B0"; - } - 1422 - { - title = "Short Flower (Blue)"; - sprite = "BSZ3C0"; - } - 1423 - { - title = "Short Flower (Cyan)"; - sprite = "BSZ3D0"; - } - 1424 - { - title = "Short Flower (Yellow)"; - sprite = "BSZ3E0"; - } - 1425 - { - title = "Short Flower (Orange)"; - sprite = "BSZ3F0"; - } - 1430 - { - title = "Tulip (Red)"; - sprite = "BSZ4A0"; - } - 1431 - { - title = "Tulip (Purple)"; - sprite = "BSZ4B0"; - } - 1432 - { - title = "Tulip (Blue)"; - sprite = "BSZ4C0"; - } - 1433 - { - title = "Tulip (Cyan)"; - sprite = "BSZ4D0"; - } - 1434 - { - title = "Tulip (Yellow)"; - sprite = "BSZ4E0"; - } - 1435 - { - title = "Tulip (Orange)"; - sprite = "BSZ4F0"; - } - 1440 - { - title = "Cluster (Red)"; - sprite = "BSZ5A0"; - } - 1441 - { - title = "Cluster (Purple)"; - sprite = "BSZ5B0"; - } - 1442 - { - title = "Cluster (Blue)"; - sprite = "BSZ5C0"; - } - 1443 - { - title = "Cluster (Cyan)"; - sprite = "BSZ5D0"; - } - 1444 - { - title = "Cluster (Yellow)"; - sprite = "BSZ5E0"; - } - 1445 - { - title = "Cluster (Orange)"; - sprite = "BSZ5F0"; - } - 1450 - { - title = "Bush (Red)"; - sprite = "BSZ6A0"; - } - 1451 - { - title = "Bush (Purple)"; - sprite = "BSZ6B0"; - } - 1452 - { - title = "Bush (Blue)"; - sprite = "BSZ6C0"; - } - 1453 - { - title = "Bush (Cyan)"; - sprite = "BSZ6D0"; - } - 1454 - { - title = "Bush (Yellow)"; - sprite = "BSZ6E0"; - } - 1455 - { - title = "Bush (Orange)"; - sprite = "BSZ6F0"; - } - 1460 - { - title = "Vine (Red)"; - sprite = "BSZ7A0"; - } - 1461 - { - title = "Vine (Purple)"; - sprite = "BSZ7B0"; - } - 1462 - { - title = "Vine (Blue)"; - sprite = "BSZ7C0"; - } - 1463 - { - title = "Vine (Cyan)"; - sprite = "BSZ7D0"; - } - 1464 - { - title = "Vine (Yellow)"; - sprite = "BSZ7E0"; - } - 1465 - { - title = "Vine (Orange)"; - sprite = "BSZ7F0"; - } - 1470 - { - title = "BSZ Shrub"; - sprite = "BSZ8A0"; - } - 1471 - { - title = "BSZ Clover"; - sprite = "BSZ8B0"; - } - 1472 - { - title = "BSZ Fish"; - sprite = "BSZ8C0"; - } - 1473 - { - title = "BSZ Sunflower"; - sprite = "BSZ8D0"; - } - } -} diff --git a/extras/conf/Srb2-21wb.cfg b/extras/conf/Srb2-21wb.cfg deleted file mode 100644 index 01f8762ac..000000000 --- a/extras/conf/Srb2-21wb.cfg +++ /dev/null @@ -1,2970 +0,0 @@ -/******************************************************************************\ - - SRB2 Workbench - Game Configuration for SRB2 version 2.0. - - Contributors: - - Kristos - - Shadow Hog - - ST218 - - Foxboy - - JJames19119 - - SRB2-Playah - - Oogaland - - SSNTails - - DarkWarrior - - Neo - -\******************************************************************************/ - -// This is required to prevent accedential use of a different configuration. -type = "SRB2 Workbench Game Configuration"; - -// This is the title to show for this game. -game = "Sonic Robo Blast 2 v2.1"; - -// This is used internally to refer to the game. -id = "srb2-21wb"; - -// Tells Workbench that 2.1 has 4 different sector type options -seceffectnybble = 1; -thingeffectnybble = 1; - -// Defaults for new thing. -defaultthingflags = 0; -defaultthing = 1; - -// Flags indicating which header features are supported. See -// ENUM_MAPHEADER_FLAGS in soc.h for values. -headerflags = 29360130; // Map Credits, Run SOC, Subtitle, Speed Music. - -// Thing numbers for Nights axes. -nights -{ - axistransfer = 1701; - axistransferline = 1702; -} - -// Wiki page names. -wiki -{ - seceffect = "Sector+Type+%d"; - ldeffect = "Linedef+Type+%d"; - thing = "Thing+Type+%d"; -} - -// Map-type flags for the TypeOfLevel header option. -leveltypes -{ - 1 = "Single Player"; - 2 = "Co-op"; - 4 = "Competition"; - 8 = "Race"; - 16 = "Match"; - 32 = "Tag/Hide and Seek"; - 64 = "Capture the Flag"; - 128 = "Chaos (disabled)"; - 256 = "2D"; - 512 = "Mario"; - 1024 = "NiGHTS"; - 2048 = "Egg Rock Zone 3"; -} - -// Weather types for use in the header-editor. -weather -{ - 0 = "None"; - 1 = "Storm"; - 2 = "Snow"; - 3 = "Rain"; - 4 = "Blank (precalculate)"; - 5 = "Storm (no rain)"; - 6 = "Storm (no strikes)"; - 7 = "Heat Wave"; -} - -/* PSEUDO-FLATS AND TEXTURES --------------------------------------------------- - -Names of flats and textures that don't really exist, but shouldn't be identified -as invalid. - -Pattern-matching is performed on lump names. You can use the following wildcards -in values to specify ranges: - -? = Any character. -* = Zero or more characters. -# = Any numeric digit. -[abc...] = Any of these characters that are between brackets. -[!abc..] = Not any of these characters that are between brackets. - -TODO: Not actually used yet! - -*/ - -pseudoflats -{ - F_SKY1; -} - -pseudotextures -{ - [#]*; -} - -// Sky flat, used to determine whether upper/lower textures are required. -sky = "F_SKY1"; - -/* MAP LUMP NAMES -------------------------------------------------------------- - -Map lumps are loaded with the map as long as they are right after each other. -When the editor meets a lump which is not defined in this list, it will stop -loading right there. - - 1 = Lump required. - 2 = Lump which must be respected. - 4 = Lump generated by node builder. - 8 = Lump allowed to be empty after nodebuilding. - 16 = Lump allowed to be missing after nodebuilding. - 4096 = Lump which can be edited as text. - 8192 = Lump which can be edited as DEHACKED. -12288 = Lump which can be edited as MAPINFO. -16384 = WAD-global. - -*/ - -maplumpnames -{ - THINGS = 13; - LINEDEFS = 5; - SIDEDEFS = 5; - VERTEXES = 5; - SEGS = 4; - SSECTORS = 4; - NODES = 4; - SECTORS = 5; - REJECT = 4; - BLOCKMAP = 20; -} - -// SECTOR TYPES ---------------------------------------------------------------- - -sectortypes -{ - nybble0 - { - 0 = "(normal)"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Modifications)"; - 7 = "Death Pit (No Camera Modifications)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (No Floor Touch)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy Sector (FOF Control Only)"; - } - - nybble1 - { - 0 = "(normal)"; - 1 = "Trigger Linedef Executor (Pushable Objects)"; - 2 = "Trigger Linedef Executor (Anywhere, All Players)"; - 3 = "Trigger Linedef Executor (Floor Touch, All Players)"; - 4 = "Trigger Linedef Executor (Anywhere in Sector)"; - 5 = "Trigger Linedef Executor (Floor Touch)"; - 6 = "Trigger Linedef Executor (Emerald Check)"; - 7 = "Trigger Linedef Executor (Nights Mare)"; - 8 = " Check for Linedef Executor on FOFs"; - 9 = "Egg Trap Capsule"; - 10 = "Special Stage Time/Rings Parameters"; - 11 = "Custom Global Gravity"; - } - - nybble2 - { - 0 = "(normal)"; - 1 = "Ice/Sludge"; - 2 = "Wind/Current"; - 3 = "Ice/Sludge and Wind/Current"; - 4 = "Conveyor Belt"; - 5 = "Speed Pad (No Spin)"; - 6 = "Speed Pad (Spin)"; - 7 = "Bustable Block Sprite Parameter (ROIA)"; - 8 = "Bustable Block Sprite Parameter (ROIB)"; - 9 = "Bustable Block Sprite Parameter (ROIC)"; - 10 = "Bustable Block Sprite Parameter (ROID)"; - 11 = "Bustable Block Sprite Parameter (ROIE)"; - 12 = "Bustable Block Sprite Parameter (ROIF)"; - 13 = "Bustable Block Sprite Parameter (ROIG)"; - 14 = "Bustable Block Sprite Parameter (ROIH)"; - 15 = "Bustable Block Sprite Parameter (ROII)"; - } - - nybble3 - { - 0 = "(normal)"; - 1 = "Star Post Activator"; - 2 = "Exit/Special Stage Goal/Return Flag"; - 3 = "CTF: Red Team Base"; - 4 = "CTF: Blue Team Base"; - 5 = "Fan Sector"; - 6 = "Super Sonic Transform"; - 7 = "Spinner"; - 8 = "Zoom Tube Start"; - 9 = "Zoom Tube End"; - 10 = "Finish Line"; - 11 = "Rope Hang"; - 12 = "Intangible to the Camera"; - } -} - -// LINEDEF FLAGS --------------------------------------------------------------- - -linedefflags -{ - 1 = "[00] Effect 6"; - 2 = "[01] Block Enemies"; - 4 = "[02] Double-Sided"; - 8 = "[03] Upper Unpegged"; - 16 = "[04] Lower Unpegged"; - 32 = "[05] Effect 1"; - 64 = "[06] Not Climbable"; - 128 = "[07] Effect 2"; - 256 = "[08] Effect 3"; - 512 = "[09] Effect 4"; - 1024 = "[10] Effect 5"; - 2048 = "[11] No Sonic"; - 4096 = "[12] No Tails"; - 8192 = "[13] No Knuckles"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - -// FOF INFORMATION ------------------------------------------------------------- - -fofs -{ - default = 100; - colourmap = 606; - defaultcustom = 259; - - // The FOF linedef specials, together with their FOF flags and a few - // other fields. - specials - { - 100 {flags = 415;} - 101 {flags = 479;} - 102 {flags = 6495;} - 103 {flags = 463;} - 104 {flags = 471;} - 105 {flags = 71;} - 120 {flags = 36665;} - 121 {flags = 40761;} - 122 {flags = 3889;} - 123 {flags = 7985;} - 124 {flags = 2137913;} - 125 {flags = 2105137;} - 140 {flags = 33588255;} - 141 {flags = 33560863;} - 142 {flags = 33560855;} - 143 {flags = 67142687;} - 144 {flags = 67115295;} - 145 {flags = 67115287;} - 146 {flags = 100696079;} - 150 {flags = 415; airbob = 1;} - 151 {flags = 415; airbob = 1;} - 152 {flags = 415; airbob = 1;} - 160 {flags = 262559; airbob = 1;} - 170 {flags = 1048991;} - 171 {flags = 1573279;} - 172 {flags = 34636831;} - 173 {flags = 35161119;} - 174 {flags = 34641311;} - 175 {flags = 35165599;} - 176 {flags = 1311135; airbob = 1;} - 177 {flags = 1835423; airbob = 1;} - 178 {flags = 1311135;} - 179 {flags = 1835423;} - 180 {flags = 1048991;} - 190 {flags = 415; rising = 1;} - 191 {flags = 479; rising = 1;} - 192 {flags = 6495; rising = 1;} - 193 {flags = 71; rising = 1;} - 194 {flags = 33588255; rising = 1;} - 195 {flags = 33594655; rising = 1;} - 200 {flags = 131585;} - 201 {flags = 513;} - 202 {flags = 257817;} - 220 {flags = 36633;} - 221 {flags = 6937;} - 222 {flags = 32777;} - 223 {flags = 65;} - 250 {flags = 4194719;} - 251 {flags = 415;} - 252 {flags = 142606367;} - 253 {flags = 142610463;} - 254 {flags = 8388639;} - 255 {flags = 276824095;} - 256 {flags = 276828191;} - 257 {flags = 16810521;} - 258 {flags = 2393;} - 259 {custom = 1;} - } - - // The significance of the FOF flags. Some of these have special - // meanings to the editor; for those which don't, the subsection name is - // ignored, but an entry will still be added to the list of flags for - // custom FOFs. - flags - { - FF_EXISTS {value = 1; text = "Exists.";} - FF_BLOCKPLAYER {value = 2; text = "Solid to players.";} - FF_BLOCKOTHERS {value = 4; text = "Solid to everything else.";} -// FF_SOLID {value = 6; text = "Solid to all objects."} - FF_RENDERSIDES {value = 8; text = "Renders the walls.";} - FF_RENDERPLANES {value = 16; text = "Renders the planes.";} -// FF_RENDERALL {value = 24; text = "Renders everything.} - FF_SWIMMABLE {value = 32; text = "Water block.";} - FF_NOSHADE {value = 64; text = "Doesn't cast a shadow.";} - FF_CUTSOLIDS {value = 128; text = "Skips rendering pixels hidden behind the block.";} - FF_CUTEXTRA {value = 256; text = "Skips rendering blocks marked with FF_EXTRA hidden behind the block.";} -// FF_CUTLEVEL {value = 384; text = "Skips rendering everything hidden behind the block."} - FF_CUTSPRITES {value = 512; text = "Splits sprites halfway inside the block.";} - FF_BOTHPLANES {value = 1024; text = "Renders both inside and outside planes.";} - FF_EXTRA {value = 2048; text = "Not rendered when seen through a block marked with FF_CUTEXTRA.";} - FF_TRANSLUCENT {value = 4096; text = "Translucent.";} - FF_FOG {value = 8192; text = "Fog block.";} - FF_INVERTPLANES {value = 16384; text = "Renders the planes only when within the block.";} - FF_ALLSIDES {value = 32768; text = "Renders both inside and outside walls.";} - FF_INVERTSIDES {value = 65536; text = "Renders the walls only when within the block.";} - FF_DOUBLESHADOW {value = 131072; text = "Light level and colormap affect only the inside of the block.";} - FF_FLOATBOB {value = 262144; text = "Floats on water and bobs when stepped on.";} - FF_NORETURN {value = 524288; text = "(Use with FF_CRUMBLE) Doesn't respawn after crumbling.";} - FF_CRUMBLE {value = 1048576; text = "Crumbles two seconds after being stepped on.";} - FF_SHATTERBOTTOM {value = 2097152; text = "(Use with FF_BUSTUP) Breaks only when hit from below.";} - FF_MARIO {value = 4194304; text = "Mario item block.";} - FF_BUSTUP {value = 8388608; text = "Can be broken by a spin or Knuckles.";} - FF_QUICKSAND {value = 16777216; text = "Quicksand block.";} - FF_PLATFORM {value = 33554432; text = "Intangible from bottom.";} - FF_REVERSEPLATFORM {value = 67108864; text = "Intangible from top.";} -// FF_INTANGABLEFLATS {value = 100663296; text = "Only tangible from sides.";} - FF_SHATTER {value = 134217728; text = "(Use with FF_BUSTUP) Breaks on any contact.";} - FF_SPINBUST {value = 268435456; text = "(Use with FF_BUSTUP) Breaks only with a spin from above.";} - FF_ONLYKNUX {value = 536870912; text = "(Use with FF_BUSTUP) Can only be broken by Knuckles.";} - FF_RIPPLE {value = 1073741824; text = "Employs a visual ripple effect.";} -// FF_COLORMAPONLY {value = 2147483648; text = "Ignores the control sector's light level.";} - } -} - -// LINEDEF TYPES --------------------------------------------------------------- - -linedeftypes -{ - misc - { - title = "Miscellaneous"; - values - { - 0 = "(normal)"; - 1 = "Per-Sector Gravity"; - 4 = "Speed Pad"; - 5 = "Camera Scanner"; - 6 = "Disable Linedef Effect On Level Load"; - 7 = "Sector Flat Alignment"; - 10 = "Culling Plane"; - 13 = "Heat Wave Effect"; - 50 = "Instantly Lower Floor On Level Load"; - 51 = "Instantly Raise Ceiling On Level Load"; - 63 = "Fake Floor/Ceiling Planes"; - 540 = "Floor Friction"; - } - } - - parameters - { - title = "Parameters"; - values - { - 2 = "Custom Exit"; - 3 = "Zoom Tube Parameters"; - 8 = "Sector Special Parameters"; - 9 = "Chain Parameters"; - 11 = "Rope Hang Parameters"; - 12 = "Rock Spawn Parameters"; - 64 = "Appearing/Disappearing FOF"; - 65 = " Bridge Thinker"; - } - } - - polyobject - { - title = "PolyObject"; - values - { - 20 = "First Line"; - 21 = "Explicity Include Line"; - 22 = "Parameters"; - 30 = "Waving Flag"; - } - } - - movement - { - title = "Plane Movement"; - values - { - 52 = "Continuously Falling Sector"; - 53 = "Continuous Floor/Ceiling Mover"; - 54 = "Continuous Floor Mover"; - 55 = "Continuous Ceiling Mover"; - 56 = "Continuous Two-Speed Floor/Ceiling Mover"; - 57 = "Continuous Two-Speed Floor Mover"; - 58 = "Continuous Two-Speed Ceiling Mover"; - 59 = "Activate Moving Platform"; - 60 = "Activate Moving Platform (Adjustable Speed)"; - 61 = "Crusher (Ceiling to Floor)"; - 62 = "Crusher (Floor to Ceiling)"; - } - } - - fofsolid - { - title = "FOF (solid)"; - values - { - 100 = "Solid, Opaque"; - 101 = "Solid, Opaque, No Shadow"; - 102 = "Solid, Translucent"; - 103 = "Solid, Sides Only"; - 104 = "Solid, No Sides"; - 105 = "Solid, Invisible"; - 140 = "Intangible from Bottom, Opaque"; - 141 = "Intangible from Bottom, Translucent"; - 142 = "Intangible from Bottom, Translucent, No Sides"; - 143 = "Intangible from Top, Opaque"; - 144 = "Intangible from Top, Translucent"; - 145 = "Intangible from Top, Translucent, No Sides"; - 146 = "Only Tangible From Sides"; - } - } - - fofintangible - { - title = "FOF (intangible)"; - values - { - 120 = "Water, Opaque"; - 121 = "Water, Translucent"; - 122 = "Water, Opaque, No Sides"; - 123 = "Water, Translucent, No Sides"; - 124 = "Goo Water, Translucent"; - 125 = "Goo Water, Translucent, No Sides"; - 220 = "Intangible, Opaque"; - 221 = "Intangible, Translucent"; - 222 = "Intangible, Sides Only"; - 223 = "Intangible, Invisible"; - } - } - - fofbobbing - { - title = "FOF (bobbing)"; - values - { - 150 = " Air Bobbing"; - 151 = " Air Bobbing (Adjustable)"; - 152 = " Reverse Air Bobbing (Adjustable)"; - 160 = "Floating, Bobbing"; - 190 = "Rising Platform, Solid, Opaque"; - 191 = "Rising Platform, Solid, Opaque, No Shadow"; - 192 = "Rising Platform, Solid, Translucent"; - 193 = "Rising Platform, Solid, Invisible"; - 194 = "Rising Platform, Intangible from Bottom, Opaque"; - 195 = "Rising Platform, Intangible from Bottom, Translucent"; - } - } - - fofcrumbling - { - title = "FOF (crumbling)"; - values - { - 170 = "Crumbling (Respawn)"; - 171 = "Crumbling (No Respawn)"; - 172 = "Crumbling (Respawn), Intangible from Bottom"; - 173 = "Crumbling (No Respawn), Intangible from Bottom"; - 174 = "Crumbling (Respawn), Int. from Bottom, Translucent"; - 175 = "Crumbling (No Respawn), Int. from Bottom, Translucent"; - 176 = "Crumbling (Respawn), Floating, Bobbing"; - 177 = "Crumbling (No Respawn), Floating, Bobbing"; - 178 = "Crumbling (Respawn), Floating"; - 179 = "Crumbling (No Respawn), Floating"; - 180 = "Crumbling (Respawn), Air Bobbing"; - } - } - - fofspecial - { - title = "FOF (special)"; - values - { - 200 = "Light Block"; - 201 = "Half Light Block"; - 202 = "Fog Block"; - 250 = "Mario Block"; - 251 = "Thwomp Block"; - 252 = "Shatter Block"; - 253 = "Shatter Block, Translucent"; - 254 = "Bustable Block"; - 255 = "Spin Bust Block"; - 256 = "Spin Bust Block, Translucent"; - 257 = "Quicksand"; - 258 = "Laser"; - 259 = "Custom FOF"; - } - } - - trigger - { - title = "Linedef Executor Trigger"; - values - { - 300 = "Continuous"; - 301 = "Each Time"; - 302 = "Once"; - 303 = "Ring Count - Continuous"; - 304 = "Ring Count - Once"; - 305 = "Character Ability - Once"; - 306 = "Character Ability - Each Time"; - 307 = "Character Ability - Continuous"; - 308 = "Race Only - Once"; - 309 = "CTF Red Team - Continuous"; - 310 = "CTF Red Team - Each Time"; - 311 = "CTF Blue Team - Continuous"; - 312 = "CTF Blue Team - Each Time"; - 313 = "No More Enemies - Once"; - 314 = "Number of Pushables - Continuous"; - 315 = "Number of Pushables - Once"; - 316 = "Land On PolyObject"; - 317 = "Unlockable Trigger - Continuous"; - 318 = "Unlockable Trigger - Once"; - 399 = "Level Load"; - } - } - - execsector - { - title = "Linedef Executor (sector)"; - values - { - 400 = "Set Tagged Sector's Floor Height/Texture"; - 401 = "Set Tagged Sector's Ceiling Height/Texture"; - 402 = "Set Tagged Sector's Light Level"; - 409 = "Change Tagged Sectors' Tag"; - 410 = "Change Front Sector's Tag"; - 416 = "Start Adjustable Fire Flicker"; - 417 = "Start Adjustable Glowing Light"; - 418 = "Start Adjustable Blinking Light (unsynchronized)"; - 419 = "Start Adjustable Blinking Light (synchronized)"; - 420 = "Fade Light Level"; - 421 = "Stop Lighting Effect"; - 435 = "Change Plane Scroller Direction"; - } - } - - execplane - { - title = "Linedef Executor (plane movement)"; - values - { - 403 = "Move Tagged Sector's Floor"; - 404 = "Move Tagged Sector's Ceiling"; - 405 = "Move Floor According to Front Texture Offsets"; - 407 = "Move Ceiling According to Front Texture Offsets"; - 411 = "Stop Plane Movement"; - 428 = "Start Platform Movement"; - 429 = "Crush Ceiling Once"; - 430 = "Crush Floor Once"; - 431 = "Crush Floor And Ceiling Once"; - } - } - - execplayer - { - title = "Linedef Executor (player/object)"; - values - { - 412 = "Teleporter"; - 425 = "Change Object State"; - 426 = "Stop Object"; - 427 = "Award Score"; - 432 = "Enable/Disable 2D Mode"; - 433 = "Enable/Disable Gravity Flip"; - 434 = "Award Power-Up"; - 437 = "Disable Player Control"; - 438 = "Change Object Size"; - 442 = "Change Object Type State"; - } - } - - execmisc - { - title = "Linedef Executor (misc.)"; - values - { - 413 = "Change Music"; - 414 = "Play Sound Effect"; - 415 = "Run Script"; - 422 = "Switch to Cut-Away View"; - 423 = "Change Sky"; - 424 = "Change Weather"; - 436 = "Shatter FOF"; - 439 = "Set Texture"; - 440 = "Start Metal Sonic Race"; - 441 = "Unlockable Trigger"; - 443 = "Call Lua Function"; - 444 = "Earthquake"; - 445 = "Force Block Disappear"; - 450 = "Execute Linedef Executor (from tag)"; - 451 = "Execute Linedef Executor (random range)"; - } - } - - execpoly - { - title = "Linedef Executor (polyobject)"; - values - { - 480 = "Door Slide"; - 481 = "Door Swing"; - 482 = "Move"; - 483 = "Move, Override"; - 484 = "Rotate Right"; - 485 = "Rotate Right, Override"; - 486 = "Rotate Left"; - 487 = "Rotate Left, Override"; - 488 = "Move by Waypoints"; - 489 = "Turn Invisible, Intangible"; - 490 = "Turn Visible, Tangible"; - 491 = "Set Translucency"; - } - } - - wall - { - title = "Texture settings/Wall Scrolling"; - values - { - 500 = "Scroll Wall Front Side Left"; - 501 = "Scroll Wall Front Side Right"; - 502 = "Scroll Wall According to Linedef"; - 503 = "Scroll Wall According to Linedef (Accelerative)"; - 504 = "Scroll Wall According to Linedef (Displacement)"; - 505 = "Scroll Texture by Front Side Offsets"; - 506 = "Scroll Texture by Back Side Offsets"; - } - } - - plane - { - title = "Plane Scrolling"; - values - { - 510 = "Scroll Floor Texture"; - 511 = "Scroll Floor Texture (Accelerative)"; - 512 = "Scroll Floor Texture (Displacement)"; - 513 = "Scroll Ceiling Texture"; - 514 = "Scroll Ceiling Texture (Accelerative)"; - 515 = "Scroll Ceiling Texture (Displacement)"; - 520 = "Carry Objects on Floor"; - 521 = "Carry Objects on Floor (Accelerative)"; - 522 = "Carry Objects on Floor (Displacement)"; - 523 = "Carry Objects on Ceiling"; - 524 = "Carry Objects on Ceiling (Accelerative)"; - 525 = "Carry Objects on Ceiling (Displacement)"; - 530 = "Scroll Floor Texture and Carry Objects"; - 531 = "Scroll Floor Texture and Carry Objects (Accelerative)"; - 532 = "Scroll Floor Texture and Carry Objects (Displacement)"; - 533 = "Scroll Ceiling Texture and Carry Objects"; - 534 = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; - 535 = "Scroll Ceiling Texture and Carry Objects (Displacement)"; - } - } - - pusher - { - title = "Pusher"; - values - { - 541 = "Wind"; - 542 = "Upwards Wind"; - 543 = "Downwards Wind"; - 544 = "Current"; - 545 = "Upwards Current"; - 546 = "Downwards Current"; - 547 = "Push/Pull"; - } - } - - lighting - { - title = "Lighting"; - values - { - 600 = "Floor Lighting"; - 601 = "Ceiling Lighting"; - 602 = "Adjustable Pulsating Light"; - 603 = "Adjustable Flickering Light"; - 604 = "Adjustable Blinking Light (unsynchronized)"; - 605 = "Adjustable Blinking Light (synchronized)"; - 606 = "Colormap"; - } - } - - transwall - { - title = "Translucent Wall"; - values - { - 900 = "90% Opaque"; - 901 = "80% Opaque"; - 902 = "70% Opaque"; - 903 = "60% Opaque"; - 904 = "50% Opaque"; - 905 = "40% Opaque"; - 906 = "30% Opaque"; - 907 = "20% Opaque"; - 908 = "10% Opaque"; - 909 = "Fog Wall"; - } - } -} - -// THING FLAGS ----------------------------------------------------------------- - -thingflags -{ - 1 = "[0] Unused Flag"; - 2 = "[1] Object Flip"; - 4 = "[2] Object Special"; - 8 = "[3] Ambush"; - 16 = "(Used for Z offsets)"; -} - -/* THING TYPES ----------------------------------------------------------------- - -Color values are 24-bit RGB colors in decimal. - -*/ - -thingtypes -{ - starts - { - color = 223; // Blue (0000DF) - arrow = 1; - title = "Player Starts"; - width = 16; - height = 56; - deaftext = "[3] Spawn On Ceiling"; - values - { - 1 - { - title = "Player 01 Start"; - sprite = "SUPTD0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "SUPTD0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "SUPTD0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "SUPTD0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "SUPTD0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "SUPTD0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "SUPTD0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "SUPTD0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "SUPTD0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "SUPTD0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "SUPTD0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "SUPTD0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "SUPTD0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "SUPTD0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "SUPTD0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "SUPTD0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "SUPTD0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "SUPTD0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "SUPTD0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "SUPTD0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "SUPTD0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "SUPTD0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "SUPTD0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "SUPTD0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "SUPTD0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "SUPTD0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "SUPTD0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "SUPTD0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "SUPTD0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "SUPTD0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "SUPTD0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "SUPTD0"; - } - 33 - { - title = "Match Start"; - sprite = "SUPTI0"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - } - - enemies - { - color = 6250495; // Light blue (5F5FFF) - arrow = 1; - title = "Enemies"; - width = 24; - height = 32; - values - { - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 20; - height = 24; - deaftext = "[3] Cannot Move"; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 20; - height = 24; - deaftext = "[3] Cannot Move"; - - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - height = 50; - deaftext = "[3] Cannot Move"; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - height = 48; - deaftext = "[3] Cannot Move"; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - height = 32; - } - 111 - { - title = "Popup Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - } - 112 - { - title = "Sharp"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - height = 48; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - deaftext = "[3] Cannot Jump"; - } - 118 - { - title = "CastleBot FaceStabber"; - sprite = "CBFSA1"; - width = 32; - height = 64; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - deaftext = "[3] Double Speed"; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA1"; - } - 122 - { - title = "Spring Shell (Green)"; - sprite = "SSHLA1"; - height = 40; - } - 123 - { - title = "Unidus"; - sprite = "UNIDA1"; - width = 18; - height = 36; - } - 124 - { - title = "AquaBuzz"; - sprite = "BBUZA1"; - width = 20; - height = 24; - } - 125 - { - title = "Spring Shell (Yellow)"; - sprite = "YSHLA1"; - height = 40; - } - 750 - { - title = " Chaos Enemy Spawn"; - sprite = "TFOGG0"; - width = 32; - height = 64; - } - } - } - - bosses - { - color = 6250335; // Grey (5F5F5F) - arrow = 1; - title = "Bosses"; - width = 24; - height = 76; - values - { - 200 - { - title = "Boss 1 - Egg Mobile"; - sprite = "EGGMA1"; - spectext = "[2] End Level On Death"; - deaftext = "[3] Rotating Spikeballs"; - } - 201 - { - title = "Boss 2 - Egg Slimer"; - sprite = "EGGNA1"; - height = 48; - spectext = "[2] End Level On Death"; - deaftext = "[3] Speed Up When Hit"; - } - 202 - { - title = "Boss 3 - Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 116; - spectext = "[2] End Level On Death"; - } - 203 - { - title = "Boss 4 - Eggscalibur"; - sprite = "EGGPA1"; - spectext = "[2] End Level On Death"; - } - 206 - { - title = "Boss - Black Eggman (Old)"; - sprite = "BRAKB1"; - width = 48; - height = 160; - spectext = "[2] End Level On Death"; - } - 207 - { - title = "Boss 5A - Metal Sonic Race Start"; - sprite = "METLI1"; - width = 16; - height = 48; - } - 208 - { - title = "Boss 5B - Metal Sonic Battle Start"; - sprite = "METLC1"; - width = 16; - height = 48; - spectext = "[2] End Level On Death"; - } - 209 - { - title = "Boss 6 - Black Eggman (New)"; - sprite = "BRAK[1"; - width = 48; - height = 160; - spectext = "[2] End Level On Death"; - deaftext = "[3] Electric Barrier"; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - } - 291 - { - arrow = 0; - title = "Egg Trap Center"; - width = 8; - height = 16; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - deaftext = "[3] Sea Egg Shooting Point"; - } - 293 = "Metal Sonic Waypoint"; - } - } - - rings - { - color = 12566272; // Yellow (BFBF00) - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - values - { - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "CPRKB0"; - } - 302 - { - title = "Rail Ring"; - sprite = "SPRKA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "TAUTA3A7"; - } - 305 - { - title = "Explosion Ring"; - sprite = "BMSLA1"; - } - 306 - { - title = "Scatter Ring"; - sprite = "TSCRA1A5"; - } - 307 - { - title = "Grenade Ring"; - sprite = "TGREA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "TRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "PIKGA0"; - } - } - } - - collectibles - { - color = 48896; // Green (00BF00) - title = "Other Collectibles"; - width = 16; - height = 32; - values - { - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Special Stage Token"; - sprite = "TOKEA0"; - width = 8; - height = 16; - deafheight = 32; - spectext = "[2] Mario Block Version"; - deaftext = "[3] Float"; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "EMMYA0"; - } - 314 - { - title = "Chaos Emerald 2 (Purple)"; - sprite = "EMMYB0"; - } - 315 - { - title = "Chaos Emerald 3 (Blue)"; - sprite = "EMMYC0"; - } - 316 - { - title = "Chaos Emerald 4 (Cyan)"; - sprite = "EMMYD0"; - } - 317 - { - title = "Chaos Emerald 5 (Orange)"; - sprite = "EMMYE0"; - } - 318 - { - title = "Chaos Emerald 6 (Red)"; - sprite = "EMMYF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "EMMYG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "EMERA0"; - } - 323 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - width = 8; - height = 48; - deafheight = 32; - deaftext = "[3] Float"; - } - } - } - - boxes - { - color = 12566463; // Silver (BFBFBF) - blocking = 2; - title = "Item Boxes"; - width = 16; - height = 32; - spectext = "[2] Random (Strong)"; - deaftext = "[3] Random (Weak)"; - values - { - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "SRBXA0"; - } - 401 - { - title = "Pity / Basic Shield"; - sprite = "GRTVA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "YLTVA0"; - } - 403 - { - title = "Force Shield"; - sprite = "BLTVA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "BKTVA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "WHTVA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "ELTVA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "SHTVA0"; - } - 408 - { - title = "Invincibility"; - sprite = "PINVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "PRUPA0"; - spectext = "[2] Random (Strong) / 10k points"; - deaftext = "[3] Random (Weak) / 10k points"; - } - 410 - { - title = "Eggman"; - sprite = "EGGBA0"; - } - 411 - { - title = "Teleporter"; - sprite = "MIXUA0"; - } - 412 - { - title = "Random"; - sprite = "QUESA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "GBTVA0"; - } - 414 - { - title = "CTF Team Ring Box (Red)"; - sprite = "RRBXA0"; - spectext = "[2] Object Special"; - deaftext = "[3] Ambush"; - } - 415 - { - title = "CTF Team Ring Box (Blue)"; - sprite = "BRBXA0"; - spectext = "[2] Object Special"; - deaftext = "[3] Ambush"; - } - 416 - { - title = "Recycler"; - sprite = "RECYA0"; - } - 418 - { - title = "1,000 Points"; - sprite = "PTTVA0"; - } - 419 - { - title = "10,000 Points"; - sprite = "PTTVF0"; - } - } - } - - miscellaneous - { - color = 49119; // Sky blue (00BFDF) - title = "Miscellaneous"; - width = 16; - height = 40; - values - { - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLA0"; - width = 8; - height = 16; - deaftext = "[3] No Distance Check"; - } - 501 - { - title = "End Level Sign"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0"; - width = 64; - height = 80; - } - 526 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 1106 - { - arrow = 1; - title = "Chain (Hang)"; - sprite = "SMCHA0"; - height = 32; - deaftext = "[3] Double Size"; - } - 1107 - { - arrow = 1; - title = "Chain (Spin)"; - sprite = "SMCHA0"; - height = 32; - deaftext = "[3] Double Size"; - } - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 28; - deaftext = "[3] Moves Perpetually"; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - deaftext = "[3] Moves Perpetually"; - } - 1504 - { - title = "ATZ Target"; - sprite = "RCRYB0"; - width = 24; - height = 32; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - } - } - - springs - { - color = 14614528; // Red (DF0000) - title = "Springs and Fans"; - width = 20; - height = 16; - values - { - 540 - { - title = "Fan"; - sprite = "FANSA0D0"; - width = 16; - deaftext = "[3] No Distance Check"; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - width = 32; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - } - } - - patterns - { - color = 10420319; // Dark Rose (9F005F) - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - values - { - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - } - 606 - { - title = "Circle of Wing Logos"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 607 - { - title = "Circle of Wing Logos (Big)"; - sprite = "NWNGA0"; - width = 192; - } - 608 - { - title = "Circle of Rings and Wings"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 609 - { - title = "Circle of Rings and Wings (Big)"; - sprite = "NWNGA0"; - width = 192; - } - } - } - - invisible - { - color = 16777215; // White (FFFFFF) - title = "Misc. Invisible"; - width = 8; - height = 16; - values - { - 700 = "Water Ambience A (Large)"; - 701 = "Water Ambience B (Large)"; - 702 = "Water Ambience C (Medium)"; - 703 = "Water Ambience D (Medium)"; - 704 = "Water Ambience E (Small)"; - 705 = "Water Ambience F (Small)"; - 706 = "Water Ambience G (Extra Large)"; - 707 = "Water Ambience H (Extra Large)"; - 708 = "Disco Ambience"; - 709 = "Volcano Ambience"; - 751 - { - arrow = 1; - title = "Teleport Destination"; - } - 752 - { - arrow = 1; - title = "Alternate View Point"; - } - 753 = "Zoom Tube Waypoint"; - 754 - { - title = "Push Point"; - spectext = "[2] Fades Using XY"; - deaftext = "[3] Push Using XYZ"; - } - 755 - { - title = "Pull Point"; - spectext = "[2] Fades Using XY"; - deaftext = "[3] Pull Using XYZ"; - } - 760 = "PolyObject Anchor"; - 761 = "PolyObject Spawn Point"; - 762 = "PolyObject Spawn Point (Crush)"; - 780 - { - title = "Skybox View Point"; - spectext = "[2] In-Map Reference Point"; - } - } - } - - hazards - { - color = 10420224; // Maroon (9F0000) - title = "Hazards"; - width = 20; - height = 40; - values - { - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 523 - { - title = "Spike (Floor)"; - sprite = "USPKA0"; - width = 8; - height = 42; - spectext = "[2] Retractable"; - deaftext = "[3] Solid"; - } - 524 - { - arrow = 1; - title = "Big Floating Mine"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 527 - { - arrow = 1; - title = "Big Floating Mine (Air)"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 525 - { - title = "Cannonball Launcher"; - sprite = "CBLLA0"; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0"; - width = 8; - height = 32; - } - 1104 - { - title = "Mace (Spinning)"; - sprite = "SMCEA0"; - spectext = "[2] No Sounds"; - deaftext = "[3] Double Size"; - } - 1105 - { - title = "Mace (Swinging)"; - sprite = "SMCEA0"; - spectext = "[2] No Sounds"; - deaftext = "[3] Double Size"; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - } - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "FLMEB0"; - width = 16; - deaftext = "[3] Waves Vertically"; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "FLMEB0"; - width = 16; - deaftext = "[3] Shoot Downwards"; - } - 1500 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle"; - sprite = "GARGA1"; - width = 16; - height = 40; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 1501 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Up)"; - sprite = "GARGA1"; - width = 16; - height = 40; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 1502 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Down)"; - sprite = "GARGA1"; - width = 16; - height = 40; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 1503 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Long)"; - sprite = "GARGA1"; - width = 16; - height = 40; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 3575 - { - title = "Spinning Flame Jet (Counter-Clockwise)"; - sprite = "FLMEB0"; - width = "16"; - } - 3576 - { - title = "Spinning Flame Jet (Clockwise)"; - sprite = "FLMEB0"; - width = "16"; - } - } - } - - decoration - { - color = 4153088; // Dark lime (3F5F00) - title = "Decoration"; - width = 16; - height = 40; - values - { - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - } - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - height = 32; - } - 900 - { - title = "THZ Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CRL1A0"; - width = 8; - height = 16; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CRL2A0"; - width = 8; - height = 16; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CRL3A0"; - width = 8; - height = 16; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1100 - { - title = "Chain"; - sprite = "CHANA0"; - width = 8; - height = 128; - hangs = 1; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - } - 1203 - { - title = "Cactus with Brown Flower"; - sprite = "CACTA0"; - height = 32; - } - 1204 - { - title = "Cactus with Brown Flower (Tall)"; - sprite = "CACTB0"; - height = 64; - } - 1205 - { - title = "Cactus with Blue Flower"; - sprite = "CACTC0"; - height = 32; - } - 1206 - { - title = "Cactus with Blue Flower (Tall)"; - sprite = "CACTD0"; - height = 80; - } - 1850 - { - title = "Xmas Pole"; - sprite = "XMS1A0"; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - height = 54; - hangs = 1; - } - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STLGA0"; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STLGB0"; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STLGC0"; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STLGD0"; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STLGE0"; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STLGF0"; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STLGG0"; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STLGH0"; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STLGI0"; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STLGJ0"; - } - } - } - - nights - { - color = 12517599; // Violet (BF00DF) - title = "Nights Items"; - width = 12; - height = 32; - values - { - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - deaftext = "[3] Die Upon Time Up"; - } - 1704 - { - arrow = 1; - title = "Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - } - 1705 - { - arrow = 1; - title = "Hoop"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1713 - { - arrow = 1; - title = "Custom Hoop"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1706 - { - title = "Wing Logo"; - sprite = "NWNGA0"; - height = 24; - } - 1707 - { - title = "Super Loop"; - sprite = "NPRUA0"; - deaftext = "[3] Spawn Immediately"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRUB0"; - deaftext = "[3] Spawn Immediately"; - } - 1709 - { - title = "Helper"; - sprite = "NPRUC0"; - deaftext = "[3] Spawn Immediately"; - } - 1711 - { - title = "Extra Time"; - sprite = "NPRUD0"; - deaftext = "[3] Spawn Immediately"; - } - 1712 - { - title = "Link Freeze"; - sprite = "NPRUE0"; - deaftext = "[3] Spawn Immediately"; - } - } - } - - nightstrk - { - color = 12517599; // Violet (BF00DF) - title = "Nights Track"; - width = 8; - height = 4096; - values - { - 1700 - { - title = "Axis"; - circle = 1; - } - 1701 - { - title = "Axis Transfer"; - } - 1702 - { - title = "Axis Transfer Line"; - } - 1710 - { - title = "Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - nightstrk1 - { - color = 12517599; // Violet (BF00DF) - title = "Nights Track (2nd Mare)"; - width = 8; - height = 4096; - values - { - 5796 - { - title = "(Mare 2) Axis"; - circle = 1; - } - 5797 - { - title = "(Mare 2) Axis Transfer"; - } - 5798 - { - title = "(Mare 2) Axis Transfer Line"; - } - 5806 - { - title = "(Mare 2) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - nightstrk2 - { - color = 12517599; // Violet (BF00DF) - title = "Nights Track (3rd Mare)"; - width = 8; - height = 4096; - values - { - 9892 - { - title = "(Mare 3) Axis"; - circle = 1; - } - 9893 - { - title = "(Mare 3) Axis Transfer"; - } - 9894 - { - title = "(Mare 3) Axis Transfer Line"; - } - 9902 - { - title = "(Mare 3) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - nightstrk3 - { - color = 12517599; // Violet (BF00DF) - title = "Nights Track (4th Mare)"; - width = 8; - height = 4096; - values - { - 13988 - { - title = "(Mare 4) Axis"; - circle = 1; - } - 13989 - { - title = "(Mare 4) Axis Transfer"; - } - 13990 - { - title = "(Mare 4) Axis Transfer Line"; - } - 13998 - { - title = "(Mare 4) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - nightstrk4 - { - color = 12517599; // Violet (BF00DF) - title = "Nights Track (5th Mare)"; - width = 8; - height = 4096; - values - { - 18084 - { - title = "(Mare 5) Axis"; - circle = 1; - } - 18085 - { - title = "(Mare 5) Axis Transfer"; - } - 18086 - { - title = "(Mare 5) Axis Transfer Line"; - } - 18094 - { - title = "(Mare 5) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - nightstrk5 - { - color = 12517599; // Violet (BF00DF) - title = "Nights Track (6th Mare)"; - width = 8; - height = 4096; - values - { - 22180 - { - title = "(Mare 6) Axis"; - circle = 1; - } - 22181 - { - title = "(Mare 6) Axis Transfer"; - } - 22182 - { - title = "(Mare 6) Axis Transfer Line"; - } - 22190 - { - title = "(Mare 6) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - nightstrk6 - { - color = 12517599; // Violet (BF00DF) - title = "Nights Track (7th Mare)"; - width = 8; - height = 4096; - values - { - 26276 - { - title = "(Mare 7) Axis"; - circle = 1; - } - 26277 - { - title = "(Mare 7) Axis Transfer"; - } - 26278 - { - title = "(Mare 7) Axis Transfer Line"; - } - 26286 - { - title = "(Mare 7) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - nightstrk7 - { - color = 12517599; // Violet (BF00DF) - title = "Nights Track (8th Mare)"; - width = 8; - height = 4096; - values - { - 30372 - { - title = "(Mare 8) Axis"; - circle = 1; - } - 30373 - { - title = "(Mare 8) Axis Transfer"; - } - 30374 - { - title = "(Mare 8) Axis Transfer Line"; - } - 30382 - { - title = "(Mare 8) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - } - - - mario - { - color = 14647040; // Orange (DF7F00) - title = "Mario Items"; - width = 16; - height = 32; - values - { - 1800 - { - title = "Coin"; - sprite = "COINA0"; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA0"; - width = 8; - height = 16; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - height = 48; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - } - } - } - - srb1 - { - color = 32607; // Teal (007F5F) - arrow = 1; - title = "SRB1 Remake Items"; - width = 20; - height = 32; - values - { - 4000 - { - title = "SRB1 Crawla"; - sprite = "SRBAA1"; - height = 40; - } - 4001 - { - title = "GuardRobo"; - sprite = "SRBBA1"; - width = 17; - height = 40; - } - 4002 - { - title = "Pyrin"; - sprite = "SRBCB1"; - width = 22; - } - 4003 - { - title = "HotRobo"; - sprite = "SRBDA0"; - height = 40; - } - 4004 - { - title = "Pogminz"; - sprite = "SRBEA1"; - } - 4005 - { - title = "Pogminz (Water)"; - sprite = "SRBEA1"; - } - 4006 - { - title = "Pog-GX2"; - sprite = "SRBFA0"; - width = 10; - height = 34; - } - 4007 - { - title = "Pyrex"; - sprite = "SRBGA1"; - width = 24; - } - 4008 - { - title = "UFO"; - sprite = "SRBHA0"; - width = 24; - hangs = 1; - } - 4009 - { - title = "SWAT Bot"; - sprite = "SRBIA1"; - width = 21; - height = 69; - } - 4010 - { - title = "SpyBot 2000"; - sprite = "SRBJA0"; - width = 36; - height = 62; - } - 4011 - { - title = "Buzz Bomber"; - sprite = "SRBKA0"; - width = 44; - height = 45; - } - 4012 - { - arrow = 0; - title = "RBZ Spike"; - sprite = "SRBLA0"; - width = 10; - height = 53; - } - 4013 - { - arrow = 0; - blocking = 2; - title = "Dumb Metal Sonic"; - sprite = "SRBMC0"; - width = 16; - height = 40; - spectext = "[2] Slides When Pushed"; - deaftext = "[3] Not Pushable"; - } - 4014 - { - title = "Super SWAT Bot"; - sprite = "SRBNA1"; - width = 21; - height = 69; - } - 4015 - { - title = "Genrex"; - sprite = "SRBOA1"; - width = 17; - height = 40; - } - } - } - - bsz - { - color = 10469120; // Light Lime (9FDF00) - title = "Botanic Serenity Items"; - width = 16; - height = 32; - values - { - 1400 - { - title = "Tall Flower (Red)"; - sprite = "BSZ1A0"; - } - 1401 - { - title = "Tall Flower (Purple)"; - sprite = "BSZ1B0"; - } - 1402 - { - title = "Tall Flower (Blue)"; - sprite = "BSZ1C0"; - } - 1403 - { - title = "Tall Flower (Cyan)"; - sprite = "BSZ1D0"; - } - 1404 - { - title = "Tall Flower (Yellow)"; - sprite = "BSZ1E0"; - } - 1405 - { - title = "Tall Flower (Orange)"; - sprite = "BSZ1F0"; - } - 1410 - { - title = "Medium Flower (Red)"; - sprite = "BSZ2A0"; - } - 1411 - { - title = "Medium Flower (Purple)"; - sprite = "BSZ2B0"; - } - 1412 - { - title = "Medium Flower (Blue)"; - sprite = "BSZ2C0"; - } - 1413 - { - title = "Medium Flower (Cyan)"; - sprite = "BSZ2D0"; - } - 1414 - { - title = "Medium Flower (Yellow)"; - sprite = "BSZ2E0"; - } - 1415 - { - title = "Medium Flower (Orange)"; - sprite = "BSZ2F0"; - } - 1420 - { - title = "Short Flower (Red)"; - sprite = "BSZ3A0"; - } - 1421 - { - title = "Short Flower (Purple)"; - sprite = "BSZ3B0"; - } - 1422 - { - title = "Short Flower (Blue)"; - sprite = "BSZ3C0"; - } - 1423 - { - title = "Short Flower (Cyan)"; - sprite = "BSZ3D0"; - } - 1424 - { - title = "Short Flower (Yellow)"; - sprite = "BSZ3E0"; - } - 1425 - { - title = "Short Flower (Orange)"; - sprite = "BSZ3F0"; - } - 1430 - { - title = "Tulip (Red)"; - sprite = "BSZ4A0"; - } - 1431 - { - title = "Tulip (Purple)"; - sprite = "BSZ4B0"; - } - 1432 - { - title = "Tulip (Blue)"; - sprite = "BSZ4C0"; - } - 1433 - { - title = "Tulip (Cyan)"; - sprite = "BSZ4D0"; - } - 1434 - { - title = "Tulip (Yellow)"; - sprite = "BSZ4E0"; - } - 1435 - { - title = "Tulip (Orange)"; - sprite = "BSZ4F0"; - } - 1440 - { - title = "Cluster (Red)"; - sprite = "BSZ5A0"; - } - 1441 - { - title = "Cluster (Purple)"; - sprite = "BSZ5B0"; - } - 1442 - { - title = "Cluster (Blue)"; - sprite = "BSZ5C0"; - } - 1443 - { - title = "Cluster (Cyan)"; - sprite = "BSZ5D0"; - } - 1444 - { - title = "Cluster (Yellow)"; - sprite = "BSZ5E0"; - } - 1445 - { - title = "Cluster (Orange)"; - sprite = "BSZ5F0"; - } - 1450 - { - title = "Bush (Red)"; - sprite = "BSZ6A0"; - } - 1451 - { - title = "Bush (Purple)"; - sprite = "BSZ6B0"; - } - 1452 - { - title = "Bush (Blue)"; - sprite = "BSZ6C0"; - } - 1453 - { - title = "Bush (Cyan)"; - sprite = "BSZ6D0"; - } - 1454 - { - title = "Bush (Yellow)"; - sprite = "BSZ6E0"; - } - 1455 - { - title = "Bush (Orange)"; - sprite = "BSZ6F0"; - } - 1460 - { - title = "Vine (Red)"; - sprite = "BSZ7A0"; - } - 1461 - { - title = "Vine (Purple)"; - sprite = "BSZ7B0"; - } - 1462 - { - title = "Vine (Blue)"; - sprite = "BSZ7C0"; - } - 1463 - { - title = "Vine (Cyan)"; - sprite = "BSZ7D0"; - } - 1464 - { - title = "Vine (Yellow)"; - sprite = "BSZ7E0"; - } - 1465 - { - title = "Vine (Orange)"; - sprite = "BSZ7F0"; - } - 1470 - { - title = "BSZ Shrub"; - sprite = "BSZ8A0"; - } - 1471 - { - title = "BSZ Clover"; - sprite = "BSZ8B0"; - } - 1472 - { - title = "BSZ Fish"; - sprite = "BSZ8C0"; - } - 1473 - { - title = "BSZ Sunflower"; - sprite = "BSZ8D0"; - } - } - } -} diff --git a/extras/conf/srb2-21db2.cfg b/extras/conf/srb2-21db2.cfg deleted file mode 100644 index 075cbbf28..000000000 --- a/extras/conf/srb2-21db2.cfg +++ /dev/null @@ -1,4881 +0,0 @@ -/*********************************************************\ - SRB2Doom Builder 2 Game Configuration - For Sonic Robo Blast 2 Version 2.1 - Contributors (alphabetical): - * Foxboy - * JJames19119 - * Kalaron - * Kristos - * Morpheus - * Neo Chaotikal - * Oogaland - * Rob - * Shadow Hog - * ST218 - * SRB2-Playah - * SSNTails - * Viola -\*********************************************************/ - -// This is required to prevent accedential use of a different configuration -type = "Doom Builder 2 Game Configuration"; - -// This is the title to show for this game -game = "Sonic Robo Blast 2 2.1"; - -// This is the simplified game engine/sourceport name -engine = "eternity"; - -// The format interface handles the map data format -formatinterface = "DoomMapSetIO"; - -// Default lump name for new map -defaultlumpname = "MAP01"; - -// Default testing parameters -testparameters = "-iwad \"%WP\" -file \"%AP\" \"%F\" -warp %L"; -testshortpaths = true; - -// Default nodebuilder configurations -defaultsavecompiler = "zennode_normal"; -defaulttestcompiler = "zennode_fast"; - -// Skill levels -skills -{ - 1 = "Normal"; -} - -// When this is set to true, sectors with the same tag will light up when a line is highlighted -linetagindicatesectors = true; - -// Special linedefs -soundlinedefflag = 64; // See linedefflags -singlesidedflag = 1; // See linedefflags -doublesidedflag = 4; // See linedefflags -impassableflag = 1; -upperunpeggedflag = 8; -lowerunpeggedflag = 16; - -// Door making -makedoortrack = "DOORTRAK"; -makedooraction = 1; // See linedeftypes - -// Generalized actions -generalizedlinedefs = false; -generalizedsectors = true; - -// Texture loading options // Kalaron: Mix the resources! -mixtexturesflats = false; -defaulttexturescale = 1.0f; -defaultflatscale = 1.0f; - -// Thing number for start position in 3D Mode -start3dmode = 32000; - -// Default flags for first new thing -// Doom Builder is picky for some reason -// and will give a small warning of 'unknown flags' -// not an issue at all though, just strange -defaultthingflags -{ - 0; -} - - -/* -TEXTURES AND FLAT SOURCES -This tells Doom Builder where to find the information for textures -and flats in the IWAD file, Addition WAD file and Map WAD file. - -Start and end lumps must be given in a structure (of which the -key name doesnt matter) and any textures or flats in between them -are loaded in either the textures category or flats category. - -For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. -Kalaron: and now TX_START -*/ - -// Texture sources -textures -{ - zdoom1 - { - start = "TX_START"; - end = "TX_END"; - } -} - -// Patch sources -patches -{ - standard1 - { - start = "P_START"; - end = "P_END"; - } - - standard2 - { - start = "PP_START"; - end = "PP_END"; - } -} - -// Sprite sources -sprites -{ - standard1 - { - start = "S_START"; - end = "S_END"; - } - - standard2 - { - start = "SS_START"; - end = "SS_END"; - } -} - -// Flat sources -flats -{ - standard1 - { - start = "F_START"; - end = "F_END"; - } - - standard2 - { - start = "FF_START"; - end = "FF_END"; - } - - standard3 - { - start = "FF_START"; - end = "F_END"; - } - - standard4 - { - start = "F_START"; - end = "FF_END"; - } -} - - -/* -GAME DETECT PATTERN -Used to guess the game for which a WAD file is made. - -1 = One of these lumps must exist -2 = None of these lumps must exist -3 = All of these lumps must exist -*/ - -gamedetect -{ - EXTENDED = 2; - - - BEHAVIOR = 2; - - E#M# = 2; - - MAP?? = 1; -} - - -/* -MAP LUMP NAMES -Map lumps are loaded with the map as long as they are right after each other. When the editor -meets a lump which is not defined in this list it will ignore the map if not satisfied. -The order of items defines the order in which lumps will be written to WAD file on save. -To indicate the map header lump, use ~MAP - -Legenda: -required = Lump is required to exist. -blindcopy = Lump will be copied along with the map blindly. (usefull for lumps Doom Builder doesn't use) -nodebuild = The nodebuilder generates this lump. -allowempty = The nodebuilder is allowed to leave this lump empty. -script = This lump is a text-based script. Specify the filename of the script configuration to use. -*/ - -maplumpnames -{ - ~MAP - { - required = true; - blindcopy = true; - nodebuild = false; - } - - THINGS - { - required = true; - nodebuild = true; - allowempty = true; - } - - LINEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - SIDEDEFS - { - required = true; - nodebuild = true; - allowempty = false; - } - - VERTEXES - { - required = true; - nodebuild = true; - allowempty = false; - } - - SEGS - { - required = false; - nodebuild = true; - allowempty = false; - } - - SSECTORS - { - required = false; - nodebuild = true; - allowempty = false; - } - - NODES - { - required = false; - nodebuild = true; - allowempty = false; - } - - SECTORS - { - required = true; - nodebuild = true; - allowempty = false; - } - - REJECT - { - required = false; - nodebuild = true; - allowempty = false; - } - - BLOCKMAP - { - required = false; - nodebuild = true; - allowempty = false; - } -} - - -// DEFAULT SECTOR BRIGHTNESS LEVELS -sectorbrightness -{ - 255; - 248; - 240; - 232; - 224; - 216; - 208; - 200; - 192; - 184; - 176; - 168; - 160; - 152; - 144; - 136; - 128; - 120; - 112; - 104; - 96; - 88; - 80; - 72; - 64; - 56; - 48; - 40; - 32; - 24; - 16; - 8; - 0; -} - -// SECTOR TYPES----------------------------------------------------------------- -sectortypes -{ - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Modifications)"; - 7 = "Death Pit (No Camera Modifications)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (No Floor Touch)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy Sector (FOF Control Only)"; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check)"; - 112 = "Trigger Line Ex. (Nights Mare)"; - 128 = " Check for Line Exec. on FOFs"; - 144 = "Egg Trap Capsule"; - 160 = "Special Stage Time/Rings Parameters"; - 176 = "Custom Global Gravity"; - 256 = "Ice/Sludge"; - 512 = "Wind/Current"; - 768 = "Ice/Sludge and Wind/Current"; - 1024 = "Conveyor Belt"; - 1280 = "Speed Pad (No Spin)"; - 1536 = "Speed Pad (Spin)"; - 1792 = "Bustable Block Sprite Parameter (ROIA)"; - 2048 = "Bustable Block Sprite Parameter (ROIB)"; - 2304 = "Bustable Block Sprite Parameter (ROIC)"; - 2560 = "Bustable Block Sprite Parameter (ROID)"; - 2816 = "Bustable Block Sprite Parameter (ROIE)"; - 3072 = "Bustable Block Sprite Parameter (ROIF)"; - 3328 = "Bustable Block Sprite Parameter (ROIG)"; - 3884 = "Bustable Block Sprite Parameter (ROIH)"; - 3840 = "Bustable Block Sprite Parameter (ROII)"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Goal/Return Flag"; - 12288 = "CTF: Red Team Base"; - 16384 = "CTF: Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Spinner"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; -} - - -// GENERALISED SECTOR TYPES----------------------------------------------------------------- -gen_sectortypes -{ - first - { - 0 = "Normal"; - 1 = "Damage"; - 2 = "Damage (Water)"; - 3 = "Damage (Fire)"; - 4 = "Damage (Electrical)"; - 5 = "Spikes"; - 6 = "Death Pit (Camera Modifications)"; - 7 = "Death Pit (No Camera Modifications)"; - 8 = "Instant Kill"; - 9 = "Ring Drainer (Floor Touch)"; - 10 = "Ring Drainer (No Floor Touch)"; - 11 = "Special Stage Damage"; - 12 = "Space Countdown"; - 13 = "Ramp Sector (double step-up/down)"; - 14 = "Non-Ramp Sector (no step-down)"; - 15 = "Bouncy Sector (FOF Control Only)"; - } - - second - { - 0 = "Normal"; - 16 = "Trigger Line Ex. (Pushable Objects)"; - 32 = "Trigger Line Ex. (Anywhere, All Players)"; - 48 = "Trigger Line Ex. (Floor Touch, All Players)"; - 64 = "Trigger Line Ex. (Anywhere in Sector)"; - 80 = "Trigger Line Ex. (Floor Touch)"; - 96 = "Trigger Line Ex. (Emerald Check)"; - 112 = "Trigger Line Ex. (Nights Mare)"; - 128 = " Check for Line Exec. on FOFs"; - 144 = "Egg Trap Capsule"; - 160 = "Special Stage Time/Rings Parameters"; - 176 = "Custom Global Gravity"; - } - - third - { - 0 = "Normal"; - 256 = "Ice/Sludge"; - 512 = "Wind/Current"; - 768 = "Ice/Sludge and Wind/Current"; - 1024 = "Conveyor Belt"; - 1280 = "Speed Pad (No Spin)"; - 1536 = "Speed Pad (Spin)"; - 1792 = "Bustable Block Sprite Parameter (ROIA)"; - 2048 = "Bustable Block Sprite Parameter (ROIB)"; - 2304 = "Bustable Block Sprite Parameter (ROIC)"; - 2560 = "Bustable Block Sprite Parameter (ROID)"; - 2816 = "Bustable Block Sprite Parameter (ROIE)"; - 3072 = "Bustable Block Sprite Parameter (ROIF)"; - 3328 = "Bustable Block Sprite Parameter (ROIG)"; - 3884 = "Bustable Block Sprite Parameter (ROIH)"; - 3840 = "Bustable Block Sprite Parameter (ROII)"; - } - - fourth - { - 0 = "Normal"; - 4096 = "Star Post Activator"; - 8192 = "Exit/Special Stage Goal/Return Flag"; - 12288 = "CTF: Red Team Base"; - 16384 = "CTF: Blue Team Base"; - 20480 = "Fan Sector"; - 24576 = "Super Sonic Transform"; - 28672 = "Spinner"; - 32768 = "Zoom Tube Start"; - 36864 = "Zoom Tube End"; - 40960 = "Finish Line"; - 45056 = "Rope Hang"; - 49152 = "Intangible to the Camera"; - } -} - -// LINEDEF FLAGS -linedefflags -{ - 1 = "[0] Effect 6"; - 2 = "[1] Block Enemies"; - 4 = "[2] Double-Sided"; - 8 = "[3] Upper Unpegged"; - 16 = "[4] Lower Unpegged"; - 32 = "[5] Effect 1"; - 64 = "[6] Not Climbable"; - 128 = "[7] Effect 2"; - 256 = "[8] Effect 3"; - 512 = "[9] Effect 4"; - 1024 = "[10] Effect 5"; - 2048 = "[11] No Sonic"; - 4096 = "[12] No Tails"; - 8192 = "[13] No Knuckles"; - 16384 = "[14] Bouncy Wall"; - 32768 = "[15] Transfer Line"; -} - -// Linedef flags UDMF translation table -// This is needed for copy/paste and prefabs to work properly -// When the UDMF field name is prefixed with ! it is inverted -linedefflagstranslation -{ - 1 = "blocking"; - 2 = "blockmonsters"; - 4 = "twosided"; - 8 = "dontpegtop"; - 16 = "dontpegbottom"; - 32 = "secret"; - 64 = "blocksound"; - 128 = "dontdraw"; - 256 = "mapped"; -} - -// LINEDEF ACTIVATIONS -linedefactivations -{ -} - -// LINEDEF TYPES -linedeftypes -{ - misc - { - title = "Miscellaneous"; - - 0 - { - title = "None"; - prefix = "(0)"; - } - - 1 - { - title = "Per-Sector Gravity"; - prefix = "(1)"; - } - - 4 - { - title = "Speed Pad"; - prefix = "(4)"; - } - - 5 - { - title = "Camera Scanner"; - prefix = "(5)"; - } - - 6 - { - title = "Disable Linedef Effect On Level Load"; - prefix = "(6)"; - } - - 7 - { - title = "Sector Flat Alignment"; - prefix = "(7)"; - } - - 10 - { - title = "Culling Plane"; - prefix = "(10)"; - } - - 13 - { - title = "Heat Wave Effect"; - prefix = "(13)"; - } - - 50 - { - title = "Instantly Lower Floor On Level Load"; - prefix = "(50)"; - } - - 51 - { - title = "Instantly Raise Ceiling On Level Load"; - prefix = "(51)"; - } - - 63 - { - title = "Fake Floor/Ceiling Planes"; - prefix = "(63)"; - } - - 540 - { - title = "Floor Friction"; - prefix = "(540)"; - } - } - - parameters - { - title = "Parameters"; - - 2 - { - title = "Custom Exit"; - prefix = "(2)"; - } - - 3 - { - title = "Zoom Tube Parameters"; - prefix = "(3)"; - } - - 8 - { - title = "Sector Special Parameters"; - prefix = "(8)"; - } - - 9 - { - title = "Chain Parameters"; - prefix = "(9)"; - } - - 11 - { - title = "Rope Hang Parameters"; - prefix = "(12)"; - } - - 12 - { - title = "Rock Spawn Parameters"; - prefix = "(12)"; - } - - 64 - { - title = "Appearing/Disappearing FOF"; - prefix = "(64)"; - } - - 65 - { - title = "Bridge Thinker "; - prefix = "(65)"; - } - } - - polyobject - { - title = "PolyObject"; - - 20 - { - title = "First Line"; - prefix = "(20)"; - } - - 21 - { - title = "Explicitly Include Line"; - prefix = "(21)"; - } - - 22 - { - title = "Parameters"; - prefix = "(22)"; - } - - 30 - { - title = "Waving Flag"; - prefix = "(30)"; - } - } - - planemove - { - title = "Plane Movement"; - - 52 - { - title = "Continuous Falling Sector"; - prefix = "(52)"; - } - - 53 - { - title = "Continuous Floor/Ceiling Mover"; - prefix = "(53)"; - } - - 54 - { - title = "Continuous Floor Mover"; - prefix = "(54)"; - } - - 55 - { - title = "Continuous Ceiling Mover"; - prefix = "(55)"; - } - - 56 - { - title = "Continuous Two-Speed Floor/Ceiling Mover"; - prefix = "(56)"; - } - - 57 - { - title = "Continuous Two-Speed Floor Mover"; - prefix = "(57)"; - } - - 58 - { - title = "Continuous Two-Speed Ceiling Mover"; - prefix = "(58)"; - } - - 59 - { - title = "Activate Moving Platform"; - prefix = "(59)"; - } - - 60 - { - title = "Activate Moving Platform (Adjustable Speed)"; - prefix = "(60)"; - } - - 61 - { - title = "Crusher (Ceiling to Floor)"; - prefix = "(61)"; - } - - 62 - { - title = "Crusher (Floor to Ceiling)"; - prefix = "(62)"; - } - } - - fofsolid - { - title = "FOF (solid)"; - - 100 - { - title = "Solid, Opaque"; - prefix = "(100)"; - } - - 101 - { - title = "Solid, Opaque, No Shadow"; - prefix = "(101)"; - } - - 102 - { - title = "Solid, Translucent"; - prefix = "(102)"; - } - - 103 - { - title = "Solid, Sides Only"; - prefix = "(103)"; - } - - 104 - { - title = "Solid, No Sides"; - prefix = "(104)"; - } - - 105 - { - title = "Solid, Invisible"; - prefix = "(105)"; - } - - 140 - { - title = "Intangible from Bottom, Opaque"; - prefix = "(140)"; - } - - 141 - { - title = "Intangible from Bottom, Translucent"; - prefix = "(141)"; - } - - 142 - { - title = "Intangible from Bottom, Translucent, No Sides"; - prefix = "(142)"; - } - - 143 - { - title = "Intangible from Top, Opaque"; - prefix = "(143)"; - } - - 144 - { - title = "Intangible from Top, Translucent"; - prefix = "(144)"; - } - - 145 - { - title = "Intangible from Top, Translucent, No Sides"; - prefix = "(145)"; - } - - 146 - { - title = "Only Tangible from Sides"; - prefix = "(146)"; - } - } - - fofintangible - { - title = "FOF (intangible)"; - - 120 - { - title = "Water, Opaque"; - prefix = "(120)"; - } - - 121 - { - title = "Water, Translucent"; - prefix = "(121)"; - } - - 122 - { - title = "Water, Opaque, No Sides"; - prefix = "(122)"; - } - - 123 - { - title = "Water, Translucent, No Sides"; - prefix = "(123)"; - } - - 124 - { - title = "Goo Water, Translucent"; - prefix = "(124)"; - } - - 125 - { - title = "Goo Water, Translucent, No Sides"; - prefix = "(125)"; - } - - 220 - { - title = "Intangible, Opaque"; - prefix = "(220)"; - } - - 221 - { - title = "Intangible, Translucent"; - prefix = "(221)"; - } - - 222 - { - title = "Intangible, Sides Only"; - prefix = "(222)"; - } - - 223 - { - title = "Intangible, Invisible"; - prefix = "(223)"; - } - } - - fofbobbing - { - title = "FOF (bobbing)"; - - 150 - { - title = " Air Bobbing"; - prefix = "(150)"; - } - - 151 - { - title = " Air Bobbing (Adjustable)"; - prefix = "(151)"; - } - - 152 - { - title = " Reverse Air Bobbing (Adjustable)"; - prefix = "(152)"; - } - - 160 - { - title = "Floating, Bobbing"; - prefix = "(160)"; - } - - 190 - { - title = "Rising Platform, Solid, Opaque"; - prefix = "(190)"; - } - - 191 - { - title = "Rising Platform, Solid, Opaque, No Shadow"; - prefix = "(191)"; - } - - 192 - { - title = "Rising Platform, Solid, Translucent"; - prefix = "(192)"; - } - - 193 - { - title = "Rising PLatform, Solid, Invisible"; - prefix = "(193)"; - } - - 194 - { - title = "Rising Platform, Intangible from Bottom, Opaque"; - prefix = "(194)"; - } - - 195 - { - title = "Rising Platform, Intangible from Bottom, Translucent"; - prefix = "(195)"; - } - } - - fofcrumbling - { - title = "FOF (crumbling)"; - - 170 - { - title = "Crumbling (Respawn)"; - prefix = "(170)"; - } - - 171 - { - title = "Crumbling (No Respawn)"; - prefix = "(171)"; - } - - 172 - { - title = "Crumbling (Respawn), Intangible from Bottom"; - prefix = "(172)"; - } - - 173 - { - title = "Crumbling (No Respawn), Intangible from Bottom"; - prefix = "(173)"; - } - - 174 - { - title = "Crumbling (Respawn), Int. from Bottom, Translucent"; - prefix = "(174)"; - } - - 175 - { - title = "Crumbling (No Respawn), Int. from Bottom, Translucent"; - prefix = "(175)"; - } - - 176 - { - title = "Crumbling (Respawn), Floating, Bobbing"; - prefix = "(176)"; - } - - 177 - { - title = "Crumbling (No Respawn), Floating, Bobbing"; - prefix = "(177)"; - } - - 178 - { - title = "Crumbling (Respawn), Floating"; - prefix = "(178)"; - } - - 179 - { - title = "Crumbling (No Respawn), Floating"; - prefix = "(179)"; - } - - 180 - { - title = "Crumbling (Respawn), Air Bobbing"; - prefix = "(180)"; - } - } - - fofspecial - { - title = "FOF (special)"; - - 200 - { - title = "Light Block"; - prefix = "(200)"; - } - - 201 - { - title = "Half Light Block"; - prefix = "(201)"; - } - - 202 - { - title = "Fog Block"; - prefix = "(202)"; - } - - 250 - { - title = "Mario Block"; - prefix = "(250)"; - } - - 251 - { - title = "Thwomp Block"; - prefix = "(251)"; - } - - 252 - { - title = "Shatter Block"; - prefix = "(252)"; - } - - 253 - { - title = "Shatter Block, Translucent"; - prefix = "(253)"; - } - - 254 - { - title = "Bustable Block"; - prefix = "(254)"; - } - - 255 - { - title = "Spin Bust Block"; - prefix = "(255)"; - } - - 256 - { - title = "Spin Bust Block, Translucent"; - prefix = "(256)"; - } - - 257 - { - title = "Quicksand"; - prefix = "(257)"; - } - - 258 - { - title = "Laser"; - prefix = "(258)"; - } - - 259 - { - title = "Custom FOF"; - prefix = "(259)"; - } - } - - linedeftrigger - { - title = "Lindef Executor Trigger"; - - 300 - { - title = "Continuous"; - prefix = "(300)"; - } - - 301 - { - title = "Each Time"; - prefix = "(301)"; - } - - 302 - { - title = "Once"; - prefix = "(302)"; - } - - 303 - { - title = "Ring Count - Continuous"; - prefix = "(303)"; - } - - 304 - { - title = "Ring Count - Once"; - prefix = "(304)"; - } - - 305 - { - title = "Character Ability - Once"; - prefix = "(305)"; - } - - 306 - { - title = "Character Ability - Each Time"; - prefix = "(306)"; - } - - 307 - { - title = "Character Ability - Continuous"; - prefix = "(307)"; - } - - 308 - { - title = "Race Only - Once"; - prefix = "(308)"; - } - - 309 - { - title = "CTF Red Team - Continuous"; - prefix = "(309)"; - } - - 310 - { - title = "CTF Red Team - Each Time"; - prefix = "(310)"; - } - - 311 - { - title = "CTF Blue Team - Continuous"; - prefix = "(311)"; - } - - 312 - { - title = "CTF Blue Team - Each Time"; - prefix = "(312)"; - } - - 313 - { - title = "No More Enemies - Once"; - prefix = "(313)"; - } - - 314 - { - title = "Number of Pushables - Continuous"; - prefix = "(314)"; - } - - 315 - { - title = "Number of Pushables - Once"; - prefix = "(315)"; - } - - 316 - { - title = "Land On PolyObject"; - prefix = "(316)"; - } - - 317 - { - title = "Unlockable Trigger - Continuous"; - prefix = "(317)"; - } - - 318 - { - title = "Unlockable Trigger - Once"; - prefix = "(316)"; - } - - 399 - { - title = "Level Load"; - prefix = "(399)"; - } - } - - linedefexecsector - { - title = "Linedef Executor (sector)"; - - 400 - { - title = "Set Tagged Sector's Floor Height/Texture"; - prefix = "(400)"; - } - - 401 - { - title = "Set Tagged Sector's Ceiling Height/Texture"; - prefix = "(401)"; - } - - 402 - { - title = "Set Tagged Sector's Light Level"; - prefix = "(402)"; - } - - 409 - { - title = "Change Tagged Sector's Tag"; - prefix = "(409)"; - } - - 410 - { - title = "Change Front Sector's Tag"; - prefix = "(410)"; - } - - 416 - { - title = "Start Adjustable Fire Flicker"; - prefix = "(416)"; - } - - 417 - { - title = "Start Adjustable Glowing Light"; - prefix = "(417)"; - } - - 418 - { - title = "Start Adjustable Blinking Light (unsynchronized)"; - prefix = "(418)"; - } - - 419 - { - title = "Start Adjustable Blinking Light (synchronized)"; - prefix = "(419)"; - } - - 420 - { - title = "Fade Light Level"; - prefix = "(420)"; - } - - 421 - { - title = "Stop Lighting Effect"; - prefix = "(421)"; - } - - 435 - { - title = "Change Plane Scroller Direction"; - prefix = "(435)"; - } - } - - linedefexecplane - { - title = "Linedef Executor (plane movement)"; - - 403 - { - title = "Move Tagged Sector's Floor"; - prefix = "(403)"; - } - - 404 - { - title = "Move Tagged Sector's Ceiling"; - prefix = "(404)"; - } - - 405 - { - title = "Move Floor According to Front Texture Offsets"; - prefix = "(405)"; - } - - 407 - { - title = "Move Ceiling According to Front Texture Offsets"; - prefix = "(407)"; - } - - 411 - { - title = "Stop Plane Movement"; - prefix = "(411)"; - } - - 428 - { - title = "Start Platform Movement"; - prefix = "(428)"; - } - - 429 - { - title = "Crush Ceiling Once"; - prefix = "(429)"; - } - - 430 - { - title = "Crush Floor Once"; - prefix = "(430)"; - } - - 431 - { - title = "Crush Floor and Ceiling Once"; - prefix = "(431)"; - } - } - - linedefexecplayer - { - title = "Linedef Executor (player/object)"; - - 412 - { - title = "Teleporter"; - prefix = "(412)"; - } - - 425 - { - title = "Change Object State"; - prefix = "(425)"; - } - - 426 - { - title = "Stop Object"; - prefix = "(426)"; - } - - 427 - { - title = "Award Score"; - prefix = "(427)"; - } - - 432 - { - title = "Enable/Disable 2D Mode"; - prefix = "(432)"; - } - - 433 - { - title = "Enable/Disable Gravity Flip"; - prefix = "(433)"; - } - - 434 - { - title = "Award Power-Up"; - prefix = "(434)"; - } - - 437 - { - title = "Disable Player Control"; - prefix = "(437)"; - } - - 438 - { - title = "Change Object Size"; - prefix = "(438)"; - } - - 442 - { - title = "Change Object Type State"; - prefix = "(442)"; - } - } - - linedefexecmisc - { - title = "Linedef Executor (misc.)"; - - 413 - { - title = "Change Music"; - prefix = "(413)"; - } - - 414 - { - title = "Play Sound Effect"; - prefix = "(414)"; - } - - 415 - { - title = "Run Script"; - prefix = "(415)"; - } - - 422 - { - title = "Switch to Cut-Away View"; - prefix = "(422)"; - } - - 423 - { - title = "Change Sky"; - prefix = "(423)"; - } - - 424 - { - title = "Change Weather"; - prefix = "(424)"; - } - - 436 - { - title = "Shatter FOF"; - prefix = "(436)"; - } - - 439 - { - title = "Set Texture"; - prefix = "(439)"; - } - - 440 - { - title = "Start Metal Sonic Race"; - prefix = "(440)"; - } - - 441 - { - title = "Unlockable Trigger"; - prefix = "(441)"; - } - - 443 - { - title = "Call Lua Function"; - prefix = "(443)"; - } - - 444 - { - title = "Earthquake"; - prefix = "(444)"; - } - - - 445 - { - title = "Force Block Disappear"; - prefix = "(445)"; - } - - 450 - { - title = "Execute Linedef Executor (from tag)"; - prefix = "(450)"; - } - - 451 - { - title = "Execute Linedef Executor (random range)"; - prefix = "(451)"; - } - } - - linedefexecpoly - { - title = "Linedef Executor (polyobject)"; - - 480 - { - title = "Door Slide"; - prefix = "(480)"; - } - - 481 - { - title = "Door Swing"; - prefix = "(481)"; - } - - 482 - { - title = "Move"; - prefix = "(482)"; - } - - 483 - { - title = "Move, Override"; - prefix = "(483)"; - } - - 484 - { - title = "Rotate Right"; - prefix = "(484)"; - } - - 485 - { - title = "Rotate Right, Override"; - prefix = "(485)"; - } - - 486 - { - title = "Rotate Left"; - prefix = "(486)"; - } - - 487 - { - title = "Rotate Left, Override"; - prefix = "(487)"; - } - - 488 - { - title = "Move by Waypoints"; - prefix = "(488)"; - } - - 489 - { - title = "Turn Inisible, Intangible"; - prefix = "(489)"; - } - - 490 - { - title = "Turn Visible, Tangible"; - prefix = "(490)"; - } - - 491 - { - title = "Set Translucency"; - prefix = "(491)"; - } - } - - wallscroll - { - title = "Wall Scrolling"; - - 500 - { - title = "Scroll Wall Front Side Left"; - prefix = "(500)"; - } - - 501 - { - title = "Scroll Wall Front Side Right"; - prefix = "(501)"; - } - - 502 - { - title = "Scroll Wall According to Linedef"; - prefix = "(502)"; - } - - 503 - { - title = "Scroll Wall According to Linedef (Accelerative)"; - prefix = "(503)"; - } - - 504 - { - title = "Scroll Wall According to Linedef (Displacement)"; - prefix = "(504)"; - } - - 505 - { - title = "Scroll Texture by Front Side Offsets"; - prefix = "(505)"; - } - - 506 - { - title = "Scroll Texture by Back Side Offsets"; - prefix = "(506)"; - } - } - - planescroll - { - title = "Plane Scrolling"; - - 510 - { - title = "Scroll Floor Texture"; - prefix = "(510)"; - } - - 511 - { - title = "Scroll Floor Texture (Accelerative)"; - prefix = "(511)"; - } - - 512 - { - title = "Scroll Floor Texture (Displacement)"; - prefix = "(512)"; - } - - 513 - { - title = "Scroll Ceiling Texture"; - prefix = "(513)"; - } - - 514 - { - title = "Scroll Ceiling Texture (Accelerative)"; - prefix = "(514)"; - } - - 515 - { - title = "Scroll Ceiling Texture (Displacement)"; - prefix = "(515)"; - } - - 520 - { - title = "Carry Objects on Floor"; - prefix = "(520)"; - } - - 521 - { - title = "Carry Objects on Floor (Accelerative)"; - prefix = "(521)"; - } - - 522 - { - title = "Carry Objects on Floor (Displacement)"; - prefix = "(522)"; - } - - 523 - { - title = "Carry Objects on Ceiling"; - prefix = "(523)"; - } - - 524 - { - title = "Carry Objects on Ceiling (Accelerative)"; - prefix = "(524)"; - } - - 525 - { - title = "Carry Objects on Ceiling (Displacement)"; - prefix = "(525)"; - } - - 530 - { - title = "Scroll Floor Texture and Carry Objects"; - prefix = "(530)"; - } - - 531 - { - title = "Scroll Floor Texture and Carry Objects (Accelerative)"; - prefix = "(531)"; - } - - 532 - { - title = "Scroll Floor Texture and Carry Objects (Displacement)"; - prefix = "(532)"; - } - - 533 - { - title = "Scroll Ceiling Texture and Carry Objects"; - prefix = "(533)"; - } - - 534 - { - title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; - prefix = "(534)"; - } - - 535 - { - title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; - prefix = "(535)"; - } - } - - pusher - { - title = "Pusher"; - - 541 - { - title = "Wind"; - prefix = "(541)"; - } - - 542 - { - title = "Upwards Wind"; - prefix = "(542)"; - } - - 543 - { - title = "Downwards Wind"; - prefix = "(543)"; - } - - 544 - { - title = "Current"; - prefix = "(544)"; - } - - 545 - { - title = "Upwards Current"; - prefix = "(545)"; - } - - 546 - { - title = "Downwards Current"; - prefix = "(546)"; - } - - 547 - { - title = "Push/Pull"; - prefix = "(547)"; - } - } - - light - { - title = "Lighting"; - - 600 - { - title = "Floor Lighting"; - prefix = "(600)"; - } - - 601 - { - title = "Ceiling Lighting"; - prefix = "(601)"; - } - - 602 - { - title = "Adjustable Pulsating Light"; - prefix = "(602)"; - } - - 603 - { - title = "Adjustable Flickering Light"; - prefix = "(603)"; - } - - 604 - { - title = "Adjustable Blinking Light (unsynchronized)"; - prefix = "(604)"; - } - - 605 - { - title = "Adjustable Blinking Light (synchronized)"; - prefix = "(605)"; - } - - 606 - { - title = "Colormap"; - prefix = "(606)"; - } - } - - transwall - { - title = "Translucent Wall"; - - 900 - { - title = "90% Opaque"; - prefix = "(900)"; - } - - 901 - { - title = "80% Opaque"; - prefix = "(901)"; - } - - 902 - { - title = "70% Opaque"; - prefix = "(902)"; - } - - 903 - { - title = "60% Opaque"; - prefix = "(903)"; - } - - 904 - { - title = "50% Opaque"; - prefix = "(904)"; - } - - 905 - { - title = "40% Opaque"; - prefix = "(905)"; - } - - 906 - { - title = "30% Opaque"; - prefix = "(906)"; - } - - 907 - { - title = "20% Opaque"; - prefix = "(907)"; - } - - 908 - { - title = "10% Opaque"; - prefix = "(908)"; - } - - 909 - { - title = "Fog Wall"; - prefix = "(909)"; - } - } -} - - -// THING FLAGS -thingflags -{ - 1 = "[0] Unused Flag"; - 2 = "[1] Object Flip"; - 4 = "[2] Object Special"; - 8 = "[3] Ambush"; - 16 = "(Used for Z offsets)"; -} - -// Thing flags UDMF translation table -// This is needed for copy/paste and prefabs to work properly -// When the UDMF field name is prefixed with ! it is inverted -thingflagstranslation -{ - 1 = "skill1"; - 2 = "skill2"; - 4 = "skill3"; - 8 = "ambush"; - 16 = "!single"; -} - -// THING FLAGS ERROR MASK -// Mask for the thing flags which indicates the options -// that make the same thing appear in the same modes -thingflagsmask1 = 7; // 1 + 2 + 4 -thingflagsmask2 = 0; - - -// THING TYPES------------------------------------------------------------------ -// Color values: 1-Blue 2-Green 3-Cyan 4-Red 5-Magenta 6-Brown 7-Gray -// 8-Dark_Gray 9-Light_Blue 10-Light_Green 11-Light_Cyan 12-Light_Red 13-Pink -// 14-Yellow 15-White -thingtypes -{ - editor - { - color = 15; // White - arrow = 1; - title = ""; - error = -1; - width = 8; - height = 16; - sort = 1; - - 32000 = "3D Mode Start"; - 32001 - { - arrow = 0; - title = "Control Sector Position Hint"; - } - } - - starts - { - color = 1; // Blue - arrow = 1; - title = "Player Starts"; - width = 16; - height = 56; - deaftext = "[3] Spawn On Ceiling"; - - 1 - { - title = "Player 01 Start"; - sprite = "SUPTD0"; - } - 2 - { - title = "Player 02 Start"; - sprite = "SUPTD0"; - } - 3 - { - title = "Player 03 Start"; - sprite = "SUPTD0"; - } - 4 - { - title = "Player 04 Start"; - sprite = "SUPTD0"; - } - 5 - { - title = "Player 05 Start"; - sprite = "SUPTD0"; - } - 6 - { - title = "Player 06 Start"; - sprite = "SUPTD0"; - } - 7 - { - title = "Player 07 Start"; - sprite = "SUPTD0"; - } - 8 - { - title = "Player 08 Start"; - sprite = "SUPTD0"; - } - 9 - { - title = "Player 09 Start"; - sprite = "SUPTD0"; - } - 10 - { - title = "Player 10 Start"; - sprite = "SUPTD0"; - } - 11 - { - title = "Player 11 Start"; - sprite = "SUPTD0"; - } - 12 - { - title = "Player 12 Start"; - sprite = "SUPTD0"; - } - 13 - { - title = "Player 13 Start"; - sprite = "SUPTD0"; - } - 14 - { - title = "Player 14 Start"; - sprite = "SUPTD0"; - } - 15 - { - title = "Player 15 Start"; - sprite = "SUPTD0"; - } - 16 - { - title = "Player 16 Start"; - sprite = "SUPTD0"; - } - 17 - { - title = "Player 17 Start"; - sprite = "SUPTD0"; - } - 18 - { - title = "Player 18 Start"; - sprite = "SUPTD0"; - } - 19 - { - title = "Player 19 Start"; - sprite = "SUPTD0"; - } - 20 - { - title = "Player 20 Start"; - sprite = "SUPTD0"; - } - 21 - { - title = "Player 21 Start"; - sprite = "SUPTD0"; - } - 22 - { - title = "Player 22 Start"; - sprite = "SUPTD0"; - } - 23 - { - title = "Player 23 Start"; - sprite = "SUPTD0"; - } - 24 - { - title = "Player 24 Start"; - sprite = "SUPTD0"; - } - 25 - { - title = "Player 25 Start"; - sprite = "SUPTD0"; - } - 26 - { - title = "Player 26 Start"; - sprite = "SUPTD0"; - } - 27 - { - title = "Player 27 Start"; - sprite = "SUPTD0"; - } - 28 - { - title = "Player 28 Start"; - sprite = "SUPTD0"; - } - 29 - { - title = "Player 29 Start"; - sprite = "SUPTD0"; - } - 30 - { - title = "Player 30 Start"; - sprite = "SUPTD0"; - } - 31 - { - title = "Player 31 Start"; - sprite = "SUPTD0"; - } - 32 - { - title = "Player 32 Start"; - sprite = "SUPTD0"; - } - 33 - { - title = "Match Start"; - sprite = "SUPTI0"; - } - 34 - { - title = "CTF Red Team Start"; - sprite = "SIGNG0"; - } - 35 - { - title = "CTF Blue Team Start"; - sprite = "SIGNE0"; - } - } - - enemies - { - color = 9; // Light_Blue - arrow = 1; - title = "Enemies"; - width = 24; - height = 32; - sort = 1; - - 100 - { - title = "Crawla (Blue)"; - sprite = "POSSA1"; - } - 101 - { - title = "Crawla (Red)"; - sprite = "SPOSA1"; - } - 102 - { - title = "Stupid Dumb Unnamed RoboFish"; - sprite = "FISHA0"; - width = 8; - height = 28; - } - 103 - { - title = "Buzz (Gold)"; - sprite = "BUZZA1"; - width = 20; - height = 24; - deaftext = "[3] Cannot Move"; - } - 104 - { - title = "Buzz (Red)"; - sprite = "RBUZA1"; - width = 20; - height = 24; - deaftext = "[3] Cannot Move"; - } - 105 - { - title = "Jetty-Syn Bomber"; - sprite = "JETBB1"; - width = 20; - height = 48; - deaftext = "[3] Cannot Move"; - } - 106 - { - title = "Jetty-Syn Gunner"; - sprite = "JETGB1"; - width = 20; - height = 48; - deaftext = "[3] Cannot Move"; - } - 107 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - width = 16; - } - 108 - { - title = "Deton"; - sprite = "DETNA1"; - width = 20; - } - 109 - { - title = "Skim"; - sprite = "SKIMA1"; - width = 16; - height = 24; - } - 110 - { - title = "Turret"; - sprite = "TRETA1"; - width = 16; - height = 32; - } - 111 - { - title = "Popup Turret"; - sprite = "TURRI1"; - width = 12; - height = 64; - } - 112 - { - title = "Sharp"; - sprite = "SHRPA1"; - width = 16; - height = 24; - } - 113 - { - title = "Jet Jaw"; - sprite = "JJAWA3A7"; - width = 12; - height = 20; - } - 114 - { - title = "Snailer"; - sprite = "SNLRA3A7"; - height = 48; - } - 115 - { - title = "Bird Aircraft Strike Hazard"; - sprite = "VLTRF1"; - width = 12; - height = 24; - } - 116 - { - title = "Pointy"; - sprite = "PNTYA1"; - width = 8; - height = 16; - } - 117 - { - title = "Robo-Hood"; - sprite = "ARCHA1"; - deaftext = "[3] Cannot Jump"; - } - 118 - { - title = "CastleBot FaceStabber"; - sprite = "CBFSA1"; - width = 32; - height = 64; - } - 119 - { - title = "Egg Guard"; - sprite = "ESHIA1"; - width = 16; - height = 48; - deaftext = "[3] Double Speed"; - } - 120 - { - title = "Green Snapper"; - sprite = "GSNPA1"; - height = 24; - } - 121 - { - title = "Minus"; - sprite = "MNUSA1"; - } - 122 - { - title = "Spring Shell (Green)"; - sprite = "SSHLA1"; - height = 40; - } - 123 - { - title = "Unidus"; - sprite = "UNIDA1"; - width = 18; - height = 36; - } - 124 - { - title = "AquaBuzz"; - sprite = "BBUZA1"; - width = 20; - height = 24; - } - 125 - { - title = "Spring Shell (Yellow)"; - sprite = "YSHLA1"; - height = 40; - } - 750 - { - title = " Chaos Enemy Spawn"; - sprite = "TFOGG0"; - width = 32; - height = 64; - } - } - - bosses - { - color = 8; // Dark_Gray - arrow = 1; - title = "Bosses"; - width = 24; - height = 52; - sort = 1; - - 200 - { - title = "Boss 1 - Egg Mobile"; - sprite = "EGGMA1"; - deaftext = "[3] Rotating Spikeballs"; - } - 201 - { - title = "Boss 2 - Egg Slimer"; - sprite = "EGGNA1"; - height = 48; - deaftext = "[3] Speed Up When Hit"; - } - 202 - { - title = "Boss 3 - Sea Egg"; - sprite = "EGGOA1"; - width = 32; - height = 80; - } - 203 - { - title = "Boss 4 - Eggscalibur"; - sprite = "EGGPA1"; - } - 206 - { - title = "Boss - Black Eggman (Old)"; - sprite = "BRAKB1"; - width = 48; - height = 160; - } - 207 - { - title = "Boss 5A - Metal Sonic Race Start"; - sprite = "METLI1"; - width = 16; - height = 48; - } - 208 - { - title = "Boss 5B - Metal Sonic Battle Start"; - sprite = "METLC1"; - width = 16; - height = 48; - } - 209 - { - title = "Boss 6 - Black Eggman (New)"; - sprite = "BRAK[1"; - width = 48; - height = 160; - deaftext = "[3] Electric Barrier"; - } - 290 - { - arrow = 0; - title = "Boss Escape Point"; - width = 8; - height = 16; - } - 291 - { - arrow = 0; - title = "Egg Trap Center"; - width = 8; - height = 16; - } - 292 - { - arrow = 0; - title = "Boss Waypoint"; - width = 8; - height = 16; - deaftext = "[3] Sea Egg Shooting Point"; - } - 293 = "Metal Sonic Waypoint"; - } - - rings - { - color = 14; // Yellow - title = "Rings and Weapon Panels"; - width = 24; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - - 300 - { - title = "Ring"; - sprite = "RINGA0"; - width = 16; - } - 301 - { - title = "Bounce Ring"; - sprite = "CPRKB0"; - } - 302 - { - title = "Rail Ring"; - sprite = "SPRKA0"; - } - 304 - { - title = "Automatic Ring"; - sprite = "TAUTA3A7"; - } - 305 - { - title = "Explosion Ring"; - sprite = "BMSLA1"; - } - 306 - { - title = "Scatter Ring"; - sprite = "TSCRA1A5"; - } - 307 - { - title = "Grenade Ring"; - sprite = "TGREA0"; - } - 308 - { - title = "CTF Team Ring (Red)"; - sprite = "RRNGA0"; - width = 16; - } - 309 - { - title = "CTF Team Ring (Blue)"; - sprite = "TRNGA0"; - width = 16; - } - 330 - { - title = "Bounce Ring Panel"; - sprite = "PIKBA0"; - } - 331 - { - title = "Rail Ring Panel"; - sprite = "PIKRA0"; - } - 332 - { - title = "Automatic Ring Panel"; - sprite = "PIKAA0"; - } - 333 - { - title = "Explosion Ring Panel"; - sprite = "PIKEA0"; - } - 334 - { - title = "Scatter Ring Panel"; - sprite = "PIKSA0"; - } - 335 - { - title = "Grenade Ring Panel"; - sprite = "PIKGA0"; - } - } - - collectibles - { - color = 10; // Light_Green - title = "Other Collectibles"; - width = 16; - height = 32; - sort = 1; - - 310 - { - title = "CTF Red Flag"; - sprite = "RFLGA0"; - width = 24; - height = 64; - } - 311 - { - title = "CTF Blue Flag"; - sprite = "BFLGA0"; - width = 24; - height = 64; - } - 312 - { - title = "Special Stage Token"; - sprite = "TOKEA0"; - width = 8; - height = 16; - deafheight = 32; - deaftext = "[3] Float"; - } - 313 - { - title = "Chaos Emerald 1 (Green)"; - sprite = "EMMYA0"; - } - 314 - { - title = "Chaos Emerald 2 (Orange)"; - sprite = "EMMYB0"; - } - 315 - { - title = "Chaos Emerald 3 (Purple)"; - sprite = "EMMYC0"; - } - 316 - { - title = "Chaos Emerald 4 (Blue)"; - sprite = "EMMYD0"; - } - 317 - { - title = "Chaos Emerald 5 (Red)"; - sprite = "EMMYE0"; - } - 318 - { - title = "Chaos Emerald 6 (Light Blue)"; - sprite = "EMMYF0"; - } - 319 - { - title = "Chaos Emerald 7 (Gray)"; - sprite = "EMMYG0"; - } - 320 - { - title = "Emerald Hunt Location"; - sprite = "EMERA0"; - } - 323 - { - title = "Match Chaos Emerald Spawn"; - sprite = "CEMGA0"; - width = 8; - height = 16; - deafheight = 32; - deaftext = "[3] Float"; - } - } - - boxes - { - color = 7; // Gray - blocking = 2; - title = "Item Boxes"; - width = 16; - height = 32; - deaftext = "[3] Random (Weak)"; - sort = 1; - - 400 - { - title = "Super Ring (10 Rings)"; - sprite = "SRBXA0"; - } - 401 - { - title = "Pity / Basic Shield"; - sprite = "GRTVA0"; - } - 402 - { - title = "Attraction Shield"; - sprite = "YLTVA0"; - } - 403 - { - title = "Force Shield"; - sprite = "BLTVA0"; - } - 404 - { - title = "Armageddon Shield"; - sprite = "BKTVA0"; - } - 405 - { - title = "Whirlwind Shield"; - sprite = "WHTVA0"; - } - 406 - { - title = "Elemental Shield"; - sprite = "ELTVA0"; - } - 407 - { - title = "Super Sneakers"; - sprite = "SHTVA0"; - } - 408 - { - title = "Invincibility"; - sprite = "PINVA0"; - } - 409 - { - title = "Extra Life"; - sprite = "PRUPA0"; - deaftext = "[3] Random (Weak) / 10k points"; - } - 410 - { - title = "Eggman"; - sprite = "EGGBA0"; - } - 411 - { - title = "Teleporter"; - sprite = "MIXUA0"; - } - 412 - { - title = "Random"; - sprite = "QUESA0"; - } - 413 - { - title = "Gravity Boots"; - sprite = "GBTVA0"; - } - 414 - { - title = "CTF Team Ring Box (Red)"; - sprite = "RRBXA0"; - deaftext = "[3] Ambush"; - } - 415 - { - title = "CTF Team Ring Box (Blue)"; - sprite = "BRBXA0"; - deaftext = "[3] Ambush"; - } - 416 - { - title = "Recycler"; - sprite = "RECYA0"; - } - 418 - { - title = "1,000 Points"; - sprite = "PTTVA0"; - } - 419 - { - title = "10,000 Points"; - sprite = "PTTVF0"; - } - } - - miscellaneous - { - color = 11; // Light_Cyan - title = "Miscellaneous"; - width = 16; - height = 40; - sort = 1; - - 500 - { - title = "Air Bubble Patch"; - sprite = "BUBLA0"; - width = 8; - height = 16; - deaftext = "[3] No Distance Check"; - } - 501 - { - title = "End Level Sign"; - sprite = "SIGND0"; - width = 8; - height = 32; - } - 502 - { - arrow = 1; - title = "Star Post"; - sprite = "STPTA0"; - width = 64; - height = 80; - } - 526 - { - blocking = 2; - title = "Cannonball"; - sprite = "CBLLA0"; - width = 20; - deaftext = "[3] Not Pushable"; - } - 1000 - { - arrow = 1; - blocking = 2; - title = "Gargoyle"; - sprite = "GARGA1"; - deaftext = "[3] Not Pushable"; - } - 1102 - { - arrow = 1; - blocking = 2; - title = "Eggman Statue"; - sprite = "ESTAA1"; - width = 32; - height = 240; - deaftext = "[3] Not Pushable"; - } - 1106 - { - arrow = 1; - title = "Chain (Hang)"; - sprite = "SMCHA0"; - height = 32; - deaftext = "[3] Double Size"; - } - 1107 - { - arrow = 1; - title = "Chain (Spin)"; - sprite = "SMCHA0"; - height = 32; - } - 1200 - { - title = "Tumbleweed (Big)"; - sprite = "BTBLA0"; - width = 24; - height = 48; - deaftext = "[3] Moves Perpetually"; - } - 1201 - { - title = "Tumbleweed (Small)"; - sprite = "STBLA0"; - width = 12; - height = 24; - deaftext = "[3] Moves Perpetually"; - } - 1504 - { - title = "ATZ Target"; - sprite = "RCRYB0"; - width = 24; - height = 32; - } - 1852 - { - blocking = 2; - title = "Snowman"; - sprite = "XMS3A0"; - deaftext = "[3] Not Pushable"; - } - 1876 - { - arrow = 1; - blocking = 2; - title = "Eggman Disco Statue"; - sprite = "ESTAB1"; - width = 20; - height = 96; - deaftext = "[3] Not Pushable"; - } - } - - springs - { - color = 12; // Light_Red - title = "Springs and Fans"; - width = 20; - height = 16; - - 540 - { - title = "Fan"; - sprite = "FANSA0D0"; - width = 16; - deaftext = "[3] No Distance Check"; - } - 541 - { - title = "Gas Jet"; - sprite = "STEMD0"; - width = 32; - } - 550 - { - title = "Yellow Spring"; - sprite = "SPRYA0"; - } - 551 - { - title = "Red Spring"; - sprite = "SPRRA0"; - } - 552 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - } - 555 - { - arrow = 1; - title = "Diagonal Yellow Spring"; - sprite = "YSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - 556 - { - arrow = 1; - title = "Diagonal Red Spring"; - sprite = "RSPRD2"; - width = 16; - deaftext = "[3] Rotate 22.5° CCW"; - } - } - - patterns - { - color = 5; // Magenta - arrow = 1; - title = "Special Placement Patterns"; - width = 16; - height = 384; - - 600 - { - arrow = 0; - title = "5 Vertical Rings (Yellow Spring)"; - sprite = "RINGA0"; - } - 601 - { - arrow = 0; - title = "5 Vertical Rings (Red Spring)"; - sprite = "RINGA0"; - height = 1024; - } - 602 - { - title = "5 Diagonal Rings (Yellow Spring)"; - sprite = "RINGA0"; - height = 32; - } - 603 - { - title = "10 Diagonal Rings (Red Spring)"; - sprite = "RINGA0"; - height = 32; - } - 604 - { - title = "Circle of Rings"; - sprite = "RINGA0"; - width = 96; - height = 192; - } - 605 - { - title = "Circle of Rings (Big)"; - sprite = "RINGA0"; - width = 192; - } - 606 - { - title = "Circle of Wing Logos"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 607 - { - title = "Circle of Wing Logos (Big)"; - sprite = "NWNGA0"; - width = 192; - } - 608 - { - title = "Circle of Rings and Wings"; - sprite = "NWNGA0"; - width = 96; - height = 192; - } - 609 - { - title = "Circle of Rings and Wings (Big)"; - sprite = "NWNGA0"; - width = 192; - } - } - - invisible - { - color = 15; // White - title = "Misc. Invisible"; - width = 8; - height = 16; - - 700 = "Water Ambience A (Large)"; - 701 = "Water Ambience B (Large)"; - 702 = "Water Ambience C (Medium)"; - 703 = "Water Ambience D (Medium)"; - 704 = "Water Ambience E (Small)"; - 705 = "Water Ambience F (Small)"; - 706 = "Water Ambience G (Extra Large)"; - 707 = "Water Ambience H (Extra Large)"; - 708 = "Disco Ambience"; - 709 = "Volcano Ambience"; - 751 - { - arrow = 1; - title = "Teleport Destination"; - } - 752 - { - arrow = 1; - title = "Alternate View Point"; - } - 753 = "Zoom Tube Waypoint"; - 754 - { - title = "Push Point"; - deaftext = "[3] Push Using XYZ"; - } - 755 - { - title = "Pull Point"; - deaftext = "[3] Pull Using XYZ"; - } - 760 = "PolyObject Anchor"; - 761 = "PolyObject Spawn Point"; - 762 = "PolyObject Spawn Point (Crush)"; - 780 = "Skybox View Point"; - - } - - hazards - { - color = 4; // Red - title = "Hazards"; - width = 20; - height = 40; - sort = 1; - - 521 - { - title = "Spikeball"; - sprite = "SPIKA0"; - width = 12; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 523 - { - title = "Spike (Floor)"; - sprite = "USPKA0"; - width = 8; - height = 42; - deaftext = "[3] Solid"; - } - 524 - { - arrow = 1; - title = "Big Floating Mine"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 527 - { - arrow = 1; - title = "Big Floating Mine (Air)"; - width = 16; - height = 32; - sprite = "BMNEA1"; - } - 525 - { - title = "Cannonball Launcher"; - sprite = "CBLLA0"; - } - 1101 - { - title = "Torch"; - sprite = "FLAMA0"; - width = 8; - height = 32; - } - 1104 - { - title = "Mace (Spinning)"; - sprite = "SMCEA0"; - deaftext = "[3] Double Size"; - } - 1105 - { - title = "Mace (Swinging)"; - sprite = "SMCEA0"; - deaftext = "[3] Double Size"; - } - 1202 - { - arrow = 1; - title = "Rock Spawner"; - sprite = "ROIAA0"; - } - 1300 - { - arrow = 1; - title = "Flame Jet (Horizontal)"; - sprite = "FLMEB0"; - width = 16; - } - 1301 - { - title = "Flame Jet (Vertical)"; - sprite = "FLMEB0"; - width = 16; - deaftext = "[3] Shoot Downwards"; - } - 1500 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle"; - sprite = "GARGA1"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 1501 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Up)"; - sprite = "GARGA1"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 1502 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Down)"; - sprite = "GARGA1"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 1503 - { - arrow = 1; - blocking = 2; - title = "Trapgoyle (Long)"; - sprite = "GARGA1"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 3575 - { - title = "Spinning Flame Jet (Counter-Clockwise)"; - sprite = "FLMEB0"; - width = "16"; - } - 3576 - { - title = "Spinning Flame Jet (Clockwise)"; - sprite = "FLMEB0"; - width = "16"; - } - } - - decoration - { - color = 2; // Green - title = "Decoration"; - width = 16; - height = 40; - - 757 - { - title = "Fan Particle Generator"; - sprite = "PRTLA0"; - width = 8; - height = 16; - } - 800 - { - title = "GFZ Flower"; - sprite = "FWR1A0"; - } - 801 - { - title = "Sunflower"; - sprite = "FWR2A0"; - height = 96; - } - 802 - { - title = "Budding Flower"; - sprite = "FWR3A0"; - width = 8; - height = 32; - } - 804 - { - title = "Berry Bush"; - sprite = "BUS1A0"; - height = 32; - } - 805 - { - title = "Bush"; - sprite = "BUS2A0"; - height = 32; - } - 900 - { - title = "THZ Flower"; - sprite = "THZPA0"; - width = 8; - height = 32; - } - 901 - { - title = "Alarm"; - sprite = "ALRMA0"; - width = 8; - height = 16; - hangs = 1; - } - 1001 - { - title = "Seaweed"; - sprite = "SEWEA0"; - width = 24; - height = 56; - } - 1002 - { - title = "Dripping Water"; - sprite = "DRIPD0"; - width = 8; - height = 16; - hangs = 1; - } - 1003 - { - title = "Coral (Green)"; - sprite = "CRL1A0"; - width = 8; - height = 16; - } - 1004 - { - title = "Coral (Red)"; - sprite = "CRL2A0"; - width = 8; - height = 16; - } - 1005 - { - title = "Coral (Orange)"; - sprite = "CRL3A0"; - width = 8; - height = 16; - } - 1006 - { - title = "Blue Crystal"; - sprite = "BCRYA1"; - width = 8; - height = 16; - } - 1100 - { - title = "Chain"; - sprite = "CHANA0"; - width = 8; - height = 128; - hangs = 1; - } - 1103 - { - title = "CEZ Flower"; - sprite = "FWR4A0"; - } - 1203 - { - title = "Cactus with Brown Flower"; - sprite = "CACTA0"; - height = 32; - } - 1204 - { - title = "Cactus with Brown Flower (Tall)"; - sprite = "CACTB0"; - height = 64; - } - 1205 - { - title = "Cactus with Blue Flower"; - sprite = "CACTC0"; - height = 32; - } - 1206 - { - title = "Cactus with Blue Flower (Tall)"; - sprite = "CACTD0"; - height = 80; - } - 1850 - { - title = "Xmas Pole"; - sprite = "XMS1A0"; - } - 1851 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - width = 8; - height = 32; - } - 1875 - { - title = "Disco Ball"; - sprite = "DBALA0"; - height = 54; - hangs = 1; - } - 1900 - { - title = "Brown Stalagmite (Tall)"; - sprite = "STLGA0"; - } - 1901 - { - title = "Brown Stalagmite"; - sprite = "STLGB0"; - } - 1902 - { - title = "Orange Stalagmite (Tall)"; - sprite = "STLGC0"; - } - 1903 - { - title = "Orange Stalagmite"; - sprite = "STLGD0"; - } - 1904 - { - title = "Red Stalagmite (Tall)"; - sprite = "STLGE0"; - } - 1905 - { - title = "Red Stalagmite"; - sprite = "STLGF0"; - } - 1906 - { - title = "Gray Stalagmite (Tall)"; - sprite = "STLGG0"; - } - 1907 - { - title = "Gray Stalagmite"; - sprite = "STLGH0"; - } - 1908 - { - title = "Blue Stalagmite (Tall)"; - sprite = "STLGI0"; - } - 1909 - { - title = "Blue Stalagmite"; - sprite = "STLGJ0"; - } - } - - nights - { - color = 13; // Pink - title = "Nights Items"; - width = 12; - height = 32; - - 1703 - { - title = "Ideya Drone"; - sprite = "NDRNA1"; - width = 16; - height = 56; - deaftext = "[3] Die Upon Time Up"; - } - 1704 - { - arrow = 1; - title = "Bumper"; - sprite = "NBMPG3G7"; - width = 32; - height = 64; - } - 1705 - { - arrow = 1; - title = "Hoop (Generic)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - 1706 - { - title = "Wing Logo"; - sprite = "NWNGA0"; - height = 24; - } - 1707 - { - title = "Super Loop"; - sprite = "NPRUA0"; - deaftext = "[3] Spawn Immediately"; - } - 1708 - { - title = "Drill Refill"; - sprite = "NPRUB0"; - deaftext = "[3] Spawn Immediately"; - } - 1709 - { - title = "Helper"; - sprite = "NPRUC0"; - deaftext = "[3] Spawn Immediately"; - } - 1711 - { - title = "Extra Time"; - sprite = "NPRUD0"; - deaftext = "[3] Spawn Immediately"; - } - 1712 - { - title = "Link Freeze"; - sprite = "NPRUE0"; - deaftext = "[3] Spawn Immediately"; - } - 1713 - { - arrow = 1; - title = "Hoop (Customizable)"; - sprite = "HOOPA0"; - width = 80; - height = 160; - } - } - - nightstrk - { - color = 13; // Pink - title = "Nights Track"; - width = 8; - height = 4096; - - 1700 - { - title = "Axis"; - circle = 1; - } - 1701 - { - title = "Axis Transfer"; - } - 1702 - { - title = "Axis Transfer Line"; - } - 1710 - { - title = "Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk1 - { - color = 13; // Pink - title = "Nights Track (2nd Mare)"; - width = 8; - height = 4096; - - 5796 - { - title = "(Mare 2) Axis"; - circle = 1; - } - 5797 - { - title = "(Mare 2) Axis Transfer"; - } - 5798 - { - title = "(Mare 2) Axis Transfer Line"; - } - 5806 - { - title = "(Mare 2) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk2 - { - color = 13; // Pink - title = "Nights Track (3rd Mare)"; - width = 8; - height = 4096; - - 9892 - { - title = "(Mare 3) Axis"; - circle = 1; - } - 9893 - { - title = "(Mare 3) Axis Transfer"; - } - 9894 - { - title = "(Mare 3) Axis Transfer Line"; - } - 9902 - { - title = "(Mare 3) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk3 - { - color = 13; // Pink - title = "Nights Track (4th Mare)"; - width = 8; - height = 4096; - - 13988 - { - title = "(Mare 4) Axis"; - circle = 1; - } - 13989 - { - title = "(Mare 4) Axis Transfer"; - } - 13990 - { - title = "(Mare 4) Axis Transfer Line"; - } - 13998 - { - title = "(Mare 4) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk4 - { - color = 13; // Pink - title = "Nights Track (5th Mare)"; - width = 8; - height = 4096; - - 18084 - { - title = "(Mare 5) Axis"; - circle = 1; - } - 18085 - { - title = "(Mare 5) Axis Transfer"; - } - 18086 - { - title = "(Mare 5) Axis Transfer Line"; - } - 18094 - { - title = "(Mare 5) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk5 - { - color = 13; // Pink - title = "Nights Track (6th Mare)"; - width = 8; - height = 4096; - - 22180 - { - title = "(Mare 6) Axis"; - circle = 1; - } - 22181 - { - title = "(Mare 6) Axis Transfer"; - } - 22182 - { - title = "(Mare 6) Axis Transfer Line"; - } - 22190 - { - title = "(Mare 6) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk6 - { - color = 13; // Pink - title = "Nights Track (7th Mare)"; - width = 8; - height = 4096; - - 26276 - { - title = "(Mare 7) Axis"; - circle = 1; - } - 26277 - { - title = "(Mare 7) Axis Transfer"; - } - 26278 - { - title = "(Mare 7) Axis Transfer Line"; - } - 26286 - { - title = "(Mare 7) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - nightstrk7 - { - color = 13; // Pink - title = "Nights Track (8th Mare)"; - width = 8; - height = 4096; - - 30372 - { - title = "(Mare 8) Axis"; - circle = 1; - } - 30373 - { - title = "(Mare 8) Axis Transfer"; - } - 30374 - { - title = "(Mare 8) Axis Transfer Line"; - } - 30382 - { - title = "(Mare 8) Egg Capsule"; - sprite = "CAPSA0"; - width = 72; - height = 144; - } - } - - mario - { - color = 6; // Brown - title = "Mario Items"; - width = 16; - height = 32; - sort = 1; - - 1800 - { - title = "Coin"; - sprite = "COINA0"; - height = 24; - deafheight = 32; - deaftext = "[3] Float"; - } - 1801 - { - arrow = 1; - title = "Goomba"; - sprite = "GOOMA0"; - width = 24; - } - 1802 - { - arrow = 1; - title = "Goomba (Blue)"; - sprite = "BGOMA0"; - width = 24; - } - 1803 - { - title = "Fire Flower"; - sprite = "FFWRB0"; - } - 1804 - { - title = "Koopa Shell"; - sprite = "SHLLA0"; - width = 8; - height = 16; - } - 1805 - { - title = "Puma (Jumping Fireball)"; - sprite = "PUMAA0"; - width = 8; - height = 16; - } - 1806 - { - title = "King Bowser"; - sprite = "KOOPA0"; - height = 28; - } - 1807 - { - title = "Axe"; - sprite = "MAXEA0"; - width = 8; - height = 16; - } - 1808 - { - title = "Bush (Short)"; - sprite = "MUS1A0"; - } - 1809 - { - title = "Bush (Tall)"; - sprite = "MUS2A0"; - } - 1810 - { - title = "Toad"; - sprite = "TOADA0"; - width = 8; - } - } - - srb1 - { - color = 3; // Cyan - arrow = 1; - title = "SRB1 Remake"; - width = 20; - height = 32; - sort = 1; - - 4000 - { - title = "SRB1 Crawla"; - sprite = "SRBAA1"; - height = 40; - } - 4001 - { - title = "GuardRobo"; - sprite = "SRBBA1"; - width = 17; - height = 40; - } - 4002 - { - title = "Pyrin"; - sprite = "SRBCB1"; - width = 22; - } - 4003 - { - title = "HotRobo"; - sprite = "SRBDA0"; - height = 40; - } - 4004 - { - title = "Pogminz"; - sprite = "SRBEA1"; - } - 4005 - { - title = "Pogminz (Water)"; - sprite = "SRBEA1"; - } - 4006 - { - title = "Pog-GX2"; - sprite = "SRBFA0"; - width = 10; - height = 34; - } - 4007 - { - title = "Pyrex"; - sprite = "SRBGA1"; - width = 24; - } - 4008 - { - title = "UFO"; - sprite = "SRBHA0"; - width = 24; - hangs = 1; - } - 4009 - { - title = "SWAT Bot"; - sprite = "SRBIA1"; - width = 21; - height = 69; - } - 4010 - { - title = "SpyBot 2000"; - sprite = "SRBJA0"; - width = 36; - height = 62; - } - 4011 - { - title = "Buzz Bomber"; - sprite = "SRBKA0"; - width = 44; - height = 45; - } - 4012 - { - arrow = 0; - title = "RBZ Spike"; - sprite = "SRBLA0"; - width = 10; - height = 53; - } - 4013 - { - arrow = 0; - blocking = 2; - title = "Dumb Metal Sonic"; - sprite = "SRBMC0"; - width = 16; - height = 40; - deaftext = "[3] Not Pushable"; - } - 4014 - { - title = "Super SWAT Bot"; - sprite = "SRBNA1"; - width = 21; - height = 69; - } - 4015 - { - title = "Genrex"; - sprite = "SRBOA1"; - width = 17; - height = 40; - } - } - - bsz - { - color = 2; // Green - title = "Botanic Serenity Items"; - width = 16; - height = 32; - 1400 - { - title = "Tall Flower (Red)"; - sprite = "BSZ1A0"; - } - 1401 - { - title = "Tall Flower (Purple)"; - sprite = "BSZ1B0"; - } - 1402 - { - title = "Tall Flower (Blue)"; - sprite = "BSZ1C0"; - } - 1403 - { - title = "Tall Flower (Cyan)"; - sprite = "BSZ1D0"; - } - 1404 - { - title = "Tall Flower (Yellow)"; - sprite = "BSZ1E0"; - } - 1405 - { - title = "Tall Flower (Orange)"; - sprite = "BSZ1F0"; - } - 1410 - { - title = "Medium Flower (Red)"; - sprite = "BSZ2A0"; - } - 1411 - { - title = "Medium Flower (Purple)"; - sprite = "BSZ2B0"; - } - 1412 - { - title = "Medium Flower (Blue)"; - sprite = "BSZ2C0"; - } - 1413 - { - title = "Medium Flower (Cyan)"; - sprite = "BSZ2D0"; - } - 1414 - { - title = "Medium Flower (Yellow)"; - sprite = "BSZ2E0"; - } - 1415 - { - title = "Medium Flower (Orange)"; - sprite = "BSZ2F0"; - } - 1420 - { - title = "Short Flower (Red)"; - sprite = "BSZ3A0"; - } - 1421 - { - title = "Short Flower (Purple)"; - sprite = "BSZ3B0"; - } - 1422 - { - title = "Short Flower (Blue)"; - sprite = "BSZ3C0"; - } - 1423 - { - title = "Short Flower (Cyan)"; - sprite = "BSZ3D0"; - } - 1424 - { - title = "Short Flower (Yellow)"; - sprite = "BSZ3E0"; - } - 1425 - { - title = "Short Flower (Orange)"; - sprite = "BSZ3F0"; - } - 1430 - { - title = "Tulip (Red)"; - sprite = "BSZ4A0"; - } - 1431 - { - title = "Tulip (Purple)"; - sprite = "BSZ4B0"; - } - 1432 - { - title = "Tulip (Blue)"; - sprite = "BSZ4C0"; - } - 1433 - { - title = "Tulip (Cyan)"; - sprite = "BSZ4D0"; - } - 1434 - { - title = "Tulip (Yellow)"; - sprite = "BSZ4E0"; - } - 1435 - { - title = "Tulip (Orange)"; - sprite = "BSZ4F0"; - } - 1440 - { - title = "Cluster (Red)"; - sprite = "BSZ5A0"; - } - 1441 - { - title = "Cluster (Purple)"; - sprite = "BSZ5B0"; - } - 1442 - { - title = "Cluster (Blue)"; - sprite = "BSZ5C0"; - } - 1443 - { - title = "Cluster (Cyan)"; - sprite = "BSZ5D0"; - } - 1444 - { - title = "Cluster (Yellow)"; - sprite = "BSZ5E0"; - } - 1445 - { - title = "Cluster (Orange)"; - sprite = "BSZ5F0"; - } - 1450 - { - title = "Bush (Red)"; - sprite = "BSZ6A0"; - } - 1451 - { - title = "Bush (Purple)"; - sprite = "BSZ6B0"; - } - 1452 - { - title = "Bush (Blue)"; - sprite = "BSZ6C0"; - } - 1453 - { - title = "Bush (Cyan)"; - sprite = "BSZ6D0"; - } - 1454 - { - title = "Bush (Yellow)"; - sprite = "BSZ6E0"; - } - 1455 - { - title = "Bush (Orange)"; - sprite = "BSZ6F0"; - } - 1460 - { - title = "Vine (Red)"; - sprite = "BSZ7A0"; - } - 1461 - { - title = "Vine (Purple)"; - sprite = "BSZ7B0"; - } - 1462 - { - title = "Vine (Blue)"; - sprite = "BSZ7C0"; - } - 1463 - { - title = "Vine (Cyan)"; - sprite = "BSZ7D0"; - } - 1464 - { - title = "Vine (Yellow)"; - sprite = "BSZ7E0"; - } - 1465 - { - title = "Vine (Orange)"; - sprite = "BSZ7F0"; - } - 1470 - { - title = "BSZ Shrub"; - sprite = "BSZ8A0"; - } - 1471 - { - title = "BSZ Clover"; - sprite = "BSZ8B0"; - } - 1472 - { - title = "BSZ Fish"; - sprite = "BSZ8C0"; - } - 1473 - { - title = "BSZ Sunflower"; - sprite = "BSZ8D0"; - } - } -} - - - -// Default thing filters -// (these are not required, just usefull for new users) -thingsfilters -{ - - filter0 - { - name = "Easy skill"; - category = ""; - type = -1; - - fields - { - 1 = true; - } - - } - - - filter1 - { - name = "Hard skill"; - category = ""; - type = -1; - - fields - { - 4 = true; - } - - } - - - filter2 - { - name = "Keys only"; - category = "keys"; - type = -1; - } - - - filter3 - { - name = "Medium skill"; - category = ""; - type = -1; - - fields - { - 2 = true; - } - - } - - - filter4 - { - name = "Multiplayer"; - category = ""; - type = -1; - - fields - { - 16 = true; - } - - } -} - - -// Default texture sets -// (these are not required, but usefull for new users) -/* -texturesets -{ - - set0 - { - name = "GFZ Themed Textures"; - filter0 = "GFZROCK"; - filter1 = "GFZGRASS"; - filter2 = "CFALL1"; - filter3 = "GFALL1"; - filter4 = "GFZBLOCK"; - filter5 = "GFZCRACK"; - filter6 = "GFZINSID"; - filter7 = "GFZVINES"; - filter8 = "GFZVCRCK"; - filter9 = "GFZBRIDG"; - filter10 = "GFZBLOK2"; - filter11 = "GFZBRICK"; - filter12 = "GFZDOOR"; - filter13 = "GFZWINDW"; - filter14 = "GFZROOF"; - filter15 = "GFZFENC2"; - filter16 = "GFZGRSW"; - } - - - set1 - { - name = "GFZ Themed Flats"; - filter0 = "FLOOR0_6"; - filter1 = "FLOOR0_3"; - filter2 = "DEM1_4"; - filter3 = "FWATER1"; - filter4 = "SFLR5_0"; - filter5 = "SFLR6_1"; - filter6 = "SLR6_4"; - filter7 = "SFLR7_1"; - filter8 = "SFLR7_4"; - filter9 = "FLOOR0_4"; - filter10 = "FLOOR1_1"; - filter11 = "FLOOR1_7"; - filter12 = "CEIL3_3"; - filter13 = "CEIL3_4"; - filter14 = "GATE1"; - filter15 = "FLOOR0_2"; - } - - - set2 - { - name = "Liquids"; - filter0 = "BFALL*"; - filter1 = "BLOOD*"; - filter2 = "DBRAIN*"; - filter3 = "FWATER*"; - filter4 = "LAVA*"; - filter5 = "NUKAGE*"; - filter6 = "SFALL*"; - filter7 = "SLIME01"; - filter8 = "SLIME02"; - filter9 = "SLIME03"; - filter10 = "SLIME04"; - filter11 = "SLIME05"; - filter12 = "SLIME06"; - filter13 = "SLIME07"; - filter14 = "SLIME08"; - } - - - set3 - { - name = "Doors"; - filter0 = "BIGDOOR*"; - filter1 = "DOOR*"; - filter2 = "EXITDOOR"; - filter3 = "SPCDOOR*"; - filter4 = "TEKBRON1"; - filter5 = "TEKBRON2"; - } - - - set4 - { - name = "Steps"; - filter0 = "STEP*"; - } - - - set5 - { - name = "Wood"; - filter0 = "BIGDOOR5"; - filter1 = "BIGDOOR6"; - filter2 = "BIGDOOR7"; - filter3 = "CEIL1_1"; - filter4 = "CEIL1_3"; - filter5 = "FLAT5_1"; - filter6 = "FLAT5_2"; - filter7 = "PAN*"; - filter8 = "SW1PANEL"; - filter9 = "SW1WDMET"; - filter10 = "SW1WOOD"; - filter11 = "SW2PANEL"; - filter12 = "SW2WDMET"; - filter13 = "SW2WOOD"; - filter14 = "WOOD*"; - } - - - set6 - { - name = "Flesh"; - filter0 = "AASHITTY"; - filter1 = "FLAT5_6"; - filter2 = "SFLR6_1"; - filter3 = "SFLR6_4"; - filter4 = "SFLR7_1"; - filter5 = "SFLR7_4"; - filter6 = "SK_LEFT"; - filter7 = "SK_RIGHT"; - filter8 = "SKIN*"; - filter9 = "SKSNAKE1"; - filter10 = "SKSNAKE2"; - filter11 = "SKSPINE1"; - filter12 = "SKSPINE2"; - filter13 = "SLOPPY1"; - filter14 = "SLOPPY2"; - filter15 = "SP_DUDE1"; - filter16 = "SP_DUDE2"; - filter17 = "SP_DUDE4"; - filter18 = "SP_DUDE5"; - filter19 = "SP_DUDE7"; - filter20 = "SP_DUDE8"; - filter21 = "SP_FACE1"; - filter22 = "SP_FACE2"; - filter23 = "SW1SKIN"; - filter24 = "SW1SKULL"; - filter25 = "SW2SKIN"; - filter26 = "SW2SKULL"; - } - - - set7 - { - name = "Switches"; - filter0 = "SW1*"; - filter1 = "SW2*"; - } - - - set8 - { - name = "Marble"; - filter0 = "DEM1_*"; - filter1 = "FLOOR7_2"; - filter2 = "GST*"; - filter3 = "MARB*"; - filter4 = "SP_DUDE1"; - filter5 = "SP_DUDE2"; - filter6 = "SP_DUDE4"; - filter7 = "SP_DUDE5"; - filter8 = "SP_HOT1"; - filter9 = "SW1GSTON"; - filter10 = "SW1MARB"; - filter11 = "SW2GSTON"; - filter12 = "SW2MARB"; - } - - - set9 - { - name = "Lights"; - filter0 = "BRICKLIT"; - filter1 = "BSTONE3"; - filter2 = "CEIL1_2"; - filter3 = "CEIL1_3"; - filter4 = "CEIL3_4"; - filter5 = "CEIL3_6"; - filter6 = "CEIL4_3"; - filter7 = "FLAT17"; - filter8 = "FLAT2"; - filter9 = "FLAT22"; - filter10 = "FLOOR1_7"; - filter11 = "GRNLITE1"; - filter12 = "LITE3"; - filter13 = "LITE5"; - filter14 = "LITEBLU1"; - filter15 = "LITEBLU4"; - filter16 = "TLITE6_1"; - filter17 = "TLITE6_4"; - filter18 = "TLITE6_5"; - filter19 = "TLITE6_6"; - } - - - set10 - { - name = "Metal"; - filter0 = "CEIL1_2"; - filter1 = "METAL*"; - filter2 = "METAL"; - filter3 = "MIDBRN1"; - filter4 = "MIDGRATE"; - filter5 = "SW1GARG"; - filter6 = "SW1LION"; - filter7 = "SW1SATYR"; - filter8 = "SW2GARG"; - filter9 = "SW2LION"; - filter10 = "SW2MET2"; - filter11 = "SW2METAL"; - filter12 = "SW1METAL"; - filter13 = "SW1MET2"; - filter14 = "SW2SATYR"; - filter15 = "WOODMET1"; - filter16 = "WOODMET2"; - filter17 = "WOODMET3"; - filter18 = "WOODMET4"; - filter19 = "SW2WDMET"; - filter20 = "SW1WDMET"; - filter21 = "SUPPORT*"; - } - - - set11 - { - name = "Silver"; - filter0 = "BIGDOOR1"; - filter1 = "DOORSTOP"; - filter2 = "LITEBLU1"; - filter3 = "SHAWN*"; - filter4 = "SILVER*"; - filter5 = "SPCDOOR3"; - filter6 = "STEP4"; - filter7 = "SUPPORT2"; - filter8 = "SW1COMM"; - filter9 = "SW2COMM"; - } - - - set12 - { - name = "Base"; - filter0 = "BIGBRIK*"; - filter1 = "BIGDOOR1"; - filter2 = "BIGDOOR2"; - filter3 = "BIGDOOR3"; - filter4 = "BIGDOOR4"; - filter5 = "BLAKWAL*"; - filter6 = "BRN*"; - filter7 = "BRONZE*"; - filter8 = "BROWN*"; - filter9 = "BROVINE2"; - filter10 = "CEIL3_1"; - filter11 = "CEIL3_2"; - filter12 = "CEIL3_3"; - filter13 = "CEIL3_4"; - filter14 = "CEIL3_5"; - filter15 = "CEIL3_6"; - filter16 = "CEIL4_1"; - filter17 = "CEIL4_2"; - filter18 = "CEIL4_3"; - filter19 = "CEIL5_1"; - filter20 = "CEIL5_2"; - filter21 = "CEMENT*"; - filter22 = "COMP*"; - filter23 = "CONS*"; - filter24 = "CRAT*"; - filter25 = "DOOR1"; - filter26 = "DOOR3"; - filter27 = "DOORBLU"; - filter28 = "DOORRED"; - filter29 = "DOORSTOP"; - filter30 = "DOORTRAK"; - filter31 = "DOORYEL"; - filter32 = "EXITDOOR"; - filter33 = "EXITSIGN"; - filter34 = "EXITSTON"; - filter35 = "FLAT1"; - filter36 = "FLAT1_1"; - filter37 = "FLAT1_2"; - filter38 = "FLAT1_3"; - filter39 = "FLAT14"; - filter40 = "FLAT17"; - filter41 = "FLAT18"; - filter42 = "FLAT19"; - filter43 = "FLAT2"; - filter44 = "FLAT20"; - filter45 = "FLAT22"; - filter46 = "FLAT23"; - filter47 = "FLAT3"; - filter48 = "FLAT4"; - filter49 = "FLAT5"; - filter50 = "FLAT5_4"; - filter51 = "FLAT5_5"; - filter52 = "FLAT8"; - filter53 = "FLAT9"; - filter54 = "FLOOR0_1"; - filter55 = "FLOOR0_2"; - filter56 = "FLOOR0_3"; - filter57 = "FLOOR0_5"; - filter58 = "FLOOR0_6"; - filter59 = "FLOOR0_7"; - filter60 = "FLOOR1_1"; - filter61 = "FLOOR1_6"; - filter62 = "FLOOR1_7"; - filter63 = "FLOOR3_3"; - filter64 = "FLOOR4_1"; - filter65 = "FLOOR4_5"; - filter66 = "FLOOR4_6"; - filter67 = "FLOOR4_8"; - filter68 = "FLOOR5_1"; - filter69 = "FLOOR5_2"; - filter70 = "FLOOR5_3"; - filter71 = "FLOOR5_4"; - filter72 = "FLOOR7_1"; - filter73 = "GRAY*"; - filter74 = "ICKWALL*"; - filter75 = "LITE*"; - filter76 = "METAL"; - filter77 = "METAL1"; - filter78 = "METAL2"; - filter79 = "METAL3"; - filter80 = "METAL4"; - filter81 = "METAL5"; - filter82 = "METAL6"; - filter83 = "METAL7"; - filter84 = "MFLR8_1"; - filter85 = "MIDBARS1"; - filter86 = "MIDBARS3"; - filter87 = "MIDBRONZ"; - filter88 = "MIDSPACE"; - filter89 = "MODWALL*"; - filter90 = "NUKE*"; - filter91 = "PIPES"; - filter92 = "PIPEWAL1"; - filter93 = "PIPEWAL2"; - filter94 = "PLAT1"; - filter95 = "RROCK14"; - filter96 = "SHAWN*"; - filter97 = "SILVER*"; - filter98 = "SLAD*"; - filter99 = "SLIME13"; - filter100 = "SLIME14"; - filter101 = "SLIME15"; - filter102 = "SLIME16"; - filter103 = "SPACE*"; - filter104 = "SPCDOOR*"; - filter105 = "STAR*"; - filter106 = "STEP*"; - filter107 = "STONE"; - filter108 = "STONE2"; - filter109 = "STONE3"; - filter110 = "SUPPORT2"; - filter111 = "SUPPORT3"; - filter112 = "SW1BLUE"; - filter113 = "SW1BRCOM"; - filter114 = "SW1BRIK"; - filter115 = "SW1BRN1"; - filter116 = "SW1BRN2"; - filter117 = "SW1BRNGN"; - filter118 = "SW1BROWN"; - filter119 = "SW1CMT"; - filter120 = "SW1COMM"; - filter121 = "SW1COMP"; - filter122 = "SW1DIRT"; - filter123 = "SW1EXIT"; - filter124 = "SW1GRAY"; - filter125 = "SW1GRAY1"; - filter126 = "SW1MET2"; - filter127 = "SW1METAL"; - filter128 = "SW1MOD1"; - filter129 = "SW1SLAD"; - filter130 = "SW1STARG"; - filter131 = "SW1STON1"; - filter132 = "SW1STON2"; - filter133 = "SW1STONE"; - filter134 = "SW1STRTN"; - filter135 = "SW1TEK"; - filter136 = "SW1VINE"; - filter137 = "SW2BLUE"; - filter138 = "SW2BRCOM"; - filter139 = "SW2BRIK"; - filter140 = "SW2BRN1"; - filter141 = "SW2BRN2"; - filter142 = "SW2BRNGN"; - filter143 = "SW2BROWN"; - filter144 = "SW2CMT"; - filter145 = "SW2COMM"; - filter146 = "SW2COMP"; - filter147 = "SW2DIRT"; - filter148 = "SW2EXIT"; - filter149 = "SW2GRAY"; - filter150 = "SW2GRAY1"; - filter151 = "SW2MET2"; - filter152 = "SW2METAL"; - filter153 = "SW2MOD1"; - filter154 = "SW2SLAD"; - filter155 = "SW2STARG"; - filter156 = "SW2STON1"; - filter157 = "SW2STON2"; - filter158 = "SW2STONE"; - filter159 = "SW2STRTN"; - filter160 = "SW2TEK"; - filter161 = "SW2VINE"; - filter162 = "TEK*"; - filter163 = "TLITE*"; - filter164 = "PIPE1"; - filter165 = "PIPE2"; - filter166 = "PIPE4"; - filter167 = "PIPE6"; - filter168 = "STUCCO*"; - filter169 = "STUCCO"; - } - - - set13 - { - name = "Hell"; - filter0 = "BFALL*"; - filter1 = "BIGDOOR5"; - filter2 = "BIGDOOR6"; - filter3 = "BIGDOOR7"; - filter4 = "BLODRIP*"; - filter5 = "BLOOD1"; - filter6 = "BLOOD2"; - filter7 = "BLOOD3"; - filter8 = "CEIL1_2"; - filter9 = "CEIL1_3"; - filter10 = "CEIL1_1"; - filter11 = "BSTONE1"; - filter12 = "BSTONE2"; - filter13 = "BSTONE3"; - filter14 = "CRACKLE2"; - filter15 = "CRACKLE4"; - filter16 = "DOORBLU2"; - filter17 = "DOORRED2"; - filter18 = "DOORYEL2"; - filter19 = "FIRE*"; - filter20 = "FLAT1_1"; - filter21 = "FLAT1_2"; - filter22 = "FLAT1_3"; - filter23 = "FLAT5_1"; - filter24 = "FLAT5_2"; - filter25 = "FLAT5_3"; - filter26 = "FLAT5_6"; - filter27 = "FLAT5_7"; - filter28 = "FLAT5_8"; - filter29 = "FLOOR1_6"; - filter30 = "FLOOR1_7"; - filter31 = "FLOOR6_1"; - filter32 = "FLOOR6_2"; - filter33 = "GATE*"; - filter34 = "GST*"; - filter35 = "LAVA*"; - filter36 = "MARB*"; - filter37 = "METAL"; - filter38 = "MFLR8_2"; - filter39 = "MFLR8_3"; - filter40 = "MIDBRN1"; - filter41 = "MIDGRATE"; - filter42 = "REDWALL"; - filter43 = "ROCKRED1"; - filter44 = "ROCKRED2"; - filter45 = "ROCKRED3"; - filter46 = "RROCK01"; - filter47 = "RROCK02"; - filter48 = "RROCK03"; - filter49 = "RROCK04"; - filter50 = "RROCK05"; - filter51 = "RROCK06"; - filter52 = "RROCK07"; - filter53 = "RROCK08"; - filter54 = "RROCK09"; - filter55 = "RROCK10"; - filter56 = "RROCK11"; - filter57 = "RROCK12"; - filter58 = "RROCK15"; - filter59 = "SFLR6_1"; - filter60 = "SFLR6_4"; - filter61 = "SFLR7_1"; - filter62 = "SFLR7_4"; - filter63 = "SK_LEFT"; - filter64 = "SK_RIGHT"; - filter65 = "SKIN*"; - filter66 = "SKSNAKE1"; - filter67 = "SKSNAKE2"; - filter68 = "SKSPINE1"; - filter69 = "SKSPINE2"; - filter70 = "SLIME09"; - filter71 = "SLIME10"; - filter72 = "SLIME11"; - filter73 = "SLIME12"; - filter74 = "SLOPPY1"; - filter75 = "SLOPPY2"; - filter76 = "SP_*"; - filter77 = "SUPPORT3"; - filter78 = "SW1GARG"; - filter79 = "SW1GSTON"; - filter80 = "SW1HOT"; - filter81 = "SW1LION"; - filter82 = "SW1MARB"; - filter83 = "SW1SATYR"; - filter84 = "SW1SKIN"; - filter85 = "SW1SKULL"; - filter86 = "SW1WDMET"; - filter87 = "SW1WOOD"; - filter88 = "SW2GARG"; - filter89 = "SW2GSTON"; - filter90 = "SW2HOT"; - filter91 = "SW2LION"; - filter92 = "SW2MARB"; - filter93 = "SW2SATYR"; - filter94 = "SW2SKIN"; - filter95 = "SW2SKULL"; - filter96 = "SW2WDMET"; - filter97 = "SW2WOOD"; - filter98 = "WOOD*"; - } - - - set14 - { - name = "Outdoors"; - filter0 = "ASHWALL*"; - filter1 = "BFALL*"; - filter2 = "FLAT10"; - filter3 = "FLAT5_7"; - filter4 = "FLAT5_8"; - filter5 = "FLOOR6_1"; - filter6 = "FLOOR6_2"; - filter7 = "FWATER*"; - filter8 = "GRASS*"; - filter9 = "LAVA*"; - filter10 = "MFLR8_2"; - filter11 = "MFLR8_3"; - filter12 = "MFLR8_4"; - filter13 = "NUKAGE*"; - filter14 = "ROCK4"; - filter15 = "ROCK5"; - filter16 = "ROCKRED1"; - filter17 = "ROCKRED2"; - filter18 = "ROCKRED3"; - filter19 = "RROCK01"; - filter20 = "RROCK02"; - filter21 = "RROCK03"; - filter22 = "RROCK04"; - filter23 = "RROCK05"; - filter24 = "RROCK06"; - filter25 = "RROCK07"; - filter26 = "RROCK08"; - filter27 = "RROCK16"; - filter28 = "RROCK17"; - filter29 = "RROCK18"; - filter30 = "RROCK19"; - filter31 = "RROCK20"; - filter32 = "SFALL*"; - filter33 = "SLIME01"; - filter34 = "SLIME02"; - filter35 = "SLIME03"; - filter36 = "SLIME04"; - filter37 = "SLIME05"; - filter38 = "SLIME06"; - filter39 = "SLIME07"; - filter40 = "SLIME08"; - filter41 = "SLIME09"; - filter42 = "SLIME10"; - filter43 = "SLIME11"; - filter44 = "SLIME12"; - filter45 = "SP_ROCK1"; - filter46 = "STONE4"; - filter47 = "STONE5"; - filter48 = "STONE6"; - filter49 = "STONE7"; - filter50 = "TANROCK5"; - filter51 = "TANROCK8"; - filter52 = "ZIMMER*"; - } - - - set15 - { - name = "Computer"; - filter0 = "COMP*"; - filter1 = "CONS*"; - filter2 = "SILVER3"; - filter3 = "SPACEW3"; - filter4 = "SW1COMP"; - filter5 = "SW2COMP"; - } -} -*/ - -/* Better version -texturesets -{ - set0 - { - name = "Greenflower Zone Flats & Textures"; - filter0 = "GFZFLR02"; - filter1 = "GFZFLR10"; - filter2 = "GFZGRASS"; - filter3 = "GFZGRSw"; - filter4 = "FWATER1"; - filter5 = "CFALL1"; - filter6 = "GFALL1"; - filter7 = "GFZFLR01"; - filter8 = "GFZROCK"; - filter9 = "GFZCRACK"; - filter10 = "GFZINSID"; - filter11 = "GFZVINES"; - filter12 = "GFZVCRCK"; - filter13 = "GFZFLR05"; - filter14 = "GFZFLR06"; - filter15 = "GFZFLR09"; - filter16 = "GFZBRIDG"; - filter17 = "GFZBLOCK"; - filter18 = "GFZFLR03"; - filter19 = "GFZFLR04"; - filter20 = "GFZBRICK"; - filter21 = "GFZDOOR"; - filter22 = "GFZWINDW"; - filter23 = "GFZROOF"; - filter31 = "FLOOR0_2"; - filter32 = "GFZFLR07"; - filter33 = "DEM1_5"; - filter34 = "GFZFENC2"; - } - - set1 - { - name = "Techno Hill Zone Flats & Textures"; - filter0 = "THZFLR01"; - filter1 = "THZFLR02"; - filter2 = "THZFLR03"; - filter3 = "THZFLR04"; - filter4 = "THZFLR05"; - filter5 = "THZFLR08"; - filter6 = "THZFLR19"; - filter7 = "THZFLR24"; - filter8 = "THZFLR27"; - filter9 = "THZWAL01"; - filter10 = "THZWAL02"; - filter11 = "THZWAL03"; - filter12 = "THZWAL04"; - filter13 = "THZWAL05"; - filter14 = "THZWAL09"; - filter15 = "THZSTONE"; - filter16 = "THZTILE"; - filter17 = "THZBLOK1"; - filter18 = "THZREACT"; - filter19 = "THZVINES"; - filter20 = "THZFLR30"; - filter21 = "THZROCK"; - filter22 = "THZCRACK"; - filter23 = "THZMECH1"; - filter24 = "THZMECH2"; - filter25 = "THZMECH3"; - filter26 = "CHEMG01"; - filter27 = "TFALL1"; - filter28 = "ALTBOXF1"; - filter29 = "THZBOXF1"; - filter30 = "ALTBOX01"; - filter31 = "THZBOX01"; - filter32 = "BOXWARNG"; - filter33 = "BOXWARN2"; - filter34 = "THZFLR06"; - filter35 = "THZFLR09"; - filter36 = "THZFLR11"; - filter37 = "THZFLR13"; - filter38 = "THZFLR21"; - filter39 = "THZFLR07"; - filter40 = "THZFLR10"; - filter41 = "THZFLR12"; - filter42 = "THZFLR20"; - filter43 = "THZFLR28"; - filter44 = "PIPE2F"; - filter45 = "PIPE3F"; - filter46 = "THZFLR22"; - filter47 = "THZFLR23"; - filter48 = "PIPE2"; - filter49 = "PIPE3"; - filter50 = "THZPIPE1"; - filter51 = "THZPIPE2"; - filter52 = "PISTON"; - filter53 = "THZPIPE"; - filter54 = "THZFLR16"; - filter55 = "THZFLR17"; - filter56 = "THZFLR25"; - filter57 = "THZFLR26"; - filter58 = "THZCONV1"; - filter59 = "THZCONv2"; - filter60 = "WHZFLR16"; - filter61 = "WHZFLR17"; - filter62 = "THZFLR18"; - filter63 = "THZFLR29"; - filter64 = "BARLSIDE"; - filter65 = "BARREL2"; - filter66 = "BARREL3"; - } -}*/ diff --git a/extras/conf/srb2.wcf b/extras/conf/srb2.wcf deleted file mode 100644 index b474633da..000000000 --- a/extras/conf/srb2.wcf +++ /dev/null @@ -1,576 +0,0 @@ - -; Defines general parameters of the game for which wadfiles are intended. -; -; Name textual name for internal use -; IWAD standard 8.3 base name and extension of main wadfile -; NewMap default name for new map -- dictates format for all maps -; Directory directory in which main wadfile (and game files) reside -; Run command to execute (from the directory) for running a map - -[WadGame] -Name=Sonic Robo Blast 2 -IWAD=srb2.srb -NewMap=MAP01 -Directory=C:\Documents and Settings\Ben\My Documents\srb2 -Run=fd\srb2win.exe -file $_Wadfile -warp $_Wadmap - -; Defines parameters of the default sector motif created when no motif -; file can be located at startup. - -[Default.Sector] -Above=GFZROCK -Main=GFZROCK -Below=GFZROCK -Ceiling=F_SKY1 -Floor=FLOOR0_6 -CeilingHeight=4096 -FloorHeight=0 -Lighting=255 - -; Defines parameters of the default door motif created when no motif -; file can be located at startup. - -[Default.Door] -Base=FLAT1 -Door=BIGDOOR2 -Track=DOORTRAK -Type=1 - -; Defines parameters of the default stair motif created when no motif -; file can be located at startup. - -[Default.Stair] -FloorRunner=GFZROCK -CeilingRunner=GFZROCK -Stairwell=GFZROCK -FloorInc=8 -CeilingInc=0 -LightingInc=0 - -; ID used to classify things -; Flags supplies some additional information: -; 0x0001 - indicate thing facing angle -; Red red value for drawing things of said class -; Green green value for drawing things of said class -; Blue blue value for drawing things of said class -; Name textual description of class - -[Things.Classes] -0x001 0x0001 255 255 255 Starts -0x002 0x0000 192 0 224 Emeralds -0x003 0x0001 255 0 0 Enemies -0x004 0x0000 255 192 0 Nights Things -0x005 0x0000 0 192 192 Power-Up Monitors -0x006 0x0000 192 0 224 Misc. -0x007 0x0000 192 192 192 Scenery -0x008 0x0000 255 255 0 Mario -0x009 0x0000 255 192 224 Christmas -0x00b 0x0000 0 0 255 Rings -0x00c 0x0000 0 224 0 Springs and Such - -; ID used to uniquely identify things in a map -; Class classification (defined above section) -; Size approximate thing size (in map units) -; Sprite name of the sprite to use for display purposes -; Name textual description of thing - -[Things.Types] -0x001 1 32 suptd0 Player 01 Start -0x002 1 32 suptd0 Player 02 Start -0x003 1 32 suptd0 Player 03 Start -0x004 1 32 suptd0 Player 04 Start -0xfa1 1 32 suptd0 Player 05 Start -0xfa2 1 32 suptd0 Player 06 Start -0xfa3 1 32 suptd0 Player 07 Start -0xfa4 1 32 suptd0 Player 08 Start -0xfa5 1 32 suptd0 Player 09 Start -0xfa6 1 32 suptd0 Player 10 Start -0xfa7 1 32 suptd0 Player 11 Start -0xfa8 1 32 suptd0 Player 12 Start -0xfa9 1 32 suptd0 Player 13 Start -0xfaa 1 32 suptd0 Player 14 Start -0xfab 1 32 suptd0 Player 15 Start -0xfac 1 32 suptd0 Player 16 Start -0xfad 1 32 suptd0 Player 17 Start -0xfae 1 32 suptd0 Player 18 Start -0xfaf 1 32 suptd0 Player 19 Start -0xfb0 1 32 suptd0 Player 20 Start -0xfb1 1 32 suptd0 Player 21 Start -0xfb2 1 32 suptd0 Player 22 Start -0xfb3 1 32 suptd0 Player 23 Start -0xfb4 1 32 suptd0 Player 24 Start -0xfb5 1 32 suptd0 Player 25 Start -0xfb6 1 32 suptd0 Player 26 Start -0xfb7 1 32 suptd0 Player 27 Start -0xfb8 1 32 suptd0 Player 28 Start -0xfb9 1 32 suptd0 Player 29 Start -0xfba 1 32 suptd0 Player 30 Start -0xfbb 1 32 suptd0 Player 31 Start -0xfbc 1 32 suptd0 Player 32 Start -0x057 1 32 suptd0 CTF Team Start (Red) -0x059 1 32 suptd0 CTF Team Start (Blue) -0x00b 1 32 suptd0 Deathmatch Start -0x1a4 2 20 cemga0 Emerald 1 (Green) -0x1a5 2 20 cemoa0 Emerald 2 (Orange) -0x1a6 2 20 cempa0 Emerald 3 (Pink) -0x1a7 2 20 cemba0 Emerald 4 (Blue) -0x1a8 2 20 cemra0 Emerald 5 (Red) -0x1a9 2 20 cemla0 Emerald 6 (Light Blue) -0x1aa 2 20 cemga0 Emerald 7 (Grey) -0x1ab 2 20 cemka0 Emerald 8 (Master) -0x009 3 40 sposa1 Crawla (Red) -0xbbc 3 40 possa1 Crawla (Blue) -0x02a 3 40 tfogi0 Pop-up Turret -0xbbd 3 40 jetba1 Jetty-Syn Bomber -0x016 3 40 jetga1 Jetty-Syn Gunner -0x03a 3 40 fisha0 Stupid Dumb Unnamed Robofish (tm) -0x047 3 40 detna1 Deton -0x038 3 40 skima0 Skim -0x7d4 3 40 treta1 THZ Turret -0x010 3 80 eggma1 Egg Mobile (Boss 1) -0x7d8 3 80 eggna1 Egg Slimer (Boss 2) -0x015 3 40 ccoma1 Crawla Commander -0x008 3 40 tfogi0 Chaos Mode Enemy Spawn -0x138d 3 40 buzza0 Gold Buzz -0x138e 3 40 rbuza0 Red Buzz -0x034 4 20 dissa0 1024 Axis -0x035 4 20 dissa0 512 Axis -0x03b 4 20 dissa0 2048 Axis -0x03e 4 20 dissa0 1024 Axis (Inverted) -0x00f 4 20 dissa0 512 Axis (Inverted) -0x02d 4 20 dissa0 2048 Axis (Inverted) -0x03d 4 20 dissa0 Axis Transfer -0x02e 4 20 dissa0 Axis Transfer Closest -0x037 4 20 dissa0 Axis Transfer LastToFirst -0x03c 4 20 ndrna1 Ideya Drone -0x039 4 20 hoopa0 Hoop -0x02f 4 20 bon1a0 Circle of Rings -0x7d7 4 20 bon1a0 Circle of Rings (Big) -0x800 4 20 nwnga0 Circle of Wing Logos -0x7da 4 20 nwnga0 Circle of Wing Logos (Big) -0x7fe 4 20 nwnga0 Circle of Rings and Wings -0x7ff 4 20 nwnga0 Circle of Rings and Wings (Big) -0x025 4 20 nwnga0 Wing Logo -0x052 4 20 dissa0 Axis Transfer Condition -0x055 4 20 dissa0 Axis Transfer Condition 2 -0xbbf 4 20 npraa0 Super Loop -0xbc0 4 20 nprba0 Drill Refill -0xbc1 4 20 nprca0 Helper -0x019 5 20 shtva0 Super Sneakers -0x023 5 20 whtva0 Whirlwind Shield -0x029 5 20 prupa0 Extra Life -0x030 5 20 yltva0 Attraction Shield -0x7d2 5 20 rdtva0 Inferno Shield -0x7e2 5 20 bktva0 Armageddon Shield -0x7e6 5 20 pinva0 Invincibility -0x7ec 5 20 bltva0 Liquid Shield -0x7db 5 20 srbxa0 Super Ring (10 Rings) -0x7dc 5 20 grbxa0 Silver Ring (25 Rings) -0x04e 5 20 mixua0 Teleporter -0x7d5 5 20 eggba0 Eggman -0xbb8 5 20 quesa0 Random -0x01f 6 20 rflga0 CTF Flag (Red) -0x022 6 20 bflga0 CTF Flag (Blue) -0x7dd 6 20 tokea0 Special Stage Token -0x056 6 20 signd0 End Level Sign -0x021 6 20 bubla0 Air Bubble Patch -0x040 6 20 emera0 Emerald Hunt Location 1 -0xbba 6 20 emera0 Emerald Hunt Location 2 -0xbb9 6 20 emera0 Emerald Hunt Location 3 -0xbbe 6 20 stpta0 Star Post -0x1389 6 20 ppsha0 Push -0x138a 6 20 pplla0 Pull -0x138b 6 20 dissa0 Teleport Destination -0x138f 6 20 dissa0 Cut-Away View -0x043 6 20 dspka0 Ceiling Spike -0x044 6 20 uspka0 Floor Spike -0x017 6 20 spika0 Spikeball (Special Stage) -0x011 6 20 dissa0 Boss Flypoint -0x012 6 20 dissa0 Zoom Tube Waypoint -0x801 6 20 dissa0 Egg Capsule Center -0x033 6 20 lasra0 Laser -0x024 7 20 fwr1b0 GFZ Flower (Normal) -0x046 7 20 fwr2a0 GFZ Sunflower -0x049 7 20 fwr3a0 GFZ Budding Flower -0x04a 7 20 bus1a0 Berry Bush -0x04b 7 20 bus2a0 Bush -0x7f3 7 20 thzpa0 THZ Flower -0x00d 7 20 xms2a0 Palm Tree -0x051 7 20 garga1 Gargoyle -;wtraa0 through wtrha0 are empty sprites, formerly used for the below -0x7ea 7 20 dumba0 Ambient Water SFX 1A (Large) -0x7e8 7 20 dumba0 Ambient Water SFX 1B (Large) -0x7e7 7 20 dumba0 Ambient Water SFX 2A (Medium) -0x7fd 7 20 dumba0 Ambient Water SFX 2B (Medium) -0x053 7 20 dumba0 Ambient Water SFX 3A (Small) -0x7e3 7 20 dumba0 Ambient Water SFX 3B (Small) -0x7e9 7 20 dumba0 Ambient Water SFX 4A (Extra Large) -0x01b 7 20 dumba0 Ambient Water SFX 4B (Extra Large) -0x00e 7 20 dumba0 Random Ambience 1 -0x02b 7 20 dumba0 Random Ambience 2 -0x031 7 20 chana0 Hanging Chain -0x7d6 7 20 alrma0 THZ Alarm -0x7d1 7 20 fwr4a0 CEZ Flower -0x018 7 20 flama0 CEZ Torch -0x7d3 7 20 dissa0 Light Source (MAP92) -0x2710 8 20 gooma0 Overworld Goomba -0x2711 8 20 bgoma0 Underworld Goomba -0x2712 8 20 mus1a0 Bush (Short) -0x2713 8 20 mus2a0 Bush (Tall) -0x2714 8 20 toada0 Toad -0x2715 8 20 coina0 Coin -0x013 8 20 koopa0 King Bowser -0x00a 8 20 shlla0 Koopa Shell -0x00c 8 20 maxea0 Axe -0x032 8 20 ffwra0 Fire Flower -0x01d 8 20 pumaa0 Puma (Mario Fireball) -0x005 9 20 xms1a0 Pole -0x006 9 20 xms3a0 Snowman -0x00d 9 20 xms2a0 Candy Cane -0x054 11 20 bon1a0 5 Vertical Rings (Yellow Spring) -0x02c 11 20 bon1a0 5 Vertical Rings (Red Spring) -0x04c 11 20 bon1a0 5 Diagonal Rings (Yellow Spring) -0x04d 11 20 bon1a0 10 Diagonal Rings (Red Spring) -0x7de 11 20 bon1a0 Ring -0x045 11 20 homra0 Homing Ring -0xbbb 11 20 raila0 Rail Ring -0x01a 11 20 autra0 Automatic Ring -0x036 11 20 bomra0 Explosion Ring -0x050 11 20 infra0 Infinity Ring -0x138c 12 20 sprba0 Blue Spring -0x01c 12 20 sprya0 Yellow Spring (Up) -0x04f 12 20 sprra0 Red Spring (Up) -0x7df 12 20 yspra1 Yellow Spring (Diagonal Up) -0x026 12 20 rspra1 Red Spring (Diagonal Up) -0x014 12 20 ysuda1 Yellow Spring (Diagonal Down) -0x027 12 20 rsuda1 Red Spring (Diagonal Down) -0x041 12 20 sudya0 Yellow Spring (Down) -0x042 12 20 sudra0 Red Spring (Down) -0x01e 12 20 stemd0 THZ Gas Jet -0x020 12 20 fansa0 THZ Fan - -; ID used to classify linedefs -; Name textual description of class -; -; Note: When converting a sector to a door, the linedef types -; available are those in class number two. - -[LineDefs.Classes] -0x001 *Important -0x002 Floor Over Floor -0x003 Linedef Executor -0x004 Plane Movement -0x005 Lighting -0x006 Scroll Effects -0x007 Pushers -0x008 Miscellaneous - -; ID -; class -; codes -; n does NOT require a tag number -; W walk-over activation -; S switch (triggered by player use) -; G gunfire (pistol, shotgun, chaingun) cross or hit line -; 1 the line may be activated once only -; R potentially repeatable activation -; & affected sectors locked out from further changes -; m monster actions can activate the line's effect -; speed -; (slow=1, medium = 2, fast = 3, turbo = 4) -; time -; texture changes -; description - -[LineDefs.Types] -; Commonly used types -0x019 1 - - - - Floor Over Floor: Solid, Opaque, Shadowcasting -0x02d 1 - - - - Floor Over Floor: Water, Translucent -0x010 1 - - - - Colormap - -0x001 2 - - - - Crumbling (No Respawn), Floating, Bobbing -0x002 4 - - - - Continuous Floor/Ceiling Mover -0x003 4 - - - - Continuous Floor Mover -0x004 4 - - - - Continuous Ceiling Mover -0x005 5 - - - - Ceiling Lighting -0x006 4 - - - - Continuous Two-Speed Floor/Ceiling Mover -0x007 4 - - - - Continuous Two-Speed Floor Mover -0x008 4 - - - - Continuous Two-Speed Ceiling Mover -0x009 3 - - - - Trigger Linedef Executor (Race Only, Once) -0x00a 3 - - - - Trigger Linedef Executor (CTF Red Team, Continuous) -0x00b 3 - - - - Trigger Linedef Executor (CTF Red Team, Each Time) -0x00c 3 - - - - Trigger Linedef Executor (CTF Blue Team, Continuous) -0x00d 3 - - - - Trigger Linedef Executor (CTF Blue Team, Each Time) - -0x00f 3 - - - - Trigger Linedef Executor (No More Enemies, Once) -0x010 5 - - - - Colormap - -0x012 8 - - - - Zoom Tube Parameters -0x013 3 - - - - Trigger Linedef Executor (Character Ability, Continuous) -0x014 3 - - - - Trigger Linedef Executor (Character Ability, Each Time) -0x015 3 - - - - Trigger Linedef Executor (Character Ability, Once) - -0x018 4 - - - - Instant Ceiling Raise -0x019 2 - - - - Solid, Opaque, Shadowcasting -0x01a 4 - - - - Instant Floor Lower - -0x021 2 - - - - Solid, Opaque, Non-Shadowcasting -0x022 2 - - - - Floating, Bobbing -0x023 2 - - - - Crumbling (No Respawn) -0x024 2 - - - - Crumbling (Respawn) -0x025 2 - - - - Crumbling (Respawn), Floating -0x026 2 - - - - Bobbing (Air) -0x027 2 - - - - Crumbling (Respawn), Floating, Bobbing -0x028 2 - - - - Crumbling (Respawn), Bobbing (Air) -0x029 2 - - - - Mario Block -0x02a 2 - - - - Crumbling (No Respawn), Floating -0x02b 4 - - - - Crusher 1 (Ceiling to Floor) -0x02c 2 - - - - Solid, Translucent -0x02d 2 - - - - Water, Translucent -0x02e 2 - - - - Fog Block -0x02f 2 - - - - Half Light Block -0x030 2 - - - - Water, Opaque -0x031 2 - - - - Light Block -0x032 4 - - - - Crusher 2 (Floor to Ceiling) -0x033 2 - - - - Solid, No Sides -0x034 2 - - - - Intangible, Translucent -0x035 2 - - - - Laser Block -0x036 2 - - - - Thwomp Block -0x037 2 - - - - Bustable Block -0x038 2 - - - - Quicksand Block -0x039 2 - - - - Solid, Invisible -0x03a 2 - - - - Intangible, Invisible -0x03b 2 - - - - Intangible from Bottom, Opaque -0x03c 5 - - - - Adjustable Pulsating Light -0x03d 5 - - - - Adjustable Flickering Light -0x03e 2 - - - - Intangible, Opaque -0x03f 8 - - - - Camera Scanner -0x040 8 - - - - Per-Sector Gravity -0x041 8 - - - - Speed Pad -0x042 8 - - - - Flat Alignment -0x043 2 - - - - Intangible, Sides Only -0x044 2 - - - - Adjustable Bobbing (Air) -0x045 2 - - - - Solid, Sides Only -0x046 8 - - - - Ideya Time Modifier -0x047 8 - - - - Custom Exit -0x048 2 - - - - Reverse Adjustable Bobbing (Air) -0x049 8 - - - - Disable Linedef -0x04a 2 - - - - Water, Translucent, No Sides -0x04b 2 - - - - Water, Opaque, No Sides -0x04c 2 - - - - Shatter Block -0x04d 2 - - - - Intangible from Bottom, Translucent, No Sides -0x04e 2 - - - - Spin Bust Block -0x04f 2 - - - - Crumbling (Respawn) -0x050 2 - - - - Crumbling (No Respawn) -0x051 2 - - - - Intangible from Bottom, Translucent -0x052 2 - - - - Intangible from Bottom, Crumbling (Respawn), Translucent -0x053 2 - - - - Intangible from Bottom, Crumbling (No Respawn), Translucent -0x054 2 - - - - Spin Bust Block, Translucent -0x055 6 - - - - Scroll Wall First Side Opposite Direction -0x056 2 - - - - Shatter Block, Translucent -0x057 2 - - - - Custom -0x058 4 - - - - Continuously Falling Sector -0x059 2 - - - - Rising, Solid, Opaque, Shadowcasting -0x05a 2 - - - - Rising, Solid, Opaque, Non-shadowcasting -0x05b 2 - - - - Rising, Solid, Translucent -0x05c 2 - - - - Rising, Intangible from Bottom, Opaque -0x05d 2 - - - - Rising, Intangible from Bottom, Translucent -0x05e 2 - - - - Rising, Solid, Invisible -0x05f 3 - - - - Trigger Linedef Executor (Ring Count, Continuous) -0x060 3 - - - - Trigger Linedef Executor (Continuous) -0x061 3 - - - - Trigger Linedef Executor (Each Time) -0x062 3 - - - - Trigger Linedef Executor (Once) -0x063 3 - - - - Trigger Linedef Executor (Ring Count, Once) -0x064 6 - - - - Scroll Wall First Side Left -0x065 3 - - - - Set Tagged Sector's Floor Height/Pic -0x066 3 - - - - Set Tagged Sector's Ceiling Height/Pic -0x067 3 - - - - Set Tagged Sector's Light Level -0x068 3 - - - - Teleport Player to Tagged Sector -0x069 3 - - - - Change Music -0x06a 3 - - - - Move Tagged Sector's Floor -0x06b 3 - - - - Move Tagged Sector's Ceiling -0x06c 3 - - - - Lower Floor by Line -0x06d 3 - - - - Raise Floor by Line -0x06e 3 - - - - Lower Ceiling by Line -0x06f 3 - - - - Raise Ceiling by Line -0x070 3 - - - - Change Tagged Sector's Tag -0x071 3 - - - - Run Script -0x072 3 - - - - Change Front Sector's Tag -0x073 3 - - - - Play SFX -0x074 3 - - - - Stop Plane Movement -0x075 3 - - - - Fade Light Level -0x076 3 - - - - Stop Lighting Effect -0x077 3 - - - - Start Adjustable Fire Flicker -0x078 3 - - - - Start Adjustable Glowing Light -0x079 3 - - - - Cut-Away View -0x07a 3 - - - - Stop Object -0x07b 3 - - - - Change Sky -0x07c 3 - - - - Change Weather -0x07d 3 - - - - Change Object State -0x07e 3 - - - - Stop Object -0x07f 3 - - - - Award Score -0x080 3 - - - - Start Platform Movement -0x081 3 - - - - Crush Ceiling Once -0x082 3 - - - - Crush Floor Once -0x083 3 - - - - Crush Floor And Ceiling Once -0x084 3 - - - - Enable/Disable 2D Mode -0x085 3 - - - - Enable/Disable Gravity Flip -0x086 3 - - - - Award Power-Up -0x087 3 - - - - Change Plane Scroller Direction -0x088 3 - - - - Shatter FOF -0x089 3 - - - - Disable Player Control -0x08a 3 - - - - Change Object Size -0x08b 3 - - - - Change Tagged Linedef Textures -0x08c 3 - - - - Start Metal Sonic Race -0x08d 3 - - - - Unlockable Trigger -0x08e 3 - - - - Change Object Type State -0x08f 3 - - - - Call Lua Function -0x090 3 - - - - Earthquake -0x096 3 - - - - Execute Linedef Executor (from tag) -0x097 3 - - - - Execute Linedef Executor (random range) - -0x0c8 6 - - - - Disp Scroll Ceiling Texture and Carry Objects -0x0c9 6 - - - - Disp Carry Objects on Ceiling -0x0ca 6 - - - - Scroll Ceiling Texture and Carry Objects -0x0cb 6 - - - - Carry Objects on Ceiling -0x0cc 6 - - - - Acc Scroll Ceiling Texture and Carry Objects -0x0cd 6 - - - - Acc Carry Objects on Ceiling - -0x0d5 5 - - - - Floor Lighting -0x0d6 6 - - - - Acc Scroll Ceiling Texture -0x0d7 6 - - - - Acc Scroll Floor Texture -0x0d8 6 - - - - Acc Carry Objects on Floor -0x0d9 6 - - - - Acc Scroll Floor Texture and Carry Objects -0x0da 6 - - - - Acc Scroll Wall According to Linedef - -0x0df 8 - - - - Friction -0x0e0 7 - - - - Wind -0x0e1 7 - - - - Current -0x0e2 7 - - - - Boom Push/Pull Thing -0x0e3 7 - - - - Upwards Current -0x0e4 7 - - - - Downwards Current -0x0e5 7 - - - - Upwards Wind -0x0e6 7 - - - - Downwards Wind - -0x0e8 4 - - - - Activate Floating Platform -0x0e9 4 - - - - Activate Floating Platform (Adjustable Speed) - -0x0f2 8 - - - - Fake Floor - -0x0f5 6 - - - - Disp Scroll Ceiling Texture -0x0f6 6 - - - - Disp Scroll Floor Texture -0x0f7 6 - - - - Disp Carry Objects on Floor -0x0f8 6 - - - - Disp Scroll Floor Texture and Carry Objects -0x0f9 6 - - - - Disp Scroll Wall According to Linedef -0x0fa 6 - - - - Scroll Ceiling Texture -0x0fb 6 - - - - Scroll Floor Texture -0x0fc 6 - - - - Carry Objects on Floor -0x0fd 6 - - - - Scroll Floor Texture and Carry Objects -0x0fe 6 - - - - Scroll Wall According to Linedef -0x0ff 6 - - - - Scroll Texture by Offsets - -[Sectors.Types] -0x001 Blink (random) -0x002 Blink (1/2 second) -0x003 Blink (1 second) -0x004 Spikes -0x005 Death Pit (no camera modifications) -0x006 Space Countdown -0x007 Damage (Fire) -0x008 Light oscillates -0x009 Damage (Special Stage) -0x00a Instant Kill -0x00b Damage (Non-Elemental) -0x00c Blink (1 second synch) -0x00d Blink (1/2 second synch) -0x00e Bouncy Sector (FOF Control Only) - -0x010 Death Pit (camera modifications) -0x011 Light flickers like fire -0x012 Damage (Electrical) - -0x021 Special Stage Goal - -0x100 Ice/Sludge - -0x200 Wind/Current - -0x207 Damage (Fire) and Current - -0x29a Egg Trap Capsule - -0x2b2 Button 1 (Open Door A/700 B/701) -0x2b3 Button 2 (Open Door A/702 B/703) -0x2b4 Button 3 (Open Door A/704 B/705) -0x2b5 Button 4 (Open Door A/706 B/707) -0x2b6 Button 5 (Open Door A/708 B/709) -0x2b7 Button 6 (Open Door A/710 B/711) -0x2b8 Button 7 (Open Door A/712 B/713) -0x2b9 Button 8 (Open Door A/714 B/715) -0x2ba Button 9 (Open Door A/716 B/717) -0x2bb Button 10 (Open Door A/718 B/719) -0x2bc Button 11 (Open Door A/720 B/721) -0x2bd Button 12 (Open Door A/722 B/723) -0x2be Button 13 (Open Door A/724 B/725) -0x2bf Button 14 (Open Door A/726 B/727) -0x2c0 Button 15 (Open Door A/728 B/729) -0x2c1 Button 16 (Open Door A/730 B/731) -0x2c2 Button 17 (Open Door A/732 B/733) -0x2c3 Button 18 (Open Door A/734 B/735) -0x2c4 Button 19 (Open Door A/736 B/737) -0x2c5 Button 20 (Open Door A/738 B/739) -0x2c6 Button 21 (THZ2 A/740 B/741 D/742) -0x2c7 Close Door Blazing (Tag 743) - -0x300 Ice/Sludge and Wind/Current - -0x3c7 Linedef Executor (Emerald Check) -0x3c8 Linedef Executor (NiGHTS Mare) -0x3c9 Super Sonic Transform -0x3ca Check 3DFloors for Linedef Executor -0x3cb Linedef Executor (Pushable Objects) -0x3cc Linedef Executor (No Floor Touch, All Players) -0x3cd Linedef Executor (Floor Touch, All Players) -0x3ce Linedef Executor (No Floor Touch) -0x3cf Linedef Executor (Floor Touch) -0x3d0 Speed Pad (No Spin) -0x3d1 Speed Pad (Spin) -0x3d2 Ring Drainer (Floor Touch) -0x3d3 Spinner -0x3d4 Ring Drainer (No Floor Touch) -0x3d5 Raise Ceiling to Highest (Tag 744) -0x3d6 Exit Sector -0x3d7 Damage (Water) -0x3d8 Damage (Water) and Current -0x3d9 Conveyor Belt -0x3da THZ2 Slime Raise (B/712 S/713 P/714 D/715 S/716) -0x3db No Tag Zone -0x3dc CTF - Red Team Base -0x3dd CTF - Blue Team Base -0x3de Special Stage (Floor=Time) (Ceiling=Rings) -0x3df Custom Gravity -0x3e0 Ramp Sector -0x3e1 Starpost Activator -0x3e2 Finish Line - -0x3e4 Non-Ramp Sector -0x3e5 Fan Sector -0x3e6 Zoom Tube Start -0x3e7 Zoom Tube End - -0x5dc Bustable Block Sprite ROIA -0x5dd Bustable Block Sprite ROIB -0x5de Bustable Block Sprite ROIC -0x5df Bustable Block Sprite ROID -0x5e0 Bustable Block Sprite ROIE -0x5e1 Bustable Block Sprite ROIF -0x5e2 Bustable Block Sprite ROIG -0x5e3 Bustable Block Sprite ROIH -0x5e4 Bustable Block Sprite ROII -0x5e5 Bustable Block Sprite ROIJ -0x5e6 Bustable Block Sprite ROIK -0x5e7 Bustable Block Sprite ROIL -0x5e8 Bustable Block Sprite ROIM -0x5e9 Bustable Block Sprite ROIN -0x5ea Bustable Block Sprite ROIO -0x5eb Bustable Block Sprite ROIP diff --git a/extras/conf/srb2.ygd b/extras/conf/srb2.ygd deleted file mode 100644 index 4d93076b8..000000000 --- a/extras/conf/srb2.ygd +++ /dev/null @@ -1,539 +0,0 @@ -# Yadex game definition file version 4 -# -# srb2.ygd -# Yadex Game Definitions for Sonic Robo Blast 2 -# See Yadex's doc/ygd.html for the specs. -# - -# File made by Alam_GBC. -# Updated by Graue, 2006-06-19 - -# Yadex has only a few games like "doom2", etc. hardcoded into it. -# Rather than hack the code, since I don't expect to ever edit Doom 2, -# I went into /usr/local/share/games/yadex/1.7.0/ and renamed -# doom2.ygd to doom2_real.ygd, then installed this file as srb2.ygd, -# then made a hard link from doom2.ygd to srb2.ygd; that is: -# ln srb2.ygd /usr/local/share/games/yadex/1.7.0/doom2.ygd - -# If you do that, change "iwad2" in yadex.cfg to point to your copy of -# srb2.srb. - -# It's not the most beautiful thing to do, but it works. Also, Doom 2 -# is the default game, so this way you don't have to do anything -# special when starting Yadex. - -# I claim no copyright on this file. -- Graue - -level_format doom -level_name map01 -picture_format normal -sky_flat sky1 -texture_format normal -texture_lumps normal - -# -# Definition of linedef type groups -# Format is : ldtgroup -# - -ldtgroup e "Linedef Executor" -ldtgroup E "3D Floors" -ldtgroup A "Water" -ldtgroup t "Scroll Effects" -ldtgroup x "Misc." -ldtgroup L "Lighting" -ldtgroup l "Pushers" -ldtgroup P "Plane Movement" - -# -# Definition of linedef types -# Format is : ldt -# must not exceed 16 characters. -# - -# Linedef Executor -ldt 00009 e "Trigger(Race1)" "Trigger (Race, Once) (1.09)" -ldt 00010 e "Trigger(RedCont)" "Trigger (CTF Red Team, Continuous) (1.09)" -ldt 00011 e "Trigger(RedEach)" "Trigger (CTF Red Team, Once per Floor Touch) (1.09)" -ldt 00012 e "Trigger(BluCont)" "Trigger (CTF Blue Team, Continuous) (1.09)" -ldt 00013 e "Trigger(BluEach)" "Trigger (CTF Blue Team, Once per Floor Touch) (1.09)" -ldt 00015 e "Trigger(NoEnemy)" "Trigger (Once when no more enemies) (1.09)" -ldt 00019 e "Trigger(ChrCont)" "Trigger (Character Ability, Continuous) (1.09)" -ldt 00020 e "Trigger(ChrEach)" "Trigger (Character Ability, Once per Floor Touch) (1.09)" -ldt 00021 e "Trigger(Chr1)" "Trigger (Character Ability, Once) (1.09)" -ldt 00095 e "Trigger(RngCont)" "Trigger (Ring Count, Continuous) (1.09)" -ldt 00096 e "Trigger (Cont)" "Trigger (Continuous)" -ldt 00097 e "Trigger (Each)" "Trigger (Once per Floor Touch)" -ldt 00098 e "Trigger (1)" "Trigger (Once)" -ldt 00099 e "Trigger (Rng1)" "Trigger (Ring Count, Once) (1.09)" -ldt 00101 e "Set Floor" "Set Tagged Sector's Floor Height/Flat" -ldt 00102 e "Set Ceiling" "Set Tagged Sector's Ceiling Height/Flat" -ldt 00103 e "Set Light Level" "Set Tagged Sector's Light Level" -ldt 00104 e "Teleport to" "Teleport to Tagged Sector" -ldt 00105 e "Music Change" "Music Change" -ldt 00106 e "Move Floor by FS" "Move Floor by Front Sector (Length=Speed)" -ldt 00107 e "Move Ceil. by FS" "Move Ceiling by Front Sector (Length=Speed)" -ldt 00108 e "Lower Flr by Ld" "Lower Floor by Line (dx=speed, dy=amount)" -ldt 00109 e "Raise Flr by Ld" "Raise Floor by Line (dx=speed, dy=amount)" -ldt 00110 e "Lower Ceil by Ld" "Lower Ceiling by Line (dx=speed, dy=amount)" -ldt 00111 e "Raise Ceil by Ld" "Raise Ceiling by Line (dx=speed, dy=amount)" -ldt 00112 e "Change Clg/T Tag" "Change Calling Sector's Tag (Change Tagged Sector's Tag in 1.09)" -ldt 00113 e "Run Script" "Run Script" -ldt 00114 e "Change FS Tag" "Change Front Sector's Tag" -ldt 00115 e "Play SFX" "Play SFX" -ldt 00116 e "Stop Plane Move" "Stop Plane Movement" -ldt 00117 e "Fade Light to FS" "Fade Light Level to Front Sector (Length=Speed)" -ldt 00118 e "Stop Light FX" "Stop Lighting Effect" -ldt 00119 e "Start Fire Flckr" "Start Adjustable Fire Flicker" -ldt 00120 e "Start Pulsate" "Start Adjustable Pulsating Light" -ldt 00121 e "Cut-Away View" "Cut-Away View" -ldt 00122 e "Stop Object" "Stop Object" -ldt 00123 e "Change Sky" "Change Sky (1.09)" -ldt 00124 e "Change Weather" "Change Weather (1.09)" -ldt 00125 e "Change Obj State" "Change Object State (1.09)" -ldt 00126 e "Award Score" "Award Score (1.09)" -ldt 00127 e "Start Platf Mvmt" "Start Platform Movement" - -# 3D Floors/Blocks -ldt 00001 E "CrumBobFlt NoRet" "Crumbling Floating Bobbing FOF (Never Reappears)" -ldt 00025 E "FOFSoliOpaquShad" "FOF (Solid, Opaque, Shadows)" -ldt 00033 E "FOFSolOpaqNShado" "FOF (Solid, Opaque, No Shadows)" -ldt 00034 E "BobbingFOFWater" "Bobbing Platform (Water)" -ldt 00035 E "CrumblingFOFNRea" "Crumbling FOF (Never Reappears)" -ldt 00036 E "CrumblingFOFReap" "Crumbling FOF (Reappears)" -ldt 00037 E "CrumblingFOFRaps" "Crumbling Floating FOF (Reappears)" -ldt 00038 E "BobbingFOF(Air)" "Bobbing FOF (Air)" -ldt 00039 E "CrumBobbFOF(Rep)" "Crumbling Floating Bobbing FOF (Reappears)" -ldt 00040 E "CrumBobbFOF(Air)" "Crumbling Bobbing FOF (Air)" -ldt 00041 E "Mario Block" "Mario Block" -ldt 00042 E "CrumblingFOF(NR)" "Crumbling Floating FOF (Never Reappears)" -ldt 00044 E "FOFSolidTransluc" "FOF (Solid, Translucent)" -ldt 00046 E "Fog Block" "Fog Block" -ldt 00047 E "Light Block" "Light Block" -ldt 00049 E "2x Light Block" "Double Light Block" -ldt 00051 E "FOFSolid,NoSides" "FOF (Solid, No Sides)" -ldt 00052 E "FOFIntangTranslu" "FOF (Intangible, Translucent)" -ldt 00053 E "Laser Block" "Laser Block" -ldt 00054 E "Thwomp Block" "Thwomp Block" -ldt 00055 E "Bustable Block" "Bustable Block" -ldt 00056 E "Quicksand Block" "Quicksand Block" -ldt 00057 E "FOFSolidInv" "FOF (Solid, Invisible)" -ldt 00058 E "FOFIntangiInvisi" "FOF (Intangible, Invisible)" -ldt 00059 E "Platform" "Platform" -ldt 00062 E "FOFIntangibOpaqu" "FOF (Intangible, Opaque)" -ldt 00067 E "FOFIntaSidesOnly" "FOF (Intangible, Sides Only)" -#removed: ldt 00068 E "AdjBobbFOF(Air)" "Adjustable Bobbing FOF (Air)" -ldt 00069 E "FOFSoliSidesOnly" "FOF (Solid, Sides Only)" -#removed: ldt 00072 E "RevAdjBobFOFAir" "Reverse Adjustable Bobbing FOF (Air)" -ldt 00076 E "Shatter Block" "Shatter Block" -ldt 00077 E "Platf (Trnsl-NS)" "Platform (Translucent, No Sides)" -ldt 00078 E "Spin Bust Block" "Spin Bust Block" -ldt 00079 E "CrumblPlatf(Rep)" "Crumbling Platform (Reappears)" -ldt 00080 E "CrumblPlat(NRep)" "Crumbling Platform (Never Reappears)" -ldt 00081 E "Platform (Trnsl)" "Platform (Translucent)" -ldt 00082 E "CrmPlt(Trns,Rep)" "Crumbling Platform (Translucent, Reappears)" -ldt 00083 E "CrmPlt(Trs,NRep)" "Crumbling Platform (Translucent, Never Reappears)" -ldt 00084 E "SpinBust (Trnsl)" "Spin Bust Block (Translucent)" -ldt 00086 E "Shatter (Trnsl.)" "Shatter Block (Translucent)" -ldt 00087 E "Custom FOF" "Custom FOF (1.09)" -ldt 00089 E "Rising FOF Shado" "Rising FOF (Solid, Opaque, Shadows) (1.09)" -ldt 00090 E "Rising FOF NShad" "Rising FOF (Solid, Opaque, No Shadows) (1.09)" -ldt 00091 E "Rising FOF Trnsl" "Rising FOF (Translucent) (1.09)" -ldt 00092 E "Rising Plat Opaq" "Rising Platform (Opaque) (1.09)" -ldt 00093 E "Rising Plat Trsl" "Rising Platform (Translucent) (1.09)" -ldt 00094 E "Rising FOF SlInv" "Rising FOF (Solid, Invisible) (1.09)" - -# Water -ldt 00045 A "Water (Transl.)" "Water (Translucent)" -ldt 00048 A "Water (Opaque)" "Water (Opaque)" -ldt 00074 A "Water (Trnsl-NS)" "Water (Translucent, No Sides)" -ldt 00075 A "Water (Opaq-NS)" "Water (Opaque, No Sides)" - -# Scroll Effects -ldt 00085 t "Scr Wl Front Opp" "Scroll Wall First Side Opposite Direction" -ldt 00100 t "Scr Wl FrontLeft" "Scroll Wall First Side Left" -ldt 00202 t "Scr&Carry Ceil" "Scroll&Carry Things Sector Ceiling (FOF Conveyor)" -ldt 00203 t "Carry Ceiling" "Carry Things on Sector Ceiling (FOF Conveyor)" -ldt 00214 t "AccScr Ceiling" "Accel Scroll Sector's Ceiling" -ldt 00215 t "AccScr Floor" "Accel Scroll Sector's Floor" -ldt 00216 t "AccCarry Floor" "Accel Carry Things on Floor" -ldt 00217 t "AccScr&Carry Flr" "Accel Scroll Floor & Carry Things" -ldt 00218 t "AccScr Front" "Accel Scroll 1st Side Tagged Line" -ldt 00245 t "RemScr Ceiling" "Remote Scroll Sector's Ceiling" -ldt 00246 t "RemScr Floor" "Remote Scroll Sector's Floor" -ldt 00247 t "RemCarry Floor" "Remote Carry Things on Floor" -ldt 00248 t "RemScr&Carry Flr" "Remote Scroll Floor & Carry Things" -ldt 00249 t "RemScr Front" "Remote Scroll 1st Side Tagged Line" -ldt 00250 t "Scroll Ceiling" "Scroll Sector's Ceiling" -ldt 00251 t "Scroll Floor" "Scroll Sector's Floor" -ldt 00252 t "Carry on Floor" "Carry Things On Sector Floor" -ldt 00253 t "Scroll&Carry Flr" "Scroll&Carry Things Sector Floor" -ldt 00254 t "Scroll Front" "Scroll First Side of Tagged Line" -ldt 00255 t "Scroll by Offset" "Effect Scrolling From XY Offsets" - -# Misc. -ldt 00018 x "Zoom Tube Params" "Zoom Tube Parameters (1.09)" -ldt 00063 x "Camera Scanner" "Camera Scanner" -ldt 00064 x "Sector Gravity" "Per-Sector Gravity" -ldt 00065 x "Speed Pad" "Speed Pad" -ldt 00066 x "Flat Alignment" "Flat Alignment" -ldt 00070 x "IdeyaTimeModify " "Ideya Time Modifier" -ldt 00071 x "Custom Exit" "Custom Exit" -ldt 00073 x "Disable Linedef" "Disable Linedef (main game only)" -ldt 00223 x "Friction" "Friction (Ice>100, Sludge<100)" -ldt 00242 x "Fake Floor" "Fake Floor" - -# Lighting -ldt 00005 L "Ceiling Lighting" "Ceiling Lighting" -ldt 00016 L "Colormap" "Colormap" -ldt 00060 L "AdjPulsLight" "Adjustable Pulsating Light" -ldt 00061 L "AdjFlickLight" "Adjustable Flickering Light" -ldt 00213 L "Floor Lighting" "Floor Lighting" - -# Plane Movement -ldt 00002 P "ContMover F/C" "Continuous Floor/Ceiling Mover" -ldt 00003 P "ContMover Floor" "Continuous Floor Mover" -ldt 00004 P "ContMover Ceilng" "Continuous Ceiling Mover" -ldt 00006 P "Cont2Mover F/C" "Continuous 2-Speed Floor/Ceiling Mover" -ldt 00007 P "Cont2Mover Floor" "Continuous 2-Speed Floor Mover" -ldt 00008 P "Cont2Mover Ceilg" "Continuous 2-Speed Ceiling Mover" -ldt 00024 P "InstCeilingRaise" "Instant Ceiling Raise" -ldt 00026 P "InstFloorLower" "Instant Floor Lower" -ldt 00043 P "Crusher 1 (C2F)" "Crusher 1 (Ceiling to Floor)" -ldt 00050 P "Crusher 2 (F2C)" "Crusher 2 (Floor to Ceiling)" -ldt 00088 P "Continuous Fall" "Continuously Falling Sector (1.09)" -ldt 00232 P "FloatingPlatform" "Floating Platform" -ldt 00233 P "FloatPFAdjuSpeed" "Floating Platform Adjustable Speed" - -# Pushers -ldt 00224 l "Wind Force/Dir" "Wind Force/Direction" -ldt 00225 l "Water Force/Dir" "Water Current Force/Direction" -ldt 00226 l "Boom Push/Pull" "Boom Push/Pull Thing" -ldt 00227 l "Upwards Current" "Upwards Current" -ldt 00228 l "DownwardsCurrent" "Downwards Current" -ldt 00229 l "Upwards Wind" "Upwards Wind" -ldt 00230 l "Downwards Wind" "Downwards Wind" - -# -# Definition of sector types -# Format is : st -# must not exceed 14 characters. -# - -st 00000 "X Normal" "X Normal" -st 00001 "Blink random" "Blink (random)" -st 00002 "Blink halfsec" "Blink (1/2 second)" -st 00003 "Blink oneasec" "Blink (1 second)" -st 00004 "Spikes of Doom" "Spikes" -st 00005 "DeathPit (ncm)" "Death Pit (no camera modifications)" -st 00006 "SpaceCountdown" "Space Countdown" -st 00007 "Fire Damage" "Damage (Fire)" -st 00008 "Lightoscilates" "Light oscillates" -st 00009 "SS Damage" "Damage (Special Stage)" -st 00010 "Instant Kill" "Instant Kill" -st 00011 "Normal Damage" "Damage (Non-elemental)" -st 00012 "Blinks oneasec" "Blink (1 second synch)" -st 00013 "Blinks hafasec" "Blink (1/2 second synch)" -st 00014 "FOF Bouncy Con" "Bouncy Sector (FOF Control Only)" -st 00016 "DeathPit (wcm)" "Death Pit (camera modifications)" -st 00017 "Lightslikefire" "Light flickers like fire" - -st 00018 "Elec Damage" "Damage (Electrical)" - -st 00256 "Ice/Sludge" "Ice/Sludge" - -st 00512 "Wind/Current" "Wind/Current" - -st 00680 "EggCapsule But" "Egg Capsule (Button)" -st 00681 "EggCapsule Top" "Egg Capsule (Top)" -st 00682 "EggCapsule Bot" "Egg Capsule (Bottom)" -st 00683 "EggCapsule Cen" "Egg Capsule (Center)" - -st 00690 "Button 01" "Button 1 (Open Door A/700 B/701)" -st 00691 "Button 02" "Button 2 (Open Door A/702 B/703)" -st 00692 "Button 03" "Button 3 (Open Door A/704 B/705)" -st 00693 "Button 04" "Button 4 (Open Door A/706 B/707)" -st 00694 "Button 05" "Button 5 (Open Door A/708 B/709)" -st 00695 "Button 06" "Button 6 (Open Door A/710 B/711)" -st 00696 "Button 07" "Button 7 (Open Door A/712 B/713)" -st 00697 "Button 08" "Button 8 (Open Door A/714 B/715)" -st 00698 "Button 09" "Button 9 (Open Door A/716 B/717)" -st 00699 "Button 10" "Button 10 (Open Door A/718 B/719)" -st 00700 "Button 11" "Button 11 (Open Door A/720 B/721)" -st 00701 "Button 12" "Button 12 (Open Door A/722 B/723)" -st 00702 "Button 13" "Button 13 (Open Door A/724 B/725)" -st 00703 "Button 14" "Button 14 (Open Door A/726 B/727)" -st 00704 "Button 15" "Button 15 (Open Door A/728 B/729)" -st 00705 "Button 16" "Button 16 (Open Door A/730 B/731)" -st 00706 "Button 17" "Button 17 (Open Door A/732 B/733)" -st 00707 "Button 18" "Button 18 (Open Door A/734 B/735)" -st 00708 "Button 19" "Button 19 (Open Door A/736 B/737)" -st 00709 "Button 20" "Button 20 (Open Door A/738 B/739)" -st 00710 "Button 21" "Button 21 (THZ2 A/740 B/741 D/742)" - -st 00768 "IceSluWindCurr" "Ice/Sludge and Wind/Current" - -st 00974 "Linedefx (NFT)" "Linedef Executor (No Floor Touch)" -st 00975 "Linedefx (WFT)" "Linedef Executor (Floor Touch)" -st 00976 "Speed Pad (NS)" "Speed Pad (No Spin)" -st 00977 "Speed Pad (WS)" "Speed Pad (Spin)" -st 00978 "Ring Drainer" "Ring Drainer" -st 00979 "Spinner" "Spinner" -st 00980 "Ring Drain NFT" "Ring Drainer (No Floor Touch)" # 1.09? -st 00981 "RaiseCeilHghst" "Raise Ceiling to Highest (tag 744) (obsolete)" -st 00982 "Exit" "Exit Sector" -st 00983 "Water Damage" "Damage (Water)" -st 00984 "WaterDm&Curent" "Damage (Water) and Current" -st 00985 "ConveyorBelt" "Conveyor Belt" -st 00986 "Slime Raise" "THZ2 Slime Raise (B/712 W/713 P/714 D/715 S/716)" -st 00987 "No Tag Zone" "No Tag Zone" -st 00988 "CTF - Red" "CTF - Red Team Base" -st 00989 "CTF - Bule" "CTF - Blue Team Base" -st 00990 "SS Control" "Special Stage (Floor=Time) (Ceiling=Rings)" -st 00991 "Custom Gravity" "Custom Gravity" -st 00992 "Ramp" "Ramp Sector (Stairs)" -st 00993 "Starpost Actor" "Starpost Activator" -st 00994 "Hockey - Red" "Hockey - Red Team Goal (Finish Line in 1.09)" -st 00995 "Hockey - Blue" "Hockey - Blue Team Goal (not in 1.09)" -st 00996 "Non-Ramp" "Non-Ramp Sector" -st 00997 "Fan Sector" "Fan Sector" -st 00998 "Zoom Tube Strt" "Zoom Tube Start (1.09)" -st 00999 "Zoom Tube End" "Zoom Tube End (1.09)" -st 01500 "BustSprt ROIA" "Bustable Block Sprite ROIA (1.09)" -st 01501 "BustSprt ROIB" "Bustable Block Sprite ROIB (1.09)" -st 01502 "BustSprt ROIC" "Bustable Block Sprite ROIC (1.09)" -st 01503 "BustSprt ROID" "Bustable Block Sprite ROID (1.09)" -st 01504 "BustSprt ROIE" "Bustable Block Sprite ROIE (1.09)" -st 01505 "BustSprt ROIF" "Bustable Block Sprite ROIF (1.09)" -st 01506 "BustSprt ROIG" "Bustable Block Sprite ROIG (1.09)" -st 01507 "BustSprt ROIH" "Bustable Block Sprite ROIH (1.09)" -st 01508 "BustSprt ROII" "Bustable Block Sprite ROII (1.09)" -st 01509 "BustSprt ROIJ" "Bustable Block Sprite ROIJ (1.09)" -st 01510 "BustSprt ROIK" "Bustable Block Sprite ROIK (1.09)" -st 01511 "BustSprt ROIL" "Bustable Block Sprite ROIL (1.09)" -st 01512 "BustSprt ROIM" "Bustable Block Sprite ROIM (1.09)" -st 01513 "BustSprt ROIN" "Bustable Block Sprite ROIN (1.09)" -st 01514 "BustSprt ROIO" "Bustable Block Sprite ROIO (1.09)" -st 01515 "BustSprt ROIP" "Bustable Block Sprite ROIP (1.09)" - -# -# Definition of thing groups -# Format is : thinggroup -# - -thinggroup b rgb:f/f/f "Starts" -thinggroup e rgb:f/0/0 "Enemies" -thinggroup n rgb:f/b/0 "Nights Things" -thinggroup p rgb:0/b/b "Power-Up Monitors" -thinggroup o rgb:b/0/c "Misc." -thinggroup d rgb:b/b/b "Scenery" -thinggroup m rgb:f/f/0 "Mario" -thinggroup c rgb:f/b/c "Christmas" -thinggroup r rgb:0/0/f "Rings" -thinggroup s rgb:0/c/0 "Springs and Such" - -# -# Definition of things -# Format is : -# thing [] -# must not exceed 19 characters. s for see-thur -# - -# FIXME: replace dissa0 and dumba0 with sprites that are really there - -# FIXME: replace start images of ndrna1 with something better. -# ndrna1 is really the nights drone -#thig 00000 g s ## " " ?????# -thing 00001 b - 32 "Player 01 Start" ndrna1 -thing 00002 b - 32 "Player 02 Start" ndrna1 -thing 00003 b - 32 "Player 03 Start" ndrna1 -thing 00004 b - 32 "Player 04 Start" ndrna1 -thing 04001 b - 32 "Player 05 Start" ndrna1 -thing 04002 b - 32 "Player 06 Start" ndrna1 -thing 04003 b - 32 "Player 07 Start" ndrna1 -thing 04004 b - 32 "Player 08 Start" ndrna1 -thing 04005 b - 32 "Player 09 Start" ndrna1 -thing 04006 b - 32 "Player 10 Start" ndrna1 -thing 04007 b - 32 "Player 11 Start" ndrna1 -thing 04008 b - 32 "Player 12 Start" ndrna1 -thing 04009 b - 32 "Player 13 Start" ndrna1 -thing 04010 b - 32 "Player 14 Start" ndrna1 -thing 04011 b - 32 "Player 15 Start" ndrna1 -thing 04012 b - 32 "Player 16 Start" ndrna1 -thing 04013 b - 32 "Player 17 Start" ndrna1 -thing 04014 b - 32 "Player 18 Start" ndrna1 -thing 04015 b - 32 "Player 19 Start" ndrna1 -thing 04016 b - 32 "Player 20 Start" ndrna1 -thing 04017 b - 32 "Player 21 Start" ndrna1 -thing 04018 b - 32 "Player 22 Start" ndrna1 -thing 04019 b - 32 "Player 23 Start" ndrna1 -thing 04020 b - 32 "Player 24 Start" ndrna1 -thing 04021 b - 32 "Player 25 Start" ndrna1 -thing 04022 b - 32 "Player 26 Start" ndrna1 -thing 04023 b - 32 "Player 27 Start" ndrna1 -thing 04024 b - 32 "Player 28 Start" ndrna1 -thing 04025 b - 32 "Player 29 Start" ndrna1 -thing 04026 b - 32 "Player 30 Start" ndrna1 -thing 04027 b - 32 "Player 31 Start" ndrna1 -thing 04028 b - 32 "Player 32 Start" ndrna1 -thing 00087 b - 32 "CTF Red Team Start" ndrna1 -thing 00089 b - 32 "CTF Blue Team Start" ndrna1 -thing 00011 b - 32 "Deathmatch Start" ndrna1 -#thig 00000 g s ## " " ?????# - -#thig 00000 g s ## " " ?????# -thing 00009 e - 40 "Crawla (Red)" sposa1 -thing 03004 e - 40 "Crawla (Blue)" possa1 -thing 03005 e - 40 "Jetty-Syn Bomber" jetba1 -thing 00022 e - 40 "Jetty-Syn Gunner" jetga1 -thing 00058 e - 40 "Robofish (tm)" fisha0 -thing 00071 e - 40 "Deton" detna1 -thing 00056 e - 40 "Skim" skima0 -thing 05005 e - 40 "Buzz (Yellow)" buzza0 -thing 05006 e - 40 "Buzz (Red)" rbuza0 -thing 02004 e - 40 "THZ Turret" treta1 -thing 00042 e - 40 "Popup Turret" turre1 -thing 00016 e - 80 "Egg Mobile (Boss 1)" eggma1 -thing 01008 e - 80 "Egg Slimer (Boss 2)" eggna1 -thing 00021 e - 40 "Crawla Commander" ccoma1 -thing 00008 e s 20 "ChaosModeEnemySpawn" tfogi0 -#thig 00000 g s ## " " ?????# - -#thig 00000 g s ## " " ?????# -thing 00052 n s 20 "1024 Axis" dissa0 -thing 00053 n s 20 "512 Axis" dissa0 -thing 00059 n s 20 "2048 Axis" dissa0 -thing 00062 n s 20 "1024 Axis(Inverted)" dissa0 -thing 00015 n s 20 "512 Axis (Inverted)" dissa0 -thing 00045 n s 20 "2048 Axis(Inverted)" dissa0 -thing 00061 n s 20 "Axis Transfer" dissa0 -thing 00046 n s 20 "Axis Transfer Closest" dissa0 -thing 00055 n s 20 "Axis Transfer LastToFirst" dissa0 -thing 00060 n - 20 "Ideya Drone" ndrna1 -thing 00057 n - 20 "Hoop" hoopa0 -thing 00047 n - 20 "Circle of Rings" bon1a0 -thing 02007 n - 20 "Circle ofRings(Big)" bon1a0 -thing 02048 n - 20 "Circle ofWing Logos" nwnga0 -thing 02010 n - 20 "CircleofWingLogos-B" nwnga0 -thing 02046 n - 20 "CircleofRings&Wings" nwnga0 -thing 02047 n - 20 "CirleofRngs&Wings-B" nwnga0 -thing 00037 n - 20 "Wing Logo" nwnga0 -thing 00082 n s 20 "AxisTrnsferCodtion" dissa0 -thing 00085 n s 20 "AxisTrnsferCodtion2" dissa0 -thing 03007 n - 20 "Super Loop" npraa0 -thing 03008 n - 20 "Drill Refill" nprba0 -thing 03009 n - 20 "Helper" nprca0 -#thig 00000 g s ## " " ?????# - -#thig 00000 g s ## " " ?????# -thing 00025 p - 20 "Super Sneakers" shtva0 -thing 00035 p - 20 "Basic/WhirlShield" bltva0 -thing 00041 p - 20 "Extra Life" prupa0 -thing 00048 p - 20 "Attraction Shield" yltva0 -thing 02002 p - 20 "Inferno Shield" rdtva0 -thing 02018 p - 20 "Armageddon Shield" bktva0 -thing 02022 p - 20 "Invincibility" pinva0 -thing 02028 p - 20 "Liquid Shield" grtva0 -thing 02011 p - 20 "SuperRing(10 Rings)" srbxa0 -thing 02012 p - 20 "SilverRing(25Rings)" grbxa0 -thing 00078 p - 20 "Teleporter" mixua0 -thing 02005 p - 20 "Eggman" eggba0 -thing 03000 p - 20 "Random" quesa0 -#thig 00000 g s ## " " ?????# - -#thig 00000 g s ## " " ?????# -thing 00031 o - 20 "CTF Flag (Red)" rflga0 -thing 00034 o - 20 "CTF Flag (Blue)" bflga0 -thing 02013 o - 20 "Special Stage Token" tokea0 -thing 00086 o - 20 "End Level Sign" signd0 -thing 00033 o - 20 "Air Bubble Patch" bubla0 -thing 00064 o - 20 "Emerald Hunt Place1" emera0 -thing 03002 o - 20 "Emerald Hunt Place2" emera0 -thing 03001 o - 20 "Emerald Hunt Place3" emera0 -thing 03006 o - 20 "Star Post" stpta0 -thing 05001 o s 20 "Push" ppsha0 -thing 05002 o s 20 "Pull" pplla0 -thing 05003 o s 20 "TeleportDestination" dissa0 -thing 05007 o s 20 "Cut-Away View Thing" dissa0 -thing 00067 o - 20 "Ceiling Spike" dspka0 -thing 00068 o - 20 "Floor Spike" uspka0 -thing 00023 o - 20 "Spikeball" spika0 -thing 00017 o s 20 "Boss Flypoint" dissa0 -thing 02049 o s 20 "Egg Capsule Center" dissa0 -thing 00051 o - 20 "Laser" lasra0 -thing 00018 o - 20 "ZoomTubeWaypoint109" dissa0 -thing 00420 o - 20 "Emerald 1 (Green)" emmya0 -thing 00421 o - 20 "Emerald 2 (Orange)" emmyb0 -thing 00422 o - 20 "Emerald 3 (Pink)" emmyc0 -thing 00423 o - 20 "Emerald 4 (Blue)" emmyd0 -thing 00424 o - 20 "Emerald 5 (Red)" emmye0 -thing 00425 o - 20 "Emerald 6 (LtBlue)" emmyf0 -thing 00426 o - 20 "Emerald 7 (Gray)" emmyg0 -# FIXME: add correct sprite for this emerald -thing 00427 o - 20 "Emerald 8 (Master)" dissa0 - -#thig 00000 g s ## " " ?????# -thing 00036 d - 20 "GFZ Flower (Normal)" fwr1b0 -thing 00070 d - 20 "GFZ Sunflower" fwr2a0 -thing 00073 d - 20 "GFZ Budding Flower" fwr3a0 -thing 00074 d - 20 "Berry Bush" bus1a0 -thing 00075 d - 20 "Bush" bus2a0 -thing 02035 d - 20 "THZ Flower" thzpa0 -thing 00081 d - 20 "Gargoyle" garga1 -thing 02026 d s 20 "AmbientWaterSFX1A-L" dumba0 -thing 02024 d s 20 "AmbientWaterSFX1B-L" dumba0 -thing 02025 d s 20 "AmbientWaterSFX2A-M" dumba0 -thing 02045 d s 20 "AmbientWaterSFX2B-M" dumba0 -thing 00083 d s 20 "AmbientWaterSFX3A-S" dumba0 -thing 02019 d s 20 "AmbientWaterSFX3B-S" dumba0 -thing 02025 d s 20 "AmbientWaterSFX4A-E" dumba0 -thing 00027 d s 20 "AmbientWaterSFX4B-E" dumba0 -thing 00014 d s 20 "Random Ambience 1" dumba0 -thing 00043 d s 20 "Random Ambience 2" dumba0 -thing 00049 d - 20 "Hanging Chain" chana0 -thing 02006 d - 20 "THZ Alarm" alrma0 -thing 02001 d - 20 "CEZ Flower" fwr4a0 -thing 00024 d - 20 "CEZ Torch" flama0 -thing 02003 d s 20 "LightSource (MAP92)" dissa0 -#thig 00000 g s ## " " ?????# - -#thig 00000 g s ## " " ?????# -thing 100000 m - 20 "Overworld Goomba" gooma0 -thing 100001 m - 20 "Underworld Goomba" bgoma0 -thing 100002 m - 20 "Bush (Short)" mus1a0 -thing 100003 m - 20 "Bush (Tall)" mus2a0 -thing 100004 m - 20 "Toad" toada0 -thing 100005 m - 20 "Coin" coina0 -thing 00019 m - 20 "King Bowser" koopa0 -thing 00010 m - 20 "Koopa Shell" shlla0 -thing 00012 m - 20 "Axe" maxea0 -thing 00050 m - 20 "Fire Flower" ffwra0 -thing 00029 m - 20 "Puma(MarioFireball)" pumaa0 -#thig 00000 g s ## " " ?????# - -#thig 00000 g s ## " " ?????# -thing 00005 c - 20 "Pole" xms1a0 -thing 00006 c - 20 "Snowman" xms3a0 -thing 00013 c - 20 "Candy Cane" xms2a0 -thing 00084 r - 20 "5VerticalRings-YwSg" bon1a0 -thing 00044 r - 20 "5VerticalRings-RdSg" bon1a0 -thing 00076 r - 20 "5DiagonalRings-YwSg" bon1a0 -thing 00077 r - 20 "10DiagonalRings-RSg" bon1a0 -thing 02014 r - 20 "Ring" bon1a0 -thing 00069 r - 20 "Homing Ring" homra0 -thing 03003 r - 20 "Rail Ring" raila0 -thing 00026 r - 20 "Automatic Ring" autra0 -thing 00054 r - 20 "Explosion Ring" bomra0 -thing 00080 r - 20 "Infinity Ring" infra0 -thing 00028 s - 20 "Yellow Spring (Up)" sprya0 -thing 00079 s - 20 "Red Spring (Up)" sprra0 -thing 02015 s - 20 "Yellow Spring (DU)" yspra1 -thing 00038 s - 20 "Red Spring (DU)" rspra1 -thing 00020 s - 20 "Yellow Spring (DD)" ysuda1 -thing 00039 s - 20 "Red Spring (DD)" rsuda1 -thing 00065 s - 20 "Yellow Spring (Dn)" sudya0 -thing 00066 s - 20 "Red Spring (Dn)" sudra0 -thing 05004 s - 20 "Blue Spring" sprba0 -thing 00030 s - 20 "THZ Gas Jet" stemd0 -thing 00032 s - 20 "THZ Fan" fansa0 -#thig 00000 g s ## " " ?????# diff --git a/extras/conf/srb2_db.cfg b/extras/conf/srb2_db.cfg deleted file mode 100644 index cad786472..000000000 --- a/extras/conf/srb2_db.cfg +++ /dev/null @@ -1,1559 +0,0 @@ -/*******************************************************\ - - XODE Multimedia Doom Builder - - Game Configuration for SRB2 version 2.0 - - Original CFG by Kristos - - Edited by Shadow Hog to eliminate one NASTY map header-eliminating bug - - Edited further by ST218 to make more organized - - Edited by Foxboy to show thing sprite previews and to update it for srb2 1.09.2 and to finally make the linedef and sector types to have the same name as the WA config. - - Edited by JJames19119 to fix parse errors, thing and linedef names, fix borked lindef categories, add the missing PASSUSE - linedef flag and put bitset flags for the lazy :P - - Edited by SRB2-Playah to make Things visable in 3D Mode, add Mario section because I think it'd be more organized, changed - a few names, put in a list of Color Values in the Things section of this CFG, and to put it large lines to make it easier - to find stuff in the CFG and thusly, easier to edit. - Dang, this was just edited to heck, wasn't it? :P - This CFG is best viewed with size 8 font, 1024x768 screen resolution, maximized. - -\*******************************************************/ - -// This is required to prevent accedential use of a different configuration -type = "Doom Builder Game Configuration"; - -// This is the title to show for this game -game = "Sonic Robo Blast 2"; - -// Map format determines the way the map will be loaded -mapformat = 1; - -// No generalized types -generalizedlinedefs = 0; -generalizedsectors = 0; - -// Thing number for start position in 3D Mode -start3dmode = 32000; - -// Load textures/flats by default from this file -texturesfile = ""; - -// Default lump name for new map -defaultlumpname = "MAP01"; - -// Default flags for first new thing -defaulthingflags = 1; - -/* -TEXTURES AND FLAT SOURCES---------------------------------------------------------------------------------------------------- -This tells Doom Builder where to find the information for textures -and flats in the IWAD file, Addition WAD file and Map WAD file. - -Start and end lumps must be given in a structure (of which the -key name doesnt matter) and any textures or flats in between them -are loaded in either the textures category or flats category. - -For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. -*/ - -// Texture sources -textures -{ -} - -// Flat sources -flats -{ - standard1 - { - start = "F_START"; - end = "F_END"; - } - - standard2 - { - start = "FF_START"; - end = "FF_END"; - } - - standard3 - { - start = "FF_START"; - end = "F_END"; - } - - standard4 - { - start = "F_START"; - end = "FF_END"; - } -} - -/* -TEXTURES AND FLATS FILTERING------------------------------------------------------------------------------------------------- -This allows you to filter textures and flats so that you only see the -textures/flats listed that you prefer to use. - -The key name doesnt matter here, only the values. You can use -the following wildcards in values to specify ranges: - -? = Any character -* = Zero or more characters -# = Any numeric digit -[abc...] = Any of these characters that are between brackets -[!abc..] = Not any of these characters that are between brackets -*/ - -// List these textures... -texturesfilter -{ - all_textures = "*"; -} - -// But do not list these textures... -notexturesfilter -{ - none = ""; -} - -// List these flats... -flatsfilter -{ - all_flats = "*"; -} - -// But do not list these flats... -noflatsfilter -{ - none = ""; -} - -/* -GAME DETECT PATTERN---------------------------------------------------------------------------------------------------------- -Used to guess the game for which a WAD file is made. - -1 = One of these lumps must exist -2 = None of these lumps must exist -3 = All of these lumps must exist -*/ -gamedetect -{ - EXTENDED = 2; - BEHAVIOR = 2; - E1M1 = 2; E1M2 = 2; E1M3 = 2; E1M4 = 2; E1M5 = 2; E1M6 = 2; E1M7 = 2; E1M8 = 2; E1M9 = 2; - E2M1 = 2; E2M2 = 2; E2M3 = 2; E2M4 = 2; E2M5 = 2; E2M6 = 2; E2M7 = 2; E2M8 = 2; E2M9 = 2; - E3M1 = 2; E3M2 = 2; E3M3 = 2; E3M4 = 2; E3M5 = 2; E3M6 = 2; E3M7 = 2; E3M8 = 2; E3M9 = 2; - E4M1 = 2; E4M2 = 2; E4M3 = 2; E4M4 = 2; E4M5 = 2; E4M6 = 2; E4M7 = 2; E4M8 = 2; E4M9 = 2; - MAP01 = 1; MAP02 = 1; MAP03 = 1; MAP04 = 1; MAP05 = 1; MAP06 = 1; MAP07 = 1; MAP08 = 1; MAP09 = 1; MAP10 = 1; - MAP11 = 1; MAP12 = 1; MAP13 = 1; MAP14 = 1; MAP15 = 1; MAP16 = 1; MAP17 = 1; MAP18 = 1; MAP19 = 1; MAP20 = 1; - MAP21 = 1; MAP22 = 1; MAP23 = 1; MAP24 = 1; MAP25 = 1; MAP26 = 1; MAP27 = 1; MAP28 = 1; MAP29 = 1; MAP30 = 1; - MAP31 = 1; MAP32 = 1; MAP33 = 1; MAP34 = 1; MAP35 = 1; MAP36 = 1; MAP37 = 1; MAP38 = 1; MAP39 = 1; MAP40 = 1; - MAP41 = 1; MAP42 = 1; MAP43 = 1; MAP44 = 1; MAP45 = 1; MAP46 = 1; MAP47 = 1; MAP48 = 1; MAP49 = 1; MAP50 = 1; - MAP51 = 1; MAP52 = 1; MAP53 = 1; MAP54 = 1; MAP55 = 1; MAP56 = 1; MAP57 = 1; MAP58 = 1; MAP59 = 1; MAP60 = 1; - MAP61 = 1; MAP62 = 1; MAP63 = 1; MAP64 = 1; MAP65 = 1; MAP66 = 1; MAP67 = 1; MAP68 = 1; MAP69 = 1; MAP70 = 1; - MAP71 = 1; MAP72 = 1; MAP73 = 1; MAP74 = 1; MAP75 = 1; MAP76 = 1; MAP77 = 1; MAP78 = 1; MAP79 = 1; MAP80 = 1; - MAP81 = 1; MAP82 = 1; MAP83 = 1; MAP84 = 1; MAP85 = 1; MAP86 = 1; MAP87 = 1; MAP88 = 1; MAP89 = 1; MAP90 = 1; - MAP91 = 1; MAP92 = 1; MAP93 = 1; MAP94 = 1; MAP95 = 1; MAP96 = 1; MAP97 = 1; MAP98 = 1; MAP99 = 1; -} - -/* -MAP LUMP NAMES--------------------------------------------------------------------------------------------------------------- -Map lumps are loaded with the map as long as they are right after each other. When the editor -meets a lump which is not defined in this list (or defined as 0) it will stop loading right there. - -The order of items defines the order in which lumps will be written to WAD file on save. -The value (flags) of items determines what the editor should do with it. -You should never mess with value 4, because it may result in incorrect map builds. - -1 = Map lump required -2 = Map lump which must be respected -4 = Lump generated by node builder -8 = Lump allowed to be empty after nodebuilding -4096 = Map lump which can be edited as Text -8192 = Map lump which can be edited as ACS -12288 = Map lump which can be edited as MAPINFO -16384 = Map lump which can be edited as DEHACKED -*/ - -maplumpnames -{ - THINGS = 13; - LINEDEFS = 5; - SIDEDEFS = 5; - VERTEXES = 5; - SEGS = 4; - SSECTORS = 4; - NODES = 4; - SECTORS = 5; - REJECT = 4; - BLOCKMAP = 4; - MAINCFG = 2; - // Here it is... all 1035 map headers, all to be "respected" by DoomBuilder... - MAP01D = 4098; MAP02D = 4098; MAP03D = 4098; MAP04D = 4098; MAP05D = 4098; MAP06D = 4098; - MAP07D = 4098; MAP08D = 4098; MAP09D = 4098; MAP10D = 4098; MAP11D = 4098; MAP12D = 4098; - MAP13D = 4098; MAP14D = 4098; MAP15D = 4098; MAP16D = 4098; MAP17D = 4098; MAP18D = 4098; - MAP19D = 4098; MAP20D = 4098; MAP21D = 4098; MAP22D = 4098; MAP23D = 4098; MAP24D = 4098; - MAP25D = 4098; MAP26D = 4098; MAP27D = 4098; MAP28D = 4098; MAP29D = 4098; MAP30D = 4098; - MAP31D = 4098; MAP32D = 4098; MAP33D = 4098; MAP34D = 4098; MAP35D = 4098; MAP36D = 4098; - MAP37D = 4098; MAP38D = 4098; MAP39D = 4098; MAP40D = 4098; MAP41D = 4098; MAP42D = 4098; - MAP43D = 4098; MAP44D = 4098; MAP45D = 4098; MAP46D = 4098; MAP47D = 4098; MAP48D = 4098; - MAP49D = 4098; MAP50D = 4098; MAP51D = 4098; MAP52D = 4098; MAP53D = 4098; MAP54D = 4098; - MAP55D = 4098; MAP56D = 4098; MAP57D = 4098; MAP58D = 4098; MAP59D = 4098; MAP60D = 4098; - MAP61D = 4098; MAP62D = 4098; MAP63D = 4098; MAP64D = 4098; MAP65D = 4098; MAP66D = 4098; - MAP67D = 4098; MAP68D = 4098; MAP69D = 4098; MAP70D = 4098; MAP71D = 4098; MAP72D = 4098; - MAP73D = 4098; MAP74D = 4098; MAP75D = 4098; MAP76D = 4098; MAP77D = 4098; MAP78D = 4098; - MAP79D = 4098; MAP80D = 4098; MAP81D = 4098; MAP82D = 4098; MAP83D = 4098; MAP84D = 4098; - MAP85D = 4098; MAP86D = 4098; MAP87D = 4098; MAP88D = 4098; MAP89D = 4098; MAP90D = 4098; - MAP91D = 4098; MAP92D = 4098; MAP93D = 4098; MAP94D = 4098; MAP95D = 4098; MAP96D = 4098; - MAP97D = 4098; MAP98D = 4098; MAP99D = 4098; - - MAPA0D = 4098; MAPA1D = 4098; MAPA2D = 4098; MAPA3D = 4098; MAPA4D = 4098; MAPA5D = 4098; - MAPA6D = 4098; MAPA7D = 4098; MAPA8D = 4098; MAPA9D = 4098; MAPAAD = 4098; MAPABD = 4098; - MAPACD = 4098; MAPADD = 4098; MAPAED = 4098; MAPAFD = 4098; MAPAGD = 4098; MAPAHD = 4098; - MAPAID = 4098; MAPAJD = 4098; MAPAKD = 4098; MAPALD = 4098; MAPAMD = 4098; MAPAND = 4098; - MAPAOD = 4098; MAPAPD = 4098; MAPAQD = 4098; MAPARD = 4098; MAPASD = 4098; MAPATD = 4098; - MAPAUD = 4098; MAPAVD = 4098; MAPAWD = 4098; MAPAXD = 4098; MAPAYD = 4098; MAPAZD = 4098; - - MAPB0D = 4098; MAPB1D = 4098; MAPB2D = 4098; MAPB3D = 4098; MAPB4D = 4098; MAPB5D = 4098; - MAPB6D = 4098; MAPB7D = 4098; MAPB8D = 4098; MAPB9D = 4098; MAPBAD = 4098; MAPBBD = 4098; - MAPBCD = 4098; MAPBDD = 4098; MAPBED = 4098; MAPBFD = 4098; MAPBGD = 4098; MAPBHD = 4098; - MAPBID = 4098; MAPBJD = 4098; MAPBKD = 4098; MAPBLD = 4098; MAPBMD = 4098; MAPBND = 4098; - MAPBOD = 4098; MAPBPD = 4098; MAPBQD = 4098; MAPBRD = 4098; MAPBSD = 4098; MAPBTD = 4098; - MAPBUD = 4098; MAPBVD = 4098; MAPBWD = 4098; MAPBXD = 4098; MAPBYD = 4098; MAPBZD = 4098; - - MAPC0D = 4098; MAPC1D = 4098; MAPC2D = 4098; MAPC3D = 4098; MAPC4D = 4098; MAPC5D = 4098; - MAPC6D = 4098; MAPC7D = 4098; MAPC8D = 4098; MAPC9D = 4098; MAPCAD = 4098; MAPCBD = 4098; - MAPCCD = 4098; MAPCDD = 4098; MAPCED = 4098; MAPCFD = 4098; MAPCGD = 4098; MAPCHD = 4098; - MAPCID = 4098; MAPCJD = 4098; MAPCKD = 4098; MAPCLD = 4098; MAPCMD = 4098; MAPCND = 4098; - MAPCOD = 4098; MAPCPD = 4098; MAPCQD = 4098; MAPCRD = 4098; MAPCSD = 4098; MAPCTD = 4098; - MAPCUD = 4098; MAPCVD = 4098; MAPCWD = 4098; MAPCXD = 4098; MAPCYD = 4098; MAPCZD = 4098; - - MAPD0D = 4098; MAPD1D = 4098; MAPD2D = 4098; MAPD3D = 4098; MAPD4D = 4098; MAPD5D = 4098; - MAPD6D = 4098; MAPD7D = 4098; MAPD8D = 4098; MAPD9D = 4098; MAPDAD = 4098; MAPDBD = 4098; - MAPDCD = 4098; MAPDDD = 4098; MAPDED = 4098; MAPDFD = 4098; MAPDGD = 4098; MAPDHD = 4098; - MAPDID = 4098; MAPDJD = 4098; MAPDKD = 4098; MAPDLD = 4098; MAPDMD = 4098; MAPDND = 4098; - MAPDOD = 4098; MAPDPD = 4098; MAPDQD = 4098; MAPDRD = 4098; MAPDSD = 4098; MAPDTD = 4098; - MAPDUD = 4098; MAPDVD = 4098; MAPDWD = 4098; MAPDXD = 4098; MAPDYD = 4098; MAPDZD = 4098; - - MAPE0D = 4098; MAPE1D = 4098; MAPE2D = 4098; MAPE3D = 4098; MAPE4D = 4098; MAPE5D = 4098; - MAPE6D = 4098; MAPE7D = 4098; MAPE8D = 4098; MAPE9D = 4098; MAPEAD = 4098; MAPEBD = 4098; - MAPECD = 4098; MAPEDD = 4098; MAPEED = 4098; MAPEFD = 4098; MAPEGD = 4098; MAPEHD = 4098; - MAPEID = 4098; MAPEJD = 4098; MAPEKD = 4098; MAPELD = 4098; MAPEMD = 4098; MAPEND = 4098; - MAPEOD = 4098; MAPEPD = 4098; MAPEQD = 4098; MAPERD = 4098; MAPESD = 4098; MAPETD = 4098; - MAPEUD = 4098; MAPEVD = 4098; MAPEWD = 4098; MAPEXD = 4098; MAPEYD = 4098; MAPEZD = 4098; - - MAPF0D = 4098; MAPF1D = 4098; MAPF2D = 4098; MAPF3D = 4098; MAPF4D = 4098; MAPF5D = 4098; - MAPF6D = 4098; MAPF7D = 4098; MAPF8D = 4098; MAPF9D = 4098; MAPFAD = 4098; MAPFBD = 4098; - MAPFCD = 4098; MAPFDD = 4098; MAPFED = 4098; MAPFFD = 4098; MAPFGD = 4098; MAPFHD = 4098; - MAPFID = 4098; MAPFJD = 4098; MAPFKD = 4098; MAPFLD = 4098; MAPFMD = 4098; MAPFND = 4098; - MAPFOD = 4098; MAPFPD = 4098; MAPFQD = 4098; MAPFRD = 4098; MAPFSD = 4098; MAPFTD = 4098; - MAPFUD = 4098; MAPFVD = 4098; MAPFWD = 4098; MAPFXD = 4098; MAPFYD = 4098; MAPFZD = 4098; - - MAPG0D = 4098; MAPG1D = 4098; MAPG2D = 4098; MAPG3D = 4098; MAPG4D = 4098; MAPG5D = 4098; - MAPG6D = 4098; MAPG7D = 4098; MAPG8D = 4098; MAPG9D = 4098; MAPGAD = 4098; MAPGBD = 4098; - MAPGCD = 4098; MAPGDD = 4098; MAPGED = 4098; MAPGFD = 4098; MAPGGD = 4098; MAPGHD = 4098; - MAPGID = 4098; MAPGJD = 4098; MAPGKD = 4098; MAPGLD = 4098; MAPGMD = 4098; MAPGND = 4098; - MAPGOD = 4098; MAPGPD = 4098; MAPGQD = 4098; MAPGRD = 4098; MAPGSD = 4098; MAPGTD = 4098; - MAPGUD = 4098; MAPGVD = 4098; MAPGWD = 4098; MAPGXD = 4098; MAPGYD = 4098; MAPGZD = 4098; - - MAPH0D = 4098; MAPH1D = 4098; MAPH2D = 4098; MAPH3D = 4098; MAPH4D = 4098; MAPH5D = 4098; - MAPH6D = 4098; MAPH7D = 4098; MAPH8D = 4098; MAPH9D = 4098; MAPHAD = 4098; MAPHBD = 4098; - MAPHCD = 4098; MAPHDD = 4098; MAPHED = 4098; MAPHFD = 4098; MAPHGD = 4098; MAPHHD = 4098; - MAPHID = 4098; MAPHJD = 4098; MAPHKD = 4098; MAPHLD = 4098; MAPHMD = 4098; MAPHND = 4098; - MAPHOD = 4098; MAPHPD = 4098; MAPHQD = 4098; MAPHRD = 4098; MAPHSD = 4098; MAPHTD = 4098; - MAPHUD = 4098; MAPHVD = 4098; MAPHWD = 4098; MAPHXD = 4098; MAPHYD = 4098; MAPHZD = 4098; - - MAPI0D = 4098; MAPI1D = 4098; MAPI2D = 4098; MAPI3D = 4098; MAPI4D = 4098; MAPI5D = 4098; - MAPI6D = 4098; MAPI7D = 4098; MAPI8D = 4098; MAPI9D = 4098; MAPIAD = 4098; MAPIBD = 4098; - MAPICD = 4098; MAPIDD = 4098; MAPIED = 4098; MAPIFD = 4098; MAPIGD = 4098; MAPIHD = 4098; - MAPIID = 4098; MAPIJD = 4098; MAPIKD = 4098; MAPILD = 4098; MAPIMD = 4098; MAPIND = 4098; - MAPIOD = 4098; MAPIPD = 4098; MAPIQD = 4098; MAPIRD = 4098; MAPISD = 4098; MAPITD = 4098; - MAPIUD = 4098; MAPIVD = 4098; MAPIWD = 4098; MAPIXD = 4098; MAPIYD = 4098; MAPIZD = 4098; - - MAPJ0D = 4098; MAPJ1D = 4098; MAPJ2D = 4098; MAPJ3D = 4098; MAPJ4D = 4098; MAPJ5D = 4098; - MAPJ6D = 4098; MAPJ7D = 4098; MAPJ8D = 4098; MAPJ9D = 4098; MAPJAD = 4098; MAPJBD = 4098; - MAPJCD = 4098; MAPJDD = 4098; MAPJED = 4098; MAPJFD = 4098; MAPJGD = 4098; MAPJHD = 4098; - MAPJID = 4098; MAPJJD = 4098; MAPJKD = 4098; MAPJLD = 4098; MAPJMD = 4098; MAPJND = 4098; - MAPJOD = 4098; MAPJPD = 4098; MAPJQD = 4098; MAPJRD = 4098; MAPJSD = 4098; MAPJTD = 4098; - MAPJUD = 4098; MAPJVD = 4098; MAPJWD = 4098; MAPJXD = 4098; MAPJYD = 4098; MAPJZD = 4098; - - MAPK0D = 4098; MAPK1D = 4098; MAPK2D = 4098; MAPK3D = 4098; MAPK4D = 4098; MAPK5D = 4098; - MAPK6D = 4098; MAPK7D = 4098; MAPK8D = 4098; MAPK9D = 4098; MAPKAD = 4098; MAPKBD = 4098; - MAPKCD = 4098; MAPKDD = 4098; MAPKED = 4098; MAPKFD = 4098; MAPKGD = 4098; MAPKHD = 4098; - MAPKID = 4098; MAPKJD = 4098; MAPKKD = 4098; MAPKLD = 4098; MAPKMD = 4098; MAPKND = 4098; - MAPKOD = 4098; MAPKPD = 4098; MAPKQD = 4098; MAPKRD = 4098; MAPKSD = 4098; MAPKTD = 4098; - MAPKUD = 4098; MAPKVD = 4098; MAPKWD = 4098; MAPKXD = 4098; MAPKYD = 4098; MAPKZD = 4098; - - MAPL0D = 4098; MAPL1D = 4098; MAPL2D = 4098; MAPL3D = 4098; MAPL4D = 4098; MAPL5D = 4098; - MAPL6D = 4098; MAPL7D = 4098; MAPL8D = 4098; MAPL9D = 4098; MAPLAD = 4098; MAPLBD = 4098; - MAPLCD = 4098; MAPLDD = 4098; MAPLED = 4098; MAPLFD = 4098; MAPLGD = 4098; MAPLHD = 4098; - MAPLID = 4098; MAPLJD = 4098; MAPLKD = 4098; MAPLLD = 4098; MAPLMD = 4098; MAPLND = 4098; - MAPLOD = 4098; MAPLPD = 4098; MAPLQD = 4098; MAPLRD = 4098; MAPLSD = 4098; MAPLTD = 4098; - MAPLUD = 4098; MAPLVD = 4098; MAPLWD = 4098; MAPLXD = 4098; MAPLYD = 4098; MAPLZD = 4098; - - MAPM0D = 4098; MAPM1D = 4098; MAPM2D = 4098; MAPM3D = 4098; MAPM4D = 4098; MAPM5D = 4098; - MAPM6D = 4098; MAPM7D = 4098; MAPM8D = 4098; MAPM9D = 4098; MAPMAD = 4098; MAPMBD = 4098; - MAPMCD = 4098; MAPMDD = 4098; MAPMED = 4098; MAPMFD = 4098; MAPMGD = 4098; MAPMHD = 4098; - MAPMID = 4098; MAPMJD = 4098; MAPMKD = 4098; MAPMLD = 4098; MAPMMD = 4098; MAPMND = 4098; - MAPMOD = 4098; MAPMPD = 4098; MAPMQD = 4098; MAPMRD = 4098; MAPMSD = 4098; MAPMTD = 4098; - MAPMUD = 4098; MAPMVD = 4098; MAPMWD = 4098; MAPMXD = 4098; MAPMYD = 4098; MAPMZD = 4098; - - MAPN0D = 4098; MAPN1D = 4098; MAPN2D = 4098; MAPN3D = 4098; MAPN4D = 4098; MAPN5D = 4098; - MAPN6D = 4098; MAPN7D = 4098; MAPN8D = 4098; MAPN9D = 4098; MAPNAD = 4098; MAPNBD = 4098; - MAPNCD = 4098; MAPNDD = 4098; MAPNED = 4098; MAPNFD = 4098; MAPNGD = 4098; MAPNHD = 4098; - MAPNID = 4098; MAPNJD = 4098; MAPNKD = 4098; MAPNLD = 4098; MAPNMD = 4098; MAPNND = 4098; - MAPNOD = 4098; MAPNPD = 4098; MAPNQD = 4098; MAPNRD = 4098; MAPNSD = 4098; MAPNTD = 4098; - MAPNUD = 4098; MAPNVD = 4098; MAPNWD = 4098; MAPNXD = 4098; MAPNYD = 4098; MAPNZD = 4098; - - MAPO0D = 4098; MAPO1D = 4098; MAPO2D = 4098; MAPO3D = 4098; MAPO4D = 4098; MAPO5D = 4098; - MAPO6D = 4098; MAPO7D = 4098; MAPO8D = 4098; MAPO9D = 4098; MAPOAD = 4098; MAPOBD = 4098; - MAPOCD = 4098; MAPODD = 4098; MAPOED = 4098; MAPOFD = 4098; MAPOGD = 4098; MAPOHD = 4098; - MAPOID = 4098; MAPOJD = 4098; MAPOKD = 4098; MAPOLD = 4098; MAPOMD = 4098; MAPOND = 4098; - MAPOOD = 4098; MAPOPD = 4098; MAPOQD = 4098; MAPORD = 4098; MAPOSD = 4098; MAPOTD = 4098; - MAPOUD = 4098; MAPOVD = 4098; MAPOWD = 4098; MAPOXD = 4098; MAPOYD = 4098; MAPOZD = 4098; - - MAPP0D = 4098; MAPP1D = 4098; MAPP2D = 4098; MAPP3D = 4098; MAPP4D = 4098; MAPP5D = 4098; - MAPP6D = 4098; MAPP7D = 4098; MAPP8D = 4098; MAPP9D = 4098; MAPPAD = 4098; MAPPBD = 4098; - MAPPCD = 4098; MAPPDD = 4098; MAPPED = 4098; MAPPFD = 4098; MAPPGD = 4098; MAPPHD = 4098; - MAPPID = 4098; MAPPJD = 4098; MAPPKD = 4098; MAPPLD = 4098; MAPPMD = 4098; MAPPND = 4098; - MAPPOD = 4098; MAPPPD = 4098; MAPPQD = 4098; MAPPRD = 4098; MAPPSD = 4098; MAPPTD = 4098; - MAPPUD = 4098; MAPPVD = 4098; MAPPWD = 4098; MAPPXD = 4098; MAPPYD = 4098; MAPPZD = 4098; - - MAPQ0D = 4098; MAPQ1D = 4098; MAPQ2D = 4098; MAPQ3D = 4098; MAPQ4D = 4098; MAPQ5D = 4098; - MAPQ6D = 4098; MAPQ7D = 4098; MAPQ8D = 4098; MAPQ9D = 4098; MAPQAD = 4098; MAPQBD = 4098; - MAPQCD = 4098; MAPQDD = 4098; MAPQED = 4098; MAPQFD = 4098; MAPQGD = 4098; MAPQHD = 4098; - MAPQID = 4098; MAPQJD = 4098; MAPQKD = 4098; MAPQLD = 4098; MAPQMD = 4098; MAPQND = 4098; - MAPQOD = 4098; MAPQPD = 4098; MAPQQD = 4098; MAPQRD = 4098; MAPQSD = 4098; MAPQTD = 4098; - MAPQUD = 4098; MAPQVD = 4098; MAPQWD = 4098; MAPQXD = 4098; MAPQYD = 4098; MAPQZD = 4098; - - MAPR0D = 4098; MAPR1D = 4098; MAPR2D = 4098; MAPR3D = 4098; MAPR4D = 4098; MAPR5D = 4098; - MAPR6D = 4098; MAPR7D = 4098; MAPR8D = 4098; MAPR9D = 4098; MAPRAD = 4098; MAPRBD = 4098; - MAPRCD = 4098; MAPRDD = 4098; MAPRED = 4098; MAPRFD = 4098; MAPRGD = 4098; MAPRHD = 4098; - MAPRID = 4098; MAPRJD = 4098; MAPRKD = 4098; MAPRLD = 4098; MAPRMD = 4098; MAPRND = 4098; - MAPROD = 4098; MAPRPD = 4098; MAPRQD = 4098; MAPRRD = 4098; MAPRSD = 4098; MAPRTD = 4098; - MAPRUD = 4098; MAPRVD = 4098; MAPRWD = 4098; MAPRXD = 4098; MAPRYD = 4098; MAPRZD = 4098; - - MAPS0D = 4098; MAPS1D = 4098; MAPS2D = 4098; MAPS3D = 4098; MAPS4D = 4098; MAPS5D = 4098; - MAPS6D = 4098; MAPS7D = 4098; MAPS8D = 4098; MAPS9D = 4098; MAPSAD = 4098; MAPSBD = 4098; - MAPSCD = 4098; MAPSDD = 4098; MAPSED = 4098; MAPSFD = 4098; MAPSGD = 4098; MAPSHD = 4098; - MAPSID = 4098; MAPSJD = 4098; MAPSKD = 4098; MAPSLD = 4098; MAPSMD = 4098; MAPSND = 4098; - MAPSOD = 4098; MAPSPD = 4098; MAPSQD = 4098; MAPSRD = 4098; MAPSSD = 4098; MAPSTD = 4098; - MAPSUD = 4098; MAPSVD = 4098; MAPSWD = 4098; MAPSXD = 4098; MAPSYD = 4098; MAPSZD = 4098; - - MAPT0D = 4098; MAPT1D = 4098; MAPT2D = 4098; MAPT3D = 4098; MAPT4D = 4098; MAPT5D = 4098; - MAPT6D = 4098; MAPT7D = 4098; MAPT8D = 4098; MAPT9D = 4098; MAPTAD = 4098; MAPTBD = 4098; - MAPTCD = 4098; MAPTDD = 4098; MAPTED = 4098; MAPTFD = 4098; MAPTGD = 4098; MAPTHD = 4098; - MAPTID = 4098; MAPTJD = 4098; MAPTKD = 4098; MAPTLD = 4098; MAPTMD = 4098; MAPTND = 4098; - MAPTOD = 4098; MAPTPD = 4098; MAPTQD = 4098; MAPTRD = 4098; MAPTSD = 4098; MAPTTD = 4098; - MAPTUD = 4098; MAPTVD = 4098; MAPTWD = 4098; MAPTXD = 4098; MAPTYD = 4098; MAPTZD = 4098; - - MAPU0D = 4098; MAPU1D = 4098; MAPU2D = 4098; MAPU3D = 4098; MAPU4D = 4098; MAPU5D = 4098; - MAPU6D = 4098; MAPU7D = 4098; MAPU8D = 4098; MAPU9D = 4098; MAPUAD = 4098; MAPUBD = 4098; - MAPUCD = 4098; MAPUDD = 4098; MAPUED = 4098; MAPUFD = 4098; MAPUGD = 4098; MAPUHD = 4098; - MAPUID = 4098; MAPUJD = 4098; MAPUKD = 4098; MAPULD = 4098; MAPUMD = 4098; MAPUND = 4098; - MAPUOD = 4098; MAPUPD = 4098; MAPUQD = 4098; MAPURD = 4098; MAPUSD = 4098; MAPUTD = 4098; - MAPUUD = 4098; MAPUVD = 4098; MAPUWD = 4098; MAPUXD = 4098; MAPUYD = 4098; MAPUZD = 4098; - - MAPV0D = 4098; MAPV1D = 4098; MAPV2D = 4098; MAPV3D = 4098; MAPV4D = 4098; MAPV5D = 4098; - MAPV6D = 4098; MAPV7D = 4098; MAPV8D = 4098; MAPV9D = 4098; MAPVAD = 4098; MAPVBD = 4098; - MAPVCD = 4098; MAPVDD = 4098; MAPVED = 4098; MAPVFD = 4098; MAPVGD = 4098; MAPVHD = 4098; - MAPVID = 4098; MAPVJD = 4098; MAPVKD = 4098; MAPVLD = 4098; MAPVMD = 4098; MAPVND = 4098; - MAPVOD = 4098; MAPVPD = 4098; MAPVQD = 4098; MAPVRD = 4098; MAPVSD = 4098; MAPVTD = 4098; - MAPVUD = 4098; MAPVVD = 4098; MAPVWD = 4098; MAPVXD = 4098; MAPVYD = 4098; MAPVZD = 4098; - - MAPW0D = 4098; MAPW1D = 4098; MAPW2D = 4098; MAPW3D = 4098; MAPW4D = 4098; MAPW5D = 4098; - MAPW6D = 4098; MAPW7D = 4098; MAPW8D = 4098; MAPW9D = 4098; MAPWAD = 4098; MAPWBD = 4098; - MAPWCD = 4098; MAPWDD = 4098; MAPWED = 4098; MAPWFD = 4098; MAPWGD = 4098; MAPWHD = 4098; - MAPWID = 4098; MAPWJD = 4098; MAPWKD = 4098; MAPWLD = 4098; MAPWMD = 4098; MAPWND = 4098; - MAPWOD = 4098; MAPWPD = 4098; MAPWQD = 4098; MAPWRD = 4098; MAPWSD = 4098; MAPWTD = 4098; - MAPWUD = 4098; MAPWVD = 4098; MAPWWD = 4098; MAPWXD = 4098; MAPWYD = 4098; MAPWZD = 4098; - - MAPX0D = 4098; MAPX1D = 4098; MAPX2D = 4098; MAPX3D = 4098; MAPX4D = 4098; MAPX5D = 4098; - MAPX6D = 4098; MAPX7D = 4098; MAPX8D = 4098; MAPX9D = 4098; MAPXAD = 4098; MAPXBD = 4098; - MAPXCD = 4098; MAPXDD = 4098; MAPXED = 4098; MAPXFD = 4098; MAPXGD = 4098; MAPXHD = 4098; - MAPXID = 4098; MAPXJD = 4098; MAPXKD = 4098; MAPXLD = 4098; MAPXMD = 4098; MAPXND = 4098; - MAPXOD = 4098; MAPXPD = 4098; MAPXQD = 4098; MAPXRD = 4098; MAPXSD = 4098; MAPXTD = 4098; - MAPXUD = 4098; MAPXVD = 4098; MAPXWD = 4098; MAPXXD = 4098; MAPXYD = 4098; MAPXZD = 4098; - - MAPY0D = 4098; MAPY1D = 4098; MAPY2D = 4098; MAPY3D = 4098; MAPY4D = 4098; MAPY5D = 4098; - MAPY6D = 4098; MAPY7D = 4098; MAPY8D = 4098; MAPY9D = 4098; MAPYAD = 4098; MAPYBD = 4098; - MAPYCD = 4098; MAPYDD = 4098; MAPYED = 4098; MAPYFD = 4098; MAPYGD = 4098; MAPYHD = 4098; - MAPYID = 4098; MAPYJD = 4098; MAPYKD = 4098; MAPYLD = 4098; MAPYMD = 4098; MAPYND = 4098; - MAPYOD = 4098; MAPYPD = 4098; MAPYQD = 4098; MAPYRD = 4098; MAPYSD = 4098; MAPYTD = 4098; - MAPYUD = 4098; MAPYVD = 4098; MAPYWD = 4098; MAPYXD = 4098; MAPYYD = 4098; MAPYZD = 4098; - - MAPZ0D = 4098; MAPZ1D = 4098; MAPZ2D = 4098; MAPZ3D = 4098; MAPZ4D = 4098; MAPZ5D = 4098; - MAPZ6D = 4098; MAPZ7D = 4098; MAPZ8D = 4098; MAPZ9D = 4098; MAPZAD = 4098; MAPZBD = 4098; - MAPZCD = 4098; MAPZDD = 4098; MAPZED = 4098; MAPZFD = 4098; MAPZGD = 4098; MAPZHD = 4098; - MAPZID = 4098; MAPZJD = 4098; MAPZKD = 4098; MAPZLD = 4098; MAPZMD = 4098; MAPZND = 4098; - MAPZOD = 4098; MAPZPD = 4098; MAPZQD = 4098; MAPZRD = 4098; MAPZSD = 4098; MAPZTD = 4098; - MAPZUD = 4098; MAPZVD = 4098; MAPZWD = 4098; MAPZXD = 4098; MAPZYD = 4098; MAPZZD = 4098; -} - - -// DEFAULT SECTOR BRIGHTNESS LEVELS------------------------------------------------------------------------------------------ -sectorbrightness -{ - 255; - 240; - 224; - 208; - 192; - 176; - 160; - 144; - 128; - 112; - 96; - 80; - 64; - 48; - 32; - 16; - 0; -} - -// SECTOR TYPES-------------------------------------------------------------------------------------------------------------- -sectortypes -{ - 0 = "Normal"; - 1 = "Light Blink Randomly"; - 2 = "Light Blink On Every 0.5 Seconds"; - 3 = "Light Blink On Every 1 Second"; - 4 = "Spikes"; - 5 = "Death Pit (No Camera Modifications)"; - 6 = "Space Countdown"; - 7 = "Damage (Fire)"; - 8 = "Light Pulse Smoothly"; - 9 = "Special Stage Damage"; - 10 = "Instant Kill"; - 11 = "Damage (Non-Elemental)"; - 12 = "Light Blinks On Every Half 0.5 (Synch)"; - 13 = "Light Blink On Every 1 Second (Synch)"; - 14 = "BOuncy Sector (FOF Control Only)"; - 16 = "Death Pit (Camera Modifications)"; - 17 = "Light Flickers Like Fire"; - 18 = "Damage (Electric)"; - 33 = "Special Stage Goal"; - 256 = "Ice/Sludge"; - 512 = "Wind/Current"; - 519 = "Damage (Fire) and Current"; - 666 = "Egg Trap Capsule"; - 690 = "Button for Door 700"; - 691 = "Button for Door 702"; - 692 = "Button for Door 704"; - 693 = "Button for Door 706"; - 694 = "Button for Door 708"; - 695 = "Button for Door 710"; - 696 = "Button for Door 712"; - 697 = "Button for Door 714"; - 698 = "Button for Door 716"; - 699 = "Button for Door 718"; - 700 = "Button for Door 720"; - 701 = "Button for Door 722"; - 702 = "Button for Door 724"; - 703 = "Button for Door 726"; - 704 = "Button for Door 728"; - 705 = "Button for Door 730"; - 706 = "Button for Door 732"; - 707 = "Button for Door 734"; - 708 = "Button for Door 736"; - 709 = "Button for Door 738"; - 710 = "Button 21 (THZ2)"; - 711 = "Close Door Blazing (Tag 743)"; - 768 = "Ice/Sludge & Wind/Current"; - 967 = "Trigger Linedef Executor (Emerald Check)"; - 968 = "Trigger Linedef Executor (NiGHTS mare)"; - 969 = "Super Sonic Transform"; - 970 = "Check for Linedef Executor On 3D Floors (ANY Object)"; - 971 = "Trigger Linedef Executor (Pushable Objects)"; - 972 = "Trigger Linedef Executor (Anywhere in Sector)(All Players)"; - 973 = "Trigger Linedef Executor (Floor touch)(All players)"; - 974 = "Trigger Linedef Executor (Anywhere in Sector)"; - 975 = "Trigger Linedef Executor (Floor Touch)"; - 976 = "Speed Pad (No Spin)"; - 977 = "Speed Pad (Spin)"; - 978 = "Ring Drainer (Floor Touch)"; - 979 = "Spinner"; - 980 = "Ring Drainer (No Floor Touch)"; - 981 = "Raise Ceiling to Highest (Tag 744)"; - 982 = "Exit Sector"; - 983 = "Damage (Water)"; - 984 = "Damage (Water) & Current"; - 985 = "Conveyor Belt"; - 986 = "THZ2 Slime Raise"; - 987 = "No Tag Zone"; - 988 = "CTF Red Team Base"; - 989 = "CTF Blue Team Base"; - 990 = "Special Stage Time/Rings"; - 991 = "Custom Gravity"; - 992 = "Ramp Sector"; - 993 = "Starpost Activator"; - 994 = "Finish Line"; - 996 = "Non-Ramp Sector"; - 997 = "Fan Sector"; - 998 = "Zoom Tube Start"; - 999 = "Zoom Tube End"; - 1500 ="Bustable Block Sprite parameter(ROIA)"; - 1501 ="Bustable Block Sprite parameter(ROIB)"; - 1502 ="Bustable Block Sprite parameter(ROIC)"; - 1503 ="Bustable Block Sprite parameter(ROID)"; - 1504 ="Bustable Block Sprite parameter(ROIE)"; - 1505 ="Bustable Block Sprite parameter(ROIF)"; - 1506 ="Bustable Block Sprite parameter(ROIG)"; - 1507 ="Bustable Block Sprite parameter(ROIH)"; - 1508 ="Bustable Block Sprite parameter(ROII)"; - 1509 ="Bustable Block Sprite parameter(ROIJ)"; - 1510 ="Bustable Block Sprite parameter(ROIK)"; - 1511 ="Bustable Block Sprite parameter(ROIL)"; - 1512 ="Bustable Block Sprite parameter(ROIM)"; - 1513 ="Bustable Block Sprite parameter(ROIN)"; - 1514 ="Bustable Block Sprite parameter(ROIO)"; - 1515 ="Bustable Block Sprite parameter(ROIP)"; -} - -// LINEDEF FLAGS------------------------------------------------------------------------------------------------------------- -linedefflags -{ - 1 = "Impassible"; - 2 = "Block Monster"; - 4 = "Double Sided"; - 8 = "Upper Unpegged"; - 16 = "Lower Unpegged"; - 32 = "Don't Activate On Easy"; - 64 = "No Climb"; - 128 = "Don't Activate On Normal"; - 256 = "Don't Activate On Hard"; - 512 = "Passuse"; - 2048 = "Don't Activate When Sonic"; - 4096 = "Don't Activate When Tails"; - 8192 = "Don't Activate When Knux"; - 16384 = "Bouncy Wall"; -} - -// LINEDEF ACTIVATIONS -linedefactivations -{ -} - -// LINEDEF TYPES------------------------------------------------------------------------------------------------------------- -linedeftypes -{ - 0 = " Normal"; - 1 = " 3D - Floor Over Floor: Crumbling (No respawn), Floating, Bobbing"; - 2 = " Continuous Floor/Ceiling Mover"; - 3 = " Continuous Floor Mover"; - 4 = " Continuous Ceiling Mover"; - 5 = " Light - Ceiling Lighting"; - 6 = " Continuous Two-Speed Floor/Ceiling Mover"; - 7 = " Continuous Two-Speed Floor Mover"; - 8 = " Continuous Two-Speed Ceiling Mover"; - 9 = " Linedef Executor: Trigger Linedef (Race - Once)"; - 10 = " Linedef Executor: Trigger Linedef (CTF Red Team, Continuous)"; - 11 = " Linedef Executor: Trigger Linedef (CTF Red Team, Each Time)"; - 12 = " Linedef Executor: Trigger Linedef (CTF Blue Team, Continuous)"; - 13 = " Linedef Executor: Trigger Linedef (CTF Red Team, Each Time)"; - 15 = " Linedef Executor: Trigger Linedef (No More Enemies, Once)"; - 16 = " ColorMap"; - 18 = " Zoom Tube Parameters"; - 19 = " Linedef Executor: Trigger Linedef (Character Ability, Continuous)"; - 20 = " Linedef Executor: Trigger Linedef (Character Ability, Each Time)"; - 21 = " Linedef Executor: Trigger Linedef (Character Ability, Once)"; - 24 = " Instant - Instant Ceiling Raise"; - 25 = " 3D - Floor Over Floor: Solid, Opaque, Shadowcasting (CTL sector light level used below"; - 26 = " Instant - Instant Floor Lower"; - 33 = " 3D - Floor Over Floor: Solid, Opaque, Non-Shadowcasting (CTL sector light level used above)"; - 34 = " 3D - Floor Over Floor: Floating & Bobbing"; - 35 = " 3D - Floor Over Floor: Crumbling (No Respawn)"; - 36 = " 3D - Floor Over Floor: Crumbling (Respawns after 15 seconds)"; - 37 = " 3D - Floor Over Floor: Crumbling (Respawn), Floating"; - 38 = " 3D - Floor Over Floor: Bobbing (Air)"; - 39 = " 3D - Floor Over Floor: Crumbling (Respawn), Floating, & Bobbing (Air)"; - 40 = " 3D - Floor Over Floor: Crumbling (Respawn), Bobbing (Air)"; - 41 = " Mario - Mario [?] Block"; - 42 = " 3D - Floor Over Floor: Crumbling (No Respawn), Floating"; - 43 = " Crusher - Crusher 1 (Ceiling to Floor)"; - 44 = " 3D - Floor Over Floor: Solid, Translucent"; - 45 = " Water - Water, Translucent"; - 46 = " 3D - Floor Over Floor: Fog Block"; - 47 = " Light - Half Light Block (From ceiling to bottom of level)"; - 48 = " Water - Water, Opaque"; - 49 = " Light - Light Block (From ceiling to floor)"; - 50 = " Crusher - Crusher 2 (Floor To Ceiling)"; - 51 = " 3D - Floor Over Floor: Solid, No Sides"; - 52 = " 3D - Floor Over Floor: Intangible, Translucent"; - 53 = " 3D - Floor Over Floor: Laser Block"; - 54 = " Mario - Floor Over Floor: Thwomp Block"; - 55 = " 3D - Floor Over Floor: Bustable Block"; - 56 = " 3D - Floor Over Floor: QuickSand Block"; - 57 = " 3D - Floor Over Floor: Solid, Invisible"; - 58 = " 3D - Floor Over Floor: Intangible, invisible"; - 59 = " 3D - Floor Over Floor: Intangible from Bottom, Opaque"; - 60 = " Light - Adjustable Pulsating Light"; - 61 = " Light - Adjustable Flickering Light"; - 62 = " 3D - Floor Over Floor: Intangible, Opaque"; - 63 = " Other - Camera Scanner"; - 64 = " Other - Per-Sector Gravity"; - 65 = " Movement/Scrolling - Speed Pad"; - 66 = " Other - Flat Alignment"; - 67 = " 3D - Floor Over Floor: Intangible, Sides Only"; - 68 = " 3D - Floor Over Floor: Adjustable Bobbing (Air)"; - 69 = " 3D - Floor Over Floor: Solid, Sides Only"; - 70 = " Other - Ideya (Nights) Time Modifier"; - 71 = " Other - Custom Exit"; - 72 = " 3D - Floor Over Floor: Reverse Adjustable Bob (Air)"; - 73 = " Other - Disable Linedef (Does Nothing)"; - 74 = " Water - Water, Translucent, No Sides"; - 75 = " Water - Water, Opaque, No Sides"; - 76 = " 3D - Floor Over Floor: Shatter Block"; - 77 = " 3D - Floor Over Floor: Platform, Translucent, No Sides"; - 78 = " 3D - Floor Over Floor: Spin Bust Block"; - 79 = " 3D - Floor Over Floor: Crumbling (Respawn)"; - 80 = " 3D - Floor Over Floor: Crumbling (No Respawn)"; - 81 = " 3D - Floor Over Floor: Platform, Translucent"; - 82 = " 3D - Floor Over Floor: Platform, Crumbling (Respawn), Translucent"; - 83 = " 3D - Floor Over Floor: Platform, Crumbling (No Respawn), Translucent"; - 84 = " 3D - Floor Over Floor: Spin Bust Block, Translucent"; - 85 = " Movement/Scrolling - Scroll Wall First Side Opposite Direction"; - 86 = " 3D - Floor Over Floor: Shatter Block, translucent"; - 87 = " 3D - Floor Over Floor: Custom"; - 88 = " Continuous Falling Sector"; - 89 = " 3D - Floor Over Floor: Rising Platform, Solid, Opaque, Shadowcasting"; - 90 = " 3D - Floor Over Floor: Rising Platform, Solid, Opaque, Non-Shadowcasting"; - 91 = " 3D - Floor Over Floor: Rising Platform Solid, Translucent"; - 92 = " 3D - Floor Over Floor: Rising Platform, Opaque"; - 93 = " 3D - Floor Over Floor: Rising Platform, Intangible from Bottom, Translucent"; - 94 = " 3D - Floor Over Floor: Rising Platform, Solid, Invisible"; - 95 = " Linedef Executor: Trigger Linedef (Ring Count - Continuous)"; - 96 = " Linedef Executor: Trigger Linedef (Continuous)"; - 97 = " Linedef Executor: Trigger Linedef (Each Time)"; - 98 = " Linedef Executor: Trigger Linedef (Once)"; - 99 = " Linedef Executor: Trigger Linedef (Ring Count - Once)"; - 100 = " Movement/Scrolling - Scroll Wall First Side Left"; - 101 = " Linedef Executor: Set Tagged Sector's Floor Height and Pic"; - 102 = " Linedef Executor: Set Tagged Sector's Ceiling Height and Pic"; - 103 = " Linedef Executor: Set Tagged Sector's Light Level"; - 104 = " Linedef Executor: Teleport Player to Tagged Sector"; - 105 = " Linedef Executor: Change Music"; - 106 = " Linedef Executor: Move Tagged Sector's Floor"; - 107 = " Linedef Executor: Move Tagged Sector's Ceiling"; - 108 = " Linedef Executor: Lower Floor by Line"; - 109 = " Linedef Executor: Raise Floor by Line"; - 110 = " Linedef Executor: Lower Ceiling by Line"; - 111 = " Linedef Executor: Raise Ceiling by Line"; - 112 = " Linedef Executor: Change Calling Sector's Tag"; - 113 = " Linedef Executor: Run Script"; - 114 = " Linedef Executor: Change Front Sector's Tag"; - 115 = " Linedef Executor: Play SFX"; - 116 = " Linedef Executor: Stop Plane Movement"; - 117 = " Linedef Executor: Fade Light Level"; - 118 = " Linedef Executor: Stop Lighting Effect"; - 119 = " Linedef Executor: Start Adjustable Fire Flicker"; - 120 = " Linedef Executor: Start Adjustable Glowing Light"; - 121 = " Linedef Executor: Cut-Away View"; - 122 = " Linedef Executor: Stop Object"; - 123 = " Linedef Executor: Change Sky"; - 124 = " Linedef Executor: Change Weather"; - 125 = " Linedef Executor: Change Object State"; - 126 = " Linedef Executor: Award Points"; - 127 = " Linedef Executor: Start Platform Movement"; - 200 = " Movement/Scrolling - Disp Scroll Ceiling Texture & Carry Objects"; - 201 = " Movement/Scrolling - Disp Carry Objects on Ceiling"; - 202 = " Movement/Scrolling - Scroll Ceiling Texture & Carry Objects"; - 203 = " Movement/Scrolling - Carry Objects on Ceiling"; - 204 = " Movement/Scrolling - Acc Scroll Ceiling Texture & Carry Objects"; - 205 = " Movement/Scrolling - Acc Carry Objects on Ceiling"; - 213 = " Light - Set Floor Lighting"; - 214 = " Movement/Scrolling - Acc Scroll Ceiling Texture"; - 215 = " Movement/Scrolling - Acc Scroll Floor Texture"; - 216 = " Movement/Scrolling - Acc Scroll Objects on Floor"; - 217 = " Movement/Scrolling - Acc Scroll Floor Texture & Carry Objects"; - 218 = " Movement/Scrolling - Acc Scroll Wall According to Linedef"; - 223 = " Other - Friction"; - 224 = " Wind/Current - Wind"; - 225 = " Wind/Current - Current"; - 226 = " Other - Boom Push/Pull"; - 227 = " Wind/Current - Upward Current"; - 228 = " Wind/Current - Downward Current"; - 229 = " Wind/Current - Upward Wind"; - 230 = " Wind/Current - Downward Wind"; - 232 = " Activate Floating Platform"; - 233 = " Activate Floating Platform (Adjustable Speed)"; - 242 = " Other - Fake Floor"; - 245 = " Movement/Scrolling - Disp Scroll Ceiling Texture"; - 246 = " Movement/Scrolling - Disp Scroll Floor Texture"; - 247 = " Movement/Scrolling - Disp Scroll Objects on Floor"; - 248 = " Movement/Scrolling - Disp Scroll Floor Texture & Carry Objects"; - 249 = " Movement/Scrolling - Disp Scroll Wall According to Linedef"; - 250 = " Movement/Scrolling - Scroll Ceiling Texture"; - 251 = " Movement/Scrolling - Scroll Floor Texture"; - 252 = " Movement/Scrolling - Carry Objects on Floor"; - 253 = " Movement/Scrolling - Scroll Floor Texture & Carry Objects"; - 254 = " Movement/Scrolling - Scroll Wall According by Linedef"; - 255 = " Movement/Scrolling - Scroll Texture by Offsets"; -} - -// THING FLAGS--------------------------------------------------------------------------------------------------------------- -thingflags -{ - 1 = "Easy"; - 2 = "Medium"; - 4 = "Hard"; - 8 = "Deaf"; - 16 = "Multiplayer"; - 32 = "Bitset: 2 Units"; - 64 = "Bitset: 4 Units"; - 128 = "Bitset: 8 Units"; - 256 = "Bitset: 16 Units"; - 512 = "Bitset: 32 Units"; - 1024 = "Bitset: 64 Units"; - 2048 = "Bitset: 128 Units"; - 4096 = "Bitset: 256 Units"; - 8192 = "Bitset: 512 Units"; - 16384 = "Bitset: 1024 Units"; - 32768 = "Bitset: 2048 Units"; -} - -// THING TYPES--------------------------------------------------------------------------------------------------------------- -// Color values: 1-Blue 2-Green 3-Cyan 4-Red 5-Magenta 6-Brown 7-Gray 8-Dark_Gray 9-Light_Blue -// 10-Light_Green 11-Light_Cyan 12-Light_Red 13-Pink 14-Yellow 15-White -thingtypes -{ - editor - { - color = 15; // White - arrow = 1; - title = "Editor Things"; - width = 16; - - 32000 - { - title = "3D Mode start"; - } - } - - players //--------------------------------------------------------------------------------------- - { - color = 1; // Blue - arrow = 1; - title = "Player Starts"; - width = 32; - sort = 2; - - 1 - { - title = "Player 1 Start"; - sprite = "SUPTD0"; - height = 74; - } - 2 - { - title = "Player 2 Start"; - sprite = "SUPTD0"; - height = 74; - } - 3 - { - title = "Player 3 Start"; - sprite = "SUPTD0"; - height = 74; - } - 4 - { - title = "Player 4 Start"; - sprite = "SUPTD0"; - height = 74; - } - 4001 - { - title = "Player 5 Start"; - sprite = "SUPTD0"; - height = 74; - } - 4002 - { - title = "Player 6 Start"; - sprite = "SUPTD0"; - height = 74; - } - 4003 - { - title = "Player 7 Start"; - sprite = "SUPTD0"; - height = 74; - } - 4004 - { - title = "Player 8 Start"; - sprite = "SUPTD0"; - height = 74; - } - 87 - { - title = "Red Team Start(CTF)"; - sprite = "SUPTD0"; - height = 74; - } - 89 - { - title = "Blue Team Start(CTF)"; - sprite = "SUPTD0"; - height = 74; - } - 11 - { - title = "Deathmatch Start"; - sprite = "SUPTD0"; - height = 74; - } - } - - enemies //----------------------------------------------------------------------------------------------- - { - color = 4; // Red - arrow = 1; - title = "Enemies"; - width = 40; - sort = 2; - - 3004 - { - title = "Blue Crawla"; - sprite = "POSSA1"; - height = 48; - } - 9 - { - title = "Red Crawla"; - sprite = "SPOSA1"; - height = 48; - } - 21 - { - title = "Crawla Commander"; - sprite = "CCOMA1"; - height = 42; - } - 5005 - { - title = "Gold Buzz"; - sprite = "BUZZA1"; - height = 29; - } - 5006 - { - title = "Red Buzz"; - sprite = "RBUZA1"; - height = 29; - } - 3005 - { - title = "Jettysyn Bomber"; - sprite = "JETBB1"; - height = 64; - } - 22 - { - title = "Jettysyn Gunner"; - sprite = "JETGC1"; - height = 64; - } - 58 - { - title = "Stupid Dumb Unnamed Robo-fish"; - sprite = "FISHA0"; - height = 32; - } - 56 - { - title = "Skim"; - sprite = "SKIMA0"; - height = 48; - } - 71 - { - title = "Deton"; - sprite = "DETNA1"; - height = 46; - } - 2004 - { - title = "Turret"; - sprite = "TRETA1"; - height = 32; - } - 42 - { - title = "Pop Up Turret"; - sprite = "TURRD1"; - height = 53; - } - 16 - { - title = "Egg Mobile(Boss A)"; - width = 112; - sprite = "EGGMA1"; - height = 96; - } - 2008 - { - title = "Egg Slimer(Boss B)"; - width = 112; - sprite = "EGGNA1"; - height = 132; - } - 17 - { - title = "Boss Flypoint"; - width = 20; - sprite = "EGGNG1"; - height = 96; - } - } - - NiGHTs //------------------------------------------------------------------------------------------ - { - color = 11; // Light Cyan - arrow = 0; - title = "NiGHTs stuff"; - width = 20; - sort = 2; - - 52 = "1024 Axis"; - 53 = "512 Axis"; - 59 = "2048 Axis"; - 62 = "1024 Axis Inverted"; - 15 = "512 Axis Inverted"; - 45 = "2048 Axis Inverted"; - 61 = "Axis Transfer"; - 46 = "Axis Transfer Closest"; - 55 = "Axis Transfer Last to First"; - 60 - { - title = "NiGHTs Super Sonic"; - sprite = "NDRNA1"; - height = 70; - } - 57 = "Hoop"; - 47 = "Ring Circle"; - 2007 = "Big Ring Circle"; - 2048 = "Wing Logo Circle"; - 40 = "NiGHT's egg capsule"; - 2010 = "Big Wing Logo Circle"; - 2046 = "Ring N Wing Circle"; - 2047 = "Big Ring N Wing Circle"; - 3007 = "Super loop"; - 3008 = "Drill refill"; - 3009 = "Helper"; - 82 = "Axis Transfer Condition"; - } - - monitors //-------------------------------------------------------------------------------------------- - { - color = 7; // Gray - arrow = 0; - title = "Moniters"; - width = 20; - sort = 2; - - 41 - { - title = "Extra Life"; - sprite = "PRUPA0"; - height = 34; - } - 2022 - { - title = "Invincibility"; - sprite = "PINVA0"; - height = 34; - } - 25 - { - title = "Super Sneakers"; - sprite = "SHTVA0"; - height = 34; - } - 2028 - { - title = "Liquid Shield"; - sprite = "BLTVA0"; - height = 34; - } - 35 - { - title = "Whirlwind shield"; - sprite = "WHTVA0"; - height = 34; - } - 48 - { - title = "Lightning Shield"; - sprite = "YLTVA0"; - height = 34; - } - 2002 - { - title = "Fire Shield"; - sprite = "RDTVA0"; - height = 34; - } - 2018 - { - title = "Armageddon Shield"; - sprite = "BKTVA0"; - height = 34; - } - 2011 - { - title = "Super Rings"; - sprite = "SRBXA0"; - height = 34; - } - 2012 - { - title = "Silver Ring"; - sprite = "GRBXA0"; - height = 34; - } - 78 - { - title = "Teleporter"; - sprite = "MIXUA0"; - height = 34; - } - 2005 - { - title = "Robotnik"; - sprite = "EGGBA0"; - height = 34; - } - 3000 - { - title = "Random Monitor"; - sprite = "QUESA0"; - height = 34; - } - } - - weapons //--------------------------------------------------------------------------------------- - { - color = 14; // Yellow - arrow = 0; - title = "Rings and Weapons"; - width = 20; - sort = 2; - - 2014 - { - title= "Ring"; - sprite = "BON1A0"; - height = 32; - } - 84 - { - title = "5 Vertical Rings for Yellow Spring"; - sprite = "BON1A0"; - height = 32; - } - 44 - { - title = "5 Vertical Rings for Red Spring"; - sprite = "BON1A0"; - height = 32; - } - 76 - { - title = "5 Diagonal Rings for Yellow Spring"; - sprite = "BON1A0"; - height = 32; - } - 77 - { - title = "10 Diagonal Rings for Red Spring"; - sprite = "BON1A0"; - height = 32; - } - 69 - { - title= "Homing Ring"; - sprite = "HOMNIND"; - height = 16; - } - 3003 - { - title = "Rail Ring"; - sprite = "RAILIND"; - height = 16; - } - 26 - { - title = "Auto Ring"; - sprite = "AUTOIND"; - height = 16; - } - 54 - { - title= "Bomb Ring"; - sprite = "BOMBIND"; - height = 16; - } - 80 - { - title= "Infinity Ring"; - sprite = "INFNIND"; - height = 16; - } - } - - collectables //----------------------------------------------------------------------------------- - { - color = 10; // Light Green - arrow = 0; - title = "Other Collectables"; - width = 20; - sort = 2; - - 31 - { - title = "Red Flag (CTF)"; - sprite = "RFLGA0"; - height = 73; - } - 34 - { - title = "Blue Flag (CTF)"; - sprite = "BFLGA0"; - height = 73; - } - 37 - { - title = "Emblem"; - sprite = "NWNGA0"; - height = 32; - } - 2013 - { - title = "Special Stage Token"; - sprite = "TOKEA0"; - height = 32; - } - 64 - { title = "Emerald Hunt Location A"; - sprite = "EMERA0"; - height = 16; - } - 3002 - { title = "Emerald Hunt Location B"; - sprite = "EMERA0"; - height = 16; - } - 3001 - { - title = "Emerald Hunt Location C"; - sprite = "EMERA0"; - height = 16; - } - 420 - { - title = "Emerald 1 (Green)"; - sprite = "cemga0"; - height = 16; - } - 421 - { - title = "Emerald 2 (Orange)"; - sprite = "cemoa0"; - height = 16; - } - 422 - { - title = "Emerald 3 (Pink)"; - sprite = "cempa0"; - height = 16; - } - 423 - { - title = "Emerald 4 (Blue)"; - sprite = "cemba0"; - height = 16; - } - 424 - { - title = "Emerald 5 (Red)"; - sprite = "cemra0"; - height = 16; - } - 425 - { - title = "Emerald 6 (Light Blue)"; - sprite = "cemla0"; - height = 16; - } - 426 - { - title = "Emerald 7 (Grey)"; - sprite = "cemya0"; - height = 16; - } - 427 - { - title = "Emerald 8 (Master)"; - sprite = "cemka0"; - height = 16; - } - } - - springs //------------------------------------------------------------------------------------------ - { - color = 12; // Light Red - arrow = 1; - title = "Springs and Other Vertical Boosters"; - width = 20; - sort = 2; - - 28 - { - title = "Yellow Spring (384 units high)"; - sprite = "SPRYA0"; - height = 32; - } - 65 - { - title = "Yellow Spring Down"; - sprite = "SUDYA0"; - height = 32; - hangs = 1; - } - 2015 - { - title = "Yellow Spring Diagonal Up"; - sprite = "YSPRD2"; - height = 41; - } - 20 - { - title = "Yellow Spring Diagonal Down"; - sprite = "YSUDE2"; - height = 41; - hangs = 1; - } - 79 - { - title = "Red Spring (1024 units high)"; - sprite = "SPRRA0"; - height = 32; - } - 66 - { - title = "Red Spring Down"; - sprite = "SUDRA0"; - height = 32; - hangs = 1; - } - 38 - { - title = "Red Spring Diagonal Up"; - sprite = "RSPRD2"; - height = 41; - } - 39 - { - title = "Red Spring Diagonal Down"; - sprite = "RSUDE2"; - height = 41; - hangs = 1; - } - 30 - { - title = "Gas Jet"; - sprite = "STEMD0"; - height = 80; - } - 32 - { - title = "Fan"; - sprite = "FANSA0"; - height = 24; - } - 5004 - { - title = "Blue Spring"; - sprite = "SPRBA0"; - height = 32; - } - } - - hazards //----------------------------------------------------------------------------------------------- - { - color = 5; // Magenta - arrow = 0; - title = "Hazards"; - width = 20; - sort = 2; - - 68 - { - title = "Spike"; - sprite = "USPKA0"; - height = 42; - } - 67 - { - title = "Hanging Spike"; - sprite = "DSPKA0"; - height = 42; - hangs = 1; - } - 23 - { - title = "Spiked ball"; - sprite = "SPIKA0"; - height = 32; - } - 24 - { - title = "Torch"; - sprite = "FLAMA0"; - height = 96; - } - 51 - { - title = "Laser"; - sprite = "LASRA0"; - height = 32; - } - - } - - others //--------------------------------------------------------------------------------------------------- - { - color = 6; // Brown - arrow = 1; - title = "Other Useful Things"; - width = 20; - sort = 2; - - 33 - { - title = "Air Bubbles"; - sprite = "BUBMA0"; - height = 31; - } - 3006 - { - title = "Star Post"; - sprite = "STPTA0"; - height = 96; - } - 2049 - { - title = "Capsule Center"; - sprite = "SQRLA1"; - height = 32; - } - 86 - { - title = "End Sign"; - sprite = "SIGNF0"; - height = 64; - width = 64; - } - 5001 = "Push"; - 5002 = "Pull"; - 5003 = "Teleport Destination"; - 5007 = "Alt View (Cut-Away)"; - } - - scenery //--------------------------------------------------------------------------------------------- - { - color = 2; // Green - arrow = 0; - title = "Scenery"; - width = 20; - sort = 2; - - 36 - { - title = "Orange Flower"; - sprite = "FWR1A0"; - height = 56; - } - 70 - { - title = "Sun-Flower"; - sprite = "FWR2A0"; - height = 128; - } - 73 - { - title = "Purple Budding Flower"; - sprite = "FWR3A0"; - height = 32; - } - 75 - { - title = "Small Tree"; - sprite = "BUS2A0"; - height = 64; - } - 74 - { - title = "Small Tree w/ Fruit"; - sprite = "BUS1A0"; - height = 64; - } - 2035 - { - title = "Polluted Flower"; - sprite = "THZPA0"; - height = 64; - } - 2001 - { - title = "Dead Flower"; - sprite = "FWR4A0"; - height = 56; - } - 81 - { - title = "Gargoyle"; - sprite = "GARGA1"; - height = 64; - } - 49 - { - title = "Chain"; - sprite = "CHANA0"; - height = 128; - hangs = 1; - } - 5 - { - title = "Christmas Pole"; - sprite = "XMS1A0"; - height = 64; - } - 13 - { - title = "Candy Cane"; - sprite = "XMS2A0"; - height = 72; - } - 6 - { - title = "Snow Man"; - sprite = "XMS3A0"; - height = 72; - } - } - - sounds //--------------------------------------------------------------------------------------------------- - { - color = 3; // Cyan - arrow = 0; - title = "Sounds and Lights"; - width = 16; - sort = 2; - - 14 = "Random Ambience"; - 43 = "Random Ambience 2"; - 2019 = "Water sound 3B (Small)"; - 2025 = "Water Sound 4A (Extra Large)"; - 2026 = "Water Sound 1A (Large)"; - 2023 = "Water Sound 2A (Medium)"; - 83 = "Water Sound 3A (Small)"; - 27 = "Water Sound 2 (Huge)"; - 2024 = "Water Sound 1B (Large)"; - 2045 = "Water Sound 2B (Medium)"; - - 2006 - { - title = "Alarm"; - sprite = "ALRMA0"; - height = 32; - hangs = 1; - } - 2003 = "Light Source"; - } - - Mario //------------------------------------------------------------------------------------------------- - { - color = 9; // Light Blue - arrow = 1; - title = "Mario themed items"; - - 10005 - { - title = "Coin"; - sprite = "COINB0"; - height = 28; - } - 50 - { - title= "Fire Flower"; - sprite = "FFWRB0"; - height = 32; - } - 10002 - { - title = "Mario Tree"; - sprite = "MUS1A0"; - height = 60; - } - 10003 - { - title = "Mario Tree (Tall)"; - sprite = "MUS2A0"; - height = 92; - } - 10004 - { - title = "Toad"; - sprite = "TOADA0"; - height = 46; - } - 12 - { - title = "Mario Bridge Axe"; - sprite = "MAXEA0"; - height = 32; - } - 10 - { - title = "Koopa Shell"; - sprite = "SHLLA0"; - height = 30; - } - 29 - { - title = "Leaping Fireball (AKA Puma)"; - sprite = "PUMAA0"; - height = 32; - } - 10000 - { - title = "Goomba"; - sprite = "GOOMB0"; - height = 48; - } - 10001 - { - title = "Blue Underground Goomba"; - sprite = "BGOMA0"; - height = 48; - } - 18 - { - title = "Bowser"; - width = 80; - sprite = "KOOPA0"; - height = 70; - } - } - -} diff --git a/extras/conf/udb/Kart2_UDMF.cfg b/extras/conf/udb/Kart2_UDMF.cfg new file mode 100644 index 000000000..3ea02325b --- /dev/null +++ b/extras/conf/udb/Kart2_UDMF.cfg @@ -0,0 +1,47 @@ +/************************************************************************\ + Ultimate Doom Builder Game Configuration for SRB2Kart +\************************************************************************/ + +// This is required to prevent accidental use of a different configuration +type = "Doom Builder 2 Game Configuration"; + +// This is the title to show for this game +game = "SRB2Kart v2.0 (UDMF)"; + +// This is the simplified game engine/sourceport name +engine = "zdoom"; + +// Settings common to all games and all map formats +include("Includes\\Kart2_common.cfg", "common"); + +// Settings common to text map format +include("Includes\\Kart2_common.cfg", "mapformat_udmf"); + +include("Includes\\Game_Kart2.cfg"); + +// Script lumps detection +scriptlumpnames +{ + include("Includes\\Kart2_misc.cfg", "scriptlumpnames"); +} + +// THING TYPES +thingtypes +{ + include("Includes\\Kart2_things.cfg"); +} + +//Default things filters +thingsfilters +{ + include("Includes\\Kart2_misc.cfg", "thingsfilters"); +} + +// ENUMERATIONS +// Each engine has its own additional thing types +// These are enumerated lists for linedef types and UDMF fields. +enums +{ + // Basic game enums + include("Includes\\Kart2_misc.cfg", "enums"); +} \ No newline at end of file diff --git a/extras/conf/udb/includes/Game_Kart2.cfg b/extras/conf/udb/includes/Game_Kart2.cfg new file mode 100644 index 000000000..f43cc51e1 --- /dev/null +++ b/extras/conf/udb/includes/Game_Kart2.cfg @@ -0,0 +1,77 @@ +// Default lump name for new map +defaultlumpname = "MAP01"; +//GZDB specific. Don't try to load lumps that don't exist. +basegame = "Doom"; + +//Sky textures for vanilla maps +defaultskytextures +{ + SKY1 = "MAP01,MAP02,MAP03,MAP33,MAP50,MAP60,MAPF0,MAPM0"; + SKY2 = "MAPM7,MAPMB"; + SKY4 = "MAP04,MAP06,MAP61,MAPF6,MAPM1"; + SKY6 = "MAP05,MAP51,MAPMA"; + SKY7 = "MAPM2,MAPM5"; + SKY8 = "MAP07,MAP08,MAP09,MAP52,MAP62,MAPF1"; + SKY10 = "MAP10,MAP12,MAP53,MAP63,MAPM3"; + SKY11 = "MAP11,MAPF7"; + SKY13 = "MAP13,MAP64"; + SKY14 = "MAP14"; + SKY15 = "MAP15,MAP54"; + SKY17 = "MAP70"; + SKY20 = "MAP32,MAP55,MAP65,MAPF2,MAPF5"; + SKY21 = "MAPM4"; + SKY22 = "MAP22,MAP23,MAP25,MAP26,MAP27,MAP56,MAP66,MAPF4,MAPM6"; + SKY30 = "MAP30"; + SKY31 = "MAP31"; + SKY35 = "MAP42"; + SKY40 = "MAP41,MAP71,MAPM9"; + SKY55 = "MAPF3,MAPM8"; + SKY68 = "MAPF8"; + SKY99 = "MAP57,MAPZ0"; + SKY159 = "MAP16"; + SKY172 = "MAP40"; + SKY300 = "MAP72"; + SKY301 = "MAP73"; +} + +// Skill levels +skills +{ + 0 = "Easy"; + 1 = "Normal"; + 2 = "Hard"; + 3 = "Master"; +} + +// Skins +skins +{ + sonic; + tails; + knuckles; + amy; + mighty; + fang; + eggman; + metalsonic; + motobug; +} + +// Gametypes +gametypes +{ + -1 = "Single Player"; + 0 = "Race"; + 1 = "Battle"; +} + +// Texture loading options +defaultwalltexture = "GFZROCK"; +defaultfloortexture = "GFZFLR01"; +defaultceilingtexture = "F_SKY1"; + +// Default texture sets +// (these are not required, but useful for new users) +texturesets +{ +} \ No newline at end of file diff --git a/extras/conf/udb/includes/Kart2_common.cfg b/extras/conf/udb/includes/Kart2_common.cfg new file mode 100644 index 000000000..5b4f645cf --- /dev/null +++ b/extras/conf/udb/includes/Kart2_common.cfg @@ -0,0 +1,172 @@ +common +{ + // Simulate Doom brightness levels (turn this off for linear lighting) + doomlightlevels = true; + + // Enables support for long (> 8 chars) texture names + // WARNING: this should only be enabled for UDMF game configurations! + // WARNING: enabling this will make maps incompatible with Doom Builder 2 and can lead to problems in Slade 3! + longtexturenames = true; + + // These directory names are ignored when loading PK3/PK7/Directory resources + ignoreddirectories = ".svn .git"; + + // Files with these extensions are ignored when loading PK3/PK7/Directory resources + ignoredextensions = "wad pk3 pk7 bak backup1 backup2 backup3 zip rar 7z"; + + // Default testing parameters + testparameters = "-file \"%AP\" \"%F\" -warp %L"; + testshortpaths = true; + + // Action special help + actionspecialhelp = "https://wiki.srb2.org/wiki/Linedef_type_%K"; + + // Generalized actions + generalizedlinedefs = false; + generalizedsectors = true; + + // Maximum safe map size check (0 means skip check) + safeboundary = 1; + + // Map boundaries. Map objects can only be placed within these boundaries + leftboundary = -32768; + rightboundary = 32767; + topboundary = 32767; + bottomboundary = -32768; + + // Texture loading options + mixtexturesflats = true; + defaulttexturescale = 1.0f; + defaultflatscale = 1.0f; + scaledtextureoffsets = true; + + // Thing number for start position in 3D Mode + start3dmode = 3328; + + // Texture sources + textures + { + include("Kart2_misc.cfg", "textures"); + } + + // Patch sources + patches + { + include("Kart2_misc.cfg", "patches"); + } + + // Sprite sources + sprites + { + include("Kart2_misc.cfg", "sprites"); + } + + // Flat sources + flats + { + include("Kart2_misc.cfg", "flats"); + } +} + +mapformat_udmf +{ + // The format interface handles the map data format + formatinterface = "UniversalMapSetIO"; + + // Default nodebuilder configurations + defaultsavecompiler = "zdbsp_udmf_normal"; + defaulttestcompiler = "zdbsp_udmf_fast"; + + // Determines the textmap namespace + engine = "srb2kart"; + + maplumpnames + { + include("UDMF_misc.cfg", "udmfmaplumpnames_begin"); + include("Kart2_misc.cfg", "udmfmaplumpnames"); + include("UDMF_misc.cfg", "udmfmaplumpnames_end"); + } + + universalfields + { + include("Kart2_misc.cfg", "universalfields"); + } + + // When this is set to true, sectors with the same tag will light up when a line is highlighted + linetagindicatesectors = false; + + // Special linedefs + include("Kart2_misc.cfg", "speciallinedefs_udmf"); + + // Default flags for first new thing + defaultthingflags + { + } + + // SECTOR FLAGS + sectorflags + { + include("Kart2_misc.cfg", "sectorflags"); + } + + // DEFAULT SECTOR BRIGHTNESS LEVELS + sectorbrightness + { + include("Kart2_misc.cfg", "sectorbrightness"); + } + + // SECTOR TYPES + sectortypes + { + include("Kart2_sectors.cfg", "sectortypes"); + } + + // GENERALISED SECTOR TYPES + gen_sectortypes + { + include("Kart2_sectors.cfg", "gen_sectortypes"); + } + + // LINEDEF FLAGS + linedefflags + { + include("Kart2_misc.cfg", "linedefflags_udmf"); + } + + linedefflagstranslation + { + include("Kart2_misc.cfg", "linedefflagstranslation"); + } + + // LINEDEF RENDERSTYLES + /*linedefrenderstyles + { + include("Kart2_misc.cfg", "linedefrenderstyles"); + }*/ + + // THING FLAGS + thingflags + { + include("Kart2_misc.cfg", "thingflags_udmf"); + } + + // Thing flags UDMF translation table + // This is needed for copy/paste and prefabs to work properly + // When the UDMF field name is prefixed with ! it is inverted + thingflagstranslation + { + include("Kart2_misc.cfg", "thingflagstranslation"); + } + + // How to compare thing flags (for the stuck things error checker) + thingflagscompare + { + include("UDMF_misc.cfg", "thingflagscompare"); + } + + // LINEDEF TYPES + linedeftypes + { + include("Kart2_linedefs.cfg", "udmf"); + } +} \ No newline at end of file diff --git a/extras/conf/udb/includes/Kart2_linedefs.cfg b/extras/conf/udb/includes/Kart2_linedefs.cfg new file mode 100644 index 000000000..0b92442e6 --- /dev/null +++ b/extras/conf/udb/includes/Kart2_linedefs.cfg @@ -0,0 +1,2508 @@ +doom +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + 1 + { + title = "Per-Sector Gravity"; + prefix = "(1)"; + } + 5 + { + title = "Camera Scanner"; + prefix = "(5)"; + } + 7 + { + title = "Sector Flat Alignment"; + prefix = "(7)"; + } + 10 + { + title = "Culling Plane"; + prefix = "(10)"; + } + 13 + { + title = "Heat Wave Effect"; + prefix = "(13)"; + } + 40 + { + title = "Visual Portal Between Tagged Linedefs"; + prefix = "(40)"; + } + 41 + { + title = "Horizon Effect"; + prefix = "(41)"; + } + 50 + { + title = "Instantly Lower Floor on Level Load"; + prefix = "(50)"; + } + 51 + { + title = "Instantly Raise Ceiling on Level Load"; + prefix = "(51)"; + } + 63 + { + title = "Fake Floor/Ceiling Planes"; + prefix = "(63)"; + } + 540 + { + title = "Floor Friction"; + prefix = "(540)"; + } + } + + parameters + { + title = "Parameters"; + + 2 + { + title = "Custom Exit"; + prefix = "(2)"; + } + 3 + { + title = "Zoom Tube Parameters"; + prefix = "(3)"; + } + 4 + { + title = "Speed Pad Parameters"; + prefix = "(4)"; + } + 8 + { + title = "Special Sector Properties"; + prefix = "(8)"; + } + 9 + { + title = "Chain Parameters"; + prefix = "(9)"; + } + 11 + { + title = "Rope Hang Parameters"; + prefix = "(11)"; + } + 12 + { + title = "Rock Spawner Parameters"; + prefix = "(12)"; + } + 14 + { + title = "Bustable Block Parameters"; + prefix = "(14)"; + } + 15 + { + title = "Fan Particle Spawner Parameters"; + prefix = "(15)"; + } + 16 + { + title = "Minecart Parameters"; + prefix = "(16)"; + } + 64 + { + title = "Continuously Appearing/Disappearing FOF"; + prefix = "(64)"; + } + 65 + { + title = "Bridge Thinker "; + prefix = "(65)"; + } + 76 + { + title = "Make FOF Bouncy"; + prefix = "(76)"; + } + } + + polyobject + { + title = "PolyObject"; + + 20 + { + title = "First Line"; + prefix = "(20)"; + } + 21 + { + title = "Explicitly Include Line "; + prefix = "(21)"; + } + 22 + { + title = "Parameters"; + prefix = "(22)"; + } + 30 + { + title = "Waving Flag"; + prefix = "(30)"; + } + 31 + { + title = "Displacement by Front Sector"; + prefix = "(31)"; + } + 32 + { + title = "Angular Displacement by Front Sector"; + prefix = "(32)"; + } + } + + planemove + { + title = "Plane Movement"; + + 52 + { + title = "Continuously Falling Sector"; + prefix = "(52)"; + } + 53 + { + title = "Continuous Floor/Ceiling Mover"; + prefix = "(53)"; + } + 54 + { + title = "Continuous Floor Mover"; + prefix = "(54)"; + } + 55 + { + title = "Continuous Ceiling Mover"; + prefix = "(55)"; + } + 56 + { + title = "Continuous Two-Speed Floor/Ceiling Mover"; + prefix = "(56)"; + } + 57 + { + title = "Continuous Two-Speed Floor Mover"; + prefix = "(57)"; + } + 58 + { + title = "Continuous Two-Speed Ceiling Mover"; + prefix = "(58)"; + } + 59 + { + title = "Activate Moving Platform"; + prefix = "(59)"; + } + 60 + { + title = "Activate Moving Platform (Adjustable Speed)"; + prefix = "(60)"; + } + 61 + { + title = "Crusher (Ceiling to Floor)"; + prefix = "(61)"; + } + 62 + { + title = "Crusher (Floor to Ceiling)"; + prefix = "(62)"; + } + 66 + { + title = "Move Floor by Displacement"; + prefix = "(66)"; + } + 67 + { + title = "Move Ceiling by Displacement"; + prefix = "(67)"; + } + 68 + { + title = "Move Floor and Ceiling by Displacement"; + prefix = "(68)"; + } + } + + fofsolid + { + title = "FOF (solid)"; + + 100 + { + title = "Solid, Opaque"; + prefix = "(100)"; + } + 101 + { + title = "Solid, Opaque, No Shadow"; + prefix = "(101)"; + } + 102 + { + title = "Solid, Translucent"; + prefix = "(102)"; + } + 103 + { + title = "Solid, Sides Only"; + prefix = "(103)"; + } + 104 + { + title = "Solid, No Sides"; + prefix = "(104)"; + } + 105 + { + title = "Solid, Invisible"; + prefix = "(105)"; + } + 140 + { + title = "Intangible from Bottom, Opaque"; + prefix = "(140)"; + } + 141 + { + title = "Intangible from Bottom, Translucent"; + prefix = "(141)"; + } + 142 + { + title = "Intangible from Bottom, Translucent, No Sides"; + prefix = "(142)"; + } + 143 + { + title = "Intangible from Top, Opaque"; + prefix = "(143)"; + } + 144 + { + title = "Intangible from Top, Translucent"; + prefix = "(144)"; + } + 145 + { + title = "Intangible from Top, Translucent, No Sides"; + prefix = "(145)"; + } + 146 + { + title = "Only Tangible from Sides"; + prefix = "(146)"; + } + } + + fofintangible + { + title = "FOF (intangible)"; + + 120 + { + title = "Water, Opaque"; + prefix = "(120)"; + } + 121 + { + title = "Water, Translucent"; + prefix = "(121)"; + } + 122 + { + title = "Water, Opaque, No Sides"; + prefix = "(122)"; + } + 123 + { + title = "Water, Translucent, No Sides"; + prefix = "(123)"; + } + 124 + { + title = "Goo Water, Translucent"; + prefix = "(124)"; + } + 125 + { + title = "Goo Water, Translucent, No Sides"; + prefix = "(125)"; + } + 220 + { + title = "Intangible, Opaque"; + prefix = "(220)"; + } + 221 + { + title = "Intangible, Translucent"; + prefix = "(221)"; + } + 222 + { + title = "Intangible, Sides Only"; + prefix = "(222)"; + } + 223 + { + title = "Intangible, Invisible"; + prefix = "(223)"; + } + } + + fofmoving + { + title = "FOF (moving)"; + + 150 + { + title = "Air Bobbing"; + prefix = "(150)"; + } + 151 + { + title = "Air Bobbing (Adjustable)"; + prefix = "(151)"; + } + 152 + { + title = "Reverse Air Bobbing (Adjustable)"; + prefix = "(152)"; + } + 153 + { + title = "Dynamically Sinking Platform"; + prefix = "(153)"; + } + 160 + { + title = "Water Bobbing"; + prefix = "(160)"; + } + 190 + { + title = "Rising Platform, Solid, Opaque"; + prefix = "(190)"; + } + 191 + { + title = "Rising Platform, Solid, Opaque, No Shadow"; + prefix = "(191)"; + } + 192 + { + title = "Rising Platform, Solid, Translucent"; + prefix = "(192)"; + } + 193 + { + title = "Rising Platform, Solid, Invisible"; + prefix = "(193)"; + } + 194 + { + title = "Rising Platform, Intangible from Bottom, Opaque"; + prefix = "(194)"; + } + 195 + { + title = "Rising Platform, Intangible from Bottom, Translucent"; + prefix = "(195)"; + } + } + + fofcrumbling + { + title = "FOF (crumbling)"; + + 170 + { + title = "Crumbling, Respawn"; + prefix = "(170)"; + } + 171 + { + title = "Crumbling, No Respawn"; + prefix = "(171)"; + } + 172 + { + title = "Crumbling, Respawn, Intangible from Bottom"; + prefix = "(172)"; + } + 173 + { + title = "Crumbling, No Respawn, Intangible from Bottom"; + prefix = "(173)"; + } + 174 + { + title = "Crumbling, Respawn, Int. from Bottom, Translucent"; + prefix = "(174)"; + } + 175 + { + title = "Crumbling, No Respawn, Int. from Bottom, Translucent"; + prefix = "(175)"; + } + 176 + { + title = "Crumbling, Respawn, Floating, Bobbing"; + prefix = "(176)"; + } + 177 + { + title = "Crumbling, No Respawn, Floating, Bobbing"; + prefix = "(177)"; + } + 178 + { + title = "Crumbling, Respawn, Floating"; + prefix = "(178)"; + } + 179 + { + title = "Crumbling, No Respawn, Floating"; + prefix = "(179)"; + } + 180 + { + title = "Crumbling, Respawn, Air Bobbing"; + prefix = "(180)"; + } + } + + fofspecial + { + title = "FOF (special)"; + + 200 + { + title = "Light Block"; + prefix = "(200)"; + } + 201 + { + title = "Half Light Block"; + prefix = "(201)"; + } + 202 + { + title = "Fog Block"; + prefix = "(202)"; + } + 250 + { + title = "Mario Block"; + prefix = "(250)"; + } + 251 + { + title = "Thwomp Block"; + prefix = "(251)"; + } + 252 + { + title = "Shatter Block"; + prefix = "(252)"; + } + 253 + { + title = "Shatter Block, Translucent"; + prefix = "(253)"; + } + 254 + { + title = "Bustable Block"; + prefix = "(254)"; + } + 255 + { + title = "Spin-Bustable Block"; + prefix = "(255)"; + } + 256 + { + title = "Spin-Bustable Block, Translucent"; + prefix = "(256)"; + } + 257 + { + title = "Quicksand"; + prefix = "(257)"; + } + 258 + { + title = "Laser"; + prefix = "(258)"; + } + 259 + { + title = "Custom FOF"; + prefix = "(259)"; + } + } + + linedeftrigger + { + title = "Linedef Executor Trigger"; + + 300 + { + title = "Continuous"; + prefix = "(300)"; + } + 301 + { + title = "Each Time"; + prefix = "(301)"; + } + 302 + { + title = "Once"; + prefix = "(302)"; + } + 303 + { + title = "Ring Count - Continuous"; + prefix = "(303)"; + } + 304 + { + title = "Ring Count - Once"; + prefix = "(304)"; + } + 305 + { + title = "Character Ability - Continuous"; + prefix = "(305)"; + } + 306 + { + title = "Character Ability - Each Time"; + prefix = "(306)"; + } + 307 + { + title = "Character Ability - Once"; + prefix = "(307)"; + } + 308 + { + title = "Race Only - Once"; + prefix = "(308)"; + } + 309 + { + title = "CTF Red Team - Continuous"; + prefix = "(309)"; + } + 310 + { + title = "CTF Red Team - Each Time"; + prefix = "(310)"; + } + 311 + { + title = "CTF Blue Team - Continuous"; + prefix = "(311)"; + } + 312 + { + title = "CTF Blue Team - Each Time"; + prefix = "(312)"; + } + 313 + { + title = "No More Enemies - Once"; + prefix = "(313)"; + } + 314 + { + title = "Number of Pushables - Continuous"; + prefix = "(314)"; + } + 315 + { + title = "Number of Pushables - Once"; + prefix = "(315)"; + } + 317 + { + title = "Condition Set Trigger - Continuous"; + prefix = "(317)"; + } + 318 + { + title = "Condition Set Trigger - Once"; + prefix = "(318)"; + } + 319 + { + title = "Unlockable - Continuous"; + prefix = "(319)"; + } + 320 + { + title = "Unlockable - Once"; + prefix = "(320)"; + } + 321 + { + title = "Trigger After X Calls - Continuous"; + prefix = "(321)"; + } + 322 + { + title = "Trigger After X Calls - Each Time"; + prefix = "(322)"; + } + 323 + { + title = "NiGHTSerize - Each Time"; + prefix = "(323)"; + } + 324 + { + title = "NiGHTSerize - Once"; + prefix = "(324)"; + } + 325 + { + title = "De-NiGHTSerize - Each Time"; + prefix = "(325)"; + } + 326 + { + title = "De-NiGHTSerize - Once"; + prefix = "(326)"; + } + 327 + { + title = "NiGHTS Lap - Each Time"; + prefix = "(327)"; + } + 328 + { + title = "NiGHTS Lap - Once"; + prefix = "(328)"; + } + 329 + { + title = "Ideya Capture Touch - Each Time"; + prefix = "(329)"; + } + 330 + { + title = "Ideya Capture Touch - Once"; + prefix = "(330)"; + } + 331 + { + title = "Player Skin - Continuous"; + flags64text = "[6] Disable for this skin"; + prefix = "(331)"; + } + 332 + { + title = "Player Skin - Each Time"; + prefix = "(332)"; + } + 333 + { + title = "Player Skin - Once"; + prefix = "(333)"; + } + 399 + { + title = "Level Load"; + prefix = "(399)"; + } + } + + linedefexecsector + { + title = "Linedef Executor (sector)"; + + 400 + { + title = "Set Tagged Sector's Floor Height/Texture"; + prefix = "(400)"; + } + 401 + { + title = "Set Tagged Sector's Ceiling Height/Texture"; + prefix = "(401)"; + } + 402 + { + title = "Set Tagged Sector's Light Level"; + prefix = "(402)"; + } + 409 + { + title = "Change Tagged Sector's Tag"; + prefix = "(409)"; + } + 410 + { + title = "Change Front Sector's Tag"; + prefix = "(410)"; + } + 416 + { + title = "Start Adjustable Flickering Light"; + prefix = "(416)"; + } + 417 + { + title = "Start Adjustable Pulsating Light"; + prefix = "(417)"; + } + 418 + { + title = "Start Adjustable Blinking Light (unsynchronized)"; + prefix = "(418)"; + } + 419 + { + title = "Start Adjustable Blinking Light (synchronized)"; + prefix = "(419)"; + } + 420 + { + title = "Fade Light Level"; + prefix = "(420)"; + } + 421 + { + title = "Stop Lighting Effect"; + prefix = "(421)"; + } + 435 + { + title = "Change Plane Scroller Direction"; + prefix = "(435)"; + } + } + + linedefexecplane + { + title = "Linedef Executor (plane movement)"; + + 403 + { + title = "Move Tagged Sector's Floor"; + prefix = "(403)"; + } + 404 + { + title = "Move Tagged Sector's Ceiling"; + prefix = "(404)"; + } + 405 + { + title = "Move Floor According to Front Texture Offsets"; + prefix = "(405)"; + } + 407 + { + title = "Move Ceiling According to Front Texture Offsets"; + prefix = "(407)"; + } + 411 + { + title = "Stop Plane Movement"; + prefix = "(411)"; + } + 428 + { + title = "Start Platform Movement"; + prefix = "(428)"; + } + 429 + { + title = "Crush Ceiling Once"; + prefix = "(429)"; + } + 430 + { + title = "Crush Floor Once"; + prefix = "(430)"; + } + 431 + { + title = "Crush Floor and Ceiling Once"; + prefix = "(431)"; + } + } + + linedefexecplayer + { + title = "Linedef Executor (player/object)"; + + 412 + { + title = "Teleporter"; + prefix = "(412)"; + } + 425 + { + title = "Change Object State"; + prefix = "(425)"; + } + 426 + { + title = "Stop Object"; + prefix = "(426)"; + } + 427 + { + title = "Award Score"; + prefix = "(427)"; + } + 432 + { + title = "Enable/Disable 2D Mode"; + prefix = "(432)"; + } + 433 + { + title = "Enable/Disable Gravity Flip"; + prefix = "(433)"; + } + 434 + { + title = "Award Power-Up"; + prefix = "(434)"; + } + 437 + { + title = "Disable Player Control"; + prefix = "(437)"; + } + 438 + { + title = "Change Object Size"; + prefix = "(438)"; + } + 442 + { + title = "Change Object Type State"; + prefix = "(442)"; + } + 457 + { + title = "Track Object's Angle"; + prefix = "(457)"; + } + 458 + { + title = "Stop Tracking Object's Angle"; + prefix = "(458)"; + } + 460 + { + title = "Award Rings"; + prefix = "(460)"; + } + 461 + { + title = "Spawn Object"; + prefix = "(461)"; + } + 462 + { + title = "Stop Timer/Exit Stage in Record Attack"; + prefix = "(462)"; + } + } + + linedefexecmisc + { + title = "Linedef Executor (misc.)"; + + 413 + { + title = "Change Music"; + prefix = "(413)"; + } + 414 + { + title = "Play Sound Effect"; + prefix = "(414)"; + } + 415 + { + title = "Run Script"; + prefix = "(415)"; + } + 422 + { + title = "Switch to Cut-Away View"; + prefix = "(422)"; + } + 423 + { + title = "Change Sky"; + prefix = "(423)"; + } + 424 + { + title = "Change Weather"; + prefix = "(424)"; + } + 436 + { + title = "Shatter FOF"; + prefix = "(436)"; + } + 439 + { + title = "Change Tagged Linedef's Textures"; + prefix = "(439)"; + } + 440 + { + title = "Start Metal Sonic Race"; + prefix = "(440)"; + } + 441 + { + title = "Condition Set Trigger"; + prefix = "(441)"; + } + 443 + { + title = "Call Lua Function"; + prefix = "(443)"; + } + 444 + { + title = "Earthquake"; + prefix = "(444)"; + } + 445 + { + title = "Make FOF Disappear/Reappear"; + prefix = "(445)"; + } + 446 + { + title = "Make FOF Crumble"; + prefix = "(446)"; + } + 447 + { + title = "Change Tagged Sector's Colormap"; + prefix = "(447)"; + } + 448 + { + title = "Change Skybox"; + prefix = "(448)"; + } + 449 + { + title = "Enable Bosses with Parameter"; + prefix = "(449)"; + } + 450 + { + title = "Execute Linedef Executor (specific tag)"; + prefix = "(450)"; + } + 451 + { + title = "Execute Linedef Executor (random tag in range)"; + prefix = "(451)"; + } + 452 + { + title = "Set FOF Translucency"; + prefix = "(452)"; + } + 453 + { + title = "Fade FOF"; + prefix = "(453)"; + } + 454 + { + title = "Stop Fading FOF"; + prefix = "(454)"; + } + 455 + { + title = "Fade Tagged Sector's Colormap"; + prefix = "(455)"; + } + 456 + { + title = "Stop Fading Tagged Sector's Colormap"; + prefix = "(456)"; + } + 459 + { + title = "Control Text Prompt"; + prefix = "(459)"; + } + } + + linedefexecpoly + { + title = "Linedef Executor (polyobject)"; + + 480 + { + title = "Door Slide"; + prefix = "(480)"; + } + 481 + { + title = "Door Swing"; + prefix = "(481)"; + } + 482 + { + title = "Move"; + prefix = "(482)"; + } + 483 + { + title = "Move, Override"; + prefix = "(483)"; + } + 484 + { + title = "Rotate Right"; + prefix = "(484)"; + } + 485 + { + title = "Rotate Right, Override"; + prefix = "(485)"; + } + 486 + { + title = "Rotate Left"; + prefix = "(486)"; + } + 487 + { + title = "Rotate Left, Override"; + prefix = "(487)"; + } + 488 + { + title = "Move by Waypoints"; + prefix = "(488)"; + } + 489 + { + title = "Turn Invisible, Intangible"; + prefix = "(489)"; + } + 490 + { + title = "Turn Visible, Tangible"; + prefix = "(490)"; + } + 491 + { + title = "Set Translucency"; + prefix = "(491)"; + } + 492 + { + title = "Fade Translucency"; + prefix = "(492)"; + } + } + + wallscroll + { + title = "Wall Scrolling"; + + 500 + { + title = "Scroll Wall Front Side Left"; + prefix = "(500)"; + } + 501 + { + title = "Scroll Wall Front Side Right"; + prefix = "(501)"; + } + 502 + { + title = "Scroll Wall According to Linedef"; + prefix = "(502)"; + } + 503 + { + title = "Scroll Wall According to Linedef (Accelerative)"; + prefix = "(503)"; + } + 504 + { + title = "Scroll Wall According to Linedef (Displacement)"; + prefix = "(504)"; + } + 505 + { + title = "Scroll Texture by Front Side Offsets"; + prefix = "(505)"; + } + 506 + { + title = "Scroll Texture by Back Side Offsets"; + prefix = "(506)"; + } + } + + planescroll + { + title = "Plane Scrolling"; + + 510 + { + title = "Scroll Floor Texture"; + prefix = "(510)"; + } + 511 + { + title = "Scroll Floor Texture (Accelerative)"; + prefix = "(511)"; + } + 512 + { + title = "Scroll Floor Texture (Displacement)"; + prefix = "(512)"; + } + 513 + { + title = "Scroll Ceiling Texture"; + prefix = "(513)"; + } + 514 + { + title = "Scroll Ceiling Texture (Accelerative)"; + prefix = "(514)"; + } + 515 + { + title = "Scroll Ceiling Texture (Displacement)"; + prefix = "(515)"; + } + 520 + { + title = "Carry Objects on Floor"; + prefix = "(520)"; + } + 521 + { + title = "Carry Objects on Floor (Accelerative)"; + prefix = "(521)"; + } + 522 + { + title = "Carry Objects on Floor (Displacement)"; + prefix = "(522)"; + } + 523 + { + title = "Carry Objects on Ceiling"; + prefix = "(523)"; + } + 524 + { + title = "Carry Objects on Ceiling (Accelerative)"; + prefix = "(524)"; + } + 525 + { + title = "Carry Objects on Ceiling (Displacement)"; + prefix = "(525)"; + } + 530 + { + title = "Scroll Floor Texture and Carry Objects"; + prefix = "(530)"; + } + 531 + { + title = "Scroll Floor Texture and Carry Objects (Accelerative)"; + prefix = "(531)"; + } + 532 + { + title = "Scroll Floor Texture and Carry Objects (Displacement)"; + prefix = "(532)"; + } + 533 + { + title = "Scroll Ceiling Texture and Carry Objects"; + prefix = "(533)"; + } + 534 + { + title = "Scroll Ceiling Texture and Carry Objects (Accelerative)"; + prefix = "(534)"; + } + 535 + { + title = "Scroll Ceiling Texture and Carry Objects (Displacement)"; + prefix = "(535)"; + } + } + + pusher + { + title = "Pusher"; + + 541 + { + title = "Wind"; + prefix = "(541)"; + } + 542 + { + title = "Upwards Wind"; + prefix = "(542)"; + } + 543 + { + title = "Downwards Wind"; + prefix = "(543)"; + } + 544 + { + title = "Current"; + prefix = "(544)"; + } + 545 + { + title = "Upwards Current"; + prefix = "(545)"; + } + 546 + { + title = "Downwards Current"; + prefix = "(546)"; + } + 547 + { + title = "Push/Pull"; + prefix = "(547)"; + } + } + + light + { + title = "Lighting"; + + 600 + { + title = "Floor Lighting"; + prefix = "(600)"; + } + 601 + { + title = "Ceiling Lighting"; + prefix = "(601)"; + } + 602 + { + title = "Adjustable Pulsating Light"; + prefix = "(602)"; + } + 603 + { + title = "Adjustable Flickering Light"; + prefix = "(603)"; + } + 604 + { + title = "Adjustable Blinking Light (unsynchronized)"; + prefix = "(604)"; + } + 605 + { + title = "Adjustable Blinking Light (synchronized)"; + prefix = "(605)"; + } + 606 + { + title = "Colormap"; + prefix = "(606)"; + } + } + + slope + { + title = "Slope"; + + 700 + { + title = "Slope Frontside Floor"; + prefix = "(700)"; + } + 701 + { + title = "Slope Frontside Ceiling"; + prefix = "(701)"; + } + 702 + { + title = "Slope Frontside Floor and Ceiling"; + prefix = "(702)"; + } + 703 + { + title = "Slope Frontside Floor and Backside Ceiling"; + prefix = "(703)"; +´ } + 704 + { + title = "Slope Frontside Floor by 3 Tagged Vertex Things"; + prefix = "(704)"; + } + 705 + { + title = "Slope Frontside Ceiling by 3 Tagged Vertex Things"; + prefix = "(705)"; + } + 710 + { + title = "Slope Backside Floor"; + prefix = "(710)"; + } + 711 + { + title = "Slope Backside Ceiling"; + prefix = "(711)"; + } + 712 + { + title = "Slope Backside Floor and Ceiling"; + prefix = "(712)"; + } + 713 + { + title = "Slope Backside Floor and Frontside Ceiling"; + prefix = "(713)"; + } + 714 + { + title = "Slope Backside Floor by 3 Tagged Vertex Things"; + prefix = "(714)"; + } + 715 + { + title = "Slope Backside Ceiling by 3 Tagged Vertex Things"; + prefix = "(715)"; + } + 720 + { + title = "Copy Frontside Floor Slope from Line Tag"; + prefix = "(720)"; + } + 721 + { + title = "Copy Frontside Ceiling Slope from Line Tag"; + prefix = "(721)"; + } + 722 + { + title = "Copy Frontside Floor and Ceiling Slope from Line Tag"; + prefix = "(722)"; + } + 799 + { + title = "Set Tagged Dynamic Slope Vertex to Front Sector Height"; + prefix = "(799)"; + } + } + + transwall + { + title = "Translucent Wall"; + + 900 + { + title = "90% Opaque"; + prefix = "(900)"; + } + 901 + { + title = "80% Opaque"; + prefix = "(901)"; + } + 902 + { + title = "70% Opaque"; + prefix = "(902)"; + } + 903 + { + title = "60% Opaque"; + prefix = "(903)"; + } + 904 + { + title = "50% Opaque"; + prefix = "(904)"; + } + 905 + { + title = "40% Opaque"; + prefix = "(905)"; + } + 906 + { + title = "30% Opaque"; + prefix = "(906)"; + } + 907 + { + title = "20% Opaque"; + prefix = "(907)"; + } + 908 + { + title = "10% Opaque"; + prefix = "(908)"; + } + 909 + { + title = "Fog Wall"; + prefix = "(909)"; + } + } +} + +udmf +{ + misc + { + title = "Miscellaneous"; + + 0 + { + title = "None"; + prefix = "(0)"; + } + } + + polyobject + { + title = "PolyObject"; + + 20 + { + title = "First Line"; + prefix = "(20)"; + arg0 + { + title = "PolyObject ID"; + type = 14; + } + arg1 + { + title = "Parent ID"; + type = 14; + } + arg2 + { + title = "Translucency"; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Don't render insides"; + 2 = "Intangible"; + 4 = "Stopped by pushables"; + 8 = "Don't render planes"; + 16 = "Trigger linedef executor on touch"; + 32 = "Crush player"; + 64 = "Cut cyan flat pixels"; + } + } + arg4 + { + title = "Trigger linedef tag"; + type = 15; + } + } + } + + fofmodifiers + { + title = "FOF Modifiers"; + + 70 + { + title = "Add Raise Thinker"; + prefix = "(70)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Speed"; + } + arg2 + { + title = "Destination height"; + } + arg3 + { + title = "Require spindash?"; + type = 11; + enum = "noyes"; + } + } + + 71 + { + title = "Add Air Bobbing Thinker"; + prefix = "(71)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Bobbing distance"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Raise"; + 2 = "Require spindash"; + 4 = "Dynamic"; + } + } + } + + 72 + { + title = "Add Thwomp Thinker"; + prefix = "(72)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Falling speed"; + } + arg2 + { + title = "Rising speed"; + } + stringarg0 + { + title = "Crushing sound"; + type = 2; + } + } + + 73 + { + title = "Add Laser Thinker"; + prefix = "(73)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Damage bosses?"; + type = 11; + enum = "yesno"; + } + } + + 74 + { + title = "Make FOF Bustable"; + prefix = "(74)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Bustable type"; + type = 11; + enum + { + 0 = "Touch"; + 1 = "Spin"; + 2 = "Regular"; + 3 = "Strong"; + } + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bustable by pushables"; + 2 = "Trigger linedef executor"; + 4 = "Only bustable from below"; + } + } + arg3 + { + title = "Linedef executor tag"; + type = 15; + } + } + + 75 + { + title = "Make FOF Quicksand"; + prefix = "(75)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Sinking speed"; + } + arg2 + { + title = "Friction"; + } + } + + 76 + { + title = "Make FOF Bouncy"; + prefix = "(76)"; + arg0 + { + title = "Control linedef tag"; + type = 15; + } + arg1 + { + title = "Bounce strength"; + } + arg2 + { + title = "Dampen?"; + type = 11; + enum = "noyes"; + } + } + } + + fof + { + title = "FOF"; + + 100 + { + title = "Solid"; + prefix = "(100)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Appearance"; + type = 12; + enum + { + 1 = "Don't render planes"; + 2 = "Don't render sides"; + 4 = "Render insides"; + 8 = "Render only insides"; + 16 = "No shadow"; + 32 = "Cut cyan flat pixels"; + } + } + arg3 + { + title = "Tangibility"; + type = 12; + enum = "tangibility"; + } + } + + 120 + { + title = "Water"; + prefix = "(120)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Alpha"; + default = 128; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Don't render sides"; + 2 = "Render separate light level"; + 4 = "Use target light level"; + 8 = "No ripple effect"; + 16 = "Goo physics"; + 32 = "Cut cyan flat pixels"; + } + } + } + + 150 + { + title = "Air Bobbing"; + prefix = "(150)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Bobbing distance"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Raise"; + 2 = "Require spindash"; + 4 = "Dynamic"; + } + } + } + + 160 + { + title = "Water Bobbing"; + prefix = "(160)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + + 170 + { + title = "Crumbling"; + prefix = "(170)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Tangibility"; + type = 12; + enum = "tangibility"; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "No shadow"; + 2 = "No respawn"; + 4 = "Air bobbing"; + 8 = "Float on water"; + 16 = "Cut cyan flat pixels"; + } + } + } + + 190 + { + title = "Rising"; + prefix = "(190)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Appearance"; + type = 12; + enum + { + 1 = "Don't render planes"; + 2 = "Don't render sides"; + 4 = "Render insides"; + 8 = "Render only insides"; + 16 = "No shadow"; + 32 = "Cut cyan flat pixels"; + } + } + arg3 + { + title = "Tangibility"; + type = 12; + enum = "tangibility"; + } + arg4 + { + title = "Speed"; + } + arg5 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Lower"; + 2 = "Require spindash"; + } + } + } + + 200 + { + title = "Light Block"; + prefix = "(200)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Expand to bottom?"; + type = 11; + enum = "noyes"; + } + } + + 202 + { + title = "Fog Block"; + prefix = "(202)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + + 220 + { + title = "Intangible"; + prefix = "(220)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Appearance"; + type = 12; + enum + { + 1 = "Don't render planes"; + 2 = "Don't render sides"; + 4 = "Don't render insides"; + 8 = "Render only insides"; + 16 = "No shadow"; + 32 = "Cut cyan flat pixels"; + } + } + } + + 223 + { + title = "Intangible, Invisible"; + prefix = "(223)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + + 250 + { + title = "Mario Block"; + prefix = "(250)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Block type"; + type = 12; + enum + { + 1 = "Brick"; + 2 = "Invisible"; + } + } + } + + 251 + { + title = "Thwomp Block"; + prefix = "(251)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Falling speed"; + } + arg2 + { + title = "Rising speed"; + } + stringarg0 + { + title = "Crushing sound"; + type = 2; + } + } + + 254 + { + title = "Bustable Block"; + prefix = "(254)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Bustable type"; + type = 11; + enum + { + 0 = "Touch"; + 1 = "Spin"; + 2 = "Regular"; + 3 = "Strong"; + } + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Bustable by pushables"; + 2 = "Trigger linedef executor"; + 4 = "Only bustable from below"; + 8 = "Cut cyan flat pixels"; + } + } + arg4 + { + title = "Linedef executor tag"; + type = 15; + } + } + + 257 + { + title = "Quicksand"; + prefix = "(257)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Ripple effect?"; + type = 11; + enum = "yesno"; + } + arg2 + { + title = "Sinking speed"; + } + arg3 + { + title = "Friction"; + } + } + + 258 + { + title = "Laser"; + prefix = "(258)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Alpha"; + default = 128; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Don't damage bosses"; + 2 = "Cut cyan flat pixels"; + } + } + } + + 259 + { + title = "Custom"; + prefix = "(259)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Alpha"; + default = 255; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Exists"; + 2 = "Block player"; + 4 = "Block others"; + 8 = "Render sides"; + 16 = "Render planes"; + 32 = "Water"; + 64 = "No shadow"; + 128 = "Cut solid walls"; + 256 = "Cut extra walls"; + 512 = "Split sprites"; + 1024 = "Render inside planes"; + 2048 = "Extra"; + 8192 = "Fog"; + 16384 = "Only render inside planes"; + 32768 = "Render inside walls"; + 65536 = "Only render inside walls"; + 131072 = "Double shadow"; + 262144 = "Water bobbing"; + 524288 = "Don't respawn"; + 1048576 = "Crumbling"; + 2097152 = "Goo water"; + 4194304 = "Mario block"; + 33554432 = "Intangible from below"; + 67108864 = "Intangible from above"; + 134217728 = "Ripple effect"; + 268435456 = "Don't copy light level"; + 536870912 = "Bouncy"; + 1073741824 = "Cut cyan flat pixels"; + } + } + } + 260 + { + title = "Generalized 3D Floor"; + id = "Sector_Set3dFloor"; + requiresactivation = false; + + arg0 + { + title = "Sector Tag"; + type = 13; + } + arg1 + { + title = "Type"; + type = 26; + default = 1; + enum + { + 1 = "Solid"; + 2 = "Water"; + 3 = "Intangible"; + } + flags + { + 4 = "Render Both Sides"; + 16 = "Invert Sides"; + } + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Disable shadowcast"; + 2 = "Double shadowcast"; + 4 = "Fog block"; + } + } + arg3 + { + title = "Opacity"; + default = 255; + } + } + } + + linedefexecmisc + { + title = "Linedef Executor (misc.)"; + + 443 + { + title = "Call Lua Function"; + prefix = "(443)"; + stringarg0 + { + title = "Function name"; + type = 2; + } + } + + 447 + { + title = "Change Tagged Sector's Colormap"; + prefix = "(447)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Colormap sector tag"; + type = 13; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Add to existing colormap"; + 2 = "Subtract light R"; + 4 = "Subtract light G"; + 8 = "Subtract light B"; + 16 = "Subtract light A"; + 32 = "Subtract fade R"; + 64 = "Subtract fade G"; + 128 = "Subtract fade B"; + 256 = "Subtract fade A"; + 512 = "Subtract fadestart"; + 1024 = "Subtract fadeend"; + 2048 = "Ignore flags"; + } + } + } + + 455 + { + title = "Fade Tagged Sector's Colormap"; + prefix = "(455)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Colormap sector tag"; + type = 13; + } + arg2 + { + title = "Fade duration"; + } + arg3 + { + title = "Flags"; + type = 12; + enum + { + 1 = "Add to existing colormap"; + 2 = "Subtract light R"; + 4 = "Subtract light G"; + 8 = "Subtract light B"; + 16 = "Subtract light A"; + 32 = "Subtract fade R"; + 64 = "Subtract fade G"; + 128 = "Subtract fade B"; + 256 = "Subtract fade A"; + 512 = "Subtract fadestart"; + 1024 = "Subtract fadeend"; + 2048 = "Ignore flags"; + 4096 = "Fade from invisible black"; + 8192 = "Interrupt ongoing fades"; + } + } + } + + 456 + { + title = "Stop Fading Tagged Sector's Colormap"; + prefix = "(456)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + } + + 465 + { + title = "Set Linedef Executor Delay"; + prefix = "(465)"; + arg0 + { + title = "Linedef tag"; + type = 15; + } + arg1 + { + title = "Value"; + } + arg2 + { + title = "Set/add?"; + type = 11; + enum + { + 0 = "Set"; + 1 = "Add"; + } + } + } + } + + light + { + 606 + { + title = "Copy Colormap"; + prefix = "(606)"; + arg0 + { + title = "Target sector tag"; + type = 13; + } + arg1 + { + title = "Colormap sector tag"; + type = 13; + } + } + } + + slope + { + title = "Slope"; + + 700 + { + title = "Create Sector-Based Slope"; + prefix = "(700)"; + id = "plane_align"; + arg0 + { + title = "Floor"; + type = 11; + enum = "frontback"; + } + arg1 + { + title = "Ceiling"; + type = 11; + enum = "frontback"; + } + arg2 + { + title = "Flags"; + type = 12; + enum + { + 1 = "No physics"; + 2 = "Dynamic"; + } + } + } + + 704 + { + title = "Create Vertex-Based Slope"; + prefix = "(704)"; + arg0 + { + title = "Plane"; + type = 11; + enum + { + 0 = "Front floor"; + 1 = "Front ceiling"; + 2 = "Back floor"; + 3 = "Back ceiling"; + } + } + arg1 + { + title = "Vertex 1 tag"; + type = 14; + } + arg2 + { + title = "Vertex 2 tag"; + type = 14; + } + arg3 + { + title = "Vertex 3 tag"; + type = 14; + } + arg4 + { + title = "Flags"; + type = 12; + enum + { + 1 = "No physics"; + 2 = "Dynamic"; + } + } + } + + 720 + { + title = "Copy Slope"; + prefix = "(720)"; + arg0 + { + title = "Front floor tag"; + type = 13; + } + arg1 + { + title = "Front ceiling tag"; + type = 13; + } + arg2 + { + title = "Back floor tag"; + type = 13; + } + arg3 + { + title = "Back ceiling tag"; + type = 13; + } + arg4 + { + title = "Share slope"; + type = 12; + enum + { + 1 = "Front floor to back sector"; + 2 = "Back floor to front sector"; + 4 = "Front ceiling to back sector"; + 8 = "Back ceiling to front sector"; + } + } + } + } +} diff --git a/extras/conf/udb/includes/Kart2_misc.cfg b/extras/conf/udb/includes/Kart2_misc.cfg new file mode 100644 index 000000000..2f93dff72 --- /dev/null +++ b/extras/conf/udb/includes/Kart2_misc.cfg @@ -0,0 +1,638 @@ +linedefflags +{ + 1 = "[0] Impassable"; + 2 = "[1] Block Enemies"; + 4 = "[2] Double-Sided"; + 8 = "[3] Upper Unpegged"; + 16 = "[4] Lower Unpegged"; + 32 = "[5] Slope Skew (E1)"; + 64 = "[6] Not Climbable"; + 128 = "[7] No Midtexture Skew (E2)"; + 256 = "[8] Peg Midtexture (E3)"; + 512 = "[9] Solid Midtexture (E4)"; + 1024 = "[10] Repeat Midtexture (E5)"; + 2048 = "[11] Netgame Only"; + 4096 = "[12] No Netgame"; + 8192 = "[13] Effect 6"; + 16384 = "[14] Bouncy Wall"; + 32768 = "[15] Transfer Line"; +} + + +// Linedef flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +linedefflagstranslation +{ + 1 = "blocking"; + 2 = "blockmonsters"; + 4 = "twosided"; + 8 = "dontpegtop"; + 16 = "dontpegbottom"; + 32 = "skewtd"; + 64 = "noclimb"; + 128 = "noskew"; + 256 = "midpeg"; + 512 = "midsolid"; + 1024 = "wrapmidtex"; + 2048 = "netonly"; + 4096 = "nonet"; + 8192 = "effect6"; + 16384 = "bouncy"; + 32768 = "transfer"; +} + + +linedefflags_udmf +{ + blocking = "Impassable"; + blockmonsters = "Block Enemies"; + twosided = "Double-Sided"; + dontpegtop = "Upper Unpegged"; + dontpegbottom = "Lower Unpegged"; + skewtd = "Slope Skew"; + noclimb = "Not Climbable"; + noskew = "No Midtexture Skew"; + midpeg = "Peg Midtexture"; + midsolid = "Solid Midtexture"; + wrapmidtex = "Repeat Midtexture"; +// effect6 = "Effect 6"; + bouncy = "Bouncy Wall"; + transfer = "Transfer Line"; +} + +linedefactivations_udmf +{ + netonly = "Netgame Only"; + nonet = "No Netgame"; +} + +/*linedefrenderstyles +{ + translucent = "Translucent"; + fog = "Fog"; +}*/ + +sectorflags +{ + colormapfog = "Fog Planes in Colormap"; + colormapfadesprites = "Fade Fullbright in Colormap"; + colormapprotected = "Protected Colormap"; +} + +thingflags +{ + 1 = "[1] Extra"; + 2 = "[2] Flip"; + 4 = "[4] Special"; + 8 = "[8] Ambush"; +} + +// THING FLAGS +thingflags_udmf +{ + extra = "Extra"; + flip = "Flip"; + special = "Special"; + ambush = "Ambush"; +} + + +// Thing flags UDMF translation table +// This is needed for copy/paste and prefabs to work properly +// When the UDMF field name is prefixed with ! it is inverted +thingflagstranslation +{ + 1 = "extra"; + 2 = "flip"; + 4 = "special"; + 8 = "ambush"; +} + + +// DEFAULT SECTOR BRIGHTNESS LEVELS +sectorbrightness +{ + 255; + 248; + 240; + 232; + 224; + 216; + 208; + 200; + 192; + 184; + 176; + 168; + 160; + 152; + 144; + 136; + 128; + 120; + 112; + 104; + 96; + 88; + 80; + 72; + 64; + 56; + 48; + 40; + 32; + 24; + 16; + 8; + 0; +} + +/* +TEXTURES AND FLAT SOURCES +This tells Doom Builder where to find the information for textures +and flats in the IWAD file, Addition WAD file and Map WAD file. + +Start and end lumps must be given in a structure (of which the +key name doesnt matter) and any textures or flats in between them +are loaded in either the textures category or flats category. + +For textures: PNAMES, TEXTURE1 and TEXTURE2 are loaded by default. +*/ +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +/* +ADDITIONAL UNIVERSAL DOOM MAP FORMAT FIELD DEFINITIONS +Only add fields here that Doom Builder does not edit with its own user-interface! +The "default" field must match the UDMF specifications! + +Field data types: +0 = integer * +1 = float +2 = string +3 = bool +4 = linedef action (integer) * +5 = sector effect (integer) * +6 = texture (string) +7 = flat (string) +8 = angle in degrees (integer) +9 = angle in radians (float) +10 = XXRRGGBB color (integer) +11 = enum option (integer) * +12 = enum bits (integer) * +13 = sector tag (integer) * +14 = thing tag (integer) * +15 = linedef tag (integer) * +16 = enum option (string) +17 = angle in degrees (float) +22 = byte angle (integer) +*/ +universalfields +{ + sector + { + lightalpha + { + type = 0; + default = 25; + } + + fadealpha + { + type = 0; + default = 25; + } + + fadestart + { + type = 0; + default = 0; + } + + fadeend + { + type = 0; + default = 33; + } + + foglighting + { + type = 3; + default = false; + } + } + + linedef + { + arg5 + { + type = 0; + default = 0; + } + stringarg0 + { + type = 2; + default = ""; + } + stringarg1 + { + type = 2; + default = ""; + } + executordelay + { + type = 0; + default = 0; + } + } + + sidedef + { + repeatcnt + { + type = 0; + default = 0; + } + } + + thing + { + } +} + +/* +MAP LUMP NAMES +Map lumps are loaded with the map as long as they are right after each other. When the editor +meets a lump which is not defined in this list it will ignore the map if not satisfied. +The order of items defines the order in which lumps will be written to WAD file on save. +To indicate the map header lump, use ~MAP + +Legenda: +required = Lump is required to exist. +blindcopy = Lump will be copied along with the map blindly. (useful for lumps Doom Builder doesn't use) +nodebuild = The nodebuilder generates this lump. +allowempty = The nodebuilder is allowed to leave this lump empty. +scriptbuild = This lump is a text-based script, which should be compiled using current script compiler; +script = This lump is a text-based script. Specify the filename of the script configuration to use. +*/ + +doommaplumpnames +{ + ~MAP + { + required = true; + blindcopy = true; + nodebuild = false; + } + + THINGS + { + required = true; + nodebuild = true; + allowempty = true; + } + + LINEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + SIDEDEFS + { + required = true; + nodebuild = true; + allowempty = false; + } + + VERTEXES + { + required = true; + nodebuild = true; + allowempty = false; + } + + SEGS + { + required = false; + nodebuild = true; + allowempty = false; + } + + SSECTORS + { + required = false; + nodebuild = true; + allowempty = false; + } + + NODES + { + required = false; + nodebuild = true; + allowempty = false; + } + + SECTORS + { + required = true; + nodebuild = true; + allowempty = false; + } + + REJECT + { + required = false; + nodebuild = true; + allowempty = false; + } + + BLOCKMAP + { + required = false; + nodebuild = true; + allowempty = true; + } +} + +udmfmaplumpnames +{ + ZNODES + { + required = false; + nodebuild = true; + allowempty = false; + } + + REJECT + { + required = false; + nodebuild = true; + allowempty = false; + } + + BLOCKMAP + { + required = false; + nodebuild = true; + allowempty = true; + } +} + +// ENUMERATIONS +// These are enumerated lists for linedef types and UDMF fields. +// Reserved names are: angledeg, anglerad, color, texture, flat +enums +{ + falsetrue + { + 0 = "False"; + 1 = "True"; + } + + yesno + { + 0 = "Yes"; + 1 = "No"; + } + + noyes + { + 0 = "No"; + 1 = "Yes"; + } + + onoff + { + 0 = "On"; + 1 = "Off"; + } + + offon + { + 0 = "Off"; + 1 = "On"; + } + + updown + { + 0 = "Up"; + 1 = "Down"; + } + + downup + { + 0 = "Down"; + 1 = "Up"; + } + + frontback + { + 0 = "None"; + 1 = "Front"; + 2 = "Back"; + } + + tangibility + { + 1 = "Intangible from top"; + 2 = "Intangible from bottom"; + 4 = "Don't block players"; + 8 = "Don't block non-players"; + } +} + +//Default things filters +thingsfilters +{ + + filter0 + { + name = "Player starts"; + category = "starts"; + type = -1; + } + + + filter1 + { + name = "Enemies"; + category = "enemies"; + type = -1; + + } + + + filter2 + { + name = "Normal Gravity"; + category = ""; + type = -1; + + fields + { + 2 = false; + } + + } + + + filter3 + { + name = "Reverse Gravity"; + category = ""; + type = -1; + + fields + { + 2 = true; + } + + } + + + filter4 + { + name = "Rings"; + category = ""; + type = 300; + + } + + + filter5 + { + name = "Waypoints"; + category = ""; + type = 2001; + + } +} + +// Special linedefs +speciallinedefs +{ + soundlinedefflag = 64; // See linedefflags + singlesidedflag = 1; // See linedefflags + doublesidedflag = 4; // See linedefflags + impassableflag = 1; + upperunpeggedflag = 8; + lowerunpeggedflag = 16; + repeatmidtextureflag = 1024; + pegmidtextureflag = 256; +} + +speciallinedefs_udmf +{ + soundlinedefflag = "noclimb"; + singlesidedflag = "blocking"; + doublesidedflag = "twosided"; + impassableflag = "blocking"; + upperunpeggedflag = "dontpegtop"; + lowerunpeggedflag = "dontpegbottom"; + repeatmidtextureflag = "wrapmidtex"; + pegmidtextureflag = "midpeg"; +} + +scriptlumpnames +{ + MAINCFG + { + script = "SOC.cfg"; + } + + OBJCTCFG + { + script = "SOC.cfg"; + } + + SOC_ + { + script = "SOC.cfg"; + isprefix = true; + } + + LUA_ + { + script = "Lua.cfg"; + isprefix = true; + } +} + +// Texture sources +textures +{ + zdoom1 + { + start = "TX_START"; + end = "TX_END"; + } +} + +// Patch sources +patches +{ + standard1 + { + start = "P_START"; + end = "P_END"; + } + + standard2 + { + start = "PP_START"; + end = "PP_END"; + } +} + +// Sprite sources +sprites +{ + standard1 + { + start = "S_START"; + end = "S_END"; + } + + standard2 + { + start = "SS_START"; + end = "SS_END"; + } +} + +// Flat sources +flats +{ + standard1 + { + start = "F_START"; + end = "F_END"; + } + + standard2 + { + start = "FF_START"; + end = "FF_END"; + } + + standard3 + { + start = "FF_START"; + end = "F_END"; + } + + standard4 + { + start = "F_START"; + end = "FF_END"; + } +} \ No newline at end of file diff --git a/extras/conf/udb/includes/Kart2_sectors.cfg b/extras/conf/udb/includes/Kart2_sectors.cfg new file mode 100644 index 000000000..aebc8fa29 --- /dev/null +++ b/extras/conf/udb/includes/Kart2_sectors.cfg @@ -0,0 +1,107 @@ +sectortypes +{ + 0 = "Normal"; + 1 = "Damage"; + 2 = "Damage (Water)"; + 3 = "Damage (Fire)"; + 4 = "Damage (Electrical)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + 9 = "Ring Drainer (Floor Touch)"; + 10 = "Ring Drainer (Anywhere in Sector)"; + 11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (NiGHTS Mare)"; + 128 = "Check for Linedef Executor on FOFs"; + 144 = "Egg Capsule"; + 160 = "Special Stage Time/Spheres Parameters"; + 176 = "Custom Global Gravity"; + 512 = "Wind/Current"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + 4096 = "Star Post Activator"; + 8192 = "Exit/Special Stage Pit/Return Flag"; + 12288 = "CTF Red Team Base"; + 16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Super Sonic Transform"; + 28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line"; + 45056 = "Rope Hang"; + 49152 = "Intangible to the Camera"; +} + +gen_sectortypes +{ + first + { + 0 = "Normal"; + 1 = "Damage"; + 2 = "Damage (Water)"; + 3 = "Damage (Fire)"; + 4 = "Damage (Electrical)"; + 5 = "Spikes"; + 6 = "Death Pit (Camera Tilt)"; + 7 = "Death Pit (No Camera Tilt)"; + 8 = "Instant Kill"; + 9 = "Ring Drainer (Floor Touch)"; + 10 = "Ring Drainer (Anywhere in Sector)"; + 11 = "Special Stage Damage"; + 12 = "Space Countdown"; + 13 = "Ramp Sector (double step-up/down)"; + 14 = "Non-Ramp Sector (no step-down)"; + } + + second + { + 0 = "Normal"; + 16 = "Trigger Line Ex. (Pushable Objects)"; + 32 = "Trigger Line Ex. (Anywhere, All Players)"; + 48 = "Trigger Line Ex. (Floor Touch, All Players)"; + 64 = "Trigger Line Ex. (Anywhere in Sector)"; + 80 = "Trigger Line Ex. (Floor Touch)"; + 96 = "Trigger Line Ex. (Emerald Check)"; + 112 = "Trigger Line Ex. (NiGHTS Mare)"; + 128 = "Check for Linedef Executor on FOFs"; + 144 = "Egg Capsule"; + 160 = "Special Stage Time/Spheres Parameters"; + 176 = "Custom Global Gravity"; + } + + third + { + 0 = "Normal"; + 512 = "Wind/Current"; + 1024 = "Conveyor Belt"; + 1280 = "Speed Pad"; + } + + fourth + { + 0 = "Normal"; + 4096 = "Star Post Activator"; + 8192 = "Exit/Special Stage Pit/Return Flag"; + 12288 = "CTF Red Team Base"; + 16384 = "CTF Blue Team Base"; + 20480 = "Fan Sector"; + 24576 = "Super Sonic Transform"; + 28672 = "Force Spin"; + 32768 = "Zoom Tube Start"; + 36864 = "Zoom Tube End"; + 40960 = "Circuit Finish Line"; + 45056 = "Rope Hang"; + 49152 = "Intangible to the Camera"; + } +} \ No newline at end of file diff --git a/extras/conf/udb/includes/Kart2_things.cfg b/extras/conf/udb/includes/Kart2_things.cfg new file mode 100644 index 000000000..54f9528fd --- /dev/null +++ b/extras/conf/udb/includes/Kart2_things.cfg @@ -0,0 +1,3047 @@ +// THING TYPES------------------------------------------------------------------ +// Color values: 1-Dark_Blue 2-Dark_Green 3-Turqoise 4-Dark_Red 5-Purple 6-Brown 7-Gray +// 8-Dark_Gray 9-Blue 10-Green 11-Cyan 12-Red 13-Magenta +// 14-Yellow 15-White 16-Pink 17-Orange 18-Gold 19-Cream + +editor +{ + color = 15; // White + arrow = 1; + title = ""; + error = -1; + width = 8; + height = 16; + sort = 1; + + 3328 = "3D Mode Start"; +} + +starts +{ + color = 1; // Blue + arrow = 1; + title = "Player Starts"; + width = 16; + height = 56; + flags8text = "[8] Spawn on ceiling"; + sprite = "SIGNE0"; + + 1 + { + title = "Player 01 Start"; + sprite = "SIGNE0"; + } + 2 + { + title = "Player 02 Start"; + sprite = "SIGNE0"; + } + 3 + { + title = "Player 03 Start"; + sprite = "SIGNE0"; + } + 4 + { + title = "Player 04 Start"; + sprite = "SIGNE0"; + } + 5 + { + title = "Player 05 Start"; + sprite = "SIGNE0"; + } + 6 + { + title = "Player 06 Start"; + sprite = "SIGNE0"; + } + 7 + { + title = "Player 07 Start"; + sprite = "SIGNE0"; + } + 8 + { + title = "Player 08 Start"; + sprite = "SIGNE0"; + } + 9 + { + title = "Player 09 Start"; + sprite = "SIGNE0"; + } + 10 + { + title = "Player 10 Start"; + sprite = "SIGNE0"; + } + 11 + { + title = "Player 11 Start"; + sprite = "SIGNE0"; + } + 12 + { + title = "Player 12 Start"; + sprite = "SIGNE0"; + } + 13 + { + title = "Player 13 Start"; + sprite = "SIGNE0"; + } + 14 + { + title = "Player 14 Start"; + sprite = "SIGNE0"; + } + 15 + { + title = "Player 15 Start"; + sprite = "SIGNE0"; + } + 16 + { + title = "Player 16 Start"; + sprite = "SIGNE0"; + } + 33 + { + title = "Match Start"; + sprite = "SUPTG0"; + } + /*34 + { + title = "CTF Red Team Start"; + sprite = "SIGNF0"; + } + 35 + { + title = "CTF Blue Team Start"; + sprite = "SIGND0"; + }*/ +} + +enemies +{ + color = 9; // Light_Blue + arrow = 1; + title = "Enemies"; + width = 24; + height = 32; + sprite = "POSSA1"; + + 100 + { + title = "Crawla (Blue)"; + sprite = "POSSA1"; + } + 101 + { + title = "Crawla (Red)"; + sprite = "SPOSA1"; + } + 102 + { + title = "Stupid Dumb Unnamed RoboFish"; + sprite = "FISHA0"; + width = 8; + height = 28; + angletext = "Jump strength"; + } + 103 + { + title = "Buzz (Gold)"; + sprite = "BUZZA1"; + width = 20; + height = 24; + flags8text = "[8] Cannot move"; + } + 104 + { + title = "Buzz (Red)"; + sprite = "RBUZA1"; + width = 20; + height = 24; + flags8text = "[8] Cannot move"; + } + 124 + { + title = "Buzz (Aqua)"; + sprite = "BBUZA1"; + width = 20; + height = 24; + } + 105 + { + title = "Jetty-Syn Bomber"; + sprite = "JETBB1"; + width = 20; + height = 48; + flags8text = "[8] Cannot move"; + } + 106 + { + title = "Jetty-Syn Gunner"; + sprite = "JETGB1"; + width = 20; + height = 48; + flags8text = "[8] Cannot move"; + } + 107 + { + title = "Crawla Commander"; + sprite = "CCOMA1"; + width = 16; + } + 108 + { + title = "Deton"; + sprite = "DETNA1"; + width = 20; + } + 109 + { + title = "Skim"; + sprite = "SKIMA1"; + width = 16; + height = 24; + } + 110 + { + title = "Turret"; + sprite = "TRETA1"; + width = 16; + height = 32; + } + 111 + { + title = "Pop-up Turret"; + sprite = "TURRI1"; + width = 12; + height = 64; + angletext = "Firing delay"; + } + 112 + { + title = "Sharp"; + sprite = "SHRPA1"; + width = 16; + height = 24; + } + 113 + { + title = "Jet Jaw"; + sprite = "JJAWA3A7"; + width = 12; + height = 20; + } + 114 + { + title = "Snailer"; + sprite = "SNLRA3A7"; + height = 48; + } + 115 + { + title = "Bird Aircraft Strike Hazard"; + sprite = "VLTRF1"; + width = 12; + height = 24; + } + 116 + { + title = "Pointy"; + sprite = "PNTYA1"; + width = 8; + height = 16; + } + 117 + { + title = "Robo-Hood"; + sprite = "ARCHA1"; + flags8text = "[8] Cannot jump"; + } + 118 + { + title = "CastleBot FaceStabber"; + sprite = "CBFSA1"; + width = 32; + height = 64; + } + 119 + { + title = "Egg Guard"; + sprite = "ESHIA1"; + width = 16; + height = 48; + flags8text = "[8] Double speed"; + } + 120 + { + title = "Green Snapper"; + sprite = "GSNPA1"; + height = 24; + } + 121 + { + title = "Minus"; + sprite = "MNUSA1"; + } + 122 + { + title = "Spring Shell (Green)"; + sprite = "SSHLA1"; + height = 40; + } + 125 + { + title = "Spring Shell (Yellow)"; + sprite = "SSHLI1"; + height = 40; + } + 123 + { + title = "Unidus"; + sprite = "UNIDA1"; + width = 18; + height = 36; + } +} + +bosses +{ + color = 8; // Dark_Gray + arrow = 1; + title = "Bosses"; + width = 24; + height = 52; + sprite = "EGGMA1"; + + 200 + { + title = "Boss 1 - Egg Mobile"; + sprite = "EGGMA1"; + flags4text = "[4] End level on death"; + flags8text = "[8] Alternate laser attack"; + } + 201 + { + title = "Boss 2 - Egg Slimer"; + sprite = "EGGNA1"; + height = 48; + flags4text = "[4] End level on death"; + flags8text = "[8] Speed up when hit"; + } + 202 + { + title = "Boss 3 - Sea Egg"; + sprite = "EGGOA1"; + width = 32; + height = 80; + flags4text = "[4] End level on death"; + } + 203 + { + title = "Boss 4 - Eggscalibur"; + sprite = "EGGPA1"; + flags4text = "[4] End level on death"; + } + 207 + { + title = "Boss 5A - Metal Sonic (Race)"; + sprite = "METLI1"; + width = 16; + height = 48; + } + 208 + { + title = "Boss 5B - Metal Sonic (Battle)"; + sprite = "METLC1"; + width = 16; + height = 48; + flags4text = "[4] End level on death"; + } + 209 + { + title = "Boss 6 - Brak Eggman"; + sprite = "BRAK[1"; + width = 48; + height = 160; + flags4text = "[4] End level on death"; + flags8text = "[8] Electric barrier"; + } + 206 + { + title = "Boss ? - Brak Eggman (Old)"; + sprite = "BRAKB1"; + width = 48; + height = 160; + flags4text = "[4] End level on death"; + } + 290 + { + arrow = 0; + title = "Boss Escape Point"; + width = 8; + height = 16; + sprite = "internal:eggmanend"; + } + 291 + { + arrow = 0; + title = "Egg Capsule Center"; + width = 8; + height = 16; + sprite = "internal:capsule"; + } + 292 + { + arrow = 0; + title = "Boss Waypoint"; + width = 8; + height = 16; + flags8text = "[8] Sea Egg shooting point"; + sprite = "internal:eggmanway"; + angletext = "No. (Sea Egg)"; + flagsvaluetext = "No. (Brak)"; + parametertext = "Next"; + } + 293 + { + title = "Metal Sonic Gather Point"; + sprite = "internal:metal"; + } +} + +rings +{ + color = 14; // Yellow + title = "Rings and Weapon Panels"; + width = 24; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + sprite = "RINGA0"; + + 300 + { + title = "Ring"; + sprite = "RINGA0"; + width = 16; + } + 301 + { + title = "Bounce Ring"; + sprite = "internal:RNGBA0"; + } + 302 + { + title = "Rail Ring"; + sprite = "internal:RNGRA0"; + } + 303 + { + title = "Infinity Ring"; + sprite = "internal:RNGIA0"; + } + 304 + { + title = "Automatic Ring"; + sprite = "internal:RNGAA0"; + } + 305 + { + title = "Explosion Ring"; + sprite = "internal:RNGEA0"; + } + 306 + { + title = "Scatter Ring"; + sprite = "internal:RNGSA0"; + } + 307 + { + title = "Grenade Ring"; + sprite = "internal:RNGGA0"; + } + 308 + { + title = "CTF Team Ring (Red)"; + sprite = "internal:RRNGA0"; + width = 16; + } + 309 + { + title = "CTF Team Ring (Blue)"; + sprite = "internal:BRNGA0"; + width = 16; + } + 330 + { + title = "Bounce Ring Panel"; + sprite = "internal:PIKBA0"; + } + 331 + { + title = "Rail Ring Panel"; + sprite = "internal:PIKRA0"; + } + 332 + { + title = "Automatic Ring Panel"; + sprite = "internal:PIKAA0"; + } + 333 + { + title = "Explosion Ring Panel"; + sprite = "internal:PIKEA0"; + } + 334 + { + title = "Scatter Ring Panel"; + sprite = "internal:PIKSA0"; + } + 335 + { + title = "Grenade Ring Panel"; + sprite = "internal:PIKGA0"; + } +} + +collectibles +{ + color = 10; // Light_Green + title = "Other Collectibles"; + width = 16; + height = 32; + sort = 1; + sprite = "CEMGA0"; + + 310 + { + title = "CTF Red Flag"; + sprite = "RFLGA0"; + width = 24; + height = 64; + } + 311 + { + title = "CTF Blue Flag"; + sprite = "BFLGA0"; + width = 24; + height = 64; + } + 312 + { + title = "Special Stage Token"; + sprite = "internal:token"; + width = 8; + height = 16; + flags8height = 24; + flags4text = "[4] Mario Block version"; + flags8text = "[8] Float"; + } + 313 + { + title = "Chaos Emerald 1 (Green)"; + sprite = "EMMYA0"; + } + 314 + { + title = "Chaos Emerald 2 (Purple)"; + sprite = "EMMYB0"; + } + 315 + { + title = "Chaos Emerald 3 (Blue)"; + sprite = "EMMYC0"; + } + 316 + { + title = "Chaos Emerald 4 (Cyan)"; + sprite = "EMMYD0"; + } + 317 + { + title = "Chaos Emerald 5 (Orange)"; + sprite = "EMMYE0"; + } + 318 + { + title = "Chaos Emerald 6 (Red)"; + sprite = "EMMYF0"; + } + 319 + { + title = "Chaos Emerald 7 (Gray)"; + sprite = "EMMYG0"; + } + 320 + { + title = "Emerald Hunt Location"; + sprite = "internal:hunt"; + } + 323 + { + title = "Match Chaos Emerald Spawn"; + sprite = "CEMGA0"; + width = 8; + height = 16; + flags8height = 24; + flags8text = "[8] Float"; + } +} + +boxes +{ + color = 7; // Gray + blocking = 2; + title = "Monitors"; + width = 16; + height = 32; + flags4text = "[4] Random (Strong)"; + flags8text = "[8] Random (Weak)"; + sprite = "SRBXA0"; + + 400 + { + title = "Super Ring (10 Rings)"; + sprite = "SRBXA0"; + } + 401 + { + title = "Pity Shield"; + sprite = "GRTVA0"; + } + 402 + { + title = "Attraction Shield"; + sprite = "YLTVA0"; + } + 403 + { + title = "Force Shield"; + sprite = "BLTVA0"; + } + 404 + { + title = "Armageddon Shield"; + sprite = "BKTVA0"; + } + 405 + { + title = "Whirlwind Shield"; + sprite = "WHTVA0"; + } + 406 + { + title = "Elemental Shield"; + sprite = "ELTVA0"; + } + 407 + { + title = "Super Sneakers"; + sprite = "SHTVA0"; + } + 408 + { + title = "Invincibility"; + sprite = "PINVA0"; + } + 409 + { + title = "Extra Life"; + sprite = "PRUPA0"; + flags4text = "[4] Random (Strong) / 10k points"; + flags8text = "[8] Random (Weak) / 10k points"; + } + 410 + { + title = "Eggman"; + sprite = "EGGBA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 411 + { + title = "Teleporter"; + sprite = "MIXUA0"; + } + 412 + { + title = "Random"; + sprite = "QUESA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 413 + { + title = "Gravity Boots"; + sprite = "GBTVA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 414 + { + title = "CTF Team Ring Monitor (Red)"; + sprite = "RRBXA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 415 + { + title = "CTF Team Ring Monitor (Blue)"; + sprite = "BRBXA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 416 + { + title = "Recycler"; + sprite = "RECYA0"; + } + 418 + { + title = "Score (1,000 Points)"; + sprite = "PTTVA0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } + 419 + { + title = "Score (10,000 Points)"; + sprite = "PTTVF0"; + flags4text = "[4] Special"; + flags8text = "[8] Ambush"; + } +} + +miscellaneous +{ + color = 11; // Light_Cyan + title = "Miscellaneous"; + width = 16; + height = 40; + sprite = "STPTA0"; + + 500 + { + title = "Air Bubble Patch"; + sprite = "BUBLA0"; + width = 8; + height = 16; + flags8text = "[8] No distance check"; + } + 501 + { + title = "Level End Sign"; + sprite = "SIGND0"; + width = 8; + height = 32; + } + 502 + { + arrow = 1; + title = "Star Post"; + sprite = "STPTA0"; + width = 64; + height = 80; + angletext = "Angle/Order"; + } + 526 + { + blocking = 2; + title = "Cannonball"; + sprite = "CBLLA0"; + width = 20; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1000 + { + arrow = 1; + blocking = 2; + title = "Gargoyle"; + sprite = "GARGA1"; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1102 + { + arrow = 1; + blocking = 2; + title = "Eggman Statue"; + sprite = "ESTAA1"; + width = 32; + height = 240; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1106 + { + arrow = 1; + title = "Chain (Swinging)"; + sprite = "internal:chain1"; + height = 32; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1107 + { + arrow = 1; + title = "Chain (Spinning)"; + sprite = "internal:chain2"; + height = 32; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1108 + { + arrow = 1; + title = "Chain (Hidden)"; + sprite = "internal:chain3"; + height = 32; + flags8text = "[8] Double size"; + } + 1200 + { + title = "Tumbleweed (Big)"; + sprite = "BTBLA0"; + width = 24; + height = 48; + flags8text = "[8] Moves perpetually"; + } + 1201 + { + title = "Tumbleweed (Small)"; + sprite = "STBLA0"; + width = 12; + height = 24; + flags8text = "[8] Moves perpetually"; + } + 1504 + { + title = "ATZ Target"; + sprite = "RCRYB0"; + width = 24; + height = 32; + } + 1852 + { + blocking = 2; + title = "Snowman"; + sprite = "XMS3A0"; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1876 + { + arrow = 1; + blocking = 2; + title = "Eggman Disco Statue"; + sprite = "ESTAB1"; + width = 20; + height = 96; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } +} + +springs +{ + color = 12; // Light_Red + title = "Springs and Fans"; + width = 48; + height = 32; + sprite = "RSPRD2"; + + 540 + { + title = "Fan"; + sprite = "FANSA0D0"; + width = 16; + height = 16; + flags4text = "[4] Invisible"; + flags8text = "[8] No distance check"; + angletext = "Lift height"; + } + 541 + { + title = "Gas Jet"; + sprite = "STEMD0"; + width = 32; + height = 16; + } + 550 + { + title = "Yellow Spring"; + sprite = "SPVYA0"; + } + 551 + { + title = "Red Spring"; + sprite = "SPVRA0"; + } + 552 + { + title = "Blue Spring"; + sprite = "SPVBA0"; + } + 553 + { + title = "Grey Spring"; + sprite = "SPVGA0"; + } + 554 + { + arrow = 1; + title = "Diagonal Yellow Spring"; + sprite = "SPDYA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 555 + { + arrow = 1; + title = "Diagonal Red Spring"; + sprite = "SPDRA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 556 + { + arrow = 1; + title = "Diagonal Blue Spring"; + sprite = "SPDBA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 557 + { + arrow = 1; + title = "Diagonal Grey Spring"; + sprite = "SPDGA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 558 + { + arrow = 1; + title = "Horizontal Yellow Spring"; + sprite = "SPHYA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 559 + { + arrow = 1; + title = "Horizontal Red Spring"; + sprite = "SPHRA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 560 + { + arrow = 1; + title = "Horizontal Blue Spring"; + sprite = "SPHBA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } + 561 + { + arrow = 1; + title = "Horizontal Grey Spring"; + sprite = "SPHGA2A8"; + flags8text = "[8] Rotate 22.5° CCW"; + } +} + +patterns +{ + color = 5; // Magenta + arrow = 1; + title = "Special Placement Patterns"; + width = 16; + height = 384; + sprite = "RINGA0"; + + 600 + { + arrow = 0; + title = "5 Vertical Rings (Yellow Spring)"; + sprite = "RINGA0"; + } + 601 + { + arrow = 0; + title = "5 Vertical Rings (Red Spring)"; + sprite = "RINGA0"; + height = 1024; + } + 602 + { + title = "5 Diagonal Rings (Yellow Spring)"; + sprite = "RINGA0"; + height = 32; + } + 603 + { + title = "10 Diagonal Rings (Red Spring)"; + sprite = "RINGA0"; + height = 32; + } + 604 + { + title = "Circle of Rings"; + sprite = "RINGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 605 + { + title = "Circle of Rings (Big)"; + sprite = "RINGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 606 + { + title = "Circle of Wing Logos"; + sprite = "NWNGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 607 + { + title = "Circle of Wing Logos (Big)"; + sprite = "NWNGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } + 608 + { + title = "Circle of Rings and Wings"; + sprite = "NWNGA0"; + width = 96; + height = 192; + unflippable = true; + centerHitbox = true; + } + 609 + { + title = "Circle of Rings and Wings (Big)"; + sprite = "NWNGA0"; + width = 192; + unflippable = true; + centerHitbox = true; + } +} + +invisible +{ + color = 15; // White + title = "Misc. Invisible"; + width = 8; + height = 16; + sprite = "UNKNA0"; + + 700 + { + title = "Water Ambience A (Large)"; + sprite = "internal:ambiance"; + } + + 701 + { + title = "Water Ambience B (Large)"; + sprite = "internal:ambiance"; + } + + 702 + { + title = "Water Ambience C (Medium)"; + sprite = "internal:ambiance"; + } + + 703 + { + title = "Water Ambience D (Medium)"; + sprite = "internal:ambiance"; + } + + 704 + { + title = "Water Ambience E (Small)"; + sprite = "internal:ambiance"; + } + + 705 + { + title = "Water Ambience F (Small)"; + sprite = "internal:ambiance"; + } + + 706 + { + title = "Water Ambience G (Extra Large)"; + sprite = "internal:ambiance"; + } + + 707 + { + title = "Water Ambience H (Extra Large)"; + sprite = "internal:ambiance"; + } + + 708 + { + title = "Disco Ambience"; + sprite = "internal:ambiance"; + } + + 709 + { + title = "Volcano Ambience"; + sprite = "internal:ambiance"; + } + + 750 + { + title = "Slope Vertex"; + sprite = "internal:vertexslope"; + angletext = "Tag"; + } + + 751 + { + arrow = 1; + title = "Teleport Destination"; + sprite = "internal:tele"; + } + + 752 + { + arrow = 1; + title = "Alternate View Point"; + sprite = "internal:view"; + } + + 753 + { + title = "Zoom Tube Waypoint"; + sprite = "internal:zoom"; + angletext = "Order"; + } + + 754 + { + title = "Push Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Push using XYZ"; + sprite = "GWLGA0"; + angletext = "Radius"; + } + 755 + { + title = "Pull Point"; + flags4text = "[4] Fades using XY"; + flags8text = "[8] Pull using XYZ"; + sprite = "GWLRA0"; + angletext = "Radius"; + } + + 760 + { + title = "PolyObject Anchor"; + sprite = "internal:polyanchor"; + angletext = "ID"; + } + + 761 + { + title = "PolyObject Spawn Point"; + sprite = "internal:polycenter"; + angletext = "ID"; + } + + 762 + { + title = "PolyObject Spawn Point (Crush)"; + sprite = "internal:polycentercrush"; + angletext = "ID"; + } + 780 + { + title = "Skybox View Point"; + sprite = "internal:skyb"; + flags4text = "[4] In-map reference point"; + angletext = "View height"; + } + +} + +hazards +{ + color = 4; // Red + title = "Hazards"; + width = 20; + height = 40; + + 521 + { + title = "Spikeball"; + sprite = "SPIKA0"; + width = 12; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 523 + { + title = "Spike"; + sprite = "USPKA0"; + width = 8; + height = 42; + flags4text = "[4] Retractable"; + flags8text = "[8] Solid"; + angletext = "Retraction interval"; + } + 524 + { + arrow = 1; + title = "Big Floating Mine"; + width = 16; + height = 32; + sprite = "BMNEA1"; + } + 527 + { + arrow = 1; + title = "Big Floating Mine (Air)"; + width = 16; + height = 32; + sprite = "BMNEA1"; + } + 525 + { + title = "Cannonball Launcher"; + sprite = "internal:cannonball"; + } + 1101 + { + title = "Torch"; + sprite = "FLAMA0"; + width = 8; + height = 32; + } + 1105 + { + title = "Mace (Swinging)"; + sprite = "internal:mace1"; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1104 + { + title = "Mace (Spinning)"; + sprite = "internal:mace2"; + flags4text = "[4] No sounds"; + flags8text = "[8] Double size"; + angletext = "Tag"; + } + 1202 + { + arrow = 1; + title = "Rock Spawner"; + sprite = "ROIAA0"; + angletext = "Tag"; + } + 1300 + { + arrow = 1; + title = "Flame Jet (Horizontal)"; + sprite = "internal:flameh"; + width = 16; + flags8text = "[8] Waves vertically"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1301 + { + title = "Flame Jet (Vertical)"; + sprite = "internal:flamev"; + width = 16; + flags8text = "[8] Shoot downwards"; + angletext = "On/Off time"; + parametertext = "Strength"; + } + 1500 + { + arrow = 1; + blocking = 2; + title = "Trapgoyle"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1501 + { + arrow = 1; + blocking = 2; + title = "Trapgoyle (Up)"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1502 + { + arrow = 1; + blocking = 2; + title = "Trapgoyle (Down)"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 1503 + { + arrow = 1; + blocking = 2; + title = "Trapgoyle (Long)"; + sprite = "GARGA1"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 3576 + { + title = "Spinning Flame Jet (Clockwise)"; + sprite = "internal:flame1"; + width = "16"; + } + 3575 + { + title = "Spinning Flame Jet (Counter-Clockwise)"; + sprite = "internal:flame2"; + width = "16"; + } +} + +decoration +{ + color = 2; // Green + title = "Decoration"; + width = 16; + height = 40; + sprite = "FWR1A0"; + + 757 + { + title = "Fan Particle Generator"; + sprite = "PRTLA0"; + width = 8; + height = 16; + angletext = "Particle speed"; + parametertext = "Interval"; + } + 800 + { + title = "GFZ Flower"; + sprite = "FWR1A0"; + } + 801 + { + title = "Sunflower"; + sprite = "FWR2A0"; + height = 96; + } + 802 + { + title = "Budding Flower"; + sprite = "FWR3A0"; + width = 8; + height = 32; + } + 804 + { + title = "Berry Bush"; + sprite = "BUS1A0"; + height = 32; + } + 805 + { + title = "Bush"; + sprite = "BUS2A0"; + height = 32; + } + 900 + { + title = "THZ Flower"; + sprite = "THZPA0"; + width = 8; + height = 32; + } + 901 + { + title = "Alarm"; + sprite = "ALRMA0"; + width = 8; + height = 16; + hangs = 1; + } + 1001 + { + title = "Seaweed"; + sprite = "SEWEA0"; + width = 24; + height = 56; + } + 1002 + { + title = "Dripping Water"; + sprite = "DRIPD0"; + width = 8; + height = 16; + hangs = 1; + angletext = "Dripping interval"; + } + 1003 + { + title = "Coral (Green)"; + sprite = "CRL1A0"; + width = 8; + height = 16; + } + 1004 + { + title = "Coral (Red)"; + sprite = "CRL2A0"; + width = 8; + height = 16; + } + 1005 + { + title = "Coral (Orange)"; + sprite = "CRL3A0"; + width = 8; + height = 16; + } + 1006 + { + title = "Blue Crystal"; + sprite = "BCRYA1"; + width = 8; + height = 16; + } + 1100 + { + title = "Chain"; + sprite = "CHANA0"; + width = 8; + height = 128; + hangs = 1; + } + 1103 + { + title = "CEZ Flower"; + sprite = "FWR4A0"; + } + 1203 + { + title = "Cactus with Brown Flower"; + sprite = "CACTA0"; + height = 32; + } + 1204 + { + title = "Cactus with Brown Flower (Tall)"; + sprite = "CACTB0"; + height = 64; + } + 1205 + { + title = "Cactus with Blue Flower"; + sprite = "CACTC0"; + height = 32; + } + 1206 + { + title = "Cactus with Blue Flower (Tall)"; + sprite = "CACTD0"; + height = 80; + } + 1850 + { + title = "Christmas Pole"; + sprite = "XMS1A0"; + } + 1851 + { + title = "Candy Cane"; + sprite = "XMS2A0"; + width = 8; + height = 32; + } + 1875 + { + title = "Disco Ball"; + sprite = "DBALA0"; + height = 54; + hangs = 1; + } + 1900 + { + title = "Brown Stalagmite (Tall)"; + sprite = "STLGA0"; + } + 1901 + { + title = "Brown Stalagmite"; + sprite = "STLGB0"; + } + 1902 + { + title = "Orange Stalagmite (Tall)"; + sprite = "STLGC0"; + } + 1903 + { + title = "Orange Stalagmite"; + sprite = "STLGD0"; + } + 1904 + { + title = "Red Stalagmite (Tall)"; + sprite = "STLGE0"; + } + 1905 + { + title = "Red Stalagmite"; + sprite = "STLGF0"; + } + 1906 + { + title = "Gray Stalagmite (Tall)"; + sprite = "STLGG0"; + } + 1907 + { + title = "Gray Stalagmite"; + sprite = "STLGH0"; + } + 1908 + { + title = "Blue Stalagmite (Tall)"; + sprite = "STLGI0"; + } + 1909 + { + title = "Blue Stalagmite"; + sprite = "STLGJ0"; + } +} + +nights +{ + color = 13; // Pink + title = "NiGHTS Items"; + width = 12; + height = 32; + sprite = "NWNGA0"; + + 1703 + { + title = "Ideya Drone"; + sprite = "NDRNA1"; + width = 16; + height = 56; + flags8text = "[8] Die upon time up"; + angletext = "Time limit"; + } + 1704 + { + arrow = 1; + title = "Bumper"; + sprite = "NBMPG3G7"; + width = 32; + height = 64; + unflippable = true; + flagsvaluetext = "Pitch"; + angletext = "Yaw"; + } + 1705 + { + arrow = 1; + title = "Hoop (Generic)"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + flagsvaluetext = "Height"; + angletext = "Pitch/Yaw"; + } + 1706 + { + title = "Wing Logo"; + sprite = "NWNGA0"; + height = 24; + unflippable = true; + } + 1707 + { + title = "Super Paraloop"; + sprite = "NPRUA0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1708 + { + title = "Drill Refill"; + sprite = "NPRUB0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1709 + { + title = "Nightopian Helper"; + sprite = "NPRUC0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1711 + { + title = "Extra Time"; + sprite = "NPRUD0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1712 + { + title = "Link Freeze"; + sprite = "NPRUE0"; + flags4text = "[4] Bonus time only"; + flags8text = "[8] Spawn immediately"; + } + 1713 + { + arrow = 1; + title = "Hoop (Customizable)"; + flags1text = "[1] Radius +16"; + flags2text = "[2] Radius +32"; + flags4text = "[4] Radius +64"; + flags8text = "[8] Radius +128"; + sprite = "HOOPA0"; + width = 80; + height = 160; + unflippable = true; + centerHitbox = true; + } +} + +nightstrk +{ + color = 13; // Pink + title = "NiGHTS Track"; + width = 8; + height = 4096; + sprite = "UNKNA0"; + + 1700 + { + title = "Axis"; + sprite = "internal:axis1"; + circle = 1; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + angletext = "Radius/Direction"; + parametertext = "Mare"; + } + 1701 + { + title = "Axis Transfer"; + sprite = "internal:axis2"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1702 + { + title = "Axis Transfer Line"; + sprite = "internal:axis3"; + unflippable = true; + ignoreZ = true; + flagsvaluetext = "Order"; + parametertext = "Mare"; + } + 1710 + { + title = "Ideya Capture"; + sprite = "CAPSA0"; + width = 72; + height = 144; + angletext = "Rings"; + parametertext = "Mare"; + } +} + +mario +{ + color = 6; // Brown + title = "Mario Items"; + width = 16; + height = 32; + sprite = "GOOMA0"; + + 1800 + { + title = "Coin"; + sprite = "COINA0"; + height = 24; + flags8height = 24; + flags8text = "[8] Float"; + } + 1801 + { + arrow = 1; + title = "Goomba"; + sprite = "GOOMA0"; + width = 24; + } + 1802 + { + arrow = 1; + title = "Goomba (Blue)"; + sprite = "BGOMA0"; + width = 24; + } + 1803 + { + title = "Fire Flower"; + sprite = "FFWRB0"; + } + 1804 + { + title = "Koopa Shell"; + sprite = "SHLLA0"; + width = 8; + height = 16; + } + 1805 + { + title = "Puma (Jumping Fireball)"; + sprite = "PUMAA0"; + width = 8; + height = 16; + angletext = "Jump strength"; + } + 1806 + { + title = "King Bowser"; + sprite = "KOOPA0"; + height = 28; + } + 1807 + { + title = "Axe"; + sprite = "MAXEA0"; + width = 8; + height = 16; + } + 1808 + { + title = "Bush (Short)"; + sprite = "MUS1A0"; + } + 1809 + { + title = "Bush (Tall)"; + sprite = "MUS2A0"; + } + 1810 + { + title = "Toad"; + sprite = "TOADA0"; + width = 8; + } +} + +srb1 +{ + color = 3; // Cyan + arrow = 1; + title = "SRB1 Remake"; + width = 20; + height = 32; + sprite = "SRBAA1"; + + 4000 + { + title = "SRB1 Crawla"; + sprite = "SRBAA1"; + height = 40; + } + 4001 + { + title = "GuardRobo"; + sprite = "SRBBA1"; + width = 17; + height = 40; + } + 4002 + { + title = "Pyrin"; + sprite = "SRBCB1"; + width = 22; + } + 4003 + { + title = "HotRobo"; + sprite = "SRBDA0"; + height = 40; + } + 4004 + { + title = "Pogminz"; + sprite = "SRBEA1"; + } + 4005 + { + title = "Pogminz (Water)"; + sprite = "SRBEA1"; + } + 4006 + { + title = "Pog-GX2"; + sprite = "SRBFA0"; + width = 10; + height = 34; + } + 4007 + { + title = "Pyrex"; + sprite = "SRBGA1"; + width = 24; + } + 4008 + { + title = "SRB1 Turret"; + sprite = "SRBHA0"; + width = 24; + hangs = 1; + } + 4009 + { + title = "SWAT Bot"; + sprite = "SRBIA1"; + width = 21; + height = 69; + } + 4010 + { + title = "SpyBot 2000"; + sprite = "SRBJA0"; + width = 36; + height = 62; + } + 4011 + { + title = "Buzz Bomber"; + sprite = "SRBKA0"; + width = 44; + height = 45; + } + 4012 + { + arrow = 0; + title = "RBZ Spike"; + sprite = "SRBLA0"; + width = 10; + height = 53; + } + 4013 + { + arrow = 0; + blocking = 2; + title = "Dumb Metal Sonic"; + sprite = "SRBMC0"; + width = 16; + height = 40; + flags4text = "[4] Slides when pushed"; + flags8text = "[8] Not pushable"; + } + 4014 + { + title = "Super SWAT Bot"; + sprite = "SRBNA1"; + width = 21; + height = 69; + } + 4015 + { + title = "Genrex"; + sprite = "SRBOA1"; + width = 17; + height = 40; + } +} + +bsz +{ + color = 2; // Green + title = "Botanic Serenity Items"; + width = 16; + height = 32; + sprite = "BSZ1A0"; + 1400 + { + title = "Tall Flower (Red)"; + sprite = "BSZ1A0"; + } + 1401 + { + title = "Tall Flower (Purple)"; + sprite = "BSZ1B0"; + } + 1402 + { + title = "Tall Flower (Blue)"; + sprite = "BSZ1C0"; + } + 1403 + { + title = "Tall Flower (Cyan)"; + sprite = "BSZ1D0"; + } + 1404 + { + title = "Tall Flower (Yellow)"; + sprite = "BSZ1E0"; + } + 1405 + { + title = "Tall Flower (Orange)"; + sprite = "BSZ1F0"; + } + 1410 + { + title = "Medium Flower (Red)"; + sprite = "BSZ2A0"; + } + 1411 + { + title = "Medium Flower (Purple)"; + sprite = "BSZ2B0"; + } + 1412 + { + title = "Medium Flower (Blue)"; + sprite = "BSZ2C0"; + } + 1413 + { + title = "Medium Flower (Cyan)"; + sprite = "BSZ2D0"; + } + 1414 + { + title = "Medium Flower (Yellow)"; + sprite = "BSZ2E0"; + } + 1415 + { + title = "Medium Flower (Orange)"; + sprite = "BSZ2F0"; + } + 1420 + { + title = "Short Flower (Red)"; + sprite = "BSZ3A0"; + } + 1421 + { + title = "Short Flower (Purple)"; + sprite = "BSZ3B0"; + } + 1422 + { + title = "Short Flower (Blue)"; + sprite = "BSZ3C0"; + } + 1423 + { + title = "Short Flower (Cyan)"; + sprite = "BSZ3D0"; + } + 1424 + { + title = "Short Flower (Yellow)"; + sprite = "BSZ3E0"; + } + 1425 + { + title = "Short Flower (Orange)"; + sprite = "BSZ3F0"; + } + 1430 + { + title = "Tulip (Red)"; + sprite = "BSZ4A0"; + } + 1431 + { + title = "Tulip (Purple)"; + sprite = "BSZ4B0"; + } + 1432 + { + title = "Tulip (Blue)"; + sprite = "BSZ4C0"; + } + 1433 + { + title = "Tulip (Cyan)"; + sprite = "BSZ4D0"; + } + 1434 + { + title = "Tulip (Yellow)"; + sprite = "BSZ4E0"; + } + 1435 + { + title = "Tulip (Orange)"; + sprite = "BSZ4F0"; + } + 1440 + { + title = "Cluster (Red)"; + sprite = "BSZ5A0"; + } + 1441 + { + title = "Cluster (Purple)"; + sprite = "BSZ5B0"; + } + 1442 + { + title = "Cluster (Blue)"; + sprite = "BSZ5C0"; + } + 1443 + { + title = "Cluster (Cyan)"; + sprite = "BSZ5D0"; + } + 1444 + { + title = "Cluster (Yellow)"; + sprite = "BSZ5E0"; + } + 1445 + { + title = "Cluster (Orange)"; + sprite = "BSZ5F0"; + } + 1450 + { + title = "Bush (Red)"; + sprite = "BSZ6A0"; + } + 1451 + { + title = "Bush (Purple)"; + sprite = "BSZ6B0"; + } + 1452 + { + title = "Bush (Blue)"; + sprite = "BSZ6C0"; + } + 1453 + { + title = "Bush (Cyan)"; + sprite = "BSZ6D0"; + } + 1454 + { + title = "Bush (Yellow)"; + sprite = "BSZ6E0"; + } + 1455 + { + title = "Bush (Orange)"; + sprite = "BSZ6F0"; + } + 1460 + { + title = "Vine (Red)"; + sprite = "BSZ7A0"; + } + 1461 + { + title = "Vine (Purple)"; + sprite = "BSZ7B0"; + } + 1462 + { + title = "Vine (Blue)"; + sprite = "BSZ7C0"; + } + 1463 + { + title = "Vine (Cyan)"; + sprite = "BSZ7D0"; + } + 1464 + { + title = "Vine (Yellow)"; + sprite = "BSZ7E0"; + } + 1465 + { + title = "Vine (Orange)"; + sprite = "BSZ7F0"; + } + 1470 + { + title = "BSZ Shrub"; + sprite = "BSZ8A0"; + } + 1471 + { + title = "BSZ Clover"; + sprite = "BSZ8B0"; + } + 1472 + { + title = "BSZ Fish"; + sprite = "BSZ8C0"; + } + 1473 + { + title = "BSZ Sunflower"; + sprite = "BSZ8D0"; + } +} + +derrobjs // sev: split these into multiple sections later +{ + color = 4; // Red + arrow = 1; + title = "SRB2Kart Stuff"; + sprite = "ITEMALAR"; + width = 8; + height = 16; + + 2000 + { + title = "Random Item"; + sprite = "RNDMA0"; + width = 36; + height = 36; + } + 2333 + { + title = "Capsule"; + //sprite = "internal:kartcapsule"; + width = 28; + height = 112; + blocking = 2; + flags4text = "[4] Reverse movement"; + flags8text = "[8] Back and forth"; + arg0 + { + title = "Movement sequence"; + type = 0; + } + arg1 + { + title = "Movement speed"; + type = 0; + } + } + 1488 + { + arrow = 1; + title = "Random Audience Member"; + sprite = "AUDIA2A8"; + width = 8; + height = 20; + } + 1479 + { + title = "Torch (no fullbright)"; + sprite = "FLAMA0"; + width = 8; + height = 32; + } + 1480 + { + blocking = 2; + arrow = 1; + title = "Devil Gargoyle"; + sprite = "DECOA1"; + width = 16; + height = 40; + } + 1481 + { + blocking = 2; + arrow = 1; + title = "Angel Gargoyle"; + sprite = "DECOB1"; + width = 16; + height = 40; + } + 1482 + { + title = "Generic Palmtree"; + sprite = "DECOC0"; + width = 16; + height = 189; + } + 1483 + { + title = "Peach's Castle Flag"; + sprite = "DECOD0"; + width = 16; + height = 40; + } + 1484 + { + title = "Sonic the Hedge (bust)"; + sprite = "DECOE0"; + width = 64; + height = 64; + } + 1485 + { + title = "Tall Bush"; + sprite = "DECOF0"; + width = 16; + height = 32; + } + 1486 + { + title = "Bush Tree"; + sprite = "DECOG0"; + width = 16; + height = 40; + } + 1487 + { + title = "Fire Hydrant"; + sprite = "DECOH0"; + width = 16; + height = 40; + } + 2400 + { + title = "Big Puma"; + sprite = "DECOI0"; + width = 24; + height = 48; + } + 2805 + { + title = "Autumn Bush"; + sprite = "DOODA0"; + width = 16; + height = 24; + } + 2800 + { + title = "Autumn Flower"; + sprite = "DOODB0"; + width = 16; + height = 40; + } + 2801 + { + title = "Autumn Sunflower"; + sprite = "DOODD0"; + width = 16; + height = 96; + } + 2802 + { + title = "Autumn Budding Flower"; + sprite = "DOODF0"; + width = 8; + height = 32; + } + 2809 + { + title = "Decorative MKSC Item"; + sprite = "DOODJ0"; + width = 16; + height = 32; + } + 2807 + { + title = "Decorative DKR Item"; + sprite = "DOODL0"; + width = 91; + height = 166; + } + 2808 + { + title = "Big Ring"; + sprite = "BRNGA0"; + width = 26; + height = 62; + } + 2301 + { + title = "SMK DP Bush 1"; + sprite = "SNESA0"; + width = 14; + height = 15; + } + 2302 + { + title = "SMK DP Bush 2"; + sprite = "SNESB0"; + width = 13; + height = 13; + } + 2303 + { + title = "SMK DP Bush 3"; + sprite = "SNESC0"; + width = 7; + height = 7; + } + /*379 + { + title = "MKSC Boo"; + sprite = "GBASA0"; + width = 16; + height = 56; + }*/ + 2015 + { + title = "Buzz Bomber"; + sprite = "BUZBA2A8"; + width = 24; + height = 24; + } + 2500 + { + title = "Chomper"; + sprite = "CHOMA2A8"; + width = 24; + height = 48; + } + 2016 + { + title = "SCZ Palmtree"; + sprite = "SACOA0"; + width = 16; + height = 96; + } + 3000 + { + title = "SCZ Blue Flower"; + sprite = "SACOB0"; + width = 16; + height = 40; + } + 3001 + { + title = "SCZ Blue Tulips"; + sprite = "SACOC0"; + width = 16; + height = 40; + } + 3002 + { + title = "SCZ Yellow Flower"; + sprite = "SACOD0"; + width = 16; + height = 40; + } + 3003 + { + title = "SCZ Yellow Tulips"; + sprite = "SACOE0"; + width = 16; + height = 40; + } + 4022 // Dupe + { + title = "SCZ Wall Plant"; + sprite = "SACOF0"; + width = 16; + height = 40; + } + 4024 + { + title = "SCZ Plant"; + sprite = "SACOG0"; + width = 16; + height = 40; + } + 4025 + { + title = "SCZ Bush"; + sprite = "SACOH0"; + width = 16; + height = 40; + } + 4026 + { + title = "CAZ Skull"; + sprite = "CRABA1"; + width = 16; + height = 40; + } + 4027 + { + title = "CAZ Phantom Tree"; + sprite = "CRABB0"; + width = 32; + height = 150; + } + 4028 + { + title = "CAZ Flying Gargoyle"; + sprite = "CRABI1"; + width = 20; + height = 170; + } + 4029 + { + title = "CAZ Lamppost"; + sprite = "CRABK0"; + width = 32; + height = 150; + } + 4030 + { + title = "CAZ Dead Tree"; + sprite = "CRABL0"; + width = 32; + height = 150; + } + 715 + { + title = "Sonic the Hedge"; + sprite = "SBUSA0"; + width = 192; + height = 922; + } + 1969 + { + title = "MZ Torch"; + sprite = "MARBA0"; + width = 12; + height = 45; + } + 1970 + { + title = "MZ Burner"; + sprite = "MARBJ0"; + width = 24; + height = 96; + } + 4050 + { + title = "CD SS1 UFO"; + sprite = "FUFOA0"; + width = 70; + height = 70; + } + 1988 + { + title = "RRZ Lamp"; + sprite = "RUSTA0"; + width = 12; + height = 45; + } + 1989 + { + title = "RRZ Chain"; + sprite = "RUSTB0"; + width = 12; + height = 45; + } + 462 + { + title = "SD2 BP Balloon"; + sprite = "BLONA0"; + width = 32; + height = 64; + angletext = "Color"; + } + 2018 + { + title = "PRZ Smoke Generator"; + sprite = "SMOKA0"; + width = 24; + height = 64; + flags4text = "[4] Spawn VVZ smoke"; + } + 1600 + { + title = "VVZ Smoke"; + sprite = "VAPEA0"; + width = 16; + height = 64; + } + 716 + { + title = "HTZ Pinetree"; + sprite = "HTZAA0"; + width = 5; + height = 204; + } + 717 + { + title = "HTZ Bush"; + sprite = "HTZBA0"; + width = 24; + height = 38; + } + 718 + { + title = "MKSC SG Vine 1"; + sprite = "SGVAA0"; + width = 32; + height = 256; + } + 719 + { + title = "MKSC SG Vine 2"; + sprite = "SGVBA0"; + width = 17; + height = 48; + } + 720 + { + title = "MKSC SG Vine 3"; + sprite = "SGVCA0"; + width = 17; + height = 48; + } + 711 + { + title = "MKDS PG Tree"; + sprite = "PGTRA0"; + width = 30; + height = 504; + } + 712 + { + title = "MKDS PG Flower 1"; + sprite = "PGF1A0"; + width = 17; + height = 48; + } + 713 + { + title = "MKDS PG Flower 2"; + sprite = "PGF2A0"; + width = 17; + height = 48; + } + 714 + { + title = "MKDS PG Flower 3"; + sprite = "PGF3A0"; + width = 17; + height = 48; + } + 715 + { + title = "MKDS PG Bush"; + sprite = "PGBHA0"; + width = 384; + height = 922; + } + 1960 + { + title = "SM SS3 Pillar"; + sprite = "DPLRA0"; + width = 58; + height = 256; + } + 3124 + { + title = "MC Spotlight"; + sprite = "SPTLA0"; + width = 8; + height = 16; + } + 3120 + { + title = "MC Random Shadow"; + sprite = "ENM1B2B8"; + width = 16; + height = 32; + } + 3121 + { + title = "MC Roaming Shadow"; + sprite = "ENM1C2C8"; + width = 16; + height = 32; + } + 3122 + { + title = "MC Sign"; + sprite = "MARRA0"; + width = 64; + height = 128; + flags1text = "[1] Flip Arrow"; + flags4text = "[4] Boost Warning"; + } + 3199 + { + title = "Mementos Reaper Waypoint"; + sprite = "ENM1B5"; + width = 64; + height = 128; + flags1text = "[1] Flip Arrow"; + flags4text = "[4] Boost Warning"; + } + 3202 + { + title = "Mementos Reaper"; + sprite = "REAPA0"; + width = 64; + height = 128; + } + 3201 + { + title = "Mementos Teleporter"; + sprite = "GARUA0"; + width = 512; + height = 16; + } + 1601 + { + title = "MCZ Jack in the Box"; + sprite = "JITBA0"; + width = 16; + height = 128; + } + 2499 + { + title = "3CD Moon"; + sprite = "CDMOA0"; + width = 30; + height = 60; + } + 2498 + { + title = "3CD Bush"; + sprite = "CDBUA0"; + width = 16; + height = 16; + } + 2496 + { + title = "3CD Tree 1"; + sprite = "CDBUB0"; + width = 20; + height = 20; + } + 2497 + { + title = "3CD Tree 2"; + sprite = "CDBUC0"; + width = 20; + height = 20; + } + 3204 + { + title = "DSZ Pinetree"; + sprite = "PINEC0"; + width = 32; + height = 192; + } + 2311 + { + title = "EZZ Propeller"; + sprite = "PPLRA0"; + width = 32; + height = 48; + } + 3742 + { + title = "DPZ Palmtree"; + sprite = "DPPTA0"; + width = 16; + height = 560; + } + 1950 + { + title = "AAZ Palmtree"; + sprite = "AATRC0"; + width = 160; + height = 256; + angletext = "Leaves"; + parametertext = "Height"; + } + 2005 + { + title = "BBZ Frogger"; + sprite = "FROGA2A8"; + width = 28; + height = 72; + } + 2006 + { + title = "BBZ Robra"; + sprite = "CBRAA2A8"; + width = 32; + height = 72; + } + 2007 + { + blocking = 2; + title = "BBZ Blue Robra"; + sprite = "BBRAA2A8"; + width = 32; + height = 72; + } + 2679 + { + title = "EGZ Fog Generator"; + sprite = "EGFGA0"; + } + 3970 + { + blocking = 2; + title = "SMK Pipe"; + sprite = "SMKPA1A5"; + width = 20; + height = 52; + flags8text = "[8] Orange"; + } + 3971 + { + title = "SMK DP Monty Mole"; + sprite = "MTYMA0"; + width = 28; + height = 32; + } + 3972 + { + blocking = 2; + title = "SMK Thwomp"; + sprite = "THWPA0"; + width = 22; + height = 52; + flags8text = "[8] Rainbow"; + } + 3745 + { + title = "SMK VL Snowball"; + sprite = "SNOBA0"; + width = 16; + height = 32; + } + 3203 + { + blocking = 2; + title = "SMK VL Ice Block"; + sprite = "ICEBARAL"; + width = 32; + height = 32; + } + 749 + { + title = "Blue Torch"; + sprite = "CNDLA0"; + width = 8; + height = 32; + } + 748 + { + title = "Green Torch"; + sprite = "CNDLE0"; + width = 8; + height = 32; + } + 744 + { + blocking = 2; + title = "CK RR Chest"; + sprite = "CHESA0"; + width = 48; + height = 64; + } + 743 + { + blocking = 2; + title = "CK RR Chimera Statue"; + sprite = "CHIMA0"; + width = 64; + height = 128; + } + 742 + { + blocking = 2; + title = "CK RR Dragon Statue"; + sprite = "DRGNA0"; + width = 64; + height = 128; + } + 741 + { + blocking = 2; + title = "CK RR Lizard Man Statue"; + sprite = "LZMNA0"; + width = 64; + height = 128; + } + 740 + { + blocking = 2; + title = "CK RR Pegasus Statue"; + sprite = "PGSSA0"; + width = 64; + height = 128; + } + 739 + { + title = "Small Purple Torch"; + sprite = "ZTCHA0"; + width = 8; + height = 32; + } + 747 + { + blocking = 2; + title = "KKR GD Thing"; + sprite = "DOCHA0"; + width = 16; + height = 64; + } + 746 + { + blocking = 2; + title = "KKR GD Duck"; + sprite = "DUCKA0"; + width = 16; + height = 64; + } + 745 + { + blocking = 2; + title = "KKR GD Tree"; + sprite = "GTREA0"; + width = 32; + height = 128; + } + 738 + { + title = "THH Monokuma"; + sprite = "MKMAA2"; + width = 16; + height = 64; + } + 737 + { + title = "Small Red Torch"; + sprite = "RTCHA0"; + width = 8; + height = 32; + } + 736 + { + title = "PC Bowling Pin"; + sprite = "BOWLA0"; + width = 16; + height = 64; + } + 735 + { + title = "PC Merry-Go-Round Ambience"; + sprite = "internal:ambiance"; + } + 734 + { + title = "Twinkle Cart Ambience"; + sprite = "internal:ambiance"; + } + 733 + { + title = "PC Exploding Barrel"; + sprite = "BRRLA0"; + width = 32; + height = 64; + } + 732 + { + blocking = 2; + title = "PC Merry-Go-Round Horse"; + sprite = "HRSEA0"; + width = 32; + height = 128; + } + 731 + { + blocking = 2; + title = "Chao Fruit (Blue)"; + sprite = "BFRTA0"; + width = 16; + height = 16; + } + 730 + { + blocking = 2; + title = "Chao Fruit (Orange)"; + sprite = "OFRTA0"; + width = 16; + height = 16; + } + 729 + { + blocking = 2; + title = "Chao Fruit (Red)"; + sprite = "RFRTA0"; + width = 16; + height = 16; + } + 728 + { + blocking = 2; + title = "Chao Fruit (Pink)"; + sprite = "OFRTA0"; + width = 16; + height = 16; + } + 727 + { + title = "RBA Spikeball 1"; + sprite = "ASPKA0"; + width = 64; + height = 32; + } + 726 + { + title = "RBA Spikeball 2"; + sprite = "ASPKA0"; + width = 64; + height = 32; + } + 725 + { + title = "RBA Spikeball 3"; + sprite = "ASPKA0"; + width = 64; + height = 32; + } + 724 + { + title = "RBA Boost Prompt"; + sprite = "HBSTA0"; + width = 64; + height = 64; + } + 724 + { + title = "RBA Boost OFF"; + sprite = "HBSFA0"; + width = 64; + height = 64; + } + 724 + { + title = "RBA Boost ON"; + sprite = "HBSOA0"; + width = 64; + height = 64; + } + 2200 + { + title = "AS Toad"; + sprite = "TOAHA0"; + width = 16; + height = 64; + } + 2201 + { + blocking = 2; + title = "FTZ Lizard Man Statue"; + sprite = "WBLZA0"; + width = 32; + height = 92; + } + 2202 + { + blocking = 2; + title = "FTZ Lion Man Statue"; + sprite = "WBLNA0"; + width = 32; + height = 92; + } +} +waypoints +{ + color = 4; // Red + arrow = 1; + title = "Waypoints"; + sprite = "KBLNC0"; + width = 16; + height = 32; + + 2001 + { + title = "Waypoint (height = next waypoint ID)"; + sprite = "EMBMP0"; + angletext = "ID"; + flags1text = "[1] Disable"; + flags4text = "[4] Shortcut"; + flags8text = "[8] No respawn"; + arg0 + { + title = "Next Waypoint ID"; + type = 14; + } + arg1 + { + title = "Radius"; + default = 384; + renderstyle = "Circle"; + } + arg2 + { + title = "Finish Line?"; + type = 0; + } + } + 2004 + { + title = "Bot Hint"; + sprite = "EMBMA0"; + flags8text = "[8] Avoid this area"; + arg0 + { + title = "Radius"; + default = 32; + renderstyle = "Circle"; + } + arg1 + { + title = "Turn strength"; + default = 2; + type = 0; + } + } +} \ No newline at end of file diff --git a/libs/DLL-README.txt b/libs/DLL-README.txt index 06fae1278..51963baca 100644 --- a/libs/DLL-README.txt +++ b/libs/DLL-README.txt @@ -1,12 +1,13 @@ # SRB2Kart - Which DLLs do I need to bundle? -Updated 12/4/2018 (v2.1.21) +Updated 8/23/2020 (v1.3) Here are the required DLLs, per build. For each architecture, copy all the binaries from these folders: * libs\dll-binaries\[i686/x86_64] * libs\SDL2\[i686/x86_64]...\bin -* libs\SDL2_mixer\[i686/x86_64]...\bin +* libs\SDL2mixerX\[i686/x86_64]...\bin +* libs\libopenmpt\[x86/x86_64]...\bin\mingw and don't forget to build r_opengl.dll for srb2dd. @@ -14,30 +15,18 @@ and don't forget to build r_opengl.dll for srb2dd. * libs\dll-binaries\i686\exchndl.dll * libs\dll-binaries\i686\libgme.dll +* libs\dll-binaries\i686\discord-rpc.dll * libs\dll-binaries\i686\mgwhelp.dll (depend for exchndl.dll) * libs\SDL2\i686-w64-mingw32\bin\SDL2.dll -* libs\SDL2_mixer\i686-w64-mingw32\bin\*.dll (get everything) +* libs\SDL2mixerX\i686-w64-mingw32\bin\*.dll (get everything) +* libs\libopenmpt\x86\bin\mingw\libopenmpt.dll ## srb2kart, 64-bit * libs\dll-binaries\x86_64\exchndl.dll * libs\dll-binaries\x86_64\libgme.dll +* libs\dll-binaries\x86_64\discord-rpc.dll * libs\dll-binaries\x86_64\mgwhelp.dll (depend for exchndl.dll) * libs\SDL2\x86_64-w64-mingw32\bin\SDL2.dll -* libs\SDL2_mixer\x86_64-w64-mingw32\bin\*.dll (get everything) - -## srb2kartdd, 32-bit - -* libs\dll-binaries\i686\exchndl.dll -* libs\dll-binaries\i686\fmodex.dll -* libs\dll-binaries\i686\libgme.dll -* libs\dll-binaries\i686\mgwhelp.dll (depend for exchndl.dll) -* r_opengl.dll (build this from make) - -## srb2kartdd, 64-bit - -* libs\dll-binaries\x86_64\exchndl.dll -* libs\dll-binaries\x86_64\fmodex.dll -* libs\dll-binaries\x86_64\libgme.dll -* libs\dll-binaries\x86_64\mgwhelp.dll (depend for exchndl.dll) -* r_opengl.dll (build this from make) +* libs\SDL2mixerX\x86_64-w64-mingw32\bin\*.dll (get everything) +* libs\libopenmpt\x86_64\bin\mingw\libopenmpt.dll diff --git a/libs/SDL2/COPYING.txt b/libs/SDL2/COPYING.txt index 694e58a09..9cdb5f8bb 100644 --- a/libs/SDL2/COPYING.txt +++ b/libs/SDL2/COPYING.txt @@ -1,6 +1,6 @@ Simple DirectMedia Layer -Copyright (C) 1997-2018 Sam Lantinga +Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/WhatsNew.txt b/libs/SDL2/WhatsNew.txt index 9074b12ba..7f305012f 100644 --- a/libs/SDL2/WhatsNew.txt +++ b/libs/SDL2/WhatsNew.txt @@ -1,6 +1,38 @@ This is a list of major changes in SDL's version history. +--------------------------------------------------------------------------- +2.0.10: +--------------------------------------------------------------------------- + +General: +* The SDL_RW* macros have been turned into functions that are available only in 2.0.10 and onward +* Added SDL_SIMDGetAlignment(), SDL_SIMDAlloc(), and SDL_SIMDFree(), to allocate memory aligned for SIMD operations for the current CPU +* Added SDL_RenderDrawPointF(), SDL_RenderDrawPointsF(), SDL_RenderDrawLineF(), SDL_RenderDrawLinesF(), SDL_RenderDrawRectF(), SDL_RenderDrawRectsF(), SDL_RenderFillRectF(), SDL_RenderFillRectsF(), SDL_RenderCopyF(), SDL_RenderCopyExF(), to allow floating point precision in the SDL rendering API. +* Added SDL_GetTouchDeviceType() to get the type of a touch device, which can be a touch screen or a trackpad in relative or absolute coordinate mode. +* The SDL rendering API now uses batched rendering by default, for improved performance +* Added SDL_RenderFlush() to force batched render commands to execute, if you're going to mix SDL rendering with native rendering +* Added the hint SDL_HINT_RENDER_BATCHING to control whether batching should be used for the rendering API. This defaults to "1" if you don't specify what rendering driver to use when creating the renderer. +* Added the hint SDL_HINT_EVENT_LOGGING to enable logging of SDL events for debugging purposes +* Added the hint SDL_HINT_GAMECONTROLLERCONFIG_FILE to specify a file that will be loaded at joystick initialization with game controller bindings +* Added the hint SDL_HINT_MOUSE_TOUCH_EVENTS to control whether SDL will synthesize touch events from mouse events +* Improved handling of malformed WAVE and BMP files, fixing potential security exploits + +Linux: +* Removed the Mir video driver in favor of Wayland + +iOS / tvOS: +* Added support for Xbox and PS4 wireless controllers in iOS 13 and tvOS 13 +* Added support for text input using Bluetooth keyboards + +Android: +* Added low latency audio using OpenSL ES +* Removed SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH (replaced by SDL_HINT_MOUSE_TOUCH_EVENTS and SDL_HINT_TOUCH_MOUSE_EVENTS) + SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH=1, should be replaced by setting both previous hints to 0. + SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH=0, should be replaced by setting both previous hints to 1. +* Added the hint SDL_HINT_ANDROID_BLOCK_ON_PAUSE to set whether the event loop will block itself when the app is paused. + + --------------------------------------------------------------------------- 2.0.9: --------------------------------------------------------------------------- diff --git a/libs/SDL2/docs/README-android.md b/libs/SDL2/docs/README-android.md index 7f3263dc3..9893dfeaf 100644 --- a/libs/SDL2/docs/README-android.md +++ b/libs/SDL2/docs/README-android.md @@ -20,7 +20,7 @@ https://developer.android.com/sdk/index.html Android NDK r15c or later https://developer.android.com/tools/sdk/ndk/index.html -Minimum API level supported by SDL: 14 (Android 4.0.1) +Minimum API level supported by SDL: 16 (Android 4.1) ================================================================================ @@ -174,7 +174,7 @@ http://ponystyle.com/blog/2010/03/26/dealing-with-asset-compression-in-android-a Pause / Resume behaviour ================================================================================ -If SDL is compiled with SDL_ANDROID_BLOCK_ON_PAUSE defined (the default), +If SDL_HINT_ANDROID_BLOCK_ON_PAUSE hint is set (the default), the event loop will block itself when the app is paused (ie, when the user returns to the main Android dashboard). Blocking is better in terms of battery use, and it allows your app to spring back to life instantaneously after resume @@ -380,13 +380,13 @@ https://developer.nvidia.com/tegra-graphics-debugger ================================================================================ - Why is API level 14 the minimum required? + Why is API level 16 the minimum required? ================================================================================ -The latest NDK toolchain doesn't support targeting earlier than API level 14. +The latest NDK toolchain doesn't support targeting earlier than API level 16. As of this writing, according to https://developer.android.com/about/dashboards/index.html -about 99% of the Android devices accessing Google Play support API level 14 or -higher (October 2017). +about 99% of the Android devices accessing Google Play support API level 16 or +higher (January 2018). ================================================================================ @@ -408,6 +408,24 @@ screen each frame. Reference: http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html +================================================================================ + Ending your application +================================================================================ + +Two legitimate ways: + +- return from your main() function. Java side will automatically terminate the +Activity by calling Activity.finish(). + +- Android OS can decide to terminate your application by calling onDestroy() +(see Activity life cycle). Your application will receive a SDL_QUIT event you +can handle to save things and quit. + +Don't call exit() as it stops the activity badly. + +NB: "Back button" can be handled as a SDL_KEYDOWN/UP events, with Keycode +SDLK_AC_BACK, for any purpose. + ================================================================================ Known issues ================================================================================ diff --git a/libs/SDL2/docs/README-linux.md b/libs/SDL2/docs/README-linux.md index 5274c60ef..bb3b1d9a4 100644 --- a/libs/SDL2/docs/README-linux.md +++ b/libs/SDL2/docs/README-linux.md @@ -25,9 +25,6 @@ fcitx-libs-dev libsamplerate0-dev libsndio-dev Ubuntu 16.04+ can also add "libwayland-dev libxkbcommon-dev wayland-protocols" to that command line for Wayland support. -Ubuntu 16.10 can also add "libmirclient-dev libxkbcommon-dev" to that command -line for Mir support. - NOTES: - This includes all the audio targets except arts, because Ubuntu pulled the artsc0-dev package, but in theory SDL still supports it. diff --git a/libs/SDL2/docs/README-macosx.md b/libs/SDL2/docs/README-macosx.md index 18d39518e..2cb80013f 100644 --- a/libs/SDL2/docs/README-macosx.md +++ b/libs/SDL2/docs/README-macosx.md @@ -100,7 +100,7 @@ You should replace EXE_NAME with the name of the executable. APP_NAME is what will be visible to the user in the Finder. Usually it will be the same as EXE_NAME but capitalized. E.g. if EXE_NAME is "testgame" then APP_NAME usually is "TestGame". You might also want to use `@PACKAGE@` to use the package -name as specified in your configure.in file. +name as specified in your configure.ac file. If your project builds more than one application, you will have to do a bit more. For each of your target applications, you need a separate rule. diff --git a/libs/SDL2/docs/README-porting.md b/libs/SDL2/docs/README-porting.md index cf8ef397a..82f35c628 100644 --- a/libs/SDL2/docs/README-porting.md +++ b/libs/SDL2/docs/README-porting.md @@ -13,7 +13,7 @@ There are two basic ways of building SDL at the moment: 1. The "UNIX" way: ./configure; make; make install - If you have a GNUish system, then you might try this. Edit configure.in, + If you have a GNUish system, then you might try this. Edit configure.ac, take a look at the large section labelled: "Set up the configuration based on the host platform!" diff --git a/libs/SDL2/docs/README-winrt.md b/libs/SDL2/docs/README-winrt.md index 35b7e6d87..fe539d83b 100644 --- a/libs/SDL2/docs/README-winrt.md +++ b/libs/SDL2/docs/README-winrt.md @@ -296,7 +296,7 @@ A few files should be included directly in your app's MSVC project, specifically included, mouse-position reporting may fail if and when the cursor is hidden, due to possible bugs/design-oddities in Windows itself.* -To include these files: +To include these files for C/C++ projects: 1. right-click on your project (again, in Visual C++'s Solution Explorer), navigate to "Add", then choose "Existing Item...". @@ -313,11 +313,14 @@ To include these files: 7. change the setting for "Consume Windows Runtime Extension" to "Yes (/ZW)". 8. click the OK button. This will close the dialog. - **NOTE: C++/CX compilation is currently required in at least one file of your app's project. This is to make sure that Visual C++'s linker builds a 'Windows Metadata' file (.winmd) for your app. Not doing so can lead to build errors.** +For non-C++ projects, you will need to call SDL_WinRTRunApp from your language's +main function, and generate SDL2-WinRTResources.res manually by using `rc` via +the Developer Command Prompt and including it as a within the +first block in your Visual Studio project file. ### 6. Add app code and assets ### diff --git a/libs/SDL2/i686-w64-mingw32/bin/SDL2.dll b/libs/SDL2/i686-w64-mingw32/bin/SDL2.dll index 701779044..3673be1ab 100755 Binary files a/libs/SDL2/i686-w64-mingw32/bin/SDL2.dll and b/libs/SDL2/i686-w64-mingw32/bin/SDL2.dll differ diff --git a/libs/SDL2/i686-w64-mingw32/bin/sdl2-config b/libs/SDL2/i686-w64-mingw32/bin/sdl2-config index e1060b3f2..18acfa7f7 100755 --- a/libs/SDL2/i686-w64-mingw32/bin/sdl2-config +++ b/libs/SDL2/i686-w64-mingw32/bin/sdl2-config @@ -39,7 +39,7 @@ while test $# -gt 0; do echo $exec_prefix ;; --version) - echo 2.0.9 + echo 2.0.10 ;; --cflags) echo -I${prefix}/include/SDL2 -Dmain=SDL_main @@ -49,7 +49,7 @@ while test $# -gt 0; do ;; --static-libs) # --libs|--static-libs) - echo -L${exec_prefix}/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -static-libgcc + echo -L${exec_prefix}/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -Wl,--dynamicbase -Wl,--nxcompat -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -static-libgcc ;; *) echo "${usage}" 1>&2 diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL.h index fc35a419e..88dce0c03 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_assert.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_assert.h index b38f928ae..8baecb63e 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_assert.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_atomic.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_atomic.h index b2287748c..deee35f91 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_atomic.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -162,12 +162,29 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") #elif defined(__GNUC__) && defined(__arm__) -#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) +#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */ +/* Information from: + https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19 + + The Linux kernel provides a helper function which provides the right code for a memory barrier, + hard-coded at address 0xffff0fa0 +*/ +typedef void (*SDL_KernelMemoryBarrierFunc)(); +#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#elif 0 /* defined(__QNXNTO__) */ +#include + +#define SDL_MemoryBarrierRelease() __cpu_membarrier() +#define SDL_MemoryBarrierAcquire() __cpu_membarrier() +#else +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__) #ifdef __thumb__ /* The mcr instruction isn't available in thumb mode, use real functions */ +#define SDL_MEMORY_BARRIER_USES_FUNCTION #define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction() #define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction() #else @@ -177,6 +194,7 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #else #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory") +#endif /* __LINUX__ || __ANDROID__ */ #endif /* __GNUC__ && __arm__ */ #else #if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_audio.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_audio.h index d3e1bface..305c01a9d 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_audio.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -420,23 +420,56 @@ extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev, /* @} *//* Pause audio functions */ /** - * This function loads a WAVE from the data source, automatically freeing - * that source if \c freesrc is non-zero. For example, to load a WAVE file, - * you could do: + * \brief Load the audio data of a WAVE file into memory + * + * Loading a WAVE file requires \c src, \c spec, \c audio_buf and \c audio_len + * to be valid pointers. The entire data portion of the file is then loaded + * into memory and decoded if necessary. + * + * If \c freesrc is non-zero, the data source gets automatically closed and + * freed before the function returns. + * + * Supported are RIFF WAVE files with the formats PCM (8, 16, 24, and 32 bits), + * IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and A-law and + * µ-law (8 bits). Other formats are currently unsupported and cause an error. + * + * If this function succeeds, the pointer returned by it is equal to \c spec + * and the pointer to the audio data allocated by the function is written to + * \c audio_buf and its length in bytes to \c audio_len. The \ref SDL_AudioSpec + * members \c freq, \c channels, and \c format are set to the values of the + * audio data in the buffer. The \c samples member is set to a sane default and + * all others are set to zero. + * + * It's necessary to use SDL_FreeWAV() to free the audio data returned in + * \c audio_buf when it is no longer used. + * + * Because of the underspecification of the Waveform format, there are many + * problematic files in the wild that cause issues with strict decoders. To + * provide compatibility with these files, this decoder is lenient in regards + * to the truncation of the file, the fact chunk, and the size of the RIFF + * chunk. The hints SDL_HINT_WAVE_RIFF_CHUNK_SIZE, SDL_HINT_WAVE_TRUNCATION, + * and SDL_HINT_WAVE_FACT_CHUNK can be used to tune the behavior of the + * loading process. + * + * Any file that is invalid (due to truncation, corruption, or wrong values in + * the headers), too big, or unsupported causes an error. Additionally, any + * critical I/O error from the data source will terminate the loading process + * with an error. The function returns NULL on error and in all cases (with the + * exception of \c src being NULL), an appropriate error message will be set. + * + * It is required that the data source supports seeking. + * + * Example: * \code * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...); * \endcode * - * If this function succeeds, it returns the given SDL_AudioSpec, - * filled with the audio data format of the wave data, and sets - * \c *audio_buf to a malloc()'d buffer containing the audio data, - * and sets \c *audio_len to the length of that audio buffer, in bytes. - * You need to free the audio buffer with SDL_FreeWAV() when you are - * done with it. - * - * This function returns NULL and sets the SDL error message if the - * wave file cannot be opened, uses an unknown data format, or is - * corrupt. Currently raw and MS-ADPCM WAVE files are supported. + * \param src The data source with the WAVE data + * \param freesrc A integer value that makes the function close the data source if non-zero + * \param spec A pointer filled with the audio format of the audio data + * \param audio_buf A pointer filled with the audio data allocated by the function + * \param audio_len A pointer filled with the length of the audio data buffer in bytes + * \return NULL on error, or non-NULL on success. */ extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_bits.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_bits.h index eb8322f0d..b116cc8d0 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_bits.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -101,6 +101,15 @@ SDL_MostSignificantBitIndex32(Uint32 x) #endif } +SDL_FORCE_INLINE SDL_bool +SDL_HasExactlyOneBitSet32(Uint32 x) +{ + if (x && !(x & (x - 1))) { + return SDL_TRUE; + } + return SDL_FALSE; +} + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_blendmode.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_blendmode.h index 36a5ea76f..6f0a22b99 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_blendmode.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -90,12 +90,12 @@ typedef enum /** * \brief Create a custom blend mode, which may or may not be supported by a given renderer * - * \param srcColorFactor - * \param dstColorFactor - * \param colorOperation - * \param srcAlphaFactor - * \param dstAlphaFactor - * \param alphaOperation + * \param srcColorFactor source color factor + * \param dstColorFactor destination color factor + * \param colorOperation color operation + * \param srcAlphaFactor source alpha factor + * \param dstAlphaFactor destination alpha factor + * \param alphaOperation alpha operation * * The result of the blend mode operation will be: * dstRGB = dstRGB * dstColorFactor colorOperation srcRGB * srcColorFactor diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_clipboard.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_clipboard.h index f28751ebb..c4f8766ce 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_clipboard.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_config.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_config.h index c58be8e72..395ad7c26 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_config.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_config.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_cpuinfo.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_cpuinfo.h index ee3a47e84..296df01aa 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_cpuinfo.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -41,24 +41,43 @@ #else #include #ifndef _WIN64 +#ifndef __MMX__ #define __MMX__ +#endif +#ifndef __3dNOW__ #define __3dNOW__ #endif +#endif +#ifndef __SSE__ #define __SSE__ +#endif +#ifndef __SSE2__ #define __SSE2__ +#endif #endif /* __clang__ */ #elif defined(__MINGW64_VERSION_MAJOR) #include #else -#ifdef __ALTIVEC__ -#if defined(HAVE_ALTIVEC_H) && !defined(__APPLE_ALTIVEC__) && !defined(SDL_DISABLE_ALTIVEC_H) +/* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC_H to have it included. */ +#if defined(HAVE_ALTIVEC_H) && defined(__ALTIVEC__) && !defined(__APPLE_ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC_H) #include -#undef pixel -#undef bool #endif -#endif -#if defined(__ARM_NEON__) && !defined(SDL_DISABLE_ARM_NEON_H) -#include +#if !defined(SDL_DISABLE_ARM_NEON_H) +# if defined(__ARM_NEON) +# include +# elif defined(__WINDOWS__) || defined(__WINRT__) +/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */ +# if defined(_M_ARM) +# include +# include +# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */ +# endif +# if defined (_M_ARM64) +# include +# include +# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */ +# endif +# endif #endif #if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H) #include @@ -177,6 +196,69 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void); */ extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void); +/** + * \brief Report the alignment this system needs for SIMD allocations. + * + * This will return the minimum number of bytes to which a pointer must be + * aligned to be compatible with SIMD instructions on the current machine. + * For example, if the machine supports SSE only, it will return 16, but if + * it supports AVX-512F, it'll return 64 (etc). This only reports values for + * instruction sets SDL knows about, so if your SDL build doesn't have + * SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and + * not 64 for the AVX-512 instructions that exist but SDL doesn't know about. + * Plan accordingly. + */ +extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void); + +/** + * \brief Allocate memory in a SIMD-friendly way. + * + * This will allocate a block of memory that is suitable for use with SIMD + * instructions. Specifically, it will be properly aligned and padded for + * the system's supported vector instructions. + * + * The memory returned will be padded such that it is safe to read or write + * an incomplete vector at the end of the memory block. This can be useful + * so you don't have to drop back to a scalar fallback at the end of your + * SIMD processing loop to deal with the final elements without overflowing + * the allocated buffer. + * + * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free() + * or delete[], etc. + * + * Note that SDL will only deal with SIMD instruction sets it is aware of; + * for example, SDL 2.0.8 knows that SSE wants 16-byte vectors + * (SDL_HasSSE()), and AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't + * know that AVX-512 wants 64. To be clear: if you can't decide to use an + * instruction set with an SDL_Has*() function, don't use that instruction + * set with memory allocated through here. + * + * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't + * out of memory. + * + * \param len The length, in bytes, of the block to allocated. The actual + * allocated block might be larger due to padding, etc. + * \return Pointer to newly-allocated block, NULL if out of memory. + * + * \sa SDL_SIMDAlignment + * \sa SDL_SIMDFree + */ +extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len); + +/** + * \brief Deallocate memory obtained from SDL_SIMDAlloc + * + * It is not valid to use this function on a pointer from anything but + * SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc, + * SDL_malloc, memalign, new[], etc. + * + * However, SDL_SIMDFree(NULL) is a legal no-op. + * + * \sa SDL_SIMDAlloc + */ +extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr); + +/* vi: set ts=4 sw=4 expandtab: */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_egl.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_egl.h index d65ed437c..f50fa5c9b 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_egl.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_egl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_endian.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_endian.h index ed0bf5ba8..54d5d486d 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_endian.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_error.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_error.h index c0e46298e..24416e693 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_error.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_events.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_events.h index af22eb646..282b9fb76 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_events.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -594,6 +594,9 @@ typedef union SDL_Event Uint8 padding[56]; } SDL_Event; +/* Make sure we haven't broken binary compatibility */ +SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == 56); + /* Function prototypes */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_filesystem.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_filesystem.h index fa6a1fa6e..6d97e5896 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_filesystem.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_filesystem.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gamecontroller.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gamecontroller.h index 6ae9c9542..ebde38715 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gamecontroller.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gamecontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gesture.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gesture.h index b223d80d4..9d25e9c1d 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gesture.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_gesture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_haptic.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_haptic.h index 2ea1bfc16..075627685 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_haptic.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hints.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hints.h index 4ee72e97d..8fa0dd660 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hints.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -315,6 +315,16 @@ extern "C" { */ #define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" +/** + * \brief A variable controlling whether mouse events should generate synthetic touch events + * + * This variable can be set to the following values: + * "0" - Mouse events will not generate touch events (default for desktop platforms) + * "1" - Mouse events will generate touch events (default for mobile platforms, such as Android and iOS) + */ + +#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" + /** * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to true. * @@ -436,6 +446,16 @@ extern "C" { */ #define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG" +/** + * \brief A variable that lets you provide a file with extra gamecontroller db entries. + * + * The file should contain lines of gamecontroller config data, see SDL_gamecontroller.h + * + * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER) + * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping() + */ +#define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE" + /** * \brief A variable containing a list of devices to skip when scanning for game controllers. * @@ -836,19 +856,7 @@ extern "C" { */ #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" - /** - * \brief A variable to control whether mouse and touch events are to be treated together or separately - * - * The variable can be set to the following values: - * "0" - Mouse events will be handled as touch events, and touch will raise fake mouse - * events. This is the behaviour of SDL <= 2.0.3. (default) - * "1" - Mouse events will be handled separately from pure touch events. - * - * The value of this hint is used at runtime, so it can be changed at any time. - */ -#define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH" - - /** +/** * \brief A variable to control whether we trap the Android back button to handle it manually. * This is necessary for the right mouse button to work on some Android devices, or * to be able to trap the back button for use in your code reliably. If set to true, @@ -865,6 +873,17 @@ extern "C" { */ #define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON" +/** + * \brief A variable to control whether the event loop will block itself when the app is paused. + * + * The variable can be set to the following values: + * "0" - Non blocking. + * "1" - Blocking. (default) + * + * The value should be set before SDL is initialized. + */ +#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE" + /** * \brief A variable to control whether the return key on the soft keyboard * should hide the soft keyboard on Android and iOS. @@ -1043,6 +1062,118 @@ extern "C" { */ #define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY" +/** + * \brief A variable controlling whether the 2D render API is compatible or efficient. + * + * This variable can be set to the following values: + * + * "0" - Don't use batching to make rendering more efficient. + * "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls. + * + * Up to SDL 2.0.9, the render API would draw immediately when requested. Now + * it batches up draw requests and sends them all to the GPU only when forced + * to (during SDL_RenderPresent, when changing render targets, by updating a + * texture that the batch needs, etc). This is significantly more efficient, + * but it can cause problems for apps that expect to render on top of the + * render API's output. As such, SDL will disable batching if a specific + * render backend is requested (since this might indicate that the app is + * planning to use the underlying graphics API directly). This hint can + * be used to explicitly request batching in this instance. It is a contract + * that you will either never use the underlying graphics API directly, or + * if you do, you will call SDL_RenderFlush() before you do so any current + * batch goes to the GPU before your work begins. Not following this contract + * will result in undefined behavior. + */ +#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" + + +/** + * \brief A variable controlling whether SDL logs all events pushed onto its internal queue. + * + * This variable can be set to the following values: + * + * "0" - Don't log any events (default) + * "1" - Log all events except mouse and finger motion, which are pretty spammy. + * "2" - Log all events. + * + * This is generally meant to be used to debug SDL itself, but can be useful + * for application developers that need better visibility into what is going + * on in the event queue. Logged events are sent through SDL_Log(), which + * means by default they appear on stdout on most platforms or maybe + * OutputDebugString() on Windows, and can be funneled by the app with + * SDL_LogSetOutputFunction(), etc. + * + * This hint can be toggled on and off at runtime, if you only need to log + * events for a small subset of program execution. + */ +#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" + + + +/** + * \brief Controls how the size of the RIFF chunk affects the loading of a WAVE file. + * + * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE + * file) is not always reliable. In case the size is wrong, it's possible to + * just ignore it and step through the chunks until a fixed limit is reached. + * + * Note that files that have trailing data unrelated to the WAVE file or + * corrupt files may slow down the loading process without a reliable boundary. + * By default, SDL stops after 10000 chunks to prevent wasting time. Use the + * environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value. + * + * This variable can be set to the following values: + * + * "force" - Always use the RIFF chunk size as a boundary for the chunk search + * "ignorezero" - Like "force", but a zero size searches up to 4 GiB (default) + * "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB + * "maximum" - Search for chunks until the end of file (not recommended) + */ +#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE" + +/** + * \brief Controls how a truncated WAVE file is handled. + * + * A WAVE file is considered truncated if any of the chunks are incomplete or + * the data chunk size is not a multiple of the block size. By default, SDL + * decodes until the first incomplete block, as most applications seem to do. + * + * This variable can be set to the following values: + * + * "verystrict" - Raise an error if the file is truncated + * "strict" - Like "verystrict", but the size of the RIFF chunk is ignored + * "dropframe" - Decode until the first incomplete sample frame + * "dropblock" - Decode until the first incomplete block (default) + */ +#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" + +/** + * \brief Controls how the fact chunk affects the loading of a WAVE file. + * + * The fact chunk stores information about the number of samples of a WAVE + * file. The Standards Update from Microsoft notes that this value can be used + * to 'determine the length of the data in seconds'. This is especially useful + * for compressed formats (for which this is a mandatory chunk) if they produce + * multiple sample frames per block and truncating the block is not allowed. + * The fact chunk can exactly specify how many sample frames there should be + * in this case. + * + * Unfortunately, most application seem to ignore the fact chunk and so SDL + * ignores it by default as well. + * + * This variable can be set to the following values: + * + * "truncate" - Use the number of samples to truncate the wave data if + * the fact chunk is present and valid + * "strict" - Like "truncate", but raise an error if the fact chunk + * is invalid, not present for non-PCM formats, or if the + * data chunk doesn't have that many samples + * "ignorezero" - Like "truncate", but ignore fact chunk if the number of + * samples is zero + * "ignore" - Ignore fact chunk entirely (default) + */ +#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" + /** * \brief An enumeration of hint priorities */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_joystick.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_joystick.h index 6e05a9c20..3a4c5d177 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_joystick.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keyboard.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keyboard.h index 874823171..4b2a055d8 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keyboard.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keycode.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keycode.h index d7d5b1dbc..3bceb418a 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keycode.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_loadso.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_loadso.h index da56fb452..793ba5358 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_loadso.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_log.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_log.h index e12b65886..40f768d57 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_log.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_main.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_main.h index 98558217f..623f2d005 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_main.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -55,6 +55,10 @@ /* On iOS SDL provides a main function that creates an application delegate and starts the iOS application run loop. + If you link with SDL dynamically on iOS, the main function can't be in a + shared library, so you need to link with libSDLmain.a, which includes a + stub main function that calls into the shared library to start execution. + See src/video/uikit/SDL_uikitappdelegate.m for more details. */ #define SDL_MAIN_NEEDED @@ -82,12 +86,6 @@ #endif #endif /* SDL_MAIN_HANDLED */ -#ifdef __cplusplus -#define C_LINKAGE "C" -#else -#define C_LINKAGE -#endif /* __cplusplus */ - #ifndef SDLMAIN_DECLSPEC #define SDLMAIN_DECLSPEC #endif @@ -111,17 +109,18 @@ #define main SDL_main #endif -/** - * The prototype for the application's main() function - */ -extern C_LINKAGE SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]); - - #include "begin_code.h" #ifdef __cplusplus extern "C" { #endif +/** + * The prototype for the application's main() function + */ +typedef int (*SDL_main_func)(int argc, char *argv[]); +extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]); + + /** * This is called by the real SDL main function to let the rest of the * library know that initialization was done properly. @@ -136,8 +135,7 @@ extern DECLSPEC void SDLCALL SDL_SetMainReady(void); /** * This can be called to set the application class at startup */ -extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, - void *hInst); +extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, void *hInst); extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); #endif /* __WIN32__ */ @@ -153,10 +151,24 @@ extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); * \return 0 on success, -1 on failure. On failure, use SDL_GetError to retrieve more * information on the failure. */ -extern DECLSPEC int SDLCALL SDL_WinRTRunApp(int (*mainFunction)(int, char **), void * reserved); +extern DECLSPEC int SDLCALL SDL_WinRTRunApp(SDL_main_func mainFunction, void * reserved); #endif /* __WINRT__ */ +#if defined(__IPHONEOS__) + +/** + * \brief Initializes and launches an SDL application. + * + * \param argc The argc parameter from the application's main() function + * \param argv The argv parameter from the application's main() function + * \param mainFunction The SDL app's C-style main(). + * \return the return value from mainFunction + */ +extern DECLSPEC int SDLCALL SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction); + +#endif /* __IPHONEOS__ */ + #ifdef __cplusplus } diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_messagebox.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_messagebox.h index b7be59d88..e34b55477 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_messagebox.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mouse.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mouse.h index d3c9f6156..277559d23 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mouse.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mutex.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mutex.h index ba4247ced..970e78713 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mutex.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_name.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_name.h index ecd863f4c..690a8199b 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_name.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_name.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengl.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengl.h index 253d9c93a..6685be73e 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengl.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles.h index 18dd984b3..1e0660c3d 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles2.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles2.h index 6ccecf216..df29d3840 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles2.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_pixels.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_pixels.h index 0b4364b18..dcb7a980d 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_pixels.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -168,7 +168,7 @@ enum ((format) && (SDL_PIXELFLAG(format) != 1)) /* Note: If you modify this list, update SDL_GetPixelFormatName() */ -enum +typedef enum { SDL_PIXELFORMAT_UNKNOWN, SDL_PIXELFORMAT_INDEX1LSB = @@ -290,7 +290,7 @@ enum SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'), SDL_PIXELFORMAT_EXTERNAL_OES = /**< Android video texture format */ SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') -}; +} SDL_PixelFormatEnum; typedef struct SDL_Color { diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_platform.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_platform.h index 7dea4ce94..c2cbc6b4e 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_platform.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_power.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_power.h index a4fe8a935..4831cb77e 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_power.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_quit.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_quit.h index fea56a8d8..c979983cb 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_quit.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_quit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rect.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rect.h index 543bb6186..71a411517 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rect.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -40,7 +40,7 @@ extern "C" { #endif /** - * \brief The structure that defines a point + * \brief The structure that defines a point (integer) * * \sa SDL_EnclosePoints * \sa SDL_PointInRect @@ -52,7 +52,20 @@ typedef struct SDL_Point } SDL_Point; /** - * \brief A rectangle, with the origin at the upper left. + * \brief The structure that defines a point (floating point) + * + * \sa SDL_EnclosePoints + * \sa SDL_PointInRect + */ +typedef struct SDL_FPoint +{ + float x; + float y; +} SDL_FPoint; + + +/** + * \brief A rectangle, with the origin at the upper left (integer). * * \sa SDL_RectEmpty * \sa SDL_RectEquals @@ -67,6 +80,19 @@ typedef struct SDL_Rect int w, h; } SDL_Rect; + +/** + * \brief A rectangle, with the origin at the upper left (floating point). + */ +typedef struct SDL_FRect +{ + float x; + float y; + float w; + float h; +} SDL_FRect; + + /** * \brief Returns true if point resides inside a rectangle. */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_render.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_render.h index d33619297..096b4a577 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_render.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -835,6 +835,148 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer, const SDL_Point *center, const SDL_RendererFlip flip); + +/** + * \brief Draw a point on the current rendering target. + * + * \param renderer The renderer which should draw a point. + * \param x The x coordinate of the point. + * \param y The y coordinate of the point. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer, + float x, float y); + +/** + * \brief Draw multiple points on the current rendering target. + * + * \param renderer The renderer which should draw multiple points. + * \param points The points to draw + * \param count The number of points to draw + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer, + const SDL_FPoint * points, + int count); + +/** + * \brief Draw a line on the current rendering target. + * + * \param renderer The renderer which should draw a line. + * \param x1 The x coordinate of the start point. + * \param y1 The y coordinate of the start point. + * \param x2 The x coordinate of the end point. + * \param y2 The y coordinate of the end point. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer, + float x1, float y1, float x2, float y2); + +/** + * \brief Draw a series of connected lines on the current rendering target. + * + * \param renderer The renderer which should draw multiple lines. + * \param points The points along the lines + * \param count The number of points, drawing count-1 lines + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer, + const SDL_FPoint * points, + int count); + +/** + * \brief Draw a rectangle on the current rendering target. + * + * \param renderer The renderer which should draw a rectangle. + * \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer, + const SDL_FRect * rect); + +/** + * \brief Draw some number of rectangles on the current rendering target. + * + * \param renderer The renderer which should draw multiple rectangles. + * \param rects A pointer to an array of destination rectangles. + * \param count The number of rectangles. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer, + const SDL_FRect * rects, + int count); + +/** + * \brief Fill a rectangle on the current rendering target with the drawing color. + * + * \param renderer The renderer which should fill a rectangle. + * \param rect A pointer to the destination rectangle, or NULL for the entire + * rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer, + const SDL_FRect * rect); + +/** + * \brief Fill some number of rectangles on the current rendering target with the drawing color. + * + * \param renderer The renderer which should fill multiple rectangles. + * \param rects A pointer to an array of destination rectangles. + * \param count The number of rectangles. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer, + const SDL_FRect * rects, + int count); + +/** + * \brief Copy a portion of the texture to the current rendering target. + * + * \param renderer The renderer which should copy parts of a texture. + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire + * texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the + * entire rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_FRect * dstrect); + +/** + * \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center + * + * \param renderer The renderer which should copy parts of a texture. + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire + * texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the + * entire rendering target. + * \param angle An angle in degrees that indicates the rotation that will be applied to dstrect, rotating it in a clockwise direction + * \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2). + * \param flip An SDL_RendererFlip value stating which flipping actions should be performed on the texture + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_FRect * dstrect, + const double angle, + const SDL_FPoint *center, + const SDL_RendererFlip flip); + /** * \brief Read pixels from the current rendering target. * @@ -876,6 +1018,31 @@ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture * texture); */ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer * renderer); +/** + * \brief Force the rendering context to flush any pending commands to the + * underlying rendering API. + * + * You do not need to (and in fact, shouldn't) call this function unless + * you are planning to call into OpenGL/Direct3D/Metal/whatever directly + * in addition to using an SDL_Renderer. + * + * This is for a very-specific case: if you are using SDL's render API, + * you asked for a specific renderer backend (OpenGL, Direct3D, etc), + * you set SDL_HINT_RENDER_BATCHING to "1", and you plan to make + * OpenGL/D3D/whatever calls in addition to SDL render API calls. If all of + * this applies, you should call SDL_RenderFlush() between calls to SDL's + * render API and the low-level API you're using in cooperation. + * + * In all other cases, you can ignore this function. This is only here to + * get maximum performance out of a specific situation. In all other cases, + * SDL will do the right thing, perhaps at a performance loss. + * + * This function is first available in SDL 2.0.10, and is not needed in + * 2.0.9 and earlier, as earlier versions did not queue rendering commands + * at all, instead flushing them to the OS immediately. + */ +extern DECLSPEC int SDLCALL SDL_RenderFlush(SDL_Renderer * renderer); + /** * \brief Bind the texture to the current OpenGL/ES/ES2 context for use with diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_revision.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_revision.h index 92fbe67b1..3b3fc85ea 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_revision.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_revision.h @@ -1,2 +1,2 @@ -#define SDL_REVISION "hg-12373:8feb5da6f2fb" -#define SDL_REVISION_NUMBER 12373 +#define SDL_REVISION "hg-12952:bc90ce38f1e2" +#define SDL_REVISION_NUMBER 12952 diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rwops.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rwops.h index 0960699d4..f66119fb0 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rwops.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_rwops.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -176,19 +176,48 @@ extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area); #define RW_SEEK_END 2 /**< Seek relative to the end of data */ /** - * \name Read/write macros - * - * Macros to easily read and write from an SDL_RWops structure. + * Return the size of the file in this rwops, or -1 if unknown */ -/* @{ */ -#define SDL_RWsize(ctx) (ctx)->size(ctx) -#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence) -#define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, RW_SEEK_CUR) -#define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n) -#define SDL_RWwrite(ctx, ptr, size, n) (ctx)->write(ctx, ptr, size, n) -#define SDL_RWclose(ctx) (ctx)->close(ctx) -/* @} *//* Read/write macros */ +extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context); +/** + * Seek to \c offset relative to \c whence, one of stdio's whence values: + * RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END + * + * \return the final offset in the data stream, or -1 on error. + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context, + Sint64 offset, int whence); + +/** + * Return the current offset in the data stream, or -1 on error. + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context); + +/** + * Read up to \c maxnum objects each of size \c size from the data + * stream to the area pointed at by \c ptr. + * + * \return the number of objects read, or 0 at error or end of file. + */ +extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, + void *ptr, size_t size, size_t maxnum); + +/** + * Write exactly \c num objects each of size \c size from the area + * pointed at by \c ptr to data stream. + * + * \return the number of objects written, or 0 at error or end of file. + */ +extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, + const void *ptr, size_t size, size_t num); + +/** + * Close and free an allocated SDL_RWops structure. + * + * \return 0 if successful or -1 on write error when flushing data. + */ +extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context); /** * Load all the data from an SDL data stream. @@ -209,9 +238,17 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, /** * Load an entire file. * - * Convenience macro. + * The data is allocated with a zero byte at the end (null terminated) + * + * If \c datasize is not NULL, it is filled with the size of the data read. + * + * If \c freesrc is non-zero, the stream will be closed after being read. + * + * The data should be freed with SDL_free(). + * + * \return the data, or NULL if there was an error. */ -#define SDL_LoadFile(file, datasize) SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, 1) +extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize); /** * \name Read endian functions diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_scancode.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_scancode.h index 63871aa3b..a50305f55 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_scancode.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -38,7 +38,7 @@ * SDL_Event structure. * * The values in this enumeration are based on the USB usage page standard: - * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf + * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf */ typedef enum { diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_sensor.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_sensor.h index ac163a8cd..966adbf21 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_sensor.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_sensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -26,8 +26,8 @@ * */ -#ifndef _SDL_sensor_h -#define _SDL_sensor_h +#ifndef SDL_sensor_h_ +#define SDL_sensor_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -246,6 +246,6 @@ extern DECLSPEC void SDLCALL SDL_SensorUpdate(void); #endif #include "close_code.h" -#endif /* _SDL_sensor_h */ +#endif /* SDL_sensor_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_shape.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_shape.h index 40a6baaae..2ab43fcdc 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_shape.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_shape.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_stdinc.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_stdinc.h index e373bc380..28bb7b961 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_stdinc.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_surface.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_surface.h index 730d49fc8..51a128300 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_surface.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -53,6 +53,7 @@ extern "C" { #define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */ #define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */ #define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */ +#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */ /* @} *//* Surface flags */ /** diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_system.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_system.h index 4dc372d6b..3b0840769 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_system.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_syswm.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_syswm.h index f1c4021cc..7aa8c6869 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_syswm.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_syswm.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -34,16 +34,16 @@ #include "SDL_version.h" /** - * \file SDL_syswm.h + * \brief SDL_syswm.h * * Your application has access to a special type of event ::SDL_SYSWMEVENT, * which contains window-manager specific information and arrives whenever * an unhandled window event occurs. This event is ignored by default, but * you can enable it with SDL_EventState(). */ -#ifdef SDL_PROTOTYPES_ONLY struct SDL_SysWMinfo; -#else + +#if !defined(SDL_PROTOTYPES_ONLY) #if defined(SDL_VIDEO_DRIVER_WINDOWS) #ifndef WIN32_LEAN_AND_MEAN @@ -103,6 +103,8 @@ typedef void *EGLSurface; #if defined(SDL_VIDEO_DRIVER_VIVANTE) #include "SDL_egl.h" #endif +#endif /* SDL_PROTOTYPES_ONLY */ + #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ @@ -110,6 +112,7 @@ typedef void *EGLSurface; extern "C" { #endif +#if !defined(SDL_PROTOTYPES_ONLY) /** * These are the various supported windowing subsystems */ @@ -122,7 +125,7 @@ typedef enum SDL_SYSWM_COCOA, SDL_SYSWM_UIKIT, SDL_SYSWM_WAYLAND, - SDL_SYSWM_MIR, + SDL_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ SDL_SYSWM_WINRT, SDL_SYSWM_ANDROID, SDL_SYSWM_VIVANTE, @@ -257,11 +260,11 @@ struct SDL_SysWMinfo struct wl_shell_surface *shell_surface; /**< Wayland shell_surface (window manager handle) */ } wl; #endif -#if defined(SDL_VIDEO_DRIVER_MIR) +#if defined(SDL_VIDEO_DRIVER_MIR) /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ struct { - struct MirConnection *connection; /**< Mir display server connection */ - struct MirSurface *surface; /**< Mir surface */ + void *connection; /**< Mir display server connection */ + void *surface; /**< Mir surface */ } mir; #endif diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test.h index 6cc373bf8..17a33dc2c 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_assert.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_assert.h index 1788d7a20..b3ebb62fb 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_assert.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_common.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_common.h index be2e6b2aa..c34d0d103 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_common.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -140,14 +140,20 @@ SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags); */ int SDLTest_CommonArg(SDLTest_CommonState * state, int index); + /** - * \brief Returns common usage information + * \brief Logs command line usage info. * - * \param state The common state describing the test window to create. + * This logs the appropriate command line options for the subsystems in use + * plus other common options, and then any application-specific options. + * This uses the SDL_Log() function and splits up output to be friendly to + * 80-character-wide terminals. * - * \returns String with usage information + * \param state The common state describing the test window for the app. + * \param argv0 argv[0], as passed to main/SDL_main. + * \param options an array of strings for application specific options. The last element of the array should be NULL. */ -const char *SDLTest_CommonUsage(SDLTest_CommonState * state); +void SDLTest_CommonLogUsage(SDLTest_CommonState * state, const char *argv0, const char **options); /** * \brief Open test window. @@ -158,6 +164,17 @@ const char *SDLTest_CommonUsage(SDLTest_CommonState * state); */ SDL_bool SDLTest_CommonInit(SDLTest_CommonState * state); +/** + * \brief Easy argument handling when test app doesn't need any custom args. + * + * \param state The common state describing the test window to create. + * \param argc argc, as supplied to SDL_main + * \param argv argv, as supplied to SDL_main + * + * \returns False if app should quit, true otherwise. + */ +SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState * state, const int argc, char **argv); + /** * \brief Common event handler for test windows. * diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_compare.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_compare.h index c22e447d8..1f751c8b9 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_compare.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_crc32.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_crc32.h index 3d235d074..e615d8929 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_crc32.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_font.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_font.h index 59cbdcad6..8fa078440 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_font.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_fuzzer.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_fuzzer.h index 8fcb9ebbf..7259685a9 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_fuzzer.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_harness.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_harness.h index 8641e0a7e..f5ae92ceb 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_harness.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_images.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_images.h index 9c4dd5b82..b8934812f 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_images.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_images.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_log.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_log.h index ebd44fb50..01d0fedac 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_log.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_md5.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_md5.h index 0e4105768..2bfd7dff9 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_md5.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_memory.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_memory.h index 4827ae6f2..5d4d39ea5 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_memory.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -42,14 +42,14 @@ extern "C" { * * \note This should be called before any other SDL functions for complete tracking coverage */ -int SDLTest_TrackAllocations(); +int SDLTest_TrackAllocations(void); /** * \brief Print a log of any outstanding allocations * * \note This can be called after SDL_Quit() */ -void SDLTest_LogAllocations(); +void SDLTest_LogAllocations(void); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_random.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_random.h index 0eb414ff2..71e9c70b6 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_random.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_test_random.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_thread.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_thread.h index 554dd0b61..f78b1145d 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_thread.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_timer.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_timer.h index 5600618ff..2a47b043a 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_timer.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_touch.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_touch.h index f4075e79a..99dbcb8c3 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_touch.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -41,6 +41,14 @@ extern "C" { typedef Sint64 SDL_TouchID; typedef Sint64 SDL_FingerID; +typedef enum +{ + SDL_TOUCH_DEVICE_INVALID = -1, + SDL_TOUCH_DEVICE_DIRECT, /* touch screen with window-relative coordinates */ + SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, /* trackpad with absolute device coordinates */ + SDL_TOUCH_DEVICE_INDIRECT_RELATIVE /* trackpad with screen cursor-relative coordinates */ +} SDL_TouchDeviceType; + typedef struct SDL_Finger { SDL_FingerID id; @@ -52,6 +60,9 @@ typedef struct SDL_Finger /* Used as the device ID for mouse events simulated with touch input */ #define SDL_TOUCH_MOUSEID ((Uint32)-1) +/* Used as the SDL_TouchID for touch events simulated with mouse input */ +#define SDL_MOUSE_TOUCHID ((Sint64)-1) + /* Function prototypes */ @@ -65,6 +76,11 @@ extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void); */ extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index); +/** + * \brief Get the type of the given touch device. + */ +extern DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID); + /** * \brief Get the number of active fingers for a given touch device. */ diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_types.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_types.h index 4ac248c8c..9c3e9896f 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_types.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_types.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_version.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_version.h index 31443e149..6c7499d32 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_version.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -59,7 +59,7 @@ typedef struct SDL_version */ #define SDL_MAJOR_VERSION 2 #define SDL_MINOR_VERSION 0 -#define SDL_PATCHLEVEL 9 +#define SDL_PATCHLEVEL 10 /** * \brief Macro to determine SDL version program was compiled against. diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_video.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_video.h index 461f13805..352afd436 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_video.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_vulkan.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_vulkan.h index 972cca4d7..d69a436b3 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_vulkan.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/SDL_vulkan.h @@ -98,8 +98,8 @@ typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */ * applications to link with libvulkan (and historically MoltenVK was * provided as a static library). If it is not found then, on macOS, SDL * will attempt to load \c vulkan.framework/vulkan, \c libvulkan.1.dylib, - * \c MoltenVK.framework/MoltenVK and \c libMoltenVK.dylib in that order. - * On iOS SDL will attempt to load \c libMoltenVK.dylib. Applications + * followed by \c libvulkan.dylib, in that order. + * On iOS SDL will attempt to load \c libvulkan.dylib only. Applications * using a dynamic framework or .dylib must ensure it is included in its * application bundle. * @@ -153,7 +153,7 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * is smaller than the number of required extensions, \c SDL_FALSE will be * returned instead of \c SDL_TRUE, to indicate that not all the required * extensions were returned. - * + * * \note If \c window is not NULL, it will be checked against its creation * flags to ensure that the Vulkan flag is present. This parameter * will be removed in a future major release. diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/begin_code.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/begin_code.h index 6c2106246..22c997c41 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/begin_code.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -105,6 +105,9 @@ #ifdef _MSC_VER #pragma warning(disable: 4103) #endif +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpragma-pack" +#endif #ifdef __BORLANDC__ #pragma nopackwarning #endif diff --git a/libs/SDL2/i686-w64-mingw32/include/SDL2/close_code.h b/libs/SDL2/i686-w64-mingw32/include/SDL2/close_code.h index b3b70a4c8..8e4cac3da 100644 --- a/libs/SDL2/i686-w64-mingw32/include/SDL2/close_code.h +++ b/libs/SDL2/i686-w64-mingw32/include/SDL2/close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -26,6 +26,9 @@ * after you finish any function and structure declarations in your headers */ +#ifndef _begin_code_h +#error close_code.h included without matching begin_code.h +#endif #undef _begin_code_h /* Reset structure packing at previous byte alignment */ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.a b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.a index 05489a95a..bee8366f9 100644 Binary files a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.a and b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.a differ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.dll.a b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.dll.a index b20371a13..c74106707 100755 Binary files a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.dll.a and b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.dll.a differ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.la b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.la index 3848c7db9..c4caaf3b0 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/libSDL2.la +++ b/libs/SDL2/i686-w64-mingw32/lib/libSDL2.la @@ -23,8 +23,8 @@ dependency_libs=' -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 - weak_library_names='' # Version information for libSDL2. -current=9 -age=9 +current=10 +age=10 revision=0 # Is this an already installed library? @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL/SDL2-2.0.9/i686-w64-mingw32/lib' +libdir='/Users/valve/release/SDL/SDL2-2.0.10/i686-w64-mingw32/lib' diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.a b/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.a index 190f9e072..997c1d4f5 100644 Binary files a/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.a and b/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.a differ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.la b/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.la index 5f96235bd..169f37757 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.la +++ b/libs/SDL2/i686-w64-mingw32/lib/libSDL2_test.la @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL/SDL2-2.0.9/i686-w64-mingw32/lib' +libdir='/Users/valve/release/SDL/SDL2-2.0.10/i686-w64-mingw32/lib' diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.a b/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.a index df7c95b95..aa33741d2 100644 Binary files a/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.a and b/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.a differ diff --git a/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.la b/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.la index d01b8a172..883237adb 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.la +++ b/libs/SDL2/i686-w64-mingw32/lib/libSDL2main.la @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL/SDL2-2.0.9/i686-w64-mingw32/lib' +libdir='/Users/valve/release/SDL/SDL2-2.0.10/i686-w64-mingw32/lib' diff --git a/libs/SDL2/i686-w64-mingw32/lib/pkgconfig/sdl2.pc b/libs/SDL2/i686-w64-mingw32/lib/pkgconfig/sdl2.pc index 25fc5928e..4e29497c8 100644 --- a/libs/SDL2/i686-w64-mingw32/lib/pkgconfig/sdl2.pc +++ b/libs/SDL2/i686-w64-mingw32/lib/pkgconfig/sdl2.pc @@ -7,9 +7,9 @@ includedir=${prefix}/include Name: sdl2 Description: Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer. -Version: 2.0.9 +Version: 2.0.10 Requires: Conflicts: Libs: -L${libdir} -lmingw32 -lSDL2main -lSDL2 -mwindows -Libs.private: -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -static-libgcc +Libs.private: -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -Wl,--dynamicbase -Wl,--nxcompat -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -static-libgcc Cflags: -I${includedir}/SDL2 -Dmain=SDL_main diff --git a/libs/SDL2/i686-w64-mingw32/share/aclocal/sdl2.m4 b/libs/SDL2/i686-w64-mingw32/share/aclocal/sdl2.m4 index b915f99ed..0a73bc7d4 100644 --- a/libs/SDL2/i686-w64-mingw32/share/aclocal/sdl2.m4 +++ b/libs/SDL2/i686-w64-mingw32/share/aclocal/sdl2.m4 @@ -74,7 +74,7 @@ AC_ARG_VAR(SDL2_FRAMEWORK, [Path to SDL2.framework]) done fi - if test -d $sdl_framework; then + if test x"$sdl_framework" != x && test -d "$sdl_framework"; then AC_MSG_RESULT($sdl_framework) sdl_framework_dir=`dirname $sdl_framework` SDL_CFLAGS="-F$sdl_framework_dir -Wl,-framework,SDL2 -I$sdl_framework/include" diff --git a/libs/SDL2/include/SDL.h b/libs/SDL2/include/SDL.h index fc35a419e..88dce0c03 100644 --- a/libs/SDL2/include/SDL.h +++ b/libs/SDL2/include/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_assert.h b/libs/SDL2/include/SDL_assert.h index b38f928ae..8baecb63e 100644 --- a/libs/SDL2/include/SDL_assert.h +++ b/libs/SDL2/include/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_atomic.h b/libs/SDL2/include/SDL_atomic.h index b2287748c..deee35f91 100644 --- a/libs/SDL2/include/SDL_atomic.h +++ b/libs/SDL2/include/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -162,12 +162,29 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") #elif defined(__GNUC__) && defined(__arm__) -#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) +#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */ +/* Information from: + https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19 + + The Linux kernel provides a helper function which provides the right code for a memory barrier, + hard-coded at address 0xffff0fa0 +*/ +typedef void (*SDL_KernelMemoryBarrierFunc)(); +#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#elif 0 /* defined(__QNXNTO__) */ +#include + +#define SDL_MemoryBarrierRelease() __cpu_membarrier() +#define SDL_MemoryBarrierAcquire() __cpu_membarrier() +#else +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__) #ifdef __thumb__ /* The mcr instruction isn't available in thumb mode, use real functions */ +#define SDL_MEMORY_BARRIER_USES_FUNCTION #define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction() #define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction() #else @@ -177,6 +194,7 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #else #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory") +#endif /* __LINUX__ || __ANDROID__ */ #endif /* __GNUC__ && __arm__ */ #else #if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) diff --git a/libs/SDL2/include/SDL_audio.h b/libs/SDL2/include/SDL_audio.h index d3e1bface..305c01a9d 100644 --- a/libs/SDL2/include/SDL_audio.h +++ b/libs/SDL2/include/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -420,23 +420,56 @@ extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev, /* @} *//* Pause audio functions */ /** - * This function loads a WAVE from the data source, automatically freeing - * that source if \c freesrc is non-zero. For example, to load a WAVE file, - * you could do: + * \brief Load the audio data of a WAVE file into memory + * + * Loading a WAVE file requires \c src, \c spec, \c audio_buf and \c audio_len + * to be valid pointers. The entire data portion of the file is then loaded + * into memory and decoded if necessary. + * + * If \c freesrc is non-zero, the data source gets automatically closed and + * freed before the function returns. + * + * Supported are RIFF WAVE files with the formats PCM (8, 16, 24, and 32 bits), + * IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and A-law and + * µ-law (8 bits). Other formats are currently unsupported and cause an error. + * + * If this function succeeds, the pointer returned by it is equal to \c spec + * and the pointer to the audio data allocated by the function is written to + * \c audio_buf and its length in bytes to \c audio_len. The \ref SDL_AudioSpec + * members \c freq, \c channels, and \c format are set to the values of the + * audio data in the buffer. The \c samples member is set to a sane default and + * all others are set to zero. + * + * It's necessary to use SDL_FreeWAV() to free the audio data returned in + * \c audio_buf when it is no longer used. + * + * Because of the underspecification of the Waveform format, there are many + * problematic files in the wild that cause issues with strict decoders. To + * provide compatibility with these files, this decoder is lenient in regards + * to the truncation of the file, the fact chunk, and the size of the RIFF + * chunk. The hints SDL_HINT_WAVE_RIFF_CHUNK_SIZE, SDL_HINT_WAVE_TRUNCATION, + * and SDL_HINT_WAVE_FACT_CHUNK can be used to tune the behavior of the + * loading process. + * + * Any file that is invalid (due to truncation, corruption, or wrong values in + * the headers), too big, or unsupported causes an error. Additionally, any + * critical I/O error from the data source will terminate the loading process + * with an error. The function returns NULL on error and in all cases (with the + * exception of \c src being NULL), an appropriate error message will be set. + * + * It is required that the data source supports seeking. + * + * Example: * \code * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...); * \endcode * - * If this function succeeds, it returns the given SDL_AudioSpec, - * filled with the audio data format of the wave data, and sets - * \c *audio_buf to a malloc()'d buffer containing the audio data, - * and sets \c *audio_len to the length of that audio buffer, in bytes. - * You need to free the audio buffer with SDL_FreeWAV() when you are - * done with it. - * - * This function returns NULL and sets the SDL error message if the - * wave file cannot be opened, uses an unknown data format, or is - * corrupt. Currently raw and MS-ADPCM WAVE files are supported. + * \param src The data source with the WAVE data + * \param freesrc A integer value that makes the function close the data source if non-zero + * \param spec A pointer filled with the audio format of the audio data + * \param audio_buf A pointer filled with the audio data allocated by the function + * \param audio_len A pointer filled with the length of the audio data buffer in bytes + * \return NULL on error, or non-NULL on success. */ extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, diff --git a/libs/SDL2/include/SDL_bits.h b/libs/SDL2/include/SDL_bits.h index eb8322f0d..b116cc8d0 100644 --- a/libs/SDL2/include/SDL_bits.h +++ b/libs/SDL2/include/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -101,6 +101,15 @@ SDL_MostSignificantBitIndex32(Uint32 x) #endif } +SDL_FORCE_INLINE SDL_bool +SDL_HasExactlyOneBitSet32(Uint32 x) +{ + if (x && !(x & (x - 1))) { + return SDL_TRUE; + } + return SDL_FALSE; +} + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/libs/SDL2/include/SDL_blendmode.h b/libs/SDL2/include/SDL_blendmode.h index 36a5ea76f..6f0a22b99 100644 --- a/libs/SDL2/include/SDL_blendmode.h +++ b/libs/SDL2/include/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -90,12 +90,12 @@ typedef enum /** * \brief Create a custom blend mode, which may or may not be supported by a given renderer * - * \param srcColorFactor - * \param dstColorFactor - * \param colorOperation - * \param srcAlphaFactor - * \param dstAlphaFactor - * \param alphaOperation + * \param srcColorFactor source color factor + * \param dstColorFactor destination color factor + * \param colorOperation color operation + * \param srcAlphaFactor source alpha factor + * \param dstAlphaFactor destination alpha factor + * \param alphaOperation alpha operation * * The result of the blend mode operation will be: * dstRGB = dstRGB * dstColorFactor colorOperation srcRGB * srcColorFactor diff --git a/libs/SDL2/include/SDL_clipboard.h b/libs/SDL2/include/SDL_clipboard.h index f28751ebb..c4f8766ce 100644 --- a/libs/SDL2/include/SDL_clipboard.h +++ b/libs/SDL2/include/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_config.h b/libs/SDL2/include/SDL_config.h index c58be8e72..395ad7c26 100644 --- a/libs/SDL2/include/SDL_config.h +++ b/libs/SDL2/include/SDL_config.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_cpuinfo.h b/libs/SDL2/include/SDL_cpuinfo.h index ee3a47e84..296df01aa 100644 --- a/libs/SDL2/include/SDL_cpuinfo.h +++ b/libs/SDL2/include/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -41,24 +41,43 @@ #else #include #ifndef _WIN64 +#ifndef __MMX__ #define __MMX__ +#endif +#ifndef __3dNOW__ #define __3dNOW__ #endif +#endif +#ifndef __SSE__ #define __SSE__ +#endif +#ifndef __SSE2__ #define __SSE2__ +#endif #endif /* __clang__ */ #elif defined(__MINGW64_VERSION_MAJOR) #include #else -#ifdef __ALTIVEC__ -#if defined(HAVE_ALTIVEC_H) && !defined(__APPLE_ALTIVEC__) && !defined(SDL_DISABLE_ALTIVEC_H) +/* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC_H to have it included. */ +#if defined(HAVE_ALTIVEC_H) && defined(__ALTIVEC__) && !defined(__APPLE_ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC_H) #include -#undef pixel -#undef bool #endif -#endif -#if defined(__ARM_NEON__) && !defined(SDL_DISABLE_ARM_NEON_H) -#include +#if !defined(SDL_DISABLE_ARM_NEON_H) +# if defined(__ARM_NEON) +# include +# elif defined(__WINDOWS__) || defined(__WINRT__) +/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */ +# if defined(_M_ARM) +# include +# include +# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */ +# endif +# if defined (_M_ARM64) +# include +# include +# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */ +# endif +# endif #endif #if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H) #include @@ -177,6 +196,69 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void); */ extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void); +/** + * \brief Report the alignment this system needs for SIMD allocations. + * + * This will return the minimum number of bytes to which a pointer must be + * aligned to be compatible with SIMD instructions on the current machine. + * For example, if the machine supports SSE only, it will return 16, but if + * it supports AVX-512F, it'll return 64 (etc). This only reports values for + * instruction sets SDL knows about, so if your SDL build doesn't have + * SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and + * not 64 for the AVX-512 instructions that exist but SDL doesn't know about. + * Plan accordingly. + */ +extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void); + +/** + * \brief Allocate memory in a SIMD-friendly way. + * + * This will allocate a block of memory that is suitable for use with SIMD + * instructions. Specifically, it will be properly aligned and padded for + * the system's supported vector instructions. + * + * The memory returned will be padded such that it is safe to read or write + * an incomplete vector at the end of the memory block. This can be useful + * so you don't have to drop back to a scalar fallback at the end of your + * SIMD processing loop to deal with the final elements without overflowing + * the allocated buffer. + * + * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free() + * or delete[], etc. + * + * Note that SDL will only deal with SIMD instruction sets it is aware of; + * for example, SDL 2.0.8 knows that SSE wants 16-byte vectors + * (SDL_HasSSE()), and AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't + * know that AVX-512 wants 64. To be clear: if you can't decide to use an + * instruction set with an SDL_Has*() function, don't use that instruction + * set with memory allocated through here. + * + * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't + * out of memory. + * + * \param len The length, in bytes, of the block to allocated. The actual + * allocated block might be larger due to padding, etc. + * \return Pointer to newly-allocated block, NULL if out of memory. + * + * \sa SDL_SIMDAlignment + * \sa SDL_SIMDFree + */ +extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len); + +/** + * \brief Deallocate memory obtained from SDL_SIMDAlloc + * + * It is not valid to use this function on a pointer from anything but + * SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc, + * SDL_malloc, memalign, new[], etc. + * + * However, SDL_SIMDFree(NULL) is a legal no-op. + * + * \sa SDL_SIMDAlloc + */ +extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr); + +/* vi: set ts=4 sw=4 expandtab: */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/libs/SDL2/include/SDL_egl.h b/libs/SDL2/include/SDL_egl.h index d65ed437c..f50fa5c9b 100644 --- a/libs/SDL2/include/SDL_egl.h +++ b/libs/SDL2/include/SDL_egl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_endian.h b/libs/SDL2/include/SDL_endian.h index ed0bf5ba8..54d5d486d 100644 --- a/libs/SDL2/include/SDL_endian.h +++ b/libs/SDL2/include/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_error.h b/libs/SDL2/include/SDL_error.h index c0e46298e..24416e693 100644 --- a/libs/SDL2/include/SDL_error.h +++ b/libs/SDL2/include/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_events.h b/libs/SDL2/include/SDL_events.h index af22eb646..282b9fb76 100644 --- a/libs/SDL2/include/SDL_events.h +++ b/libs/SDL2/include/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -594,6 +594,9 @@ typedef union SDL_Event Uint8 padding[56]; } SDL_Event; +/* Make sure we haven't broken binary compatibility */ +SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == 56); + /* Function prototypes */ diff --git a/libs/SDL2/include/SDL_filesystem.h b/libs/SDL2/include/SDL_filesystem.h index fa6a1fa6e..6d97e5896 100644 --- a/libs/SDL2/include/SDL_filesystem.h +++ b/libs/SDL2/include/SDL_filesystem.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_gamecontroller.h b/libs/SDL2/include/SDL_gamecontroller.h index 6ae9c9542..ebde38715 100644 --- a/libs/SDL2/include/SDL_gamecontroller.h +++ b/libs/SDL2/include/SDL_gamecontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_gesture.h b/libs/SDL2/include/SDL_gesture.h index b223d80d4..9d25e9c1d 100644 --- a/libs/SDL2/include/SDL_gesture.h +++ b/libs/SDL2/include/SDL_gesture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_haptic.h b/libs/SDL2/include/SDL_haptic.h index 2ea1bfc16..075627685 100644 --- a/libs/SDL2/include/SDL_haptic.h +++ b/libs/SDL2/include/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_hints.h b/libs/SDL2/include/SDL_hints.h index 4ee72e97d..8fa0dd660 100644 --- a/libs/SDL2/include/SDL_hints.h +++ b/libs/SDL2/include/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -315,6 +315,16 @@ extern "C" { */ #define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" +/** + * \brief A variable controlling whether mouse events should generate synthetic touch events + * + * This variable can be set to the following values: + * "0" - Mouse events will not generate touch events (default for desktop platforms) + * "1" - Mouse events will generate touch events (default for mobile platforms, such as Android and iOS) + */ + +#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" + /** * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to true. * @@ -436,6 +446,16 @@ extern "C" { */ #define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG" +/** + * \brief A variable that lets you provide a file with extra gamecontroller db entries. + * + * The file should contain lines of gamecontroller config data, see SDL_gamecontroller.h + * + * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER) + * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping() + */ +#define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE" + /** * \brief A variable containing a list of devices to skip when scanning for game controllers. * @@ -836,19 +856,7 @@ extern "C" { */ #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" - /** - * \brief A variable to control whether mouse and touch events are to be treated together or separately - * - * The variable can be set to the following values: - * "0" - Mouse events will be handled as touch events, and touch will raise fake mouse - * events. This is the behaviour of SDL <= 2.0.3. (default) - * "1" - Mouse events will be handled separately from pure touch events. - * - * The value of this hint is used at runtime, so it can be changed at any time. - */ -#define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH" - - /** +/** * \brief A variable to control whether we trap the Android back button to handle it manually. * This is necessary for the right mouse button to work on some Android devices, or * to be able to trap the back button for use in your code reliably. If set to true, @@ -865,6 +873,17 @@ extern "C" { */ #define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON" +/** + * \brief A variable to control whether the event loop will block itself when the app is paused. + * + * The variable can be set to the following values: + * "0" - Non blocking. + * "1" - Blocking. (default) + * + * The value should be set before SDL is initialized. + */ +#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE" + /** * \brief A variable to control whether the return key on the soft keyboard * should hide the soft keyboard on Android and iOS. @@ -1043,6 +1062,118 @@ extern "C" { */ #define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY" +/** + * \brief A variable controlling whether the 2D render API is compatible or efficient. + * + * This variable can be set to the following values: + * + * "0" - Don't use batching to make rendering more efficient. + * "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls. + * + * Up to SDL 2.0.9, the render API would draw immediately when requested. Now + * it batches up draw requests and sends them all to the GPU only when forced + * to (during SDL_RenderPresent, when changing render targets, by updating a + * texture that the batch needs, etc). This is significantly more efficient, + * but it can cause problems for apps that expect to render on top of the + * render API's output. As such, SDL will disable batching if a specific + * render backend is requested (since this might indicate that the app is + * planning to use the underlying graphics API directly). This hint can + * be used to explicitly request batching in this instance. It is a contract + * that you will either never use the underlying graphics API directly, or + * if you do, you will call SDL_RenderFlush() before you do so any current + * batch goes to the GPU before your work begins. Not following this contract + * will result in undefined behavior. + */ +#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" + + +/** + * \brief A variable controlling whether SDL logs all events pushed onto its internal queue. + * + * This variable can be set to the following values: + * + * "0" - Don't log any events (default) + * "1" - Log all events except mouse and finger motion, which are pretty spammy. + * "2" - Log all events. + * + * This is generally meant to be used to debug SDL itself, but can be useful + * for application developers that need better visibility into what is going + * on in the event queue. Logged events are sent through SDL_Log(), which + * means by default they appear on stdout on most platforms or maybe + * OutputDebugString() on Windows, and can be funneled by the app with + * SDL_LogSetOutputFunction(), etc. + * + * This hint can be toggled on and off at runtime, if you only need to log + * events for a small subset of program execution. + */ +#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" + + + +/** + * \brief Controls how the size of the RIFF chunk affects the loading of a WAVE file. + * + * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE + * file) is not always reliable. In case the size is wrong, it's possible to + * just ignore it and step through the chunks until a fixed limit is reached. + * + * Note that files that have trailing data unrelated to the WAVE file or + * corrupt files may slow down the loading process without a reliable boundary. + * By default, SDL stops after 10000 chunks to prevent wasting time. Use the + * environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value. + * + * This variable can be set to the following values: + * + * "force" - Always use the RIFF chunk size as a boundary for the chunk search + * "ignorezero" - Like "force", but a zero size searches up to 4 GiB (default) + * "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB + * "maximum" - Search for chunks until the end of file (not recommended) + */ +#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE" + +/** + * \brief Controls how a truncated WAVE file is handled. + * + * A WAVE file is considered truncated if any of the chunks are incomplete or + * the data chunk size is not a multiple of the block size. By default, SDL + * decodes until the first incomplete block, as most applications seem to do. + * + * This variable can be set to the following values: + * + * "verystrict" - Raise an error if the file is truncated + * "strict" - Like "verystrict", but the size of the RIFF chunk is ignored + * "dropframe" - Decode until the first incomplete sample frame + * "dropblock" - Decode until the first incomplete block (default) + */ +#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" + +/** + * \brief Controls how the fact chunk affects the loading of a WAVE file. + * + * The fact chunk stores information about the number of samples of a WAVE + * file. The Standards Update from Microsoft notes that this value can be used + * to 'determine the length of the data in seconds'. This is especially useful + * for compressed formats (for which this is a mandatory chunk) if they produce + * multiple sample frames per block and truncating the block is not allowed. + * The fact chunk can exactly specify how many sample frames there should be + * in this case. + * + * Unfortunately, most application seem to ignore the fact chunk and so SDL + * ignores it by default as well. + * + * This variable can be set to the following values: + * + * "truncate" - Use the number of samples to truncate the wave data if + * the fact chunk is present and valid + * "strict" - Like "truncate", but raise an error if the fact chunk + * is invalid, not present for non-PCM formats, or if the + * data chunk doesn't have that many samples + * "ignorezero" - Like "truncate", but ignore fact chunk if the number of + * samples is zero + * "ignore" - Ignore fact chunk entirely (default) + */ +#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" + /** * \brief An enumeration of hint priorities */ diff --git a/libs/SDL2/include/SDL_joystick.h b/libs/SDL2/include/SDL_joystick.h index 6e05a9c20..3a4c5d177 100644 --- a/libs/SDL2/include/SDL_joystick.h +++ b/libs/SDL2/include/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_keyboard.h b/libs/SDL2/include/SDL_keyboard.h index 874823171..4b2a055d8 100644 --- a/libs/SDL2/include/SDL_keyboard.h +++ b/libs/SDL2/include/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_keycode.h b/libs/SDL2/include/SDL_keycode.h index d7d5b1dbc..3bceb418a 100644 --- a/libs/SDL2/include/SDL_keycode.h +++ b/libs/SDL2/include/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_loadso.h b/libs/SDL2/include/SDL_loadso.h index da56fb452..793ba5358 100644 --- a/libs/SDL2/include/SDL_loadso.h +++ b/libs/SDL2/include/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_log.h b/libs/SDL2/include/SDL_log.h index e12b65886..40f768d57 100644 --- a/libs/SDL2/include/SDL_log.h +++ b/libs/SDL2/include/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_main.h b/libs/SDL2/include/SDL_main.h index 98558217f..623f2d005 100644 --- a/libs/SDL2/include/SDL_main.h +++ b/libs/SDL2/include/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -55,6 +55,10 @@ /* On iOS SDL provides a main function that creates an application delegate and starts the iOS application run loop. + If you link with SDL dynamically on iOS, the main function can't be in a + shared library, so you need to link with libSDLmain.a, which includes a + stub main function that calls into the shared library to start execution. + See src/video/uikit/SDL_uikitappdelegate.m for more details. */ #define SDL_MAIN_NEEDED @@ -82,12 +86,6 @@ #endif #endif /* SDL_MAIN_HANDLED */ -#ifdef __cplusplus -#define C_LINKAGE "C" -#else -#define C_LINKAGE -#endif /* __cplusplus */ - #ifndef SDLMAIN_DECLSPEC #define SDLMAIN_DECLSPEC #endif @@ -111,17 +109,18 @@ #define main SDL_main #endif -/** - * The prototype for the application's main() function - */ -extern C_LINKAGE SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]); - - #include "begin_code.h" #ifdef __cplusplus extern "C" { #endif +/** + * The prototype for the application's main() function + */ +typedef int (*SDL_main_func)(int argc, char *argv[]); +extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]); + + /** * This is called by the real SDL main function to let the rest of the * library know that initialization was done properly. @@ -136,8 +135,7 @@ extern DECLSPEC void SDLCALL SDL_SetMainReady(void); /** * This can be called to set the application class at startup */ -extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, - void *hInst); +extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, void *hInst); extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); #endif /* __WIN32__ */ @@ -153,10 +151,24 @@ extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); * \return 0 on success, -1 on failure. On failure, use SDL_GetError to retrieve more * information on the failure. */ -extern DECLSPEC int SDLCALL SDL_WinRTRunApp(int (*mainFunction)(int, char **), void * reserved); +extern DECLSPEC int SDLCALL SDL_WinRTRunApp(SDL_main_func mainFunction, void * reserved); #endif /* __WINRT__ */ +#if defined(__IPHONEOS__) + +/** + * \brief Initializes and launches an SDL application. + * + * \param argc The argc parameter from the application's main() function + * \param argv The argv parameter from the application's main() function + * \param mainFunction The SDL app's C-style main(). + * \return the return value from mainFunction + */ +extern DECLSPEC int SDLCALL SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction); + +#endif /* __IPHONEOS__ */ + #ifdef __cplusplus } diff --git a/libs/SDL2/include/SDL_messagebox.h b/libs/SDL2/include/SDL_messagebox.h index b7be59d88..e34b55477 100644 --- a/libs/SDL2/include/SDL_messagebox.h +++ b/libs/SDL2/include/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_mouse.h b/libs/SDL2/include/SDL_mouse.h index d3c9f6156..277559d23 100644 --- a/libs/SDL2/include/SDL_mouse.h +++ b/libs/SDL2/include/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_mutex.h b/libs/SDL2/include/SDL_mutex.h index ba4247ced..970e78713 100644 --- a/libs/SDL2/include/SDL_mutex.h +++ b/libs/SDL2/include/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_name.h b/libs/SDL2/include/SDL_name.h index ecd863f4c..690a8199b 100644 --- a/libs/SDL2/include/SDL_name.h +++ b/libs/SDL2/include/SDL_name.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_opengl.h b/libs/SDL2/include/SDL_opengl.h index 253d9c93a..6685be73e 100644 --- a/libs/SDL2/include/SDL_opengl.h +++ b/libs/SDL2/include/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_opengles.h b/libs/SDL2/include/SDL_opengles.h index 18dd984b3..1e0660c3d 100644 --- a/libs/SDL2/include/SDL_opengles.h +++ b/libs/SDL2/include/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_opengles2.h b/libs/SDL2/include/SDL_opengles2.h index 6ccecf216..df29d3840 100644 --- a/libs/SDL2/include/SDL_opengles2.h +++ b/libs/SDL2/include/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_pixels.h b/libs/SDL2/include/SDL_pixels.h index 0b4364b18..dcb7a980d 100644 --- a/libs/SDL2/include/SDL_pixels.h +++ b/libs/SDL2/include/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -168,7 +168,7 @@ enum ((format) && (SDL_PIXELFLAG(format) != 1)) /* Note: If you modify this list, update SDL_GetPixelFormatName() */ -enum +typedef enum { SDL_PIXELFORMAT_UNKNOWN, SDL_PIXELFORMAT_INDEX1LSB = @@ -290,7 +290,7 @@ enum SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'), SDL_PIXELFORMAT_EXTERNAL_OES = /**< Android video texture format */ SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') -}; +} SDL_PixelFormatEnum; typedef struct SDL_Color { diff --git a/libs/SDL2/include/SDL_platform.h b/libs/SDL2/include/SDL_platform.h index 7dea4ce94..c2cbc6b4e 100644 --- a/libs/SDL2/include/SDL_platform.h +++ b/libs/SDL2/include/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_power.h b/libs/SDL2/include/SDL_power.h index a4fe8a935..4831cb77e 100644 --- a/libs/SDL2/include/SDL_power.h +++ b/libs/SDL2/include/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_quit.h b/libs/SDL2/include/SDL_quit.h index fea56a8d8..c979983cb 100644 --- a/libs/SDL2/include/SDL_quit.h +++ b/libs/SDL2/include/SDL_quit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_rect.h b/libs/SDL2/include/SDL_rect.h index 543bb6186..71a411517 100644 --- a/libs/SDL2/include/SDL_rect.h +++ b/libs/SDL2/include/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -40,7 +40,7 @@ extern "C" { #endif /** - * \brief The structure that defines a point + * \brief The structure that defines a point (integer) * * \sa SDL_EnclosePoints * \sa SDL_PointInRect @@ -52,7 +52,20 @@ typedef struct SDL_Point } SDL_Point; /** - * \brief A rectangle, with the origin at the upper left. + * \brief The structure that defines a point (floating point) + * + * \sa SDL_EnclosePoints + * \sa SDL_PointInRect + */ +typedef struct SDL_FPoint +{ + float x; + float y; +} SDL_FPoint; + + +/** + * \brief A rectangle, with the origin at the upper left (integer). * * \sa SDL_RectEmpty * \sa SDL_RectEquals @@ -67,6 +80,19 @@ typedef struct SDL_Rect int w, h; } SDL_Rect; + +/** + * \brief A rectangle, with the origin at the upper left (floating point). + */ +typedef struct SDL_FRect +{ + float x; + float y; + float w; + float h; +} SDL_FRect; + + /** * \brief Returns true if point resides inside a rectangle. */ diff --git a/libs/SDL2/include/SDL_render.h b/libs/SDL2/include/SDL_render.h index d33619297..096b4a577 100644 --- a/libs/SDL2/include/SDL_render.h +++ b/libs/SDL2/include/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -835,6 +835,148 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer, const SDL_Point *center, const SDL_RendererFlip flip); + +/** + * \brief Draw a point on the current rendering target. + * + * \param renderer The renderer which should draw a point. + * \param x The x coordinate of the point. + * \param y The y coordinate of the point. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer, + float x, float y); + +/** + * \brief Draw multiple points on the current rendering target. + * + * \param renderer The renderer which should draw multiple points. + * \param points The points to draw + * \param count The number of points to draw + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer, + const SDL_FPoint * points, + int count); + +/** + * \brief Draw a line on the current rendering target. + * + * \param renderer The renderer which should draw a line. + * \param x1 The x coordinate of the start point. + * \param y1 The y coordinate of the start point. + * \param x2 The x coordinate of the end point. + * \param y2 The y coordinate of the end point. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer, + float x1, float y1, float x2, float y2); + +/** + * \brief Draw a series of connected lines on the current rendering target. + * + * \param renderer The renderer which should draw multiple lines. + * \param points The points along the lines + * \param count The number of points, drawing count-1 lines + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer, + const SDL_FPoint * points, + int count); + +/** + * \brief Draw a rectangle on the current rendering target. + * + * \param renderer The renderer which should draw a rectangle. + * \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer, + const SDL_FRect * rect); + +/** + * \brief Draw some number of rectangles on the current rendering target. + * + * \param renderer The renderer which should draw multiple rectangles. + * \param rects A pointer to an array of destination rectangles. + * \param count The number of rectangles. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer, + const SDL_FRect * rects, + int count); + +/** + * \brief Fill a rectangle on the current rendering target with the drawing color. + * + * \param renderer The renderer which should fill a rectangle. + * \param rect A pointer to the destination rectangle, or NULL for the entire + * rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer, + const SDL_FRect * rect); + +/** + * \brief Fill some number of rectangles on the current rendering target with the drawing color. + * + * \param renderer The renderer which should fill multiple rectangles. + * \param rects A pointer to an array of destination rectangles. + * \param count The number of rectangles. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer, + const SDL_FRect * rects, + int count); + +/** + * \brief Copy a portion of the texture to the current rendering target. + * + * \param renderer The renderer which should copy parts of a texture. + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire + * texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the + * entire rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_FRect * dstrect); + +/** + * \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center + * + * \param renderer The renderer which should copy parts of a texture. + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire + * texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the + * entire rendering target. + * \param angle An angle in degrees that indicates the rotation that will be applied to dstrect, rotating it in a clockwise direction + * \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2). + * \param flip An SDL_RendererFlip value stating which flipping actions should be performed on the texture + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_FRect * dstrect, + const double angle, + const SDL_FPoint *center, + const SDL_RendererFlip flip); + /** * \brief Read pixels from the current rendering target. * @@ -876,6 +1018,31 @@ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture * texture); */ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer * renderer); +/** + * \brief Force the rendering context to flush any pending commands to the + * underlying rendering API. + * + * You do not need to (and in fact, shouldn't) call this function unless + * you are planning to call into OpenGL/Direct3D/Metal/whatever directly + * in addition to using an SDL_Renderer. + * + * This is for a very-specific case: if you are using SDL's render API, + * you asked for a specific renderer backend (OpenGL, Direct3D, etc), + * you set SDL_HINT_RENDER_BATCHING to "1", and you plan to make + * OpenGL/D3D/whatever calls in addition to SDL render API calls. If all of + * this applies, you should call SDL_RenderFlush() between calls to SDL's + * render API and the low-level API you're using in cooperation. + * + * In all other cases, you can ignore this function. This is only here to + * get maximum performance out of a specific situation. In all other cases, + * SDL will do the right thing, perhaps at a performance loss. + * + * This function is first available in SDL 2.0.10, and is not needed in + * 2.0.9 and earlier, as earlier versions did not queue rendering commands + * at all, instead flushing them to the OS immediately. + */ +extern DECLSPEC int SDLCALL SDL_RenderFlush(SDL_Renderer * renderer); + /** * \brief Bind the texture to the current OpenGL/ES/ES2 context for use with diff --git a/libs/SDL2/include/SDL_revision.h b/libs/SDL2/include/SDL_revision.h index 92fbe67b1..3b3fc85ea 100644 --- a/libs/SDL2/include/SDL_revision.h +++ b/libs/SDL2/include/SDL_revision.h @@ -1,2 +1,2 @@ -#define SDL_REVISION "hg-12373:8feb5da6f2fb" -#define SDL_REVISION_NUMBER 12373 +#define SDL_REVISION "hg-12952:bc90ce38f1e2" +#define SDL_REVISION_NUMBER 12952 diff --git a/libs/SDL2/include/SDL_rwops.h b/libs/SDL2/include/SDL_rwops.h index 0960699d4..f66119fb0 100644 --- a/libs/SDL2/include/SDL_rwops.h +++ b/libs/SDL2/include/SDL_rwops.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -176,19 +176,48 @@ extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area); #define RW_SEEK_END 2 /**< Seek relative to the end of data */ /** - * \name Read/write macros - * - * Macros to easily read and write from an SDL_RWops structure. + * Return the size of the file in this rwops, or -1 if unknown */ -/* @{ */ -#define SDL_RWsize(ctx) (ctx)->size(ctx) -#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence) -#define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, RW_SEEK_CUR) -#define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n) -#define SDL_RWwrite(ctx, ptr, size, n) (ctx)->write(ctx, ptr, size, n) -#define SDL_RWclose(ctx) (ctx)->close(ctx) -/* @} *//* Read/write macros */ +extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context); +/** + * Seek to \c offset relative to \c whence, one of stdio's whence values: + * RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END + * + * \return the final offset in the data stream, or -1 on error. + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context, + Sint64 offset, int whence); + +/** + * Return the current offset in the data stream, or -1 on error. + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context); + +/** + * Read up to \c maxnum objects each of size \c size from the data + * stream to the area pointed at by \c ptr. + * + * \return the number of objects read, or 0 at error or end of file. + */ +extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, + void *ptr, size_t size, size_t maxnum); + +/** + * Write exactly \c num objects each of size \c size from the area + * pointed at by \c ptr to data stream. + * + * \return the number of objects written, or 0 at error or end of file. + */ +extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, + const void *ptr, size_t size, size_t num); + +/** + * Close and free an allocated SDL_RWops structure. + * + * \return 0 if successful or -1 on write error when flushing data. + */ +extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context); /** * Load all the data from an SDL data stream. @@ -209,9 +238,17 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, /** * Load an entire file. * - * Convenience macro. + * The data is allocated with a zero byte at the end (null terminated) + * + * If \c datasize is not NULL, it is filled with the size of the data read. + * + * If \c freesrc is non-zero, the stream will be closed after being read. + * + * The data should be freed with SDL_free(). + * + * \return the data, or NULL if there was an error. */ -#define SDL_LoadFile(file, datasize) SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, 1) +extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize); /** * \name Read endian functions diff --git a/libs/SDL2/include/SDL_scancode.h b/libs/SDL2/include/SDL_scancode.h index 63871aa3b..a50305f55 100644 --- a/libs/SDL2/include/SDL_scancode.h +++ b/libs/SDL2/include/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -38,7 +38,7 @@ * SDL_Event structure. * * The values in this enumeration are based on the USB usage page standard: - * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf + * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf */ typedef enum { diff --git a/libs/SDL2/include/SDL_sensor.h b/libs/SDL2/include/SDL_sensor.h index ac163a8cd..966adbf21 100644 --- a/libs/SDL2/include/SDL_sensor.h +++ b/libs/SDL2/include/SDL_sensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -26,8 +26,8 @@ * */ -#ifndef _SDL_sensor_h -#define _SDL_sensor_h +#ifndef SDL_sensor_h_ +#define SDL_sensor_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -246,6 +246,6 @@ extern DECLSPEC void SDLCALL SDL_SensorUpdate(void); #endif #include "close_code.h" -#endif /* _SDL_sensor_h */ +#endif /* SDL_sensor_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDL2/include/SDL_shape.h b/libs/SDL2/include/SDL_shape.h index 40a6baaae..2ab43fcdc 100644 --- a/libs/SDL2/include/SDL_shape.h +++ b/libs/SDL2/include/SDL_shape.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_stdinc.h b/libs/SDL2/include/SDL_stdinc.h index e373bc380..28bb7b961 100644 --- a/libs/SDL2/include/SDL_stdinc.h +++ b/libs/SDL2/include/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_surface.h b/libs/SDL2/include/SDL_surface.h index 730d49fc8..51a128300 100644 --- a/libs/SDL2/include/SDL_surface.h +++ b/libs/SDL2/include/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -53,6 +53,7 @@ extern "C" { #define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */ #define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */ #define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */ +#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */ /* @} *//* Surface flags */ /** diff --git a/libs/SDL2/include/SDL_system.h b/libs/SDL2/include/SDL_system.h index 4dc372d6b..3b0840769 100644 --- a/libs/SDL2/include/SDL_system.h +++ b/libs/SDL2/include/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_syswm.h b/libs/SDL2/include/SDL_syswm.h index f1c4021cc..7aa8c6869 100644 --- a/libs/SDL2/include/SDL_syswm.h +++ b/libs/SDL2/include/SDL_syswm.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -34,16 +34,16 @@ #include "SDL_version.h" /** - * \file SDL_syswm.h + * \brief SDL_syswm.h * * Your application has access to a special type of event ::SDL_SYSWMEVENT, * which contains window-manager specific information and arrives whenever * an unhandled window event occurs. This event is ignored by default, but * you can enable it with SDL_EventState(). */ -#ifdef SDL_PROTOTYPES_ONLY struct SDL_SysWMinfo; -#else + +#if !defined(SDL_PROTOTYPES_ONLY) #if defined(SDL_VIDEO_DRIVER_WINDOWS) #ifndef WIN32_LEAN_AND_MEAN @@ -103,6 +103,8 @@ typedef void *EGLSurface; #if defined(SDL_VIDEO_DRIVER_VIVANTE) #include "SDL_egl.h" #endif +#endif /* SDL_PROTOTYPES_ONLY */ + #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ @@ -110,6 +112,7 @@ typedef void *EGLSurface; extern "C" { #endif +#if !defined(SDL_PROTOTYPES_ONLY) /** * These are the various supported windowing subsystems */ @@ -122,7 +125,7 @@ typedef enum SDL_SYSWM_COCOA, SDL_SYSWM_UIKIT, SDL_SYSWM_WAYLAND, - SDL_SYSWM_MIR, + SDL_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ SDL_SYSWM_WINRT, SDL_SYSWM_ANDROID, SDL_SYSWM_VIVANTE, @@ -257,11 +260,11 @@ struct SDL_SysWMinfo struct wl_shell_surface *shell_surface; /**< Wayland shell_surface (window manager handle) */ } wl; #endif -#if defined(SDL_VIDEO_DRIVER_MIR) +#if defined(SDL_VIDEO_DRIVER_MIR) /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ struct { - struct MirConnection *connection; /**< Mir display server connection */ - struct MirSurface *surface; /**< Mir surface */ + void *connection; /**< Mir display server connection */ + void *surface; /**< Mir surface */ } mir; #endif diff --git a/libs/SDL2/include/SDL_test.h b/libs/SDL2/include/SDL_test.h index 6cc373bf8..17a33dc2c 100644 --- a/libs/SDL2/include/SDL_test.h +++ b/libs/SDL2/include/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_assert.h b/libs/SDL2/include/SDL_test_assert.h index 1788d7a20..b3ebb62fb 100644 --- a/libs/SDL2/include/SDL_test_assert.h +++ b/libs/SDL2/include/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_common.h b/libs/SDL2/include/SDL_test_common.h index be2e6b2aa..c34d0d103 100644 --- a/libs/SDL2/include/SDL_test_common.h +++ b/libs/SDL2/include/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -140,14 +140,20 @@ SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags); */ int SDLTest_CommonArg(SDLTest_CommonState * state, int index); + /** - * \brief Returns common usage information + * \brief Logs command line usage info. * - * \param state The common state describing the test window to create. + * This logs the appropriate command line options for the subsystems in use + * plus other common options, and then any application-specific options. + * This uses the SDL_Log() function and splits up output to be friendly to + * 80-character-wide terminals. * - * \returns String with usage information + * \param state The common state describing the test window for the app. + * \param argv0 argv[0], as passed to main/SDL_main. + * \param options an array of strings for application specific options. The last element of the array should be NULL. */ -const char *SDLTest_CommonUsage(SDLTest_CommonState * state); +void SDLTest_CommonLogUsage(SDLTest_CommonState * state, const char *argv0, const char **options); /** * \brief Open test window. @@ -158,6 +164,17 @@ const char *SDLTest_CommonUsage(SDLTest_CommonState * state); */ SDL_bool SDLTest_CommonInit(SDLTest_CommonState * state); +/** + * \brief Easy argument handling when test app doesn't need any custom args. + * + * \param state The common state describing the test window to create. + * \param argc argc, as supplied to SDL_main + * \param argv argv, as supplied to SDL_main + * + * \returns False if app should quit, true otherwise. + */ +SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState * state, const int argc, char **argv); + /** * \brief Common event handler for test windows. * diff --git a/libs/SDL2/include/SDL_test_compare.h b/libs/SDL2/include/SDL_test_compare.h index c22e447d8..1f751c8b9 100644 --- a/libs/SDL2/include/SDL_test_compare.h +++ b/libs/SDL2/include/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_crc32.h b/libs/SDL2/include/SDL_test_crc32.h index 3d235d074..e615d8929 100644 --- a/libs/SDL2/include/SDL_test_crc32.h +++ b/libs/SDL2/include/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_font.h b/libs/SDL2/include/SDL_test_font.h index 59cbdcad6..8fa078440 100644 --- a/libs/SDL2/include/SDL_test_font.h +++ b/libs/SDL2/include/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_fuzzer.h b/libs/SDL2/include/SDL_test_fuzzer.h index 8fcb9ebbf..7259685a9 100644 --- a/libs/SDL2/include/SDL_test_fuzzer.h +++ b/libs/SDL2/include/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_harness.h b/libs/SDL2/include/SDL_test_harness.h index 8641e0a7e..f5ae92ceb 100644 --- a/libs/SDL2/include/SDL_test_harness.h +++ b/libs/SDL2/include/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_images.h b/libs/SDL2/include/SDL_test_images.h index 9c4dd5b82..b8934812f 100644 --- a/libs/SDL2/include/SDL_test_images.h +++ b/libs/SDL2/include/SDL_test_images.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_log.h b/libs/SDL2/include/SDL_test_log.h index ebd44fb50..01d0fedac 100644 --- a/libs/SDL2/include/SDL_test_log.h +++ b/libs/SDL2/include/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_md5.h b/libs/SDL2/include/SDL_test_md5.h index 0e4105768..2bfd7dff9 100644 --- a/libs/SDL2/include/SDL_test_md5.h +++ b/libs/SDL2/include/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_test_memory.h b/libs/SDL2/include/SDL_test_memory.h index 4827ae6f2..5d4d39ea5 100644 --- a/libs/SDL2/include/SDL_test_memory.h +++ b/libs/SDL2/include/SDL_test_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -42,14 +42,14 @@ extern "C" { * * \note This should be called before any other SDL functions for complete tracking coverage */ -int SDLTest_TrackAllocations(); +int SDLTest_TrackAllocations(void); /** * \brief Print a log of any outstanding allocations * * \note This can be called after SDL_Quit() */ -void SDLTest_LogAllocations(); +void SDLTest_LogAllocations(void); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL2/include/SDL_test_random.h b/libs/SDL2/include/SDL_test_random.h index 0eb414ff2..71e9c70b6 100644 --- a/libs/SDL2/include/SDL_test_random.h +++ b/libs/SDL2/include/SDL_test_random.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_thread.h b/libs/SDL2/include/SDL_thread.h index 554dd0b61..f78b1145d 100644 --- a/libs/SDL2/include/SDL_thread.h +++ b/libs/SDL2/include/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_timer.h b/libs/SDL2/include/SDL_timer.h index 5600618ff..2a47b043a 100644 --- a/libs/SDL2/include/SDL_timer.h +++ b/libs/SDL2/include/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_touch.h b/libs/SDL2/include/SDL_touch.h index f4075e79a..99dbcb8c3 100644 --- a/libs/SDL2/include/SDL_touch.h +++ b/libs/SDL2/include/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -41,6 +41,14 @@ extern "C" { typedef Sint64 SDL_TouchID; typedef Sint64 SDL_FingerID; +typedef enum +{ + SDL_TOUCH_DEVICE_INVALID = -1, + SDL_TOUCH_DEVICE_DIRECT, /* touch screen with window-relative coordinates */ + SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, /* trackpad with absolute device coordinates */ + SDL_TOUCH_DEVICE_INDIRECT_RELATIVE /* trackpad with screen cursor-relative coordinates */ +} SDL_TouchDeviceType; + typedef struct SDL_Finger { SDL_FingerID id; @@ -52,6 +60,9 @@ typedef struct SDL_Finger /* Used as the device ID for mouse events simulated with touch input */ #define SDL_TOUCH_MOUSEID ((Uint32)-1) +/* Used as the SDL_TouchID for touch events simulated with mouse input */ +#define SDL_MOUSE_TOUCHID ((Sint64)-1) + /* Function prototypes */ @@ -65,6 +76,11 @@ extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void); */ extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index); +/** + * \brief Get the type of the given touch device. + */ +extern DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID); + /** * \brief Get the number of active fingers for a given touch device. */ diff --git a/libs/SDL2/include/SDL_types.h b/libs/SDL2/include/SDL_types.h index 4ac248c8c..9c3e9896f 100644 --- a/libs/SDL2/include/SDL_types.h +++ b/libs/SDL2/include/SDL_types.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_version.h b/libs/SDL2/include/SDL_version.h index 31443e149..6c7499d32 100644 --- a/libs/SDL2/include/SDL_version.h +++ b/libs/SDL2/include/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -59,7 +59,7 @@ typedef struct SDL_version */ #define SDL_MAJOR_VERSION 2 #define SDL_MINOR_VERSION 0 -#define SDL_PATCHLEVEL 9 +#define SDL_PATCHLEVEL 10 /** * \brief Macro to determine SDL version program was compiled against. diff --git a/libs/SDL2/include/SDL_video.h b/libs/SDL2/include/SDL_video.h index 461f13805..352afd436 100644 --- a/libs/SDL2/include/SDL_video.h +++ b/libs/SDL2/include/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/include/SDL_vulkan.h b/libs/SDL2/include/SDL_vulkan.h index 972cca4d7..d69a436b3 100644 --- a/libs/SDL2/include/SDL_vulkan.h +++ b/libs/SDL2/include/SDL_vulkan.h @@ -98,8 +98,8 @@ typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */ * applications to link with libvulkan (and historically MoltenVK was * provided as a static library). If it is not found then, on macOS, SDL * will attempt to load \c vulkan.framework/vulkan, \c libvulkan.1.dylib, - * \c MoltenVK.framework/MoltenVK and \c libMoltenVK.dylib in that order. - * On iOS SDL will attempt to load \c libMoltenVK.dylib. Applications + * followed by \c libvulkan.dylib, in that order. + * On iOS SDL will attempt to load \c libvulkan.dylib only. Applications * using a dynamic framework or .dylib must ensure it is included in its * application bundle. * @@ -153,7 +153,7 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * is smaller than the number of required extensions, \c SDL_FALSE will be * returned instead of \c SDL_TRUE, to indicate that not all the required * extensions were returned. - * + * * \note If \c window is not NULL, it will be checked against its creation * flags to ensure that the Vulkan flag is present. This parameter * will be removed in a future major release. diff --git a/libs/SDL2/include/begin_code.h b/libs/SDL2/include/begin_code.h index 6c2106246..22c997c41 100644 --- a/libs/SDL2/include/begin_code.h +++ b/libs/SDL2/include/begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -105,6 +105,9 @@ #ifdef _MSC_VER #pragma warning(disable: 4103) #endif +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpragma-pack" +#endif #ifdef __BORLANDC__ #pragma nopackwarning #endif diff --git a/libs/SDL2/include/close_code.h b/libs/SDL2/include/close_code.h index b3b70a4c8..8e4cac3da 100644 --- a/libs/SDL2/include/close_code.h +++ b/libs/SDL2/include/close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -26,6 +26,9 @@ * after you finish any function and structure declarations in your headers */ +#ifndef _begin_code_h +#error close_code.h included without matching begin_code.h +#endif #undef _begin_code_h /* Reset structure packing at previous byte alignment */ diff --git a/libs/SDL2/lib/ARM/SDL2.dll b/libs/SDL2/lib/ARM/SDL2.dll new file mode 100644 index 000000000..3eec027ef Binary files /dev/null and b/libs/SDL2/lib/ARM/SDL2.dll differ diff --git a/libs/SDL2/lib/ARM/SDL2.lib b/libs/SDL2/lib/ARM/SDL2.lib index be9d86949..b027b8956 100644 Binary files a/libs/SDL2/lib/ARM/SDL2.lib and b/libs/SDL2/lib/ARM/SDL2.lib differ diff --git a/libs/SDL2/lib/ARM64/SDL2.dll b/libs/SDL2/lib/ARM64/SDL2.dll index f9eac1c0b..9e2d2c785 100644 Binary files a/libs/SDL2/lib/ARM64/SDL2.dll and b/libs/SDL2/lib/ARM64/SDL2.dll differ diff --git a/libs/SDL2/lib/ARM64/SDL2.lib b/libs/SDL2/lib/ARM64/SDL2.lib index 40904c308..3e8cf8d46 100644 Binary files a/libs/SDL2/lib/ARM64/SDL2.lib and b/libs/SDL2/lib/ARM64/SDL2.lib differ diff --git a/libs/SDL2/lib/x64/SDL2.dll b/libs/SDL2/lib/x64/SDL2.dll index 934f8091c..0edb386ee 100644 Binary files a/libs/SDL2/lib/x64/SDL2.dll and b/libs/SDL2/lib/x64/SDL2.dll differ diff --git a/libs/SDL2/lib/x64/SDL2.lib b/libs/SDL2/lib/x64/SDL2.lib index f4941ae0e..89f7d37fc 100644 Binary files a/libs/SDL2/lib/x64/SDL2.lib and b/libs/SDL2/lib/x64/SDL2.lib differ diff --git a/libs/SDL2/lib/x64/SDL2main.lib b/libs/SDL2/lib/x64/SDL2main.lib index 612994657..4d07170c4 100644 Binary files a/libs/SDL2/lib/x64/SDL2main.lib and b/libs/SDL2/lib/x64/SDL2main.lib differ diff --git a/libs/SDL2/lib/x64/SDL2test.lib b/libs/SDL2/lib/x64/SDL2test.lib index 5b0328280..f3ad021f7 100644 Binary files a/libs/SDL2/lib/x64/SDL2test.lib and b/libs/SDL2/lib/x64/SDL2test.lib differ diff --git a/libs/SDL2/lib/x86/SDL2.dll b/libs/SDL2/lib/x86/SDL2.dll index 701779044..3673be1ab 100644 Binary files a/libs/SDL2/lib/x86/SDL2.dll and b/libs/SDL2/lib/x86/SDL2.dll differ diff --git a/libs/SDL2/lib/x86/SDL2.lib b/libs/SDL2/lib/x86/SDL2.lib index cef79017c..da3b4432b 100644 Binary files a/libs/SDL2/lib/x86/SDL2.lib and b/libs/SDL2/lib/x86/SDL2.lib differ diff --git a/libs/SDL2/lib/x86/SDL2main.lib b/libs/SDL2/lib/x86/SDL2main.lib index 55c40c7a0..27b48de2a 100644 Binary files a/libs/SDL2/lib/x86/SDL2main.lib and b/libs/SDL2/lib/x86/SDL2main.lib differ diff --git a/libs/SDL2/lib/x86/SDL2test.lib b/libs/SDL2/lib/x86/SDL2test.lib index d7a395ff1..1f195015b 100644 Binary files a/libs/SDL2/lib/x86/SDL2test.lib and b/libs/SDL2/lib/x86/SDL2test.lib differ diff --git a/libs/SDL2/test/Makefile.in b/libs/SDL2/test/Makefile.in index 9ddd6ffe7..9a62156ec 100644 --- a/libs/SDL2/test/Makefile.in +++ b/libs/SDL2/test/Makefile.in @@ -28,9 +28,6 @@ TARGETS = \ testfilesystem$(EXE) \ testgamecontroller$(EXE) \ testgesture$(EXE) \ - testgl2$(EXE) \ - testgles$(EXE) \ - testgles2$(EXE) \ testhaptic$(EXE) \ testhittesting$(EXE) \ testhotplug$(EXE) \ @@ -56,7 +53,6 @@ TARGETS = \ testscale$(EXE) \ testsem$(EXE) \ testsensor$(EXE) \ - testshader$(EXE) \ testshape$(EXE) \ testsprite2$(EXE) \ testspriteminimal$(EXE) \ @@ -69,7 +65,13 @@ TARGETS = \ testwm2$(EXE) \ testyuv$(EXE) \ torturethread$(EXE) \ + +@OPENGL_TARGETS@ += testgl2$(EXE) testshader$(EXE) +@OPENGLES1_TARGETS@ += testgles$(EXE) +@OPENGLES2_TARGETS@ += testgles2$(EXE) + + all: Makefile $(TARGETS) copydatafiles Makefile: $(srcdir)/Makefile.in diff --git a/libs/SDL2/test/Makefile.os2 b/libs/SDL2/test/Makefile.os2 new file mode 100644 index 000000000..59866a056 --- /dev/null +++ b/libs/SDL2/test/Makefile.os2 @@ -0,0 +1,91 @@ +BINPATH = . + +TARGETS = testatomic.exe testdisplayinfo.exe testbounds.exe testdraw2.exe & + testdrawchessboard.exe testdropfile.exe testerror.exe testfile.exe & + testfilesystem.exe testgamecontroller.exe testgesture.exe & + testhittesting.exe testhotplug.exe testiconv.exe testime.exe & + testintersections.exe testjoystick.exe testkeys.exe testloadso.exe & + testlock.exe testmessage.exe testoverlay2.exe testplatform.exe & + testpower.exe testsensor.exe testrelative.exe testrendercopyex.exe & + testrendertarget.exe testrumble.exe testscale.exe testsem.exe & + testshader.exe testshape.exe testsprite2.exe testspriteminimal.exe & + teststreaming.exe testthread.exe testtimer.exe testver.exe & + testviewport.exe testwm2.exe torturethread.exe checkkeys.exe & + controllermap.exe testhaptic.exe testqsort.exe testresample.exe & + testaudioinfo.exe testaudiocapture.exe loopwave.exe loopwavequeue.exe & + testyuv.exe testgl2.exe testvulkan.exe testautomation.exe + +# SDL2test.lib sources (../src/test) + +CSRCS = SDL_test_assert.c SDL_test_common.c SDL_test_compare.c & + SDL_test_crc32.c SDL_test_font.c SDL_test_fuzzer.c SDL_test_harness.c & + SDL_test_imageBlit.c SDL_test_imageBlitBlend.c SDL_test_imageFace.c & + SDL_test_imagePrimitives.c SDL_test_imagePrimitivesBlend.c & + SDL_test_log.c SDL_test_md5.c SDL_test_random.c SDL_test_memory.c +TESTLIB = SDL2test.lib + +# testautomation sources + +TASRCS = testautomation.c testautomation_audio.c testautomation_clipboard.c & + testautomation_events.c testautomation_hints.c & + testautomation_keyboard.c testautomation_main.c & + testautomation_mouse.c testautomation_pixels.c & + testautomation_platform.c testautomation_rect.c & + testautomation_render.c testautomation_rwops.c & + testautomation_sdltest.c testautomation_stdlib.c & + testautomation_surface.c testautomation_syswm.c & + testautomation_timer.c testautomation_video.c + +OBJS = $(TARGETS:.exe=.obj) +COBJS = $(CSRCS:.c=.obj) +TAOBJS = $(TASRCS:.c=.obj) + +all: $(TARGETS) + +INCPATH = -I$(%WATCOM)/h/os2 -I$(%WATCOM)/h -I../include + +CFLAGS = $(INCPATH) -bt=os2 -d0 -q -bm -5s -fp5 -fpi87 -sg -oteanbmier -ei + +LIBPATH = .. +LIBS = SDL2.lib $(TESTLIB) + +#CFLAGS+= -DHAVE_SDL_TTF +#LIBS_TTF = SDL2ttf.lib + +.c: ../src/test + +$(TESTLIB): $(COBJS) + wlib -q -b -n $@ $(COBJS) + +.obj.exe: + @%make $(TESTLIB) + wlink SYS os2v2 libpath $(LIBPATH) lib {$(LIBS)} op q op el file {$<} name $@ + +.c.obj: + wcc386 $(CFLAGS) -wcd=107 -fo=$^@ $< + +# specials +testautomation.exe: $(TAOBJS) + @%make $(TESTLIB) + wlink SYS os2v2 libpath $(LIBPATH) lib {$(LIBS)} op q op el file {$<} name $@ + +testoverlay2.exe: testoverlay2.obj testyuv_cvt.obj + @%make $(TESTLIB) + wlink SYS os2v2 libpath $(LIBPATH) lib {$(LIBS)} op q op el file {$<} name $@ + +testyuv.exe: testyuv.obj testyuv_cvt.obj + @%make $(TESTLIB) + wlink SYS os2v2 libpath $(LIBPATH) lib {$(LIBS)} op q op el file {$<} name $@ + +testime.exe: testime.obj + @%make $(TESTLIB) + wlink SYS os2v2 libpath $(LIBPATH) lib {$(LIBS) $(LIBS_TTF)} op q op el file {$<} name $@ + +clean: .SYMBOLIC + @echo * Clean tests in $(BINPATH) + @if exist *.obj rm *.obj + @if exist *.err rm *.err + +distclean: .SYMBOLIC clean + @if exist *.exe rm *.exe + @if exist $(TESTLIB) rm $(TESTLIB) diff --git a/libs/SDL2/test/checkkeys.c b/libs/SDL2/test/checkkeys.c index 4452acaba..421f8f923 100644 --- a/libs/SDL2/test/checkkeys.c +++ b/libs/SDL2/test/checkkeys.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/configure b/libs/SDL2/test/configure index 61c32fba1..909a485ac 100755 --- a/libs/SDL2/test/configure +++ b/libs/SDL2/test/configure @@ -589,6 +589,9 @@ XLIB GLES2LIB GLESLIB GLLIB +OPENGL_TARGETS +OPENGLES2_TARGETS +OPENGLES1_TARGETS CPP XMKMF SDL_CONFIG @@ -3901,17 +3904,23 @@ $as_echo "$have_opengles2" >&6; } GLLIB="" GLESLIB="" GLES2LIB="" +OPENGLES1_TARGETS="UNUSED" +OPENGLES2_TARGETS="UNUSED" +OPENGL_TARGETS="UNUSED" if test x$have_opengles = xyes; then CFLAGS="$CFLAGS -DHAVE_OPENGLES" GLESLIB="$XPATH -lGLESv1_CM" + OPENGLES1_TARGETS="TARGETS" fi if test x$have_opengles2 = xyes; then CFLAGS="$CFLAGS -DHAVE_OPENGLES2" #GLES2LIB="$XPATH -lGLESv2" + OPENGLES2_TARGETS="TARGETS" fi if test x$have_opengl = xyes; then CFLAGS="$CFLAGS -DHAVE_OPENGL" GLLIB="$XPATH $SYS_GL_LIBS" + OPENGL_TARGETS="TARGETS" fi @@ -3919,6 +3928,9 @@ fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for TTF_Init in -lSDL2_ttf" >&5 $as_echo_n "checking for TTF_Init in -lSDL2_ttf... " >&6; } if ${ac_cv_lib_SDL2_ttf_TTF_Init+:} false; then : diff --git a/libs/SDL2/test/configure.ac b/libs/SDL2/test/configure.ac new file mode 100644 index 000000000..2e237262e --- /dev/null +++ b/libs/SDL2/test/configure.ac @@ -0,0 +1,200 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(README) + +dnl Detect the canonical build and host environments +AC_CONFIG_AUX_DIRS($srcdir/../build-scripts) +AC_CANONICAL_HOST + +dnl Check for tools + +AC_PROG_CC + +dnl Check for compiler environment + +AC_C_CONST + +dnl We only care about this for building testnative at the moment, so these +dnl values shouldn't be considered absolute truth. +dnl (Haiku, for example, sets none of these.) +ISUNIX="false" +ISWINDOWS="false" +ISMACOSX="false" + +dnl Figure out which math library to use +case "$host" in + *-*-cygwin* | *-*-mingw32*) + ISWINDOWS="true" + EXE=".exe" + MATHLIB="" + SYS_GL_LIBS="-lopengl32" + ;; + *-*-haiku*) + EXE="" + MATHLIB="" + SYS_GL_LIBS="-lGL" + ;; + *-*-darwin* ) + ISMACOSX="true" + EXE="" + MATHLIB="" + SYS_GL_LIBS="-Wl,-framework,OpenGL" + ;; + *-*-aix*) + ISUNIX="true" + EXE="" + if test x$ac_cv_prog_gcc = xyes; then + CFLAGS="-mthreads" + fi + SYS_GL_LIBS="" + ;; + *-*-mint*) + EXE="" + MATHLIB="" + AC_PATH_PROG(OSMESA_CONFIG, osmesa-config, no) + if test "x$OSMESA_CONFIG" = "xyes"; then + OSMESA_CFLAGS=`$OSMESA_CONFIG --cflags` + OSMESA_LIBS=`$OSMESA_CONFIG --libs` + CFLAGS="$CFLAGS $OSMESA_CFLAGS" + SYS_GL_LIBS="$OSMESA_LIBS" + else + SYS_GL_LIBS="-lOSMesa" + fi + ;; + *-*-qnx*) + EXE="" + MATHLIB="" + SYS_GL_LIBS="-lGLES_CM" + ;; + *-*-emscripten* ) + dnl This should really be .js, but we need to specify extra flags when compiling to js + EXE=".bc" + MATHLIB="" + SYS_GL_LIBS="" + ;; + *) + dnl Oh well, call it Unix... + ISUNIX="true" + EXE="" + MATHLIB="-lm" + SYS_GL_LIBS="-lGL" + ;; +esac +AC_SUBST(EXE) +AC_SUBST(MATHLIB) +AC_SUBST(ISMACOSX) +AC_SUBST(ISWINDOWS) +AC_SUBST(ISUNIX) + +dnl Check for SDL +SDL_VERSION=2.0.0 +AM_PATH_SDL2($SDL_VERSION, + :, + AC_MSG_ERROR([*** SDL version $SDL_VERSION not found!]) +) +CFLAGS="$CFLAGS $SDL_CFLAGS" +LIBS="$LIBS -lSDL2_test $SDL_LIBS" + +dnl Check for X11 path, needed for OpenGL on some systems +AC_PATH_X +if test x$have_x = xyes; then + if test x$ac_x_includes = xno || test "x$ac_x_includes" = xNone || test "x$ac_x_includes" = x; then + : + else + CFLAGS="$CFLAGS -I$ac_x_includes" + fi + if test x$ac_x_libraries = xno || test "x$ac_x_libraries" = xNone; then + : + else + if test "x$ac_x_libraries" = x; then + XPATH="" + XLIB="-lX11" + else + XPATH="-L$ac_x_libraries" + XLIB="-L$ac_x_libraries -lX11" + fi + fi +fi + +dnl Check for OpenGL +AC_MSG_CHECKING(for OpenGL support) +have_opengl=no +AC_TRY_COMPILE([ + #include "SDL_opengl.h" +],[ +],[ +have_opengl=yes +]) +AC_MSG_RESULT($have_opengl) + +dnl Check for OpenGL ES +AC_MSG_CHECKING(for OpenGL ES support) +have_opengles=no +AC_TRY_COMPILE([ + #if defined (__IPHONEOS__) + #include + #else + #include + #endif /* __QNXNTO__ */ +],[ +],[ +have_opengles=yes +]) +AC_MSG_RESULT($have_opengles) + +dnl Check for OpenGL ES2 +AC_MSG_CHECKING(for OpenGL ES2 support) +have_opengles2=no +AC_TRY_COMPILE([ + #if defined (__IPHONEOS__) + #include + #include + #else + #include + #include + #endif +],[ +],[ +have_opengles2=yes +]) +AC_MSG_RESULT($have_opengles2) + +GLLIB="" +GLESLIB="" +GLES2LIB="" +OPENGLES1_TARGETS="UNUSED" +OPENGLES2_TARGETS="UNUSED" +OPENGL_TARGETS="UNUSED" +if test x$have_opengles = xyes; then + CFLAGS="$CFLAGS -DHAVE_OPENGLES" + GLESLIB="$XPATH -lGLESv1_CM" + OPENGLES1_TARGETS="TARGETS" +fi +if test x$have_opengles2 = xyes; then + CFLAGS="$CFLAGS -DHAVE_OPENGLES2" + #GLES2LIB="$XPATH -lGLESv2" + OPENGLES2_TARGETS="TARGETS" +fi +if test x$have_opengl = xyes; then + CFLAGS="$CFLAGS -DHAVE_OPENGL" + GLLIB="$XPATH $SYS_GL_LIBS" + OPENGL_TARGETS="TARGETS" +fi + +AC_SUBST(OPENGLES1_TARGETS) +AC_SUBST(OPENGLES2_TARGETS) +AC_SUBST(OPENGL_TARGETS) +AC_SUBST(GLLIB) +AC_SUBST(GLESLIB) +AC_SUBST(GLES2LIB) +AC_SUBST(XLIB) + +dnl Check for SDL_ttf +AC_CHECK_LIB(SDL2_ttf, TTF_Init, have_SDL_ttf=yes) +if test x$have_SDL_ttf = xyes; then + CFLAGS="$CFLAGS -DHAVE_SDL_TTF" + SDL_TTF_LIB="-lSDL2_ttf" +fi +AC_SUBST(SDL_TTF_LIB) + +dnl Finally create all the generated files +AC_OUTPUT([Makefile]) diff --git a/libs/SDL2/test/controllermap.c b/libs/SDL2/test/controllermap.c index 2ca53518a..b52baebfc 100644 --- a/libs/SDL2/test/controllermap.c +++ b/libs/SDL2/test/controllermap.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/loopwave.c b/libs/SDL2/test/loopwave.c index 88d8fc871..09fb2a385 100644 --- a/libs/SDL2/test/loopwave.c +++ b/libs/SDL2/test/loopwave.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/loopwavequeue.c b/libs/SDL2/test/loopwavequeue.c index 3f0a69e15..e1accb40a 100644 --- a/libs/SDL2/test/loopwavequeue.c +++ b/libs/SDL2/test/loopwavequeue.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testatomic.c b/libs/SDL2/test/testatomic.c index 6af9d4bf6..0a7d08424 100644 --- a/libs/SDL2/test/testatomic.c +++ b/libs/SDL2/test/testatomic.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testaudiocapture.c b/libs/SDL2/test/testaudiocapture.c index a418d123c..1a94b0af2 100644 --- a/libs/SDL2/test/testaudiocapture.c +++ b/libs/SDL2/test/testaudiocapture.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testaudiohotplug.c b/libs/SDL2/test/testaudiohotplug.c index 374cbb27b..998d319f1 100644 --- a/libs/SDL2/test/testaudiohotplug.c +++ b/libs/SDL2/test/testaudiohotplug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testaudioinfo.c b/libs/SDL2/test/testaudioinfo.c index adecce9b7..3ee1bfb65 100644 --- a/libs/SDL2/test/testaudioinfo.c +++ b/libs/SDL2/test/testaudioinfo.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testautomation.c b/libs/SDL2/test/testautomation.c index bb799ea43..1a0ecbd12 100644 --- a/libs/SDL2/test/testautomation.c +++ b/libs/SDL2/test/testautomation.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -80,8 +80,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log("Usage: %s %s [--iterations #] [--execKey #] [--seed string] [--filter suite_name|test_name]\n", - argv[0], SDLTest_CommonUsage(state)); + static const char *options[] = { "[--iterations #]", "[--execKey #]", "[--seed string]", "[--filter suite_name|test_name]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); quit(1); } diff --git a/libs/SDL2/test/testbounds.c b/libs/SDL2/test/testbounds.c index 764809446..7b8876c3c 100644 --- a/libs/SDL2/test/testbounds.c +++ b/libs/SDL2/test/testbounds.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testcustomcursor.c b/libs/SDL2/test/testcustomcursor.c index 469449818..b0b7fa79b 100644 --- a/libs/SDL2/test/testcustomcursor.c +++ b/libs/SDL2/test/testcustomcursor.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -203,7 +203,7 @@ main(int argc, char *argv[]) break; } if (consumed < 0) { - SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state)); + SDLTest_CommonLogUsage(state, argv[0], NULL); quit(1); } i += consumed; diff --git a/libs/SDL2/test/testdisplayinfo.c b/libs/SDL2/test/testdisplayinfo.c index 0cc5fbdd7..90919baf7 100644 --- a/libs/SDL2/test/testdisplayinfo.c +++ b/libs/SDL2/test/testdisplayinfo.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testdraw2.c b/libs/SDL2/test/testdraw2.c index 91ee7eea2..77a0f11eb 100644 --- a/libs/SDL2/test/testdraw2.c +++ b/libs/SDL2/test/testdraw2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -256,8 +256,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log("Usage: %s %s [--blend none|blend|add|mod] [--cyclecolor] [--cyclealpha]\n", - argv[0], SDLTest_CommonUsage(state)); + static const char *options[] = { "[--blend none|blend|add|mod]", "[--cyclecolor]", "[--cyclealpha]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); return 1; } i += consumed; diff --git a/libs/SDL2/test/testdrawchessboard.c b/libs/SDL2/test/testdrawchessboard.c index 3dd78e1ac..78e89d2a5 100644 --- a/libs/SDL2/test/testdrawchessboard.c +++ b/libs/SDL2/test/testdrawchessboard.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testdropfile.c b/libs/SDL2/test/testdropfile.c index 1c2a3f0e6..97ab872a2 100644 --- a/libs/SDL2/test/testdropfile.c +++ b/libs/SDL2/test/testdropfile.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -52,7 +52,7 @@ main(int argc, char *argv[]) consumed = -1; } if (consumed < 0) { - SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state)); + SDLTest_CommonLogUsage(state, argv[0], NULL); quit(1); } i += consumed; @@ -75,8 +75,6 @@ main(int argc, char *argv[]) while (!done) { /* Check for events */ while (SDL_PollEvent(&event)) { - SDLTest_CommonEvent(state, &event, &done); - if (event.type == SDL_DROPBEGIN) { SDL_Log("Drop beginning on window %u", (unsigned int) event.drop.windowID); } else if (event.type == SDL_DROPCOMPLETE) { @@ -85,8 +83,11 @@ main(int argc, char *argv[]) const char *typestr = (event.type == SDL_DROPFILE) ? "File" : "Text"; char *dropped_filedir = event.drop.file; SDL_Log("%s dropped on window %u: %s", typestr, (unsigned int) event.drop.windowID, dropped_filedir); - SDL_free(dropped_filedir); + /* Normally you'd have to do this, but this is freed in SDLTest_CommonEvent() */ + /*SDL_free(dropped_filedir);*/ } + + SDLTest_CommonEvent(state, &event, &done); } } diff --git a/libs/SDL2/test/testerror.c b/libs/SDL2/test/testerror.c index 87fcab21b..1f42a4fe2 100644 --- a/libs/SDL2/test/testerror.c +++ b/libs/SDL2/test/testerror.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testfile.c b/libs/SDL2/test/testfile.c index e563d77be..85ff8091c 100644 --- a/libs/SDL2/test/testfile.c +++ b/libs/SDL2/test/testfile.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testfilesystem.c b/libs/SDL2/test/testfilesystem.c index ada4e864c..cc26f34d1 100644 --- a/libs/SDL2/test/testfilesystem.c +++ b/libs/SDL2/test/testfilesystem.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testgamecontroller.c b/libs/SDL2/test/testgamecontroller.c index c8616d7cd..4d3c93937 100644 --- a/libs/SDL2/test/testgamecontroller.c +++ b/libs/SDL2/test/testgamecontroller.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testgesture.c b/libs/SDL2/test/testgesture.c index f4b254a65..a41604a6f 100644 --- a/libs/SDL2/test/testgesture.c +++ b/libs/SDL2/test/testgesture.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -9,6 +9,7 @@ including commercial applications, and to alter it and redistribute it freely. */ + /* Usage: * Spacebar to begin recording a gesture on all touches. * s to save all touches into "./gestureSave" @@ -22,6 +23,9 @@ #include #endif +#include "SDL_test.h" +#include "SDL_test_common.h" + #define WIDTH 640 #define HEIGHT 480 #define BPP 4 @@ -29,242 +33,231 @@ /* MUST BE A POWER OF 2! */ #define EVENT_BUF_SIZE 256 - #define VERBOSE 0 +static SDLTest_CommonState *state; static SDL_Event events[EVENT_BUF_SIZE]; static int eventWrite; - - static int colors[7] = {0xFF,0xFF00,0xFF0000,0xFFFF00,0x00FFFF,0xFF00FF,0xFFFFFF}; +static int quitting = 0; -SDL_Surface *screen; -SDL_Window *window; -SDL_bool quitting = SDL_FALSE; - -typedef struct { - float x,y; +typedef struct +{ + float x, y; } Point; -typedef struct { - float ang,r; - Point p; +typedef struct +{ + float ang, r; + Point p; } Knob; -static Knob knob; +static Knob knob = { 0.0f, 0.1f, { 0.0f, 0.0f } }; -void setpix(SDL_Surface *screen, float _x, float _y, unsigned int col) + +static void +setpix(SDL_Surface *screen, float _x, float _y, unsigned int col) { - Uint32 *pixmem32; - Uint32 colour; - Uint8 r,g,b; - int x = (int)_x; - int y = (int)_y; - float a; + Uint32 *pixmem32; + Uint32 colour; + Uint8 r, g, b; + const int x = (int)_x; + const int y = (int)_y; + float a; - if(x < 0 || x >= screen->w) return; - if(y < 0 || y >= screen->h) return; - - pixmem32 = (Uint32*) screen->pixels + y*screen->pitch/BPP + x; - - SDL_memcpy(&colour,pixmem32,screen->format->BytesPerPixel); - - SDL_GetRGB(colour,screen->format,&r,&g,&b); - /* r = 0;g = 0; b = 0; */ - a = (float)((col>>24)&0xFF); - if(a == 0) a = 0xFF; /* Hack, to make things easier. */ - a /= 0xFF; - r = (Uint8)(r*(1-a) + ((col>>16)&0xFF)*(a)); - g = (Uint8)(g*(1-a) + ((col>> 8)&0xFF)*(a)); - b = (Uint8)(b*(1-a) + ((col>> 0)&0xFF)*(a)); - colour = SDL_MapRGB( screen->format,r, g, b); - - - *pixmem32 = colour; -} - -void drawLine(SDL_Surface *screen,float x0,float y0,float x1,float y1,unsigned int col) { - float t; - for(t=0;t<1;t+=(float)(1.f/SDL_max(SDL_fabs(x0-x1),SDL_fabs(y0-y1)))) - setpix(screen,x1+t*(x0-x1),y1+t*(y0-y1),col); -} - -void drawCircle(SDL_Surface* screen,float x,float y,float r,unsigned int c) -{ - float tx,ty; - float xr; - for(ty = (float)-SDL_fabs(r);ty <= (float)SDL_fabs((int)r);ty++) { - xr = (float)SDL_sqrt(r*r - ty*ty); - if(r > 0) { /* r > 0 ==> filled circle */ - for(tx=-xr+.5f;tx<=xr-.5;tx++) { - setpix(screen,x+tx,y+ty,c); - } + if ( (x < 0) || (x >= screen->w) || (y < 0) || (y >= screen->h) ) { + return; } - else { - setpix(screen,x-xr+.5f,y+ty,c); - setpix(screen,x+xr-.5f,y+ty,c); + + pixmem32 = (Uint32 *) screen->pixels + y * screen->pitch / BPP + x; + + SDL_memcpy(&colour, pixmem32, screen->format->BytesPerPixel); + + SDL_GetRGB(colour,screen->format,&r,&g,&b); + + /* r = 0;g = 0; b = 0; */ + a = (float) ((col >> 24) & 0xFF); + if (a == 0) { + a = 0xFF; /* Hack, to make things easier. */ } - } + + a = (a == 0.0f) ? 1 : (a / 255.0f); + r = (Uint8) (r * (1 - a) + ((col >> 16) & 0xFF) * a); + g = (Uint8) (g * (1 - a) + ((col >> 8) & 0xFF) * a); + b = (Uint8) (b * (1 - a) + ((col >> 0) & 0xFF) * a); + colour = SDL_MapRGB(screen->format, r, g, b); + + *pixmem32 = colour; } -void drawKnob(SDL_Surface* screen,Knob k) { - drawCircle(screen,k.p.x*screen->w,k.p.y*screen->h,k.r*screen->w,0xFFFFFF); - drawCircle(screen,(k.p.x+k.r/2*SDL_cosf(k.ang))*screen->w, - (k.p.y+k.r/2*SDL_sinf(k.ang))*screen->h,k.r/4*screen->w,0); -} - -void DrawScreen(SDL_Surface* screen, SDL_Window* window) +static void +drawLine(SDL_Surface *screen, float x0, float y0, float x1, float y1, unsigned int col) { - int i; -#if 1 - SDL_FillRect(screen, NULL, 0); -#else - int x, y; - for(y = 0;y < screen->h;y++) - for(x = 0;x < screen->w;x++) - setpix(screen,(float)x,(float)y,((x%255)<<16) + ((y%255)<<8) + (x+y)%255); -#endif - - /* draw Touch History */ - for(i = eventWrite; i < eventWrite+EVENT_BUF_SIZE; ++i) { - const SDL_Event *event = &events[i&(EVENT_BUF_SIZE-1)]; - float age = (float)(i - eventWrite) / EVENT_BUF_SIZE; - float x, y; - unsigned int c, col; - - if(event->type == SDL_FINGERMOTION || - event->type == SDL_FINGERDOWN || - event->type == SDL_FINGERUP) { - x = event->tfinger.x; - y = event->tfinger.y; - - /* draw the touch: */ - c = colors[event->tfinger.fingerId%7]; - col = ((unsigned int)(c*(.1+.85))) | (unsigned int)(0xFF*age)<<24; - - if(event->type == SDL_FINGERMOTION) - drawCircle(screen,x*screen->w,y*screen->h,5,col); - else if(event->type == SDL_FINGERDOWN) - drawCircle(screen,x*screen->w,y*screen->h,-10,col); + float t; + for (t = 0; t < 1; t += (float) (1.0f / SDL_max(SDL_fabs(x0 - x1), SDL_fabs(y0 - y1)))) { + setpix(screen, x1 + t * (x0 - x1), y1 + t * (y0 - y1), col); } - } - - if(knob.p.x > 0) - drawKnob(screen,knob); - - SDL_UpdateWindowSurface(window); } -/* Returns a new SDL_Window if window is NULL or window if not. */ -SDL_Window* initWindow(SDL_Window *window, int width,int height) +static void +drawCircle(SDL_Surface *screen, float x, float y, float r, unsigned int c) { - if (!window) { - window = SDL_CreateWindow("Gesture Test", - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - width, height, SDL_WINDOW_RESIZABLE); - } - return window; + float tx,ty, xr; + for (ty = (float) -SDL_fabs(r); ty <= (float) SDL_fabs((int) r); ty++) { + xr = (float) SDL_sqrt(r * r - ty * ty); + if (r > 0) { /* r > 0 ==> filled circle */ + for(tx = -xr + 0.5f; tx <= xr - 0.5f; tx++) { + setpix(screen, x + tx, y + ty, c); + } + } else { + setpix(screen, x - xr + 0.5f, y + ty, c); + setpix(screen, x + xr - 0.5f, y + ty, c); + } + } } -void loop() +static void +drawKnob(SDL_Surface *screen, const Knob *k) +{ + drawCircle(screen, k->p.x * screen->w, k->p.y * screen->h, k->r * screen->w, 0xFFFFFF); + drawCircle(screen, (k->p.x + k->r / 2 * SDL_cosf(k->ang)) * screen->w, + (k->p.y + k->r / 2 * SDL_sinf(k->ang)) * screen->h, k->r / 4 * screen->w, 0); +} + +static void +DrawScreen(SDL_Window *window) +{ + SDL_Surface *screen = SDL_GetWindowSurface(window); + int i; + + if (!screen) { + return; + } + + SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 75, 75, 75)); + + /* draw Touch History */ + for (i = eventWrite; i < eventWrite + EVENT_BUF_SIZE; ++i) { + const SDL_Event *event = &events[i & (EVENT_BUF_SIZE - 1)]; + const float age = (float)(i - eventWrite) / EVENT_BUF_SIZE; + float x, y; + unsigned int c, col; + + if ( (event->type == SDL_FINGERMOTION) || + (event->type == SDL_FINGERDOWN) || + (event->type == SDL_FINGERUP) ) { + x = event->tfinger.x; + y = event->tfinger.y; + + /* draw the touch: */ + c = colors[event->tfinger.fingerId % 7]; + col = ((unsigned int) (c * (0.1f + 0.85f))) | (unsigned int) (0xFF * age) << 24; + + if (event->type == SDL_FINGERMOTION) { + drawCircle(screen, x * screen->w, y * screen->h, 5, col); + } else if (event->type == SDL_FINGERDOWN) { + drawCircle(screen, x * screen->w, y * screen->h, -10, col); + } + } + } + + if (knob.p.x > 0) { + drawKnob(screen, &knob); + } + + SDL_UpdateWindowSurface(window); +} + +static void +loop(void) { SDL_Event event; SDL_RWops *stream; + int i; - while(SDL_PollEvent(&event)) - { - /* Record _all_ events */ - events[eventWrite & (EVENT_BUF_SIZE-1)] = event; - eventWrite++; + while (SDL_PollEvent(&event)) { + SDLTest_CommonEvent(state, &event, &quitting); - switch (event.type) - { - case SDL_QUIT: - quitting = SDL_TRUE; - break; - case SDL_KEYDOWN: - switch (event.key.keysym.sym) - { - case SDLK_i: - { - int i; - for (i = 0; i < SDL_GetNumTouchDevices(); ++i) { - SDL_TouchID id = SDL_GetTouchDevice(i); - SDL_Log("Fingers Down on device %"SDL_PRIs64": %d", id, SDL_GetNumTouchFingers(id)); - } - break; - } - case SDLK_SPACE: - SDL_RecordGesture(-1); - break; - case SDLK_s: - stream = SDL_RWFromFile("gestureSave", "w"); - SDL_Log("Wrote %i templates", SDL_SaveAllDollarTemplates(stream)); - SDL_RWclose(stream); - break; - case SDLK_l: - stream = SDL_RWFromFile("gestureSave", "r"); - SDL_Log("Loaded: %i", SDL_LoadDollarTemplates(-1, stream)); - SDL_RWclose(stream); - break; - case SDLK_ESCAPE: - quitting = SDL_TRUE; - break; + /* Record _all_ events */ + events[eventWrite & (EVENT_BUF_SIZE-1)] = event; + eventWrite++; + + switch (event.type) { + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_i: { + for (i = 0; i < SDL_GetNumTouchDevices(); ++i) { + const SDL_TouchID id = SDL_GetTouchDevice(i); + SDL_Log("Fingers Down on device %"SDL_PRIs64": %d", id, SDL_GetNumTouchFingers(id)); + } + break; + } + + case SDLK_SPACE: + SDL_RecordGesture(-1); + break; + + case SDLK_s: + stream = SDL_RWFromFile("gestureSave", "w"); + SDL_Log("Wrote %i templates", SDL_SaveAllDollarTemplates(stream)); + SDL_RWclose(stream); + break; + + case SDLK_l: + stream = SDL_RWFromFile("gestureSave", "r"); + SDL_Log("Loaded: %i", SDL_LoadDollarTemplates(-1, stream)); + SDL_RWclose(stream); + break; + } + break; + +#if VERBOSE + case SDL_FINGERMOTION: + SDL_Log("Finger: %"SDL_PRIs64",x: %f, y: %f",event.tfinger.fingerId, + event.tfinger.x,event.tfinger.y); + break; + + case SDL_FINGERDOWN: + SDL_Log("Finger: %"SDL_PRIs64" down - x: %f, y: %f", + event.tfinger.fingerId,event.tfinger.x,event.tfinger.y); + break; + + case SDL_FINGERUP: + SDL_Log("Finger: %"SDL_PRIs64" up - x: %f, y: %f", + event.tfinger.fingerId,event.tfinger.x,event.tfinger.y); + break; +#endif + + case SDL_MULTIGESTURE: +#if VERBOSE + SDL_Log("Multi Gesture: x = %f, y = %f, dAng = %f, dR = %f", + event.mgesture.x, event.mgesture.y, + event.mgesture.dTheta, event.mgesture.dDist); + SDL_Log("MG: numDownTouch = %i",event.mgesture.numFingers); +#endif + + knob.p.x = event.mgesture.x; + knob.p.y = event.mgesture.y; + knob.ang += event.mgesture.dTheta; + knob.r += event.mgesture.dDist; + break; + + case SDL_DOLLARGESTURE: + SDL_Log("Gesture %"SDL_PRIs64" performed, error: %f", + event.dgesture.gestureId, event.dgesture.error); + break; + + case SDL_DOLLARRECORD: + SDL_Log("Recorded gesture: %"SDL_PRIs64"",event.dgesture.gestureId); + break; + } + } + + for (i = 0; i < state->num_windows; ++i) { + if (state->windows[i]) { + DrawScreen(state->windows[i]); } - break; - case SDL_WINDOWEVENT: - if (event.window.event == SDL_WINDOWEVENT_RESIZED) { - if (!(window = initWindow(window, event.window.data1, event.window.data2)) || - !(screen = SDL_GetWindowSurface(window))) - { - SDL_Quit(); - exit(1); - } - } - break; - case SDL_FINGERMOTION: -#if VERBOSE - SDL_Log("Finger: %"SDL_PRIs64",x: %f, y: %f",event.tfinger.fingerId, - event.tfinger.x,event.tfinger.y); -#endif - break; - case SDL_FINGERDOWN: -#if VERBOSE - SDL_Log("Finger: %"SDL_PRIs64" down - x: %f, y: %f", - event.tfinger.fingerId,event.tfinger.x,event.tfinger.y); -#endif - break; - case SDL_FINGERUP: -#if VERBOSE - SDL_Log("Finger: %"SDL_PRIs64" up - x: %f, y: %f", - event.tfinger.fingerId,event.tfinger.x,event.tfinger.y); -#endif - break; - case SDL_MULTIGESTURE: -#if VERBOSE - SDL_Log("Multi Gesture: x = %f, y = %f, dAng = %f, dR = %f", - event.mgesture.x, - event.mgesture.y, - event.mgesture.dTheta, - event.mgesture.dDist); - SDL_Log("MG: numDownTouch = %i",event.mgesture.numFingers); -#endif - knob.p.x = event.mgesture.x; - knob.p.y = event.mgesture.y; - knob.ang += event.mgesture.dTheta; - knob.r += event.mgesture.dDist; - break; - case SDL_DOLLARGESTURE: - SDL_Log("Gesture %"SDL_PRIs64" performed, error: %f", - event.dgesture.gestureId, - event.dgesture.error); - break; - case SDL_DOLLARRECORD: - SDL_Log("Recorded gesture: %"SDL_PRIs64"",event.dgesture.gestureId); - break; - } } - DrawScreen(screen, window); #ifdef __EMSCRIPTEN__ if (quitting) { @@ -275,35 +268,30 @@ void loop() int main(int argc, char* argv[]) { - window = NULL; - screen = NULL; - quitting = SDL_FALSE; + state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO); + if (!state) { + return 1; + } - /* Enable standard application logging */ - SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); + state->window_title = "Gesture Test"; + state->window_w = WIDTH; + state->window_h = HEIGHT; + state->skip_renderer = SDL_TRUE; - /* gesture variables */ - knob.r = .1f; - knob.ang = 0; - - if (SDL_Init(SDL_INIT_VIDEO) < 0 ) return 1; - - if (!(window = initWindow(window, WIDTH, HEIGHT)) || - !(screen = SDL_GetWindowSurface(window))) - { - SDL_Quit(); - return 1; - } + if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) { + SDLTest_CommonQuit(state); + return 1; + } #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(loop, 0, 1); #else - while(!quitting) { + while (!quitting) { loop(); } #endif - SDL_Quit(); - return 0; + SDLTest_CommonQuit(state); + return 0; } diff --git a/libs/SDL2/test/testgl2.c b/libs/SDL2/test/testgl2.c index dd01d0e29..a8bc181a3 100644 --- a/libs/SDL2/test/testgl2.c +++ b/libs/SDL2/test/testgl2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -218,6 +218,7 @@ main(int argc, char *argv[]) Uint32 then, now, frames; int status; int dw, dh; + int swap_interval = 0; /* Enable standard application logging */ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); @@ -247,8 +248,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log("Usage: %s %s [--fsaa n] [--accel n]\n", argv[0], - SDLTest_CommonUsage(state)); + static const char *options[] = { "[--fsaa n]", "[--accel n]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); quit(1); } i += consumed; @@ -289,11 +290,15 @@ main(int argc, char *argv[]) if (state->render_flags & SDL_RENDERER_PRESENTVSYNC) { /* try late-swap-tearing first. If not supported, try normal vsync. */ - if (SDL_GL_SetSwapInterval(-1) == -1) { + if (SDL_GL_SetSwapInterval(-1) == 0) { + swap_interval = -1; + } else { SDL_GL_SetSwapInterval(1); + swap_interval = 1; } } else { SDL_GL_SetSwapInterval(0); /* disable vsync. */ + swap_interval = 0; } SDL_GetCurrentDisplayMode(0, &mode); @@ -377,16 +382,35 @@ main(int argc, char *argv[]) then = SDL_GetTicks(); done = 0; while (!done) { + SDL_bool update_swap_interval = SDL_FALSE; + /* Check for events */ ++frames; while (SDL_PollEvent(&event)) { SDLTest_CommonEvent(state, &event, &done); + if (event.type == SDL_KEYDOWN) { + if (event.key.keysym.sym == SDLK_o) { + swap_interval--; + update_swap_interval = SDL_TRUE; + } else if (event.key.keysym.sym == SDLK_p) { + swap_interval++; + update_swap_interval = SDL_TRUE; + } + } } + + if (update_swap_interval) { + SDL_Log("Swap interval to be set to %d\n", swap_interval); + } + for (i = 0; i < state->num_windows; ++i) { int w, h; if (state->windows[i] == NULL) continue; SDL_GL_MakeCurrent(state->windows[i], context); + if (update_swap_interval) { + SDL_GL_SetSwapInterval(swap_interval); + } SDL_GL_GetDrawableSize(state->windows[i], &w, &h); ctx.glViewport(0, 0, w, h); Render(); diff --git a/libs/SDL2/test/testgles.c b/libs/SDL2/test/testgles.c index 96895da0f..c4ea45f54 100644 --- a/libs/SDL2/test/testgles.c +++ b/libs/SDL2/test/testgles.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -146,8 +146,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log("Usage: %s %s [--fsaa] [--accel] [--zdepth %%d]\n", argv[0], - SDLTest_CommonUsage(state)); + static const char *options[] = { "[--fsaa]", "[--accel]", "[--zdepth %d]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); quit(1); } i += consumed; diff --git a/libs/SDL2/test/testgles2.c b/libs/SDL2/test/testgles2.c index c4578a5cc..641a8975c 100644 --- a/libs/SDL2/test/testgles2.c +++ b/libs/SDL2/test/testgles2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -518,8 +518,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log ("Usage: %s %s [--fsaa] [--accel] [--zdepth %%d]\n", argv[0], - SDLTest_CommonUsage(state)); + static const char *options[] = { "[--fsaa]", "[--accel]", "[--zdepth %d]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); quit(1); } i += consumed; diff --git a/libs/SDL2/test/testhotplug.c b/libs/SDL2/test/testhotplug.c index 72c90e8d9..4a6a954f7 100644 --- a/libs/SDL2/test/testhotplug.c +++ b/libs/SDL2/test/testhotplug.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testiconv.c b/libs/SDL2/test/testiconv.c index 47e8c377a..4729b58fa 100644 --- a/libs/SDL2/test/testiconv.c +++ b/libs/SDL2/test/testiconv.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testime.c b/libs/SDL2/test/testime.c index 77bb86962..45bcdb559 100644 --- a/libs/SDL2/test/testime.c +++ b/libs/SDL2/test/testime.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testintersections.c b/libs/SDL2/test/testintersections.c index 619df0640..0c824cb95 100644 --- a/libs/SDL2/test/testintersections.c +++ b/libs/SDL2/test/testintersections.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -315,8 +315,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log("Usage: %s %s [--blend none|blend|add|mod] [--cyclecolor] [--cyclealpha]\n", - argv[0], SDLTest_CommonUsage(state)); + static const char *options[] = { "[--blend none|blend|add|mod]", "[--cyclecolor]", "[--cyclealpha]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); return 1; } i += consumed; diff --git a/libs/SDL2/test/testjoystick.c b/libs/SDL2/test/testjoystick.c index bca749244..16877a152 100644 --- a/libs/SDL2/test/testjoystick.c +++ b/libs/SDL2/test/testjoystick.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testkeys.c b/libs/SDL2/test/testkeys.c index 73f880e13..fc770d3e2 100644 --- a/libs/SDL2/test/testkeys.c +++ b/libs/SDL2/test/testkeys.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testloadso.c b/libs/SDL2/test/testloadso.c index c6fa33106..e5273815f 100644 --- a/libs/SDL2/test/testloadso.c +++ b/libs/SDL2/test/testloadso.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testlock.c b/libs/SDL2/test/testlock.c index 8299a9a67..b6e2935ac 100644 --- a/libs/SDL2/test/testlock.c +++ b/libs/SDL2/test/testlock.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testmessage.c b/libs/SDL2/test/testmessage.c index 8488d8eda..4ce8a13c8 100644 --- a/libs/SDL2/test/testmessage.c +++ b/libs/SDL2/test/testmessage.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testmultiaudio.c b/libs/SDL2/test/testmultiaudio.c index 52a4cac7d..e702b39e9 100644 --- a/libs/SDL2/test/testmultiaudio.c +++ b/libs/SDL2/test/testmultiaudio.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testnative.c b/libs/SDL2/test/testnative.c index 674d9d3b4..c1facd398 100644 --- a/libs/SDL2/test/testnative.c +++ b/libs/SDL2/test/testnative.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testnative.h b/libs/SDL2/test/testnative.h index 29d85fb32..1f9275311 100644 --- a/libs/SDL2/test/testnative.h +++ b/libs/SDL2/test/testnative.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testnativew32.c b/libs/SDL2/test/testnativew32.c index 7e96bc697..544c413cd 100644 --- a/libs/SDL2/test/testnativew32.c +++ b/libs/SDL2/test/testnativew32.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testnativex11.c b/libs/SDL2/test/testnativex11.c index 386c25e9e..a8303c714 100644 --- a/libs/SDL2/test/testnativex11.c +++ b/libs/SDL2/test/testnativex11.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testoverlay2.c b/libs/SDL2/test/testoverlay2.c index daf07d3e9..6da1f960c 100644 --- a/libs/SDL2/test/testoverlay2.c +++ b/libs/SDL2/test/testoverlay2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -252,7 +252,7 @@ main(int argc, char **argv) } while (argc > 1) { - if (strcmp(argv[1], "-fps") == 0) { + if (SDL_strcmp(argv[1], "-fps") == 0) { if (argv[2]) { fps = SDL_atoi(argv[2]); if (fps == 0) { @@ -272,11 +272,11 @@ main(int argc, char **argv) "The -fps option requires an argument [from 1 to 1000], default is 12.\n"); quit(10); } - } else if (strcmp(argv[1], "-nodelay") == 0) { + } else if (SDL_strcmp(argv[1], "-nodelay") == 0) { nodelay = 1; argv += 1; argc -= 1; - } else if (strcmp(argv[1], "-scale") == 0) { + } else if (SDL_strcmp(argv[1], "-scale") == 0) { if (argv[2]) { scale = SDL_atoi(argv[2]); if (scale == 0) { @@ -296,8 +296,8 @@ main(int argc, char **argv) "The -fps option requires an argument [from 1 to 1000], default is 12.\n"); quit(10); } - } else if ((strcmp(argv[1], "-help") == 0) - || (strcmp(argv[1], "-h") == 0)) { + } else if ((SDL_strcmp(argv[1], "-help") == 0) + || (SDL_strcmp(argv[1], "-h") == 0)) { PrintUsage(argv[0]); quit(0); } else { @@ -307,7 +307,7 @@ main(int argc, char **argv) break; } - RawMooseData = (Uint8 *) malloc(MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT); + RawMooseData = (Uint8 *) SDL_malloc(MOOSEFRAME_SIZE * MOOSEFRAMES_COUNT); if (RawMooseData == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't allocate memory for movie !\n"); quit(1); @@ -317,7 +317,7 @@ main(int argc, char **argv) handle = SDL_RWFromFile("moose.dat", "rb"); if (handle == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Can't find the file moose.dat !\n"); - free(RawMooseData); + SDL_free(RawMooseData); quit(2); } @@ -335,21 +335,21 @@ main(int argc, char **argv) SDL_WINDOW_RESIZABLE); if (!window) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create window: %s\n", SDL_GetError()); - free(RawMooseData); + SDL_free(RawMooseData); quit(4); } renderer = SDL_CreateRenderer(window, -1, 0); if (!renderer) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create renderer: %s\n", SDL_GetError()); - free(RawMooseData); + SDL_free(RawMooseData); quit(4); } MooseTexture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, MOOSEPIC_W, MOOSEPIC_H); if (!MooseTexture) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't set create texture: %s\n", SDL_GetError()); - free(RawMooseData); + SDL_free(RawMooseData); quit(5); } /* Uncomment this to check vertex color with a YUV texture */ @@ -373,7 +373,7 @@ main(int argc, char **argv) 0, 100); } - free(RawMooseData); + SDL_free(RawMooseData); /* set the start frame */ i = 0; diff --git a/libs/SDL2/test/testplatform.c b/libs/SDL2/test/testplatform.c index 1c1d2dcd8..44128111b 100644 --- a/libs/SDL2/test/testplatform.c +++ b/libs/SDL2/test/testplatform.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testpower.c b/libs/SDL2/test/testpower.c index adb58832a..985607788 100644 --- a/libs/SDL2/test/testpower.c +++ b/libs/SDL2/test/testpower.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testqsort.c b/libs/SDL2/test/testqsort.c index e83b0731e..8286832c3 100644 --- a/libs/SDL2/test/testqsort.c +++ b/libs/SDL2/test/testqsort.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testrelative.c b/libs/SDL2/test/testrelative.c index 816329ff5..3b61be4fa 100644 --- a/libs/SDL2/test/testrelative.c +++ b/libs/SDL2/test/testrelative.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testrendercopyex.c b/libs/SDL2/test/testrendercopyex.c index 209a35157..fc01b654e 100644 --- a/libs/SDL2/test/testrendercopyex.c +++ b/libs/SDL2/test/testrendercopyex.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -174,18 +174,10 @@ main(int argc, char *argv[]) if (!state) { return 1; } - for (i = 1; i < argc;) { - int consumed; - consumed = SDLTest_CommonArg(state, i); - if (consumed == 0) { - SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state)); - return 1; - } - i += consumed; - } - if (!SDLTest_CommonInit(state)) { - quit(2); + if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) { + SDLTest_CommonQuit(state); + return 1; } drawstates = SDL_stack_alloc(DrawState, state->num_windows); diff --git a/libs/SDL2/test/testrendertarget.c b/libs/SDL2/test/testrendertarget.c index 7d24d8aea..bc50007ff 100644 --- a/libs/SDL2/test/testrendertarget.c +++ b/libs/SDL2/test/testrendertarget.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -275,8 +275,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log("Usage: %s %s [--composite]\n", - argv[0], SDLTest_CommonUsage(state)); + static const char *options[] = { "[--composite]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); quit(1); } i += consumed; diff --git a/libs/SDL2/test/testresample.c b/libs/SDL2/test/testresample.c index 4234d9e45..ded2ae3d3 100644 --- a/libs/SDL2/test/testresample.c +++ b/libs/SDL2/test/testresample.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testrumble.c b/libs/SDL2/test/testrumble.c index 908a6aafb..c8473f56a 100644 --- a/libs/SDL2/test/testrumble.c +++ b/libs/SDL2/test/testrumble.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testscale.c b/libs/SDL2/test/testscale.c index e1b46fcc8..363927721 100644 --- a/libs/SDL2/test/testscale.c +++ b/libs/SDL2/test/testscale.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -164,18 +164,10 @@ main(int argc, char *argv[]) if (!state) { return 1; } - for (i = 1; i < argc;) { - int consumed; - consumed = SDLTest_CommonArg(state, i); - if (consumed == 0) { - SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state)); - return 1; - } - i += consumed; - } - if (!SDLTest_CommonInit(state)) { - quit(2); + if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) { + SDLTest_CommonQuit(state); + return 1; } drawstates = SDL_stack_alloc(DrawState, state->num_windows); diff --git a/libs/SDL2/test/testsem.c b/libs/SDL2/test/testsem.c index 884763e6a..804344020 100644 --- a/libs/SDL2/test/testsem.c +++ b/libs/SDL2/test/testsem.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testsensor.c b/libs/SDL2/test/testsensor.c index 00bfd137d..0896c3067 100644 --- a/libs/SDL2/test/testsensor.c +++ b/libs/SDL2/test/testsensor.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testshader.c b/libs/SDL2/test/testshader.c index ee0ccdad2..c791cd5b9 100644 --- a/libs/SDL2/test/testshader.c +++ b/libs/SDL2/test/testshader.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testshape.c b/libs/SDL2/test/testshape.c index 7e451e667..dab3a8747 100644 --- a/libs/SDL2/test/testshape.c +++ b/libs/SDL2/test/testshape.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testsprite2.c b/libs/SDL2/test/testsprite2.c index b0348f85d..76ac7ebd1 100644 --- a/libs/SDL2/test/testsprite2.c +++ b/libs/SDL2/test/testsprite2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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,6 +37,8 @@ static SDL_Rect *positions; static SDL_Rect *velocities; static int sprite_w, sprite_h; static SDL_BlendMode blendMode = SDL_BLENDMODE_BLEND; +static Uint32 next_fps_check, frames; +static const Uint32 fps_check_delay = 5000; /* Number of iterations to move sprites - used for visual tests. */ /* -1: infinite random moves (default); >=0: enables N deterministic moves */ @@ -244,6 +246,7 @@ MoveSprites(SDL_Renderer * renderer, SDL_Texture * sprite) void loop() { + Uint32 now; int i; SDL_Event event; @@ -261,13 +264,24 @@ loop() emscripten_cancel_main_loop(); } #endif + + frames++; + now = SDL_GetTicks(); + if (SDL_TICKS_PASSED(now, next_fps_check)) { + /* Print out some timing information */ + const Uint32 then = next_fps_check - fps_check_delay; + const double fps = ((double) frames * 1000) / (now - then); + SDL_Log("%2.2f frames per second\n", fps); + next_fps_check = now + fps_check_delay; + frames = 0; + } + } int main(int argc, char *argv[]) { int i; - Uint32 then, now, frames; Uint64 seed; const char *icon = "icon.bmp"; @@ -326,8 +340,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log("Usage: %s %s [--blend none|blend|add|mod] [--cyclecolor] [--cyclealpha] [--iterations N] [num_sprites] [icon.bmp]\n", - argv[0], SDLTest_CommonUsage(state)); + static const char *options[] = { "[--blend none|blend|add|mod]", "[--cyclecolor]", "[--cyclealpha]", "[--iterations N]", "[num_sprites]", "[icon.bmp]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); quit(1); } i += consumed; @@ -384,24 +398,17 @@ main(int argc, char *argv[]) /* Main render loop */ frames = 0; - then = SDL_GetTicks(); + next_fps_check = SDL_GetTicks() + fps_check_delay; done = 0; #ifdef __EMSCRIPTEN__ emscripten_set_main_loop(loop, 0, 1); #else while (!done) { - ++frames; loop(); } #endif - /* Print out some timing information */ - now = SDL_GetTicks(); - if (now > then) { - double fps = ((double) frames * 1000) / (now - then); - SDL_Log("%2.2f frames per second\n", fps); - } quit(0); return 0; } diff --git a/libs/SDL2/test/testspriteminimal.c b/libs/SDL2/test/testspriteminimal.c index 92560002a..3eebdf8cf 100644 --- a/libs/SDL2/test/testspriteminimal.c +++ b/libs/SDL2/test/testspriteminimal.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/teststreaming.c b/libs/SDL2/test/teststreaming.c index 7ec689106..ade436bf2 100644 --- a/libs/SDL2/test/teststreaming.c +++ b/libs/SDL2/test/teststreaming.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testthread.c b/libs/SDL2/test/testthread.c index 4555a1e94..34c5d8821 100644 --- a/libs/SDL2/test/testthread.c +++ b/libs/SDL2/test/testthread.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testtimer.c b/libs/SDL2/test/testtimer.c index 34764c1c9..e3fa93acf 100644 --- a/libs/SDL2/test/testtimer.c +++ b/libs/SDL2/test/testtimer.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testver.c b/libs/SDL2/test/testver.c index 1ae008345..2c39c637c 100644 --- a/libs/SDL2/test/testver.c +++ b/libs/SDL2/test/testver.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testviewport.c b/libs/SDL2/test/testviewport.c index 4b8d20e76..2706ab2ff 100644 --- a/libs/SDL2/test/testviewport.c +++ b/libs/SDL2/test/testviewport.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -161,8 +161,8 @@ main(int argc, char *argv[]) } } if (consumed < 0) { - SDL_Log("Usage: %s %s [--target]\n", - argv[0], SDLTest_CommonUsage(state)); + static const char *options[] = { "[--target]", NULL }; + SDLTest_CommonLogUsage(state, argv[0], options); quit(1); } i += consumed; diff --git a/libs/SDL2/test/testvulkan.c b/libs/SDL2/test/testvulkan.c index cd682af1f..a0c1113a1 100644 --- a/libs/SDL2/test/testvulkan.c +++ b/libs/SDL2/test/testvulkan.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -1119,7 +1119,7 @@ static SDL_bool render(void) int main(int argc, char *argv[]) { int fsaa, accel; - int i, done; + int done; SDL_DisplayMode mode; SDL_Event event; Uint32 then, now, frames; @@ -1138,27 +1138,15 @@ int main(int argc, char *argv[]) { return 1; } - for(i = 1; i < argc;) - { - int consumed; - - consumed = SDLTest_CommonArg(state, i); - if(consumed < 0) - { - SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state)); - quit(1); - } - i += consumed; - } /* Set Vulkan parameters */ state->window_flags |= SDL_WINDOW_VULKAN; state->num_windows = 1; state->skip_renderer = 1; - if(!SDLTest_CommonInit(state)) - { - quit(2); + if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) { + SDLTest_CommonQuit(state); + return 1; } SDL_GetCurrentDisplayMode(0, &mode); diff --git a/libs/SDL2/test/testwm2.c b/libs/SDL2/test/testwm2.c index 5da387309..9ec867b04 100644 --- a/libs/SDL2/test/testwm2.c +++ b/libs/SDL2/test/testwm2.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -129,21 +129,10 @@ main(int argc, char *argv[]) if (!state) { return 1; } - for (i = 1; i < argc;) { - int consumed; - consumed = SDLTest_CommonArg(state, i); - if (consumed == 0) { - consumed = -1; - } - if (consumed < 0) { - SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state)); - quit(1); - } - i += consumed; - } - if (!SDLTest_CommonInit(state)) { - quit(2); + if (!SDLTest_CommonDefaultArgs(state, argc, argv) || !SDLTest_CommonInit(state)) { + SDLTest_CommonQuit(state); + return 1; } SDL_EventState(SDL_DROPFILE, SDL_ENABLE); diff --git a/libs/SDL2/test/testyuv.c b/libs/SDL2/test/testyuv.c index f52ab9f72..1b05f0ab4 100644 --- a/libs/SDL2/test/testyuv.c +++ b/libs/SDL2/test/testyuv.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testyuv_cvt.c b/libs/SDL2/test/testyuv_cvt.c index 553a3fa18..91e5071e5 100644 --- a/libs/SDL2/test/testyuv_cvt.c +++ b/libs/SDL2/test/testyuv_cvt.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/testyuv_cvt.h b/libs/SDL2/test/testyuv_cvt.h index bd845878f..15ac93260 100644 --- a/libs/SDL2/test/testyuv_cvt.h +++ b/libs/SDL2/test/testyuv_cvt.h @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/test/torturethread.c b/libs/SDL2/test/torturethread.c index 9b1a407ee..e41280d7a 100644 --- a/libs/SDL2/test/torturethread.c +++ b/libs/SDL2/test/torturethread.c @@ -1,5 +1,5 @@ /* - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/bin/SDL2.dll b/libs/SDL2/x86_64-w64-mingw32/bin/SDL2.dll index 934f8091c..0edb386ee 100755 Binary files a/libs/SDL2/x86_64-w64-mingw32/bin/SDL2.dll and b/libs/SDL2/x86_64-w64-mingw32/bin/SDL2.dll differ diff --git a/libs/SDL2/x86_64-w64-mingw32/bin/sdl2-config b/libs/SDL2/x86_64-w64-mingw32/bin/sdl2-config index 9809f6002..0b03712c7 100755 --- a/libs/SDL2/x86_64-w64-mingw32/bin/sdl2-config +++ b/libs/SDL2/x86_64-w64-mingw32/bin/sdl2-config @@ -39,7 +39,7 @@ while test $# -gt 0; do echo $exec_prefix ;; --version) - echo 2.0.9 + echo 2.0.10 ;; --cflags) echo -I${prefix}/include/SDL2 -Dmain=SDL_main @@ -49,7 +49,7 @@ while test $# -gt 0; do ;; --static-libs) # --libs|--static-libs) - echo -L${exec_prefix}/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -static-libgcc + echo -L${exec_prefix}/lib -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -static-libgcc ;; *) echo "${usage}" 1>&2 diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL.h index fc35a419e..88dce0c03 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_assert.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_assert.h index b38f928ae..8baecb63e 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_assert.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_atomic.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_atomic.h index b2287748c..deee35f91 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_atomic.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_atomic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -162,12 +162,29 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") #elif defined(__GNUC__) && defined(__arm__) -#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) +#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */ +/* Information from: + https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19 + + The Linux kernel provides a helper function which provides the right code for a memory barrier, + hard-coded at address 0xffff0fa0 +*/ +typedef void (*SDL_KernelMemoryBarrierFunc)(); +#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)() +#elif 0 /* defined(__QNXNTO__) */ +#include + +#define SDL_MemoryBarrierRelease() __cpu_membarrier() +#define SDL_MemoryBarrierAcquire() __cpu_membarrier() +#else +#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__) #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory") #elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__) #ifdef __thumb__ /* The mcr instruction isn't available in thumb mode, use real functions */ +#define SDL_MEMORY_BARRIER_USES_FUNCTION #define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction() #define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction() #else @@ -177,6 +194,7 @@ extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void); #else #define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory") #define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory") +#endif /* __LINUX__ || __ANDROID__ */ #endif /* __GNUC__ && __arm__ */ #else #if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120)) diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_audio.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_audio.h index d3e1bface..305c01a9d 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_audio.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_audio.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -420,23 +420,56 @@ extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev, /* @} *//* Pause audio functions */ /** - * This function loads a WAVE from the data source, automatically freeing - * that source if \c freesrc is non-zero. For example, to load a WAVE file, - * you could do: + * \brief Load the audio data of a WAVE file into memory + * + * Loading a WAVE file requires \c src, \c spec, \c audio_buf and \c audio_len + * to be valid pointers. The entire data portion of the file is then loaded + * into memory and decoded if necessary. + * + * If \c freesrc is non-zero, the data source gets automatically closed and + * freed before the function returns. + * + * Supported are RIFF WAVE files with the formats PCM (8, 16, 24, and 32 bits), + * IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and A-law and + * µ-law (8 bits). Other formats are currently unsupported and cause an error. + * + * If this function succeeds, the pointer returned by it is equal to \c spec + * and the pointer to the audio data allocated by the function is written to + * \c audio_buf and its length in bytes to \c audio_len. The \ref SDL_AudioSpec + * members \c freq, \c channels, and \c format are set to the values of the + * audio data in the buffer. The \c samples member is set to a sane default and + * all others are set to zero. + * + * It's necessary to use SDL_FreeWAV() to free the audio data returned in + * \c audio_buf when it is no longer used. + * + * Because of the underspecification of the Waveform format, there are many + * problematic files in the wild that cause issues with strict decoders. To + * provide compatibility with these files, this decoder is lenient in regards + * to the truncation of the file, the fact chunk, and the size of the RIFF + * chunk. The hints SDL_HINT_WAVE_RIFF_CHUNK_SIZE, SDL_HINT_WAVE_TRUNCATION, + * and SDL_HINT_WAVE_FACT_CHUNK can be used to tune the behavior of the + * loading process. + * + * Any file that is invalid (due to truncation, corruption, or wrong values in + * the headers), too big, or unsupported causes an error. Additionally, any + * critical I/O error from the data source will terminate the loading process + * with an error. The function returns NULL on error and in all cases (with the + * exception of \c src being NULL), an appropriate error message will be set. + * + * It is required that the data source supports seeking. + * + * Example: * \code * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, ...); * \endcode * - * If this function succeeds, it returns the given SDL_AudioSpec, - * filled with the audio data format of the wave data, and sets - * \c *audio_buf to a malloc()'d buffer containing the audio data, - * and sets \c *audio_len to the length of that audio buffer, in bytes. - * You need to free the audio buffer with SDL_FreeWAV() when you are - * done with it. - * - * This function returns NULL and sets the SDL error message if the - * wave file cannot be opened, uses an unknown data format, or is - * corrupt. Currently raw and MS-ADPCM WAVE files are supported. + * \param src The data source with the WAVE data + * \param freesrc A integer value that makes the function close the data source if non-zero + * \param spec A pointer filled with the audio format of the audio data + * \param audio_buf A pointer filled with the audio data allocated by the function + * \param audio_len A pointer filled with the length of the audio data buffer in bytes + * \return NULL on error, or non-NULL on success. */ extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src, int freesrc, diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_bits.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_bits.h index eb8322f0d..b116cc8d0 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_bits.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_bits.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -101,6 +101,15 @@ SDL_MostSignificantBitIndex32(Uint32 x) #endif } +SDL_FORCE_INLINE SDL_bool +SDL_HasExactlyOneBitSet32(Uint32 x) +{ + if (x && !(x & (x - 1))) { + return SDL_TRUE; + } + return SDL_FALSE; +} + /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_blendmode.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_blendmode.h index 36a5ea76f..6f0a22b99 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_blendmode.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_blendmode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -90,12 +90,12 @@ typedef enum /** * \brief Create a custom blend mode, which may or may not be supported by a given renderer * - * \param srcColorFactor - * \param dstColorFactor - * \param colorOperation - * \param srcAlphaFactor - * \param dstAlphaFactor - * \param alphaOperation + * \param srcColorFactor source color factor + * \param dstColorFactor destination color factor + * \param colorOperation color operation + * \param srcAlphaFactor source alpha factor + * \param dstAlphaFactor destination alpha factor + * \param alphaOperation alpha operation * * The result of the blend mode operation will be: * dstRGB = dstRGB * dstColorFactor colorOperation srcRGB * srcColorFactor diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_clipboard.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_clipboard.h index f28751ebb..c4f8766ce 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_clipboard.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_clipboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_config.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_config.h index c58be8e72..395ad7c26 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_config.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_config.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_cpuinfo.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_cpuinfo.h index ee3a47e84..296df01aa 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_cpuinfo.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_cpuinfo.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -41,24 +41,43 @@ #else #include #ifndef _WIN64 +#ifndef __MMX__ #define __MMX__ +#endif +#ifndef __3dNOW__ #define __3dNOW__ #endif +#endif +#ifndef __SSE__ #define __SSE__ +#endif +#ifndef __SSE2__ #define __SSE2__ +#endif #endif /* __clang__ */ #elif defined(__MINGW64_VERSION_MAJOR) #include #else -#ifdef __ALTIVEC__ -#if defined(HAVE_ALTIVEC_H) && !defined(__APPLE_ALTIVEC__) && !defined(SDL_DISABLE_ALTIVEC_H) +/* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC_H to have it included. */ +#if defined(HAVE_ALTIVEC_H) && defined(__ALTIVEC__) && !defined(__APPLE_ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC_H) #include -#undef pixel -#undef bool #endif -#endif -#if defined(__ARM_NEON__) && !defined(SDL_DISABLE_ARM_NEON_H) -#include +#if !defined(SDL_DISABLE_ARM_NEON_H) +# if defined(__ARM_NEON) +# include +# elif defined(__WINDOWS__) || defined(__WINRT__) +/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */ +# if defined(_M_ARM) +# include +# include +# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */ +# endif +# if defined (_M_ARM64) +# include +# include +# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */ +# endif +# endif #endif #if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H) #include @@ -177,6 +196,69 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void); */ extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void); +/** + * \brief Report the alignment this system needs for SIMD allocations. + * + * This will return the minimum number of bytes to which a pointer must be + * aligned to be compatible with SIMD instructions on the current machine. + * For example, if the machine supports SSE only, it will return 16, but if + * it supports AVX-512F, it'll return 64 (etc). This only reports values for + * instruction sets SDL knows about, so if your SDL build doesn't have + * SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and + * not 64 for the AVX-512 instructions that exist but SDL doesn't know about. + * Plan accordingly. + */ +extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void); + +/** + * \brief Allocate memory in a SIMD-friendly way. + * + * This will allocate a block of memory that is suitable for use with SIMD + * instructions. Specifically, it will be properly aligned and padded for + * the system's supported vector instructions. + * + * The memory returned will be padded such that it is safe to read or write + * an incomplete vector at the end of the memory block. This can be useful + * so you don't have to drop back to a scalar fallback at the end of your + * SIMD processing loop to deal with the final elements without overflowing + * the allocated buffer. + * + * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free() + * or delete[], etc. + * + * Note that SDL will only deal with SIMD instruction sets it is aware of; + * for example, SDL 2.0.8 knows that SSE wants 16-byte vectors + * (SDL_HasSSE()), and AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't + * know that AVX-512 wants 64. To be clear: if you can't decide to use an + * instruction set with an SDL_Has*() function, don't use that instruction + * set with memory allocated through here. + * + * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't + * out of memory. + * + * \param len The length, in bytes, of the block to allocated. The actual + * allocated block might be larger due to padding, etc. + * \return Pointer to newly-allocated block, NULL if out of memory. + * + * \sa SDL_SIMDAlignment + * \sa SDL_SIMDFree + */ +extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len); + +/** + * \brief Deallocate memory obtained from SDL_SIMDAlloc + * + * It is not valid to use this function on a pointer from anything but + * SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc, + * SDL_malloc, memalign, new[], etc. + * + * However, SDL_SIMDFree(NULL) is a legal no-op. + * + * \sa SDL_SIMDAlloc + */ +extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr); + +/* vi: set ts=4 sw=4 expandtab: */ /* Ends C function definitions when using C++ */ #ifdef __cplusplus } diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_egl.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_egl.h index d65ed437c..f50fa5c9b 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_egl.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_egl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_endian.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_endian.h index ed0bf5ba8..54d5d486d 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_endian.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_endian.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_error.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_error.h index c0e46298e..24416e693 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_error.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_error.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_events.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_events.h index af22eb646..282b9fb76 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_events.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_events.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -594,6 +594,9 @@ typedef union SDL_Event Uint8 padding[56]; } SDL_Event; +/* Make sure we haven't broken binary compatibility */ +SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == 56); + /* Function prototypes */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_filesystem.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_filesystem.h index fa6a1fa6e..6d97e5896 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_filesystem.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_filesystem.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gamecontroller.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gamecontroller.h index 6ae9c9542..ebde38715 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gamecontroller.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gamecontroller.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gesture.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gesture.h index b223d80d4..9d25e9c1d 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gesture.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_gesture.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_haptic.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_haptic.h index 2ea1bfc16..075627685 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_haptic.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_haptic.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hints.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hints.h index 4ee72e97d..8fa0dd660 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hints.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_hints.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -315,6 +315,16 @@ extern "C" { */ #define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS" +/** + * \brief A variable controlling whether mouse events should generate synthetic touch events + * + * This variable can be set to the following values: + * "0" - Mouse events will not generate touch events (default for desktop platforms) + * "1" - Mouse events will generate touch events (default for mobile platforms, such as Android and iOS) + */ + +#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS" + /** * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to true. * @@ -436,6 +446,16 @@ extern "C" { */ #define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG" +/** + * \brief A variable that lets you provide a file with extra gamecontroller db entries. + * + * The file should contain lines of gamecontroller config data, see SDL_gamecontroller.h + * + * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER) + * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping() + */ +#define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE" + /** * \brief A variable containing a list of devices to skip when scanning for game controllers. * @@ -836,19 +856,7 @@ extern "C" { */ #define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING" - /** - * \brief A variable to control whether mouse and touch events are to be treated together or separately - * - * The variable can be set to the following values: - * "0" - Mouse events will be handled as touch events, and touch will raise fake mouse - * events. This is the behaviour of SDL <= 2.0.3. (default) - * "1" - Mouse events will be handled separately from pure touch events. - * - * The value of this hint is used at runtime, so it can be changed at any time. - */ -#define SDL_HINT_ANDROID_SEPARATE_MOUSE_AND_TOUCH "SDL_ANDROID_SEPARATE_MOUSE_AND_TOUCH" - - /** +/** * \brief A variable to control whether we trap the Android back button to handle it manually. * This is necessary for the right mouse button to work on some Android devices, or * to be able to trap the back button for use in your code reliably. If set to true, @@ -865,6 +873,17 @@ extern "C" { */ #define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON" +/** + * \brief A variable to control whether the event loop will block itself when the app is paused. + * + * The variable can be set to the following values: + * "0" - Non blocking. + * "1" - Blocking. (default) + * + * The value should be set before SDL is initialized. + */ +#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE" + /** * \brief A variable to control whether the return key on the soft keyboard * should hide the soft keyboard on Android and iOS. @@ -1043,6 +1062,118 @@ extern "C" { */ #define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY" +/** + * \brief A variable controlling whether the 2D render API is compatible or efficient. + * + * This variable can be set to the following values: + * + * "0" - Don't use batching to make rendering more efficient. + * "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls. + * + * Up to SDL 2.0.9, the render API would draw immediately when requested. Now + * it batches up draw requests and sends them all to the GPU only when forced + * to (during SDL_RenderPresent, when changing render targets, by updating a + * texture that the batch needs, etc). This is significantly more efficient, + * but it can cause problems for apps that expect to render on top of the + * render API's output. As such, SDL will disable batching if a specific + * render backend is requested (since this might indicate that the app is + * planning to use the underlying graphics API directly). This hint can + * be used to explicitly request batching in this instance. It is a contract + * that you will either never use the underlying graphics API directly, or + * if you do, you will call SDL_RenderFlush() before you do so any current + * batch goes to the GPU before your work begins. Not following this contract + * will result in undefined behavior. + */ +#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING" + + +/** + * \brief A variable controlling whether SDL logs all events pushed onto its internal queue. + * + * This variable can be set to the following values: + * + * "0" - Don't log any events (default) + * "1" - Log all events except mouse and finger motion, which are pretty spammy. + * "2" - Log all events. + * + * This is generally meant to be used to debug SDL itself, but can be useful + * for application developers that need better visibility into what is going + * on in the event queue. Logged events are sent through SDL_Log(), which + * means by default they appear on stdout on most platforms or maybe + * OutputDebugString() on Windows, and can be funneled by the app with + * SDL_LogSetOutputFunction(), etc. + * + * This hint can be toggled on and off at runtime, if you only need to log + * events for a small subset of program execution. + */ +#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING" + + + +/** + * \brief Controls how the size of the RIFF chunk affects the loading of a WAVE file. + * + * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE + * file) is not always reliable. In case the size is wrong, it's possible to + * just ignore it and step through the chunks until a fixed limit is reached. + * + * Note that files that have trailing data unrelated to the WAVE file or + * corrupt files may slow down the loading process without a reliable boundary. + * By default, SDL stops after 10000 chunks to prevent wasting time. Use the + * environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value. + * + * This variable can be set to the following values: + * + * "force" - Always use the RIFF chunk size as a boundary for the chunk search + * "ignorezero" - Like "force", but a zero size searches up to 4 GiB (default) + * "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB + * "maximum" - Search for chunks until the end of file (not recommended) + */ +#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE" + +/** + * \brief Controls how a truncated WAVE file is handled. + * + * A WAVE file is considered truncated if any of the chunks are incomplete or + * the data chunk size is not a multiple of the block size. By default, SDL + * decodes until the first incomplete block, as most applications seem to do. + * + * This variable can be set to the following values: + * + * "verystrict" - Raise an error if the file is truncated + * "strict" - Like "verystrict", but the size of the RIFF chunk is ignored + * "dropframe" - Decode until the first incomplete sample frame + * "dropblock" - Decode until the first incomplete block (default) + */ +#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION" + +/** + * \brief Controls how the fact chunk affects the loading of a WAVE file. + * + * The fact chunk stores information about the number of samples of a WAVE + * file. The Standards Update from Microsoft notes that this value can be used + * to 'determine the length of the data in seconds'. This is especially useful + * for compressed formats (for which this is a mandatory chunk) if they produce + * multiple sample frames per block and truncating the block is not allowed. + * The fact chunk can exactly specify how many sample frames there should be + * in this case. + * + * Unfortunately, most application seem to ignore the fact chunk and so SDL + * ignores it by default as well. + * + * This variable can be set to the following values: + * + * "truncate" - Use the number of samples to truncate the wave data if + * the fact chunk is present and valid + * "strict" - Like "truncate", but raise an error if the fact chunk + * is invalid, not present for non-PCM formats, or if the + * data chunk doesn't have that many samples + * "ignorezero" - Like "truncate", but ignore fact chunk if the number of + * samples is zero + * "ignore" - Ignore fact chunk entirely (default) + */ +#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK" + /** * \brief An enumeration of hint priorities */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_joystick.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_joystick.h index 6e05a9c20..3a4c5d177 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_joystick.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_joystick.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keyboard.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keyboard.h index 874823171..4b2a055d8 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keyboard.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keyboard.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keycode.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keycode.h index d7d5b1dbc..3bceb418a 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keycode.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_keycode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_loadso.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_loadso.h index da56fb452..793ba5358 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_loadso.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_loadso.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_log.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_log.h index e12b65886..40f768d57 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_log.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_main.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_main.h index 98558217f..623f2d005 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_main.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_main.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -55,6 +55,10 @@ /* On iOS SDL provides a main function that creates an application delegate and starts the iOS application run loop. + If you link with SDL dynamically on iOS, the main function can't be in a + shared library, so you need to link with libSDLmain.a, which includes a + stub main function that calls into the shared library to start execution. + See src/video/uikit/SDL_uikitappdelegate.m for more details. */ #define SDL_MAIN_NEEDED @@ -82,12 +86,6 @@ #endif #endif /* SDL_MAIN_HANDLED */ -#ifdef __cplusplus -#define C_LINKAGE "C" -#else -#define C_LINKAGE -#endif /* __cplusplus */ - #ifndef SDLMAIN_DECLSPEC #define SDLMAIN_DECLSPEC #endif @@ -111,17 +109,18 @@ #define main SDL_main #endif -/** - * The prototype for the application's main() function - */ -extern C_LINKAGE SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]); - - #include "begin_code.h" #ifdef __cplusplus extern "C" { #endif +/** + * The prototype for the application's main() function + */ +typedef int (*SDL_main_func)(int argc, char *argv[]); +extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]); + + /** * This is called by the real SDL main function to let the rest of the * library know that initialization was done properly. @@ -136,8 +135,7 @@ extern DECLSPEC void SDLCALL SDL_SetMainReady(void); /** * This can be called to set the application class at startup */ -extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, - void *hInst); +extern DECLSPEC int SDLCALL SDL_RegisterApp(char *name, Uint32 style, void *hInst); extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); #endif /* __WIN32__ */ @@ -153,10 +151,24 @@ extern DECLSPEC void SDLCALL SDL_UnregisterApp(void); * \return 0 on success, -1 on failure. On failure, use SDL_GetError to retrieve more * information on the failure. */ -extern DECLSPEC int SDLCALL SDL_WinRTRunApp(int (*mainFunction)(int, char **), void * reserved); +extern DECLSPEC int SDLCALL SDL_WinRTRunApp(SDL_main_func mainFunction, void * reserved); #endif /* __WINRT__ */ +#if defined(__IPHONEOS__) + +/** + * \brief Initializes and launches an SDL application. + * + * \param argc The argc parameter from the application's main() function + * \param argv The argv parameter from the application's main() function + * \param mainFunction The SDL app's C-style main(). + * \return the return value from mainFunction + */ +extern DECLSPEC int SDLCALL SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction); + +#endif /* __IPHONEOS__ */ + #ifdef __cplusplus } diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_messagebox.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_messagebox.h index b7be59d88..e34b55477 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_messagebox.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_messagebox.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mouse.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mouse.h index d3c9f6156..277559d23 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mouse.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mouse.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mutex.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mutex.h index ba4247ced..970e78713 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mutex.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_mutex.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_name.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_name.h index ecd863f4c..690a8199b 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_name.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_name.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengl.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengl.h index 253d9c93a..6685be73e 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengl.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengl.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles.h index 18dd984b3..1e0660c3d 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles2.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles2.h index 6ccecf216..df29d3840 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles2.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_opengles2.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_pixels.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_pixels.h index 0b4364b18..dcb7a980d 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_pixels.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_pixels.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -168,7 +168,7 @@ enum ((format) && (SDL_PIXELFLAG(format) != 1)) /* Note: If you modify this list, update SDL_GetPixelFormatName() */ -enum +typedef enum { SDL_PIXELFORMAT_UNKNOWN, SDL_PIXELFORMAT_INDEX1LSB = @@ -290,7 +290,7 @@ enum SDL_DEFINE_PIXELFOURCC('N', 'V', '2', '1'), SDL_PIXELFORMAT_EXTERNAL_OES = /**< Android video texture format */ SDL_DEFINE_PIXELFOURCC('O', 'E', 'S', ' ') -}; +} SDL_PixelFormatEnum; typedef struct SDL_Color { diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_platform.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_platform.h index 7dea4ce94..c2cbc6b4e 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_platform.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_platform.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_power.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_power.h index a4fe8a935..4831cb77e 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_power.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_power.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_quit.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_quit.h index fea56a8d8..c979983cb 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_quit.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_quit.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rect.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rect.h index 543bb6186..71a411517 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rect.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rect.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -40,7 +40,7 @@ extern "C" { #endif /** - * \brief The structure that defines a point + * \brief The structure that defines a point (integer) * * \sa SDL_EnclosePoints * \sa SDL_PointInRect @@ -52,7 +52,20 @@ typedef struct SDL_Point } SDL_Point; /** - * \brief A rectangle, with the origin at the upper left. + * \brief The structure that defines a point (floating point) + * + * \sa SDL_EnclosePoints + * \sa SDL_PointInRect + */ +typedef struct SDL_FPoint +{ + float x; + float y; +} SDL_FPoint; + + +/** + * \brief A rectangle, with the origin at the upper left (integer). * * \sa SDL_RectEmpty * \sa SDL_RectEquals @@ -67,6 +80,19 @@ typedef struct SDL_Rect int w, h; } SDL_Rect; + +/** + * \brief A rectangle, with the origin at the upper left (floating point). + */ +typedef struct SDL_FRect +{ + float x; + float y; + float w; + float h; +} SDL_FRect; + + /** * \brief Returns true if point resides inside a rectangle. */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_render.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_render.h index d33619297..096b4a577 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_render.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_render.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -835,6 +835,148 @@ extern DECLSPEC int SDLCALL SDL_RenderCopyEx(SDL_Renderer * renderer, const SDL_Point *center, const SDL_RendererFlip flip); + +/** + * \brief Draw a point on the current rendering target. + * + * \param renderer The renderer which should draw a point. + * \param x The x coordinate of the point. + * \param y The y coordinate of the point. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawPointF(SDL_Renderer * renderer, + float x, float y); + +/** + * \brief Draw multiple points on the current rendering target. + * + * \param renderer The renderer which should draw multiple points. + * \param points The points to draw + * \param count The number of points to draw + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawPointsF(SDL_Renderer * renderer, + const SDL_FPoint * points, + int count); + +/** + * \brief Draw a line on the current rendering target. + * + * \param renderer The renderer which should draw a line. + * \param x1 The x coordinate of the start point. + * \param y1 The y coordinate of the start point. + * \param x2 The x coordinate of the end point. + * \param y2 The y coordinate of the end point. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawLineF(SDL_Renderer * renderer, + float x1, float y1, float x2, float y2); + +/** + * \brief Draw a series of connected lines on the current rendering target. + * + * \param renderer The renderer which should draw multiple lines. + * \param points The points along the lines + * \param count The number of points, drawing count-1 lines + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawLinesF(SDL_Renderer * renderer, + const SDL_FPoint * points, + int count); + +/** + * \brief Draw a rectangle on the current rendering target. + * + * \param renderer The renderer which should draw a rectangle. + * \param rect A pointer to the destination rectangle, or NULL to outline the entire rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawRectF(SDL_Renderer * renderer, + const SDL_FRect * rect); + +/** + * \brief Draw some number of rectangles on the current rendering target. + * + * \param renderer The renderer which should draw multiple rectangles. + * \param rects A pointer to an array of destination rectangles. + * \param count The number of rectangles. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderDrawRectsF(SDL_Renderer * renderer, + const SDL_FRect * rects, + int count); + +/** + * \brief Fill a rectangle on the current rendering target with the drawing color. + * + * \param renderer The renderer which should fill a rectangle. + * \param rect A pointer to the destination rectangle, or NULL for the entire + * rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderFillRectF(SDL_Renderer * renderer, + const SDL_FRect * rect); + +/** + * \brief Fill some number of rectangles on the current rendering target with the drawing color. + * + * \param renderer The renderer which should fill multiple rectangles. + * \param rects A pointer to an array of destination rectangles. + * \param count The number of rectangles. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderFillRectsF(SDL_Renderer * renderer, + const SDL_FRect * rects, + int count); + +/** + * \brief Copy a portion of the texture to the current rendering target. + * + * \param renderer The renderer which should copy parts of a texture. + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire + * texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the + * entire rendering target. + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyF(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_FRect * dstrect); + +/** + * \brief Copy a portion of the source texture to the current rendering target, rotating it by angle around the given center + * + * \param renderer The renderer which should copy parts of a texture. + * \param texture The source texture. + * \param srcrect A pointer to the source rectangle, or NULL for the entire + * texture. + * \param dstrect A pointer to the destination rectangle, or NULL for the + * entire rendering target. + * \param angle An angle in degrees that indicates the rotation that will be applied to dstrect, rotating it in a clockwise direction + * \param center A pointer to a point indicating the point around which dstrect will be rotated (if NULL, rotation will be done around dstrect.w/2, dstrect.h/2). + * \param flip An SDL_RendererFlip value stating which flipping actions should be performed on the texture + * + * \return 0 on success, or -1 on error + */ +extern DECLSPEC int SDLCALL SDL_RenderCopyExF(SDL_Renderer * renderer, + SDL_Texture * texture, + const SDL_Rect * srcrect, + const SDL_FRect * dstrect, + const double angle, + const SDL_FPoint *center, + const SDL_RendererFlip flip); + /** * \brief Read pixels from the current rendering target. * @@ -876,6 +1018,31 @@ extern DECLSPEC void SDLCALL SDL_DestroyTexture(SDL_Texture * texture); */ extern DECLSPEC void SDLCALL SDL_DestroyRenderer(SDL_Renderer * renderer); +/** + * \brief Force the rendering context to flush any pending commands to the + * underlying rendering API. + * + * You do not need to (and in fact, shouldn't) call this function unless + * you are planning to call into OpenGL/Direct3D/Metal/whatever directly + * in addition to using an SDL_Renderer. + * + * This is for a very-specific case: if you are using SDL's render API, + * you asked for a specific renderer backend (OpenGL, Direct3D, etc), + * you set SDL_HINT_RENDER_BATCHING to "1", and you plan to make + * OpenGL/D3D/whatever calls in addition to SDL render API calls. If all of + * this applies, you should call SDL_RenderFlush() between calls to SDL's + * render API and the low-level API you're using in cooperation. + * + * In all other cases, you can ignore this function. This is only here to + * get maximum performance out of a specific situation. In all other cases, + * SDL will do the right thing, perhaps at a performance loss. + * + * This function is first available in SDL 2.0.10, and is not needed in + * 2.0.9 and earlier, as earlier versions did not queue rendering commands + * at all, instead flushing them to the OS immediately. + */ +extern DECLSPEC int SDLCALL SDL_RenderFlush(SDL_Renderer * renderer); + /** * \brief Bind the texture to the current OpenGL/ES/ES2 context for use with diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_revision.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_revision.h index 92fbe67b1..3b3fc85ea 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_revision.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_revision.h @@ -1,2 +1,2 @@ -#define SDL_REVISION "hg-12373:8feb5da6f2fb" -#define SDL_REVISION_NUMBER 12373 +#define SDL_REVISION "hg-12952:bc90ce38f1e2" +#define SDL_REVISION_NUMBER 12952 diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rwops.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rwops.h index 0960699d4..f66119fb0 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rwops.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_rwops.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -176,19 +176,48 @@ extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area); #define RW_SEEK_END 2 /**< Seek relative to the end of data */ /** - * \name Read/write macros - * - * Macros to easily read and write from an SDL_RWops structure. + * Return the size of the file in this rwops, or -1 if unknown */ -/* @{ */ -#define SDL_RWsize(ctx) (ctx)->size(ctx) -#define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence) -#define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, RW_SEEK_CUR) -#define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n) -#define SDL_RWwrite(ctx, ptr, size, n) (ctx)->write(ctx, ptr, size, n) -#define SDL_RWclose(ctx) (ctx)->close(ctx) -/* @} *//* Read/write macros */ +extern DECLSPEC Sint64 SDLCALL SDL_RWsize(SDL_RWops *context); +/** + * Seek to \c offset relative to \c whence, one of stdio's whence values: + * RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END + * + * \return the final offset in the data stream, or -1 on error. + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWseek(SDL_RWops *context, + Sint64 offset, int whence); + +/** + * Return the current offset in the data stream, or -1 on error. + */ +extern DECLSPEC Sint64 SDLCALL SDL_RWtell(SDL_RWops *context); + +/** + * Read up to \c maxnum objects each of size \c size from the data + * stream to the area pointed at by \c ptr. + * + * \return the number of objects read, or 0 at error or end of file. + */ +extern DECLSPEC size_t SDLCALL SDL_RWread(SDL_RWops *context, + void *ptr, size_t size, size_t maxnum); + +/** + * Write exactly \c num objects each of size \c size from the area + * pointed at by \c ptr to data stream. + * + * \return the number of objects written, or 0 at error or end of file. + */ +extern DECLSPEC size_t SDLCALL SDL_RWwrite(SDL_RWops *context, + const void *ptr, size_t size, size_t num); + +/** + * Close and free an allocated SDL_RWops structure. + * + * \return 0 if successful or -1 on write error when flushing data. + */ +extern DECLSPEC int SDLCALL SDL_RWclose(SDL_RWops *context); /** * Load all the data from an SDL data stream. @@ -209,9 +238,17 @@ extern DECLSPEC void *SDLCALL SDL_LoadFile_RW(SDL_RWops * src, size_t *datasize, /** * Load an entire file. * - * Convenience macro. + * The data is allocated with a zero byte at the end (null terminated) + * + * If \c datasize is not NULL, it is filled with the size of the data read. + * + * If \c freesrc is non-zero, the stream will be closed after being read. + * + * The data should be freed with SDL_free(). + * + * \return the data, or NULL if there was an error. */ -#define SDL_LoadFile(file, datasize) SDL_LoadFile_RW(SDL_RWFromFile(file, "rb"), datasize, 1) +extern DECLSPEC void *SDLCALL SDL_LoadFile(const char *file, size_t *datasize); /** * \name Read endian functions diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_scancode.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_scancode.h index 63871aa3b..a50305f55 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_scancode.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_scancode.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -38,7 +38,7 @@ * SDL_Event structure. * * The values in this enumeration are based on the USB usage page standard: - * http://www.usb.org/developers/hidpage/Hut1_12v2.pdf + * https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf */ typedef enum { diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_sensor.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_sensor.h index ac163a8cd..966adbf21 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_sensor.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_sensor.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -26,8 +26,8 @@ * */ -#ifndef _SDL_sensor_h -#define _SDL_sensor_h +#ifndef SDL_sensor_h_ +#define SDL_sensor_h_ #include "SDL_stdinc.h" #include "SDL_error.h" @@ -246,6 +246,6 @@ extern DECLSPEC void SDLCALL SDL_SensorUpdate(void); #endif #include "close_code.h" -#endif /* _SDL_sensor_h */ +#endif /* SDL_sensor_h_ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_shape.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_shape.h index 40a6baaae..2ab43fcdc 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_shape.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_shape.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_stdinc.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_stdinc.h index e373bc380..28bb7b961 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_stdinc.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_stdinc.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_surface.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_surface.h index 730d49fc8..51a128300 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_surface.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_surface.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -53,6 +53,7 @@ extern "C" { #define SDL_PREALLOC 0x00000001 /**< Surface uses preallocated memory */ #define SDL_RLEACCEL 0x00000002 /**< Surface is RLE encoded */ #define SDL_DONTFREE 0x00000004 /**< Surface is referenced internally */ +#define SDL_SIMD_ALIGNED 0x00000008 /**< Surface uses aligned memory */ /* @} *//* Surface flags */ /** diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_system.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_system.h index 4dc372d6b..3b0840769 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_system.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_system.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_syswm.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_syswm.h index f1c4021cc..7aa8c6869 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_syswm.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_syswm.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -34,16 +34,16 @@ #include "SDL_version.h" /** - * \file SDL_syswm.h + * \brief SDL_syswm.h * * Your application has access to a special type of event ::SDL_SYSWMEVENT, * which contains window-manager specific information and arrives whenever * an unhandled window event occurs. This event is ignored by default, but * you can enable it with SDL_EventState(). */ -#ifdef SDL_PROTOTYPES_ONLY struct SDL_SysWMinfo; -#else + +#if !defined(SDL_PROTOTYPES_ONLY) #if defined(SDL_VIDEO_DRIVER_WINDOWS) #ifndef WIN32_LEAN_AND_MEAN @@ -103,6 +103,8 @@ typedef void *EGLSurface; #if defined(SDL_VIDEO_DRIVER_VIVANTE) #include "SDL_egl.h" #endif +#endif /* SDL_PROTOTYPES_ONLY */ + #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ @@ -110,6 +112,7 @@ typedef void *EGLSurface; extern "C" { #endif +#if !defined(SDL_PROTOTYPES_ONLY) /** * These are the various supported windowing subsystems */ @@ -122,7 +125,7 @@ typedef enum SDL_SYSWM_COCOA, SDL_SYSWM_UIKIT, SDL_SYSWM_WAYLAND, - SDL_SYSWM_MIR, + SDL_SYSWM_MIR, /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ SDL_SYSWM_WINRT, SDL_SYSWM_ANDROID, SDL_SYSWM_VIVANTE, @@ -257,11 +260,11 @@ struct SDL_SysWMinfo struct wl_shell_surface *shell_surface; /**< Wayland shell_surface (window manager handle) */ } wl; #endif -#if defined(SDL_VIDEO_DRIVER_MIR) +#if defined(SDL_VIDEO_DRIVER_MIR) /* no longer available, left for API/ABI compatibility. Remove in 2.1! */ struct { - struct MirConnection *connection; /**< Mir display server connection */ - struct MirSurface *surface; /**< Mir surface */ + void *connection; /**< Mir display server connection */ + void *surface; /**< Mir surface */ } mir; #endif diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test.h index 6cc373bf8..17a33dc2c 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_assert.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_assert.h index 1788d7a20..b3ebb62fb 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_assert.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_assert.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_common.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_common.h index be2e6b2aa..c34d0d103 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_common.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_common.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -140,14 +140,20 @@ SDLTest_CommonState *SDLTest_CommonCreateState(char **argv, Uint32 flags); */ int SDLTest_CommonArg(SDLTest_CommonState * state, int index); + /** - * \brief Returns common usage information + * \brief Logs command line usage info. * - * \param state The common state describing the test window to create. + * This logs the appropriate command line options for the subsystems in use + * plus other common options, and then any application-specific options. + * This uses the SDL_Log() function and splits up output to be friendly to + * 80-character-wide terminals. * - * \returns String with usage information + * \param state The common state describing the test window for the app. + * \param argv0 argv[0], as passed to main/SDL_main. + * \param options an array of strings for application specific options. The last element of the array should be NULL. */ -const char *SDLTest_CommonUsage(SDLTest_CommonState * state); +void SDLTest_CommonLogUsage(SDLTest_CommonState * state, const char *argv0, const char **options); /** * \brief Open test window. @@ -158,6 +164,17 @@ const char *SDLTest_CommonUsage(SDLTest_CommonState * state); */ SDL_bool SDLTest_CommonInit(SDLTest_CommonState * state); +/** + * \brief Easy argument handling when test app doesn't need any custom args. + * + * \param state The common state describing the test window to create. + * \param argc argc, as supplied to SDL_main + * \param argv argv, as supplied to SDL_main + * + * \returns False if app should quit, true otherwise. + */ +SDL_bool SDLTest_CommonDefaultArgs(SDLTest_CommonState * state, const int argc, char **argv); + /** * \brief Common event handler for test windows. * diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_compare.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_compare.h index c22e447d8..1f751c8b9 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_compare.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_compare.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_crc32.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_crc32.h index 3d235d074..e615d8929 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_crc32.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_crc32.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_font.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_font.h index 59cbdcad6..8fa078440 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_font.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_font.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_fuzzer.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_fuzzer.h index 8fcb9ebbf..7259685a9 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_fuzzer.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_fuzzer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_harness.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_harness.h index 8641e0a7e..f5ae92ceb 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_harness.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_harness.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_images.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_images.h index 9c4dd5b82..b8934812f 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_images.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_images.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_log.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_log.h index ebd44fb50..01d0fedac 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_log.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_log.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_md5.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_md5.h index 0e4105768..2bfd7dff9 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_md5.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_md5.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_memory.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_memory.h index 4827ae6f2..5d4d39ea5 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_memory.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_memory.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -42,14 +42,14 @@ extern "C" { * * \note This should be called before any other SDL functions for complete tracking coverage */ -int SDLTest_TrackAllocations(); +int SDLTest_TrackAllocations(void); /** * \brief Print a log of any outstanding allocations * * \note This can be called after SDL_Quit() */ -void SDLTest_LogAllocations(); +void SDLTest_LogAllocations(void); /* Ends C function definitions when using C++ */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_random.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_random.h index 0eb414ff2..71e9c70b6 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_random.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_test_random.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_thread.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_thread.h index 554dd0b61..f78b1145d 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_thread.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_thread.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_timer.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_timer.h index 5600618ff..2a47b043a 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_timer.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_timer.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_touch.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_touch.h index f4075e79a..99dbcb8c3 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_touch.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_touch.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -41,6 +41,14 @@ extern "C" { typedef Sint64 SDL_TouchID; typedef Sint64 SDL_FingerID; +typedef enum +{ + SDL_TOUCH_DEVICE_INVALID = -1, + SDL_TOUCH_DEVICE_DIRECT, /* touch screen with window-relative coordinates */ + SDL_TOUCH_DEVICE_INDIRECT_ABSOLUTE, /* trackpad with absolute device coordinates */ + SDL_TOUCH_DEVICE_INDIRECT_RELATIVE /* trackpad with screen cursor-relative coordinates */ +} SDL_TouchDeviceType; + typedef struct SDL_Finger { SDL_FingerID id; @@ -52,6 +60,9 @@ typedef struct SDL_Finger /* Used as the device ID for mouse events simulated with touch input */ #define SDL_TOUCH_MOUSEID ((Uint32)-1) +/* Used as the SDL_TouchID for touch events simulated with mouse input */ +#define SDL_MOUSE_TOUCHID ((Sint64)-1) + /* Function prototypes */ @@ -65,6 +76,11 @@ extern DECLSPEC int SDLCALL SDL_GetNumTouchDevices(void); */ extern DECLSPEC SDL_TouchID SDLCALL SDL_GetTouchDevice(int index); +/** + * \brief Get the type of the given touch device. + */ +extern DECLSPEC SDL_TouchDeviceType SDLCALL SDL_GetTouchDeviceType(SDL_TouchID touchID); + /** * \brief Get the number of active fingers for a given touch device. */ diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_types.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_types.h index 4ac248c8c..9c3e9896f 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_types.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_types.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_version.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_version.h index 31443e149..6c7499d32 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_version.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_version.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -59,7 +59,7 @@ typedef struct SDL_version */ #define SDL_MAJOR_VERSION 2 #define SDL_MINOR_VERSION 0 -#define SDL_PATCHLEVEL 9 +#define SDL_PATCHLEVEL 10 /** * \brief Macro to determine SDL version program was compiled against. diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_video.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_video.h index 461f13805..352afd436 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_video.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_video.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga 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/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_vulkan.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_vulkan.h index 972cca4d7..d69a436b3 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_vulkan.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/SDL_vulkan.h @@ -98,8 +98,8 @@ typedef VkSurfaceKHR SDL_vulkanSurface; /* for compatibility with Tizen */ * applications to link with libvulkan (and historically MoltenVK was * provided as a static library). If it is not found then, on macOS, SDL * will attempt to load \c vulkan.framework/vulkan, \c libvulkan.1.dylib, - * \c MoltenVK.framework/MoltenVK and \c libMoltenVK.dylib in that order. - * On iOS SDL will attempt to load \c libMoltenVK.dylib. Applications + * followed by \c libvulkan.dylib, in that order. + * On iOS SDL will attempt to load \c libvulkan.dylib only. Applications * using a dynamic framework or .dylib must ensure it is included in its * application bundle. * @@ -153,7 +153,7 @@ extern DECLSPEC void SDLCALL SDL_Vulkan_UnloadLibrary(void); * is smaller than the number of required extensions, \c SDL_FALSE will be * returned instead of \c SDL_TRUE, to indicate that not all the required * extensions were returned. - * + * * \note If \c window is not NULL, it will be checked against its creation * flags to ensure that the Vulkan flag is present. This parameter * will be removed in a future major release. diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/begin_code.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/begin_code.h index 6c2106246..22c997c41 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/begin_code.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/begin_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -105,6 +105,9 @@ #ifdef _MSC_VER #pragma warning(disable: 4103) #endif +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wpragma-pack" +#endif #ifdef __BORLANDC__ #pragma nopackwarning #endif diff --git a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/close_code.h b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/close_code.h index b3b70a4c8..8e4cac3da 100644 --- a/libs/SDL2/x86_64-w64-mingw32/include/SDL2/close_code.h +++ b/libs/SDL2/x86_64-w64-mingw32/include/SDL2/close_code.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -26,6 +26,9 @@ * after you finish any function and structure declarations in your headers */ +#ifndef _begin_code_h +#error close_code.h included without matching begin_code.h +#endif #undef _begin_code_h /* Reset structure packing at previous byte alignment */ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.a b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.a index 827950682..1a0479ba2 100644 Binary files a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.a and b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.a differ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.dll.a b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.dll.a index 669b6a637..f5d4d2bbb 100755 Binary files a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.dll.a and b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.dll.a differ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.la b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.la index d5295eec8..f6f05ab4c 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.la +++ b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2.la @@ -23,8 +23,8 @@ dependency_libs=' -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 - weak_library_names='' # Version information for libSDL2. -current=9 -age=9 +current=10 +age=10 revision=0 # Is this an already installed library? @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL/SDL2-2.0.9/x86_64-w64-mingw32/lib' +libdir='/Users/valve/release/SDL/SDL2-2.0.10/x86_64-w64-mingw32/lib' diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.a b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.a index fcbdbbf76..7ac4da628 100644 Binary files a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.a and b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.a differ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.la b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.la index 76ad43f0f..e7a7872ea 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.la +++ b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2_test.la @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL/SDL2-2.0.9/x86_64-w64-mingw32/lib' +libdir='/Users/valve/release/SDL/SDL2-2.0.10/x86_64-w64-mingw32/lib' diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.a b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.a index 3a26e430d..ea1086e49 100644 Binary files a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.a and b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.a differ diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.la b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.la index 5aa469333..583786205 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.la +++ b/libs/SDL2/x86_64-w64-mingw32/lib/libSDL2main.la @@ -38,4 +38,4 @@ dlopen='' dlpreopen='' # Directory that this library needs to be installed in: -libdir='/Users/valve/release/SDL/SDL2-2.0.9/x86_64-w64-mingw32/lib' +libdir='/Users/valve/release/SDL/SDL2-2.0.10/x86_64-w64-mingw32/lib' diff --git a/libs/SDL2/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc b/libs/SDL2/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc index ae83be160..ceb157f25 100644 --- a/libs/SDL2/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc +++ b/libs/SDL2/x86_64-w64-mingw32/lib/pkgconfig/sdl2.pc @@ -7,9 +7,9 @@ includedir=${prefix}/include Name: sdl2 Description: Simple DirectMedia Layer is a cross-platform multimedia library designed to provide low level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL, and 2D video framebuffer. -Version: 2.0.9 +Version: 2.0.10 Requires: Conflicts: Libs: -L${libdir} -lmingw32 -lSDL2main -lSDL2 -mwindows -Libs.private: -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -static-libgcc +Libs.private: -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,--no-undefined -Wl,--dynamicbase -Wl,--nxcompat -Wl,--high-entropy-va -lm -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -static-libgcc Cflags: -I${includedir}/SDL2 -Dmain=SDL_main diff --git a/libs/SDL2/x86_64-w64-mingw32/share/aclocal/sdl2.m4 b/libs/SDL2/x86_64-w64-mingw32/share/aclocal/sdl2.m4 index b915f99ed..0a73bc7d4 100644 --- a/libs/SDL2/x86_64-w64-mingw32/share/aclocal/sdl2.m4 +++ b/libs/SDL2/x86_64-w64-mingw32/share/aclocal/sdl2.m4 @@ -74,7 +74,7 @@ AC_ARG_VAR(SDL2_FRAMEWORK, [Path to SDL2.framework]) done fi - if test -d $sdl_framework; then + if test x"$sdl_framework" != x && test -d "$sdl_framework"; then AC_MSG_RESULT($sdl_framework) sdl_framework_dir=`dirname $sdl_framework` SDL_CFLAGS="-F$sdl_framework_dir -Wl,-framework,SDL2 -I$sdl_framework/include" diff --git a/libs/SDLMixerX/CHANGES.X.txt b/libs/SDLMixerX/CHANGES.X.txt new file mode 100644 index 000000000..17b43d9af --- /dev/null +++ b/libs/SDLMixerX/CHANGES.X.txt @@ -0,0 +1,48 @@ +2.1.0: +Vitaly Novichkov - Sat, Jan 20, 2018 18:06:00 + * SDL Mixer X has been re-created from original again as official SDL Mixer had a big and incompatible rework + * Custom resampler is no more needed as SDL2 now finally uses new better resampler + * Added CMake build + * Added an ability to toggle MIDI playing libraries (NativeMidi, Timidity or FluidSynth) + * Added a full seekability with "tell" and "length" commands + * Added a basic support for Meta-Tags to show Title, Artist, Album and Copyright captured from music files. + * Added an extra arguments in music path string to support song individual settings per some codecs (for example, play different MIDI files with different MIDI playing libraries) + * Timidity: Added ability to set a config search pach, for example, inside of application directory API. + * Added OPNMIDI MIDI sequencer based on YM2612 chip emulation. Includes a complete General-MIDI embedded bank. + * Added functions to use custom bank files for ADL/OPN-MIDI sequencers (WOPL for ADLMIDI and WOPN for OPNMIDI) + * WAVE: Added support for PCM24, PCM32, Float32, Float64m, ALAW, and MULAW sample formats, + * AIFF: Added support for AIFF-C, also support for PCM24, PCM32, Float32, Float64, ALAW, and MULAW formats + * WAVE & AIFF: Added full seekability support (seek, tell, length) + * MP3: More accurate MP3 file detection as some weird MP3 files are can't be detected by existing code; Added usage lf libID3tag library to fetch ID3 tags and also detect begin offset inside of MP3 files as some MP3 files are causing libMAD play ID3 data as actual encoded sound data that causes weird playback and later crash. To avoid this, ID3 parse is needed to detect actual begin of audio data. + * Fixed: SMPEG: Fix a broken build + * Fixed: OGG: Fixed support for pre-defined count of loops when loop tags are presented + * Warning fixes + * Some C90 compatibility fixes + * Internally: Added MIX_UNUSED() macro to mute warnings on various compilers + +1.0.3: +Vitaly Novichkov - 2016 + * Implemented own resampler to don't use buggy SDL Audio's resampler + * Added support of path arguments to allow dynamic configuring of GME and MIDI playing per every file + * ModPlug now is part of SDL Mixer X in same project + * Link all dependent libraries (libOGG, libVorbis, libFLAC, libMAD) statically + +1.0.2: +Vitaly Novichkov - 2015 + * Added ADLMIDI MIDI sequencer which is completely independent MIDI sequencer which requires no extra bank files to play MIDI. + * Added ability to dynamically switch MIDI device (ADLMIDI, Timidity, Native MIDI, FluidSynth) + * Added meta-tag getting functions: Mix_GetMusicTitle, Mix_GetMusicTitleTag, Mix_GetMusicArtistTag, Mix_GetMusicAlbumTag, Mix_GetMusicCopyrightTag. + * Added ability to build VB6-Compatible version to use it as standalone audio library + +1.0.1: +Vitaly Novichkov - 2015 + * Added GME library to support many game music formats + * Added support of loop tags for OGG Vorbis files (based on vorbis comments "LOOPSTART" and "LOOPEND" (also supported "LOOPLENGTH" for RPG-Maker compatibility)) + * Added MIX_Timidity_addToPathList(const char *path) to customize Timidity path + +1.0.0: +Vitaly Novichkov - 2015 + * Added support of SPC playback + * Attempt to fix resampling + * Using QMake instead of autotools to build library + diff --git a/libs/SDLMixerX/CHANGES.txt b/libs/SDLMixerX/CHANGES.txt new file mode 100644 index 000000000..50c0fee0b --- /dev/null +++ b/libs/SDLMixerX/CHANGES.txt @@ -0,0 +1,184 @@ +2.0.3: +Sam Lantinga - Thu, Mar 1, 2018 9:06:58 AM + * Fixed regression where Mix_Init() would return 0 for available music formats + +2.0.2: +Sam Lantinga - Fri Oct 20 22:04:50 PDT 2017 + * Implemented 24-bit and surround sound support for FLAC audio files +Sam Lantinga - Thu Oct 12 21:32:44 PDT 2017 + * Updated external libraries flac-1.3.2, libmodplug-0.8.9.0, libogg-1.3.2 and libvorbis-1.3.5 +Ryan Gordon - Thu Oct 12 21:29:59 PDT 2017 + * Updated for SDL 2.0.6 and newer +Franc[e]sco - Thu Jul 20 22:03:19 2017 +0200 + * Added support for MP3 playback using mpg123 +David Ludwig - Sun Apr 10 22:35:38 2016 + * Added support for UWP / Windows 10 apps +Juha Kuikka - Fri Jan 29 12:44:01 PST 2016 + * Added Mix_OpenAudioDevice() so you can specify the audio device to open + +2.0.1: +Sam Lantinga - Tue Jul 7 11:40:33 PDT 2015 + * Added support for 'smpl' format loop points in music WAV files +Sam Lantinga - Sat Aug 23 10:57:26 2014 + * Fixed floating point exception in Mix_Volume() +David Ludwig - Mon Apr 14 22:15:36 2014 + * Added support for building for Windows RT and Windows Phone +Isaac Burns - Sun Sep 15 21:50:27 PDT 2013 + * Added support for loading MP3 files as sound chunks + +2.0.0: +Sam Lantinga - Sun Jun 9 14:45:30 PDT 2013 + * Made libmodplug the default MOD player as it is now in the public domain +Sam Lantinga - Sat Jun 1 19:11:08 PDT 2013 + * Updated for SDL 2.0 release + * SDL_LoadMUS_RW() now takes an argument telling whether or not the data source should be freed when done. + +1.2.13: +Paul P Komkoff Jr - Sun Jul 22 16:12:28 PDT 2012 + * Fixed malloc/free mismatch in the MikMod driver + +1.2.12: +Sam Lantinga - Sat Jan 14 22:00:29 2012 -0500 + * Fixed seek offset with SMPEG (was relative, should be absolute) +Sam Lantinga - Fri Jan 13 03:04:27 EST 2012 + * Fixed memory crash loading Ogg Vorbis files on Windows +Sam Lantinga - Thu Jan 05 22:51:54 2012 -0500 + * Added an Xcode project for iOS +Nikos Chantziaras - 2012-01-02 17:37:36 PST + * Added Mix_LoadMUSType_RW() so you can tell SDL_mixer what type the music is +Sam Lantinga - Sun Jan 01 16:45:58 2012 -0500 + * Fixed looping native MIDI on Mac OS X and Windows +Sam Lantinga - Sun Jan 01 01:00:51 2012 -0500 + * Added /usr/local/share/timidity to the timidity data path +Sam Lantinga - Sat Dec 31 21:26:46 2011 -0500 + * Fixed timidity loading of some MIDI files +Sam Lantinga - Sat Dec 31 19:11:59 EST 2011 + * Fixed dropping audio in the FLAC audio decoding +Sam Lantinga - Sat Dec 31 18:32:05 EST 2011 + * Fixed memory leak in SDL_LoadMUS() +Sam Lantinga - Sat Dec 31 10:22:05 EST 2011 + * Removed GPL native MIDI code for new licensing +Sam Lantinga - Sat Dec 31 10:22:05 EST 2011 + * SDL_mixer is now under the zlib license +Manuel Montezelo - 2011-12-28 11:42:44 PST + * Fixed drums playing on MIDI channel 16 with timidity +Ryan C. Gordon - Wed Jun 15 03:41:31 2011 -0400 + * The music-finished hook can start a track immediately +James Le Cuirot - Mon Mar 21 16:54:11 PDT 2011 + * Added support for FluidSynth +Egor Suvorov - Tue Jan 18 11:06:47 PST 2011 + * Added support for native MIDI on Haiku +Sam Lantinga - Tue Jan 11 01:29:19 2011 -0800 + * Added Android.mk to build on the Android platform +Jon Atkins - Sat Nov 14 13:00:18 PST 2009 + * Added support for libmodplug (disabled by default) + +1.2.11: +Sam Lantinga - Sat Nov 14 12:38:01 PST 2009 + * Fixed initialization error and crashes if MikMod library isn't available +Sam Lantinga - Sat Nov 14 11:22:14 PST 2009 + * Fixed bug loading multiple music files + +1.2.10: +Sam Lantinga - Sun Nov 8 08:34:48 PST 2009 + * Added Mix_Init()/Mix_Quit() to prevent constantly loading and unloading DLLs +Mike Frysinger - 2009-11-05 09:11:43 PST + * Check for fork/vfork on any platform, don't just assume it on UNIX +Jon Atkins - Thu Nov 5 00:02:50 2009 UTC + * Fixed export of Mix_GetNumChunkDecoders() and Mix_GetNumMusicDecoders() +C.W. Betts - 2009-11-02 00:16:21 PST + * Use newer MIDI API on Mac OS X 10.5+ + +1.2.9: +Ryan Gordon - Sun Oct 18 11:42:31 PDT 2009 + * Updated native MIDI support on Mac OS X for 10.6 +Ryan Gordon - Sun Oct 11 05:29:55 2009 UTC + * Reset channel volumes after a fade out interrupts a fade in. +Ryan Gordon - Sun Oct 11 02:59:12 2009 UTC + * Fixed crash race condition with position audio functions +Ryan Gordon - Sat Oct 10 17:05:45 2009 UTC + * Fixed stereo panning in 8-bit mode +Sam Lantinga - Sat Oct 10 11:07:15 2009 UTC + * Added /usr/share/timidity to the default timidity.cfg locations +Sam Lantinga - Sat Oct 3 13:33:36 PDT 2009 + * MOD support uses libmikmod and is dynamically loaded by default + * A patched version of libmikmod is included in libmikmod-3.1.12.zip + * The libmikmod patches fix security issues CVE-2007-6720 and CVE-2009-0179. +Sam Lantinga - Sat Oct 3 02:49:41 PDT 2009 + * Added TIMIDITY_CFG environment variable to fully locate timidity.cfg +Sam Lantinga - Fri Oct 2 07:15:35 PDT 2009 + * Implemented seamless looping for music playback +Forrest Voight - 2009-06-13 20:31:38 PDT + * ID3 files are now recognized as MP3 format +Steven Noonan - 2008-05-13 13:31:36 PDT + * Fixed native MIDI crash on 64-bit Windows +Ryan Gordon - Fri Jun 5 16:07:08 2009 UTC + * Added decoder enumeration API: + Mix_GetNumChunkDecoders(), Mix_GetChunkDecoder(), + Mix_GetNumMusicDecoders(), Mix_GetMusicDecoder() +Austen Dicken - Tue Feb 26 23:28:27 PST 2008 + * Added support for FLAC audio both as chunks and streaming +Tilman Sauerbeck - Tue Feb 26 03:44:47 PST 2008 + * Added support for streaming WAV files with Mix_LoadMUS_RW() +Ryan Gordon - Mon Feb 4 17:10:08 UTC 2008 + * Fixed crash caused by not resetting position_channels + +1.2.8: +Sam Lantinga - Wed Jul 18 09:45:54 PDT 2007 + * Improved detection of Ogg Vorbis and Tremor libraries +Ryan Gordon - Sun Jul 15 12:03:54 EDT 2007 + * Fixed memory leaks in Effects API. +David Rose - Sat Jul 14 22:16:09 PDT 2007 + * Added support for MP3 playback with libmad (for GPL projects only!) +Sam Lantinga - Sat Jul 14 21:39:30 PDT 2007 + * Fixed the final loop of audio samples of a certain size +Sam Lantinga - Sat Jul 14 21:05:09 PDT 2007 + * Fixed opening Ogg Vorbis files using different C runtimes on Windows +Philippe Simons - Sat Jul 14 20:33:17 PDT 2007 + * Added support for Ogg Vorbis playback with Tremor (an integer decoder) +Sam Lantinga - Sat Jul 14 07:02:09 PDT 2007 + * Fixed memory corruption in timidity resampling code +Ryan Gordon - Tue Jul 3 10:44:29 2007 UTC + * Fixed building SDL_mixer with SDL 1.3 pre-release +Ryan Gordon - Tue Feb 13 08:11:54 2007 UTC + * Fixed compiling both timidity and native midi in the same build +Hans de Goede - Sun Aug 20 23:25:46 2006 UTC + * Added volume control to playmus +Jonathan Atkins - Thu Aug 10 15:06:40 2006 UTC + * Fixed linking with system libmikmod +David Ergo - Fri Jun 23 09:07:19 2006 UTC + * Corrected no-op conditions in SetDistance(), SetPanning() and SetPosition() + * Fixed copy/paste errors in channel amplitudes + +1.2.7: +Sam Lantinga - Fri May 12 00:04:32 PDT 2006 + * Added support for dynamically loading SMPEG library +Sam Lantinga - Thu May 11 22:22:43 PDT 2006 + * Added support for dynamically loading Ogg Vorbis library +Sam Lantinga - Sun Apr 30 09:01:44 PDT 2006 + * Removed automake dependency, to allow Universal binaries on Mac OS X + * Added gcc-fat.sh for generating Universal binaries on Mac OS X +Sam Lantinga - Sun Apr 30 01:48:40 PDT 2006 + * Updated libtool support to version 1.5.22 +Patrice Mandin - Sat Jul 16 16:43:24 UTC 2005 + * Use SDL_RWops also for native midi mac and win32 +Patrice Mandin - Sat Jul 9 14:40:09 UTC 2005 + * Use SDL_RWops also for native midi gpl (todo: mac and win32) +Ryan C. Gordon - Sat Jul 9 01:54:03 EDT 2005 + * Tweaked Mix_Chunk's definition to make predeclaration easier. +Patrice Mandin - Mon Jul 4 19:45:40 UTC 2005 + * Search timidity.cfg also in /etc + * Fix memory leaks in timidity player + * Use also SDL_RWops to read midifiles for timidity +Ryan C. Gordon - Mon Jun 13 18:18:12 EDT 2005 + * Patch from Eric Wing to fix native midi compiling on MacOS/x86. +Sam Lantinga - Wed Dec 22 17:14:32 PST 2004 + * Disabled support for the system version of libmikmod by default +Sam Lantinga - Tue Dec 21 09:51:29 PST 2004 + * Fixed building mikmod support on UNIX + * Always build SDL_RWops music support + * Added SDL_RWops support for reading MP3 files + +1.2.6: +Jonathan Atkins - Wed, 15 Sep 2004 23:26:42 -0500 + * Added support for using the system version of libmikmod diff --git a/libs/SDLMixerX/CMakeLists.txt b/libs/SDLMixerX/CMakeLists.txt new file mode 100644 index 000000000..af55b0265 --- /dev/null +++ b/libs/SDLMixerX/CMakeLists.txt @@ -0,0 +1,818 @@ +cmake_minimum_required (VERSION 2.8.11) +project(SDLMixerX C) + +include(FindPkgConfig) +include(CheckIncludeFiles) +include(CheckFunctionExists) +include(CheckLibraryExists) +#include(CheckCSourceRuns) +#include(CheckCCompilerFlag) + +if(NOT CMAKE_VERSION VERSION_LESS 2.8.12) + set(CMAKE_MACOSX_RPATH 0) +endif() + +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE) + message("== Using default build configuration which is a Release!") +endif() + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + set(MIX_DEBUG_SUFFIX "d") +else() + set(MIX_DEBUG_SUFFIX "") +endif() + +if(WIN32) + set(CMAKE_SHARED_LIBRARY_PREFIX "") +endif() + +if(POLICY CMP0058) + cmake_policy(SET CMP0058 NEW) +endif() + +option(SSEMATH "Allow GCC to use SSE floating point math" ${OPT_DEF_SSEMATH}) +option(MMX "Use MMX assembly routines" ${OPT_DEF_ASM}) +option(3DNOW "Use 3Dnow! MMX assembly routines" ${OPT_DEF_ASM}) +option(SSE "Use SSE assembly routines" ${OPT_DEF_ASM}) +option(SSE2 "Use SSE2 assembly routines" ${OPT_DEF_SSEMATH}) +option(SSE3 "Use SSE3 assembly routines" ${OPT_DEF_SSEMATH}) + +# Settings +option(SDL_MIXER_X_STATIC "Build static library of SDL Mixer X" ON) +option(SDL_MIXER_X_SHARED "Build shared library of SDL Mixer X" ON) + +option(DOWNLOAD_AUDIO_CODECS_DEPENDENCY "Downloads and compiles AudioCodecs dependencies pack directly" OFF) +set(AUDIO_CODECS_REPO_PATH "" CACHE PATH "Path to the AudioCodecs dependencies pack") +set(AUDIO_CODECS_INSTALL_PATH "" CACHE PATH "Path to installed AudioCodecs prefix") + +if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) + # Turn on warnings and legacy C/C++ standards to support more compilers + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -std=c90") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -std=c++98") + # Deny undefined symbols + if(NOT APPLE) + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined" ) + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined" ) + endif() +endif() + +set(SDL_MIXER_INCLUDE_PATHS) + +if(NOT AUDIO_CODECS_REPO_PATH AND NOT AUDIO_CODECS_INSTALL_PATH) + # Try to resolve sqlite dependency + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + # Download and configure AudioCodecs dependency + set(SDL2_REPO_PATH ${CMAKE_INSTALL_PREFIX}) + set(SDL2_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/include/SDL2) + set(SDL2_LIBS_PATH ${CMAKE_INSTALL_PREFIX}/lib) + include(cmake/DownloadAudioCodecs.cmake) + set(AUDIO_CODECS_REPO_PATH ${AUDIO_CODECS_REPOSITORY_PATH}) + set(AUDIO_CODECS_INSTALL_PATH ${AUDIO_CODECS_INSTALL_DIR}) + endif() +endif() + +set(FIND_PREFER_STATIC + "-static${MIX_DEBUG_SUFFIX}.a" + "-static${MIX_DEBUG_SUFFIX}.lib" + "${MIX_DEBUG_SUFFIX}.a" + "${MIX_DEBUG_SUFFIX}.lib" + "-static.a" + "-static.lib" + ".a" + ".lib" + "${MIX_DEBUG_SUFFIX}.dll.a" + "${MIX_DEBUG_SUFFIX}.dll.lib" + ".dll.a" + ".dll.lib" + "${MIX_DEBUG_SUFFIX}.so" + "${MIX_DEBUG_SUFFIX}.dylib" + ".so" + ".dylib" +) + +set(FIND_PREFER_SHARED + "${MIX_DEBUG_SUFFIX}.dll.a" + "${MIX_DEBUG_SUFFIX}.dll.lib" + ".dll.a" + ".dll.lib" + "${MIX_DEBUG_SUFFIX}.so" + "${MIX_DEBUG_SUFFIX}.dylib" + ".so" + ".dylib" + "-static${MIX_DEBUG_SUFFIX}.a" + "-static${MIX_DEBUG_SUFFIX}.lib" + "${MIX_DEBUG_SUFFIX}.a" + "${MIX_DEBUG_SUFFIX}.lib" + "-static.a" + "-static.lib" + ".a" + ".lib" +) + +if(AUDIO_CODECS_REPO_PATH OR AUDIO_CODECS_INSTALL_PATH) + set(AUDIO_CODECS_PATH ${AUDIO_CODECS_REPO_PATH}) + set(AUDIO_CODECS_INSTALL_DIR ${AUDIO_CODECS_INSTALL_PATH}) + set(SDL2_REPO_PATH ${AUDIO_CODECS_INSTALL_DIR}) + set(SDL2_INCLUDE_PATH ${AUDIO_CODECS_INSTALL_DIR}/include/SDL2) + link_directories(${AUDIO_CODECS_INSTALL_DIR}/lib) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_INSTALL_DIR}/include ${SDL2_INCLUDE_PATH}) + message("AudioCodecs will be used. No needed extra libraries installed in the system.") + set(USE_SYSTEM_AUDIO_LIBRARIES 0) + set(CMAKE_FIND_LIBRARY_SUFFIXES ${FIND_PREFER_STATIC}) +else() + message("AudioCodecs will NOT be used. Libraries will be recognized in the system.") + set(USE_SYSTEM_AUDIO_LIBRARIES 1) +endif() + +add_definitions(-DHAVE_INTTYPES_H -DHAVE_SETENV -DHAVE_SINF) +add_definitions(-Dmain=SDL_main -DPIC -D_REENTRANT -D_USE_MATH_DEFINES) + +set(SDLMixerX_SOURCES) +set(SDLMixerX_LINK_LIBS) + +# Recognize SDL2 library from the system +if(USE_SYSTEM_AUDIO_LIBRARIES) + find_package(PkgConfig) + pkg_check_modules(SDL2 REQUIRED sdl2) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${SDL2_INCLUDE_DIRS}) + list(APPEND SDLMixerX_LINK_LIBS ${SDL2_LIBRARIES}) + message("== SDL2: ${SDL2_INCLUDE_DIRS} ${SDL2_LIBRARIES} ==") +endif() + +option(USE_WAV "Build with WAV codec" ON) +if(USE_WAV) + add_definitions(-DMUSIC_WAV) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/load_aiff.c + ${SDLMixerX_SOURCE_DIR}/src/codecs/load_voc.c + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_wav.c) +endif() + +option(USE_OGG_VORBIS "Build with OGG Vorbis codec" ON) +if(USE_OGG_VORBIS) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(vorbisfile ov_open "vorbis/vorbisfile.h" FOUND_VORBIS) + find_path(LIBVORBIS_INCLUDE_DIR vorbis/codec.h) + find_library(LIBVORBISFILE_LIB NAMES vorbisfile) + find_library(LIBVORBIS_LIB NAMES vorbis) + message("Vorbis: ${LIBVORBIS_INCLUDE_DIR} ${LIBVORBIS_LIB}") + else() + set(FOUND_VORBIS 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBVORBISFILE_LIB vorbisfile) + set(LIBVORBIS_LIB vorbis) + else() + find_library(LIBVORBISFILE_LIB NAMES vorbisfile + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + find_library(LIBVORBIS_LIB NAMES vorbis + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_VORBIS) + message("== using Vorbis ==") + add_definitions(-DMUSIC_OGG) + list(APPEND SDL_MIXER_INCLUDE_PATHS + ${AUDIO_CODECS_PATH}/libogg/include + ${AUDIO_CODECS_PATH}/libvorbis/include + ) + list(APPEND SDLMixerX_LINK_LIBS ${LIBVORBISFILE_LIB} ${LIBVORBIS_LIB}) + set(LIBOGG_NEEDED ON) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_ogg.c) + endif() +endif() + +option(USE_OPUS "Build with OPUS codec" ON) +if(USE_OPUS) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(opusfile op_open_file "opus/opusfile.h" FOUND_OPUS) + find_path(LIBOPUS_INCLUDE_DIR opus/opusfile.h) + find_library(LIBOPUSFILE_LIB NAMES opusfile) + find_library(LIBOPUS_LIB NAMES opusfile) + message("Opus: ${LIBOPUS_INCLUDE_DIR} ${LIBOPUSFILE_LIB} ${LIBOPUS_LIB}") + else() + set(FOUND_OPUS 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBOPUSFILE_LIB opusfile) + set(LIBOPUS_LIB opus) + else() + find_library(LIBOPUSFILE_LIB NAMES opusfile + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + find_library(LIBOPUS_LIB NAMES opus + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_OPUS) + message("== using Opus ==") + add_definitions(-DMUSIC_OPUS) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS + ${AUDIO_CODECS_PATH}/libogg/include + ${AUDIO_CODECS_PATH}/libopus/include + ${AUDIO_CODECS_PATH}/libopusfile/include + ) + endif() + if(AUDIO_CODECS_INSTALL_DIR) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_INSTALL_DIR}/include/opus) + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBOPUSFILE_LIB} ${LIBOPUS_LIB}) + set(LIBOGG_NEEDED ON) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_opus.c) + endif() +endif() + +option(USE_FLAC "Build with FLAC codec" ON) +if(USE_FLAC) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(FLAC FLAC__format_sample_rate_is_valid "FLAC/format.h" FOUND_FLAC) + find_path(LIBFLAC_INCLUDE_DIR "FLAC/all.h") + find_library(LIBFLAC_LIB NAMES FLAC) + message("FLAC: ${LIBFLAC_INCLUDE_DIR} ${LIBFLAC_LIB}") + else() + set(FOUND_FLAC 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBFLAC_LIB FLAC) + else() + find_library(LIBFLAC_LIB NAMES FLAC + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_FLAC) + message("== using FLAC ==") + add_definitions(-DMUSIC_FLAC -DFLAC__NO_DLL) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS + ${AUDIO_CODECS_PATH}/libogg/include + ${AUDIO_CODECS_PATH}/libFLAC/include + ) + endif() + set(LIBOGG_NEEDED ON) + list(APPEND SDLMixerX_LINK_LIBS ${LIBFLAC_LIB}) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_flac.c) + endif() +endif() + +if(LIBOGG_NEEDED) + if(USE_SYSTEM_AUDIO_LIBRARIES) + find_library(LIBOGG_LIB NAMES ogg) + else() + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBOGG_LIB ogg) + else() + find_library(LIBOGG_LIB NAMES ogg + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBOGG_LIB}) +endif() + +option(USE_MP3_ID3TAG "Build with MP3 Meta tags support provided by libID3Tag library" ON) +if(USE_MP3_ID3TAG AND NOT USE_SYSTEM_AUDIO_LIBRARIES) + message("== using ID3Tag (custom) ==") + add_definitions(-DMUSIC_MP3_ID3TAG) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/libid3tag/include) + endif() + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBID3TAG_LIB id3tag) + else() + find_library(LIBID3TAG_LIB NAMES id3tag + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBID3TAG_LIB}) +endif() + +option(USE_MP3_MAD "Build with MAD MP3 codec" ON) +option(USE_MP3_MAD_GPL_DITHERING "Enable GPL-Licensed dithering functions for MAD library" ON) +if(USE_MP3_MAD) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(mad mad_frame_init "mad.h" FOUND_MAD) + find_path(LIBMAD_INCLUDE_DIR "FLAC/all.h") + find_library(LIBMAD_LIB NAMES mad) + message("MAD: ${LIBMAD_INCLUDE_DIR} ${LIBMAD_LIB}") + else() + set(FOUND_MAD 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBMAD_LIB mad) + else() + find_library(LIBMAD_LIB NAMES mad + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_MAD) + message("== using MAD ==") + add_definitions(-DMUSIC_MP3_MAD) + if(USE_MP3_MAD_GPL_DITHERING) + add_definitions(-DMUSIC_MP3_MAD_GPL_DITHERING) + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBMAD_LIB}) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/libmad/include) + endif() + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_mad.c) + endif() +endif() + +option(USE_MP3_SMPEG "Build with SMPEG MP3 codec" OFF) +if(USE_MP3_SMPEG) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(smpeg SMPEG_new "smpeg/smpeg.h" FOUND_SMPEG) + find_path(LIBSMPEG_INCLUDE_DIR "smpeg/smpeg.h") + find_library(LIBSMPEG_LIB NAMES smpeg) + message("SMPEG: ${LIBSMPEG_INCLUDE_DIR} ${LIBSMPEG_LIB}") + else() + set(FOUND_SMPEG 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBSMPEG_LIB smpeg) + else() + find_library(LIBSMPEG_LIB NAMES smpeg + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_SMPEG) + message("== using SMPEG ==") + add_definitions(-DMUSIC_MP3_SMPEG) + list(APPEND SDLMixerX_LINK_LIBS ${LIBSMPEG_LIB}) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/smpeg/include) + endif() + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_smpeg.c) + endif() +endif() + +option(USE_MP3_MPG123 "[WIP, DON'T USE IT] Build with MPG123 MP3 codec" OFF) +if(USE_MP3_MPG123) + add_definitions(-DMUSIC_MP3_MPG123) + + message(WARNING "MPG123 SUPPORT IS WIP, DON'T USE IT IN PRODUCTION!!!") + # ======= Until AudioCodecs will receive buildable mpg123, detect it externally ======= + include(cmake/FindMpg123.cmake) + + if(NOT MPG123_FOUND) + message(FATAL_ERROR "MPG123 is not found!") + else() + message("MPG123 found in ${MPG123_INCLUDE_DIR} folder") + endif() + + list(APPEND SDL_MIXER_INCLUDE_PATHS ${MPG123_INCLUDE_DIRS}) + set(LIBS ${LIBS} ${MPG123_LIBRARIES}) + list(APPEND SDLMixerX_LINK_LIBS mpg123) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_mpg123.c) +endif() + +if(USE_MP3_MAD OR USE_MP3_MPG123 OR USE_MP3_SMPEG) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_id3tag.c) +endif() + +option(USE_MODPLUG "Build with ModPlug library" ON) +if(USE_MODPLUG) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(modplug ModPlug_Load "libmodplug/modplug.h" FOUND_MODPLUG) + find_path(LIBMODPLUG_INCLUDE_DIR libmodplug/modplug.h) + find_library(LIBMODPLUG_LIB NAMES modplug) + message("ModPlug: ${LIBMODPLUG_INCLUDE_DIR} ${LIBMODPLUG_LIB}") + else() + set(FOUND_MODPLUG 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBMODPLUG_LIB modplug) + else() + find_library(LIBMODPLUG_LIB NAMES modplug + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_MODPLUG) + message("== using libModPlug ==") + add_definitions(-DMUSIC_MOD_MODPLUG -DMODPLUG_STATIC) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/libmodplug/include) + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBMODPLUG_LIB}) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_modplug.c) + endif() +endif() + +option(USE_MIKMOD "Build with MikMod library" OFF) +if(USE_MIKMOD) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(mikmod Player_Load "mikmod.h" FOUND_MIKMOD) + find_path(LIBMIKMOD_INCLUDE_DIR "mikmod.h") + find_library(LIBMIKMOD_LIB NAMES mikmod) + message("MikMod: ${LIBMIKMOD_INCLUDE_DIR} ${LIBMIKMOD_LIB}") + else() + set(FOUND_MIKMOD 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBMIKMOD_LIB mikmod) + else() + find_library(LIBMIKMOD_LIB NAMES mikmod + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_MIKMOD) + message("== using MikMod ==") + add_definitions(-DMUSIC_MOD_MIKMOD) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/libmikmod/include) + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBMIKMOD_LIB}) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_mikmod.c) + endif() +endif() + +option(USE_GME "Build with Game Music Emulators library" ON) +if(USE_GME) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(gme gme_load_file "gme.h" FOUND_GME) + find_path(LIBGME_INCLUDE_DIR "gme.h") + find_library(LIBGME_LIB NAMES gme) + find_library(LIBZLIB_LIB NAMES z zlib) + message("GME: ${LIBGME_INCLUDE_DIR} ${LIBGME_LIB}") + else() + set(FOUND_GME 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBGME_LIB gme) + set(LIBZLIB_LIB zlib) + else() + find_library(LIBGME_LIB NAMES gme + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + find_library(LIBZLIB_LIB NAMES zlib z + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_GME) + message("== using GME ==") + add_definitions(-DMUSIC_GME) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/libgme/include) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/zlib/include) + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBGME_LIB} ${LIBZLIB_LIB}) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_gme.c) + endif() +endif() + +if(NOT WIN32) # CMD Music is not supported on Windows + option(USE_CMD "Build with CMD music player support" ON) + if(USE_CMD) + message("== using CMD Music ==") + add_definitions(-DMUSIC_CMD -D_POSIX_C_SOURCE=1) + CHECK_FUNCTION_EXISTS(fork HAVE_FORK) + if(HAVE_FORK) + add_definitions(-DHAVE_FORK) + endif() + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_cmd.c) + endif() +endif() + +option(USE_MIDI "Build with MIDI support" ON) +if(USE_MIDI) + + option(USE_MIDI_ADLMIDI "Build with libADLMIDI OPL3 Emulator based MIDI sequencer support" ON) + if(USE_MIDI_ADLMIDI) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(ADLMIDI adl_init "adlmidi.h" FOUND_ADLMIDI) + find_path(LIBADLMIDI_INCLUDE_DIR "adlmidi.h") + find_library(LIBADLMIDI_LIB NAMES ADLMIDI) + message("ADLMIDI: ${LIBADLMIDI_INCLUDE_DIR} ${LIBADLMIDI_LIB}") + else() + set(FOUND_ADLMIDI 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBADLMIDI_LIB ADLMIDI) + else() + find_library(LIBADLMIDI_LIB NAMES ADLMIDI + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_ADLMIDI) + message("== using ADLMIDI ==") + add_definitions(-DMUSIC_MID_ADLMIDI) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/libADLMIDI/include) + endif() + set(LIBMATH_NEEDED 1) + list(APPEND SDLMixerX_LINK_LIBS ${LIBADLMIDI_LIB}) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_midi_adl.c) + endif() + endif() + + option(USE_MIDI_OPNMIDI "Build with libOPNMIDI OPN2 Emulator based MIDI sequencer support" ON) + if(USE_MIDI_OPNMIDI) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(OPNMIDI opn_init "opnmidi.h" FOUND_OPNMIDI) + find_path(LIBOPNMIDI_INCLUDE_DIR "opnmidi.h") + find_library(LIBOPNMIDI_LIB NAMES OPNMIDI) + message("OPNMIDI: ${LIBOPNMIDI_INCLUDE_DIR} ${LIBOPNMIDI_LIB}") + else() + set(FOUND_OPNMIDI 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBOPNMIDI_LIB OPNMIDI) + else() + find_library(LIBOPNMIDI_LIB NAMES OPNMIDI + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_OPNMIDI) + message("== using OPNMIDI ==") + add_definitions(-DMUSIC_MID_OPNMIDI) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/libOPNMIDI/include) + endif() + set(LIBMATH_NEEDED 1) + list(APPEND SDLMixerX_LINK_LIBS ${LIBOPNMIDI_LIB}) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_midi_opn.c) + endif() + endif() + + option(USE_MIDI_TIMIDITY "Build with Timidity wave table MIDI sequencer support" ON) + if(USE_MIDI_TIMIDITY AND NOT USE_SYSTEM_AUDIO_LIBRARIES) + message("== using Timidity (custom) ==") + add_definitions(-DMUSIC_MID_TIMIDITY) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/libtimidity/include) + endif() + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBTIMIDITY_LIB timidity) + else() + find_library(LIBTIMIDITY_LIB NAMES timidity + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBTIMIDITY_LIB}) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_timidity.c) + endif() + + option(USE_MIDI_FLUIDSYNTH "Build with FluidSynth wave table MIDI sequencer support" OFF) + if(USE_MIDI_FLUIDSYNTH) + if(USE_SYSTEM_AUDIO_LIBRARIES) + check_library_exists(fluidsynth new_fluid_midi_router "fluidsynth.h" FOUND_FLUIDSYNTH) + find_path(LIBFLUIDSYNTH_INCLUDE_DIR "fluidsynth.h") + find_library(LIBFLUIDSYNTH_LIB NAMES fluidsynth) + message("FluidSynth: ${LIBFLUIDSYNTH_INCLUDE_DIR} ${LIBFLUIDSYNTH_LIB}") + else() + set(FOUND_FLUIDSYNTH 1) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBFLUIDSYNTH_LIB fluidsynth) + else() + find_library(LIBFLUIDSYNTH_LIB NAMES fluidsynth + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() + endif() + if(FOUND_FLUIDSYNTH) + message("== using FluidSynth ==") + add_definitions(-DMUSIC_MID_FLUIDSYNTH) + if(AUDIO_CODECS_REPO_PATH) + list(APPEND SDL_MIXER_INCLUDE_PATHS ${AUDIO_CODECS_PATH}/FluidLite/include) + endif() + list(APPEND SDLMixerX_LINK_LIBS ${LIBFLUIDSYNTH_LIB}) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_fluidsynth.c) + endif() + endif() + + # Native MIDI correctly works on Windows and macOS only. + if(WIN32 OR APPLE) + set(NATIVE_MIDI_SUPPORTED ON) + else() + set(NATIVE_MIDI_SUPPORTED OFF) + endif() + + option(USE_MIDI_NATIVE "Build with operating system native MIDI output support" ${NATIVE_MIDI_SUPPORTED}) + if(USE_MIDI_NATIVE) + add_definitions(-DMUSIC_MID_NATIVE) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/music_nativemidi.c + ${SDLMixerX_SOURCE_DIR}/src/codecs/native_midi/native_midi_common.c) + if(WIN32) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/native_midi/native_midi_win32.c) + list(APPEND SDLMixerX_LINK_LIBS winmm) + endif() + if(APPLE) + list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/codecs/native_midi/native_midi_macosx.c) + endif() + endif() + if(NOT USE_MIDI_ADLMIDI AND + NOT USE_MIDI_OPNMIDI AND + NOT USE_MIDI_TIMIDITY AND + NOT USE_MIDI_FLUIDSYNTH AND + NOT USE_MIDI_NATIVE) + message_error("To have MIDI support you must enable at least one MIDI sequencer library") + endif() + +endif() + +if(USE_SYSTEM_AUDIO_LIBRARIES) + find_library(LIBSDL2CUSTOM_LIB NAMES SDL2) +else() + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + set(LIBSDL2CUSTOM_LIB SDL2$<$:d>) + else() + set(CMAKE_FIND_LIBRARY_SUFFIXES ${FIND_PREFER_SHARED}) + find_library(LIBSDL2CUSTOM_LIB NAMES SDL2 + HINTS "${AUDIO_CODECS_INSTALL_PATH}/lib") + endif() +endif() +list(APPEND SDLMixerX_LINK_LIBS ${LIBSDL2CUSTOM_LIB}) + +if(LIBMATH_NEEDED AND NOT MSVC) + list(APPEND SDLMixerX_LINK_LIBS m) +endif() + +if(WIN32) + option(BUILD_AS_VB6_BINDING "Compile library into solid module compatible with VisualBasic 6" OFF) + if(BUILD_AS_VB6_BINDING) + message("== SDL Mixer X will be built as solid module that is ready for MS-VB6 binding! ==") + list(APPEND SDLMixerX_SOURCES ${SDLMixerX_SOURCE_DIR}/src/vb6_binding/vb6_sdl_binds.c) + list(REMOVE_ITEM SDLMixerX_LINK_LIBS SDL2) + list(REMOVE_ITEM SDLMixerX_LINK_LIBS SDL2$<$:d>) + list(APPEND SDLMixerX_LINK_LIBS + SDL2-static + uuid winmm ole32 imm32 version oleaut32 user32 gdi32) + if(NOT MSVC) + list(APPEND SDLMixerX_LINK_LIBS stdc++ gcc pthread) + endif() + endif() +endif() + +if(APPLE) + find_library(APPLE_CORE_AUDIO CoreAudio) + find_library(APPLE_IOKIT IOKit) + find_library(APPLE_COCOA Cocoa) + find_library(APPLE_AUDIOTOOLBOX AudioToolbox) + find_library(APPLE_CORE_VIDEO CoreVideo) + find_library(APPLE_CORE_FOUNDATION CoreFoundation) + find_library(APPLE_CARBON Carbon) + find_library(APPLE_FORCE_FEEDBACK ForceFeedback) + find_library(ICONV_LIB iconv) + list(APPEND SDLMixerX_LINK_LIBS + ${APPLE_CORE_AUDIO} + ${APPLE_COCOA} + ${APPLE_CORE_VIDEO} + ${APPLE_CORE_FOUNDATION} + ${APPLE_FORCE_FEEDBACK} + ${APPLE_IOKIT} + ${APPLE_CARBON} + ${APPLE_AUDIOTOOLBOX} + ${ICONV_LIB}) + list(APPEND SDLMixerX_LINK_LIBS objc) +endif() + +if(NOT MSVC) + list(APPEND SDLMixerX_LINK_LIBS stdc++) +endif() + +list(APPEND SDLMixerX_SOURCES + ${SDLMixerX_SOURCE_DIR}/src/effect_position.c + ${SDLMixerX_SOURCE_DIR}/src/effects_internal.c + ${SDLMixerX_SOURCE_DIR}/src/effect_stereoreverse.c + ${SDLMixerX_SOURCE_DIR}/src/mixer.c + ${SDLMixerX_SOURCE_DIR}/src/music.c + ${SDLMixerX_SOURCE_DIR}/src/mixer_x_deprecated.c + ) + +file(GLOB SDLMixerX_SOURCES ${SDLMixerX_SOURCES}) + +set(SDLMixerX_INSTALLS) + +if(SDL_MIXER_X_STATIC AND NOT BUILD_AS_VB6_BINDING) + add_library(SDL2_mixer_ext_Static STATIC ${SDLMixerX_SOURCES}) + if(WIN32) + set_target_properties(SDL2_mixer_ext_Static PROPERTIES OUTPUT_NAME SDL2_mixer_ext-static) + else() + set_target_properties(SDL2_mixer_ext_Static PROPERTIES OUTPUT_NAME SDL2_mixer_ext) + endif() + target_include_directories(SDL2_mixer_ext_Static PRIVATE + ${SDLMixerX_SOURCE_DIR}/include/SDL_mixer_ext + ${SDLMixerX_SOURCE_DIR}/src + ${SDLMixerX_SOURCE_DIR}/src/codecs + ${AUDIO_CODECS_INSTALL_DIR}/include/SDL2 + ) + target_include_directories(SDL2_mixer_ext_Static PUBLIC + ${SDLMixerX_SOURCE_DIR}/include + ${SDL_MIXER_INCLUDE_PATHS} + ) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY AND AUDIO_CODECS_INSTALL_PATH) + add_dependencies(SDL2_mixer_ext_Static AudioCodecs) + endif() + set_target_properties(SDL2_mixer_ext_Static + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + ) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + add_custom_command( + TARGET SDL2_mixer_ext_Static POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_SOURCE_DIR}/include/SDL_mixer_ext/SDL_mixer_ext.h + ${AUDIO_CODECS_INSTALL_DIR}/include/SDL2) + endif() + list(APPEND SDLMixerX_INSTALLS SDL2_mixer_ext_Static) +endif() + +if(WIN32) + list(APPEND SDLMixerX_SOURCES ${SDLMixerX_SOURCE_DIR}/version.rc) +endif() + +if(SDL_MIXER_X_SHARED AND NOT BUILD_AS_VB6_BINDING) + add_library(SDL2_mixer_ext SHARED ${SDLMixerX_SOURCES}) + target_link_libraries(SDL2_mixer_ext ${SDLMixerX_LINK_LIBS}) + target_include_directories(SDL2_mixer_ext PRIVATE + ${SDLMixerX_SOURCE_DIR}/include/SDL_mixer_ext + ${SDLMixerX_SOURCE_DIR}/src + ${SDLMixerX_SOURCE_DIR}/src/codecs + ${AUDIO_CODECS_INSTALL_DIR}/include/SDL2 + ) + target_include_directories(SDL2_mixer_ext PUBLIC + ${SDLMixerX_SOURCE_DIR}/include + ${SDL_MIXER_INCLUDE_PATHS} + ) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY AND AUDIO_CODECS_INSTALL_PATH) + add_dependencies(SDL2_mixer_ext AudioCodecs) + endif() + set_target_properties(SDL2_mixer_ext + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" + ) + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + add_custom_command( + TARGET SDL2_mixer_ext POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_SOURCE_DIR}/include/SDL_mixer_ext/SDL_mixer_ext.h + ${AUDIO_CODECS_INSTALL_DIR}/include/SDL2) + endif() + list(APPEND SDLMixerX_INSTALLS SDL2_mixer_ext) +endif() + +if(BUILD_AS_VB6_BINDING) + add_library(SDL2_mixer_ext_VB6 MODULE ${SDLMixerX_SOURCES}) + set_target_properties(SDL2_mixer_ext_VB6 PROPERTIES OUTPUT_NAME SDL2MixerVB) + set_target_properties(SDL2_mixer_ext_VB6 PROPERTIES PREFIX "") + target_compile_definitions(SDL2_mixer_ext_VB6 PRIVATE -DFORCE_STDCALLS) + target_link_libraries(SDL2_mixer_ext_VB6 ${SDLMixerX_LINK_LIBS}) + target_include_directories(SDL2_mixer_ext_VB6 PUBLIC + ${SDLMixerX_SOURCE_DIR}/include/SDL_mixer_ext + ${SDLMixerX_SOURCE_DIR}/src + ${SDLMixerX_SOURCE_DIR}/src/codecs + ${AUDIO_CODECS_INSTALL_DIR}/include/SDL2 + ) + target_include_directories(SDL2_mixer_ext_VB6 PUBLIC + ${SDLMixerX_SOURCE_DIR}/include + ${SDL_MIXER_INCLUDE_PATHS} + ) + set_target_properties(SDL2_mixer_ext_VB6 PROPERTIES LINK_FLAGS + "-Wl,--add-stdcall-alias -static-libgcc -static-libstdc++ -static -lpthread") + if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY AND AUDIO_CODECS_INSTALL_PATH) + add_dependencies(SDL2_mixer_ext_VB6 AudioCodecs) + endif() + set_target_properties(SDL2_mixer_ext_VB6 + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/sdl-mixer-vb6" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/sdl-mixer-vb6" + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/sdl-mixer-vb6" + ) + add_custom_command( + TARGET SDL2_mixer_ext_VB6 POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${CMAKE_SOURCE_DIR}/VB6_Wrapper/modSDL2_mixer_ext_vb6.bas + ${CMAKE_BINARY_DIR}/sdl-mixer-vb6) + list(APPEND SDLMixerX_INSTALLS SDL2_mixer_ext_VB6) +endif() + +install(TARGETS ${SDLMixerX_INSTALLS} + RUNTIME DESTINATION "bin" + LIBRARY DESTINATION "lib" + ARCHIVE DESTINATION "lib" + FRAMEWORK DESTINATION "lib" + INCLUDES DESTINATION "include") + +if(DOWNLOAD_AUDIO_CODECS_DEPENDENCY) + install(DIRECTORY ${AUDIO_CODECS_INSTALL_DIR}/bin + DESTINATION .) + install(DIRECTORY ${AUDIO_CODECS_INSTALL_DIR}/lib + DESTINATION .) + install(DIRECTORY ${AUDIO_CODECS_INSTALL_DIR}/include + DESTINATION .) +endif() + +install(FILES + include/SDL_mixer_ext/begin_code.h + include/SDL_mixer_ext/close_code.h + include/SDL_mixer_ext/SDL_mixer_ext.h + DESTINATION include/SDL2) + diff --git a/libs/SDLMixerX/COPYING.txt b/libs/SDLMixerX/COPYING.txt new file mode 100644 index 000000000..e8f8643f2 --- /dev/null +++ b/libs/SDLMixerX/COPYING.txt @@ -0,0 +1,24 @@ +/* + SDL Mixer X: An extended audio mixer library, forked from SDL_mixer + Copyright (C) 2014-2018 Vitaly Novichkov + + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2018 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + +*/ diff --git a/libs/SDLMixerX/GPLv2.txt b/libs/SDLMixerX/GPLv2.txt new file mode 100644 index 000000000..1f963da0d --- /dev/null +++ b/libs/SDLMixerX/GPLv2.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. 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 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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 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. + + You should have received a copy of the GNU General Public License along + with this program; 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. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + diff --git a/libs/SDLMixerX/GPLv3.txt b/libs/SDLMixerX/GPLv3.txt new file mode 100644 index 000000000..10926e87f --- /dev/null +++ b/libs/SDLMixerX/GPLv3.txt @@ -0,0 +1,675 @@ + 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. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state 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 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 . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. + diff --git a/libs/SDLMixerX/README.txt b/libs/SDLMixerX/README.txt new file mode 100644 index 000000000..998e0d9d3 --- /dev/null +++ b/libs/SDLMixerX/README.txt @@ -0,0 +1,248 @@ +SDL Mixer X (aka SDL Mixer 2.0 Modded or SDL_mixer_ext), +by Vitaly Novichkov , +forked from SDL Mixer 2.0 by Sam Lantinga + +vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +WARNING: The licenses for libmad, ADLMIDI, OPNMIDI, and GME is GPL, + which means that in order to use it your application must + also be GPL! +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The latest original version of this library is available from: +http://www.libsdl.org/projects/SDL_mixer/ + +Sources of modified library version is available in the PGE Project's sources: +https://github.com/Wohlhabend-Networks/PGE-Project/ + in the folder: _Libs/SDL2_mixer_modified/ +or: +https://bitbucket.org/Wohlstand/pge-project + in the folder: _Libs/SDL2_mixer_modified/ + +============================================================================= +Difference between original and this library: +----------------------------------------------------------------------------- ++ Added new codecs: + - Game Music Emulators (LGPL v2.1) which adds support of chip tunes + like NSF, VGM, SPC, HES, etc. + - libADLMIDI (GPL v3, LGPL v3) (remake from ADLMIDI) to play MIDI with + emulated OPL3 synthesiser, also supports loop points + "loopStart" and "loopEnd" + - libOPNMIDI (GPL v3, LGPL v3) to play MIDI with + emulated OPN2 synthesiser, also supports loop points + "loopStart" and "loopEnd" ++ Added some new functions ++ Added support of loop points for OGG files (via "LOOPSTART" and "LOOPEND" + (or "LOOPLENGTH" to be compatible with RPG Maker) vorbis comments) ++ Reorganized music codecs processing system ++ Added support to get current position and track lenght for a seekable codecs + +vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +IMPORTANT: To choice a track number of NSF, GBM, HES, etc file, + you must append "|xxx" to end of file path for + Mix_LoadMUS function. + Where xxx - actual number of chip track, (from 0 to N-1) + Examples: "file.nsf|12", "file.hes|2" +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +Arguments are passing like argument for a GME-based files (NSF, HES, etc.): +Syntax for MIDI is: + myfile.mid|xyy;xyy;xyy;...; + where x - parameter type + where y - value (every value must be ended with semicolon!) + +available parameters: + s - use a specific synthesiser + 0 - ADLMIDI + 1 - Native MIDI [Win32/OSX/Haiku only] + 2 - Timidity + 3 - Fluidsynth + b - value from 0 to 66 - number of ADLMIDI bank + t - (0 or 1) enable deep tremolo on ADLMIDI + v - (0 or 1) enable deep vibrato on ADLMIDI + m - (0 or 1) enable scalable modulation on ADLMIDI + a - (0 or 1) enable AdLib mode of percussion on ADLMIDI +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +============================================================================= +Added music codecs: +----------------------------------------------------------------------------- +General: +- MUS_GME - Game Music Emulatirs + +MIDI Playing: +- ADLMIDI - A software synthesizer is based on Yamaha OPL3 (YMF262) chip emulator +- OPNMIDI - A software synthesizer is based on Yamaha OPL3 (YM2612) chip emulator + +============================================================================= +Added functions: +----------------------------------------------------------------------------- +/* + Allows you to set up custom path for Timidify patches +*/ +void MIX_Timidity_addToPathList(const char *path); + +/* + Get music title from meta-tag if possible. If title tag is empty, filename will be returned +*/ +const char* Mix_GetMusicTitle(const Mix_Music *music); + +/* + Get music title from meta-tag if possible +*/ +const char* Mix_GetMusicTitleTag(const Mix_Music *music); + +/* + Get music artist from meta-tag if possible +*/ +const char* Mix_GetMusicArtistTag(const Mix_Music *music); + +/* + Get music album from meta-tag if possible +*/ +const char* Mix_GetMusicAlbumTag(const Mix_Music *music); + +/* + Get music copyright from meta-tag if possible +*/ +const char* Mix_GetMusicCopyrightTag(const Mix_Music *music); + +/* + Load music from memory with passing of extra arguments +*/ +Mix_Music * SDLCALLCC Mix_LoadMUS_RW_ARG(SDL_RWops *src, int freesrc, char *args) + +/* + Load music from memory with passing NSF/HES/etc. track number (accepts integer unlike SDLCALLCC Mix_LoadMUS_RW_ARG) +*/ +Mix_Music * SDLCALLCC Mix_LoadMUS_RW_GME(SDL_RWops *src, int freesrc, int trackID) + +typedef enum +{ + MIDI_ADLMIDI, + MIDI_Native, + MIDI_Timidity, + MIDI_OPNMIDI, + MIDI_Fluidsynth, + MIDI_KnuwnDevices /* Count of MIDI device types */ +} Mix_MIDI_Device; + +/* + Allows you to toggle MIDI Devices! + (change will be applied on re-opening of MIDI file) + Attempt to toggle unsupported MIDI device takes no effect + (for case when library built without linking of required library) +*/ +int Mix_SetMidiDevice(int device); + +/* + Returns current ADLMIDI bank number +*/ +int MIX_ADLMIDI_getBankID(); + +/* + Changes ADLMIDI bank number (changes applying on MIDI file reopen) +*/ +void MIX_ADLMIDI_setBankID(int bnk); + +/* + Returns current state of ADLMIDI deep tremolo flag +*/ +int MIX_ADLMIDI_getTremolo(); + +/* + Changes ADLMIDI deep tremolo flag (changes applying on MIDI file reopen) +*/ +void MIX_ADLMIDI_setTremolo(int tr); + +/* + Returns current state of ADLMIDI deep vibrato flag +*/ +int MIX_ADLMIDI_getVibrato(); + +/* + Changes ADLMIDI deep vibrato flag (changes applying on MIDI file reopen) +*/ +void MIX_ADLMIDI_setVibrato(int vib); + +/* + Returns current state of ADLMIDI deep scaling modulation flag +*/ +int MIX_ADLMIDI_getScaleMod(); + +/* + Changes ADLMIDI scaling modulation flag (changes applying on MIDI file reopen) +*/ +void MIX_ADLMIDI_setScaleMod(int sc); + +/* + Resets ADLMIDI flags and settings to default state +*/ +void MIX_ADLMIDI_setSetDefaults(); + +/* + Get the time current position of music stream + returns -1.0 if this feature is not supported for some codec +*/ +double Mix_GetMusicPosition(Mix_Music *music); +/* + Get the total time length of music stream + returns -1.0 if this feature is not supported for some codec + */ +double Mix_GetMusicTotalTime(Mix_Music *music); + +/* + Get the loop start time position of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec +*/ +double Mix_GetMusicLoopStartTime(Mix_Music *music); +/* + Get the loop end time position of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec +*/ +double Mix_GetMusicLoopEndTime(Mix_Music *music); +/* + Get the loop time length of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec +*/ +double Mix_GetMusicLoopLengthTime(Mix_Music *music); + +============================================================================= + +Due to popular demand, here is a simple multi-channel audio mixer. +It supports 8 channels of 16 bit stereo audio, plus a single channel +of music, mixed by the Modplug MOD, Timidity MIDI, ADLMIDI, GME +and LibMAD MP3 libraries. + +See the header file SDL_mixer_ext.h for documentation on this mixer library. + +The mixer can currently load Microsoft WAVE files and Creative Labs VOC +files as audio samples, and can load MIDI files via Timidity and the +following music formats via MikMod: .MOD .S3M .IT .XM. It can load +Ogg Vorbis streams as music if built with Ogg Vorbis or Tremor libraries, +and finally it can load MP3 music using the SMPEG or libmad libraries. + +Tremor decoding is disabled by default; you can enable it by passing + --enable-music-ogg-tremor +to configure, or by defining OGG_MUSIC and OGG_USE_TREMOR. + +libmad decoding is disabled by default; you can enable it by passing + --enable-music-mp3-mad +to configure, or by defining MP3_MAD_MUSIC +vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +WARNING: The license for libmad is GPL, which means that in order to + use it your application must also be GPL! +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The process of mixing MIDI files to wave output is very CPU intensive, +so if playing regular WAVE files sound great, but playing MIDI files +sound choppy on slow computers, try using 8-bit audio, mono audio, +or lower frequencies. + +To play MIDI files via Timidity, you'll need to get a complete set of GUS patches +from: +http://www.libsdl.org/projects/mixer/timidity/timidity.tar.gz +and unpack them in /usr/local/lib under UNIX, and C:\ under Win32. + +This library is under the zlib license, see the file "COPYING.txt" for details. + + + diff --git a/libs/SDLMixerX/SDL2_mixer_ext.License.txt b/libs/SDLMixerX/SDL2_mixer_ext.License.txt new file mode 100644 index 000000000..58806358d --- /dev/null +++ b/libs/SDLMixerX/SDL2_mixer_ext.License.txt @@ -0,0 +1,104 @@ +======================================================================== +SDL_mixer_ext {aka SDL Mixer X, SDL Mixer 2.0 Modded}, by Vitaly Novichkov +forked from SDL Mixer 2.0 by Sam Lantinga +======================================================================== + +SDL_mixer_ext: An extended audio mixer library, forked from SDL_mixer +Copyright (C) 2014-2018 Vitaly Novichkov + +SDL_mixer: An audio mixer library based on the SDL library +Copyright (C) 1997-2018 Sam Lantinga + +Sources of modified library version is available on GitHub: +https://github.com/WohlSoft/SDL-Mixer-X + +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. + +======================================================================== +Statically linked libraries: +======================================================================== +------------------------------------------------------------------------ +libADLMIDI: is a free MIDI to WAV conversion library with OPL3 emulation + +Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma +ADLMIDI Library API: Copyright (c) 2015-2018 Vitaly Novichkov + +Library is based on the ADLMIDI, a MIDI player for Linux and Windows +with OPL3 emulation: +http://iki.fi/bisqwit/source/adlmidi.html + +Source code: https://github.com/Wohlstand/libADLMIDI + +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 +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 . + +------------------------------------------------------------------------ + +Game Music Emulators: is a free chuptunes to WAV conversion library. + +Source code: https://bitbucket.org/mpyne/game-music-emu + +Copyright (C) 2003-2006 Shay Green. + +This module 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 module 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 module; +If not, see . + +------------------------------------------------------------------------ + +libmad: MPEG audio decoder library + +Copyright (C) 2000-2004 Underbit Technologies, 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 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. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +If you would like to negotiate alternate licensing terms, you may do +so by contacting: Underbit Technologies, Inc. + +------------------------------------------------------------------------ diff --git a/libs/SDLMixerX/SRB2Note.txt b/libs/SDLMixerX/SRB2Note.txt new file mode 100644 index 000000000..6036d394e --- /dev/null +++ b/libs/SDLMixerX/SRB2Note.txt @@ -0,0 +1,7 @@ +i686-w64-mingw32/bin/libfluidsynth-2.dll was grabbed from GZDoom v3.5.1, because this build does not have glib, gthread, or sndfile external dependencies. + +sdl_mixer_ext2.dll requires libgcc and libstdc++ external dependencies. While passing to the linker "-Bstatic -lgcc" works fine, adding "-lstdc++" to -Bstatic generates linker errors. + +Hence, libstdc++ needs to be bundled as DLL (and consequently, libgcc.) + +If you try to build yourself, make sure -lstdc++ does not follow -Bdynamic in the linker flags, because otherwise it will link to the DLL. diff --git a/libs/SDLMixerX/SRB2Note_cmakeflags.png b/libs/SDLMixerX/SRB2Note_cmakeflags.png new file mode 100644 index 000000000..ffcf269a4 Binary files /dev/null and b/libs/SDLMixerX/SRB2Note_cmakeflags.png differ diff --git a/libs/SDLMixerX/i686-w64-mingw32/bin/SDL2_mixer_ext.dll b/libs/SDLMixerX/i686-w64-mingw32/bin/SDL2_mixer_ext.dll new file mode 100644 index 000000000..158aad8c3 Binary files /dev/null and b/libs/SDLMixerX/i686-w64-mingw32/bin/SDL2_mixer_ext.dll differ diff --git a/libs/SDLMixerX/i686-w64-mingw32/bin/libfluidsynth-2.dll b/libs/SDLMixerX/i686-w64-mingw32/bin/libfluidsynth-2.dll new file mode 100644 index 000000000..1b768a6c1 Binary files /dev/null and b/libs/SDLMixerX/i686-w64-mingw32/bin/libfluidsynth-2.dll differ diff --git a/libs/SDLMixerX/i686-w64-mingw32/bin/libgcc_s_sjlj-1.dll b/libs/SDLMixerX/i686-w64-mingw32/bin/libgcc_s_sjlj-1.dll new file mode 100644 index 000000000..0a62946cb Binary files /dev/null and b/libs/SDLMixerX/i686-w64-mingw32/bin/libgcc_s_sjlj-1.dll differ diff --git a/libs/SDLMixerX/i686-w64-mingw32/bin/libstdc++-6.dll b/libs/SDLMixerX/i686-w64-mingw32/bin/libstdc++-6.dll new file mode 100644 index 000000000..e9feebaaa Binary files /dev/null and b/libs/SDLMixerX/i686-w64-mingw32/bin/libstdc++-6.dll differ diff --git a/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/SDL_mixer_ext.h b/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/SDL_mixer_ext.h new file mode 100644 index 000000000..3a6b91b50 --- /dev/null +++ b/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/SDL_mixer_ext.h @@ -0,0 +1,867 @@ +/* + SDL Mixer X: An extended audio mixer library, forked from SDL_mixer + Copyright (C) 2014-2018 Vitaly Novichkov + + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2018 Sam Lantinga + + 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. +*/ + +#ifndef SDL_MIXER_H_ +#define SDL_MIXER_H_ + +#include "SDL_stdinc.h" +#include "SDL_rwops.h" +#include "SDL_audio.h" +#include "SDL_endian.h" +#include "SDL_version.h" +#include "begin_code.h" + +/* Let applications recogonize which SDL Mixer edition is in use: Official or Extended fork by Wohlstand */ +#define SDL_MIXER_X 1 + +#define MIXSDLCALL + +#if defined(FORCE_STDCALLS) && defined(_WIN32) +#ifdef SDLCALL +#undef SDLCALL +#endif +#define SDLCALL __stdcall +#define SDLCALLCC __stdcall +#else +#define SDLCALLCC +#endif + +#ifndef DEPRECATED +#ifdef __GNUC__ +#define DEPRECATED(func) func __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define DEPRECATED(func) __declspec(deprecated) func +#else +#pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#define DEPRECATED(func) func +#endif +#endif + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL +*/ +#define SDL_MIXER_MAJOR_VERSION 2 +#define SDL_MIXER_MINOR_VERSION 2 +#define SDL_MIXER_PATCHLEVEL 0 + +/* This macro can be used to fill a version structure with the compile-time + * version of the SDL_mixer library. + */ +#define SDL_MIXER_VERSION(X) \ +{ \ + (X)->major = SDL_MIXER_MAJOR_VERSION; \ + (X)->minor = SDL_MIXER_MINOR_VERSION; \ + (X)->patch = SDL_MIXER_PATCHLEVEL; \ +} + +/* Backwards compatibility */ +#define MIX_MAJOR_VERSION SDL_MIXER_MAJOR_VERSION +#define MIX_MINOR_VERSION SDL_MIXER_MINOR_VERSION +#define MIX_PATCHLEVEL SDL_MIXER_PATCHLEVEL +#define MIX_VERSION(X) SDL_MIXER_VERSION(X) + +/** + * This is the version number macro for the current SDL_mixer version. + */ +#define SDL_MIXER_COMPILEDVERSION \ + SDL_VERSIONNUM(SDL_MIXER_MAJOR_VERSION, SDL_MIXER_MINOR_VERSION, SDL_MIXER_PATCHLEVEL) + +/** + * This macro will evaluate to true if compiled with SDL_mixer at least X.Y.Z. + */ +#define SDL_MIXER_VERSION_ATLEAST(X, Y, Z) \ + (SDL_MIXER_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) + +/* This function gets the version of the dynamically linked SDL_mixer library. + it should NOT be used to fill a version structure, instead you should + use the SDL_MIXER_VERSION() macro. + */ +extern DECLSPEC const SDL_version * SDLCALL Mix_Linked_Version(void); + +typedef enum +{ + MIX_INIT_FLAC = 0x00000001, + MIX_INIT_MOD = 0x00000002, + MIX_INIT_MP3 = 0x00000008, + MIX_INIT_OGG = 0x00000010, + MIX_INIT_MID = 0x00000020, + MIX_INIT_OPUS = 0x00000040 +} MIX_InitFlags; + +/* Loads dynamic libraries and prepares them for use. Flags should be + one or more flags from MIX_InitFlags OR'd together. + It returns the flags successfully initialized, or 0 on failure. + */ +extern DECLSPEC int SDLCALL Mix_Init(int flags); + +/* Unloads libraries loaded with Mix_Init */ +extern DECLSPEC void SDLCALL Mix_Quit(void); + + +/* The default mixer has 8 simultaneous mixing channels */ +#ifndef MIX_CHANNELS +#define MIX_CHANNELS 8 +#endif + +/* Good default values for a PC soundcard */ +#define MIX_DEFAULT_FREQUENCY 44100 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define MIX_DEFAULT_FORMAT AUDIO_S16LSB +#else +#define MIX_DEFAULT_FORMAT AUDIO_S16MSB +#endif +#define MIX_DEFAULT_CHANNELS 2 +#define MIX_MAX_VOLUME SDL_MIX_MAXVOLUME /* Volume of a chunk */ + +/* The internal format for an audio chunk */ +typedef struct Mix_Chunk { + int allocated; + Uint8 *abuf; + Uint32 alen; + Uint8 volume; /* Per-sample volume, 0-128 */ +} Mix_Chunk; + +/* The different fading types supported */ +typedef enum { + MIX_NO_FADING, + MIX_FADING_OUT, + MIX_FADING_IN +} Mix_Fading; + +/* These are types of music files (not libraries used to load them) */ +typedef enum { + MUS_NONE, + MUS_CMD, + MUS_WAV, + MUS_MOD, + MUS_MID, + MUS_OGG, + MUS_MP3, + MUS_MP3_MAD_UNUSED, + MUS_FLAC, + MUS_MODPLUG_UNUSED, + MUS_OPUS, + MUS_GME, + MUS_ADLMIDI/*Use ADLMIDI coded for super-special formats like IMF, MUS or XMI are can't be played without ADLMIDI*/ +} Mix_MusicType; + +typedef enum { + MIDI_ADLMIDI, + MIDI_Native, + MIDI_Timidity, + MIDI_OPNMIDI, + MIDI_Fluidsynth, + MIDI_ANY, + MIDI_KnuwnDevices /* Count of MIDI device types */ +} Mix_MIDI_Device; + +/* Volume model type in the ADLMIDI */ +typedef enum { + ADLMIDI_VM_AUTO, + ADLMIDI_VM_GENERIC, + ADLMIDI_VM_CMF, + ADLMIDI_VM_DMX, + ADLMIDI_VM_APOGEE, + ADLMIDI_VM_9X +} Mix_ADLMIDI_VolumeModel; + +/* OPL3 chip emulators for ADLMIDI */ +typedef enum { + ADLMIDI_OPL3_EMU_DEFAULT = -1, + ADLMIDI_OPL3_EMU_NUKED = 0, + ADLMIDI_OPL3_EMU_NUKED_1_7_4, + ADLMIDI_OPL3_EMU_DOSBOX, +} Mix_ADLMIDI_Emulator; + +/* OPN2 chip emulators for OPNMIDI */ +typedef enum { + OPNMIDI_OPN2_EMU_DEFAULT = -1, + OPNMIDI_OPN2_EMU_MIME = 0, + OPNMIDI_OPN2_EMU_NUKED, + OPNMIDI_OPN2_EMU_GENS, +} Mix_OPNMIDI_Emulator; + +/* The internal format for a music chunk interpreted via mikmod */ +typedef struct _Mix_Music Mix_Music; + +/* Open the mixer with a certain audio format */ +extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, int chunksize); + +/* Open the mixer with specific device and certain audio format */ +extern DECLSPEC int SDLCALL Mix_OpenAudioDevice(int frequency, Uint16 format, int channels, int chunksize, const char* device, int allowed_changes); + +/* Dynamically change the number of channels managed by the mixer. + If decreasing the number of channels, the upper channels are + stopped. + This function returns the new number of allocated channels. + */ +extern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans); + +/* Find out what the actual audio device parameters are. + This function returns 1 if the audio has been opened, 0 otherwise. + */ +extern DECLSPEC int SDLCALL Mix_QuerySpec(int *frequency,Uint16 *format,int *channels); + +/* Load a wave file or a music (.mod .s3m .it .xm) file + IMPORTANT: To choice a track number of NSF, GBM, HES, etc file, + you must append "|xxx" to end of file path for + Mix_LoadMUS function. + Where xxx - actual number of chip track, (from 0 to N-1) + Examples: "file.nsf|12", "file.hes|2" +*/ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, int freesrc); +#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1) +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file); + +/* Load a music file from an SDL_RWop object + * Matt Campbell (matt@campbellhome.dhs.org) April 2000 */ +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *src, int freesrc); + +/* Load a music file from an SDL_RWop object with custom arguments (trackID for GME or settings for a MIDI playing) + * Arguments are taking no effect for file formats which are not supports extra arguments. + */ +extern DECLSPEC Mix_Music *SDLCALL Mix_LoadMUS_RW_ARG(SDL_RWops *src, int freesrc, const char *args); + +/* Load a music file from an SDL_RWop object with custom trackID for GME. + * trackID argument takes no effect for non-NSF,HES,GBM,etc. file formats. + * Default value should be 0 + */ +extern DECLSPEC Mix_Music *SDLCALL Mix_LoadMUS_RW_GME(SDL_RWops *src, int freesrc, int trackID); + +/* Load a music file from an SDL_RWop object assuming a specific format */ +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *src, Mix_MusicType type, int freesrc); + +/* Load a music file from an SDL_RWop object assuming a specific format + with custom arguments (trackID for GME or settings for a MIDI playing) */ +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW_ARG(SDL_RWops *src, Mix_MusicType type, int freesrc, const char *args); + +/* Load a wave file of the mixer format from a memory buffer */ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_WAV(Uint8 *mem); + +/* Load raw audio data of the mixer format from a memory buffer */ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len); + +/* Free an audio chunk previously loaded */ +extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk); +extern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music); + +/* Get a list of chunk/music decoders that this build of SDL_mixer provides. + This list can change between builds AND runs of the program, if external + libraries that add functionality become available. + You must successfully call Mix_OpenAudio() before calling these functions. + This API is only available in SDL_mixer 1.2.9 and later. + + // usage... + int i; + const int total = Mix_GetNumChunkDecoders(); + for (i = 0; i < total; i++) + printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i)); + + Appearing in this list doesn't promise your specific audio file will + decode...but it's handy to know if you have, say, a functioning Timidity + install. + + These return values are static, read-only data; do not modify or free it. + The pointers remain valid until you call Mix_CloseAudio(). +*/ +extern DECLSPEC int SDLCALL Mix_GetNumChunkDecoders(void); +extern DECLSPEC const char * SDLCALL Mix_GetChunkDecoder(int index); +extern DECLSPEC SDL_bool SDLCALL Mix_HasChunkDecoder(const char *name); +extern DECLSPEC int SDLCALL Mix_GetNumMusicDecoders(void); +extern DECLSPEC const char * SDLCALL Mix_GetMusicDecoder(int index); +extern DECLSPEC SDL_bool SDLCALL Mix_HasMusicDecoder(const char *name); + +/* Find out the music format of a mixer music, or the currently playing + music, if 'music' is NULL. +*/ +extern DECLSPEC Mix_MusicType SDLCALL Mix_GetMusicType(const Mix_Music *music); + +/* Get music title from meta-tag if possible. If title tag is empty, filename will be returned */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicTitle(const Mix_Music *music); +/* Get music title from meta-tag if possible */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicTitleTag(const Mix_Music *music); +/* Get music artist from meta-tag if possible */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicArtistTag(const Mix_Music *music); +/* Get music album from meta-tag if possible */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicAlbumTag(const Mix_Music *music); +/* Get music copyright from meta-tag if possible */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicCopyrightTag(const Mix_Music *music); + +/* Set a function that is called after all mixing is performed. + This can be used to provide real-time visual display of the audio stream + or add a custom mixer filter for the stream data. +*/ +extern DECLSPEC void SDLCALL Mix_SetPostMix(void (SDLCALL *mix_func)(void *udata, Uint8 *stream, int len), void *arg); + +/* Add your own music player or additional mixer function. + If 'mix_func' is NULL, the default music player is re-enabled. + */ +extern DECLSPEC void SDLCALL Mix_HookMusic(void (SDLCALL *mix_func)(void *udata, Uint8 *stream, int len), void *arg); + +/* Add your own callback for when the music has finished playing or when it is + * stopped from a call to Mix_HaltMusic. + */ +extern DECLSPEC void SDLCALL Mix_HookMusicFinished(void (SDLCALL *music_finished)(void)); + +/* Get a pointer to the user data for the current music hook */ +extern DECLSPEC void * SDLCALL Mix_GetMusicHookData(void); + +/* + * Add your own callback when a channel has finished playing. NULL + * to disable callback. The callback may be called from the mixer's audio + * callback or it could be called as a result of Mix_HaltChannel(), etc. + * do not call SDL_LockAudio() from this callback; you will either be + * inside the audio callback, or SDL_mixer will explicitly lock the audio + * before calling your callback. + */ +extern DECLSPEC void SDLCALL Mix_ChannelFinished(void (SDLCALL *channel_finished)(int channel)); + + +/* Special Effects API by ryan c. gordon. (icculus@icculus.org) */ + +#define MIX_CHANNEL_POST -2 + +/* This is the format of a special effect callback: + * + * myeffect(int chan, void *stream, int len, void *udata); + * + * (chan) is the channel number that your effect is affecting. (stream) is + * the buffer of data to work upon. (len) is the size of (stream), and + * (udata) is a user-defined bit of data, which you pass as the last arg of + * Mix_RegisterEffect(), and is passed back unmolested to your callback. + * Your effect changes the contents of (stream) based on whatever parameters + * are significant, or just leaves it be, if you prefer. You can do whatever + * you like to the buffer, though, and it will continue in its changed state + * down the mixing pipeline, through any other effect functions, then finally + * to be mixed with the rest of the channels and music for the final output + * stream. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + */ +typedef void (SDLCALL *Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata); + +/* + * This is a callback that signifies that a channel has finished all its + * loops and has completed playback. This gets called if the buffer + * plays out normally, or if you call Mix_HaltChannel(), implicitly stop + * a channel via Mix_AllocateChannels(), or unregister a callback while + * it's still playing. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + */ +typedef void (SDLCALL *Mix_EffectDone_t)(int chan, void *udata); + + +/* Register a special effect function. At mixing time, the channel data is + * copied into a buffer and passed through each registered effect function. + * After it passes through all the functions, it is mixed into the final + * output stream. The copy to buffer is performed once, then each effect + * function performs on the output of the previous effect. Understand that + * this extra copy to a buffer is not performed if there are no effects + * registered for a given chunk, which saves CPU cycles, and any given + * effect will be extra cycles, too, so it is crucial that your code run + * fast. Also note that the data that your function is given is in the + * format of the sound device, and not the format you gave to Mix_OpenAudio(), + * although they may in reality be the same. This is an unfortunate but + * necessary speed concern. Use Mix_QuerySpec() to determine if you can + * handle the data before you register your effect, and take appropriate + * actions. + * You may also specify a callback (Mix_EffectDone_t) that is called when + * the channel finishes playing. This gives you a more fine-grained control + * than Mix_ChannelFinished(), in case you need to free effect-specific + * resources, etc. If you don't need this, you can specify NULL. + * You may set the callbacks before or after calling Mix_PlayChannel(). + * Things like Mix_SetPanning() are just internal special effect functions, + * so if you are using that, you've already incurred the overhead of a copy + * to a separate buffer, and that these effects will be in the queue with + * any functions you've registered. The list of registered effects for a + * channel is reset when a chunk finishes playing, so you need to explicitly + * set them with each call to Mix_PlayChannel*(). + * You may also register a special effect function that is to be run after + * final mixing occurs. The rules for these callbacks are identical to those + * in Mix_RegisterEffect, but they are run after all the channels and the + * music have been mixed into a single stream, whereas channel-specific + * effects run on a given channel before any other mixing occurs. These + * global effect callbacks are call "posteffects". Posteffects only have + * their Mix_EffectDone_t function called when they are unregistered (since + * the main output stream is never "done" in the same sense as a channel). + * You must unregister them manually when you've had enough. Your callback + * will be told that the channel being mixed is (MIX_CHANNEL_POST) if the + * processing is considered a posteffect. + * + * After all these effects have finished processing, the callback registered + * through Mix_SetPostMix() runs, and then the stream goes to the audio + * device. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + * + * returns zero if error (no such channel), nonzero if added. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, Mix_EffectDone_t d, void *arg); + + +/* You may not need to call this explicitly, unless you need to stop an + * effect from processing in the middle of a chunk's playback. + * Posteffects are never implicitly unregistered as they are for channels, + * but they may be explicitly unregistered through this function by + * specifying MIX_CHANNEL_POST for a channel. + * returns zero if error (no such channel or effect), nonzero if removed. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f); + + +/* You may not need to call this explicitly, unless you need to stop all + * effects from processing in the middle of a chunk's playback. Note that + * this will also shut off some internal effect processing, since + * Mix_SetPanning() and others may use this API under the hood. This is + * called internally when a channel completes playback. + * Posteffects are never implicitly unregistered as they are for channels, + * but they may be explicitly unregistered through this function by + * specifying MIX_CHANNEL_POST for a channel. + * returns zero if error (no such channel), nonzero if all effects removed. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_UnregisterAllEffects(int channel); + + +#define MIX_EFFECTSMAXSPEED "MIX_EFFECTSMAXSPEED" + +/* + * These are the internally-defined mixing effects. They use the same API that + * effects defined in the application use, but are provided here as a + * convenience. Some effects can reduce their quality or use more memory in + * the name of speed; to enable this, make sure the environment variable + * MIX_EFFECTSMAXSPEED (see above) is defined before you call + * Mix_OpenAudio(). + */ + + +/* Set the panning of a channel. The left and right channels are specified + * as integers between 0 and 255, quietest to loudest, respectively. + * + * Technically, this is just individual volume control for a sample with + * two (stereo) channels, so it can be used for more than just panning. + * If you want real panning, call it like this: + * + * Mix_SetPanning(channel, left, 255 - left); + * + * ...which isn't so hard. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the panning will be done to the final mixed stream before passing it on + * to the audio device. + * + * This uses the Mix_RegisterEffect() API internally, and returns without + * registering the effect function if the audio device is not configured + * for stereo output. Setting both (left) and (right) to 255 causes this + * effect to be unregistered, since that is the data's normal state. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if panning effect enabled. Note that an audio device in mono + * mode is a no-op, but this call will return successful in that case. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetPanning(int channel, Uint8 left, Uint8 right); + + +/* Set the position of a channel. (angle) is an integer from 0 to 360, that + * specifies the location of the sound in relation to the listener. (angle) + * will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260). + * Angle 0 is due north, and rotates clockwise as the value increases. + * For efficiency, the precision of this effect may be limited (angles 1 + * through 7 might all produce the same effect, 8 through 15 are equal, etc). + * (distance) is an integer between 0 and 255 that specifies the space + * between the sound and the listener. The larger the number, the further + * away the sound is. Using 255 does not guarantee that the channel will be + * culled from the mixing process or be completely silent. For efficiency, + * the precision of this effect may be limited (distance 0 through 5 might + * all produce the same effect, 6 through 10 are equal, etc). Setting (angle) + * and (distance) to 0 unregisters this effect, since the data would be + * unchanged. + * + * If you need more precise positional audio, consider using OpenAL for + * spatialized effects instead of SDL_mixer. This is only meant to be a + * basic effect for simple "3D" games. + * + * If the audio device is configured for mono output, then you won't get + * any effectiveness from the angle; however, distance attenuation on the + * channel will still occur. While this effect will function with stereo + * voices, it makes more sense to use voices with only one channel of sound, + * so when they are mixed through this effect, the positioning will sound + * correct. You can convert them to mono through SDL before giving them to + * the mixer in the first place if you like. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the positioning will be done to the final mixed stream before passing it + * on to the audio device. + * + * This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning(). + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if position effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetPosition(int channel, Sint16 angle, Uint8 distance); + + +/* Set the "distance" of a channel. (distance) is an integer from 0 to 255 + * that specifies the location of the sound in relation to the listener. + * Distance 0 is overlapping the listener, and 255 is as far away as possible + * A distance of 255 does not guarantee silence; in such a case, you might + * want to try changing the chunk's volume, or just cull the sample from the + * mixing process with Mix_HaltChannel(). + * For efficiency, the precision of this effect may be limited (distances 1 + * through 7 might all produce the same effect, 8 through 15 are equal, etc). + * (distance) is an integer between 0 and 255 that specifies the space + * between the sound and the listener. The larger the number, the further + * away the sound is. + * Setting (distance) to 0 unregisters this effect, since the data would be + * unchanged. + * If you need more precise positional audio, consider using OpenAL for + * spatialized effects instead of SDL_mixer. This is only meant to be a + * basic effect for simple "3D" games. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the distance attenuation will be done to the final mixed stream before + * passing it on to the audio device. + * + * This uses the Mix_RegisterEffect() API internally. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if position effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetDistance(int channel, Uint8 distance); + + +/* + * !!! FIXME : Haven't implemented, since the effect goes past the + * end of the sound buffer. Will have to think about this. + * --ryan. + */ +#if 0 +/* Causes an echo effect to be mixed into a sound. (echo) is the amount + * of echo to mix. 0 is no echo, 255 is infinite (and probably not + * what you want). + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the reverbing will be done to the final mixed stream before passing it on + * to the audio device. + * + * This uses the Mix_RegisterEffect() API internally. If you specify an echo + * of zero, the effect is unregistered, as the data is already in that state. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if reversing effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern no_parse_DECLSPEC int SDLCALL Mix_SetReverb(int channel, Uint8 echo); +#endif + +/* Causes a channel to reverse its stereo. This is handy if the user has his + * speakers hooked up backwards, or you would like to have a minor bit of + * psychedelia in your sound code. :) Calling this function with (flip) + * set to non-zero reverses the chunks's usual channels. If (flip) is zero, + * the effect is unregistered. + * + * This uses the Mix_RegisterEffect() API internally, and thus is probably + * more CPU intensive than having the user just plug in his speakers + * correctly. Mix_SetReverseStereo() returns without registering the effect + * function if the audio device is not configured for stereo output. + * + * If you specify MIX_CHANNEL_POST for (channel), then this the effect is used + * on the final mixed stream before sending it on to the audio device (a + * posteffect). + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if reversing effect is enabled. Note that an audio device in mono + * mode is a no-op, but this call will return successful in that case. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetReverseStereo(int channel, int flip); + +/* end of effects API. --ryan. */ + + +/* Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate + them dynamically to the next sample if requested with a -1 value below. + Returns the number of reserved channels. + */ +extern DECLSPEC int SDLCALL Mix_ReserveChannels(int num); + +/* Channel grouping functions */ + +/* Attach a tag to a channel. A tag can be assigned to several mixer + channels, to form groups of channels. + If 'tag' is -1, the tag is removed (actually -1 is the tag used to + represent the group of all the channels). + Returns true if everything was OK. + */ +extern DECLSPEC int SDLCALL Mix_GroupChannel(int which, int tag); +/* Assign several consecutive channels to a group */ +extern DECLSPEC int SDLCALL Mix_GroupChannels(int from, int to, int tag); +/* Finds the first available channel in a group of channels, + returning -1 if none are available. + */ +extern DECLSPEC int SDLCALL Mix_GroupAvailable(int tag); +/* Returns the number of channels in a group. This is also a subtle + way to get the total number of channels when 'tag' is -1 + */ +extern DECLSPEC int SDLCALL Mix_GroupCount(int tag); +/* Finds the "oldest" sample playing in a group of channels */ +extern DECLSPEC int SDLCALL Mix_GroupOldest(int tag); +/* Finds the "most recent" (i.e. last) sample playing in a group of channels */ +extern DECLSPEC int SDLCALL Mix_GroupNewer(int tag); + +/* Play an audio chunk on a specific channel. + If the specified channel is -1, play on the first free channel. + If 'loops' is greater than zero, loop the sound that many times. + If 'loops' is -1, loop inifinitely (~65000 times). + Returns which channel was used to play the sound. +*/ +#define Mix_PlayChannel(channel,chunk,loops) Mix_PlayChannelTimed(channel,chunk,loops,-1) +/* The same as above, but the sound is played at most 'ticks' milliseconds */ +extern DECLSPEC int SDLCALL Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks); +extern DECLSPEC int SDLCALL Mix_PlayMusic(Mix_Music *music, int loops); +#define Mix_PlayChannelVol(channel,chunk,loops,vol) Mix_PlayChannelTimedVolume(channel,chunk,loops,-1,vol)/*MIXER-X*/ +extern DECLSPEC int SDLCALL Mix_PlayChannelTimedVolume(int which, Mix_Chunk *chunk, int loops, int ticks, int volume);/*MIXER-X*/ + +/* Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions */ +extern DECLSPEC int SDLCALL Mix_FadeInMusic(Mix_Music *music, int loops, int ms); +extern DECLSPEC int SDLCALL Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position); +#define Mix_FadeInChannel(channel,chunk,loops,ms) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1) +extern DECLSPEC int SDLCALL Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ms, int ticks); +#define Mix_FadeInChannelVolume(channel,chunk,loops,ms,vol) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1,vol)/*MIXER-X*/ +extern DECLSPEC int SDLCALL Mix_FadeInChannelTimedVolume(int which, Mix_Chunk *chunk, int loops, int ms, int ticks, int volume);/*MIXER-X*/ + + +/* Set the volume in the range of 0-128 of a specific channel or chunk. + If the specified channel is -1, set volume for all channels. + Returns the original volume. + If the specified volume is -1, just return the current volume. +*/ +extern DECLSPEC int SDLCALL Mix_Volume(int channel, int volume); +extern DECLSPEC int SDLCALL Mix_VolumeChunk(Mix_Chunk *chunk, int volume); +extern DECLSPEC int SDLCALL Mix_VolumeMusic(int volume); + +/* Halt playing of a particular channel */ +extern DECLSPEC int SDLCALL Mix_HaltChannel(int channel); +extern DECLSPEC int SDLCALL Mix_HaltGroup(int tag); +extern DECLSPEC int SDLCALL Mix_HaltMusic(void); + +/* Change the expiration delay for a particular channel. + The sample will stop playing after the 'ticks' milliseconds have elapsed, + or remove the expiration if 'ticks' is -1 +*/ +extern DECLSPEC int SDLCALL Mix_ExpireChannel(int channel, int ticks); + +/* Halt a channel, fading it out progressively till it's silent + The ms parameter indicates the number of milliseconds the fading + will take. + */ +extern DECLSPEC int SDLCALL Mix_FadeOutChannel(int which, int ms); +extern DECLSPEC int SDLCALL Mix_FadeOutGroup(int tag, int ms); +extern DECLSPEC int SDLCALL Mix_FadeOutMusic(int ms); + +/* Query the fading status of a channel */ +extern DECLSPEC Mix_Fading SDLCALL Mix_FadingMusic(void); +extern DECLSPEC Mix_Fading SDLCALL Mix_FadingChannel(int which); + +/* Pause/Resume a particular channel */ +extern DECLSPEC void SDLCALL Mix_Pause(int channel); +extern DECLSPEC void SDLCALL Mix_Resume(int channel); +extern DECLSPEC int SDLCALL Mix_Paused(int channel); + +/* Pause/Resume the music stream */ +extern DECLSPEC void SDLCALL Mix_PauseMusic(void); +extern DECLSPEC void SDLCALL Mix_ResumeMusic(void); +extern DECLSPEC void SDLCALL Mix_RewindMusic(void); +extern DECLSPEC int SDLCALL Mix_PausedMusic(void); + +/* Set the current position in the music stream. + This returns 0 if successful, or -1 if it failed or isn't implemented. + This function is only implemented for MOD music formats (set pattern + order number) and for WAV, OGG, FLAC, MP3_MAD, MP3_MPG, and MODPLUG music + (set position in seconds), at the moment. +*/ +extern DECLSPEC int SDLCALL Mix_SetMusicPosition(double position); +/* + Get the time current position of music stream + returns -1.0 if this feature is not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicPosition(Mix_Music *music); +/* + Get the total time length of music stream + returns -1.0 if this feature is not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicTotalTime(Mix_Music *music); + +/* + Get the loop start time position of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicLoopStartTime(Mix_Music *music); +/* + Get the loop end time position of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicLoopEndTime(Mix_Music *music); +/* + Get the loop time length of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicLoopLengthTime(Mix_Music *music); + + +/* Check the status of a specific channel. + If the specified channel is -1, check all channels. +*/ +extern DECLSPEC int SDLCALL Mix_Playing(int channel); +extern DECLSPEC int SDLCALL Mix_PlayingMusic(void); + +/* Stop music and set external music playback command */ +extern DECLSPEC int SDLCALL Mix_SetMusicCMD(const char *command); + +/* Synchro value is set by MikMod from modules while playing */ +extern DECLSPEC int SDLCALL Mix_SetSynchroValue(int value); +extern DECLSPEC int SDLCALL Mix_GetSynchroValue(void); + +/* Set/Get/Iterate SoundFonts paths to use by supported MIDI backends */ +extern DECLSPEC int SDLCALL Mix_SetSoundFonts(const char *paths); +extern DECLSPEC const char* SDLCALL Mix_GetSoundFonts(void); +extern DECLSPEC int SDLCALL Mix_EachSoundFont(int (SDLCALL *function)(const char*, void*), void *data); + +/* Get the Mix_Chunk currently associated with a mixer channel + Returns NULL if it's an invalid channel, or there's no chunk associated. +*/ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_GetChunk(int channel); + +/* Close the mixer, halting all playing audio */ +extern DECLSPEC void SDLCALL Mix_CloseAudio(void); + +/* Add additional Timidity bank path */ +extern DECLSPEC void SDLCALL Mix_Timidity_addToPathList(const char *path); + +/* ADLMIDI Setup functions */ +/* Get count of available hardcoded banks */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getTotalBanks(void); +/* Get array of the bank names */ +extern DECLSPEC const char *const *SDLCALL Mix_ADLMIDI_getBankNames(void); +/* Get bank ID */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getBankID(void); +/* Set bank ID (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setBankID(int bnk); +/* Get state of deep vibrato */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getTremolo(void); +/* Set deep tremolo mode (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setTremolo(int tr); +/* Get state of deep vibrato */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getVibrato(void); +/* Set deep vibrato mode (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setVibrato(int vib); +/* Get state of scalable modulation mode */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getScaleMod(void); +/* Set scalable modulation mode (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setScaleMod(int sc); +/* Get state of adlib drums mode */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getAdLibMode(void); +/* Set adlib drums mode mode (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setAdLibMode(int tr); +/* Get state of logarithmic mode */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getLogarithmicVolumes(void); +/* Set logarithmic volumes mode in the generic/CMF volume models (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setLogarithmicVolumes(int lv); +/* Get current volume model ID */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getVolumeModel(void); +/* Change current volumes model (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setVolumeModel(int vm); +/* Get full range mode for CC74-Brightness controller */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getFullRangeBrightness(void); +/* Set full range mode for CC74-Brightness controller */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setFullRangeBrightness(int frb); +/* Get the current OPL3 Emulator for ADLMIDI */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getEmulator(void); +/* Select the OPL3 Emulator for ADLMIDI */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setEmulator(int emu); +/* Reset all ADLMIDI properties to default state */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setSetDefaults(void); + +/* Sets WOPL bank file for ADLMIDI playing device, affects on MIDI file reopen */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setCustomBankFile(const char *bank_wonl_path); + +/* Reset all OPNMIDI properties to default state */ +extern DECLSPEC void SDLCALL Mix_OPNMIDI_setSetDefaults(void); +/* Get full range mode for CC74-Brightness controller */ +extern DECLSPEC int SDLCALL Mix_OPNMIDI_getFullRangeBrightness(void); +/* Set full range mode for CC74-Brightness controller */ +extern DECLSPEC void SDLCALL Mix_OPNMIDI_setFullRangeBrightness(int frb); +/* Get the OPN2 Emulator for OPNMIDI */ +extern DECLSPEC int SDLCALL Mix_OPNMIDI_getEmulator(void); +/* Select the OPN2 Emulator for OPNMIDI */ +extern DECLSPEC void SDLCALL Mix_OPNMIDI_setEmulator(int emu); +/* Sets WOPN bank file for OPNMIDI playing device, affects on MIDI file reopen */ +extern DECLSPEC void SDLCALL Mix_OPNMIDI_setCustomBankFile(const char *bank_wonp_path); + +/* Get type of MIDI player library currently in use */ +extern DECLSPEC int SDLCALL Mix_GetMidiPlayer(void); + +/* Get type of MIDI player library prepared for next opening of MIDI file */ +extern DECLSPEC int SDLCALL Mix_GetNextMidiPlayer(void); + +/* Set the MIDI playing library (ADLMIDI, Timidity, Native MIDI (if available) and FluidSynth) */ +extern DECLSPEC int SDLCALL Mix_SetMidiPlayer(int player); + +/* Disables support of MIDI file arguments */ +extern DECLSPEC void SDLCALL Mix_SetLockMIDIArgs(int lock_midiargs); + +/* DEPRECATED NAMES for new-added SDL Mixer X functions + Those names are made with mistake - beginning with "MIX_" than "Mix_" + which makes confusion when you looking for Mix_ function in your IDE + because some applications are still use them, to don't break ABI we will keep those + aliases until we will remove all usages of them from applications and libraries are used them +*/ +DEPRECATED(extern DECLSPEC int SDLCALL Mix_GetMidiDevice(void)); +DEPRECATED(extern DECLSPEC int SDLCALL Mix_GetNextMidiDevice(void)); +DEPRECATED(extern DECLSPEC int SDLCALL Mix_SetMidiDevice(int player)); + +/* We'll use SDL for reporting errors */ +#define Mix_SetError SDL_SetError +#define Mix_GetError SDL_GetError +#define Mix_ClearError SDL_ClearError + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* SDL_MIXER_H_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/begin_code.h b/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/begin_code.h new file mode 100644 index 000000000..6c2106246 --- /dev/null +++ b/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/begin_code.h @@ -0,0 +1,167 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + 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. +*/ + +/** + * \file begin_code.h + * + * This file sets things up for C dynamic library function definitions, + * static inlined functions, and structures aligned at 4-byte alignment. + * If you don't like ugly C preprocessor code, don't look at this file. :) + */ + +/* This shouldn't be nested -- included it around code only. */ +#ifdef _begin_code_h +#error Nested inclusion of begin_code.h +#endif +#define _begin_code_h + +#ifndef SDL_DEPRECATED +# if (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */ +# define SDL_DEPRECATED __attribute__((deprecated)) +# else +# define SDL_DEPRECATED +# endif +#endif + +#ifndef SDL_UNUSED +# ifdef __GNUC__ +# define SDL_UNUSED __attribute__((unused)) +# else +# define SDL_UNUSED +# endif +#endif + +/* Some compilers use a special export keyword */ +#ifndef DECLSPEC +# if defined(__WIN32__) || defined(__WINRT__) +# ifdef __BORLANDC__ +# ifdef BUILD_SDL +# define DECLSPEC +# else +# define DECLSPEC __declspec(dllimport) +# endif +# else +# define DECLSPEC __declspec(dllexport) +# endif +# elif defined(__OS2__) +# ifdef BUILD_SDL +# define DECLSPEC __declspec(dllexport) +# else +# define DECLSPEC +# endif +# else +# if defined(__GNUC__) && __GNUC__ >= 4 +# define DECLSPEC __attribute__ ((visibility("default"))) +# else +# define DECLSPEC +# endif +# endif +#endif + +/* By default SDL uses the C calling convention */ +#ifndef SDLCALL +#if (defined(__WIN32__) || defined(__WINRT__)) && !defined(__GNUC__) +#define SDLCALL __cdecl +#elif defined(__OS2__) || defined(__EMX__) +#define SDLCALL _System +# if defined (__GNUC__) && !defined(_System) +# define _System /* for old EMX/GCC compat. */ +# endif +#else +#define SDLCALL +#endif +#endif /* SDLCALL */ + +/* Removed DECLSPEC on Symbian OS because SDL cannot be a DLL in EPOC */ +#ifdef __SYMBIAN32__ +#undef DECLSPEC +#define DECLSPEC +#endif /* __SYMBIAN32__ */ + +/* Force structure packing at 4 byte alignment. + This is necessary if the header is included in code which has structure + packing set to an alternate value, say for loading structures from disk. + The packing is reset to the previous value in close_code.h + */ +#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) +#ifdef _MSC_VER +#pragma warning(disable: 4103) +#endif +#ifdef __BORLANDC__ +#pragma nopackwarning +#endif +#ifdef _M_X64 +/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */ +#pragma pack(push,8) +#else +#pragma pack(push,4) +#endif +#endif /* Compiler needs structure packing set */ + +#ifndef SDL_INLINE +#if defined(__GNUC__) +#define SDL_INLINE __inline__ +#elif defined(_MSC_VER) || defined(__BORLANDC__) || \ + defined(__DMC__) || defined(__SC__) || \ + defined(__WATCOMC__) || defined(__LCC__) || \ + defined(__DECC) || defined(__CC_ARM) +#define SDL_INLINE __inline +#ifndef __inline__ +#define __inline__ __inline +#endif +#else +#define SDL_INLINE inline +#ifndef __inline__ +#define __inline__ inline +#endif +#endif +#endif /* SDL_INLINE not defined */ + +#ifndef SDL_FORCE_INLINE +#if defined(_MSC_VER) +#define SDL_FORCE_INLINE __forceinline +#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) ) +#define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__ +#else +#define SDL_FORCE_INLINE static SDL_INLINE +#endif +#endif /* SDL_FORCE_INLINE not defined */ + +#ifndef SDL_NORETURN +#if defined(__GNUC__) +#define SDL_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define SDL_NORETURN __declspec(noreturn) +#else +#define SDL_NORETURN +#endif +#endif /* SDL_NORETURN not defined */ + +/* Apparently this is needed by several Windows compilers */ +#if !defined(__MACH__) +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif /* NULL */ +#endif /* ! Mac OS X - breaks precompiled headers */ diff --git a/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/close_code.h b/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/close_code.h new file mode 100644 index 000000000..b3b70a4c8 --- /dev/null +++ b/libs/SDLMixerX/i686-w64-mingw32/include/SDL2/close_code.h @@ -0,0 +1,37 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + 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. +*/ + +/** + * \file close_code.h + * + * This file reverses the effects of begin_code.h and should be included + * after you finish any function and structure declarations in your headers + */ + +#undef _begin_code_h + +/* Reset structure packing at previous byte alignment */ +#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) +#ifdef __BORLANDC__ +#pragma nopackwarning +#endif +#pragma pack(pop) +#endif /* Compiler needs structure packing set */ diff --git a/libs/SDLMixerX/i686-w64-mingw32/lib/libSDL2_mixer_ext-static.a b/libs/SDLMixerX/i686-w64-mingw32/lib/libSDL2_mixer_ext-static.a new file mode 100644 index 000000000..8a59b5a61 Binary files /dev/null and b/libs/SDLMixerX/i686-w64-mingw32/lib/libSDL2_mixer_ext-static.a differ diff --git a/libs/SDLMixerX/i686-w64-mingw32/lib/libSDL2_mixer_ext.dll.a b/libs/SDLMixerX/i686-w64-mingw32/lib/libSDL2_mixer_ext.dll.a new file mode 100644 index 000000000..b5e43ef62 Binary files /dev/null and b/libs/SDLMixerX/i686-w64-mingw32/lib/libSDL2_mixer_ext.dll.a differ diff --git a/libs/SDLMixerX/x86_64-w64-mingw32/bin/SDL2_mixer_ext.dll b/libs/SDLMixerX/x86_64-w64-mingw32/bin/SDL2_mixer_ext.dll new file mode 100644 index 000000000..7762d5e8d Binary files /dev/null and b/libs/SDLMixerX/x86_64-w64-mingw32/bin/SDL2_mixer_ext.dll differ diff --git a/libs/SDLMixerX/x86_64-w64-mingw32/bin/libfluidsynth-2.dll b/libs/SDLMixerX/x86_64-w64-mingw32/bin/libfluidsynth-2.dll new file mode 100644 index 000000000..5dbcac34a Binary files /dev/null and b/libs/SDLMixerX/x86_64-w64-mingw32/bin/libfluidsynth-2.dll differ diff --git a/libs/SDLMixerX/x86_64-w64-mingw32/bin/libgcc_s_sjlj-1.dll b/libs/SDLMixerX/x86_64-w64-mingw32/bin/libgcc_s_sjlj-1.dll new file mode 100644 index 000000000..9684a2155 Binary files /dev/null and b/libs/SDLMixerX/x86_64-w64-mingw32/bin/libgcc_s_sjlj-1.dll differ diff --git a/libs/SDLMixerX/x86_64-w64-mingw32/bin/libstdc++-6.dll b/libs/SDLMixerX/x86_64-w64-mingw32/bin/libstdc++-6.dll new file mode 100644 index 000000000..220099c40 Binary files /dev/null and b/libs/SDLMixerX/x86_64-w64-mingw32/bin/libstdc++-6.dll differ diff --git a/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/SDL_mixer_ext.h b/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/SDL_mixer_ext.h new file mode 100644 index 000000000..3a6b91b50 --- /dev/null +++ b/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/SDL_mixer_ext.h @@ -0,0 +1,867 @@ +/* + SDL Mixer X: An extended audio mixer library, forked from SDL_mixer + Copyright (C) 2014-2018 Vitaly Novichkov + + SDL_mixer: An audio mixer library based on the SDL library + Copyright (C) 1997-2018 Sam Lantinga + + 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. +*/ + +#ifndef SDL_MIXER_H_ +#define SDL_MIXER_H_ + +#include "SDL_stdinc.h" +#include "SDL_rwops.h" +#include "SDL_audio.h" +#include "SDL_endian.h" +#include "SDL_version.h" +#include "begin_code.h" + +/* Let applications recogonize which SDL Mixer edition is in use: Official or Extended fork by Wohlstand */ +#define SDL_MIXER_X 1 + +#define MIXSDLCALL + +#if defined(FORCE_STDCALLS) && defined(_WIN32) +#ifdef SDLCALL +#undef SDLCALL +#endif +#define SDLCALL __stdcall +#define SDLCALLCC __stdcall +#else +#define SDLCALLCC +#endif + +#ifndef DEPRECATED +#ifdef __GNUC__ +#define DEPRECATED(func) func __attribute__ ((deprecated)) +#elif defined(_MSC_VER) +#define DEPRECATED(func) __declspec(deprecated) func +#else +#pragma message("WARNING: You need to implement DEPRECATED for this compiler") +#define DEPRECATED(func) func +#endif +#endif + +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +extern "C" { +#endif + +/* Printable format: "%d.%d.%d", MAJOR, MINOR, PATCHLEVEL +*/ +#define SDL_MIXER_MAJOR_VERSION 2 +#define SDL_MIXER_MINOR_VERSION 2 +#define SDL_MIXER_PATCHLEVEL 0 + +/* This macro can be used to fill a version structure with the compile-time + * version of the SDL_mixer library. + */ +#define SDL_MIXER_VERSION(X) \ +{ \ + (X)->major = SDL_MIXER_MAJOR_VERSION; \ + (X)->minor = SDL_MIXER_MINOR_VERSION; \ + (X)->patch = SDL_MIXER_PATCHLEVEL; \ +} + +/* Backwards compatibility */ +#define MIX_MAJOR_VERSION SDL_MIXER_MAJOR_VERSION +#define MIX_MINOR_VERSION SDL_MIXER_MINOR_VERSION +#define MIX_PATCHLEVEL SDL_MIXER_PATCHLEVEL +#define MIX_VERSION(X) SDL_MIXER_VERSION(X) + +/** + * This is the version number macro for the current SDL_mixer version. + */ +#define SDL_MIXER_COMPILEDVERSION \ + SDL_VERSIONNUM(SDL_MIXER_MAJOR_VERSION, SDL_MIXER_MINOR_VERSION, SDL_MIXER_PATCHLEVEL) + +/** + * This macro will evaluate to true if compiled with SDL_mixer at least X.Y.Z. + */ +#define SDL_MIXER_VERSION_ATLEAST(X, Y, Z) \ + (SDL_MIXER_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) + +/* This function gets the version of the dynamically linked SDL_mixer library. + it should NOT be used to fill a version structure, instead you should + use the SDL_MIXER_VERSION() macro. + */ +extern DECLSPEC const SDL_version * SDLCALL Mix_Linked_Version(void); + +typedef enum +{ + MIX_INIT_FLAC = 0x00000001, + MIX_INIT_MOD = 0x00000002, + MIX_INIT_MP3 = 0x00000008, + MIX_INIT_OGG = 0x00000010, + MIX_INIT_MID = 0x00000020, + MIX_INIT_OPUS = 0x00000040 +} MIX_InitFlags; + +/* Loads dynamic libraries and prepares them for use. Flags should be + one or more flags from MIX_InitFlags OR'd together. + It returns the flags successfully initialized, or 0 on failure. + */ +extern DECLSPEC int SDLCALL Mix_Init(int flags); + +/* Unloads libraries loaded with Mix_Init */ +extern DECLSPEC void SDLCALL Mix_Quit(void); + + +/* The default mixer has 8 simultaneous mixing channels */ +#ifndef MIX_CHANNELS +#define MIX_CHANNELS 8 +#endif + +/* Good default values for a PC soundcard */ +#define MIX_DEFAULT_FREQUENCY 44100 +#if SDL_BYTEORDER == SDL_LIL_ENDIAN +#define MIX_DEFAULT_FORMAT AUDIO_S16LSB +#else +#define MIX_DEFAULT_FORMAT AUDIO_S16MSB +#endif +#define MIX_DEFAULT_CHANNELS 2 +#define MIX_MAX_VOLUME SDL_MIX_MAXVOLUME /* Volume of a chunk */ + +/* The internal format for an audio chunk */ +typedef struct Mix_Chunk { + int allocated; + Uint8 *abuf; + Uint32 alen; + Uint8 volume; /* Per-sample volume, 0-128 */ +} Mix_Chunk; + +/* The different fading types supported */ +typedef enum { + MIX_NO_FADING, + MIX_FADING_OUT, + MIX_FADING_IN +} Mix_Fading; + +/* These are types of music files (not libraries used to load them) */ +typedef enum { + MUS_NONE, + MUS_CMD, + MUS_WAV, + MUS_MOD, + MUS_MID, + MUS_OGG, + MUS_MP3, + MUS_MP3_MAD_UNUSED, + MUS_FLAC, + MUS_MODPLUG_UNUSED, + MUS_OPUS, + MUS_GME, + MUS_ADLMIDI/*Use ADLMIDI coded for super-special formats like IMF, MUS or XMI are can't be played without ADLMIDI*/ +} Mix_MusicType; + +typedef enum { + MIDI_ADLMIDI, + MIDI_Native, + MIDI_Timidity, + MIDI_OPNMIDI, + MIDI_Fluidsynth, + MIDI_ANY, + MIDI_KnuwnDevices /* Count of MIDI device types */ +} Mix_MIDI_Device; + +/* Volume model type in the ADLMIDI */ +typedef enum { + ADLMIDI_VM_AUTO, + ADLMIDI_VM_GENERIC, + ADLMIDI_VM_CMF, + ADLMIDI_VM_DMX, + ADLMIDI_VM_APOGEE, + ADLMIDI_VM_9X +} Mix_ADLMIDI_VolumeModel; + +/* OPL3 chip emulators for ADLMIDI */ +typedef enum { + ADLMIDI_OPL3_EMU_DEFAULT = -1, + ADLMIDI_OPL3_EMU_NUKED = 0, + ADLMIDI_OPL3_EMU_NUKED_1_7_4, + ADLMIDI_OPL3_EMU_DOSBOX, +} Mix_ADLMIDI_Emulator; + +/* OPN2 chip emulators for OPNMIDI */ +typedef enum { + OPNMIDI_OPN2_EMU_DEFAULT = -1, + OPNMIDI_OPN2_EMU_MIME = 0, + OPNMIDI_OPN2_EMU_NUKED, + OPNMIDI_OPN2_EMU_GENS, +} Mix_OPNMIDI_Emulator; + +/* The internal format for a music chunk interpreted via mikmod */ +typedef struct _Mix_Music Mix_Music; + +/* Open the mixer with a certain audio format */ +extern DECLSPEC int SDLCALL Mix_OpenAudio(int frequency, Uint16 format, int channels, int chunksize); + +/* Open the mixer with specific device and certain audio format */ +extern DECLSPEC int SDLCALL Mix_OpenAudioDevice(int frequency, Uint16 format, int channels, int chunksize, const char* device, int allowed_changes); + +/* Dynamically change the number of channels managed by the mixer. + If decreasing the number of channels, the upper channels are + stopped. + This function returns the new number of allocated channels. + */ +extern DECLSPEC int SDLCALL Mix_AllocateChannels(int numchans); + +/* Find out what the actual audio device parameters are. + This function returns 1 if the audio has been opened, 0 otherwise. + */ +extern DECLSPEC int SDLCALL Mix_QuerySpec(int *frequency,Uint16 *format,int *channels); + +/* Load a wave file or a music (.mod .s3m .it .xm) file + IMPORTANT: To choice a track number of NSF, GBM, HES, etc file, + you must append "|xxx" to end of file path for + Mix_LoadMUS function. + Where xxx - actual number of chip track, (from 0 to N-1) + Examples: "file.nsf|12", "file.hes|2" +*/ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_LoadWAV_RW(SDL_RWops *src, int freesrc); +#define Mix_LoadWAV(file) Mix_LoadWAV_RW(SDL_RWFromFile(file, "rb"), 1) +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS(const char *file); + +/* Load a music file from an SDL_RWop object + * Matt Campbell (matt@campbellhome.dhs.org) April 2000 */ +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUS_RW(SDL_RWops *src, int freesrc); + +/* Load a music file from an SDL_RWop object with custom arguments (trackID for GME or settings for a MIDI playing) + * Arguments are taking no effect for file formats which are not supports extra arguments. + */ +extern DECLSPEC Mix_Music *SDLCALL Mix_LoadMUS_RW_ARG(SDL_RWops *src, int freesrc, const char *args); + +/* Load a music file from an SDL_RWop object with custom trackID for GME. + * trackID argument takes no effect for non-NSF,HES,GBM,etc. file formats. + * Default value should be 0 + */ +extern DECLSPEC Mix_Music *SDLCALL Mix_LoadMUS_RW_GME(SDL_RWops *src, int freesrc, int trackID); + +/* Load a music file from an SDL_RWop object assuming a specific format */ +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW(SDL_RWops *src, Mix_MusicType type, int freesrc); + +/* Load a music file from an SDL_RWop object assuming a specific format + with custom arguments (trackID for GME or settings for a MIDI playing) */ +extern DECLSPEC Mix_Music * SDLCALL Mix_LoadMUSType_RW_ARG(SDL_RWops *src, Mix_MusicType type, int freesrc, const char *args); + +/* Load a wave file of the mixer format from a memory buffer */ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_WAV(Uint8 *mem); + +/* Load raw audio data of the mixer format from a memory buffer */ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_QuickLoad_RAW(Uint8 *mem, Uint32 len); + +/* Free an audio chunk previously loaded */ +extern DECLSPEC void SDLCALL Mix_FreeChunk(Mix_Chunk *chunk); +extern DECLSPEC void SDLCALL Mix_FreeMusic(Mix_Music *music); + +/* Get a list of chunk/music decoders that this build of SDL_mixer provides. + This list can change between builds AND runs of the program, if external + libraries that add functionality become available. + You must successfully call Mix_OpenAudio() before calling these functions. + This API is only available in SDL_mixer 1.2.9 and later. + + // usage... + int i; + const int total = Mix_GetNumChunkDecoders(); + for (i = 0; i < total; i++) + printf("Supported chunk decoder: [%s]\n", Mix_GetChunkDecoder(i)); + + Appearing in this list doesn't promise your specific audio file will + decode...but it's handy to know if you have, say, a functioning Timidity + install. + + These return values are static, read-only data; do not modify or free it. + The pointers remain valid until you call Mix_CloseAudio(). +*/ +extern DECLSPEC int SDLCALL Mix_GetNumChunkDecoders(void); +extern DECLSPEC const char * SDLCALL Mix_GetChunkDecoder(int index); +extern DECLSPEC SDL_bool SDLCALL Mix_HasChunkDecoder(const char *name); +extern DECLSPEC int SDLCALL Mix_GetNumMusicDecoders(void); +extern DECLSPEC const char * SDLCALL Mix_GetMusicDecoder(int index); +extern DECLSPEC SDL_bool SDLCALL Mix_HasMusicDecoder(const char *name); + +/* Find out the music format of a mixer music, or the currently playing + music, if 'music' is NULL. +*/ +extern DECLSPEC Mix_MusicType SDLCALL Mix_GetMusicType(const Mix_Music *music); + +/* Get music title from meta-tag if possible. If title tag is empty, filename will be returned */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicTitle(const Mix_Music *music); +/* Get music title from meta-tag if possible */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicTitleTag(const Mix_Music *music); +/* Get music artist from meta-tag if possible */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicArtistTag(const Mix_Music *music); +/* Get music album from meta-tag if possible */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicAlbumTag(const Mix_Music *music); +/* Get music copyright from meta-tag if possible */ +extern DECLSPEC const char *SDLCALL Mix_GetMusicCopyrightTag(const Mix_Music *music); + +/* Set a function that is called after all mixing is performed. + This can be used to provide real-time visual display of the audio stream + or add a custom mixer filter for the stream data. +*/ +extern DECLSPEC void SDLCALL Mix_SetPostMix(void (SDLCALL *mix_func)(void *udata, Uint8 *stream, int len), void *arg); + +/* Add your own music player or additional mixer function. + If 'mix_func' is NULL, the default music player is re-enabled. + */ +extern DECLSPEC void SDLCALL Mix_HookMusic(void (SDLCALL *mix_func)(void *udata, Uint8 *stream, int len), void *arg); + +/* Add your own callback for when the music has finished playing or when it is + * stopped from a call to Mix_HaltMusic. + */ +extern DECLSPEC void SDLCALL Mix_HookMusicFinished(void (SDLCALL *music_finished)(void)); + +/* Get a pointer to the user data for the current music hook */ +extern DECLSPEC void * SDLCALL Mix_GetMusicHookData(void); + +/* + * Add your own callback when a channel has finished playing. NULL + * to disable callback. The callback may be called from the mixer's audio + * callback or it could be called as a result of Mix_HaltChannel(), etc. + * do not call SDL_LockAudio() from this callback; you will either be + * inside the audio callback, or SDL_mixer will explicitly lock the audio + * before calling your callback. + */ +extern DECLSPEC void SDLCALL Mix_ChannelFinished(void (SDLCALL *channel_finished)(int channel)); + + +/* Special Effects API by ryan c. gordon. (icculus@icculus.org) */ + +#define MIX_CHANNEL_POST -2 + +/* This is the format of a special effect callback: + * + * myeffect(int chan, void *stream, int len, void *udata); + * + * (chan) is the channel number that your effect is affecting. (stream) is + * the buffer of data to work upon. (len) is the size of (stream), and + * (udata) is a user-defined bit of data, which you pass as the last arg of + * Mix_RegisterEffect(), and is passed back unmolested to your callback. + * Your effect changes the contents of (stream) based on whatever parameters + * are significant, or just leaves it be, if you prefer. You can do whatever + * you like to the buffer, though, and it will continue in its changed state + * down the mixing pipeline, through any other effect functions, then finally + * to be mixed with the rest of the channels and music for the final output + * stream. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + */ +typedef void (SDLCALL *Mix_EffectFunc_t)(int chan, void *stream, int len, void *udata); + +/* + * This is a callback that signifies that a channel has finished all its + * loops and has completed playback. This gets called if the buffer + * plays out normally, or if you call Mix_HaltChannel(), implicitly stop + * a channel via Mix_AllocateChannels(), or unregister a callback while + * it's still playing. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + */ +typedef void (SDLCALL *Mix_EffectDone_t)(int chan, void *udata); + + +/* Register a special effect function. At mixing time, the channel data is + * copied into a buffer and passed through each registered effect function. + * After it passes through all the functions, it is mixed into the final + * output stream. The copy to buffer is performed once, then each effect + * function performs on the output of the previous effect. Understand that + * this extra copy to a buffer is not performed if there are no effects + * registered for a given chunk, which saves CPU cycles, and any given + * effect will be extra cycles, too, so it is crucial that your code run + * fast. Also note that the data that your function is given is in the + * format of the sound device, and not the format you gave to Mix_OpenAudio(), + * although they may in reality be the same. This is an unfortunate but + * necessary speed concern. Use Mix_QuerySpec() to determine if you can + * handle the data before you register your effect, and take appropriate + * actions. + * You may also specify a callback (Mix_EffectDone_t) that is called when + * the channel finishes playing. This gives you a more fine-grained control + * than Mix_ChannelFinished(), in case you need to free effect-specific + * resources, etc. If you don't need this, you can specify NULL. + * You may set the callbacks before or after calling Mix_PlayChannel(). + * Things like Mix_SetPanning() are just internal special effect functions, + * so if you are using that, you've already incurred the overhead of a copy + * to a separate buffer, and that these effects will be in the queue with + * any functions you've registered. The list of registered effects for a + * channel is reset when a chunk finishes playing, so you need to explicitly + * set them with each call to Mix_PlayChannel*(). + * You may also register a special effect function that is to be run after + * final mixing occurs. The rules for these callbacks are identical to those + * in Mix_RegisterEffect, but they are run after all the channels and the + * music have been mixed into a single stream, whereas channel-specific + * effects run on a given channel before any other mixing occurs. These + * global effect callbacks are call "posteffects". Posteffects only have + * their Mix_EffectDone_t function called when they are unregistered (since + * the main output stream is never "done" in the same sense as a channel). + * You must unregister them manually when you've had enough. Your callback + * will be told that the channel being mixed is (MIX_CHANNEL_POST) if the + * processing is considered a posteffect. + * + * After all these effects have finished processing, the callback registered + * through Mix_SetPostMix() runs, and then the stream goes to the audio + * device. + * + * DO NOT EVER call SDL_LockAudio() from your callback function! + * + * returns zero if error (no such channel), nonzero if added. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_RegisterEffect(int chan, Mix_EffectFunc_t f, Mix_EffectDone_t d, void *arg); + + +/* You may not need to call this explicitly, unless you need to stop an + * effect from processing in the middle of a chunk's playback. + * Posteffects are never implicitly unregistered as they are for channels, + * but they may be explicitly unregistered through this function by + * specifying MIX_CHANNEL_POST for a channel. + * returns zero if error (no such channel or effect), nonzero if removed. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_UnregisterEffect(int channel, Mix_EffectFunc_t f); + + +/* You may not need to call this explicitly, unless you need to stop all + * effects from processing in the middle of a chunk's playback. Note that + * this will also shut off some internal effect processing, since + * Mix_SetPanning() and others may use this API under the hood. This is + * called internally when a channel completes playback. + * Posteffects are never implicitly unregistered as they are for channels, + * but they may be explicitly unregistered through this function by + * specifying MIX_CHANNEL_POST for a channel. + * returns zero if error (no such channel), nonzero if all effects removed. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_UnregisterAllEffects(int channel); + + +#define MIX_EFFECTSMAXSPEED "MIX_EFFECTSMAXSPEED" + +/* + * These are the internally-defined mixing effects. They use the same API that + * effects defined in the application use, but are provided here as a + * convenience. Some effects can reduce their quality or use more memory in + * the name of speed; to enable this, make sure the environment variable + * MIX_EFFECTSMAXSPEED (see above) is defined before you call + * Mix_OpenAudio(). + */ + + +/* Set the panning of a channel. The left and right channels are specified + * as integers between 0 and 255, quietest to loudest, respectively. + * + * Technically, this is just individual volume control for a sample with + * two (stereo) channels, so it can be used for more than just panning. + * If you want real panning, call it like this: + * + * Mix_SetPanning(channel, left, 255 - left); + * + * ...which isn't so hard. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the panning will be done to the final mixed stream before passing it on + * to the audio device. + * + * This uses the Mix_RegisterEffect() API internally, and returns without + * registering the effect function if the audio device is not configured + * for stereo output. Setting both (left) and (right) to 255 causes this + * effect to be unregistered, since that is the data's normal state. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if panning effect enabled. Note that an audio device in mono + * mode is a no-op, but this call will return successful in that case. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetPanning(int channel, Uint8 left, Uint8 right); + + +/* Set the position of a channel. (angle) is an integer from 0 to 360, that + * specifies the location of the sound in relation to the listener. (angle) + * will be reduced as neccesary (540 becomes 180 degrees, -100 becomes 260). + * Angle 0 is due north, and rotates clockwise as the value increases. + * For efficiency, the precision of this effect may be limited (angles 1 + * through 7 might all produce the same effect, 8 through 15 are equal, etc). + * (distance) is an integer between 0 and 255 that specifies the space + * between the sound and the listener. The larger the number, the further + * away the sound is. Using 255 does not guarantee that the channel will be + * culled from the mixing process or be completely silent. For efficiency, + * the precision of this effect may be limited (distance 0 through 5 might + * all produce the same effect, 6 through 10 are equal, etc). Setting (angle) + * and (distance) to 0 unregisters this effect, since the data would be + * unchanged. + * + * If you need more precise positional audio, consider using OpenAL for + * spatialized effects instead of SDL_mixer. This is only meant to be a + * basic effect for simple "3D" games. + * + * If the audio device is configured for mono output, then you won't get + * any effectiveness from the angle; however, distance attenuation on the + * channel will still occur. While this effect will function with stereo + * voices, it makes more sense to use voices with only one channel of sound, + * so when they are mixed through this effect, the positioning will sound + * correct. You can convert them to mono through SDL before giving them to + * the mixer in the first place if you like. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the positioning will be done to the final mixed stream before passing it + * on to the audio device. + * + * This is a convenience wrapper over Mix_SetDistance() and Mix_SetPanning(). + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if position effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetPosition(int channel, Sint16 angle, Uint8 distance); + + +/* Set the "distance" of a channel. (distance) is an integer from 0 to 255 + * that specifies the location of the sound in relation to the listener. + * Distance 0 is overlapping the listener, and 255 is as far away as possible + * A distance of 255 does not guarantee silence; in such a case, you might + * want to try changing the chunk's volume, or just cull the sample from the + * mixing process with Mix_HaltChannel(). + * For efficiency, the precision of this effect may be limited (distances 1 + * through 7 might all produce the same effect, 8 through 15 are equal, etc). + * (distance) is an integer between 0 and 255 that specifies the space + * between the sound and the listener. The larger the number, the further + * away the sound is. + * Setting (distance) to 0 unregisters this effect, since the data would be + * unchanged. + * If you need more precise positional audio, consider using OpenAL for + * spatialized effects instead of SDL_mixer. This is only meant to be a + * basic effect for simple "3D" games. + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the distance attenuation will be done to the final mixed stream before + * passing it on to the audio device. + * + * This uses the Mix_RegisterEffect() API internally. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if position effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetDistance(int channel, Uint8 distance); + + +/* + * !!! FIXME : Haven't implemented, since the effect goes past the + * end of the sound buffer. Will have to think about this. + * --ryan. + */ +#if 0 +/* Causes an echo effect to be mixed into a sound. (echo) is the amount + * of echo to mix. 0 is no echo, 255 is infinite (and probably not + * what you want). + * + * Setting (channel) to MIX_CHANNEL_POST registers this as a posteffect, and + * the reverbing will be done to the final mixed stream before passing it on + * to the audio device. + * + * This uses the Mix_RegisterEffect() API internally. If you specify an echo + * of zero, the effect is unregistered, as the data is already in that state. + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if reversing effect is enabled. + * Error messages can be retrieved from Mix_GetError(). + */ +extern no_parse_DECLSPEC int SDLCALL Mix_SetReverb(int channel, Uint8 echo); +#endif + +/* Causes a channel to reverse its stereo. This is handy if the user has his + * speakers hooked up backwards, or you would like to have a minor bit of + * psychedelia in your sound code. :) Calling this function with (flip) + * set to non-zero reverses the chunks's usual channels. If (flip) is zero, + * the effect is unregistered. + * + * This uses the Mix_RegisterEffect() API internally, and thus is probably + * more CPU intensive than having the user just plug in his speakers + * correctly. Mix_SetReverseStereo() returns without registering the effect + * function if the audio device is not configured for stereo output. + * + * If you specify MIX_CHANNEL_POST for (channel), then this the effect is used + * on the final mixed stream before sending it on to the audio device (a + * posteffect). + * + * returns zero if error (no such channel or Mix_RegisterEffect() fails), + * nonzero if reversing effect is enabled. Note that an audio device in mono + * mode is a no-op, but this call will return successful in that case. + * Error messages can be retrieved from Mix_GetError(). + */ +extern DECLSPEC int SDLCALL Mix_SetReverseStereo(int channel, int flip); + +/* end of effects API. --ryan. */ + + +/* Reserve the first channels (0 -> n-1) for the application, i.e. don't allocate + them dynamically to the next sample if requested with a -1 value below. + Returns the number of reserved channels. + */ +extern DECLSPEC int SDLCALL Mix_ReserveChannels(int num); + +/* Channel grouping functions */ + +/* Attach a tag to a channel. A tag can be assigned to several mixer + channels, to form groups of channels. + If 'tag' is -1, the tag is removed (actually -1 is the tag used to + represent the group of all the channels). + Returns true if everything was OK. + */ +extern DECLSPEC int SDLCALL Mix_GroupChannel(int which, int tag); +/* Assign several consecutive channels to a group */ +extern DECLSPEC int SDLCALL Mix_GroupChannels(int from, int to, int tag); +/* Finds the first available channel in a group of channels, + returning -1 if none are available. + */ +extern DECLSPEC int SDLCALL Mix_GroupAvailable(int tag); +/* Returns the number of channels in a group. This is also a subtle + way to get the total number of channels when 'tag' is -1 + */ +extern DECLSPEC int SDLCALL Mix_GroupCount(int tag); +/* Finds the "oldest" sample playing in a group of channels */ +extern DECLSPEC int SDLCALL Mix_GroupOldest(int tag); +/* Finds the "most recent" (i.e. last) sample playing in a group of channels */ +extern DECLSPEC int SDLCALL Mix_GroupNewer(int tag); + +/* Play an audio chunk on a specific channel. + If the specified channel is -1, play on the first free channel. + If 'loops' is greater than zero, loop the sound that many times. + If 'loops' is -1, loop inifinitely (~65000 times). + Returns which channel was used to play the sound. +*/ +#define Mix_PlayChannel(channel,chunk,loops) Mix_PlayChannelTimed(channel,chunk,loops,-1) +/* The same as above, but the sound is played at most 'ticks' milliseconds */ +extern DECLSPEC int SDLCALL Mix_PlayChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ticks); +extern DECLSPEC int SDLCALL Mix_PlayMusic(Mix_Music *music, int loops); +#define Mix_PlayChannelVol(channel,chunk,loops,vol) Mix_PlayChannelTimedVolume(channel,chunk,loops,-1,vol)/*MIXER-X*/ +extern DECLSPEC int SDLCALL Mix_PlayChannelTimedVolume(int which, Mix_Chunk *chunk, int loops, int ticks, int volume);/*MIXER-X*/ + +/* Fade in music or a channel over "ms" milliseconds, same semantics as the "Play" functions */ +extern DECLSPEC int SDLCALL Mix_FadeInMusic(Mix_Music *music, int loops, int ms); +extern DECLSPEC int SDLCALL Mix_FadeInMusicPos(Mix_Music *music, int loops, int ms, double position); +#define Mix_FadeInChannel(channel,chunk,loops,ms) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1) +extern DECLSPEC int SDLCALL Mix_FadeInChannelTimed(int channel, Mix_Chunk *chunk, int loops, int ms, int ticks); +#define Mix_FadeInChannelVolume(channel,chunk,loops,ms,vol) Mix_FadeInChannelTimed(channel,chunk,loops,ms,-1,vol)/*MIXER-X*/ +extern DECLSPEC int SDLCALL Mix_FadeInChannelTimedVolume(int which, Mix_Chunk *chunk, int loops, int ms, int ticks, int volume);/*MIXER-X*/ + + +/* Set the volume in the range of 0-128 of a specific channel or chunk. + If the specified channel is -1, set volume for all channels. + Returns the original volume. + If the specified volume is -1, just return the current volume. +*/ +extern DECLSPEC int SDLCALL Mix_Volume(int channel, int volume); +extern DECLSPEC int SDLCALL Mix_VolumeChunk(Mix_Chunk *chunk, int volume); +extern DECLSPEC int SDLCALL Mix_VolumeMusic(int volume); + +/* Halt playing of a particular channel */ +extern DECLSPEC int SDLCALL Mix_HaltChannel(int channel); +extern DECLSPEC int SDLCALL Mix_HaltGroup(int tag); +extern DECLSPEC int SDLCALL Mix_HaltMusic(void); + +/* Change the expiration delay for a particular channel. + The sample will stop playing after the 'ticks' milliseconds have elapsed, + or remove the expiration if 'ticks' is -1 +*/ +extern DECLSPEC int SDLCALL Mix_ExpireChannel(int channel, int ticks); + +/* Halt a channel, fading it out progressively till it's silent + The ms parameter indicates the number of milliseconds the fading + will take. + */ +extern DECLSPEC int SDLCALL Mix_FadeOutChannel(int which, int ms); +extern DECLSPEC int SDLCALL Mix_FadeOutGroup(int tag, int ms); +extern DECLSPEC int SDLCALL Mix_FadeOutMusic(int ms); + +/* Query the fading status of a channel */ +extern DECLSPEC Mix_Fading SDLCALL Mix_FadingMusic(void); +extern DECLSPEC Mix_Fading SDLCALL Mix_FadingChannel(int which); + +/* Pause/Resume a particular channel */ +extern DECLSPEC void SDLCALL Mix_Pause(int channel); +extern DECLSPEC void SDLCALL Mix_Resume(int channel); +extern DECLSPEC int SDLCALL Mix_Paused(int channel); + +/* Pause/Resume the music stream */ +extern DECLSPEC void SDLCALL Mix_PauseMusic(void); +extern DECLSPEC void SDLCALL Mix_ResumeMusic(void); +extern DECLSPEC void SDLCALL Mix_RewindMusic(void); +extern DECLSPEC int SDLCALL Mix_PausedMusic(void); + +/* Set the current position in the music stream. + This returns 0 if successful, or -1 if it failed or isn't implemented. + This function is only implemented for MOD music formats (set pattern + order number) and for WAV, OGG, FLAC, MP3_MAD, MP3_MPG, and MODPLUG music + (set position in seconds), at the moment. +*/ +extern DECLSPEC int SDLCALL Mix_SetMusicPosition(double position); +/* + Get the time current position of music stream + returns -1.0 if this feature is not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicPosition(Mix_Music *music); +/* + Get the total time length of music stream + returns -1.0 if this feature is not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicTotalTime(Mix_Music *music); + +/* + Get the loop start time position of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicLoopStartTime(Mix_Music *music); +/* + Get the loop end time position of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicLoopEndTime(Mix_Music *music); +/* + Get the loop time length of music stream + returns -1.0 if this feature is not used for this music or not supported for some codec + */ +extern DECLSPEC double SDLCALL Mix_GetMusicLoopLengthTime(Mix_Music *music); + + +/* Check the status of a specific channel. + If the specified channel is -1, check all channels. +*/ +extern DECLSPEC int SDLCALL Mix_Playing(int channel); +extern DECLSPEC int SDLCALL Mix_PlayingMusic(void); + +/* Stop music and set external music playback command */ +extern DECLSPEC int SDLCALL Mix_SetMusicCMD(const char *command); + +/* Synchro value is set by MikMod from modules while playing */ +extern DECLSPEC int SDLCALL Mix_SetSynchroValue(int value); +extern DECLSPEC int SDLCALL Mix_GetSynchroValue(void); + +/* Set/Get/Iterate SoundFonts paths to use by supported MIDI backends */ +extern DECLSPEC int SDLCALL Mix_SetSoundFonts(const char *paths); +extern DECLSPEC const char* SDLCALL Mix_GetSoundFonts(void); +extern DECLSPEC int SDLCALL Mix_EachSoundFont(int (SDLCALL *function)(const char*, void*), void *data); + +/* Get the Mix_Chunk currently associated with a mixer channel + Returns NULL if it's an invalid channel, or there's no chunk associated. +*/ +extern DECLSPEC Mix_Chunk * SDLCALL Mix_GetChunk(int channel); + +/* Close the mixer, halting all playing audio */ +extern DECLSPEC void SDLCALL Mix_CloseAudio(void); + +/* Add additional Timidity bank path */ +extern DECLSPEC void SDLCALL Mix_Timidity_addToPathList(const char *path); + +/* ADLMIDI Setup functions */ +/* Get count of available hardcoded banks */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getTotalBanks(void); +/* Get array of the bank names */ +extern DECLSPEC const char *const *SDLCALL Mix_ADLMIDI_getBankNames(void); +/* Get bank ID */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getBankID(void); +/* Set bank ID (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setBankID(int bnk); +/* Get state of deep vibrato */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getTremolo(void); +/* Set deep tremolo mode (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setTremolo(int tr); +/* Get state of deep vibrato */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getVibrato(void); +/* Set deep vibrato mode (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setVibrato(int vib); +/* Get state of scalable modulation mode */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getScaleMod(void); +/* Set scalable modulation mode (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setScaleMod(int sc); +/* Get state of adlib drums mode */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getAdLibMode(void); +/* Set adlib drums mode mode (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setAdLibMode(int tr); +/* Get state of logarithmic mode */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getLogarithmicVolumes(void); +/* Set logarithmic volumes mode in the generic/CMF volume models (0 off, 1 on) (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setLogarithmicVolumes(int lv); +/* Get current volume model ID */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getVolumeModel(void); +/* Change current volumes model (Applying on stop/play) */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setVolumeModel(int vm); +/* Get full range mode for CC74-Brightness controller */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getFullRangeBrightness(void); +/* Set full range mode for CC74-Brightness controller */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setFullRangeBrightness(int frb); +/* Get the current OPL3 Emulator for ADLMIDI */ +extern DECLSPEC int SDLCALL Mix_ADLMIDI_getEmulator(void); +/* Select the OPL3 Emulator for ADLMIDI */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setEmulator(int emu); +/* Reset all ADLMIDI properties to default state */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setSetDefaults(void); + +/* Sets WOPL bank file for ADLMIDI playing device, affects on MIDI file reopen */ +extern DECLSPEC void SDLCALL Mix_ADLMIDI_setCustomBankFile(const char *bank_wonl_path); + +/* Reset all OPNMIDI properties to default state */ +extern DECLSPEC void SDLCALL Mix_OPNMIDI_setSetDefaults(void); +/* Get full range mode for CC74-Brightness controller */ +extern DECLSPEC int SDLCALL Mix_OPNMIDI_getFullRangeBrightness(void); +/* Set full range mode for CC74-Brightness controller */ +extern DECLSPEC void SDLCALL Mix_OPNMIDI_setFullRangeBrightness(int frb); +/* Get the OPN2 Emulator for OPNMIDI */ +extern DECLSPEC int SDLCALL Mix_OPNMIDI_getEmulator(void); +/* Select the OPN2 Emulator for OPNMIDI */ +extern DECLSPEC void SDLCALL Mix_OPNMIDI_setEmulator(int emu); +/* Sets WOPN bank file for OPNMIDI playing device, affects on MIDI file reopen */ +extern DECLSPEC void SDLCALL Mix_OPNMIDI_setCustomBankFile(const char *bank_wonp_path); + +/* Get type of MIDI player library currently in use */ +extern DECLSPEC int SDLCALL Mix_GetMidiPlayer(void); + +/* Get type of MIDI player library prepared for next opening of MIDI file */ +extern DECLSPEC int SDLCALL Mix_GetNextMidiPlayer(void); + +/* Set the MIDI playing library (ADLMIDI, Timidity, Native MIDI (if available) and FluidSynth) */ +extern DECLSPEC int SDLCALL Mix_SetMidiPlayer(int player); + +/* Disables support of MIDI file arguments */ +extern DECLSPEC void SDLCALL Mix_SetLockMIDIArgs(int lock_midiargs); + +/* DEPRECATED NAMES for new-added SDL Mixer X functions + Those names are made with mistake - beginning with "MIX_" than "Mix_" + which makes confusion when you looking for Mix_ function in your IDE + because some applications are still use them, to don't break ABI we will keep those + aliases until we will remove all usages of them from applications and libraries are used them +*/ +DEPRECATED(extern DECLSPEC int SDLCALL Mix_GetMidiDevice(void)); +DEPRECATED(extern DECLSPEC int SDLCALL Mix_GetNextMidiDevice(void)); +DEPRECATED(extern DECLSPEC int SDLCALL Mix_SetMidiDevice(int player)); + +/* We'll use SDL for reporting errors */ +#define Mix_SetError SDL_SetError +#define Mix_GetError SDL_GetError +#define Mix_ClearError SDL_ClearError + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +} +#endif +#include "close_code.h" + +#endif /* SDL_MIXER_H_ */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/begin_code.h b/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/begin_code.h new file mode 100644 index 000000000..6c2106246 --- /dev/null +++ b/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/begin_code.h @@ -0,0 +1,167 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + 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. +*/ + +/** + * \file begin_code.h + * + * This file sets things up for C dynamic library function definitions, + * static inlined functions, and structures aligned at 4-byte alignment. + * If you don't like ugly C preprocessor code, don't look at this file. :) + */ + +/* This shouldn't be nested -- included it around code only. */ +#ifdef _begin_code_h +#error Nested inclusion of begin_code.h +#endif +#define _begin_code_h + +#ifndef SDL_DEPRECATED +# if (__GNUC__ >= 4) /* technically, this arrived in gcc 3.1, but oh well. */ +# define SDL_DEPRECATED __attribute__((deprecated)) +# else +# define SDL_DEPRECATED +# endif +#endif + +#ifndef SDL_UNUSED +# ifdef __GNUC__ +# define SDL_UNUSED __attribute__((unused)) +# else +# define SDL_UNUSED +# endif +#endif + +/* Some compilers use a special export keyword */ +#ifndef DECLSPEC +# if defined(__WIN32__) || defined(__WINRT__) +# ifdef __BORLANDC__ +# ifdef BUILD_SDL +# define DECLSPEC +# else +# define DECLSPEC __declspec(dllimport) +# endif +# else +# define DECLSPEC __declspec(dllexport) +# endif +# elif defined(__OS2__) +# ifdef BUILD_SDL +# define DECLSPEC __declspec(dllexport) +# else +# define DECLSPEC +# endif +# else +# if defined(__GNUC__) && __GNUC__ >= 4 +# define DECLSPEC __attribute__ ((visibility("default"))) +# else +# define DECLSPEC +# endif +# endif +#endif + +/* By default SDL uses the C calling convention */ +#ifndef SDLCALL +#if (defined(__WIN32__) || defined(__WINRT__)) && !defined(__GNUC__) +#define SDLCALL __cdecl +#elif defined(__OS2__) || defined(__EMX__) +#define SDLCALL _System +# if defined (__GNUC__) && !defined(_System) +# define _System /* for old EMX/GCC compat. */ +# endif +#else +#define SDLCALL +#endif +#endif /* SDLCALL */ + +/* Removed DECLSPEC on Symbian OS because SDL cannot be a DLL in EPOC */ +#ifdef __SYMBIAN32__ +#undef DECLSPEC +#define DECLSPEC +#endif /* __SYMBIAN32__ */ + +/* Force structure packing at 4 byte alignment. + This is necessary if the header is included in code which has structure + packing set to an alternate value, say for loading structures from disk. + The packing is reset to the previous value in close_code.h + */ +#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) +#ifdef _MSC_VER +#pragma warning(disable: 4103) +#endif +#ifdef __BORLANDC__ +#pragma nopackwarning +#endif +#ifdef _M_X64 +/* Use 8-byte alignment on 64-bit architectures, so pointers are aligned */ +#pragma pack(push,8) +#else +#pragma pack(push,4) +#endif +#endif /* Compiler needs structure packing set */ + +#ifndef SDL_INLINE +#if defined(__GNUC__) +#define SDL_INLINE __inline__ +#elif defined(_MSC_VER) || defined(__BORLANDC__) || \ + defined(__DMC__) || defined(__SC__) || \ + defined(__WATCOMC__) || defined(__LCC__) || \ + defined(__DECC) || defined(__CC_ARM) +#define SDL_INLINE __inline +#ifndef __inline__ +#define __inline__ __inline +#endif +#else +#define SDL_INLINE inline +#ifndef __inline__ +#define __inline__ inline +#endif +#endif +#endif /* SDL_INLINE not defined */ + +#ifndef SDL_FORCE_INLINE +#if defined(_MSC_VER) +#define SDL_FORCE_INLINE __forceinline +#elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) ) +#define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__ +#else +#define SDL_FORCE_INLINE static SDL_INLINE +#endif +#endif /* SDL_FORCE_INLINE not defined */ + +#ifndef SDL_NORETURN +#if defined(__GNUC__) +#define SDL_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define SDL_NORETURN __declspec(noreturn) +#else +#define SDL_NORETURN +#endif +#endif /* SDL_NORETURN not defined */ + +/* Apparently this is needed by several Windows compilers */ +#if !defined(__MACH__) +#ifndef NULL +#ifdef __cplusplus +#define NULL 0 +#else +#define NULL ((void *)0) +#endif +#endif /* NULL */ +#endif /* ! Mac OS X - breaks precompiled headers */ diff --git a/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/close_code.h b/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/close_code.h new file mode 100644 index 000000000..b3b70a4c8 --- /dev/null +++ b/libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2/close_code.h @@ -0,0 +1,37 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2018 Sam Lantinga + + 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. +*/ + +/** + * \file close_code.h + * + * This file reverses the effects of begin_code.h and should be included + * after you finish any function and structure declarations in your headers + */ + +#undef _begin_code_h + +/* Reset structure packing at previous byte alignment */ +#if defined(_MSC_VER) || defined(__MWERKS__) || defined(__BORLANDC__) +#ifdef __BORLANDC__ +#pragma nopackwarning +#endif +#pragma pack(pop) +#endif /* Compiler needs structure packing set */ diff --git a/libs/SDLMixerX/x86_64-w64-mingw32/lib/libSDL2_mixer_ext.dll.a b/libs/SDLMixerX/x86_64-w64-mingw32/lib/libSDL2_mixer_ext.dll.a new file mode 100644 index 000000000..c1cede98d Binary files /dev/null and b/libs/SDLMixerX/x86_64-w64-mingw32/lib/libSDL2_mixer_ext.dll.a differ diff --git a/libs/discord-rpc.props b/libs/discord-rpc.props new file mode 100644 index 000000000..83c7a03f3 --- /dev/null +++ b/libs/discord-rpc.props @@ -0,0 +1,16 @@ + + + + + $(SolutionDir)libs\discord-rpc\win32-dynamic\lib;$(LibraryPath) + $(SolutionDir)libs\discord-rpc\win32-dynamic\lib;$(IncludePath) + $(SolutionDir)libs\discord-rpc\win64-dynamic\lib;$(LibraryPath) + $(SolutionDir)libs\discord-rpc\win64-dynamic\lib;$(IncludePath) + + + + discord-rpc.dll.a;%(AdditionalDependencies) + + + + \ No newline at end of file diff --git a/libs/discord-rpc/win32-dynamic/include/discord_register.h b/libs/discord-rpc/win32-dynamic/include/discord_register.h new file mode 100644 index 000000000..16fb42f32 --- /dev/null +++ b/libs/discord-rpc/win32-dynamic/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/libs/discord-rpc/win32-dynamic/include/discord_rpc.h b/libs/discord-rpc/win32-dynamic/include/discord_rpc.h new file mode 100644 index 000000000..3e1441e05 --- /dev/null +++ b/libs/discord-rpc/win32-dynamic/include/discord_rpc.h @@ -0,0 +1,87 @@ +#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; + 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 + +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/libs/discord-rpc/win32-dynamic/lib/discord-rpc.lib b/libs/discord-rpc/win32-dynamic/lib/discord-rpc.lib new file mode 100644 index 000000000..d8b6689f3 Binary files /dev/null and b/libs/discord-rpc/win32-dynamic/lib/discord-rpc.lib differ diff --git a/libs/discord-rpc/win64-dynamic/include/discord_register.h b/libs/discord-rpc/win64-dynamic/include/discord_register.h new file mode 100644 index 000000000..16fb42f32 --- /dev/null +++ b/libs/discord-rpc/win64-dynamic/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/libs/discord-rpc/win64-dynamic/include/discord_rpc.h b/libs/discord-rpc/win64-dynamic/include/discord_rpc.h new file mode 100644 index 000000000..3e1441e05 --- /dev/null +++ b/libs/discord-rpc/win64-dynamic/include/discord_rpc.h @@ -0,0 +1,87 @@ +#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; + 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 + +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/libs/discord-rpc/win64-dynamic/lib/discord-rpc.lib b/libs/discord-rpc/win64-dynamic/lib/discord-rpc.lib new file mode 100644 index 000000000..fcd009d82 Binary files /dev/null and b/libs/discord-rpc/win64-dynamic/lib/discord-rpc.lib differ diff --git a/libs/dll-binaries/i686/discord-rpc.dll b/libs/dll-binaries/i686/discord-rpc.dll new file mode 100644 index 000000000..88c7d0cef Binary files /dev/null and b/libs/dll-binaries/i686/discord-rpc.dll differ diff --git a/libs/dll-binaries/x86_64/discord-rpc.dll b/libs/dll-binaries/x86_64/discord-rpc.dll new file mode 100644 index 000000000..8493c5490 Binary files /dev/null and b/libs/dll-binaries/x86_64/discord-rpc.dll differ diff --git a/libs/drmingw/include/exchndl.h b/libs/drmingw/include/exchndl.h new file mode 100644 index 000000000..37dafb88e --- /dev/null +++ b/libs/drmingw/include/exchndl.h @@ -0,0 +1,39 @@ +/* + * Copyright 2002-2015 Jose Fonseca + * + * 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. + * + * 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 + */ + + +#pragma once + + +#include + + +// Set the unhandled exception handler. +// Must be called when exchndll.dll is statically loaded (as opposed to loaded +// dynamically via LoadLibrary) +EXTERN_C VOID APIENTRY +ExcHndlInit(void); + + +// Override the report file name. +// +// Default is prog_name.RPT, in the same directory as the main executable. +// +// You can also pass "-" for stderr. +EXTERN_C BOOL APIENTRY +ExcHndlSetLogFileNameA(const char *szLogFileName); diff --git a/libs/drmingw/lib/win32/libexchndl.a b/libs/drmingw/lib/win32/libexchndl.a new file mode 100644 index 000000000..cd462a0df Binary files /dev/null and b/libs/drmingw/lib/win32/libexchndl.a differ diff --git a/libs/drmingw/lib/win32/libmgwhelp.a b/libs/drmingw/lib/win32/libmgwhelp.a new file mode 100644 index 000000000..330cb52fe Binary files /dev/null and b/libs/drmingw/lib/win32/libmgwhelp.a differ diff --git a/libs/libopenmpt.props b/libs/libopenmpt.props new file mode 100644 index 000000000..8825907b6 --- /dev/null +++ b/libs/libopenmpt.props @@ -0,0 +1,16 @@ + + + + + + $(SolutionDir)libs\libopenmpt\inc;$(IncludePath) + $(SolutionDir)libs\libopenmpt\lib\x86;$(LibraryPath) + $(SolutionDir)libs\libopenmpt\lib\x86_64;$(LibraryPath) + + + + libopenmpt.lib;%(AdditionalDependencies) + + + + \ No newline at end of file diff --git a/libs/libopenmpt/LICENSE.txt b/libs/libopenmpt/LICENSE.txt new file mode 100644 index 000000000..e0f012166 --- /dev/null +++ b/libs/libopenmpt/LICENSE.txt @@ -0,0 +1,26 @@ +Copyright (c) 2004-2019, OpenMPT contributors +Copyright (c) 1997-2003, Olivier Lapicque +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 OpenMPT project 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 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 CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/libs/libopenmpt/Licenses/License.Vorbis.txt b/libs/libopenmpt/Licenses/License.Vorbis.txt new file mode 100644 index 000000000..153b926a1 --- /dev/null +++ b/libs/libopenmpt/Licenses/License.Vorbis.txt @@ -0,0 +1,28 @@ +Copyright (c) 2002-2018 Xiph.org Foundation + +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 Xiph.org Foundation 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 FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/libopenmpt/Licenses/License.mpg123.Authors.txt b/libs/libopenmpt/Licenses/License.mpg123.Authors.txt new file mode 100644 index 000000000..c1eac976d --- /dev/null +++ b/libs/libopenmpt/Licenses/License.mpg123.Authors.txt @@ -0,0 +1,175 @@ +This is an attempt to give credit to the people who contributed in some way to the mpg123 project. +There are names and email addresses listed. Please use these addresses only to contact contributors with some question about their mpg123 contribution. +You are explicitly not allowed to send them unwanted business offers or to question the quality of their sex life. +-------------------- + +Being on the list of contributing authors not necessarily means that there +is significant copyright in parts of the source code. There are obviously +contributions of differing complexity. I try to mention people who motivated +changes at least by suggesting some definite code changes, even if their +code did not enter the mpg123 source verbatim. Trivial changes like pointing +out ovbious syntax errors that make compilers cry do not land here. + +-------------------- + +Current maintainers with various sorts of contributions: + Thomas Orgis + Patrick Dehne + Jonathan Yong <10walls@gmail.com> + Taihei Momma + +Co-initiator of the revived mpg123 project, but not that involved anymore: + Nicholas J Humfrey + +Special thanks go to Taihei, the person who keeps the assembly optimisations alive +and takes care of portability to OSX/iOS platforms. + +Generic address pointing to the current maintainer (hopefully still works in future in case maintainership will change again): + +The creator: Michael Hipp (email: hippm@informatik.uni-tuebingen.de - please bother maintainers first) + +Contributions/ideas Thomas Orgis era (includes backports from mhipp trunk): + +Won-Kyu Park : patch to get rid of asm textrels (x86 PIC) +Michael Weiser : update of coreaudio output to AudioComponents API +Bent Bisballe Nyeng : patch for MPG123_NO_PEEK_END and MPG123_FORCE_SEEKABLE +Eric S. Raymond : man page fixes +Tobias Weber : patch for --disable-equalizer +Hans de Goede : patch to skip APE tags +Stephan Vedder : MSVC++ 2013 port update +Rajeev V. Pillai : pointing out/patching issues in HTTP code and behaviour of mpg123 remote/terminal control +Jarno Lehtinen : tinyalsa output +Anthony Wells : initial version of ID3v2 APIC patch +David Wohlferd : Win32 WaveOut buffer destructor fix. +Mike Gorchak : QNX native audio output (QSA) +Dan McGee : various patches (also for test suite) +Jonathan Yong (jon_y) <10walls@gmail.com>: win32 hacking, win32 wasapi audio. +Malcolm Boczek : Common language runtime wrapper +Elbert Pol (TeLLie) : OS/2 port fixup +Jeroen Valkonet : motivate pitch control, suggestive patch for pitch command in generic control interface +Andy Hefner : patch for that second UTF16 issue +Taihei Monma : A whole lot of new/improved assembler code, including Altivec! +Christian Weisgerber , Brad Smith: sndio output +Patrick Dehne (P4tr3ck) : more MSVC++ porting, patch to handle missing bit reservoirs +Thorsten Glaser : icy2utf8, suggest utf8 locale stuff +Dan Smith : ABI fixes for ensuring stack alignment (esp. for MinGW-built DLL with MSVC) +Michael Ryzhykh : mpg123.spec.in +Stefan Lenselink : initial aRts output +Sergej Kvachonok : win32 audio rewrite +Winston: SunOS-4.1.4/gcc-2.7.0 testing and suggestions for fixes (legacy Makefile, integer type headers) +Mika Tiainen: pointing out the fix for the UTF to ASCII filtering of tags to actually work +Nick Kurshev : extended 3dnow (from mplayer) +Zuxy Meng : SSE (from mplayer) +Honza : idea and prototype patch for ICY meta data support +Petr Baudis : patches: term sigcont, id3 display unicode fallback and condensed output +Petr Salinger : i486 enhancement +mpdavig@users.sourceforge.net: linux-ppc-nas Makefile.legacy entry +Adrian Bacon : patched decode_i586_dither (noise shaped float/int rounding) +Cool Feet Audio project : realtime equalizer control +Steve Grundell : clean stdout in control mode with stdout decoding +Romain Dolbeau : Altivec support (taken from mplayer) +higway : MMX Patch +Clemens Ladisch : ALSA 0.9/1.0 support + +Debian Daniel Kobras era: + +Steve Kemp +Dan Olson +Syuuhei Kashiyama +Rupert Levene +Andreas Dilger +Erik B. Andersen +Chris Butler +Martin Sjogren +Chet Hosey +Roland Rosenfeld + + +Debian Colin Watson era: + +Helge Deller +Chet Hosey +Christopher C. Chimelis +Roland Rosenfeld +Marcelo E. Magallon + + +Initial Debianers: + +Tommi Virtanen +Paul Haggart + + +Contributions/ideas Michael Hipp era: + +Mikko Tommila: DCT9 +Oliver Fromme +MPEG Software Simulation Group: reference decoder package +Tobias Bading: idea for DCT64 in subband synthesis from maplay package +Jeff Tsay and Mikko Tommila: MDCT36 from maplay package +Philipp Knirsch : DCT36/manual unroll idea +Thomas Woerner: SGI Audio +Damien Clermonte: HP-UX audio fixes +Niclas Lindstrom : OS2 port +Stefan Bieschewski : Pentium optimizations, decode_i586.s +Martin Denn : NAS port +Niklas Beisert : MPEG 2.5 tables + and : NetBSD Patch(es) +Kevin Brintnall : BSD patch +Tony Million: win32 port +Steven Tiger Lang: advanced shuffle +Eric B. Mitchell: esd port +Ryan R. Prosser : esd port for Solaris +Andreas Neuhaus: initial generic control interface + +(additionally fetched from changelog:) + +Ralf Hildebrandt : audio_alib changes +: BSDOS 4.0 with gcc added to Makefile +Bertrand Petit : frontend changes +Erik Mouw : SGI audio fix for non RAD machines +Daniel O'Connor : freebsd-esd make-entry +D. Skarda <0rfelyus@atrey.karlin.mff.cuni.cz>: enhanced head_check +Wilson, Jeff D : xterm-title +Robert Bihlmeyer : esd changes +Hannu Napari's : SGI audio patches +: native AIX support +: playlist patch +Gilles Zunino : SGI audio patches +Matthew Parslow : esdserver patch +: equalizer patch (equalfile setting) +Ducroquet Erwan : HPUX/ALib support +Shane Wegner : genrepatch +Samuel Audet : wav-File patch +"J. Dean Brederson" : SGI-RAD support +Chou Ye-chi : sajberplay/FreeBSD patch +Fabrice Bellard : 486 optimizations +A. Hermansen and J. Kysela : ALSA output +KIMURA Takuhiro : K6-3DNow +Petr Stehlik : MINT +Andy : float2int speed up proposal +Brian Foutz : TK3Play +Thomas Niederreiter : RIFF header fix +Stefan Gybas : m68k patch +Grant Erickson : Linux PPC patch +Peter Berger : BSDi patch +Henrik P Johnson : HTTP auth +Steven Tiger Lang : advanced shuffle +"Brian J. Swetland" : front-end (remote) patch + +Tillmann Steinbrecher : shuffle patch +M.Stekelenburg : i386-getbits +Antti Andreimann : outburst patch +Hur TaeSung : 'http accept' patch + +(from post-0.59 changes that yet have to go into new trunk:) + +Hans Schwengeler : audio_dec additions +Wojciech Barañski's Mp3Play (check the tools folder): Mp3Play frontend +Daniel Koukola: audio_oss.c patch +Munechika SUMIKAWA : IPv6 +TEMNOTA : HTTP,FTP patch/playlist fix +Peter Surda : VBR patch +Ben : ARM startup time improvements +Dave MacKenzie : init_output() patch +pasky's : close-on-stop patch diff --git a/libs/libopenmpt/Licenses/License.mpg123.txt b/libs/libopenmpt/Licenses/License.mpg123.txt new file mode 100644 index 000000000..d7bb85fc3 --- /dev/null +++ b/libs/libopenmpt/Licenses/License.mpg123.txt @@ -0,0 +1,772 @@ +This is the file that contains the terms of use, copying, etc. for the mpg123 distribution package. + +Main message, to include in "About ..." boxes, etc: + + Copyright (c) 1995-2013 by Michael Hipp and others, + free software under the terms of the LGPL v2.1 + +There is an attempt to cover the actual list of authors in the AUTHORS file. +Project maintainer since 2006 is Thomas Orgis and many people have contributed +since the Michael Hipp era, but he stays the initial source and it would +be impractical to count them all individually, so it's "and others". +Source files contain the phrase "the mpg123 project" to the same effect +in their license boilerplate; especially those that were added after +maintainership changed. The person mainly responsible for the first version +is usually named in the phrase "initially written by ...". + +All files in the distribution that don't carry a license note on their own are +licensed under the terms of the LGPL 2.1; exceptions may apply, especially to +files not in the official distribution but in the revision control repository. + +The formal license text follows. + +======================= +1. The LGPL version 2.1 +======================= + + + 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 + + +==================== +2. The GPL version 2 +==================== + + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 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. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. 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 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. + + END OF TERMS AND CONDITIONS diff --git a/libs/libopenmpt/Licenses/License.ogg.txt b/libs/libopenmpt/Licenses/License.ogg.txt new file mode 100644 index 000000000..6111c6c5a --- /dev/null +++ b/libs/libopenmpt/Licenses/License.ogg.txt @@ -0,0 +1,28 @@ +Copyright (c) 2002, Xiph.org Foundation + +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 Xiph.org Foundation 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 FOUNDATION +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/libs/libopenmpt/Licenses/License.zlib.txt b/libs/libopenmpt/Licenses/License.zlib.txt new file mode 100644 index 000000000..51106de47 --- /dev/null +++ b/libs/libopenmpt/Licenses/License.zlib.txt @@ -0,0 +1,115 @@ +ZLIB DATA COMPRESSION LIBRARY + +zlib 1.2.11 is a general purpose data compression library. All the code is +thread safe. The data format used by the zlib library is described by RFCs +(Request for Comments) 1950 to 1952 in the files +http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and +rfc1952 (gzip format). + +All functions of the compression library are documented in the file zlib.h +(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example +of the library is given in the file test/example.c which also tests that +the library is working correctly. Another example is given in the file +test/minigzip.c. The compression library itself is composed of all source +files in the root directory. + +To compile all files and run the test program, follow the instructions given at +the top of Makefile.in. In short "./configure; make test", and if that goes +well, "make install" should work for most flavors of Unix. For Windows, use +one of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use +make_vms.com. + +Questions about zlib should be sent to , or to Gilles Vollant + for the Windows DLL version. The zlib home page is +http://zlib.net/ . Before reporting a problem, please check this site to +verify that you have the latest version of zlib; otherwise get the latest +version and check whether the problem still exists or not. + +PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help. + +Mark Nelson wrote an article about zlib for the Jan. 1997 +issue of Dr. Dobb's Journal; a copy of the article is available at +http://marknelson.us/1997/01/01/zlib-engine/ . + +The changes made in version 1.2.11 are documented in the file ChangeLog. + +Unsupported third party contributions are provided in directory contrib/ . + +zlib is available in Java using the java.util.zip package, documented at +http://java.sun.com/developer/technicalArticles/Programming/compression/ . + +A Perl interface to zlib written by Paul Marquess is available +at CPAN (Comprehensive Perl Archive Network) sites, including +http://search.cpan.org/~pmqs/IO-Compress-Zlib/ . + +A Python interface to zlib written by A.M. Kuchling is +available in Python 1.5 and later versions, see +http://docs.python.org/library/zlib.html . + +zlib is built into tcl: http://wiki.tcl.tk/4610 . + +An experimental package to read and write files in .zip format, written on top +of zlib by Gilles Vollant , is available in the +contrib/minizip directory of zlib. + + +Notes for some targets: + +- For Windows DLL versions, please see win32/DLL_FAQ.txt + +- For 64-bit Irix, deflate.c must be compiled without any optimization. With + -O, one libpng test fails. The test works in 32 bit mode (with the -n32 + compiler flag). The compiler bug has been reported to SGI. + +- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works + when compiled with cc. + +- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is + necessary to get gzprintf working correctly. This is done by configure. + +- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with + other compilers. Use "make test" to check your compiler. + +- gzdopen is not supported on RISCOS or BEOS. + +- For PalmOs, see http://palmzlib.sourceforge.net/ + + +Acknowledgments: + + The deflate format used by zlib was defined by Phil Katz. The deflate and + zlib specifications were written by L. Peter Deutsch. Thanks to all the + people who reported problems and suggested various improvements in zlib; they + are too numerous to cite here. + +Copyright notice: + + (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +If you use the zlib library in a product, we would appreciate *not* receiving +lengthy legal documents to sign. The sources are provided for free but without +warranty of any kind. The library has been entirely written by Jean-loup +Gailly and Mark Adler; it does not include third-party code. + +If you redistribute modified sources, we would appreciate that you include in +the file ChangeLog history information documenting your changes. Please read +the FAQ for more information on the distribution of modified source versions. diff --git a/libs/libopenmpt/SRB2NOTE-DEBIAN.md b/libs/libopenmpt/SRB2NOTE-DEBIAN.md new file mode 100644 index 000000000..7e050d29a --- /dev/null +++ b/libs/libopenmpt/SRB2NOTE-DEBIAN.md @@ -0,0 +1,90 @@ +# libopenmpt Debian backport info + +Backported libopenmpt 0.4.0 packages are available at ppa:stjr/srb2 +for Ubuntu Disco, Cosmic, Bionic, Xenial, and Trusty as of 2019/01/04. + +Debian Jessie users should use the Trusty package. Later Debian versions +may use Disco or another working version. + +* libopenmpt 0.4.0 source package: http://archive.ubuntu.com/ubuntu/pool/universe/libo/libopenmpt/libopenmpt_0.4.0-1.dsc + +# Backporting from Disco to Cosmic and Bionic + +Cosmic and Bionic require no changes to the source package. They have +the prerequisite `debhelper` and `dpkg-dev` versions, a matching +`automake` version (1.15), as well as G++ > 5. + +Use the `backportpackage` script to automatically tag the package to +Cosmic and Bionic, then upload to PPA: + +``` +sudo apt install ubuntu-dev-tools +export UBUMAIL="John Doe " # Name and email associated with your PGP sign key +backportpackage -d [cosmic/bionic] -u [path-to-ppa] --key=[key-fingerprint] http://archive.ubuntu.com/ubuntu/pool/universe/libo/libopenmpt/libopenmpt_0.4.0-1.dsc +``` + +# Backporting from Disco to Xenial + +Download the package: + +``` +dget http://archive.ubuntu.com/ubuntu/pool/universe/libo/libopenmpt/libopenmpt_0.4.0-1.dsc +``` + +Xenial has an earlier `debhelper` version, but the rest of the prerequisites +are available. + +The required changes (see patch `debian/libopenmpt-0.4.0-xenial-backport.diff` in this directory): + +* `debian/control` + * Add `automake` to Build-Depends + * Change `debhelper` version to `(>= 9.0~)` +* `debian/compat` + * Change to `10` + +Then run these commands: + +``` +dch -i # Edit the changelog; make sure the Name and email match the PGP sign key and that the changelog targets xenial +debuild -s -d -k0x[key-fingerprint] # Build the updated package +dput [path-to-ppa] [path-to-changes-file] # Upload to PPA +``` + +# Backporting from Disco to Trusty + +Download the package: + +``` +dget http://archive.ubuntu.com/ubuntu/pool/universe/libo/libopenmpt/libopenmpt_0.4.0-1.dsc +``` + +Trusty requires more changes because it uses G++ 4.8 whereas the source +package expects G++ >= 5. Automake is an earlier version as well -- +1.14 vs 1.15 -- so `autoreconf` needs to be run at build time. + +The required changes (see patch `debian/libopenmpt-0.4.0-trusty-backport.diff` in this directory): + +* `debian/control` + * Add `automake` and `libtool` to Build-Depends + * Change `debhelper` version to `(>= 9.0~)` + * Change `dpkg-dev` version to `(>= 1.17.0)` +* `debian/compat` + * Change to `10` +* `debian/rules` + * Under `override_dh_auto_configure`, input this line as the first command: + `autoreconf --force --install` + * This re-configures the package for Automake 1.14 +* `debian/libopenmpt-modplug1.symbols` and `debian/libopenmpt0.symbols` + * Delete these files + * The C++ ABI for G++ 4.8 is incompatible with G++ >= 5, so the + generated symbols will be different than the expected symbols + in the `*.symbols` files. Deleting these files will skip the + symbol check. + +Then run these commands: + +``` +dch -i # Edit the changelog; make sure the Name and email match the PGP sign key and that the changelog targets trusty +debuild -s -d -k0x[key-fingerprint] # Build the updated package +dput [path-to-ppa] [path-to-changes-file] # Upload to PPA +``` diff --git a/libs/libopenmpt/SRB2NOTE.md b/libs/libopenmpt/SRB2NOTE.md new file mode 100644 index 000000000..7eac9183b --- /dev/null +++ b/libs/libopenmpt/SRB2NOTE.md @@ -0,0 +1,54 @@ +# libopenmpt mingw-w64 binary info + +Current built version as of 2019/09/27 is 0.4.7+r12088.pkg + +* mingw binaries (.dll): `bin/[x86 or x86_64]/mingw` +* mingw import libraries (.dll.a): `lib/[x86 or x86_64]/mingw` + +# Building libopenmpt with mingw-w64 + +libopenmpt must be built from the Makefile / Android dev package in the +[Downloads page](https://lib.openmpt.org/libopenmpt/download/#all-downloads) + +Use the mingw-w64 distributions from +[SourceForge](https://sourceforge.net/projects/mingw-w64/files/#readme). + +You can download the appropriate 7-zip archive, extract to a folder of +your choice, remove any existing mingw directories from your PATH, +then call `mingw32-make.exe` from its direct location. + +FOR LIBOPENMPT, YOU MUST USE A MINGW PACKAGE THAT SUPPORTS THE POSIX +THREADING MODEL! DO NOT COMPILE WITH A WIN32 THREADING MODEL! + +I use GCC 7.3.0: + +* [x86_64-posix-seh](https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win64/Personal%20Builds/mingw-builds/7.3.0/threads-posix/seh/x86_64-7.3.0-release-posix-seh-rt_v5-rev0.7z) +* [i686-posix-dwarf](https://sourceforge.net/projects/mingw-w64/files/Toolchains%20targetting%20Win32/Personal%20Builds/mingw-builds/7.3.0/threads-posix/dwarf/i686-7.3.0-release-posix-dwarf-rt_v5-rev0.7z) + +## x86 build instructions + +``` +set CFLAGS=-march=pentium -static-libgcc +set CXXFLAGS=-march=pentium -static-libgcc -static-libstdc++ +set LDFLAGS=-Wl,--out-implib,bin/libopenmpt.dll.a -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,-Bdynamic,--no-whole-archive + +cd [libopenmpt-make-src] +[x86-mingw-w64-bin]/mingw32-make.exe CONFIG=mingw64-win32 +``` + +`libopenmpt.dll` and `libopenmpt.dll.a` will be built in the +`bin/` folder. + +## x86_64 build instructions + +``` +set CFLAGS=-march=nocona -static-libgcc +set CXXFLAGS=-march=nocona -static-libgcc -static-libstdc++ +set LDFLAGS=-Wl,--out-implib,bin/libopenmpt.dll.a -Wl,-Bstatic,--whole-archive -lwinpthread -Wl,-Bdynamic,--no-whole-archive + +cd [libopenmpt-make-src] +[x86_64-mingw-w64-bin]/mingw32-make.exe CONFIG=mingw64-win64 +``` + +`libopenmpt.dll` and `libopenmpt.dll.a` will be built in the +`bin/` folder. \ No newline at end of file diff --git a/libs/libopenmpt/bin/x86/libopenmpt.dll b/libs/libopenmpt/bin/x86/libopenmpt.dll new file mode 100644 index 000000000..8ad64fdfd Binary files /dev/null and b/libs/libopenmpt/bin/x86/libopenmpt.dll differ diff --git a/libs/libopenmpt/bin/x86/mingw/libopenmpt.dll b/libs/libopenmpt/bin/x86/mingw/libopenmpt.dll new file mode 100644 index 000000000..945b475e6 Binary files /dev/null and b/libs/libopenmpt/bin/x86/mingw/libopenmpt.dll differ diff --git a/libs/libopenmpt/bin/x86/openmpt-mpg123.dll b/libs/libopenmpt/bin/x86/openmpt-mpg123.dll new file mode 100644 index 000000000..b068ddd0c Binary files /dev/null and b/libs/libopenmpt/bin/x86/openmpt-mpg123.dll differ diff --git a/libs/libopenmpt/bin/x86/openmpt-ogg.dll b/libs/libopenmpt/bin/x86/openmpt-ogg.dll new file mode 100644 index 000000000..a5b460063 Binary files /dev/null and b/libs/libopenmpt/bin/x86/openmpt-ogg.dll differ diff --git a/libs/libopenmpt/bin/x86/openmpt-vorbis.dll b/libs/libopenmpt/bin/x86/openmpt-vorbis.dll new file mode 100644 index 000000000..1ebed9b0e Binary files /dev/null and b/libs/libopenmpt/bin/x86/openmpt-vorbis.dll differ diff --git a/libs/libopenmpt/bin/x86/openmpt-zlib.dll b/libs/libopenmpt/bin/x86/openmpt-zlib.dll new file mode 100644 index 000000000..41bc22d2f Binary files /dev/null and b/libs/libopenmpt/bin/x86/openmpt-zlib.dll differ diff --git a/libs/libopenmpt/bin/x86_64/libopenmpt.dll b/libs/libopenmpt/bin/x86_64/libopenmpt.dll new file mode 100644 index 000000000..ffbb4b19a Binary files /dev/null and b/libs/libopenmpt/bin/x86_64/libopenmpt.dll differ diff --git a/libs/libopenmpt/bin/x86_64/mingw/libopenmpt.dll b/libs/libopenmpt/bin/x86_64/mingw/libopenmpt.dll new file mode 100644 index 000000000..018ae8276 Binary files /dev/null and b/libs/libopenmpt/bin/x86_64/mingw/libopenmpt.dll differ diff --git a/libs/libopenmpt/bin/x86_64/openmpt-mpg123.dll b/libs/libopenmpt/bin/x86_64/openmpt-mpg123.dll new file mode 100644 index 000000000..9a0fca874 Binary files /dev/null and b/libs/libopenmpt/bin/x86_64/openmpt-mpg123.dll differ diff --git a/libs/libopenmpt/bin/x86_64/openmpt-ogg.dll b/libs/libopenmpt/bin/x86_64/openmpt-ogg.dll new file mode 100644 index 000000000..4bc1a336b Binary files /dev/null and b/libs/libopenmpt/bin/x86_64/openmpt-ogg.dll differ diff --git a/libs/libopenmpt/bin/x86_64/openmpt-vorbis.dll b/libs/libopenmpt/bin/x86_64/openmpt-vorbis.dll new file mode 100644 index 000000000..ebe8ef9b3 Binary files /dev/null and b/libs/libopenmpt/bin/x86_64/openmpt-vorbis.dll differ diff --git a/libs/libopenmpt/bin/x86_64/openmpt-zlib.dll b/libs/libopenmpt/bin/x86_64/openmpt-zlib.dll new file mode 100644 index 000000000..319b646ff Binary files /dev/null and b/libs/libopenmpt/bin/x86_64/openmpt-zlib.dll differ diff --git a/libs/libopenmpt/changelog.md b/libs/libopenmpt/changelog.md new file mode 100644 index 000000000..0b7279558 --- /dev/null +++ b/libs/libopenmpt/changelog.md @@ -0,0 +1,829 @@ + +Changelog {#changelog} +========= + +For fully detailed change log, please see the source repository directly. This +is just a high-level summary. + +### libopenmpt 0.4.7 (2019-09-23) + + * [**Bug**] Compilation fix for various platforms that do not provide + `std::aligned_alloc` in C++17 mode. The problematic dependency has been + removed. This should fix build problems on MinGW, OpenBSD, Haiku, and others + for good. + + * J2B: Ignore notes with non-existing instrument (fixes Ending.j2b). + + * mpg123: Update to v1.25.13 (2019-08-24). + * ogg: Update to v1.3.4. (2019-08-31). + * flac: Update to v1.3.3. (2019-08-04). + +### libopenmpt 0.4.6 (2019-08-10) + + * [**Bug**] Compilation fix for OpenBSD. + * [**Bug**] Compilation fix for NO_PLUGINS being defined. + + * in_openmpt: Correct documentation. `openmpt-mpg123.dll` must be placed into + the Winamp directory. + + * Detect IT files unpacked with early UNMO3 versions. + + * mpg123: Update to v1.25.11 (2019-07-18). + * minimp3: Update to commit 977514a6dfc4960d819a103f43b358e58ac6c28f + (2019-07-24). + * miniz: Update to v2.1.0 (2019-05-05). + * stb_vorbis: Update to v1.17 (2019-08-09). + +### libopenmpt 0.4.5 (2019-05-27) + + * [**Sec**] Possible crash during playback due out-of-bounds read in XM and + MT2 files (r11608). + + * Breaking out of a sustain loop through Note-Off sometimes didn't continue in + the regular sample loop. + * Seeking did not stop notes playing with XM Key Off (Kxx) effect. + +### libopenmpt 0.4.4 (2019-04-07) + + * [**Bug**] Channel VU meters were swapped. + + * Startrekker: Clamp speed to 31 ticks per row. + * MTM: Ignore unused Exy commands on import. Command E5x (Set Finetune) is now + applied correctly. + * MOD: Sample swapping was always enabled since it has been separated from the + ProTracker 1/2 compatibility flag. Now it is always enabled for Amiga-style + modules and otherwise the old heuristic is used again. + + * stb_vorbis: Update to v1.16 (2019-03-05). + +### libopenmpt 0.4.3 (2019-02-11) + + * [**Sec**] Possible crash due to null-pointer access when doing a portamento + from an OPL instrument to an empty instrument note map slot (r11348). + + * [**Bug**] libopenmpt did not compile on Apple platforms in C++17 mode. + + * IT: Various fixes for note-off + instrument number in Old Effects mode. + * MO3: Import IT row highlights as written by MO3 2.4.1.2 or newer. Required + for modules using modern tempo mode. + + * miniz: Update to v2.0.8 (2018-09-19). + * stb_vorbis: Update to v1.15 (2019-02-07). + +### libopenmpt 0.4.2 (2019-01-22) + + * [**Sec**] DSM: Assertion failure during file parsing with debug STLs + (r11209). + * [**Sec**] J2B: Assertion failure during file parsing with debug STLs + (r11216). + + * S3M: Allow volume change of OPL instruments after Note Cut. + +### libopenmpt 0.4.1 (2019-01-06) + + * [**Bug**] Binaries compiled for winold (Windows XP, Vista, 7, for CPUs + without SSE2 support) did not actually work on CPUs without SSE2 support. + * [**Bug**] libmodplug: Public symbols of the C++ API had `visibility=hidden` + set on non-MSVC systems, which made them not publicly accessible. + * [**Bug**] Project files for Windows 10 desktop builds on ARM and ARM64 + (`build/vs2017win10`) were missing from Windows source package. + * [**Bug**] MSVC project files in Windows source package lacked additional + files required to build DLLs. + + * MO3: Apply playback changes based on "ModPlug-made" header flag. + + * minimp3: Update to commit e9df0760e94044caded36a55d70ab4152134adc5 + (2018-12-23). + +### libopenmpt 0.4.0 (2018-12-23) + + * [**New**] libopenmpt now includes emulation of the OPL chip and thus plays + OPL instruments in S3M, C67 and MPTM files. OPL chip emulation volume can be + changed with the new ctl `render.opl.volume_factor`. + * [**New**] libopenmpt now supports CDFM / Composer 670 module files. + * [**New**] Autotools `configure` and plain `Makefile` now honor the variable + `CXXSTDLIB_PCLIBSPRIVATE` which serves the sole purpose of listing the + standard library (or libraries) required for static linking. The contents of + this variable will be put in `libopenmpt.pc` `Libs.private` and used for + nothing else. See \ref libopenmpt_c_staticlinking . + * [**New**] foo_openmpt: foo_openmpt now also works on Windows XP. + * [**New**] libopenmpt Emscripten builds now ship with MP3 support by + default, based on minimp3 by Lion (github.com/lieff). + * [**New**] libopenmpt: New ctl `play.at_end` can be used to change what + happens when the song end is reached: + * "fadeout": Fades the module out for a short while. Subsequent reads + after the fadeout will return 0 rendered frames. This is the default and + identical to the behaviour in previous libopenmpt versions. + * "continue": Returns 0 rendered frames when the song end is reached. + Subsequent reads will continue playing from the song start or loop + start. This can be used for custom loop logic, such as loop + auto-detection and longer fadeouts. + * "stop": Returns 0 rendered frames when the song end is reached. + Subsequent reads will return 0 rendered frames. + * [**New**] Add new metadata fields `"originaltype"` and `"originaltype_long"` + which allow more clearly reflecting what is going on with converted formats + like MO3 and GDM. + * [**New**] `Makefile` `CONFIG=emscripten` now can generate WebAssembly via + the additional option `EMSCRIPTEN_TARGET=wasm`. + * [**New**] Compiling for DOS is now experimentally supported via DJGPP GCC + 7.2 or later. + + * [**Change**] minimp3: Instead of the LGPL-2.1-licensed minimp3 by KeyJ, + libopenmpt now uses the CC0-1.0-licensed minimp3 by Lion (github.com/lieff) + as a fallback if libmpg123 is unavailable. The `USE_MINIMP3` `Makefile` + option is gone and minimp3 will be used automatically in the `Makefile` + build system if libmpg123 is not available. + * [**Change**] openmpt123: openmpt123 now rejects `--output-type` in `--ui` + and `--batch` modes and also rejects `--output` in `--render` mode. These + combinations of options really made no sense and were rather confusing. + * [**Change**] Android NDK build system now uses libc++ (`c++_shared`) instead + of GNU libstdc++ (`gnustl_shared`), as recommended by Android NDK r16b. + * [**Change**] xmp-openmpt: `openmpt-mpg123.dll` is no longer optional and + must be placed into the same directory as `xmp-openmpt.dll`. + * [**Change**] in_openmpt: `openmpt-mpg123.dll` is no longer optional and must + be placed either into the directory of the player itself or into the same + directory as `in_openmpt.dll`. This is dependent on how the player loads its + plugins. For WinAMP 5, `openmpt-mpg123.dll` needs to be in the directory + which contains `winamp.exe`. `in_openmpt.dll` needs to be in the `Plugins` + directory. + * [**Change**] foo_openmpt: foo_openmpt is now packaged as a fb2k-component + package for easier installation. + * [**Change**] When building libopenmpt with MinGW-w64, it is now recommended + to use the posix thread model (as opposed to the win32 threading model), + because the former does support std::mutex while the latter does not. When + building with win32 threading model with the Autotools build system, it is + recommended to provide the `mingw-std-threads` package. Building libopenmpt + with MinGW-w64 without any `std::thread`/`std::mutex` support is deprecated + and support for such configurations will be removed in libopenmpt 0.5. + * [**Change**] `Makefile` `CONFIG=emscripten` now has 4 `EMSCRIPTEN_TARGET=` + settings: `wasm` generates WebAssembly, `asmjs128m` generates asm.js with a + fixed size 128MB heap, `asmjs` generates asm.js with a fixed default size + heap (as of Emscripten 1.38.11, this amounts to 16MB), `js` generates + JavaScript with dynamic heap growth and with compatibility for older VMs. + * [**Change**] libmodplug: Update public headers to libmodplug 0.8.8.5. This + adds support for kind-of automatic MODPLUG_EXPORT decoration on Windows. + + * [**Regression**] Support for Clang 3.4, 3.5 has been removed. + * [**Regression**] Building with Android NDK older than NDK r16b is not + supported any more. + * [**Regression**] Support for Emscripten versions older than 1.38.5 has been + removed. + * [**Regression**] Support for libmpg123 older than 1.14.0 has been removed. + * [**Regression**] Using MediaFoundation to decode MP3 samples is no longer + supported. Use libmpg123 or minimp3 instead. + * [**Regression**] libmodplug: Support for emulating libmodplug 0.8.7 API/ABI + has been removed. + + * [**Bug**] xmp-openmpt: Sample rate and number of output channels were not + applied correctly when using per-file settings. + * [**Bug**] Internal mixer state was not initialized properly when initially + rendering in 44100kHz stereo format. + * [**Bug**] openmpt123: Prevent libsdl2 and libsdl from being enabled at the + same time because they conflict with each other. + * [**Bug**] libmodplug: Setting `SNDMIX_NORESAMPLING` in the C++ API always + resulted in linear interpolation instead of nearest neighbour + + * IT: In Compatible Gxx mode, allow sample changes next to a tone portamento + effect if a previous sample has already stopped playing. + * IT: Fix broken volume envelopes with negative values as found in breakdwn.it + by Elysis. + * MOD: Slides and delayed notes are executed on every repetition of a row with + row delay (fixes "ode to protracker"). + * XM: If the sustain point of the panning envelope is reached before key-off, + it is never released. + * XM: Do not default recall volume / panning for delayed instrument-less notes + * XM :E60 loop bug was not considered in song length calucation. + * S3M: Notes without instrument number use previous note's sample offset. + * Tighten M15 and MOD file rejection heuristics. + * J2B: Ignore frequency limits from file header. Fixes Medivo.j2b, broken + since libopenmpt-0.2.6401-beta17. + * STM: More accurate tempo calculation. + * STM: Better support for early format revisions (no such files have been + found in the wild, though). + * STM: Last character of sample name was missing. + * SFX: Work around bad conversions of the "Operation Stealth" soundtrack by + turning pattern breaks into note stops. + * IMF: Filter cutoff was upside down and the cutoff range was too small. + * ParamEq plugin center frequency was not limited correctly. + * Keep track of active SFx macro during seeking. + * The "note cut" duplicate note action did not volume-ramp the previously + playing sample. + * A song starting with non-existing patterns could not be played. + * DSM: Support restart position and 16-bit samples. + * DTM: Import global volume. + * MOD: Support notes in octave 2, like in FastTracker 2 (fixes DOPE.MOD). + * Do not apply Amiga playback heuristics to MOD files that have clearly been + written with a PC tracker. + * MPTM: More logical release node behaviour. + * Subsong search is now less thorough. It could previously find many subsongs + that are technically correct (unplayed rows at the beginning of patterns + that have been jumped over due to pattern breaks), but so far no real-world + module that would require such a thorough subsong detection was found. The + old mechanism caused way more false positives than intended with real-world + modules, though. + * Restrict the unpacked size of compressed DMF, IT, MDL and MO3 samples to + avoid huge allocations with malformed small files. + +### libopenmpt 0.3 (2017-09-27) + + * [**New**] New error handling functionality in the C API, which in particular + allows distinguishing potentially transient out-of-memory errors from parse + errors during module loading. + * [**New**] New API `openmpt::module::get_selected_subsong()` (C++) and + `openmpt_module_get_selected_subsong()` (C). + * [**New**] Faster file header probing API `openmpt::probe_file_header()` and + `openmpt::probe_file_header_get_recommended_size` (C++), and + `openmpt_probe_file_header()`, + `openmpt_probe_file_header_without_filesize()`, + `openmpt_probe_file_header_from_stream()` and + `openmpt_probe_file_header_get_recommended_size()` (C). + * [**New**] New API `openmpt::could_open_probability()` (C++) and + `openmpt_could_open_probability()` (C). This fixes a spelling error in the + old 0.2 API. + * [**New**] openmpt123: openmpt123 can now open M3U, M3U8, M3UEXT, M3U8EXT and + PLSv2 playlists via the `--playlist` option. + * [**New**] openmpt123: openmpt123 now supports very fast file header probing + via the `--probe` option. + * [**New**] Libopenmpt now supports building for Windows 10 Universal (Windows + Store 8.2) APIs with MSVC, and also for the older Windows Runtime APIs with + MinGW-w64. + * [**New**] New API header `libopenmpt_ext.h` which implements the libopenmpt + extension APIs also for the C interface. + * [**New**] The Reverb effect (S99 in S3M/IT/MPTM, and X99 in XM) is now + implemented in libopenmpt. + * [**New**] For Amiga modules, a new resampler based on the Amiga's sound + characteristics has been added. It can be activated by passing the + `render.resampler.emulate_amiga` ctl with a value of `1`. Non-Amiga modules + are not affected by this, and setting the ctl overrides the resampler choice + specified by `OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH` or + `openmpt::module::RENDER_INTERPOLATIONFILTER_LENGTH`. Support for the MOD + command E0x (Set LED Filter) is also available when the Amiga resampler is + enabled. + + * [**Change**] libopenmpt versioning changed and follows the more conventional + major.minor.patch as well as the recommendations of the + [SemVer](http://semver.org/) scheme now. In addition to the SemVer + requirements, pre-1.0.0 versions will also honor API and ABI stability in + libopenmpt (i.e. libopenmpt ignores SemVer Clause 4). + * [**Change**] The output directories of the MSVC build system were changed to + `bin/vs2015-shared/x86-64-win7/` (and similar) layout which allows building + in the same tree with different compiler versions without overwriting other + outputs. + * [**Change**] The emscripten build now exports libopenmpt as 'libopenmpt' + instead of the default 'Module'. + * [**Change**] Android: The build system changed. The various Android.mk files + have been merged into a single one which can be controlled using command + line options. + * [**Change**] The `Makefile` build system now passes `std=c++11` to the + compiler by default. Older compilers may still work if you pass + `STDCXX=c++0x` to the `make` invocation. + * [**Change**] The `Makefile` option `ANCIENT=1` is gone. + * [**Change**] The optional dependencies on `libltdl` or `libdl` are gone. + They are no longer needed for any functionality. + + * [**Regression**] Compiling client code using the C++ API now requires a + compiler running in C++11 mode. + * [**Regression**] Support for GCC 4.1, 4.2, 4.3, 4.4, 4.5, 4.6, 4.7 has been + removed. + * [**Regression**] Support for Clang 3.0, 3.1, 3.2, 3.3 has been removed. + * [**Regression**] Support for Emscripten versions older than 1.31.0 has been + removed. + * [**Regression**] Support for Android NDK versions older than 11 has been + removed. + * [**Regression**] Visual Studio 2008, 2010, 2012, 2013 support has been + removed. + * [**Regression**] Dynamic run-time loading of libmpg123 is no longer + supported. Libmpg123 must be linked at link-time now. + * [**Regression**] xmp-openmpt: xmp-openmpt now requires XMPlay 3.8 or later + and compiling xmp-openmpt requires an appropriate XMPlay SDK with + `XMPIN_FACE` >= `4`. + * [**Regression**] Support for libmpg123 older than 1.13.0 has been removed. + * [**Regression**] Un4seen unmo3 support has been removed. + + * [**Bug**] C++ API: `openmpt::exception` did not define copy and move + constructors or copy and move assignment operators in libopenmpt 0.2. The + compiler-generated ones were not adequate though. libopenmpt 0.3 adds the + appropriate special member functions. This adds the respective symbol names + to the exported ABI, which, depending on the compiler, might or might not + have been there in libopenmpt 0.2. The possibly resulting possible ODR + violation only affects cases that did crash in the libopenmpt 0.2 API anyway + due to memory double-free, and does not cause any further problems in + practice for all known platforms and compilers. + * [**Bug**] The C API could crash instead of failing gracefully in + out-of-memory situations. + * [**Bug**] The test suite could fail on MacOSX or FreeBSD in non-fatal ways + when no locale was active. + * [**Bug**] `libopenmpt_stream_callbacks_fd.h` and + `libopenmpt_stream_callbacks_file.h` were missing in Windows development + packages. + * [**Bug**] libopenmpt on Windows did not properly guard against current + working directory DLL injection attacks. + * [**Bug**] localtime() was used to determine the version of Schism Tracker + used to save IT and S3M files. This function is not guaranteed to be + thread-safe by the standard and is now no longer used. + * [**Bug**] Possible crashes with malformed IT, ITP, AMS, MDL, MED, MPTM, PSM + and Startrekker files. + * [**Bug**] Possible hangs with malformed DBM, MPTM and PSM files. + * [**Bug**] Possible hangs with malformed files containing cyclic plugin + routings. + * [**Bug**] Excessive loading times with malformed ITP / truncated AMS files. + * [**Bug**] Plugins did not work correctly when changing the sample rate + between two render calls. + * [**Bug**] Possible NULL-pointer dereference read during obscure + out-of-memory situations while handling exceptions in the C API. + * [**Bug**] libmodplug: `libmodplug.pc` was wrong. + * [**Bug**] Cross-compiling libopenmpt with autotools for Windows now properly + sets `-municode` and `-mconsole` as well as all required Windows system + libraries. + * [**Bug**] foo_openmpt: Interpolation filter and volume ramping settings were + confused in previous versions. This version resets both to the defaults. + * [**Bug**] libmodplug: The CSoundFile::Read function in the emulated + libmodplug C++ API returned the wrong value, causing qmmp (and possibly + other software) to crash. + + * Support for SoundTracker Pro II (STP) and Digital Tracker (DTM) modules. + * Increased accuracy of the sample position and sample rate to drift less when + playing very long samples. + * Various playback improvements for IT and XM files. + * Channel frequency could wrap around after some excessive portamento / down + in some formats since libopenmpt 0.2-beta17. + * Playback improvements for S3M files made with Impulse Tracker and + Schism Tracker. + * ParamEq plugin emulation didn't do anything at full gain (+15dB). + * All standard DMO effects are now also emulated on non-Windows and non-MSVC + systems. + * Added `libopenmpt_stream_callbacks_buffer.h` which adds + `openmpt_stream_callbacks` support for in-memory buffers, possibly even only + using a truncated prefix view into a bigger file which is useful for + probing. + * Avoid enabling some ProTracker-specific quirks for MOD files most likely + created with ScreamTracker 3. + * Tremolo effect only had half the intended strength in MOD files. + * Pattern loops ending on the last row a pattern were not executed correctly + in S3M files. + * Work-around for reading MIDI macros and plugin settings in some malformed IT + files written by old UNMO3 versions. + * Improve tracker detection in IT format. + * Playback fixes for 8-channel MED files + * Do not set note volume to 0 on out-of-range offset in XM files. + * Better import of some slide commands in SFX files. + * Sample 15 in "Crew Generation" by Necros requires short loops at the + beginning of the sample to not be ignored. Since we need to ignore them in + some (non-ProTracker) modules, we heuristically disable the old loop + sanitization behaviour based on the module channel count. + * Both normal and percentage offset in PLM files were handled as percentage + offset. + * MT2 files with instruments that had both sample and plugin assignments were + not read correctly. + * Some valid FAR files were rejected erroneously. + * Support for VBlank timing flag and comment field in PT36 files. + * Improved accuracy of vibrato command in DIGI / DBM files. + * STM: Add support for "WUZAMOD!" magic bytes and allow some slightly + malformed STM files to load which were previously rejected. + * Detect whether "hidden" patterns in the order list of SoundTracker modules + should be taken into account or not. + * Tighten heuristics for rejecting invalid 669, M15, MOD and ICE files and + loosen them in other places to allow some valid MOD files to load. + * Improvements to seeking: Channel panning was not always updated from + instruments / samples when seeking, and out-of-range global volume was not + applied correctly in some formats. + * seek.sync_samples=1 did not apply PTM reverse offset effect and the volume + slide part of combined volume slide + vibrato commands. + * If the order list was longer than 256 items and there was a pattern break + effect without a position jump on the last pattern of the sequence, it did + not jump to the correct restart order. + * `Makefile` has now explicit support for FreeBSD with no special option or + configuration required. + * openmpt123: Improved section layout in man page. + * libmodplug: Added all missing C++ API symbols that are accessible via the + public libmodplug header file. + * Autotools build system now has options `--disable-openmpt123`, + `--disable-tests` and `--disable-examples` which may be desireable when + cross-compiling. + * Windows binary packages now ship with libmpg123 included. + +### libopenmpt 0.2-beta20 (2016-08-07) + + * [**Bug**] PSM loader was broken on big-endian platforms since forever. + * [**Bug**] `load.skip_samples` ctl did not work for PSM16 modules. + + * There is a new `subsong` ctl, which can return the currently selected + subsong. + * More accurate ProTracker arpeggio wrap-around emulation. + * More accurate sample tuning in PSM16 files. + * Samples in DSM files were sometimes detuned and some pattern commands were + not imported correctly. + * More accurate import of MDL 7-bit panning command. + * Only import pattern commands supported by the UltraTracker version that was + used to save ULT files. Add support for command 5-C (end loop). + * DMF sample loop lengths were off by one. + * Unis 669 pan slide effect was too deep. + * Several valid (but slightly corrupted possibly due to disk failures or data + transfer errors) SoundTracker files were no longer loading since libopenmpt + 0.2-beta18. + +### libopenmpt 0.2-beta19 (2016-07-23) + + * [**Change**] libopenmpt now uses C++14 `[[deprecated]]` attribute instead + of compiler-specific solutions when appropriate. + * [**Change**] libopenmpt C++ header now uses C++11 `noexcept` instead of + C++98 `throw()` exception specification when supported. `throw()` is + deprecated since C++11. This does not change API or ABI as they are + equivalent. Use `LIBOPENMPT_ASSUME_CPLUSPLUS_NOEXCEPT` to override the + default. + * [**Change**] The preprocessor macro `LIBOPENMPT_ANCIENT_COMPILER_STDINT` is + gone. Please use `LIBOPENMPT_ASSUME_CPLUSPLUS_CSTDINT instead`. + Additionally, the typedefs moved from illegal namespace ::std into somewhat + less dangerous namespace ::openmpt::std. You can test + `#ifdef LIBOPENMPT_QUIRK_NO_CSTDINT` client-side to check whether + `libopenmpt.hpp` used the non-standard types. (Note: Of all supported + compilers, this change only affects the 3 compilers with only limited + support: MSVC 2008, GCC 4.1, GCC 4.2.) + + * [**Bug**] xmp-openmpt: Crash when viewing sample texts. + + * The public libopenmpt C++ header has auto-detection logic for the used C++ + standard now. In case your client code compiler misreports the standard + version or you want to override it for other reasons, + `#define LIBOPENMPT_ASSUME_CPLUSPLUS` to the value of the standard version + you desire to be used. There is also a macro for each individual aspect, + like `LIBOPENMPT_ASSUME_CPLUSPLUS_CSTDINT`, + `LIBOPENMPT_ASSUME_CPLUSPLUS_DEPRECATED`, + `LIBOPENMPT_ASSUME_CPLUSPLUS_NOEXCEPT` which take precedence over the + general macro. + * Portamento with sample swap behaviour was wrong for ProTracker MODs. + * Rewritten loader and various playback fixes for MDL files. + * libopenmpt 0.2-beta18 broke import of many pattern commands in DBM, DMF and + ULT files. + * ADPCM samples in MOD files were broken since libopenmpt 0.2-beta17. + +### libopenmpt 0.2-beta18 (2016-07-11) + + * [**Change**] openmpt123: Add PulseAudio output support. Autotools and + `Makefile` build systems now depend on `libpulse` and `libpulse-simple` by + default. Disable with `--without-pulseaudio` or `NO_PULSEAUDIO=1` + respectively. When enabled, PulseAudio will be the default output driver, + * [**Change**] xmp-openmpt: Settings are now stored in xmplay.ini like with + every other plugin. + + * [**Regression**] openmpt123: Support for FLAC < 1.3.0 has been removed. FLAC + before 1.3.0 is broken beyond repair as it provides `assert.h` in the + include path. + + * [**Bug**] Generated pkg-config file libopenmpt.pc by both `Makefile` and + Autotools build systems was totally broken. + * [**Bug**] libopenmpt no longer uses the non-thread-safe global std::rand() + function. + * [**Bug**] Sample loops in GDM modules did not work when using Emscripten. + * [**Bug**] XM and MO3 loaders could crash due to unaligned memory accesses. + * [**Bug**] Fixed incorrect handling of custom MPTM tunings on big endian + platforms. + * [**Bug**] Fixed various problems found with clang 3.8 static analyzer, + address sanitizer and undefined behaviour sanitizer. + * [**Bug**] File header probing functionality was broken for most formats. + * [**Bug**] With non-seekable streams, the entire file was almost always + cached even if it was not of any supported module type. + + * Seeking in allsubsongs-mode now works correctly. + * openmpt123: Added subsong support. + * Various playback fixes for 669, IT, MT2 and MTM files. + * Some MOD files with more than 128 patterns (e.g. NIETNU.MOD) were not loaded + correctly. + * A new example `libopenmpt_example_c_probe` has been added which demonstrates + the usage and flexibility of openmpt_could_open_propability() in the C API + under various constraints. + +### libopenmpt 0.2-beta17 (2016-05-21) + + * [**Change**] The Makefile and Autotools build systems now require to + explicitly specify `NO_LTDL=1` or `--without-ltdl` respectively if no + support for dynamic loading of third party libraries via libtool libltdl is + desired. + * [**Change**] In the Makefile build system option `USE_MO3` and the Autotools + build system option `--enable-mo3` are gone. Dynamic loading of un4seen + unmo3 is now always enabled when dynamic loading is possible and built-in + MO3 support is not possible because either a MP3 or a Vorbis decoder is + missing. + * [**Change**] The MSVC build system changed. The `libopenmptDLL` project is + gone. Use the new `ReleaseShared` configuration of the `libopenmpt` project + instead. libopenmpt now links against zlib by default. A separate project + with smaller footprint linking against miniz is still available as + `libopenmpt-small`. + * [**Change**] The constants used to query library information from + `openmpt_get_string()` and `openmpt::string::get()` (i.e. OPENMPT_STRING_FOO + and openmpt::string::FOO) have been deprecated because having syntactic + constants for theses keys makes extending the API in a backwards and + forwards compatible way harder than it should be. Please just use the string + literals directly. + * [**Change**] Deprecated API identifiers will now cause deprecation warnings + with MSVC, GCC and clang. `#define LIBOPENMPT_NO_DEPRECATE` to disable the + warnings. + * [**Change**] openmpt123: `--[no-]shuffle` option has been renamed to + `--[no-]randomize`. A new `--[no-]shuffle` option has been added which + shuffles randomly through the playlist as opposed to randomizing the + playlist upfront. + * [**Change**] Support for Un4seen unmo3 has generally been deprecated in + favour of the new internal mo3 decoder. Un4seen unmo3 support will be + removed on 2018-01-01. + + * [**Bug**] Memory consumption during loading has been reduced by about 1/3 in + case a seekable input stream is provided (either via C API callback open + functions or via C++ API iostream constructors). + * [**Bug**] Some samples in AMS modules were detuned when using Emscripten. + * [**Bug**] Possible crash with excessive portamento down in some formats. + * [**Bug**] Possible crashes with malformed AMF, AMS, DBM, IT, MDL, MED, MPTM, + MT2, PSM and MMCMP-, XPK- and PP20-compressed files. + * [**Bug**] `openmpt::module::format_pattern_row_channel` with `width == 0` + was returning an empty string instead of an string with unconstrained + length. + + * Support for ProTracker 3.6 IFF-style modules and SoundFX / MultiMedia Sound + (SFX / MMS) modules. + * libopenmpt now has support for DMO plugins on Windows when built with MSVC. + Additionally, the DMO Compression, Distortion, Echo, Gargle, ParamEQ and + WavesReverb DSPs are emulated on on all other platforms. + * libopenmpt now supports the DigiBooster Echo DSP. + * To avoid any of the aforementioned plugins to be used, the load.skip_plugins + ctl can be passed when loading a module. + * libopenmpt got native MO3 support with MP3 decoding either via libmpg123 or + MediaFoundation (on Windows 7 and up) and Vorbis decoding via libogg, + libvorbis, libvorbisfile or stb_vorbis. + * libopenmpt MSVC builds with Visual Studio 2010 or later on Windows 7 or + later now use an internal MO3 decoder with libogg, libvorbis, libvorbisfile, + and libmpg123 or minimp3 or MediaFoundation suppport by default. Visual + Studio 2008 builds still use unmo3.dll by default but also support the + built-in decoder in which case libmpg123 is required. + * libopenmpt with Makefile or Autotools build system can now also use + glibc/libdl instead of libtool/libltdl for dynamic loading of third-party + libraries. Options `NO_DL=1` and `--without-dl` have been added + respectively. + * The `Makefile` build system got 4 new options NO_MPG123, NO_OGG, NO_VORBIS, + NO_VORBISFILE. The default is to use the new dependencies automatically. + * The `Autotools` build system got 4 new options --without-mpg123, + --without-ogg, --without-vorbis, --without-vorbisfile. The default is to use + the new dependencies automatically. + * Makefile and Android builds got support for using minimp3 instead of + libmpg123. For Android, use `Android-minimp3-stbvorbis.mk`, for Makefile use + `USE_MINIMP3=1`. You have to download + [minimp3](http://keyj.emphy.de/minimp3/) yourself and put its contents into + `include/minimp3/`. + * `"source_url"`, `"source_date"` and `"build_compiler"` keys have been added + to `openmpt_string_get()` and `openmpt::string::get()`. + * openmpt123: Add new `--[no-]restart]` option which restarts the playlist + when finished. + * Improved Ultimate SoundTracker version detection heuristics. + * Playing a sample at a sample rate close to the mix rate could lead to small + clicks when using vibrato. + * More fine-grained internal legacy module compatibility settings to correctly + play back modules made with older versions of OpenMPT and a few other + trackers. + * The tail of compressed MDL samples was slightly off. + * Some probably hex-edited XM files (e.g. cybernostra weekend.xm) were not + loaded correctly. + * Countless other playback fixes for MOD, XM, S3M, IT and MT2 files. + +### libopenmpt 0.2-beta16 (2015-11-22) + + * [**Change**] The Autotools build system does strict checking of all + dependencies now. Instead of best effort auto-magic detection of all + potentially optional dependencies, the default set of dependencies is now + enforced unless each individual dependency gets explicitely disabled via + `--without-foo` or `--disable-foo` `./configure` switches. Run + `./configure --help` for the full list of options. + + * [**Bug**] Some MOD files were erroneously detected as 669 files. + * [**Bug**] Some malformed AMF files could result in very long loading times. + * [**Bug**] Fixed crashes in IMF and MT2 loaders. + * [**Bug**] MTM files generated by UNMO3 were not loaded properly. + + * Improved MTM playback. + * `make CONFIG=haiku` for Haiku has been added. + * Language bindings for FreeBASIC have been added (see + `libopenmpt/bindings/`). + +### libopenmpt 0.2-beta15 (2015-10-31) + + * [**Change**] openmpt123: SDL2 is now supported and preferred to SDL1 if + available with the `Makefile` build system. + + * [**Bug**] Emscripten support for older emscripten versions broke in -beta14. + These are now supported again when using `make CONFIG=emscripten-old`. + * [**Bug**] Fixed crashes in MED loader. + + * Playback improvements and loader fixes for MOD, MT2 and MED. + +### libopenmpt 0.2-beta14 (2015-09-13) + + * [**Change**] The C++ API example now uses the PortAudio C++ bindings + instead of the C API. + * [**Change**] Default compiler options for Emscripten have been changed to + more closely match the Emscripten recommendations. + + * [**Bug**] Client code compilation with C89 compilers was broken in beta13. + * [**Bug**] Test suite failed on certain Emscripten/node.js combinations. + * [**Bug**] Fixed various crashes or hangs in DMF, OKT, PLM, IT and MPTM + loaders. + + * Implemented error handling in the libopenmpt API examples. + * Various playback improvements and fixes for OKT, IT and MOD. + +### libopenmpt 0.2-beta13 (2015-08-16) + + * [**Change**] The MSVC build system has been redone. Solutions are now + located in `build/vsVERSION/`. + + * [**Bug**] get_current_channel_vu_left and get_current_channel_vu_right only + return the volume of the front left and right channels now. + get_current_channel_vu_rear_left and get_current_channel_vu_rear_right + do now actually work and return non-zero values. + * [**Bug**] Fix crashes and hangs in MED and MDL loaders and with some + truncated compressed IT samples. + * [**Bug**] Fix crash when playing extremely high-pitched samples. + + * Completed C and C++ documentation + * Added new key for openmpt::module::get_metadata, "message_raw", which + returns an empty string if there is no song message rather than a list of + instrument names. + * in_openmpt: Support for compiling with VS2008. + * xmp-openmpt: Support for compiling with VS2008. + * in_openmpt: Add a more readable file information window. + +### libopenmpt 0.2-beta12 (2015-04-19) + + * Playback fix when row delay effect is used together with offset command. + * A couple of fixes for the seek.sync_samples=1 case. + * IT compatibility fix for IT note delay. + * ProTracker MOD playback compatibility improvement. + +### libopenmpt 0.2-beta11 (2015-04-18) + + * [**Change**] openmpt_stream_seek_func() now gets called with + OPENMPT_STREAM_SEEK_SET, OPENMPT_STREAM_SEEK_CUR and + OPENMPT_STREAM_SEEK_END whence parameter instead of SEEK_SET, SEEK_CUR and + SEEK_END. These are defined to 0, 1 and 2 respectively which corresponds to + the definition in all common C libraries. If your C library uses different + constants, this theoretically breaks binary compatibility. The old + libopenmpt code, however, never actually called the seek function, thus, + there will be no problem in practice. + * [**Change**] openmpt123: When both SDL1.2 and PortAudio are available, + SDL is now the preferred backend because SDL is more widespread and better + tested on all kinds of different platforms, and in general, SDL is just + more reliable. + + * [**Bug**] libopenmpt now also compiles with GCC 4.3. + + * libopenmpt now supports PLM (Disorder Tracker 2) files. + * Various playback improvements and fixes for IT, S3M, XM, MOD, PTM and 669 + files. + +### libopenmpt 0.2-beta10 (2015-02-17) + + * [**Change**] Makefile configuration filenames changed from + `build/make/Makefile.config.*` to `build/make/config-*.mk`. + * [**Change**] libopenmpt for Android now supports unmo3 from un4seen. See + `build/android_ndk/README.AndroidNDK.txt` for details. + + * [**Bug**] Fix out-of-bounds read in mixer code for ProTracker-compatible + MOD files which was introduced back in r4223 / beta6. + + * Vibrato effect was too weak in beta8 and beta9 in IT linear slide mode. + * Very small fine portamento was wrong in beta8 and beta9 in IT linear slide + mode. + * Tiny IT playback compatibility improvements. + * STM playback improvements. + +### libopenmpt 0.2-beta9 (2014-12-21) + + * [**Bug**] libopenmpt_ext.hpp was missing from the Windows binary zip files. + +### libopenmpt 0.2-beta8 (2014-12-21) + + * [**Change**] foo_openmpt: Settings are now accessible via foobar2000 + advanced settings. + * [**Change**] Autotools based build now supports libunmo3. Specify + --enable-unmo3. + * [**Change**] Support for dynamic loading of libunmo3 on MacOS X. + * [**Change**] libopenmpt now uses libltld (from libtool) for dynamic loading + of libunmo3 on all non-Windows platforms. + * [**Change**] Support for older compilers: + * GCC 4.1.x to 4.3.x (use `make ANCIENT=1`) + * Microsoft Visual Studio 2008 (with latest Service Pack) + (see `build/vs2008`) + * [**Change**] libopenmpt_ext.hpp is now distributed by default. The API is + still considered experimental and not guaranteed to stay API or ABI + compatible. + * [**Change**] xmp-openmpt / in_openmpt: No more libopenmpt_settings.dll. + The settings dialog now uses a statically linked copy of MFC. + + * [**Bug**] The -autotools tarballs were not working at all. + + * Vastly improved MT2 loader. + * Improved S3M playback compatibility. + * Added openmpt::ext::interactive, an extension which adds a whole bunch of + new functionality to change playback in some way or another. + * Added possibility to sync sample playback when using + openmpt::module::set_position_* by setting the ctl value + seek.sync_samples=1 + * Support for "hidden" subsongs has been added. + They are accessible through the same interface as ordinary subsongs, i.e. + use openmpt::module::select_subsong to switch between any kind of subsongs. + * All subsongs can now be played consecutively by passing -1 as the subsong + index in openmpt::module::select_subsong. + * Added documentation for a couple of more functions. + +### libopenmpt 0.2-beta7 (2014-09-07) + + * [**Change**] libopenmpt now has an GNU Autotools based build system (in + addition to all previously supported ways of building libopenmpt). + Autotools support is packaged separately as tarballs ending in + `-autotools.tar.gz`. + + * [**Bug**] The distributed windows .zip file did not include pugixml. + + * [**Regression**] openmpt123: Support for writing WavPack (.wv) files has + been removed. + + Reasoning: + 1. WavPack support was incomplete and did not include support for writing + WavPack metadata at all. + 2. openmpt123 already supports libSndFile which can be used to write + uncompressed lossless WAV files which can then be encoded to whatever + format the user desires with other tools. + +### libopenmpt 0.2-beta6 (2014-09-06) + + * [**Change**] openmpt123: SDL is now also used by default if availble, in + addition to PortAudio. + * [**Change**] Support for emscripten is no longer experimental. + * [**Change**] libopenmpt itself can now also be compiled with VS2008. + + * [**Bug**] Fix all known crashes on platforms that do not support unaligned + memory access. + * [**Bug**] openmpt123: Effect column was always missing in pattern display. + +### libopenmpt 0.2-beta5 (2014-06-15) + + * [**Change**] Add unmo3 support for non-Windows builds. + * [**Change**] Namespace all internal functions in order to allow statically + linking against libopenmpt without risking duplicate symbols. + * [**Change**] Iconv is now completely optional and only used on Linux + systems by default. + * [**Change**] Added libopenmpt_example_c_stdout.c, an example without + requiring PortAudio. + * [**Change**] Add experimental support for building libopenmpt with + emscripten. + + * [**Bug**] Fix ping-pong loop behaviour which broke in 0.2-beta3. + * [**Bug**] Fix crashes when accessing invalid patterns through libopenmpt + API. + * [**Bug**] Makefile: Support building with missing optional dependencies + without them being stated explicitely. + * [**Bug**] openmpt123: Crash when quitting while playback is stopped. + * [**Bug**] openmpt123: Crash when writing output to a file in interactive UI + mode. + * [**Bug**] openmpt123: Wrong FLAC output filename in --render mode. + + * Various smaller playback accuracy improvements. + +### libopenmpt 0.2-beta4 (2014-02-25) + + * [**Bug**] Makefile: Dependency tracking for the test suite did not work. + +### libopenmpt 0.2-beta3 (2014-02-21) + + * [**Change**] The test suite is now built by default with Makefile based + builds. Use `TEST=0` to skip building the tests. `make check` runs the test + suite. + + * [**Bug**] Crash in MOD and XM loaders on architectures not supporting + unaligned memory access. + * [**Bug**] MMCMP, PP20 and XPK unpackers should now work on non-x86 hardware + and implement proper bounds checking. + * [**Bug**] openmpt_module_get_num_samples() returned the wrong value. + * [**Bug**] in_openmpt: DSP plugins did not work properly. + * [**Bug**] in_openmpt/xmp-openmpt: Setting name for stereo separation was + misspelled. This version will revert your stereo separation settings to + default. + * [**Bug**] Crash when loading some corrupted modules with stereo samples. + + * Support building on Android NDK. + * Avoid clicks in sample loops when using interpolation. + * IT filters are now done in integer instead of floating point. This improves + performance, especially on architectures with no or a slow FPU. + * MOD pattern break handling fixes. + * Various XM playback improvements. + * Improved and switchable dithering when using 16bit integer API. + +### libopenmpt 0.2-beta2 (2014-01-12) + + * [**Bug**] MT2 loader crash. + * [**Bug**] Saving settings in in_openmpt and xmp-openmpt did not work. + * [**Bug**] Load libopenmpt_settings.dll also from below Plugins directory in + Winamp. + + * DBM playback improvements. + +### libopenmpt 0.2-beta1 (2013-12-31) + + * First release. + diff --git a/libs/libopenmpt/debian/libopenmpt-0.4.0-trusty-backport.diff b/libs/libopenmpt/debian/libopenmpt-0.4.0-trusty-backport.diff new file mode 100644 index 000000000..1c9b56ba5 --- /dev/null +++ b/libs/libopenmpt/debian/libopenmpt-0.4.0-trusty-backport.diff @@ -0,0 +1,550 @@ +diff -uraN ../../orig/libopenmpt-0.4.0/debian/changelog ./debian/changelog +--- ../../orig/libopenmpt-0.4.0/debian/changelog 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/changelog 2019-01-04 17:56:35.024725537 -0500 +@@ -1,3 +1,38 @@ ++libopenmpt (0.4.0-ubuntu14.04.1~ppa14) trusty; urgency=medium ++ ++ * Remove debian symbols files due to gcc 4.8 - 5 C++ abi incompatibility ++ ++ -- Sonic Team Junior Fri, 04 Jan 2019 17:56:01 -0500 ++ ++libopenmpt (0.4.0-ubuntu14.04.1~ppa13) trusty; urgency=medium ++ ++ * autoreconf libtool ++ ++ -- Sonic Team Junior Fri, 04 Jan 2019 17:10:45 -0500 ++ ++libopenmpt (0.4.0-ubuntu14.04.1~ppa12) trusty; urgency=medium ++ ++ * debian/rules autoreconf ++ ++ -- Sonic Team Junior Fri, 04 Jan 2019 17:03:19 -0500 ++ ++libopenmpt (0.4.0-ubuntu14.04.1~ppa11) trusty; urgency=medium ++ ++ * debian/rules autoreconf ++ ++ -- Sonic Team Junior Fri, 04 Jan 2019 16:59:08 -0500 ++ ++libopenmpt (0.4.0-ubuntu14.04.1~ppa10) trusty; urgency=medium ++ ++ * Backport to trusty ++ * Added automake build depend ++ * Adjusted debhelper depend to >= 9.0~ ++ * Adjusted dpkg-dev depend to >= 1.17.0 ++ * Adjusted debian/compat to 10 ++ * autoreconf --force --install ++ ++ -- Sonic Team Junior Fri, 04 Jan 2019 16:54:04 -0500 ++ + libopenmpt (0.4.0-1) unstable; urgency=medium + + * New upstream release. +diff -uraN ../../orig/libopenmpt-0.4.0/debian/compat ./debian/compat +--- ../../orig/libopenmpt-0.4.0/debian/compat 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/compat 2019-01-04 16:39:17.613976357 -0500 +@@ -1 +1 @@ +-11 ++10 +diff -uraN ../../orig/libopenmpt-0.4.0/debian/control ./debian/control +--- ../../orig/libopenmpt-0.4.0/debian/control 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/control 2019-01-04 17:10:42.008523333 -0500 +@@ -4,10 +4,12 @@ + Maintainer: Debian Multimedia Maintainers + Uploaders: James Cowgill + Build-Depends: +- debhelper (>= 11.1~), ++ automake, ++ libtool, ++ debhelper (>= 9.0~), + dh-exec, + doxygen, +- dpkg-dev (>= 1.18.0), ++ dpkg-dev (>= 1.17.0), + libflac-dev, + libmpg123-dev, + libogg-dev, +diff -uraN ../../orig/libopenmpt-0.4.0/debian/files ./debian/files +--- ../../orig/libopenmpt-0.4.0/debian/files 1969-12-31 19:00:00.000000000 -0500 ++++ ./debian/files 2019-01-04 17:56:47.813250880 -0500 +@@ -0,0 +1 @@ ++libopenmpt_0.4.0-ubuntu14.04.1~ppa14_source.buildinfo libs optional +diff -uraN ../../orig/libopenmpt-0.4.0/debian/libopenmpt0.symbols ./debian/libopenmpt0.symbols +--- ../../orig/libopenmpt-0.4.0/debian/libopenmpt0.symbols 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/libopenmpt0.symbols 1969-12-31 19:00:00.000000000 -0500 +@@ -1,256 +0,0 @@ +-libopenmpt.so.0 libopenmpt0 #MINVER# +-* Build-Depends-Package: libopenmpt-dev +-# Ignore std:: template instantiations +- (regex|optional)"^_ZN?K?S" 0.2.7025~beta20.1 +- _ZN7openmpt10module_ext13get_interfaceERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt10module_extC1EPKcjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt10module_extC1EPKcmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt10module_extC1EPKvjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt10module_extC1EPKvmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extC1ERKS0_@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extC1ERKSt6vectorIcSaIcEERSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcES2_EESC_St4lessISC_ESaISt4pairIKSC_SC_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extC1ERSiRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_St4lessIS9_ESaISt4pairIKS9_S9_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt10module_extC2EPKcjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt10module_extC2EPKcmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt10module_extC2EPKvjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt10module_extC2EPKvmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extC2ERKS0_@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extC2ERKSt6vectorIcSaIcEERSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcES2_EESC_St4lessISC_ESaISt4pairIKSC_SC_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extC2ERSiRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_St4lessIS9_ESaISt4pairIKS9_S9_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extD0Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extD1Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extD2Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt10module_extaSERKS0_@Base 0.2.7025~beta20.1 +- _ZN7openmpt16get_core_versionEv@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt17probe_file_headerEyPKhj@Base 0.3.0 +- (arch-bits=64)_ZN7openmpt17probe_file_headerEmPKhm@Base 0.3.0 +- (arch-bits=32)_ZN7openmpt17probe_file_headerEyPKhjy@Base 0.3.0 +- (arch-bits=64)_ZN7openmpt17probe_file_headerEmPKhmm@Base 0.3.0 +- (arch-bits=32)_ZN7openmpt17probe_file_headerEyRSi@Base 0.3.0 +- (arch-bits=64)_ZN7openmpt17probe_file_headerEmRSi@Base 0.3.0 +- _ZN7openmpt19get_library_versionEv@Base 0.2.7025~beta20.1 +- _ZN7openmpt22could_open_probabilityERSidRSo@Base 0.3.0 +- _ZN7openmpt22could_open_propabilityERSidRSo@Base 0.2.7025~beta20.1 +- _ZN7openmpt22is_extension_supportedERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt24get_supported_extensionsB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt38probe_file_header_get_recommended_sizeEv@Base 0.3.0 +- _ZN7openmpt6module14select_subsongEi@Base 0.2.7025~beta20.1 +- _ZN7openmpt6module16set_render_paramEii@Base 0.2.7025~beta20.1 +- _ZN7openmpt6module16set_repeat_countEi@Base 0.2.7025~beta20.1 +- _ZN7openmpt6module20set_position_secondsEd@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module21read_interleaved_quadEijPf@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module21read_interleaved_quadEimPf@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module21read_interleaved_quadEijPs@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module21read_interleaved_quadEimPs@Base 0.2.7025~beta20.1 +- _ZN7openmpt6module22set_position_order_rowEii@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module23read_interleaved_stereoEijPf@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module23read_interleaved_stereoEimPf@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module23read_interleaved_stereoEijPs@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module23read_interleaved_stereoEimPs@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module4readEijPf@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module4readEimPf@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module4readEijPfS1_@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module4readEimPfS1_@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module4readEijPfS1_S1_S1_@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module4readEimPfS1_S1_S1_@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module4readEijPs@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module4readEimPs@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module4readEijPsS1_@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module4readEimPsS1_@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6module4readEijPsS1_S1_S1_@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6module4readEimPsS1_S1_S1_@Base 0.2.7025~beta20.1 +- _ZN7openmpt6module7ctl_setERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES8_@Base 0.2.7025~beta20.1 +- _ZN7openmpt6module8set_implEPNS_11module_implE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC1EPKcS2_RSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6moduleC1EPKcjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6moduleC1EPKcmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC1EPKhS2_RSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6moduleC1EPKhjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6moduleC1EPKhmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6moduleC1EPKvjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6moduleC1EPKvmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC1ERKS0_@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC1ERKSt6vectorIcSaIcEERSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcES2_EESC_St4lessISC_ESaISt4pairIKSC_SC_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC1ERKSt6vectorIhSaIhEERSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESD_St4lessISD_ESaISt4pairIKSD_SD_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC1ERSiRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_St4lessIS9_ESaISt4pairIKS9_S9_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC1Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC2EPKcS2_RSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6moduleC2EPKcjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6moduleC2EPKcmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC2EPKhS2_RSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6moduleC2EPKhjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6moduleC2EPKhmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZN7openmpt6moduleC2EPKvjRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZN7openmpt6moduleC2EPKvmRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESA_St4lessISA_ESaISt4pairIKSA_SA_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC2ERKS0_@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC2ERKSt6vectorIcSaIcEERSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcES2_EESC_St4lessISC_ESaISt4pairIKSC_SC_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC2ERKSt6vectorIhSaIhEERSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEESD_St4lessISD_ESaISt4pairIKSD_SD_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC2ERSiRSoRKSt3mapINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEES9_St4lessIS9_ESaISt4pairIKS9_S9_EEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleC2Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleD0Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleD1Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleD2Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt6moduleaSERKS0_@Base 0.2.7025~beta20.1 +- _ZN7openmpt6string3getERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt9exceptionC1EOS0_@Base 0.3.0 +- _ZN7openmpt9exceptionC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt9exceptionC1ERKS0_@Base 0.3.0 +- _ZN7openmpt9exceptionC2EOS0_@Base 0.3.0 +- _ZN7openmpt9exceptionC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0.2.7025~beta20.1 +- _ZN7openmpt9exceptionC2ERKS0_@Base 0.3.0 +- _ZN7openmpt9exceptionD0Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt9exceptionD1Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt9exceptionD2Ev@Base 0.2.7025~beta20.1 +- _ZN7openmpt9exceptionaSEOS0_@Base 0.3.0 +- _ZN7openmpt9exceptionaSERKS0_@Base 0.3.0 +- _ZNK7openmpt6module12get_metadataERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module14get_num_ordersEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module15get_current_rowEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module15get_num_samplesEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module15get_order_namesB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module16get_num_channelsEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module16get_num_patternsEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module16get_num_subsongsEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module16get_render_paramEi@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module16get_repeat_countEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module16get_sample_namesB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module17get_channel_namesB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module17get_current_orderEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module17get_current_speedEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module17get_current_tempoEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module17get_metadata_keysB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module17get_order_patternEi@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module17get_pattern_namesB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module17get_subsong_namesB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module19get_current_patternEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module19get_num_instrumentsEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module20get_duration_secondsEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module20get_instrument_namesB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module20get_pattern_num_rowsEi@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module20get_position_secondsEv@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module20get_selected_subsongEv@Base 0.3.0 +- (arch-bits=32)_ZNK7openmpt6module26format_pattern_row_channelB5cxx11Eiiijb@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZNK7openmpt6module26format_pattern_row_channelB5cxx11Eiiimb@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module27get_current_channel_vu_leftEi@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module27get_current_channel_vu_monoEi@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module28get_current_channel_vu_rightEi@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module28get_current_playing_channelsEv@Base 0.2.7025~beta20.1 +- (arch-bits=32)_ZNK7openmpt6module29highlight_pattern_row_channelB5cxx11Eiiijb@Base 0.2.7025~beta20.1 +- (arch-bits=64)_ZNK7openmpt6module29highlight_pattern_row_channelB5cxx11Eiiimb@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module31get_pattern_row_channel_commandEiiii@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module32get_current_channel_vu_rear_leftEi@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module33get_current_channel_vu_rear_rightEi@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module34format_pattern_row_channel_commandB5cxx11Eiiii@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module37highlight_pattern_row_channel_commandB5cxx11Eiiii@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module7ctl_getERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE@Base 0.2.7025~beta20.1 +- _ZNK7openmpt6module8get_ctlsB5cxx11Ev@Base 0.2.7025~beta20.1 +- _ZNK7openmpt9exception4whatEv@Base 0.2.7025~beta20.1 +- _ZTIN7openmpt10module_extE@Base 0.2.7025~beta20.1 +- _ZTIN7openmpt6moduleE@Base 0.2.7025~beta20.1 +- _ZTIN7openmpt9exceptionE@Base 0.2.7025~beta20.1 +- (optional=weak)_ZTISt11_Mutex_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 0.2.7025~beta20.1 +- (optional=weak)_ZTISt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 0.2.7025~beta20.1 +- _ZTSN7openmpt10module_extE@Base 0.2.7025~beta20.1 +- _ZTSN7openmpt6moduleE@Base 0.2.7025~beta20.1 +- _ZTSN7openmpt9exceptionE@Base 0.2.7025~beta20.1 +- (optional=weak)_ZTSSt11_Mutex_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 0.2.7025~beta20.1 +- (optional=weak)_ZTSSt16_Sp_counted_baseILN9__gnu_cxx12_Lock_policyE2EE@Base 0.2.7025~beta20.1 +- (optional=weak)_ZTSSt19_Sp_make_shared_tag@Base 0.2.7025~beta20.1 +- _ZTVN7openmpt10module_extE@Base 0.2.7025~beta20.1 +- _ZTVN7openmpt6moduleE@Base 0.2.7025~beta20.1 +- _ZTVN7openmpt9exceptionE@Base 0.2.7025~beta20.1 +- (optional=weak)_ZZNSt19_Sp_make_shared_tag5_S_tiEvE5__tag@Base 0.4.0 +- openmpt_could_open_probability2@Base 0.3.0 +- openmpt_could_open_probability@Base 0.3.0 +- openmpt_could_open_propability@Base 0.2.7025~beta20.1 +- openmpt_error_func_default@Base 0.3.0 +- openmpt_error_func_errno@Base 0.3.0 +- openmpt_error_func_errno_userdata@Base 0.3.0 +- openmpt_error_func_ignore@Base 0.3.0 +- openmpt_error_func_log@Base 0.3.0 +- openmpt_error_func_store@Base 0.3.0 +- openmpt_error_is_transient@Base 0.3.0 +- openmpt_error_string@Base 0.3.0 +- openmpt_free_string@Base 0.2.7025~beta20.1 +- openmpt_get_core_version@Base 0.2.7025~beta20.1 +- openmpt_get_library_version@Base 0.2.7025~beta20.1 +- openmpt_get_string@Base 0.2.7025~beta20.1 +- openmpt_get_supported_extensions@Base 0.2.7025~beta20.1 +- openmpt_is_extension_supported@Base 0.2.7025~beta20.1 +- openmpt_log_func_default@Base 0.2.7025~beta20.1 +- openmpt_log_func_silent@Base 0.2.7025~beta20.1 +- openmpt_module_create2@Base 0.3.0 +- openmpt_module_create@Base 0.2.7025~beta20.1 +- openmpt_module_create_from_memory2@Base 0.3.0 +- openmpt_module_create_from_memory@Base 0.2.7025~beta20.1 +- openmpt_module_ctl_get@Base 0.2.7025~beta20.1 +- openmpt_module_ctl_set@Base 0.2.7025~beta20.1 +- openmpt_module_destroy@Base 0.2.7025~beta20.1 +- openmpt_module_error_clear@Base 0.3.0 +- openmpt_module_error_get_last@Base 0.3.0 +- openmpt_module_error_get_last_message@Base 0.3.0 +- openmpt_module_error_set_last@Base 0.3.0 +- openmpt_module_ext_create@Base 0.3.0 +- openmpt_module_ext_create_from_memory@Base 0.3.0 +- openmpt_module_ext_destroy@Base 0.3.0 +- openmpt_module_ext_get_interface@Base 0.3.0 +- openmpt_module_ext_get_module@Base 0.3.0 +- openmpt_module_format_pattern_row_channel@Base 0.2.7025~beta20.1 +- openmpt_module_format_pattern_row_channel_command@Base 0.2.7025~beta20.1 +- openmpt_module_get_channel_name@Base 0.2.7025~beta20.1 +- openmpt_module_get_ctls@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_channel_vu_left@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_channel_vu_mono@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_channel_vu_rear_left@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_channel_vu_rear_right@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_channel_vu_right@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_order@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_pattern@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_playing_channels@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_row@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_speed@Base 0.2.7025~beta20.1 +- openmpt_module_get_current_tempo@Base 0.2.7025~beta20.1 +- openmpt_module_get_duration_seconds@Base 0.2.7025~beta20.1 +- openmpt_module_get_instrument_name@Base 0.2.7025~beta20.1 +- openmpt_module_get_metadata@Base 0.2.7025~beta20.1 +- openmpt_module_get_metadata_keys@Base 0.2.7025~beta20.1 +- openmpt_module_get_num_channels@Base 0.2.7025~beta20.1 +- openmpt_module_get_num_instruments@Base 0.2.7025~beta20.1 +- openmpt_module_get_num_orders@Base 0.2.7025~beta20.1 +- openmpt_module_get_num_patterns@Base 0.2.7025~beta20.1 +- openmpt_module_get_num_samples@Base 0.2.7025~beta20.1 +- openmpt_module_get_num_subsongs@Base 0.2.7025~beta20.1 +- openmpt_module_get_order_name@Base 0.2.7025~beta20.1 +- openmpt_module_get_order_pattern@Base 0.2.7025~beta20.1 +- openmpt_module_get_pattern_name@Base 0.2.7025~beta20.1 +- openmpt_module_get_pattern_num_rows@Base 0.2.7025~beta20.1 +- openmpt_module_get_pattern_row_channel_command@Base 0.2.7025~beta20.1 +- openmpt_module_get_position_seconds@Base 0.2.7025~beta20.1 +- openmpt_module_get_render_param@Base 0.2.7025~beta20.1 +- openmpt_module_get_repeat_count@Base 0.2.7025~beta20.1 +- openmpt_module_get_sample_name@Base 0.2.7025~beta20.1 +- openmpt_module_get_selected_subsong@Base 0.3.0 +- openmpt_module_get_subsong_name@Base 0.2.7025~beta20.1 +- openmpt_module_highlight_pattern_row_channel@Base 0.2.7025~beta20.1 +- openmpt_module_highlight_pattern_row_channel_command@Base 0.2.7025~beta20.1 +- openmpt_module_read_float_mono@Base 0.2.7025~beta20.1 +- openmpt_module_read_float_quad@Base 0.2.7025~beta20.1 +- openmpt_module_read_float_stereo@Base 0.2.7025~beta20.1 +- openmpt_module_read_interleaved_float_quad@Base 0.2.7025~beta20.1 +- openmpt_module_read_interleaved_float_stereo@Base 0.2.7025~beta20.1 +- openmpt_module_read_interleaved_quad@Base 0.2.7025~beta20.1 +- openmpt_module_read_interleaved_stereo@Base 0.2.7025~beta20.1 +- openmpt_module_read_mono@Base 0.2.7025~beta20.1 +- openmpt_module_read_quad@Base 0.2.7025~beta20.1 +- openmpt_module_read_stereo@Base 0.2.7025~beta20.1 +- openmpt_module_select_subsong@Base 0.2.7025~beta20.1 +- openmpt_module_set_error_func@Base 0.3.0 +- openmpt_module_set_log_func@Base 0.3.0 +- openmpt_module_set_position_order_row@Base 0.2.7025~beta20.1 +- openmpt_module_set_position_seconds@Base 0.2.7025~beta20.1 +- openmpt_module_set_render_param@Base 0.2.7025~beta20.1 +- openmpt_module_set_repeat_count@Base 0.2.7025~beta20.1 +- openmpt_probe_file_header@Base 0.3.0 +- openmpt_probe_file_header_from_stream@Base 0.3.0 +- openmpt_probe_file_header_get_recommended_size@Base 0.3.0 +- openmpt_probe_file_header_without_filesize@Base 0.3.0 +diff -uraN ../../orig/libopenmpt-0.4.0/debian/libopenmpt-modplug1.symbols ./debian/libopenmpt-modplug1.symbols +--- ../../orig/libopenmpt-0.4.0/debian/libopenmpt-modplug1.symbols 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/libopenmpt-modplug1.symbols 1969-12-31 19:00:00.000000000 -0500 +@@ -1,200 +0,0 @@ +-libopenmpt_modplug.so.1 libopenmpt-modplug1 #MINVER# +-* Build-Depends-Package: libopenmpt-modplug-dev +- LIBOPENMPT_MODPLUG1@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_ExportIT@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_ExportMOD@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_ExportS3M@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_ExportXM@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetCurrentOrder@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetCurrentPattern@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetCurrentRow@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetCurrentSpeed@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetCurrentTempo@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetLength@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetMasterVolume@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetMessage@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetModuleType@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetName@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetPattern@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetPlayingChannels@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_GetSettings@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_InitMixerCallback@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_InstrumentName@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_Load@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_NumChannels@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_NumInstruments@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_NumPatterns@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_NumSamples@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_Read@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_SampleName@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_Seek@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_SeekOrder@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_SetMasterVolume@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_SetSettings@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_Unload@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- ModPlug_UnloadMixerCallback@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile10FreeSampleEPv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile10InitPlayerEb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile10NoteChangeEjibb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile10PackSampleERii@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile10ProcessAGCEi@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile10ProcessRowEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile10ReadSampleEP14_MODINSTRUMENTjPKcj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile10RetrigNoteEjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile10gdwSysInfoE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile10gnCPUUsageE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile10gnChannelsE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile11DoFreqSlideEP11_MODCHANNELi@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile11FineVibratoEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile11FreePatternEPv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile11InitSysInfoEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile11LoopPatternEii@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile11PatternLoopEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile11VolumeSlideEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile12FineVolumeUpEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile12ITInstrToMPTEPKvP17_INSTRUMENTHEADERj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile12IsSampleUsedEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile12PanningSlideEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile12PortamentoUpEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile12ResetMidiCfgEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile12SetMixConfigEjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile12gnReverbTypeE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile12gpSndMixHookE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile13CanPackSampleEPcjjPh@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile13CheckCPUUsageEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile13DestroySampleEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile13ResetChannelsEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile13SetCurrentPosEj@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile13SetWaveConfigEjjjb@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile13gdwMixingFreqE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile13gdwSoundSetupE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile13m_nXBassDepthE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile13m_nXBassRangeE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile14AllocateSampleEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14FineVolumeDownEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14GlobalFadeSongEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14GlobalVolSlideEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14LoadMixPluginsEPKvj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14PortamentoDownEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14ProcessEffectsEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14SaveMixPluginsEP8_IO_FILEb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14SetPatternNameEjPKc@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14TonePortamentoEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile14m_nReverbDelayE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile14m_nReverbDepthE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile15AllocatePatternEjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile15ChannelVolSlideEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile15CreateStereoMixEi@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile15GetSongCommentsEPcjj@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile15SetCurrentOrderEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile15SetMasterVolumeEjb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile15SetWaveConfigExEbbbbbbb@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile15gnBitsPerSampleE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile15m_nStreamVolumeE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile16AdjustSampleLoopEP14_MODINSTRUMENT@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile16FinePortamentoUpEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile16InstrumentChangeEP11_MODCHANNELjbbb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile16IsInstrumentUsedEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile16ProcessMidiMacroEjPKcj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile16m_nProLogicDelayE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile16m_nProLogicDepthE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile17DestroyInstrumentEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile17MapMidiInstrumentEjjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile17SetResamplingModeEj@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile17m_nMaxMixChannelsE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile18FinePortamentoDownEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile18GetRawSongCommentsEPcjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile18ReadSampleFromSongEjPS_j@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile18SetXBassParametersEjj@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile19DetectUnusedSamplesEPb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile19ExtendedMODCommandsEjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile19ExtendedS3MCommandsEjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile19SetReverbParametersEjj@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile19gnVolumeRampSamplesE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile19m_nStereoSeparationE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile20FrequencyToTransposeEP14_MODINSTRUMENT@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile20FrequencyToTransposeEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile20Normalize24BitBufferEPhjjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile20TransposeToFrequencyEii@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile21ExtendedChannelEffectEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile21ExtraFinePortamentoUpEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile21RemoveSelectedSamplesEPb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile21SetSurroundParametersEjj@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile21gpMixPluginCreateProcE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile22ReadInstrumentFromSongEjPS_j@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile23ExtraFinePortamentoDownEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile23RemoveInstrumentSamplesEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile4ReadEPvj@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile5gnAGCE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile6CreateEPKhj@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile6KeyOffEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile6ReadITEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile6ReadXMEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile6SetAGCEb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7DestroyEv@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile7NoteCutEjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7Read669EPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadABCEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadAMFEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadAMSEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadDBMEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadDMFEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadDSMEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadFAREPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadJ2BEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadMDLEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadMIDEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadMT2EPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadMTMEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadMedEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadModEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadOKTEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadPATEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadPSMEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadPTMEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadS3MEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadSTMEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadUMXEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadUltEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7ReadWavEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7TestABCEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7TestMIDEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7TestPATEPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7TremoloEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile7VibratoEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile8CheckNNAEjjib@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile8FadeSongEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile8ReadAMS2EPKhj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile8ReadNoteEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile8ResetAGCEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile8SetSpeedEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile8SetTempoEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile9GetLengthEbb@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFile9PanbrelloEP11_MODCHANNELj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZN10CSoundFile9gnVUMeterE@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFileC1Ev@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFileC2Ev@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFileD1Ev@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZN10CSoundFileD2Ev@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZNK10CSoundFile10S3MConvertEP11_MODCOMMANDb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile13GetCurrentPosEv@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZNK10CSoundFile13GetNNAChannelEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile13GetSampleNameEjPc@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile14GetMaxPositionEv@LIBOPENMPT_MODPLUG1 0.2.7386~beta20.3 +- _ZNK10CSoundFile14GetNumChannelsEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile14GetNumPatternsEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile14GetPatternNameEjPcj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile14GetSaveFormatsEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile14IsSongFinishedEjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile14ModSaveCommandEPK11_MODCOMMANDb@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile14S3MSaveConvertEPjS0_b@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile17ConvertModCommandEP11_MODCOMMAND@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile17CutOffToFrequencyEji@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile17GetBestSaveFormatEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile17GetFreqFromPeriodEjji@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile17GetInstrumentNameEjPc@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile17GetNoteFromPeriodEj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile17GetNumInstrumentsEv@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile17GetPeriodFromNoteEjij@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile18SetupChannelFilterEP11_MODCHANNELbi@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +- _ZNK10CSoundFile19IsValidBackwardJumpEjjjj@LIBOPENMPT_MODPLUG1 0.2.7561~beta20.5 +diff -uraN ../../orig/libopenmpt-0.4.0/debian/rules ./debian/rules +--- ../../orig/libopenmpt-0.4.0/debian/rules 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/rules 2019-01-04 17:03:16.206691071 -0500 +@@ -11,9 +11,10 @@ + dh $@ + + override_dh_autoreconf: +- dh_autoreconf --as-needed ++ autoreconf --force --install + + override_dh_auto_configure: ++ debian/rules override_dh_autoreconf + dh_auto_configure -- --disable-static --enable-libopenmpt_modplug + + override_dh_auto_build: diff --git a/libs/libopenmpt/debian/libopenmpt-0.4.0-xenial-backport.diff b/libs/libopenmpt/debian/libopenmpt-0.4.0-xenial-backport.diff new file mode 100644 index 000000000..9cb88b748 --- /dev/null +++ b/libs/libopenmpt/debian/libopenmpt-0.4.0-xenial-backport.diff @@ -0,0 +1,40 @@ +diff -uraN ../../orig/libopenmpt-0.4.0/debian/changelog ./debian/changelog +--- ../../orig/libopenmpt-0.4.0/debian/changelog 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/changelog 2019-01-04 16:37:08.788775423 -0500 +@@ -1,3 +1,12 @@ ++libopenmpt (0.4.0-ubuntu16.04.1~ppa10) xenial; urgency=medium ++ ++ * Backport to Xenial ++ * automake build depend added ++ * debhelper depend adjusted to >= 9.0~ ++ * deb compat level adjusted to 10 ++ ++ -- Sonic Team Junior Fri, 04 Jan 2019 16:35:08 -0500 ++ + libopenmpt (0.4.0-1) unstable; urgency=medium + + * New upstream release. +diff -uraN ../../orig/libopenmpt-0.4.0/debian/compat ./debian/compat +--- ../../orig/libopenmpt-0.4.0/debian/compat 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/compat 2019-01-04 16:34:31.830370437 -0500 +@@ -1 +1 @@ +-11 ++10 +diff -uraN ../../orig/libopenmpt-0.4.0/debian/control ./debian/control +--- ../../orig/libopenmpt-0.4.0/debian/control 2018-12-24 16:43:58.000000000 -0500 ++++ ./debian/control 2019-01-04 16:34:59.339499384 -0500 +@@ -4,7 +4,8 @@ + Maintainer: Debian Multimedia Maintainers + Uploaders: James Cowgill + Build-Depends: +- debhelper (>= 11.1~), ++ automake, ++ debhelper (>= 9.0~), + dh-exec, + doxygen, + dpkg-dev (>= 1.18.0), +diff -uraN ../../orig/libopenmpt-0.4.0/debian/files ./debian/files +--- ../../orig/libopenmpt-0.4.0/debian/files 1969-12-31 19:00:00.000000000 -0500 ++++ ./debian/files 2019-01-04 16:37:20.001229883 -0500 +@@ -0,0 +1 @@ ++libopenmpt_0.4.0-ubuntu16.04.1~ppa10_source.buildinfo libs optional diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt.h b/libs/libopenmpt/inc/libopenmpt/libopenmpt.h new file mode 100644 index 000000000..d41324885 --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt.h @@ -0,0 +1,1449 @@ +/* + * libopenmpt.h + * ------------ + * Purpose: libopenmpt public c interface + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_H +#define LIBOPENMPT_H + +#include "libopenmpt_config.h" +#include +#include + +/*! + * \page libopenmpt_c_overview C API + * + * \section libopenmpt_c_error Error Handling + * + * - Functions with no return value in the corresponding C++ API return 0 on + * failure and 1 on success. + * - Functions that return a string in the corresponding C++ API return a + * dynamically allocated const char *. In case of failure or memory allocation + * failure, a NULL pointer is returned. + * - Functions that return integer values signal error condition by returning + * an invalid value (-1 in most cases, 0 in some cases). + * - All functions that work on an \ref openmpt_module object will call an + * \ref openmpt_error_func and depending on the value returned by this function + * log the error code and/xor/or store it inside the openmpt_module object. + * Stored error codes can be accessed with the openmpt_module_error_get_last() + * and openmpt_module_error_get_last_message(). Stored errors will not get + * cleared automatically and should be reset with openmpt_module_error_clear(). + * - Some functions not directly related to an \ref openmpt_module object take + * an explicit \ref openmpt_error_func error function callback and a pointer to + * an int and behave analog to the functions working on an \ref openmpt_module + * object. + * + * \section libopenmpt_c_strings Strings + * + * - All strings returned from libopenmpt are encoded in UTF-8. + * - All strings passed to libopenmpt should also be encoded in UTF-8. + * Behaviour in case of invalid UTF-8 is unspecified. + * - libopenmpt does not enforce or expect any particular Unicode + * normalization form. + * - All strings returned from libopenmpt are dynamically allocated and must + * be freed with openmpt_free_string(). Do NOT use the C standard library + * free() for libopenmpt strings as that would make your code invalid on + * windows when dynamically linking against libopenmpt which itself statically + * links to the C runtime. + * - All strings passed to libopenmpt are copied. No ownership is assumed or + * transferred. + * + * \section libopenmpt_c_fileio File I/O + * + * libopenmpt can use 3 different strategies for file I/O. + * + * - openmpt_module_create_from_memory2() will load the module from the provided + * memory buffer, which will require loading all data upfront by the library + * caller. + * - openmpt_module_create2() with a seekable stream will load the module via + * callbacks to the stream interface. libopenmpt will not implement an + * additional buffering layer in this case which means the callbacks are assumed + * to be performant even with small i/o sizes. + * - openmpt_module_create2() with an unseekable stream will load the module via + * callbacks to the stream interface. libopempt will make an internal copy as + * it goes along, and sometimes have to pre-cache the whole file in case it + * needs to know the complete file size. This strategy is intended to be used + * if the file is located on a high latency network. + * + * | create function | speed | memory consumption | + * | ----------------------------------------------: | :----: | :----------------: | + * | openmpt_module_create_from_memory2() |

fast

|

medium

| + * | openmpt_module_create2() with seekable stream |

slow

|

low

| + * | openmpt_module_create2() with unseekable stream |

medium

|

high

| + * + * In all cases, the data or stream passed to the create function is no longer + * needed after the openmpt_module has been created and can be freed by the + * caller. + * + * \section libopenmpt_c_outputformat Output Format + * + * libopenmpt supports a wide range of PCM output formats: + * [8000..192000]/[mono|stereo|quad]/[f32|i16]. + * + * Unless you have some very specific requirements demanding a particular aspect + * of the output format, you should always prefer 48000/stereo/f32 as the + * libopenmpt PCM format. + * + * - Please prefer 48000Hz unless the user explicitly demands something else. + * Practically all audio equipment and file formats use 48000Hz nowadays. + * - Practically all module formats are made for stereo output. Mono will not + * give you any measurable speed improvements and can trivially be obtained from + * the stereo output anyway. Quad is not expected by almost all modules and even + * if they do use surround effects, they expect the effects to be mixed to + * stereo. + * - Floating point output provides headroom instead of hard clipping if the + * module is louder than 0dBFs, will give you a better signal-to-noise ratio + * than int16 output, and avoid the need to apply an additional dithering to the + * output by libopenmpt. Unless your platform has no floating point unit at all, + * floating point will thus also be slightly faster. + * + * \section libopenmpt_c_threads libopenmpt in multi-threaded environments + * + * - libopenmpt is thread-aware. + * - Individual libopenmpt objects are not thread-safe. + * - libopenmpt itself does not spawn any user-visible threads but may spawn + * threads for internal use. + * - You must ensure to only ever access a particular libopenmpt object from a + * single thread at a time. + * - Consecutive accesses can happen from different threads. + * - Different objects can be accessed concurrently from different threads. + * + * \section libopenmpt_c_staticlinking Statically linking to libopenmpt + * + * libopenmpt is implemented in C++. This implies that linking to libopenmpt + * statically requires linking to the C++ runtime and standard library. The + * **highly preferred and recommended** way to do this is by using the C++ + * compiler instead of the platform linker to do the linking. This will do all + * necessary things that are C++ specific (in particular, it will pull in the + * appropriate runtime and/or library). If for whatever reason it is not + * possible to use the C++ compiler for statically linking against libopenmpt, + * the libopenmpt build system can list the required libraries in the pkg-config + * file `libopenmpt.pc`. However, there is no reliable way to determine the name + * of the required library or libraries from within the build system. The + * libopenmpt autotools `configure` and plain `Makefile` honor the custom + * variable `CXXSTDLIB_PCLIBSPRIVATE` which serves the sole purpose of listing + * the standard library (or libraries) required for static linking. The contents + * of this variable will be put in `libopenmpt.pc` `Libs.private` and used for + * nothing else. + * + * This problem is inherent to libraries implemented in C++ that can also be used + * without a C++ compiler. Other libraries try to solve that by listing + * `-lstdc++` unconditionally in `Libs.private`. However, that will break + * platforms that use a different C++ standard library (in particular FreeBSD). + * + * See https://lists.freedesktop.org/archives/pkg-config/2016-August/001055.html . + * + * Dymically linking to libopenmpt does not require anything special and will + * work as usual (and exactly as done for libraries implemented in C). + * + * Note: This section does not apply when using Microsoft Visual Studio or + * Andriod NDK ndk-build build systems. + * + * \section libopenmpt_c_detailed Detailed documentation + * + * \ref libopenmpt_c + * + * In case a function is not documented here, you might want to look at the + * \ref libopenmpt_cpp documentation. The C and C++ APIs are kept semantically + * as close as possible. + * + * \section libopenmpt_c_examples Examples + * + * \subsection libopenmpt_c_example_unsafe Unsafe, simplified example without any error checking to get a first idea of the API + * \include libopenmpt_example_c_unsafe.c + * \subsection libopenmpt_c_example_file FILE* + * \include libopenmpt_example_c.c + * \subsection libopenmpt_c_example_inmemory in memory + * \include libopenmpt_example_c_mem.c + * \subsection libopenmpt_c_example_stdout reading FILE* and writing PCM data to STDOUT (usable without PortAudio) + * \include libopenmpt_example_c_stdout.c + * + */ + +/*! \defgroup libopenmpt_c libopenmpt C */ + +/*! \addtogroup libopenmpt_c + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/*! \brief Get the libopenmpt version number + * + * Returns the libopenmpt version number. + * \return The value represents (major << 24 + minor << 16 + patch << 0). + * \remarks libopenmpt < 0.3.0-pre used the following scheme: (major << 24 + minor << 16 + revision). + */ +LIBOPENMPT_API uint32_t openmpt_get_library_version(void); + +/*! \brief Get the core version number + * + * Return the OpenMPT core version number. + * \return The value represents (majormajor << 24 + major << 16 + minor << 8 + minorminor). + */ +LIBOPENMPT_API uint32_t openmpt_get_core_version(void); + +/*! Return a verbose library version string from openmpt_get_string(). \deprecated Please use `"library_version"` directly. */ +#define OPENMPT_STRING_LIBRARY_VERSION LIBOPENMPT_DEPRECATED_STRING( "library_version" ) +/*! Return a verbose library features string from openmpt_get_string(). \deprecated Please use `"library_features"` directly. */ +#define OPENMPT_STRING_LIBRARY_FEATURES LIBOPENMPT_DEPRECATED_STRING( "library_features" ) +/*! Return a verbose OpenMPT core version string from openmpt_get_string(). \deprecated Please use `"core_version"` directly. */ +#define OPENMPT_STRING_CORE_VERSION LIBOPENMPT_DEPRECATED_STRING( "core_version" ) +/*! Return information about the current build (e.g. the build date or compiler used) from openmpt_get_string(). \deprecated Please use `"build"` directly. */ +#define OPENMPT_STRING_BUILD LIBOPENMPT_DEPRECATED_STRING( "build" ) +/*! Return all contributors from openmpt_get_string(). \deprecated Please use `"credits"` directly. */ +#define OPENMPT_STRING_CREDITS LIBOPENMPT_DEPRECATED_STRING( "credits" ) +/*! Return contact information about libopenmpt from openmpt_get_string(). \deprecated Please use `"contact"` directly. */ +#define OPENMPT_STRING_CONTACT LIBOPENMPT_DEPRECATED_STRING( "contact" ) +/*! Return the libopenmpt license from openmpt_get_string(). \deprecated Please use `"license"` directly. */ +#define OPENMPT_STRING_LICENSE LIBOPENMPT_DEPRECATED_STRING( "license" ) + +/*! \brief Free a string returned by libopenmpt + * + * Frees any string that got returned by libopenmpt. + */ +LIBOPENMPT_API void openmpt_free_string( const char * str ); + +/*! \brief Get library related metadata. + * + * \param key Key to query. + * Possible keys are: + * - "library_version": verbose library version string + * - "library_version_is_release": "1" if the version is an officially released version + * - "library_features": verbose library features string + * - "core_version": verbose OpenMPT core version string + * - "source_url": original source code URL + * - "source_date": original source code date + * - "source_revision": original source code revision + * - "source_is_modified": "1" if the original source has been modified + * - "source_has_mixed_revisions": "1" if the original source has been compiled from different various revision + * - "source_is_package": "1" if the original source has been obtained from a source pacakge instead of source code version control + * - "build": information about the current build (e.g. the build date or compiler used) + * - "build_compiler": information about the compiler used to build libopenmpt + * - "credits": all contributors + * - "contact": contact information about libopenmpt + * - "license": the libopenmpt license + * - "url": libopenmpt website URL + * - "support_forum_url": libopenmpt support and discussions forum URL + * - "bugtracker_url": libopenmpt bug and issue tracker URL + * \return A (possibly multi-line) string containing the queried information. If no information is available, the string is empty. + */ +LIBOPENMPT_API const char * openmpt_get_string( const char * key ); + +/*! \brief Get a list of supported file extensions + * + * \return The semicolon-separated list of extensions supported by this libopenmpt build. The extensions are returned lower-case without a leading dot. + */ +LIBOPENMPT_API const char * openmpt_get_supported_extensions(void); + +/*! \brief Query whether a file extension is supported + * + * \param extension file extension to query without a leading dot. The case is ignored. + * \return 1 if the extension is supported by libopenmpt, 0 otherwise. + */ +LIBOPENMPT_API int openmpt_is_extension_supported( const char * extension ); + +/*! Seek to the given offset relative to the beginning of the file. */ +#define OPENMPT_STREAM_SEEK_SET 0 +/*! Seek to the given offset relative to the current position in the file. */ +#define OPENMPT_STREAM_SEEK_CUR 1 +/*! Seek to the given offset relative to the end of the file. */ +#define OPENMPT_STREAM_SEEK_END 2 + +/*! \brief Read bytes from stream + * + * Read bytes data from stream to dst. + * \param stream Stream to read data from + * \param dst Target where to copy data. + * \param bytes Number of bytes to read. + * \return Number of bytes actually read and written to dst. + * \retval 0 End of stream or error. + * \remarks Short reads are allowed as long as they return at least 1 byte if EOF is not reached. + */ +typedef size_t (*openmpt_stream_read_func)( void * stream, void * dst, size_t bytes ); + +/*! \brief Seek stream position + * + * Seek to stream position offset at whence. + * \param stream Stream to operate on. + * \param offset Offset to seek to. + * \param whence OPENMPT_STREAM_SEEK_SET, OPENMPT_STREAM_SEEK_CUR, OPENMPT_STREAM_SEEK_END. See C89 documentation. + * \return Returns 0 on success. + * \retval 0 Success. + * \retval -1 Failure. Position does not get updated. + * \remarks libopenmpt will not try to seek beyond the file size, thus it is not important whether you allow for virtual positioning after the file end, or return an error in that case. The position equal to the file size needs to be seekable to. + */ +typedef int (*openmpt_stream_seek_func)( void * stream, int64_t offset, int whence ); + +/*! \brief Tell stream position + * + * Tell position of stream. + * \param stream Stream to operate on. + * \return Current position in stream. + * \retval -1 Failure. + */ +typedef int64_t (*openmpt_stream_tell_func)( void * stream ); + +/*! \brief Stream callbacks + * + * Stream callbacks used by libopenmpt for stream operations. + * \sa openmpt_stream_get_file_callbacks + * \sa openmpt_stream_get_fd_callbacks + * \sa openmpt_stream_get_buffer_callbacks + */ +typedef struct openmpt_stream_callbacks { + + /*! \brief Read callback. + * + * \sa openmpt_stream_read_func + */ + openmpt_stream_read_func read; + + /*! \brief Seek callback. + * + * Seek callback can be NULL if seeking is not supported. + * \sa openmpt_stream_seek_func + */ + openmpt_stream_seek_func seek; + + /*! \brief Tell callback. + * + * Tell callback can be NULL if seeking is not supported. + * \sa openmpt_stream_tell_func + */ + openmpt_stream_tell_func tell; + +} openmpt_stream_callbacks; + +/*! \brief Logging function + * + * \param message UTF-8 encoded log message. + * \param user User context that was passed to openmpt_module_create2(), openmpt_module_create_from_memory2() or openmpt_could_open_probability2(). + */ +typedef void (*openmpt_log_func)( const char * message, void * user ); + +/*! \brief Default logging function + * + * Default logging function that logs anything to stderr. + */ +LIBOPENMPT_API void openmpt_log_func_default( const char * message, void * user ); + +/*! \brief Silent logging function + * + * Silent logging function that throws any log message away. + */ +LIBOPENMPT_API void openmpt_log_func_silent( const char * message, void * user ); + +/*! No error. \since 0.3.0 */ +#define OPENMPT_ERROR_OK 0 + +/*! Lowest value libopenmpt will use for any of its own error codes. \since 0.3.0 */ +#define OPENMPT_ERROR_BASE 256 + +/*! Unknown internal error. \since 0.3.0 */ +#define OPENMPT_ERROR_UNKNOWN ( OPENMPT_ERROR_BASE + 1 ) + +/*! Unknown internal C++ exception. \since 0.3.0 */ +#define OPENMPT_ERROR_EXCEPTION ( OPENMPT_ERROR_BASE + 11 ) + +/*! Out of memory. \since 0.3.0 */ +#define OPENMPT_ERROR_OUT_OF_MEMORY ( OPENMPT_ERROR_BASE + 21 ) + +/*! Runtime error. \since 0.3.0 */ +#define OPENMPT_ERROR_RUNTIME ( OPENMPT_ERROR_BASE + 30 ) +/*! Range error. \since 0.3.0 */ +#define OPENMPT_ERROR_RANGE ( OPENMPT_ERROR_BASE + 31 ) +/*! Arithmetic overflow. \since 0.3.0 */ +#define OPENMPT_ERROR_OVERFLOW ( OPENMPT_ERROR_BASE + 32 ) +/*! Arithmetic underflow. \since 0.3.0 */ +#define OPENMPT_ERROR_UNDERFLOW ( OPENMPT_ERROR_BASE + 33 ) + +/*! Logic error. \since 0.3.0 */ +#define OPENMPT_ERROR_LOGIC ( OPENMPT_ERROR_BASE + 40 ) +/*! Value domain error. \since 0.3.0 */ +#define OPENMPT_ERROR_DOMAIN ( OPENMPT_ERROR_BASE + 41 ) +/*! Maximum supported size exceeded. \since 0.3.0 */ +#define OPENMPT_ERROR_LENGTH ( OPENMPT_ERROR_BASE + 42 ) +/*! Argument out of range. \since 0.3.0 */ +#define OPENMPT_ERROR_OUT_OF_RANGE ( OPENMPT_ERROR_BASE + 43 ) +/*! Invalid argument. \since 0.3.0 */ +#define OPENMPT_ERROR_INVALID_ARGUMENT ( OPENMPT_ERROR_BASE + 44 ) + +/*! General libopenmpt error. \since 0.3.0 */ +#define OPENMPT_ERROR_GENERAL ( OPENMPT_ERROR_BASE + 101 ) +/*! openmpt_module * is invalid. \since 0.3.0 */ +#define OPENMPT_ERROR_INVALID_MODULE_POINTER ( OPENMPT_ERROR_BASE + 102 ) +/*! NULL pointer argument. \since 0.3.0 */ +#define OPENMPT_ERROR_ARGUMENT_NULL_POINTER ( OPENMPT_ERROR_BASE + 103 ) + +/*! \brief Check whether the error is transient + * + * Checks whether an error code represents a transient error which may not occur again in a later try if for example memory has been freed up after an out-of-memory error. + * \param error Error code. + * \retval 0 Error is not transient. + * \retval 1 Error is transient. + * \sa OPENMPT_ERROR_OUT_OF_MEMORY + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_error_is_transient( int error ); + +/*! \brief Convert error code to text + * + * Converts an error code into a text string describing the error. + * \param error Error code. + * \return Allocated string describing the error. + * \retval NULL Not enough memory to allocate the string. + * \since 0.3.0 + */ +LIBOPENMPT_API const char * openmpt_error_string( int error ); + +/*! Do not log or store the error. \since 0.3.0 */ +#define OPENMPT_ERROR_FUNC_RESULT_NONE 0 +/*! Log the error. \since 0.3.0 */ +#define OPENMPT_ERROR_FUNC_RESULT_LOG ( 1 << 0 ) +/*! Store the error. \since 0.3.0 */ +#define OPENMPT_ERROR_FUNC_RESULT_STORE ( 1 << 1 ) +/*! Log and store the error. \since 0.3.0 */ +#define OPENMPT_ERROR_FUNC_RESULT_DEFAULT ( OPENMPT_ERROR_FUNC_RESULT_LOG | OPENMPT_ERROR_FUNC_RESULT_STORE ) + +/*! \brief Error function + * + * \param error Error code. + * \param user User context that was passed to openmpt_module_create2(), openmpt_module_create_from_memory2() or openmpt_could_open_probability2(). + * \return Mask of OPENMPT_ERROR_FUNC_RESULT_LOG and OPENMPT_ERROR_FUNC_RESULT_STORE. + * \retval OPENMPT_ERROR_FUNC_RESULT_NONE Do not log or store the error. + * \retval OPENMPT_ERROR_FUNC_RESULT_LOG Log the error. + * \retval OPENMPT_ERROR_FUNC_RESULT_STORE Store the error. + * \retval OPENMPT_ERROR_FUNC_RESULT_DEFAULT Log and store the error. + * \sa OPENMPT_ERROR_FUNC_RESULT_NONE + * \sa OPENMPT_ERROR_FUNC_RESULT_LOG + * \sa OPENMPT_ERROR_FUNC_RESULT_STORE + * \sa OPENMPT_ERROR_FUNC_RESULT_DEFAULT + * \sa openmpt_error_func_default + * \sa openmpt_error_func_log + * \sa openmpt_error_func_store + * \sa openmpt_error_func_ignore + * \sa openmpt_error_func_errno + * \since 0.3.0 + */ +typedef int (*openmpt_error_func)( int error, void * user ); + +/*! \brief Default error function + * + * Causes all errors to be logged and stored. + * \param error Error code. + * \param user Ignored. + * \retval OPENMPT_ERROR_FUNC_RESULT_DEFAULT Always. + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_error_func_default( int error, void * user ); + +/*! \brief Log error function + * + * Causes all errors to be logged. + * \param error Error code. + * \param user Ignored. + * \retval OPENMPT_ERROR_FUNC_RESULT_LOG Always. + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_error_func_log( int error, void * user ); + +/*! \brief Store error function + * + * Causes all errors to be stored. + * \param error Error code. + * \param user Ignored. + * \retval OPENMPT_ERROR_FUNC_RESULT_STORE Always. + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_error_func_store( int error, void * user ); + +/*! \brief Ignore error function + * + * Causes all errors to be neither logged nor stored. + * \param error Error code. + * \param user Ignored. + * \retval OPENMPT_ERROR_FUNC_RESULT_NONE Always. + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_error_func_ignore( int error, void * user ); + +/*! \brief Errno error function + * + * Causes all errors to be stored in the pointer passed in as user. + * \param error Error code. + * \param user Pointer to an int as generated by openmpt_error_func_errno_userdata. + * \retval OPENMPT_ERROR_FUNC_RESULT_NONE user is not NULL. + * \retval OPENMPT_ERROR_FUNC_RESULT_DEFAULT user is NULL. + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_error_func_errno( int error, void * user ); + +/*! \brief User pointer for openmpt_error_func_errno + * + * Provides a suitable user pointer argument for openmpt_error_func_errno. + * \param error Pointer to an integer value to be used as output by openmpt_error_func_errno. + * \retval (void*)error. + * \since 0.3.0 + */ +LIBOPENMPT_API void * openmpt_error_func_errno_userdata( int * error ); + +/*! \brief Roughly scan the input stream to find out whether libopenmpt might be able to open it + * + * \param stream_callbacks Input stream callback operations. + * \param stream Input stream to scan. + * \param effort Effort to make when validating stream. Effort 0.0 does not even look at stream at all and effort 1.0 completely loads the file from stream. A lower effort requires less data to be loaded but only gives a rough estimate answer. Use an effort of 0.25 to only verify the header data of the module file. + * \param logfunc Logging function where warning and errors are written. May be NULL. + * \param user Logging function user context. Used to pass any user-defined data associated with this module to the logging function. + * \return Probability between 0.0 and 1.0. + * \remarks openmpt_could_open_probability() can return any value between 0.0 and 1.0. Only 0.0 and 1.0 are definitive answers, all values in between are just estimates. In general, any return value >0.0 means that you should try loading the file, and any value below 1.0 means that loading may fail. If you want a threshold above which you can be reasonably sure that libopenmpt will be able to load the file, use >=0.5. If you see the need for a threshold below which you could reasonably outright reject a file, use <0.25 (Note: Such a threshold for rejecting on the lower end is not recommended, but may be required for better integration into some other framework's probe scoring.). + * \remarks openmpt_could_open_probability() expects the complete file data to be eventually available to it, even if it is asked to just parse the header. Verification will be unreliable (both false positives and false negatives), if you pretend that the file is just some few bytes of initial data threshold in size. In order to really just access the first bytes of a file, check in your callback functions whether data or seeking is requested beyond your initial data threshold, and in that case, return an error. openmpt_could_open_probability() will treat this as any other I/O error and return 0.0. You must not expect the correct result in this case. You instead must remember that it asked for more data than you currently want to provide to it and treat this situation as if openmpt_could_open_probability() returned 0.5. + * \sa \ref libopenmpt_c_fileio + * \sa openmpt_stream_callbacks + * \deprecated Please use openmpt_could_open_probability2(). + * \since 0.3.0 + */ +LIBOPENMPT_API LIBOPENMPT_DEPRECATED double openmpt_could_open_probability( openmpt_stream_callbacks stream_callbacks, void * stream, double effort, openmpt_log_func logfunc, void * user ); + +/*! \brief Roughly scan the input stream to find out whether libopenmpt might be able to open it + * + * \param stream_callbacks Input stream callback operations. + * \param stream Input stream to scan. + * \param effort Effort to make when validating stream. Effort 0.0 does not even look at stream at all and effort 1.0 completely loads the file from stream. A lower effort requires less data to be loaded but only gives a rough estimate answer. Use an effort of 0.25 to only verify the header data of the module file. + * \param logfunc Logging function where warning and errors are written. May be NULL. + * \param user Logging function user context. Used to pass any user-defined data associated with this module to the logging function. + * \return Probability between 0.0 and 1.0. + * \remarks openmpt_could_open_probability() can return any value between 0.0 and 1.0. Only 0.0 and 1.0 are definitive answers, all values in between are just estimates. In general, any return value >0.0 means that you should try loading the file, and any value below 1.0 means that loading may fail. If you want a threshold above which you can be reasonably sure that libopenmpt will be able to load the file, use >=0.5. If you see the need for a threshold below which you could reasonably outright reject a file, use <0.25 (Note: Such a threshold for rejecting on the lower end is not recommended, but may be required for better integration into some other framework's probe scoring.). + * \remarks openmpt_could_open_probability() expects the complete file data to be eventually available to it, even if it is asked to just parse the header. Verification will be unreliable (both false positives and false negatives), if you pretend that the file is just some few bytes of initial data threshold in size. In order to really just access the first bytes of a file, check in your callback functions whether data or seeking is requested beyond your initial data threshold, and in that case, return an error. openmpt_could_open_probability() will treat this as any other I/O error and return 0.0. You must not expect the correct result in this case. You instead must remember that it asked for more data than you currently want to provide to it and treat this situation as if openmpt_could_open_probability() returned 0.5. + * \sa \ref libopenmpt_c_fileio + * \sa openmpt_stream_callbacks + * \deprecated Please use openmpt_could_open_probability2(). + */ +LIBOPENMPT_API LIBOPENMPT_DEPRECATED double openmpt_could_open_propability( openmpt_stream_callbacks stream_callbacks, void * stream, double effort, openmpt_log_func logfunc, void * user ); + +/*! \brief Roughly scan the input stream to find out whether libopenmpt might be able to open it + * + * \param stream_callbacks Input stream callback operations. + * \param stream Input stream to scan. + * \param effort Effort to make when validating stream. Effort 0.0 does not even look at stream at all and effort 1.0 completely loads the file from stream. A lower effort requires less data to be loaded but only gives a rough estimate answer. Use an effort of 0.25 to only verify the header data of the module file. + * \param logfunc Logging function where warning and errors are written. May be NULL. + * \param loguser Logging function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param error Pointer to an integer where an error may get stored. May be NULL. + * \param error_message Pointer to a string pointer where an error message may get stored. May be NULL. + * \return Probability between 0.0 and 1.0. + * \remarks openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize() provide a simpler and faster interface that fits almost all use cases better. It is recommended to use openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize() instead of openmpt_could_open_probability(). + * \remarks openmpt_could_open_probability2() can return any value between 0.0 and 1.0. Only 0.0 and 1.0 are definitive answers, all values in between are just estimates. In general, any return value >0.0 means that you should try loading the file, and any value below 1.0 means that loading may fail. If you want a threshold above which you can be reasonably sure that libopenmpt will be able to load the file, use >=0.5. If you see the need for a threshold below which you could reasonably outright reject a file, use <0.25 (Note: Such a threshold for rejecting on the lower end is not recommended, but may be required for better integration into some other framework's probe scoring.). + * \remarks openmpt_could_open_probability2() expects the complete file data to be eventually available to it, even if it is asked to just parse the header. Verification will be unreliable (both false positives and false negatives), if you pretend that the file is just some few bytes of initial data threshold in size. In order to really just access the first bytes of a file, check in your callback functions whether data or seeking is requested beyond your initial data threshold, and in that case, return an error. openmpt_could_open_probability2() will treat this as any other I/O error and return 0.0. You must not expect the correct result in this case. You instead must remember that it asked for more data than you currently want to provide to it and treat this situation as if openmpt_could_open_probability2() returned 0.5. \include libopenmpt_example_c_probe.c + * \sa \ref libopenmpt_c_fileio + * \sa openmpt_stream_callbacks + * \sa openmpt_probe_file_header + * \sa openmpt_probe_file_header_without_filesize + * \since 0.3.0 + */ +LIBOPENMPT_API double openmpt_could_open_probability2( openmpt_stream_callbacks stream_callbacks, void * stream, double effort, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message ); + +/*! \brief Get recommended header size for successfull format probing + * + * \sa openmpt_probe_file_header() + * \sa openmpt_probe_file_header_without_filesize() + * \since 0.3.0 + */ +LIBOPENMPT_API size_t openmpt_probe_file_header_get_recommended_size(void); + +/*! Probe for module formats in openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ +#define OPENMPT_PROBE_FILE_HEADER_FLAGS_MODULES 0x1ul +/*! Probe for module-specific container formats in openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ +#define OPENMPT_PROBE_FILE_HEADER_FLAGS_CONTAINERS 0x2ul + +/*! Probe for the default set of formats in openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ +#define OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT ( OPENMPT_PROBE_FILE_HEADER_FLAGS_MODULES | OPENMPT_PROBE_FILE_HEADER_FLAGS_CONTAINERS ) +/*! Probe for no formats in openmpt_probe_file_header() or openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ +#define OPENMPT_PROBE_FILE_HEADER_FLAGS_NONE 0x0ul + +/*! Possible return values fo openmpt_probe_file_header() and openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ +#define OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS 1 +/*! Possible return values fo openmpt_probe_file_header() and openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ +#define OPENMPT_PROBE_FILE_HEADER_RESULT_FAILURE 0 +/*! Possible return values fo openmpt_probe_file_header() and openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ +#define OPENMPT_PROBE_FILE_HEADER_RESULT_WANTMOREDATA (-1) +/*! Possible return values fo openmpt_probe_file_header() and openmpt_probe_file_header_without_filesize(). \since 0.3.0 */ +#define OPENMPT_PROBE_FILE_HEADER_RESULT_ERROR (-255) + +/*! \brief Probe the provided bytes from the beginning of a file for supported file format headers to find out whether libopenmpt might be able to open it + * + * \param flags Ored mask of OPENMPT_PROBE_FILE_HEADER_FLAGS_MODULES and OPENMPT_PROBE_FILE_HEADER_FLAGS_CONTAINERS, or OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT. + * \param data Beginning of the file data. + * \param size Size of the beginning of the file data. + * \param filesize Full size of the file data on disk. + * \param logfunc Logging function where warning and errors are written. May be NULL. + * \param loguser Logging function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param error Pointer to an integer where an error may get stored. May be NULL. + * \param error_message Pointer to a string pointer where an error message may get stored. May be NULL. + * \remarks It is recommended to provide openmpt_probe_file_header_get_recommended_size() bytes of data for data and size. If the file is smaller, only provide the filesize amount and set size and filesize to the file's size. + * \remarks openmpt_could_open_probability2() provides a more elaborate interface that might be required for special use cases. It is recommended to use openmpt_probe_file_header() though, if possible. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS The file will most likely be supported by libopenmpt. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_FAILURE The file is not supported by libopenmpt. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_WANTMOREDATA An answer could not be determined with the amount of data provided. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_ERROR An internal error occurred. + * \sa openmpt_probe_file_header_get_recommended_size() + * \sa openmpt_probe_file_header_without_filesize() + * \sa openmpt_probe_file_header_from_stream() + * \sa openmpt_could_open_probability2() + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_probe_file_header( uint64_t flags, const void * data, size_t size, uint64_t filesize, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message ); +/*! \brief Probe the provided bytes from the beginning of a file for supported file format headers to find out whether libopenmpt might be able to open it + * + * \param flags Ored mask of OPENMPT_PROBE_FILE_HEADER_FLAGS_MODULES and OPENMPT_PROBE_FILE_HEADER_FLAGS_CONTAINERS, or OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT. + * \param data Beginning of the file data. + * \param size Size of the beginning of the file data. + * \param logfunc Logging function where warning and errors are written. May be NULL. + * \param loguser Logging function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param error Pointer to an integer where an error may get stored. May be NULL. + * \param error_message Pointer to a string pointer where an error message may get stored. May be NULL. + * \remarks It is recommended to use openmpt_probe_file_header() and provide the acutal file's size as a parameter if at all possible. libopenmpt can provide more accurate answers if the filesize is known. + * \remarks It is recommended to provide openmpt_probe_file_header_get_recommended_size() bytes of data for data and size. If the file is smaller, only provide the filesize amount and set size to the file's size. + * \remarks openmpt_could_open_probability2() provides a more elaborate interface that might be required for special use cases. It is recommended to use openmpt_probe_file_header() though, if possible. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS The file will most likely be supported by libopenmpt. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_FAILURE The file is not supported by libopenmpt. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_WANTMOREDATA An answer could not be determined with the amount of data provided. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_ERROR An internal error occurred. + * \sa openmpt_probe_file_header_get_recommended_size() + * \sa openmpt_probe_file_header() + * \sa openmpt_probe_file_header_from_stream() + * \sa openmpt_could_open_probability2() + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_probe_file_header_without_filesize( uint64_t flags, const void * data, size_t size, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message ); + +/*! \brief Probe the provided bytes from the beginning of a file for supported file format headers to find out whether libopenmpt might be able to open it + * + * \param flags Ored mask of OPENMPT_PROBE_FILE_HEADER_FLAGS_MODULES and OPENMPT_PROBE_FILE_HEADER_FLAGS_CONTAINERS, or OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT. + * \param stream_callbacks Input stream callback operations. + * \param stream Input stream to scan. + * \param logfunc Logging function where warning and errors are written. May be NULL. + * \param loguser Logging function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param error Pointer to an integer where an error may get stored. May be NULL. + * \param error_message Pointer to a string pointer where an error message may get stored. May be NULL. + * \remarks The stream is left in an unspecified state when this function returns. + * \remarks It is recommended to provide openmpt_probe_file_header_get_recommended_size() bytes of data for data and size. If the file is smaller, only provide the filesize amount and set size and filesize to the file's size. + * \remarks openmpt_could_open_probability2() provides a more elaborate interface that might be required for special use cases. It is recommended to use openmpt_probe_file_header() though, if possible. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS The file will most likely be supported by libopenmpt. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_FAILURE The file is not supported by libopenmpt. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_WANTMOREDATA An answer could not be determined with the amount of data provided. + * \retval OPENMPT_PROBE_FILE_HEADER_RESULT_ERROR An internal error occurred. + * \sa openmpt_probe_file_header_get_recommended_size() + * \sa openmpt_probe_file_header() + * \sa openmpt_probe_file_header_without_filesize() + * \sa openmpt_could_open_probability2() + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_probe_file_header_from_stream( uint64_t flags, openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message ); + + +/*! \brief Opaque type representing a libopenmpt module + */ +typedef struct openmpt_module openmpt_module; + +typedef struct openmpt_module_initial_ctl { + const char * ctl; + const char * value; +} openmpt_module_initial_ctl; + +/*! \brief Construct an openmpt_module + * + * \param stream_callbacks Input stream callback operations. + * \param stream Input stream to load the module from. + * \param logfunc Logging function where warning and errors are written. The logging function may be called throughout the lifetime of openmpt_module. May be NULL. + * \param loguser User-defined data associated with this module. This value will be passed to the logging callback function (logfunc) + * \param ctls A map of initial ctl values. See openmpt_module_get_ctls() + * \return A pointer to the constructed openmpt_module, or NULL on failure. + * \remarks The input data can be discarded after an openmpt_module has been constructed successfully. + * \sa openmpt_stream_callbacks + * \sa \ref libopenmpt_c_fileio + * \deprecated Please use openmpt_module_create2(). + */ +LIBOPENMPT_API LIBOPENMPT_DEPRECATED openmpt_module * openmpt_module_create( openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * loguser, const openmpt_module_initial_ctl * ctls ); + +/*! \brief Construct an openmpt_module + * + * \param stream_callbacks Input stream callback operations. + * \param stream Input stream to load the module from. + * \param logfunc Logging function where warning and errors are written. The logging function may be called throughout the lifetime of openmpt_module. May be NULL. + * \param loguser User-defined data associated with this module. This value will be passed to the logging callback function (logfunc) + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param error Pointer to an integer where an error may get stored. May be NULL. + * \param error_message Pointer to a string pointer where an error message may get stored. May be NULL. + * \param ctls A map of initial ctl values. See openmpt_module_get_ctls() + * \return A pointer to the constructed openmpt_module, or NULL on failure. + * \remarks The input data can be discarded after an openmpt_module has been constructed successfully. + * \sa openmpt_stream_callbacks + * \sa \ref libopenmpt_c_fileio + * \since 0.3.0 + */ +LIBOPENMPT_API openmpt_module * openmpt_module_create2( openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ); + +/*! \brief Construct an openmpt_module + * + * \param filedata Data to load the module from. + * \param filesize Amount of data available. + * \param logfunc Logging function where warning and errors are written. The logging function may be called throughout the lifetime of openmpt_module. + * \param loguser User-defined data associated with this module. This value will be passed to the logging callback function (logfunc) + * \param ctls A map of initial ctl values. See openmpt_module_get_ctls() + * \return A pointer to the constructed openmpt_module, or NULL on failure. + * \remarks The input data can be discarded after an openmpt_module has been constructed successfully. + * \sa \ref libopenmpt_c_fileio + * \deprecated Please use openmpt_module_create_from_memory2(). + */ +LIBOPENMPT_API LIBOPENMPT_DEPRECATED openmpt_module * openmpt_module_create_from_memory( const void * filedata, size_t filesize, openmpt_log_func logfunc, void * loguser, const openmpt_module_initial_ctl * ctls ); + +/*! \brief Construct an openmpt_module + * + * \param filedata Data to load the module from. + * \param filesize Amount of data available. + * \param logfunc Logging function where warning and errors are written. The logging function may be called throughout the lifetime of openmpt_module. + * \param loguser User-defined data associated with this module. This value will be passed to the logging callback function (logfunc) + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param error Pointer to an integer where an error may get stored. May be NULL. + * \param error_message Pointer to a string pointer where an error message may get stored. May be NULL. + * \param ctls A map of initial ctl values. See openmpt_module_get_ctls() + * \return A pointer to the constructed openmpt_module, or NULL on failure. + * \remarks The input data can be discarded after an openmpt_module has been constructed successfully. + * \sa \ref libopenmpt_c_fileio + * \since 0.3.0 + */ +LIBOPENMPT_API openmpt_module * openmpt_module_create_from_memory2( const void * filedata, size_t filesize, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ); + +/*! \brief Unload a previously created openmpt_module from memory. + * + * \param mod The module to unload. + */ +LIBOPENMPT_API void openmpt_module_destroy( openmpt_module * mod ); + +/*! \brief Set logging function. + * + * Set the logging function of an already constructed openmpt_module. + * \param mod The module handle to work on. + * \param logfunc Logging function where warning and errors are written. The logging function may be called throughout the lifetime of openmpt_module. + * \param loguser User-defined data associated with this module. This value will be passed to the logging callback function (logfunc) + * \since 0.3.0 + */ +LIBOPENMPT_API void openmpt_module_set_log_func( openmpt_module * mod, openmpt_log_func logfunc, void * loguser ); + +/*! \brief Set error function. + * + * Set the error function of an already constructed openmpt_module. + * \param mod The module handle to work on. + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. + * \since 0.3.0 + */ +LIBOPENMPT_API void openmpt_module_set_error_func( openmpt_module * mod, openmpt_error_func errfunc, void * erruser ); + +/*! \brief Get last error. + * + * Return the error currently stored in an openmpt_module. The stored error is not cleared. + * \param mod The module handle to work on. + * \return The error currently stored. + * \sa openmpt_module_error_get_last_message + * \sa openmpt_module_error_set_last + * \sa openmpt_module_error_clear + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_module_error_get_last( openmpt_module * mod ); + +/*! \brief Get last error message. + * + * Return the error message currently stored in an openmpt_module. The stored error is not cleared. + * \param mod The module handle to work on. + * \return The error message currently stored. + * \sa openmpt_module_error_set_last + * \sa openmpt_module_error_clear + * \since 0.3.0 + */ +LIBOPENMPT_API const char * openmpt_module_error_get_last_message( openmpt_module * mod ); + +/*! \brief Set last error. + * + * Set the error currently stored in an openmpt_module. + * \param mod The module handle to work on. + * \param error Error to be stored. + * \sa openmpt_module_error_get_last + * \sa openmpt_module_error_clear + * \since 0.3.0 + */ +LIBOPENMPT_API void openmpt_module_error_set_last( openmpt_module * mod, int error ); + +/*! \brief Clear last error. + * + * Set the error currently stored in an openmpt_module to OPPENMPT_ERROR_OK. + * \param mod The module handle to work on. + * \sa openmpt_module_error_get_last + * \sa openmpt_module_error_set_last + * \since 0.3.0 + */ +LIBOPENMPT_API void openmpt_module_error_clear( openmpt_module * mod ); + +/** + * \defgroup openmpt_module_render_param Render param indices + * + * \brief Parameter index to use with openmpt_module_get_render_param() and openmpt_module_set_render_param() + * @{ + */ +/*! \brief Master Gain + * + * The related value represents a relative gain in milliBel.\n + * The default value is 0.\n + * The supported value range is unlimited.\n + */ +#define OPENMPT_MODULE_RENDER_MASTERGAIN_MILLIBEL 1 +/*! \brief Stereo Separation + * + * The related value represents the stereo separation generated by the libopenmpt mixer in percent.\n + * The default value is 100.\n + * The supported value range is [0,200].\n + */ +#define OPENMPT_MODULE_RENDER_STEREOSEPARATION_PERCENT 2 +/*! \brief Interpolation Filter + * + * The related value represents the interpolation filter length used by the libopenmpt mixer.\n + * The default value is 0, which indicates a recommended default value.\n + * The supported value range is [0,inf). Values greater than the implementation limit are clamped to the maximum supported value.\n + * Currently supported values: + * - 0: internal default + * - 1: no interpolation (zero order hold) + * - 2: linear interpolation + * - 4: cubic interpolation + * - 8: windowed sinc with 8 taps + */ +#define OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH 3 +/*! \brief Volume Ramping Strength + * + * The related value represents the amount of volume ramping done by the libopenmpt mixer.\n + * The default value is -1, which indicates a recommended default value.\n + * The meaningful value range is [-1..10].\n + * A value of 0 completely disables volume ramping. This might cause clicks in sound output.\n + * Higher values imply slower/softer volume ramps. + */ +#define OPENMPT_MODULE_RENDER_VOLUMERAMPING_STRENGTH 4 +/** @}*/ + +/** + * \defgroup openmpt_module_command_index Pattern cell indices + * + * \brief Parameter index to use with openmpt_module_get_pattern_row_channel_command(), openmpt_module_format_pattern_row_channel_command() and openmpt_module_highlight_pattern_row_channel_command() + * @{ + */ +#define OPENMPT_MODULE_COMMAND_NOTE 0 +#define OPENMPT_MODULE_COMMAND_INSTRUMENT 1 +#define OPENMPT_MODULE_COMMAND_VOLUMEEFFECT 2 +#define OPENMPT_MODULE_COMMAND_EFFECT 3 +#define OPENMPT_MODULE_COMMAND_VOLUME 4 +#define OPENMPT_MODULE_COMMAND_PARAMETER 5 +/** @}*/ + +/*! \brief Select a sub-song from a multi-song module + * + * \param mod The module handle to work on. + * \param subsong Index of the sub-song. -1 plays all sub-songs consecutively. + * \return 1 on success, 0 on failure. + * \sa openmpt_module_get_num_subsongs, openmpt_module_get_selected_subsong, openmpt_module_get_subsong_name + * \remarks Whether subsong -1 (all subsongs consecutively), subsong 0 or some other subsong is selected by default, is an implementation detail and subject to change. If you do not want to care about subsongs, it is recommended to just not call openmpt_module_select_subsong() at all. + */ +LIBOPENMPT_API int openmpt_module_select_subsong( openmpt_module * mod, int32_t subsong ); +/*! \brief Get currently selected sub-song from a multi-song module + * + * \param mod The module handle to work on. + * \return Currently selected sub-song. -1 for all subsongs consecutively, 0 or greater for the current sub-song index. + * \sa openmpt_module_get_num_subsongs, openmpt_module_select_subsong, openmpt_module_get_subsong_name + * \since 0.3.0 + */ +LIBOPENMPT_API int32_t openmpt_module_get_selected_subsong( openmpt_module * mod ); +/*! \brief Set Repeat Count + * + * \param mod The module handle to work on. + * \param repeat_count Repeat Count + * - -1: repeat forever + * - 0: play once, repeat zero times (the default) + * - n>0: play once and repeat n times after that + * \return 1 on success, 0 on failure. + * \sa openmpt_module_get_repeat_count + */ +LIBOPENMPT_API int openmpt_module_set_repeat_count( openmpt_module * mod, int32_t repeat_count ); +/*! \brief Get Repeat Count + * + * \param mod The module handle to work on. + * \return Repeat Count + * - -1: repeat forever + * - 0: play once, repeat zero times (the default) + * - n>0: play once and repeat n times after that + * \sa openmpt_module_set_repeat_count + */ +LIBOPENMPT_API int32_t openmpt_module_get_repeat_count( openmpt_module * mod ); + +/*! \brief approximate song duration + * + * \param mod The module handle to work on. + * \return Approximate duration of current sub-song in seconds. + */ +LIBOPENMPT_API double openmpt_module_get_duration_seconds( openmpt_module * mod ); + +/*! \brief Set approximate current song position + * + * \param mod The module handle to work on. + * \param seconds Seconds to seek to. If seconds is out of range, the position gets set to song start or end respectively. + * \return Approximate new song position in seconds. + * \sa openmpt_module_get_position_seconds + */ +LIBOPENMPT_API double openmpt_module_set_position_seconds( openmpt_module * mod, double seconds ); +/*! \brief Get current song position + * + * \param mod The module handle to work on. + * \return Current song position in seconds. + * \sa openmpt_module_set_position_seconds + */ +LIBOPENMPT_API double openmpt_module_get_position_seconds( openmpt_module * mod ); + +/*! \brief Set approximate current song position + * + * If order or row are out of range, to position is not modified and the current position is returned. + * \param mod The module handle to work on. + * \param order Pattern order number to seek to. + * \param row Pattern row number to seek to. + * \return Approximate new song position in seconds. + * \sa openmpt_module_set_position_seconds + * \sa openmpt_module_get_position_seconds + */ +LIBOPENMPT_API double openmpt_module_set_position_order_row( openmpt_module * mod, int32_t order, int32_t row ); + +/*! \brief Get render parameter + * + * \param mod The module handle to work on. + * \param param Parameter to query. See \ref openmpt_module_render_param + * \param value Pointer to the variable that receives the current value of the parameter. + * \return 1 on success, 0 on failure (invalid param or value is NULL). + * \sa OPENMPT_MODULE_RENDER_MASTERGAIN_MILLIBEL + * \sa OPENMPT_MODULE_RENDER_STEREOSEPARATION_PERCENT + * \sa OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH + * \sa OPENMPT_MODULE_RENDER_VOLUMERAMPING_STRENGTH + * \sa openmpt_module_set_render_param + */ +LIBOPENMPT_API int openmpt_module_get_render_param( openmpt_module * mod, int param, int32_t * value ); +/*! \brief Set render parameter + * + * \param mod The module handle to work on. + * \param param Parameter to set. See \ref openmpt_module_render_param + * \param value The value to set param to. + * \return 1 on success, 0 on failure (invalid param). + * \sa OPENMPT_MODULE_RENDER_MASTERGAIN_MILLIBEL + * \sa OPENMPT_MODULE_RENDER_STEREOSEPARATION_PERCENT + * \sa OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH + * \sa OPENMPT_MODULE_RENDER_VOLUMERAMPING_STRENGTH + * \sa openmpt_module_get_render_param + */ +LIBOPENMPT_API int openmpt_module_set_render_param( openmpt_module * mod, int param, int32_t value ); + +/*@{*/ +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param mono Pointer to a buffer of at least count elements that receives the mono/center output. + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_mono( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * mono ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param left Pointer to a buffer of at least count elements that receives the left output. + * \param right Pointer to a buffer of at least count elements that receives the right output. + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_stereo( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * left, int16_t * right ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param left Pointer to a buffer of at least count elements that receives the left output. + * \param right Pointer to a buffer of at least count elements that receives the right output. + * \param rear_left Pointer to a buffer of at least count elements that receives the rear left output. + * \param rear_right Pointer to a buffer of at least count elements that receives the rear right output. + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_quad( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * left, int16_t * right, int16_t * rear_left, int16_t * rear_right ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param mono Pointer to a buffer of at least count elements that receives the mono/center output. + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_float_mono( openmpt_module * mod, int32_t samplerate, size_t count, float * mono ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param left Pointer to a buffer of at least count elements that receives the left output. + * \param right Pointer to a buffer of at least count elements that receives the right output. + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_float_stereo( openmpt_module * mod, int32_t samplerate, size_t count, float * left, float * right ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param left Pointer to a buffer of at least count elements that receives the left output. + * \param right Pointer to a buffer of at least count elements that receives the right output. + * \param rear_left Pointer to a buffer of at least count elements that receives the rear left output. + * \param rear_right Pointer to a buffer of at least count elements that receives the rear right output. + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_float_quad( openmpt_module * mod, int32_t samplerate, size_t count, float * left, float * right, float * rear_left, float * rear_right ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param interleaved_stereo Pointer to a buffer of at least count*2 elements that receives the interleaved stereo output in the order (L,R). + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_interleaved_stereo( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * interleaved_stereo ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param interleaved_quad Pointer to a buffer of at least count*4 elements that receives the interleaved suad surround output in the order (L,R,RL,RR). + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_interleaved_quad( openmpt_module * mod, int32_t samplerate, size_t count, int16_t * interleaved_quad ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param interleaved_stereo Pointer to a buffer of at least count*2 elements that receives the interleaved stereo output in the order (L,R). + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + * \sa \ref libopenmpt_c_outputformat + */ +LIBOPENMPT_API size_t openmpt_module_read_interleaved_float_stereo( openmpt_module * mod, int32_t samplerate, size_t count, float * interleaved_stereo ); +/*! \brief Render audio data + * + * \param mod The module handle to work on. + * \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + * \param count Number of audio frames to render per channel. + * \param interleaved_quad Pointer to a buffer of at least count*4 elements that receives the interleaved suad surround output in the order (L,R,RL,RR). + * \return The number of frames actually rendered. + * \retval 0 The end of song has been reached. + * \remarks The output buffers are only written to up to the returned number of elements. + * \remarks You can freely switch between any of the "openmpt_module_read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + * \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + * \sa \ref libopenmpt_c_outputformat +*/ +LIBOPENMPT_API size_t openmpt_module_read_interleaved_float_quad( openmpt_module * mod, int32_t samplerate, size_t count, float * interleaved_quad ); +/*@}*/ + +/*! \brief Get the list of supported metadata item keys + * + * \param mod The module handle to work on. + * \return Metadata item keys supported by openmpt_module_get_metadata, as a semicolon-separated list. + * \sa openmpt_module_get_metadata + */ +LIBOPENMPT_API const char * openmpt_module_get_metadata_keys( openmpt_module * mod ); +/*! \brief Get a metadata item value + * + * \param mod The module handle to work on. + * \param key Metadata item key to query. Use openmpt_module_get_metadata_keys to check for available keys. + * Possible keys are: + * - type: Module format extension (e.g. it) + * - type_long: Format name associated with the module format (e.g. Impulse Tracker) + * - originaltype: Module format extension (e.g. it) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) + * - originaltype_long: Format name associated with the module format (e.g. Impulse Tracker) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) + * - container: Container format the module file is embedded in, if any (e.g. umx) + * - container_long: Full container name if the module is embedded in a container (e.g. Unreal Music) + * - tracker: Tracker that was (most likely) used to save the module file, if known + * - artist: Author of the module + * - title: Module title + * - date: Date the module was last saved, in ISO-8601 format. + * - message: Song message. If the song message is empty or the module format does not support song messages, a list of instrument and sample names is returned instead. + * - message_raw: Song message. If the song message is empty or the module format does not support song messages, an empty string is returned. + * - warnings: A list of warnings that were generated while loading the module. + * \return The associated value for key. + * \sa openmpt_module_get_metadata_keys + */ +LIBOPENMPT_API const char * openmpt_module_get_metadata( openmpt_module * mod, const char * key ); + +/*! \brief Get the current speed + * + * \param mod The module handle to work on. + * \return The current speed in ticks per row. + */ +LIBOPENMPT_API int32_t openmpt_module_get_current_speed( openmpt_module * mod ); +/*! \brief Get the current tempo + * + * \param mod The module handle to work on. + * \return The current tempo in tracker units. The exact meaning of this value depends on the tempo mode being used. + */ +LIBOPENMPT_API int32_t openmpt_module_get_current_tempo( openmpt_module * mod ); +/*! \brief Get the current order + * + * \param mod The module handle to work on. + * \return The current order at which the module is being played back. + */ +LIBOPENMPT_API int32_t openmpt_module_get_current_order( openmpt_module * mod ); +/*! \brief Get the current pattern + * + * \param mod The module handle to work on. + * \return The current pattern that is being played. + */ +LIBOPENMPT_API int32_t openmpt_module_get_current_pattern( openmpt_module * mod ); +/*! \brief Get the current row + * + * \param mod The module handle to work on. + * \return The current row at which the current pattern is being played. + */ +LIBOPENMPT_API int32_t openmpt_module_get_current_row( openmpt_module * mod ); +/*! \brief Get the current amount of playing channels. + * + * \param mod The module handle to work on. + * \return The amount of sample channels that are currently being rendered. + */ +LIBOPENMPT_API int32_t openmpt_module_get_current_playing_channels( openmpt_module * mod ); + +/*! \brief Get an approximate indication of the channel volume. + * + * \param mod The module handle to work on. + * \param channel The channel whose volume should be retrieved. + * \return The approximate channel volume. + * \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ +LIBOPENMPT_API float openmpt_module_get_current_channel_vu_mono( openmpt_module * mod, int32_t channel ); +/*! \brief Get an approximate indication of the channel volume on the front-left speaker. + * + * \param mod The module handle to work on. + * \param channel The channel whose volume should be retrieved. + * \return The approximate channel volume. + * \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ +LIBOPENMPT_API float openmpt_module_get_current_channel_vu_left( openmpt_module * mod, int32_t channel ); +/*! \brief Get an approximate indication of the channel volume on the front-right speaker. + * + * \param mod The module handle to work on. + * \param channel The channel whose volume should be retrieved. + * \return The approximate channel volume. + * \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ +LIBOPENMPT_API float openmpt_module_get_current_channel_vu_right( openmpt_module * mod, int32_t channel ); +/*! \brief Get an approximate indication of the channel volume on the rear-left speaker. + * + * \param mod The module handle to work on. + * \param channel The channel whose volume should be retrieved. + * \return The approximate channel volume. + * \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ +LIBOPENMPT_API float openmpt_module_get_current_channel_vu_rear_left( openmpt_module * mod, int32_t channel ); +/*! \brief Get an approximate indication of the channel volume on the rear-right speaker. + * + * \param mod The module handle to work on. + * \param channel The channel whose volume should be retrieved. + * \return The approximate channel volume. + * \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ +LIBOPENMPT_API float openmpt_module_get_current_channel_vu_rear_right( openmpt_module * mod, int32_t channel ); + +/*! \brief Get the number of sub-songs + * + * \param mod The module handle to work on. + * \return The number of sub-songs in the module. This includes any "hidden" songs (songs that share the same sequence, but start at different order indices) and "normal" sub-songs or "sequences" (if the format supports them). + * \sa openmpt_module_get_subsong_name, openmpt_module_select_subsong, openmpt_module_get_selected_subsong + */ +LIBOPENMPT_API int32_t openmpt_module_get_num_subsongs( openmpt_module * mod ); +/*! \brief Get the number of pattern channels + * + * \param mod The module handle to work on. + * \return The number of pattern channels in the module. Not all channels do necessarily contain data. + * \remarks The number of pattern channels is completely independent of the number of output channels. libopenmpt can render modules in mono, stereo or quad surround, but the choice of which of the three modes to use must not be made based on the return value of this function, which may be any positive integer amount. Only use this function for informational purposes. + */ +LIBOPENMPT_API int32_t openmpt_module_get_num_channels( openmpt_module * mod ); +/*! \brief Get the number of orders + * + * \param mod The module handle to work on. + * \return The number of orders in the current sequence of the module. + */ +LIBOPENMPT_API int32_t openmpt_module_get_num_orders( openmpt_module * mod ); +/*! \brief Get the number of patterns + * + * \param mod The module handle to work on. + * \return The number of distinct patterns in the module. + */ +LIBOPENMPT_API int32_t openmpt_module_get_num_patterns( openmpt_module * mod ); +/*! \brief Get the number of instruments + * + * \param mod The module handle to work on. + * \return The number of instrument slots in the module. Instruments are a layer on top of samples, and are not supported by all module formats. + */ +LIBOPENMPT_API int32_t openmpt_module_get_num_instruments( openmpt_module * mod ); +/*! \brief Get the number of samples + * + * \param mod The module handle to work on. + * \return The number of sample slots in the module. + */ +LIBOPENMPT_API int32_t openmpt_module_get_num_samples( openmpt_module * mod ); + +/*! \brief Get a sub-song name + * + * \param mod The module handle to work on. + * \param index The sub-song whose name should be retrieved + * \return The sub-song name. + * \sa openmpt_module_get_num_subsongs, openmpt_module_select_subsong, openmpt_module_get_selected_subsong + */ +LIBOPENMPT_API const char * openmpt_module_get_subsong_name( openmpt_module * mod, int32_t index ); +/*! \brief Get a channel name + * + * \param mod The module handle to work on. + * \param index The channel whose name should be retrieved + * \return The channel name. + * \sa openmpt_module_get_num_channels + */ +LIBOPENMPT_API const char * openmpt_module_get_channel_name( openmpt_module * mod, int32_t index ); +/*! \brief Get an order name + * + * \param mod The module handle to work on. + * \param index The order whose name should be retrieved + * \return The order name. + * \sa openmpt_module_get_num_orders + */ +LIBOPENMPT_API const char * openmpt_module_get_order_name( openmpt_module * mod, int32_t index ); +/*! \brief Get a pattern name + * + * \param mod The module handle to work on. + * \param index The pattern whose name should be retrieved + * \return The pattern name. + * \sa openmpt_module_get_num_patterns + */ +LIBOPENMPT_API const char * openmpt_module_get_pattern_name( openmpt_module * mod, int32_t index ); +/*! \brief Get an instrument name + * + * \param mod The module handle to work on. + * \param index The instrument whose name should be retrieved + * \return The instrument name. + * \sa openmpt_module_get_num_instruments + */ +LIBOPENMPT_API const char * openmpt_module_get_instrument_name( openmpt_module * mod, int32_t index ); +/*! \brief Get a sample name + * + * \param mod The module handle to work on. + * \param index The sample whose name should be retrieved + * \return The sample name. + * \sa openmpt_module_get_num_samples + */ +LIBOPENMPT_API const char * openmpt_module_get_sample_name( openmpt_module * mod, int32_t index ); + +/*! \brief Get pattern at order position + * + * \param mod The module handle to work on. + * \param order The order item whose pattern index should be retrieved. + * \return The pattern index found at the given order position of the current sequence. + */ +LIBOPENMPT_API int32_t openmpt_module_get_order_pattern( openmpt_module * mod, int32_t order ); +/*! \brief Get the number of rows in a pattern + * + * \param mod The module handle to work on. + * \param pattern The pattern whose row count should be retrieved. + * \return The number of rows in the given pattern. If the pattern does not exist, 0 is returned. + */ +LIBOPENMPT_API int32_t openmpt_module_get_pattern_num_rows( openmpt_module * mod, int32_t pattern ); + +/*! \brief Get raw pattern content + * + * \param mod The module handle to work on. + * \param pattern The pattern whose data should be retrieved. + * \param row The row from which the data should be retrieved. + * \param channel The channel from which the data should be retrieved. + * \param command The cell index at which the data should be retrieved. See \ref openmpt_module_command_index + * \return The internal, raw pattern data at the given pattern position. + */ +LIBOPENMPT_API uint8_t openmpt_module_get_pattern_row_channel_command( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, int command ); + +/*! \brief Get formatted (human-readable) pattern content + * + * \param mod The module handle to work on. + * \param pattern The pattern whose data should be retrieved. + * \param row The row from which the data should be retrieved. + * \param channel The channel from which the data should be retrieved. + * \param command The cell index at which the data should be retrieved. + * \return The formatted pattern data at the given pattern position. See \ref openmpt_module_command_index + * \sa openmpt_module_highlight_pattern_row_channel_command + */ +LIBOPENMPT_API const char * openmpt_module_format_pattern_row_channel_command( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, int command ); +/*! \brief Get highlighting information for formatted pattern content + * + * \param mod The module handle to work on. + * \param pattern The pattern whose data should be retrieved. + * \param row The row from which the data should be retrieved. + * \param channel The channel from which the data should be retrieved. + * \param command The cell index at which the data should be retrieved. See \ref openmpt_module_command_index + * \return The highlighting string for the formatted pattern data as retrieved by openmpt_module_get_pattern_row_channel_command at the given pattern position. + * \remarks The returned string will map each character position of the string returned by openmpt_module_get_pattern_row_channel_command to a highlighting instruction. + * Possible highlighting characters are: + * - " " : empty/space + * - "." : empty/dot + * - "n" : generic note + * - "m" : special note + * - "i" : generic instrument + * - "u" : generic volume column effect + * - "v" : generic volume column parameter + * - "e" : generic effect column effect + * - "f" : generic effect column parameter + * \sa openmpt_module_get_pattern_row_channel_command + */ +LIBOPENMPT_API const char * openmpt_module_highlight_pattern_row_channel_command( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, int command ); + +/*! \brief Get formatted (human-readable) pattern content + * + * \param mod The module handle to work on. + * \param pattern The pattern whose data should be retrieved. + * \param row The row from which the data should be retrieved. + * \param channel The channel from which the data should be retrieved. + * \param width The maximum number of characters the string should contain. 0 means no limit. + * \param pad If true, the string will be resized to the exact length provided in the width parameter. + * \return The formatted pattern data at the given pattern position. + * \sa openmpt_module_highlight_pattern_row_channel + */ +LIBOPENMPT_API const char * openmpt_module_format_pattern_row_channel( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, size_t width, int pad ); +/*! \brief Get highlighting information for formatted pattern content + * + * \param mod The module handle to work on. + * \param pattern The pattern whose data should be retrieved. + * \param row The row from which the data should be retrieved. + * \param channel The channel from which the data should be retrieved. + * \param width The maximum number of characters the string should contain. 0 means no limit. + * \param pad If true, the string will be resized to the exact length provided in the width parameter. + * \return The highlighting string for the formatted pattern data as retrieved by openmpt_module_format_pattern_row_channel at the given pattern position. + * \sa openmpt_module_format_pattern_row_channel + */ +LIBOPENMPT_API const char * openmpt_module_highlight_pattern_row_channel( openmpt_module * mod, int32_t pattern, int32_t row, int32_t channel, size_t width, int pad ); + +/*! \brief Retrieve supported ctl keys + * + * \param mod The module handle to work on. + * \return A semicolon-separated list containing all supported ctl keys. + * \remarks Currently supported ctl values are: + * - load.skip_samples: Set to "1" to avoid loading samples into memory + * - load.skip_patterns: Set to "1" to avoid loading patterns into memory + * - load.skip_plugins: Set to "1" to avoid loading plugins + * - load.skip_subsongs_init: Set to "1" to avoid pre-initializing sub-songs. Skipping results in faster module loading but slower seeking. + * - seek.sync_samples: Set to "1" to sync sample playback when using openmpt_module_set_position_seconds or openmpt_module_set_position_order_row. + * - subsong: The current subsong. Setting it has identical semantics as openmpt_module_select_subsong(), getting it returns the currently selected subsong. + * - play.at_end: Chooses the behaviour when the end of song is reached: + * - "fadeout": Fades the module out for a short while. Subsequent reads after the fadeout will return 0 rendered frames. + * - "continue": Returns 0 rendered frames when the song end is reached. Subsequent reads will continue playing from the song start or loop start. + * - "stop": Returns 0 rendered frames when the song end is reached. Subsequent reads will return 0 rendered frames. + * - play.tempo_factor: Set a floating point tempo factor. "1.0" is the default tempo. + * - play.pitch_factor: Set a floating point pitch factor. "1.0" is the default pitch. + * - render.resampler.emulate_amiga: Set to "1" to enable the Amiga resampler for Amiga modules. This emulates the sound characteristics of the Paula chip and overrides the selected interpolation filter. Non-Amiga module formats are not affected by this setting. + * - render.opl.volume_factor: Set volume factor applied to synthesized OPL sounds, relative to the default OPL volume. + * - dither: Set the dither algorithm that is used for the 16 bit versions of openmpt_module_read. Supported values are: + * - 0: No dithering. + * - 1: Default mode. Chosen by OpenMPT code, might change. + * - 2: Rectangular, 0.5 bit depth, no noise shaping (original ModPlug Tracker). + * - 3: Rectangular, 1 bit depth, simple 1st order noise shaping + */ +LIBOPENMPT_API const char * openmpt_module_get_ctls( openmpt_module * mod ); +/*! \brief Get current ctl value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be retrieved. + * \return The associated ctl value, or NULL on failure. + * \sa openmpt_module_get_ctls + */ +LIBOPENMPT_API const char * openmpt_module_ctl_get( openmpt_module * mod, const char * ctl ); +/*! \brief Set ctl value + * + * \param mod The module handle to work on. + * \param ctl The ctl key whose value should be set. + * \param value The value that should be set. + * \return 1 if successful, 0 in case the value is not sensible (e.g. negative tempo factor) or the ctl is not recognized. + * \sa openmpt_module_get_ctls + */ +LIBOPENMPT_API int openmpt_module_ctl_set( openmpt_module * mod, const char * ctl, const char * value ); + +/* remember to add new functions to both C and C++ interfaces and to increase OPENMPT_API_VERSION_MINOR */ + +#ifdef __cplusplus +} +#endif + +/*! + * @} + */ + +#endif /* LIBOPENMPT_H */ + diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt.hpp b/libs/libopenmpt/inc/libopenmpt/libopenmpt.hpp new file mode 100644 index 000000000..55097f830 --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt.hpp @@ -0,0 +1,1015 @@ +/* + * libopenmpt.hpp + * -------------- + * Purpose: libopenmpt public c++ interface + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_HPP +#define LIBOPENMPT_HPP + +#include "libopenmpt_config.h" + +#include +#include +#include +#include +#include +#include + +#include + +/*! + * \page libopenmpt_cpp_overview C++ API + * + * \section libopenmpt_cpp_error Error Handling + * + * libopenmpt C++ uses C++ exception handling for errror reporting. + * + * Unless otherwise noted, any libopenmpt function may throw exceptions and + * all exceptions thrown by libopenmpt itself are derived from + * openmpt::exception. + * In addition, any libopenmpt function may also throw any exception specified + * by the C++ language and C++ standard library. These are all derived from + * std::exception. + * + * \section libopenmpt_cpp_strings Strings + * + * - All strings returned from libopenmpt are encoded in UTF-8. + * - All strings passed to libopenmpt should also be encoded in UTF-8. + * Behaviour in case of invalid UTF-8 is unspecified. + * - libopenmpt does not enforce or expect any particular Unicode + * normalization form. + * + * \section libopenmpt_cpp_fileio File I/O + * + * libopenmpt can use 3 different strategies for file I/O. + * + * - openmpt::module::module() with any kind of memory buffer as parameter will + * load the module from the provided memory buffer, which will require loading + * all data upfront by the library + * caller. + * - openmpt::module::module() with a seekable std::istream as parameter will + * load the module via the stream interface. libopenmpt will not implement an + * additional buffering layer in this case whih means the callbacks are assumed + * to be performant even with small i/o sizes. + * - openmpt::module::module() with an unseekable std::istream as parameter + * will load the module via the stream interface. libopempt will make an + * internal copy as it goes along, and sometimes have to pre-cache the whole + * file in case it needs to know the complete file size. This strategy is + * intended to be used if the file is located on a high latency network. + * + * | constructor | speed | memory consumption | + * | ----------------: | :----: | :----------------: | + * | memory buffer |

fast

|

medium

| + * | seekable stream |

slow

|

low

| + * | unseekable stream |

medium

|

high

| + * + * In all cases, the data or stream passed to the constructor is no longer + * needed after the openmpt::module has been constructed and can be destroyed + * by the caller. + * + * \section libopenmpt_cpp_outputformat Output Format + * + * libopenmpt supports a wide range of PCM output formats: + * [8000..192000]/[mono|stereo|quad]/[f32|i16]. + * + * Unless you have some very specific requirements demanding a particular aspect + * of the output format, you should always prefer 48000/stereo/f32 as the + * libopenmpt PCM format. + * + * - Please prefer 48000Hz unless the user explicitly demands something else. + * Practically all audio equipment and file formats use 48000Hz nowadays. + * - Practically all module formats are made for stereo output. Mono will not + * give you any measurable speed improvements and can trivially be obtained from + * the stereo output anyway. Quad is not expected by almost all modules and even + * if they do use surround effects, they expect the effects to be mixed to + * stereo. + * - Floating point output provides headroom instead of hard clipping if the + * module is louder than 0dBFs, will give you a better signal-to-noise ratio + * than int16 output, and avoid the need to apply an additional dithering to the + * output by libopenmpt. Unless your platform has no floating point unit at all, + * floating point will thus also be slightly faster. + * + * \section libopenmpt_cpp_threads libopenmpt in multi-threaded environments + * + * - libopenmpt is thread-aware. + * - Individual libopenmpt objects are not thread-safe. + * - libopenmpt itself does not spawn any user-visible threads but may spawn + * threads for internal use. + * - You must ensure to only ever access a particular libopenmpt object via + * non-const member functions from a single thread at a time. + * - You may access a particular libopenmpt objects concurrently from different + * threads when using only const member functions from all threads. + * - Consecutive accesses can happen from different threads. + * - Different objects can be accessed concurrently from different threads. + * + * \section libopenmpt-cpp-windows Windows support + * + * Using the libopenmpt C++ API when libopenmpt is compiled as a DLL on Windows + * requires `#define LIBOPENMPT_USE_DLL` (or some equivalent build system + * configuration) before `#include ` in order to + * correctly import the symbols from the DLL. + * + * \section libopenmpt-cpp-detailed Detailed documentation + * + * \ref libopenmpt_cpp + * + * \section libopenmpt_cpp_examples Example + * + * \include libopenmpt_example_cxx.cpp + * + */ + +/*! \defgroup libopenmpt_cpp libopenmpt C++ */ + +/*! \addtogroup libopenmpt_cpp + @{ +*/ + +namespace openmpt { + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable:4275) +#endif +//! libopenmpt exception base class +/*! + Base class used for all exceptions that are thrown by libopenmpt itself. Libopenmpt may additionally throw any exception thrown by the standard library which are all derived from std::exception. + \sa \ref libopenmpt_cpp_error +*/ +class LIBOPENMPT_CXX_API exception : public std::exception { +private: + char * text; +public: + exception( const std::string & text ) noexcept; + exception( const exception & other ) noexcept; + exception( exception && other ) noexcept; + exception & operator = ( const exception & other ) noexcept; + exception & operator = ( exception && other ) noexcept; + virtual ~exception() noexcept; + const char * what() const noexcept override; +}; // class exception +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +//! Get the libopenmpt version number +/*! + Returns the libopenmpt version number. + \return The value represents (major << 24 + minor << 16 + patch << 0). + \remarks libopenmpt < 0.3.0-pre used the following scheme: (major << 24 + minor << 16 + revision). +*/ +LIBOPENMPT_CXX_API std::uint32_t get_library_version(); + +//! Get the core version number +/*! + Return the OpenMPT core version number. + \return The value represents (majormajor << 24 + major << 16 + minor << 8 + minorminor). +*/ +LIBOPENMPT_CXX_API std::uint32_t get_core_version(); + +namespace string { + +//! Return a verbose library version string from openmpt::string::get(). \deprecated Please use `"library_version"` directly. +LIBOPENMPT_DEPRECATED static const char library_version LIBOPENMPT_ATTR_DEPRECATED [] = "library_version"; +//! Return a verbose library features string from openmpt::string::get(). \deprecated Please use `"library_features"` directly. +LIBOPENMPT_DEPRECATED static const char library_features LIBOPENMPT_ATTR_DEPRECATED [] = "library_features"; +//! Return a verbose OpenMPT core version string from openmpt::string::get(). \deprecated Please use `"core_version"` directly. +LIBOPENMPT_DEPRECATED static const char core_version LIBOPENMPT_ATTR_DEPRECATED [] = "core_version"; +//! Return information about the current build (e.g. the build date or compiler used) from openmpt::string::get(). \deprecated Please use `"build"` directly. +LIBOPENMPT_DEPRECATED static const char build LIBOPENMPT_ATTR_DEPRECATED [] = "build"; +//! Return all contributors from openmpt::string::get(). \deprecated Please use `"credits"` directly. +LIBOPENMPT_DEPRECATED static const char credits LIBOPENMPT_ATTR_DEPRECATED [] = "credits"; +//! Return contact information about libopenmpt from openmpt::string::get(). \deprecated Please use `"contact"` directly. +LIBOPENMPT_DEPRECATED static const char contact LIBOPENMPT_ATTR_DEPRECATED [] = "contact"; +//! Return the libopenmpt license from openmpt::string::get(). \deprecated Please use `"license"` directly. +LIBOPENMPT_DEPRECATED static const char license LIBOPENMPT_ATTR_DEPRECATED [] = "license"; + +//! Get library related metadata. +/*! + \param key Key to query. + Possible keys are: + - "library_version": verbose library version string + - "library_version_major": libopenmpt major version number + - "library_version_minor": libopenmpt minor version number + - "library_version_patch": libopenmpt patch version number + - "library_version_prerel": libopenmpt pre-release version string + - "library_version_is_release": "1" if the version is an officially released version + - "library_features": verbose library features string + - "core_version": verbose OpenMPT core version string + - "source_url": original source code URL + - "source_date": original source code date + - "source_revision": original source code revision + - "source_is_modified": "1" if the original source has been modified + - "source_has_mixed_revisions": "1" if the original source has been compiled from different various revision + - "source_is_package": "1" if the original source has been obtained from a source pacakge instead of source code version control + - "build": information about the current build (e.g. the build date or compiler used) + - "build_compiler": information about the compiler used to build libopenmpt + - "credits": all contributors + - "contact": contact information about libopenmpt + - "license": the libopenmpt license + - "url": libopenmpt website URL + - "support_forum_url": libopenmpt support and discussions forum URL + - "bugtracker_url": libopenmpt bug and issue tracker URL + + \return A (possibly multi-line) string containing the queried information. If no information is available, the string is empty. +*/ +LIBOPENMPT_CXX_API std::string get( const std::string & key ); + +} // namespace string + +//! Get a list of supported file extensions +/*! + \return The list of extensions supported by this libopenmpt build. The extensions are returned lower-case without a leading dot. +*/ +LIBOPENMPT_CXX_API std::vector get_supported_extensions(); + +//! Query whether a file extension is supported +/*! + \param extension file extension to query without a leading dot. The case is ignored. + \return true if the extension is supported by libopenmpt, false otherwise. +*/ +LIBOPENMPT_CXX_API bool is_extension_supported( const std::string & extension ); + +//! Roughly scan the input stream to find out whether libopenmpt might be able to open it +/*! + \param stream Input stream to scan. + \param effort Effort to make when validating stream. Effort 0.0 does not even look at stream at all and effort 1.0 completely loads the file from stream. A lower effort requires less data to be loaded but only gives a rough estimate answer. Use an effort of 0.25 to only verify the header data of the module file. + \param log Log where warning and errors are written. + \return Probability between 0.0 and 1.0. + \remarks openmpt::probe_file_header() provides a simpler and faster interface that fits almost all use cases better. It is recommended to use openmpt::probe_file_header() instead of openmpt::could_open_probability(). + \remarks openmpt::could_open_probability() can return any value between 0.0 and 1.0. Only 0.0 and 1.0 are definitive answers, all values in between are just estimates. In general, any return value >0.0 means that you should try loading the file, and any value below 1.0 means that loading may fail. If you want a threshold above which you can be reasonably sure that libopenmpt will be able to load the file, use >=0.5. If you see the need for a threshold below which you could reasonably outright reject a file, use <0.25 (Note: Such a threshold for rejecting on the lower end is not recommended, but may be required for better integration into some other framework's probe scoring.). + \remarks openmpt::could_open_probability() expects the complete file data to be eventually available to it, even if it is asked to just parse the header. Verification will be unreliable (both false positives and false negatives), if you pretend that the file is just some few bytes of initial data threshold in size. In order to really just access the first bytes of a file, check in your std::istream implementation whether data or seeking is requested beyond your initial data threshold, and in that case, return an error. openmpt::could_open_probability() will treat this as any other I/O error and return 0.0. You must not expect the correct result in this case. You instead must remember that it asked for more data than you currently want to provide to it and treat this situation as if openmpt::could_open_probability() returned 0.5. + \sa \ref libopenmpt_c_fileio + \sa openmpt::probe_file_header() + \since 0.3.0 +*/ +LIBOPENMPT_CXX_API double could_open_probability( std::istream & stream, double effort = 1.0, std::ostream & log = std::clog ); + +//! Roughly scan the input stream to find out whether libopenmpt might be able to open it +/*! + \deprecated Please use openmpt::module::could_open_probability(). +*/ +LIBOPENMPT_ATTR_DEPRECATED LIBOPENMPT_CXX_API LIBOPENMPT_DEPRECATED double could_open_propability( std::istream & stream, double effort = 1.0, std::ostream & log = std::clog ); + +//! Get recommended header size for successfull format probing +/*! + \sa openmpt::probe_file_header() + \since 0.3.0 +*/ +LIBOPENMPT_CXX_API std::size_t probe_file_header_get_recommended_size(); + +//! Probe for module formats in openmpt::probe_file_header(). \since 0.3.0 +static const std::uint64_t probe_file_header_flags_modules = 0x1ul; + +//! Probe for module-specific container formats in openmpt::probe_file_header(). \since 0.3.0 +static const std::uint64_t probe_file_header_flags_containers = 0x2ul; + +//! Probe for the default set of formats in openmpt::probe_file_header(). \since 0.3.0 +static const std::uint64_t probe_file_header_flags_default = probe_file_header_flags_modules | probe_file_header_flags_containers; + +//! Probe for no formats in openmpt::probe_file_header(). \since 0.3.0 +static const std::uint64_t probe_file_header_flags_none = 0x0ul; + +//! Possible return values for openmpt::probe_file_header(). \since 0.3.0 +enum probe_file_header_result { + probe_file_header_result_success = 1, + probe_file_header_result_failure = 0, + probe_file_header_result_wantmoredata = -1 +}; + +//! Probe the provided bytes from the beginning of a file for supported file format headers to find out whether libopenmpt might be able to open it +/*! + \param flags Ored mask of openmpt::probe_file_header_flags_modules and openmpt::probe_file_header_flags_containers, or openmpt::probe_file_header_flags_default. + \param data Beginning of the file data. + \param size Size of the beginning of the file data. + \param filesize Full size of the file data on disk. + \remarks It is recommended to provide openmpt::probe_file_header_get_recommended_size() bytes of data for data and size. If the file is smaller, only provide the filesize amount and set size and filesize to the file's size. + \remarks openmpt::could_open_probability() provides a more elaborate interface that might be required for special use cases. It is recommended to use openmpt::probe_file_header() though, if possible. + \retval probe_file_header_result_success The file will most likely be supported by libopenmpt. + \retval probe_file_header_result_failure The file is not supported by libopenmpt. + \retval probe_file_header_result_wantmoredata An answer could not be determined with the amount of data provided. + \sa openmpt::probe_file_header_get_recommended_size() + \sa openmpt::could_open_probability() + \since 0.3.0 +*/ +LIBOPENMPT_CXX_API int probe_file_header( std::uint64_t flags, const std::uint8_t * data, std::size_t size, std::uint64_t filesize ); + +//! Probe the provided bytes from the beginning of a file for supported file format headers to find out whether libopenmpt might be able to open it +/*! + \param flags Ored mask of openmpt::probe_file_header_flags_modules and openmpt::probe_file_header_flags_containers, or openmpt::probe_file_header_flags_default. + \param data Beginning of the file data. + \param size Size of the beginning of the file data. + \remarks It is recommended to use the overload of this function that also takes the filesize as parameter if at all possile. libopenmpt can provide more accurate answers if the filesize is known. + \remarks It is recommended to provide openmpt::probe_file_header_get_recommended_size() bytes of data for data and size. If the file is smaller, only provide the filesize amount and set size to the file's size. + \remarks openmpt::could_open_probability() provides a more elaborate interface that might be required for special use cases. It is recommended to use openmpt::probe_file_header() though, if possible. + \retval probe_file_header_result_success The file will most likely be supported by libopenmpt. + \retval probe_file_header_result_failure The file is not supported by libopenmpt. + \retval probe_file_header_result_wantmoredata An answer could not be determined with the amount of data provided. + \sa openmpt::probe_file_header_get_recommended_size() + \sa openmpt::could_open_probability() + \since 0.3.0 +*/ +LIBOPENMPT_CXX_API int probe_file_header( std::uint64_t flags, const std::uint8_t * data, std::size_t size ); + +//! Probe the provided bytes from the beginning of a file for supported file format headers to find out whether libopenmpt might be able to open it +/*! + \param flags Ored mask of openmpt::probe_file_header_flags_modules and openmpt::probe_file_header_flags_containers, or openmpt::probe_file_header_flags_default. + \param stream Input stream to scan. + \remarks stream is left in an unspecified state when this function returns. + \remarks openmpt::could_open_probability() provides a more elaborate interface that might be required for special use cases. It is recommended to use openmpt::probe_file_header() though, if possible. + \retval probe_file_header_result_success The file will most likely be supported by libopenmpt. + \retval probe_file_header_result_failure The file is not supported by libopenmpt. + \retval probe_file_header_result_wantmoredata An answer could not be determined with the amount of data provided. + \sa openmpt::probe_file_header_get_recommended_size() + \sa openmpt::could_open_probability() + \since 0.3.0 +*/ +LIBOPENMPT_CXX_API int probe_file_header( std::uint64_t flags, std::istream & stream ); + +class module_impl; + +class module_ext; + +namespace detail { + +typedef std::map< std::string, std::string > initial_ctls_map; + +} // namespace detail + +class LIBOPENMPT_CXX_API module { + + friend class module_ext; + +public: + + //! Parameter index to use with openmpt::module::get_render_param and openmpt::module::set_render_param + enum render_param { + //! Master Gain + /*! + The related value represents a relative gain in milliBel.\n + The default value is 0.\n + The supported value range is unlimited.\n + */ + RENDER_MASTERGAIN_MILLIBEL = 1, + //! Stereo Separation + /*! + The related value represents the stereo separation generated by the libopenmpt mixer in percent.\n + The default value is 100.\n + The supported value range is [0,200].\n + */ + RENDER_STEREOSEPARATION_PERCENT = 2, + //! Interpolation Filter + /*! + The related value represents the interpolation filter length used by the libopenmpt mixer.\n + The default value is 0, which indicates a recommended default value.\n + The supported value range is [0,inf). Values greater than the implementation limit are clamped to the maximum supported value.\n + Currently supported values: + - 0: internal default + - 1: no interpolation (zero order hold) + - 2: linear interpolation + - 4: cubic interpolation + - 8: windowed sinc with 8 taps + */ + RENDER_INTERPOLATIONFILTER_LENGTH = 3, + //! Volume Ramping Strength + /*! + The related value represents the amount of volume ramping done by the libopenmpt mixer.\n + The default value is -1, which indicates a recommended default value.\n + The meaningful value range is [-1..10].\n + A value of 0 completely disables volume ramping. This might cause clicks in sound output.\n + Higher values imply slower/softer volume ramps. + */ + RENDER_VOLUMERAMPING_STRENGTH = 4 + }; + + //! Parameter index to use with openmpt::module::get_pattern_row_channel_command, openmpt::module::format_pattern_row_channel_command and openmpt::module::highlight_pattern_row_channel_command + enum command_index { + command_note = 0, + command_instrument = 1, + command_volumeffect = 2, + command_effect = 3, + command_volume = 4, + command_parameter = 5 + }; + +private: + module_impl * impl; +private: + // non-copyable + module( const module & ); + void operator = ( const module & ); +private: + // for module_ext + module(); + void set_impl( module_impl * i ); +public: + //! Construct an openmpt::module + /*! + \param stream Input stream from which the module is loaded. After the constructor has finished successfully, the input position of stream is set to the byte after the last byte that has been read. If the constructor fails, the state of the input position of stream is undefined. + \param log Log where any warnings or errors are printed to. The lifetime of the reference has to be as long as the lifetime of the module instance. + \param ctls A map of initial ctl values, see openmpt::module::get_ctls. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the provided file cannot be opened. + \remarks The input data can be discarded after an openmpt::module has been constructed successfully. + \sa \ref libopenmpt_cpp_fileio + */ + module( std::istream & stream, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + /*! + \param data Data to load the module from. + \param log Log where any warnings or errors are printed to. The lifetime of the reference has to be as long as the lifetime of the module instance. + \param ctls A map of initial ctl values, see openmpt::module::get_ctls. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the provided file cannot be opened. + \remarks The input data can be discarded after an openmpt::module has been constructed successfully. + \sa \ref libopenmpt_cpp_fileio + */ + module( const std::vector & data, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + /*! + \param beg Begin of data to load the module from. + \param end End of data to load the module from. + \param log Log where any warnings or errors are printed to. The lifetime of the reference has to be as long as the lifetime of the module instance. + \param ctls A map of initial ctl values, see openmpt::module::get_ctls. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the provided file cannot be opened. + \remarks The input data can be discarded after an openmpt::module has been constructed successfully. + \sa \ref libopenmpt_cpp_fileio + */ + module( const std::uint8_t * beg, const std::uint8_t * end, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + /*! + \param data Data to load the module from. + \param size Amount of data available. + \param log Log where any warnings or errors are printed to. The lifetime of the reference has to be as long as the lifetime of the module instance. + \param ctls A map of initial ctl values, see openmpt::module::get_ctls. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the provided file cannot be opened. + \remarks The input data can be discarded after an openmpt::module has been constructed successfully. + \sa \ref libopenmpt_cpp_fileio + */ + module( const std::uint8_t * data, std::size_t size, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + /*! + \param data Data to load the module from. + \param log Log where any warnings or errors are printed to. The lifetime of the reference has to be as long as the lifetime of the module instance. + \param ctls A map of initial ctl values, see openmpt::module::get_ctls. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the provided file cannot be opened. + \remarks The input data can be discarded after an openmpt::module has been constructed successfully. + \sa \ref libopenmpt_cpp_fileio + */ + module( const std::vector & data, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + /*! + \param beg Begin of data to load the module from. + \param end End of data to load the module from. + \param log Log where any warnings or errors are printed to. The lifetime of the reference has to be as long as the lifetime of the module instance. + \param ctls A map of initial ctl values, see openmpt::module::get_ctls. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the provided file cannot be opened. + \remarks The input data can be discarded after an openmpt::module has been constructed successfully. + \sa \ref libopenmpt_cpp_fileio + */ + module( const char * beg, const char * end, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + /*! + \param data Data to load the module from. + \param size Amount of data available. + \param log Log where any warnings or errors are printed to. The lifetime of the reference has to be as long as the lifetime of the module instance. + \param ctls A map of initial ctl values, see openmpt::module::get_ctls. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the provided file cannot be opened. + \remarks The input data can be discarded after an openmpt::module has been constructed successfully. + \sa \ref libopenmpt_cpp_fileio + */ + module( const char * data, std::size_t size, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + /*! + \param data Data to load the module from. + \param size Amount of data available. + \param log Log where any warnings or errors are printed to. The lifetime of the reference has to be as long as the lifetime of the module instance. + \param ctls A map of initial ctl values, see openmpt::module::get_ctls. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the provided file cannot be opened. + \remarks The input data can be discarded after an openmpt::module has been constructed successfully. + \sa \ref libopenmpt_cpp_fileio + */ + module( const void * data, std::size_t size, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + virtual ~module(); +public: + + //! Select a sub-song from a multi-song module + /*! + \param subsong Index of the sub-song. -1 plays all sub-songs consecutively. + \throws openmpt::exception Throws an exception derived from openmpt::exception if sub-song is not in range [-1,openmpt::module::get_num_subsongs()[ + \sa openmpt::module::get_num_subsongs, openmpt::module::get_selected_subsong, openmpt::module::get_subsong_names + \remarks Whether subsong -1 (all subsongs consecutively), subsong 0 or some other subsong is selected by default, is an implementation detail and subject to change. If you do not want to care about subsongs, it is recommended to just not call openmpt::module::select_subsong() at all. + */ + void select_subsong( std::int32_t subsong ); + //! Get currently selected sub-song from a multi-song module + /*! + \return Currently selected sub-song. -1 for all subsongs consecutively, 0 or greater for the current sub-song index. + \sa openmpt::module::get_num_subsongs, openmpt::module::select_subsong, openmpt::module::get_subsong_names + \since 0.3.0 + */ + std::int32_t get_selected_subsong() const; + //! Set Repeat Count + /*! + \param repeat_count Repeat Count + - -1: repeat forever + - 0: play once, repeat zero times (the default) + - n>0: play once and repeat n times after that + \sa openmpt::module::get_repeat_count + */ + void set_repeat_count( std::int32_t repeat_count ); + //! Get Repeat Count + /*! + \return Repeat Count + - -1: repeat forever + - 0: play once, repeat zero times (the default) + - n>0: play once and repeat n times after that + \sa openmpt::module::set_repeat_count + */ + std::int32_t get_repeat_count() const; + + //! Get approximate song duration + /*! + \return Approximate duration of current sub-song in seconds. + */ + double get_duration_seconds() const; + + //! Set approximate current song position + /*! + \param seconds Seconds to seek to. If seconds is out of range, the position gets set to song start or end respectively. + \return Approximate new song position in seconds. + \sa openmpt::module::get_position_seconds + */ + double set_position_seconds( double seconds ); + //! Get current song position + /*! + \return Current song position in seconds. + \sa openmpt::module::set_position_seconds + */ + double get_position_seconds() const; + + //! Set approximate current song position + /*! + If order or row are out of range, to position is not modified and the current position is returned. + \param order Pattern order number to seek to. + \param row Pattern row number to seek to. + \return Approximate new song position in seconds. + \sa openmpt::module::set_position_seconds + \sa openmpt::module::get_position_seconds + */ + double set_position_order_row( std::int32_t order, std::int32_t row ); + + //! Get render parameter + /*! + \param param Parameter to query. See openmpt::module::render_param. + \return The current value of the parameter. + \throws openmpt::exception Throws an exception derived from openmpt::exception if param is invalid. + \sa openmpt::module::render_param + \sa openmpt::module::set_render_param + */ + std::int32_t get_render_param( int param ) const; + //! Set render parameter + /*! + \param param Parameter to set. See openmpt::module::render_param. + \param value The value to set param to. + \throws openmpt::exception Throws an exception derived from openmpt::exception if param is invalid or value is out of range. + \sa openmpt::module::render_param + \sa openmpt::module::get_render_param + */ + void set_render_param( int param, std::int32_t value ); + + /*@{*/ + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param mono Pointer to a buffer of at least count elements that receives the mono/center output. + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read( std::int32_t samplerate, std::size_t count, std::int16_t * mono ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param left Pointer to a buffer of at least count elements that receives the left output. + \param right Pointer to a buffer of at least count elements that receives the right output. + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read( std::int32_t samplerate, std::size_t count, std::int16_t * left, std::int16_t * right ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param left Pointer to a buffer of at least count elements that receives the left output. + \param right Pointer to a buffer of at least count elements that receives the right output. + \param rear_left Pointer to a buffer of at least count elements that receives the rear left output. + \param rear_right Pointer to a buffer of at least count elements that receives the rear right output. + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read( std::int32_t samplerate, std::size_t count, std::int16_t * left, std::int16_t * right, std::int16_t * rear_left, std::int16_t * rear_right ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param mono Pointer to a buffer of at least count elements that receives the mono/center output. + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read( std::int32_t samplerate, std::size_t count, float * mono ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param left Pointer to a buffer of at least count elements that receives the left output. + \param right Pointer to a buffer of at least count elements that receives the right output. + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read( std::int32_t samplerate, std::size_t count, float * left, float * right ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param left Pointer to a buffer of at least count elements that receives the left output. + \param right Pointer to a buffer of at least count elements that receives the right output. + \param rear_left Pointer to a buffer of at least count elements that receives the rear left output. + \param rear_right Pointer to a buffer of at least count elements that receives the rear right output. + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read( std::int32_t samplerate, std::size_t count, float * left, float * right, float * rear_left, float * rear_right ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param interleaved_stereo Pointer to a buffer of at least count*2 elements that receives the interleaved stereo output in the order (L,R). + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read_interleaved_stereo( std::int32_t samplerate, std::size_t count, std::int16_t * interleaved_stereo ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param interleaved_quad Pointer to a buffer of at least count*4 elements that receives the interleaved suad surround output in the order (L,R,RL,RR). + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks It is recommended to use the floating point API because of the greater dynamic range and no implied clipping. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read_interleaved_quad( std::int32_t samplerate, std::size_t count, std::int16_t * interleaved_quad ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param interleaved_stereo Pointer to a buffer of at least count*2 elements that receives the interleaved stereo output in the order (L,R). + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read_interleaved_stereo( std::int32_t samplerate, std::size_t count, float * interleaved_stereo ); + //! Render audio data + /*! + \param samplerate Sample rate to render output. Should be in [8000,192000], but this is not enforced. + \param count Number of audio frames to render per channel. + \param interleaved_quad Pointer to a buffer of at least count*4 elements that receives the interleaved suad surround output in the order (L,R,RL,RR). + \return The number of frames actually rendered. + \retval 0 The end of song has been reached. + \remarks The output buffers are only written to up to the returned number of elements. + \remarks You can freely switch between any of the "read*" variants if you see a need to do so. libopenmpt tries to introduce as little switching annoyances as possible. Normally, you would only use a single one of these functions for rendering a particular module. + \remarks Floating point samples are in the [-1.0..1.0] nominal range. They are not clipped to that range though and thus might overshoot. + \sa \ref libopenmpt_cpp_outputformat + */ + std::size_t read_interleaved_quad( std::int32_t samplerate, std::size_t count, float * interleaved_quad ); + /*@}*/ + + //! Get the list of supported metadata item keys + /*! + \return Metadata item keys supported by openmpt::module::get_metadata + \sa openmpt::module::get_metadata + */ + std::vector get_metadata_keys() const; + //! Get a metadata item value + /*! + \param key Metadata item key to query. Use openmpt::module::get_metadata_keys to check for available keys. + Possible keys are: + - type: Module format extension (e.g. it) + - type_long: Format name associated with the module format (e.g. Impulse Tracker) + - originaltype: Module format extension (e.g. it) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) + - originaltype_long: Format name associated with the module format (e.g. Impulse Tracker) of the original module in case the actual type is a converted format (e.g. mo3 or gdm) + - container: Container format the module file is embedded in, if any (e.g. umx) + - container_long: Full container name if the module is embedded in a container (e.g. Unreal Music) + - tracker: Tracker that was (most likely) used to save the module file, if known + - artist: Author of the module + - title: Module title + - date: Date the module was last saved, in ISO-8601 format. + - message: Song message. If the song message is empty or the module format does not support song messages, a list of instrument and sample names is returned instead. + - message_raw: Song message. If the song message is empty or the module format does not support song messages, an empty string is returned. + - warnings: A list of warnings that were generated while loading the module. + \return The associated value for key. + \sa openmpt::module::get_metadata_keys + */ + std::string get_metadata( const std::string & key ) const; + + //! Get the current speed + /*! + \return The current speed in ticks per row. + */ + std::int32_t get_current_speed() const; + //! Get the current tempo + /*! + \return The current tempo in tracker units. The exact meaning of this value depends on the tempo mode being used. + */ + std::int32_t get_current_tempo() const; + //! Get the current order + /*! + \return The current order at which the module is being played back. + */ + std::int32_t get_current_order() const; + //! Get the current pattern + /*! + \return The current pattern that is being played. + */ + std::int32_t get_current_pattern() const; + //! Get the current row + /*! + \return The current row at which the current pattern is being played. + */ + std::int32_t get_current_row() const; + //! Get the current amount of playing channels. + /*! + \return The amount of sample channels that are currently being rendered. + */ + std::int32_t get_current_playing_channels() const; + + //! Get an approximate indication of the channel volume. + /*! + \param channel The channel whose volume should be retrieved. + \return The approximate channel volume. + \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ + float get_current_channel_vu_mono( std::int32_t channel ) const; + //! Get an approximate indication of the channel volume on the front-left speaker. + /*! + \param channel The channel whose volume should be retrieved. + \return The approximate channel volume. + \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ + float get_current_channel_vu_left( std::int32_t channel ) const; + //! Get an approximate indication of the channel volume on the front-right speaker. + /*! + \param channel The channel whose volume should be retrieved. + \return The approximate channel volume. + \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ + float get_current_channel_vu_right( std::int32_t channel ) const; + //! Get an approximate indication of the channel volume on the rear-left speaker. + /*! + \param channel The channel whose volume should be retrieved. + \return The approximate channel volume. + \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ + float get_current_channel_vu_rear_left( std::int32_t channel ) const; + //! Get an approximate indication of the channel volume on the rear-right speaker. + /*! + \param channel The channel whose volume should be retrieved. + \return The approximate channel volume. + \remarks The returned value is solely based on the note velocity and does not take the actual waveform of the playing sample into account. + */ + float get_current_channel_vu_rear_right( std::int32_t channel ) const; + + //! Get the number of sub-songs + /*! + \return The number of sub-songs in the module. This includes any "hidden" songs (songs that share the same sequence, but start at different order indices) and "normal" sub-songs or "sequences" (if the format supports them). + \sa openmpt::module::get_subsong_names, openmpt::module::select_subsong, openmpt::module::get_selected_subsong + */ + std::int32_t get_num_subsongs() const; + //! Get the number of pattern channels + /*! + \return The number of pattern channels in the module. Not all channels do necessarily contain data. + \remarks The number of pattern channels is completely independent of the number of output channels. libopenmpt can render modules in mono, stereo or quad surround, but the choice of which of the three modes to use must not be made based on the return value of this function, which may be any positive integer amount. Only use this function for informational purposes. + */ + std::int32_t get_num_channels() const; + //! Get the number of orders + /*! + \return The number of orders in the current sequence of the module. + */ + std::int32_t get_num_orders() const; + //! Get the number of patterns + /*! + \return The number of distinct patterns in the module. + */ + std::int32_t get_num_patterns() const; + //! Get the number of instruments + /*! + \return The number of instrument slots in the module. Instruments are a layer on top of samples, and are not supported by all module formats. + */ + std::int32_t get_num_instruments() const; + //! Get the number of samples + /*! + \return The number of sample slots in the module. + */ + std::int32_t get_num_samples() const; + + //! Get a list of sub-song names + /*! + \return All sub-song names. + \sa openmpt::module::get_num_subsongs, openmpt::module::select_subsong, openmpt::module::get_selected_subsong + */ + std::vector get_subsong_names() const; + //! Get a list of channel names + /*! + \return All channel names. + \sa openmpt::module::get_num_channels + */ + std::vector get_channel_names() const; + //! Get a list of order names + /*! + \return All order names. + \sa openmpt::module::get_num_orders + */ + std::vector get_order_names() const; + //! Get a list of pattern names + /*! + \return All pattern names. + \sa openmpt::module::get_num_patterns + */ + std::vector get_pattern_names() const; + //! Get a list of instrument names + /*! + \return All instrument names. + \sa openmpt::module::get_num_instruments + */ + std::vector get_instrument_names() const; + //! Get a list of sample names + /*! + \return All sample names. + \sa openmpt::module::get_num_samples + */ + std::vector get_sample_names() const; + + //! Get pattern at order position + /*! + \param order The order item whose pattern index should be retrieved. + \return The pattern index found at the given order position of the current sequence. + */ + std::int32_t get_order_pattern( std::int32_t order ) const; + + //! Get the number of rows in a pattern + /*! + \param pattern The pattern whose row count should be retrieved. + \return The number of rows in the given pattern. If the pattern does not exist, 0 is returned. + */ + std::int32_t get_pattern_num_rows( std::int32_t pattern ) const; + + //! Get raw pattern content + /*! + \param pattern The pattern whose data should be retrieved. + \param row The row from which the data should be retrieved. + \param channel The channel from which the data should be retrieved. + \param command The cell index at which the data should be retrieved. See openmpt::module::command_index + \return The internal, raw pattern data at the given pattern position. + */ + std::uint8_t get_pattern_row_channel_command( std::int32_t pattern, std::int32_t row, std::int32_t channel, int command ) const; + + //! Get formatted (human-readable) pattern content + /*! + \param pattern The pattern whose data should be retrieved. + \param row The row from which the data should be retrieved. + \param channel The channel from which the data should be retrieved. + \param command The cell index at which the data should be retrieved. + \return The formatted pattern data at the given pattern position. See openmpt::module::command_index + \sa openmpt::module::highlight_pattern_row_channel_command + */ + std::string format_pattern_row_channel_command( std::int32_t pattern, std::int32_t row, std::int32_t channel, int command ) const; + + //! Get highlighting information for formatted pattern content + /*! + \param pattern The pattern whose data should be retrieved. + \param row The row from which the data should be retrieved. + \param channel The channel from which the data should be retrieved. + \param command The cell index at which the data should be retrieved. See openmpt::module::command_index + \return The highlighting string for the formatted pattern data as retrieved by openmpt::module::get_pattern_row_channel_command at the given pattern position. + \remarks The returned string will map each character position of the string returned by openmpt::module::get_pattern_row_channel_command to a highlighting instruction. + Possible highlighting characters are: + - " " : empty/space + - "." : empty/dot + - "n" : generic note + - "m" : special note + - "i" : generic instrument + - "u" : generic volume column effect + - "v" : generic volume column parameter + - "e" : generic effect column effect + - "f" : generic effect column parameter + \sa openmpt::module::get_pattern_row_channel_command + */ + std::string highlight_pattern_row_channel_command( std::int32_t pattern, std::int32_t row, std::int32_t channel, int command ) const; + + //! Get formatted (human-readable) pattern content + /*! + \param pattern The pattern whose data should be retrieved. + \param row The row from which the data should be retrieved. + \param channel The channel from which the data should be retrieved. + \param width The maximum number of characters the string should contain. 0 means no limit. + \param pad If true, the string will be resized to the exact length provided in the width parameter. + \return The formatted pattern data at the given pattern position. + \sa openmpt::module::highlight_pattern_row_channel + */ + std::string format_pattern_row_channel( std::int32_t pattern, std::int32_t row, std::int32_t channel, std::size_t width = 0, bool pad = true ) const; + //! Get highlighting information for formatted pattern content + /*! + \param pattern The pattern whose data should be retrieved. + \param row The row from which the data should be retrieved. + \param channel The channel from which the data should be retrieved. + \param width The maximum number of characters the string should contain. 0 means no limit. + \param pad If true, the string will be resized to the exact length provided in the width parameter. + \return The highlighting string for the formatted pattern data as retrieved by openmpt::module::format_pattern_row_channel at the given pattern position. + \sa openmpt::module::format_pattern_row_channel + */ + std::string highlight_pattern_row_channel( std::int32_t pattern, std::int32_t row, std::int32_t channel, std::size_t width = 0, bool pad = true ) const; + + //! Retrieve supported ctl keys + /*! + \return A vector containing all supported ctl keys. + \remarks Currently supported ctl values are: + - load.skip_samples: Set to "1" to avoid loading samples into memory + - load.skip_patterns: Set to "1" to avoid loading patterns into memory + - load.skip_plugins: Set to "1" to avoid loading plugins + - load.skip_subsongs_init: Set to "1" to avoid pre-initializing sub-songs. Skipping results in faster module loading but slower seeking. + - seek.sync_samples: Set to "1" to sync sample playback when using openmpt::module::set_position_seconds or openmpt::module::set_position_order_row. + - subsong: The current subsong. Setting it has identical semantics as openmpt::module::select_subsong(), getting it returns the currently selected subsong. + - play.at_end: Chooses the behaviour when the end of song is reached: + - "fadeout": Fades the module out for a short while. Subsequent reads after the fadeout will return 0 rendered frames. + - "continue": Returns 0 rendered frames when the song end is reached. Subsequent reads will continue playing from the song start or loop start. + - "stop": Returns 0 rendered frames when the song end is reached. Subsequent reads will return 0 rendered frames. + - play.tempo_factor: Set a floating point tempo factor. "1.0" is the default tempo. + - play.pitch_factor: Set a floating point pitch factor. "1.0" is the default pitch. + - render.resampler.emulate_amiga: Set to "1" to enable the Amiga resampler for Amiga modules. This emulates the sound characteristics of the Paula chip and overrides the selected interpolation filter. Non-Amiga module formats are not affected by this setting. + - render.opl.volume_factor: Set volume factor applied to synthesized OPL sounds, relative to the default OPL volume. + - dither: Set the dither algorithm that is used for the 16 bit versions of openmpt::module::read. Supported values are: + - 0: No dithering. + - 1: Default mode. Chosen by OpenMPT code, might change. + - 2: Rectangular, 0.5 bit depth, no noise shaping (original ModPlug Tracker). + - 3: Rectangular, 1 bit depth, simple 1st order noise shaping + + An exclamation mark ("!") or a question mark ("?") can be appended to any ctl key in order to influence the behaviour in case of an unknown ctl key. "!" causes an exception to be thrown; "?" causes the ctl to be silently ignored. In case neither is appended to the key name, unknown init_ctls are ignored by default and other ctls throw an exception by default. + */ + std::vector get_ctls() const; + + //! Get current ctl value + /*! + \param ctl The ctl key whose value should be retrieved. + \return The associated ctl value. + \sa openmpt::module::get_ctls + */ + std::string ctl_get( const std::string & ctl ) const; + //! Set ctl value + /*! + \param ctl The ctl key whose value should be set. + \param value The value that should be set. + \throws openmpt::exception Throws an exception derived from openmpt::exception in case the value is not sensible (e.g. negative tempo factor) or under the circumstances outlined in openmpt::module::get_ctls. + \sa openmpt::module::get_ctls + */ + void ctl_set( const std::string & ctl, const std::string & value ); + + // remember to add new functions to both C and C++ interfaces and to increase OPENMPT_API_VERSION_MINOR + +}; // class module + +} // namespace openmpt + +/*! + @} +*/ + +#endif // LIBOPENMPT_HPP diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt_config.h b/libs/libopenmpt/inc/libopenmpt/libopenmpt_config.h new file mode 100644 index 000000000..0323ab1e0 --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt_config.h @@ -0,0 +1,204 @@ +/* + * libopenmpt_config.h + * ------------------- + * Purpose: libopenmpt public interface configuration + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_CONFIG_H +#define LIBOPENMPT_CONFIG_H + +/*! \defgroup libopenmpt libopenmpt */ + +/*! \addtogroup libopenmpt + @{ +*/ + +/* provoke warnings if already defined */ +#define LIBOPENMPT_API +#undef LIBOPENMPT_API +#define LIBOPENMPT_CXX_API +#undef LIBOPENMPT_CXX_API + +/*! \brief Defined if libopenmpt/libopenmpt_stream_callbacks_buffer.h exists. */ +#define LIBOPENMPT_STREAM_CALLBACKS_BUFFER + +/*! \brief Defined if libopenmpt/libopenmpt_stream_callbacks_fd.h exists. + * \since 0.3 + * \remarks + * Use the following to check for availability: + * \code + * #include + * #if defined(LIBOPENMPT_STREAM_CALLBACKS_FD) || ((OPENMPT_API_VERSION_MAJOR == 0) && ((OPENMPT_API_VERSION_MINOR == 2) || (OPENMPT_API_VERSION_MINOR == 1))) + * #include + * #endif + * \endcode + */ +#define LIBOPENMPT_STREAM_CALLBACKS_FD + +/*! \brief Defined if libopenmpt/libopenmpt_stream_callbacks_file.h exists. + * \since 0.3 + * \remarks + * Use the following to check for availability: + * \code + * #include + * #if defined(LIBOPENMPT_STREAM_CALLBACKS_FILE) || ((OPENMPT_API_VERSION_MAJOR == 0) && ((OPENMPT_API_VERSION_MINOR == 2) || (OPENMPT_API_VERSION_MINOR == 1))) + * #include + * #endif + * \endcode + */ +#define LIBOPENMPT_STREAM_CALLBACKS_FILE + +#if defined(__DOXYGEN__) + +#define LIBOPENMPT_API_HELPER_EXPORT +#define LIBOPENMPT_API_HELPER_IMPORT +#define LIBOPENMPT_API_HELPER_PUBLIC +#define LIBOPENMPT_API_HELPER_LOCAL + +#elif defined(_MSC_VER) + +#define LIBOPENMPT_API_HELPER_EXPORT __declspec(dllexport) +#define LIBOPENMPT_API_HELPER_IMPORT __declspec(dllimport) +#define LIBOPENMPT_API_HELPER_PUBLIC +#define LIBOPENMPT_API_HELPER_LOCAL + +#elif defined(__EMSCRIPTEN__) + +#define LIBOPENMPT_API_HELPER_EXPORT __attribute__((visibility("default"))) __attribute__((used)) +#define LIBOPENMPT_API_HELPER_IMPORT __attribute__((visibility("default"))) __attribute__((used)) +#define LIBOPENMPT_API_HELPER_PUBLIC __attribute__((visibility("default"))) __attribute__((used)) +#define LIBOPENMPT_API_HELPER_LOCAL __attribute__((visibility("hidden"))) + +#elif (defined(__GNUC__) || defined(__clang__)) && defined(_WIN32) + +#define LIBOPENMPT_API_HELPER_EXPORT __declspec(dllexport) +#define LIBOPENMPT_API_HELPER_IMPORT __declspec(dllimport) +#define LIBOPENMPT_API_HELPER_PUBLIC __attribute__((visibility("default"))) +#define LIBOPENMPT_API_HELPER_LOCAL __attribute__((visibility("hidden"))) + +#elif defined(__GNUC__) || defined(__clang__) + +#define LIBOPENMPT_API_HELPER_EXPORT __attribute__((visibility("default"))) +#define LIBOPENMPT_API_HELPER_IMPORT __attribute__((visibility("default"))) +#define LIBOPENMPT_API_HELPER_PUBLIC __attribute__((visibility("default"))) +#define LIBOPENMPT_API_HELPER_LOCAL __attribute__((visibility("hidden"))) + +#elif defined(_WIN32) + +#define LIBOPENMPT_API_HELPER_EXPORT __declspec(dllexport) +#define LIBOPENMPT_API_HELPER_IMPORT __declspec(dllimport) +#define LIBOPENMPT_API_HELPER_PUBLIC +#define LIBOPENMPT_API_HELPER_LOCAL + +#else + +#define LIBOPENMPT_API_HELPER_EXPORT +#define LIBOPENMPT_API_HELPER_IMPORT +#define LIBOPENMPT_API_HELPER_PUBLIC +#define LIBOPENMPT_API_HELPER_LOCAL + +#endif + +#if defined(LIBOPENMPT_BUILD_DLL) +#define LIBOPENMPT_API LIBOPENMPT_API_HELPER_EXPORT +#elif defined(LIBOPENMPT_USE_DLL) +#define LIBOPENMPT_API LIBOPENMPT_API_HELPER_IMPORT +#else +#define LIBOPENMPT_API LIBOPENMPT_API_HELPER_PUBLIC +#endif + +#ifdef __cplusplus + +#define LIBOPENMPT_CXX_API LIBOPENMPT_API + +#if defined(LIBOPENMPT_USE_DLL) +#if defined(_MSC_VER) && !defined(_DLL) +#error "C++ interface is disabled if libopenmpt is built as a DLL and the runtime is statically linked. This is not supported by microsoft and cannot possibly work. Ever." +#undef LIBOPENMPT_CXX_API +#define LIBOPENMPT_CXX_API LIBOPENMPT_API_HELPER_LOCAL +#endif +#endif + +#if defined(__EMSCRIPTEN__) + +/* Only the C API is supported for emscripten. Disable the C++ API. */ +#undef LIBOPENMPT_CXX_API +#define LIBOPENMPT_CXX_API LIBOPENMPT_API_HELPER_LOCAL +#endif + +#endif + +/*! + @} +*/ + + +/* C */ + +#if !defined(LIBOPENMPT_NO_DEPRECATE) +#if defined(__clang__) +#define LIBOPENMPT_DEPRECATED __attribute__((deprecated)) +#elif defined(__GNUC__) +#define LIBOPENMPT_DEPRECATED __attribute__((deprecated)) +#elif defined(_MSC_VER) +#define LIBOPENMPT_DEPRECATED __declspec(deprecated) +#else +#define LIBOPENMPT_DEPRECATED +#endif +#endif + +#ifndef __cplusplus +#if !defined(LIBOPENMPT_NO_DEPRECATE) +LIBOPENMPT_DEPRECATED static const int LIBOPENMPT_DEPRECATED_STRING_CONSTANT = 0; +#define LIBOPENMPT_DEPRECATED_STRING( str ) ( LIBOPENMPT_DEPRECATED_STRING_CONSTANT ? ( str ) : ( str ) ) +#else +#define LIBOPENMPT_DEPRECATED_STRING( str ) str +#endif +#endif + + +/* C++ */ + +#ifdef __cplusplus + +#ifndef LIBOPENMPT_ASSUME_CPLUSPLUS_DEPRECATED +/* handle known broken compilers here by defining LIBOPENMPT_ASSUME_CPLUSPLUS_DEPRECATED appropriately */ +#endif + +#if defined(LIBOPENMPT_ASSUME_CPLUSPLUS) +#ifndef LIBOPENMPT_ASSUME_CPLUSPLUS_DEPRECATED +#define LIBOPENMPT_ASSUME_CPLUSPLUS_DEPRECATED LIBOPENMPT_ASSUME_CPLUSPLUS +#endif +#endif + +#if !defined(LIBOPENMPT_NO_DEPRECATE) +#if defined(LIBOPENMPT_ASSUME_CPLUSPLUS_DEPRECATED) +#if (LIBOPENMPT_ASSUME_CPLUSPLUS_DEPRECATED >= 201402L) +#define LIBOPENMPT_ATTR_DEPRECATED [[deprecated]] +#undef LIBOPENMPT_DEPRECATED +#define LIBOPENMPT_DEPRECATED +#else +#define LIBOPENMPT_ATTR_DEPRECATED +#endif +#elif (__cplusplus >= 201402L) +#define LIBOPENMPT_ATTR_DEPRECATED [[deprecated]] +#undef LIBOPENMPT_DEPRECATED +#define LIBOPENMPT_DEPRECATED +#else +#define LIBOPENMPT_ATTR_DEPRECATED +#endif +#else +#undef LIBOPENMPT_DEPRECATED +#define LIBOPENMPT_DEPRECATED +#define LIBOPENMPT_ATTR_DEPRECATED +#endif + +#endif + + +#include "libopenmpt_version.h" + +#endif /* LIBOPENMPT_CONFIG_H */ diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt_ext.h b/libs/libopenmpt/inc/libopenmpt/libopenmpt_ext.h new file mode 100644 index 000000000..e76f758de --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt_ext.h @@ -0,0 +1,318 @@ +/* + * libopenmpt_ext.h + * ---------------- + * Purpose: libopenmpt public c interface for libopenmpt extensions + * Notes : + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_EXT_H +#define LIBOPENMPT_EXT_H + +#include "libopenmpt_config.h" +#include "libopenmpt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * \page libopenmpt_ext_c_overview libopenmpt_ext C API + * + * libopenmpt_ext is included in all builds by default. + * + * \section libopenmpt-ext-c-detailed Detailed documentation + * + * \ref libopenmpt_ext_c + * + */ + +/*! \defgroup libopenmpt_ext_c libopenmpt_ext C */ + +/*! \addtogroup libopenmpt_ext_c + * @{ + */ + +/*! \brief Opaque type representing a libopenmpt extension module + */ +typedef struct openmpt_module_ext openmpt_module_ext; + +/*! \brief Construct an openmpt_module_ext + * + * \param stream_callbacks Input stream callback operations. + * \param stream Input stream to load the module from. + * \param logfunc Logging function where warning and errors are written. The logging function may be called throughout the lifetime of openmpt_module_ext. May be NULL. + * \param loguser User-defined data associated with this module. This value will be passed to the logging callback function (logfunc) + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param error Pointer to an integer where an error may get stored. May be NULL. + * \param error_message Pointer to a string pointer where an error message may get stored. May be NULL. + * \param ctls A map of initial ctl values, see openmpt_module_get_ctls. + * \return A pointer to the constructed openmpt_module_ext, or NULL on failure. + * \remarks The input data can be discarded after an openmpt_module_ext has been constructed successfully. + * \sa openmpt_stream_callbacks + * \sa \ref libopenmpt_c_fileio + * \since 0.3.0 + */ +LIBOPENMPT_API openmpt_module_ext * openmpt_module_ext_create( openmpt_stream_callbacks stream_callbacks, void * stream, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ); + +/*! \brief Construct an openmpt_module_ext + * + * \param filedata Data to load the module from. + * \param filesize Amount of data available. + * \param logfunc Logging function where warning and errors are written. The logging function may be called throughout the lifetime of openmpt_module_ext. + * \param loguser User-defined data associated with this module. This value will be passed to the logging callback function (logfunc) + * \param errfunc Error function to define error behaviour. May be NULL. + * \param erruser Error function user context. Used to pass any user-defined data associated with this module to the logging function. + * \param error Pointer to an integer where an error may get stored. May be NULL. + * \param error_message Pointer to a string pointer where an error message may get stored. May be NULL. + * \param ctls A map of initial ctl values, see openmpt_module_get_ctls. + * \return A pointer to the constructed openmpt_module_ext, or NULL on failure. + * \remarks The input data can be discarded after an openmpt_module_ext has been constructed successfully. + * \sa \ref libopenmpt_c_fileio + * \since 0.3.0 + */ +LIBOPENMPT_API openmpt_module_ext * openmpt_module_ext_create_from_memory( const void * filedata, size_t filesize, openmpt_log_func logfunc, void * loguser, openmpt_error_func errfunc, void * erruser, int * error, const char * * error_message, const openmpt_module_initial_ctl * ctls ); + +/*! \brief Unload a previously created openmpt_module_ext from memory. + * + * \param mod_ext The module to unload. + */ +LIBOPENMPT_API void openmpt_module_ext_destroy( openmpt_module_ext * mod_ext ); + +/*! \brief Retrieve the openmpt_module handle from an openmpt_module_ext handle. + * + * \param mod_ext The extension module handle to convert + * \return An equivalent openmpt_module handle to pass to standard libopenmpt functions + * \since 0.3.0 + */ +LIBOPENMPT_API openmpt_module * openmpt_module_ext_get_module( openmpt_module_ext * mod_ext ); + +/*! Retrieve a libopenmpt extension. + * + * \param mod_ext The module handle to work on. + * \param interface_id The name of the extension interface to retrieve (e.g. LIBOPENMPT_EXT_C_INTERFACE_PATTERN_VIS). + * \param interface Appropriate structure of interface function pointers which is to be filled by this function (e.g. a pointer to a openmpt_module_ext_interface_pattern_vis structure). + * \param interface_size Size of the interface's structure of function pointers (e.g. sizeof(openmpt_module_ext_interface_pattern_vis)). + * \return 1 on success, 0 if the interface was not found. + * \since 0.3.0 + */ +LIBOPENMPT_API int openmpt_module_ext_get_interface( openmpt_module_ext * mod_ext, const char * interface_id, void * interface, size_t interface_size ); + + + +#ifndef LIBOPENMPT_EXT_C_INTERFACE_PATTERN_VIS +#define LIBOPENMPT_EXT_C_INTERFACE_PATTERN_VIS "pattern_vis" +#endif + +/*! Pattern command type */ +#define OPENMPT_MODULE_EXT_INTERFACE_PATTERN_VIS_EFFECT_TYPE_UNKNOWN 0 +#define OPENMPT_MODULE_EXT_INTERFACE_PATTERN_VIS_EFFECT_TYPE_GENERAL 1 +#define OPENMPT_MODULE_EXT_INTERFACE_PATTERN_VIS_EFFECT_TYPE_GLOBAL 2 +#define OPENMPT_MODULE_EXT_INTERFACE_PATTERN_VIS_EFFECT_TYPE_VOLUME 3 +#define OPENMPT_MODULE_EXT_INTERFACE_PATTERN_VIS_EFFECT_TYPE_PANNING 4 +#define OPENMPT_MODULE_EXT_INTERFACE_PATTERN_VIS_EFFECT_TYPE_PITCH 5 + +typedef struct openmpt_module_ext_interface_pattern_vis { + /*! Get pattern command type for pattern highlighting + * + * \param mod_ext The module handle to work on. + * \param pattern The pattern whose data should be retrieved. + * \param row The row from which the data should be retrieved. + * \param channel The channel from which the data should be retrieved. + * \return The command type in the effect column at the given pattern position (see OPENMPT_MODULE_EXT_INTERFACE_PATTERN_VIS_EFFECT_TYPE_*) + * \sa openmpt_module_ext_interface_pattern_vis::get_pattern_row_channel_volume_effect_type + */ + int ( * get_pattern_row_channel_volume_effect_type ) ( openmpt_module_ext * mod_ext, int32_t pattern, int32_t row, int32_t channel ); + + /*! Get pattern command type for pattern highlighting + * + * \param mod_ext The module handle to work on. + * \param pattern The pattern whose data should be retrieved. + * \param row The row from which the data should be retrieved. + * \param channel The channel from which the data should be retrieved. + * \return The command type in the effect column at the given pattern position (see OPENMPT_MODULE_EXT_INTERFACE_PATTERN_VIS_EFFECT_TYPE_*) + * \sa openmpt_module_ext_interface_pattern_vis::get_pattern_row_channel_volume_effect_type + */ + int ( * get_pattern_row_channel_effect_type ) ( openmpt_module_ext * mod_ext, int32_t pattern, int32_t row, int32_t channel ); +} openmpt_module_ext_interface_pattern_vis; + + + +#ifndef LIBOPENMPT_EXT_C_INTERFACE_INTERACTIVE +#define LIBOPENMPT_EXT_C_INTERFACE_INTERACTIVE "interactive" +#endif + +typedef struct openmpt_module_ext_interface_interactive { + /*! Set the current ticks per row (speed) + * + * \param mod_ext The module handle to work on. + * \param speed The new tick count in range [1, 65535]. + * \return 1 on success, 0 on failure. + * \remarks The tick count may be reset by pattern commands at any time. + * \sa openmpt_module_get_current_speed + */ + int ( * set_current_speed ) ( openmpt_module_ext * mod_ext, int32_t speed ); + + /*! Set the current module tempo + * + * \param mod_ext The module handle to work on. + * \param tempo The new tempo in range [32, 512]. The exact meaning of the value depends on the tempo mode used by the module. + * \return 1 on success, 0 on failure. + * \remarks The tempo may be reset by pattern commands at any time. Use openmpt_module_ext_interface_interactive::set_tempo_factor to apply a tempo factor that is independent of pattern commands. + * \sa openmpt_module_get_current_tempo + */ + int ( * set_current_tempo ) ( openmpt_module_ext * mod_ext, int32_t tempo ); + + /*! Set the current module tempo factor without affecting playback pitch + * + * \param mod_ext The module handle to work on. + * \param factor The new tempo factor in range ]0.0, 4.0] - 1.0 means unmodified tempo. + * \return 1 on success, 0 on failure. + * \remarks Modifying the tempo without applying the same pitch factor using openmpt_module_ext_interface_interactive::set_pitch_factor may cause rhythmic samples (e.g. drum loops) to go out of sync. + * \sa openmpt_module_ext_interface_interactive::get_tempo_factor + */ + int ( * set_tempo_factor ) ( openmpt_module_ext * mod_ext, double factor ); + + /*! Gets the current module tempo factor + * + * \param mod_ext The module handle to work on. + * \return The current tempo factor. + * \sa openmpt_module_ext_interface_interactive::set_tempo_factor + */ + double ( * get_tempo_factor ) ( openmpt_module_ext * mod_ext ); + + /*! Set the current module pitch factor without affecting playback speed + * + * \param mod_ext The module handle to work on. + * \param factor The new pitch factor in range ]0.0, 4.0] - 1.0 means unmodified pitch. + * \return 1 on success, 0 on failure. + * \remarks Modifying the pitch without applying the the same tempo factor using openmpt_module_ext_interface_interactive::set_tempo_factor may cause rhythmic samples (e.g. drum loops) to go out of sync. + * \remarks To shift the pich by `n` semitones, the parameter can be calculated as follows: `pow( 2.0, n / 12.0 )` + * \sa openmpt_module_ext_interface_interactive::get_pitch_factor + */ + int ( * set_pitch_factor ) ( openmpt_module_ext * mod_ext, double factor ); + + /*! Gets the current module pitch factor + * + * \param mod_ext The module handle to work on. + * \return The current pitch factor. + * \sa openmpt_module_ext_interface_interactive::set_pitch_factor + */ + double ( * get_pitch_factor ) ( openmpt_module_ext * mod_ext ); + + /*! Set the current global volume + * + * \param mod_ext The module handle to work on. + * \param volume The new global volume in range [0.0, 1.0] + * \return 1 on success, 0 on failure. + * \remarks The global volume may be reset by pattern commands at any time. Use openmpt_module_set_render_param to apply a global overall volume factor that is independent of pattern commands. + * \sa openmpt_module_ext_interface_interactive::get_global_volume + */ + int ( * set_global_volume ) ( openmpt_module_ext * mod_ext, double volume ); + + /*! Get the current global volume + * + * \param mod_ext The module handle to work on. + * \return The current global volume in range [0.0, 1.0] + * \sa openmpt_module_ext_interface_interactive::set_global_volume + */ + double ( * get_global_volume ) ( openmpt_module_ext * mod_ext ); + + /*! Set the current channel volume for a channel + * + * \param mod_ext The module handle to work on. + * \param channel The channel whose volume should be set, in range [0, openmpt_module_get_num_channels()[ + * \param volume The new channel volume in range [0.0, 1.0] + * \return 1 on success, 0 on failure (channel out of range). + * \remarks The channel volume may be reset by pattern commands at any time. + * \sa openmpt_module_ext_interface_interactive::get_channel_volume + */ + int ( * set_channel_volume ) ( openmpt_module_ext * mod_ext, int32_t channel, double volume ); + + /*! Get the current channel volume for a channel + * + * \param mod_ext The module handle to work on. + * \param channel The channel whose volume should be retrieved, in range [0, openmpt_module_get_num_channels()[ + * \return The current channel volume in range [0.0, 1.0] + * \sa openmpt_module_ext_interface_interactive::set_channel_volume + */ + double ( * get_channel_volume ) ( openmpt_module_ext * mod_ext, int32_t channel ); + + /*! Set the current mute status for a channel + * + * \param mod_ext The module handle to work on. + * \param channel The channel whose mute status should be set, in range [0, openmpt_module_get_num_channels()[ + * \param mute The new mute status. true is muted, false is unmuted. + * \return 1 on success, 0 on failure (channel out of range). + * \sa openmpt_module_ext_interface_interactive::get_channel_mute_status + */ + int ( * set_channel_mute_status ) ( openmpt_module_ext * mod_ext, int32_t channel, int mute ); + + /*! Get the current mute status for a channel + * + * \param mod_ext The module handle to work on. + * \param channel The channel whose mute status should be retrieved, in range [0, openmpt_module_get_num_channels()[ + * \return The current channel mute status. 1 is muted, 0 is unmuted, -1 means the instrument was out of range + * \sa openmpt_module_ext_interface_interactive::set_channel_mute_status + */ + int ( * get_channel_mute_status ) ( openmpt_module_ext * mod_ext, int32_t channel ); + + /*! Set the current mute status for an instrument + * + * \param mod_ext The module handle to work on. + * \param instrument The instrument whose mute status should be set, in range [0, openmpt_module_get_num_instruments()[ if openmpt_module_get_num_instruments is not 0, otherwise in [0, openmpt_module_get_num_samples()[ + * \param mute The new mute status. true is muted, false is unmuted. + * \return 1 on success, 0 on failure (instrument out of range). + * \sa openmpt_module_ext_interface_interactive::get_instrument_mute_status + */ + int ( * set_instrument_mute_status ) ( openmpt_module_ext * mod_ext, int32_t instrument, int mute ); + + /*! Get the current mute status for an instrument + * + * \param mod_ext The module handle to work on. + * \param instrument The instrument whose mute status should be retrieved, in range [0, openmpt_module_get_num_instruments()[ if openmpt_module_get_num_instruments is not 0, otherwise in [0, openmpt_module_get_num_samples()[ + * \return The current instrument mute status. 1 is muted, 0 is unmuted, -1 means the instrument was out of range + * \sa openmpt_module_ext_interface_interactive::set_instrument_mute_status + */ + int ( * get_instrument_mute_status ) ( openmpt_module_ext * mod_ext, int32_t instrument ); + + /*! Play a note using the specified instrument + * + * \param mod_ext The module handle to work on. + * \param instrument The instrument that should be played, in range [0, openmpt_module_get_num_instruments()[ if openmpt_module_get_num_instruments is not 0, otherwise in [0, openmpt_module_get_num_samples()[ + * \param note The note to play, in rage [0, 119]. 60 is the middle C. + * \param volume The volume at which the note should be triggered, in range [0.0, 1.0] + * \param panning The panning position at which the note should be triggered, in range [-1.0, 1.0], 0.0 is center. + * \return The channel on which the note is played. This can pe be passed to openmpt_module_ext_interface_interactive::stop_note to stop the note. -1 means that no channel could be allocated and the note is not played. + * \sa openmpt_module_ext_interface_interactive::stop_note + */ + int32_t ( * play_note ) ( openmpt_module_ext * mod_ext, int32_t instrument, int32_t note, double volume, double panning ); + + /*! Stop the note playing on the specified channel + * + * \param mod_ext The module handle to work on. + * \param channel The channel on which the note should be stopped. + * \return 1 on success, 0 on failure (channel out of range). + * \sa openmpt_module_ext_interface_interactive::play_note + */ + int ( * stop_note ) ( openmpt_module_ext * mod_ext, int32_t channel ); +} openmpt_module_ext_interface_interactive; + + + +/* add stuff here */ + + + +#ifdef __cplusplus +} +#endif + +/*! + * @} + */ + +#endif /* LIBOPENMPT_EXT_H */ + diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt_ext.hpp b/libs/libopenmpt/inc/libopenmpt/libopenmpt_ext.hpp new file mode 100644 index 000000000..686eaeeed --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt_ext.hpp @@ -0,0 +1,306 @@ +/* + * libopenmpt_ext.hpp + * ------------------ + * Purpose: libopenmpt public c++ interface for libopenmpt extensions + * Notes : + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_EXT_HPP +#define LIBOPENMPT_EXT_HPP + +#include "libopenmpt_config.h" +#include "libopenmpt.hpp" + +/*! + * \page libopenmpt_ext_cpp_overview libopenmpt_ext C++ API + * + * libopenmpt_ext is now included in all builds by default. + * + * \section libopenmpt-ext-cpp-detailed Detailed documentation + * + * \ref libopenmpt_ext_cpp + * + */ + +/*! \defgroup libopenmpt_ext_cpp libopenmpt_ext C++ */ + +/*! \addtogroup libopenmpt_ext_cpp + @{ +*/ + +namespace openmpt { + +class module_ext_impl; + +class LIBOPENMPT_CXX_API module_ext : public module { + +private: + module_ext_impl * ext_impl; +private: + // non-copyable + module_ext( const module_ext & ); + void operator = ( const module_ext & ); +public: + module_ext( std::istream & stream, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + module_ext( const std::vector & data, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + module_ext( const char * data, std::size_t size, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + module_ext( const void * data, std::size_t size, std::ostream & log = std::clog, const std::map< std::string, std::string > & ctls = detail::initial_ctls_map() ); + virtual ~module_ext(); + +public: + + //! Retrieve a libopenmpt extension. + /*! Example: Retrieving the interactive extension to change the tempo of a module: + \code{.cpp} + openmpt::module_ext *mod = new openmpt::module_ext( stream ); + #ifdef LIBOPENMPT_EXT_INTERFACE_INTERACTIVE + openmpt::ext::interactive *interactive = static_cast( self->mod->get_interface( openmpt::ext::interactive_id ) ); + if ( interactive ) { + interactive->set_tempo_factor( 2.0 ); // play module at double speed + } else { + // interface not available + } + #else + // interfae not available + #endif + \endcode + \param interface_id The name of the extension interface to retrieve. + \return The interface object. This may be a nullptr if the extension was not found. + */ + void * get_interface( const std::string & interface_id ); + +}; // class module_ext + +namespace ext { + +#define LIBOPENMPT_DECLARE_EXT_CXX_INTERFACE(name) \ + static const char name ## _id [] = # name ; \ + class name; \ +/**/ + +#define LIBOPENMPT_EXT_CXX_INTERFACE(name) \ + protected: \ + name () {} \ + virtual ~ name () {} \ + public: \ +/**/ + + +#ifndef LIBOPENMPT_EXT_INTERFACE_PATTERN_VIS +#define LIBOPENMPT_EXT_INTERFACE_PATTERN_VIS +#endif + +LIBOPENMPT_DECLARE_EXT_CXX_INTERFACE(pattern_vis) + +class pattern_vis { + + LIBOPENMPT_EXT_CXX_INTERFACE(pattern_vis) + + //! Pattern command type + enum effect_type { + + effect_unknown = 0, + effect_general = 1, + effect_global = 2, + effect_volume = 3, + effect_panning = 4, + effect_pitch = 5 + + }; // enum effect_type + + //! Get pattern command type for pattern highlighting + /*! + \param pattern The pattern whose data should be retrieved. + \param row The row from which the data should be retrieved. + \param channel The channel from which the data should be retrieved. + \return The command type in the effect column at the given pattern position (see openmpt::ext::pattern_vis::effect_type) + \sa openmpt::ext::pattern_vis::get_pattern_row_channel_effect_type + */ + virtual effect_type get_pattern_row_channel_volume_effect_type( std::int32_t pattern, std::int32_t row, std::int32_t channel ) const = 0; + + //! Get pattern command type for pattern highlighting + /*! + \param pattern The pattern whose data should be retrieved. + \param row The row from which the data should be retrieved. + \param channel The channel from which the data should be retrieved. + \return The command type in the volume column at the given pattern position (see openmpt::ext::pattern_vis::effect_type) + \sa openmpt::ext::pattern_vis::get_pattern_row_channel_volume_effect_type + */ + virtual effect_type get_pattern_row_channel_effect_type( std::int32_t pattern, std::int32_t row, std::int32_t channel ) const = 0; + +}; // class pattern_vis + + +#ifndef LIBOPENMPT_EXT_INTERFACE_INTERACTIVE +#define LIBOPENMPT_EXT_INTERFACE_INTERACTIVE +#endif + +LIBOPENMPT_DECLARE_EXT_CXX_INTERFACE(interactive) + +class interactive { + + LIBOPENMPT_EXT_CXX_INTERFACE(interactive) + + //! Set the current ticks per row (speed) + /*! + \param speed The new tick count in range [1, 65535]. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the speed is outside the specified range. + \remarks The tick count may be reset by pattern commands at any time. + \sa openmpt::module::get_current_speed + */ + virtual void set_current_speed( std::int32_t speed ) = 0; + + //! Set the current module tempo + /*! + \param tempo The new tempo in range [32, 512]. The exact meaning of the value depends on the tempo mode used by the module. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the tempo is outside the specified range. + \remarks The tempo may be reset by pattern commands at any time. Use openmpt::ext:interactive::set_tempo_factor to apply a tempo factor that is independent of pattern commands. + \sa openmpt::module::get_current_tempo + */ + virtual void set_current_tempo( std::int32_t tempo ) = 0; + + //! Set the current module tempo factor without affecting playback pitch + /*! + \param factor The new tempo factor in range ]0.0, 4.0] - 1.0 means unmodified tempo. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the factor is outside the specified range. + \remarks Modifying the tempo without applying the same pitch factor using openmpt::ext::interactive::set_pitch_factor may cause rhythmic samples (e.g. drum loops) to go out of sync. + \sa openmpt::ext::interactive::get_tempo_factor + */ + virtual void set_tempo_factor( double factor ) = 0; + + //! Gets the current module tempo factor + /*! + \return The current tempo factor. + \sa openmpt::ext::interactive::set_tempo_factor + */ + virtual double get_tempo_factor( ) const = 0; + + //! Set the current module pitch factor without affecting playback speed + /*! + \param factor The new pitch factor in range ]0.0, 4.0] - 1.0 means unmodified pitch. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the factor is outside the specified range. + \remarks Modifying the pitch without applying the the same tempo factor using openmpt::ext::interactive::set_tempo_factor may cause rhythmic samples (e.g. drum loops) to go out of sync. + \remarks To shift the pich by `n` semitones, the parameter can be calculated as follows: `pow( 2.0, n / 12.0 )` + \sa openmpt::ext::interactive::get_pitch_factor + */ + virtual void set_pitch_factor( double factor ) = 0; + + //! Gets the current module pitch factor + /*! + \return The current pitch factor. + \sa openmpt::ext::interactive::set_pitch_factor + */ + virtual double get_pitch_factor( ) const = 0; + + //! Set the current global volume + /*! + \param volume The new global volume in range [0.0, 1.0] + \throws openmpt::exception Throws an exception derived from openmpt::exception if the volume is outside the specified range. + \remarks The global volume may be reset by pattern commands at any time. Use openmpt::module::set_render_param to apply a global overall volume factor that is independent of pattern commands. + \sa openmpt::ext::interactive::get_global_volume + */ + virtual void set_global_volume( double volume ) = 0; + + //! Get the current global volume + /*! + \return The current global volume in range [0.0, 1.0] + \sa openmpt::ext::interactive::set_global_volume + */ + virtual double get_global_volume( ) const = 0; + + //! Set the current channel volume for a channel + /*! + \param channel The channel whose volume should be set, in range [0, openmpt::module::get_num_channels()[ + \param volume The new channel volume in range [0.0, 1.0] + \throws openmpt::exception Throws an exception derived from openmpt::exception if the channel or volume is outside the specified range. + \remarks The channel volume may be reset by pattern commands at any time. + \sa openmpt::ext::interactive::get_channel_volume + */ + virtual void set_channel_volume( std::int32_t channel, double volume ) = 0; + + //! Get the current channel volume for a channel + /*! + \param channel The channel whose volume should be retrieved, in range [0, openmpt::module::get_num_channels()[ + \return The current channel volume in range [0.0, 1.0] + \throws openmpt::exception Throws an exception derived from openmpt::exception if the channel is outside the specified range. + \sa openmpt::ext::interactive::set_channel_volume + */ + virtual double get_channel_volume( std::int32_t channel ) const = 0; + + //! Set the current mute status for a channel + /*! + \param channel The channel whose mute status should be set, in range [0, openmpt::module::get_num_channels()[ + \param mute The new mute status. true is muted, false is unmuted. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the channel is outside the specified range. + \sa openmpt::ext::interactive::get_channel_mute_status + */ + virtual void set_channel_mute_status( std::int32_t channel, bool mute ) = 0; + + //! Get the current mute status for a channel + /*! + \param channel The channel whose mute status should be retrieved, in range [0, openmpt::module::get_num_channels()[ + \return The current channel mute status. true is muted, false is unmuted. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the channel is outside the specified range. + \sa openmpt::ext::interactive::set_channel_mute_status + */ + virtual bool get_channel_mute_status( std::int32_t channel ) const = 0; + + //! Set the current mute status for an instrument + /*! + \param instrument The instrument whose mute status should be set, in range [0, openmpt::module::get_num_instruments()[ if openmpt::module::get_num_instruments is not 0, otherwise in [0, openmpt::module::get_num_samples()[ + \param mute The new mute status. true is muted, false is unmuted. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the instrument is outside the specified range. + \sa openmpt::ext::interactive::get_instrument_mute_status + */ + virtual void set_instrument_mute_status( std::int32_t instrument, bool mute ) = 0; + + //! Get the current mute status for an instrument + /*! + \param instrument The instrument whose mute status should be retrieved, in range [0, openmpt::module::get_num_instruments()[ if openmpt::module::get_num_instruments is not 0, otherwise in [0, openmpt::module::get_num_samples()[ + \return The current instrument mute status. true is muted, false is unmuted. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the instrument is outside the specified range. + \sa openmpt::ext::interactive::set_instrument_mute_status + */ + virtual bool get_instrument_mute_status( std::int32_t instrument ) const = 0; + + //! Play a note using the specified instrument + /*! + \param instrument The instrument that should be played, in range [0, openmpt::module::get_num_instruments()[ if openmpt::module::get_num_instruments is not 0, otherwise in [0, openmpt::module::get_num_samples()[ + \param note The note to play, in rage [0, 119]. 60 is the middle C. + \param volume The volume at which the note should be triggered, in range [0.0, 1.0] + \param panning The panning position at which the note should be triggered, in range [-1.0, 1.0], 0.0 is center. + \return The channel on which the note is played. This can pe be passed to openmpt::ext::interactive::stop_note to stop the note. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the instrument or note is outside the specified range. + \sa openmpt::ext::interactive::stop_note + */ + virtual std::int32_t play_note( std::int32_t instrument, std::int32_t note, double volume, double panning ) = 0; + + //! Stop the note playing on the specified channel + /*! + \param channel The channel on which the note should be stopped. + \throws openmpt::exception Throws an exception derived from openmpt::exception if the channel index is invalid. + \sa openmpt::ext::interactive::play_note + */ + virtual void stop_note( std::int32_t channel ) = 0; + +}; // class interactive + + +/* add stuff here */ + + + +#undef LIBOPENMPT_DECLARE_EXT_CXX_INTERFACE +#undef LIBOPENMPT_EXT_CXX_INTERFACE + +} // namespace ext + +} // namespace openmpt + +/*! + @} +*/ + +#endif // LIBOPENMPT_EXT_HPP diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_buffer.h b/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_buffer.h new file mode 100644 index 000000000..575049e4d --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_buffer.h @@ -0,0 +1,198 @@ +/* + * libopenmpt_stream_callbacks_buffer.h + * ------------------------------------ + * Purpose: libopenmpt public c interface + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_STREAM_CALLBACKS_BUFFER_H +#define LIBOPENMPT_STREAM_CALLBACKS_BUFFER_H + +#include "libopenmpt.h" + +/* The use of this header requires: + +#include +#if defined( LIBOPENMPT_STREAM_CALLBACKS_BUFFER ) +#include +#else +#error "libopenmpt too old." +#endif + +*/ + +#include +#include +#include + +/*! \addtogroup libopenmpt_c + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct openmpt_stream_buffer { + const void * file_data; /* or prefix data IFF prefix_size < file_size */ + int64_t file_size; + int64_t file_pos; + int64_t prefix_size; + int overflow; +} openmpt_stream_buffer; + +static size_t openmpt_stream_buffer_read_func( void * stream, void * dst, size_t bytes ) { + openmpt_stream_buffer * s = (openmpt_stream_buffer*)stream; + int64_t offset = 0; + int64_t begpos = 0; + int64_t endpos = 0; + size_t valid_bytes = 0; + if ( !s ) { + return 0; + } + offset = bytes; + begpos = s->file_pos; + endpos = s->file_pos; + valid_bytes = 0; + endpos = (uint64_t)endpos + (uint64_t)offset; + if ( ( offset > 0 ) && !( (uint64_t)endpos > (uint64_t)begpos ) ) { + /* integer wrapped */ + return 0; + } + if ( bytes == 0 ) { + return 0; + } + if ( begpos >= s->file_size ) { + return 0; + } + if ( endpos > s->file_size ) { + /* clip to eof */ + bytes = bytes - (size_t)( endpos - s->file_size ); + endpos = endpos - ( endpos - s->file_size ); + } + memset( dst, 0, bytes ); + if ( begpos >= s->prefix_size ) { + s->overflow = 1; + valid_bytes = 0; + } else if ( endpos > s->prefix_size ) { + s->overflow = 1; + valid_bytes = bytes - (size_t)( endpos - s->prefix_size ); + } else { + valid_bytes = bytes; + } + memcpy( dst, (const char*)s->file_data + s->file_pos, valid_bytes ); + s->file_pos = s->file_pos + bytes; + return bytes; +} + +static int openmpt_stream_buffer_seek_func( void * stream, int64_t offset, int whence ) { + openmpt_stream_buffer * s = (openmpt_stream_buffer*)stream; + int result = -1; + if ( !s ) { + return -1; + } + switch ( whence ) { + case OPENMPT_STREAM_SEEK_SET: + if ( offset < 0 ) { + return -1; + } + if ( offset > s->file_size ) { + return -1; + } + s->file_pos = offset; + result = 0; + break; + case OPENMPT_STREAM_SEEK_CUR: + do { + int64_t oldpos = s->file_pos; + int64_t pos = s->file_pos; + pos = (uint64_t)pos + (uint64_t)offset; + if ( ( offset > 0 ) && !( (uint64_t)pos > (uint64_t)oldpos ) ) { + /* integer wrapped */ + return -1; + } + if ( ( offset < 0 ) && !( (uint64_t)pos < (uint64_t)oldpos ) ) { + /* integer wrapped */ + return -1; + } + s->file_pos = pos; + } while(0); + result = 0; + break; + case OPENMPT_STREAM_SEEK_END: + if ( offset > 0 ) { + return -1; + } + do { + int64_t oldpos = s->file_pos; + int64_t pos = s->file_pos; + pos = s->file_size; + pos = (uint64_t)pos + (uint64_t)offset; + if ( ( offset < 0 ) && !( (uint64_t)pos < (uint64_t)oldpos ) ) { + /* integer wrapped */ + return -1; + } + s->file_pos = pos; + } while(0); + result = 0; + break; + } + return result; +} + +static int64_t openmpt_stream_buffer_tell_func( void * stream ) { + openmpt_stream_buffer * s = (openmpt_stream_buffer*)stream; + if ( !s ) { + return -1; + } + return s->file_pos; +} + +static void openmpt_stream_buffer_init( openmpt_stream_buffer * buffer, const void * file_data, int64_t file_size ) { + memset( buffer, 0, sizeof( openmpt_stream_buffer ) ); + buffer->file_data = file_data; + buffer->file_size = file_size; + buffer->file_pos = 0; + buffer->prefix_size = file_size; + buffer->overflow = 0; +} + +#define openmpt_stream_buffer_init_prefix_only( buffer_, prefix_data_, prefix_size_, file_size_ ) do { \ + openmpt_stream_buffer_init( (buffer_), (prefix_data_), (file_size_) ); \ + (buffer_)->prefix_size = (prefix_size_); \ +} while(0) + +#define openmpt_stream_buffer_overflowed( buffer_ ) ( (buffer_)->overflow ) + +/*! \brief Provide openmpt_stream_callbacks for in-memoy buffers + * + * Fills openmpt_stream_callbacks suitable for passing an in-memory buffer as a stream parameter to functions doing file input/output. + * + * \remarks The stream argument must be passed as `(void*)(openmpt_stream_buffer*)stream_buffer`. + * \sa \ref libopenmpt_c_fileio + * \sa openmpt_stream_callbacks + * \sa openmpt_could_open_probability2 + * \sa openmpt_probe_file_header_from_stream + * \sa openmpt_module_create2 + */ +static openmpt_stream_callbacks openmpt_stream_get_buffer_callbacks(void) { + openmpt_stream_callbacks retval; + memset( &retval, 0, sizeof( openmpt_stream_callbacks ) ); + retval.read = openmpt_stream_buffer_read_func; + retval.seek = openmpt_stream_buffer_seek_func; + retval.tell = openmpt_stream_buffer_tell_func; + return retval; +} + +#ifdef __cplusplus +} +#endif + +/*! + * @} + */ + +#endif /* LIBOPENMPT_STREAM_CALLBACKS_BUFFER_H */ + diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_fd.h b/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_fd.h new file mode 100644 index 000000000..46b39f129 --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_fd.h @@ -0,0 +1,101 @@ +/* + * libopenmpt_stream_callbacks_fd.h + * -------------------------------- + * Purpose: libopenmpt public c interface + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_STREAM_CALLBACKS_FD_H +#define LIBOPENMPT_STREAM_CALLBACKS_FD_H + +#include "libopenmpt.h" + +#ifdef _MSC_VER +#include +#endif +#include +#include +#include +#include +#ifndef _MSC_VER +#include +#endif + +/*! \addtogroup libopenmpt_c + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* This stuff has to be in a header file because of possibly different MSVC CRTs which cause problems for fd crossing CRT boundaries. */ + +static size_t openmpt_stream_fd_read_func( void * stream, void * dst, size_t bytes ) { + int fd = 0; + #if defined(_MSC_VER) + size_t retval = 0; + int to_read = 0; + int ret_read = 0; + #else + ssize_t retval = 0; + #endif + fd = (int)(uintptr_t)stream; + if ( fd < 0 ) { + return 0; + } + #if defined(_MSC_VER) + retval = 0; + while ( bytes > 0 ) { + to_read = 0; + if ( bytes < (size_t)INT_MAX ) { + to_read = (int)bytes; + } else { + to_read = INT_MAX; + } + ret_read = _read( fd, dst, to_read ); + if ( ret_read <= 0 ) { + return retval; + } + bytes -= ret_read; + retval += ret_read; + } + #else + retval = read( fd, dst, bytes ); + #endif + if ( retval <= 0 ) { + return 0; + } + return retval; +} + +/*! \brief Provide openmpt_stream_callbacks for standard POSIX file descriptors + * + * Fills openmpt_stream_callbacks suitable for passing a POSIX filer descriptor as a stream parameter to functions doing file input/output. + * + * \remarks The stream argument must be passed as `(void*)(uintptr_t)(int)fd`. + * \sa \ref libopenmpt_c_fileio + * \sa openmpt_stream_callbacks + * \sa openmpt_could_open_probability2 + * \sa openmpt_probe_file_header_from_stream + * \sa openmpt_module_create2 + */ +static openmpt_stream_callbacks openmpt_stream_get_fd_callbacks(void) { + openmpt_stream_callbacks retval; + memset( &retval, 0, sizeof( openmpt_stream_callbacks ) ); + retval.read = openmpt_stream_fd_read_func; + return retval; +} + +#ifdef __cplusplus +} +#endif + +/*! + * @} + */ + +#endif /* LIBOPENMPT_STREAM_CALLBACKS_FD_H */ + diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_file.h b/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_file.h new file mode 100644 index 000000000..643049153 --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt_stream_callbacks_file.h @@ -0,0 +1,132 @@ +/* + * libopenmpt_stream_callbacks_file.h + * ---------------------------------- + * Purpose: libopenmpt public c interface + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_STREAM_CALLBACKS_FILE_H +#define LIBOPENMPT_STREAM_CALLBACKS_FILE_H + +#include "libopenmpt.h" + +#include +#include +#include +#include +#ifdef _MSC_VER +#include /* off_t */ +#endif + +/*! \addtogroup libopenmpt_c + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* This stuff has to be in a header file because of possibly different MSVC CRTs which cause problems for FILE * crossing CRT boundaries. */ + +static size_t openmpt_stream_file_read_func( void * stream, void * dst, size_t bytes ) { + FILE * f = 0; + size_t retval = 0; + f = (FILE*)stream; + if ( !f ) { + return 0; + } + retval = fread( dst, 1, bytes, f ); + if ( retval <= 0 ) { + return 0; + } + return retval; +} + +static int openmpt_stream_file_seek_func( void * stream, int64_t offset, int whence ) { + FILE * f = 0; + int fwhence = 0; + f = (FILE*)stream; + if ( !f ) { + return -1; + } + switch ( whence ) { +#if defined(SEEK_SET) + case OPENMPT_STREAM_SEEK_SET: + fwhence = SEEK_SET; + break; +#endif +#if defined(SEEK_CUR) + case OPENMPT_STREAM_SEEK_CUR: + fwhence = SEEK_CUR; + break; +#endif +#if defined(SEEK_END) + case OPENMPT_STREAM_SEEK_END: + fwhence = SEEK_END; + break; +#endif + default: + return -1; + break; + } + #if defined(_MSC_VER) + return _fseeki64( f, offset, fwhence ) ? -1 : 0; + #elif defined(_POSIX_SOURCE) && (_POSIX_SOURCE == 1) + return fseeko( f, offset, fwhence ) ? -1 : 0; + #else + return fseek( f, offset, fwhence ) ? -1 : 0; + #endif +} + +static int64_t openmpt_stream_file_tell_func( void * stream ) { + FILE * f = 0; + int64_t retval = 0; + f = (FILE*)stream; + if ( !f ) { + return -1; + } + #if defined(_MSC_VER) + retval = _ftelli64( f ); + #elif defined(_POSIX_SOURCE) && (_POSIX_SOURCE == 1) + retval = ftello( f ); + #else + retval = ftell( f ); + #endif + if ( retval < 0 ) { + return -1; + } + return retval; +} + +/*! \brief Provide openmpt_stream_callbacks for standard C FILE objects + * + * Fills openmpt_stream_callbacks suitable for passing a standard C FILE object as a stream parameter to functions doing file input/output. + * + * \remarks The stream argument must be passed as `(void*)(FILE*)file`. + * \sa \ref libopenmpt_c_fileio + * \sa openmpt_stream_callbacks + * \sa openmpt_could_open_probability2 + * \sa openmpt_probe_file_header_from_stream + * \sa openmpt_module_create2 + */ +static openmpt_stream_callbacks openmpt_stream_get_file_callbacks(void) { + openmpt_stream_callbacks retval; + memset( &retval, 0, sizeof( openmpt_stream_callbacks ) ); + retval.read = openmpt_stream_file_read_func; + retval.seek = openmpt_stream_file_seek_func; + retval.tell = openmpt_stream_file_tell_func; + return retval; +} + +#ifdef __cplusplus +} +#endif + +/*! + * @} + */ + +#endif /* LIBOPENMPT_STREAM_CALLBACKS_FILE_H */ + diff --git a/libs/libopenmpt/inc/libopenmpt/libopenmpt_version.h b/libs/libopenmpt/inc/libopenmpt/libopenmpt_version.h new file mode 100644 index 000000000..4bb90278c --- /dev/null +++ b/libs/libopenmpt/inc/libopenmpt/libopenmpt_version.h @@ -0,0 +1,75 @@ +/* + * libopenmpt_version.h + * -------------------- + * Purpose: libopenmpt public interface version + * Notes : (currently none) + * Authors: OpenMPT Devs + * The OpenMPT source code is released under the BSD license. Read LICENSE for more details. + */ + +#ifndef LIBOPENMPT_VERSION_H +#define LIBOPENMPT_VERSION_H + +/*! \addtogroup libopenmpt + @{ +*/ + +/*! \brief libopenmpt major version number */ +#define OPENMPT_API_VERSION_MAJOR 0 +/*! \brief libopenmpt minor version number */ +#define OPENMPT_API_VERSION_MINOR 4 +/*! \brief libopenmpt patch version number */ +#define OPENMPT_API_VERSION_PATCH 7 +/*! \brief libopenmpt pre-release tag */ +#define OPENMPT_API_VERSION_PREREL "" +/*! \brief libopenmpt pre-release flag */ +#define OPENMPT_API_VERSION_IS_PREREL 0 + +/*! \brief libopenmpt version number as a single integer value + * \since 0.3 + * \remarks Use the following shim if you need to support earlier libopenmpt versions: + * \code + * #include + * #if !defined(OPENMPT_API_VERSION_MAKE) + * #define OPENMPT_API_VERSION_MAKE(major, minor, patch) (((major)<<24)|((minor)<<16)|((patch)<<0)) + * #endif + * \endcode + */ +#define OPENMPT_API_VERSION_MAKE(major, minor, patch) (((major)<<24)|((minor)<<16)|((patch)<<0)) + +/*! \brief libopenmpt API version number */ +#define OPENMPT_API_VERSION OPENMPT_API_VERSION_MAKE(OPENMPT_API_VERSION_MAJOR, OPENMPT_API_VERSION_MINOR, OPENMPT_API_VERSION_PATCH) + +/*! \brief Check whether the libopenmpt API is at least the provided version + * \since 0.3 + * \remarks Use the following shim if you need to support earlier libopenmpt versions: + * \code + * #include + * #if !defined(OPENMPT_API_VERSION_AT_LEAST) + * #define OPENMPT_API_VERSION_AT_LEAST(major, minor, patch) (OPENMPT_API_VERSION >= OPENMPT_API_VERSION_MAKE((major), (minor), (patch))) + * #endif + * \endcode + */ +#define OPENMPT_API_VERSION_AT_LEAST(major, minor, patch) (OPENMPT_API_VERSION >= OPENMPT_API_VERSION_MAKE((major), (minor), (patch))) + +/*! \brief Check whether the libopenmpt API is before the provided version + * \since 0.3 + * \remarks Use the following shim if you need to support earlier libopenmpt versions: + * \code + * #include + * #if !defined(OPENMPT_API_VERSION_BEFORE) + * #define OPENMPT_API_VERSION_BEFORE(major, minor, patch) (OPENMPT_API_VERSION < OPENMPT_API_VERSION_MAKE((major), (minor), (patch))) + * #endif + * \endcode + */ +#define OPENMPT_API_VERSION_BEFORE(major, minor, patch) (OPENMPT_API_VERSION < OPENMPT_API_VERSION_MAKE((major), (minor), (patch))) + +#define OPENMPT_API_VERSION_HELPER_STRINGIZE(x) #x +#define OPENMPT_API_VERSION_STRINGIZE(x) OPENMPT_API_VERSION_HELPER_STRINGIZE(x) +#define OPENMPT_API_VERSION_STRING OPENMPT_API_VERSION_STRINGIZE(OPENMPT_API_VERSION_MAJOR) "." OPENMPT_API_VERSION_STRINGIZE(OPENMPT_API_VERSION_MINOR) "." OPENMPT_API_VERSION_STRINGIZE(OPENMPT_API_VERSION_PATCH) OPENMPT_API_VERSION_PREREL + +/*! + @} +*/ + +#endif /* LIBOPENMPT_VERSION_H */ diff --git a/libs/libopenmpt/lib/x86/libopenmpt.lib b/libs/libopenmpt/lib/x86/libopenmpt.lib new file mode 100644 index 000000000..c81c4c4ed Binary files /dev/null and b/libs/libopenmpt/lib/x86/libopenmpt.lib differ diff --git a/libs/libopenmpt/lib/x86/mingw/libopenmpt.dll.a b/libs/libopenmpt/lib/x86/mingw/libopenmpt.dll.a new file mode 100644 index 000000000..1d7637253 Binary files /dev/null and b/libs/libopenmpt/lib/x86/mingw/libopenmpt.dll.a differ diff --git a/libs/libopenmpt/lib/x86_64/libopenmpt.lib b/libs/libopenmpt/lib/x86_64/libopenmpt.lib new file mode 100644 index 000000000..216d93b45 Binary files /dev/null and b/libs/libopenmpt/lib/x86_64/libopenmpt.lib differ diff --git a/libs/libopenmpt/lib/x86_64/mingw/libopenmpt.dll.a b/libs/libopenmpt/lib/x86_64/mingw/libopenmpt.dll.a new file mode 100644 index 000000000..c6eda119f Binary files /dev/null and b/libs/libopenmpt/lib/x86_64/mingw/libopenmpt.dll.a differ diff --git a/libs/libpng-src/ANNOUNCE b/libs/libpng-src/ANNOUNCE index 02a24bd6b..ecf9c7043 100644 --- a/libs/libpng-src/ANNOUNCE +++ b/libs/libpng-src/ANNOUNCE @@ -1,65 +1,47 @@ +libpng 1.6.37 - April 14, 2019 +============================== -Libpng 1.2.46 - July 9, 2011 +This is a public release of libpng, intended for use in production code. -This is a public release of libpng, intended for use in production codes. -Files available for download: +Files available for download +---------------------------- -Source files with LF line endings (for Unix/Linux) and with a -"configure" script +Source files with LF line endings (for Unix/Linux): - libpng-1.2.46.tar.xz (LZMA-compressed, recommended) - libpng-1.2.46.tar.gz - libpng-1.2.46.tar.bz2 + * libpng-1.6.37.tar.xz (LZMA-compressed, recommended) + * libpng-1.6.37.tar.gz -Source files with LF line endings (for Unix/Linux) without the -"configure" script +Source files with CRLF line endings (for Windows): - libpng-1.2.46-no-config.tar.xz (LZMA-compressed, recommended) - libpng-1.2.46-no-config.tar.gz - libpng-1.2.46-no-config.tar.bz2 - -Source files with CRLF line endings (for Windows), without the -"configure" script - - lpng1246.zip - lpng1246.7z - lpng1246.tar.bz2 - -Project files - - libpng-1.2.46-project-netware.zip - libpng-1.2.46-project-wince.zip + * lp1637.7z (LZMA-compressed, recommended) + * lp1637.zip Other information: - libpng-1.2.46-README.txt - libpng-1.2.46-KNOWNBUGS.txt - libpng-1.2.46-LICENSE.txt - libpng-1.2.46-Y2K-compliance.txt - libpng-1.2.46-[previous version]-diff.txt + * README.md + * LICENSE.md + * AUTHORS.md + * TRADEMARK.md -Changes since the last public release (1.2.43): -version 1.2.45 [July 9, 2011] +Changes since the previous public release (version 1.6.36) +---------------------------------------------------------- - Fixed uninitialized memory read in png_format_buffer() (Bug - report by Frank Busse, related to CVE-2004-0421). - Pass "" instead of '\0' to png_default_error() in png_err(). This mistake - was introduced in libpng-1.2.20beta01. - Check for up->location !PNG_AFTER_IDAT when writing unknown chunks - before IDAT. - Ported bugfix in pngrtran.c from 1.5.3: when expanding a paletted image, - always expand to RGBA if transparency is present. - Check for integer overflow in png_set_rgb_to_gray(). - Check for sCAL chunk too short. - Added CMakeLists.txt, projects/xcode, and pnggccrd.c to EXTRA_DIST in - Makefile.am and Makefile.in - Udated copyright year to 2011. + * Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free. + * Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette. + * Fixed a memory leak in pngtest.c. + * Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in + contrib/pngminus; refactor. + * Changed the license of contrib/pngminus to MIT; refresh makefile and docs. + (Contributed by Willem van Schaik) + * Fixed a typo in the libpng license v2. + (Contributed by Miguel Ojeda) + * Added makefiles for AddressSanitizer-enabled builds. + * Cleaned up various makefiles. -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net. +Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) or to glennrp at users.sourceforge.net - -Glenn R-P +to subscribe. diff --git a/libs/libpng-src/AUTHORS b/libs/libpng-src/AUTHORS new file mode 100644 index 000000000..79a3d1036 --- /dev/null +++ b/libs/libpng-src/AUTHORS @@ -0,0 +1,45 @@ +PNG REFERENCE LIBRARY AUTHORS +============================= + +This is the list of PNG Reference Library ("libpng") Contributing +Authors, for copyright and licensing purposes. + + * Andreas Dilger + * Cosmin Truta + * Dave Martindale + * Eric S. Raymond + * Gilles Vollant + * Glenn Randers-Pehrson + * Greg Roelofs + * Guy Eric Schalnat + * James Yu + * John Bowler + * Kevin Bracey + * Magnus Holmgren + * Mandar Sahastrabuddhe + * Mans Rullgard + * Matt Sarett + * Mike Klein + * Paul Schmidt + * Sam Bushell + * Samuel Williams + * Simon-Pierre Cadieux + * Tim Wegner + * Tom Lane + * Tom Tanner + * Vadim Barkov + * Willem van Schaik + * Zhijie Liang + * Arm Holdings + - Richard Townsend + * Google Inc. + - Matt Sarett + - Mike Klein + +The build projects, the build scripts, the test scripts, and other +files in the "projects", "scripts" and "tests" directories, have other +copyright owners, but are released under the libpng license. + +Some files in the "contrib" directory, and some tools-generated files +that are distributed with libpng, have other copyright owners, and are +released under other open source licenses. diff --git a/libs/libpng-src/CHANGES b/libs/libpng-src/CHANGES index 1b7a30ee4..f0b0a9342 100644 --- a/libs/libpng-src/CHANGES +++ b/libs/libpng-src/CHANGES @@ -1,11 +1,13 @@ -/* CHANGES - changes for libpng -version 0.2 +version 0.1 [March 29, 1995] + initial work-in-progress release + +version 0.2 [April 1, 1995] added reader into png.h fixed small problems in stub file -version 0.3 +version 0.3 [April 8, 1995] added pull reader split up pngwrite.c to several files added pnglib.txt @@ -16,7 +18,7 @@ version 0.3 added K&R support added check for 64 KB blocks for 16 bit machines -version 0.4 +version 0.4 [April 26, 1995] cleaned up code and commented code simplified time handling into png_time created png_color_16 and png_color_8 to handle color needs @@ -27,28 +29,29 @@ version 0.4 cleaned up zTXt reader and writer (using zlib's Reset functions) split transformations into pngrtran.c and pngwtran.c -version 0.5 +version 0.5 [April 30, 1995] interfaced with zlib 0.8 fixed many reading and writing bugs saved using 3 spaces instead of tabs -version 0.6 +version 0.6 [May 1, 1995] + first beta release added png_large_malloc() and png_large_free() added png_size_t cleaned up some compiler warnings added png_start_read_image() -version 0.7 +version 0.7 [June 24, 1995] cleaned up lots of bugs finished dithering and other stuff added test program changed name from pnglib to libpng -version 0.71 [June, 1995] +version 0.71 [June 26, 1995] changed pngtest.png for zlib 0.93 fixed error in libpng.txt and example.c -version 0.8 +version 0.8 [August 20, 1995] cleaned up some bugs added png_set_filler() split up pngstub.c into pngmem.c, pngio.c, and pngerror.c @@ -62,191 +65,199 @@ version 0.8 changed external functions passing floats to doubles (k&r problems?) put all the configurable stuff in pngconf.h enabled png_set_shift to work with paletted images on read - added png_read_update_info() - updates info structure with - transformations + added png_read_update_info() - updates info structure with transformations -version 0.81 [August, 1995] +Version 0.81 [August, 1995] incorporated Tim Wegner's medium model code (thanks, Tim) -version 0.82 [September, 1995] +Version 0.82 [September, 1995] [unspecified changes] -version 0.85 [December, 1995] +Version 0.85 [December, 1995] added more medium model code (almost everything's a far) added i/o, error, and memory callback functions - fixed some bugs (16 bit, 4 bit interlaced, etc.) + fixed some bugs (16-bit, 4-bit interlaced, etc.) added first run progressive reader (barely tested) -version 0.86 [January, 1996] +Version 0.86 [January, 1996] fixed bugs improved documentation -version 0.87 [January, 1996] +Version 0.87 [January, 1996] fixed medium model bugs fixed other bugs introduced in 0.85 and 0.86 added some minor documentation -version 0.88 [January, 1996] +Version 0.88 [January, 1996] fixed progressive bugs replaced tabs with spaces cleaned up documentation added callbacks for read/write and warning/error functions -version 0.89 [July, 1996] - added new initialization API to make libpng work better with shared libs - we now have png_create_read_struct(), png_create_write_struct(), - png_create_info_struct(), png_destroy_read_struct(), and - png_destroy_write_struct() instead of the separate calls to - malloc and png_read_init(), png_info_init(), and png_write_init() - changed warning/error callback functions to fix bug - this means you - should use the new initialization API if you were using the old - png_set_message_fn() calls, and that the old API no longer exists - so that people are aware that they need to change their code - changed filter selection API to allow selection of multiple filters - since it didn't work in previous versions of libpng anyways - optimized filter selection code - fixed png_set_background() to allow using an arbitrary RGB color for - paletted images - fixed gamma and background correction for paletted images, so - png_correct_palette is not needed unless you are correcting an - external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED - in pngconf.h) - if nobody uses this, it may disappear in the future. - fixed bug with Borland 64K memory allocation (Alexander Lehmann) - fixed bug in interlace handling (Smarasderagd, I think) - added more error checking for writing and image to reduce invalid files - separated read and write functions so that they won't both be linked - into a binary when only reading or writing functionality is used - new pngtest image also has interlacing and zTXt - updated documentation to reflect new API +Version 0.89 [June 5, 1996] + Added new initialization API to make libpng work better with shared libs + we now have png_create_read_struct(), png_create_write_struct(), + png_create_info_struct(), png_destroy_read_struct(), and + png_destroy_write_struct() instead of the separate calls to + malloc and png_read_init(), png_info_init(), and png_write_init() + Changed warning/error callback functions to fix bug - this means you + should use the new initialization API if you were using the old + png_set_message_fn() calls, and that the old API no longer exists + so that people are aware that they need to change their code + Changed filter selection API to allow selection of multiple filters + since it didn't work in previous versions of libpng anyways + Optimized filter selection code + Fixed png_set_background() to allow using an arbitrary RGB color for + paletted images + Fixed gamma and background correction for paletted images, so + png_correct_palette is not needed unless you are correcting an + external palette (you will need to #define PNG_CORRECT_PALETTE_SUPPORTED + in pngconf.h) - if nobody uses this, it may disappear in the future. + Fixed bug with Borland 64K memory allocation (Alexander Lehmann) + Fixed bug in interlace handling (Smarasderagd, I think) + Added more error checking for writing and image to reduce invalid files + Separated read and write functions so that they won't both be linked + into a binary when only reading or writing functionality is used + New pngtest image also has interlacing and zTXt + Updated documentation to reflect new API -version 0.90 [January, 1997] - made CRC errors/warnings on critical and ancillary chunks configurable +Version 0.89c [June 17, 1996] + Bug fixes. + +Version 0.90 [January, 1997] + Made CRC errors/warnings on critical and ancillary chunks configurable libpng will use the zlib CRC routines by (compile-time) default - changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) - added external C++ wrapper statements to png.h (Gilles Dauphin) - allow PNG file to be read when some or all of file signature has already - been read from the beginning of the stream. ****This affects the size - of info_struct and invalidates all programs that use a shared libpng**** - fixed png_filler() declarations - fixed? background color conversions - fixed order of error function pointers to match documentation - current chunk name is now available in png_struct to reduce the number - of nearly identical error messages (will simplify multi-lingual - support when available) - try to get ready for unknown-chunk callback functions: - - previously read critical chunks are flagged, so the chunk handling - routines can determine if the chunk is in the right place - - all chunk handling routines have the same prototypes, so we will - be able to handle all chunks via a callback mechanism - try to fix Linux "setjmp" buffer size problems - removed png_large_malloc, png_large_free, and png_realloc functions. + Changed DOS small/medium model memory support - needs zlib 1.04 (Tim Wegner) + Added external C++ wrapper statements to png.h (Gilles Dauphin) + Allow PNG file to be read when some or all of file signature has already + been read from the beginning of the stream. ****This affects the size + of info_struct and invalidates all programs that use a shared libpng**** + Fixed png_filler() declarations + Fixed? background color conversions + Fixed order of error function pointers to match documentation + Current chunk name is now available in png_struct to reduce the number + of nearly identical error messages (will simplify multi-lingual + support when available) + Try to get ready for unknown-chunk callback functions: + - previously read critical chunks are flagged, so the chunk handling + routines can determine if the chunk is in the right place + - all chunk handling routines have the same prototypes, so we will + be able to handle all chunks via a callback mechanism + Try to fix Linux "setjmp" buffer size problems + Removed png_large_malloc, png_large_free, and png_realloc functions. -version 0.95 [March, 1997] - fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never - fixed bug in PNG file signature compares when start != 0 - changed parameter type of png_set_filler(...filler...) from png_byte - to png_uint_32 - added test for MACOS to ensure that both math.h and fp.h are not #included - added macros for libpng to be compiled as a Windows DLL (Andreas Kupries) - added "packswap" transformation, which changes the endianness of - packed-pixel bytes (Kevin Bracey) - added "strip_alpha" transformation, which removes the alpha channel of - input images without using it (not necessarily a good idea) - added "swap_alpha" transformation, which puts the alpha channel in front - of the color bytes instead of after - removed all implicit variable tests which assume NULL == 0 (I think) - changed several variables to "png_size_t" to show 16/32-bit limitations - added new pCAL chunk read/write support - added experimental filter selection weighting (Greg Roelofs) - removed old png_set_rgbx() and png_set_xrgb() functions that have been - obsolete for about 2 years now (use png_set_filler() instead) - added macros to read 16- and 32-bit ints directly from buffer, to be - used only on those systems that support it (namely PowerPC and 680x0) - With some testing, this may become the default for MACOS/PPC systems. - only calculate CRC on data if we are going to use it - added macros for zTXt compression type PNG_zTXt_COMPRESSION_??? - added macros for simple libpng debugging output selectable at compile time - removed PNG_READ_END_MODE in progressive reader (Smarasderagd) - more description of info_struct in libpng.txt and png.h - more instructions in example.c - more chunk types tested in pngtest.c - renamed pngrcb.c to pngset.c, and all png_read_ functions to be - png_set_. We now have corresponding png_get_ - functions in pngget.c to get information in info_ptr. This isolates - the application from the internal organization of png_info_struct - (good for shared library implementations). +Version 0.95 [March, 1997] + Fixed bug in pngwutil.c allocating "up_row" twice and "avg_row" never + Fixed bug in PNG file signature compares when start != 0 + Changed parameter type of png_set_filler(...filler...) from png_byte + to png_uint_32 + Added test for MACOS to ensure that both math.h and fp.h are not #included + Added macros for libpng to be compiled as a Windows DLL (Andreas Kupries) + Added "packswap" transformation, which changes the endianness of + packed-pixel bytes (Kevin Bracey) + Added "strip_alpha" transformation, which removes the alpha channel of + input images without using it (not necessarily a good idea) + Added "swap_alpha" transformation, which puts the alpha channel in front + of the color bytes instead of after + Removed all implicit variable tests which assume NULL == 0 (I think) + Changed several variables to "png_size_t" to show 16/32-bit limitations + Added new pCAL chunk read/write support + Added experimental filter selection weighting (Greg Roelofs) + Removed old png_set_rgbx() and png_set_xrgb() functions that have been + obsolete for about 2 years now (use png_set_filler() instead) + Added macros to read 16- and 32-bit ints directly from buffer, to be + used only on those systems that support it (namely PowerPC and 680x0) + With some testing, this may become the default for MACOS/PPC systems. + Only calculate CRC on data if we are going to use it + Added macros for zTXt compression type PNG_zTXt_COMPRESSION_??? + Added macros for simple libpng debugging output selectable at compile time + Removed PNG_READ_END_MODE in progressive reader (Smarasderagd) + More description of info_struct in libpng.txt and png.h + More instructions in example.c + More chunk types tested in pngtest.c + Renamed pngrcb.c to pngset.c, and all png_read_ functions to be + png_set_. We now have corresponding png_get_ + functions in pngget.c to get information in info_ptr. This isolates + the application from the internal organization of png_info_struct + (good for shared library implementations). -version 0.96 [May, 1997] - fixed serious bug with < 8bpp images introduced in 0.95 - fixed 256-color transparency bug (Greg Roelofs) - fixed up documentation (Greg Roelofs, Laszlo Nyul) - fixed "error" in pngconf.h for Linux setjmp() behaviour - fixed DOS medium model support (Tim Wegner) - fixed png_check_keyword() for case with error in static string text - added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) - added typecasts to quiet compiler errors - added more debugging info +Version 0.96 [May, 1997] + Fixed serious bug with < 8bpp images introduced in 0.95 + Fixed 256-color transparency bug (Greg Roelofs) + Fixed up documentation (Greg Roelofs, Laszlo Nyul) + Fixed "error" in pngconf.h for Linux setjmp() behavior + Fixed DOS medium model support (Tim Wegner) + Fixed png_check_keyword() for case with error in static string text + Added read of CRC after IEND chunk for embedded PNGs (Laszlo Nyul) + Added typecasts to quiet compiler errors + Added more debugging info -version 0.97 [January, 1998] - removed PNG_USE_OWN_CRC capability - relocated png_set_crc_action from pngrutil.c to pngrtran.c - fixed typecasts of "new_key", etc. (Andreas Dilger) - added RFC 1152 [sic] date support - fixed bug in gamma handling of 4-bit grayscale - added 2-bit grayscale gamma handling (Glenn R-P) - added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) - minor corrections in libpng.txt - added simple sRGB support (Glenn R-P) - easier conditional compiling, e.g. define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; - all configurable options can be selected from command-line instead - of having to edit pngconf.h (Glenn R-P) - fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) - added more conditions for png_do_background, to avoid changing - black pixels to background when a background is supplied and - no pixels are transparent - repaired PNG_NO_STDIO behaviour - tested NODIV support and made it default behaviour (Greg Roelofs) - added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) - regularized version numbering scheme and bumped shared-library major - version number to 2 to avoid problems with libpng 0.89 apps (Greg Roelofs) +Version 0.97 [January, 1998] + Removed PNG_USE_OWN_CRC capability + Relocated png_set_crc_action from pngrutil.c to pngrtran.c + Fixed typecasts of "new_key", etc. (Andreas Dilger) + Added RFC 1152 [sic] date support + Fixed bug in gamma handling of 4-bit grayscale + Added 2-bit grayscale gamma handling (Glenn R-P) + Added more typecasts. 65536L becomes (png_uint_32)65536L, etc. (Glenn R-P) + Minor corrections in libpng.txt + Added simple sRGB support (Glenn R-P) + Easier conditional compiling, e.g., + define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; + all configurable options can be selected from command-line instead + of having to edit pngconf.h (Glenn R-P) + Fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) + Added more conditions for png_do_background, to avoid changing + black pixels to background when a background is supplied and + no pixels are transparent + Repaired PNG_NO_STDIO behavior + Tested NODIV support and made it default behavior (Greg Roelofs) + Added "-m" option and PNGTEST_DEBUG_MEMORY to pngtest (John Bowler) + Regularized version numbering scheme and bumped shared-library major + version number to 2 to avoid problems with libpng 0.89 apps + (Greg Roelofs) -version 0.98 [January, 1998] - cleaned up some typos in libpng.txt and in code documentation - fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) - cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c - changed recommendation about file_gamma for PC images to .51 from .45, - in example.c and libpng.txt, added comments to distinguish between - screen_gamma, viewing_gamma, and display_gamma. - changed all references to RFC1152 to read RFC1123 and changed the - PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED - added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) - changed srgb_intent from png_byte to int to avoid compiler bugs +Version 0.98 [January, 1998] + Cleaned up some typos in libpng.txt and in code documentation + Fixed memory leaks in pCAL chunk processing (Glenn R-P and John Bowler) + Cosmetic change "display_gamma" to "screen_gamma" in pngrtran.c + Changed recommendation about file_gamma for PC images to .51 from .45, + in example.c and libpng.txt, added comments to distinguish between + screen_gamma, viewing_gamma, and display_gamma. + Changed all references to RFC1152 to read RFC1123 and changed the + PNG_TIME_RFC1152_SUPPORTED macro to PNG_TIME_RFC1123_SUPPORTED + Added png_invert_alpha capability (Glenn R-P -- suggestion by Jon Vincent) + Changed srgb_intent from png_byte to int to avoid compiler bugs -version 0.99 [January 30, 1998] - free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) - fixed a longstanding "packswap" bug in pngtrans.c - fixed some inconsistencies in pngconf.h that prevented compiling with - PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined - fixed some typos and made other minor rearrangement of libpng.txt (Andreas) - changed recommendation about file_gamma for PC images to .50 from .51 in - example.c and libpng.txt, and changed file_gamma for sRGB images to .45 - added a number of functions to access information from the png structure - png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) - added TARGET_MACOS similar to zlib-1.0.8 - define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined - added type casting to all png_malloc() function calls -version 0.99a [January 31, 1998] +Version 0.99 [January 30, 1998] + Free info_ptr->text instead of end_info_ptr->text in pngread.c (John Bowler) + Fixed a longstanding "packswap" bug in pngtrans.c + Fixed some inconsistencies in pngconf.h that prevented compiling with + PNG_READ_GAMMA_SUPPORTED and PNG_READ_hIST_SUPPORTED undefined + Fixed some typos and made other minor rearrangement of libpng.txt (Andreas) + Changed recommendation about file_gamma for PC images to .50 from .51 in + example.c and libpng.txt, and changed file_gamma for sRGB images to .45 + Added a number of functions to access information from the png structure + png_get_image_height(), etc. (Glenn R-P, suggestion by Brad Pettit) + Added TARGET_MACOS similar to zlib-1.0.8 + Define PNG_ALWAYS_EXTERN when __MWERKS__ && WIN32 are defined + Added type casting to all png_malloc() function calls + +Version 0.99a [January 31, 1998] Added type casts and parentheses to all returns that return a value.(Tim W.) -version 0.99b [February 4, 1998] + +Version 0.99b [February 4, 1998] Added type cast png_uint_32 on malloc function calls where needed. Changed type of num_hist from png_uint_32 to int (same as num_palette). Added checks for rowbytes overflow, in case png_size_t is less than 32 bits. Renamed makefile.elf to makefile.lnx. -version 0.99c [February 7, 1998] + +Version 0.99c [February 7, 1998] More type casting. Removed erroneous overflow test in pngmem.c. Added png_buffered_memcpy() and png_buffered_memset(), apply them to rowbytes. Added UNIX manual pages libpng.3 (incorporating libpng.txt) and png.5. -version 0.99d [February 11, 1998] + +Version 0.99d [February 11, 1998] Renamed "far_to_near()" "png_far_to_near()" Revised libpng.3 Version 99c "buffered" operations didn't work as intended. Replaced them @@ -256,7 +267,8 @@ version 0.99d [February 11, 1998] Check for overlength tRNS chunk present when indexed-color PLTE is read. Cleaned up spelling errors in libpng.3/libpng.txt Corrected a problem with png_get_tRNS() which returned undefined trans array -version 0.99e [February 28, 1998] + +Version 0.99e [February 28, 1998] Corrected png_get_tRNS() again. Add parentheses for easier reading of pngget.c, fixed "||" should be "&&". Touched up example.c to make more of it compileable, although the entire @@ -266,53 +278,59 @@ version 0.99e [February 28, 1998] Replaced pngtest.png with one created with zlib 1.1.1 Changed pngtest to report PASS even when file size is different (Jean-loup G.) Corrected some logic errors in png_do_invert_alpha() (Chris Patterson) -version 0.99f [March 5, 1998] + +Version 0.99f [March 5, 1998] Corrected a bug in pngpread() introduced in version 99c (Kevin Bracey) Moved makefiles into a "scripts" directory, and added INSTALL instruction file Added makefile.os2 and pngos2.def (A. Zabolotny) and makefile.s2x (W. Sebok) Added pointers to "note on libpng versions" in makefile.lnx and README Added row callback feature when reading and writing nonprogressive rows - and added a test of this feature in pngtest.c + and added a test of this feature in pngtest.c Added user transform callbacks, with test of the feature in pngtest.c -version 0.99g [March 6, 1998, morning] + +Version 0.99g [March 6, 1998, morning] Minor changes to pngtest.c to suppress compiler warnings. Removed "beta" language from documentation. -version 0.99h [March 6, 1998, evening] + +Version 0.99h [March 6, 1998, evening] Minor changes to previous minor changes to pngtest.c Changed PNG_READ_NOT_FULLY_SUPPORTED to PNG_READ_TRANSFORMS_NOT_SUPPORTED - and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro + and added PNG_PROGRESSIVE_READ_NOT_SUPPORTED macro Added user transform capability -version 1.00 [March 7, 1998] +Version 1.00 [March 7, 1998] Changed several typedefs in pngrutil.c Added makefile.wat (Pawel Mrochen), updated makefile.tc3 (Willem van Schaik) - replaced "while(1)" with "for(;;)" - added PNGARG() to prototypes in pngtest.c and removed some prototypes - updated some of the makefiles (Tom Lane) - changed some typedefs (s_start, etc.) in pngrutil.c - fixed dimensions of "short_months" array in pngwrite.c + Replaced "while(1)" with "for(;;)" + Added PNGARG() to prototypes in pngtest.c and removed some prototypes + Updated some of the makefiles (Tom Lane) + Changed some typedefs (s_start, etc.) in pngrutil.c + Fixed dimensions of "short_months" array in pngwrite.c Replaced ansi2knr.c with the one from jpeg-v6 -version 1.0.0 [March 8, 1998] +Version 1.0.0 [March 8, 1998] Changed name from 1.00 to 1.0.0 (Adam Costello) Added smakefile.ppc (with SCOPTIONS.ppc) for Amiga PPC (Andreas Kleinert) -version 1.0.0a [March 9, 1998] + +Version 1.0.0a [March 9, 1998] Fixed three bugs in pngrtran.c to make gamma+background handling consistent - (Greg Roelofs) + (Greg Roelofs) Changed format of the PNG_LIBPNG_VER integer to xyyzz instead of xyz - for major, minor, and bugfix releases. This is 10001. (Adam Costello, - Tom Lane) + for major, minor, and bugfix releases. This is 10001. (Adam Costello, + Tom Lane) Make months range from 1-12 in png_convert_to_rfc1123 -version 1.0.0b [March 13, 1998] + +Version 1.0.0b [March 13, 1998] Quieted compiler complaints about two empty "for" loops in pngrutil.c Minor changes to makefile.s2x Removed #ifdef/#endif around a png_free() in pngread.c -version 1.0.1 [March 14, 1998] +Version 1.0.1 [March 14, 1998] Changed makefile.s2x to reduce security risk of using a relative pathname Fixed some typos in the documentation (Greg). Fixed a problem with value of "channels" returned by png_read_update_info() -version 1.0.1a [April 21, 1998] + +Version 1.0.1a [April 21, 1998] Optimized Paeth calculations by replacing abs() function calls with intrinsics plus other loop optimizations. Improves avg decoding speed by about 20%. Commented out i386istic "align" compiler flags in makefile.lnx. @@ -326,19 +344,24 @@ version 1.0.1a [April 21, 1998] Moved a misplaced pngrutil code block that truncates tRNS if it has more than num_palette entries -- test was done before num_palette was defined. Fixed a png_convert_to_rfc1123() bug that converts day 31 to 0 (Steve Eddins). - Changed compiler flags in makefile.wat for better optimization (Pawel Mrochen). -version 1.0.1b [May 2, 1998] + Changed compiler flags in makefile.wat for better optimization + (Pawel Mrochen). + +Version 1.0.1b [May 2, 1998] Relocated png_do_gray_to_rgb() within png_do_read_transformations() (Greg). Relocated the png_composite macros from pngrtran.c to png.h (Greg). Added makefile.sco (contributed by Mike Hopkirk). Fixed two bugs (missing definitions of "istop") introduced in libpng-1.0.1a. Fixed a bug in pngrtran.c that would set channels=5 under some circumstances. - More work on the Paeth-filtering, achieving imperceptible speedup (A Kleinert). - More work on loop optimization which may help when compiled with C++ compilers. + More work on the Paeth-filtering, achieving imperceptible speedup + (A Kleinert). + More work on loop optimization which may help when compiled with C++ + compilers. Added warnings when people try to use transforms they've defined out. Collapsed 4 "i" and "c" loops into single "i" loops in pngrtran and pngwtran. Revised paragraph about png_set_expand() in libpng.txt and libpng.3 (Greg) -version 1.0.1c [May 11, 1998] + +Version 1.0.1c [May 11, 1998] Fixed a bug in pngrtran.c (introduced in libpng-1.0.1a) where the masks for filler bytes should have been 0xff instead of 0xf. Added max_pixel_depth=32 in pngrutil.c when using FILLER with palette images. @@ -350,7 +373,8 @@ version 1.0.1c [May 11, 1998] to remove unwanted capabilities via the compile line Made some corrections to grammar (which, it's) in documentation (Greg). Corrected example.c, use of row_pointers in png_write_image(). -version 1.0.1d [May 24, 1998] + +Version 1.0.1d [May 24, 1998] Corrected several statements that used side effects illegally in pngrutil.c and pngtrans.c, that were introduced in version 1.0.1b Revised png_read_rows() to avoid repeated if-testing for NULL (A Kleinert) @@ -360,7 +384,8 @@ version 1.0.1d [May 24, 1998] Bob Dellaca, to make a png32bd.dll with Borland C++ 4.5 Fixed error in example.c with png_set_text: num_text is 3, not 2 (Guido V.) Changed several loops from count-down to count-up, for consistency. -version 1.0.1e [June 6, 1998] + +Version 1.0.1e [June 6, 1998] Revised libpng.txt and libpng.3 description of png_set_read|write_fn(), and added warnings when people try to set png_read_fn and png_write_fn in the same structure. @@ -377,9 +402,10 @@ version 1.0.1e [June 6, 1998] PNGTEST_DEBUG_MEM feature. Added makefile.w32, for Microsoft C++ 4.0 and later (Tim Wegner). -version 1.0.2 [June 14, 1998] +Version 1.0.2 [June 14, 1998] Fixed two bugs in makefile.bor . -version 1.0.2a [December 30, 1998] + +Version 1.0.2a [December 30, 1998] Replaced and extended code that was removed from png_set_filler() in 1.0.1a. Fixed a bug in png_do_filler() that made it fail to write filler bytes in the left-most pixel of each row (Kevin Bracey). @@ -401,23 +427,26 @@ version 1.0.2a [December 30, 1998] Added png_get_copyright() and png_get_header_version() functions. Revised comments on png_set_progressive_read_fn() in libpng.txt and example.c Added information about debugging in libpng.txt and libpng.3 . - Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and makefile.sco. + Changed "ln -sf" to "ln -s -f" in makefile.s2x, makefile.lnx, and + makefile.sco. Removed lines after Dynamic Dependencies" in makefile.aco . Revised makefile.dec to make a shared library (Jeremie Petit). Removed trailing blanks from all files. -version 1.0.2a [January 6, 1999] + +Version 1.0.2a [January 6, 1999] Removed misplaced #endif and #ifdef PNG_NO_EXTERN near the end of png.h Added "if" tests to silence complaints about unused png_ptr in png.h and png.c Changed "check_if_png" function in example.c to return true (nonzero) if PNG. Changed libpng.txt to demonstrate png_sig_cmp() instead of png_check_sig() which is obsolete. -version 1.0.3 [January 14, 1999] +Version 1.0.3 [January 14, 1999] Added makefile.hux, for Hewlett Packard HPUX 10.20 and 11.00 (Jim Rice) Added a statement of Y2K compliance in png.h, libpng.3, and Y2KINFO. -version 1.0.3a [August 12, 1999] + +Version 1.0.3a [August 12, 1999] Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning - if an attempt is made to read an interlaced image when it's not supported. + if an attempt is made to read an interlaced image when it's not supported. Added check if png_ptr->trans is defined before freeing it in pngread.c Modified the Y2K statement to include versions back to version 0.71 Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c @@ -425,7 +454,7 @@ version 1.0.3a [August 12, 1999] Replaced leading blanks with tab characters in makefile.hux Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. Changed (float)red and (float)green to (double)red, (double)green - in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. + in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. Fixed a bug in pngconf.h that omitted when PNG_DEBUG==0 (K Bracey). Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). Updated documentation to refer to the PNG-1.2 specification. @@ -442,13 +471,15 @@ version 1.0.3a [August 12, 1999] Correct gamma with srgb is 45455 instead of 45000 in pngrutil.c, to be consistent with PNG-1.2, and allow variance of 500 before complaining. Added assembler code contributed by Intel in file pngvcrd.c and modified - makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, Gilles Vollant) + makefile.w32 to use it (Nirav Chhatrapati, INTEL Corporation, + Gilles Vollant) Changed "ln -s -f" to "ln -f -s" in the makefiles to make Solaris happy. Added some aliases for png_set_expand() in pngrtran.c, namely png_set_expand_PLTE(), png_set_expand_depth(), and png_set_expand_tRNS() (Greg Roelofs, in "PNG: The Definitive Guide"). Added makefile.beo for BEOS on X86, contributed by Sander Stok. -version 1.0.3b [August 26, 1999] + +Version 1.0.3b [August 26, 1999] Replaced 2147483647L several places with PNG_MAX_UINT macro, defined in png.h Changed leading blanks to tabs in all makefiles. Define PNG_USE_PNGVCRD in makefile.w32, to get MMX assembler code. @@ -460,12 +491,13 @@ version 1.0.3b [August 26, 1999] negative shift distance, whose results are undefined in the C language. Added a check in pngset.c to prevent writing multiple tIME chunks. Added a check in pngwrite.c to detect invalid small window_bits sizes. -version 1.0.3d [September 4, 1999] + +Version 1.0.3d [September 4, 1999] Fixed type casting of igamma in pngrutil.c Added new png_expand functions to scripts/pngdef.pas and pngos2.def Added a demo read_user_transform_fn that examines the row filters in pngtest.c -version 1.0.4 [September 24, 1999] +Version 1.0.4 [September 24, 1999, not distributed publicly] Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h Made several minor corrections to pngtest.c @@ -479,24 +511,31 @@ version 1.0.4 [September 24, 1999] assembler code) and makefile.vcwin32 (doesn't). Added a CPU timing report to pngtest.c (enabled by defining PNGTEST_TIMING) Added a copy of pngnow.png to the distribution. -version 1.0.4a [September 25, 1999] + +Version 1.0.4a [September 25, 1999] Increase max_pixel_depth in pngrutil.c if a user transform needs it. Changed several division operations to right-shifts in pngvcrd.c -version 1.0.4b [September 30, 1999] + +Version 1.0.4b [September 30, 1999] Added parentheses in line 3732 of pngvcrd.c Added a comment in makefile.linux warning about buggy -O3 in pgcc 2.95.1 -version 1.0.4c [October 1, 1999] + +Version 1.0.4c [October 1, 1999] Added a "png_check_version" function in png.c and pngtest.c that will generate a helpful compiler error if an old png.h is found in the search path. Changed type of png_user_transform_depth|channels from int to png_byte. -version 1.0.4d [October 6, 1999] + Added "Libpng is OSI Certified Open Source Software" statement to png.h + +Version 1.0.4d [October 6, 1999] Changed 0.45 to 0.45455 in png_set_sRGB() Removed unused PLTE entries from pngnow.png Re-enabled some parts of pngvcrd.c (png_combine_row) that work properly. -version 1.0.4e [October 10, 1999] + +Version 1.0.4e [October 10, 1999] Fixed sign error in pngvcrd.c (Greg Roelofs) Replaced some instances of memcpy with simple assignments in pngvcrd (GR-P) -version 1.0.4f [October 15, 1999] + +Version 1.0.4f [October 15, 1999] Surrounded example.c code with #if 0 .. #endif to prevent people from inadvertently trying to compile it. Changed png_get_header_version() from a function to a macro in png.h @@ -504,9 +543,10 @@ version 1.0.4f [October 15, 1999] Removed some pointless "ptr = NULL" in pngmem.c Added a "contrib" directory containing the source code from Greg's book. -version 1.0.5 [October 15, 1999] +Version 1.0.5 [October 15, 1999] Minor editing of the INSTALL and README files. -version 1.0.5a [October 23, 1999] + +Version 1.0.5a [October 23, 1999] Added contrib/pngsuite and contrib/pngminus (Willem van Schaik) Fixed a typo in the png_set_sRGB() function call in example.c (Jan Nijtmans) Further optimization and bugfix of pngvcrd.c @@ -514,14 +554,16 @@ version 1.0.5a [October 23, 1999] text_ptr structure. Instead, it makes its own copy. Created separate write_end_info_struct in pngtest.c for a more severe test. Added code in pngwrite.c to free info_ptr->text[i].key to stop a memory leak. -version 1.0.5b [November 23, 1999] + +Version 1.0.5b [November 23, 1999] Moved PNG_FLAG_HAVE_CHUNK_HEADER, PNG_FLAG_BACKGROUND_IS_GRAY and PNG_FLAG_WROTE_tIME from flags to mode. Added png_write_info_before_PLTE() function. Fixed some typecasting in contrib/gregbook/*.c Updated scripts/makevms.com and added makevms.com to contrib/gregbook and contrib/pngminus (Martin Zinser) -version 1.0.5c [November 26, 1999] + +Version 1.0.5c [November 26, 1999] Moved png_get_header_version from png.h to png.c, to accommodate ansi2knr. Removed all global arrays (according to PNG_NO_GLOBAL_ARRAYS macro), to accommodate making DLL's: Moved usr_png_ver from global variable to function @@ -534,21 +576,23 @@ version 1.0.5c [November 26, 1999] Removed some extraneous "-I" from contrib/pngminus/makefile.std Changed the PNG_sRGB_INTENT macros in png.h to be consistent with PNG-1.2. Change PNG_SRGB_INTENT to PNG_sRGB_INTENT in libpng.txt and libpng.3 -version 1.0.5d [November 29, 1999] + +Version 1.0.5d [November 29, 1999] Add type cast (png_const_charp) two places in png.c Eliminated pngtypes.h; use macros instead to declare PNG_CHNK arrays. Renamed "PNG_GLOBAL_ARRAYS" to "PNG_USE_GLOBAL_ARRAYS" and made available to applications a macro "PNG_USE_LOCAL_ARRAYS". - Remove all the new declarations with #ifdef/#endif when + comment out (with #ifdef) all the new declarations when PNG_USE_GLOBAL_ARRAYS is defined. Added PNG_EXPORT_VAR macro to accommodate making DLL's. -version 1.0.5e [November 30, 1999] + +Version 1.0.5e [November 30, 1999] Added iCCP, iTXt, and sPLT support; added "lang" member to the png_text structure; refactored the inflate/deflate support to make adding new chunks with trailing compressed parts easier in the future, and added new functions png_free_iCCP, png_free_pCAL, png_free_sPLT, png_free_text, png_get_iCCP, png_get_spalettes, png_set_iCCP, png_set_spalettes (Eric S. Raymond). - NOTE: Applications that write text chunks MUST define png_text->lang + NOTE: Applications that write text chunks MUST define png_text->lang before calling png_set_text(). It must be set to NULL if you want to write tEXt or zTXt chunks. If you want your application to be able to run with older versions of libpng, use @@ -563,18 +607,21 @@ version 1.0.5e [November 30, 1999] PNG_cHNK_SUPPORTED and combined the three types of PNG_text_SUPPORTED macros, leaving the separate macros also available. Removed comments on #endifs at the end of many short, non-nested #if-blocks. -version 1.0.5f [December 6, 1999] + +Version 1.0.5f [December 6, 1999] Changed makefile.solaris to issue a warning about potential problems when the ucb "ld" is in the path ahead of the ccs "ld". Removed "- [date]" from the "synopsis" line in libpng.3 and libpngpf.3. Added sCAL chunk support (Eric S. Raymond). -version 1.0.5g [December 7, 1999] + +Version 1.0.5g [December 7, 1999] Fixed "png_free_spallettes" typo in png.h Added code to handle new chunks in pngpread.c Moved PNG_CHNK string macro definitions outside of PNG_NO_EXTERN block Added "translated_key" to png_text structure and png_write_iTXt(). Added code in pngwrite.c to work around a newly discovered zlib bug. -version 1.0.5h [December 10, 1999] + +Version 1.0.5h [December 10, 1999] NOTE: regarding the note for version 1.0.5e, the following must also be included in your code: png_text[i].translated_key = NULL; @@ -582,7 +629,8 @@ version 1.0.5h [December 10, 1999] Option to eliminate all floating point support was added. Some new fixed-point functions such as png_set_gAMA_fixed() were added. Expanded tabs and removed trailing blanks in source files. -version 1.0.5i [December 13, 1999] + +Version 1.0.5i [December 13, 1999] Added some type casts to silence compiler warnings. Renamed "png_free_spalette" to "png_free_spalettes" for consistency. Removed leading blanks from a #define in pngvcrd.c @@ -594,7 +642,8 @@ version 1.0.5i [December 13, 1999] Added png_free_hIST() function. Various patches to fix bugs in the sCAL and integer cHRM processing, and to add some convenience macros for use with sCAL. -version 1.0.5j [December 21, 1999] + +Version 1.0.5j [December 21, 1999] Changed "unit" parameter of png_write_sCAL from png_byte to int, to work around buggy compilers. Added new type "png_fixed_point" for integers that hold float*100000 values @@ -610,7 +659,8 @@ version 1.0.5j [December 21, 1999] and to write the iTXt chunk after IDAT if it appears in the end_ptr. Added pnggccrd.c, version of pngvcrd.c Intel assembler for gcc (Greg Roelofs) Reversed the order of trying to write floating-point and fixed-point gAMA. -version 1.0.5k [December 27, 1999] + +Version 1.0.5k [December 27, 1999] Added many parentheses, e.g., "if (a && b & c)" becomes "if (a && (b & c))" Added png_handle_as_unknown() function (Glenn) Added png_free_chunk_list() function and chunk_list and num_chunk_list members @@ -621,33 +671,41 @@ version 1.0.5k [December 27, 1999] Added png_free_tRNS(); png_set_tRNS() now malloc's its own trans array (ESR). Define png_get_int_32 when oFFs chunk is supported as well as when pCAL is. Changed type of proflen from png_int_32 to png_uint_32 in png_get_iCCP(). -version 1.0.5l [January 1, 2000] + +Version 1.0.5l [January 1, 2000] Added functions png_set_read_user_chunk_fn() and png_get_user_chunk_ptr() for setting a callback function to handle unknown chunks and for retrieving the associated user pointer (Glenn). -version 1.0.5m [January 7, 2000] + +Version 1.0.5m [January 7, 2000] Added high-level functions png_read_png(), png_write_png(), png_free_pixels(). -version 1.0.5n [January 9, 2000] + +Version 1.0.5n [January 9, 2000] Added png_free_PLTE() function, and modified png_set_PLTE() to malloc its own memory for info_ptr->palette. This makes it safe for the calling application to free its copy of the palette any time after it calls png_set_PLTE(). -version 1.0.5o [January 20, 2000] + +Version 1.0.5o [January 20, 2000] Cosmetic changes only (removed some trailing blanks and TABs) -version 1.0.5p [January 31, 2000] + +Version 1.0.5p [January 31, 2000] Renamed pngdll.mak to makefile.bd32 Cosmetic changes in pngtest.c -version 1.0.5q [February 5, 2000] + +Version 1.0.5q [February 5, 2000] Relocated the makefile.solaris warning about PATH problems. Fixed pngvcrd.c bug by pushing/popping registers in mmxsupport (Bruce Oberg) Revised makefile.gcmmx Added PNG_SETJMP_SUPPORTED, PNG_SETJMP_NOT_SUPPORTED, and PNG_ABORT() macros -version 1.0.5r [February 7, 2000] + +Version 1.0.5r [February 7, 2000] Removed superfluous prototype for png_get_itxt from png.h Fixed a bug in pngrtran.c that improperly expanded the background color. Return *num_text=0 from png_get_text() when appropriate, and fix documentation of png_get_text() in libpng.txt/libpng.3. -version 1.0.5s [February 18, 2000] + +Version 1.0.5s [February 18, 2000] Added "png_jmp_env()" macro to pngconf.h, to help people migrate to the new error handler that's planned for the next libpng release, and changed example.c, pngtest.c, and contrib programs to use this macro. @@ -666,7 +724,8 @@ version 1.0.5s [February 18, 2000] Added png_set_rows() and png_get_rows(), for use with png_read|write_png(). Modified png_read_png() to allocate info_ptr->row_pointers only if it hasn't already been allocated. -version 1.0.5t [March 4, 2000] + +Version 1.0.5t [March 4, 2000] Changed png_jmp_env() migration aiding macro to png_jmpbuf(). Fixed "interlace" typo (should be "interlaced") in contrib/gregbook/read2-x.c Fixed bug with use of PNG_BEFORE_IHDR bit in png_ptr->mode, introduced when @@ -675,13 +734,15 @@ version 1.0.5t [March 4, 2000] a 24-bit visual if one is available, and to allow abbreviated options. Files in contrib/pngminus were revised to use the png_jmpbuf() macro. Removed spaces in makefile.linux and makefile.gcmmx, introduced in 1.0.5s -version 1.0.5u [March 5, 2000] + +Version 1.0.5u [March 5, 2000] Simplified the code that detects old png.h in png.c and pngtest.c Renamed png_spalette (_p, _pp) to png_sPLT_t (_tp, _tpp) Increased precision of rgb_to_gray calculations from 8 to 15 bits and added png_set_rgb_to_gray_fixed() function. Added makefile.bc32 (32-bit Borland C++, C mode) -version 1.0.5v [March 11, 2000] + +Version 1.0.5v [March 11, 2000] Added some parentheses to the png_jmpbuf macro definition. Updated references to the zlib home page, which has moved to freesoftware.com. Corrected bugs in documentation regarding png_read_row() and png_write_row(). @@ -689,10 +750,11 @@ version 1.0.5v [March 11, 2000] Renamed makefile.borland,turboc3 back to makefile.bor,tc3 as in version 1.0.3, revised borland makefiles; added makefile.ibmvac3 and makefile.gcc (Cosmin) -version 1.0.6 [March 20, 2000] +Version 1.0.6 [March 20, 2000] Minor revisions of makefile.bor, libpng.txt, and gregbook/rpng2-win.c Added makefile.sggcc (SGI IRIX with gcc) -version 1.0.6d [April 7, 2000] + +Version 1.0.6d [April 7, 2000] Changed sprintf() to strcpy() in png_write_sCAL_s() to work without STDIO Added data_length parameter to png_decompress_chunk() function Revised documentation to remove reference to abandoned png_free_chnk functions @@ -701,7 +763,8 @@ version 1.0.6d [April 7, 2000] Renamed makefile.ibmvac3 to makefile.ibmc, added libpng.icc IBM project file Added a check for info_ptr->free_me&PNG_FREE_TEXT when freeing text in png.c Simplify png_sig_bytes() function to remove use of non-ISO-C strdup(). -version 1.0.6e [April 9, 2000] + +Version 1.0.6e [April 9, 2000] Added png_data_freer() function. In the code that checks for over-length tRNS chunks, added check of info_ptr->num_trans as well as png_ptr->num_trans (Matthias Benckmann) @@ -712,25 +775,29 @@ version 1.0.6e [April 9, 2000] is defined. Changed several instances of PNG_NO_CONSOLE_ID to PNG_NO_STDIO in pngrutil.c and mentioned the purposes of the two macros in libpng.txt/libpng.3. -version 1.0.6f [April 14, 2000] + +Version 1.0.6f [April 14, 2000] Revised png_set_iCCP() and png_set_rows() to avoid prematurely freeing data. Add checks in png_set_text() for NULL members of the input text structure. Revised libpng.txt/libpng.3. - Removed superfluous prototype for png_set_itxt from png.h + Removed superfluous prototype for png_set_iTXt from png.h Removed "else" from pngread.c, after png_error(), and changed "0" to "length". Changed several png_errors about malformed ancillary chunks to png_warnings. -version 1.0.6g [April 24, 2000] + +Version 1.0.6g [April 24, 2000] Added png_pass-* arrays to pnggccrd.c when PNG_USE_LOCAL_ARRAYS is defined. Relocated paragraph about png_set_background() in libpng.3/libpng.txt and other revisions (Matthias Benckmann) Relocated info_ptr->free_me, png_ptr->free_me, and other info_ptr and png_ptr members to restore binary compatibility with libpng-1.0.5 (breaks compatibility with libpng-1.0.6). -version 1.0.6h [April 24, 2000] + +Version 1.0.6h [April 24, 2000] Changed shared library so-number pattern from 2.x.y.z to xy.z (this builds libpng.so.10 & libpng.so.10.6h instead of libpng.so.2 & libpng.so.2.1.0.6h) This is a temporary change for test purposes. -version 1.0.6i [May 2, 2000] + +Version 1.0.6i [May 2, 2000] Rearranged some members at the end of png_info and png_struct, to put unknown_chunks_num and free_me within the original size of the png_structs and free_me, png_read_user_fn, and png_free_fn within the original png_info, @@ -755,22 +822,25 @@ version 1.0.6i [May 2, 2000] generate a libpng error if the modes aren't set and PNG_LEGACY_SUPPORTED was not defined. Added makefile.intel and updated makefile.watcom (Pawel Mrochen) -version 1.0.6j [May 3, 2000] + +Version 1.0.6j [May 3, 2000] Overloaded png_read_init() and png_write_init() with macros that convert calls to png_read_init_2() or png_write_init_2() that check the version and structure sizes. -version 1.0.7beta11 [May 7, 2000] + +Version 1.0.7beta11 [May 7, 2000] Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes which are no longer used. Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is - defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXt_SUPPORTED is defined. Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory overrun when old applications fill the info_ptr->text structure directly. Added PNGAPI macro, and added it to the definitions of all exported functions. Relocated version macro definitions ahead of the includes of zlib.h and pngconf.h in png.h. -version 1.0.7beta12 [May 12, 2000] + +Version 1.0.7beta12 [May 12, 2000] Revised pngset.c to avoid a problem with expanding the png_debug macro. Deleted some extraneous defines from pngconf.h Made PNG_NO_CONSOLE_IO the default condition when PNG_BUILD_DLL is defined. @@ -778,7 +848,8 @@ version 1.0.7beta12 [May 12, 2000] Added png_access_version_number() function. Check for mask&PNG_FREE_CHNK (for TEXT, SCAL, PCAL) in png_free_data(). Expanded libpng.3/libpng.txt information about png_data_freer(). -version 1.0.7beta14 [May 17, 2000] (beta13 was not published) + +Version 1.0.7beta14 [May 17, 2000] (beta13 was not published) Changed pnggccrd.c and pngvcrd.c to handle bad adaptive filter types as warnings instead of errors, as pngrutil.c does. Set the PNG_INFO_IDAT valid flag in png_set_rows() so png_write_png() @@ -790,7 +861,8 @@ version 1.0.7beta14 [May 17, 2000] (beta13 was not published) Removed info_ptr->valid tests from png_free_data(), as in version 1.0.5. Added png_set_invalid() function. Fixed incorrect illustrations of png_destroy_write_struct() in example.c. -version 1.0.7beta15 [May 30, 2000] + +Version 1.0.7beta15 [May 30, 2000] Revised the deliberately erroneous Linux setjmp code in pngconf.h to produce fewer error messages. Rearranged checks for Z_OK to check the most likely path first in pngpread.c @@ -802,9 +874,11 @@ version 1.0.7beta15 [May 30, 2000] Fixed some bugs in the unused PNG_INCH_CONVERSIONS functions in pngget.c Set each pointer to NULL after freeing it in png_free_data(). Worked around a problem in pngconf.h; AIX's strings.h defines an "index" - macro that conflicts with libpng's png_color_16.index. (Dimitri Papadapoulos) + macro that conflicts with libpng's png_color_16.index. (Dimitri + Papadapoulos) Added "msvc" directory with MSVC++ project files (Simon-Pierre Cadieux). -version 1.0.7beta16 [June 4, 2000] + +Version 1.0.7beta16 [June 4, 2000] Revised the workaround of AIX string.h "index" bug. Added a check for overlength PLTE chunk in pngrutil.c. Added PNG_NO_POINTER_INDEXING macro to use array-indexing instead of pointer @@ -814,49 +888,58 @@ version 1.0.7beta16 [June 4, 2000] Added PNG_USE_DLL macro. Revised the copyright/disclaimer/license notice. Added contrib/msvctest directory -version 1.0.7rc1 [June 9, 2000] + +Version 1.0.7rc1 [June 9, 2000] Corrected the definition of PNG_TRANSFORM_INVERT_ALPHA (0x0400 not 0x0200) Added contrib/visupng directory (Willem van Schaik) -version 1.0.7beta18 [June 23, 2000] + +Version 1.0.7beta18 [June 23, 2000] Revised PNGAPI definition, and pngvcrd.c to work with __GCC__ and do not redefine PNGAPI if it is passed in via a compiler directive. Revised visupng/PngFile.c to remove returns from within the Try block. Removed leading underscores from "_PNG_H" and "_PNG_SAVE_BSD_SOURCE" macros. Updated contrib/visupng/cexcept.h to version 1.0.0. Fixed bugs in pngwrite.c and pngwutil.c that prevented writing iCCP chunks. -version 1.0.7rc2 [June 28, 2000] + +Version 1.0.7rc2 [June 28, 2000] Updated license to include disclaimers required by UCITA. Fixed "DJBPP" typo in pnggccrd.c introduced in beta18. -version 1.0.7 [July 1, 2000] +Version 1.0.7 [July 1, 2000] Revised the definition of "trans_values" in libpng.3/libpng.txt -version 1.0.8beta1 [July 8, 2000] + +Version 1.0.8beta1 [July 8, 2000] Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and - pngwutil.c. + pngwutil.c. Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. Removed unused "#include " from png.c Added WindowsCE support. Revised pnggccrd.c to work with gcc-2.95.2 and in the Cygwin environment. -version 1.0.8beta2 [July 10, 2000] + +Version 1.0.8beta2 [July 10, 2000] Added project files to the wince directory and made further revisions - of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. -version 1.0.8beta3 [July 11, 2000] + of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. + +Version 1.0.8beta3 [July 11, 2000] Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() - for indexed-color input files to avoid potential double-freeing trans array - under some unusual conditions; problem was introduced in version 1.0.6f. + for indexed-color input files to avoid potential double-freeing trans array + under some unusual conditions; problem was introduced in version 1.0.6f. Further revisions to pngtest.c and files in the wince subdirectory. -version 1.0.8beta4 [July 14, 2000] + +Version 1.0.8beta4 [July 14, 2000] Added the files pngbar.png and pngbar.jpg to the distribution. Added makefile.cygwin, and cygwin support in pngconf.h Added PNG_NO_ZALLOC_ZERO macro (makes png_zalloc skip zeroing memory) -version 1.0.8rc1 [July 16, 2000] + +Version 1.0.8rc1 [July 16, 2000] Revised png_debug() macros and statements to eliminate compiler warnings. -version 1.0.8 [July 24, 2000] +Version 1.0.8 [July 24, 2000] Added png_flush() in pngwrite.c, after png_write_IEND(). Updated makefile.hpux to build a shared library. -version 1.0.9beta1 [November 10, 2000] + +Version 1.0.9beta1 [November 10, 2000] Fixed typo in scripts/makefile.hpux Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) @@ -875,59 +958,72 @@ version 1.0.9beta1 [November 10, 2000] Revised makefile.cygwin Fixed bugs in iCCP support in pngrutil.c and pngwutil.c. Replaced png_set_empty_plte_permitted() with png_permit_mng_features(). -version 1.0.9beta2 [November 19, 2000] + +Version 1.0.9beta2 [November 19, 2000] Renamed the "dll" subdirectory "projects". Added borland project files to "projects" subdirectory. Set VS_FF_PRERELEASE and VS_FF_PATCHED flags in msvc/png.rc when appropriate. Add error message in png_set_compression_buffer_size() when malloc fails. -version 1.0.9beta3 [November 23, 2000] + +Version 1.0.9beta3 [November 23, 2000] Revised PNG_LIBPNG_BUILD_TYPE macro in png.h, used in the msvc project. Removed the png_flush() in pngwrite.c that crashes some applications that don't set png_output_flush_fn. Added makefile.macosx and makefile.aix to scripts directory. -version 1.0.9beta4 [December 1, 2000] + +Version 1.0.9beta4 [December 1, 2000] Change png_chunk_warning to png_warning in png_check_keyword(). Increased the first part of msg buffer from 16 to 18 in png_chunk_error(). -version 1.0.9beta5 [December 15, 2000] + +Version 1.0.9beta5 [December 15, 2000] Added support for filter method 64 (for PNG datastreams embedded in MNG). -version 1.0.9beta6 [December 18, 2000] + +Version 1.0.9beta6 [December 18, 2000] Revised png_set_filter() to accept filter method 64 when appropriate. Added new PNG_HAVE_PNG_SIGNATURE bit to png_ptr->mode and use it to help prevent applications from using MNG features in PNG datastreams. Added png_permit_mng_features() function. Revised libpng.3/libpng.txt. Changed "filter type" to "filter method". -version 1.0.9rc1 [December 23, 2000] + +Version 1.0.9rc1 [December 23, 2000] Revised test for PNG_HAVE_PNG_SIGNATURE in pngrutil.c Fixed error handling of unknown compression type in png_decompress_chunk(). In pngconf.h, define __cdecl when _MSC_VER is defined. -version 1.0.9beta7 [December 28, 2000] + +Version 1.0.9beta7 [December 28, 2000] Changed PNG_TEXT_COMPRESSION_zTXt to PNG_COMPRESSION_TYPE_BASE several places. Revised memory management in png_set_hIST and png_handle_hIST in a backward compatible manner. PLTE and tRNS were revised similarly. Revised the iCCP chunk reader to ignore trailing garbage. -version 1.0.9beta8 [January 12, 2001] + +Version 1.0.9beta8 [January 12, 2001] Moved pngasmrd.h into pngconf.h. Improved handling of out-of-spec garbage iCCP chunks generated by PhotoShop. -version 1.0.9beta9 [January 15, 2001] + +Version 1.0.9beta9 [January 15, 2001] Added png_set_invalid, png_permit_mng_features, and png_mmx_supported to wince and msvc project module definition files. Minor revision of makefile.cygwin. Fixed bug with progressive reading of narrow interlaced images in pngpread.c -version 1.0.9beta10 [January 16, 2001] + +Version 1.0.9beta10 [January 16, 2001] Do not typedef png_FILE_p in pngconf.h when PNG_NO_STDIO is defined. Fixed "png_mmx_supported" typo in project definition files. -version 1.0.9beta11 [January 19, 2001] + +Version 1.0.9beta11 [January 19, 2001] Updated makefile.sgi to make shared library. Removed png_mmx_support() function and disabled PNG_MNG_FEATURES_SUPPORTED by default, for the benefit of DLL forward compatibility. These will be re-enabled in version 1.2.0. -version 1.0.9rc2 [January 22, 2001] + +Version 1.0.9rc2 [January 22, 2001] Revised cygwin support. -version 1.0.9 [January 31, 2001] +Version 1.0.9 [January 31, 2001] Added check of cygwin's ALL_STATIC in pngconf.h Added "-nommx" parameter to contrib/gregbook/rpng2-win and rpng2-x demos. -version 1.0.10beta1 [March 14, 2001] + +Version 1.0.10beta1 [March 14, 2001] Revised makefile.dec, makefile.sgi, and makefile.sggcc; added makefile.hpgcc. Reformatted libpng.3 to eliminate bad line breaks. Added checks for _mmx_supported in the read_filter_row function of pnggccrd.c @@ -940,33 +1036,39 @@ version 1.0.10beta1 [March 14, 2001] Fixed bugs in png_combine_row() in pnggccrd.c and pngvcrd.c (C version) Added warnings when retrieving or setting gamma=0. Increased the first part of msg buffer from 16 to 18 in png_chunk_warning(). -version 1.0.10rc1 [March 23, 2001] + +Version 1.0.10rc1 [March 23, 2001] Changed all instances of memcpy, strcpy, and strlen to png_memcpy, png_strcpy, and png_strlen. Revised png_mmx_supported() function in pnggccrd.c to return proper value. Fixed bug in progressive reading (pngpread.c) with small images (height < 8). -version 1.0.10 [March 30, 2001] +Version 1.0.10 [March 30, 2001] Deleted extraneous space (introduced in 1.0.9) from line 42 of makefile.cygwin Added beos project files (Chris Herborth) -version 1.0.11beta1 [April 3, 2001] + +Version 1.0.11beta1 [April 3, 2001] Added type casts on several png_malloc() calls (Dimitri Papadapoulos). Removed a no-longer needed AIX work-around from pngconf.h Changed several "//" single-line comments to C-style in pnggccrd.c -version 1.0.11beta2 [April 11, 2001] + +Version 1.0.11beta2 [April 11, 2001] Removed PNGAPI from several functions whose prototypes did not have PNGAPI. Updated scripts/pngos2.def -version 1.0.11beta3 [April 14, 2001] + +Version 1.0.11beta3 [April 14, 2001] Added checking the results of many instances of png_malloc() for NULL -version 1.0.11beta4 [April 20, 2001] + +Version 1.0.11beta4 [April 20, 2001] Undid the changes from version 1.0.11beta3. Added a check for NULL return from user's malloc_fn(). Removed some useless type casts of the NULL pointer. Added makefile.netbsd -version 1.0.11 [April 27, 2001] +Version 1.0.11 [April 27, 2001] Revised makefile.netbsd -version 1.0.12beta1 [May 14, 2001] + +Version 1.0.12beta1 [May 14, 2001] Test for Windows platform in pngconf.h when including malloc.h (Emmanuel Blot) Updated makefile.cygwin and handling of Cygwin's ALL_STATIC in pngconf.h Added some never-to-be-executed code in pnggccrd.c to quiet compiler warnings. @@ -974,66 +1076,76 @@ version 1.0.12beta1 [May 14, 2001] libpng will reallocate the png_struct and info_struct if they are too small. This retains future binary compatibility for old applications written for libpng-0.88 and earlier. -version 1.2.0beta1 [May 6, 2001] + +Version 1.2.0beta1 [May 6, 2001] Bumped DLLNUM to 2. Re-enabled PNG_MNG_FEATURES_SUPPORTED and enabled PNG_ASSEMBLER_CODE_SUPPORTED by default. Added runtime selection of MMX features. Added png_set_strip_error_numbers function and related macros. -version 1.2.0beta2 [May 7, 2001] + +Version 1.2.0beta2 [May 7, 2001] Finished merging 1.2.0beta1 with version 1.0.11 Added a check for attempts to read or write PLTE in grayscale PNG datastreams. -version 1.2.0beta3 [May 17, 2001] + +Version 1.2.0beta3 [May 17, 2001] Enabled user memory function by default. Modified png_create_struct so it passes user mem_ptr to user memory allocator. Increased png_mng_features flag from png_byte to png_uint_32. Bumped shared-library (so-number) and dll-number to 3. -version 1.2.0beta4 [June 23, 2001] + +Version 1.2.0beta4 [June 23, 2001] Check for missing profile length field in iCCP chunk and free chunk_data - in case of truncated iCCP chunk. + in case of truncated iCCP chunk. Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc Bumped dll-number from 2 to 3 in makefile.cygwin Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly - if user attempts to run it on an 8-bit display. + if user attempts to run it on an 8-bit display. Updated contrib/gregbook Use png_malloc instead of png_zalloc to allocate palette in pngset.c Updated makefile.ibmc Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes - of png_write_oFFS width and height from png_uint_32 to png_int_32. + of png_write_oFFS width and height from png_uint_32 to png_int_32. Updated example.c Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c -version 1.2.0beta5 [August 8, 2001] + +Version 1.2.0beta5 [August 8, 2001] Revised contrib/gregbook Revised makefile.gcmmx Revised pnggccrd.c to conditionally compile some thread-unsafe code only - when PNG_THREAD_UNSAFE_OK is defined. + when PNG_THREAD_UNSAFE_OK is defined. Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with - value exceeding 2^bit_depth-1 + value exceeding 2^bit_depth-1 Revised makefile.sgi and makefile.sggcc Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c Removed restriction that do_invert_mono only operate on 1-bit opaque files -version 1.2.0 [September 1, 2001] +Version 1.2.0 [September 1, 2001] Changed a png_warning() to png_debug() in pnggccrd.c Fixed contrib/gregbook/rpng-x.c, rpng2-x.c to avoid crash with XFreeGC(). -version 1.2.1beta1 [October 19, 2001] + +Version 1.2.1beta1 [October 19, 2001] Revised makefile.std in contrib/pngminus Include background_1 in png_struct regardless of gamma support. Revised makefile.netbsd and makefile.macosx, added makefile.darwin. Revised example.c to provide more details about using row_callback(). -version 1.2.1beta2 [October 25, 2001] + +Version 1.2.1beta2 [October 25, 2001] Added type cast to each NULL appearing in a function call, except for WINCE functions. Added makefile.so9. -version 1.2.1beta3 [October 27, 2001] + +Version 1.2.1beta3 [October 27, 2001] Removed type casts from all NULLs. Simplified png_create_struct_2(). -version 1.2.1beta4 [November 7, 2001] + +Version 1.2.1beta4 [November 7, 2001] Revised png_create_info_struct() and png_creat_struct_2(). Added error message if png_write_info() was omitted. Type cast NULLs appearing in function calls when _NO_PROTO or PNG_TYPECAST_NULL is defined. -version 1.2.1rc1 [November 24, 2001] + +Version 1.2.1rc1 [November 24, 2001] Type cast NULLs appearing in function calls except when PNG_NO_TYPECAST_NULL is defined. Changed typecast of "size" argument to png_size_t in pngmem.c calls to @@ -1042,14 +1154,16 @@ version 1.2.1rc1 [November 24, 2001] Updated makefile.sgi to recognize LIBPATH and INCPATH. Updated various makefiles so "make clean" does not remove previous major version of the shared library. -version 1.2.1rc2 [December 4, 2001] + +Version 1.2.1rc2 [December 4, 2001] Always allocate 256-entry internal palette, hist, and trans arrays, to avoid out-of-bounds memory reference caused by invalid PNG datastreams. Added a check for prefix_length > data_length in iCCP chunk handler. -version 1.2.1 [December 7, 2001] +Version 1.2.1 [December 7, 2001] None. -version 1.2.2beta1 [February 22, 2002] + +Version 1.2.2beta1 [February 22, 2002] Fixed a bug with reading the length of iCCP profiles (Larry Reeves). Revised makefile.linux, makefile.gcmmx, and makefile.sgi to generate libpng.a, libpng12.so (not libpng.so.3), and libpng12/png.h @@ -1059,13 +1173,15 @@ version 1.2.2beta1 [February 22, 2002] Revised calls to png_create_read_struct() and png_create_write_struct() for simpler debugging. Revised png_zalloc() so zlib handles errors (uses PNG_FLAG_MALLOC_NULL_MEM_OK) -version 1.2.2beta2 [February 23, 2002] + +Version 1.2.2beta2 [February 23, 2002] Check chunk_length and idat_size for invalid (over PNG_MAX_UINT) lengths. Check for invalid image dimensions in png_get_IHDR. Added missing "fi;" in the install target of the SGI makefiles. Added install-static to all makefiles that make shared libraries. Always do gamma compensation when image is partially transparent. -version 1.2.2beta3 [March 7, 2002] + +Version 1.2.2beta3 [March 7, 2002] Compute background.gray and background_1.gray even when color_type is RGB in case image gets reduced to gray later. Modified shared-library makefiles to install pkgconfig/libpngNN.pc. @@ -1075,12 +1191,14 @@ version 1.2.2beta3 [March 7, 2002] Added install-shared target to all makefiles that make shared libraries. Stopped a double free of palette, hist, and trans when not using free_me. Added makefile.32sunu for Sun Ultra 32 and makefile.64sunu for Sun Ultra 64. -version 1.2.2beta4 [March 8, 2002] + +Version 1.2.2beta4 [March 8, 2002] Compute background.gray and background_1.gray even when color_type is RGB in case image gets reduced to gray later (Jason Summers). Relocated a misplaced /bin/rm in the "install-shared" makefile targets Added PNG_1_0_X macro which can be used to build a 1.0.x-compatible library. -version 1.2.2beta5 [March 26, 2002] + +Version 1.2.2beta5 [March 26, 2002] Added missing PNGAPI to several function definitions. Check for invalid bit_depth or color_type in png_get_IHDR(), and check for missing PLTE or IHDR in png_push_read_chunk() (Matthias Clasen). @@ -1089,33 +1207,45 @@ version 1.2.2beta5 [March 26, 2002] Changed "()" to "{}" in scripts/libpng.pc.in. Revised makefiles to put png.h and pngconf.h only in $prefix/include/libpngNN Revised makefiles to make symlink to libpng.so.NN in addition to libpngNN.so -version 1.2.2beta6 [March 31, 2002] -version 1.0.13beta1 [March 31, 2002] + +Version 1.2.2beta6 [March 31, 2002] + +Version 1.0.13beta1 [March 31, 2002] Prevent png_zalloc() from trying to memset memory that it failed to acquire. Add typecasts of PNG_MAX_UINT in pngset_cHRM_fixed() (Matt Holgate). Ensure that the right function (user or default) is used to free the png_struct after an error in png_create_read_struct_2(). -version 1.2.2rc1 [April 7, 2002] -version 1.0.13rc1 [April 7, 2002] + +Version 1.2.2rc1 [April 7, 2002] + +Version 1.0.13rc1 [April 7, 2002] Save the ebx register in pnggccrd.c (Sami Farin) Add "mem_ptr = png_ptr->mem_ptr" in png_destroy_write_struct() (Paul Gardner). Updated makefiles to put headers in include/libpng and remove old include/*.h. -version 1.2.2 [April 15, 2002] -version 1.0.13 [April 15, 2002] +Version 1.2.2 [April 15, 2002] + +Version 1.0.13 [April 15, 2002] Revised description of png_set_filter() in libpng.3/libpng.txt. Revised makefile.netbsd and added makefile.neNNbsd and makefile.freebsd -version 1.0.13patch01 [April 17, 2002] -version 1.2.2patch01 [April 17, 2002] - Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and makefile.sggcc - Fixed VER -> PNGVER typo in makefile.macosx and added install-static to install + +Version 1.0.13patch01 [April 17, 2002] + +Version 1.2.2patch01 [April 17, 2002] + Changed ${PNGMAJ}.${PNGVER} bug to ${PNGVER} in makefile.sgi and + makefile.sggcc + Fixed VER -> PNGVER typo in makefile.macosx and added install-static to + install Added install: target to makefile.32sunu and makefile.64sunu -version 1.0.13patch03 [April 18, 2002] -version 1.2.2patch03 [April 18, 2002] + +Version 1.0.13patch03 [April 18, 2002] + +Version 1.2.2patch03 [April 18, 2002] Revised 15 makefiles to link libpng.a to libpngNN.a and the include libpng subdirectory to libpngNN subdirectory without the full pathname. Moved generation of libpng.pc from "install" to "all" in 15 makefiles. -version 1.2.3rc1 [April 28, 2002] + +Version 1.2.3rc1 [April 28, 2002] Added install-man target to 15 makefiles (Dimitri Papadopolous-Orfanos). Added $(DESTDIR) feature to 24 makefiles (Tim Mooney) Fixed bug with $prefix, should be $(prefix) in makefile.hpux. @@ -1127,70 +1257,83 @@ version 1.2.3rc1 [April 28, 2002] to put one in their application. Restored png_zalloc() and png_zfree() prototypes to version 1.2.1 and removed them from module definition files. -version 1.2.3rc2 [May 1, 2002] + +Version 1.2.3rc2 [May 1, 2002] Fixed bug in reporting number of channels in pngget.c and pngset.c, that was introduced in version 1.2.2beta5. Exported png_zalloc(), png_zfree(), png_default_read(), png_default_write(), png_default_flush(), and png_push_fill_buffer() and included them in module definition files. Added "libpng.pc" dependency to the "install-shared" target in 15 makefiles. -version 1.2.3rc3 [May 1, 2002] + +Version 1.2.3rc3 [May 1, 2002] Revised prototype for png_default_flush() Remove old libpng.pc and libpngNN.pc before installing new ones. -version 1.2.3rc4 [May 2, 2002] + +Version 1.2.3rc4 [May 2, 2002] Typos in *.def files (png_default_read|write -> png_default_read|write_data) In makefiles, changed rm libpng.NN.pc to rm libpngNN.pc - Added libpng-config and libpngNN-config and modified makefiles to install them. + Added libpng-config and libpngNN-config and modified makefiles to install + them. Changed $(MANPATH) to $(DESTDIR)$(MANPATH) in makefiles Added "Win32 DLL VB" configuration to projects/msvc/libpng.dsp -version 1.2.3rc5 [May 11, 2002] + +Version 1.2.3rc5 [May 11, 2002] Changed "error" and "message" in prototypes to "error_message" and "warning_message" to avoid namespace conflict. Revised 15 makefiles to build libpng-config from libpng-config-*.in Once more restored png_zalloc and png_zfree to regular nonexported form. Restored png_default_read|write_data, png_default_flush, png_read_fill_buffer - to nonexported form, but with PNGAPI, and removed them from module def files. -version 1.2.3rc6 [May 14, 2002] + to nonexported form, but with PNGAPI, and removed them from module def + files. + +Version 1.2.3rc6 [May 14, 2002] Removed "PNGAPI" from png_zalloc() and png_zfree() in png.c Changed "Gz" to "Gd" in projects/msvc/libpng.dsp and zlib.dsp. Removed leftover libpng-config "sed" script from four makefiles. Revised libpng-config creating script in 16 makefiles. -version 1.2.3 [May 22, 2002] +Version 1.2.3 [May 22, 2002] Revised libpng-config target in makefile.cygwin. Removed description of png_set_mem_fn() from documentation. Revised makefile.freebsd. Minor cosmetic changes to 15 makefiles, e.g., $(DI) = $(DESTDIR)/$(INCDIR). Revised projects/msvc/README.txt Changed -lpng to -lpngNN in LDFLAGS in several makefiles. -version 1.2.4beta1 [May 24, 2002] + +Version 1.2.4beta1 [May 24, 2002] Added libpng.pc and libpng-config to "all:" target in 16 makefiles. Fixed bug in 16 makefiles: $(DESTDIR)/$(LIBPATH) to $(DESTDIR)$(LIBPATH) Added missing "\" before closing double quote in makefile.gcmmx. Plugged various memory leaks; added png_malloc_warn() and png_set_text_2() functions. -version 1.2.4beta2 [June 25, 2002] + +Version 1.2.4beta2 [June 25, 2002] Plugged memory leak of png_ptr->current_text (Matt Holgate). Check for buffer overflow before reading CRC in pngpread.c (Warwick Allison) Added -soname to the loader flags in makefile.dec, makefile.sgi, and makefile.sggcc. Added "test-installed" target to makefile.linux, makefile.gcmmx, makefile.sgi, and makefile.sggcc. -version 1.2.4beta3 [June 28, 2002] + +Version 1.2.4beta3 [June 28, 2002] Plugged memory leak of row_buf in pngtest.c when there is a png_error(). Detect buffer overflow in pngpread.c when IDAT is corrupted with extra data. Added "test-installed" target to makefile.32sunu, makefile.64sunu, makefile.beos, makefile.darwin, makefile.dec, makefile.macosx, makefile.solaris, makefile.hpux, makefile.hpgcc, and makefile.so9. -version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] + +Version 1.2.4rc1 and 1.0.14rc1 [July 2, 2002] Added "test-installed" target to makefile.cygwin and makefile.sco. Revised pnggccrd.c to be able to back out version 1.0.x via PNG_1_0_X macro. -version 1.2.4 and 1.0.14 [July 8, 2002] +Version 1.2.4 and 1.0.14 [July 8, 2002] Changed png_warning() to png_error() when width is too large to process. -version 1.2.4patch01 [July 20, 2002] + +Version 1.2.4patch01 [July 20, 2002] Revised makefile.cygwin to use DLL number 12 instead of 13. -version 1.2.5beta1 [August 6, 2002] + +Version 1.2.5beta1 [August 6, 2002] Added code to contrib/gregbook/readpng2.c to ignore unused chunks. Replaced toucan.png in contrib/gregbook (it has been corrupt since 1.0.11) Removed some stray *.o files from contrib/gregbook. @@ -1199,36 +1342,43 @@ version 1.2.5beta1 [August 6, 2002] Prevent png_ptr->pass from exceeding 7 in png_push_finish_row(). Updated makefile.hpgcc Updated png.c and pnggccrd.c handling of return from png_mmx_support() -version 1.2.5beta2 [August 15, 2002] + +Version 1.2.5beta2 [August 15, 2002] Only issue png_warning() about "Too much data" in pngpread.c when avail_in is nonzero. Updated makefiles to install a separate libpng.so.3 with its own rpath. -version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] + +Version 1.2.5rc1 and 1.0.15rc1 [August 24, 2002] Revised makefiles to not remove previous minor versions of shared libraries. -version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] + +Version 1.2.5rc2 and 1.0.15rc2 [September 16, 2002] Revised 13 makefiles to remove "-lz" and "-L$(ZLIBLIB)", etc., from shared library loader directive. Added missing "$OBJSDLL" line to makefile.gcmmx. Added missing "; fi" to makefile.32sunu. -version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] + +Version 1.2.5rc3 and 1.0.15rc3 [September 18, 2002] Revised libpng-config script. -version 1.2.5 and 1.0.15 [October 3, 2002] +Version 1.2.5 and 1.0.15 [October 3, 2002] Revised makefile.macosx, makefile.darwin, makefile.hpgcc, and makefile.hpux, and makefile.aix. Relocated two misplaced PNGAPI lines in pngtest.c -version 1.2.6beta1 [October 22, 2002] + +Version 1.2.6beta1 [October 22, 2002] Commented out warning about uninitialized mmx_support in pnggccrd.c. Changed "IBMCPP__" flag to "__IBMCPP__" in pngconf.h. Relocated two more misplaced PNGAPI lines in pngtest.c Fixed memory overrun bug in png_do_read_filler() with 16-bit datastreams, introduced in version 1.0.2. Revised makefile.macosx, makefile.dec, makefile.aix, and makefile.32sunu. -version 1.2.6beta2 [November 1, 2002] + +Version 1.2.6beta2 [November 1, 2002] Added libpng-config "--ldopts" output. Added "AR=ar" and "ARFLAGS=rc" and changed "ar rc" to "$(AR) $(ARFLAGS)" in makefiles. -version 1.2.6beta3 [July 18, 2004] + +Version 1.2.6beta3 [July 18, 2004] Reverted makefile changes from version 1.2.6beta2 and some of the changes from version 1.2.6beta1; these will be postponed until version 1.2.7. Version 1.2.6 is going to be a simple bugfix release. @@ -1281,7 +1431,8 @@ version 1.2.6beta3 [July 18, 2004] Updated contrib/visupng/VisualPng.dsp (Cosmin). Updated contrib/visupng/cexcept.h to version 2.0.0 (Cosmin). Added a separate distribution with "configure" and supporting files (Junichi). -version 1.2.6beta4 [July 28, 2004] + +Version 1.2.6beta4 [July 28, 2004] Added user ability to change png_size_t via a PNG_SIZE_T macro. Added png_sizeof() and png_convert_size() functions. Added PNG_SIZE_MAX (maximum value of a png_size_t variable. @@ -1301,11 +1452,13 @@ version 1.2.6beta4 [July 28, 2004] Added PNG_NO_SEQUENTIAL_READ_SUPPORTED macro to conditionally remove sequential read support. Added some "#if PNG_WRITE_SUPPORTED" blocks. - Removed some redundancy with #ifdef/#endif in png_malloc_default(). - Use png_malloc instead of png_zalloc to allocate the pallete. -version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] - Fixed buffer overflow vulnerability in png_handle_tRNS() - Fixed integer arithmetic overflow vulnerability in png_read_png(). + Added #ifdef to remove some redundancy in png_malloc_default(). + Use png_malloc instead of png_zalloc to allocate the palette. + +Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] + Fixed buffer overflow vulnerability (CVE-2004-0597) in png_handle_tRNS(). + Fixed NULL dereference vulnerability (CVE-2004-0598) in png_handle_iCCP(). + Fixed integer overflow vulnerability (CVE-2004-0599) in png_read_png(). Fixed some harmless bugs in png_handle_sBIT, etc, that would cause duplicate chunk types to go undetected. Fixed some timestamps in the -config version @@ -1318,7 +1471,8 @@ version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] Fixed wrong cast of returns from png_get_user_width|height_max(). Changed some "keep the compiler happy" from empty statements to returns, Revised libpng.txt to remove 1.2.x stuff from the 1.0.x distribution -version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] + +Version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] Revised makefile.darwin and makefile.solaris. Removed makefile.macosx. Revised pngtest's png_debug_malloc() to use png_malloc() instead of png_malloc_default() which is not supposed to be exported. @@ -1332,91 +1486,106 @@ version 1.0.16rc2 and 1.2.6rc2 [August 7, 2004] Changed "HANDLE_CHUNK_*" to "PNG_HANDLE_CHUNK_*" (Cosmin) Added "-@/bin/rm -f $(DL)/$(LIBNAME).so.$(PNGMAJ)" to 15 *NIX makefiles. Added code to update the row_info->colortype in png_do_read_filler() (MSB). -version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] + +Version 1.0.16rc3 and 1.2.6rc3 [August 9, 2004] Eliminated use of "abs()" in testing cHRM and gAMA values, to avoid trouble with some 64-bit compilers. Created PNG_OUT_OF_RANGE() macro. Revised documentation of png_set_keep_unknown_chunks(). Check handle_as_unknown status in pngpread.c, as in pngread.c previously. Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_INTERNAL section of png.h Added "rim" definitions for CONST4 and CONST6 in pnggccrd.c -version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] + +Version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] Fixed mistake in pngtest.c introduced in 1.2.6rc2 (declaration of "pinfo" was out of place). -version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] - Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED - section of png.h where they were inadvertently placed in version rc3. -version 1.2.6 and 1.0.16 [August 15, 2004] +Version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] + Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED + section of png.h where they were inadvertently placed in version rc3. + +Version 1.2.6 and 1.0.16 [August 15, 2004] Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. -version 1.2.7beta1 [August 26, 2004] + +Version 1.2.7beta1 [August 26, 2004] Removed unused pngasmrd.h file. Removed references to uu.net for archived files. Added references to PNG Spec (second edition) and the PNG ISO/IEC Standard. Added "test-dd" target in 15 makefiles, to run pngtest in DESTDIR. Fixed bug with "optimized window size" in the IDAT datastream, that causes libpng to write PNG files with incorrect zlib header bytes. -version 1.2.7beta2 [August 28, 2004] + +Version 1.2.7beta2 [August 28, 2004] Fixed bug with sCAL chunk and big-endian machines (David Munro). Undid new code added in 1.2.6rc2 to update the color_type in png_set_filler(). Added png_set_add_alpha() that updates color type. -version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] + +Version 1.0.17rc1 and 1.2.7rc1 [September 4, 2004] Revised png_set_strip_filler() to not remove alpha if color_type has alpha. -version 1.2.7 and 1.0.17 [September 12, 2004] +Version 1.2.7 and 1.0.17 [September 12, 2004] Added makefile.hp64 Changed projects/msvc/png32ms.def to scripts/png32ms.def in makefile.cygwin -version 1.2.8beta1 [November 1, 2004] + +Version 1.2.8beta1 [November 1, 2004] Fixed bug in png_text_compress() that would fail to complete a large block. Fixed bug, introduced in libpng-1.2.7, that overruns a buffer during strip alpha operation in png_do_strip_filler(). Added PNG_1_2_X definition in pngconf.h - Comment out with #ifdef/#endif png_info_init in png.c and png_read_init - in pngread.c (as of 1.3.0) -version 1.2.8beta2 [November 2, 2004] + Use #ifdef to comment out png_info_init in png.c and png_read_init in + pngread.c (as of 1.3.0) + +Version 1.2.8beta2 [November 2, 2004] Reduce color_type to a nonalpha type after strip alpha operation in png_do_strip_filler(). -version 1.2.8beta3 [November 3, 2004] + +Version 1.2.8beta3 [November 3, 2004] Revised definitions of PNG_MAX_UINT_32, PNG_MAX_SIZE, and PNG_MAXSUM -version 1.2.8beta4 [November 12, 2004] + +Version 1.2.8beta4 [November 12, 2004] Fixed (again) definition of PNG_LIBPNG_VER_DLLNUM in png.h (Cosmin). Added PNG_LIBPNG_BUILD_PRIVATE in png.h (Cosmin). Set png_ptr->zstream.data_type to Z_BINARY, to avoid unnecessary detection of data type in deflate (Cosmin). Deprecated but continue to support SPECIALBUILD and PRIVATEBUILD in favor of PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. -version 1.2.8beta5 [November 20, 2004] + +Version 1.2.8beta5 [November 20, 2004] Use png_ptr->flags instead of png_ptr->transformations to pass PNG_STRIP_ALPHA info to png_do_strip_filler(), to preserve ABI compatibility. Revised handling of SPECIALBUILD, PRIVATEBUILD, PNG_LIBPNG_BUILD_SPECIAL_STRING and PNG_LIBPNG_BUILD_PRIVATE_STRING. -version 1.2.8rc1 [November 24, 2004] + +Version 1.2.8rc1 [November 24, 2004] Moved handling of BUILD macros from pngconf.h to png.h Added definition of PNG_LIBPNG_BASE_TYPE in png.h, inadvertently omitted from beta5. Revised scripts/pngw32.rc Despammed mailing addresses by masking "@" with "at". Inadvertently installed a supposedly faster test version of pngrutil.c -version 1.2.8rc2 [November 26, 2004] + +Version 1.2.8rc2 [November 26, 2004] Added two missing "\" in png.h Change tests in pngread.c and pngpread.c to if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) png_do_read_transformations(png_ptr); -version 1.2.8rc3 [November 28, 2004] + +Version 1.2.8rc3 [November 28, 2004] Reverted pngrutil.c to version libpng-1.2.8beta5. Added scripts/makefile.elf with supporting code in pngconf.h for symbol versioning (John Bowler). -version 1.2.8rc4 [November 29, 2004] + +Version 1.2.8rc4 [November 29, 2004] Added projects/visualc7 (Simon-pierre). -version 1.2.8rc5 [November 29, 2004] + +Version 1.2.8rc5 [November 29, 2004] Fixed new typo in scripts/pngw32.rc -version 1.2.8 [December 3, 2004] +Version 1.2.8 [December 3, 2004] Removed projects/visualc7, added projects/visualc71. -version 1.2.9beta1 [February 21, 2006] - +Version 1.2.9beta1 [February 21, 2006] Initialized some structure members in pngwutil.c to avoid gcc-4.0.0 complaints Revised man page and libpng.txt to make it clear that one should not call png_read_end or png_write_end after png_read_png or png_write_png. @@ -1438,8 +1607,7 @@ version 1.2.9beta1 [February 21, 2006] Fixed scripts/makefile.cygwin (Christian Biesinger, Cosmin). Default iTXt support was inadvertently enabled. -version 1.2.9beta2 [February 21, 2006] - +Version 1.2.9beta2 [February 21, 2006] Check for png_rgb_to_gray and png_gray_to_rgb read transformations before checking for png_read_dither in pngrtran.c Revised checking of chromaticity limits to accommodate extended RGB @@ -1452,8 +1620,7 @@ version 1.2.9beta2 [February 21, 2006] Eliminated distributions without the "configure" script. Updated INSTALL instructions. -version 1.2.9beta3 [February 24, 2006] - +Version 1.2.9beta3 [February 24, 2006] Fixed CRCRLF line endings in contrib/visupng/VisualPng.dsp Made libpng.pc respect EXEC_PREFIX (D. P. Kreil, J. Bowler) Removed reference to pngasmrd.h from Makefile.am @@ -1462,8 +1629,7 @@ version 1.2.9beta3 [February 24, 2006] Renamed ANNOUNCE to NEWS. Created AUTHORS file. -version 1.2.9beta4 [March 3, 2006] - +Version 1.2.9beta4 [March 3, 2006] Changed definition of PKGCONFIG from $prefix/lib to $libdir in configure.ac Reverted to filenames LICENSE and ANNOUNCE; removed AUTHORS and COPYING. Removed newline from the end of some error and warning messages. @@ -1474,17 +1640,17 @@ version 1.2.9beta4 [March 3, 2006] Added "OS2" to list of systems that don't need underscores, in pnggccrd.c Removed libpng version and date from *.c files. -version 1.2.9beta5 [March 4, 2006] +Version 1.2.9beta5 [March 4, 2006] Removed trailing blanks from source files. Put version and date of latest change in each source file, and changed copyright year accordingly. More cleanup of configure.ac, Makefile.am, and associated scripts. Restored scripts/makefile.elf which was inadvertently deleted. -version 1.2.9beta6 [March 6, 2006] +Version 1.2.9beta6 [March 6, 2006] Fixed typo (RELEASE) in configuration files. -version 1.2.9beta7 [March 7, 2006] +Version 1.2.9beta7 [March 7, 2006] Removed libpng.vers and libpng.sym from libpng12_la_SOURCES in Makefile.am Fixed inconsistent #ifdef's around png_sig_bytes() and png_set_sCAL_s() in png.h. @@ -1492,7 +1658,7 @@ version 1.2.9beta7 [March 7, 2006] Made cosmetic changes to some makefiles, adding LN_SF and other macros. Made some makefiles accept "exec_prefix". -version 1.2.9beta8 [March 9, 2006] +Version 1.2.9beta8 [March 9, 2006] Fixed some "#if defined (..." which should be "#if defined(..." Bug introduced in libpng-1.2.8. Fixed inconsistency in definition of png_default_read_data() @@ -1503,82 +1669,82 @@ version 1.2.9beta8 [March 9, 2006] Added png_set_expand_gray_1_2_4_to_8() and deprecated png_set_gray_1_2_4_to_8() which also expands tRNS to alpha. -version 1.2.9beta9 [March 10, 2006] +Version 1.2.9beta9 [March 10, 2006] Include "config.h" in pngconf.h when available. Added some checks for NULL png_ptr or NULL info_ptr (timeless) -version 1.2.9beta10 [March 20, 2006] +Version 1.2.9beta10 [March 20, 2006] Removed extra CR from contrib/visualpng/VisualPng.dsw (Cosmin) Made pnggccrd.c PIC-compliant (Christian Aichinger). Added makefile.mingw (Wolfgang Glas). Revised pngconf.h MMX checking. -version 1.2.9beta11 [March 22, 2006] +Version 1.2.9beta11 [March 22, 2006] Fixed out-of-order declaration in pngwrite.c that was introduced in beta9 Simplified some makefiles by using LIBSO, LIBSOMAJ, and LIBSOVER macros. -version 1.2.9rc1 [March 31, 2006] +Version 1.2.9rc1 [March 31, 2006] Defined PNG_USER_PRIVATEBUILD when including "pngusr.h" (Cosmin). Removed nonsensical assertion check from pngtest.c (Cosmin). -version 1.2.9 [April 14, 2006] +Version 1.2.9 [April 14, 2006] Revised makefile.beos and added "none" selector in ltmain.sh -version 1.2.10beta1 [April 15, 2006] +Version 1.2.10beta1 [April 15, 2006] Renamed "config.h" to "png_conf.h" and revised Makefile.am to add -DPNG_BUILDING_LIBPNG to compile directive, and modified pngconf.h to include png_conf.h only when PNG_BUILDING_LIBPNG is defined. -version 1.2.10beta2 [April 15, 2006] +Version 1.2.10beta2 [April 15, 2006] Manually updated Makefile.in and configure. Changed png_conf.h.in back to config.h. -version 1.2.10beta3 [April 15, 2006] +Version 1.2.10beta3 [April 15, 2006] Change png_conf.h back to config.h in pngconf.h. -version 1.2.10beta4 [April 16, 2006] +Version 1.2.10beta4 [April 16, 2006] Change PNG_BUILDING_LIBPNG to PNG_CONFIGURE_LIBPNG in config/Makefile*. -version 1.2.10beta5 [April 16, 2006] +Version 1.2.10beta5 [April 16, 2006] Added a configure check for compiling assembler code in pnggccrd.c -version 1.2.10beta6 [April 17, 2006] +Version 1.2.10beta6 [April 17, 2006] Revised the configure check for pnggccrd.c Moved -DPNG_CONFIGURE_LIBPNG into @LIBPNG_DEFINES@ Added @LIBPNG_DEFINES@ to arguments when building libpng.sym -version 1.2.10beta7 [April 18, 2006] +Version 1.2.10beta7 [April 18, 2006] Change "exec_prefix=$prefix" to "exec_prefix=$(prefix)" in makefiles. -version 1.2.10rc1 [April 19, 2006] +Version 1.2.10rc1 [April 19, 2006] Ensure pngconf.h doesn't define both PNG_USE_PNGGCCRD and PNG_USE_PNGVCRD Fixed "LN_FS" typo in makefile.sco and makefile.solaris. -version 1.2.10rc2 [April 20, 2006] +Version 1.2.10rc2 [April 20, 2006] Added a backslash between -DPNG_CONFIGURE_LIBPNG and -DPNG_NO_ASSEMBLER_CODE in configure.ac and configure Made the configure warning about versioned symbols less arrogant. -version 1.2.10rc3 [April 21, 2006] +Version 1.2.10rc3 [April 21, 2006] Added a note in libpng.txt that png_set_sig_bytes(8) can be used when writing an embedded PNG without the 8-byte signature. Revised makefiles and configure to avoid making links to libpng.so.* -version 1.2.10 [April 23, 2006] +Version 1.2.10 [April 23, 2006] Reverted configure to "rc2" state. -version 1.2.11beta1 [May 31, 2006] +Version 1.2.11beta1 [May 31, 2006] scripts/libpng.pc.in contained "configure" style version info and would not work with makefiles. The shared-library makefiles were linking to libpng.so.0 instead of libpng.so.3 compatibility as the library. -version 1.2.11beta2 [June 2, 2006] +Version 1.2.11beta2 [June 2, 2006] Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid buffer overflow. Fixed bug in example.c (png_set_palette_rgb -> png_set_palette_to_rgb) -version 1.2.11beta3 [June 5, 2006] +Version 1.2.11beta3 [June 5, 2006] Prepended "#! /bin/sh" to ltmail.sh and contrib/pngminus/*.sh (Cosmin). Removed the accidental leftover Makefile.in~ (Cosmin). Avoided potential buffer overflow and optimized buffer in @@ -1586,116 +1752,116 @@ version 1.2.11beta3 [June 5, 2006] Removed the include directories and libraries from CFLAGS and LDFLAGS in scripts/makefile.gcc (Nelson A. de Oliveira, Cosmin). -version 1.2.11beta4 [June 6, 2006] +Version 1.2.11beta4 [June 6, 2006] Allow zero-length IDAT chunks after the entire zlib datastream, but not after another intervening chunk type. -version 1.0.19rc1, 1.2.11rc1 [June 13, 2006] +Version 1.0.19rc1, 1.2.11rc1 [June 13, 2006] Deleted extraneous square brackets from [config.h] in configure.ac -version 1.0.19rc2, 1.2.11rc2 [June 14, 2006] +Version 1.0.19rc2, 1.2.11rc2 [June 14, 2006] Added prototypes for PNG_INCH_CONVERSIONS functions to png.h Revised INSTALL and autogen.sh Fixed typo in several makefiles (-W1 should be -Wl) Added typedef for png_int_32 and png_uint_32 on 64-bit systems. -version 1.0.19rc3, 1.2.11rc3 [June 15, 2006] +Version 1.0.19rc3, 1.2.11rc3 [June 15, 2006] Removed the new typedefs for 64-bit systems (delay until version 1.4.0) Added one zero element to png_gamma_shift[] array in pngrtran.c to avoid reading out of bounds. -version 1.0.19rc4, 1.2.11rc4 [June 15, 2006] +Version 1.0.19rc4, 1.2.11rc4 [June 15, 2006] Really removed the new typedefs for 64-bit systems. -version 1.0.19rc5, 1.2.11rc5 [June 22, 2006] +Version 1.0.19rc5, 1.2.11rc5 [June 22, 2006] Removed png_sig_bytes entry from scripts/pngw32.def -version 1.0.19, 1.2.11 [June 26, 2006] +Version 1.0.19, 1.2.11 [June 26, 2006] None. -version 1.0.20, 1.2.12 [June 27, 2006] +Version 1.0.20, 1.2.12 [June 27, 2006] Really increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid buffer overflow. -version 1.2.13beta1 [October 2, 2006] +Version 1.2.13beta1 [October 2, 2006] Removed AC_FUNC_MALLOC from configure.ac Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h Change "logical" to "bitwise" throughout documentation. - Detect and fix attempt to write wrong iCCP profile length. + Detect and fix attempt to write wrong iCCP profile length (CVE-2006-7244) -version 1.0.21, 1.2.13 [November 14, 2006] +Version 1.0.21, 1.2.13 [November 14, 2006] Fix potential buffer overflow in sPLT chunk handler. Fix Makefile.am to not try to link to noexistent files. Check all exported functions for NULL png_ptr. -version 1.2.14beta1 [November 17, 2006] +Version 1.2.14beta1 [November 17, 2006] Relocated three misplaced tests for NULL png_ptr. Built Makefile.in with automake-1.9.6 instead of 1.9.2. Build configure with autoconf-2.60 instead of 2.59 -version 1.2.14beta2 [November 17, 2006] +Version 1.2.14beta2 [November 17, 2006] Added some typecasts in png_zalloc(). -version 1.2.14rc1 [November 20, 2006] +Version 1.2.14rc1 [November 20, 2006] Changed "strtod" to "png_strtod" in pngrutil.c -version 1.0.22, 1.2.14 [November 27, 2006] +Version 1.0.22, 1.2.14 [November 27, 2006] Added missing "$(srcdir)" in Makefile.am and Makefile.in -version 1.2.15beta1 [December 3, 2006] +Version 1.2.15beta1 [December 3, 2006] Generated configure with autoconf-2.61 instead of 2.60 Revised configure.ac to update libpng.pc and libpng-config. -version 1.2.15beta2 [December 3, 2006] +Version 1.2.15beta2 [December 3, 2006] Always export MMX asm functions, just stubs if not building pnggccrd.c -version 1.2.15beta3 [December 4, 2006] +Version 1.2.15beta3 [December 4, 2006] Add "png_bytep" typecast to profile while calculating length in pngwutil.c -version 1.2.15beta4 [December 7, 2006] +Version 1.2.15beta4 [December 7, 2006] Added scripts/CMakeLists.txt Changed PNG_NO_ASSEMBLER_CODE to PNG_NO_MMX_CODE in scripts, like 1.4.0beta -version 1.2.15beta5 [December 7, 2006] +Version 1.2.15beta5 [December 7, 2006] Changed some instances of PNG_ASSEMBLER_* to PNG_MMX_* in pnggccrd.c Revised scripts/CMakeLists.txt -version 1.2.15beta6 [December 13, 2006] +Version 1.2.15beta6 [December 13, 2006] Revised scripts/CMakeLists.txt and configure.ac -version 1.2.15rc1 [December 18, 2006] +Version 1.2.15rc1 [December 18, 2006] Revised scripts/CMakeLists.txt -version 1.2.15rc2 [December 21, 2006] +Version 1.2.15rc2 [December 21, 2006] Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. Added scripts/makefile.nommx -version 1.2.15rc3 [December 25, 2006] +Version 1.2.15rc3 [December 25, 2006] Fixed shared library numbering error that was introduced in 1.2.15beta6. -version 1.2.15rc4 [December 27, 2006] +Version 1.2.15rc4 [December 27, 2006] Fixed handling of rgb_to_gray when png_ptr->color.gray isn't set. -version 1.2.15rc5 [December 31, 2006] +Version 1.2.15rc5 [December 31, 2006] Revised handling of rgb_to_gray. -version 1.0.23, 1.2.15 [January 5, 2007] +Version 1.2.15 [January 5, 2007] Added some (unsigned long) typecasts in pngtest.c to avoid printing errors. -version 1.2.16beta1 [January 6, 2007] +Version 1.2.16beta1 [January 6, 2007] Fix bugs in makefile.nommx -version 1.2.16beta2 [January 16, 2007] +Version 1.2.16beta2 [January 16, 2007] Revised scripts/CMakeLists.txt -version 1.0.24, 1.2.16 [January 31, 2007] +Version 1.2.16 [January 31, 2007] No changes. -version 1.2.17beta1 [March 6, 2007] +Version 1.2.17beta1 [March 6, 2007] Revised scripts/CMakeLists.txt to install both shared and static libraries. Deleted a redundant line from pngset.c. -version 1.2.17beta2 [April 26, 2007] +Version 1.2.17beta2 [April 26, 2007] Relocated misplaced test for png_ptr == NULL in pngpread.c Change "==" to "&" for testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN flags. @@ -1704,10 +1870,10 @@ version 1.2.17beta2 [April 26, 2007] Added "const" to some array declarations. Mention examples of libpng usage in the libpng*.txt and libpng.3 documents. -version 1.2.17rc1 [May 4, 2007] +Version 1.2.17rc1 [May 4, 2007] No changes. -version 1.2.17rc2 [May 8, 2007] +Version 1.2.17rc2 [May 8, 2007] Moved several PNG_HAVE_* macros out of PNG_INTERNAL because applications calling set_unknown_chunk_location() need them. Changed transformation flag from PNG_EXPAND_tRNS to PNG_EXPAND in @@ -1716,693 +1882,445 @@ version 1.2.17rc2 [May 8, 2007] can be free'ed in case of error. Revised unknown chunk handling in pngrutil.c and pngpread.c to use this structure. -version 1.2.17rc3 [May 8, 2007] +Version 1.2.17rc3 [May 8, 2007] Revised symbol-handling in configure script. -version 1.2.17rc4 [May 10, 2007] +Version 1.2.17rc4 [May 10, 2007] Revised unknown chunk handling to avoid storing unknown critical chunks. -version 1.0.25 [May 15, 2007] -version 1.2.17 [May 15, 2007] +Version 1.0.25 [May 15, 2007] +Version 1.2.17 [May 15, 2007] Added "png_ptr->num_trans=0" before error return in png_handle_tRNS, to eliminate a vulnerability (CVE-2007-2445, CERT VU#684664) -version 1.0.26 [May 15, 2007] -version 1.2.18 [May 15, 2007] +Version 1.0.26 [May 15, 2007] +Version 1.2.18 [May 15, 2007] Reverted the libpng-1.2.17rc3 change to symbol-handling in configure script -version 1.2.19beta1 [May 18, 2007] +Version 1.2.19beta1 [May 18, 2007] Changed "const static" to "static PNG_CONST" everywhere, mostly undoing change of libpng-1.2.17beta2. Changed other "const" to "PNG_CONST" Changed some handling of unused parameters, to avoid compiler warnings. "if (unused == NULL) return;" becomes "unused = unused". -version 1.2.19beta2 [May 18, 2007] +Version 1.2.19beta2 [May 18, 2007] Only use the valid bits of tRNS value in png_do_expand() (Brian Cartier) -version 1.2.19beta3 [May 19, 2007] +Version 1.2.19beta3 [May 19, 2007] Add some "png_byte" typecasts in png_check_keyword() and write new_key instead of key in zTXt chunk (Kevin Ryde). -version 1.2.19beta4 [May 21, 2007] +Version 1.2.19beta4 [May 21, 2007] Add png_snprintf() function and use it in place of sprint() for improved defense against buffer overflows. -version 1.2.19beta5 [May 21, 2007] +Version 1.2.19beta5 [May 21, 2007] Fixed png_handle_tRNS() to only use the valid bits of tRNS value. Changed handling of more unused parameters, to avoid compiler warnings. Removed some PNG_CONST in pngwutil.c to avoid compiler warnings. -version 1.2.19beta6 [May 22, 2007] +Version 1.2.19beta6 [May 22, 2007] Added some #ifdef PNG_MMX_CODE_SUPPORTED where needed in pngvcrd.c Added a special "_MSC_VER" case that defines png_snprintf to _snprintf -version 1.2.19beta7 [May 22, 2007] +Version 1.2.19beta7 [May 22, 2007] Squelched png_squelch_warnings() in pnggccrd.c and added - an #ifdef PNG_MMX_CODE_SUPPORTED/#endif block around the declarations - that caused the warnings that png_squelch_warnings was squelching. + an #ifdef PNG_MMX_CODE_SUPPORTED block around the declarations that caused + the warnings that png_squelch_warnings was squelching. -version 1.2.19beta8 [May 22, 2007] +Version 1.2.19beta8 [May 22, 2007] Removed __MMX__ from test in pngconf.h. -version 1.2.19beta9 [May 23, 2007] +Version 1.2.19beta9 [May 23, 2007] Made png_squelch_warnings() available via PNG_SQUELCH_WARNINGS macro. Revised png_squelch_warnings() so it might work. Updated makefile.sgcc and makefile.solaris; added makefile.solaris-x86. -version 1.2.19beta10 [May 24, 2007] +Version 1.2.19beta10 [May 24, 2007] Resquelched png_squelch_warnings(), use "__attribute__((used))" instead. -version 1.2.19beta11 [May 28, 2007] - Return 0 from png_get_sPLT() and png_get_unknown_chunks() if png_ptr is NULL; - changed three remaining instances of png_strcpy() to png_strncpy() (David - Hill). - Make test for NULL row_buf at the beginning of png_do_read_transformations - unconditional. +Version 1.4.0beta1 [April 20, 2006] + Enabled iTXt support (changes png_struct, thus requires so-number change). + Cleaned up PNG_ASSEMBLER_CODE_SUPPORTED vs PNG_MMX_CODE_SUPPORTED + Eliminated PNG_1_0_X and PNG_1_2_X macros. + Removed deprecated functions png_read_init, png_write_init, png_info_init, + png_permit_empty_plte, png_set_gray_1_2_4_to_8, png_check_sig, and + removed the deprecated macro PNG_MAX_UINT. + Moved "PNG_INTERNAL" parts of png.h and pngconf.h into pngintrn.h + Removed many WIN32_WCE #ifdefs (Cosmin). + Reduced dependency on C-runtime library when on Windows (Simon-Pierre) + Replaced sprintf() with png_sprintf() (Simon-Pierre) -version 1.2.19beta12 [May 28, 2007] - Revised pnggccrd.c. +Version 1.4.0beta2 [April 20, 2006] + Revised makefiles and configure to avoid making links to libpng.so.* + Moved some leftover MMX-related defines from pngconf.h to pngintrn.h + Updated scripts/pngos2.def, pngw32.def, and projects/wince/png32ce.def -version 1.2.19beta13 [June 14, 2007] - Prefer PNG_USE_PNGVCRD when _MSC_VER is defined in pngconf.h +Version 1.4.0beta3 [May 10, 2006] + Updated scripts/pngw32.def to comment out MMX functions. + Added PNG_NO_GET_INT_32 and PNG_NO_SAVE_INT_32 macros. + Scripts/libpng.pc.in contained "configure" style version info and would + not work with makefiles. + Revised pngconf.h and added pngconf.h.in, so makefiles and configure can + pass defines to libpng and applications. -version 1.2.19beta14 [June 16, 2007] - Fix bug with handling of 16-bit transparency, introduced in 1.2.19beta2 +Version 1.4.0beta4 [May 11, 2006] + Revised configure.ac, Makefile.am, and many of the makefiles to write + their defines in pngconf.h. -version 1.2.19beta15 [June 17, 2007] - Revised pnggccrd.c. +Version 1.4.0beta5 [May 15, 2006] + Added a missing semicolon in Makefile.am and Makefile.in + Deleted extraneous square brackets from configure.ac -version 1.2.19beta16 [June 18, 2007] - Revised pnggccrd.c again. - Updated contrib/gregbook. - Changed '#include "pnggccrd.c"' to 'include "$srcdir/pnggccrd.c"' - in configure.ac +Version 1.4.0beta6 [June 2, 2006] + Increased sprintf buffer from 50 to 52 chars in pngrutil.c to avoid + buffer overflow. + Changed sonum from 0 to 1. + Removed unused prototype for png_check_sig() from png.h -version 1.2.19beta17 [June 19, 2007] - Revised many of the makefiles, to set -DPNG_NO_MMX_CODE where needed - and to not use -O3 unless -DPNG_NO_MMX_CODE is also set. +Version 1.4.0beta7 [June 16, 2006] + Exported png_write_sig (Cosmin). + Optimized buffer in png_handle_cHRM() (Cosmin). + Set pHYs = 2835 x 2835 pixels per meter, and added + sCAL = 0.352778e-3 x 0.352778e-3 meters, in pngtest.png (Cosmin). + Added png_set_benign_errors(), png_benign_error(), png_chunk_benign_error(). + Added typedef for png_int_32 and png_uint_32 on 64-bit systems. + Added "(unsigned long)" typecast on png_uint_32 variables in printf lists. -version 1.2.19beta18 [June 23, 2007] - Replaced some C++ style comments with C style comments in pnggccrd.c. - Copied optimized C code from pnggccrd.c to pngrutil.c, removed dependency - on pnggccrd.o from many makefiles. - Added sl and dylib to list of extensions be installed by Makefile.am +Version 1.4.0beta8 [June 22, 2006] + Added demonstration of user chunk support in pngtest.c, to support the + public sTER chunk and a private vpAg chunk. -version 1.2.19beta19 [June 28, 2007] - Fixed testing PNG_RGB_TO_GRAY_ERR & PNG_RGB_TO_GRAY_WARN in pngrtran.c - More cleanup of pnggccrd.c and pngvcrd.c +Version 1.4.0beta9 [July 3, 2006] + Removed ordinals from scripts/pngw32.def and removed png_info_int and + png_set_gray_1_2_4_to_8 entries. + Inline call of png_get_uint_32() in png_get_uint_31(). + Use png_get_uint_31() to get vpAg width and height in pngtest.c + Removed WINCE and Netware projects. + Removed standalone Y2KINFO file. -version 1.2.19beta20 [June 29, 2007] - Rebuilt Makefile.in and configure using libtool-1.5.24. - Fixed typo in pnggccrd.c +Version 1.4.0beta10 [July 12, 2006] + Eliminated automatic copy of pngconf.h to pngconf.h.in from configure and + some makefiles, because it was not working reliably. Instead, distribute + pngconf.h.in along with pngconf.h and cause configure and some of the + makefiles to update pngconf.h from pngconf.h.in. + Added pngconf.h to DEPENDENCIES in Makefile.am -version 1.2.19beta21 [June 30, 2007] - More revision of pnggccrd.c - Added "test" target to Makefile.in and Makefile.am +Version 1.4.0beta11 [August 19, 2006] + Removed AC_FUNC_MALLOC from configure.ac. + Added a warning when writing iCCP profile with mismatched profile length. + Patched pnggccrd.c to assemble on x86_64 platforms. + Moved chunk header reading into a separate function png_read_chunk_header() + in pngrutil.c. The chunk header (len+sig) is now serialized in a single + operation (Cosmin). + Implemented support for I/O states. Added png_ptr member io_state, and + functions png_get_io_chunk_name() and png_get_io_state() in pngget.c + (Cosmin). + Added png_get_io_chunk_name and png_get_io_state to scripts/*.def (Cosmin). + Renamed scripts/pngw32.* to scripts/pngwin.* (Cosmin). + Removed the include directories and libraries from CFLAGS and LDFLAGS + in scripts/makefile.gcc (Cosmin). + Used png_save_uint_32() to set vpAg width and height in pngtest.c (Cosmin). + Cast to proper type when getting/setting vpAg units in pngtest.c (Cosmin). + Added pngintrn.h to the Visual C++ projects (Cosmin). + Removed scripts/list (Cosmin). + Updated copyright year in scripts/pngwin.def (Cosmin). + Removed PNG_TYPECAST_NULL and used standard NULL consistently (Cosmin). + Disallowed the user to redefine png_size_t, and enforced a consistent use + of png_size_t across libpng (Cosmin). + Changed the type of png_ptr->rowbytes, PNG_ROWBYTES() and friends + to png_size_t (Cosmin). + Removed png_convert_size() and replaced png_sizeof with sizeof (Cosmin). + Removed some unnecessary type casts (Cosmin). + Changed prototype of png_get_compression_buffer_size() and + png_set_compression_buffer_size() to work with png_size_t instead of + png_uint_32 (Cosmin). + Removed png_memcpy_check() and png_memset_check() (Cosmin). + Fixed a typo (png_byte --> png_bytep) in libpng.3 and libpng.txt (Cosmin). + Clarified that png_zalloc() does not clear the allocated memory, + and png_zalloc() and png_zfree() cannot be PNGAPI (Cosmin). + Renamed png_mem_size_t to png_alloc_size_t, fixed its definition in + pngconf.h, and used it in all memory allocation functions (Cosmin). + Renamed pngintrn.h to pngpriv.h, added a comment at the top of the file + mentioning that the symbols declared in that file are private, and + updated the scripts and the Visual C++ projects accordingly (Cosmin). + Removed circular references between pngconf.h and pngconf.h.in in + scripts/makefile.vc*win32 (Cosmin). + Removing trailing '.' from the warning and error messages (Cosmin). + Added pngdefs.h that is built by makefile or configure, instead of + pngconf.h.in (Glenn). + Detect and fix attempt to write wrong iCCP profile length. -version 1.2.19beta22 [July 3, 2007] - Added info about pngrutil/pnggccrd/pngvcrd to png_get_header_version() - Fix type definition of dummy_value_a, b in pnggccrd.c +Version 1.4.0beta12 [October 19, 2006] + Changed "logical" to "bitwise" in the documentation. + Work around Intel-Mac compiler bug by setting PNG_NO_MMX_CODE in pngconf.h + Add a typecast to stifle compiler warning in pngrutil.c -version 1.2.19beta23 [July 10, 2007] - Revert change to type definition of dummy_value_a, b in pnggccrd.c - Make sure __PIC__ is defined in pnggccrd.c when PIC is defined. - Require gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW on x86_64 platforms +Version 1.4.0beta13 [November 10, 2006] + Fix potential buffer overflow in sPLT chunk handler. + Fix Makefile.am to not try to link to noexistent files. -version 1.2.19beta24 [July 14, 2007] - Added PNG_NO_READ_FILTER, PNG_NO_WRITE_FILTER, PNG_NO_WARNING macros. - Added contrib/pngminim to demonstrate building minimal encoder and decoder +Version 1.4.0beta14 [November 15, 2006] + Check all exported functions for NULL png_ptr. -version 1.2.19beta25 [July 15, 2007] - Removed the new PNG_NO_READ_FILTER macro since it would make the library - unable to read valid PNG files, and filtering is at the heart of the - PNG format. +Version 1.4.0beta15 [November 17, 2006] + Relocated two misplaced tests for NULL png_ptr. + Built Makefile.in with automake-1.9.6 instead of 1.9.2. + Build configure with autoconf-2.60 instead of 2.59 + Add "install: all" in Makefile.am so "configure; make install" will work. -version 1.2.19beta26 [July 16, 2007] - Changed "png_free(str)" to "png_free(png_ptr,str)" in pngrutil.c WinCE - code (Yves Piguet). This bug was introduced in libpng-1.2.14. - Updated scripts/CMakeLists.txt - Relocated a misplaced #endif in pnggccrd.c +Version 1.4.0beta16 [November 17, 2006] + Added a typecast in png_zalloc(). -version 1.2.19beta27 [July 17, 2007] - Fixed incorrect stride and number of bytes copied (was 4 instead of - 6 bytes) in the cleanup loop of pnggccrd.c and pngvcrd.c for handling - the end of 48-bit interlaced rows (Glenn R-P). +Version 1.4.0beta17 [December 4, 2006] + Changed "new_key[79] = '\0';" to "(*new_key)[79] = '\0';" in pngwutil.c + Add "png_bytep" typecast to profile while calculating length in pngwutil.c -version 1.2.19beta28 [July 19, 2007] - Removed requirement for gcc-4.1 or better to use PNG_HAVE_MMX_FILTER_ROW - on x86_64 platforms - Added png_warning() in pngrutil.c for short iCCP, iTXt, sPLT, or zTXT chunks. - Revised pngtest.c so warnings are displayed regardless of PNG_NO_STDIO. +Version 1.4.0beta18 [December 7, 2006] + Added scripts/CMakeLists.txt -version 1.2.19beta29 [July 20, 2007] - Fix typo in pnggccrd.c (%%eax should be %%ax in secondloop48) - -version 1.2.19beta30 [July 26, 2007] - Revised pnggccrd.c - -version 1.2.19beta31 [July 27, 2007] - Fix typos in pnggccrd.c - -version 1.0.27rc1 and 1.2.19rc1 [July 31, 2007] - Disable PNG_MMX_CODE_SUPPORTED when PNG_ASSEMBLER_CODE_SUPPORTED is off. - Enable PNG_MMX_READ_FILTER_* by default, except when gcc-3.x is being - used (they were inadvertently disabled in libpng-1.2.19beta23). - Fix some debugging statements in pnggccrd.c and pngrutil.c - Added information about disabling the MMX code in libpng documentation. - -version 1.0.27rc2 and 1.2.19rc2 [August 4, 2007] - Removed some "#if 0" blocks. - Made a global struct local in pngvcrd.c to make it thread safe. - Issue a png_error() if application attempts to transform a row tht - has not been initialized. - -version 1.0.27rc3 and 1.2.19rc3 [August 9, 2007] - Slightly revised pngvcrd.c - -version 1.0.27rc4 and 1.2.19rc4 [August 9, 2007] - Revised pnggccrd.c debugging change of rc1, which was broken. +Version 1.4.0beta19 [May 16, 2007] Revised scripts/CMakeLists.txt - Change default to PNG_NO_GLOBAL_ARRAYS for MSVC. - Turn off PNG_FLAG_ROW_INIT flag when setting transforms that expand pixels. - -version 1.0.27rc5 and 1.2.19rc5 [August 10, 2007] - Fix typo (missing '"') in pnggccrd.c - Revise handling of png_strtod in recent versions of WINCE - -version 1.0.27rc6 and 1.2.19rc6 [August 15, 2007] - Fix typo (missing ',') in contrib/gregbook/readpng2.c - Undid row initialization error exit added to rc2 and rc4. - -version 1.0.27 and 1.2.19 [August 18, 2007] - Conditionally restored row initialization error exit. - -version 1.2.20beta01 [August 19, 2007] - Fixed problem with compiling pnggccrd.c on Intel-Apple platforms. - Changed png_malloc() to png_malloc_warn() in png_set_sPLT(). - Added PNG_NO_ERROR_TEXT feature, with demo in contrib/pngminim - Removed define PNG_WARN_UNINITIALIZED_ROW 1 /* 0: warning; 1: error */ - because it caused some trouble. - -version 1.2.20beta02 [August 20, 2007] - Avoid compiling pnggccrd.c on Intel-Apple platforms. - -version 1.2.20beta03 [August 20, 2007] - Added "/D PNG_NO_MMX_CODE" to the non-mmx builds of projects/visualc6 - and visualc71. - -version 1.2.20beta04 [August 21, 2007] - Revised pngvcrd.c for improved efficiency (Steve Snyder). - -version 1.2.20rc1 [August 23, 2007] - Revised pngconf.h to set PNG_NO_MMX_CODE for gcc-3.x compilers. - -version 1.2.20rc2 [August 27, 2007] - Revised scripts/CMakeLists.txt - Revised #ifdefs to ensure one and only one of pnggccrd.c, pngvcrd.c, - or part of pngrutil.c is selected. - -version 1.2.20rc3 [August 30, 2007] - Remove a little more code in pngwutil.c when PNG_NO_WRITE_FILTER is selected. - Added /D _CRT_SECURE_NO_WARNINGS to visual6c and visualc71 projects. - Compile png_mmx_support() in png.c even when PNG_NO_MMX_CODE is defined. - Restored a "superfluous" #ifdef that was removed from 1.2.20rc2 pnggccrd.c, - breaking the png_mmx_support() function. - -version 1.2.20rc4 [September 1, 2007] - Removed Intel contributions (MMX, Optimized C). - -version 1.2.20rc5 [September 2, 2007] - Restored configure and Makefile.in to rc3 and put a snippet of code in - pnggccrd.c, to ensure configure makes the same PNG_NO_MMX_CODE selection - -version 1.2.20rc6 [September 2, 2007] - Fixed bugs in scripts/CMakeLists.txt - Removed pngvcrd.c references from msvc projects. - -version 1.0.28 and 1.2.20 [September 8, 2007] - Removed "(NO READ SUPPORT)" from png_get_header_version() string. - -version 1.2.21beta1 [September 14, 2007] - Fixed various mistakes reported by George Cook and Jeff Phillips: - logical vs bitwise NOT in pngrtran.c, bug introduced in 1.2.19rc2 - 16-bit cheap transparency expansion, bug introduced in 1.2.19beta2 - errors with sizeof(unknown_chunk.name), bugs introduced in 1.2.19beta11 - <= compare with unsigned var in pngset.c, should be ==. - -version 1.2.21beta2 [September 18, 2007] - Removed some extraneous typecasts. - -version 1.2.21rc1 [September 25, 2007] - Fixed potential out-of-bounds reads in png_handle_pCAL() and - png_handle_ztXt() ("flayer" results reported by Tavis Ormandy). - -version 1.2.21rc2 [September 26, 2007] - Fixed potential out-of-bounds reads in png_handle_sCAL(), - png_handle_iTXt(), and png_push_read_tEXt(). - Remove some PNG_CONST declarations from pngwutil.c to avoid compiler warnings - Revised makefiles to update paths in libpng.pc properly. - -version 1.2.21rc3 [September 27, 2007] - Revised makefiles to update "Libs" in libpng.pc properly. - -version 1.0.29 and 1.2.21rc3 [October 4, 2007] - No changes. - -version 1.2.22beta1 [October 4, 2007] - Again, fixed logical vs bitwise NOT in pngrtran.c, bug introduced - in 1.2.19rc2 - -version 1.2.22beta2 [October 5, 2007] - Fixed string length error in pngset.c (caused crashes while decoding iCCP) - Add terminating NULL after each instance of png_strncpy(). - -version 1.2.22beta3 [October 6, 2007] - Fix two off-by-one terminating NULL after png_strncpy(). - -version 1.2.22beta4 [October 7, 2007] - Changed some 0 to '\0'. - -version 1.0.30rc1 and 1.2.22rc1 [October 8, 2007] - No changes. - -version 1.0.30 and 1.2.22 [October 13, 2007] - No changes. - -version 1.2.23beta01 [October 15, 2007] - Reduced number of invocations of png_strlen() in pngset.c. - Changed [azAZ09_] to [_abcde...89] in Makefile.am for better localization. - -version 1.2.23beta02 [October 16, 2007] - Eliminated png_strncpy() and png_strcpy() (Pierre Poissinger) - Changed $AN to $(AN) in Makefile.am. - -version 1.2.23beta03 [October 16, 2007] - Fixed off-by-one error in pngset.c - Restore statement to set last character of buffer to \0 in pngerror.c - -version 1.2.23beta04 [October 23, 2007] - Reject attempt to set all-zero cHRM values. - -version 1.2.23beta05 [October 26, 2007] - Add missing quotes in projects/visualc6, lost in version 1.2.20rc3 - -version 1.2.23rc01 [November 2, 2007] - No changes. - -version 1.2.23 [November 6, 2007] - No changes. - -version 1.2.24beta01 [November 19, 2007] - Moved misplaced test for malloc failure in png_set_sPLT(). This bug was - introduced in libpng-1.2.20beta01. - Ifdef out avg_row etc from png.h and pngwrite.c when PNG_NO_WRITE_FILTER - Do not use png_ptr->free_fn and png_ptr->mem_fn in png_destroy_read_struct() - when png_ptr is NULL (Marshall Clow). - Updated handling of symbol prefixes in Makefile.am and configure.ac (Mike - Frysinger). - -version 1.2.24beta02 [November 30, 2007] - Removed a useless test and fixed incorrect test in png_set_cHRM_fixed() - (David Hill). - -version 1.2.24rc01 [December 7, 2007] - No changes. - -version 1.2.24 [December 14, 2007] - Make sure not to redefine _BSD_SOURCE in pngconf.h - Revised gather.sh and makefile.std in contrib/pngminim to avoid compiling - unused files. - -version 1.2.25beta01 [January 7, 2008] - Fixed bug with unknown chunk handling, introduced in version 1.2.17rc2 - -version 1.2.25beta02 [January 10, 2008] - Prevent gamma from being applied twice. - -version 1.2.25rc01 [January 17, 2008] - No changes. - -version 1.2.25beta03 [January 22, 2008] - Fixed some continue-after-malloc-failure errors in pngset.c (David Hill) - Check for info_ptr == NULL in png_read_info() and png_process_data(). - Check for possible use of NULL user_png_ver[] in png_create_read_struct(). - Change "if (swidth == NULL)" to "if (sheight == NULL)" in png_handle_sCAL - (bug introduced in libpng-1.2.4/1.0.13). - Return from png_destroy_read_struct() if png_ptr_ptr is NULL. - Fix overflow of "msg" in png_decompress_chunk(). - -version 1.2.25beta04 [January 26, 2008] - Work around Coverity bug report by slightly refactoring - png_read_push_finish_row() - -version 1.2.25beta05 [January 31, 2008] - Added libpng-1.2.25beta05.tar.lzma to distribution. Get the lzma codec - from . - Added lp1225b05.7z to distribution. Get the 7-zip decoder from - from . - Fixed some broken links in the README file. - -version 1.2.25beta06 [February 6, 2008] - Refactored png_read_push_finish_row() again, trying to satisfy Coverity. - Fixed potential NULL dereference of png_ptr in png_destroy_write_struct(); - clarified potential NULL dereference of png_ptr in png_destroy_read_struct(); - fixed potential NULL dereference of info_ptr in png_handle_bKGD(); - fixed potential NULL dereference of user_png_ver[] in - png_create_write_struct_2(). (Coverity) - -version 1.2.25rc02 [February 10, 2008] - Reset png_ptr->pass in png_read_push_finish_row() before break. - Changed "pass" from png_byte to int. - -version 1.2.25 and 1.0.31 [February 18, 2008] - No changes. - -version 1.2.26beta01 [February 21, 2008] - Added missing "(" in pngmem.c. Bug introduced in libpng-1.2.2/1.0.13 - -version 1.2.26beta02 [March 12, 2008] - Refined error message returned from deflateInit2 in pngwutil.c - Check IHDR length in png_push_read_chunk() before saving it. - -version 1.2.26beta03 [March 16, 2008] - Revised contrib/gregbook to handle premature end-of-file and file - read errors correctly. - -version 1.2.26beta04 [March 18, 2008] - Free png_ptr->big_row_buf and png_ptr->prev_row before allocating - new copies in png_read_start_row(). Bug introduced in libpng-1.2.22. - -version 1.2.26beta05 [March 19, 2008] - Removed extra png_free() added in libpng-1.2.26beta04. - -version 1.2.26beta06 [March 19, 2008] - Avoid reallocating big_row_buf and prev_row when the size does not increase. - -version 1.2.26rc01 [March 26, 2008] - Ifdef out some code that is unused when interlacing is not supported. - -versions 1.0.32 and 1.2.26 [April 2, 2008] - No changes. - -version 1.2.27beta01 [April 12, 2008] - Fixed bug (introduced in libpng-1.0.5h) with handling zero-length - unknown chunks. - Added more information about png_set_keep_unknown_chunks() to the - documentation. - Reject tRNS chunk with out-of-range samples instead of masking off - the invalid high bits as done in since libpng-1.2.19beta5. - -version 1.2.27beta02 [April 13, 2008] - Revised documentation about unknown chunk and user chunk handling. - Keep tRNS chunk with out-of-range samples and issue a png_warning(). - -version 1.2.27beta03 [April 14, 2008] - Added check for NULL ptr in TURBOC version of png_free_default(). - Removed several unnecessary checks for NULL before calling png_free(). - Revised png_set_tRNS() so that calling it twice removes and invalidates - the previous call. - Revised pngtest to check for out-of-range tRNS samples. - -version 1.2.27beta04 [April 18, 2008] - Added AC_LIBTOOL_WIN32_DLL to configure.ac - Rebuilt Makefile.in, aclocal.m4, and configure with autoconf-2.62 - -version 1.2.27beta05 [April 19, 2008] - Added MAINTAINERCLEANFILES variable to Makefile.am - -version 1.2.27beta06 [April 21, 2008] - Avoid changing color_type from GRAY to RGB by - png_set_expand_gray_1_2_4_to_8(). - -version 1.2.27rc01 [April 23, 2008] - Fix broken URL for rfc2083 in png.5 and libpng-*.txt - -version 1.0.33 and 1.2.27 [April 30, 2008] - No changes. - -version 1.0.34 and 1.2.28 [April 30, 2008] - Rebuilt Makefile.in, aclocal.m4, and configure with autoconf-2.61 - due to backward incompatibilities. - Removed a stray object file from contrib/gregbook - -version 1.2.29beta01 [May 1, 2008] - Removed some stray *.diff and *.orig files - -version 1.2.29beta02 [May 1, 2008] - Reverted Makefile.in, aclocal.m4, and configure to the libpng-1.2.26 - versions. - -version 1.2.29beta03 [May 2, 2008] - Added --force to autogen libtoolize options and --force-missing to - automake options. - Changed $(ECHO) to echo in Makefile.am and Makefile.in - Updated all configure files to autoconf-2.62 - Comment out pnggcrd.c code with #ifdef/#endif if using MSC_VER - -version 1.2.29rc01 [May 4, 2008] - No changes. - -version 1.0.35 and 1.2.29 [May 8, 2008] - No changes. - -version 1.0.37 [May 9, 2008] - Updated Makefile.in and configure (omitted version 1.0.36). - -version 1.2.30beta01 [May 29, 2008] - Updated libpng.pc-configure.in and libpng-config.in per debian bug reports. - -version 1.2.30beta02 [June 25, 2008] - Restored png_flush(png_ptr) at the end of png_write_end(), that was - removed from libpng-1.0.9beta03. - -version 1.2.30beta03 [July 6, 2008] - Merged some cosmetic whitespace changes from libpng-1.4.0beta19. - Inline call of png_get_uint_32() in png_get_uint_31(), as in 1.4.0beta19. - Added demo of decoding vpAg and sTER chunks to pngtest.c, from 1.4.0beta19. - Changed PNGMAJ from 0 to 12 in makefile.darwin, which does not like 0. - Added new private function png_read_chunk_header() from 1.4.0beta19. - Merge reading of chunk length and chunk type into a single 8-byte read. - Merge writing of chunk length and chunk type into a single 8-byte write. - -version 1.2.30beta04 [July 10, 2008] - Merged more cosmetic whitespace changes from libpng-1.4.0beta19. - -version 1.0.38rc01, 1.2.30rc01 [July 18, 2008] - No changes. - -version 1.0.38rc02, 1.2.30rc02 [July 21, 2008] + Rebuilt configure and Makefile.in with newer tools. + Added conditional #undef jmpbuf in pngtest.c to undo #define in AIX headers. + Added scripts/makefile.nommx + +Version 1.4.0beta20 [July 9, 2008] + Moved several PNG_HAVE_* macros from pngpriv.h to png.h because applications + calling set_unknown_chunk_location() need them. + Moved several macro definitions from pngpriv.h to pngconf.h + Merge with changes to the 1.2.X branch, as of 1.2.30beta04. + Deleted all use of the MMX assembler code and Intel-licensed optimizations. + Revised makefile.mingw + +Version 1.4.0beta21 [July 21, 2008] Moved local array "chunkdata" from pngrutil.c to the png_struct, so it will be freed by png_read_destroy() in case of a read error (Kurt Christensen). -version 1.0.38rc03, 1.2.30rc03 [July 21, 2008] - Changed "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking. +Version 1.4.0beta22 [July 21, 2008] + Change "purpose" and "buffer" to png_ptr->chunkdata to avoid memory leaking. -version 1.0.38rc04, 1.2.30rc04 [July 22, 2008] - Changed "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in +Version 1.4.0beta23 [July 22, 2008] + Change "chunkdata = NULL" to "png_ptr->chunkdata = NULL" several places in png_decompress_chunk(). -version 1.0.38rc05, 1.2.30rc05 [July 25, 2008] - Changed all remaining "chunkdata" to "png_ptr->chunkdata" in - png_decompress_chunk() and remove chunkdata from parameter list. +Version 1.4.0beta24 [July 25, 2008] + Change all remaining "chunkdata" to "png_ptr->chunkdata" in + png_decompress_chunk(), and remove "chunkdata" from parameter list. Put a call to png_check_chunk_name() in png_read_chunk_header(). Revised png_check_chunk_name() to reject a name with a lowercase 3rd byte. - Removed two calls to png_check_chunk_name() occuring later in the process. + Removed two calls to png_check_chunk_name() occurring later in the process. + Define PNG_NO_ERROR_NUMBERS by default in pngconf.h -version 1.0.38rc06, 1.2.30rc06 [July 29, 2008] +Version 1.4.0beta25 [July 30, 2008] Added a call to png_check_chunk_name() in pngpread.c Reverted png_check_chunk_name() to accept a name with a lowercase 3rd byte. - -version 1.0.38r07, 1.2.30r07 [August 2, 2008] - Changed "-Wall" to "-W -Wall" in the CFLAGS in all makefiles (Cosmin Truta) - Declared png_ptr "volatile" in pngread.c and pngwrite.c to avoid warnings. - Added code in pngset.c to quiet compiler warnings. - Updated contrib/visupng/cexcept.h to version 2.0.1 + Added png_push_have_buffer() function to pngpread.c + Eliminated PNG_BIG_ENDIAN_SUPPORTED and associated png_get_* macros. + Made inline expansion of png_get_*() optional with PNG_USE_READ_MACROS. + Eliminated all PNG_USELESS_TESTS and PNG_CORRECT_PALETTE_SUPPORTED code. + Synced contrib directory and configure files with libpng-1.2.30beta06. + Eliminated no-longer-used pngdefs.h (but it's still built in the makefiles) Relocated a misplaced "#endif /* PNG_NO_WRITE_FILTER */" in pngwutil.c -version 1.0.38r08, 1.2.30r08 [August 2, 2008] - Enclose "volatile" declarations in #ifdef PNG_SETJMP_SUPPORTED (Cosmin). +Version 1.4.0beta26 [August 4, 2008] + Removed png_push_have_buffer() function in pngpread.c. It increased the + compiled library size slightly. + Changed "-Wall" to "-W -Wall" in the CFLAGS in all makefiles (Cosmin Truta) + Declared png_ptr "volatile" in pngread.c and pngwrite.c to avoid warnings. + Updated contrib/visupng/cexcept.h to version 2.0.1 + Added PNG_LITERAL_CHARACTER macros for #, [, and ]. -version 1.0.38, 1.2.30 [August 14, 2008] - No changes. +Version 1.4.0beta27 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Moved newline character from individual png_debug messages into the + png_debug macros. + Allow user to #define their own png_debug, png_debug1, and png_debug2. -version 1.2.31rc01 [August 19, 2008] +Version 1.4.0beta28 [August 5, 2008] + Revised usage of PNG_LITERAL_SHARP in pngerror.c. + Added PNG_STRING_NEWLINE macro + +Version 1.4.0beta29 [August 9, 2008] + Revised usage of PNG_STRING_NEWLINE to work on non-ISO compilers. + Added PNG_STRING_COPYRIGHT macro. + Added non-ISO versions of png_debug macros. + +Version 1.4.0beta30 [August 14, 2008] + Added premultiplied alpha feature (Volker Wiendl). + +Version 1.4.0beta31 [August 18, 2008] + Moved png_set_premultiply_alpha from pngtrans.c to pngrtran.c Removed extra crc check at the end of png_handle_cHRM(). Bug introduced - in libpng-1.2.30beta03 (Heiko Nitzsche). + in libpng-1.4.0beta20. -version 1.2.31rc02 [August 19, 2008] +Version 1.4.0beta32 [August 19, 2008] Added PNG_WRITE_FLUSH_SUPPORTED block around new png_flush() call. + Revised PNG_NO_STDIO version of png_write_flush() -version 1.2.31rc03 [August 19, 2008] - Added PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED block, off by default, around - new png_flush(). +Version 1.4.0beta33 [August 20, 2008] + Added png_get|set_chunk_cache_max() to limit the total number of sPLT, + text, and unknown chunks that can be stored. -version 1.0.39, 1.2.31 [August 21, 2008] - No changes. - -version 1.2.32beta01 [September 6, 2008] - Shortened tIME_string to 29 bytes in pngtest.c (bug introduced in - libpng-1.2.22). +Version 1.4.0beta34 [September 6, 2008] + Shortened tIME_string to 29 bytes in pngtest.c Fixed off-by-one error introduced in png_push_read_zTXt() function in libpng-1.2.30beta04/pngpread.c (Harald van Dijk) - These bugs have been given the vulnerability id CVE-2008-3964. -version 1.0.40, 1.2.32 [September 18, 2008] - No changes. - -version 1.2.33beta01 [October 6, 2008] +Version 1.4.0beta35 [October 6, 2008] + Changed "trans_values" to "trans_color". + Changed so-number from 0 to 14. Some OS do not like 0. Revised makefile.darwin to fix shared library numbering. Change png_set_gray_1_2_4_to_8() to png_set_expand_gray_1_2_4_to_8() in example.c (debian bug report) -version 1.2.33rc01 [October 15, 2008] - No changes. +Version 1.4.0beta36 [October 25, 2008] + Sync with tEXt vulnerability fix in libpng-1.2.33rc02. -version 1.0.41rc01, version 1.2.33rc02 [October 23, 2008] - Changed remaining "key" to "png_ptr->chunkdata" in png_handle_tEXt() - to avoid memory leak after memory failure while reading tEXt chunk.` +Version 1.4.0beta37 [November 13, 2008] + Added png_check_cHRM in png.c and moved checking from pngget.c, pngrutil.c, + and pngwrite.c -version 1.2.33 [October 31, 2008] - No changes. +Version 1.4.0beta38 [November 22, 2008] + Added check for zero-area RGB cHRM triangle in png_check_cHRM() and + png_check_cHRM_fixed(). -version 1.2.34beta01 [November 27, 2008] - Revised png_warning() to write its message on standard output by default - when warning_fn is NULL. This was the behavior prior to libpng-1.2.9beta9. - Fixed string vs pointer-to-string error in png_check_keyword(). - Added png_check_cHRM_fixed() in png.c and moved checking from pngget.c, - pngrutil.c, and pngwrite.c, and eliminated floating point cHRM checking. - Added check for zero-area RGB cHRM triangle in png_check_cHRM_fixed(). - In png_check_cHRM_fixed(), ensure white_y is > 0, and removed redundant - check for all-zero coordinates that is detected by the triangle check. +Version 1.4.0beta39 [November 23, 2008] Revised png_warning() to write its message on standard output by default when warning_fn is NULL. -version 1.2.34beta02 [November 28, 2008] - Corrected off-by-one error in bKGD validity check in png_write_bKGD() - and in png_handle_bKGD(). +Version 1.4.0beta40 [November 24, 2008] + Eliminated png_check_cHRM(). Instead, always use png_check_cHRM_fixed(). + In png_check_cHRM_fixed(), ensure white_y is > 0, and removed redundant + check for all-zero coordinates that is detected by the triangle check. -version 1.2.34beta03 [December 1, 2008] - Revised bKGD validity check to use >= x instead of > x + 1 - Merged with png_debug from libpng-1.4.0 to remove newlines. +Version 1.4.0beta41 [November 26, 2008] + Fixed string vs pointer-to-string error in png_check_keyword(). + Rearranged test expressions in png_check_cHRM_fixed() to avoid internal + overflows. + Added PNG_NO_CHECK_cHRM conditional. -version 1.2.34beta04 [December 2, 2008] - More merging with png_debug from libpng-1.4.0 to remove newlines. +Version 1.4.0beta42, 43 [December 1, 2008] + Merge png_debug with version 1.2.34beta04. -version 1.2.34beta05 [December 5, 2008] +Version 1.4.0beta44 [December 6, 2008] Removed redundant check for key==NULL before calling png_check_keyword() to ensure that new_key gets initialized and removed extra warning - (Arvan Pritchard). + (Merge with version 1.2.34beta05 -- Arvan Pritchard). -version 1.2.34beta06 [December 9, 2008] +Version 1.4.0beta45 [December 9, 2008] In png_write_png(), respect the placement of the filler bytes in an earlier call to png_set_filler() (Jim Barry). -version 1.2.34beta07 [December 9, 2008] +Version 1.4.0beta46 [December 10, 2008] Undid previous change and added PNG_TRANSFORM_STRIP_FILLER_BEFORE and PNG_TRANSFORM_STRIP_FILLER_AFTER conditionals and deprecated PNG_TRANSFORM_STRIP_FILLER (Jim Barry). -version 1.0.42rc01, 1.2.34rc01 [December 11, 2008] - No changes. +Version 1.4.0beta47 [December 15, 2008] + Support for dithering was disabled by default, because it has never + been well tested and doesn't work very well. The code has not + been removed, however, and can be enabled by building libpng with + PNG_READ_DITHER_SUPPORTED defined. -version 1.0.42, 1.2.34 [December 18, 2008] - No changes. +Version 1.4.0beta48 [February 14, 2009] + Added new exported function png_calloc(). + Combined several instances of png_malloc(); png_memset() into png_calloc(). + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined. -version 1.2.35beta01 [February 4, 2009] - Zero out some arrays of pointers after png_malloc(). (Tavis Ormandy) - -version 1.2.35beta02 [February 4, 2009] - Zero out more arrays of pointers after png_malloc(). - -version 1.2.35beta03 [February 5, 2009] - Use png_memset() instead of a loop to intialize pointers. We realize - this will not work on platforms where the NULL pointer is not all zeroes. - -version 1.2.35rc01 [February 11, 2009] - No changes. - -version 1.2.35rc02 [February 12, 2009] - Fix typo in new png_memset call in pngset.c (png_color should be png_charp) - -version 1.0.43 and 1.2.35 [February 14, 2009] - No changes. - -version 1.2.36beta01 [February 28, 2009] +Version 1.4.0beta49 [February 28, 2009] + Added png_fileno() macro to pngconf.h, used in pngwio.c + Corrected order of #ifdef's in png_debug definition in png.h + Fixed bug introduced in libpng-1.4.0beta48 with the memset arguments + for pcal_params. + Fixed order of #ifdef directives in the png_debug defines in png.h + (bug introduced in libpng-1.2.34/1.4.0beta29). Revised comments in png_set_read_fn() and png_set_write_fn(). - Revised order of #ifdef's and indentation in png_debug definitions of png.h - bug introduced in libpng-1.2.34. -version 1.2.36beta02 [March 21, 2009] - Use png_memset() after png_malloc() of big_row_buf when reading an - interlaced file, to avoid a possible UMR. - Undid recent revision of PNG_NO_STDIO version of png_write_flush(). Users - having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined. - Revised libpng*.txt documentation about use of png_write_flush(). +Version 1.4.0beta50 [March 18, 2009] + Use png_calloc() instead of png_malloc() to allocate big_row_buf when + reading an interlaced file, to avoid a possible UMR. + Undid revision of PNG_NO_STDIO version of png_write_flush(). Users + having trouble with fflush() can build with PNG_NO_WRITE_FLUSH defined + or supply their own flush_fn() replacement. + Revised libpng*.txt and png.h documentation about use of png_write_flush() + and png_set_write_fn(). Removed fflush() from pngtest.c. Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h -version 1.2.36beta03 [March 27, 2009] - Relocated misplaced PNG_1_0_X define in png.h that caused the prototype - for png_set_strip_error_numbers() to be omitted from PNG_NO_ASSEMBLER_CODE - builds. This bug was introduced in libpng-1.2.15beta4. +Version 1.4.0beta51 [March 21, 2009] + Removed new png_fileno() macro from pngconf.h . + +Version 1.4.0beta52 [March 27, 2009] + Relocated png_do_chop() ahead of building gamma tables in pngrtran.c + This avoids building 16-bit gamma tables unnecessarily. + Removed fflush() from pngtest.c. + Added "#define PNG_NO_WRITE_FLUSH" to contrib/pngminim/encoder/pngusr.h Added a section on differences between 1.0.x and 1.2.x to libpng.3/libpng.txt -version 1.2.36beta04 [April 5, 2009] +Version 1.4.0beta53 [April 1, 2009] + Removed some remaining MMX macros from pngpriv.h Fixed potential memory leak of "new_name" in png_write_iCCP() (Ralph Giles) -version 1.2.36beta05 [April 24, 2009] +Version 1.4.0beta54 [April 13, 2009] Added "ifndef PNG_SKIP_SETJMP_CHECK" block in pngconf.h to allow application code writers to bypass the check for multiple inclusion of setjmp.h when they know that it is safe to ignore the situation. - Made some cosmetic changes to whitespace in pngtest output. + Eliminated internal use of setjmp() in pngread.c and pngwrite.c + Reordered ancillary chunks in pngtest.png to be the same as what + pngtest now produces, and made some cosmetic changes to pngtest output. + Eliminated deprecated png_read_init_3() and png_write_init_3() functions. + +Version 1.4.0beta55 [April 15, 2009] + Simplified error handling in pngread.c and pngwrite.c by putting + the new png_read_cleanup() and png_write_cleanup() functions inline. + +Version 1.4.0beta56 [April 25, 2009] Renamed "user_chunk_data" to "my_user_chunk_data" in pngtest.c to suppress "shadowed declaration" warning from gcc-4.3.3. Renamed "gamma" to "png_gamma" in pngset.c to avoid "shadowed declaration" warning about a global "gamma" variable in math.h on some platforms. -version 1.2.36rc01 [April 30, 2009] - No changes. +Version 1.4.0beta57 [May 2, 2009] + Removed prototype for png_freeptr() that was added in libpng-1.4.0beta24 + but was never defined (again). + Rebuilt configure scripts with autoconf-2.63 instead of 2.62 + Removed pngprefs.h and MMX from makefiles -version 1.0.44 and 1.2.36 [May 7, 2009] - No changes. - -version 1.2.37beta01 [May 14, 2009] - Fixed inconsistency in pngrutil.c, introduced in libpng-1.2.36. The - memset() was using "png_ptr->rowbytes" instead of "row_bytes", which - the corresponding png_malloc() uses (Joe Drew). +Version 1.4.0beta58 [May 14, 2009] + Changed pngw32.def to pngwin.def in makefile.mingw (typo was introduced + in beta57). Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) - Updated some of the makefiles in the scripts directory (merged with - those in libpng-1.4.0beta57). -version 1.2.37beta02 [May 19, 2009] - Fixed typo in libpng documentation (FILTER_AVE should be FILTER_AVG) +Version 1.4.0beta59 [May 15, 2009] + Reformated sources in libpng style (3-space intentation, comment format) + Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) + Added sections about the git repository and our coding style to the + documentation Relocated misplaced #endif in pngwrite.c, sCAL chunk handler. + +Version 1.4.0beta60 [May 19, 2009] Conditionally compile png_read_finish_row() which is not used by progressive readers. Added contrib/pngminim/preader to demonstrate building minimal progressive decoder, based on contrib/gregbook with embedded libpng and zlib. -version 1.2.37beta03 [May 20, 2009] +Version 1.4.0beta61 [May 20, 2009] In contrib/pngminim/*, renamed "makefile.std" to "makefile", since there is only one makefile in those directories, and revised the README files accordingly. - Reformated sources in libpng style (3-space indentation, comment format) + More reformatting of comments, mostly to capitalize sentences. -version 1.2.37rc01 [May 27, 2009] - No changes. - -versions 1.2.37 and 1.0.45 [June 4, 2009] - Reformatted several remaining "else statement;" and "if () statement;" into - two lines. +Version 1.4.0beta62 [June 2, 2009] Added "#define PNG_NO_WRITE_SWAP" to contrib/pngminim/encoder/pngusr.h and "define PNG_NO_READ_SWAP" to decoder/pngusr.h and preader/pngusr.h - Added sections about the git repository and our coding style to the - documentation (merged from libpng-1.4.0beta62) + Reformatted several remaining "else statement" into two lines. Added a section to the libpng documentation about using png_get_io_ptr() in configure scripts to detect the presence of libpng. -version 1.2.38beta01 [June 17, 2009] +Version 1.4.0beta63 [June 15, 2009] Revised libpng*.txt and libpng.3 to mention calling png_set_IHDR() multiple times and to specify the sample order in the tRNS chunk, because the ISO PNG specification has a typo in the tRNS table. @@ -2411,154 +2329,143 @@ version 1.2.38beta01 [June 17, 2009] available for ignoring known chunks even when not saving unknown chunks. Adopted preference for consistent use of "#ifdef" and "#ifndef" versus "#if defined()" and "if !defined()" where possible. - Added PNG_NO_HANDLE_AS_UNKNOWN in the PNG_LEGACY_SUPPORTED block of - pngconf.h, and moved the various unknown chunk macro definitions - outside of the PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. -version 1.0.46 [June 18, 2009] - Removed some editing cruft from scripts/libpng.pc.in and some makefiles. +Version 1.4.0beta64 [June 24, 2009] + Eliminated PNG_LEGACY_SUPPORTED code. + Moved the various unknown chunk macro definitions outside of the + PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. -version 1.2.38rc01 [June 24, 2009] - No changes. +Version 1.4.0beta65 [June 26, 2009] + Added a reference to the libpng license in each file. -version 1.2.38rc02 [June 29, 2009] - Added a reference to the libpng license in each source file. +Version 1.4.0beta66 [June 27, 2009] + Refer to the libpng license instead of the libpng license in each file. -version 1.2.38rc03 [July 11, 2009] - Revised references to the libpng license in pngconf.h and contrib/visupng - source files. - Rebuilt configure scripts with autoconf-2.63. +Version 1.4.0beta67 [July 6, 2009] + Relocated INVERT_ALPHA within png_read_png() and png_write_png(). + Added high-level API transform PNG_TRANSFORM_GRAY_TO_RGB. + Added an "xcode" project to the projects directory (Alam Arias). -version 1.0.47 and 1.2.38 [July 16, 2009] - No changes. +Version 1.4.0beta68 [July 19, 2009] + Avoid some tests in filter selection in pngwutil.c -version 1.2.39beta01 [July 25, 2009] +Version 1.4.0beta69 [July 25, 2009] + Simplified the new filter-selection test. This runs faster in the + common "PNG_ALL_FILTERS" and PNG_FILTER_NONE cases. + Removed extraneous declaration from the new call to png_read_gray_to_rgb() + (bug introduced in libpng-1.4.0beta67). + Fixed up xcode project (Alam Arias) Added a prototype for png_64bit_product() in png.c -version 1.2.39beta02 [July 27, 2009] +Version 1.4.0beta70 [July 27, 2009] Avoid a possible NULL dereference in debug build, in png_set_text_2(). (bug introduced in libpng-0.95, discovered by Evan Rouault) -version 1.2.39beta03 [July 29, 2009] - Relocated new png_64_bit_product() prototype into png.h - Expanded the information about prototypes in the libpng style section of - the documentation. +Version 1.4.0beta71 [July 29, 2009] Rebuilt configure scripts with autoconf-2.64. -version 1.2.39beta04 [August 1, 2009] - Replaced *.tar.lzma with *.txz in distribution. Get the xz codec +Version 1.4.0beta72 [August 1, 2009] + Replaced *.tar.lzma with *.tar.xz in distribution. Get the xz codec from . -version 1.2.39beta05 [August 1, 2009] +Version 1.4.0beta73 [August 1, 2009] Reject attempt to write iCCP chunk with negative embedded profile length - (JD Chen) + (JD Chen) (CVE-2009-5063). -version 1.2.39c01 [August 6, 2009] - No changes. +Version 1.4.0beta74 [August 8, 2009] + Changed png_ptr and info_ptr member "trans" to "trans_alpha". -version 1.2.39 and 1.0.48 [August 13, 2009] - No changes. - -version 1.2.40beta01 [August 20, 2009] +Version 1.4.0beta75 [August 21, 2009] Removed an extra png_debug() recently added to png_write_find_filter(). Fixed incorrect #ifdef in pngset.c regarding unknown chunk support. -version 1.2.40rc01 [September 2, 2009] +Version 1.4.0beta76 [August 22, 2009] + Moved an incorrectly located test in png_read_row() in pngread.c + +Version 1.4.0beta77 [August 27, 2009] + Removed lpXYZ.tar.bz2 (with CRLF), KNOWNBUG, libpng-x.y.z-KNOWNBUG.txt, + and the "noconfig" files from the distribution. + Moved CMakeLists.txt from scripts into the main libpng directory. Various bugfixes and improvements to CMakeLists.txt (Philip Lowman) -version 1.2.40 and 1.0.49 [September 2, 2009] - No changes. +Version 1.4.0beta78 [August 31, 2009] + Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h + Eliminated PNG_NO_FREE_ME and PNG_FREE_ME_SUPPORTED macros. + Use png_malloc plus a loop instead of png_calloc() to initialize + row_pointers in png_read_png(). -version 1.0.50 [September 10, 2009] - Removed some editing cruft from pngset.c and pngwutil.c. +Version 1.4.0beta79 [September 1, 2009] + Eliminated PNG_GLOBAL_ARRAYS and PNG_LOCAL_ARRAYS; always use local arrays. + Eliminated PNG_CALLOC_SUPPORTED macro and always provide png_calloc(). -version 1.2.41beta01 [September 25, 2009] +Version 1.4.0beta80 [September 17, 2009] + Removed scripts/libpng.icc + Changed typecast of filler from png_byte to png_uint_16 in png_set_filler(). + (Dennis Gustafsson) + Fixed typo introduced in beta78 in pngtest.c ("#if def " should be "#ifdef ") + +Version 1.4.0beta81 [September 23, 2009] + Eliminated unused PNG_FLAG_FREE_* defines from pngpriv.h + Expanded TAB characters in pngrtran.c + Removed PNG_CONST from all "PNG_CONST PNG_CHNK" declarations to avoid + compiler complaints about doubly declaring things "const". + Changed all "#if [!]defined(X)" to "if[n]def X" where possible. + Eliminated unused png_ptr->row_buf_size + +Version 1.4.0beta82 [September 25, 2009] Moved redundant IHDR checking into new png_check_IHDR() in png.c and report all errors found in the IHDR data. Eliminated useless call to png_check_cHRM() from pngset.c - Expanded TAB characters in pngrtran.c -version 1.2.41beta02 [September 30, 2009] - Revised png_check_IHDR(). +Version 1.4.0beta83 [September 25, 2009] + Revised png_check_IHDR() to eliminate bogus complaint about filter_type. -version 1.2.41beta03 [October 1, 2009] +Version 1.4.0beta84 [September 30, 2009] + Fixed some inconsistent indentation in pngconf.h + Revised png_check_IHDR() to add a test for width variable less than 32-bit. + +Version 1.4.0beta85 [October 1, 2009] Revised png_check_IHDR() again, to check info_ptr members instead of the contents of the returned parameters. -version 1.2.41beta04 [October 7, 2009] - Added "xcode" project similar one already in libpng-1.4.0beta (Alam Arias). - Ported some cosmetic changes from libpng-1.4.0beta86. +Version 1.4.0beta86 [October 9, 2009] + Updated the "xcode" project (Alam Arias). Eliminated a shadowed declaration of "pp" in png_handle_sPLT(). -version 1.2.41beta05 [October 17, 2009] - Revised pngconf.h to make it easier to enable iTXt support. From libpng - version 1.2.9 through 1.2.40, defining PNG_iTXt_SUPPORTED did not work - as expected. - Ported some cosmetic changes from libpng-1.4.0beta87, changing - many "#if defined(x)" to "#ifdef x". +Version 1.4.0rc01 [October 19, 2009] + Trivial cosmetic changes. -version 1.2.41beta06 [October 18, 2009] - Restored PNG_USE_LOCAL_ARRAYS code in pngread.c that was inadvertently - deleted in libpng-1.2.41beta05. - Converted all PNG_NO_* tests to PNG_*_SUPPORTED everywhere except pngconf.h - as in libpng-1.4.0beta78 and later. +Version 1.4.0beta87 [October 30, 2009] + Moved version 1.4.0 back into beta. -version 1.2.41beta07 [October 21, 2009] - Ported some cosmetic changes from libpng-1.4.0rc01, changing - many "#if defined(x)" to "#ifdef x" in png.h and pngconf.h. +Version 1.4.0beta88 [October 30, 2009] + Revised libpng*.txt section about differences between 1.2.x and 1.4.0 + because most of the new features have now been ported back to 1.2.41 -version 1.2.41beta08 [October 30, 2009] - Ported from libpng-1.4.0rc01: png_calloc(), png_get_io_chunk_name(), - png_get_io_state(), png_set_user_cache_max(), png_get_user_cache_max(), - png_set_premultiply_alpha, and png_do_read_premultiply_alpha(). - Relocated png_do_chop() ahead of building gamma tables in pngrtran.c - This avoids building 16-bit gamma tables unnecessarily. - -version 1.2.41beta09 [November 1, 2009] - Removed a harmless extra png_set_invert_alpha() from pngwrite.c +Version 1.4.0beta89 [November 1, 2009] More bugfixes and improvements to CMakeLists.txt (Philip Lowman) - Moved CMakeLists.txt from scripts into the main libpng directory. + Removed a harmless extra png_set_invert_alpha() from pngwrite.c Apply png_user_chunk_cache_max within png_decompress_chunk(). Merged libpng-1.2.41.txt with libpng-1.4.0.txt where appropriate. -version 1.2.41beta10 [November 1, 2009] - Enabled iTXt support by default. To ensure binary compatibility with - previous versions, the "lang" and "lang_key" members will be assumed - to be omitted from previous versions unless the current libpng - version was built with PNG_iTXt_SUPPORTED (which is otherwise no - longer necessary to gain iTXt support), as a signal that the user has - been building previous versions with PNG_iTXt_SUPPORTED as well. +Version 1.4.0beta90 [November 2, 2009] + Removed all remaining WIN32_WCE #ifdefs except those involving the + time.h "tm" structure -version 1.2.41beta11 [November 2, 2009] - Store user's user_png_ver in new png_ptr->user_png_ver element. - Revised iTXt support. To ensure binary compatibility with - previous versions, the "lang" and "lang_key" members will be assumed - to be omitted from versions prior to 1.2.41beta11 whenever there is a - library mismatch. - -version 1.2.41beta12 [November 2, 2009] - Free png_ptr->user_png_ver when destroying png_ptr. - -version 1.2.41beta13 [November 3, 2009] +Version 1.4.0beta91 [November 3, 2009] Updated scripts/pngw32.def and projects/wince/png32ce.def Copied projects/wince/png32ce.def to the scripts directory. Added scripts/makefile.wce Patched ltmain.sh for wince support. Added PNG_CONVERT_tIME_SUPPORTED macro. -version 1.2.41beta14 [November 8, 2009] - versions 1.2.41beta05 through 1.2.41beta13 were abandoned. - The 1.0.x/1.2.x series will only receive security updates from now on. +Version 1.4.0beta92 [November 4, 2009] Make inclusion of time.h in pngconf.h depend on PNG_CONVERT_tIME_SUPPORTED Make #define PNG_CONVERT_tIME_SUPPORTED depend on PNG_WRITE_tIME_SUPPORTED - Reverted iTXt compatibility stuff from 1.2.41beta05, 1.2.41beta11, and - 1.2.41beta12. - Reverted IOSTATE feature, user_cache_max, and premultiply_alpha features - from 1.2.41beta08. - Retained png_calloc() from 1.2.41beta08 but as a non-exported function, - and removed reference to png_calloc from scripts/*.def + Revised libpng*.txt to describe differences from 1.2.40 to 1.4.0 (instead + of differences from 1.2.41 to 1.4.0) -version 1.2.41beta15 [November 8, 2009] +Version 1.4.0beta93 [November 7, 2009] Added PNG_DEPSTRUCT, PNG_DEPRECATED, PNG_USE_RESULT, PNG_NORETURN, and PNG_ALLOCATED macros to detect deprecated direct access to the png_struct or info_struct members and other deprecated usage in @@ -2568,179 +2475,3635 @@ version 1.2.41beta15 [November 8, 2009] functions while building libpng. They need to be tested, especially those using compilers other than gcc. Updated projects/visualc6 and visualc71 with "/d PNG_CONFIGURE_LIBPNG". - -version 1.2.41beta16 [November 9, 2009] + They should work but still need to be updated to remove + references to pnggccrd.c or pngvcrd.c and ASM building. + Added README.txt to the beos, cbuilder5, netware, and xcode projects warning + that they need to be updated, to remove references to pnggccrd.c and + pngvcrd.c and to depend on pngpriv.h Removed three direct references to read_info_ptr members in pngtest.c that were detected by the new PNG_DEPSTRUCT macro. + Moved the png_debug macro definitions and the png_read_destroy(), + png_write_destroy() and png_far_to_near() prototypes from png.h + to pngpriv.h (John Bowler) + Moved the synopsis lines for png_read_destroy(), png_write_destroy() + png_debug(), png_debug1(), and png_debug2() from libpng.3 to libpngpf.3. + +Version 1.4.0beta94 [November 9, 2009] + Removed the obsolete, unused pnggccrd.c and pngvcrd.c files. + Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions. + Removed dependency of pngtest.o on pngpriv.h in the makefiles. Only #define PNG_DEPSTRUCT, etc. in pngconf.h if not already defined. -version 1.2.41beta17 [November 10, 2009] - Updated CMakeLists.txt to add "-DPNG_CONFIGURE_LIBPNG" to the definitions. - Marked deprecated function prototypes with PNG_DEPRECATED. - Marked memory allocation function prototypes with PNG_ALLOCATED. +Version 1.4.0beta95 [November 10, 2009] + Changed png_check_sig() to !png_sig_cmp() in contrib programs. + Added -DPNG_CONFIGURE_LIBPNG to contrib/pngminm/*/makefile Changed png_check_sig() to !png_sig_cmp() in contrib programs. Corrected the png_get_IHDR() call in contrib/gregbook/readpng2.c - Added "-DPNG_CONFIGURE_LIBPNG" to the contrib/pngminum makefiles. + Changed pngminim/*/gather.sh to stop trying to remove pnggccrd.c and pngvcrd.c + Added dependency on pngpriv.h in contrib/pngminim/*/makefile -version 1.2.41beta18 [November 11, 2009] +Version 1.4.0beta96 [November 12, 2009] Renamed scripts/makefile.wce to scripts/makefile.cegcc - Marked nonexported functions with PNG_PRIVATE macro. + Revised Makefile.am to use libpng.sys while building libpng.so + so that only PNG_EXPORT functions are exported. + Removed the deprecated png_check_sig() function/macro. + Removed recently removed function names from scripts/*.def + Revised pngtest.png to put chunks in the same order written by pngtest + (evidently the same change made in libpng-1.0beta54 was lost). + Added PNG_PRIVATE macro definition in pngconf.h for possible future use. -version 1.2.41rc01 and 1.0.51rc01 [November 18, 2009] - Revised scripts/*.def to reflect functions actually exported by libpng. - Updated the copyright year in scripts/pngw32.rc from 2004 to 2009. +Version 1.4.0beta97 [November 13, 2009] + Restored pngtest.png to the libpng-1.4.0beta7 version. + Removed projects/beos and netware.txt; no one seems to be supporting them. + Revised Makefile.in + +Version 1.4.0beta98 [November 13, 2009] + Added the "xcode" project to zip distributions, + Fixed a typo in scripts/pngwin.def introduced in beta97. + +Version 1.4.0beta99 [November 14, 2009] + Moved libpng-config.in and libpng.pc-configure.in out of the scripts + directory, to libpng-config.in and libpng-pc.in, respectively, and + modified Makefile.am and configure.ac accordingly. Now "configure" + needs nothing from the "scripts" directory. + Avoid redefining PNG_CONST in pngconf.h + +Version 1.4.0beta100 [November 14, 2009] + Removed ASM builds from projects/visualc6 and projects/visualc71 + Removed scripts/makefile.nommx and makefile.vcawin32 + Revised CMakeLists.txt to account for new location of libpng-config.in + and libpng-pc.in + Updated INSTALL to reflect removal and relocation of files. + +Version 1.4.0beta101 [November 14, 2009] + Restored the binary files (*.jpg, *.png, some project files) that were + accidentally deleted from the zip and 7z distributions when the xcode + project was added. + +Version 1.4.0beta102 [November 18, 2009] + Added libpng-config.in and libpng-pc.in to the zip and 7z distributions. + Fixed a typo in projects/visualc6/pngtest.dsp, introduced in beta100. Moved descriptions of makefiles and other scripts out of INSTALL into scripts/README.txt + Updated the copyright year in scripts/pngwin.rc from 2006 to 2009. -version 1.2.41rc02 [November 22, 2009] - Rebuilt the configure scripts with autoconf-2.65 +Version 1.4.0beta103 [November 21, 2009] + Removed obsolete comments about ASM from projects/visualc71/README_zlib.txt + Align row_buf on 16-byte boundary in memory. + Restored the PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED guard around the call + to png_flush() after png_write_IEND(). See 1.4.0beta32, 1.4.0beta50 + changes above and 1.2.30, 1.2.30rc01 and rc03 in 1.2.41 CHANGES. Someone + needs this feature. + Make the 'png_jmpbuf' macro expand to a call that records the correct + longjmp function as well as returning a pointer to the setjmp + jmp_buf buffer, and marked direct access to jmpbuf 'deprecated'. + (John Bowler) -version 1.2.41rc03 [November 25, 2009] - Disabled the new pedantic warnings about deprecated function use - and deprecated structure access unless the user defines - PNG_PEDANTIC_WARNINGS. +Version 1.4.0beta104 [November 22, 2009] + Removed png_longjmp_ptr from scripts/*.def and libpng.3 + Rebuilt configure scripts with autoconf-2.65 + +Version 1.4.0beta105 [November 25, 2009] + Use fast integer PNG_DIVIDE_BY_255() or PNG_DIVIDE_BY_65535() + to accomplish alpha premultiplication when + PNG_READ_COMPOSITE_NODIV_SUPPORTED is defined. + Changed "/255" to "/255.0" in background calculations to make it clear + that the 255 is used as a double. + +Version 1.4.0beta106 [November 27, 2009] + Removed premultiplied alpha feature. + +Version 1.4.0beta107 [December 4, 2009] + Updated README Added "#define PNG_NO_PEDANTIC_WARNINGS" in the libpng source files. Removed "-DPNG_CONFIGURE_LIBPNG" from the makefiles and projects. - -version 1.2.41 and 1.0.51 [December 3, 2009] - Updated the list of files and made some cosmetic changes in README. - -version 1.2.42beta01 [December 4, 2009] - Removed "#define PNG_NO_ERROR_NUMBERS" that was inadvertently added - to pngconf.h in version 1.2.41. Revised scripts/makefile.netbsd, makefile.openbsd, and makefile.sco to put png.h and pngconf.h in $prefix/include, like the other scripts, instead of in $prefix/include/libpng. Also revised makefile.sco - to put them in $prefix/include/libpng12 instead of in - $prefix/include/libpng/libpng12. - Removed leftover "-DPNG_CONFIGURE_LIBPNG" from scripts/makefile.darwin + to put them in $prefix/include/libpng15 instead of in + $prefix/include/libpng/libpng15. -version 1.2.42beta02 [December 11, 2009] +Version 1.4.0beta108 [December 11, 2009] Removed leftover "-DPNG_CONFIGURE_LIBPNG" from contrib/pngminim/*/makefile - Relocated png_do_chop() to its original position in pngrtran.c. The + Relocated png_do_chop() to its original position in pngrtran.c; the change in version 1.2.41beta08 caused transparency to be handled wrong in some 16-bit datastreams (Yusaku Sugai). -version 1.2.42rc01 [December 17, 2009] - No changes. +Version 1.4.0beta109 [December 13, 2009] + Added "bit_depth" parameter to the private png_build_gamma_table() function. + Pass bit_depth=8 to png_build_gamma_table() when bit_depth is 16 but the + PNG_16_TO_8 transform has been set, to avoid unnecessary build of 16-bit + tables. -version 1.2.42rc02 [December 22, 2009] +Version 1.4.0rc02 [December 20, 2009] + Declared png_cleanup_needed "volatile" in pngread.c and pngwrite.c + +Version 1.4.0rc03 [December 22, 2009] Renamed libpng-pc.in back to libpng.pc.in and revised CMakeLists.txt - (revising changes made in 1.2.41beta17 and 1.2.41rc01) + (revising the change in 1.4.0beta99) -version 1.2.42rc03 [December 25, 2009] +Version 1.4.0rc04 [December 25, 2009] Swapped PNG_UNKNOWN_CHUNKS_SUPPORTED and PNG_HANDLE_AS_UNKNOWN_SUPPORTED in pngset.c to be consistent with other changes in version 1.2.38. -version 1.2.42rc04 [January 1, 2010] - Marked png_memcpy_check() and png_memset_check() PNG_DEPRECATED. - Updated copyright year. +Version 1.4.0rc05 [December 25, 2009] + Changed "libpng-pc.in" to "libpng.pc.in" in configure.ac, configure, and + Makefile.in to be consistent with changes in libpng-1.4.0rc03 -version 1.2.42rc05 [January 2, 2010] +Version 1.4.0rc06 [December 29, 2009] + Reverted the gamma_table changes from libpng-1.4.0beta109. + Fixed some indentation errors. + +Version 1.4.0rc07 [January 1, 2010] + Revised libpng*.txt and libpng.3 about 1.2.x->1.4.x differences. + Use png_calloc() instead of png_malloc(); png_memset() in pngrutil.c + Update copyright year to 2010. + +Version 1.4.0rc08 [January 2, 2010] Avoid deprecated references to png_ptr-io_ptr and png_ptr->error_ptr in pngtest.c -version 1.2.42 and 1.0.52 [January 3, 2010] +Version 1.4.0 [January 3, 2010] No changes. -version 1.2.43beta01 [January 27, 2010] +Version 1.4.1beta01 [January 8, 2010] Updated CMakeLists.txt for consistent indentation and to avoid an unclosed if-statement warning (Philip Lowman). - Removed "#ifdef PNG_1_0_X / #endif" surrounding - PNG_READ_16_TO_8_SUPPORTED and PNG_READ_GRAY_TO_RGB_SUPPORTED - in pngconf.h. These were added in libpng-1.2.41beta08 and libpng-1.0.51, - which introduced a binary incompatibility with libpng-1.0.50. - Backported new png_decompress_chunk() algorithm from libpng-1.4.1. + Revised Makefile.am and Makefile.in to remove references to Y2KINFO, + KNOWNBUG, and libpng.la (Robert Schwebel). + Revised the makefiles to install the same files and symbolic + links as configure, except for libpng.la and libpng14.la. + Make png_set|get_compression_buffer_size() available even when + PNG_WRITE_SUPPORTED is not enabled. + Revised Makefile.am and Makefile.in to simplify their maintenance. + Revised scripts/makefile.linux to install a link to libpng14.so.14.1 -version 1.2.43beta02 [February 1, 2010] - Backported two-pass png_decompress_chunk() algorithm from libpng-1.4.1. +Version 1.4.1beta02 [January 9, 2010] + Revised the rest of the makefiles to install a link to libpng14.so.14.1 -version 1.2.43beta03 [February 6, 2010] - Backported fast png_push_save_buffer() algorithm from libpng-1.4.1. - Backported some cosmetic changes from libpng-1.4.1. +Version 1.4.1beta03 [January 10, 2010] + Removed png_set_premultiply_alpha() from scripts/*.def -version 1.2.43beta04 [February 8, 2010] - Reverted recent changes to png_push_save-buffer(). - Removed PNGAPI declaration of png_calloc() and png_write_sig() in - 1ibpng-1.2.X, introduced by mistake in libpng-1.2.41. - Return allocated "old_buffer" in png_push_save_buffer() before png_error() - to avoid a potential memory leak. - -version 1.2.43beta05 [February 8, 2010] - Ported rewritten png_decompress_chunk() by John Bowler from libpng-1.4.1. - -version 1.0.53rc01 and 1.2.43rc01 [February 18, 2010] +Version 1.4.1rc01 [January 16, 2010] No changes. -version 1.0.53rc02 and 1.2.43rc02 [February 19, 2010] - Define _ALL_SOURCE in configure.ac, makefile.aix, and CMakeLists.txt - when using AIX compiler. +Version 1.4.1beta04 [January 23, 2010] + Revised png_decompress_chunk() to improve speed and memory usage when + decoding large chunks. + Added png_set|get_chunk_malloc_max() functions. -version 1.0.53 and 1.2.43 [February 25, 2010] +Version 1.4.1beta05 [January 26, 2010] + Relocated "int k" declaration in pngtest.c to minimize its scope. + +Version 1.4.1beta06 [January 28, 2010] + Revised png_decompress_chunk() to use a two-pass method suggested by + John Bowler. + +Version 1.4.1beta07 [February 6, 2010] + Folded some long lines in the source files. + Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, + and a PNG_USER_LIMITS_SUPPORTED flag. + Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as + png_ptr->png_user_chunk_malloc_max. + Revised png_push_save_buffer() to do fewer but larger png_malloc() calls. + +Version 1.4.1beta08 [February 6, 2010] + Minor cleanup and updating of dates and copyright year. + +Version 1.5.0beta01 [February 7, 2010] + Moved declaration of png_struct into private pngstruct.h and png_info + into pnginfo.h + +Version 1.4.1beta09 and 1.5.0beta02 [February 7, 2010] + Reverted to original png_push_save_buffer() code. + +Version 1.4.1beta10 and 1.5.0beta03 [February 8, 2010] + Return allocated "old_buffer" in png_push_save_buffer() before + calling png_error(), to avoid a potential memory leak. + Updated configure script to use SO number 15. + +Version 1.5.0beta04 [February 9, 2010] + Removed malformed "incomplete struct declaration" of png_info from png.h + +Version 1.5.0beta05 [February 12, 2010] + Removed PNG_DEPSTRUCT markup in pngstruct.h and pnginfo.h, and undid the + linewrapping that it entailed. + Revised comments in pngstruct.h and pnginfo.h and added pointers to + the libpng license. + Changed PNG_INTERNAL to PNG_EXPOSE_INTERNAL_STRUCTURES + Removed the cbuilder5 project, which has not been updated to 1.4.0. + +Version 1.4.1beta12 and 1.5.0beta06 [February 14, 2010] + Fixed type declaration of png_get_chunk_malloc_max() in pngget.c (Daisuke + Nishikawa) + +Version 1.5.0beta07 [omitted] + +Version 1.5.0beta08 [February 19, 2010] + Changed #ifdef PNG_NO_STDIO_SUPPORTED to #ifdef PNG_NO_CONSOLE_IO_SUPPORTED + wherever png_snprintf() is used to construct error and warning messages. + Noted in scripts/makefile.mingw that it expects to be run under MSYS. + Removed obsolete unused MMX-querying support from contrib/gregbook + Added exported png_longjmp() function. + Removed the AIX redefinition of jmpbuf in png.h + Added -D_ALLSOURCE in configure.ac, makefile.aix, and CMakeLists.txt + when building on AIX. + +Version 1.5.0beta09 [February 19, 2010] + Removed -D_ALLSOURCE from configure.ac, makefile.aix, and CMakeLists.txt. + Changed the name of png_ptr->jmpbuf to png_ptr->png_jmpbuf in pngstruct.h + +Version 1.5.0beta10 [February 25, 2010] Removed unused gzio.c from contrib/pngminim gather and makefile scripts + Removed replacement error handlers from contrib/gregbook. Because of + the new png_longjmp() function they are no longer needed. -version 1.2.44beta01 [June 18, 2010] +Version 1.5.0beta11 [March 6, 2010] + Removed checking for already-included setjmp.h from pngconf.h + Fixed inconsistent indentations and made numerous cosmetic changes. + Revised the "SEE ALSO" style of libpng.3, libpngpf.3, and png.5 + +Version 1.5.0beta12 [March 9, 2010] + Moved "#include png.h" inside pngpriv.h and removed "#include png.h" from + the source files, along with "#define PNG_EXPOSE_INTERNAL_STRUCTURES" + and "#define PNG_NO_PEDANTIC_WARNINGS" (John Bowler). + Created new pngdebug.h and moved debug definitions there. + +Version 1.5.0beta13 [March 10, 2010] + Protect pngstruct.h, pnginfo.h, and pngdebug.h from being included twice. + Revise the "#ifdef" blocks in png_inflate() so it will compile when neither + PNG_USER_CHUNK_MALLOC_MAX nor PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED + is defined. + Removed unused png_measure_compressed_chunk() from pngpriv.h and libpngpf.3 + Moved the 'config.h' support from pngconf.h to pngpriv.h + Removed PNGAPI from the png_longjmp_ptr typedef. + Eliminated dependence of pngtest.c on the private pngdebug.h file. + Make all png_debug macros into *unterminated* statements or + expressions (i.e. a trailing ';' must always be added) and correct + the format statements in various png_debug messages. + +Version 1.5.0beta14 [March 14, 2010] + Removed direct access to png_ptr->io_ptr from the Windows code in pngtest.c + Revised Makefile.am to account for recent additions and replacements. + Corrected CE and OS/2 DEF files (scripts/png*def) for symbols removed and + added ordinal numbers to the Windows DEF file and corrected the duplicated + ordinal numbers on CE symbols that are commented out. + Added back in export symbols that can be present in the Windows build but + are disabled by default. + PNG_EXPORT changed to include an 'ordinal' field for DEF file generation. + PNG_CALLBACK added to make callback definitions uniform. PNGAPI split + into PNGCAPI (base C form), PNGAPI (exports) and PNGCBAPI (callbacks), + and appropriate changes made to all files. Cygwin builds re-hinged to + allow procedure call standard changes and to remove the need for the DEF + file (fixes build on Cygwin). + Enabled 'attribute' warnings that are relevant to library APIs and callbacks. + Changed rules for generation of the various symbol files and added a new + rule for a DEF file (which is also added to the distribution). + Updated the symbol file generation to stop it adding spurious spaces + to EOL (coming from preprocessor macro expansion). Added a facility + to join tokens in the output and rewrite *.dfn to use this. + Eliminated scripts/*.def in favor of libpng.def; updated projects/visualc71 + and removed scripts/makefile.cygwin. + Made PNG_BUILD_DLL safe: it can be set whenever a DLL is being built. + Removed the include of sys/types.h - apparently unnecessary now on the + platforms on which it happened (all but Mac OS and RISC OS). + Moved the Mac OS test into pngpriv.h (the only place it is used.) + +Version 1.5.0beta15 [March 17, 2010] + Added symbols.chk target to Makefile.am to validate the symbols in png.h + against the new DEF file scripts/symbols.def. + Changed the default DEF file back to pngwin.def. + Removed makefile.mingw. + Eliminated PNG_NO_EXTERN and PNG_ALL_EXTERN + +Version 1.5.0beta16 [April 1, 2010] + Make png_text_struct independent of PNG_iTXt_SUPPORTED, so that + fields are initialized in all configurations. The READ/WRITE + macros (PNG_(READ|WRITE)_iTXt_SUPPORTED) still function as + before to disable code to actually read or write iTXt chunks + and iTXt_SUPPORTED can be used to detect presence of either + read or write support (but it is probably better to check for + the one actually required - read or write.) + Combined multiple png_warning() calls for a single error. + Restored the macro definition of png_check_sig(). + +Version 1.5.0beta17 [April 17, 2010] + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Documented the fact that png_set_dither() was disabled since libpng-1.4.0. + Reenabled png_set_dither() but renamed it to png_set_quantize() to reflect + more accurately what it actually does. At the same time, renamed + the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros to + PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS. + Added some "(long)" typecasts to printf calls in png_handle_cHRM(). + Freeze build-time only configuration in the build. + In all prior versions of libpng most configuration options + controlled by compiler #defines had to be repeated by the + application code that used libpng. This patch changes this + so that compilation options that can only be changed at build + time are frozen in the build. Options that are compiler + dependent (and those that are system dependent) are evaluated + each time - pngconf.h holds these. Options that can be changed + per-file in the application are in png.h. Frozen options are + in the new installed header file pnglibconf.h (John Bowler) + Removed the xcode project because it has not been updated to work + with libpng-1.5.0. + Removed the ability to include optional pngusr.h + +Version 1.5.0beta18 [April 17, 2010] + Restored the ability to include optional pngusr.h + Moved replacements for png_error() and png_warning() from the + contrib/pngminim project to pngerror.c, for use when warnings or + errors are disabled via PNG_NO_WARN or PNG_NO_ERROR_TEXT, to avoid + storing unneeded error/warning text. + Updated contrib/pngminim project to work with the new pnglibconf.h + Added some PNG_NO_* defines to contrib/pngminim/*/pngusr.h to save space. + +Version 1.5.0beta19 [April 24, 2010] + Added PNG_{READ,WRITE}_INT_FUNCTIONS_SUPPORTED. This allows the functions + to read and write ints to be disabled independently of PNG_USE_READ_MACROS, + which allows libpng to be built with the functions even though the default + is to use the macros - this allows applications to choose at app build + time whether or not to use macros (previously impossible because the + functions weren't in the default build.) + Changed Windows calling convention back to __cdecl for API functions. + For Windows/x86 platforms only: + __stdcall is no longer needed for Visual Basic, so libpng-1.5.0 uses + __cdecl throughout (both API functions and callbacks) on Windows/x86 + platforms. + Replaced visualc6 and visualc71 projects with new vstudio project + Relaxed the overly-restrictive permissions of some files. + +Version 1.5.0beta20 [April 24, 2010] + Relaxed more overly-restrictive permissions of some files. + +Version 1.5.0beta21 [April 27, 2010] + Removed some unwanted binary bytes and changed CRLF to NEWLINE in the new + vstudio project files, and some trivial editing of some files in the + scripts directory. + Set PNG_NO_READ_BGR, PNG_NO_IO_STATE, and PNG_NO_TIME_RFC1123 in + contrib/pngminim/decoder/pngusr.h to make a smaller decoder application. + +Version 1.5.0beta22 [April 28, 2010] + Fixed dependencies of GET_INT_32 - it does not require READ_INT_FUNCTIONS + because it has a macro equivalent. + Improved the options.awk script; added an "everything off" option. + Revised contrib/pngminim to use the "everything off" option in pngusr.dfa. + +Version 1.5.0beta23 [April 29, 2010] + Corrected PNG_REMOVED macro to take five arguments. + The macro was documented with two arguments (name,ordinal), however + the symbol checking .dfn files assumed five arguments. The five + argument form seems more useful so it is changed to that. + Corrected PNG_UNKNOWN_CHUNKS_SUPPORTED to PNG_HANDLE_AS_UNKNOWN_SUPPORTED + in gregbook/readpng2.c + Corrected protection of png_get_user_transform_ptr. The API declaration in + png.h is removed if both READ and WRITE USER_TRANSFORM are turned off + but was left defined in pngtrans.c + Added logunsupported=1 to cause pnglibconf.h to document disabled options. + This makes the installed pnglibconf.h more readable but causes no + other change. The intention is that users of libpng will find it + easier to understand if an API they need is missing. + Include png_reset_zstream() in png.c only when PNG_READ_SUPPORTED is defined. + Removed dummy_inflate.c from contrib/pngminim/encoder + Removed contrib/pngminim/*/gather.sh; gathering is now done in the makefile. + +Version 1.5.0beta24 [May 7, 2010] + Use bitwise "&" instead of arithmetic mod in pngrutil.c calculation of the + offset of the png_ptr->rowbuf pointer into png_ptr->big_row_buf. + Added more blank lines for readability. + +Version 1.5.0beta25 [June 18, 2010] In pngpread.c: png_push_have_row() add check for new_row > height Removed the now-redundant check for out-of-bounds new_row from example.c -version 1.2.44beta02 [June 19, 2010] +Version 1.5.0beta26 [June 18, 2010] In pngpread.c: png_push_process_row() add check for too many rows. - Removed the now-redundant check for new_row > height in png_push_have_row(). -version 1.2.44beta03 [June 20, 2010] - Rewrote png_process_IDAT_data() to consistently treat extra data as warnings +Version 1.5.0beta27 [June 18, 2010] + Removed the check added in beta25 as it is now redundant. + +Version 1.5.0beta28 [June 20, 2010] + Rewrote png_process_IDAT_data to consistently treat extra data as warnings and handle end conditions more cleanly. - Removed the new (beta02) check in png_push_process_row(). + Removed the new (beta26) check in png_push_process_row(). -version 1.2.44rc01 [June 21, 2010] - Revised some comments in png_process_IDAT_data(). +Version 1.5.0beta29 [June 21, 2010] + Revised scripts/options.awk to work on Sunos (but still doesn't work) + Added comment to options.awk and contrib/pngminim/*/makefile to try nawk. -version 1.2.44rc02 [June 22, 2010] +Version 1.5.0beta30 [June 22, 2010] Stop memory leak when reading a malformed sCAL chunk. -version 1.2.44rc03 [June 23, 2010] - Revised pngpread.c patch of beta05 to avoid an endless loop. +Version 1.5.0beta31 [June 26, 2010] + Revised pngpread.c patch of beta28 to avoid an endless loop. + Removed some trailing blanks. -version 1.2.44 [June 26, 2010] - Updated some of the "last changed" dates. +Version 1.5.0beta32 [June 26, 2010] + Removed leftover scripts/options.patch and scripts/options.rej -version 1.2.45beta01 [June 7, 2011] - Fixed uninitialized memory read in png_format_buffer() (Bug - report by Frank Busse, related to CVE-2004-0421). - Pass "" instead of '\0' to png_default_error() in png_err(). This mistake - was introduced in libpng-1.2.20beta01. - Check for up->location !PNG_AFTER_IDAT when writing unknown chunks - before IDAT. - Ported bugfix in pngrtran.c from 1.5.3: when expanding a paletted image, - always expand to RGBA if transparency is present. +Version 1.5.0beta33 [July 6, 3010] + Made FIXED and FLOATING options consistent in the APIs they enable and + disable. Corrected scripts/options.awk to handle both command line + options and options specified in the .dfa files. + Changed char *msg to PNG_CONST char *msg in pngrutil.c + Make png_set_sRGB_gAMA_and_cHRM set values using either the fixed or + floating point APIs, but not both. + Reversed patch to remove error handler when the jmp_buf is stored in the + main program structure, not the png_struct. + The error handler is needed because the default handler in libpng will + always use the jmp_buf in the library control structure; this is never + set. The gregbook code is a useful example because, even though it + uses setjmp/longjmp, it shows how error handling can be implemented + using control mechanisms not directly supported by libpng. The + technique will work correctly with mechanisms such as Microsoft + Structure Exceptions or C++ exceptions (compiler willing - note that gcc + does not by default support interworking of C and C++ error handling.) + Reverted changes to call png_longjmp in contrib/gregbook where it is not + appropriate. If mainprog->jmpbuf is used by setjmp, then png_longjmp + cannot be used. + Changed "extern PNG_EXPORT" to "PNG_EXPORT" in png.h (Jan Nijtmans) + Changed "extern" to "PNG_EXTERN" in pngpriv.h (except for the 'extern "C" {') -version 1.2.45beta02 [June 8, 2011] - Check for integer overflow in png_set_rgb_to_gray(). +Version 1.5.0beta34 [July 12, 2010] + Put #ifndef PNG_EXTERN, #endif around the define PNG_EXTERN in pngpriv.h -version 1.2.45beta03 [June 19, 2011] - Check for sCAL chunk too short. +Version 1.5.0beta35 [July 24, 2010] + Removed some newly-added TAB characters. + Added -DNO_PNG_SNPRINTF to CFLAGS in scripts/makefile.dj2 + Moved the definition of png_snprintf() outside of the enclosing + #ifdef blocks in pngconf.h -version 1.2.45rc01 and 1.0.55rc01 [June 30, 2011] - Updated "last changed" dates and copyright year. +Version 1.5.0beta36 [July 29, 2010] + Patches by John Bowler: + Fixed point APIs are now supported throughout (no missing APIs). + Internal fixed point arithmetic support exists for all internal floating + point operations. + sCAL validates the floating point strings it is passed. + Safe, albeit rudimentary, Watcom support is provided by PNG_API_RULE==2 + Two new APIs exist to get the number of passes without turning on the + PNG_INTERLACE transform and to get the number of rows in the current + pass. + A new test program, pngvalid.c, validates the gamma code. + Errors in the 16-bit gamma correction (overflows) have been corrected. + cHRM chunk testing is done consistently (previously the floating point + API bypassed it, because the test really didn't work on FP, now the test + is performed on the actual values to be stored in the PNG file so it + works in the FP case too.) + Most floating point APIs now simply call the fixed point APIs after + converting the values to the fixed point form used in the PNG file. + The standard headers no longer include zlib.h, which is currently only + required for pngstruct.h and can therefore be internal. + Revised png_get_int_32 to undo the PNG two's complement representation of + negative numbers. -version 1.2.45 and 1.0.55 [July 7, 2011] +Version 1.5.0beta37 [July 30, 2010] + Added a typecast in png_get_int_32() in png.h and pngrutil.h to avoid + a compiler warning. + Replaced oFFs 0,0 with oFFs -10,20 in pngtest.png + +Version 1.5.0beta38 [July 31, 2010] + Implemented remaining "_fixed" functions. + Corrected a number of recently introduced warnings mostly resulting from + safe but uncast assignments to shorter integers. Also added a zlib + VStudio release library project because the latest zlib Official Windows + build does not include such a thing. + Revised png_get_int_16() to be similar to png_get_int_32(). + Restored projects/visualc71. + +Version 1.5.0beta39 [August 2, 2010] + VisualC/GCC warning fixes, VisualC build fixes + The changes include support for function attributes in VC in addition to + those already present in GCC - necessary because without these some + warnings are unavoidable. Fixes include signed/unsigned fixes in + pngvalid and checks with gcc -Wall -Wextra -Wunused. + VC requires function attributes on function definitions as well as + declarations, PNG_FUNCTION has been added to enable this and the + relevant function definitions changed. + +Version 1.5.0beta40 [August 6, 2010] + Correct use of _WINDOWS_ in pngconf.h + Removed png_mem_ #defines; they are no longer used. + Added the sRGB chunk to pngtest.png + +Version 1.5.0beta41 [August 11, 2010] + Added the cHRM chunk to pngtest.png + Don't try to use version-script with cygwin/mingw. + Revised contrib/gregbook to work under cygwin/mingw. + +Version 1.5.0beta42 [August 18, 2010] + Add .dll.a to the list of extensions to be symlinked by Makefile.am (Yaakov) + Made all API functions that have const arguments and constant string + literal pointers declare them (John Bowler). + +Version 1.5.0beta43 [August 20, 2010] + Removed spurious tabs, shorten long lines (no source change) + Also added scripts/chkfmt to validate the format of all the files that can + reasonably be validated (it is suggested to run "make distclean" before + checking, because some machine generated files have long lines.) + Reformatted the CHANGES file to be more consistent throughout. + Made changes to address various issues identified by GCC, mostly + signed/unsigned and shortening problems on assignment but also a few + difficult to optimize (for GCC) loops. + Fixed non-GCC fixed point builds. In png.c a declaration was misplaced + in an earlier update. Fixed to declare the auto variables at the head. + Use cexcept.h in pngvalid.c. + +Version 1.5.0beta44 [August 24, 2010] + Updated CMakeLists.txt to use CMAKE_INSTALL_LIBDIR variable; useful for + installing libpng in /usr/lib64 (Funda Wang). + Revised CMakeLists.txt to put the man pages in share/man/man* not man/man* + Revised CMakeLists.txt to make symlinks instead of copies when installing. + Changed PNG_LIB_NAME from pngNN to libpngNN in CMakeLists.txt (Philip Lowman) + Implemented memory checks within pngvalid + Reformatted/rearranged pngvalid.c to assist use of progressive reader. + Check interlaced images in pngvalid + Clarified pngusr.h comments in pnglibconf.dfa + Simplified the pngvalid error-handling code now that cexcept.h is in place. + Implemented progressive reader in pngvalid.c for standard tests + Implemented progressive read in pngvalid.c gamma tests + Turn on progressive reader in pngvalid.c by default and tidy code. + +Version 1.5.0beta45 [August 26, 2010] + Added an explicit make step to projects/vstudio for pnglibconf.h + Also corrected zlib.vcxproj into which Visual Studio had introduced + what it calls an "authoring error". The change to make pnglibconf.h + simply copies the file; in the future it may actually generate the + file from scripts/pnglibconf.dfa as the other build systems do. + Changed pngvalid to work when floating point APIs are disabled + Renamed the prebuilt scripts/pnglibconf.h to scripts/pnglibconf.h.prebuilt + Supply default values for PNG_USER_PRIVATEBUILD and PNG_USER_DLLFNAME_POSTFIX + in pngpriv.h in case the user neglected to define them in their pngusr.h + +Version 1.5.0beta46 [August 28, 2010] + Added new private header files to libpng_sources in CMakeLists.txt + Added PNG_READ_16BIT, PNG_WRITE_16BIT, and PNG_16BIT options. + Added reference to scripts/pnglibconf.h.prebuilt in the visualc71 project. + +Version 1.5.0beta47 [September 11, 2010] + Fixed a number of problems with 64-bit compilation reported by Visual + Studio 2010 (John Bowler). + +Version 1.5.0beta48 [October 4, 2010] + Updated CMakeLists.txt (Philip Lowman). + Revised autogen.sh to recognize and use $AUTOCONF, $AUTOMAKE, $AUTOHEADER, + $AUTOPOINT, $ACLOCAL and $LIBTOOLIZE + Fixed problem with symbols creation in Makefile.am which was assuming that + all versions of ccp write to standard output by default (Martin Banky). The + bug was introduced in libpng-1.2.9beta5. + Removed unused mkinstalldirs. + +Version 1.5.0beta49 [October 8, 2010] + Undid Makefile.am revision of 1.5.0beta48. + +Version 1.5.0beta50 [October 14, 2010] + Revised Makefile.in to account for mkinstalldirs being removed. + Added some "(unsigned long)" typecasts in printf statements in pngvalid.c. + Suppressed a compiler warning in png_handle_sPLT(). + Check for out-of-range text compression mode in png_set_text(). + +Version 1.5.0beta51 [October 15, 2010] + Changed embedded dates to "(PENDING RELEASE) in beta releases (and future + rc releases) to minimize the difference between releases. + +Version 1.5.0beta52 [October 16, 2010] + Restored some of the embedded dates (in png.h, png.c, documentation, etc.) + +Version 1.5.0beta53 [October 18, 2010] + Updated INSTALL to mention using "make maintainer-clean" and to remove + obsolete statement about a custom ltmain.sh + Disabled "color-tests" by default in Makefile.am so it will work with + automake versions earlier than 1.11.1 + Use document name "libpng-manual.txt" instead of "libpng-.txt" + to simplify version differences. + Removed obsolete remarks about setjmp handling from INSTALL. + Revised and renamed the typedef in png.h and png.c that was designed + to catch library and header mismatch. + +Version 1.5.0beta54 [November 10, 2010] + Require 48 bytes, not 64 bytes, for big_row_buf in overflow checks. + Used a consistent structure for the pngget.c functions. + +Version 1.5.0beta55 [November 21, 2010] + Revised png_get_uint_32, png_get_int_32, png_get_uint_16 (Cosmin) + Moved reading of file signature into png_read_sig (Cosmin) + Fixed atomicity of chunk header serialization (Cosmin) + Added test for io_state in pngtest.c (Cosmin) + Added "#!/bin/sh" at the top of contrib/pngminim/*/gather.sh scripts. + Changes to remove gcc warnings (John Bowler) + Certain optional gcc warning flags resulted in warnings in libpng code. + With these changes only -Wconversion and -Wcast-qual cannot be turned on. + Changes are trivial rearrangements of code. -Wconversion is not possible + for pngrutil.c (because of the widespread use of += et al on variables + smaller than (int) or (unsigned int)) and -Wcast-qual is not possible + with pngwio.c and pngwutil.c because the 'write' callback and zlib + compression both fail to declare their input buffers with 'const'. + +Version 1.5.0beta56 [December 7, 2010] + Added the private PNG_UNUSED() macro definition in pngpriv.h. + Added some commentary about PNG_EXPORT in png.h and pngconf.h + Revised PNG_EXPORT() macro and added PNG_EXPORTA() macro, with the + objective of simplifying and improving the cosmetic appearance of png.h. + Fixed some incorrect "=" macro names in pnglibconf.dfa + Included documentation of changes in 1.5.0 from 1.4.x in libpng-manual.txt + +Version 1.5.0beta57 [December 9, 2010] + Documented the pngvalid gamma error summary with additional comments and + print statements. + Improved missing symbol handling in checksym.awk; symbols missing in both + the old and new files can now be optionally ignored, treated as errors + or warnings. + Removed references to pngvcrd.c and pnggccrd.c from the vstudio project. + Updated "libpng14" to "libpng15" in the visualc71 project. + Enabled the strip16 tests in pngvalid.` + Don't display test results (except PASS/FAIL) when running "make test". + Instead put them in pngtest-log.txt + Added "--with-zprefix=" to configure.ac + Updated the prebuilt configuration files to autoconf version 2.68 + +Version 1.5.0beta58 [December 19, 2010] + Fixed interlace image handling and add test cases (John Bowler) + Fixed the clean rule in Makefile.am to remove pngtest-log.txt + Made minor changes to work around warnings in gcc 3.4 + +Version 1.5.0rc01 [December 27, 2010] No changes. -version 1.2.46rc01 and 1.0.56rc01 [July 8, 2011] - Reverted changes to Makefile.am and Makefile.in to libpng-1.2.44 versions. +Version 1.5.0rc02 [December 27, 2010] + Eliminated references to the scripts/*.def files in project/visualc71. -version 1.2.46rc02 and 1.0.56rc02 [July 8, 2011] - Added CMakeLists.txt, projects/xcode, and pnggccrd.c to EXTRA_DIST in - Makefile.am and Makefile.in +Version 1.5.0rc03 [December 28, 2010] + Eliminated scripts/*.def and revised Makefile.am accordingly -version 1.2.46 and 1.0.56 [July 9, 2011] - Udated copyright year to 2011. +Version 1.5.0rc04 [December 29, 2010] + Fixed bug in background transformation handling in pngrtran.c (it was + looking for the flag in png_ptr->transformations instead of in + png_ptr->flags) (David Raymond). -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit +Version 1.5.0rc05 [December 31, 2010] + Fixed typo in a comment in CMakeLists.txt (libpng14 => libpng15) (Cosmin) + +Version 1.5.0rc06 [January 4, 2011] + Changed the new configure option "zprefix=string" to "zlib-prefix=string" + +Version 1.5.0rc07 [January 4, 2011] + Updated copyright year. + +Version 1.5.0 [January 6, 2011] + No changes. + +version 1.5.1beta01 [January 8, 2011] + Added description of png_set_crc_action() to the manual. + Added a note in the manual that the type of the iCCP profile was changed + from png_charpp to png_bytepp in png_get_iCCP(). This change happened + in version 1.5.0beta36 but is not noted in the CHANGES. Similarly, + it was changed from png_charpp to png_const_bytepp in png_set_iCCP(). + Ensure that png_rgb_to_gray ignores palette mapped images, if libpng + internally happens to call it with one, and fixed a failure to handle + palette mapped images correctly. This fixes CVE-2690. + +Version 1.5.1beta02 [January 14, 2011] + Fixed a bug in handling of interlaced images (bero at arklinux.org). + Updated CMakeLists.txt (Clifford Yapp) + +Version 1.5.1beta03 [January 14, 2011] + Fixed typecasting of some png_debug() statements (Cosmin) + +Version 1.5.1beta04 [January 16, 2011] + Updated documentation of png_set|get_tRNS() (Thomas Klausner). + Mentioned in the documentation that applications must #include "zlib.h" + if they need access to anything in zlib.h, and that a number of + macros such as png_memset() are no longer accessible by applications. + Corrected pngvalid gamma test "sample" function to access all of the color + samples of each pixel, instead of sampling the red channel three times. + Prefixed variable names index, div, exp, gamma with "png_" to avoid "shadow" + warnings, and (mistakenly) changed png_exp() to exp(). + +Version 1.5.1beta05 [January 16, 2011] + Changed variable names png_index, png_div, png_exp, and png_gamma to + char_index, divisor, exp_b10, and gamma_val, respectively, and + changed exp() back to png_exp(). + +Version 1.5.1beta06 [January 20, 2011] + Prevent png_push_crc_skip() from hanging while reading an unknown chunk + or an over-large compressed zTXt chunk with the progressive reader. + Eliminated more GCC "shadow" warnings. + Revised png_fixed() in png.c to avoid compiler warning about reaching the + end without returning anything. + +Version 1.5.1beta07 [January 22, 2011] + In the manual, describe the png_get_IHDR() arguments in the correct order. + Added const_png_structp and const_png_infop types, and used them in + prototypes for most png_get_*() functions. + +Version 1.5.1beta08 [January 23, 2011] + Added png_get_io_chunk_type() and deprecated png_get_io_chunk_name() + Added synopses for the IO_STATE functions and other missing synopses + to the manual. Removed the synopses from libpngpf.3 because they + were out of date and no longer useful. Better information can be + obtained by reading the prototypes and comments in pngpriv.h + Attempted to fix cpp on Solaris with S. Studio 12 cc, fix build + Added a make macro DFNCPP that is a CPP that will accept the tokens in + a .dfn file and adds configure stuff to test for such a CPP. ./configure + should fail if one is not available. + Corrected const_png_ in png.h to png_const_ to avoid polluting the namespace. + Added png_get_current_row_number and png_get_current_pass_number for the + benefit of the user transform callback. + Added png_process_data_pause and png_process_data_skip for the benefit of + progressive readers that need to stop data processing or want to optimize + skipping of unread data (e.g., if the reader marks a chunk to be skipped.) + +Version 1.5.1beta09 [January 24, 2011] + Enhanced pngvalid, corrected an error in gray_to_rgb, corrected doc error. + pngvalid contains tests of transforms, which tests are currently disabled + because they are incompletely tested. gray_to_rgb was failing to expand + the bit depth for smaller bit depth images; this seems to be a long + standing error and resulted, apparently, in invalid output + (CVE-2011-0408, CERT VU#643140). The documentation did not accurately + describe what libpng really does when converting RGB to gray. + +Version 1.5.1beta10 [January 27, 2010] + Fixed incorrect examples of callback prototypes in the manual, that were + introduced in libpng-1.0.0. + In addition the order of the png_get_uint macros with respect to the + relevant function definitions has been reversed. This helps the + preprocessing of the symbol files be more robust. Furthermore, the + symbol file preprocessing now uses -DPNG_NO_USE_READ_MACROS even when + the library may actually be built with PNG_USE_READ_MACROS; this stops + the read macros interfering with the symbol file format. + Made the manual, synopses, and function prototypes use the function + argument names file_gamma, int_file_gamma, and srgb_intent consistently. + +Version 1.5.1beta11 [January 28, 2011] + Changed PNG_UNUSED from "param=param;" to "{if(param){}}". + Corrected local variable type in new API png_process_data_skip() + The type was self-evidently incorrect but only causes problems on 64-bit + architectures. + Added transform tests to pngvalid and simplified the arguments. + +Version 1.5.1rc01 [January 29, 2011] + No changes. + +Version 1.5.1rc02 [January 31, 2011] + Added a request in the manual that applications do not use "png_" or + "PNG_" to begin any of their own symbols. + Changed PNG_UNUSED to "(void)param;" and updated the commentary in pngpriv.h + +Version 1.5.1 [February 3, 2011] + No changes. + +Version 1.5.2beta01 [February 13, 2011] + More -Wshadow fixes for older gcc compilers. Older gcc versions apparently + check formal parameters names in function declarations (as well as + definitions) to see if they match a name in the global namespace. + Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the + old VisualC++ preprocessor. + Turned on interlace handling in png_read_png(). + Fixed gcc pedantic warnings. + Handle longjmp in Cygwin. + Fixed png_get_current_row_number() in the interlaced case. + Cleaned up ALPHA flags and transformations. + Implemented expansion to 16 bits. + +Version 1.5.2beta02 [February 19, 2011] + Fixed mistake in the descriptions of user read_transform and write_transform + function prototypes in the manual. The row_info struct is png_row_infop. + Reverted png_get_current_row_number() to previous (1.5.2beta01) behavior. + Corrected png_get_current_row_number documentation + Fixed the read/write row callback documentation. + This documents the current behavior, where the callback is called after + every row with information pertaining to the next row. + +Version 1.5.2beta03 [March 3, 2011] + Fixed scripts/makefile.vcwin32 + Updated contrib/pngsuite/README to add the word "modify". + Define PNG_ALLOCATED to blank when _MSC_VER<1300. + +Version 1.5.2rc01 [March 19, 2011] + Define remaining attributes to blank when MSC_VER<1300. + ifdef out mask arrays in pngread.c when interlacing is not supported. + +Version 1.5.2rc02 [March 22, 2011] + Added a hint to try CPP=/bin/cpp if "cpp -E" fails in scripts/pnglibconf.mak + and in contrib/pngminim/*/makefile, eg., on SunOS 5.10, and removed "strip" + from the makefiles. + Fixed a bug (present since libpng-1.0.7) that makes png_handle_sPLT() fail + to compile when PNG_NO_POINTER_INDEXING is defined (Chubanov Kirill) + +Version 1.5.2rc03 [March 24, 2011] + Don't include standard header files in png.h while building the symbol table, + to avoid cpp failure on SunOS (introduced PNG_BUILDING_SYMBOL_TABLE macro). + +Version 1.5.2 [March 31, 2011] + No changes. + +Version 1.5.3beta01 [April 1, 2011] + Re-initialize the zlib compressor before compressing non-IDAT chunks. + Added API functions (png_set_text_compression_level() and four others) to + set parameters for zlib compression of non-IDAT chunks. + +Version 1.5.3beta02 [April 3, 2011] + Updated scripts/symbols.def with new API functions. + Only compile the new zlib re-initializing code when text or iCCP is + supported, using PNG_WRITE_COMPRESSED_TEXT_SUPPORTED macro. + Improved the optimization of the zlib CMF byte (see libpng-1.2.6beta03). + Optimize the zlib CMF byte in non-IDAT compressed chunks + +Version 1.5.3beta03 [April 16, 2011] + Fixed gcc -ansi -pedantic compile. A strict ANSI system does not have + snprintf, and the "__STRICT_ANSI__" detects that condition more reliably + than __STDC__ (John Bowler). + Removed the PNG_PTR_NORETURN attribute because it too dangerous. It tells + the compiler that a user supplied callback (the error handler) does not + return, yet there is no guarantee in practice that the application code + will correctly implement the error handler because the compiler only + issues a warning if there is a mistake (John Bowler). + Removed the no-longer-used PNG_DEPSTRUCT macro. + Updated the zlib version to 1.2.5 in the VStudio project. + Fixed 64-bit builds where png_uint_32 is smaller than png_size_t in + pngwutil.c (John Bowler). + Fixed bug with stripping the filler or alpha channel when writing, that + was introduced in libpng-1.5.2beta01 (bug report by Andrew Church). + +Version 1.5.3beta04 [April 27, 2011] + Updated pngtest.png with the new zlib CMF optimization. + Cleaned up conditional compilation code and of background/gamma handling + Internal changes only except a new option to avoid compiling the + png_build_grayscale_palette API (which is not used at all internally.) + The main change is to move the transform tests (READ_TRANSFORMS, + WRITE_TRANSFORMS) up one level to the caller of the APIs. This avoids + calls to spurious functions if all transforms are disabled and slightly + simplifies those functions. Pngvalid modified to handle this. + A minor change is to stop the strip_16 and expand_16 interfaces from + disabling each other; this allows the future alpha premultiplication + code to use 16-bit intermediate values while still producing 8-bit output. + png_do_background and png_do_gamma have been simplified to take a single + pointer to the png_struct rather than pointers to every item required + from the png_struct. This makes no practical difference to the internal + code. + A serious bug in the pngvalid internal routine 'standard_display_init' has + been fixed - this failed to initialize the red channel and accidentally + initialized the alpha channel twice. + Changed png_struct jmp_buf member name from png_jmpbuf to tmp_jmpbuf to + avoid a possible clash with the png_jmpbuf macro on some platforms. + +Version 1.5.3beta05 [May 6, 2011] + Added the "_POSIX_SOURCE" feature test macro to ensure libpng sees the + correct API. _POSIX_SOURCE is defined in pngpriv.h, pngtest.c and + pngvalid.c to ensure that POSIX conformant systems disable non-POSIX APIs. + Removed png_snprintf and added formatted warning messages. This change adds + internal APIs to allow png_warning messages to have parameters without + requiring the host OS to implement snprintf. As a side effect the + dependency of the tIME-supporting RFC1132 code on stdio is removed and + PNG_NO_WARNINGS does actually work now. + Pass "" instead of '\0' to png_default_error() in png_err(). This mistake + was introduced in libpng-1.2.20beta01. This fixes CVE-2011-2691. + Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte + optimization configurable. + IDAT compression failed if preceded by a compressed text chunk (bug + introduced in libpng-1.5.3beta01-02). This was because the attempt to + reset the zlib stream in png_write_IDAT happened after the first IDAT + chunk had been deflated - much too late. In this change internal + functions were added to claim/release the z_stream and, hopefully, make + the code more robust. Also deflateEnd checking is added - previously + libpng would ignore an error at the end of the stream. + +Version 1.5.3beta06 [May 8, 2011] + Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt + Implemented premultiplied alpha support: png_set_alpha_mode API + +Version 1.5.3beta07 [May 11, 2011] + Added expand_16 support to the high level interface. + Added named value and 'flag' gamma support to png_set_gamma. Made a minor + change from the previous (unreleased) ABI/API to hide the exact value used + for Macs - it's not a good idea to embed this in the ABI! + Moved macro definitions for PNG_HAVE_IHDR, PNG_HAVE_PLTE, and PNG_AFTER_IDAT + from pngpriv.h to png.h because they must be visible to applications + that call png_set_unknown_chunks(). + Check for up->location !PNG_AFTER_IDAT when writing unknown chunks + before IDAT. + +Version 1.5.3beta08 [May 16, 2011] + Improved "pngvalid --speed" to exclude more of pngvalid from the time. + Documented png_set_alpha_mode(), other changes in libpng.3/libpng-manual.txt + The cHRM chunk now sets the defaults for png_set_rgb_to_gray() (when negative + parameters are supplied by the caller), while in the absence of cHRM + sRGB/Rec 709 values are still used. This introduced a divide-by-zero + bug in png_handle_cHRM(). + The bKGD chunk no longer overwrites the background value set by + png_set_background(), allowing the latter to be used before the file + header is read. It never performed any useful function to override + the default anyway. + Added memory overwrite and palette image checks to pngvalid.c + Previously palette image code was poorly checked. Since the transformation + code has a special palette path in most cases this was a severe weakness. + Minor cleanup and some extra checking in pngrutil.c and pngrtran.c. When + expanding an indexed image, always expand to RGBA if transparency is + present. + +Version 1.5.3beta09 [May 17, 2011] + Reversed earlier 1.5.3 change of transformation order; move png_expand_16 + back where it was. The change doesn't work because it requires 16-bit + gamma tables when the code only generates 8-bit ones. This fails + silently; the libpng code just doesn't do any gamma correction. Moving + the tests back leaves the old, inaccurate, 8-bit gamma calculations, but + these are clearly better than none! + +Version 1.5.3beta10 [May 20, 2011] + + png_set_background() and png_expand_16() did not work together correctly. + This problem is present in 1.5.2; if png_set_background is called with + need_expand false and the matching 16 bit color libpng erroneously just + treats it as an 8-bit color because of where png_do_expand_16 is in the + transform list. This simple fix reduces the supplied colour to 8-bits, + so it gets smashed, but this is better than the current behavior. + Added tests for expand16, more fixes for palette image tests to pngvalid. + Corrects the code for palette image tests and disables attempts to + validate palette colors. + +Version 1.5.3rc01 [June 3, 2011] + No changes. + +Version 1.5.3rc02 [June 8, 2011] + Fixed uninitialized memory read in png_format_buffer() (Bug report by + Frank Busse, CVE-2011-2501, related to CVE-2004-0421). + +Version 1.5.3beta11 [June 11, 2011] + Fixed png_handle_sCAL which is broken in 1.5. This fixes CVE 2011-2692. + Added sCAL to pngtest.png + Revised documentation about png_set_user_limits() to say that it also affects + png writing. + Revised handling of png_set_user_limits() so that it can increase the + limit beyond the PNG_USER_WIDTH|HEIGHT_MAX; previously it could only + reduce it. + Make the 16-to-8 scaling accurate. Dividing by 256 with no rounding is + wrong (high by one) 25% of the time. Dividing by 257 with rounding is + wrong in 128 out of 65536 cases. Getting the right answer all the time + without division is easy. + Added "_SUPPORTED" to the PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION macro. + Added projects/owatcom, an IDE project for OpenWatcom to replace + scripts/makefile.watcom. This project works with OpenWatcom 1.9. The + IDE autogenerates appropriate makefiles (libpng.mk) for batch processing. + The project is configurable, unlike the Visual Studio project, so long + as the developer has an awk. + Changed png_set_gAMA to limit the gamma value range so that the inverse + of the stored value cannot overflow the fixed point representation, + and changed other things OpenWatcom warns about. + Revised pngvalid.c to test PNG_ALPHA_MODE_SUPPORTED correctly. This allows + pngvalid to build when ALPHA_MODE is not supported, which is required if + it is to build on libpng 1.4. + Removed string/memory macros that are no longer used and are not + necessarily fully supportable, particularly png_strncpy and png_snprintf. + Added log option to pngvalid.c and attempted to improve gamma messages. + +Version 1.5.3 [omitted] + People found the presence of a beta release following an rc release + to be confusing; therefore we bump the version to libpng-1.5.4beta01 + and there will be no libpng-1.5.3 release. + +Version 1.5.4beta01 [June 14, 2011] + Made it possible to undefine PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED + to get the same (inaccurate) output as libpng-1.5.2 and earlier. + Moved definitions of PNG_HAVE_IHDR, PNG_AFTER_IDAT, and PNG_HAVE_PLTE + outside of an unknown-chunk block in png.h because they are also + needed for other uses. + +Version 1.5.4beta02 [June 14, 2011] + Fixed and clarified LEGACY 16-to-8 scaling code. + Added png_set_chop_16() API, to match inaccurate results from previous + libpng versions. + Removed the ACCURATE and LEGACY options (they are no longer useable) + Use the old scaling method for background if png_set_chop_16() was + called. + Made png_set_chop_16() API removeable by disabling PNG_CHOP_16_TO_8_SUPPORTED + +Version 1.5.4beta03 [June 15, 2011] + Fixed a problem in png_do_expand_palette() exposed by optimization in + 1.5.3beta06 + Also removed a spurious and confusing "trans" member ("trans") from png_info. + The palette expand optimization prevented expansion to an intermediate RGBA + form if tRNS was present but alpha was marked to be stripped; this exposed + a check for tRNS in png_do_expand_palette() which is inconsistent with the + code elsewhere in libpng. + Correction to the expand_16 code; removed extra instance of + png_set_scale_16_to_8 from pngpriv.h + +Version 1.5.4beta04 [June 16, 2011] + Added a missing "#ifdef PNG_READ_BACKGROUND_SUPPORTED/#endif" in pngrtran.c + Added PNG_TRANSFORM_CHOP_16 to the high-level read transforms. + Made PNG_READ_16_TO_8_ACCURATE_SCALE configurable again. If this is + not enabled, png_set_strip_16() and png_do_scale_16_to_8() aren't built. + Revised contrib/visupng, gregbook, and pngminim to demonstrate chop_16_to_8 + +Version 1.5.4beta05 [June 16, 2011] + Renamed png_set_strip_16() to png_set_scale_16() and renamed + png_set_chop_16() to png_set_strip(16) in an attempt to minimize the + behavior changes between libpng14 and libpng15. + +Version 1.5.4beta06 [June 18, 2011] + Fixed new bug that was causing both strip_16 and scale_16 to be applied. + +Version 1.5.4beta07 [June 19, 2011] + Fixed pngvalid, simplified macros, added checking for 0 in sCAL. + The ACCURATE scale macro is no longer defined in 1.5 - call the + png_scale_16_to_8 API. Made sure that PNG_READ_16_TO_8 is still defined + if the png_strip_16_to_8 API is present. png_check_fp_number now + maintains some state so that positive, negative and zero values are + identified. sCAL uses these to be strictly spec conformant. + +Version 1.5.4beta08 [June 23, 2011] + Fixed pngvalid if ACCURATE_SCALE is defined. + Updated scripts/pnglibconf.h.prebuilt. + +Version 1.5.4rc01 [June 30, 2011] + Define PNG_ALLOCATED to "restrict" only if MSC_VER >= 1400. + +Version 1.5.4 [July 7, 2011] + No changes. + +Version 1.5.5beta01 [July 13, 2011] + Fixed some typos and made other minor changes in the manual. + Updated contrib/pngminus/makefile.std (Samuli Souminen) + +Version 1.5.5beta02 [July 14, 2011] + Revised Makefile.am and Makefile.in to look in the right directory for + pnglibconf.h.prebuilt + +Version 1.5.5beta03 [July 27, 2011] + Enabled compilation with g++ compiler. This compiler does not recognize + the file extension, so it always compiles with C++ rules. Made minor + changes to pngrutil.c to cast results where C++ expects it but C does not. + Minor editing of libpng.3 and libpng-manual.txt. + +Version 1.5.5beta04 [July 29, 2011] + Revised CMakeLists.txt (Clifford Yapp) + Updated commentary about the png_rgb_to_gray() default coefficients + in the manual and in pngrtran.c + +Version 1.5.5beta05 [August 17, 2011] + Prevent unexpected API exports from non-libpng DLLs on Windows. The "_DLL" + is removed from the test of whether a DLL is being built (this erroneously + caused the libpng APIs to be marked as DLL exports in static builds under + Microsoft Visual Studio). Almost all of the libpng building configuration + is moved from pngconf.h to pngpriv.h, but PNG_DLL_EXPORT remains in + pngconf.h, though, so that it is colocated with the import definition (it + is no longer used anywhere in the installed headers). The VStudio project + definitions have been cleaned up: "_USRDLL" has been removed from the + static library builds (this was incorrect), and PNG_USE_DLL has been added + to pngvalid to test the functionality (pngtest does not supply it, + deliberately). The spurious "_EXPORTS" has been removed from the + libpng build (all these errors were a result of copy/paste between project + configurations.) + Added new types and internal functions for CIE RGB end point handling to + pngpriv.h (functions yet to be implemented). + +Version 1.5.5beta06 [August 26, 2011] + Ensure the CMAKE_LIBRARY_OUTPUT_DIRECTORY is set in CMakeLists.txt + (Clifford Yap) + Fixes to rgb_to_gray and cHRM XYZ APIs (John Bowler): + The rgb_to_gray code had errors when combined with gamma correction. + Some pixels were treated as true grey when they weren't and such pixels + and true grey ones were not gamma corrected (the original value of the + red component was used instead). APIs to get and set cHRM using color + space end points have been added and the rgb_to_gray code that defaults + based on cHRM, and the divide-by-zero bug in png_handle_cHRM (CERT + VU#477046, CVE-2011-3328, introduced in 1.5.4) have been corrected. + A considerable number of tests has been added to pngvalid for the + rgb_to_gray transform. + Arithmetic errors in rgb_to_gray whereby the calculated gray value was + truncated to the bit depth rather than rounded have been fixed except in + the 8-bit non-gamma-corrected case (where consistency seems more important + than correctness.) The code still has considerable inaccuracies in the + 8-bit case because 8-bit linear arithmetic is used. + +Version 1.5.5beta07 [September 7, 2011] + Added "$(ARCH)" option to makefile.darwin + Added SunOS support to configure.ac and Makefile.am + Changed png_chunk_benign_error() to png_warning() in png.c, in + png_XYZ_from_xy_checked(). + +Version 1.5.5beta08 [September 10, 2011] + Fixed 64-bit compilation errors (gcc). The errors fixed relate + to conditions where types that are 32 bits in the GCC 32-bit + world (uLong and png_size_t) become 64 bits in the 64-bit + world. This produces potential truncation errors which the + compiler correctly flags. + Relocated new HAVE_SOLARIS_LD definition in configure.ac + Constant changes for 64-bit compatibility (removal of L suffixes). The + 16-bit cases still use "L" as we don't have a 16-bit test system. + +Version 1.5.5rc01 [September 15, 2011] + Removed "L" suffixes in pngpriv.h + +Version 1.5.5 [September 22, 2011] + No changes. + +Version 1.5.6beta01 [September 22, 2011] + Fixed some 64-bit type conversion warnings in pngrtran.c + Moved row_info from png_struct to a local variable. + The various interlace mask arrays have been made into arrays of + bytes and made PNG_CONST and static (previously some arrays were + marked PNG_CONST and some weren't). + Additional checks have been added to the transform code to validate the + pixel depths after the transforms on both read and write. + Removed some redundant code from pngwrite.c, in png_destroy_write_struct(). + Changed chunk reading/writing code to use png_uint_32 instead of png_byte[4]. + This removes the need to allocate temporary strings for chunk names on + the stack in the read/write code. Unknown chunk handling still uses the + string form because this is exposed in the API. + +Version 1.5.6beta02 [September 26, 2011] + Added a note in the manual the png_read_update_info() must be called only + once with a particular info_ptr. + Fixed a typo in the definition of the new PNG_STRING_FROM_CHUNK(s,c) macro. + +Version 1.5.6beta03 [September 28, 2011] + Revised test-pngtest.sh to report FAIL when pngtest fails. + Added "--strict" option to pngtest, to report FAIL when the failure is + only because the resulting valid files are different. + Revised CMakeLists.txt to work with mingw and removed some material from + CMakeLists.txt that is no longer useful in libpng-1.5. + +Version 1.5.6beta04 [October 5, 2011] + Fixed typo in Makefile.in and Makefile.am ("-M Wl" should be "-M -Wl")." + +Version 1.5.6beta05 [October 12, 2011] + Speed up png_combine_row() for interlaced images. This reduces the generality + of the code, allowing it to be optimized for Adam7 interlace. The masks + passed to png_combine_row() are now generated internally, avoiding + some code duplication and localizing the interlace handling somewhat. + Align png_struct::row_buf - previously it was always unaligned, caused by + a bug in the code that attempted to align it; the code needs to subtract + one from the pointer to take account of the filter byte prepended to + each row. + Optimized png_combine_row() when rows are aligned. This gains a small + percentage for 16-bit and 32-bit pixels in the typical case where the + output row buffers are appropriately aligned. The optimization was not + previously possible because the png_struct buffer was always misaligned. + Fixed bug in png_write_chunk_header() debug print, introduced in 1.5.6beta01. + +Version 1.5.6beta06 [October 17, 2011] + Removed two redundant tests for uninitialized row. + Fixed a relatively harmless memory overwrite in compressed text writing + with a 1 byte zlib buffer. + Add ability to call png_read_update_info multiple times to pngvalid.c. + Fixes for multiple calls to png_read_update_info. These fixes attend to + most of the errors revealed in pngvalid, however doing the gamma work + twice results in inaccuracies that can't be easily fixed. There is now + a warning in the code if this is going to happen. + Turned on multiple png_read_update_info in pngvalid transform tests. + Prevent libpng from overwriting unused bits at the end of the image when + it is not byte aligned, while reading. Prior to libpng-1.5.6 libpng would + overwrite the partial byte at the end of each row if the row width was not + an exact multiple of 8 bits and the image is not interlaced. + +Version 1.5.6beta07 [October 21, 2011] + Made png_ptr->prev_row an aligned pointer into png_ptr->big_prev_row + (Mans Rullgard). + +Version 1.5.6rc01 [October 26, 2011] + Changed misleading "Missing PLTE before cHRM" warning to "Out of place cHRM" + +Version 1.5.6rc02 [October 27, 2011] + Added LSR() macro to defend against buggy compilers that evaluate non-taken + code branches and complain about out-of-range shifts. + +Version 1.5.6rc03 [October 28, 2011] + Renamed the LSR() macro to PNG_LSR() and added PNG_LSL() macro. + Fixed compiler warnings with Intel and MSYS compilers. The logical shift + fix for Microsoft Visual C is required by other compilers, so this + enables that fix for all compilers when using compile-time constants. + Under MSYS 'byte' is a name declared in a system header file, so we + changed the name of a local variable to avoid the warnings that result. + Added #define PNG_ALIGN_TYPE PNG_ALIGN_NONE to contrib/pngminim/*/pngusr.h + +Version 1.5.6 [November 3, 2011] + No changes. + +Version 1.5.7beta01 [November 4, 2011] + Added support for ARM processor, when decoding all PNG up-filtered rows + and any other-filtered rows with 3 or 4 bytes per pixel (Mans Rullgard). + Fixed bug in pngvalid on early allocation failure; fixed type cast in + pngmem.c; pngvalid would attempt to call png_error() if the allocation + of a png_struct or png_info failed. This would probably have led to a + crash. The pngmem.c implementation of png_malloc() included a cast + to png_size_t which would fail on large allocations on 16-bit systems. + Fix for the preprocessor of the Intel C compiler. The preprocessor + splits adjacent @ signs with a space; this changes the concatenation + token from @-@-@ to PNG_JOIN; that should work with all compiler + preprocessors. + Paeth filter speed improvements from work by Siarhei Siamashka. This + changes the 'Paeth' reconstruction function to improve the GCC code + generation on x86. The changes are only part of the suggested ones; + just the changes that definitely improve speed and remain simple. + The changes also slightly increase the clarity of the code. + +Version 1.5.7beta02 [November 11, 2011] + Check compression_type parameter in png_get_iCCP and remove spurious + casts. The compression_type parameter is always assigned to, so must + be non-NULL. The cast of the profile length potentially truncated the + value unnecessarily on a 16-bit int system, so the cast of the (byte) + compression type to (int) is specified by ANSI-C anyway. + Fixed FP division by zero in pngvalid.c; the 'test_pixel' code left + the sBIT fields in the test pixel as 0, which resulted in a floating + point division by zero which was irrelevant but causes systems where + FP exceptions cause a crash. Added code to pngvalid to turn on FP + exceptions if the appropriate glibc support is there to ensure this is + tested in the future. + Updated scripts/pnglibconf.mak and scripts/makefile.std to handle the + new PNG_JOIN macro. + Added versioning to pnglibconf.h comments. + Simplified read/write API initial version; basic read/write tested on + a variety of images, limited documentation (in the header file.) + Installed more accurate linear to sRGB conversion tables. The slightly + modified tables reduce the number of 16-bit values that + convert to an off-by-one 8-bit value. The "makesRGB.c" code that was used + to generate the tables is now in a contrib/sRGBtables sub-directory. + +Version 1.5.7beta03 [November 17, 2011] + Removed PNG_CONST from the sRGB table declarations in pngpriv.h and png.c + Added run-time detection of NEON support. + Added contrib/libtests; includes simplified API test and timing test and + a color conversion utility for rapid checking of failed 'pngstest' results. + Multiple transform bug fixes plus a work-round for double gamma correction. + libpng does not support more than one transform that requires linear data + at once - if this is tried typically the results is double gamma + correction. Since the simplified APIs can need rgb to gray combined with + a compose operation it is necessary to do one of these outside the main + libpng transform code. This check-in also contains fixes to various bugs + in the simplified APIs themselves and to some bugs in compose and rgb to + gray (on palette) itself. + Fixes for C++ compilation using g++ When libpng source is compiled + using g++. The compiler imposes C++ rules on the C source; thus it + is desirable to make the source work with either C or C++ rules + without throwing away useful error information. This change adds + png_voidcast to allow C semantic (void*) cases or the corresponding + C++ static_cast operation, as appropriate. + Added --noexecstack to assembler file compilation. GCC does not set + this on assembler compilation, even though it does on C compilation. + This creates security issues if assembler code is enabled; the + work-around is to set it by default in the flags for $(CCAS) + Work around compilers that don't support declaration of const data. Some + compilers fault 'extern const' data declarations (because the data is + not initialized); this turns on const-ness only for compilers where + this is known to work. + +Version 1.5.7beta04 [November 17, 2011] + Since the gcc driver does not recognize the --noexecstack flag, we must + use the -Wa prefix to have it passed through to the assembler. + Also removed a duplicate setting of this flag. + Added files that were omitted from the libpng-1.5.7beta03 zip distribution. + +Version 1.5.7beta05 [November 25, 2011] + Removed "zTXt" from warning in generic chunk decompression function. + Validate time settings passed to png_set_tIME() and png_convert_to_rfc1123() + (Frank Busse). Note: This prevented CVE-2015-7981 from affecting + libpng-1.5.7 and later. + Added MINGW support to CMakeLists.txt + Reject invalid compression flag or method when reading the iTXt chunk. + Backed out 'simplified' API changes. The API seems too complex and there + is a lack of consensus or enthusiasm for the proposals. The API also + reveals significant bugs inside libpng (double gamma correction and the + known bug of being unable to retrieve a corrected palette). It seems + better to wait until the bugs, at least, are corrected. + Moved pngvalid.c into contrib/libtests + Rebuilt Makefile.in, configure, etc., with autoconf-2.68 + +Version 1.5.7rc01 [December 1, 2011] + Replaced an "#if" with "#ifdef" in pngrtran.c + Revised #if PNG_DO_BC block in png.c (use #ifdef and add #else) + +Version 1.5.7rc02 [December 5, 2011] + Revised project files and contrib/pngvalid/pngvalid.c to account for + the relocation of pngvalid into contrib/libtests. + Revised pngconf.h to use " __declspec(restrict)" only when MSC_VER >= 1400, + as in libpng-1.5.4. + Put CRLF line endings in the owatcom project files. + +Version 1.5.7rc03 [December 7, 2011] + Updated CMakeLists.txt to account for the relocation of pngvalid.c + +Version 1.5.7 [December 15, 2011] + Minor fixes to pngvalid.c for gcc 4.6.2 compatibility to remove warnings + reported by earlier versions. + Fixed minor memset/sizeof errors in pngvalid.c. + +Version 1.6.0beta01 [December 15, 2011] + Removed machine-generated configure files from the GIT repository (they will + continue to appear in the tarball distributions and in the libpng15 and + earlier GIT branches). + Restored the new 'simplified' API, which was started in libpng-1.5.7beta02 + but later deleted from libpng-1.5.7beta05. + Added example programs for the new 'simplified' API. + Added ANSI-C (C90) headers and require them, and take advantage of the + change. Also fixed some of the projects/* and contrib/* files that needed + updates for libpng16 and the move of pngvalid.c. + With this change the required ANSI-C header files are assumed to exist: the + implementation must provide float.h, limits.h, stdarg.h and stddef.h and + libpng relies on limits.h and stddef.h existing and behaving as defined + (the other two required headers aren't used). Non-ANSI systems that don't + have stddef.h or limits.h will have to provide an appropriate fake + containing the relevant types and #defines. + Dropped support for 16-bit platforms. The use of FAR/far has been eliminated + and the definition of png_alloc_size_t is now controlled by a flag so + that 'small size_t' systems can select it if necessary. Libpng 1.6 may + not currently work on such systems -- it seems likely that it will + ask 'malloc' for more than 65535 bytes with any image that has a + sufficiently large row size (rather than simply failing to read such + images). + New tools directory containing tools used to generate libpng code. + Fixed race conditions in parallel make builds. With higher degrees of + parallelism during 'make' the use of the same temporary file names such + as 'dfn*' can result in a race where a temporary file from one arm of the + build is deleted or overwritten in another arm. This changes the + temporary files for suffix rules to always use $* and ensures that the + non-suffix rules use unique file names. + +Version 1.6.0beta02 [December 21, 2011] + Correct configure builds where build and source directories are separate. + The include path of 'config.h' was erroneously made relative in pngvalid.c + in libpng 1.5.7. + +Version 1.6.0beta03 [December 22, 2011] + Start-up code size improvements, error handler flexibility. These changes + alter how the tricky allocation of the initial png_struct and png_info + structures are handled. png_info is now handled in pretty much the same + way as everything else, except that the allocations handle NULL return + silently. png_struct is changed in a similar way on allocation and on + deallocation a 'safety' error handler is put in place (which should never + be required). The error handler itself is changed to permit mismatches + in the application and libpng error buffer size; however, this means a + silent change to the API to return the jmp_buf if the size doesn't match + the size from the libpng compilation; libpng now allocates the memory and + this may fail. Overall these changes result in slight code size + reductions; however, this is a reduction in code that is always executed + so is particularly valuable. Overall on a 64-bit system the libpng DLL + decreases in code size by 1733 bytes. pngerror.o increases in size by + about 465 bytes because of the new functionality. + Added png_convert_to_rfc1123_buffer() and deprecated png_convert_to_rfc1123() + to avoid including a spurious buffer in the png_struct. + +Version 1.6.0beta04 [December 30, 2011] + Regenerated configure scripts with automake-1.11.2 + Eliminated png_info_destroy(). It is now used only in png.c and only calls + one other internal function and memset(). + Enabled png_get_sCAL_fixed() if floating point APIs are enabled. Previously + it was disabled whenever internal fixed point arithmetic was selected, + which meant it didn't exist even on systems where FP was available but not + preferred. + Added pngvalid.c compile time checks for const APIs. + Implemented 'restrict' for png_info and png_struct. Because of the way + libpng works both png_info and png_struct are always accessed via a + single pointer. This means adding C99 'restrict' to the pointer gives + the compiler some opportunity to optimize the code. This change allows + that. + Moved AC_MSG_CHECKING([if libraries can be versioned]) later to the proper + location in configure.ac (Gilles Espinasse). + Changed png_memcpy to C assignment where appropriate. Changed all those + uses of png_memcpy that were doing a simple assignment to assignments + (all those cases where the thing being copied is a non-array C L-value). + Added some error checking to png_set_*() routines. + Removed the reference to the non-exported function png_memcpy() from + example.c. + Fixed the Visual C 64-bit build - it requires jmp_buf to be aligned, but + it had become misaligned. + Revised contrib/pngminus/pnm2png.c to avoid warnings when png_uint_32 + and unsigned long are of different sizes. + +Version 1.6.0beta05 [January 15, 2012] + Updated manual with description of the simplified API (copied from png.h) + Fix bug in pngerror.c: some long warnings were being improperly truncated + (CVE-2011-3464, bug introduced in libpng-1.5.3beta05). + +Version 1.6.0beta06 [January 24, 2012] + Added palette support to the simplified APIs. This commit + changes some of the macro definitions in png.h, app code + may need corresponding changes. + Increased the formatted warning buffer to 192 bytes. + Added color-map support to simplified API. This is an initial version for + review; the documentation has not yet been updated. + Fixed Min/GW uninstall to remove libpng.dll.a + +Version 1.6.0beta07 [January 28, 2012] + Eliminated Intel icc/icl compiler warnings. The Intel (GCC derived) + compiler issues slightly different warnings from those issued by the + current vesions of GCC. This eliminates those warnings by + adding/removing casts and small code rewrites. + Updated configure.ac from autoupdate: added --enable-werror option. + Also some layout regularization and removal of introduced tab characters + (replaced with 3-character indentation). Obsolete macros identified by + autoupdate have been removed; the replacements are all in 2.59 so + the pre-req hasn't been changed. --enable-werror checks for support + for -Werror (or the given argument) in the compiler. This mimics the + gcc configure option by allowing -Werror to be turned on safely; without + the option the tests written in configure itself fail compilation because + they cause compiler warnings. + Rewrote autogen.sh to run autoreconf instead of running tools one-by-one. + Conditionalize the install rules for MINGW and CYGWIN in CMakeLists.txt and + set CMAKE_LIBRARY_OUTPUT_DIRECTORY to "lib" on all platforms (C. Yapp). + Freeze libtool files in the 'scripts' directory. This version of autogen.sh + attempts to dissuade people from running it when it is not, or should not, + be necessary. In fact, autogen.sh does not work when run in a libpng + directory extracted from a tar distribution anymore. You must run it in + a GIT clone instead. + Added two images to contrib/pngsuite (1-bit and 2-bit transparent grayscale), + and renamed three whose names were inconsistent with those in + pngsuite/README.txt. + +Version 1.6.0beta08 [February 1, 2012] + Fixed Image::colormap misalignment in pngstest.c + Check libtool/libtoolize version number (2.4.2) in configure.ac + Divide test-pngstest.sh into separate pngstest runs for basic and + transparent images. + Moved automake options to AM_INIT_AUTOMAKE in configure.ac + Added color-tests, silent-rules (Not yet implemented in Makefile.am) and + version checking to configure.ac + Improved pngstest speed by not doing redundant tests and add const to + the background parameter of png_image_finish_read. The --background + option is now done automagically only when required, so that commandline + option no longer exists. + Cleaned up pngpriv.h to consistently declare all functions and data. + Also eliminated PNG_CONST_DATA, which is apparently not needed but we + can't be sure until it is gone. + Added symbol prefixing that allows all the libpng external symbols + to be prefixed (suggested by Reuben Hawkins). + Updated "ftbb*.png" list in the owatcom and vstudio projects. + Fixed 'prefix' builds on clean systems. The generation of pngprefix.h + should not require itself. + Updated INSTALL to explain that autogen.sh must be run in a GIT clone, + not in a libpng directory extracted from a tar distribution. + +Version 1.6.0beta09 [February 1, 2012] + Reverted the prebuilt configure files to libpng-1.6.0beta05 condition. + +Version 1.6.0beta10 [February 3, 2012] + Added Z_SOLO for zlib-1.2.6+ and correct pngstest tests + Updated list of test images in CMakeLists.txt + Updated the prebuilt configure files to current condition. + Revised INSTALL information about autogen.sh; it works in tar distributions. + +Version 1.6.0beta11 [February 16, 2012] + Fix character count in pngstest command in projects/owatcom/pngstest.tgt + Revised test-pngstest.sh to report PASS/FAIL for each image. + Updated documentation about the simplified API. + Corrected estimate of error in libpng png_set_rgb_to_gray API. The API is + extremely inaccurate for sRGB conversions because it uses an 8-bit + intermediate linear value and it does not use the sRGB transform, so it + suffers from the known instability in gamma transforms for values close + to 0 (see Poynton). The net result is that the calculation has a maximum + error of 14.99/255; 0.5/255^(1/2.2). pngstest now uses 15 for the + permitted 8-bit error. This may still not be enough because of arithmetic + error. + Removed some unused arrays (with #ifdef) from png_read_push_finish_row(). + Fixed a memory overwrite bug in simplified read of RGB PNG with + non-linear gamma Also bugs in the error checking in pngread.c and changed + quite a lot of the checks in pngstest.c to be correct; either correctly + written or not over-optimistic. The pngstest changes are insufficient to + allow all possible RGB transforms to be passed; pngstest cmppixel needs + to be rewritten to make it clearer which errors it allows and then changed + to permit known inaccuracies. + Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h + Fixed fixed/float API export conditionals. 1) If FIXED_POINT or + FLOATING_POINT options were switched off, png.h ended up with lone ';' + characters. This is not valid ANSI-C outside a function. The ';' + characters have been moved inside the definition of PNG_FP_EXPORT and + PNG_FIXED_EXPORT. 2) If either option was switched off, the declaration + of the corresponding functions were completely omitted, even though some + of them are still used internally. The result is still valid, but + produces warnings from gcc with some warning options (including -Wall). The + fix is to cause png.h to declare the functions with PNG_INTERNAL_FUNCTION + when png.h is included from pngpriv.h. + Check for invalid palette index while reading paletted PNG. When one is + found, issue a warning and increase png_ptr->num_palette accordingly. + Apps are responsible for checking to see if that happened. + +Version 1.6.0beta12 [February 18, 2012] + Do not increase num_palette on invalid_index. + Relocated check for invalid palette index to pngrtran.c, after unpacking + the sub-8-bit pixels. + Fixed CVE-2011-3026 buffer overrun bug. This bug was introduced when + iCCP chunk support was added at libpng-1.0.6. Deal more correctly with the + test on iCCP chunk length. Also removed spurious casts that may hide + problems on 16-bit systems. + +Version 1.6.0beta13 [February 24, 2012] + Eliminated redundant png_push_read_tEXt|zTXt|iTXt|unknown code from + pngpread.c and use the sequential png_handle_tEXt, etc., in pngrutil.c; + now that png_ptr->buffer is inaccessible to applications, the special + handling is no longer useful. + Added PNG_SAFE_LIMITS feature to pnglibconf.dfa, pngpriv.h, and new + pngusr.dfa to reset the user limits to safe ones if PNG_SAFE_LIMITS is + defined. To enable, use "CPPFLAGS=-DPNG_SAFE_LIMITS_SUPPORTED=1" on the + configure command or put #define PNG_SAFE_LIMITS_SUPPORTED in + pnglibconf.h.prebuilt and pnglibconf.h. + +Version 1.6.0beta14 [February 27, 2012] + Added information about the new limits in the manual. + Updated Makefile.in + +Version 1.6.0beta15 [March 2, 2012] + Removed unused "current_text" members of png_struct and the png_free() + of png_ptr->current_text from pngread.c + Rewrote pngstest.c for substantial speed improvement. + Fixed transparent pixel and 16-bit rgb tests in pngstest and removed a + spurious check in pngwrite.c + Added PNG_IMAGE_FLAG_FAST for the benefit of applications that store + intermediate files, or intermediate in-memory data, while processing + image data with the simplified API. The option makes the files larger + but faster to write and read. pngstest now uses this by default; this + can be disabled with the --slow option. + Improved pngstest fine tuning of error numbers, new test file generator. + The generator generates images that test the full range of sample values, + allow the error numbers in pngstest to be tuned and checked. makepng + also allows generation of images with extra chunks, although this is + still work-in-progress. + Added check for invalid palette index while reading. + Fixed some bugs in ICC profile writing. The code should now accept + all potentially valid ICC profiles and reject obviously invalid ones. + It now uses png_error() to do so rather than casually writing a PNG + without the necessary color data. + Removed whitespace from the end of lines in all source files and scripts. + +Version 1.6.0beta16 [March 6, 2012] + Relocated palette-index checking function from pngrutil.c to pngtrans.c + Added palette-index checking while writing. + Changed png_inflate() and calling routines to avoid overflow problems. + This is an intermediate check-in that solves the immediate problems and + introduces one performance improvement (avoiding a copy via png_ptr->zbuf.) + Further changes will be made to make ICC profile handling more secure. + Fixed build warnings (MSVC, GCC, GCC v3). Cygwin GCC with default options + declares 'index' as a global, causing a warning if it is used as a local + variable. GCC 64-bit warns about assigning a (size_t) (unsigned 64-bit) + to an (int) (signed 32-bit). MSVC, however, warns about using the + unary '-' operator on an unsigned value (even though it is well defined + by ANSI-C to be ~x+1). The padding calculation was changed to use a + different method. Removed the tests on png_ptr->pass. + Added contrib/libtests/tarith.c to test internal arithmetic functions from + png.c. This is a libpng maintainer program used to validate changes to the + internal arithmetic functions. + Made read 'inflate' handling like write 'deflate' handling. The read + code now claims and releases png_ptr->zstream, like the write code. + The bug whereby the progressive reader failed to release the zstream + is now fixed, all initialization is delayed, and the code checks for + changed parameters on deflate rather than always calling + deflatedEnd/deflateInit. + Validate the zTXt strings in pngvalid. + Added code to validate the windowBits value passed to deflateInit2(). + If the call to deflateInit2() is wrong a png_warning will be issued + (in fact this is harmless, but the PNG data produced may be sub-optimal). + +Version 1.6.0beta17 [March 10, 2012] + Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition. + Reject all iCCP chunks after the first, even if the first one is invalid. + Deflate/inflate was reworked to move common zlib calls into single + functions [rw]util.c. A new shared keyword check routine was also added + and the 'zbuf' is no longer allocated on progressive read. It is now + possible to call png_inflate() incrementally. A warning is no longer + issued if the language tag or translated keyword in the iTXt chunk + has zero length. + If benign errors are disabled use maximum window on ancillary inflate. + This works round a bug introduced in 1.5.4 where compressed ancillary + chunks could end up with a too-small windowBits value in the deflate + header. + +Version 1.6.0beta18 [March 16, 2012] + Issue a png_benign_error() instead of png_warning() about bad palette index. + In pngtest, treat benign errors as errors if "-strict" is present. + Fixed an off-by-one error in the palette index checking function. + Fixed a compiler warning under Cygwin (Windows-7, 32-bit system) + Revised example.c to put text strings in a temporary character array + instead of directly assigning string constants to png_textp members. + This avoids compiler warnings when -Wwrite-strings is enabled. + Added output flushing to aid debugging under Visual Studio. Unfortunately + this is necessary because the VS2010 output window otherwise simply loses + the error messages on error (they weren't flushed to the window before + the process exited, apparently!) + Added configuration support for benign errors and changed the read + default. Also changed some warnings in the iCCP and sRGB handling + from to benign errors. Configuration now makes read benign + errors warnings and write benign errors to errors by default (thus + changing the behavior on read). The simplified API always forces + read benign errors to warnings (regardless of the system default, unless + this is disabled in which case the simplified API can't be built.) + +Version 1.6.0beta19 [March 18, 2012] + Work around for duplicate row start calls; added warning messages. + This turns on PNG_FLAG_DETECT_UNINITIALIZED to detect app code that + fails to call one of the 'start' routines (not enabled in libpng-1.5 + because it is technically an API change, since it did normally work + before.) It also makes duplicate calls to png_read_start_row (an + internal function called at the start of the image read) benign, as + they were before changes to use png_inflate_claim. Somehow webkit is + causing this to happen; this is probably a mis-feature in the zlib + changes so this commit is only a work-round. + Removed erroneous setting of DETECT_UNINITIALIZED and added more + checks. The code now does a png_error if an attempt is made to do the + row initialization twice; this is an application error and it has + serious consequences because the transform data in png_struct is + changed by each call. + Added application error reporting and added chunk names to read + benign errors; also added --strict to pngstest - not enabled + yet because a warning is produced. + Avoid the double gamma correction warning in the simplified API. + This allows the --strict option to pass in the pngstest checks + +Version 1.6.0beta20 [March 29, 2012] + Changed chunk handler warnings into benign errors, incrementally load iCCP + Added checksum-icc.c to contrib/tools + Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice. + Recognize known sRGB ICC profiles while reading; prefer writing the + iCCP profile over writing the sRGB chunk, controlled by the + PNG_sRGB_PROFILE_CHECKS option. + Revised png_set_text_2() to avoid potential memory corruption (fixes + CVE-2011-3048, also known as CVE-2012-3425). + +Version 1.6.0beta21 [April 27, 2012] + Revised scripts/makefile.darwin: use system zlib; remove quotes around + architecture list; add missing ppc architecture; add architecture options + to shared library link; don't try to create a shared lib based on missing + RELEASE variable. + Enable png_set_check_for_invalid_index() for both read and write. + Removed #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED in pngpriv.h around + declaration of png_handle_unknown(). + Added -lssp_nonshared in a comment in scripts/makefile.freebsd + and changed deprecated NOOBJ and NOPROFILE to NO_OBJ and NO_PROFILE. + +Version 1.6.0beta22 [May 23, 2012] + Removed need for -Wno-cast-align with clang. clang correctly warns on + alignment increasing pointer casts when -Wcast-align is passed. This + fixes the cases that clang warns about either by eliminating the + casts from png_bytep to png_uint_16p (pngread.c), or, for pngrutil.c + where the cast is previously verified or pngstest.c where it is OK, by + introducing new png_aligncast macros to do the cast in a way that clang + accepts. + +Version 1.6.0beta23 [June 6, 2012] + Revised CMakeLists.txt to not attempt to make a symlink under mingw. + Made fixes for new optimization warnings from gcc 4.7.0. The compiler + performs an optimization which is safe; however it then warns about it. + Changing the type of 'palette_number' in pngvalid.c removes the warning. + Do not depend upon a GCC feature macro being available for use in generating + the linker mapfile symbol prefix. + Improved performance of new do_check_palette_indexes() function (only + update the value when it actually increases, move test for whether + the check is wanted out of the function. + +Version 1.6.0beta24 [June 7, 2012] + Don't check palette indexes if num_palette is 0 (as it can be in MNG files). + +Version 1.6.0beta25 [June 16, 2012] + Revised png_set_keep_unknown_chunks() so num_chunks < 0 means ignore all + unknown chunks and all known chunks except for IHDR, PLTE, tRNS, IDAT, + and IEND. Previously it only meant ignore all unknown chunks, the + same as num_chunks == 0. Revised png_image_skip_unused_chunks() to + provide a list of chunks to be processed instead of a list of chunks to + ignore. Revised contrib/gregbook/readpng2.c accordingly. + +Version 1.6.0beta26 [July 10, 2012] + Removed scripts/makefile.cegcc from the *.zip and *.7z distributions; it + depends on configure, which is not included in those archives. + Moved scripts/chkfmt to contrib/tools. + Changed "a+w" to "u+w" in Makefile.in to fix CVE-2012-3386. + +Version 1.6.0beta27 [August 11, 2012] + Do not compile PNG_DEPRECATED, PNG_ALLOC and PNG_PRIVATE when __GNUC__ < 3. + Do not use __restrict when GNUC is <= 3.1 + Removed references to png_zalloc() and png_zfree() from the manual. + Fixed configurations where floating point is completely disabled. Because + of the changes to support symbol prefixing PNG_INTERNAL_FUNCTION declares + floating point APIs during libpng builds even if they are completely + disabled. This requires the png floating point types (png_double*) to be + declared even though the functions are never actually defined. This + change provides a dummy definition so that the declarations work, yet any + implementation will fail to compile because of an incomplete type. + Re-eliminated the use of strcpy() in pngtest.c. An unnecessary use of + strcpy() was accidentally re-introduced in libpng16; this change replaces + it with strncpy(). + Eliminated use of png_sizeof(); use sizeof() instead. + Use a consistent style for (sizeof type) and (sizeof (array)) + Cleanup of png_set_filler(). This function does very different things on + read and write. In libpng 1.6 the two cases can be distinguished and + considerable code cleanup, and extra error checking, is possible. This + makes calls on the write side that have no effect be ignored with a + png_app_error(), which can be disabled in the app using + png_set_benign_errors(), and removes the spurious use of usr_channels + on the read side. + Insist on autotools 1.12.1 for git builds because there are security issues + with 1.12 and insisting on anything less would allow 1.12 to be used. + Removed info_ptr->signature[8] from WRITE-only builds. + Add some conditions for compiling png_fixed(). This is a small function + but it requires "-lm" on some platforms. + Cause pngtest --strict to fail on any warning from libpng (not just errors) + and cause it not to fail at the comparison step if libpng lacks support + for writing chunks that it reads from the input (currently only implemented + for compressed text chunks). + Make all three "make check" test programs work without READ or WRITE support. + Now "make check" will succeed even if libpng is compiled with -DPNG_NO_READ + or -DPNG_NO_WRITE. The tests performed are reduced, but the basic reading + and writing of a PNG file is always tested by one or more of the tests. + Consistently use strlen(), memset(), memcpy(), and memcmp() instead of the + png_strlen(), png_memset(), png_memcpy(), and png_memcmp() macros. + Removed the png_sizeof(), png_strlen(), png_memset(), png_memcpy(), and + png_memcmp() macros. + Work around gcc 3.x and Microsoft Visual Studio 2010 complaints. Both object + to the split initialization of num_chunks. + +Version 1.6.0beta28 [August 29, 2012] + Unknown handling fixes and clean up. This adds more correct option + control of the unknown handling, corrects the pre-existing bug where + the per-chunk 'keep' setting is ignored and makes it possible to skip + IDAT chunks in the sequential reader (broken in earlier 1.6 versions). + There is a new test program, test-unknown.c, which is a work in progress + (not currently part of the test suite). Comments in the header files now + explain how the unknown handling works. + Allow fine grain control of unknown chunk APIs. This change allows + png_set_keep_unknown_chunks() to be turned off if not required and causes + both read and write to behave appropriately (on read this is only possible + if the user callback is used to handle unknown chunks). The change + also removes the support for storing unknown chunks in the info_struct + if the only unknown handling enabled is via the callback, allowing libpng + to be configured with callback reading and none of the unnecessary code. + Corrected fix for unknown handling in pngtest. This reinstates the + libpng handling of unknown chunks other than vpAg and sTER (including + unsafe-to-copy chunks which were dropped before) and eliminates the + repositioning of vpAg and sTER in pngtest.png by changing pngtest.png + (so the chunks are where libpng would put them). + Added "tunknown" test and corrected a logic error in png_handle_unknown() + when SAVE support is absent. Moved the shell test scripts for + contrib/libtests from the libpng top directory to contrib/libtests. + png_handle_unknown() must always read or skip the chunk, if + SAVE_UNKNOWN_CHUNKS is turned off *and* the application does not set + a user callback an unknown chunk will not be read, leading to a read + error, which was revealed by the "tunknown" test. + Cleaned up and corrected ICC profile handling. + contrib/libtests/makepng: corrected 'rgb' and 'gray' cases. profile_error + messages could be truncated; made a correct buffer size calculation and + adjusted pngerror.c appropriately. png_icc_check_* checking improved; + changed the functions to receive the correct color type of the PNG on read + or write and check that it matches the color space of the profile (despite + what the comments said before, there is danger in assuming the app will + cope correctly with an RGB profile on a grayscale image and, since it + violates the PNG spec, allowing it is certain to produce inconsistent + app behavior and might even cause app crashes.) Check that profiles + contain the tags needed to process the PNG (tags all required by the ICC + spec). Removed unused PNG_STATIC from pngpriv.h. + +Version 1.6.0beta29 [September 4, 2012] + Fixed the simplified API example programs to add the *colormap parameter + to several of he API and improved the error message if the version field + is not set. + Added contrib/examples/* to the *.zip and *.7z distributions. + Updated simplified API synopses and description of the png_image structure + in the manual. + Made makepng and pngtest produce identical PNGs, add "--relaxed" option + to pngtest. The "--relaxed" option turns off the benign errors that are + enabled by default in pre-RC builds. makepng can now write ICC profiles + where the length has not been extended to a multiple of 4, and pngtest + now intercepts all libpng errors, allowing the previously-introduced + "--strict test" on no warnings to actually work. + Improved ICC profile handling including cHRM chunk generation and fixed + Cygwin+MSVC build errors. The ICC profile handling now includes more + checking. Several errors that caused rejection of the profile are now + handled with a warning in such a way that the invalid profiles will be + read by default in release (but not pre-RC) builds but will not be + written by default. The easy part of handling the cHRM chunk is written, + where the ICC profile contains the required data. The more difficult + part plus guessing a gAMA value requires code to pass selected RGB values + through the profile. + +Version 1.6.0beta30 [October 24, 2012] + Changed ICC profile matrix/vector types to not depend on array type rules. + By the ANSI-C standard the new types should be identical to the previous + versions, and all known versions of gcc tested with the previous versions + except for GCC-4.2.1 work with this version. The change makes the ANSI-C + rule that const applied to an array of elements applies instead to the + elements in the array moot by explicitly applying const to the base + elements of the png_icc_matrix and png_icc_vector types. The accidental + (harmless) 'const' previously applied to the parameters of two of the + functions have also been removed. + Added a work around for GCC 4.2 optimization bug. + Marked the broken (bad white point) original HP sRGB profiles correctly and + correct comments. + Added -DZ_SOLO to contrib/pngminim/*/makefile to work with zlib-1.2.7 + Use /MDd for vstudio debug builds. Also added pngunkown to the vstudio + builds, fixed build errors and corrected a minor exit code error in + pngvalid if the 'touch' file name is invalid. + Add updated WARNING file to projects/vstudio from libpng 1.5/vstudio + Fixed build when using #define PNG_NO_READ_GAMMA in png_do_compose() in + pngrtran.c (Domani Hannes). + +Version 1.6.0beta31 [November 1, 2012] + Undid the erroneous change to vstudio/pngvalid build in libpng-1.6.0beta30. + Made pngvalid so that it will build outside the libpng source tree. + Made builds -DPNG_NO_READ_GAMMA compile (the unit tests still fail). + Made PNG_NO_READ_GAMMA switch off interfaces that depend on READ_GAMMA. + Prior to 1.6.0 switching off READ_GAMMA did unpredictable things to the + interfaces that use it (specifically, png_do_background in 1.4 would + simply display composite for grayscale images but do composition + with the incorrect arithmetic for color ones). In 1.6 the semantic + of -DPNG_NO_READ_GAMMA is changed to simply disable any interface that + depends on it; this obliges people who set it to consider whether they + really want it off if they happen to use any of the interfaces in + question (typically most users who disable it won't). + Fixed GUIDs in projects/vstudio. Some were duplicated or missing, + resulting in VS2010 having to update the files. + Removed non-working ICC profile support code that was mostly added to + libpng-1.6.0beta29 and beta30. There was too much code for too little + gain; implementing full ICC color correction may be desirable but is left + up to applications. + +Version 1.6.0beta32 [November 25, 2012] + Fixed an intermittent SEGV in pngstest due to an uninitialized array element. + Added the ability for contrib/libtests/makepng.c to make a PNG with just one + color. This is useful for debugging pngstest color inaccuracy reports. + Fixed error checking in the simplified write API (Olaf van der Spek) + Made png_user_version_check() ok to use with libpng version 1.10.x and later. + +Version 1.6.0beta33 [December 15, 2012] + Fixed typo in png.c (PNG_SET_CHUNK_MALLOC_MAX should be PNG_CHUNK_MALLOC_MAX) + that causes the MALLOC_MAX limit not to work (John Bowler) + Change png_warning() to png_app_error() in pngwrite.c and comment the + fall-through condition. + Change png_warning() to png_app_warning() in png_write_tRNS(). + Rearranged the ARM-NEON optimizations: Isolated the machine specific code + to the hardware subdirectory and added comments to pngrutil.c so that + implementors of other optimizations know what to do. + Fixed cases of unquoted DESTDIR in Makefile.am + Rebuilt Makefile.in, etc., with autoconf-2.69 and automake-1.12.5. + +Version 1.6.0beta34 [December 19, 2012] + Cleaned up whitespace in the synopsis portion of the manpage "libpng.3" + Disassembled the version number in scripts/options.awk (necessary for + building on SunOs). + +Version 1.6.0beta35 [December 23, 2012] + Made default Zlib compression settings be configurable. This adds #defines to + pnglibconf.h to control the defaults. + Fixed Windows build issues, enabled ARM compilation. Various warnings issued + by earlier versions of GCC fixed for Cygwin and Min/GW (which both use old + GCCs.) ARM support is enabled by default in zlib.props (unsupported by + Microsoft) and ARM compilation is made possible by deleting the check for + x86. The test programs cannot be run because they are not signed. + +Version 1.6.0beta36 [January 2, 2013] + Discontinued distributing libpng-1.x.x.tar.bz2. + Discontinued distributing libpng-1.7.0-1.6.0-diff.txt and similar. + Rebuilt configure with autoconf-2.69 (inadvertently not done in beta33) + Fixed 'make distcheck' on SUN OS - libpng.so was not being removed + +Version 1.6.0beta37 [January 10, 2013] + Fixed conceivable but difficult to repro overflow. Also added two test + programs to generate and test a PNG which should have the problem. + +Version 1.6.0beta39 [January 19, 2013] + Again corrected attempt at overflow detection in png_set_unknown_chunks() + (CVE-2013-7353). Added overflow detection in png_set_sPLT() and + png_set_text_2() (CVE-2013-7354). + +Version 1.6.0beta40 [January 20, 2013] + Use consistent handling of overflows in text, sPLT and unknown png_set_* APIs + +Version 1.6.0rc01 [January 26, 2013] + No changes. + +Version 1.6.0rc02 [February 4, 2013] + Added png_get_palette_max() function. + +Version 1.6.0rc03 [February 5, 2013] + Fixed the png_get_palette_max API. + +Version 1.6.0rc04 [February 7, 2013] + Turn serial tests back on (recently turned off by autotools upgrade). + +Version 1.6.0rc05 [February 8, 2013] + Update manual about png_get_palette_max(). + +Version 1.6.0rc06 [February 9, 2013] + Fixed missing dependency in --prefix builds The intermediate + internal 'prefix.h' file can only be generated correctly after + pnglibconf.h, however the dependency was not in Makefile.am. The + symptoms are unpredictable depending on the order make chooses to + build pngprefix.h and pnglibconf.h, often the error goes unnoticed + because there is a system pnglibconf.h to use instead. + +Version 1.6.0rc07 [February 10, 2013] + Enclosed the new png_get_palette_max in #ifdef PNG_GET_PALETTE_MAX_SUPPORTED + block, and revised pnglibconf.h and pnglibconf.h.prebuilt accordingly. + +Version 1.6.0rc08 [February 10, 2013] + Fix typo in png.h #ifdef + +Version 1.6.0 [February 14, 2013] + No changes. + +Version 1.6.1beta01 [February 16, 2013] + Made symbol prefixing work with the ARM neon optimizations. Also allow + pngpriv.h to be included for preprocessor definitions only, so it can + be used in non-C/C++ files. Back ported from libpng 1.7. + Made sRGB check numbers consistent. + Ported libpng 1.5 options.awk/dfn file handling to 1.6, fixed one bug. + Removed cc -E workround, corrected png_get_palette_max API Tested on + SUN OS cc 5.9, which demonstrates the tokenization problem previously + avoided by using /lib/cpp. Since all .dfn output is now protected in + double quotes unless it is to be macro substituted the fix should + work everywhere. + Enabled parallel tests - back ported from libpng-1.7. + scripts/pnglibconf.dfa formatting improvements back ported from libpng17. + Fixed a race condition in the creation of the build 'scripts' directory + while building with a parallel make. + Use approved/supported Android method to check for NEON, use Linux/POSIX + 1003.1 API to check /proc/self/auxv avoiding buffer allocation and other + library calls (ported from libpng15). + +Version 1.6.1beta02 [February 19, 2013] + Use parentheses more consistently in "#if defined(MACRO)" tests. + Folded long lines. + Reenabled code to allow zero length PLTE chunks for MNG. + +Version 1.6.1beta03 [February 22, 2013] + Fixed ALIGNED_MEMORY support. + Added a new configure option: + --enable-arm-neon=always will stop the run-time checks. New checks + within arm/arm_init.c will cause the code not to be compiled unless + __ARM_NEON__ is set. This should make it fail safe (if someone asks + for it on then the build will fail if it can't be done.) + Updated the INSTALL document. + +Version 1.6.1beta04 [February 27, 2013] + Revised INSTALL to recommend using CPPFLAGS instead of INCLUDES. + Revised scripts/makefile.freebsd to respect ZLIBLIB and ZLIBINC. + Revised scripts/dfn.awk to work with the buggy MSYS awk that has trouble + with CRLF line endings. + +Version 1.6.1beta05 [March 1, 2013] + Avoid a possible memory leak in contrib/gregbook/readpng.c + +Version 1.6.1beta06 [March 4, 2013] + Better documentation of unknown handling API interactions. + Corrected Android builds and corrected libpng.vers with symbol + prefixing. It also makes those tests compile and link on Android. + Added an API png_set_option() to set optimization options externally, + providing an alternative and general solution for the non-portable + run-time tests used by the ARM Neon code, using the PNG_ARM_NEON option. + The order of settings vs options in pnglibconf.h is reversed to allow + settings to depend on options and options can now set (or override) the + defaults for settings. + +Version 1.6.1beta07 [March 7, 2013] + Corrected simplified API default gamma for color-mapped output, added + a flag to change default. In 1.6.0 when the simplified API was used + to produce color-mapped output from an input image with no gamma + information the gamma assumed for the input could be different from + that assumed for non-color-mapped output. In particular 16-bit depth + input files were assumed to be sRGB encoded, whereas in the 'direct' + case they were assumed to have linear data. This was an error. The + fix makes the simplified API treat all input files the same way and + adds a new flag to the png_image::flags member to allow the + application/user to specify that 16-bit files contain sRGB data + rather than the default linear. + Fixed bugs in the pngpixel and makepng test programs. + +Version 1.6.1beta08 [March 7, 2013] + Fixed CMakelists.txt to allow building a single variant of the library + (Claudio Bley): + Introduced a PNG_LIB_TARGETS variable that lists all activated library + targets. It is an error if this variable ends up empty, ie. you have + to build at least one library variant. + Made the *_COPY targets only depend on library targets actually being build. + Use PNG_LIB_TARGETS to unify a code path. + Changed the CREATE_SYMLINK macro to expect the full path to a file as the + first argument. When symlinking the filename component of that path is + determined and used as the link target. + Use copy_if_different in the CREATE_SYMLINK macro. + +Version 1.6.1beta09 [March 13, 2013] + Eliminated two warnings from the Intel C compiler. The warnings are + technically valid, although a reasonable treatment of division would + show it to be incorrect. + +Version 1.6.1rc01 [March 21, 2013] + No changes. + +Version 1.6.1 [March 28, 2013] + No changes. + +Version 1.6.2beta01 [April 14, 2013] + Updated documentation of 1.5.x to 1.6.x changes in iCCP chunk handling. + Fixed incorrect warning of excess deflate data. End condition - the + warning would be produced if the end of the deflate stream wasn't read + in the last row. The warning is harmless. + Corrected the test on user transform changes on read. It was in the + png_set of the transform function, but that doesn't matter unless the + transform function changes the rowbuf size, and that is only valid if + transform_info is called. + Corrected a misplaced closing bracket in contrib/libtests/pngvalid.c + (Flavio Medeiros). + Corrected length written to uncompressed iTXt chunks (Samuli Suominen). + Bug was introduced in libpng-1.6.0. + +Version 1.6.2rc01 [April 18, 2013] + Added contrib/tools/fixitxt.c, to repair the erroneous iTXt chunk length + written by libpng-1.6.0 and 1.6.1. + Disallow storing sRGB information when the sRGB is not supported. + +Version 1.6.2rc02 [April 18, 2013] + Merge pngtest.c with libpng-1.7.0 + +Version 1.6.2rc03 [April 22, 2013] + Trivial spelling cleanup. + +Version 1.6.2rc04 and 1.6.2rc05 [omitted] + +Version 1.6.2rc06 [April 24, 2013] + Reverted to version 1.6.2rc03. Recent changes to arm/neon support + have been ported to libpng-1.7.0beta09 and will reappear in version + 1.6.3beta01. + +Version 1.6.2 [April 25, 2013] + No changes. + +Version 1.6.3beta01 [April 25, 2013] + Revised stack marking in arm/filter_neon.S and configure.ac. + Ensure that NEON filter stuff is completely disabled when switched 'off'. + Previously the ARM NEON specific files were still built if the option + was switched 'off' as opposed to being explicitly disabled. + +Version 1.6.3beta02 [April 26, 2013] + Test for 'arm*' not just 'arm' in the host_cpu configure variable. + Rebuilt the configure scripts. + +Version 1.6.3beta03 [April 30, 2013] + Expanded manual paragraph about writing private chunks, particularly + the need to call png_set_keep_unknown_chunks() when writing them. + Avoid dereferencing NULL pointer possibly returned from + png_create_write_struct() (Andrew Church). + +Version 1.6.3beta05 [May 9, 2013] + Calculate our own zlib windowBits when decoding rather than trusting the + CMF bytes in the PNG datastream. + Added an option to force maximum window size for inflating, which was + the behavior of libpng15 and earlier, via a new PNG_MAXIMUM_INFLATE_WINDOW + option for png_set_options(). + Added png-fix-itxt and png-fix-too-far-back to the built programs and + removed warnings from the source code and timepng that are revealed as + a result. + Detect wrong libpng versions linked to png-fix-too-far-back, which currently + only works with libpng versions that can be made to reliably fail when + the deflate data contains an out-of-window reference. This means only + 1.6 and later. + Fixed gnu issues: g++ needs a static_cast, gcc 4.4.7 has a broken warning + message which it is easier to work round than ignore. + Updated contrib/pngminus/pnm2png.c (Paul Stewart): + Check for EOF + Ignore "#" delimited comments in input file to pnm2png.c. + Fixed whitespace handling + Added a call to png_set_packing() + Initialize dimension values so if sscanf fails at least we have known + invalid values. + Attempt to detect configuration issues with png-fix-too-far-back, which + requires both the correct libpng and the correct zlib to function + correctly. + Check ZLIB_VERNUM for mismatches, enclose #error in quotes + Added information in the documentation about problems with and fixes for + the bad CRC and bad iTXt chunk situations. + +Version 1.6.3beta06 [May 12, 2013] + Allow contrib/pngminus/pnm2png.c to compile without WRITE_INVERT and + WRITE_PACK supported (writes error message that it can't read P1 or + P4 PBM files). + Improved png-fix-too-far-back usage message, added --suffix option. + Revised contrib/pngminim/*/makefile to generate pnglibconf.h with the + right zlib header files. + Separated CPPFLAGS and CFLAGS in contrib/pngminim/*/makefile + +Version 1.6.3beta07 [June 8, 2013] + Removed a redundant test in png_set_IHDR(). + Added set(CMAKE_CONFIGURATION_TYPES ...) to CMakeLists.txt (Andrew Hundt) + Deleted set(CMAKE_BUILD_TYPE) block from CMakeLists.txt + Enclose the prototypes for the simplified write API in + #ifdef PNG_STDIO_SUPPORTED/#endif + Make ARM NEON support work at compile time (not just configure time). + This moves the test on __ARM_NEON__ into pngconf.h to avoid issues when + using a compiler that compiles for multiple architectures at one time. + Removed PNG_FILTER_OPTIMIZATIONS and PNG_ARM_NEON_SUPPORTED from + pnglibconf.h, allowing more of the decisions to be made internally + (pngpriv.h) during the compile. Without this, symbol prefixing is broken + under certain circumstances on ARM platforms. Now only the API parts of + the optimizations ('check' vs 'api') are exposed in the public header files + except that the new setting PNG_ARM_NEON_OPT documents how libpng makes the + decision about whether or not to use the optimizations. + Protect symbol prefixing against CC/CPPFLAGS/CFLAGS usage. + Previous iOS/Xcode fixes for the ARM NEON optimizations moved the test + on __ARM_NEON__ from configure time to compile time. This breaks symbol + prefixing because the definition of the special png_init_filter_functions + call was hidden at configure time if the relevant compiler arguments are + passed in CFLAGS as opposed to CC. This change attempts to avoid all + the confusion that would result by declaring the init function even when + it is not used, so that it will always get prefixed. + +Version 1.6.3beta08 [June 18, 2013] + Revised libpng.3 so that "doclifter" can process it. + +Version 1.6.3beta09 [June 27, 2013] + Revised example.c to illustrate use of PNG_DEFAULT_sRGB and PNG_GAMMA_MAC_18 + as parameters for png_set_gamma(). These have been available since + libpng-1.5.4. + Renamed contrib/tools/png-fix-too-far-back.c to pngfix.c and revised it + to check all compressed chunks known to libpng. + +Version 1.6.3beta10 [July 5, 2013] + Updated documentation to show default behavior of benign errors correctly. + Only compile ARM code when PNG_READ_SUPPORTED is defined. + Fixed undefined behavior in contrib/tools/pngfix.c and added new strip + option. pngfix relied on undefined behavior and even a simple change from + gcc to g++ caused it to fail. The new strip option 'unsafe' has been + implemented and is the default if --max is given. Option names have + been clarified, with --strip=transform now stripping the bKGD chunk, + which was stripped previously with --strip=unused. + Added all documented chunk types to pngpriv.h + Unified pngfix.c source with libpng17. + +Version 1.6.3rc01 [July 11, 2013] + No changes. + +Version 1.6.3 [July 18, 2013] + Revised manual about changes in iTXt chunk handling made in libpng-1.6.0. + Added "/* SAFE */" comments in pngrutil.c and pngrtran.c where warnings + may be erroneously issued by code-checking applications. + +Version 1.6.4beta01 [August 21, 2013] + Added information about png_set_options() to the manual. + Delay calling png_init_filter_functions() until a row with nonzero filter + is found. + +Version 1.6.4beta02 [August 30, 2013] + Fixed inconsistent conditional compilation of png_chunk_unknown_handling() + prototype, definition, and usage. Made it depend on + PNG_HANDLE_AS_UNKNOWN_SUPPORTED everywhere. + +Version 1.6.4rc01 [September 5, 2013] + No changes. + +Version 1.6.4 [September 12, 2013] + No changes. + +Version 1.6.5 [September 14, 2013] + Removed two stray lines of code from arm/arm_init.c. + +Version 1.6.6 [September 16, 2013] + Removed two stray lines of code from arm/arm_init.c, again. + +Version 1.6.7beta01 [September 30, 2013] + Revised unknown chunk code to correct several bugs in the NO_SAVE_/NO_WRITE + combination + Allow HANDLE_AS_UNKNOWN to work when other options are configured off. Also + fixed the pngminim makefiles to work when $(MAKEFLAGS) contains stuff + which terminates the make options (as by default in recent versions of + Gentoo). + Avoid up-cast warnings in pngvalid.c. On ARM the alignment requirements of + png_modifier are greater than that of png_store and as a consequence + compilation of pngvalid.c results in a warning about increased alignment + requirements because of the bare cast to (png_modifier*). The code is safe, + because the pointer is known to point to a stack allocated png_modifier, + but this change avoids the warning. + Fixed default behavior of ARM_NEON_API. If the ARM NEON API option was + compiled without the CHECK option it defaulted to on, not off. + Check user callback behavior in pngunknown.c. Previous versions compiled + if SAVE_UNKNOWN was not available but did nothing since the callback + was never implemented. + Merged pngunknown.c with 1.7 version and back ported 1.7 improvements/fixes + +Version 1.6.7beta02 [October 12, 2013] + Made changes for compatibility with automake 1.14: + 1) Added the 'compile' program to the list of programs that must be cleaned + in autogen.sh + 2) Added 'subdir-objects' which causes .c files in sub-directories to be + compiled such that the corresponding .o files are also in the + sub-directory. This is because automake 1.14 warns that the + current behavior of compiling to the top level directory may be removed + in the future. + 3) Updated dependencies on pnglibconf.h to match the new .o locations and + added all the files in contrib/libtests and contrib/tools that depend + on pnglibconf.h + 4) Added 'BUILD_SOURCES = pnglibconf.h'; this is the automake recommended + way of handling the dependencies of sources that are machine generated; + unfortunately it only works if the user does 'make all' or 'make check', + so the dependencies (3) are still required. + Cleaned up (char*) casts of zlib messages. The latest version of the Intel C + compiler complains about casting a string literal as (char*), so copied the + treatment of z_const from the library code into pngfix.c + Simplified error message code in pngunknown. The simplification has the + useful side effect of avoiding a bogus warning generated by the latest + version of the Intel C compiler (it objects to + condition ? string-literal : string-literal). + Make autogen.sh work with automake 1.13 as well as 1.14. Do this by always + removing the 1.14 'compile' script but never checking for it. + +Version 1.6.7beta03 [October 19, 2013] + Added ARMv8 support (James Yu ). Added file + arm/filter_neon_intrinsics.c; enable with -mfpu=neon. + Revised pngvalid to generate size images with as many filters as it can + manage, limited by the number of rows. + Cleaned up ARM NEON compilation handling. The tests are now in pngpriv.h + and detect the broken GCC compilers. + +Version 1.6.7beta04 [October 26, 2013] + Allow clang derived from older GCC versions to use ARM intrinsics. This + causes all clang builds that use -mfpu=neon to use the intrinsics code, + not the assembler code. This has only been tested on iOS 7. It may be + necessary to exclude some earlier clang versions but this seems unlikely. + Changed NEON implementation selection mechanism. This allows assembler + or intrinsics to be turned on at compile time during the build by defining + PNG_ARM_NEON_IMPLEMENTATION to the correct value (2 or 1). This macro + is undefined by default and the build type is selected in pngpriv.h. + +Version 1.6.7rc01 [November 2, 2013] + No changes. + +Version 1.6.7rc02 [November 7, 2013] + Fixed #include in filter_neon_intrinsics.c and ctype macros. The ctype char + checking macros take an unsigned char argument, not a signed char. + +Version 1.6.7 [November 14, 2013] + No changes. + +Version 1.6.8beta01 [November 24, 2013] + Moved prototype for png_handle_unknown() in pngpriv.h outside of + the #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED/#endif block. + Added "-Wall" to CFLAGS in contrib/pngminim/*/makefile + Conditionally compile some unused functions reported by -Wall in + pngminim. + Fixed 'minimal' builds. Various obviously useful minimal configurations + don't build because of missing contrib/libtests test programs and + overly complex dependencies in scripts/pnglibconf.dfa. This change + adds contrib/conftest/*.dfa files that can be used in automatic build + scripts to ensure that these configurations continue to build. + Enabled WRITE_INVERT and WRITE_PACK in contrib/pngminim/encoder. + Fixed pngvalid 'fail' function declaration on the Intel C Compiler. + This reverts to the previous 'static' implementation and works round + the 'unused static function' warning by using PNG_UNUSED(). + +Version 1.6.8beta02 [November 30, 2013] + Removed or marked PNG_UNUSED some harmless "dead assignments" reported + by clang scan-build. + Changed tabs to 3 spaces in png_debug macros and changed '"%s"m' + to '"%s" m' to improve portability among compilers. + Changed png_free_default() to free() in pngtest.c + +Version 1.6.8rc01 [December 12, 2013] + Tidied up pngfix inits and fixed pngtest no-write builds. + +Version 1.6.8rc02 [December 14, 2013] + Handle zero-length PLTE chunk or NULL palette with png_error() + instead of png_chunk_report(), which by default issues a warning + rather than an error, leading to later reading from a NULL pointer + (png_ptr->palette) in png_do_expand_palette(). This is CVE-2013-6954 + and VU#650142. Libpng-1.6.1 through 1.6.7 are vulnerable. + Libpng-1.6.0 and earlier do not have this bug. + +Version 1.6.8 [December 19, 2013] + No changes. + +Version 1.6.9beta01 [December 26, 2013] + Bookkeeping: Moved functions around (no changes). Moved transform + function definitions before the place where they are called so that + they can be made static. Move the intrapixel functions and the + grayscale palette builder out of the png?tran.c files. The latter + isn't a transform function and is no longer used internally, and the + former MNG specific functions are better placed in pngread/pngwrite.c + Made transform implementation functions static. This makes the internal + functions called by png_do_{read|write}_transformations static. On an + x86-64 DLL build (Gentoo Linux) this reduces the size of the text + segment of the DLL by 1208 bytes, about 0.6%. It also simplifies + maintenance by removing the declarations from pngpriv.h and allowing + easier changes to the internal interfaces. + Rebuilt configure scripts with automake-1.14.1 and autoconf-2.69 + in the tar distributions. + +Version 1.6.9beta02 [January 1, 2014] + Added checks for libpng 1.5 to pngvalid.c. This supports the use of + this version of pngvalid in libpng 1.5 + Merged with pngvalid.c from libpng-1.7 changes to create a single + pngvalid.c + Removed #error macro from contrib/tools/pngfix.c (Thomas Klausner). + Merged pngrio.c, pngtrans.c, pngwio.c, and pngerror.c with libpng-1.7.0 + Merged libpng-1.7.0 changes to make no-interlace configurations work + with test programs. + Revised pngvalid.c to support libpng 1.5, which does not support the + PNG_MAXIMUM_INFLATE_WINDOW option, so #define it out when appropriate in + pngvalid.c + Allow unversioned links created on install to be disabled in configure. + In configure builds 'make install' changes/adds links like png.h + and libpng.a to point to the newly installed, versioned, files (e.g. + libpng17/png.h and libpng17.a). Three new configure options and some + rearrangement of Makefile.am allow creation of these links to be disabled. + +Version 1.6.9beta03 [January 10, 2014] + Removed potentially misleading warning from png_check_IHDR(). + +Version 1.6.9beta04 [January 20, 2014] + Updated scripts/makefile.* to use CPPFLAGS (Cosmin). + Added clang attribute support (Cosmin). + +Version 1.6.9rc01 [January 28, 2014] + No changes. + +Version 1.6.9rc02 [January 30, 2014] + Quiet an uninitialized memory warning from VC2013 in png_get_png(). + +Version 1.6.9 [February 6, 2014] + +Version 1.6.10beta01 [February 9, 2014] + Backported changes from libpng-1.7.0beta30 and beta31: + Fixed a large number of instances where PNGCBAPI was omitted from + function definitions. + Added pngimage test program for png_read_png() and png_write_png() + with two new test scripts. + Removed dependence on !PNG_READ_EXPAND_SUPPORTED for calling + png_set_packing() in png_read_png(). + Fixed combination of ~alpha with shift. On read invert alpha, processing + occurred after shift processing, which causes the final values to be + outside the range that should be produced by the shift. Reversing the + order on read makes the two transforms work together correctly and mirrors + the order used on write. + Do not read invalid sBIT chunks. Previously libpng only checked sBIT + values on write, so a malicious PNG writer could therefore cause + the read code to return an invalid sBIT chunk, which might lead to + application errors or crashes. Such chunks are now skipped (with + chunk_benign_error). + Make png_read_png() and png_write_png() prototypes in png.h depend + upon PNG_READ_SUPPORTED and PNG_WRITE_SUPPORTED. + Support builds with unsupported PNG_TRANSFORM_* values. All of the + PNG_TRANSFORM_* values are always defined in png.h and, because they + are used for both read and write in some cases, it is not reliable + to #if out ones that are totally unsupported. This change adds error + detection in png_read_image() and png_write_image() to do a + png_app_error() if the app requests something that cannot be done + and it adds corresponding code to pngimage.c to handle such options + by not attempting to test them. + +Version 1.6.10beta02 [February 23, 2014] + Moved redefines of png_error(), png_warning(), png_chunk_error(), + and png_chunk_warning() from pngpriv.h to png.h to make them visible + to libpng-calling applications. + Moved OS dependent code from arm/arm_init.c, to allow the included + implementation of the ARM NEON discovery function to be set at + build-time and provide sample implementations from the current code in the + contrib/arm-neon subdirectory. The __linux__ code has also been changed to + compile and link on Android by using /proc/cpuinfo, and the old linux code + is in contrib/arm-neon/linux-auxv.c. The new code avoids POSIX and Linux + dependencies apart from opening /proc/cpuinfo and is C90 compliant. + Check for info_ptr == NULL early in png_read_end() so we don't need to + run all the png_handle_*() and depend on them to return if info_ptr == NULL. + This improves the performance of png_read_end(png_ptr, NULL) and makes + it more robust against future programming errors. + Check for __has_extension before using it in pngconf.h, to + support older Clang versions (Jeremy Sequoia). + Treat CRC error handling with png_set_crc_action(), instead of with + png_set_benign_errors(), which has been the case since libpng-1.6.0beta18. + Use a user warning handler in contrib/gregbook/readpng2.c instead of default, + so warnings will be put on stderr even if libpng has CONSOLE_IO disabled. + Added png_ptr->process_mode = PNG_READ_IDAT_MODE in png_push_read_chunk + after recognizing the IDAT chunk, which avoids an infinite loop while + reading a datastream whose first IDAT chunk is of zero-length. + This fixes CERT VU#684412 and CVE-2014-0333. + Don't recognize known sRGB profiles as sRGB if they have been hacked, + but don't reject them and don't issue a copyright violation warning. + +Version 1.6.10beta03 [February 25, 2014] + Moved some documentation from png.h to libpng.3 and libpng-manual.txt + Minor editing of contrib/arm-neon/README and contrib/examples/*.c + +Version 1.6.10rc01 [February 27, 2014] + Fixed typos in the manual and in scripts/pnglibconf.dfa (CFLAGS -> CPPFLAGS + and PNG_USR_CONFIG -> PNG_USER_CONFIG). + +Version 1.6.10rc02 [February 28, 2014] + Removed unreachable return statement after png_chunk_error() + in pngrutil.c + +Version 1.6.10rc03 [March 4, 2014] + Un-deprecated png_data_freer(). + +Version 1.6.10 [March 6, 2014] + No changes. + +Version 1.6.11beta01 [March 17, 2014] + Use "if (value != 0)" instead of "if (value)" consistently. + Changed ZlibSrcDir from 1.2.5 to 1.2.8 in projects/vstudio. + Moved configuration information from the manual to the INSTALL file. + +Version 1.6.11beta02 [April 6, 2014] + Removed #if/#else/#endif from inside two pow() calls in pngvalid.c because + they were handled improperly by Portland Group's PGI-14.1 - PGI-14.3 + when using its "__builtin_pow()" function. + Silence 'unused parameter' build warnings (Cosmin Truta). + $(CP) is now used alongside $(RM_F). Also, use 'copy' instead of 'cp' + where applicable, and applied other minor makefile changes (Cosmin). + Don't warn about invalid dimensions exceeding user limits (Cosmin). + Allow an easy replacement of the default pre-built configuration + header with a custom header, via the make PNGLIBCONF_H_PREBUILT + macro (Cosmin). + +Version 1.6.11beta03 [April 6, 2014] + Fixed a typo in pngrutil.c, introduced in libpng-1.5.6, that interferes + with "blocky" expansion of sub-8-bit interlaced PNG files (Eric Huss). + Optionally use __builtin_bswap16() in png_do_swap(). + +Version 1.6.11beta04 [April 19, 2014] + Made progressive reading of interlaced images consistent with the + behavior of the sequential reader and consistent with the manual, by + moving some code out of the PNG_READ_INTERLACING_SUPPORTED blocks. The + row_callback now receives the proper pass number and unexpanded rows, when + png_combine_row() isn't built or used, and png_set_interlace_handling() + is not called. + Allow PNG_sRGB_PROFILE_CHECKING = (-1) to mean no sRGB profile checking. + +Version 1.6.11beta05 [April 26, 2014] + Do not reject ICC V2 profiles that lack padding (Kai-Uwe Behrmann). + Relocated closing bracket of the sRGB profile test loop to avoid getting + "Not recognizing known sRGB profile that has been edited" warning for + ICC V2 profiles that lack the MD5 signature in the profile header. + +Version 1.6.11beta06 [May 19, 2014] + Added PNG_SKIP_sRGB_CHECK_PROFILE choice for png_set_option(). + +Version 1.6.11rc01 [May 27, 2014] + No changes. + +Version 1.6.11rc02 [June 3, 2014] + Test ZLIB_VERNUM instead of PNG_ZLIB_VERNUM in contrib/tools/pngfix.c + +Version 1.6.11 [June 5, 2014] + No changes. + +Version 1.6.12rc01 [June 6, 2014] + Relocated new code from 1.6.11beta06 in png.c to a point after the + declarations (Max Stepin). + +Version 1.6.12rc02 [June 7, 2014] + Changed file permissions of contrib/tools/intgamma.sh, + test-driver, and compile from 0644 to 0755 (Cosmin). + +Version 1.6.12rc03 [June 8, 2014] + Ensure "__has_attribute()" macro exists before trying to use it with + old clang compilers (MacPorts Ticket #43939). + +Version 1.6.12 [June 12, 2014] + No changes. + +Version 1.6.13beta01 [July 4, 2014] + Quieted -Wsign-compare and -Wclobber compiler warnings in + contrib/pngminus/*.c + Added "(void) png_ptr;" where needed in contrib/gregbook to quiet + compiler complaints about unused pointers. + Split a long output string in contrib/gregbook/rpng2-x.c. + Added "PNG_SET_OPTION" requirement for sRGB chunk support to pnglibconf.dfa, + Needed for write-only support (John Bowler). + Changed "if defined(__ARM_NEON__)" to + "if (defined(__ARM_NEON__) || defined(__ARM_NEON))" (James Wu). + Fixed clang no-warning builds: png_digit was defined but never used. + +Version 1.6.13beta02 [July 21, 2014] + Fixed an incorrect separator ("/" should be "\") in scripts/makefile.vcwin32 + (bug report from Wolfgang S. Kechel). Bug was introduced in libpng-1.6.11. + Also fixed makefile.bc32, makefile.bor, makefile.msc, makefile.intel, and + makefile.tc3 similarly. + +Version 1.6.13beta03 [August 3, 2014] + Removed scripts/makefile.elf. It has not worked since libpng-1.5.0beta14 + due to elimination of the PNG_FUNCTION_EXPORT and PNG_DATA_EXPORT + definitions from pngconf.h. + Ensure that CMakeLists.txt makes the target "lib" directory before making + symbolic link into it (SourceForge bug report #226 by Rolf Timmermans). + +Version 1.6.13beta04 [August 8, 2014] + Added opinion that the ECCN (Export Control Classification Number) for + libpng is EAR99 to the README file. + Eliminated use of "$<" in makefile explicit rules, when copying + $PNGLIBCONF_H_PREBUILT. This does not work on some versions of make; + bug introduced in libpng version 1.6.11. + +Version 1.6.13rc01 [August 14, 2014] + Made "ccopts" agree with "CFLAGS" in scripts/makefile.hp* and makefile.*sunu + +Version 1.6.13 [August 21, 2014] + No changes. + +Version 1.6.14beta01 [September 14, 2014] + Guard usage of png_ptr->options with #ifdef PNG_SET_OPTION_SUPPORTED. + Do not build contrib/tools/pngfix.c when PNG_SETJMP_NOT_SUPPORTED, + to allow "make" to complete without setjmp support (bug report by + Claudio Fontana) + Add "#include " to contrib/tools/pngfix.c (John Bowler) + +Version 1.6.14beta02 [September 18, 2014] + Use nanosleep() instead of usleep() in contrib/gregbook/rpng2-x.c + because usleep() is deprecated. + Define usleep() in contrib/gregbook/rpng2-x.c if not already defined + in unistd.h and nanosleep() is not available; fixes error introduced + in libpng-1.6.13. + Disable floating point exception handling in pngvalid.c when + PNG_FLOATING_ARITHMETIC is not supported (bug report by "zootus + at users.sourceforge.net"). + +Version 1.6.14beta03 [September 19, 2014] + Define FE_DIVBYZERO, FE_INVALID, and FE_OVERFLOW in pngvalid.c if not + already defined. Revert floating point exception handling in pngvalid.c + to version 1.6.14beta01 behavior. + +Version 1.6.14beta04 [September 27, 2014] + Fixed incorrect handling of the iTXt compression flag in pngrutil.c + (bug report by Shunsaku Hirata). Bug was introduced in libpng-1.6.0. + +Version 1.6.14beta05 [October 1, 2014] + Added "option READ_iCCP enables READ_COMPRESSED_TEXT" to pnglibconf.dfa + +Version 1.6.14beta06 [October 5, 2014] + Removed unused "text_len" parameter from private function png_write_zTXt(). + Conditionally compile some code in png_deflate_claim(), when + PNG_WARNINGS_SUPPORTED and PNG_ERROR_TEXT_SUPPORTED are disabled. + Replaced repeated code in pngpread.c with PNG_PUSH_SAVE_BUFFER_IF_FULL. + Added "chunk iTXt enables TEXT" and "chunk zTXt enables TEXT" + to pnglibconf.dfa. + Removed "option READ_COMPRESSED_TEXT enables READ_TEXT" from pnglibconf.dfa, + to make it possible to configure a libpng that supports iCCP but not TEXT. + +Version 1.6.14beta07 [October 7, 2014] + Removed "option WRITE_COMPRESSED_TEXT enables WRITE_TEXT" from pnglibconf.dfa + Only mark text chunks as written after successfully writing them. + +Version 1.6.14rc01 [October 15, 2014] + Fixed some typos in comments. + +Version 1.6.14rc02 [October 17, 2014] + Changed png_convert_to_rfc_1123() to png_convert_to_rfc_1123_buffer() + in the manual, to reflect the change made in libpng-1.6.0. + Updated README file to explain that direct access to the png_struct + and info_struct members has not been permitted since libpng-1.5.0. + +Version 1.6.14 [October 23, 2014] + No changes. + +Version 1.6.15beta01 [October 29, 2014] + Changed "if (!x)" to "if (x == 0)" and "if (x)" to "if (x != 0)" + Simplified png_free_data(). + Added missing "ptr = NULL" after some instances of png_free(). + +Version 1.6.15beta02 [November 1, 2014] + Changed remaining "if (!x)" to "if (x == 0)" and "if (x)" to "if (x != 0)" + +Version 1.6.15beta03 [November 3, 2014] + Added PNG_USE_ARM_NEON configuration flag (Marcin Juszkiewicz). + +Version 1.6.15beta04 [November 4, 2014] + Removed new PNG_USE_ARM_NEON configuration flag and made a one-line + revision to configure.ac to support ARM on aarch64 instead (John Bowler). + +Version 1.6.15beta05 [November 5, 2014] + Use png_get_libpng_ver(NULL) instead of PNG_LIBPNG_VER_STRING in + example.c, pngtest.c, and applications in the contrib directory. + Fixed an out-of-range read in png_user_version_check() (Bug report from + Qixue Xiao, CVE-2015-8540). + Simplified and future-proofed png_user_version_check(). + Fixed GCC unsigned int->float warnings. Various versions of GCC + seem to generate warnings when an unsigned value is implicitly + converted to double. This is probably a GCC bug but this change + avoids the issue by explicitly converting to (int) where safe. + Free all allocated memory in pngimage. The file buffer cache was left + allocated at the end of the program, harmless but it causes memory + leak reports from clang. + Fixed array size calculations to avoid warnings. At various points + in the code the number of elements in an array is calculated using + sizeof. This generates a compile time constant of type (size_t) which + is then typically assigned to an (unsigned int) or (int). Some versions + of GCC on 64-bit systems warn about the apparent narrowing, even though + the same compiler does apparently generate the correct, in-range, + numeric constant. This adds appropriate, safe, casts to make the + warnings go away. + +Version 1.6.15beta06 [November 6, 2014] + Reverted use png_get_libpng_ver(NULL) instead of PNG_LIBPNG_VER_STRING + in the manual, example.c, pngtest.c, and applications in the contrib + directory. It was incorrect advice. + +Version 1.6.15beta07 [November 7, 2014] + Removed #ifdef PNG_16BIT_SUPPORTED/#endif around png_product2(); it is + needed by png_reciprocal2(). + Added #ifdef PNG_16BIT_SUPPORTED/#endif around png_log16bit() and + png_do_swap(). + Changed all "#endif /* PNG_FEATURE_SUPPORTED */" to "#endif /* FEATURE */" + +Version 1.6.15beta08 [November 8, 2014] + More housecleaning in *.h + +Version 1.6.15rc01 [November 13, 2014] + +Version 1.6.15rc02 [November 14, 2014] + The macros passed in the command line to Borland make were ignored if + similarly-named macros were already defined in makefiles. This behavior + is different from POSIX make and other make programs. Surround the + macro definitions with ifndef guards (Cosmin). + +Version 1.6.15rc03 [November 16, 2014] + Added "-D_CRT_SECURE_NO_WARNINGS" to CFLAGS in scripts/makefile.vcwin32. + Removed the obsolete $ARCH variable from scripts/makefile.darwin. + +Version 1.6.15 [November 20, 2014] + No changes. + +Version 1.6.16beta01 [December 14, 2014] + Added ".align 2" to arm/filter_neon.S to support old GAS assemblers that + don't do alignment correctly. + Revised Makefile.am and scripts/symbols.dfn to work with MinGW/MSYS + (Bob Friesenhahn). + +Version 1.6.16beta02 [December 15, 2014] + Revised Makefile.am and scripts/*.dfn again to work with MinGW/MSYS; + renamed scripts/*.dfn to scripts/*.c (John Bowler). + +Version 1.6.16beta03 [December 21, 2014] + Quiet a "comparison always true" warning in pngstest.c (John Bowler). + +Version 1.6.16rc01 [December 21, 2014] + Restored a test on width that was removed from png.c at libpng-1.6.9 + (Bug report by Alex Eubanks, CVE-2015-0973). + +Version 1.6.16rc02 [December 21, 2014] + Undid the update to pngrutil.c in 1.6.16rc01. + +Version 1.6.16rc03 [December 21, 2014] + Fixed an overflow in png_combine_row() with very wide interlaced images + (Bug report and fix by John Bowler, CVE-2014-9495). + +Version 1.6.16 [December 22, 2014] + No changes. + +Version 1.6.17beta01 [January 29, 2015] + Removed duplicate PNG_SAFE_LIMITS_SUPPORTED handling from pngconf.h + Corrected the width limit calculation in png_check_IHDR(). + Removed user limits from pngfix. Also pass NULL pointers to + png_read_row to skip the unnecessary row de-interlace stuff. + Added testing of png_set_packing() to pngvalid.c + Regenerated configure scripts in the *.tar distributions with libtool-2.4.4 + Implement previously untested cases of libpng transforms in pngvalid.c + Fixed byte order in png_do_read_filler() with 16-bit input. Previously + the high and low bytes of the filler, from png_set_filler() or from + png_set_add_alpha(), were read in the wrong order. + Made the check for out-of-range values in png_set_tRNS() detect + values that are exactly 2^bit_depth, and work on 16-bit platforms. + Merged some parts of libpng-1.6.17beta01 and libpng-1.7.0beta47. + Added #ifndef __COVERITY__ where needed in png.c, pngrutil.c and + pngset.c to avoid warnings about dead code. + Added "& 0xff" to many instances of expressions that are typecast + to (png_byte), to avoid Coverity warnings. + +Version 1.6.17beta02 [February 7, 2015] + Work around one more Coverity-scan dead-code warning. + Do not build png_product2() when it is unused. + +Version 1.6.17beta03 [February 17, 2015] + Display user limits in the output from pngtest. + Eliminated the PNG_SAFE_LIMITS macro and restored the 1-million-column + and 1-million-row default limits in pnglibconf.dfa, that can be reset + by the user at build time or run time. This provides a more robust + defense against DOS and as-yet undiscovered overflows. + +Version 1.6.17beta04 [February 21, 2015] + Added PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED macro, on by default. + Allow user to call png_get_IHDR() with NULL arguments (Reuben Hawkins). + Rebuilt configure scripts with automake-1.15 and libtool-2.4.6 + +Version 1.6.17beta05 [February 25, 2015] + Restored compiling of png_reciprocal2 with PNG_NO_16BIT. + +Version 1.6.17beta06 [February 27, 2015] + Moved png_set_filter() prototype into a PNG_WRITE_SUPPORTED block + of png.h. + Avoid runtime checks when converting integer to png_byte with + Visual Studio (Sergey Kosarevsky) + +Version 1.6.17rc01 [March 4, 2015] + No changes. + +Version 1.6.17rc02 [March 9, 2015] + Removed some comments that the configure script did not handle + properly from scripts/pnglibconf.dfa and pnglibconf.h.prebuilt. + Free the unknown_chunks structure even when it contains no data. + +Version 1.6.17rc03 [March 12, 2015] + Updated CMakeLists.txt to add OSX framework, change YES/NO to ON/OFF + for consistency, and remove some useless tests (Alexey Petruchik). + +Version 1.6.17rc04 [March 16, 2015] + Remove pnglibconf.h, pnglibconf.c, and pnglibconf.out instead of + pnglibconf.* in "make clean" (Cosmin). + Fix bug in calculation of maxbits, in png_write_sBIT, introduced + in libpng-1.6.17beta01 (John Bowler). + +Version 1.6.17rc05 [March 21, 2015] + Define PNG_FILTER_* and PNG_FILTER_VALUE_* in png.h even when WRITE + is not supported (John Bowler). This fixes an error introduced in + libpng-1.6.17beta06. + Reverted "& 0xff" additions of version 1.6.17beta01. Libpng passes + the Coverity scan without them. + +Version 1.6.17rc06 [March 23, 2015] + Remove pnglibconf.dfn and pnglibconf.pre with "make clean". + Reformatted some "&0xff" instances to "& 0xff". + Fixed simplified 8-bit-linear to sRGB alpha. The calculated alpha + value was wrong. It's not clear if this affected the final stored + value; in the obvious code path the upper and lower 8-bits of the + alpha value were identical and the alpha was truncated to 8-bits + rather than dividing by 257 (John Bowler). + +Version 1.6.17 [March 26, 2015] + No changes. + +Version 1.6.18beta01 [April 1, 2015] + Removed PNG_SET_CHUNK_[CACHE|MALLOC]_LIMIT_SUPPORTED macros. They + have been combined with PNG_SET_USER_LIMITS_SUPPORTED (resolves + bug report by Andrew Church). + Fixed rgb_to_gray checks and added tRNS checks to pngvalid.c. This + fixes some arithmetic errors that caused some tests to fail on + some 32-bit platforms (Bug reports by Peter Breitenlohner [i686] + and Petr Gajdos [i586]). + +Version 1.6.18beta02 [April 26, 2015] + Suppressed some warnings from the Borland C++ 5.5.1/5.82 compiler + (Bug report by Viktor Szakats). + +Version 1.6.18beta03 [May 6, 2015] + Replaced "unexpected" with an integer (0xabadca11) in pngset.c + where a long was expected, to avoid a compiler warning when PNG_DEBUG > 1. + Added contrib/examples/simpleover.c, to demonstrate how to handle + alpha compositing of multiple images, using the "simplified API" + and an example PNG generation tool, contrib/examples/genpng.c + (John Bowler). + +Version 1.6.18beta04 [May 20, 2015] + PNG_RELEASE_BUILD replaces tests where the code depended on the build base + type and can be defined on the command line, allowing testing in beta + builds (John Bowler). + Avoid Coverity issue 80858 (REVERSE NULL) in pngtest.c PNG_DEBUG builds. + Avoid a harmless potential integer overflow in png_XYZ_from_xy() (Bug + report from Christopher Ferris). + +Version 1.6.18beta05 [May 31, 2015] + Backport filter selection code from libpng-1.7.0beta51, to combine + sub_row, up_row, avg_row, and paeth_row into try_row and tst_row. + Changed png_voidcast(), etc., to voidcast(), etc., in contrib/tools/pngfix.c + to avoid confusion with the libpng private macros. + Fixed old cut&paste bug in the weighted filter selection code in + pngwutil.c, introduced in libpng-0.95, March 1997. + +Version 1.6.18beta06 [June 1, 2015] + Removed WRITE_WEIGHTED_FILTERED code, to save a few kbytes of the + compiled library size. It never worked properly and as far as we can + tell, no one uses it. The png_set_filter_heuristics() and + png_set_filter_heuristics_fixed() APIs are retained but deprecated + and do nothing. + +Version 1.6.18beta07 [June 6, 2015] + Removed non-working progressive reader 'skip' function. This + function has apparently never been used. It was implemented + to support back-door modification of png_struct in libpng-1.4.x + but (because it does nothing and cannot do anything) was apparently + never tested (John Bowler). + Fixed cexcept.h in which GCC 5 now reports that one of the auto + variables in the Try macro needs to be volatile to prevent value + being lost over the setjmp (John Bowler). + Fixed NO_WRITE_FILTER and -Wconversion build breaks (John Bowler). + Fix g++ build breaks (John Bowler). + Quieted some Coverity issues in pngfix.c, png-fix-itxt.c, pngvalid.c, + pngstest.c, and pngimage.c. Most seem harmless, but png-fix-itxt + would only work with iTXt chunks with length 255 or less. + Added #ifdef's to contrib/examples programs so people don't try + to compile them without the minimum required support enabled + (suggested by Flavio Medeiros). + +Version 1.6.18beta08 [June 30, 2015] + Eliminated the final two Coverity defects (insecure temporary file + handling in contrib/libtests/pngstest.c; possible overflow of + unsigned char in contrib/tools/png-fix-itxt.c). To use the "secure" + file handling, define PNG_USE_MKSTEMP, otherwise "tmpfile()" will + be used. + Removed some unused WEIGHTED_FILTER macros from png.h and pngstruct.h + +Version 1.6.18beta09 [July 5, 2015] + Removed some useless typecasts from contrib/tools/png-fix-itxt.c + Fixed a new signed-unsigned comparison in pngrtran.c (Max Stepin). + Replaced arbitrary use of 'extern' with #define PNG_LINKAGE_*. To + preserve API compatibility, the new defines all default to "extern" + (requested by Jan Nijtmans). + +Version 1.6.18rc01 [July 9, 2015] + Belatedly added Mans Rullgard and James Yu to the list of Contributing + Authors. + +Version 1.6.18rc02 [July 12, 2015] + Restored unused FILTER_HEURISTIC macros removed at libpng-1.6.18beta08 + to png.h to avoid compatibility warnings. + +Version 1.6.18rc03 [July 15, 2015] + Minor changes to the man page + +Version 1.6.18 [July 23, 2015] + No changes. + +Version 1.6.19beta01 [July 30, 2015] + Updated obsolete information about the simplified API macros in the + manual pages (Bug report by Arc Riley). + Avoid potentially dereferencing NULL info_ptr in png_info_init_3(). + Rearranged png.h to put the major sections in the same order as + in libpng17. + Eliminated unused PNG_COST_SHIFT, PNG_WEIGHT_SHIFT, PNG_COST_FACTOR, and + PNG_WEIGHT_FACTOR macros. + Suppressed some warnings from the Borland C++ 5.5.1/5.82 compiler + (Bug report by Viktor Szakats). Several warnings remain and are + unavoidable, where we test for overflow. + Fixed potential leak of png_pixels in contrib/pngminus/pnm2png.c + Fixed uninitialized variable in contrib/gregbook/rpng2-x.c + +Version 1.6.19beta02 [August 19, 2015] + Moved config.h.in~ from the "libpng_autotools_files" list to the + "libpng_autotools_extra" list in autogen.sh because it was causing a + false positive for missing files (bug report by Robert C. Seacord). + Removed unreachable "break" statements in png.c, pngread.c, and pngrtran.c + to suppress clang warnings (Bug report by Viktor Szakats). + Fixed some bad links in the man page. + Changed "n bit" to "n-bit" in comments. + Added signed/unsigned 16-bit safety net. This removes the dubious + 0x8000 flag definitions on 16-bit systems. They aren't supported + yet the defs *probably* work, however it seems much safer to do this + and be advised if anyone, contrary to advice, is building libpng 1.6 + on a 16-bit system. It also adds back various switch default clauses + for GCC; GCC errors out if they are not present (with an appropriately + high level of warnings). + Safely convert num_bytes to a png_byte in png_set_sig_bytes() (Robert + Seacord). + Fixed the recently reported 1's complement security issue by replacing + the value that is illegal in the PNG spec, in both signed and unsigned + values, with 0. Illegal unsigned values (anything greater than or equal + to 0x80000000) can still pass through, but since these are not illegal + in ANSI-C (unlike 0x80000000 in the signed case) the checking that + occurs later can catch them (John Bowler). + +Version 1.6.19beta03 [September 26, 2015] + Fixed png_save_int_32 when int is not 2's complement (John Bowler). + Updated libpng16 with all the recent test changes from libpng17, + including changes to pngvalid.c to ensure that the original, + distributed, version of contrib/visupng/cexcept.h can be used + (John Bowler). + pngvalid contains the correction to the use of SAVE/STORE_ + UNKNOWN_CHUNKS; a bug revealed by changes in libpng 1.7. More + tests contain the --strict option to detect warnings and the + pngvalid-standard test has been corrected so that it does not + turn on progressive-read. There is a separate test which does + that. (John Bowler) + Also made some signed/unsigned fixes. + Make pngstest error limits version specific. Splitting the machine + generated error structs out to a file allows the values to be updated + without changing pngstest.c itself. Since libpng 1.6 and 1.7 have + slightly different error limits this simplifies maintenance. The + makepngs.sh script has also been updated to more accurately reflect + current problems in libpng 1.7 (John Bowler). + Incorporated new test PNG files into make check. tests/pngstest-* + are changed so that the new test files are divided into 8 groups by + gamma and alpha channel. These tests have considerably better code + and pixel-value coverage than contrib/pngsuite; however,coverage is + still incomplete (John Bowler). + Removed the '--strict' in 1.6 because of the double-gamma-correction + warning, updated pngstest-errors.h for the errors detected with the + new contrib/testspngs PNG test files (John Bowler). + +Version 1.6.19beta04 [October 15, 2015] + Worked around rgb-to-gray issues in libpng 1.6. The previous + attempts to ignore the errors in the code aren't quite enough to + deal with the 'channel selection' encoding added to libpng 1.7; abort. + pngvalid.c is changed to drop this encoding in prior versions. + Fixed 'pow' macros in pngvalid.c. It is legal for 'pow' to be a + macro, therefore the argument list cannot contain preprocessing + directives. Make sure pow is a function where this happens. This is + a minimal safe fix, the issue only arises in non-performance-critical + code (bug report by Curtis Leach, fix by John Bowler). + Added sPLT support to pngtest.c + +Version 1.6.19rc01 [October 23, 2015] + No changes. + +Version 1.6.19rc02 [October 31, 2015] + Prevent setting or writing over-length PLTE chunk (Cosmin Truta). + Silently truncate over-length PLTE chunk while reading. + Libpng incorrectly calculated the output rowbytes when the application + decreased either the number of channels or the bit depth (or both) in + a user transform. This was safe; libpng overallocated buffer space + (potentially by quite a lot; up to 4 times the amount required) but, + from 1.5.4 on, resulted in a png_error (John Bowler). + +Version 1.6.19rc03 [November 3, 2015] + Fixed some inconsequential cut-and-paste typos in png_set_cHRM_XYZ_fixed(). + Clarified COPYRIGHT information to state explicitly that versions + are derived from previous versions. + Removed much of the long list of previous versions from png.h and + libpng.3. + +Version 1.6.19rc04 [November 5, 2015] + Fixed new bug with CRC error after reading an over-length palette + (bug report by Cosmin Truta) (CVE-2015-8126). + +Version 1.6.19 [November 12, 2015] + Cleaned up coding style in png_handle_PLTE(). + +Version 1.6.20beta01 [November 20, 2015] + Avoid potential pointer overflow/underflow in png_handle_sPLT() and + png_handle_pCAL() (Bug report by John Regehr). + +Version 1.6.20beta02 [November 23, 2015] + Fixed incorrect implementation of png_set_PLTE() that uses png_ptr + not info_ptr, that left png_set_PLTE() open to the CVE-2015-8126 + vulnerability. Fixes CVE-2015-8472. + +Version 1.6.20beta03 [November 24, 2015] + Backported tests from libpng-1.7.0beta69. + +Version 1.6.20rc01 [November 26, 2015] + Fixed an error in handling of bad zlib CMINFO field in pngfix, found by + American Fuzzy Lop, reported by Brian Carpenter. inflate() doesn't + immediately fault a bad CMINFO field; instead a 'too far back' error + happens later (at least some times). pngfix failed to limit CMINFO to + the allowed values but then assumed that window_bits was in range, + triggering an assert. The bug is mostly harmless; the PNG file cannot + be fixed. + +Version 1.6.20rc02 [November 29, 2015] + In libpng 1.6 zlib initialization was changed to use the window size + in the zlib stream, not a fixed value. This causes some invalid images, + where CINFO is too large, to display 'correctly' if the rest of the + data is valid. This provides a workaround for zlib versions where the + error arises (ones that support the API change to use the window size + in the stream). + +Version 1.6.20 [December 3, 2015] + No changes. + +Version 1.6.21beta01 [December 11, 2015] + Fixed syntax "$(command)" in tests/pngstest that some shells other than + bash could not parse (Bug report by Nelson Beebe). Use `command` instead. + +Version 1.6.21beta02 [December 14, 2015] + Moved png_check_keyword() from pngwutil.c to pngset.c + Removed LE/BE dependencies in pngvalid, to 'fix' the current problem + in the BigEndian tests by not testing it, making the BE code the same + as the LE version. + Fixes to pngvalid for various reduced build configurations (eliminate unused + statics) and a fix for the case in rgb_to_gray when the digitize option + reduces graylo to 0, producing a large error. + +Version 1.6.21beta03 [December 18, 2015] + Widened the 'limit' check on the internally calculated error limits in + the 'DIGITIZE' case (the code used prior to 1.7 for rgb_to_gray error + checks) and changed the check to only operate in non-release builds + (base build type not RC or RELEASE.) + Fixed undefined behavior in pngvalid.c, undefined because + (png_byte) << shift is undefined if it changes the signed bit + (because png_byte is promoted to int). The libpng exported functions + png_get_uint_32 and png_get_uint_16 handle this. (Bug reported by + David Drysdale as a result of reports from UBSAN in clang 3.8). + This changes pngvalid to use BE random numbers; this used to produce + errors but these should not be fixed as a result of the previous changes. + +Version 1.6.21rc01 [January 4, 2016] + In projects/vstudio, combined readme.txt and WARNING into README.txt + +Version 1.6.21rc02 [January 7, 2016] + Relocated assert() in contrib/tools/pngfix.c, bug found by American + Fuzzy Lop, reported by Brian Carpenter. + Marked 'limit' UNUSED in transform_range_check(). This only affects + release builds. + +Version 1.6.21 [January 15, 2016] + Worked around a false-positive Coverity issue in pngvalid.c. + +Version 1.6.22beta01 [January 23, 2016] + Changed PNG_USE_MKSTEMP to __COVERITY__ to select alternate + "tmpfile()" implementation in contrib/libtests/pngstest.c + Fixed NO_STDIO build of pngunknown.c to skip calling png_init_io() + if there is no stdio.h support. + Added a png_image_write_to_memory() API and a number of assist macros + to allow an application that uses the simplified API write to bypass + stdio and write directly to memory. + Added some warnings (png.h) and some check code to detect *possible* + overflow in the ROW_STRIDE and simplified image SIZE macros. This + disallows image width/height/format that *might* overflow. This is + a quiet API change that limits in-memory image size (uncompressed) to + less than 4GByte and image row size (stride) to less than 2GByte. + Revised workaround for false-positive Coverity issue in pngvalid.c. + +Version 1.6.22beta02 [February 8, 2016] + Only use exit(77) in configure builds. + Corrected error in PNG_IMAGE_PNG_SIZE_MAX. This new macro underreported + the palette size because it failed to take into account that the memory + palette has to be expanded to full RGB when it is written to PNG. + Updated CMakeLists.txt, added supporting scripts/gen*.cmake.in + and test.cmake.in (Roger Leigh). + Relaxed limit checks on gamma values in pngrtran.c. As suggested in + the comments gamma values outside the range currently permitted + by png_set_alpha_mode are useful for HDR data encoding. These values + are already permitted by png_set_gamma so it is reasonable caution to + extend the png_set_alpha_mode range as HDR imaging systems are starting + to emerge. + +Version 1.6.22beta03 [March 9, 2016] + Added a common-law trademark notice and export control information + to the LICENSE file, png.h, and the man page. + Restored "& 0xff" in png_save_uint_16() and png_save_uint_32() that + were accidentally removed from libpng-1.6.17. + Changed PNG_INFO_cHNK and PNG_FREE_cHNK from 0xnnnn to 0xnnnnU in png.h + (Robert C. Seacord). + Removed dubious "#if INT_MAX" test from png.h that was added to + libpng-1.6.19beta02 (John Bowler). + Add ${INCLUDES} in scripts/genout.cmake.in (Bug report by Nixon Kwok). + Updated LICENSE to say files in the contrib directory are not + necessarily under the libpng license, and that some makefiles have + other copyright owners. + Added INTEL-SSE2 support (Mike Klein and Matt Sarett, Google, Inc.). + Made contrib/libtests/timepng more robust. The code no longer gives + up/fails on invalid PNG data, it just skips it (with error messages). + The code no longer fails on PNG files with data beyond IEND. Options + exist to use png_read_png (reading the whole image, not by row) and, in + that case, to apply any of the supported transforms. This makes for + more realistic testing; the decoded data actually gets used in a + meaningful fashion (John Bowler). + Fixed some misleading indentation (Krishnaraj Bhat). + +Version 1.6.22beta04 [April 5, 2016] + Force GCC compilation to C89 if needed (Dagobert Michelsen). + SSE filter speed improvements for bpp=3: + memcpy-free implementations of load3() / store3(). + call load3() only when needed at the end of a scanline. + +Version 1.6.22beta05 [April 27, 2016] + Added PNG_FAST_FILTERS macro (defined as + PNG_FILTER_NONE|PNG_FILTER_SUB|PNG_FILTER_UP). + Various fixes for contrib/libtests/timepng.c + Moved INTEL-SSE code from pngpriv.h into contrib/intel/intel_sse.patch. + Fixed typo (missing underscore) in #define PNG_READ_16_TO_8_SUPPORTED + (Bug report by Y.Ohashik). + +Version 1.6.22beta06 [May 5, 2016] + Rebased contrib/intel_sse.patch. + Quieted two Coverity issues in contrib/libtests/timepng.c. + Fixed issues with scripts/genout.cmake.in (David Capello, Nixon Kwok): + Added support to use multiple directories in ZLIBINCDIR variable, + Fixed CMAKE_C_FLAGS with multiple values when genout is compiled on MSVC, + Fixed pnglibconf.c compilation on OS X including the sysroot path. + +Version 1.6.22rc01 [May 14, 2016] + No changes. + +Version 1.6.22rc02 [May 16, 2016] + Removed contrib/timepng from default build; it does not build on platforms + that don't supply clock_gettime(). + +Version 1.6.22rc03 [May 17, 2016] + Restored contrib/timepng to default build but check for the presence + of clock_gettime() in configure.ac and Makefile.am. + +Version 1.6.22 [May 26, 2016] + No changes. + +Version 1.6.23beta01 [May 29, 2016] + Stop a potential memory leak in png_set_tRNS() (Bug report by Ted Ying). + Fixed the progressive reader to handle empty first IDAT chunk properly + (patch by Timothy Nikkel). This bug was introduced in libpng-1.6.0 and + only affected the libpng16 branch. + Added tests in pngvalid.c to check zero-length IDAT chunks in various + positions. Fixed the sequential reader to handle these more robustly + (John Bowler). + +Version 1.6.23rc01 [June 2, 2016] + Corrected progressive read input buffer in pngvalid.c. The previous version + the code invariably passed just one byte at a time to libpng. The intent + was to pass a random number of bytes in the range 0..511. + Moved sse2 prototype from pngpriv.h to contrib/intel/intel_sse.patch. + Added missing ")" in pngerror.c (Matt Sarrett). + +Version 1.6.23rc02 [June 4, 2016] + Fixed undefined behavior in png_push_save_buffer(). Do not call + memcpy() with a null source, even if count is zero (Leon Scroggins III). + +Version 1.6.23 [June 9, 2016] + Fixed bad link to RFC2083 in png.5 (Nikola Forro). + +Version 1.6.24beta01 [June 11, 2016] + Avoid potential overflow of the PNG_IMAGE_SIZE macro. This macro + is not used within libpng, but is used in some of the examples. + +Version 1.6.24beta02 [June 23, 2016] + Correct filter heuristic overflow handling. This was broken when the + write filter code was moved out-of-line; if there is a single filter and + the heuristic sum overflows the calculation of the filtered line is not + completed. In versions prior to 1.6 the code was duplicated in-line + and the check not performed, so the filter operation completed; however, + in the multi-filter case where the sum is performed the 'none' filter would + be selected if all the sums overflowed, even if it wasn't in the filter + list. The fix to the first problem is simply to provide PNG_SIZE_MAX as + the current lmins sum value; this means the sum can never exceed it and + overflows silently. A reasonable compiler that does choose to inline + the code will simply eliminate the sum check. + The fix to the second problem is to use high precision arithmetic (this is + implemented in 1.7), however a simple safe fix here is to chose the lowest + numbered filter in the list from png_set_filter (this only works if the + first problem is also fixed) (John Bowler). + Use a more efficient absolute value calculation on SSE2 (Matthieu Darbois). + Fixed the case where PNG_IMAGE_BUFFER_SIZE can overflow in the application + as a result of the application using an increased 'row_stride'; previously + png_image_finish_read only checked for overflow on the base calculation of + components. (I.e. it checked for overflow of a 32-bit number on the total + number of pixel components in the output format, not the possibly padded row + length and not the number of bytes, which for linear formats is twice the + number of components.) + MSVC does not like '-(unsigned)', so replaced it with 0U-(unsigned) + MSVC does not like (uInt) = -(unsigned) (i.e. as an initializer), unless + the conversion is explicitly invoked by a cast. + Put the SKIP definition in the correct place. It needs to come after the + png.h include (see all the other .c files in contrib/libtests) because it + depends on PNG_LIBPNG_VER. + Removed the three compile warning options from the individual project + files into the zlib.props globals. It increases the warning level from 4 + to All and adds a list of the warnings that need to be turned off. This is + semi-documentary; the intent is to tell libpng users which warnings have + been examined and judged non-fixable at present. The warning about + structure padding is fixable, but it would be a significant change (moving + structure members around). + +Version 1.6.24beta03 [July 4, 2016] + Optimized absolute value calculation in filter selection, similar to + code in the PAETH decoder in pngrutil.c. Build with PNG_USE_ABS to + use this. + Added pngcp to the build together with a pngcp.dfa configuration test. + Added high resolution timing to pngcp. + Added "Common linking failures" section to INSTALL. + Relocated misplaced #endif in png.c sRGB profile checking. + Fixed two Coverity issues in pngcp.c. + +Version 1.6.24beta04 [July 8, 2016] + Avoid filter-selection heuristic sum calculations in cases where only one + filter is a candidate for selection. This trades off code size (added + private png_setup_*_row_only() functions) for speed. + +Version 1.6.24beta05 [July 13, 2016] + Fixed some indentation to comply with our coding style. + Added contrib/tools/reindent. + +Version 1.6.24beta06 [July 18, 2016] + Fixed more indentation to comply with our coding style. + Eliminated unnecessary tests of boolean png_isaligned() vs 0. + +Version 1.6.24rc01 [July 25, 2016] + No changes. + +Version 1.6.24rc02 [August 1, 2016] + Conditionally compile SSE2 headers in contrib/intel/intel_sse.patch + Conditionally compile png_decompress_chunk(). + +Version 1.6.24rc03 [August 2, 2016] + Conditionally compile ARM_NEON headers in pngpriv.h + Updated contrib/intel/intel_sse.patch + +Version 1.6.24[August 4, 2016] + No changes. + +Version 1.6.25beta01 [August 12, 2016] + Reject oversized iCCP profile immediately. + Cleaned up PNG_DEBUG compile of pngtest.c. + Conditionally compile png_inflate(). + +Version 1.6.25beta02 [August 18, 2016] + Don't install pngcp; it conflicts with pngcp in the pngtools package. + Minor editing of INSTALL, (whitespace, added copyright line) + +Version 1.6.25rc01 [August 24, 2016] + No changes. + +Version 1.6.25rc02 [August 29, 2016] + Added MIPS support (Mandar Sahastrabuddhe ). + Only the UP filter is currently implemented. + +Version 1.6.25rc03 [August 29, 2016] + Rebased contrib/intel/intel_sse.patch after the MIPS implementation. + +Version 1.6.25rc04 [August 30, 2016] + Added MIPS support for SUB, AVG, and PAETH filters (Mandar Sahastrabuddhe). + +Version 1.6.25rc05 [August 30, 2016] + Rebased contrib/intel/intel_sse.patch after the MIPS implementation update.. + +Version 1.6.25 [September 1, 2016] + No changes. + +Version 1.6.26beta01 [September 26, 2016] + Fixed handling zero length IDAT in pngfix (bug report by Agostino Sarubbo, + bugfix by John Bowler). + Do not issue a png_error() on read in png_set_pCAL() because png_handle_pCAL + has allocated memory that libpng needs to free. + Conditionally compile png_set_benign_errors() in pngread.c and pngtest.c + Issue a png_benign_error instead of a png_error on ADLER32 mismatch + while decoding compressed data chunks. + Changed PNG_ZLIB_VERNUM to ZLIB_VERNUM in pngpriv.h, pngstruct.h, and + pngrutil.c. + If CRC handling of critical chunks has been set to PNG_CRC_QUIET_USE, + ignore the ADLER32 checksum in the IDAT chunk as well as the chunk CRCs. + Issue png_benign_error() on ADLER32 checksum mismatch instead of png_error(). + Add tests/badcrc.png and tests/badadler.png to tests/pngtest. + Merged pngtest.c with libpng-1.7.0beta84/pngtest.c + +Version 1.6.26beta02 [October 1, 2016] + Updated the documentation about CRC and ADLER32 handling. + Quieted 117 warnings from clang-3.8 in pngtrans.c, pngread.c, + pngwrite.c, pngunknown.c, and pngvalid.c. + Quieted 58 (out of 144) -Wconversion compiler warnings by changing + flag definitions in pngpriv.h from 0xnnnn to 0xnnnnU and trivial changes + in png.c, pngread.c, and pngwutil.c. + +Version 1.6.26beta03 [October 2, 2016] + Removed contrib/libtests/*.orig and *.rej that slipped into the tarballs. + Quieted the 86 remaining -Wconversion compiler warnings by + revising the png_isaligned() macro and trivial changes in png.c, + pngerror.c, pngget.c, pngmem.c, pngset.c, pngrtran.c, pngrutil.c, + pngwtran.c, pngwrite.c, and pngwutil.c. + +Version 1.6.26beta04 [October 3, 2016] + Quieted (bogus?) clang warnings about "absolute value has no effect" + when PNG_USE_ABS is defined. + Fixed offsets in contrib/intel/intel_sse.patch + +Version 1.6.26beta05 [October 6, 2016] + Changed integer constant 4294967294 to unsigned 4294967294U in pngconf.h + to avoid a signed/unsigned compare in the preprocessor. + +Version 1.6.26beta06 [October 7, 2016] + Use zlib-1.2.8.1 inflateValidate() instead of inflateReset2() to + optionally avoid ADLER32 evaluation. + +Version 1.6.26rc01 [October 12, 2016] + No changes. + +Version 1.6.26 [October 20, 2016] + Cosmetic change, "ptr != 0" to "ptr != NULL" in png.c and pngrutil.c + Despammed email addresses (replaced "@" with " at "). + +Version 1.6.27beta01 [November 2, 2016] + Restrict the new ADLER32-skipping to IDAT chunks. It broke iCCP chunk + handling: an erroneous iCCP chunk would throw a png_error and reject the + entire PNG image instead of rejecting just the iCCP chunk with a warning, + if built with zlib-1.2.8.1. + +Version 1.6.27rc01 [December 27, 2016] + Control ADLER32 checking with new PNG_IGNORE_ADLER32 option. Fixes + an endless loop when handling erroneous ADLER32 checksums; bug + introduced in libpng-1.6.26. + Removed the use of a macro containing the pre-processor 'defined' + operator. It is unclear whether this is valid; a macro that + "generates" 'defined' is not permitted, but the use of the word + "generates" within the C90 standard seems to imply more than simple + substitution of an expression itself containing a well-formed defined + operation. + Added ARM support to CMakeLists.txt (Andreas Franek). + +Version 1.6.27 [December 29, 2016] + Fixed a potential null pointer dereference in png_set_text_2() (bug report + and patch by Patrick Keshishian, CVE-2016-10087). + +Version 1.6.28rc01 [January 3, 2017] + Fixed arm/aarch64 detection in CMakeLists.txt (Gianfranco Costamagna). + Added option to Cmake build allowing a custom location of zlib to be + specified in a scenario where libpng is being built as a subproject + alongside zlib by another project (Sam Serrels). + Changed png_ptr->options from a png_byte to png_uint_32, to accommodate + up to 16 options. + +Version 1.6.28rc02 [January 4, 2017] + Added "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + +Version 1.6.28rc03 [January 4, 2017] + Backed out the SSE optimization and last CMakeLists.txt to allow time for QA. + +Version 1.6.28 [January 5, 2017] + No changes. + +Version 1.6.29beta01 [January 12, 2017] + Readded "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + Simplified conditional compilation in pngvalid.c, for AIX (Michael Felt). + +Version 1.6.29beta02 [February 22, 2017] + Avoid conditional directives that break statements in pngrutil.c (Romero + Malaquias) + The contrib/examples/pngtopng.c recovery code was in the wrong "if" + branches; the comments were correct. + Added code for PowerPC VSX optimisation (Vadim Barkov). + +Version 1.6.29beta03 [March 1, 2017] + Avoid potential overflow of shift operations in png_do_expand() (Aaron Boxer). + Change test ZLIB_VERNUM >= 0x1281 to ZLIB_VERNUM >= 0x1290 in pngrutil.c + because Solaris 11 distributes zlib-1.2.8.f that is older than 1.2.8.1, + as suggested in zlib FAQ, item 24. + Suppress clang warnings about implicit sign changes in png.c + +Version 1.6.29 [March 16, 2017] + No changes. + +Version 1.6.30beta01 [April 1, 2017] + Added missing "$(CPPFLAGS)" to the compile line for c.pic.o in + makefile.linux and makefile.solaris-x86 (Cosmin). + Revised documentation of png_get_error_ptr() in the libpng manual. + Silence clang -Wcomma and const drop warnings (Viktor Szakats). + Update Sourceforge URLs in documentation (https instead of http). + +Version 1.6.30beta02 [April 22, 2017] + Document need to check for integer overflow when allocating a pixel + buffer for multiple rows in contrib/gregbook, contrib/pngminus, + example.c, and in the manual (suggested by Jaeseung Choi). This + is similar to the bug reported against pngquant in CVE-2016-5735. + Removed reference to the obsolete PNG_SAFE_LIMITS macro in the documentation. + +Version 1.6.30beta03 [May 22, 2017] + Check for integer overflow in contrib/visupng and contrib/tools/genpng. + Do not double evaluate CMAKE_SYSTEM_PROCESSOR in CMakeLists.txt. + Test CMAKE_HOST_WIN32 instead of WIN32 in CMakeLists.txt. + Fix some URL in documentation. + +Version 1.6.30beta04 [June 7, 2017] + Avoid writing an empty IDAT when the last IDAT exactly fills the + compression buffer (bug report by Brian Baird). This bug was + introduced in libpng-1.6.0. + +Version 1.6.30rc01 [June 14, 2017] + No changes. + +Version 1.6.30rc02 [June 25, 2017] + Update copyright year in pnglibconf.h, make ltmain.sh executable. + Add a reference to the libpng.download site in README. + +Version 1.6.30 [June 28, 2017] + No changes. + +Version 1.6.31beta01 [July 5, 2017] + Guard the definition of _POSIX_SOURCE in pngpriv.h (AIX already defines it; + bug report by Michael Felt). + Revised pngpriv.h to work around failure to compile arm/filter_neon.S + ("typedef" directive is unrecognized by the assembler). The problem + was introduced in libpng-1.6.30beta01. + Added "Requires: zlib" to libpng.pc.in (Pieter Neerincx). + Added special case for FreeBSD in arm/filter_neon.S (Maya Rashish). + +Version 1.6.31beta02 [July 8, 2017] + Added instructions for disabling hardware optimizations in INSTALL. + Added "--enable-hardware-optimizations" configuration flag to enable + or disable all hardware optimizations with one flag. + +Version 1.6.31beta03 [July 9, 2017] + Updated CMakeLists.txt to add INTEL_SSE and MIPS_MSA platforms. + Changed "int" to "png_size_t" in intel/filter_sse2.c to prevent + possible integer overflow (Bug report by John Bowler). + Quieted "declaration after statement" warnings in intel/filter_sse2.c. + Added scripts/makefile-linux-opt, which has hardware optimizations enabled. + +Version 1.6.31beta04 [July 11, 2017] + Removed one of the GCC-7.1.0 'strict-overflow' warnings that result when + integers appear on both sides of a compare. Worked around the others by + forcing the strict-overflow setting in the relevant functions to a level + where they are not reported (John Bowler). + Changed "FALL THROUGH" comments to "FALLTHROUGH" because GCC doesn't like + the space. + Worked around some C-style casts from (void*) because g++ 5.4.0 objects + to them. + Increased the buffer size for 'sprint' to pass the gcc 7.1.0 'sprint + overflow' check that is on by default with -Wall -Wextra. + +Version 1.6.31beta05 [July 13, 2017] + Added eXIf chunk support. + +Version 1.6.31beta06 [July 17, 2017] + Added a minimal eXIf chunk (with Orientation and FocalLengthIn35mmFilm + tags) to pngtest.png. + +Version 1.6.31beta07 [July 18, 2017] + Revised the eXIf chunk in pngtest.png to fix "Bad IFD1 Directory" warning. + +Version 1.6.31rc01 [July 19, 2017] + No changes. + +Version 1.6.31rc02 [July 25, 2017] + Fixed typo in example.c (png_free_image should be png_image_free) (Bug + report by John Smith) + +Version 1.6.31 [July 27, 2017] + No changes. + +Version 1.6.32beta01 [July 31, 2017] + Avoid possible NULL dereference in png_handle_eXIf when benign_errors + are allowed. Avoid leaking the input buffer "eXIf_buf". + Eliminated png_ptr->num_exif member from pngstruct.h and added num_exif + to arguments for png_get_eXIf() and png_set_eXIf(). + Added calls to png_handle_eXIf(() in pngread.c and png_write_eXIf() in + pngwrite.c, and made various other fixes to png_write_eXIf(). + Changed name of png_get_eXIF and png_set_eXIf() to png_get_eXIf_1() and + png_set_eXIf_1(), respectively, to avoid breaking API compatibility + with libpng-1.6.31. + +Version 1.6.32beta02 [August 1, 2017] + Updated contrib/libtests/pngunknown.c with eXIf chunk. + +Version 1.6.32beta03 [August 2, 2017] + Initialized btoa[] in pngstest.c + Stop memory leak when returning from png_handle_eXIf() with an error + (Bug report from the OSS-fuzz project). + +Version 1.6.32beta04 [August 2, 2017] + Replaced local eXIf_buf with info_ptr-eXIf_buf in png_handle_eXIf(). + Update libpng.3 and libpng-manual.txt about eXIf functions. + +Version 1.6.32beta05 [August 2, 2017] + Restored png_get_eXIf() and png_set_eXIf() to maintain API compatibility. + +Version 1.6.32beta06 [August 2, 2017] + Removed png_get_eXIf_1() and png_set_eXIf_1(). + +Version 1.6.32beta07 [August 3, 2017] + Check length of all chunks except IDAT against user limit to fix an + OSS-fuzz issue (Fixes CVE-2017-12652). + +Version 1.6.32beta08 [August 3, 2017] + Check length of IDAT against maximum possible IDAT size, accounting + for height, rowbytes, interlacing and zlib/deflate overhead. + Restored png_get_eXIf_1() and png_set_eXIf_1(), because strlen(eXIf_buf) + does not work (the eXIf chunk data can contain zeroes). + +Version 1.6.32beta09 [August 3, 2017] + Require cmake-2.8.8 in CMakeLists.txt. Revised symlink creation, + no longer using deprecated cmake LOCATION feature (Clifford Yapp). + Fixed five-byte error in the calculation of IDAT maximum possible size. + +Version 1.6.32beta10 [August 5, 2017] + Moved chunk-length check into a png_check_chunk_length() private + function (Suggested by Max Stepin). + Moved bad pngs from tests to contrib/libtests/crashers + Moved testing of bad pngs into a separate tests/pngtest-badpngs script + Added the --xfail (expected FAIL) option to pngtest.c. It writes XFAIL + in the output but PASS for the libpng test. + Require cmake-3.0.2 in CMakeLists.txt (Clifford Yapp). + Fix "const" declaration info_ptr argument to png_get_eXIf_1() and the + num_exif argument to png_get_eXIf_1() (Github Issue 171). + +Version 1.6.32beta11 [August 7, 2017] + Added "eXIf" to "chunks_to_ignore[]" in png_set_keep_unknown_chunks(). + Added huge_IDAT.png and empty_ancillary_chunks.png to testpngs/crashers. + Make pngtest --strict, --relax, --xfail options imply -m (multiple). + Removed unused chunk_name parameter from png_check_chunk_length(). + Relocated setting free_me for eXIf data, to stop an OSS-fuzz leak. + Initialize profile_header[] in png_handle_iCCP() to fix OSS-fuzz issue. + Initialize png_ptr->row_buf[0] to 255 in png_read_row() to fix OSS-fuzz UMR. + Attempt to fix a UMR in png_set_text_2() to fix OSS-fuzz issue. + Increase minimum zlib stream from 9 to 14 in png_handle_iCCP(), to account + for the minimum 'deflate' stream, and relocate the test to a point + after the keyword has been read. + Check that the eXIf chunk has at least 2 bytes and begins with "II" or "MM". + +Version 1.6.32rc01 [August 18, 2017] + Added a set of "huge_xxxx_chunk.png" files to contrib/testpngs/crashers, + one for each known chunk type, with length = 2GB-1. + Check for 0 return from png_get_rowbytes() and added some (size_t) typecasts + in contrib/pngminus/*.c to stop some Coverity issues (162705, 162706, + and 162707). + Renamed chunks in contrib/testpngs/crashers to avoid having files whose + names differ only in case; this causes problems with some platforms + (github issue #172). + +Version 1.6.32rc02 [August 22, 2017] + Added contrib/oss-fuzz directory which contains files used by the oss-fuzz + project (https://github.com/google/oss-fuzz/tree/master/projects/libpng). + +Version 1.6.32 [August 24, 2017] + No changes. + +Version 1.6.33beta01 [August 28, 2017] + Added PNGMINUS_UNUSED macro to contrib/pngminus/p*.c and added missing + parenthesis in contrib/pngminus/pnm2png.c (bug report by Christian Hesse). + Fixed off-by-one error in png_do_check_palette_indexes() (Bug report + by Mick P., Source Forge Issue #269). + +Version 1.6.33beta02 [September 3, 2017] + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + to fix shortlived oss-fuzz issue 3234. + Compute a larger limit on IDAT because some applications write a deflate + buffer for each row (Bug report by Andrew Church). + Use current date (DATE) instead of release-date (RDATE) in last + changed date of contrib/oss-fuzz files. + Enabled ARM support in CMakeLists.txt (Bernd Kuhls). + +Version 1.6.33beta03 [September 14, 2017] + Fixed incorrect typecast of some arguments to png_malloc() and + png_calloc() that were png_uint_32 instead of png_alloc_size_t + (Bug report by "irwir" in Github libpng issue #175). + Use pnglibconf.h.prebuilt when building for ANDROID with cmake (Github + issue 162, by rcdailey). + +Version 1.6.33rc01 [September 20, 2017] + Initialize memory allocated by png_inflate to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in png_set_text_2() + due to truncated iTXt or zTXt chunk. + Initialize memory allocated by png_read_buffer to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in + png_icc_check_tag_table() due to truncated iCCP chunk. + Removed a redundant test (suggested by "irwir" in Github issue #180). + +Version 1.6.33rc02 [September 23, 2017] + Added an interlaced version of each file in contrib/pngsuite. + Relocate new memset() call in pngrutil.c. + Removed more redundant tests (suggested by "irwir" in Github issue #180). + Add support for loading images with associated alpha in the Simplified + API (Samuel Williams). + +Version 1.6.33 [September 28, 2017] + Revert contrib/oss-fuzz/libpng_read_fuzzer.cc to libpng-1.6.32 state. + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + Add end_info structure and png_read_end() to the libpng fuzzer. + +Version 1.6.34 [September 29, 2017] + Removed contrib/pngsuite/i*.png; some of them caused test failures. + +Version 1.6.35beta01 [March 6, 2018] + Restored 21 of the contrib/pngsuite/i*.png, which do not cause test + failures. Placed the remainder in contrib/pngsuite/interlaced/i*.png. + Added calls to png_set_*() transforms commonly used by browsers to + the fuzzer. + Removed some unnecessary brackets in pngrtran.c + Fixed miscellaneous typos (Patch by github user "luzpaz"). + Change "ASM C" to "C ASM" in CMakeLists.txt + Fixed incorrect handling of bKGD chunk in sub-8-bit files (Cosmin) + Added hardware optimization directories to zip and 7z distributions. + Fixed incorrect bitmask for options. + Fixed many spelling typos. + +Version 1.6.35beta02 [March 28, 2018] + Make png_get_iCCP consistent with man page (allow compression-type argument + to be NULL, bug report by Lenard Szolnoki). + +Version 1.6.35 [July 15, 2018] + Replaced the remaining uses of png_size_t with size_t (Cosmin) + Fixed the calculation of row_factor in png_check_chunk_length + (reported by Thuan Pham in SourceForge issue #278) + Added missing parentheses to a macro definition + (suggested by "irwir" in GitHub issue #216) + +Version 1.6.36 [December 1, 2018] + Optimized png_do_expand_palette for ARM processors. + Improved performance by around 10-22% on a recent ARM Chromebook. + (Contributed by Richard Townsend, ARM Holdings) + Fixed manipulation of machine-specific optimization options. + (Contributed by Vicki Pfau) + Used memcpy instead of manual pointer arithmetic on Intel SSE2. + (Contributed by Samuel Williams) + Fixed build errors with MSVC on ARM64. + (Contributed by Zhijie Liang) + Fixed detection of libm in CMakeLists. + (Contributed by Cameron Cawley) + Fixed incorrect creation of pkg-config file in CMakeLists. + (Contributed by Kyle Bentley) + Fixed the CMake build on Windows MSYS by avoiding symlinks. + Fixed a build warning on OpenBSD. + (Contributed by Theo Buehler) + Fixed various typos in comments. + (Contributed by "luz.paz") + Raised the minimum required CMake version from 3.0.2 to 3.1. + Removed yet more of the vestigial support for pre-ANSI C compilers. + Removed ancient makefiles for ancient systems that have been broken + across all previous libpng-1.6.x versions. + Removed the Y2K compliance statement and the export control + information. + Applied various code style and documentation fixes. + +Version 1.6.37 [April 14, 2019] + Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free. + Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette. + Fixed a memory leak in pngtest.c. + Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in + contrib/pngminus; refactor. + Changed the license of contrib/pngminus to MIT; refresh makefile and docs. + (Contributed by Willem van Schaik) + Fixed a typo in the libpng license v2. + (Contributed by Miguel Ojeda) + Added makefiles for AddressSanitizer-enabled builds. + Cleaned up various makefiles. + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net. +Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) -or to glennrp at users.sourceforge.net - -Glenn R-P -*/ +to subscribe. diff --git a/libs/libpng-src/CMakeLists.txt b/libs/libpng-src/CMakeLists.txt index a3ab4649b..6451fcf1b 100644 --- a/libs/libpng-src/CMakeLists.txt +++ b/libs/libpng-src/CMakeLists.txt @@ -1,106 +1,476 @@ -cmake_minimum_required(VERSION 2.4.3) -set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) +# CMakeLists.txt -if(UNIX AND NOT DEFINED CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING - "Choose the type of build, options are: - None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) - Debug - Release - RelWithDebInfo - MinSizeRel.") -endif() - -project(libpng C) -enable_testing() - -# Copyright (C) 2007-2010 Glenn Randers-Pehrson +# Copyright (C) 2018 Cosmin Truta +# Copyright (C) 2007,2009-2018 Glenn Randers-Pehrson +# Written by Christian Ehrlicher, 2007 +# Revised by Roger Lowman, 2009-2010 +# Revised by Clifford Yapp, 2011-2012,2017 +# Revised by Roger Leigh, 2016 +# Revised by Andreas Franek, 2016 +# Revised by Sam Serrels, 2017 +# Revised by Vadim Barkov, 2017 +# Revised by Vicky Pfau, 2018 +# Revised by Cameron Cawley, 2018 +# Revised by Cosmin Truta, 2018 +# Revised by Kyle Bentley, 2018 # This code is released under the libpng license. # For conditions of distribution and use, see the disclaimer # and license in png.h +cmake_minimum_required(VERSION 3.1) +cmake_policy(VERSION 3.1) + +project(libpng C ASM) +enable_testing() + set(PNGLIB_MAJOR 1) -set(PNGLIB_MINOR 2) -set(PNGLIB_RELEASE 46) +set(PNGLIB_MINOR 6) +set(PNGLIB_RELEASE 37) set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR}) set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE}) -# needed packages -find_package(ZLIB REQUIRED) -include_directories(${ZLIB_INCLUDE_DIR}) +include(GNUInstallDirs) -if(NOT WIN32) - find_library(M_LIBRARY - NAMES m - PATHS /usr/lib /usr/local/lib - ) - if(NOT M_LIBRARY) - message(STATUS - "math library 'libm' not found - floating point support disabled") - endif() +# needed packages + +# Allow users to specify location of Zlib. +# Useful if zlib is being built alongside this as a sub-project. +option(PNG_BUILD_ZLIB "Custom zlib Location, else find_package is used" OFF) + +if(NOT PNG_BUILD_ZLIB) + find_package(ZLIB REQUIRED) + include_directories(${ZLIB_INCLUDE_DIR}) +endif() + +if(UNIX AND NOT APPLE AND NOT BEOS AND NOT HAIKU) + find_library(M_LIBRARY m) else() - # not needed on windows + # libm is not needed and/or not available set(M_LIBRARY "") endif() # COMMAND LINE OPTIONS -if(DEFINED PNG_SHARED) - option(PNG_SHARED "Build shared lib" ${PNG_SHARED}) -else() - option(PNG_SHARED "Build shared lib" ON) -endif() -if(DEFINED PNG_STATIC) - option(PNG_STATIC "Build static lib" ${PNG_STATIC}) -else() - option(PNG_STATIC "Build static lib" ON) +option(PNG_SHARED "Build shared lib" ON) +option(PNG_STATIC "Build static lib" ON) +option(PNG_TESTS "Build libpng tests" ON) + +# Many more configuration options could be added here +option(PNG_FRAMEWORK "Build OS X framework" OFF) +option(PNG_DEBUG "Build with debug output" OFF) +option(PNG_HARDWARE_OPTIMIZATIONS "Enable hardware optimizations" ON) + +set(PNG_PREFIX "" CACHE STRING "Prefix to add to the API function names") +set(DFA_XTRA "" CACHE FILEPATH "File containing extra configuration settings") + +if(PNG_HARDWARE_OPTIMIZATIONS) + +# set definitions and sources for arm +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + set(PNG_ARM_NEON_POSSIBLE_VALUES check on off) + set(PNG_ARM_NEON "check" CACHE STRING "Enable ARM NEON optimizations: + check: (default) use internal checking code; + off: disable the optimizations; + on: turn on unconditionally.") + set_property(CACHE PNG_ARM_NEON PROPERTY STRINGS + ${PNG_ARM_NEON_POSSIBLE_VALUES}) + list(FIND PNG_ARM_NEON_POSSIBLE_VALUES ${PNG_ARM_NEON} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_ARM_NEON must be one of [${PNG_ARM_NEON_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_ARM_NEON} STREQUAL "off") + set(libpng_arm_sources + arm/arm_init.c + arm/filter_neon.S + arm/filter_neon_intrinsics.c + arm/palette_neon_intrinsics.c) + + if(${PNG_ARM_NEON} STREQUAL "on") + add_definitions(-DPNG_ARM_NEON_OPT=2) + elseif(${PNG_ARM_NEON} STREQUAL "check") + add_definitions(-DPNG_ARM_NEON_CHECK_SUPPORTED) + endif() + else() + add_definitions(-DPNG_ARM_NEON_OPT=0) + endif() endif() -if(MINGW) - option(PNG_TESTS "Build pngtest" NO) -else() - option(PNG_TESTS "Build pngtest" YES) +# set definitions and sources for powerpc +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*") + set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off) + set(PNG_POWERPC_VSX "on" CACHE STRING "Enable POWERPC VSX optimizations: + off: disable the optimizations.") + set_property(CACHE PNG_POWERPC_VSX PROPERTY STRINGS + ${PNG_POWERPC_VSX_POSSIBLE_VALUES}) + list(FIND PNG_POWERPC_VSX_POSSIBLE_VALUES ${PNG_POWERPC_VSX} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_POWERPC_VSX must be one of [${PNG_POWERPC_VSX_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_POWERPC_VSX} STREQUAL "off") + set(libpng_powerpc_sources + powerpc/powerpc_init.c + powerpc/filter_vsx_intrinsics.c) + if(${PNG_POWERPC_VSX} STREQUAL "on") + add_definitions(-DPNG_POWERPC_VSX_OPT=2) + endif() + else() + add_definitions(-DPNG_POWERPC_VSX_OPT=0) + endif() endif() -option(PNG_NO_CONSOLE_IO "FIXME" YES) -option(PNG_NO_STDIO "FIXME" YES) -option(PNG_DEBUG "Build with debug output" NO) -option(PNGARG "FIXME" YES) -#TODO: -# PNG_CONSOLE_IO_SUPPORTED - -# maybe needs improving, but currently I don't know when we can enable what :) -set(png_asm_tmp "OFF") -if(NOT WIN32) - find_program(uname_executable NAMES uname PATHS /bin /usr/bin /usr/local/bin) - if(uname_executable) - exec_program(${uname_executable} - ARGS --machine OUTPUT_VARIABLE uname_output) - if("uname_output" MATCHES "^.*i[1-9]86.*$") - set(png_asm_tmp "ON") - else("uname_output" MATCHES "^.*i[1-9]86.*$") - set(png_asm_tmp "OFF") - endif("uname_output" MATCHES "^.*i[1-9]86.*$") - endif(uname_executable) -else() - # this env var is normally only set on win64 - set(TEXT "ProgramFiles(x86)") - if("$ENV{${TEXT}}" STREQUAL "") - set(png_asm_tmp "ON") - endif("$ENV{${TEXT}}" STREQUAL "") +# set definitions and sources for intel +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*") + set(PNG_INTEL_SSE_POSSIBLE_VALUES on off) + set(PNG_INTEL_SSE "on" CACHE STRING "Enable INTEL_SSE optimizations: + off: disable the optimizations") + set_property(CACHE PNG_INTEL_SSE PROPERTY STRINGS + ${PNG_INTEL_SSE_POSSIBLE_VALUES}) + list(FIND PNG_INTEL_SSE_POSSIBLE_VALUES ${PNG_INTEL_SSE} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_INTEL_SSE must be one of [${PNG_INTEL_SSE_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_INTEL_SSE} STREQUAL "off") + set(libpng_intel_sources + intel/intel_init.c + intel/filter_sse2_intrinsics.c) + if(${PNG_INTEL_SSE} STREQUAL "on") + add_definitions(-DPNG_INTEL_SSE_OPT=1) + endif() + else() + add_definitions(-DPNG_INTEL_SSE_OPT=0) + endif() endif() +# set definitions and sources for MIPS +if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*") + set(PNG_MIPS_MSA_POSSIBLE_VALUES on off) + set(PNG_MIPS_MSA "on" CACHE STRING "Enable MIPS_MSA optimizations: + off: disable the optimizations") + set_property(CACHE PNG_MIPS_MSA PROPERTY STRINGS + ${PNG_MIPS_MSA_POSSIBLE_VALUES}) + list(FIND PNG_MIPS_MSA_POSSIBLE_VALUES ${PNG_MIPS_MSA} index) + if(index EQUAL -1) + message(FATAL_ERROR + "PNG_MIPS_MSA must be one of [${PNG_MIPS_MSA_POSSIBLE_VALUES}]") + elseif(NOT ${PNG_MIPS_MSA} STREQUAL "off") + set(libpng_mips_sources + mips/mips_init.c + mips/filter_msa_intrinsics.c) + if(${PNG_MIPS_MSA} STREQUAL "on") + add_definitions(-DPNG_MIPS_MSA_OPT=2) + endif() + else() + add_definitions(-DPNG_MIPS_MSA_OPT=0) + endif() +endif() + +else(PNG_HARDWARE_OPTIMIZATIONS) + +# set definitions and sources for arm +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64") + add_definitions(-DPNG_ARM_NEON_OPT=0) +endif() + +# set definitions and sources for powerpc +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^powerpc*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^ppc64*") + add_definitions(-DPNG_POWERPC_VSX_OPT=0) +endif() + +# set definitions and sources for intel +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^i?86" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64*") + add_definitions(-DPNG_INTEL_SSE_OPT=0) +endif() + +# set definitions and sources for MIPS +if(CMAKE_SYSTEM_PROCESSOR MATCHES "mipsel*" OR + CMAKE_SYSTEM_PROCESSOR MATCHES "mips64el*") + add_definitions(-DPNG_MIPS_MSA_OPT=0) +endif() + +endif(PNG_HARDWARE_OPTIMIZATIONS) + # SET LIBNAME set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR}) # to distinguish between debug and release lib set(CMAKE_DEBUG_POSTFIX "d") +include(CheckCSourceCompiles) +option(ld-version-script "Enable linker version script" ON) +if(ld-version-script AND NOT APPLE) + # Check if LD supports linker scripts. + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "VERS_1 { + global: sym; + local: *; +}; + +VERS_2 { + global: sym2; + main; +} VERS_1; +") + set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS}) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/conftest.map'") + check_c_source_compiles("void sym(void) {} +void sym2(void) {} +int main(void) {return 0;} +" HAVE_LD_VERSION_SCRIPT) + if(NOT HAVE_LD_VERSION_SCRIPT) + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE} "-Wl,-M -Wl,${CMAKE_CURRENT_BINARY_DIR}/conftest.map") + check_c_source_compiles("void sym(void) {} +void sym2(void) {} +int main(void) {return 0;} +" HAVE_SOLARIS_LD_VERSION_SCRIPT) + endif() + set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE}) + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map") +endif() + +# Find symbol prefix. Likely obsolete and unnecessary with recent +# toolchains (it's not done in many other projects). +function(symbol_prefix) + set(SYMBOL_PREFIX) + + execute_process(COMMAND "${CMAKE_C_COMPILER}" "-E" "-" + INPUT_FILE /dev/null + OUTPUT_VARIABLE OUT + RESULT_VARIABLE STATUS) + + if(CPP_FAIL) + message(WARNING "Failed to run the C preprocessor") + endif() + + string(REPLACE "\n" ";" OUT "${OUT}") + foreach(line ${OUT}) + string(REGEX MATCH "^PREFIX=" found_match "${line}") + if(found_match) + string(REGEX REPLACE "^PREFIX=(.*\)" "\\1" prefix "${line}") + string(REGEX MATCH "__USER_LABEL_PREFIX__" found_match "${prefix}") + if(found_match) + string(REGEX REPLACE "(.*)__USER_LABEL_PREFIX__(.*)" "\\1\\2" prefix "${prefix}") + endif() + set(SYMBOL_PREFIX "${prefix}") + endif() + endforeach() + + message(STATUS "Symbol prefix: ${SYMBOL_PREFIX}") + set(SYMBOL_PREFIX "${SYMBOL_PREFIX}" PARENT_SCOPE) +endfunction() + +if(UNIX) + symbol_prefix() +endif() + +find_program(AWK NAMES gawk awk) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +if(NOT AWK OR ANDROID) + # No awk available to generate sources; use pre-built pnglibconf.h + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt + ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h) + add_custom_target(genfiles) # Dummy +else() + include(CMakeParseArguments) + # Generate .chk from .out with awk + # generate_chk(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]]) + function(generate_chk) + set(options) + set(oneValueArgs INPUT OUTPUT) + set(multiValueArgs DEPENDS) + cmake_parse_arguments(_GC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(NOT _GC_INPUT) + message(FATAL_ERROR "generate_chk: Missing INPUT argument") + endif() + if(NOT _GC_OUTPUT) + message(FATAL_ERROR "generate_chk: Missing OUTPUT argument") + endif() + + add_custom_command(OUTPUT "${_GC_OUTPUT}" + COMMAND "${CMAKE_COMMAND}" + "-DINPUT=${_GC_INPUT}" + "-DOUTPUT=${_GC_OUTPUT}" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake" + DEPENDS "${_GC_INPUT}" ${_GC_DEPENDS} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endfunction() + + # Generate .out from .c with awk + # generate_out(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]]) + function(generate_out) + set(options) + set(oneValueArgs INPUT OUTPUT) + set(multiValueArgs DEPENDS) + cmake_parse_arguments(_GO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(NOT _GO_INPUT) + message(FATAL_ERROR "generate_out: Missing INPUT argument") + endif() + if(NOT _GO_OUTPUT) + message(FATAL_ERROR "generate_out: Missing OUTPUT argument") + endif() + + add_custom_command(OUTPUT "${_GO_OUTPUT}" + COMMAND "${CMAKE_COMMAND}" + "-DINPUT=${_GO_INPUT}" + "-DOUTPUT=${_GO_OUTPUT}" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake" + DEPENDS "${_GO_INPUT}" ${_GO_DEPENDS} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endfunction() + + # Generate specific source file with awk + # generate_source(OUTPUT outputfile [DEPENDS dep1 [dep2...]]) + function(generate_source) + set(options) + set(oneValueArgs OUTPUT) + set(multiValueArgs DEPENDS) + cmake_parse_arguments(_GSO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + if(NOT _GSO_OUTPUT) + message(FATAL_ERROR "generate_source: Missing OUTPUT argument") + endif() + + add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_GSO_OUTPUT}" + COMMAND "${CMAKE_COMMAND}" + "-DOUTPUT=${_GSO_OUTPUT}" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake" + DEPENDS ${_GSO_DEPENDS} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endfunction() + + # Copy file + function(generate_copy source destination) + add_custom_command(OUTPUT "${destination}" + COMMAND "${CMAKE_COMMAND}" -E remove "${destination}" + COMMAND "${CMAKE_COMMAND}" -E copy "${source}" + "${destination}" + DEPENDS "${source}") + endfunction() + + # Generate scripts/pnglibconf.h + generate_source(OUTPUT "scripts/pnglibconf.c" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h") + + # Generate pnglibconf.c + generate_source(OUTPUT "pnglibconf.c" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h") + + if(PNG_PREFIX) + set(PNGLIBCONF_H_EXTRA_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/macro.lst") + set(PNGPREFIX_H_EXTRA_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out") + endif() + + generate_out(INPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out") + + # Generate pnglibconf.h + generate_source(OUTPUT "pnglibconf.h" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" + ${PNGLIBCONF_H_EXTRA_DEPENDS}) + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/intprefix.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/prefix.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out") + + # Generate pngprefix.h + generate_source(OUTPUT "pngprefix.h" + DEPENDS ${PNGPREFIX_H_EXTRA_DEPENDS}) + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/sym.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/vers.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_chk(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/checksym.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def") + + add_custom_target(symbol-check DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk") + + generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out" + "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym") + generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out" + "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers") + + add_custom_target(genvers DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers") + add_custom_target(gensym DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym") + + add_custom_target("genprebuilt" + COMMAND "${CMAKE_COMMAND}" + "-DOUTPUT=scripts/pnglibconf.h.prebuilt" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + + # A single target handles generation of all generated files. If + # they are depended upon separately by multiple targets, this + # confuses parallel make (it would require a separate top-level + # target for each file to track the dependencies properly). + add_custom_target(genfiles DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym" + "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" + "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out") +endif(NOT AWK OR ANDROID) # OUR SOURCES -set(libpng_sources +set(libpng_public_hdrs png.h pngconf.h + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" +) +set(libpng_private_hdrs + pngpriv.h + pngdebug.h + pnginfo.h + pngstruct.h +) +if(AWK AND NOT ANDROID) + list(APPEND libpng_private_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h") +endif() +set(libpng_sources + ${libpng_public_hdrs} + ${libpng_private_hdrs} png.c pngerror.c pngget.c @@ -116,169 +486,446 @@ set(libpng_sources pngwrite.c pngwtran.c pngwutil.c + ${libpng_arm_sources} + ${libpng_intel_sources} + ${libpng_mips_sources} + ${libpng_powerpc_sources} ) set(pngtest_sources pngtest.c ) -# SOME NEEDED DEFINITIONS - -add_definitions(-DPNG_CONFIGURE_LIBPNG) - -if(_AIX) - add_definitions(-D_ALL_SOURCE) -endif(_AIX) +set(pngvalid_sources + contrib/libtests/pngvalid.c +) +set(pngstest_sources + contrib/libtests/pngstest.c +) +set(pngunknown_sources + contrib/libtests/pngunknown.c +) +set(pngimage_sources + contrib/libtests/pngimage.c +) +set(pngfix_sources + contrib/tools/pngfix.c +) +set(png_fix_itxt_sources + contrib/tools/png-fix-itxt.c +) if(MSVC) - add_definitions(-DPNG_NO_MODULEDEF -D_CRT_SECURE_NO_DEPRECATE) -endif(MSVC) - -if(PNG_SHARED OR NOT MSVC) - #if building msvc static this has NOT to be defined - add_definitions(-DZLIB_DLL) -endif() - -add_definitions(-DLIBPNG_NO_MMX) -add_definitions(-DPNG_NO_MMX_CODE) - - -if(PNG_CONSOLE_IO_SUPPORTED) - add_definitions(-DPNG_CONSOLE_IO_SUPPORTED) -endif() - -if(PNG_NO_CONSOLE_IO) - add_definitions(-DPNG_NO_CONSOLE_IO) -endif() - -if(PNG_NO_STDIO) - add_definitions(-DPNG_NO_STDIO) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) endif() if(PNG_DEBUG) add_definitions(-DPNG_DEBUG) endif() -if(NOT M_LIBRARY AND NOT WIN32) - add_definitions(-DPNG_NO_FLOATING_POINT_SUPPORTED) -endif() - # NOW BUILD OUR TARGET include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${ZLIB_INCLUDE_DIR}) +unset(PNG_LIB_TARGETS) + if(PNG_SHARED) - add_library(${PNG_LIB_NAME} SHARED ${libpng_sources}) + add_library(png SHARED ${libpng_sources}) + set(PNG_LIB_TARGETS png) + set_target_properties(png PROPERTIES OUTPUT_NAME ${PNG_LIB_NAME}) + add_dependencies(png genfiles) if(MSVC) # msvc does not append 'lib' - do it here to have consistent name - set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib") + set_target_properties(png PROPERTIES PREFIX "lib") + set_target_properties(png PROPERTIES IMPORT_PREFIX "lib") + endif() + target_link_libraries(png ${ZLIB_LIBRARY} ${M_LIBRARY}) + + if(UNIX AND AWK) + if(HAVE_LD_VERSION_SCRIPT) + set_target_properties(png PROPERTIES LINK_FLAGS + "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'") + elseif(HAVE_SOLARIS_LD_VERSION_SCRIPT) + set_target_properties(png PROPERTIES LINK_FLAGS + "-Wl,-M -Wl,'${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'") + endif() endif() - target_link_libraries(${PNG_LIB_NAME} ${ZLIB_LIBRARY} ${M_LIBRARY}) endif() if(PNG_STATIC) -# does not work without changing name - set(PNG_LIB_NAME_STATIC ${PNG_LIB_NAME}_static) - add_library(${PNG_LIB_NAME_STATIC} STATIC ${libpng_sources}) + # does not work without changing name + set(PNG_LIB_NAME_STATIC png_static) + add_library(png_static STATIC ${libpng_sources}) + add_dependencies(png_static genfiles) + # MSVC doesn't use a different file extension for shared vs. static + # libs. We are able to change OUTPUT_NAME to remove the _static + # for all other platforms. + if(NOT MSVC) + set_target_properties(png_static PROPERTIES + OUTPUT_NAME "${PNG_LIB_NAME}" + CLEAN_DIRECT_OUTPUT 1) + else() + set_target_properties(png_static PROPERTIES + OUTPUT_NAME "${PNG_LIB_NAME}_static" + CLEAN_DIRECT_OUTPUT 1) + endif() + list(APPEND PNG_LIB_TARGETS png_static) if(MSVC) # msvc does not append 'lib' - do it here to have consistent name - set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib") + set_target_properties(png_static PROPERTIES PREFIX "lib") endif() + target_link_libraries(png_static ${ZLIB_LIBRARY} ${M_LIBRARY}) endif() +if(PNG_FRAMEWORK) + set(PNG_LIB_NAME_FRAMEWORK png_framework) + add_library(png_framework SHARED ${libpng_sources}) + add_dependencies(png_framework genfiles) + list(APPEND PNG_LIB_TARGETS png_framework) + set_target_properties(png_framework PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION ${PNGLIB_VERSION} + MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PNGLIB_MAJOR}.${PNGLIB_MINOR} + MACOSX_FRAMEWORK_BUNDLE_VERSION ${PNGLIB_VERSION} + MACOSX_FRAMEWORK_IDENTIFIER org.libpng.libpng + XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" + PUBLIC_HEADER "${libpng_public_hdrs}" + OUTPUT_NAME png) + target_link_libraries(png_framework ${ZLIB_LIBRARY} ${M_LIBRARY}) +endif() + +if(NOT PNG_LIB_TARGETS) + message(SEND_ERROR + "No library variant selected to build. " + "Please enable at least one of the following options: " + "PNG_STATIC, PNG_SHARED, PNG_FRAMEWORK") +endif() if(PNG_SHARED AND WIN32) - set_target_properties(${PNG_LIB_NAME} PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL) + set_target_properties(png PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL) endif() +function(png_add_test) + set(options) + set(oneValueArgs NAME COMMAND) + set(multiValueArgs OPTIONS FILES) + cmake_parse_arguments(_PAT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if(NOT _PAT_NAME) + message(FATAL_ERROR "png_add_test: Missing NAME argument") + endif() + if(NOT _PAT_COMMAND) + message(FATAL_ERROR "png_add_test: Missing COMMAND argument") + endif() + + set(TEST_OPTIONS "${_PAT_OPTIONS}") + set(TEST_FILES "${_PAT_FILES}") + + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/test.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake" @ONLY) + add_test(NAME "${_PAT_NAME}" + COMMAND "${CMAKE_COMMAND}" + "-DLIBPNG=$" + "-DTEST_COMMAND=$" + -P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake") +endfunction() + if(PNG_TESTS AND PNG_SHARED) - # does not work with msvc due to png_lib_ver issue + # Find test PNG files by globbing, but sort lists to ensure + # consistency between different filesystems. + file(GLOB PNGSUITE_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/*.png") + list(SORT PNGSUITE_PNGS) + file(GLOB TEST_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/*.png") + list(SORT TEST_PNGS) + + set(PNGTEST_PNG "${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png") + add_executable(pngtest ${pngtest_sources}) - target_link_libraries(pngtest ${PNG_LIB_NAME}) - add_test(pngtest pngtest ${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png) + target_link_libraries(pngtest png) + + png_add_test(NAME pngtest COMMAND pngtest FILES "${PNGTEST_PNG}") + + add_executable(pngvalid ${pngvalid_sources}) + target_link_libraries(pngvalid png) + + png_add_test(NAME pngvalid-gamma-16-to-8 + COMMAND pngvalid OPTIONS --gamma-16-to-8) + png_add_test(NAME pngvalid-gamma-alpha-mode + COMMAND pngvalid OPTIONS --gamma-alpha-mode) + png_add_test(NAME pngvalid-gamma-background + COMMAND pngvalid OPTIONS --gamma-background) + png_add_test(NAME pngvalid-gamma-expand16-alpha-mode + COMMAND pngvalid OPTIONS --gamma-alpha-mode --expand16) + png_add_test(NAME pngvalid-gamma-expand16-background + COMMAND pngvalid OPTIONS --gamma-background --expand16) + png_add_test(NAME pngvalid-gamma-expand16-transform + COMMAND pngvalid OPTIONS --gamma-transform --expand16) + png_add_test(NAME pngvalid-gamma-sbit + COMMAND pngvalid OPTIONS --gamma-sbit) + png_add_test(NAME pngvalid-gamma-threshold + COMMAND pngvalid OPTIONS --gamma-threshold) + png_add_test(NAME pngvalid-gamma-transform + COMMAND pngvalid OPTIONS --gamma-transform) + png_add_test(NAME pngvalid-progressive-interlace-standard + COMMAND pngvalid OPTIONS --standard --progressive-read --interlace) + png_add_test(NAME pngvalid-progressive-size + COMMAND pngvalid OPTIONS --size --progressive-read) + png_add_test(NAME pngvalid-progressive-standard + COMMAND pngvalid OPTIONS --standard --progressive-read) + png_add_test(NAME pngvalid-standard + COMMAND pngvalid OPTIONS --standard) + png_add_test(NAME pngvalid-transform + COMMAND pngvalid OPTIONS --transform) + + add_executable(pngstest ${pngstest_sources}) + target_link_libraries(pngstest png) + + foreach(gamma_type 1.8 linear none sRGB) + foreach(alpha_type none alpha) + set(PNGSTEST_FILES) + foreach(test_png ${TEST_PNGS}) + string(REGEX MATCH ".*-linear[-.].*" TEST_PNG_LINEAR "${test_png}") + string(REGEX MATCH ".*-sRGB[-.].*" TEST_PNG_SRGB "${test_png}") + string(REGEX MATCH ".*-1.8[-.].*" TEST_PNG_G18 "${test_png}") + string(REGEX MATCH ".*-alpha-.*" TEST_PNG_ALPHA "${test_png}") + + set(TEST_PNG_VALID TRUE) + + if(TEST_PNG_ALPHA) + if(NOT "${alpha_type}" STREQUAL "alpha") + set(TEST_PNG_VALID FALSE) + endif() + else() + if("${alpha_type}" STREQUAL "alpha") + set(TEST_PNG_VALID FALSE) + endif() + endif() + + if(TEST_PNG_LINEAR) + if(NOT "${gamma_type}" STREQUAL "linear") + set(TEST_PNG_VALID FALSE) + endif() + elseif(TEST_PNG_SRGB) + if(NOT "${gamma_type}" STREQUAL "sRGB") + set(TEST_PNG_VALID FALSE) + endif() + elseif(TEST_PNG_G18) + if(NOT "${gamma_type}" STREQUAL "1.8") + set(TEST_PNG_VALID FALSE) + endif() + else() + if(NOT "${gamma_type}" STREQUAL "none") + set(TEST_PNG_VALID FALSE) + endif() + endif() + + if(TEST_PNG_VALID) + list(APPEND PNGSTEST_FILES "${test_png}") + endif() + endforeach() + # Should already be sorted, but sort anyway to be certain. + list(SORT PNGSTEST_FILES) + png_add_test(NAME pngstest-${gamma_type}-${alpha_type} + COMMAND pngstest + OPTIONS --tmpfile "${gamma_type}-${alpha_type}-" --log + FILES ${PNGSTEST_FILES}) + endforeach() + endforeach() + + add_executable(pngunknown ${pngunknown_sources}) + target_link_libraries(pngunknown png) + + png_add_test(NAME pngunknown-discard COMMAND pngunknown OPTIONS --strict default=discard FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-IDAT COMMAND pngunknown OPTIONS --strict default=discard IDAT=save FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-if-safe COMMAND pngunknown OPTIONS --strict default=if-safe FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-sAPI COMMAND pngunknown OPTIONS --strict bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-save COMMAND pngunknown OPTIONS --strict default=save FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-sTER COMMAND pngunknown OPTIONS --strict sTER=if-safe FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-vpAg COMMAND pngunknown OPTIONS --strict vpAg=if-safe FILES "${PNGTEST_PNG}") + + add_executable(pngimage ${pngimage_sources}) + target_link_libraries(pngimage png) + + png_add_test(NAME pngimage-quick COMMAND pngimage OPTIONS --list-combos --log FILES ${PNGSUITE_PNGS}) + png_add_test(NAME pngimage-full COMMAND pngimage OPTIONS --exhaustive --list-combos --log FILES ${PNGSUITE_PNGS}) endif() +if(PNG_SHARED) + add_executable(pngfix ${pngfix_sources}) + target_link_libraries(pngfix png) + set(PNG_BIN_TARGETS pngfix) + + add_executable(png-fix-itxt ${png_fix_itxt_sources}) + target_link_libraries(png-fix-itxt ${ZLIB_LIBRARY} ${M_LIBRARY}) + list(APPEND PNG_BIN_TARGETS png-fix-itxt) +endif() + +# Set a variable with CMake code which: +# Creates a symlink from src to dest (if possible) or alternatively +# copies if different. +include(CMakeParseArguments) + +function(create_symlink DEST_FILE) + + cmake_parse_arguments(S "" "FILE;TARGET" "" ${ARGN}) + + if(NOT S_TARGET AND NOT S_FILE) + message(FATAL_ERROR "create_symlink: Missing TARGET or FILE argument") + endif() + + if(S_TARGET AND S_FILE) + message(FATAL_ERROR "create_symlink: Both source file ${S_FILE} and build target ${S_TARGET} arguments are present; can only have one.") + endif() + + if(S_FILE) + # If we don't need to symlink something that's coming from a build target, + # we can go ahead and symlink/copy at configure time. + if(CMAKE_HOST_WIN32 AND NOT CYGWIN) + execute_process( + COMMAND "${CMAKE_COMMAND}" -E copy_if_different ${S_FILE} ${DEST_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + else() + execute_process( + COMMAND ${CMAKE_COMMAND} -E create_symlink ${S_FILE} ${DEST_FILE} + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + endif() + + if(S_TARGET) + # We need to use generator expressions, which can be a bit tricky, so for + # simplicity make the symlink a POST_BUILD step and use the TARGET + # signature of add_custom_command. + if(CMAKE_HOST_WIN32 AND NOT CYGWIN) + add_custom_command(TARGET ${S_TARGET} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E copy_if_different $ $/${DEST_FILE}) + else() + add_custom_command(TARGET ${S_TARGET} POST_BUILD + COMMAND "${CMAKE_COMMAND}" -E create_symlink $ $/${DEST_FILE}) + endif() + endif() + +endfunction() + +# Create source generation scripts. +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genchk.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genout.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake @ONLY) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/gensrc.cmake.in + ${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake @ONLY) + +# libpng is a library so default to 'lib' +if(NOT DEFINED CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR lib) +endif() # CREATE PKGCONFIG FILES -# we use the same files like ./configure, so we have to set its vars -set(prefix ${CMAKE_INSTALL_PREFIX}) -set(exec_prefix ${CMAKE_INSTALL_PREFIX}) -set(libdir ${CMAKE_INSTALL_PREFIX}/lib) -set(includedir ${CMAKE_INSTALL_PREFIX}/include) +# We use the same files like ./configure, so we have to set its vars. +# Only do this on Windows for Cygwin - the files don't make much sense outside +# of a UNIX look-alike. +if(NOT WIN32 OR CYGWIN OR MINGW) + set(prefix ${CMAKE_INSTALL_PREFIX}) + set(exec_prefix ${CMAKE_INSTALL_PREFIX}) + set(libdir ${CMAKE_INSTALL_FULL_LIBDIR}) + set(includedir ${CMAKE_INSTALL_FULL_INCLUDEDIR}) + set(LIBS "-lz -lm") + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc @ONLY) + create_symlink(libpng.pc FILE ${PNGLIB_NAME}.pc) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/libpng.pc.in - ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/libpng-config.in - ${CMAKE_CURRENT_BINARY_DIR}/libpng-config) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/libpng.pc.in - ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/libpng-config.in - ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/libpng-config.in + ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config @ONLY) + create_symlink(libpng-config FILE ${PNGLIB_NAME}-config) +endif() # SET UP LINKS if(PNG_SHARED) - set_target_properties(${PNG_LIB_NAME} PROPERTIES -# VERSION 0.${PNGLIB_RELEASE}.1.2.46 - VERSION 0.${PNGLIB_RELEASE}.0 - SOVERSION 0 + set_target_properties(png PROPERTIES +# VERSION 16.${PNGLIB_RELEASE}.1.6.37 + VERSION 16.${PNGLIB_RELEASE}.0 + SOVERSION 16 CLEAN_DIRECT_OUTPUT 1) endif() -if(PNG_STATIC) - if(NOT WIN32) - # that's uncool on win32 - it overwrites our static import lib... - set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES - OUTPUT_NAME ${PNG_LIB_NAME} - CLEAN_DIRECT_OUTPUT 1) - endif() -endif() # INSTALL -if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL ) +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PNG_LIB_TARGETS} + EXPORT libpng + RUNTIME DESTINATION bin + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR}) + if(PNG_SHARED) - install(TARGETS ${PNG_LIB_NAME} - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) + # Create a symlink for libpng.dll.a => libpng16.dll.a on Cygwin + if(CYGWIN OR MINGW) + create_symlink(libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} TARGET png) + install(FILES $/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() + + if(NOT WIN32) + create_symlink(libpng${CMAKE_SHARED_LIBRARY_SUFFIX} TARGET png) + install(FILES $/libpng${CMAKE_SHARED_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() endif() + if(PNG_STATIC) - install(TARGETS ${PNG_LIB_NAME_STATIC} - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib) + if(NOT WIN32 OR CYGWIN OR MINGW) + create_symlink(libpng${CMAKE_STATIC_LIBRARY_SUFFIX} TARGET png_static) + install(FILES $/libpng${CMAKE_STATIC_LIBRARY_SUFFIX} + DESTINATION ${CMAKE_INSTALL_LIBDIR}) + endif() endif() endif() -if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL ) - install(FILES png.h pngconf.h DESTINATION include) - install(FILES png.h pngconf.h DESTINATION include/${PNGLIB_NAME}) +if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) + install(FILES ${libpng_public_hdrs} DESTINATION include) + install(FILES ${libpng_public_hdrs} DESTINATION include/${PNGLIB_NAME}) endif() -if(NOT SKIP_INSTALL_EXECUTABLES AND NOT SKIP_INSTALL_ALL ) - install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config DESTINATION bin) - install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config - DESTINATION bin) +if(NOT SKIP_INSTALL_EXECUTABLES AND NOT SKIP_INSTALL_ALL) + if(NOT WIN32 OR CYGWIN OR MINGW) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config DESTINATION bin) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config DESTINATION bin) + endif() endif() -if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL ) + +if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PNG_BIN_TARGETS} + RUNTIME DESTINATION bin) +endif() + +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL) # Install man pages - install(FILES libpng.3 libpngpf.3 DESTINATION man/man3) - install(FILES png.5 DESTINATION man/man5) + if(NOT PNG_MAN_DIR) + set(PNG_MAN_DIR "share/man") + endif() + install(FILES libpng.3 libpngpf.3 DESTINATION ${PNG_MAN_DIR}/man3) + install(FILES png.5 DESTINATION ${PNG_MAN_DIR}/man5) # Install pkg-config files - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc - DESTINATION lib/pkgconfig) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng-config - DESTINATION bin) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc - DESTINATION lib/pkgconfig) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config - DESTINATION bin) + if(NOT CMAKE_HOST_WIN32 OR CYGWIN OR MINGW) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/libpng-config + DESTINATION bin) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/${PNGLIB_NAME}-config + DESTINATION bin) + endif() endif() -# what's with libpng.txt and all the extra files? +# Create an export file that CMake users can include() to import our targets. +if(NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL) + install(EXPORT libpng DESTINATION lib/libpng FILE lib${PNG_LIB_NAME}.cmake) +endif() +# what's with libpng-manual.txt and all the extra files? # UNINSTALL # do we need this? - # DIST # do we need this? # to create msvc import lib for mingw compiled shared lib # pexports libpng.dll > libpng.def # lib /def:libpng.def /machine:x86 - diff --git a/libs/libpng-src/INSTALL b/libs/libpng-src/INSTALL index 99e5ccc2a..4c1702251 100644 --- a/libs/libpng-src/INSTALL +++ b/libs/libpng-src/INSTALL @@ -1,5 +1,28 @@ -Installing libpng version 1.2.46 - July 9, 2011 + Installing libpng + +Contents + + I. Simple installation + II. Rebuilding the configure scripts + III. Using scripts/makefile* + IV. Using cmake + V. Directory structure + VI. Building with project files + VII. Building with makefiles + VIII. Configuring libpng for 16-bit platforms + IX. Configuring for DOS + X. Configuring for Medium Model + XI. Prepending a prefix to exported symbols + XII. Configuring for compiler xxx: + XIII. Removing unwanted object code + XIV. Enabling or disabling hardware optimizations + XV. Changes to the build and configuration of libpng in libpng-1.5.x + XVI. Setjmp/longjmp issues + XVII. Common linking failures + XVIII. Other sources of information about libpng + +I. Simple installation On Unix/Linux and similar systems, you can simply type @@ -7,20 +30,44 @@ On Unix/Linux and similar systems, you can simply type make check make install -and ignore the rest of this document. +and ignore the rest of this document. "/path" is the path to the directory +where you want to install the libpng "lib", "include", and "bin" +subdirectories. -If configure does not work on your system and you have a reasonably -up-to-date set of tools, running ./autogen.sh before running ./configure -may fix the problem. You can also run the individual commands in -autogen.sh with the --force option, if supported by your version of -the tools. If you run 'libtoolize --force', though, this will replace -the distributed, patched, version of ltmain.sh with an unpatched version -and your shared library builds may fail to produce libraries with the -correct version numbers. +If you downloaded a GIT clone, you will need to run ./autogen.sh before +running ./configure, to create "configure" and "Makefile.in" which are +not included in the GIT repository. + +Note that "configure" is only included in the "*.tar" distributions and not +in the "*.zip" or "*.7z" distributions. If you downloaded one of those +distributions, see "Building with project files" or "Building with makefiles", +below. + +II. Rebuilding the configure scripts + +If configure does not work on your system, or if you have a need to +change configure.ac or Makefile.am, and you have a reasonably +up-to-date set of tools, running ./autogen.sh in a git clone before +running ./configure may fix the problem. To be really sure that you +aren't using any of the included pre-built scripts, especially if you +are building from a tar distribution instead of a git distribution, +do this: + + ./configure --enable-maintainer-mode + make maintainer-clean + ./autogen.sh --maintainer --clean + ./autogen.sh --maintainer + ./configure [--prefix=/path] [other options] + make + make install + make check + +III. Using scripts/makefile* Instead, you can use one of the custom-built makefiles in the "scripts" directory + cp scripts/pnglibconf.h.prebuilt pnglibconf.h cp scripts/makefile.system makefile make test make install @@ -32,82 +79,107 @@ Or you can use one of the "projects" in the "projects" directory. Before installing libpng, you must first install zlib, if it is not already on your system. zlib can usually be found -wherever you got libpng. zlib can be placed in another directory, -at the same level as libpng. - -If you want to use "cmake" (see www.cmake.org), type - - cmake . -DCMAKE_INSTALL_PREFIX=/path - make - make install +wherever you got libpng; otherwise go to https://zlib.net/. You can +place zlib in the same directory as libpng or in another directory. If your system already has a preinstalled zlib you will still need to have access to the zlib.h and zconf.h include files that correspond to the version of zlib that's installed. +If you wish to test with a particular zlib that is not first in the +standard library search path, put ZLIBLIB, ZLIBINC, CPPFLAGS, LDFLAGS, +and LD_LIBRARY_PATH in your environment before running "make test" +or "make distcheck": + + ZLIBLIB=/path/to/lib export ZLIBLIB + ZLIBINC=/path/to/include export ZLIBINC + CPPFLAGS="-I$ZLIBINC" export CPPFLAGS + LDFLAGS="-L$ZLIBLIB" export LDFLAGS + LD_LIBRARY_PATH="$ZLIBLIB:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH + +If you are using one of the makefile scripts, put ZLIBLIB and ZLIBINC +in your environment and type + + make ZLIBLIB=$ZLIBLIB ZLIBINC=$ZLIBINC test + +IV. Using cmake + +If you want to use "cmake" (see www.cmake.org), type + + cmake . -DCMAKE_INSTALL_PREFIX=/path + make + make install + +As when using the simple configure method described above, "/path" points to +the installation directory where you want to put the libpng "lib", "include", +and "bin" subdirectories. + +V. Directory structure + You can rename the directories that you downloaded (they -might be called "libpng-1.2.46" or "libpng12" and "zlib-1.2.3" -or "zlib123") so that you have directories called "zlib" and "libpng". +might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.8" +or "zlib128") so that you have directories called "zlib" and "libpng". Your directory structure should look like this: - .. (the parent directory) - libpng (this directory) + .. (the parent directory) + libpng (this directory) INSTALL (this file) README - *.h - *.c + *.h, *.c => libpng source files CMakeLists.txt => "cmake" script configuration files: configure.ac, configure, Makefile.am, Makefile.in, - autogen.sh, config.guess, ltmain.sh, missing, - aclocal.m4, config.h.in, config.sub, + autogen.sh, config.guess, ltmain.sh, missing, libpng.pc.in, + libpng-config.in, aclocal.m4, config.h.in, config.sub, depcomp, install-sh, mkinstalldirs, test-pngtest.sh contrib - gregbook - pngminim - pngminus - pngsuite - visupng + arm-neon, conftest, examples, gregbook, libtests, pngminim, + pngminus, pngsuite, tools, visupng projects - cbuilder5 (Borland) - visualc6 (msvc) - visualc71 - xcode + cbuilder5, owatcom, visualc71, vstudio, xcode scripts makefile.* *.def (module definition files) + etc. pngtest.png etc. zlib - README - *.h - *.c - contrib - etc. + README, *.h, *.c contrib, etc. If the line endings in the files look funny, you may wish to get the other distribution of libpng. It is available in both tar.gz (UNIX style line endings) and zip (DOS style line endings) formats. +VI. Building with project files + If you are building libpng with MSVC, you can enter the -libpng projects\visualc6 or visualc71 directory and follow the instructions +libpng projects\visualc71 or vstudio directory and follow the instructions in README.txt. Otherwise enter the zlib directory and follow the instructions in zlib/README, then come back here and run "configure" or choose the appropriate makefile.sys in the scripts directory. +VII. Building with makefiles + Copy the file (or files) that you need from the scripts directory into this directory, for example - MSDOS example: copy scripts\makefile.msc makefile - UNIX example: cp scripts/makefile.std makefile +MSDOS example: + + copy scripts\makefile.msc makefile + copy scripts\pnglibconf.h.prebuilt pnglibconf.h + +UNIX example: + + cp scripts/makefile.std makefile + cp scripts/pnglibconf.h.prebuilt pnglibconf.h Read the makefile to see if you need to change any source or target directories to match your preferences. -Then read pngconf.h to see if you want to make any configuration +Then read pnglibconf.dfa to see if you want to make any configuration changes. Then just run "make" which will create the libpng library in @@ -125,39 +197,269 @@ do that, run "make install" in the zlib directory first if necessary). Some also allow you to run "make test-installed" after you have run "make install". -If you encounter a compiler error message complaining about the -lines +VIII. Configuring libpng for 16-bit platforms - __png.h__ already includes setjmp.h; - __dont__ include it again.; +You will want to look into zconf.h to tell zlib (and thus libpng) that +it cannot allocate more than 64K at a time. Even if you can, the memory +won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K. -this means you have compiled another module that includes setjmp.h, -which is hazardous because the two modules might not include exactly -the same setjmp.h. If you are sure that you know what you are doing -and that they are exactly the same, then you can comment out or -delete the two lines. Better yet, use the cexcept interface -instead, as demonstrated in contrib/visupng of the libpng distribution. +IX. Configuring for DOS -Further information can be found in the README and libpng.txt +For DOS users who only have access to the lower 640K, you will +have to limit zlib's memory usage via a png_set_compression_mem_level() +call. See zlib.h or zconf.h in the zlib library for more information. + +X. Configuring for Medium Model + +Libpng's support for medium model has been tested on most of the popular +compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets +defined, and FAR gets defined to far in pngconf.h, and you should be +all set. Everything in the library (except for zlib's structure) is +expecting far data. You must use the typedefs with the p or pp on +the end for pointers (or at least look at them and be careful). Make +note that the rows of data are defined as png_bytepp, which is +an "unsigned char far * far *". + +XI. Prepending a prefix to exported symbols + +Starting with libpng-1.6.0, you can configure libpng (when using the +"configure" script) to prefix all exported symbols by means of the +configuration option "--with-libpng-prefix=FOO_", where FOO_ can be any +string beginning with a letter and containing only uppercase +and lowercase letters, digits, and the underscore (i.e., a C language +identifier). This creates a set of macros in pnglibconf.h, so this is +transparent to applications; their function calls get transformed by +the macros to use the modified names. + +XII. Configuring for compiler xxx: + +All includes for libpng are in pngconf.h. If you need to add, change +or delete an include, this is the place to do it. +The includes that are not needed outside libpng are placed in pngpriv.h, +which is only used by the routines inside libpng itself. +The files in libpng proper only include pngpriv.h and png.h, which +in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h. +As of libpng-1.5.0, pngpriv.h also includes three other private header +files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material +that previously appeared in the public headers. + +XIII. Removing unwanted object code + +There are a bunch of #define's in pngconf.h that control what parts of +libpng are compiled. All the defines end in _SUPPORTED. If you are +never going to use a capability, you can change the #define to #undef +before recompiling libpng and save yourself code and data space, or +you can turn off individual capabilities with defines that begin with +"PNG_NO_". + +In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead. + +You can also turn all of the transforms and ancillary chunk capabilities +off en masse with compiler directives that define +PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS, +or all four, along with directives to turn on any of the capabilities that +you do want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the +extra transformations but still leave the library fully capable of reading +and writing PNG files with all known public chunks. Use of the +PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library +that is incapable of reading or writing ancillary chunks. If you are +not using the progressive reading capability, you can turn that off +with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING +capability, which you'll still have). + +All the reading and writing specific code are in separate files, so the +linker should only grab the files it needs. However, if you want to +make sure, or if you are building a stand alone library, all the +reading files start with "pngr" and all the writing files start with "pngw". +The files that don't match either (like png.c, pngtrans.c, etc.) +are used for both reading and writing, and always need to be included. +The progressive reader is in pngpread.c + +If you are creating or distributing a dynamically linked library (a .so +or DLL file), you should not remove or disable any parts of the library, +as this will cause applications linked with different versions of the +library to fail if they call functions not available in your library. +The size of the library itself should not be an issue, because only +those sections that are actually used will be loaded into memory. + +XIV. Enabling or disabling hardware optimizations + +Certain hardware capabilities, such as the Intel SSE instructions, +are normally detected at run time. Enable them with configure options +such as one of + + --enable-arm-neon=yes + --enable-mips-msa=yes + --enable-intel-sse=yes + --enable-powerpc-vsx=yes + +or enable them all at once with + + --enable-hardware-optimizations=yes + +or, if you are not using "configure", you can use one +or more of + + CPPFLAGS += "-DPNG_ARM_NEON" + CPPFLAGS += "-DPNG_MIPS_MSA" + CPPFLAGS += "-DPNG_INTEL_SSE" + CPPFLAGS += "-DPNG_POWERPC_VSX" + +See for example scripts/makefile.linux-opt + +If you wish to avoid using them, +you can disable them via the configure option + + --disable-hardware-optimizations + +to disable them all, or + + --enable-intel-sse=no + +to disable a particular one, +or via compiler-command options such as + + CPPFLAGS += "-DPNG_ARM_NEON_OPT=0, -DPNG_MIPS_MSA_OPT=0, + -DPNG_INTEL_SSE_OPT=0, -DPNG_POWERPC_VSX_OPT=0" + +If you are using cmake, hardware optimizations are "on" +by default. To disable them, use + + cmake . -DPNG_ARM_NEON=no -DPNG_INTEL_SSE=no \ + -DPNG_MIPS_MSA=no -DPNG_POWERPC_VSX=no + +or disable them all at once with + + cmake . -DPNG_HARDWARE_OPTIMIZATIONS=no + +XV. Changes to the build and configuration of libpng in libpng-1.5.x + +Details of internal changes to the library code can be found in the CHANGES +file and in the GIT repository logs. These will be of no concern to the vast +majority of library users or builders; however, the few who configure libpng +to a non-default feature set may need to change how this is done. + +There should be no need for library builders to alter build scripts if +these use the distributed build support - configure or the makefiles - +however, users of the makefiles may care to update their build scripts +to build pnglibconf.h where the corresponding makefile does not do so. + +Building libpng with a non-default configuration has changed completely. +The old method using pngusr.h should still work correctly even though the +way pngusr.h is used in the build has been changed; however, library +builders will probably want to examine the changes to take advantage of +new capabilities and to simplify their build system. + +A. Specific changes to library configuration capabilities + +The exact mechanism used to control attributes of API functions has +changed. A single set of operating system independent macro definitions +is used and operating system specific directives are defined in +pnglibconf.h + +As part of this the mechanism used to choose procedure call standards on +those systems that allow a choice has been changed. At present this only +affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems +running on Intel processors. As before, PNGAPI is defined where required +to control the exported API functions; however, two new macros, PNGCBAPI +and PNGCAPI, are used instead for callback functions (PNGCBAPI) and +(PNGCAPI) for functions that must match a C library prototype (currently +only png_longjmp_ptr, which must match the C longjmp function.) The new +approach is documented in pngconf.h + +Despite these changes, libpng 1.5.0 only supports the native C function +calling standard on those platforms tested so far ("__cdecl" on Microsoft +Windows). This is because the support requirements for alternative +calling conventions seem to no longer exist. Developers who find it +necessary to set PNG_API_RULE to 1 should advise the mailing list +(png-mng-implement) of this and library builders who use Openwatcom and +therefore set PNG_API_RULE to 2 should also contact the mailing list. + +B. Changes to the configuration mechanism + +Prior to libpng-1.5.0 library builders who needed to configure libpng +had either to modify the exported pngconf.h header file to add system +specific configuration or had to write feature selection macros into +pngusr.h and cause this to be included into pngconf.h by defining +PNG_USER_CONFIG. The latter mechanism had the disadvantage that an +application built without PNG_USER_CONFIG defined would see the +unmodified, default, libpng API and thus would probably fail to link. + +These mechanisms still work in the configure build and in any makefile +build that builds pnglibconf.h, although the feature selection macros +have changed somewhat as described above. In 1.5.0, however, pngusr.h is +processed only once, at the time the exported header file pnglibconf.h is +built. pngconf.h no longer includes pngusr.h; therefore, pngusr.h is ignored +after the build of pnglibconf.h and it is never included in an application +build. + +The formerly used alternative of adding a list of feature macros to the +CPPFLAGS setting in the build also still works; however, the macros will be +copied to pnglibconf.h and this may produce macro redefinition warnings +when the individual C files are compiled. + +All configuration now only works if pnglibconf.h is built from +scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan +(the original author of awk) maintains C source code of that awk and this +and all known later implementations (often called by subtly different +names - nawk and gawk for example) are adequate to build pnglibconf.h. +The Sun Microsystems (now Oracle) program 'awk' is an earlier version +and does not work; this may also apply to other systems that have a +functioning awk called 'nawk'. + +Configuration options are now documented in scripts/pnglibconf.dfa. This +file also includes dependency information that ensures a configuration is +consistent; that is, if a feature is switched off, dependent features are +also switched off. As a recommended alternative to using feature macros in +pngusr.h a system builder may also define equivalent options in pngusr.dfa +(or, indeed, any file) and add that to the configuration by setting +DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate +how to do this, and also illustrate a case where pngusr.h is still required. + +After you have built libpng, the definitions that were recorded in +pnglibconf.h are available to your application (pnglibconf.h is included +in png.h and gets installed alongside png.h and pngconf.h in your +$PREFIX/include directory). Do not edit pnglibconf.h after you have built +libpng, because than the settings would not accurately reflect the settings +that were used to build libpng. + +XVI. Setjmp/longjmp issues + +Libpng uses setjmp()/longjmp() for error handling. Unfortunately setjmp() +is known to be not thread-safe on some platforms and we don't know of +any platform where it is guaranteed to be thread-safe. Therefore, if +your application is going to be using multiple threads, you should +configure libpng with PNG_NO_SETJMP in your pngusr.dfa file, with +-DPNG_NO_SETJMP on your compile line, or with + + #undef PNG_SETJMP_SUPPORTED + +in your pnglibconf.h or pngusr.h. + +Starting with libpng-1.6.0, the library included a "simplified API". +This requires setjmp/longjmp, so you must either build the library +with PNG_SETJMP_SUPPORTED defined, or with PNG_SIMPLIFIED_READ_SUPPORTED +and PNG_SIMPLIFIED_WRITE_SUPPORTED undefined. + +XVII. Common linking failures + +If your application fails to find libpng or zlib entries while linking: + + Be sure "-lz" appears after "-lpng" on your linking command. + + Be sure you have built libpng, zlib, and your application for the + same platform (e.g., 32-bit or 64-bit). + + If you are using the vstudio project, observe the WARNING in + project/vstudio/README.txt. + +XVIII. Other sources of information about libpng: + +Further information can be found in the README and libpng-manual.txt files, in the individual makefiles, in png.h, and the manual pages libpng.3 and png.5. - -Using the ./configure script -- 16 December 2002. -================================================= - - -The ./configure script should work compatibly with what scripts/makefile.* -did, however there are some options you need to add to configure explicitly, -which previously was done semi-automatically (if you didn't edit -scripts/makefile.* yourself, that is) - - -CFLAGS="-Wall -O -funroll-loops \ --malign-loops=2 -malign-functions=2" ./configure --prefix=/usr/include \ ---with-pkgconfigdir=/usr/lib/pkgconfig --includedir=/usr/include - -You can alternatively specify --includedir=/usr/include, /usr/local/include, -/usr/include/png12, or whatever. - - +Copyright (c) 1998-2002,2006-2016 Glenn Randers-Pehrson +This document is released under the libpng license. +For conditions of distribution and use, see the disclaimer +and license in png.h. diff --git a/libs/libpng-src/LICENSE b/libs/libpng-src/LICENSE index 0fa9cb703..e0c5b531c 100644 --- a/libs/libpng-src/LICENSE +++ b/libs/libpng-src/LICENSE @@ -1,111 +1,134 @@ +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE +========================================= -This copy of the libpng notices is provided for your convenience. In case of -any discrepancy between this copy and the notices in the file png.h that is -included in the libpng distribution, the latter shall prevail. +PNG Reference Library License version 2 +--------------------------------------- -COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + * Copyright (c) 1995-2019 The PNG Reference Library Authors. + * Copyright (c) 2018-2019 Cosmin Truta. + * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. + * Copyright (c) 1996-1997 Andreas Dilger. + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. -If you modify libpng you may insert additional notices immediately following -this sentence. +The software is supplied "as is", without warranty of any kind, +express or implied, including, without limitation, the warranties +of merchantability, fitness for a particular purpose, title, and +non-infringement. In no event shall the Copyright owners, or +anyone distributing the software, be liable for any damages or +other liability, whether in contract, tort or otherwise, arising +from, out of, or in connection with the software, or the use or +other dealings in the software, even if advised of the possibility +of such damage. -This code is released under the libpng license. +Permission is hereby granted to use, copy, modify, and distribute +this software, or portions hereof, for any purpose, without fee, +subject to the following restrictions: -libpng versions 1.2.6, August 15, 2004, through 1.2.46, July 9, 2011, are -Copyright (c) 2004, 2006-2009 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.2.5 -with the following individual added to the list of Contributing Authors + 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. - Cosmin Truta + 2. Altered source versions must be plainly marked as such, and must + not be misrepresented as being the original software. -libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are -Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.0.6 -with the following individuals added to the list of Contributing Authors + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. - Simon-Pierre Cadieux - Eric S. Raymond - Gilles Vollant + +PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35) +----------------------------------------------------------------------- + +libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are +Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are +derived from libpng-1.0.6, and are distributed according to the same +disclaimer and license as libpng-1.0.6 with the following individuals +added to the list of Contributing Authors: + + Simon-Pierre Cadieux + Eric S. Raymond + Mans Rullgard + Cosmin Truta + Gilles Vollant + James Yu + Mandar Sahastrabuddhe + Google Inc. + Vadim Barkov and with the following additions to the disclaimer: - There is no warranty against interference with your enjoyment of the - library or against infringement. There is no warranty that our - efforts or the library will fulfill any of your particular purposes - or needs. This library is provided with all faults, and the entire - risk of satisfactory quality, performance, accuracy, and effort is with - the user. + There is no warranty against interference with your enjoyment of + the library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is + with the user. + +Some files in the "contrib" directory and some configure-generated +files that are distributed with libpng have other copyright owners, and +are released under other open source licenses. libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are -Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-0.96, -with the following individuals added to the list of Contributing Authors: +Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from +libpng-0.96, and are distributed according to the same disclaimer and +license as libpng-0.96, with the following individuals added to the +list of Contributing Authors: - Tom Lane - Glenn Randers-Pehrson - Willem van Schaik + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik libpng versions 0.89, June 1996, through 0.96, May 1997, are -Copyright (c) 1996, 1997 Andreas Dilger -Distributed according to the same disclaimer and license as libpng-0.88, -with the following individuals added to the list of Contributing Authors: +Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, +and are distributed according to the same disclaimer and license as +libpng-0.88, with the following individuals added to the list of +Contributing Authors: - John Bowler - Kevin Bracey - Sam Bushell - Magnus Holmgren - Greg Roelofs - Tom Tanner + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +Some files in the "scripts" directory have other copyright owners, +but are released under this license. libpng versions 0.5, May 1995, through 0.88, January 1996, are -Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. +Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. For the purposes of this copyright and license, "Contributing Authors" is defined as the following set of individuals: - Andreas Dilger - Dave Martindale - Guy Eric Schalnat - Paul Schmidt - Tim Wegner + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner -The PNG Reference Library is supplied "AS IS". The Contributing Authors -and Group 42, Inc. disclaim all warranties, expressed or implied, -including, without limitation, the warranties of merchantability and of -fitness for any purpose. The Contributing Authors and Group 42, Inc. -assume no liability for direct, indirect, incidental, special, exemplary, -or consequential damages, which may result from the use of the PNG -Reference Library, even if advised of the possibility of such damage. +The PNG Reference Library is supplied "AS IS". The Contributing +Authors and Group 42, Inc. disclaim all warranties, expressed or +implied, including, without limitation, the warranties of +merchantability and of fitness for any purpose. The Contributing +Authors and Group 42, Inc. assume no liability for direct, indirect, +incidental, special, exemplary, or consequential damages, which may +result from the use of the PNG Reference Library, even if advised of +the possibility of such damage. Permission is hereby granted to use, copy, modify, and distribute this source code, or portions hereof, for any purpose, without fee, subject to the following restrictions: -1. The origin of this source code must not be misrepresented. + 1. The origin of this source code must not be misrepresented. -2. Altered versions must be plainly marked as such and must not - be misrepresented as being the original source. + 2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. -3. This Copyright notice may not be removed or altered from any - source or altered source distribution. + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. -The Contributing Authors and Group 42, Inc. specifically permit, without -fee, and encourage the use of this source code as a component to -supporting the PNG file format in commercial products. If you use this -source code in a product, acknowledgment is not required but would be -appreciated. - - -A "png_get_copyright" function is available, for convenient use in "about" -boxes and the like: - - printf("%s",png_get_copyright(NULL)); - -Also, the PNG logo (in PNG format, of course) is supplied in the -files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). - -Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a -certification mark of the Open Source Initiative. - -Glenn Randers-Pehrson -glennrp at users.sourceforge.net -July 9, 2011 +The Contributing Authors and Group 42, Inc. specifically permit, +without fee, and encourage the use of this source code as a component +to supporting the PNG file format in commercial products. If you use +this source code in a product, acknowledgment is not required but would +be appreciated. diff --git a/libs/libpng-src/Makefile.am b/libs/libpng-src/Makefile.am index d3289ca95..4f621aa4d 100644 --- a/libs/libpng-src/Makefile.am +++ b/libs/libpng-src/Makefile.am @@ -1,155 +1,393 @@ -# Makefile.am: -# Source file for Makefile.in (and hence Makefile) +# Makefile.am, the source file for Makefile.in (and hence Makefile), is # -# Makefile.am need only be changed on a major version number -# change (e.g. libpng12 --> libpng14). In that case seach -# this file for every instance of the old base name (libpng12) -# and change to the new one (libpng14), then change the -# -version-number settings below so that the new values have -# the correct major part (first field). +# Copyright (c) 2018 Cosmin Truta +# Copyright (c) 2004-2016 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ -# libpng does not follow GNU file name conventions -AUTOMAKE_OPTIONS = foreign +ACLOCAL_AMFLAGS = -I scripts # test programs - run on make check, make distcheck -check_PROGRAMS= pngtest +check_PROGRAMS= pngtest pngunknown pngstest pngvalid pngimage pngcp +if HAVE_CLOCK_GETTIME +check_PROGRAMS += timepng +endif + +# Utilities - installed +bin_PROGRAMS= pngfix png-fix-itxt + +# This ensures that pnglibconf.h gets built at the start of 'make all' or +# 'make check', but it does not add dependencies to the individual programs, +# this is done below. +# +# IMPORTANT: always add the object modules of new programs to the list below +# because otherwise the sequence 'configure; make new-program' will *sometimes* +# result in the installed (system) pnglibconf.h being used and the result is +# always wrong and always very confusing. +BUILT_SOURCES = pnglibconf.h + pngtest_SOURCES = pngtest.c -pngtest_LDADD = libpng12.la -TESTS = test-pngtest.sh -TESTS_ENVIRONMENT= srcdir=$(srcdir) +pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngvalid_SOURCES = contrib/libtests/pngvalid.c +pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngstest_SOURCES = contrib/libtests/pngstest.c +pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngunknown_SOURCES = contrib/libtests/pngunknown.c +pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngimage_SOURCES = contrib/libtests/pngimage.c +pngimage_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +timepng_SOURCES = contrib/libtests/timepng.c +timepng_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngfix_SOURCES = contrib/tools/pngfix.c +pngfix_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +png_fix_itxt_SOURCES = contrib/tools/png-fix-itxt.c + +pngcp_SOURCES = contrib/tools/pngcp.c +pngcp_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +# Generally these are single line shell scripts to run a test with a particular +# set of parameters: +TESTS =\ + tests/pngtest\ + tests/pngtest-badpngs\ + tests/pngvalid-gamma-16-to-8 tests/pngvalid-gamma-alpha-mode\ + tests/pngvalid-gamma-background tests/pngvalid-gamma-expand16-alpha-mode\ + tests/pngvalid-gamma-expand16-background\ + tests/pngvalid-gamma-expand16-transform tests/pngvalid-gamma-sbit\ + tests/pngvalid-gamma-threshold tests/pngvalid-gamma-transform\ + tests/pngvalid-progressive-size\ + tests/pngvalid-progressive-interlace-standard\ + tests/pngvalid-transform\ + tests/pngvalid-progressive-standard tests/pngvalid-standard\ + tests/pngstest-1.8 tests/pngstest-1.8-alpha tests/pngstest-linear\ + tests/pngstest-linear-alpha tests/pngstest-none tests/pngstest-none-alpha\ + tests/pngstest-sRGB tests/pngstest-sRGB-alpha tests/pngunknown-IDAT\ + tests/pngunknown-discard tests/pngunknown-if-safe tests/pngunknown-sAPI\ + tests/pngunknown-sTER tests/pngunknown-save tests/pngunknown-vpAg\ + tests/pngimage-quick tests/pngimage-full # man pages dist_man_MANS= libpng.3 libpngpf.3 png.5 # generate the -config scripts if required -binconfigs= libpng12-config -EXTRA_SCRIPTS= libpng-config libpng12-config +binconfigs= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +EXTRA_SCRIPTS= libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config bin_SCRIPTS= @binconfigs@ # rules to build libpng, only build the old library on request -lib_LTLIBRARIES=libpng12.la @compatlib@ -EXTRA_LTLIBRARIES= libpng.la -libpng12_la_SOURCES = png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \ - pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \ - pngwtran.c pngmem.c pngerror.c pngpread.c \ - png.h pngconf.h -libpng_la_SOURCES = $(libpng12_la_SOURCES) +lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +# EXTRA_LTLIBRARIES= libpng.la +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\ + pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\ + pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ + png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa -libpng_la_CPPFLAGS = @LIBPNG_DEFINES@ -libpng12_la_CPPFLAGS = @LIBPNG_DEFINES@ +if PNG_ARM_NEON +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\ + arm/filter_neon.S arm/filter_neon_intrinsics.c \ + arm/palette_neon_intrinsics.c +endif -# MAJOR UPGRADE: the version-number settings below must be changed. -libpng12_la_LDFLAGS = -no-undefined -export-dynamic \ - -version-number 0:@PNGLIB_RELEASE@:0 -# -rpath is needed as automake doesn't know the directory -libpng_la_LDFLAGS = -rpath '$(libdir)' -no-undefined -export-dynamic \ - -version-number 3:@PNGLIB_RELEASE@:0 +if PNG_MIPS_MSA +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += mips/mips_init.c\ + mips/filter_msa_intrinsics.c +endif + +if PNG_INTEL_SSE +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += intel/intel_init.c\ + intel/filter_sse2_intrinsics.c +endif + +if PNG_POWERPC_VSX +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += powerpc/powerpc_init.c\ + powerpc/filter_vsx_intrinsics.c +endif + +nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \ + -version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0 if HAVE_LD_VERSION_SCRIPT - # Versioned symbols and restricted exports - libpng12_la_LDFLAGS += -Wl,--version-script=libpng.vers - libpng12_la_DEPENDENCIES = libpng.vers +# Versioned symbols and restricted exports +if HAVE_SOLARIS_LD + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,-M -Wl,libpng.vers else - # Only restricted exports when possible - libpng12_la_LDFLAGS += -export-symbols libpng.sym - libpng12_la_DEPENDENCIES = libpng.sym + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,--version-script=libpng.vers endif -libpng_la_DEPENDENCIES = $(libpng12_la_DEPENDENCIES) -# Avoid depending upon Character Ranges. -AN = '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.vers +else +# Only restricted exports when possible + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -export-symbols libpng.sym + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym +endif #distribute headers in /usr/include/libpng/* pkgincludedir= $(includedir)/$(PNGLIB_BASENAME) pkginclude_HEADERS= png.h pngconf.h +nodist_pkginclude_HEADERS= pnglibconf.h # pkg-config stuff, note that libpng.pc is always required in order # to get the correct library pkgconfigdir = @pkgconfigdir@ -pkgconfig_DATA = libpng12.pc +pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc -#extra source distribution files. +# Extra source distribution files, '${srcdir}' is used below to stop build files +# from those directories being included. This only works if the configure is +# not done in the source directory! EXTRA_DIST= \ - ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO \ + ANNOUNCE AUTHORS CHANGES INSTALL LICENSE README TODO TRADEMARK \ pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \ - CMakeLists.txt \ - ${srcdir}/projects/cbuilder5/* \ - ${srcdir}/projects/beos/* \ - ${srcdir}/projects/visualc6/* \ - ${srcdir}/projects/visualc71/* \ - ${srcdir}/projects/wince.txt \ - ${srcdir}/projects/netware.txt \ - ${srcdir}/projects/xcode/* \ - ${srcdir}/scripts/* \ - ${srcdir}/contrib/gregbook/* \ - ${srcdir}/contrib/pngminim/* \ - ${srcdir}/contrib/pngminus/* \ - ${srcdir}/contrib/pngsuite/* \ - ${srcdir}/contrib/visupng/* \ - $(TESTS) \ - example.c libpng-1.2.46.txt pnggccrd.c pngvcrd.c + ${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \ + $(TESTS) $(XFAIL_TESTS) tests/pngstest \ + CMakeLists.txt example.c libpng-manual.txt -CLEANFILES= pngout.png libpng12.pc libpng12-config libpng.vers \ -libpng.sym +SCRIPT_CLEANFILES=scripts/*.out scripts/*.chk + +CLEANFILES= *.tf? pngout.png libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config libpng.vers libpng.sym \ + check.new pnglibconf.h pngprefix.h symbols.new pngtest-log.txt \ + pnglibconf.out pnglibconf.c pnglibconf.pre pnglibconf.dfn \ + $(SCRIPT_CLEANFILES) MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \ config.sub configure depcomp install-sh ltmain.sh missing +# PNG_COPTS give extra options for the C compiler to be used on all compilation +# steps (unless targe_CFLAGS is specified; that will take precedence over +# AM_CFLAGS) +PNG_COPTS = @PNG_COPTS@ +AM_CFLAGS = ${PNG_COPTS} + +# DFNCPP is normally just CPP - the C preprocessor - but on Solaris and maybe +# other operating systems (NeXT?) the C preprocessor selected by configure +# checks input tokens for validity - effectively it performs part of the ANSI-C +# parsing - and therefore fails with the .df files. configure.ac has special +# checks for this and sets DFNCPP appropriately. +DFNCPP = @DFNCPP@ + +SUFFIXES = .chk .out + $(PNGLIB_BASENAME).pc: libpng.pc cp libpng.pc $@ $(PNGLIB_BASENAME)-config: libpng-config cp libpng-config $@ -libpng.sym: png.h pngconf.h - rm -f $@ $@.new - $(CPP) @LIBPNG_DEFINES@ $(CPPFLAGS) -DPNG_BUILDSYMS $(srcdir)/png.h | \ - $(SED) -n -e \ - 's|^.*PNG_FUNCTION_EXPORT[ ]*\([$(AN)]*\).*$$|$(SYMBOL_PREFIX)\1|p' \ - -e 's|^.*PNG_DATA_EXPORT[ ]*\([$(AN)]*\).*$$|$(SYMBOL_PREFIX)\1|p' \ - >$@.new - mv $@.new $@ +scripts/sym.out scripts/vers.out: png.h pngconf.h pnglibconf.h +scripts/prefix.out: png.h pngconf.h pnglibconf.out +scripts/symbols.out: png.h pngconf.h $(srcdir)/scripts/pnglibconf.h.prebuilt +scripts/intprefix.out: pnglibconf.h -libpng.vers: libpng.sym - rm -f $@ $@.new - echo PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0 '{global:' > $@.new - $(SED) s/$$/\;/ libpng.sym >> $@.new - echo 'local: *; };' >> $@.new - mv $@.new $@ +libpng.sym: scripts/sym.out + rm -f $@ + cp $? $@ +libpng.vers: scripts/vers.out + rm -f $@ + cp $? $@ -test: check +if DO_PNG_PREFIX +# Rename functions in scripts/prefix.out with a PNG_PREFIX prefix. +# Rename macros in scripts/macro.lst from PNG_PREFIXpng_ to PNG_ (the actual +# implementation of the macro). +pnglibconf.h: pnglibconf.out scripts/prefix.out scripts/macro.lst + rm -f $@ + $(AWK) 's==0 && NR>1{print prev}\ + s==0{prev=$$0}\ + s==1{print "#define", $$1, "@PNG_PREFIX@" $$1}\ + s==2{print "#define @PNG_PREFIX@png_" $$1, "PNG_" $$1}\ + END{print prev}' s=0 pnglibconf.out s=1 scripts/prefix.out\ + s=2 ${srcdir}/scripts/macro.lst >pnglibconf.tf8 + mv pnglibconf.tf8 $@ -# install the .../include headers as links to the new ones -install-data-hook: - cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h - cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/png.h png.h - cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/pngconf.h pngconf.h - cd $(DESTDIR)$(pkgconfigdir); rm -f libpng.pc - cd $(DESTDIR)$(pkgconfigdir); $(LN_S) $(PNGLIB_BASENAME).pc libpng.pc +pngprefix.h: scripts/intprefix.out + rm -f pngprefix.tf1 + $(AWK) '{print "#define", $$1, "@PNG_PREFIX@" $$1}' $? >pngprefix.tf1 + mv pngprefix.tf1 $@ +else +pnglibconf.h: pnglibconf.out + rm -f $@ + cp $? $@ -# do evil things to libpng to cause libpng12 to be used -install-exec-hook: - cd $(DESTDIR)$(bindir); rm -f libpng-config - cd $(DESTDIR)$(bindir); $(LN_S) $(PNGLIB_BASENAME)-config libpng-config - @set -x;\ - cd $(DESTDIR)$(libdir);\ - for ext in a la so sl dylib; do\ - rm -f libpng.$$ext;\ - if test -f $(PNGLIB_BASENAME).$$ext; then\ - $(LN_S) $(PNGLIB_BASENAME).$$ext libpng.$$ext;\ - fi;\ +pngprefix.h: # is empty + :>$@ +endif + +$(srcdir)/scripts/pnglibconf.h.prebuilt: + @echo "Attempting to build $@" >&2 + @echo "This is a machine generated file, but if you want to make" >&2 + @echo "a new one simply make 'scripts/pnglibconf.out', copy that" >&2 + @echo "AND set PNG_ZLIB_VERNUM to 0 (you MUST do this)" >&2 + @exit 1 + +# The following is necessary to ensure that the local pnglibconf.h is used, not +# an installed one (this can happen immediately after on a clean system if +# 'make test' is the first thing the user does.) Only files which include +# one of the png source files (typically png.h or pngpriv.h) need to be listed +# here: +pngtest.o: pnglibconf.h + +contrib/libtests/makepng.o: pnglibconf.h +contrib/libtests/pngstest.o: pnglibconf.h +contrib/libtests/pngunknown.o: pnglibconf.h +contrib/libtests/pngimage.o: pnglibconf.h +contrib/libtests/pngvalid.o: pnglibconf.h +contrib/libtests/readpng.o: pnglibconf.h +contrib/libtests/tarith.o: pnglibconf.h +contrib/libtests/timepng.o: pnglibconf.h + +contrib/tools/makesRGB.o: pnglibconf.h +contrib/tools/pngfix.o: pnglibconf.h +contrib/tools/pngcp.o: pnglibconf.h + +# We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually +# be built with PNG_USE_READ_MACROS; this prevents the read macros from +# interfering with the symbol file format. +SYMBOL_CFLAGS = -DPNGLIB_LIBNAME='PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0'\ + -DPNGLIB_VERSION='@PNGLIB_VERSION@'\ + -DSYMBOL_PREFIX='$(SYMBOL_PREFIX)'\ + -DPNG_NO_USE_READ_MACROS -DPNG_BUILDING_SYMBOL_TABLE + +if DO_PNG_PREFIX +SYMBOL_CFLAGS += -DPNG_PREFIX='@PNG_PREFIX@' +endif + +.c.out: + rm -f $@ $*.tf[12] + test -d scripts || mkdir scripts || test -d scripts + $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\ + $(CPPFLAGS) $(SYMBOL_CFLAGS) $< > $*.tf1 + $(AWK) -f "${srcdir}/scripts/dfn.awk" out="$*.tf2" $*.tf1 1>&2 + rm -f $*.tf1 + mv $*.tf2 $@ + +# The .c file for pnglibconf.h is machine generated +pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_XTRA) + rm -f $@ $*.tf[45] + $(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf4 version=search\ + ${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\ + ${srcdir}/pngusr.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf5 $*.tf4 1>&2 + rm $*.tf4 + mv $*.tf5 $@ + +# Symbol checks (.def and .out files should match) +scripts/symbols.chk: scripts/checksym.awk scripts/symbols.def scripts/symbols.out + +.out.chk: + rm -f $@ $*.new + $(AWK) -f ${srcdir}/scripts/checksym.awk ${srcdir}/scripts/${*F}.def\ + of="$*.new" $< >&2 + mv $*.new $@ + +# used on demand to regenerate the standard header, CPPFLAGS should +# be empty - no non-standard defines +scripts/pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h + rm -f $@ pnglibconf.tf[67] + test -z "$(CPPFLAGS)" + echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\ + $(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf6\ + logunsupported=1 version=search ${srcdir}/pngconf.h -\ + ${srcdir}/scripts/pnglibconf.dfa 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf7\ + pnglibconf.tf6 1>&2 + rm pnglibconf.tf6 + mv pnglibconf.tf7 $@ + +$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS): png.h pngconf.h \ + pnglibconf.h pngpriv.h pngdebug.h pnginfo.h pngstruct.h pngprefix.h + +test: check-am + +# Extra checks +check: scripts/symbols.chk + +# Don't distribute the generated script files +dist-hook: + cd '$(top_distdir)'; rm -f $(SCRIPT_CLEANFILES) + +# Make links between installed files with release-specific names and the generic +# file names. If this install rule is run the generic names will be deleted and +# recreated - this has obvious issues for systems with multiple installations. + +install-header-links: + @set -ex; cd '$(DESTDIR)$(includedir)'; for f in $(HEADERS); do \ + rm -f "$$f"; $(LN_S) "$(PNGLIB_BASENAME)/$$f" "$$f"; done + +uninstall-header-links: + cd '$(DESTDIR)$(includedir)'; rm -f $(HEADERS) + +install-libpng-pc: + @set -ex; cd '$(DESTDIR)$(pkgconfigdir)'; rm -f libpng.pc; \ + $(LN_S) '$(PNGLIB_BASENAME).pc' libpng.pc + +uninstall-libpng-pc: + rm -f '$(DESTDIR)$(pkgconfigdir)/libpng.pc' + +# EXT_LIST is a list of the possibly library directory extensions, this exists +# because we can't find a good way of discovering the file extensions that are +# actually installed on a given system, so instead we check for every extension +# we have seen. + +EXT_LIST = a dll.a so so.@PNGLIB_MAJOR@@PNGLIB_MINOR@.@PNGLIB_RELEASE@ la sl dylib + +install-library-links: + @set -x; cd '$(DESTDIR)$(libdir)';\ + for ext in $(EXT_LIST); do\ + rm -f "libpng.$$ext";\ + if test -f "$(PNGLIB_BASENAME).$$ext"; then\ + $(LN_S) "$(PNGLIB_BASENAME).$$ext" "libpng.$$ext" || exit 1;\ + fi;\ done -uninstall-hook: - cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h - rm -f $(DESTDIR)$(pkgconfigdir)/libpng.pc - rm -f $(DESTDIR)$(bindir)/libpng-config - @if test -n "@compatlib@"; then\ - set -x;\ - cd $(DESTDIR)$(libdir);\ - for ext in a la so sl dylib; do\ - rm -f libpng.$$ext;\ - done;\ - fi +uninstall-library-links: + @set -x; cd '$(DESTDIR)$(libdir)'; for ext in $(EXT_LIST); do\ + rm -f "libpng.$$ext"; done + +install-libpng-config: + @set -ex; cd '$(DESTDIR)$(bindir)'; rm -f libpng-config; \ + $(LN_S) '$(PNGLIB_BASENAME)-config' libpng-config + +uninstall-libpng-config: + rm -f '$(DESTDIR)$(bindir)/libpng-config' + +if DO_INSTALL_LINKS +# If --enable-unversioned-links is specified the header and lib file links +# will be automatically made on a 'make install': + +install-data-hook: install-header-links +uninstall-hook: uninstall-header-links +install-exec-hook: install-library-links +uninstall-hook: uninstall-library-links +endif + +if DO_INSTALL_LIBPNG_PC +# Likewise, --install-pc causes libpng.pc to be constructed: + +install-data-hook: install-libpng-pc +uninstall-hook: uninstall-libpng-pc +endif + +if DO_INSTALL_LIBPNG_CONFIG +# And --install-config: + +install-exec-hook: install-libpng-config +uninstall-hook: uninstall-libpng-config +endif + +# The following addition ensures that 'make all' always builds the test programs +# too. It used to, but some change either in libpng or configure stopped this +# working. +all-am: $(check_PROGRAMS) diff --git a/libs/libpng-src/Makefile.in b/libs/libpng-src/Makefile.in index d07cb3d7b..81ac1c855 100644 --- a/libs/libpng-src/Makefile.in +++ b/libs/libpng-src/Makefile.in @@ -1,9 +1,8 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.16.1 from Makefile.am. # @configure_input@ -# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, -# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. + # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -15,20 +14,75 @@ @SET_MAKE@ -# Makefile.am: -# Source file for Makefile.in (and hence Makefile) +# Makefile.am, the source file for Makefile.in (and hence Makefile), is # -# Makefile.am need only be changed on a major version number -# change (e.g. libpng12 --> libpng14). In that case seach -# this file for every instance of the old base name (libpng12) -# and change to the new one (libpng14), then change the -# -version-number settings below so that the new values have -# the correct major part (first field). +# Copyright (c) 2018 Cosmin Truta +# Copyright (c) 2004-2016 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ @@ -46,27 +100,55 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ -check_PROGRAMS = pngtest$(EXEEXT) -@HAVE_LD_VERSION_SCRIPT_TRUE@am__append_1 = -Wl,--version-script=libpng.vers -@HAVE_LD_VERSION_SCRIPT_FALSE@am__append_2 = -export-symbols libpng.sym +check_PROGRAMS = pngtest$(EXEEXT) pngunknown$(EXEEXT) \ + pngstest$(EXEEXT) pngvalid$(EXEEXT) pngimage$(EXEEXT) \ + pngcp$(EXEEXT) $(am__EXEEXT_1) +@HAVE_CLOCK_GETTIME_TRUE@am__append_1 = timepng +bin_PROGRAMS = pngfix$(EXEEXT) png-fix-itxt$(EXEEXT) +@PNG_ARM_NEON_TRUE@am__append_2 = arm/arm_init.c\ +@PNG_ARM_NEON_TRUE@ arm/filter_neon.S arm/filter_neon_intrinsics.c \ +@PNG_ARM_NEON_TRUE@ arm/palette_neon_intrinsics.c + +@PNG_MIPS_MSA_TRUE@am__append_3 = mips/mips_init.c\ +@PNG_MIPS_MSA_TRUE@ mips/filter_msa_intrinsics.c + +@PNG_INTEL_SSE_TRUE@am__append_4 = intel/intel_init.c\ +@PNG_INTEL_SSE_TRUE@ intel/filter_sse2_intrinsics.c + +@PNG_POWERPC_VSX_TRUE@am__append_5 = powerpc/powerpc_init.c\ +@PNG_POWERPC_VSX_TRUE@ powerpc/filter_vsx_intrinsics.c + + +# Versioned symbols and restricted exports +@HAVE_LD_VERSION_SCRIPT_TRUE@@HAVE_SOLARIS_LD_TRUE@am__append_6 = -Wl,-M -Wl,libpng.vers +@HAVE_LD_VERSION_SCRIPT_TRUE@@HAVE_SOLARIS_LD_FALSE@am__append_7 = -Wl,--version-script=libpng.vers +# Only restricted exports when possible +@HAVE_LD_VERSION_SCRIPT_FALSE@am__append_8 = -export-symbols libpng.sym +@DO_PNG_PREFIX_TRUE@am__append_9 = -DPNG_PREFIX='@PNG_PREFIX@' subdir = . -DIST_COMMON = README $(am__configure_deps) $(dist_man_MANS) \ - $(pkginclude_HEADERS) $(srcdir)/Makefile.am \ - $(srcdir)/Makefile.in $(srcdir)/config.h.in \ - $(top_srcdir)/configure $(top_srcdir)/scripts/libpng-config.in \ - $(top_srcdir)/scripts/libpng.pc-configure.in INSTALL TODO \ - config.guess config.sub depcomp install-sh ltmain.sh missing \ - mkinstalldirs ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 -am__aclocal_m4_deps = $(top_srcdir)/configure.ac +am__aclocal_m4_deps = $(top_srcdir)/scripts/libtool.m4 \ + $(top_srcdir)/scripts/ltoptions.m4 \ + $(top_srcdir)/scripts/ltsugar.m4 \ + $(top_srcdir)/scripts/ltversion.m4 \ + $(top_srcdir)/scripts/lt~obsolete.m4 \ + $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(top_srcdir)/configure \ + $(am__configure_deps) $(pkginclude_HEADERS) $(am__DIST_COMMON) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno -mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = libpng.pc libpng-config CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \ + "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man3dir)" \ + "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(pkgconfigdir)" \ + "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(pkgincludedir)" +@HAVE_CLOCK_GETTIME_TRUE@am__EXEEXT_1 = timepng$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ @@ -88,83 +170,396 @@ am__nobase_list = $(am__nobase_strip_setup); \ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' -am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ - "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)" \ - "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgincludedir)" +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } LTLIBRARIES = $(lib_LTLIBRARIES) -libpng_la_LIBADD = -am__objects_1 = libpng_la-png.lo libpng_la-pngset.lo \ - libpng_la-pngget.lo libpng_la-pngrutil.lo \ - libpng_la-pngtrans.lo libpng_la-pngwutil.lo \ - libpng_la-pngread.lo libpng_la-pngrio.lo libpng_la-pngwio.lo \ - libpng_la-pngwrite.lo libpng_la-pngrtran.lo \ - libpng_la-pngwtran.lo libpng_la-pngmem.lo \ - libpng_la-pngerror.lo libpng_la-pngpread.lo -am_libpng_la_OBJECTS = $(am__objects_1) -libpng_la_OBJECTS = $(am_libpng_la_OBJECTS) -libpng_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libpng_la_LDFLAGS) $(LDFLAGS) -o $@ -libpng12_la_LIBADD = -am_libpng12_la_OBJECTS = libpng12_la-png.lo libpng12_la-pngset.lo \ - libpng12_la-pngget.lo libpng12_la-pngrutil.lo \ - libpng12_la-pngtrans.lo libpng12_la-pngwutil.lo \ - libpng12_la-pngread.lo libpng12_la-pngrio.lo \ - libpng12_la-pngwio.lo libpng12_la-pngwrite.lo \ - libpng12_la-pngrtran.lo libpng12_la-pngwtran.lo \ - libpng12_la-pngmem.lo libpng12_la-pngerror.lo \ - libpng12_la-pngpread.lo -libpng12_la_OBJECTS = $(am_libpng12_la_OBJECTS) -libpng12_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ - $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ - $(libpng12_la_LDFLAGS) $(LDFLAGS) -o $@ +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LIBADD = +am__libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES_DIST = png.c \ + pngerror.c pngget.c pngmem.c pngpread.c pngread.c pngrio.c \ + pngrtran.c pngrutil.c pngset.c pngtrans.c pngwio.c pngwrite.c \ + pngwtran.c pngwutil.c png.h pngconf.h pngdebug.h pnginfo.h \ + pngpriv.h pngstruct.h pngusr.dfa arm/arm_init.c \ + arm/filter_neon.S arm/filter_neon_intrinsics.c \ + arm/palette_neon_intrinsics.c mips/mips_init.c \ + mips/filter_msa_intrinsics.c intel/intel_init.c \ + intel/filter_sse2_intrinsics.c powerpc/powerpc_init.c \ + powerpc/filter_vsx_intrinsics.c +am__dirstamp = $(am__leading_dot)dirstamp +@PNG_ARM_NEON_TRUE@am__objects_1 = arm/arm_init.lo arm/filter_neon.lo \ +@PNG_ARM_NEON_TRUE@ arm/filter_neon_intrinsics.lo \ +@PNG_ARM_NEON_TRUE@ arm/palette_neon_intrinsics.lo +@PNG_MIPS_MSA_TRUE@am__objects_2 = mips/mips_init.lo \ +@PNG_MIPS_MSA_TRUE@ mips/filter_msa_intrinsics.lo +@PNG_INTEL_SSE_TRUE@am__objects_3 = intel/intel_init.lo \ +@PNG_INTEL_SSE_TRUE@ intel/filter_sse2_intrinsics.lo +@PNG_POWERPC_VSX_TRUE@am__objects_4 = powerpc/powerpc_init.lo \ +@PNG_POWERPC_VSX_TRUE@ powerpc/filter_vsx_intrinsics.lo +am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = png.lo pngerror.lo \ + pngget.lo pngmem.lo pngpread.lo pngread.lo pngrio.lo \ + pngrtran.lo pngrutil.lo pngset.lo pngtrans.lo pngwio.lo \ + pngwrite.lo pngwtran.lo pngwutil.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) +nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS = \ + $(am_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) \ + $(nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LINK = $(LIBTOOL) $(AM_V_lt) \ + --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link \ + $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS) $(LDFLAGS) -o \ + $@ +am_png_fix_itxt_OBJECTS = contrib/tools/png-fix-itxt.$(OBJEXT) +png_fix_itxt_OBJECTS = $(am_png_fix_itxt_OBJECTS) +png_fix_itxt_LDADD = $(LDADD) +am_pngcp_OBJECTS = contrib/tools/pngcp.$(OBJEXT) +pngcp_OBJECTS = $(am_pngcp_OBJECTS) +pngcp_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +am_pngfix_OBJECTS = contrib/tools/pngfix.$(OBJEXT) +pngfix_OBJECTS = $(am_pngfix_OBJECTS) +pngfix_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +am_pngimage_OBJECTS = contrib/libtests/pngimage.$(OBJEXT) +pngimage_OBJECTS = $(am_pngimage_OBJECTS) +pngimage_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +am_pngstest_OBJECTS = contrib/libtests/pngstest.$(OBJEXT) +pngstest_OBJECTS = $(am_pngstest_OBJECTS) +pngstest_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la am_pngtest_OBJECTS = pngtest.$(OBJEXT) pngtest_OBJECTS = $(am_pngtest_OBJECTS) -pngtest_DEPENDENCIES = libpng12.la +pngtest_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +am_pngunknown_OBJECTS = contrib/libtests/pngunknown.$(OBJEXT) +pngunknown_OBJECTS = $(am_pngunknown_OBJECTS) +pngunknown_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +am_pngvalid_OBJECTS = contrib/libtests/pngvalid.$(OBJEXT) +pngvalid_OBJECTS = $(am_pngvalid_OBJECTS) +pngvalid_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +am_timepng_OBJECTS = contrib/libtests/timepng.$(OBJEXT) +timepng_OBJECTS = $(am_timepng_OBJECTS) +timepng_DEPENDENCIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la SCRIPTS = $(bin_SCRIPTS) +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/depcomp -am__depfiles_maybe = depfiles +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/png.Plo ./$(DEPDIR)/pngerror.Plo \ + ./$(DEPDIR)/pngget.Plo ./$(DEPDIR)/pngmem.Plo \ + ./$(DEPDIR)/pngpread.Plo ./$(DEPDIR)/pngread.Plo \ + ./$(DEPDIR)/pngrio.Plo ./$(DEPDIR)/pngrtran.Plo \ + ./$(DEPDIR)/pngrutil.Plo ./$(DEPDIR)/pngset.Plo \ + ./$(DEPDIR)/pngtest.Po ./$(DEPDIR)/pngtrans.Plo \ + ./$(DEPDIR)/pngwio.Plo ./$(DEPDIR)/pngwrite.Plo \ + ./$(DEPDIR)/pngwtran.Plo ./$(DEPDIR)/pngwutil.Plo \ + arm/$(DEPDIR)/arm_init.Plo arm/$(DEPDIR)/filter_neon.Plo \ + arm/$(DEPDIR)/filter_neon_intrinsics.Plo \ + arm/$(DEPDIR)/palette_neon_intrinsics.Plo \ + contrib/libtests/$(DEPDIR)/pngimage.Po \ + contrib/libtests/$(DEPDIR)/pngstest.Po \ + contrib/libtests/$(DEPDIR)/pngunknown.Po \ + contrib/libtests/$(DEPDIR)/pngvalid.Po \ + contrib/libtests/$(DEPDIR)/timepng.Po \ + contrib/tools/$(DEPDIR)/png-fix-itxt.Po \ + contrib/tools/$(DEPDIR)/pngcp.Po \ + contrib/tools/$(DEPDIR)/pngfix.Po \ + intel/$(DEPDIR)/filter_sse2_intrinsics.Plo \ + intel/$(DEPDIR)/intel_init.Plo \ + mips/$(DEPDIR)/filter_msa_intrinsics.Plo \ + mips/$(DEPDIR)/mips_init.Plo \ + powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo \ + powerpc/$(DEPDIR)/powerpc_init.Plo am__mv = mv -f +CPPASCOMPILE = $(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CCASFLAGS) $(CCASFLAGS) +LTCPPASCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CCAS) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CCASFLAGS) $(CCASFLAGS) +AM_V_CPPAS = $(am__v_CPPAS_@AM_V@) +am__v_CPPAS_ = $(am__v_CPPAS_@AM_DEFAULT_V@) +am__v_CPPAS_0 = @echo " CPPAS " $@; +am__v_CPPAS_1 = COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ -SOURCES = $(libpng_la_SOURCES) $(libpng12_la_SOURCES) \ - $(pngtest_SOURCES) -DIST_SOURCES = $(libpng_la_SOURCES) $(libpng12_la_SOURCES) \ - $(pngtest_SOURCES) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES) \ + $(nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES) \ + $(png_fix_itxt_SOURCES) $(pngcp_SOURCES) $(pngfix_SOURCES) \ + $(pngimage_SOURCES) $(pngstest_SOURCES) $(pngtest_SOURCES) \ + $(pngunknown_SOURCES) $(pngvalid_SOURCES) $(timepng_SOURCES) +DIST_SOURCES = \ + $(am__libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES_DIST) \ + $(png_fix_itxt_SOURCES) $(pngcp_SOURCES) $(pngfix_SOURCES) \ + $(pngimage_SOURCES) $(pngstest_SOURCES) $(pngtest_SOURCES) \ + $(pngunknown_SOURCES) $(pngvalid_SOURCES) $(timepng_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac man3dir = $(mandir)/man3 man5dir = $(mandir)/man5 NROFF = nroff MANS = $(dist_man_MANS) DATA = $(pkgconfig_DATA) -HEADERS = $(pkginclude_HEADERS) +HEADERS = $(nodist_pkginclude_HEADERS) $(pkginclude_HEADERS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ + $(LISP)config.h.in +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags -am__tty_colors = \ -red=; grn=; lgn=; blu=; std= +CSCOPE = cscope +AM_RECURSIVE_TARGETS = cscope check recheck +am__tty_colors_dummy = \ + mgn= red= grn= lgn= blu= brg= std=; \ + am__color_tests=no +am__tty_colors = { \ + $(am__tty_colors_dummy); \ + if test "X$(AM_COLOR_TESTS)" = Xno; then \ + am__color_tests=no; \ + elif test "X$(AM_COLOR_TESTS)" = Xalways; then \ + am__color_tests=yes; \ + elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \ + am__color_tests=yes; \ + fi; \ + if test $$am__color_tests = yes; then \ + red=''; \ + grn=''; \ + lgn=''; \ + blu=''; \ + mgn=''; \ + brg=''; \ + std=''; \ + fi; \ +} +am__recheck_rx = ^[ ]*:recheck:[ ]* +am__global_test_result_rx = ^[ ]*:global-test-result:[ ]* +am__copy_in_global_log_rx = ^[ ]*:copy-in-global-log:[ ]* +# A command that, given a newline-separated list of test names on the +# standard input, print the name of the tests that are to be re-run +# upon "make recheck". +am__list_recheck_tests = $(AWK) '{ \ + recheck = 1; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + { \ + if ((getline line2 < ($$0 ".log")) < 0) \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[nN][Oo]/) \ + { \ + recheck = 0; \ + break; \ + } \ + else if (line ~ /$(am__recheck_rx)[yY][eE][sS]/) \ + { \ + break; \ + } \ + }; \ + if (recheck) \ + print $$0; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# A command that, given a newline-separated list of test names on the +# standard input, create the global log from their .trs and .log files. +am__create_global_log = $(AWK) ' \ +function fatal(msg) \ +{ \ + print "fatal: making $@: " msg | "cat >&2"; \ + exit 1; \ +} \ +function rst_section(header) \ +{ \ + print header; \ + len = length(header); \ + for (i = 1; i <= len; i = i + 1) \ + printf "="; \ + printf "\n\n"; \ +} \ +{ \ + copy_in_global_log = 1; \ + global_test_result = "RUN"; \ + while ((rc = (getline line < ($$0 ".trs"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".trs"); \ + if (line ~ /$(am__global_test_result_rx)/) \ + { \ + sub("$(am__global_test_result_rx)", "", line); \ + sub("[ ]*$$", "", line); \ + global_test_result = line; \ + } \ + else if (line ~ /$(am__copy_in_global_log_rx)[nN][oO]/) \ + copy_in_global_log = 0; \ + }; \ + if (copy_in_global_log) \ + { \ + rst_section(global_test_result ": " $$0); \ + while ((rc = (getline line < ($$0 ".log"))) != 0) \ + { \ + if (rc < 0) \ + fatal("failed to read from " $$0 ".log"); \ + print line; \ + }; \ + printf "\n"; \ + }; \ + close ($$0 ".trs"); \ + close ($$0 ".log"); \ +}' +# Restructured Text title. +am__rst_title = { sed 's/.*/ & /;h;s/./=/g;p;x;s/ *$$//;p;g' && echo; } +# Solaris 10 'make', and several other traditional 'make' implementations, +# pass "-e" to $(SHELL), and POSIX 2008 even requires this. Work around it +# by disabling -e (using the XSI extension "set +e") if it's set. +am__sh_e_setup = case $$- in *e*) set +e;; esac +# Default flags passed to test drivers. +am__common_driver_flags = \ + --color-tests "$$am__color_tests" \ + --enable-hard-errors "$$am__enable_hard_errors" \ + --expect-failure "$$am__expect_failure" +# To be inserted before the command running the test. Creates the +# directory for the log if needed. Stores in $dir the directory +# containing $f, in $tst the test, in $log the log. Executes the +# developer- defined test setup AM_TESTS_ENVIRONMENT (if any), and +# passes TESTS_ENVIRONMENT. Set up options for the wrapper that +# will run the test scripts (or their associated LOG_COMPILER, if +# thy have one). +am__check_pre = \ +$(am__sh_e_setup); \ +$(am__vpath_adj_setup) $(am__vpath_adj) \ +$(am__tty_colors); \ +srcdir=$(srcdir); export srcdir; \ +case "$@" in \ + */*) am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`;; \ + *) am__odir=.;; \ +esac; \ +test "x$$am__odir" = x"." || test -d "$$am__odir" \ + || $(MKDIR_P) "$$am__odir" || exit $$?; \ +if test -f "./$$f"; then dir=./; \ +elif test -f "$$f"; then dir=; \ +else dir="$(srcdir)/"; fi; \ +tst=$$dir$$f; log='$@'; \ +if test -n '$(DISABLE_HARD_ERRORS)'; then \ + am__enable_hard_errors=no; \ +else \ + am__enable_hard_errors=yes; \ +fi; \ +case " $(XFAIL_TESTS) " in \ + *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \ + am__expect_failure=yes;; \ + *) \ + am__expect_failure=no;; \ +esac; \ +$(AM_TESTS_ENVIRONMENT) $(TESTS_ENVIRONMENT) +# A shell command to get the names of the tests scripts with any registered +# extension removed (i.e., equivalently, the names of the test logs, with +# the '.log' extension removed). The result is saved in the shell variable +# '$bases'. This honors runtime overriding of TESTS and TEST_LOGS. Sadly, +# we cannot use something simpler, involving e.g., "$(TEST_LOGS:.log=)", +# since that might cause problem with VPATH rewrites for suffix-less tests. +# See also 'test-harness-vpath-rewrite.sh' and 'test-trs-basic.sh'. +am__set_TESTS_bases = \ + bases='$(TEST_LOGS)'; \ + bases=`for i in $$bases; do echo $$i; done | sed 's/\.log$$//'`; \ + bases=`echo $$bases` +RECHECK_LOGS = $(TEST_LOGS) +TEST_SUITE_LOG = test-suite.log +TEST_EXTENSIONS = @EXEEXT@ .test +LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS) +am__set_b = \ + case '$@' in \ + */*) \ + case '$*' in \ + */*) b='$*';; \ + *) b=`echo '$@' | sed 's/\.log$$//'`; \ + esac;; \ + *) \ + b='$*';; \ + esac +am__test_logs1 = $(TESTS:=.log) +am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) +TEST_LOGS = $(am__test_logs2:.test.log=.log) +TEST_LOG_DRIVER = $(SHELL) $(top_srcdir)/test-driver +TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \ + $(TEST_LOG_FLAGS) +am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/Makefile.in \ + $(srcdir)/config.h.in $(srcdir)/libpng-config.in \ + $(srcdir)/libpng.pc.in AUTHORS INSTALL README TODO compile \ + config.guess config.sub depcomp install-sh ltmain.sh missing \ + test-driver DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ - { test ! -d "$(distdir)" \ - || { find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ - && rm -fr "$(distdir)"; }; } -DIST_ARCHIVES = $(distdir).tar.gz + if test -d "$(distdir)"; then \ + find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -rf "$(distdir)" \ + || { sleep 5 && rm -rf "$(distdir)"; }; \ + else :; fi +am__post_remove_distdir = $(am__remove_distdir) +DIST_ARCHIVES = $(distdir).tar.gz $(distdir).tar.xz GZIP_ENV = --best +DIST_TARGETS = dist-xz dist-gzip distuninstallcheck_listfiles = find . -type f -print +am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ + | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print #distribute headers in /usr/include/libpng/* pkgincludedir = $(includedir)/$(PNGLIB_BASENAME) ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ @@ -172,6 +567,9 @@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ +CCAS = @CCAS@ +CCASDEPMODE = @CCASDEPMODE@ +CCASFLAGS = @CCASFLAGS@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ @@ -179,6 +577,13 @@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ + +# DFNCPP is normally just CPP - the C preprocessor - but on Solaris and maybe +# other operating systems (NeXT?) the C preprocessor selected by configure +# checks input tokens for validity - effectively it performs part of the ANSI-C +# parsing - and therefore fails with the .df files. configure.ac has special +# checks for this and sets DFNCPP appropriately. +DFNCPP = @DFNCPP@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ @@ -197,15 +602,15 @@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ -LIBPNG_DEFINES = @LIBPNG_DEFINES@ -LIBPNG_NO_MMX = @LIBPNG_NO_MMX@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ MAINT = @MAINT@ MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ @@ -225,6 +630,12 @@ PNGLIB_MAJOR = @PNGLIB_MAJOR@ PNGLIB_MINOR = @PNGLIB_MINOR@ PNGLIB_RELEASE = @PNGLIB_RELEASE@ PNGLIB_VERSION = @PNGLIB_VERSION@ + +# PNG_COPTS give extra options for the C compiler to be used on all compilation +# steps (unless targe_CFLAGS is specified; that will take precedence over +# AM_CFLAGS) +PNG_COPTS = @PNG_COPTS@ +PNG_PREFIX = @PNG_PREFIX@ POW_LIB = @POW_LIB@ RANLIB = @RANLIB@ SED = @SED@ @@ -237,6 +648,7 @@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ @@ -246,7 +658,7 @@ am__tar = @am__tar@ am__untar = @am__untar@ # generate the -config scripts if required -binconfigs = libpng12-config +binconfigs = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config bindir = @bindir@ build = @build@ build_alias = @build_alias@ @@ -254,7 +666,6 @@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ -compatlib = @compatlib@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ @@ -273,7 +684,6 @@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ -lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ @@ -294,80 +704,124 @@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ PNGLIB_BASENAME = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ +ACLOCAL_AMFLAGS = -I scripts -# libpng does not follow GNU file name conventions -AUTOMAKE_OPTIONS = foreign +# This ensures that pnglibconf.h gets built at the start of 'make all' or +# 'make check', but it does not add dependencies to the individual programs, +# this is done below. +# +# IMPORTANT: always add the object modules of new programs to the list below +# because otherwise the sequence 'configure; make new-program' will *sometimes* +# result in the installed (system) pnglibconf.h being used and the result is +# always wrong and always very confusing. +BUILT_SOURCES = pnglibconf.h pngtest_SOURCES = pngtest.c -pngtest_LDADD = libpng12.la -TESTS = test-pngtest.sh -TESTS_ENVIRONMENT = srcdir=$(srcdir) +pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +pngvalid_SOURCES = contrib/libtests/pngvalid.c +pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +pngstest_SOURCES = contrib/libtests/pngstest.c +pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +pngunknown_SOURCES = contrib/libtests/pngunknown.c +pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +pngimage_SOURCES = contrib/libtests/pngimage.c +pngimage_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +timepng_SOURCES = contrib/libtests/timepng.c +timepng_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +pngfix_SOURCES = contrib/tools/pngfix.c +pngfix_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +png_fix_itxt_SOURCES = contrib/tools/png-fix-itxt.c +pngcp_SOURCES = contrib/tools/pngcp.c +pngcp_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +# Generally these are single line shell scripts to run a test with a particular +# set of parameters: +TESTS = \ + tests/pngtest\ + tests/pngtest-badpngs\ + tests/pngvalid-gamma-16-to-8 tests/pngvalid-gamma-alpha-mode\ + tests/pngvalid-gamma-background tests/pngvalid-gamma-expand16-alpha-mode\ + tests/pngvalid-gamma-expand16-background\ + tests/pngvalid-gamma-expand16-transform tests/pngvalid-gamma-sbit\ + tests/pngvalid-gamma-threshold tests/pngvalid-gamma-transform\ + tests/pngvalid-progressive-size\ + tests/pngvalid-progressive-interlace-standard\ + tests/pngvalid-transform\ + tests/pngvalid-progressive-standard tests/pngvalid-standard\ + tests/pngstest-1.8 tests/pngstest-1.8-alpha tests/pngstest-linear\ + tests/pngstest-linear-alpha tests/pngstest-none tests/pngstest-none-alpha\ + tests/pngstest-sRGB tests/pngstest-sRGB-alpha tests/pngunknown-IDAT\ + tests/pngunknown-discard tests/pngunknown-if-safe tests/pngunknown-sAPI\ + tests/pngunknown-sTER tests/pngunknown-save tests/pngunknown-vpAg\ + tests/pngimage-quick tests/pngimage-full + # man pages dist_man_MANS = libpng.3 libpngpf.3 png.5 -EXTRA_SCRIPTS = libpng-config libpng12-config +EXTRA_SCRIPTS = libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config bin_SCRIPTS = @binconfigs@ # rules to build libpng, only build the old library on request -lib_LTLIBRARIES = libpng12.la @compatlib@ -EXTRA_LTLIBRARIES = libpng.la -libpng12_la_SOURCES = png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \ - pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \ - pngwtran.c pngmem.c pngerror.c pngpread.c \ - png.h pngconf.h - -libpng_la_SOURCES = $(libpng12_la_SOURCES) -libpng_la_CPPFLAGS = @LIBPNG_DEFINES@ -libpng12_la_CPPFLAGS = @LIBPNG_DEFINES@ - -# MAJOR UPGRADE: the version-number settings below must be changed. -libpng12_la_LDFLAGS = -no-undefined -export-dynamic -version-number \ - 0:@PNGLIB_RELEASE@:0 $(am__append_1) $(am__append_2) -# -rpath is needed as automake doesn't know the directory -libpng_la_LDFLAGS = -rpath '$(libdir)' -no-undefined -export-dynamic \ - -version-number 3:@PNGLIB_RELEASE@:0 - -@HAVE_LD_VERSION_SCRIPT_FALSE@libpng12_la_DEPENDENCIES = libpng.sym -@HAVE_LD_VERSION_SCRIPT_TRUE@libpng12_la_DEPENDENCIES = libpng.vers -libpng_la_DEPENDENCIES = $(libpng12_la_DEPENDENCIES) - -# Avoid depending upon Character Ranges. -AN = '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789' +lib_LTLIBRARIES = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +# EXTRA_LTLIBRARIES= libpng.la +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c \ + pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c \ + pngrutil.c pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c \ + pngwutil.c png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h \ + pngstruct.h pngusr.dfa $(am__append_2) $(am__append_3) \ + $(am__append_4) $(am__append_5) +nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined \ + -export-dynamic -version-number \ + @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0 \ + $(am__append_6) $(am__append_7) $(am__append_8) +@HAVE_LD_VERSION_SCRIPT_FALSE@libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym +@HAVE_LD_VERSION_SCRIPT_TRUE@libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.vers pkginclude_HEADERS = png.h pngconf.h -pkgconfig_DATA = libpng12.pc +nodist_pkginclude_HEADERS = pnglibconf.h +pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc -#extra source distribution files. +# Extra source distribution files, '${srcdir}' is used below to stop build files +# from those directories being included. This only works if the configure is +# not done in the source directory! EXTRA_DIST = \ - ANNOUNCE CHANGES INSTALL KNOWNBUG LICENSE README TODO Y2KINFO \ - CMakeLists.txt \ + ANNOUNCE AUTHORS CHANGES INSTALL LICENSE README TODO TRADEMARK \ pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \ - ${srcdir}/projects/cbuilder5/* \ - ${srcdir}/projects/beos/* \ - ${srcdir}/projects/visualc6/* \ - ${srcdir}/projects/visualc71/* \ - ${srcdir}/projects/wince.txt \ - ${srcdir}/projects/xcode/* \ - ${srcdir}/projects/netware.txt \ - ${srcdir}/scripts/* \ - ${srcdir}/contrib/gregbook/* \ - ${srcdir}/contrib/pngminim/* \ - ${srcdir}/contrib/pngminus/* \ - ${srcdir}/contrib/pngsuite/* \ - ${srcdir}/contrib/visupng/* \ - $(TESTS) \ - example.c libpng-1.2.46.txt pnggccrd.c pngvcrd.c + ${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \ + $(TESTS) $(XFAIL_TESTS) tests/pngstest \ + CMakeLists.txt example.c libpng-manual.txt -CLEANFILES = pngout.png libpng12.pc libpng12-config libpng.vers \ -libpng.sym +SCRIPT_CLEANFILES = scripts/*.out scripts/*.chk +CLEANFILES = *.tf? pngout.png libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config libpng.vers libpng.sym \ + check.new pnglibconf.h pngprefix.h symbols.new pngtest-log.txt \ + pnglibconf.out pnglibconf.c pnglibconf.pre pnglibconf.dfn \ + $(SCRIPT_CLEANFILES) MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \ config.sub configure depcomp install-sh ltmain.sh missing -all: config.h +AM_CFLAGS = ${PNG_COPTS} +SUFFIXES = .chk .out + +# We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually +# be built with PNG_USE_READ_MACROS; this prevents the read macros from +# interfering with the symbol file format. +SYMBOL_CFLAGS = -DPNGLIB_LIBNAME='PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0' \ + -DPNGLIB_VERSION='@PNGLIB_VERSION@' \ + -DSYMBOL_PREFIX='$(SYMBOL_PREFIX)' -DPNG_NO_USE_READ_MACROS \ + -DPNG_BUILDING_SYMBOL_TABLE $(am__append_9) + +# EXT_LIST is a list of the possibly library directory extensions, this exists +# because we can't find a good way of discovering the file extensions that are +# actually installed on a given system, so instead we check for every extension +# we have seen. +EXT_LIST = a dll.a so so.@PNGLIB_MAJOR@@PNGLIB_MINOR@.@PNGLIB_RELEASE@ la sl dylib +all: $(BUILT_SOURCES) config.h $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: -.SUFFIXES: .c .lo .o .obj -am--refresh: +.SUFFIXES: .chk .out .S .c .lo .log .o .obj .test .test$(EXEEXT) .trs +am--refresh: Makefile @: $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ @@ -382,15 +836,14 @@ $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__confi echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile -.PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ - echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ - cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) @@ -403,28 +856,84 @@ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) $(am__aclocal_m4_deps): config.h: stamp-h1 - @if test ! -f $@; then \ - rm -f stamp-h1; \ - $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ - else :; fi + @test -f $@ || rm -f stamp-h1 + @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h -$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) +$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 -libpng.pc: $(top_builddir)/config.status $(top_srcdir)/scripts/libpng.pc-configure.in +libpng.pc: $(top_builddir)/config.status $(srcdir)/libpng.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ -libpng-config: $(top_builddir)/config.status $(top_srcdir)/scripts/libpng-config.in +libpng-config: $(top_builddir)/config.status $(srcdir)/libpng-config.in cd $(top_builddir) && $(SHELL) ./config.status $@ +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +clean-checkPROGRAMS: + @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) - test -z "$(libdir)" || $(MKDIR_P) "$(DESTDIR)$(libdir)" @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ @@ -432,6 +941,8 @@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) else :; fi; \ done; \ test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } @@ -447,32 +958,130 @@ uninstall-libLTLIBRARIES: clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) - @list='$(lib_LTLIBRARIES)'; for p in $$list; do \ - dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ - test "$$dir" != "$$p" || dir=.; \ - echo "rm -f \"$${dir}/so_locations\""; \ - rm -f "$${dir}/so_locations"; \ - done -libpng.la: $(libpng_la_OBJECTS) $(libpng_la_DEPENDENCIES) - $(libpng_la_LINK) $(libpng_la_OBJECTS) $(libpng_la_LIBADD) $(LIBS) -libpng12.la: $(libpng12_la_OBJECTS) $(libpng12_la_DEPENDENCIES) - $(libpng12_la_LINK) -rpath $(libdir) $(libpng12_la_OBJECTS) $(libpng12_la_LIBADD) $(LIBS) + @list='$(lib_LTLIBRARIES)'; \ + locs=`for p in $$list; do echo $$p; done | \ + sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ + sort -u`; \ + test -z "$$locs" || { \ + echo rm -f $${locs}; \ + rm -f $${locs}; \ + } +arm/$(am__dirstamp): + @$(MKDIR_P) arm + @: > arm/$(am__dirstamp) +arm/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) arm/$(DEPDIR) + @: > arm/$(DEPDIR)/$(am__dirstamp) +arm/arm_init.lo: arm/$(am__dirstamp) arm/$(DEPDIR)/$(am__dirstamp) +arm/filter_neon.lo: arm/$(am__dirstamp) arm/$(DEPDIR)/$(am__dirstamp) +arm/filter_neon_intrinsics.lo: arm/$(am__dirstamp) \ + arm/$(DEPDIR)/$(am__dirstamp) +arm/palette_neon_intrinsics.lo: arm/$(am__dirstamp) \ + arm/$(DEPDIR)/$(am__dirstamp) +mips/$(am__dirstamp): + @$(MKDIR_P) mips + @: > mips/$(am__dirstamp) +mips/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) mips/$(DEPDIR) + @: > mips/$(DEPDIR)/$(am__dirstamp) +mips/mips_init.lo: mips/$(am__dirstamp) mips/$(DEPDIR)/$(am__dirstamp) +mips/filter_msa_intrinsics.lo: mips/$(am__dirstamp) \ + mips/$(DEPDIR)/$(am__dirstamp) +intel/$(am__dirstamp): + @$(MKDIR_P) intel + @: > intel/$(am__dirstamp) +intel/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) intel/$(DEPDIR) + @: > intel/$(DEPDIR)/$(am__dirstamp) +intel/intel_init.lo: intel/$(am__dirstamp) \ + intel/$(DEPDIR)/$(am__dirstamp) +intel/filter_sse2_intrinsics.lo: intel/$(am__dirstamp) \ + intel/$(DEPDIR)/$(am__dirstamp) +powerpc/$(am__dirstamp): + @$(MKDIR_P) powerpc + @: > powerpc/$(am__dirstamp) +powerpc/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) powerpc/$(DEPDIR) + @: > powerpc/$(DEPDIR)/$(am__dirstamp) +powerpc/powerpc_init.lo: powerpc/$(am__dirstamp) \ + powerpc/$(DEPDIR)/$(am__dirstamp) +powerpc/filter_vsx_intrinsics.lo: powerpc/$(am__dirstamp) \ + powerpc/$(DEPDIR)/$(am__dirstamp) -clean-checkPROGRAMS: - @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \ - echo " rm -f" $$list; \ - rm -f $$list || exit $$?; \ - test -n "$(EXEEXT)" || exit 0; \ - list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ - echo " rm -f" $$list; \ - rm -f $$list -pngtest$(EXEEXT): $(pngtest_OBJECTS) $(pngtest_DEPENDENCIES) +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la: $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES) $(EXTRA_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES) + $(AM_V_CCLD)$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LINK) -rpath $(libdir) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS) $(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LIBADD) $(LIBS) +contrib/tools/$(am__dirstamp): + @$(MKDIR_P) contrib/tools + @: > contrib/tools/$(am__dirstamp) +contrib/tools/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) contrib/tools/$(DEPDIR) + @: > contrib/tools/$(DEPDIR)/$(am__dirstamp) +contrib/tools/png-fix-itxt.$(OBJEXT): contrib/tools/$(am__dirstamp) \ + contrib/tools/$(DEPDIR)/$(am__dirstamp) + +png-fix-itxt$(EXEEXT): $(png_fix_itxt_OBJECTS) $(png_fix_itxt_DEPENDENCIES) $(EXTRA_png_fix_itxt_DEPENDENCIES) + @rm -f png-fix-itxt$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(png_fix_itxt_OBJECTS) $(png_fix_itxt_LDADD) $(LIBS) +contrib/tools/pngcp.$(OBJEXT): contrib/tools/$(am__dirstamp) \ + contrib/tools/$(DEPDIR)/$(am__dirstamp) + +pngcp$(EXEEXT): $(pngcp_OBJECTS) $(pngcp_DEPENDENCIES) $(EXTRA_pngcp_DEPENDENCIES) + @rm -f pngcp$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pngcp_OBJECTS) $(pngcp_LDADD) $(LIBS) +contrib/tools/pngfix.$(OBJEXT): contrib/tools/$(am__dirstamp) \ + contrib/tools/$(DEPDIR)/$(am__dirstamp) + +pngfix$(EXEEXT): $(pngfix_OBJECTS) $(pngfix_DEPENDENCIES) $(EXTRA_pngfix_DEPENDENCIES) + @rm -f pngfix$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pngfix_OBJECTS) $(pngfix_LDADD) $(LIBS) +contrib/libtests/$(am__dirstamp): + @$(MKDIR_P) contrib/libtests + @: > contrib/libtests/$(am__dirstamp) +contrib/libtests/$(DEPDIR)/$(am__dirstamp): + @$(MKDIR_P) contrib/libtests/$(DEPDIR) + @: > contrib/libtests/$(DEPDIR)/$(am__dirstamp) +contrib/libtests/pngimage.$(OBJEXT): contrib/libtests/$(am__dirstamp) \ + contrib/libtests/$(DEPDIR)/$(am__dirstamp) + +pngimage$(EXEEXT): $(pngimage_OBJECTS) $(pngimage_DEPENDENCIES) $(EXTRA_pngimage_DEPENDENCIES) + @rm -f pngimage$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pngimage_OBJECTS) $(pngimage_LDADD) $(LIBS) +contrib/libtests/pngstest.$(OBJEXT): contrib/libtests/$(am__dirstamp) \ + contrib/libtests/$(DEPDIR)/$(am__dirstamp) + +pngstest$(EXEEXT): $(pngstest_OBJECTS) $(pngstest_DEPENDENCIES) $(EXTRA_pngstest_DEPENDENCIES) + @rm -f pngstest$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pngstest_OBJECTS) $(pngstest_LDADD) $(LIBS) + +pngtest$(EXEEXT): $(pngtest_OBJECTS) $(pngtest_DEPENDENCIES) $(EXTRA_pngtest_DEPENDENCIES) @rm -f pngtest$(EXEEXT) - $(LINK) $(pngtest_OBJECTS) $(pngtest_LDADD) $(LIBS) + $(AM_V_CCLD)$(LINK) $(pngtest_OBJECTS) $(pngtest_LDADD) $(LIBS) +contrib/libtests/pngunknown.$(OBJEXT): \ + contrib/libtests/$(am__dirstamp) \ + contrib/libtests/$(DEPDIR)/$(am__dirstamp) + +pngunknown$(EXEEXT): $(pngunknown_OBJECTS) $(pngunknown_DEPENDENCIES) $(EXTRA_pngunknown_DEPENDENCIES) + @rm -f pngunknown$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pngunknown_OBJECTS) $(pngunknown_LDADD) $(LIBS) +contrib/libtests/pngvalid.$(OBJEXT): contrib/libtests/$(am__dirstamp) \ + contrib/libtests/$(DEPDIR)/$(am__dirstamp) + +pngvalid$(EXEEXT): $(pngvalid_OBJECTS) $(pngvalid_DEPENDENCIES) $(EXTRA_pngvalid_DEPENDENCIES) + @rm -f pngvalid$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(pngvalid_OBJECTS) $(pngvalid_LDADD) $(LIBS) +contrib/libtests/timepng.$(OBJEXT): contrib/libtests/$(am__dirstamp) \ + contrib/libtests/$(DEPDIR)/$(am__dirstamp) + +timepng$(EXEEXT): $(timepng_OBJECTS) $(timepng_DEPENDENCIES) $(EXTRA_timepng_DEPENDENCIES) + @rm -f timepng$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(timepng_OBJECTS) $(timepng_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) - test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ @@ -500,294 +1109,139 @@ uninstall-binSCRIPTS: @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ - test -n "$$list" || exit 0; \ - echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(bindir)" && rm -f $$files + dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) + -rm -f arm/*.$(OBJEXT) + -rm -f arm/*.lo + -rm -f contrib/libtests/*.$(OBJEXT) + -rm -f contrib/tools/*.$(OBJEXT) + -rm -f intel/*.$(OBJEXT) + -rm -f intel/*.lo + -rm -f mips/*.$(OBJEXT) + -rm -f mips/*.lo + -rm -f powerpc/*.$(OBJEXT) + -rm -f powerpc/*.lo distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-png.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngerror.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngget.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngmem.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngpread.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngread.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngrio.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngrtran.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngrutil.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngset.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngtrans.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngwio.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngwrite.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngwtran.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng12_la-pngwutil.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-png.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngerror.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngget.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngmem.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngpread.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngread.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngrio.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngrtran.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngrutil.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngset.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngtrans.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngwio.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngwrite.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngwtran.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libpng_la-pngwutil.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngtest.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/png.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngerror.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngget.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngmem.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngpread.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngread.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngrio.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngrtran.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngrutil.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngset.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngtest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngtrans.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngwio.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngwrite.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngwtran.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pngwutil.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@arm/$(DEPDIR)/arm_init.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@arm/$(DEPDIR)/filter_neon.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@arm/$(DEPDIR)/filter_neon_intrinsics.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@arm/$(DEPDIR)/palette_neon_intrinsics.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/libtests/$(DEPDIR)/pngimage.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/libtests/$(DEPDIR)/pngstest.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/libtests/$(DEPDIR)/pngunknown.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/libtests/$(DEPDIR)/pngvalid.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/libtests/$(DEPDIR)/timepng.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/tools/$(DEPDIR)/png-fix-itxt.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/tools/$(DEPDIR)/pngcp.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@contrib/tools/$(DEPDIR)/pngfix.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@intel/$(DEPDIR)/filter_sse2_intrinsics.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@intel/$(DEPDIR)/intel_init.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@mips/$(DEPDIR)/filter_msa_intrinsics.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@mips/$(DEPDIR)/mips_init.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@powerpc/$(DEPDIR)/powerpc_init.Plo@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.S.o: +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ $< + +.S.obj: +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCCAS_TRUE@ $(CPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CPPASCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.S.lo: +@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCCAS_TRUE@ $(LTCPPASCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCCAS_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(LTCPPASCOMPILE) -c -o $@ $< .c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ +@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ +@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ +@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< - -libpng_la-png.lo: png.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-png.lo -MD -MP -MF $(DEPDIR)/libpng_la-png.Tpo -c -o libpng_la-png.lo `test -f 'png.c' || echo '$(srcdir)/'`png.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-png.Tpo $(DEPDIR)/libpng_la-png.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='png.c' object='libpng_la-png.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-png.lo `test -f 'png.c' || echo '$(srcdir)/'`png.c - -libpng_la-pngset.lo: pngset.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngset.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngset.Tpo -c -o libpng_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngset.Tpo $(DEPDIR)/libpng_la-pngset.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngset.c' object='libpng_la-pngset.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c - -libpng_la-pngget.lo: pngget.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngget.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngget.Tpo -c -o libpng_la-pngget.lo `test -f 'pngget.c' || echo '$(srcdir)/'`pngget.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngget.Tpo $(DEPDIR)/libpng_la-pngget.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngget.c' object='libpng_la-pngget.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngget.lo `test -f 'pngget.c' || echo '$(srcdir)/'`pngget.c - -libpng_la-pngrutil.lo: pngrutil.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngrutil.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngrutil.Tpo -c -o libpng_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngrutil.Tpo $(DEPDIR)/libpng_la-pngrutil.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrutil.c' object='libpng_la-pngrutil.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c - -libpng_la-pngtrans.lo: pngtrans.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngtrans.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngtrans.Tpo -c -o libpng_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngtrans.Tpo $(DEPDIR)/libpng_la-pngtrans.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngtrans.c' object='libpng_la-pngtrans.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c - -libpng_la-pngwutil.lo: pngwutil.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngwutil.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngwutil.Tpo -c -o libpng_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngwutil.Tpo $(DEPDIR)/libpng_la-pngwutil.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwutil.c' object='libpng_la-pngwutil.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c - -libpng_la-pngread.lo: pngread.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngread.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngread.Tpo -c -o libpng_la-pngread.lo `test -f 'pngread.c' || echo '$(srcdir)/'`pngread.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngread.Tpo $(DEPDIR)/libpng_la-pngread.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngread.c' object='libpng_la-pngread.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngread.lo `test -f 'pngread.c' || echo '$(srcdir)/'`pngread.c - -libpng_la-pngrio.lo: pngrio.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngrio.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngrio.Tpo -c -o libpng_la-pngrio.lo `test -f 'pngrio.c' || echo '$(srcdir)/'`pngrio.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngrio.Tpo $(DEPDIR)/libpng_la-pngrio.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrio.c' object='libpng_la-pngrio.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngrio.lo `test -f 'pngrio.c' || echo '$(srcdir)/'`pngrio.c - -libpng_la-pngwio.lo: pngwio.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngwio.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngwio.Tpo -c -o libpng_la-pngwio.lo `test -f 'pngwio.c' || echo '$(srcdir)/'`pngwio.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngwio.Tpo $(DEPDIR)/libpng_la-pngwio.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwio.c' object='libpng_la-pngwio.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngwio.lo `test -f 'pngwio.c' || echo '$(srcdir)/'`pngwio.c - -libpng_la-pngwrite.lo: pngwrite.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngwrite.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngwrite.Tpo -c -o libpng_la-pngwrite.lo `test -f 'pngwrite.c' || echo '$(srcdir)/'`pngwrite.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngwrite.Tpo $(DEPDIR)/libpng_la-pngwrite.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwrite.c' object='libpng_la-pngwrite.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngwrite.lo `test -f 'pngwrite.c' || echo '$(srcdir)/'`pngwrite.c - -libpng_la-pngrtran.lo: pngrtran.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngrtran.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngrtran.Tpo -c -o libpng_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngrtran.Tpo $(DEPDIR)/libpng_la-pngrtran.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrtran.c' object='libpng_la-pngrtran.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c - -libpng_la-pngwtran.lo: pngwtran.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngwtran.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngwtran.Tpo -c -o libpng_la-pngwtran.lo `test -f 'pngwtran.c' || echo '$(srcdir)/'`pngwtran.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngwtran.Tpo $(DEPDIR)/libpng_la-pngwtran.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwtran.c' object='libpng_la-pngwtran.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngwtran.lo `test -f 'pngwtran.c' || echo '$(srcdir)/'`pngwtran.c - -libpng_la-pngmem.lo: pngmem.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngmem.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngmem.Tpo -c -o libpng_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngmem.Tpo $(DEPDIR)/libpng_la-pngmem.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngmem.c' object='libpng_la-pngmem.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c - -libpng_la-pngerror.lo: pngerror.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngerror.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngerror.Tpo -c -o libpng_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngerror.Tpo $(DEPDIR)/libpng_la-pngerror.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngerror.c' object='libpng_la-pngerror.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c - -libpng_la-pngpread.lo: pngpread.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng_la-pngpread.lo -MD -MP -MF $(DEPDIR)/libpng_la-pngpread.Tpo -c -o libpng_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng_la-pngpread.Tpo $(DEPDIR)/libpng_la-pngpread.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngpread.c' object='libpng_la-pngpread.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c - -libpng12_la-png.lo: png.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-png.lo -MD -MP -MF $(DEPDIR)/libpng12_la-png.Tpo -c -o libpng12_la-png.lo `test -f 'png.c' || echo '$(srcdir)/'`png.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-png.Tpo $(DEPDIR)/libpng12_la-png.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='png.c' object='libpng12_la-png.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-png.lo `test -f 'png.c' || echo '$(srcdir)/'`png.c - -libpng12_la-pngset.lo: pngset.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngset.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngset.Tpo -c -o libpng12_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngset.Tpo $(DEPDIR)/libpng12_la-pngset.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngset.c' object='libpng12_la-pngset.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngset.lo `test -f 'pngset.c' || echo '$(srcdir)/'`pngset.c - -libpng12_la-pngget.lo: pngget.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngget.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngget.Tpo -c -o libpng12_la-pngget.lo `test -f 'pngget.c' || echo '$(srcdir)/'`pngget.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngget.Tpo $(DEPDIR)/libpng12_la-pngget.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngget.c' object='libpng12_la-pngget.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngget.lo `test -f 'pngget.c' || echo '$(srcdir)/'`pngget.c - -libpng12_la-pngrutil.lo: pngrutil.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngrutil.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngrutil.Tpo -c -o libpng12_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngrutil.Tpo $(DEPDIR)/libpng12_la-pngrutil.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrutil.c' object='libpng12_la-pngrutil.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngrutil.lo `test -f 'pngrutil.c' || echo '$(srcdir)/'`pngrutil.c - -libpng12_la-pngtrans.lo: pngtrans.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngtrans.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngtrans.Tpo -c -o libpng12_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngtrans.Tpo $(DEPDIR)/libpng12_la-pngtrans.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngtrans.c' object='libpng12_la-pngtrans.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngtrans.lo `test -f 'pngtrans.c' || echo '$(srcdir)/'`pngtrans.c - -libpng12_la-pngwutil.lo: pngwutil.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngwutil.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngwutil.Tpo -c -o libpng12_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngwutil.Tpo $(DEPDIR)/libpng12_la-pngwutil.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwutil.c' object='libpng12_la-pngwutil.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngwutil.lo `test -f 'pngwutil.c' || echo '$(srcdir)/'`pngwutil.c - -libpng12_la-pngread.lo: pngread.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngread.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngread.Tpo -c -o libpng12_la-pngread.lo `test -f 'pngread.c' || echo '$(srcdir)/'`pngread.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngread.Tpo $(DEPDIR)/libpng12_la-pngread.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngread.c' object='libpng12_la-pngread.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngread.lo `test -f 'pngread.c' || echo '$(srcdir)/'`pngread.c - -libpng12_la-pngrio.lo: pngrio.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngrio.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngrio.Tpo -c -o libpng12_la-pngrio.lo `test -f 'pngrio.c' || echo '$(srcdir)/'`pngrio.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngrio.Tpo $(DEPDIR)/libpng12_la-pngrio.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrio.c' object='libpng12_la-pngrio.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngrio.lo `test -f 'pngrio.c' || echo '$(srcdir)/'`pngrio.c - -libpng12_la-pngwio.lo: pngwio.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngwio.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngwio.Tpo -c -o libpng12_la-pngwio.lo `test -f 'pngwio.c' || echo '$(srcdir)/'`pngwio.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngwio.Tpo $(DEPDIR)/libpng12_la-pngwio.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwio.c' object='libpng12_la-pngwio.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngwio.lo `test -f 'pngwio.c' || echo '$(srcdir)/'`pngwio.c - -libpng12_la-pngwrite.lo: pngwrite.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngwrite.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngwrite.Tpo -c -o libpng12_la-pngwrite.lo `test -f 'pngwrite.c' || echo '$(srcdir)/'`pngwrite.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngwrite.Tpo $(DEPDIR)/libpng12_la-pngwrite.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwrite.c' object='libpng12_la-pngwrite.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngwrite.lo `test -f 'pngwrite.c' || echo '$(srcdir)/'`pngwrite.c - -libpng12_la-pngrtran.lo: pngrtran.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngrtran.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngrtran.Tpo -c -o libpng12_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngrtran.Tpo $(DEPDIR)/libpng12_la-pngrtran.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngrtran.c' object='libpng12_la-pngrtran.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngrtran.lo `test -f 'pngrtran.c' || echo '$(srcdir)/'`pngrtran.c - -libpng12_la-pngwtran.lo: pngwtran.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngwtran.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngwtran.Tpo -c -o libpng12_la-pngwtran.lo `test -f 'pngwtran.c' || echo '$(srcdir)/'`pngwtran.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngwtran.Tpo $(DEPDIR)/libpng12_la-pngwtran.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngwtran.c' object='libpng12_la-pngwtran.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngwtran.lo `test -f 'pngwtran.c' || echo '$(srcdir)/'`pngwtran.c - -libpng12_la-pngmem.lo: pngmem.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngmem.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngmem.Tpo -c -o libpng12_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngmem.Tpo $(DEPDIR)/libpng12_la-pngmem.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngmem.c' object='libpng12_la-pngmem.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngmem.lo `test -f 'pngmem.c' || echo '$(srcdir)/'`pngmem.c - -libpng12_la-pngerror.lo: pngerror.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngerror.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngerror.Tpo -c -o libpng12_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngerror.Tpo $(DEPDIR)/libpng12_la-pngerror.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngerror.c' object='libpng12_la-pngerror.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngerror.lo `test -f 'pngerror.c' || echo '$(srcdir)/'`pngerror.c - -libpng12_la-pngpread.lo: pngpread.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT libpng12_la-pngpread.lo -MD -MP -MF $(DEPDIR)/libpng12_la-pngpread.Tpo -c -o libpng12_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/libpng12_la-pngpread.Tpo $(DEPDIR)/libpng12_la-pngpread.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='pngpread.c' object='libpng12_la-pngpread.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libpng12_la_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o libpng12_la-pngpread.lo `test -f 'pngpread.c' || echo '$(srcdir)/'`pngpread.c +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs + -rm -rf arm/.libs arm/_libs + -rm -rf intel/.libs intel/_libs + -rm -rf mips/.libs mips/_libs + -rm -rf powerpc/.libs powerpc/_libs distclean-libtool: -rm -f libtool config.lt install-man3: $(dist_man_MANS) @$(NORMAL_INSTALL) - test -z "$(man3dir)" || $(MKDIR_P) "$(DESTDIR)$(man3dir)" - @list=''; test -n "$(man3dir)" || exit 0; \ - { for i in $$list; do echo "$$i"; done; \ - l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ - sed -n '/\.3[a-z]*$$/p'; \ + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man3dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man3dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man3dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.3[a-z]*$$/p'; \ + fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ @@ -816,16 +1270,21 @@ uninstall-man3: sed -n '/\.3[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^3][0-9a-z]*$$,3,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ - test -z "$$files" || { \ - echo " ( cd '$(DESTDIR)$(man3dir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(man3dir)" && rm -f $$files; } + dir='$(DESTDIR)$(man3dir)'; $(am__uninstall_files_from_dir) install-man5: $(dist_man_MANS) @$(NORMAL_INSTALL) - test -z "$(man5dir)" || $(MKDIR_P) "$(DESTDIR)$(man5dir)" - @list=''; test -n "$(man5dir)" || exit 0; \ - { for i in $$list; do echo "$$i"; done; \ - l2='$(dist_man_MANS)'; for i in $$l2; do echo "$$i"; done | \ - sed -n '/\.5[a-z]*$$/p'; \ + @list1=''; \ + list2='$(dist_man_MANS)'; \ + test -n "$(man5dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.5[a-z]*$$/p'; \ + fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ @@ -854,13 +1313,14 @@ uninstall-man5: sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ - test -z "$$files" || { \ - echo " ( cd '$(DESTDIR)$(man5dir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(man5dir)" && rm -f $$files; } + dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) - test -z "$(pkgconfigdir)" || $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -874,13 +1334,35 @@ uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(pkgconfigdir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(pkgconfigdir)" && rm -f $$files + dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) +install-nodist_pkgincludeHEADERS: $(nodist_pkginclude_HEADERS) + @$(NORMAL_INSTALL) + @list='$(nodist_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ + fi; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(pkgincludedir)'"; \ + $(INSTALL_HEADER) $$files "$(DESTDIR)$(pkgincludedir)" || exit $$?; \ + done + +uninstall-nodist_pkgincludeHEADERS: + @$(NORMAL_UNINSTALL) + @list='$(nodist_pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) install-pkgincludeHEADERS: $(pkginclude_HEADERS) @$(NORMAL_INSTALL) - test -z "$(pkgincludedir)" || $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(pkgincludedir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(pkgincludedir)" || exit 1; \ + fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ @@ -894,30 +1376,17 @@ uninstall-pkgincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(pkginclude_HEADERS)'; test -n "$(pkgincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ - test -n "$$files" || exit 0; \ - echo " ( cd '$(DESTDIR)$(pkgincludedir)' && rm -f" $$files ")"; \ - cd "$(DESTDIR)$(pkgincludedir)" && rm -f $$files + dir='$(DESTDIR)$(pkgincludedir)'; $(am__uninstall_files_from_dir) -ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) - list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ - mkid -fID $$unique -tags: TAGS +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags -TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ - list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ + $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ @@ -929,15 +1398,11 @@ TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ $$unique; \ fi; \ fi -ctags: CTAGS -CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ - $(TAGS_FILES) $(LISP) - list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ - unique=`for i in $$list; do \ - if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ - done | \ - $(AWK) '{ files[$$0] = 1; nonempty = 1; } \ - END { if (nonempty) { for (i in files) print i; }; }'`; \ +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique @@ -946,116 +1411,423 @@ GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" +cscope: cscope.files + test ! -s cscope.files \ + || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) +clean-cscope: + -rm -f cscope.files +cscope.files: clean-cscope cscopelist +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + -rm -f cscope.out cscope.in.out cscope.po.out cscope.files -check-TESTS: $(TESTS) - @failed=0; all=0; xfail=0; xpass=0; skip=0; \ - srcdir=$(srcdir); export srcdir; \ - list=' $(TESTS) '; \ - $(am__tty_colors); \ - if test -n "$$list"; then \ - for tst in $$list; do \ - if test -f ./$$tst; then dir=./; \ - elif test -f $$tst; then dir=; \ - else dir="$(srcdir)/"; fi; \ - if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xpass=`expr $$xpass + 1`; \ - failed=`expr $$failed + 1`; \ - col=$$red; res=XPASS; \ - ;; \ - *) \ - col=$$grn; res=PASS; \ - ;; \ - esac; \ - elif test $$? -ne 77; then \ - all=`expr $$all + 1`; \ - case " $(XFAIL_TESTS) " in \ - *[\ \ ]$$tst[\ \ ]*) \ - xfail=`expr $$xfail + 1`; \ - col=$$lgn; res=XFAIL; \ - ;; \ - *) \ - failed=`expr $$failed + 1`; \ - col=$$red; res=FAIL; \ - ;; \ - esac; \ - else \ - skip=`expr $$skip + 1`; \ - col=$$blu; res=SKIP; \ - fi; \ - echo "$${col}$$res$${std}: $$tst"; \ +# Recover from deleted '.trs' file; this should ensure that +# "rm -f foo.log; make foo.trs" re-run 'foo.test', and re-create +# both 'foo.log' and 'foo.trs'. Break the recipe in two subshells +# to avoid problems with "make -n". +.log.trs: + rm -f $< $@ + $(MAKE) $(AM_MAKEFLAGS) $< + +# Leading 'am--fnord' is there to ensure the list of targets does not +# expand to empty, as could happen e.g. with make check TESTS=''. +am--fnord $(TEST_LOGS) $(TEST_LOGS:.log=.trs): $(am__force_recheck) +am--force-recheck: + @: + +$(TEST_SUITE_LOG): $(TEST_LOGS) + @$(am__set_TESTS_bases); \ + am__f_ok () { test -f "$$1" && test -r "$$1"; }; \ + redo_bases=`for i in $$bases; do \ + am__f_ok $$i.trs && am__f_ok $$i.log || echo $$i; \ + done`; \ + if test -n "$$redo_bases"; then \ + redo_logs=`for i in $$redo_bases; do echo $$i.log; done`; \ + redo_results=`for i in $$redo_bases; do echo $$i.trs; done`; \ + if $(am__make_dryrun); then :; else \ + rm -f $$redo_logs && rm -f $$redo_results || exit 1; \ + fi; \ + fi; \ + if test -n "$$am__remaking_logs"; then \ + echo "fatal: making $(TEST_SUITE_LOG): possible infinite" \ + "recursion detected" >&2; \ + elif test -n "$$redo_logs"; then \ + am__remaking_logs=yes $(MAKE) $(AM_MAKEFLAGS) $$redo_logs; \ + fi; \ + if $(am__make_dryrun); then :; else \ + st=0; \ + errmsg="fatal: making $(TEST_SUITE_LOG): failed to create"; \ + for i in $$redo_bases; do \ + test -f $$i.trs && test -r $$i.trs \ + || { echo "$$errmsg $$i.trs" >&2; st=1; }; \ + test -f $$i.log && test -r $$i.log \ + || { echo "$$errmsg $$i.log" >&2; st=1; }; \ done; \ - if test "$$all" -eq 1; then \ - tests="test"; \ - All=""; \ - else \ - tests="tests"; \ - All="All "; \ - fi; \ - if test "$$failed" -eq 0; then \ - if test "$$xfail" -eq 0; then \ - banner="$$All$$all $$tests passed"; \ + test $$st -eq 0 || exit 1; \ + fi + @$(am__sh_e_setup); $(am__tty_colors); $(am__set_TESTS_bases); \ + ws='[ ]'; \ + results=`for b in $$bases; do echo $$b.trs; done`; \ + test -n "$$results" || results=/dev/null; \ + all=` grep "^$$ws*:test-result:" $$results | wc -l`; \ + pass=` grep "^$$ws*:test-result:$$ws*PASS" $$results | wc -l`; \ + fail=` grep "^$$ws*:test-result:$$ws*FAIL" $$results | wc -l`; \ + skip=` grep "^$$ws*:test-result:$$ws*SKIP" $$results | wc -l`; \ + xfail=`grep "^$$ws*:test-result:$$ws*XFAIL" $$results | wc -l`; \ + xpass=`grep "^$$ws*:test-result:$$ws*XPASS" $$results | wc -l`; \ + error=`grep "^$$ws*:test-result:$$ws*ERROR" $$results | wc -l`; \ + if test `expr $$fail + $$xpass + $$error` -eq 0; then \ + success=true; \ + else \ + success=false; \ + fi; \ + br='==================='; br=$$br$$br$$br$$br; \ + result_count () \ + { \ + if test x"$$1" = x"--maybe-color"; then \ + maybe_colorize=yes; \ + elif test x"$$1" = x"--no-color"; then \ + maybe_colorize=no; \ else \ - if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \ - banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \ + echo "$@: invalid 'result_count' usage" >&2; exit 4; \ fi; \ - else \ - if test "$$xpass" -eq 0; then \ - banner="$$failed of $$all $$tests failed"; \ + shift; \ + desc=$$1 count=$$2; \ + if test $$maybe_colorize = yes && test $$count -gt 0; then \ + color_start=$$3 color_end=$$std; \ else \ - if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \ - banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \ + color_start= color_end=; \ fi; \ - fi; \ - dashes="$$banner"; \ - skipped=""; \ - if test "$$skip" -ne 0; then \ - if test "$$skip" -eq 1; then \ - skipped="($$skip test was not run)"; \ - else \ - skipped="($$skip tests were not run)"; \ - fi; \ - test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$skipped"; \ - fi; \ - report=""; \ - if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \ - report="Please report to $(PACKAGE_BUGREPORT)"; \ - test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \ - dashes="$$report"; \ - fi; \ - dashes=`echo "$$dashes" | sed s/./=/g`; \ - if test "$$failed" -eq 0; then \ - echo "$$grn$$dashes"; \ - else \ - echo "$$red$$dashes"; \ - fi; \ - echo "$$banner"; \ - test -z "$$skipped" || echo "$$skipped"; \ - test -z "$$report" || echo "$$report"; \ - echo "$$dashes$$std"; \ - test "$$failed" -eq 0; \ - else :; fi + echo "$${color_start}# $$desc $$count$${color_end}"; \ + }; \ + create_testsuite_report () \ + { \ + result_count $$1 "TOTAL:" $$all "$$brg"; \ + result_count $$1 "PASS: " $$pass "$$grn"; \ + result_count $$1 "SKIP: " $$skip "$$blu"; \ + result_count $$1 "XFAIL:" $$xfail "$$lgn"; \ + result_count $$1 "FAIL: " $$fail "$$red"; \ + result_count $$1 "XPASS:" $$xpass "$$red"; \ + result_count $$1 "ERROR:" $$error "$$mgn"; \ + }; \ + { \ + echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \ + $(am__rst_title); \ + create_testsuite_report --no-color; \ + echo; \ + echo ".. contents:: :depth: 2"; \ + echo; \ + for b in $$bases; do echo $$b; done \ + | $(am__create_global_log); \ + } >$(TEST_SUITE_LOG).tmp || exit 1; \ + mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \ + if $$success; then \ + col="$$grn"; \ + else \ + col="$$red"; \ + test x"$$VERBOSE" = x || cat $(TEST_SUITE_LOG); \ + fi; \ + echo "$${col}$$br$${std}"; \ + echo "$${col}Testsuite summary for $(PACKAGE_STRING)$${std}"; \ + echo "$${col}$$br$${std}"; \ + create_testsuite_report --maybe-color; \ + echo "$$col$$br$$std"; \ + if $$success; then :; else \ + echo "$${col}See $(subdir)/$(TEST_SUITE_LOG)$${std}"; \ + if test -n "$(PACKAGE_BUGREPORT)"; then \ + echo "$${col}Please report to $(PACKAGE_BUGREPORT)$${std}"; \ + fi; \ + echo "$$col$$br$$std"; \ + fi; \ + $$success || exit 1 -distdir: $(DISTFILES) - @list='$(MANS)'; if test -n "$$list"; then \ - list=`for p in $$list; do \ - if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ - if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ - if test -n "$$list" && \ - grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ - echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ - grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ - echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ - echo " typically \`make maintainer-clean' will remove them" >&2; \ - exit 1; \ - else :; fi; \ - else :; fi +check-TESTS: $(check_PROGRAMS) + @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list + @list='$(RECHECK_LOGS:.log=.trs)'; test -z "$$list" || rm -f $$list + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + trs_list=`for i in $$bases; do echo $$i.trs; done`; \ + log_list=`echo $$log_list`; trs_list=`echo $$trs_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) TEST_LOGS="$$log_list"; \ + exit $$?; +recheck: all $(check_PROGRAMS) + @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) + @set +e; $(am__set_TESTS_bases); \ + bases=`for i in $$bases; do echo $$i; done \ + | $(am__list_recheck_tests)` || exit 1; \ + log_list=`for i in $$bases; do echo $$i.log; done`; \ + log_list=`echo $$log_list`; \ + $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) \ + am__force_recheck=am--force-recheck \ + TEST_LOGS="$$log_list"; \ + exit $$? +tests/pngtest.log: tests/pngtest + @p='tests/pngtest'; \ + b='tests/pngtest'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngtest-badpngs.log: tests/pngtest-badpngs + @p='tests/pngtest-badpngs'; \ + b='tests/pngtest-badpngs'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-16-to-8.log: tests/pngvalid-gamma-16-to-8 + @p='tests/pngvalid-gamma-16-to-8'; \ + b='tests/pngvalid-gamma-16-to-8'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-alpha-mode.log: tests/pngvalid-gamma-alpha-mode + @p='tests/pngvalid-gamma-alpha-mode'; \ + b='tests/pngvalid-gamma-alpha-mode'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-background.log: tests/pngvalid-gamma-background + @p='tests/pngvalid-gamma-background'; \ + b='tests/pngvalid-gamma-background'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-expand16-alpha-mode.log: tests/pngvalid-gamma-expand16-alpha-mode + @p='tests/pngvalid-gamma-expand16-alpha-mode'; \ + b='tests/pngvalid-gamma-expand16-alpha-mode'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-expand16-background.log: tests/pngvalid-gamma-expand16-background + @p='tests/pngvalid-gamma-expand16-background'; \ + b='tests/pngvalid-gamma-expand16-background'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-expand16-transform.log: tests/pngvalid-gamma-expand16-transform + @p='tests/pngvalid-gamma-expand16-transform'; \ + b='tests/pngvalid-gamma-expand16-transform'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-sbit.log: tests/pngvalid-gamma-sbit + @p='tests/pngvalid-gamma-sbit'; \ + b='tests/pngvalid-gamma-sbit'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-threshold.log: tests/pngvalid-gamma-threshold + @p='tests/pngvalid-gamma-threshold'; \ + b='tests/pngvalid-gamma-threshold'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-gamma-transform.log: tests/pngvalid-gamma-transform + @p='tests/pngvalid-gamma-transform'; \ + b='tests/pngvalid-gamma-transform'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-progressive-size.log: tests/pngvalid-progressive-size + @p='tests/pngvalid-progressive-size'; \ + b='tests/pngvalid-progressive-size'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-progressive-interlace-standard.log: tests/pngvalid-progressive-interlace-standard + @p='tests/pngvalid-progressive-interlace-standard'; \ + b='tests/pngvalid-progressive-interlace-standard'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-transform.log: tests/pngvalid-transform + @p='tests/pngvalid-transform'; \ + b='tests/pngvalid-transform'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-progressive-standard.log: tests/pngvalid-progressive-standard + @p='tests/pngvalid-progressive-standard'; \ + b='tests/pngvalid-progressive-standard'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngvalid-standard.log: tests/pngvalid-standard + @p='tests/pngvalid-standard'; \ + b='tests/pngvalid-standard'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngstest-1.8.log: tests/pngstest-1.8 + @p='tests/pngstest-1.8'; \ + b='tests/pngstest-1.8'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngstest-1.8-alpha.log: tests/pngstest-1.8-alpha + @p='tests/pngstest-1.8-alpha'; \ + b='tests/pngstest-1.8-alpha'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngstest-linear.log: tests/pngstest-linear + @p='tests/pngstest-linear'; \ + b='tests/pngstest-linear'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngstest-linear-alpha.log: tests/pngstest-linear-alpha + @p='tests/pngstest-linear-alpha'; \ + b='tests/pngstest-linear-alpha'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngstest-none.log: tests/pngstest-none + @p='tests/pngstest-none'; \ + b='tests/pngstest-none'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngstest-none-alpha.log: tests/pngstest-none-alpha + @p='tests/pngstest-none-alpha'; \ + b='tests/pngstest-none-alpha'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngstest-sRGB.log: tests/pngstest-sRGB + @p='tests/pngstest-sRGB'; \ + b='tests/pngstest-sRGB'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngstest-sRGB-alpha.log: tests/pngstest-sRGB-alpha + @p='tests/pngstest-sRGB-alpha'; \ + b='tests/pngstest-sRGB-alpha'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngunknown-IDAT.log: tests/pngunknown-IDAT + @p='tests/pngunknown-IDAT'; \ + b='tests/pngunknown-IDAT'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngunknown-discard.log: tests/pngunknown-discard + @p='tests/pngunknown-discard'; \ + b='tests/pngunknown-discard'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngunknown-if-safe.log: tests/pngunknown-if-safe + @p='tests/pngunknown-if-safe'; \ + b='tests/pngunknown-if-safe'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngunknown-sAPI.log: tests/pngunknown-sAPI + @p='tests/pngunknown-sAPI'; \ + b='tests/pngunknown-sAPI'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngunknown-sTER.log: tests/pngunknown-sTER + @p='tests/pngunknown-sTER'; \ + b='tests/pngunknown-sTER'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngunknown-save.log: tests/pngunknown-save + @p='tests/pngunknown-save'; \ + b='tests/pngunknown-save'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngunknown-vpAg.log: tests/pngunknown-vpAg + @p='tests/pngunknown-vpAg'; \ + b='tests/pngunknown-vpAg'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngimage-quick.log: tests/pngimage-quick + @p='tests/pngimage-quick'; \ + b='tests/pngimage-quick'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +tests/pngimage-full.log: tests/pngimage-full + @p='tests/pngimage-full'; \ + b='tests/pngimage-full'; \ + $(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +.test.log: + @p='$<'; \ + $(am__set_b); \ + $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ + --log-file $$b.log --trs-file $$b.trs \ + $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ + "$$tst" $(AM_TESTS_FD_REDIRECT) +@am__EXEEXT_TRUE@.test$(EXEEXT).log: +@am__EXEEXT_TRUE@ @p='$<'; \ +@am__EXEEXT_TRUE@ $(am__set_b); \ +@am__EXEEXT_TRUE@ $(am__check_pre) $(TEST_LOG_DRIVER) --test-name "$$f" \ +@am__EXEEXT_TRUE@ --log-file $$b.log --trs-file $$b.trs \ +@am__EXEEXT_TRUE@ $(am__common_driver_flags) $(AM_TEST_LOG_DRIVER_FLAGS) $(TEST_LOG_DRIVER_FLAGS) -- $(TEST_LOG_COMPILE) \ +@am__EXEEXT_TRUE@ "$$tst" $(AM_TESTS_FD_REDIRECT) + +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @@ -1087,44 +1859,53 @@ distdir: $(DISTFILES) || exit 1; \ fi; \ done + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" distdir="$(distdir)" \ + dist-hook -test -n "$(am__skip_mode_fix)" \ - || find "$(distdir)" -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + || find "$(distdir)" -type d ! -perm -755 \ + -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) + tardir=$(distdir) && $(am__tar) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).tar.gz + $(am__post_remove_distdir) dist-bzip2: distdir - tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 - $(am__remove_distdir) - -dist-lzma: distdir - tardir=$(distdir) && $(am__tar) | lzma -9 -c >$(distdir).tar.lzma - $(am__remove_distdir) + tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 + $(am__post_remove_distdir) +dist-lzip: distdir + tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz + $(am__post_remove_distdir) dist-xz: distdir - tardir=$(distdir) && $(am__tar) | xz -c >$(distdir).tar.xz - $(am__remove_distdir) + tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz + $(am__post_remove_distdir) dist-tarZ: distdir + @echo WARNING: "Support for distribution archives compressed with" \ + "legacy program 'compress' is deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z - $(am__remove_distdir) + $(am__post_remove_distdir) dist-shar: distdir - shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz - $(am__remove_distdir) + @echo WARNING: "Support for shar distribution archives is" \ + "deprecated." >&2 + @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 + shar $(distdir) | eval GZIP= gzip $(GZIP_ENV) -c >$(distdir).shar.gz + $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) - $(am__remove_distdir) + $(am__post_remove_distdir) -dist dist-all: distdir - tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz - $(am__remove_distdir) +dist dist-all: + $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' + $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another @@ -1132,31 +1913,33 @@ dist dist-all: distdir distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ - bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ - *.tar.lzma*) \ - unlzma -c $(distdir).tar.lzma | $(am__untar) ;;\ + bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ + *.tar.lz*) \ + lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ - GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ + eval GZIP= gzip $(GZIP_ENV) -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac - chmod -R a-w $(distdir); chmod a+w $(distdir) - mkdir $(distdir)/_build - mkdir $(distdir)/_inst + chmod -R a-w $(distdir) + chmod u+w $(distdir) + mkdir $(distdir)/_build $(distdir)/_build/sub $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ - && $(am__cd) $(distdir)/_build \ - && ../configure --srcdir=.. --prefix="$$dc_install_base" \ + && $(am__cd) $(distdir)/_build/sub \ + && ../../configure \ + $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ + --srcdir=../.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ @@ -1179,13 +1962,21 @@ distcheck: dist && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 - $(am__remove_distdir) + $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: - @$(am__cd) '$(distuninstallcheck_dir)' \ - && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ + @test -n '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: trying to run $@ with an empty' \ + '$$(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + $(am__cd) '$(distuninstallcheck_dir)' || { \ + echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ + exit 1; \ + }; \ + test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ @@ -1204,14 +1995,18 @@ distcleancheck: distclean check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS) $(MAKE) $(AM_MAKEFLAGS) check-TESTS -check: check-am -all-am: Makefile $(LTLIBRARIES) $(SCRIPTS) $(MANS) $(DATA) $(HEADERS) \ - config.h +check: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) check-am +all-am: Makefile $(PROGRAMS) $(LTLIBRARIES) $(SCRIPTS) $(MANS) $(DATA) \ + $(HEADERS) config.h +install-binPROGRAMS: install-libLTLIBRARIES + installdirs: - for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgincludedir)"; do \ + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man3dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgincludedir)" "$(DESTDIR)$(pkgincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done -install: install-am +install: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am @@ -1221,11 +2016,19 @@ install-am: all-am installcheck: installcheck-am install-strip: - $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ - install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ - `test -z '$(STRIP)' || \ - echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi mostlyclean-generic: + -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS) + -test -z "$(TEST_LOGS:.log=.trs)" || rm -f $(TEST_LOGS:.log=.trs) + -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG) clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) @@ -1233,19 +2036,68 @@ clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + -rm -f arm/$(DEPDIR)/$(am__dirstamp) + -rm -f arm/$(am__dirstamp) + -rm -f contrib/libtests/$(DEPDIR)/$(am__dirstamp) + -rm -f contrib/libtests/$(am__dirstamp) + -rm -f contrib/tools/$(DEPDIR)/$(am__dirstamp) + -rm -f contrib/tools/$(am__dirstamp) + -rm -f intel/$(DEPDIR)/$(am__dirstamp) + -rm -f intel/$(am__dirstamp) + -rm -f mips/$(DEPDIR)/$(am__dirstamp) + -rm -f mips/$(am__dirstamp) + -rm -f powerpc/$(DEPDIR)/$(am__dirstamp) + -rm -f powerpc/$(am__dirstamp) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." + -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +@DO_INSTALL_LIBPNG_CONFIG_FALSE@@DO_INSTALL_LINKS_FALSE@install-exec-hook: +@DO_INSTALL_LIBPNG_PC_FALSE@@DO_INSTALL_LINKS_FALSE@install-data-hook: +@DO_INSTALL_LIBPNG_CONFIG_FALSE@@DO_INSTALL_LIBPNG_PC_FALSE@@DO_INSTALL_LINKS_FALSE@uninstall-hook: clean: clean-am -clean-am: clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ - clean-libtool mostlyclean-am +clean-am: clean-binPROGRAMS clean-checkPROGRAMS clean-generic \ + clean-libLTLIBRARIES clean-libtool mostlyclean-am distclean: distclean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/png.Plo + -rm -f ./$(DEPDIR)/pngerror.Plo + -rm -f ./$(DEPDIR)/pngget.Plo + -rm -f ./$(DEPDIR)/pngmem.Plo + -rm -f ./$(DEPDIR)/pngpread.Plo + -rm -f ./$(DEPDIR)/pngread.Plo + -rm -f ./$(DEPDIR)/pngrio.Plo + -rm -f ./$(DEPDIR)/pngrtran.Plo + -rm -f ./$(DEPDIR)/pngrutil.Plo + -rm -f ./$(DEPDIR)/pngset.Plo + -rm -f ./$(DEPDIR)/pngtest.Po + -rm -f ./$(DEPDIR)/pngtrans.Plo + -rm -f ./$(DEPDIR)/pngwio.Plo + -rm -f ./$(DEPDIR)/pngwrite.Plo + -rm -f ./$(DEPDIR)/pngwtran.Plo + -rm -f ./$(DEPDIR)/pngwutil.Plo + -rm -f arm/$(DEPDIR)/arm_init.Plo + -rm -f arm/$(DEPDIR)/filter_neon.Plo + -rm -f arm/$(DEPDIR)/filter_neon_intrinsics.Plo + -rm -f arm/$(DEPDIR)/palette_neon_intrinsics.Plo + -rm -f contrib/libtests/$(DEPDIR)/pngimage.Po + -rm -f contrib/libtests/$(DEPDIR)/pngstest.Po + -rm -f contrib/libtests/$(DEPDIR)/pngunknown.Po + -rm -f contrib/libtests/$(DEPDIR)/pngvalid.Po + -rm -f contrib/libtests/$(DEPDIR)/timepng.Po + -rm -f contrib/tools/$(DEPDIR)/png-fix-itxt.Po + -rm -f contrib/tools/$(DEPDIR)/pngcp.Po + -rm -f contrib/tools/$(DEPDIR)/pngfix.Po + -rm -f intel/$(DEPDIR)/filter_sse2_intrinsics.Plo + -rm -f intel/$(DEPDIR)/intel_init.Plo + -rm -f mips/$(DEPDIR)/filter_msa_intrinsics.Plo + -rm -f mips/$(DEPDIR)/mips_init.Plo + -rm -f powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo + -rm -f powerpc/$(DEPDIR)/powerpc_init.Plo -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags @@ -1262,15 +2114,16 @@ info: info-am info-am: -install-data-am: install-man install-pkgconfigDATA \ - install-pkgincludeHEADERS +install-data-am: install-man install-nodist_pkgincludeHEADERS \ + install-pkgconfigDATA install-pkgincludeHEADERS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-data-hook install-dvi: install-dvi-am install-dvi-am: -install-exec-am: install-binSCRIPTS install-libLTLIBRARIES +install-exec-am: install-binPROGRAMS install-binSCRIPTS \ + install-libLTLIBRARIES @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) install-exec-hook install-html: install-html-am @@ -1296,7 +2149,40 @@ installcheck-am: maintainer-clean: maintainer-clean-am -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache - -rm -rf ./$(DEPDIR) + -rm -f ./$(DEPDIR)/png.Plo + -rm -f ./$(DEPDIR)/pngerror.Plo + -rm -f ./$(DEPDIR)/pngget.Plo + -rm -f ./$(DEPDIR)/pngmem.Plo + -rm -f ./$(DEPDIR)/pngpread.Plo + -rm -f ./$(DEPDIR)/pngread.Plo + -rm -f ./$(DEPDIR)/pngrio.Plo + -rm -f ./$(DEPDIR)/pngrtran.Plo + -rm -f ./$(DEPDIR)/pngrutil.Plo + -rm -f ./$(DEPDIR)/pngset.Plo + -rm -f ./$(DEPDIR)/pngtest.Po + -rm -f ./$(DEPDIR)/pngtrans.Plo + -rm -f ./$(DEPDIR)/pngwio.Plo + -rm -f ./$(DEPDIR)/pngwrite.Plo + -rm -f ./$(DEPDIR)/pngwtran.Plo + -rm -f ./$(DEPDIR)/pngwutil.Plo + -rm -f arm/$(DEPDIR)/arm_init.Plo + -rm -f arm/$(DEPDIR)/filter_neon.Plo + -rm -f arm/$(DEPDIR)/filter_neon_intrinsics.Plo + -rm -f arm/$(DEPDIR)/palette_neon_intrinsics.Plo + -rm -f contrib/libtests/$(DEPDIR)/pngimage.Po + -rm -f contrib/libtests/$(DEPDIR)/pngstest.Po + -rm -f contrib/libtests/$(DEPDIR)/pngunknown.Po + -rm -f contrib/libtests/$(DEPDIR)/pngvalid.Po + -rm -f contrib/libtests/$(DEPDIR)/timepng.Po + -rm -f contrib/tools/$(DEPDIR)/png-fix-itxt.Po + -rm -f contrib/tools/$(DEPDIR)/pngcp.Po + -rm -f contrib/tools/$(DEPDIR)/pngfix.Po + -rm -f intel/$(DEPDIR)/filter_sse2_intrinsics.Plo + -rm -f intel/$(DEPDIR)/intel_init.Plo + -rm -f mips/$(DEPDIR)/filter_msa_intrinsics.Plo + -rm -f mips/$(DEPDIR)/mips_init.Plo + -rm -f powerpc/$(DEPDIR)/filter_vsx_intrinsics.Plo + -rm -f powerpc/$(DEPDIR)/powerpc_init.Plo -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic @@ -1313,41 +2199,45 @@ ps: ps-am ps-am: -uninstall-am: uninstall-binSCRIPTS uninstall-libLTLIBRARIES \ - uninstall-man uninstall-pkgconfigDATA \ +uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ + uninstall-libLTLIBRARIES uninstall-man \ + uninstall-nodist_pkgincludeHEADERS uninstall-pkgconfigDATA \ uninstall-pkgincludeHEADERS @$(NORMAL_INSTALL) $(MAKE) $(AM_MAKEFLAGS) uninstall-hook uninstall-man: uninstall-man3 uninstall-man5 -.MAKE: all check-am install-am install-data-am install-exec-am \ - install-strip uninstall-am +.MAKE: all check check-am install install-am install-data-am \ + install-exec-am install-strip uninstall-am -.PHONY: CTAGS GTAGS all all-am am--refresh check check-TESTS check-am \ - clean clean-checkPROGRAMS clean-generic clean-libLTLIBRARIES \ - clean-libtool ctags dist dist-all dist-bzip2 dist-gzip \ - dist-lzma dist-shar dist-tarZ dist-xz dist-zip distcheck \ +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles am--refresh check \ + check-TESTS check-am clean clean-binPROGRAMS \ + clean-checkPROGRAMS clean-cscope clean-generic \ + clean-libLTLIBRARIES clean-libtool cscope cscopelist-am ctags \ + ctags-am dist dist-all dist-bzip2 dist-gzip dist-hook \ + dist-lzip dist-shar dist-tarZ dist-xz dist-zip distcheck \ distclean distclean-compile distclean-generic distclean-hdr \ distclean-libtool distclean-tags distcleancheck distdir \ distuninstallcheck dvi dvi-am html html-am info info-am \ - install install-am install-binSCRIPTS install-data \ - install-data-am install-data-hook install-dvi install-dvi-am \ - install-exec install-exec-am install-exec-hook install-html \ - install-html-am install-info install-info-am \ + install install-am install-binPROGRAMS install-binSCRIPTS \ + install-data install-data-am install-data-hook install-dvi \ + install-dvi-am install-exec install-exec-am install-exec-hook \ + install-html install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-man3 install-man5 \ - install-pdf install-pdf-am install-pkgconfigDATA \ - install-pkgincludeHEADERS install-ps install-ps-am \ - install-strip installcheck installcheck-am installdirs \ - maintainer-clean maintainer-clean-generic mostlyclean \ - mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ - pdf pdf-am ps ps-am tags uninstall uninstall-am \ + install-nodist_pkgincludeHEADERS install-pdf install-pdf-am \ + install-pkgconfigDATA install-pkgincludeHEADERS install-ps \ + install-ps-am install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool pdf pdf-am ps ps-am recheck tags tags-am \ + uninstall uninstall-am uninstall-binPROGRAMS \ uninstall-binSCRIPTS uninstall-hook uninstall-libLTLIBRARIES \ uninstall-man uninstall-man3 uninstall-man5 \ - uninstall-pkgconfigDATA uninstall-pkgincludeHEADERS + uninstall-nodist_pkgincludeHEADERS uninstall-pkgconfigDATA \ + uninstall-pkgincludeHEADERS +.PRECIOUS: Makefile -@HAVE_LD_VERSION_SCRIPT_TRUE@ # Versioned symbols and restricted exports -@HAVE_LD_VERSION_SCRIPT_FALSE@ # Only restricted exports when possible $(PNGLIB_BASENAME).pc: libpng.pc cp libpng.pc $@ @@ -1355,56 +2245,183 @@ $(PNGLIB_BASENAME).pc: libpng.pc $(PNGLIB_BASENAME)-config: libpng-config cp libpng-config $@ -libpng.sym: png.h pngconf.h - rm -f $@ $@.new - $(CPP) @LIBPNG_DEFINES@ $(CPPFLAGS) -DPNG_BUILDSYMS $(srcdir)/png.h | \ - $(SED) -n -e \ - 's|^.*PNG_FUNCTION_EXPORT[ ]*\([$(AN)]*\).*$$|$(SYMBOL_PREFIX)\1|p' \ - -e 's|^.*PNG_DATA_EXPORT[ ]*\([$(AN)]*\).*$$|$(SYMBOL_PREFIX)\1|p' \ - >$@.new - mv $@.new $@ +scripts/sym.out scripts/vers.out: png.h pngconf.h pnglibconf.h +scripts/prefix.out: png.h pngconf.h pnglibconf.out +scripts/symbols.out: png.h pngconf.h $(srcdir)/scripts/pnglibconf.h.prebuilt +scripts/intprefix.out: pnglibconf.h -libpng.vers: libpng.sym - rm -f $@ $@.new - echo PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0 '{global:' > $@.new - $(SED) s/$$/\;/ libpng.sym >> $@.new - echo 'local: *; };' >> $@.new - mv $@.new $@ +libpng.sym: scripts/sym.out + rm -f $@ + cp $? $@ +libpng.vers: scripts/vers.out + rm -f $@ + cp $? $@ -test: check +# Rename functions in scripts/prefix.out with a PNG_PREFIX prefix. +# Rename macros in scripts/macro.lst from PNG_PREFIXpng_ to PNG_ (the actual +# implementation of the macro). +@DO_PNG_PREFIX_TRUE@pnglibconf.h: pnglibconf.out scripts/prefix.out scripts/macro.lst +@DO_PNG_PREFIX_TRUE@ rm -f $@ +@DO_PNG_PREFIX_TRUE@ $(AWK) 's==0 && NR>1{print prev}\ +@DO_PNG_PREFIX_TRUE@ s==0{prev=$$0}\ +@DO_PNG_PREFIX_TRUE@ s==1{print "#define", $$1, "@PNG_PREFIX@" $$1}\ +@DO_PNG_PREFIX_TRUE@ s==2{print "#define @PNG_PREFIX@png_" $$1, "PNG_" $$1}\ +@DO_PNG_PREFIX_TRUE@ END{print prev}' s=0 pnglibconf.out s=1 scripts/prefix.out\ +@DO_PNG_PREFIX_TRUE@ s=2 ${srcdir}/scripts/macro.lst >pnglibconf.tf8 +@DO_PNG_PREFIX_TRUE@ mv pnglibconf.tf8 $@ -# install the .../include headers as links to the new ones -install-data-hook: - cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h - cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/png.h png.h - cd $(DESTDIR)$(includedir); $(LN_S) $(PNGLIB_BASENAME)/pngconf.h pngconf.h - cd $(DESTDIR)$(pkgconfigdir); rm -f libpng.pc - cd $(DESTDIR)$(pkgconfigdir); $(LN_S) $(PNGLIB_BASENAME).pc libpng.pc +@DO_PNG_PREFIX_TRUE@pngprefix.h: scripts/intprefix.out +@DO_PNG_PREFIX_TRUE@ rm -f pngprefix.tf1 +@DO_PNG_PREFIX_TRUE@ $(AWK) '{print "#define", $$1, "@PNG_PREFIX@" $$1}' $? >pngprefix.tf1 +@DO_PNG_PREFIX_TRUE@ mv pngprefix.tf1 $@ +@DO_PNG_PREFIX_FALSE@pnglibconf.h: pnglibconf.out +@DO_PNG_PREFIX_FALSE@ rm -f $@ +@DO_PNG_PREFIX_FALSE@ cp $? $@ -# do evil things to libpng to cause libpng12 to be used -install-exec-hook: - cd $(DESTDIR)$(bindir); rm -f libpng-config - cd $(DESTDIR)$(bindir); $(LN_S) $(PNGLIB_BASENAME)-config libpng-config - @set -x;\ - cd $(DESTDIR)$(libdir);\ - for ext in a la so sl dylib; do\ - rm -f libpng.$$ext;\ - if test -f $(PNGLIB_BASENAME).$$ext; then\ - $(LN_S) $(PNGLIB_BASENAME).$$ext libpng.$$ext;\ - fi;\ +@DO_PNG_PREFIX_FALSE@pngprefix.h: # is empty +@DO_PNG_PREFIX_FALSE@ :>$@ + +$(srcdir)/scripts/pnglibconf.h.prebuilt: + @echo "Attempting to build $@" >&2 + @echo "This is a machine generated file, but if you want to make" >&2 + @echo "a new one simply make 'scripts/pnglibconf.out', copy that" >&2 + @echo "AND set PNG_ZLIB_VERNUM to 0 (you MUST do this)" >&2 + @exit 1 + +# The following is necessary to ensure that the local pnglibconf.h is used, not +# an installed one (this can happen immediately after on a clean system if +# 'make test' is the first thing the user does.) Only files which include +# one of the png source files (typically png.h or pngpriv.h) need to be listed +# here: +pngtest.o: pnglibconf.h + +contrib/libtests/makepng.o: pnglibconf.h +contrib/libtests/pngstest.o: pnglibconf.h +contrib/libtests/pngunknown.o: pnglibconf.h +contrib/libtests/pngimage.o: pnglibconf.h +contrib/libtests/pngvalid.o: pnglibconf.h +contrib/libtests/readpng.o: pnglibconf.h +contrib/libtests/tarith.o: pnglibconf.h +contrib/libtests/timepng.o: pnglibconf.h + +contrib/tools/makesRGB.o: pnglibconf.h +contrib/tools/pngfix.o: pnglibconf.h +contrib/tools/pngcp.o: pnglibconf.h + +.c.out: + rm -f $@ $*.tf[12] + test -d scripts || mkdir scripts || test -d scripts + $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\ + $(CPPFLAGS) $(SYMBOL_CFLAGS) $< > $*.tf1 + $(AWK) -f "${srcdir}/scripts/dfn.awk" out="$*.tf2" $*.tf1 1>&2 + rm -f $*.tf1 + mv $*.tf2 $@ + +# The .c file for pnglibconf.h is machine generated +pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_XTRA) + rm -f $@ $*.tf[45] + $(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf4 version=search\ + ${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\ + ${srcdir}/pngusr.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf5 $*.tf4 1>&2 + rm $*.tf4 + mv $*.tf5 $@ + +# Symbol checks (.def and .out files should match) +scripts/symbols.chk: scripts/checksym.awk scripts/symbols.def scripts/symbols.out + +.out.chk: + rm -f $@ $*.new + $(AWK) -f ${srcdir}/scripts/checksym.awk ${srcdir}/scripts/${*F}.def\ + of="$*.new" $< >&2 + mv $*.new $@ + +# used on demand to regenerate the standard header, CPPFLAGS should +# be empty - no non-standard defines +scripts/pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h + rm -f $@ pnglibconf.tf[67] + test -z "$(CPPFLAGS)" + echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\ + $(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf6\ + logunsupported=1 version=search ${srcdir}/pngconf.h -\ + ${srcdir}/scripts/pnglibconf.dfa 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf7\ + pnglibconf.tf6 1>&2 + rm pnglibconf.tf6 + mv pnglibconf.tf7 $@ + +$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS): png.h pngconf.h \ + pnglibconf.h pngpriv.h pngdebug.h pnginfo.h pngstruct.h pngprefix.h + +test: check-am + +# Extra checks +check: scripts/symbols.chk + +# Don't distribute the generated script files +dist-hook: + cd '$(top_distdir)'; rm -f $(SCRIPT_CLEANFILES) + +# Make links between installed files with release-specific names and the generic +# file names. If this install rule is run the generic names will be deleted and +# recreated - this has obvious issues for systems with multiple installations. + +install-header-links: + @set -ex; cd '$(DESTDIR)$(includedir)'; for f in $(HEADERS); do \ + rm -f "$$f"; $(LN_S) "$(PNGLIB_BASENAME)/$$f" "$$f"; done + +uninstall-header-links: + cd '$(DESTDIR)$(includedir)'; rm -f $(HEADERS) + +install-libpng-pc: + @set -ex; cd '$(DESTDIR)$(pkgconfigdir)'; rm -f libpng.pc; \ + $(LN_S) '$(PNGLIB_BASENAME).pc' libpng.pc + +uninstall-libpng-pc: + rm -f '$(DESTDIR)$(pkgconfigdir)/libpng.pc' + +install-library-links: + @set -x; cd '$(DESTDIR)$(libdir)';\ + for ext in $(EXT_LIST); do\ + rm -f "libpng.$$ext";\ + if test -f "$(PNGLIB_BASENAME).$$ext"; then\ + $(LN_S) "$(PNGLIB_BASENAME).$$ext" "libpng.$$ext" || exit 1;\ + fi;\ done -uninstall-hook: - cd $(DESTDIR)$(includedir); rm -f png.h pngconf.h - rm -f $(DESTDIR)$(pkgconfigdir)/libpng.pc - rm -f $(DESTDIR)$(bindir)/libpng-config - @if test -n "@compatlib@"; then\ - set -x;\ - cd $(DESTDIR)$(libdir);\ - for ext in a la so sl dylib; do\ - rm -f libpng.$$ext;\ - done;\ - fi +uninstall-library-links: + @set -x; cd '$(DESTDIR)$(libdir)'; for ext in $(EXT_LIST); do\ + rm -f "libpng.$$ext"; done + +install-libpng-config: + @set -ex; cd '$(DESTDIR)$(bindir)'; rm -f libpng-config; \ + $(LN_S) '$(PNGLIB_BASENAME)-config' libpng-config + +uninstall-libpng-config: + rm -f '$(DESTDIR)$(bindir)/libpng-config' + +# If --enable-unversioned-links is specified the header and lib file links +# will be automatically made on a 'make install': + +@DO_INSTALL_LINKS_TRUE@install-data-hook: install-header-links +@DO_INSTALL_LINKS_TRUE@uninstall-hook: uninstall-header-links +@DO_INSTALL_LINKS_TRUE@install-exec-hook: install-library-links +@DO_INSTALL_LINKS_TRUE@uninstall-hook: uninstall-library-links + +# Likewise, --install-pc causes libpng.pc to be constructed: + +@DO_INSTALL_LIBPNG_PC_TRUE@install-data-hook: install-libpng-pc +@DO_INSTALL_LIBPNG_PC_TRUE@uninstall-hook: uninstall-libpng-pc + +# And --install-config: + +@DO_INSTALL_LIBPNG_CONFIG_TRUE@install-exec-hook: install-libpng-config +@DO_INSTALL_LIBPNG_CONFIG_TRUE@uninstall-hook: uninstall-libpng-config + +# The following addition ensures that 'make all' always builds the test programs +# too. It used to, but some change either in libpng or configure stopped this +# working. +all-am: $(check_PROGRAMS) # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. diff --git a/libs/libpng-src/README b/libs/libpng-src/README index cbff54441..cfc1f0e3d 100644 --- a/libs/libpng-src/README +++ b/libs/libpng-src/README @@ -1,19 +1,16 @@ -README for libpng version 1.2.46 - July 9, 2011 (shared library 12.0) -See the note about version numbers near the top of png.h +README for libpng version 1.6.37 - April 14, 2019 +================================================= +See the note about version numbers near the top of png.h. See INSTALL for instructions on how to install libpng. -Libpng comes in several distribution formats. Get libpng-*.tar.gz, -libpng-*.tar.xz, or libpng-*.tar.bz2 if you want UNIX-style line -endings in the text files, or lpng*.7z or lpng*.zip if you want DOS-style -line endings. You can get UNIX-style line endings from the *.zip file -by using "unzip -a" but there seems to be no simple way to recover -UNIX-style line endings from the *.7z file. The *.tar.xz file is -recommended for *NIX users instead. +Libpng comes in several distribution formats. Get libpng-*.tar.gz or +libpng-*.tar.xz or if you want UNIX-style line endings in the text +files, or lpng*.7z or lpng*.zip if you want DOS-style line endings. Version 0.89 was the first official release of libpng. Don't let the -fact that it's the first release fool you. The libpng library has been in -extensive use and testing since mid-1995. By late 1997 it had +fact that it's the first release fool you. The libpng library has been +in extensive use and testing since mid-1995. By late 1997 it had finally gotten to the stage where there hadn't been significant changes to the API in some time, and people have a bad feeling about libraries with versions < 1.0. Version 1.0.0 was released in @@ -27,18 +24,25 @@ earlier versions if you are using a shared library. The type of the png_uint_32, which will affect shared-library applications that use this function. -To avoid problems with changes to the internals of png_info_struct, +To avoid problems with changes to the internals of the png info_struct, new APIs have been made available in 0.95 to avoid direct application access to info_ptr. These functions are the png_set_ and png_get_ functions. These functions should be used when accessing/storing the info_struct data, rather than manipulating it directly, to avoid such problems in the future. -It is important to note that the APIs do not make current programs +It is important to note that the APIs did not make current programs that access the info struct directly incompatible with the new -library. However, it is strongly suggested that new programs use -the new APIs (as shown in example.c and pngtest.c), and older programs -be converted to the new format, to facilitate upgrades in the future. +library, through libpng-1.2.x. In libpng-1.4.x, which was meant to +be a transitional release, members of the png_struct and the +info_struct can still be accessed, but the compiler will issue a +warning about deprecated usage. Since libpng-1.5.0, direct access +to these structs is not allowed, and the definitions of the structs +reside in private pngstruct.h and pnginfo.h header files that are not +accessible to applications. It is strongly suggested that new +programs use the new APIs (as shown in example.c and pngtest.c), and +older programs be converted to the new format, to facilitate upgrades +in the future. **** Additions since 0.90 include the ability to compile libpng as a @@ -57,101 +61,71 @@ the library action on the detection of chunk CRC errors. It is possible to set different actions based on whether the CRC error occurred in a critical or an ancillary chunk. -The changes made to the library, and bugs fixed are based on discussions -on the png-mng-implement mailing list and not on material submitted -privately to Guy, Andreas, or Glenn. They will forward any good -suggestions to the list. - -For a detailed description on using libpng, read libpng.txt. For -examples of libpng in a program, see example.c and pngtest.c. For usage -information and restrictions (what little they are) on libpng, see -png.h. For a description on using zlib (the compression library used by -libpng) and zlib's restrictions, see zlib.h +For a detailed description on using libpng, read libpng-manual.txt. +For examples of libpng in a program, see example.c and pngtest.c. For +usage information and restrictions (what little they are) on libpng, +see png.h. For a description on using zlib (the compression library +used by libpng) and zlib's restrictions, see zlib.h I have included a general makefile, as well as several machine and -compiler specific ones, but you may have to modify one for your own needs. +compiler specific ones, but you may have to modify one for your own +needs. You should use zlib 1.0.4 or later to run this, but it MAY work with versions as old as zlib 0.95. Even so, there are bugs in older zlib versions which can cause the output of invalid compression streams for -some images. You will definitely need zlib 1.0.4 or later if you are -taking advantage of the MS-DOS "far" structure allocation for the small -and medium memory models. You should also note that zlib is a -compression library that is useful for more things than just PNG files. -You can use zlib as a drop-in replacement for fread() and fwrite() if -you are so inclined. +some images. + +You should also note that zlib is a compression library that is useful +for more things than just PNG files. You can use zlib as a drop-in +replacement for fread() and fwrite(), if you are so inclined. zlib should be available at the same place that libpng is, or at -ftp://ftp.simplesystems.org/pub/png/src/ +https://zlib.net. You may also want a copy of the PNG specification. It is available as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find -these at http://www.libpng.org/pub/png/pngdocs.html +these at http://www.libpng.org/pub/png/pngdocs.html . -This code is currently being archived at libpng.sf.net in the -[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT) -at GO GRAPHSUP. If you can't find it in any of those places, -e-mail me, and I'll help you find it. +This code is currently being archived at libpng.sourceforge.io in the +[DOWNLOAD] area, and at http://libpng.download/src . -If you have any code changes, requests, problems, etc., please e-mail -them to me. Also, I'd appreciate any make files or project files, -and any modifications you needed to make to get libpng to compile, -along with a #define variable to tell what compiler/system you are on. -If you needed to add transformations to libpng, or wish libpng would -provide the image in a different way, drop me a note (and code, if -possible), so I can consider supporting the transformation. -Finally, if you get any warning messages when compiling libpng -(note: not zlib), and they are easy to fix, I'd appreciate the -fix. Please mention "libpng" somewhere in the subject line. Thanks. - -This release was created and will be supported by myself (of course -based in a large way on Guy's and Andreas' earlier work), and the PNG +This release, based in a large way on Glenn's, Guy's and Andreas' +earlier work, was created and will be supported by myself and the PNG development group. -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit +Send comments/corrections/commendations to png-mng-implement at +lists.sourceforge.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) or to glennrp at users.sourceforge.net +to subscribe). -You can't reach Guy, the original libpng author, at the addresses -given in previous versions of this document. He and Andreas will -read mail addressed to the png-mng-implement list, however. - -Please do not send general questions about PNG. Send them to -the (png-mng-misc at lists.sourceforge.net, subscription required, visit +Send general questions about the PNG specification to png-mng-misc +at lists.sourceforge.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-misc to -subscribe). On the other hand, please do not send libpng questions to -that address, send them to me or to the png-mng-implement list. I'll -get them in the end anyway. If you have a question about something -in the PNG specification that is related to using libpng, send it -to me. Send me any questions that start with "I was using libpng, -and ...". If in doubt, send questions to me. I'll bounce them -to others, if necessary. - -Please do not send suggestions on how to change PNG. We have -been discussing PNG for twelve years now, and it is official and -finished. If you have suggestions for libpng, however, I'll -gladly listen. Even if your suggestion is not used immediately, -it may be used later. +subscribe). Files in this distribution: ANNOUNCE => Announcement of this version, with recent changes + AUTHORS => List of contributing authors CHANGES => Description of changes between libpng versions KNOWNBUG => List of known bugs and deficiencies LICENSE => License to use and redistribute libpng README => This file TODO => Things not implemented in the current library - Y2KINFO => Statement of Y2K compliance + TRADEMARK => Trademark information example.c => Example code for using libpng functions - libpng-*-*-diff.txt => Diff from previous release - libpng.3 => manual page for libpng (includes libpng.txt) - libpng.txt => Description of libpng and its functions + libpng.3 => manual page for libpng (includes libpng-manual.txt) + libpng-manual.txt => Description of libpng and its functions libpngpf.3 => manual page for libpng's private functions png.5 => manual page for the PNG format png.c => Basic interface functions common to library - png.h => Library function and interface declarations - pngconf.h => System specific library configuration + png.h => Library function and interface declarations (public) + pngpriv.h => Library function and interface declarations (private) + pngconf.h => System specific library configuration (public) + pngstruct.h => png_struct declaration (private) + pnginfo.h => png_info struct declaration (private) + pngdebug.h => debugging macros (private) pngerror.c => Error/warning message I/O functions pngget.c => Functions for retrieving info from struct pngmem.c => Memory handling functions @@ -170,106 +144,40 @@ Files in this distribution: pngwrite.c => High-level write functions pngwtran.c => Write data transformations pngwutil.c => Write utility functions + arm => Contains optimized code for the ARM platform + powerpc => Contains optimized code for the PowerPC platform contrib => Contributions + arm-neon => Optimized code for ARM-NEON platform + powerpc-vsx => Optimized code for POWERPC-VSX platform + examples => Example programs gregbook => source code for PNG reading and writing, from Greg Roelofs' "PNG: The Definitive Guide", O'Reilly, 1999 - msvctest => Builds and runs pngtest using a MSVC workspace - pngminim => Simple pnm2pngm and png2pnmm programs - pngminus => Simple pnm2png and png2pnm programs - pngsuite => Test images - visupng => Contains a MSVC workspace for VisualPng + libtests => Test programs + mips-msa => Optimized code for MIPS-MSA platform + pngminim => Minimal decoder, encoder, and progressive decoder + programs demonstrating use of pngusr.dfa + pngminus => Simple pnm2png and png2pnm programs + pngsuite => Test images + testpngs + tools => Various tools + visupng => Contains a MSVC workspace for VisualPng + intel => Optimized code for INTEL-SSE2 platform + mips => Optimized code for MIPS platform projects => Contains project files and workspaces for building a DLL - beos => Contains a Beos workspace for building libpng - c5builder => Contains a Borland workspace for building - libpng and zlib - netware.txt => Contains instructions for downloading a set - of project files for building libpng and - zlib on Netware. - visualc6 => Contains a Microsoft Visual C++ (MSVC) + owatcom => Contains a WATCOM project for building libpng + visualc71 => Contains a Microsoft Visual C++ (MSVC) + workspace for building libpng and zlib + vstudio => Contains a Microsoft Visual C++ (MSVC) workspace for building libpng and zlib - wince.txt => Contains instructions for downloading a - Microsoft Visual C++ (Windows CD Toolkit) - workspace for building libpng and zlib on - WindowsCE - xcode => Contains xcode project files scripts => Directory containing scripts for building libpng: - descrip.mms => VMS makefile for MMS or MMK - makefile.std => Generic UNIX makefile (cc, creates static - libpng.a) - makefile.elf => Linux/ELF gcc makefile symbol versioning, - creates libpng12.so.0.1.2.46) - makefile.linux => Linux/ELF makefile (gcc, creates - libpng12.so.0.1.2.46) - makefile.gcmmx => Linux/ELF makefile (gcc, creates - libpng12.so.0.1.2.46, previously - used assembler code tuned for Intel MMX - platform) - makefile.gcc => Generic makefile (gcc, creates static - libpng.a) - makefile.knr => Archaic UNIX Makefile that converts files - with ansi2knr (Requires ansi2knr.c from - ftp://ftp.cs.wisc.edu/ghost) - makefile.aix => AIX makefile - makefile.cygwin => Cygwin/gcc makefile - makefile.darwin => Darwin makefile - makefile.dec => DEC Alpha UNIX makefile - makefile.freebsd => FreeBSD makefile - makefile.hpgcc => HPUX makefile using gcc - makefile.hpux => HPUX (10.20 and 11.00) makefile - makefile.hp64 => HPUX (10.20 and 11.00) makefile, 64 bit - makefile.ibmc => IBM C/C++ version 3.x for Win32 and OS/2 - (static) - makefile.intel => Intel C/C++ version 4.0 and later - libpng.icc => Project file, IBM VisualAge/C++ 4.0 or later - makefile.netbsd => NetBSD/cc makefile, makes libpng.so. - makefile.ne12bsd => NetBSD/cc makefile, makes libpng12.so - makefile.openbsd => OpenBSD makefile - makefile.sgi => Silicon Graphics IRIX (cc, creates static lib) - makefile.sggcc => Silicon Graphics - (gcc, creates libpng12.so.0.1.2.46) - makefile.sunos => Sun makefile - makefile.solaris => Solaris 2.X makefile - (gcc, creates libpng12.so.0.1.2.46) - makefile.so9 => Solaris 9 makefile - (gcc, creates libpng12.so.0.1.2.46) - makefile.32sunu => Sun Ultra 32-bit makefile - makefile.64sunu => Sun Ultra 64-bit makefile - makefile.sco => For SCO OSr5 ELF and Unixware 7 with Native cc - makefile.mips => MIPS makefile - makefile.acorn => Acorn makefile - makefile.amiga => Amiga makefile - smakefile.ppc => AMIGA smakefile for SAS C V6.58/7.00 PPC - compiler (Requires SCOPTIONS, copied from - scripts/SCOPTIONS.ppc) - makefile.atari => Atari makefile - makefile.beos => BEOS makefile for X86 - makefile.bor => Borland makefile (uses bcc) - makefile.bc32 => 32-bit Borland C++ (all modules compiled in C mode) - makefile.tc3 => Turbo C 3.0 makefile - makefile.dj2 => DJGPP 2 makefile - makefile.msc => Microsoft C makefile - makefile.vcawin32=> makefile for Microsoft Visual C++ 5.0 and - later (previously used assembler code tuned - for Intel MMX platform) - makefile.vcwin32 => makefile for Microsoft Visual C++ 4.0 and - later (does not use assembler code) - makefile.os2 => OS/2 Makefile (gcc and emx, requires pngos2.def) - pngos2.def => OS/2 module definition file used by makefile.os2 - makefile.watcom => Watcom 10a+ Makefile, 32-bit flat memory model - makevms.com => VMS build script - SCOPTIONS.ppc => Used with smakefile.ppc + (see scripts/README.txt for the list of scripts) -Good luck, and happy coding. +Good luck, and happy coding! --Glenn Randers-Pehrson (current maintainer, since 1998) - Internet: glennrp at users.sourceforge.net - --Andreas Eric Dilger (former maintainer, 1996-1997) - Internet: adilger at enel.ucalgary.ca - Web: http://members.shaw.ca/adilger/ - --Guy Eric Schalnat (original author and former maintainer, 1995-1996) - (formerly of Group 42, Inc) - Internet: gschal at infinet.com + * Cosmin Truta (current maintainer, since 2018) + * Glenn Randers-Pehrson (former maintainer, 1998-2018) + * Andreas Eric Dilger (former maintainer, 1996-1997) + * Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc.) diff --git a/libs/libpng-src/TODO b/libs/libpng-src/TODO index face7658c..562dab069 100644 --- a/libs/libpng-src/TODO +++ b/libs/libpng-src/TODO @@ -1,25 +1,23 @@ TODO - list of things to do for libpng: -Final bug fixes. -Improve API by hiding the png_struct and png_info structs. -Finish work on the no-floating-point version (including gamma compensation) -Better C++ wrapper/full C++ implementation? -Fix problem with C++ and EXTERN "C". -cHRM transformation. -Improve setjmp/longjmp usage or remove it in favor of returning error codes. -Add "grayscale->palette" transformation and "palette->grayscale" detection. -Improved dithering. -Multi-lingual error and warning message support. -Complete sRGB transformation (presently it simply uses gamma=0.45455). -Man pages for function calls. -Better documentation. -Better filter selection - (counting huffman bits/precompression? filter inertia? filter costs?). -Histogram creation. -Text conversion between different code pages (Latin-1 -> Mac and DOS). -Should we always malloc 2^bit_depth PLTE/tRNS/hIST entries for safety? -Build gamma tables using fixed point (and do away with floating point entirely). -Use greater precision when changing to linear gamma for compositing against - background and doing rgb-to-gray transformation. -Investigate pre-incremented loop counters and other loop constructions. -Add interpolated method of handling interlacing. +* Fix all defects (duh!) +* Better C++ wrapper / full C++ implementation (?) +* Fix the problems with C++ and 'extern "C"'. +* cHRM transformation. +* Palette creation. +* "grayscale->palette" transformation and "palette->grayscale" detection. +* Improved dithering. +* Multi-lingual error and warning message support. +* Complete sRGB transformation. (Currently it simply uses gamma=0.45455.) +* Man pages for function calls. +* Better documentation. +* Better filter selection + (e.g., counting huffman bits/precompression; filter inertia; filter costs). +* Histogram creation. +* Text conversion between different code pages (e.g., Latin-1 -> Mac). +* Avoid building gamma tables whenever possible. +* Greater precision in changing to linear gamma for compositing against + background, and in doing rgb-to-gray transformations. +* Investigate pre-incremented loop counters and other loop constructions. +* Interpolated method of handling interlacing. +* More validations for libpng transformations. diff --git a/libs/libpng-src/TRADEMARK b/libs/libpng-src/TRADEMARK new file mode 100644 index 000000000..ac667187d --- /dev/null +++ b/libs/libpng-src/TRADEMARK @@ -0,0 +1,8 @@ +TRADEMARK +========= + +The name "libpng" has not been registered by the Copyright owners +as a trademark in any jurisdiction. However, because libpng has +been distributed and maintained world-wide, continually since 1995, +the Copyright owners claim "common-law trademark protection" in any +jurisdiction where common-law trademark is recognized. diff --git a/libs/libpng-src/aclocal.m4 b/libs/libpng-src/aclocal.m4 index 27bc57cf4..bc18c34f0 100644 --- a/libs/libpng-src/aclocal.m4 +++ b/libs/libpng-src/aclocal.m4 @@ -1,7 +1,7 @@ -# generated automatically by aclocal 1.11 -*- Autoconf -*- +# generated automatically by aclocal 1.16.1 -*- Autoconf -*- + +# Copyright (C) 1996-2018 Free Software Foundation, Inc. -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. @@ -11,7961 +11,16 @@ # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl -m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.65],, -[m4_warning([this file was generated for autoconf 2.65. +m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.69],, +[m4_warning([this file was generated for autoconf 2.69. You have another version of autoconf. It may work, but is not guaranteed to. If you have problems, you may need to regenerate the build system entirely. -To do so, use the procedure documented by the package, typically `autoreconf'.])]) +To do so, use the procedure documented by the package, typically 'autoreconf'.])]) -# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- -# -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -m4_define([_LT_COPYING], [dnl -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 -# -# This file is part of GNU Libtool. -# -# GNU Libtool 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. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -]) - -# serial 56 LT_INIT - - -# LT_PREREQ(VERSION) -# ------------------ -# Complain and exit if this libtool version is less that VERSION. -m4_defun([LT_PREREQ], -[m4_if(m4_version_compare(m4_defn([LT_PACKAGE_VERSION]), [$1]), -1, - [m4_default([$3], - [m4_fatal([Libtool version $1 or higher is required], - 63)])], - [$2])]) - - -# _LT_CHECK_BUILDDIR -# ------------------ -# Complain if the absolute build directory name contains unusual characters -m4_defun([_LT_CHECK_BUILDDIR], -[case `pwd` in - *\ * | *\ *) - AC_MSG_WARN([Libtool does not cope well with whitespace in `pwd`]) ;; -esac -]) - - -# LT_INIT([OPTIONS]) -# ------------------ -AC_DEFUN([LT_INIT], -[AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT -AC_BEFORE([$0], [LT_LANG])dnl -AC_BEFORE([$0], [LT_OUTPUT])dnl -AC_BEFORE([$0], [LTDL_INIT])dnl -m4_require([_LT_CHECK_BUILDDIR])dnl - -dnl Autoconf doesn't catch unexpanded LT_ macros by default: -m4_pattern_forbid([^_?LT_[A-Z_]+$])dnl -m4_pattern_allow([^(_LT_EOF|LT_DLGLOBAL|LT_DLLAZY_OR_NOW|LT_MULTI_MODULE)$])dnl -dnl aclocal doesn't pull ltoptions.m4, ltsugar.m4, or ltversion.m4 -dnl unless we require an AC_DEFUNed macro: -AC_REQUIRE([LTOPTIONS_VERSION])dnl -AC_REQUIRE([LTSUGAR_VERSION])dnl -AC_REQUIRE([LTVERSION_VERSION])dnl -AC_REQUIRE([LTOBSOLETE_VERSION])dnl -m4_require([_LT_PROG_LTMAIN])dnl - -dnl Parse OPTIONS -_LT_SET_OPTIONS([$0], [$1]) - -# This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" - -# Always use our own libtool. -LIBTOOL='$(SHELL) $(top_builddir)/libtool' -AC_SUBST(LIBTOOL)dnl - -_LT_SETUP - -# Only expand once: -m4_define([LT_INIT]) -])# LT_INIT - -# Old names: -AU_ALIAS([AC_PROG_LIBTOOL], [LT_INIT]) -AU_ALIAS([AM_PROG_LIBTOOL], [LT_INIT]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PROG_LIBTOOL], []) -dnl AC_DEFUN([AM_PROG_LIBTOOL], []) - - -# _LT_CC_BASENAME(CC) -# ------------------- -# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. -m4_defun([_LT_CC_BASENAME], -[for cc_temp in $1""; do - case $cc_temp in - compile | *[[\\/]]compile | ccache | *[[\\/]]ccache ) ;; - distcc | *[[\\/]]distcc | purify | *[[\\/]]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` -]) - - -# _LT_FILEUTILS_DEFAULTS -# ---------------------- -# It is okay to use these file commands and assume they have been set -# sensibly after `m4_require([_LT_FILEUTILS_DEFAULTS])'. -m4_defun([_LT_FILEUTILS_DEFAULTS], -[: ${CP="cp -f"} -: ${MV="mv -f"} -: ${RM="rm -f"} -])# _LT_FILEUTILS_DEFAULTS - - -# _LT_SETUP -# --------- -m4_defun([_LT_SETUP], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -_LT_DECL([], [host_alias], [0], [The host system])dnl -_LT_DECL([], [host], [0])dnl -_LT_DECL([], [host_os], [0])dnl -dnl -_LT_DECL([], [build_alias], [0], [The build system])dnl -_LT_DECL([], [build], [0])dnl -_LT_DECL([], [build_os], [0])dnl -dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -dnl -AC_REQUIRE([AC_PROG_LN_S])dnl -test -z "$LN_S" && LN_S="ln -s" -_LT_DECL([], [LN_S], [1], [Whether we need soft or hard links])dnl -dnl -AC_REQUIRE([LT_CMD_MAX_LEN])dnl -_LT_DECL([objext], [ac_objext], [0], [Object file suffix (normally "o")])dnl -_LT_DECL([], [exeext], [0], [Executable file suffix (normally "")])dnl -dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_CHECK_SHELL_FEATURES])dnl -m4_require([_LT_CMD_RELOAD])dnl -m4_require([_LT_CHECK_MAGIC_METHOD])dnl -m4_require([_LT_CMD_OLD_ARCHIVE])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl - -_LT_CONFIG_LIBTOOL_INIT([ -# See if we are running on zsh, and set the options which allow our -# commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi -]) -if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST -fi - -_LT_CHECK_OBJDIR - -m4_require([_LT_TAG_COMPILER])dnl -_LT_PROG_ECHO_BACKSLASH - -case $host_os in -aix3*) - # AIX sometimes has problems with the GCC collect2 program. For some - # reason, if we set the COLLECT_NAMES environment variable, the problems - # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES - fi - ;; -esac - -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([["`\\]]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld="$lt_cv_prog_gnu_ld" - -old_CC="$CC" -old_CFLAGS="$CFLAGS" - -# Set sane defaults for various variables -test -z "$CC" && CC=cc -test -z "$LTCC" && LTCC=$CC -test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS -test -z "$LD" && LD=ld -test -z "$ac_objext" && ac_objext=o - -_LT_CC_BASENAME([$compiler]) - -# Only perform the check for file, if the check method requires it -test -z "$MAGIC_CMD" && MAGIC_CMD=file -case $deplibs_check_method in -file_magic*) - if test "$file_magic_cmd" = '$MAGIC_CMD'; then - _LT_PATH_MAGIC - fi - ;; -esac - -# Use C for the default configuration in the libtool script -LT_SUPPORTED_TAG([CC]) -_LT_LANG_C_CONFIG -_LT_LANG_DEFAULT_CONFIG -_LT_CONFIG_COMMANDS -])# _LT_SETUP - - -# _LT_PROG_LTMAIN -# --------------- -# Note that this code is called both from `configure', and `config.status' -# now that we use AC_CONFIG_COMMANDS to generate libtool. Notably, -# `config.status' has no value for ac_aux_dir unless we are using Automake, -# so we pass a copy along to make sure it has a sensible value anyway. -m4_defun([_LT_PROG_LTMAIN], -[m4_ifdef([AC_REQUIRE_AUX_FILE], [AC_REQUIRE_AUX_FILE([ltmain.sh])])dnl -_LT_CONFIG_LIBTOOL_INIT([ac_aux_dir='$ac_aux_dir']) -ltmain="$ac_aux_dir/ltmain.sh" -])# _LT_PROG_LTMAIN - - - -# So that we can recreate a full libtool script including additional -# tags, we accumulate the chunks of code to send to AC_CONFIG_COMMANDS -# in macros and then make a single call at the end using the `libtool' -# label. - - -# _LT_CONFIG_LIBTOOL_INIT([INIT-COMMANDS]) -# ---------------------------------------- -# Register INIT-COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL_INIT], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_INIT], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_INIT]) - - -# _LT_CONFIG_LIBTOOL([COMMANDS]) -# ------------------------------ -# Register COMMANDS to be passed to AC_CONFIG_COMMANDS later. -m4_define([_LT_CONFIG_LIBTOOL], -[m4_ifval([$1], - [m4_append([_LT_OUTPUT_LIBTOOL_COMMANDS], - [$1 -])])]) - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS]) - - -# _LT_CONFIG_SAVE_COMMANDS([COMMANDS], [INIT_COMMANDS]) -# ----------------------------------------------------- -m4_defun([_LT_CONFIG_SAVE_COMMANDS], -[_LT_CONFIG_LIBTOOL([$1]) -_LT_CONFIG_LIBTOOL_INIT([$2]) -]) - - -# _LT_FORMAT_COMMENT([COMMENT]) -# ----------------------------- -# Add leading comment marks to the start of each line, and a trailing -# full-stop to the whole comment if one is not present already. -m4_define([_LT_FORMAT_COMMENT], -[m4_ifval([$1], [ -m4_bpatsubst([m4_bpatsubst([$1], [^ *], [# ])], - [['`$\]], [\\\&])]m4_bmatch([$1], [[!?.]$], [], [.]) -)]) - - - - - -# _LT_DECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION], [IS-TAGGED?]) -# ------------------------------------------------------------------- -# CONFIGNAME is the name given to the value in the libtool script. -# VARNAME is the (base) name used in the configure script. -# VALUE may be 0, 1 or 2 for a computed quote escaped value based on -# VARNAME. Any other value will be used directly. -m4_define([_LT_DECL], -[lt_if_append_uniq([lt_decl_varnames], [$2], [, ], - [lt_dict_add_subkey([lt_decl_dict], [$2], [libtool_name], - [m4_ifval([$1], [$1], [$2])]) - lt_dict_add_subkey([lt_decl_dict], [$2], [value], [$3]) - m4_ifval([$4], - [lt_dict_add_subkey([lt_decl_dict], [$2], [description], [$4])]) - lt_dict_add_subkey([lt_decl_dict], [$2], - [tagged?], [m4_ifval([$5], [yes], [no])])]) -]) - - -# _LT_TAGDECL([CONFIGNAME], VARNAME, VALUE, [DESCRIPTION]) -# -------------------------------------------------------- -m4_define([_LT_TAGDECL], [_LT_DECL([$1], [$2], [$3], [$4], [yes])]) - - -# lt_decl_tag_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_tag_varnames], -[_lt_decl_filter([tagged?], [yes], $@)]) - - -# _lt_decl_filter(SUBKEY, VALUE, [SEPARATOR], [VARNAME1..]) -# --------------------------------------------------------- -m4_define([_lt_decl_filter], -[m4_case([$#], - [0], [m4_fatal([$0: too few arguments: $#])], - [1], [m4_fatal([$0: too few arguments: $#: $1])], - [2], [lt_dict_filter([lt_decl_dict], [$1], [$2], [], lt_decl_varnames)], - [3], [lt_dict_filter([lt_decl_dict], [$1], [$2], [$3], lt_decl_varnames)], - [lt_dict_filter([lt_decl_dict], $@)])[]dnl -]) - - -# lt_decl_quote_varnames([SEPARATOR], [VARNAME1...]) -# -------------------------------------------------- -m4_define([lt_decl_quote_varnames], -[_lt_decl_filter([value], [1], $@)]) - - -# lt_decl_dquote_varnames([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_dquote_varnames], -[_lt_decl_filter([value], [2], $@)]) - - -# lt_decl_varnames_tagged([SEPARATOR], [VARNAME1...]) -# --------------------------------------------------- -m4_define([lt_decl_varnames_tagged], -[m4_assert([$# <= 2])dnl -_$0(m4_quote(m4_default([$1], [[, ]])), - m4_ifval([$2], [[$2]], [m4_dquote(lt_decl_tag_varnames)]), - m4_split(m4_normalize(m4_quote(_LT_TAGS)), [ ]))]) -m4_define([_lt_decl_varnames_tagged], -[m4_ifval([$3], [lt_combine([$1], [$2], [_], $3)])]) - - -# lt_decl_all_varnames([SEPARATOR], [VARNAME1...]) -# ------------------------------------------------ -m4_define([lt_decl_all_varnames], -[_$0(m4_quote(m4_default([$1], [[, ]])), - m4_if([$2], [], - m4_quote(lt_decl_varnames), - m4_quote(m4_shift($@))))[]dnl -]) -m4_define([_lt_decl_all_varnames], -[lt_join($@, lt_decl_varnames_tagged([$1], - lt_decl_tag_varnames([[, ]], m4_shift($@))))dnl -]) - - -# _LT_CONFIG_STATUS_DECLARE([VARNAME]) -# ------------------------------------ -# Quote a variable value, and forward it to `config.status' so that its -# declaration there will have the same value as in `configure'. VARNAME -# must have a single quote delimited value for this to work. -m4_define([_LT_CONFIG_STATUS_DECLARE], -[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) - - -# _LT_CONFIG_STATUS_DECLARATIONS -# ------------------------------ -# We delimit libtool config variables with single quotes, so when -# we write them to config.status, we have to be sure to quote all -# embedded single quotes properly. In configure, this macro expands -# each variable declared with _LT_DECL (and _LT_TAGDECL) into: -# -# ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' -m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], -[m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), - [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAGS -# ---------------- -# Output comment and list of tags supported by the script -m4_defun([_LT_LIBTOOL_TAGS], -[_LT_FORMAT_COMMENT([The names of the tagged configurations supported by this script])dnl -available_tags="_LT_TAGS"dnl -]) - - -# _LT_LIBTOOL_DECLARE(VARNAME, [TAG]) -# ----------------------------------- -# Extract the dictionary values for VARNAME (optionally with TAG) and -# expand to a commented shell variable setting: -# -# # Some comment about what VAR is for. -# visible_name=$lt_internal_name -m4_define([_LT_LIBTOOL_DECLARE], -[_LT_FORMAT_COMMENT(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], - [description])))[]dnl -m4_pushdef([_libtool_name], - m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [libtool_name])))[]dnl -m4_case(m4_quote(lt_dict_fetch([lt_decl_dict], [$1], [value])), - [0], [_libtool_name=[$]$1], - [1], [_libtool_name=$lt_[]$1], - [2], [_libtool_name=$lt_[]$1], - [_libtool_name=lt_dict_fetch([lt_decl_dict], [$1], [value])])[]dnl -m4_ifval([$2], [_$2])[]m4_popdef([_libtool_name])[]dnl -]) - - -# _LT_LIBTOOL_CONFIG_VARS -# ----------------------- -# Produce commented declarations of non-tagged libtool config variables -# suitable for insertion in the LIBTOOL CONFIG section of the `libtool' -# script. Tagged libtool config variables (even for the LIBTOOL CONFIG -# section) are produced by _LT_LIBTOOL_TAG_VARS. -m4_defun([_LT_LIBTOOL_CONFIG_VARS], -[m4_foreach([_lt_var], - m4_quote(_lt_decl_filter([tagged?], [no], [], lt_decl_varnames)), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var)])])]) - - -# _LT_LIBTOOL_TAG_VARS(TAG) -# ------------------------- -m4_define([_LT_LIBTOOL_TAG_VARS], -[m4_foreach([_lt_var], m4_quote(lt_decl_tag_varnames), - [m4_n([_LT_LIBTOOL_DECLARE(_lt_var, [$1])])])]) - - -# _LT_TAGVAR(VARNAME, [TAGNAME]) -# ------------------------------ -m4_define([_LT_TAGVAR], [m4_ifval([$2], [$1_$2], [$1])]) - - -# _LT_CONFIG_COMMANDS -# ------------------- -# Send accumulated output to $CONFIG_STATUS. Thanks to the lists of -# variables for single and double quote escaping we saved from calls -# to _LT_DECL, we can put quote escaped variables declarations -# into `config.status', and then the shell code to quote escape them in -# for loops in `config.status'. Finally, any additional code accumulated -# from calls to _LT_CONFIG_LIBTOOL_INIT is expanded. -m4_defun([_LT_CONFIG_COMMANDS], -[AC_PROVIDE_IFELSE([LT_OUTPUT], - dnl If the libtool generation code has been placed in $CONFIG_LT, - dnl instead of duplicating it all over again into config.status, - dnl then we will have config.status run $CONFIG_LT later, so it - dnl needs to know what name is stored there: - [AC_CONFIG_COMMANDS([libtool], - [$SHELL $CONFIG_LT || AS_EXIT(1)], [CONFIG_LT='$CONFIG_LT'])], - dnl If the libtool generation code is destined for config.status, - dnl expand the accumulated commands and init code now: - [AC_CONFIG_COMMANDS([libtool], - [_LT_OUTPUT_LIBTOOL_COMMANDS], [_LT_OUTPUT_LIBTOOL_COMMANDS_INIT])]) -])#_LT_CONFIG_COMMANDS - - -# Initialize. -m4_define([_LT_OUTPUT_LIBTOOL_COMMANDS_INIT], -[ - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -sed_quote_subst='$sed_quote_subst' -double_quote_subst='$double_quote_subst' -delay_variable_subst='$delay_variable_subst' -_LT_CONFIG_STATUS_DECLARATIONS -LTCC='$LTCC' -LTCFLAGS='$LTCFLAGS' -compiler='$compiler_DEFAULT' - -# Quote evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_quote_varnames); do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Double-quote double-evaled strings. -for var in lt_decl_all_varnames([[ \ -]], lt_decl_dquote_varnames); do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in - *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" - ;; - *) - eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" - ;; - esac -done - -# Fix-up fallback echo if it was mangled by the above quoting rules. -case \$lt_ECHO in -*'\\\[$]0 --fallback-echo"')dnl " - lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` - ;; -esac - -_LT_OUTPUT_LIBTOOL_INIT -]) - - -# LT_OUTPUT -# --------- -# This macro allows early generation of the libtool script (before -# AC_OUTPUT is called), incase it is used in configure for compilation -# tests. -AC_DEFUN([LT_OUTPUT], -[: ${CONFIG_LT=./config.lt} -AC_MSG_NOTICE([creating $CONFIG_LT]) -cat >"$CONFIG_LT" <<_LTEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate a libtool stub with the current configuration. - -lt_cl_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_LTEOF - -cat >>"$CONFIG_LT" <<\_LTEOF -AS_SHELL_SANITIZE -_AS_PREPARE - -exec AS_MESSAGE_FD>&1 -exec AS_MESSAGE_LOG_FD>>config.log -{ - echo - AS_BOX([Running $as_me.]) -} >&AS_MESSAGE_LOG_FD - -lt_cl_help="\ -\`$as_me' creates a local libtool stub from the current configuration, -for use in further configure time tests before the real libtool is -generated. - -Usage: $[0] [[OPTIONS]] - - -h, --help print this help, then exit - -V, --version print version number, then exit - -q, --quiet do not print progress messages - -d, --debug don't remove temporary files - -Report bugs to ." - -lt_cl_version="\ -m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl -m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) -configured by $[0], generated by m4_PACKAGE_STRING. - -Copyright (C) 2008 Free Software Foundation, Inc. -This config.lt script is free software; the Free Software Foundation -gives unlimited permision to copy, distribute and modify it." - -while test $[#] != 0 -do - case $[1] in - --version | --v* | -V ) - echo "$lt_cl_version"; exit 0 ;; - --help | --h* | -h ) - echo "$lt_cl_help"; exit 0 ;; - --debug | --d* | -d ) - debug=: ;; - --quiet | --q* | --silent | --s* | -q ) - lt_cl_silent=: ;; - - -*) AC_MSG_ERROR([unrecognized option: $[1] -Try \`$[0] --help' for more information.]) ;; - - *) AC_MSG_ERROR([unrecognized argument: $[1] -Try \`$[0] --help' for more information.]) ;; - esac - shift -done - -if $lt_cl_silent; then - exec AS_MESSAGE_FD>/dev/null -fi -_LTEOF - -cat >>"$CONFIG_LT" <<_LTEOF -_LT_OUTPUT_LIBTOOL_COMMANDS_INIT -_LTEOF - -cat >>"$CONFIG_LT" <<\_LTEOF -AC_MSG_NOTICE([creating $ofile]) -_LT_OUTPUT_LIBTOOL_COMMANDS -AS_EXIT(0) -_LTEOF -chmod +x "$CONFIG_LT" - -# configure is writing to config.log, but config.lt does its own redirection, -# appending to config.log, which fails on DOS, as config.log is still kept -# open by configure. Here we exec the FD to /dev/null, effectively closing -# config.log, so it can be properly (re)opened and appended to by config.lt. -if test "$no_create" != yes; then - lt_cl_success=: - test "$silent" = yes && - lt_config_lt_args="$lt_config_lt_args --quiet" - exec AS_MESSAGE_LOG_FD>/dev/null - $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false - exec AS_MESSAGE_LOG_FD>>config.log - $lt_cl_success || AS_EXIT(1) -fi -])# LT_OUTPUT - - -# _LT_CONFIG(TAG) -# --------------- -# If TAG is the built-in tag, create an initial libtool script with a -# default configuration from the untagged config vars. Otherwise add code -# to config.status for appending the configuration named by TAG from the -# matching tagged config vars. -m4_defun([_LT_CONFIG], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_CONFIG_SAVE_COMMANDS([ - m4_define([_LT_TAG], m4_if([$1], [], [C], [$1]))dnl - m4_if(_LT_TAG, [C], [ - # See if we are running on zsh, and set the options which allow our - # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then - setopt NO_GLOB_SUBST - fi - - cfgfile="${ofile}T" - trap "$RM \"$cfgfile\"; exit 1" 1 2 15 - $RM "$cfgfile" - - cat <<_LT_EOF >> "$cfgfile" -#! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION -# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: -# NOTE: Changes made to this file will be lost: look at ltmain.sh. -# -_LT_COPYING -_LT_LIBTOOL_TAGS - -# ### BEGIN LIBTOOL CONFIG -_LT_LIBTOOL_CONFIG_VARS -_LT_LIBTOOL_TAG_VARS -# ### END LIBTOOL CONFIG - -_LT_EOF - - case $host_os in - aix3*) - cat <<\_LT_EOF >> "$cfgfile" -# AIX sometimes has problems with the GCC collect2 program. For some -# reason, if we set the COLLECT_NAMES environment variable, the problems -# vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then - COLLECT_NAMES= - export COLLECT_NAMES -fi -_LT_EOF - ;; - esac - - _LT_PROG_LTMAIN - - # We use sed instead of cat because bash on DJGPP gets confused if - # if finds mixed CR/LF and LF-only lines. Since sed operates in - # text mode, it properly converts lines to CR/LF. This bash problem - # is reportedly fixed, but why not run on old versions too? - sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - _LT_PROG_XSI_SHELLFNS - - sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || - (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") - chmod +x "$ofile" -], -[cat <<_LT_EOF >> "$ofile" - -dnl Unfortunately we have to use $1 here, since _LT_TAG is not expanded -dnl in a comment (ie after a #). -# ### BEGIN LIBTOOL TAG CONFIG: $1 -_LT_LIBTOOL_TAG_VARS(_LT_TAG) -# ### END LIBTOOL TAG CONFIG: $1 -_LT_EOF -])dnl /m4_if -], -[m4_if([$1], [], [ - PACKAGE='$PACKAGE' - VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' - RM='$RM' - ofile='$ofile'], []) -])dnl /_LT_CONFIG_SAVE_COMMANDS -])# _LT_CONFIG - - -# LT_SUPPORTED_TAG(TAG) -# --------------------- -# Trace this macro to discover what tags are supported by the libtool -# --tag option, using: -# autoconf --trace 'LT_SUPPORTED_TAG:$1' -AC_DEFUN([LT_SUPPORTED_TAG], []) - - -# C support is built-in for now -m4_define([_LT_LANG_C_enabled], []) -m4_define([_LT_TAGS], []) - - -# LT_LANG(LANG) -# ------------- -# Enable libtool support for the given language if not already enabled. -AC_DEFUN([LT_LANG], -[AC_BEFORE([$0], [LT_OUTPUT])dnl -m4_case([$1], - [C], [_LT_LANG(C)], - [C++], [_LT_LANG(CXX)], - [Java], [_LT_LANG(GCJ)], - [Fortran 77], [_LT_LANG(F77)], - [Fortran], [_LT_LANG(FC)], - [Windows Resource], [_LT_LANG(RC)], - [m4_ifdef([_LT_LANG_]$1[_CONFIG], - [_LT_LANG($1)], - [m4_fatal([$0: unsupported language: "$1"])])])dnl -])# LT_LANG - - -# _LT_LANG(LANGNAME) -# ------------------ -m4_defun([_LT_LANG], -[m4_ifdef([_LT_LANG_]$1[_enabled], [], - [LT_SUPPORTED_TAG([$1])dnl - m4_append([_LT_TAGS], [$1 ])dnl - m4_define([_LT_LANG_]$1[_enabled], [])dnl - _LT_LANG_$1_CONFIG($1)])dnl -])# _LT_LANG - - -# _LT_LANG_DEFAULT_CONFIG -# ----------------------- -m4_defun([_LT_LANG_DEFAULT_CONFIG], -[AC_PROVIDE_IFELSE([AC_PROG_CXX], - [LT_LANG(CXX)], - [m4_define([AC_PROG_CXX], defn([AC_PROG_CXX])[LT_LANG(CXX)])]) - -AC_PROVIDE_IFELSE([AC_PROG_F77], - [LT_LANG(F77)], - [m4_define([AC_PROG_F77], defn([AC_PROG_F77])[LT_LANG(F77)])]) - -AC_PROVIDE_IFELSE([AC_PROG_FC], - [LT_LANG(FC)], - [m4_define([AC_PROG_FC], defn([AC_PROG_FC])[LT_LANG(FC)])]) - -dnl The call to [A][M_PROG_GCJ] is quoted like that to stop aclocal -dnl pulling things in needlessly. -AC_PROVIDE_IFELSE([AC_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], - [LT_LANG(GCJ)], - [AC_PROVIDE_IFELSE([LT_PROG_GCJ], - [LT_LANG(GCJ)], - [m4_ifdef([AC_PROG_GCJ], - [m4_define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([A][M_PROG_GCJ], - [m4_define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[LT_LANG(GCJ)])]) - m4_ifdef([LT_PROG_GCJ], - [m4_define([LT_PROG_GCJ], defn([LT_PROG_GCJ])[LT_LANG(GCJ)])])])])]) - -AC_PROVIDE_IFELSE([LT_PROG_RC], - [LT_LANG(RC)], - [m4_define([LT_PROG_RC], defn([LT_PROG_RC])[LT_LANG(RC)])]) -])# _LT_LANG_DEFAULT_CONFIG - -# Obsolete macros: -AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) -AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) -AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) -AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_CXX], []) -dnl AC_DEFUN([AC_LIBTOOL_F77], []) -dnl AC_DEFUN([AC_LIBTOOL_FC], []) -dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) - - -# _LT_TAG_COMPILER -# ---------------- -m4_defun([_LT_TAG_COMPILER], -[AC_REQUIRE([AC_PROG_CC])dnl - -_LT_DECL([LTCC], [CC], [1], [A C compiler])dnl -_LT_DECL([LTCFLAGS], [CFLAGS], [1], [LTCC compiler flags])dnl -_LT_TAGDECL([CC], [compiler], [1], [A language specific compiler])dnl -_LT_TAGDECL([with_gcc], [GCC], [0], [Is the compiler the GNU compiler?])dnl - -# If no C compiler was specified, use CC. -LTCC=${LTCC-"$CC"} - -# If no C compiler flags were specified, use CFLAGS. -LTCFLAGS=${LTCFLAGS-"$CFLAGS"} - -# Allow CC to be a program name with arguments. -compiler=$CC -])# _LT_TAG_COMPILER - - -# _LT_COMPILER_BOILERPLATE -# ------------------------ -# Check for compiler boilerplate output or warnings with -# the simple compiler test code. -m4_defun([_LT_COMPILER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_compile_test_code" >conftest.$ac_ext -eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_compiler_boilerplate=`cat conftest.err` -$RM conftest* -])# _LT_COMPILER_BOILERPLATE - - -# _LT_LINKER_BOILERPLATE -# ---------------------- -# Check for linker boilerplate output or warnings with -# the simple link test code. -m4_defun([_LT_LINKER_BOILERPLATE], -[m4_require([_LT_DECL_SED])dnl -ac_outfile=conftest.$ac_objext -echo "$lt_simple_link_test_code" >conftest.$ac_ext -eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err -_lt_linker_boilerplate=`cat conftest.err` -$RM -r conftest* -])# _LT_LINKER_BOILERPLATE - -# _LT_REQUIRED_DARWIN_CHECKS -# ------------------------- -m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ - case $host_os in - rhapsody* | darwin*) - AC_CHECK_TOOL([DSYMUTIL], [dsymutil], [:]) - AC_CHECK_TOOL([NMEDIT], [nmedit], [:]) - AC_CHECK_TOOL([LIPO], [lipo], [:]) - AC_CHECK_TOOL([OTOOL], [otool], [:]) - AC_CHECK_TOOL([OTOOL64], [otool64], [:]) - _LT_DECL([], [DSYMUTIL], [1], - [Tool to manipulate archived DWARF debug symbol files on Mac OS X]) - _LT_DECL([], [NMEDIT], [1], - [Tool to change global to local symbols on Mac OS X]) - _LT_DECL([], [LIPO], [1], - [Tool to manipulate fat objects and archives on Mac OS X]) - _LT_DECL([], [OTOOL], [1], - [ldd/readelf like tool for Mach-O binaries on Mac OS X]) - _LT_DECL([], [OTOOL64], [1], - [ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4]) - - AC_CACHE_CHECK([for -single_module linker flag],[lt_cv_apple_cc_single_mod], - [lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then - # By default we will add the -single_module flag. You can override - # by either setting the environment variable LT_MULTI_MODULE - # non-empty at configure time, or by adding -multi_module to the - # link flags. - rm -rf libconftest.dylib* - echo "int foo(void){return 1;}" > conftest.c - echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ --dynamiclib -Wl,-single_module conftest.c" >&AS_MESSAGE_LOG_FD - $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ - -dynamiclib -Wl,-single_module conftest.c 2>conftest.err - _lt_result=$? - if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then - lt_cv_apple_cc_single_mod=yes - else - cat conftest.err >&AS_MESSAGE_LOG_FD - fi - rm -rf libconftest.dylib* - rm -f conftest.* - fi]) - AC_CACHE_CHECK([for -exported_symbols_list linker flag], - [lt_cv_ld_exported_symbols_list], - [lt_cv_ld_exported_symbols_list=no - save_LDFLAGS=$LDFLAGS - echo "_main" > conftest.sym - LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [lt_cv_ld_exported_symbols_list=yes], - [lt_cv_ld_exported_symbols_list=no]) - LDFLAGS="$save_LDFLAGS" - ]) - case $host_os in - rhapsody* | darwin1.[[012]]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; - darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - darwin*) # darwin 5.x on - # if running on 10.5 or later, the deployment target defaults - # to the OS version, if on x86, and 10.4, the deployment - # target defaults to 10.4. Don't you love it? - case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in - 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[[012]]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; - 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - esac - ;; - esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then - _lt_dar_single_mod='$single_module' - fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' - else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' - fi - if test "$DSYMUTIL" != ":"; then - _lt_dsymutil='~$DSYMUTIL $lib || :' - else - _lt_dsymutil= - fi - ;; - esac -]) - - -# _LT_DARWIN_LINKER_FEATURES -# -------------------------- -# Checks for linker and compiler features on darwin -m4_defun([_LT_DARWIN_LINKER_FEATURES], -[ - m4_require([_LT_REQUIRED_DARWIN_CHECKS]) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_automatic, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(whole_archive_flag_spec, $1)='' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" - case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; - *) _lt_dar_can_shared=$GCC ;; - esac - if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=echo - _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - _LT_TAGVAR(module_expsym_cmds, $1)="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" - m4_if([$1], [CXX], -[ if test "$lt_cv_apple_cc_single_mod" != "yes"; then - _LT_TAGVAR(archive_cmds, $1)="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" - _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" - fi -],[]) - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi -]) - -# _LT_SYS_MODULE_PATH_AIX -# ----------------------- -# Links a minimal program and checks the executable -# for the system default hardcoded library path. In most cases, -# this is /usr/lib:/lib, but when the MPI compilers are used -# the location of the communication and MPI libs are included too. -# If we don't find anything, use the default library path according -# to the aix ld manual. -m4_defun([_LT_SYS_MODULE_PATH_AIX], -[m4_require([_LT_DECL_SED])dnl -AC_LINK_IFELSE(AC_LANG_PROGRAM,[ -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi],[]) -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi -])# _LT_SYS_MODULE_PATH_AIX - - -# _LT_SHELL_INIT(ARG) -# ------------------- -m4_define([_LT_SHELL_INIT], -[ifdef([AC_DIVERSION_NOTICE], - [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], - [AC_DIVERT_PUSH(NOTICE)]) -$1 -AC_DIVERT_POP -])# _LT_SHELL_INIT - - -# _LT_PROG_ECHO_BACKSLASH -# ----------------------- -# Add some code to the start of the generated configure script which -# will find an echo command which doesn't interpret backslashes. -m4_defun([_LT_PROG_ECHO_BACKSLASH], -[_LT_SHELL_INIT([ -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$lt_ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` - ;; -esac - -ECHO=${lt_ECHO-echo} -if test "X[$]1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X[$]1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then - # Yippee, $ECHO works! - : -else - # Restart under the correct shell. - exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} -fi - -if test "X[$]1" = X--fallback-echo; then - # used as fallback echo - shift - cat <<_LT_EOF -[$]* -_LT_EOF - exit 0 -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test -z "$lt_ECHO"; then - if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if { echo_test_string=`eval $cmd`; } 2>/dev/null && - { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null - then - break - fi - done - fi - - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : - else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$ECHO" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - ECHO='print -r' - elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} - else - # Try using printf. - ECHO='printf %s\n' - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - ECHO="$CONFIG_SHELL [$]0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$CONFIG_SHELL [$]0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do - if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "[$]0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} - else - # Oops. We lost completely, so just stick with echo. - ECHO=echo - fi - fi - fi - fi - fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -lt_ECHO=$ECHO -if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then - lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" -fi - -AC_SUBST(lt_ECHO) -]) -_LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) -_LT_DECL([], [ECHO], [1], - [An echo program that does not interpret backslashes]) -])# _LT_PROG_ECHO_BACKSLASH - - -# _LT_ENABLE_LOCK -# --------------- -m4_defun([_LT_ENABLE_LOCK], -[AC_ARG_ENABLE([libtool-lock], - [AS_HELP_STRING([--disable-libtool-lock], - [avoid locking (might break parallel builds)])]) -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes - -# Some flags need to be propagated to the compiler or linker for good -# libtool support. -case $host in -ia64-*-hpux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.$ac_objext` in - *ELF-32*) - HPUX_IA64_MODE="32" - ;; - *ELF-64*) - HPUX_IA64_MODE="64" - ;; - esac - fi - rm -rf conftest* - ;; -*-*-irix6*) - # Find out which ABI we are using. - echo '[#]line __oline__ "configure"' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - if test "$lt_cv_prog_gnu_ld" = yes; then - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -melf32bsmip" - ;; - *N32*) - LD="${LD-ld} -melf32bmipn32" - ;; - *64-bit*) - LD="${LD-ld} -melf64bmip" - ;; - esac - else - case `/usr/bin/file conftest.$ac_objext` in - *32-bit*) - LD="${LD-ld} -32" - ;; - *N32*) - LD="${LD-ld} -n32" - ;; - *64-bit*) - LD="${LD-ld} -64" - ;; - esac - fi - fi - rm -rf conftest* - ;; - -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ -s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *32-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_i386_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_i386" - ;; - ppc64-*linux*|powerpc64-*linux*) - LD="${LD-ld} -m elf32ppclinux" - ;; - s390x-*linux*) - LD="${LD-ld} -m elf_s390" - ;; - sparc64-*linux*) - LD="${LD-ld} -m elf32_sparc" - ;; - esac - ;; - *64-bit*) - case $host in - x86_64-*kfreebsd*-gnu) - LD="${LD-ld} -m elf_x86_64_fbsd" - ;; - x86_64-*linux*) - LD="${LD-ld} -m elf_x86_64" - ;; - ppc*-*linux*|powerpc*-*linux*) - LD="${LD-ld} -m elf64ppc" - ;; - s390*-*linux*|s390*-*tpf*) - LD="${LD-ld} -m elf64_s390" - ;; - sparc*-*linux*) - LD="${LD-ld} -m elf64_sparc" - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; - -*-*-sco3.2v5*) - # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" - CFLAGS="$CFLAGS -belf" - AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, - [AC_LANG_PUSH(C) - AC_LINK_IFELSE([AC_LANG_PROGRAM([[]],[[]])],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) - AC_LANG_POP]) - if test x"$lt_cv_cc_needs_belf" != x"yes"; then - # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" - fi - ;; -sparc*-*solaris*) - # Find out which ABI we are using. - echo 'int i;' > conftest.$ac_ext - if AC_TRY_EVAL(ac_compile); then - case `/usr/bin/file conftest.o` in - *64-bit*) - case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; - *) - if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then - LD="${LD-ld} -64" - fi - ;; - esac - ;; - esac - fi - rm -rf conftest* - ;; -esac - -need_locks="$enable_libtool_lock" -])# _LT_ENABLE_LOCK - - -# _LT_CMD_OLD_ARCHIVE -# ------------------- -m4_defun([_LT_CMD_OLD_ARCHIVE], -[AC_CHECK_TOOL(AR, ar, false) -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru -_LT_DECL([], [AR], [1], [The archiver]) -_LT_DECL([], [AR_FLAGS], [1]) - -AC_CHECK_TOOL(STRIP, strip, :) -test -z "$STRIP" && STRIP=: -_LT_DECL([], [STRIP], [1], [A symbol stripping program]) - -AC_CHECK_TOOL(RANLIB, ranlib, :) -test -z "$RANLIB" && RANLIB=: -_LT_DECL([], [RANLIB], [1], - [Commands used to install an old-style archive]) - -# Determine commands to create old-style static archives. -old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' -old_postinstall_cmds='chmod 644 $oldlib' -old_postuninstall_cmds= - -if test -n "$RANLIB"; then - case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" - ;; - *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" - ;; - esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" -fi -_LT_DECL([], [old_postinstall_cmds], [2]) -_LT_DECL([], [old_postuninstall_cmds], [2]) -_LT_TAGDECL([], [old_archive_cmds], [2], - [Commands used to build an old-style archive]) -])# _LT_CMD_OLD_ARCHIVE - - -# _LT_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------------------- -# Check whether the given compiler option works -AC_DEFUN([_LT_COMPILER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - m4_if([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$3" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - # The option is referenced via a variable to avoid confusing sed. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>conftest.err) - ac_status=$? - cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s "$ac_outfile"; then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - fi - $RM conftest* -]) - -if test x"[$]$2" = xyes; then - m4_if([$5], , :, [$5]) -else - m4_if([$6], , :, [$6]) -fi -])# _LT_COMPILER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_COMPILER_OPTION], [_LT_COMPILER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], []) - - -# _LT_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, -# [ACTION-SUCCESS], [ACTION-FAILURE]) -# ---------------------------------------------------- -# Check whether the given linker option works -AC_DEFUN([_LT_LINKER_OPTION], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_SED])dnl -AC_CACHE_CHECK([$1], [$2], - [$2=no - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS $3" - echo "$lt_simple_link_test_code" > conftest.$ac_ext - if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then - # The linker can only warn and ignore the option if not recognized - # So say no if there are warnings - if test -s conftest.err; then - # Append any errors to the config.log. - cat conftest.err 1>&AS_MESSAGE_LOG_FD - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp - $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 - if diff conftest.exp conftest.er2 >/dev/null; then - $2=yes - fi - else - $2=yes - fi - fi - $RM -r conftest* - LDFLAGS="$save_LDFLAGS" -]) - -if test x"[$]$2" = xyes; then - m4_if([$4], , :, [$4]) -else - m4_if([$5], , :, [$5]) -fi -])# _LT_LINKER_OPTION - -# Old name: -AU_ALIAS([AC_LIBTOOL_LINKER_OPTION], [_LT_LINKER_OPTION]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], []) - - -# LT_CMD_MAX_LEN -#--------------- -AC_DEFUN([LT_CMD_MAX_LEN], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -# find the maximum length of command line arguments -AC_MSG_CHECKING([the maximum length of command line arguments]) -AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl - i=0 - teststring="ABCD" - - case $build_os in - msdosdjgpp*) - # On DJGPP, this test can blow up pretty badly due to problems in libc - # (any single argument exceeding 2000 bytes causes a buffer overrun - # during glob expansion). Even if it were fixed, the result of this - # check would be larger than it should be. - lt_cv_sys_max_cmd_len=12288; # 12K is about right - ;; - - gnu*) - # Under GNU Hurd, this test is not required because there is - # no limit to the length of command line arguments. - # Libtool will interpret -1 as no limit whatsoever - lt_cv_sys_max_cmd_len=-1; - ;; - - cygwin* | mingw* | cegcc*) - # On Win9x/ME, this test blows up -- it succeeds, but takes - # about 5 minutes as the teststring grows exponentially. - # Worse, since 9x/ME are not pre-emptively multitasking, - # you end up with a "frozen" computer, even though with patience - # the test eventually succeeds (with a max line length of 256k). - # Instead, let's just punt: use the minimum linelength reported by - # all of the supported platforms: 8192 (on NT/2K/XP). - lt_cv_sys_max_cmd_len=8192; - ;; - - amigaos*) - # On AmigaOS with pdksh, this test takes hours, literally. - # So we just punt and use a minimum line length of 8192. - lt_cv_sys_max_cmd_len=8192; - ;; - - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) - # This has been around since 386BSD, at least. Likely further. - if test -x /sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` - elif test -x /usr/sbin/sysctl; then - lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` - else - lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs - fi - # And add a safety zone - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - ;; - - interix*) - # We know the value 262144 and hardcode it with a safety zone (like BSD) - lt_cv_sys_max_cmd_len=196608 - ;; - - osf*) - # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure - # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not - # nice to cause kernel panics so lets avoid the loop below. - # First set a reasonable default. - lt_cv_sys_max_cmd_len=16384 - # - if test -x /sbin/sysconfig; then - case `/sbin/sysconfig -q proc exec_disable_arg_limit` in - *1*) lt_cv_sys_max_cmd_len=-1 ;; - esac - fi - ;; - sco3.2v5*) - lt_cv_sys_max_cmd_len=102400 - ;; - sysv5* | sco5v6* | sysv4.2uw2*) - kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` - if test -n "$kargmax"; then - lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[[ ]]//'` - else - lt_cv_sys_max_cmd_len=32768 - fi - ;; - *) - lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` - else - # Make teststring a little bigger before we do anything with it. - # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do - teststring=$teststring$teststring - done - SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} - # If test is not a shell built-in, we'll probably end up computing a - # maximum length that is only half of the actual maximum length, but - # we can't tell. - while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ - = "XX$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough - do - i=`expr $i + 1` - teststring=$teststring$teststring - done - # Only check the string length outside the loop. - lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` - teststring= - # Add a significant safety factor because C++ compilers can tack on - # massive amounts of additional arguments before passing them to the - # linker. It appears as though 1/2 is a usable value. - lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` - fi - ;; - esac -]) -if test -n $lt_cv_sys_max_cmd_len ; then - AC_MSG_RESULT($lt_cv_sys_max_cmd_len) -else - AC_MSG_RESULT(none) -fi -max_cmd_len=$lt_cv_sys_max_cmd_len -_LT_DECL([], [max_cmd_len], [0], - [What is the maximum length of a command?]) -])# LT_CMD_MAX_LEN - -# Old name: -AU_ALIAS([AC_LIBTOOL_SYS_MAX_CMD_LEN], [LT_CMD_MAX_LEN]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], []) - - -# _LT_HEADER_DLFCN -# ---------------- -m4_defun([_LT_HEADER_DLFCN], -[AC_CHECK_HEADERS([dlfcn.h], [], [], [AC_INCLUDES_DEFAULT])dnl -])# _LT_HEADER_DLFCN - - -# _LT_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, -# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) -# ---------------------------------------------------------------- -m4_defun([_LT_TRY_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test "$cross_compiling" = yes; then : - [$4] -else - lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 - lt_status=$lt_dlunknown - cat > conftest.$ac_ext <<_LT_EOF -[#line __oline__ "configure" -#include "confdefs.h" - -#if HAVE_DLFCN_H -#include -#endif - -#include - -#ifdef RTLD_GLOBAL -# define LT_DLGLOBAL RTLD_GLOBAL -#else -# ifdef DL_GLOBAL -# define LT_DLGLOBAL DL_GLOBAL -# else -# define LT_DLGLOBAL 0 -# endif -#endif - -/* We may have to define LT_DLLAZY_OR_NOW in the command line if we - find out it does not work in some platform. */ -#ifndef LT_DLLAZY_OR_NOW -# ifdef RTLD_LAZY -# define LT_DLLAZY_OR_NOW RTLD_LAZY -# else -# ifdef DL_LAZY -# define LT_DLLAZY_OR_NOW DL_LAZY -# else -# ifdef RTLD_NOW -# define LT_DLLAZY_OR_NOW RTLD_NOW -# else -# ifdef DL_NOW -# define LT_DLLAZY_OR_NOW DL_NOW -# else -# define LT_DLLAZY_OR_NOW 0 -# endif -# endif -# endif -# endif -#endif - -void fnord() { int i=42;} -int main () -{ - void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); - int status = $lt_dlunknown; - - if (self) - { - if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; - /* dlclose (self); */ - } - else - puts (dlerror ()); - - return status; -}] -_LT_EOF - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then - (./conftest; exit; ) >&AS_MESSAGE_LOG_FD 2>/dev/null - lt_status=$? - case x$lt_status in - x$lt_dlno_uscore) $1 ;; - x$lt_dlneed_uscore) $2 ;; - x$lt_dlunknown|x*) $3 ;; - esac - else : - # compilation failed - $3 - fi -fi -rm -fr conftest* -])# _LT_TRY_DLOPEN_SELF - - -# LT_SYS_DLOPEN_SELF -# ------------------ -AC_DEFUN([LT_SYS_DLOPEN_SELF], -[m4_require([_LT_HEADER_DLFCN])dnl -if test "x$enable_dlopen" != xyes; then - enable_dlopen=unknown - enable_dlopen_self=unknown - enable_dlopen_self_static=unknown -else - lt_cv_dlopen=no - lt_cv_dlopen_libs= - - case $host_os in - beos*) - lt_cv_dlopen="load_add_on" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ;; - - mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" - lt_cv_dlopen_libs= - ;; - - cygwin*) - lt_cv_dlopen="dlopen" - lt_cv_dlopen_libs= - ;; - - darwin*) - # if libdl is installed we need to link against it - AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ - lt_cv_dlopen="dyld" - lt_cv_dlopen_libs= - lt_cv_dlopen_self=yes - ]) - ;; - - *) - AC_CHECK_FUNC([shl_load], - [lt_cv_dlopen="shl_load"], - [AC_CHECK_LIB([dld], [shl_load], - [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld"], - [AC_CHECK_FUNC([dlopen], - [lt_cv_dlopen="dlopen"], - [AC_CHECK_LIB([dl], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], - [AC_CHECK_LIB([svld], [dlopen], - [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], - [AC_CHECK_LIB([dld], [dld_link], - [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld"]) - ]) - ]) - ]) - ]) - ]) - ;; - esac - - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else - enable_dlopen=no - fi - - case $lt_cv_dlopen in - dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - - save_LDFLAGS="$LDFLAGS" - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - - save_LIBS="$LIBS" - LIBS="$lt_cv_dlopen_libs $LIBS" - - AC_CACHE_CHECK([whether a program can dlopen itself], - lt_cv_dlopen_self, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, - lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) - ]) - - if test "x$lt_cv_dlopen_self" = xyes; then - wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" - AC_CACHE_CHECK([whether a statically linked program can dlopen itself], - lt_cv_dlopen_self_static, [dnl - _LT_TRY_DLOPEN_SELF( - lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, - lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) - ]) - fi - - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" - ;; - esac - - case $lt_cv_dlopen_self in - yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; - *) enable_dlopen_self=unknown ;; - esac - - case $lt_cv_dlopen_self_static in - yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; - *) enable_dlopen_self_static=unknown ;; - esac -fi -_LT_DECL([dlopen_support], [enable_dlopen], [0], - [Whether dlopen is supported]) -_LT_DECL([dlopen_self], [enable_dlopen_self], [0], - [Whether dlopen of programs is supported]) -_LT_DECL([dlopen_self_static], [enable_dlopen_self_static], [0], - [Whether dlopen of statically linked programs is supported]) -])# LT_SYS_DLOPEN_SELF - -# Old name: -AU_ALIAS([AC_LIBTOOL_DLOPEN_SELF], [LT_SYS_DLOPEN_SELF]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], []) - - -# _LT_COMPILER_C_O([TAGNAME]) -# --------------------------- -# Check to see if options -c and -o are simultaneously supported by compiler. -# This macro does not hard code the compiler like AC_PROG_CC_C_O. -m4_defun([_LT_COMPILER_C_O], -[m4_require([_LT_DECL_SED])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)], - [_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no - $RM -r conftest 2>/dev/null - mkdir conftest - cd conftest - mkdir out - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - lt_compiler_flag="-o out/conftest2.$ac_objext" - # Insert the option either (1) after the last *FLAGS variable, or - # (2) before a word containing "conftest.", or (3) at the end. - # Note that $ac_compile itself does not contain backslashes and begins - # with a dollar sign (not a hyphen), so the echo should work correctly. - lt_compile=`echo "$ac_compile" | $SED \ - -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ - -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ - -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$lt_compile" 2>out/conftest.err) - ac_status=$? - cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD - if (exit $ac_status) && test -s out/conftest2.$ac_objext - then - # The compiler can only warn and ignore the option if not recognized - # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp - $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 - if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then - _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - fi - fi - chmod u+w . 2>&AS_MESSAGE_LOG_FD - $RM conftest* - # SGI C++ compiler will create directory out/ii_files/ for - # template instantiation - test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files - $RM out/* && rmdir out - cd .. - $RM -r conftest - $RM conftest* -]) -_LT_TAGDECL([compiler_c_o], [lt_cv_prog_compiler_c_o], [1], - [Does compiler simultaneously support -c and -o options?]) -])# _LT_COMPILER_C_O - - -# _LT_COMPILER_FILE_LOCKS([TAGNAME]) -# ---------------------------------- -# Check to see if we can do hard links to lock some files if needed -m4_defun([_LT_COMPILER_FILE_LOCKS], -[m4_require([_LT_ENABLE_LOCK])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -_LT_COMPILER_C_O([$1]) - -hard_links="nottested" -if test "$_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then - # do not overwrite the value of need_locks provided by the user - AC_MSG_CHECKING([if we can lock with hard links]) - hard_links=yes - $RM conftest* - ln conftest.a conftest.b 2>/dev/null && hard_links=no - touch conftest.a - ln conftest.a conftest.b 2>&5 || hard_links=no - ln conftest.a conftest.b 2>/dev/null && hard_links=no - AC_MSG_RESULT([$hard_links]) - if test "$hard_links" = no; then - AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) - need_locks=warn - fi -else - need_locks=no -fi -_LT_DECL([], [need_locks], [1], [Must we lock files when doing compilation?]) -])# _LT_COMPILER_FILE_LOCKS - - -# _LT_CHECK_OBJDIR -# ---------------- -m4_defun([_LT_CHECK_OBJDIR], -[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], -[rm -f .libs 2>/dev/null -mkdir .libs 2>/dev/null -if test -d .libs; then - lt_cv_objdir=.libs -else - # MS-DOS does not allow filenames that begin with a dot. - lt_cv_objdir=_libs -fi -rmdir .libs 2>/dev/null]) -objdir=$lt_cv_objdir -_LT_DECL([], [objdir], [0], - [The name of the directory that contains temporary libtool files])dnl -m4_pattern_allow([LT_OBJDIR])dnl -AC_DEFINE_UNQUOTED(LT_OBJDIR, "$lt_cv_objdir/", - [Define to the sub-directory in which libtool stores uninstalled libraries.]) -])# _LT_CHECK_OBJDIR - - -# _LT_LINKER_HARDCODE_LIBPATH([TAGNAME]) -# -------------------------------------- -# Check hardcoding attributes. -m4_defun([_LT_LINKER_HARDCODE_LIBPATH], -[AC_MSG_CHECKING([how to hardcode library paths into programs]) -_LT_TAGVAR(hardcode_action, $1)= -if test -n "$_LT_TAGVAR(hardcode_libdir_flag_spec, $1)" || - test -n "$_LT_TAGVAR(runpath_var, $1)" || - test "X$_LT_TAGVAR(hardcode_automatic, $1)" = "Xyes" ; then - - # We can hardcode non-existent directories. - if test "$_LT_TAGVAR(hardcode_direct, $1)" != no && - # If the only mechanism to avoid hardcoding is shlibpath_var, we - # have to relink, otherwise we might link with an installed library - # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, $1)" != no && - test "$_LT_TAGVAR(hardcode_minus_L, $1)" != no; then - # Linking always hardcodes the temporary library directory. - _LT_TAGVAR(hardcode_action, $1)=relink - else - # We can link without hardcoding, and we can hardcode nonexisting dirs. - _LT_TAGVAR(hardcode_action, $1)=immediate - fi -else - # We cannot hardcode anything, or else we can only hardcode existing - # directories. - _LT_TAGVAR(hardcode_action, $1)=unsupported -fi -AC_MSG_RESULT([$_LT_TAGVAR(hardcode_action, $1)]) - -if test "$_LT_TAGVAR(hardcode_action, $1)" = relink || - test "$_LT_TAGVAR(inherit_rpath, $1)" = yes; then - # Fast installation is not supported - enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then - # Fast installation is not necessary - enable_fast_install=needless -fi -_LT_TAGDECL([], [hardcode_action], [0], - [How to hardcode a shared library path into an executable]) -])# _LT_LINKER_HARDCODE_LIBPATH - - -# _LT_CMD_STRIPLIB -# ---------------- -m4_defun([_LT_CMD_STRIPLIB], -[m4_require([_LT_DECL_EGREP]) -striplib= -old_striplib= -AC_MSG_CHECKING([whether stripping libraries is possible]) -if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then - test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" - test -z "$striplib" && striplib="$STRIP --strip-unneeded" - AC_MSG_RESULT([yes]) -else -# FIXME - insert some real tests, host_os isn't really good enough - case $host_os in - darwin*) - if test -n "$STRIP" ; then - striplib="$STRIP -x" - old_striplib="$STRIP -S" - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - ;; - *) - AC_MSG_RESULT([no]) - ;; - esac -fi -_LT_DECL([], [old_striplib], [1], [Commands to strip libraries]) -_LT_DECL([], [striplib], [1]) -])# _LT_CMD_STRIPLIB - - -# _LT_SYS_DYNAMIC_LINKER([TAG]) -# ----------------------------- -# PORTME Fill in your ld.so characteristics -m4_defun([_LT_SYS_DYNAMIC_LINKER], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_OBJDUMP])dnl -m4_require([_LT_DECL_SED])dnl -AC_MSG_CHECKING([dynamic linker characteristics]) -m4_if([$1], - [], [ -if test "$GCC" = yes; then - case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; - esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then - # if the path contains ";" then we assume it to be the separator - # otherwise default to the standard path separator (i.e. ":") - it is - # assumed that no part of a normal pathname contains ";" but that should - # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. - lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` - for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else - test -d "$lt_sys_path" && \ - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" - fi - done - lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; - for (lt_i = NF; lt_i > 0; lt_i--) { - if ($lt_i != "" && $lt_i != ".") { - if ($lt_i == "..") { - lt_count++; - } else { - if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; - } else { - lt_count--; - } - } - } - } - if (lt_foo != "") { lt_freq[[lt_foo]]++; } - if (lt_freq[[lt_foo]] == 1) { print lt_foo; } -}'` - sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` -else - sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" -fi]) -library_names_spec= -libname_spec='lib$name' -soname_spec= -shrext_cmds=".so" -postinstall_cmds= -postuninstall_cmds= -finish_cmds= -finish_eval= -shlibpath_var= -shlibpath_overrides_runpath=unknown -version_type=none -dynamic_linker="$host_os ld.so" -sys_lib_dlsearch_path_spec="/lib /usr/lib" -need_lib_prefix=unknown -hardcode_into_libs=no - -# when you set need_version to no, make sure it does not cause -set_version -# flags to be left without arguments -need_version=unknown - -case $host_os in -aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' - shlibpath_var=LIBPATH - - # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' - ;; - -aix[[4-9]]*) - version_type=linux - need_lib_prefix=no - need_version=no - hardcode_into_libs=yes - if test "$host_cpu" = ia64; then - # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - else - # With GCC up to 2.95.x, collect2 would create an import file - # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in - # development snapshots of GCC prior to 3.0. - case $host_os in - aix4 | aix4.[[01]] | aix4.[[01]].*) - if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' - echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then - : - else - can_build_shared=no - fi - ;; - esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct - # soname into executable. Probably we can add versioning support to - # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then - # If using run time linking (on AIX 4.2 or later) use lib.so - # instead of lib.a to let people know that these are not - # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else - # We preserve .a as extension for shared libraries through AIX4.2 - # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi - shlibpath_var=LIBPATH - fi - ;; - -amigaos*) - case $host_cpu in - powerpc) - # Since July 2007 AmigaOS4 officially supports .so libraries. - # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - ;; - m68k) - library_names_spec='$libname.ixlibrary $libname.a' - # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' - ;; - esac - ;; - -beos*) - library_names_spec='${libname}${shared_ext}' - dynamic_linker="$host_os ld.so" - shlibpath_var=LIBRARY_PATH - ;; - -bsdi[[45]]*) - version_type=linux - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" - sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" - # the default ld.so.conf also contains /usr/contrib/lib and - # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow - # libtool to hard-code these into programs - ;; - -cygwin* | mingw* | pw32* | cegcc*) - version_type=windows - shrext_cmds=".dll" - need_version=no - need_lib_prefix=no - - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) - library_names_spec='$libname.dll.a' - # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ - dldir=$destdir/`dirname \$dlpath`~ - test -d \$dldir || mkdir -p \$dldir~ - $install_prog $dir/$dlname \$dldir/$dlname~ - chmod a+x \$dldir/$dlname~ - if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then - eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; - fi' - postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ - dlpath=$dir/\$dldll~ - $RM \$dlpath' - shlibpath_overrides_runpath=yes - - case $host_os in - cygwin*) - # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" - ;; - mingw* | cegcc*) - # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi - ;; - pw32*) - # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - ;; - esac - ;; - - *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' - ;; - esac - dynamic_linker='Win32 ld.exe' - # FIXME: first we should search . and the directory the executable is in - shlibpath_var=PATH - ;; - -darwin* | rhapsody*) - dynamic_linker="$host_os dyld" - version_type=darwin - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' - shlibpath_overrides_runpath=yes - shlibpath_var=DYLD_LIBRARY_PATH - shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' -m4_if([$1], [],[ - sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"]) - sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' - ;; - -dgux*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -freebsd1*) - dynamic_linker=no - ;; - -freebsd* | dragonfly*) - # DragonFly does not have aout. When/if they implement a new - # versioning mechanism, adjust this. - if test -x /usr/bin/objformat; then - objformat=`/usr/bin/objformat` - else - case $host_os in - freebsd[[123]]*) objformat=aout ;; - *) objformat=elf ;; - esac - fi - version_type=freebsd-$objformat - case $version_type in - freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - need_version=no - need_lib_prefix=no - ;; - freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' - need_version=yes - ;; - esac - shlibpath_var=LD_LIBRARY_PATH - case $host_os in - freebsd2*) - shlibpath_overrides_runpath=yes - ;; - freebsd3.[[01]]* | freebsdelf3.[[01]]*) - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - freebsd3.[[2-9]]* | freebsdelf3.[[2-9]]* | \ - freebsd4.[[0-5]] | freebsdelf4.[[0-5]] | freebsd4.1.1 | freebsdelf4.1.1) - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - *) # from 4.6 on, and DragonFly - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - esac - ;; - -gnu*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - hardcode_into_libs=yes - ;; - -hpux9* | hpux10* | hpux11*) - # Give a soname corresponding to the major version so that dld.sl refuses to - # link against other versions. - version_type=sunos - need_lib_prefix=no - need_version=no - case $host_cpu in - ia64*) - shrext_cmds='.so' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.so" - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then - sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" - else - sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" - fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - hppa*64*) - shrext_cmds='.sl' - hardcode_into_libs=yes - dynamic_linker="$host_os dld.sl" - shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH - shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec - ;; - *) - shrext_cmds='.sl' - dynamic_linker="$host_os dld.sl" - shlibpath_var=SHLIB_PATH - shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - ;; - esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. - postinstall_cmds='chmod 555 $lib' - ;; - -interix[[3-9]]*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -irix5* | irix6* | nonstopux*) - case $host_os in - nonstopux*) version_type=nonstopux ;; - *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux - else - version_type=irix - fi ;; - esac - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' - case $host_os in - irix5* | nonstopux*) - libsuff= shlibsuff= - ;; - *) - case $LD in # libtool.m4 will add one of these switches to LD - *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") - libsuff= shlibsuff= libmagic=32-bit;; - *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") - libsuff=32 shlibsuff=N32 libmagic=N32;; - *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") - libsuff=64 shlibsuff=64 libmagic=64-bit;; - *) libsuff= shlibsuff= libmagic=never-match;; - esac - ;; - esac - shlibpath_var=LD_LIBRARY${shlibsuff}_PATH - shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" - hardcode_into_libs=yes - ;; - -# No shared lib support for Linux oldld, aout, or coff. -linux*oldld* | linux*aout* | linux*coff*) - dynamic_linker=no - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ - LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], - [shlibpath_overrides_runpath=yes])]) - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir - - # This implies no fast_install, which is unacceptable. - # Some rework will be needed to allow for fast_install - # before this can be enabled. - hardcode_into_libs=yes - - # Append ld.so.conf contents to the search path - if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` - sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" - fi - - # We used to test for /lib/ld.so.1 and disable shared libraries on - # powerpc, because MkLinux only supported shared libraries with the - # GNU dynamic linker. Since this was broken with cross compilers, - # most powerpc-linux boxes support dynamic linking these days and - # people can always --disable-shared, the test was removed, and we - # assume the GNU/Linux dynamic linker is in use. - dynamic_linker='GNU/Linux ld.so' - ;; - -netbsd*) - version_type=sunos - need_lib_prefix=no - need_version=no - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - dynamic_linker='NetBSD (a.out) ld.so' - else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - dynamic_linker='NetBSD ld.elf_so' - fi - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - ;; - -newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - ;; - -*nto* | *qnx*) - version_type=qnx - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - dynamic_linker='ldqnx.so' - ;; - -openbsd*) - version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" - need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' - shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[[89]] | openbsd2.[[89]].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi - ;; - -os2*) - libname_spec='$name' - shrext_cmds=".dll" - need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' - dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH - ;; - -osf3* | osf4* | osf5*) - version_type=osf - need_lib_prefix=no - need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" - ;; - -rdos*) - dynamic_linker=no - ;; - -solaris*) - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - # ldd complains unless libraries are executable - postinstall_cmds='chmod +x $lib' - ;; - -sunos4*) - version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' - finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then - need_lib_prefix=no - fi - need_version=yes - ;; - -sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - case $host_vendor in - sni) - shlibpath_overrides_runpath=no - need_lib_prefix=no - runpath_var=LD_RUN_PATH - ;; - siemens) - need_lib_prefix=no - ;; - motorola) - need_lib_prefix=no - need_version=no - shlibpath_overrides_runpath=no - sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' - ;; - esac - ;; - -sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' - shlibpath_var=LD_LIBRARY_PATH - fi - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=yes - hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then - sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' - else - sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' - case $host_os in - sco3.2v5*) - sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" - ;; - esac - fi - sys_lib_dlsearch_path_spec='/usr/lib' - ;; - -tpf*) - # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux - need_lib_prefix=no - need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - shlibpath_var=LD_LIBRARY_PATH - shlibpath_overrides_runpath=no - hardcode_into_libs=yes - ;; - -uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH - ;; - -*) - dynamic_linker=no - ;; -esac -AC_MSG_RESULT([$dynamic_linker]) -test "$dynamic_linker" = no && can_build_shared=no - -variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then - variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" -fi - -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" -fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" -fi - -_LT_DECL([], [variables_saved_for_relink], [1], - [Variables whose values should be saved in libtool wrapper scripts and - restored at link time]) -_LT_DECL([], [need_lib_prefix], [0], - [Do we need the "lib" prefix for modules?]) -_LT_DECL([], [need_version], [0], [Do we need a version for libraries?]) -_LT_DECL([], [version_type], [0], [Library versioning type]) -_LT_DECL([], [runpath_var], [0], [Shared library runtime path variable]) -_LT_DECL([], [shlibpath_var], [0],[Shared library path variable]) -_LT_DECL([], [shlibpath_overrides_runpath], [0], - [Is shlibpath searched before the hard-coded library search path?]) -_LT_DECL([], [libname_spec], [1], [Format of library name prefix]) -_LT_DECL([], [library_names_spec], [1], - [[List of archive names. First name is the real one, the rest are links. - The last name is the one that the linker finds with -lNAME]]) -_LT_DECL([], [soname_spec], [1], - [[The coded name of the library, if different from the real name]]) -_LT_DECL([], [postinstall_cmds], [2], - [Command to use after installation of a shared archive]) -_LT_DECL([], [postuninstall_cmds], [2], - [Command to use after uninstallation of a shared archive]) -_LT_DECL([], [finish_cmds], [2], - [Commands used to finish a libtool library installation in a directory]) -_LT_DECL([], [finish_eval], [1], - [[As "finish_cmds", except a single script fragment to be evaled but - not shown]]) -_LT_DECL([], [hardcode_into_libs], [0], - [Whether we should hardcode library paths into libraries]) -_LT_DECL([], [sys_lib_search_path_spec], [2], - [Compile-time system search path for libraries]) -_LT_DECL([], [sys_lib_dlsearch_path_spec], [2], - [Run-time system search path for libraries]) -])# _LT_SYS_DYNAMIC_LINKER - - -# _LT_PATH_TOOL_PREFIX(TOOL) -# -------------------------- -# find a file program which can recognize shared library -AC_DEFUN([_LT_PATH_TOOL_PREFIX], -[m4_require([_LT_DECL_EGREP])dnl -AC_MSG_CHECKING([for $1]) -AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, -[case $MAGIC_CMD in -[[\\/*] | ?:[\\/]*]) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. - ;; -*) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR -dnl $ac_dummy forces splitting on constant user-supplied paths. -dnl POSIX.2 word splitting is done only on the output of word expansions, -dnl not every word. This closes a longstanding sh security hole. - ac_dummy="m4_if([$2], , $PATH, [$2])" - for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/$1; then - lt_cv_path_MAGIC_CMD="$ac_dir/$1" - if test -n "$file_magic_test_file"; then - case $deplibs_check_method in - "file_magic "*) - file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" - if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | - $EGREP "$file_magic_regex" > /dev/null; then - : - else - cat <<_LT_EOF 1>&2 - -*** Warning: the command libtool uses to detect shared libraries, -*** $file_magic_cmd, produces output that libtool cannot recognize. -*** The result is that libtool may fail to recognize shared libraries -*** as such. This will affect the creation of libtool libraries that -*** depend on shared libraries, but programs linked with such libtool -*** libraries will work regardless of this problem. Nevertheless, you -*** may want to report the problem to your system manager and/or to -*** bug-libtool@gnu.org - -_LT_EOF - fi ;; - esac - fi - break - fi - done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" - ;; -esac]) -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" -if test -n "$MAGIC_CMD"; then - AC_MSG_RESULT($MAGIC_CMD) -else - AC_MSG_RESULT(no) -fi -_LT_DECL([], [MAGIC_CMD], [0], - [Used to examine libraries when file_magic_cmd begins with "file"])dnl -])# _LT_PATH_TOOL_PREFIX - -# Old name: -AU_ALIAS([AC_PATH_TOOL_PREFIX], [_LT_PATH_TOOL_PREFIX]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_PATH_TOOL_PREFIX], []) - - -# _LT_PATH_MAGIC -# -------------- -# find a file program which can recognize a shared library -m4_defun([_LT_PATH_MAGIC], -[_LT_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) -if test -z "$lt_cv_path_MAGIC_CMD"; then - if test -n "$ac_tool_prefix"; then - _LT_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) - else - MAGIC_CMD=: - fi -fi -])# _LT_PATH_MAGIC - - -# LT_PATH_LD -# ---------- -# find the pathname to the GNU or non-GNU linker -AC_DEFUN([LT_PATH_LD], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_CANONICAL_BUILD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl - -AC_ARG_WITH([gnu-ld], - [AS_HELP_STRING([--with-gnu-ld], - [assume the C compiler uses GNU ld @<:@default=no@:>@])], - [test "$withval" = no || with_gnu_ld=yes], - [with_gnu_ld=no])dnl - -ac_prog=ld -if test "$GCC" = yes; then - # Check if gcc -print-prog-name=ld gives a path. - AC_MSG_CHECKING([for ld used by $CC]) - case $host in - *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw - ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; - *) - ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; - esac - case $ac_prog in - # Accept absolute paths. - [[\\/]]* | ?:[[\\/]]*) - re_direlt='/[[^/]][[^/]]*/\.\./' - # Canonicalize the pathname of ld - ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` - while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do - ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` - done - test -z "$LD" && LD="$ac_prog" - ;; - "") - # If it fails, then pretend we aren't using GCC. - ac_prog=ld - ;; - *) - # If it is relative, then search for the first ld in PATH. - with_gnu_ld=unknown - ;; - esac -elif test "$with_gnu_ld" = yes; then - AC_MSG_CHECKING([for GNU ld]) -else - AC_MSG_CHECKING([for non-GNU ld]) -fi -AC_CACHE_VAL(lt_cv_path_LD, -[if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" - # Check to see if the program is GNU ld. I'd rather use --version, - # but apparently some variants of GNU ld only accept -v. - # Break only if it was the GNU/non-GNU ld that we prefer. - case `"$lt_cv_path_LD" -v 2>&1 &1 /dev/null 2>&1; then - lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' - lt_cv_file_magic_cmd='func_win32_libid' - else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - fi - ;; - -cegcc) - # use the weaker test based on 'objdump'. See mingw*. - lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' - lt_cv_file_magic_cmd='$OBJDUMP -f' - ;; - -darwin* | rhapsody*) - lt_cv_deplibs_check_method=pass_all - ;; - -freebsd* | dragonfly*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - case $host_cpu in - i*86 ) - # Not sure whether the presence of OpenBSD here was a mistake. - # Let's accept both of them until this is cleared up. - lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[[3-9]]86 (compact )?demand paged shared library' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` - ;; - esac - else - lt_cv_deplibs_check_method=pass_all - fi - ;; - -gnu*) - lt_cv_deplibs_check_method=pass_all - ;; - -hpux10.20* | hpux11*) - lt_cv_file_magic_cmd=/usr/bin/file - case $host_cpu in - ia64*) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' - lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so - ;; - hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] - lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl - ;; - *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' - lt_cv_file_magic_test_file=/usr/lib/libc.sl - ;; - esac - ;; - -interix[[3-9]]*) - # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|\.a)$' - ;; - -irix5* | irix6* | nonstopux*) - case $LD in - *-32|*"-32 ") libmagic=32-bit;; - *-n32|*"-n32 ") libmagic=N32;; - *-64|*"-64 ") libmagic=64-bit;; - *) libmagic=never-match;; - esac - lt_cv_deplibs_check_method=pass_all - ;; - -# This must be Linux ELF. -linux* | k*bsd*-gnu) - lt_cv_deplibs_check_method=pass_all - ;; - -netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' - fi - ;; - -newos6*) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' - lt_cv_file_magic_cmd=/usr/bin/file - lt_cv_file_magic_test_file=/usr/lib/libnls.so - ;; - -*nto* | *qnx*) - lt_cv_deplibs_check_method=pass_all - ;; - -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|\.so|_pic\.a)$' - else - lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' - fi - ;; - -osf3* | osf4* | osf5*) - lt_cv_deplibs_check_method=pass_all - ;; - -rdos*) - lt_cv_deplibs_check_method=pass_all - ;; - -solaris*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - lt_cv_deplibs_check_method=pass_all - ;; - -sysv4 | sysv4.3*) - case $host_vendor in - motorola) - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' - lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` - ;; - ncr) - lt_cv_deplibs_check_method=pass_all - ;; - sequent) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' - ;; - sni) - lt_cv_file_magic_cmd='/bin/file' - lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" - lt_cv_file_magic_test_file=/lib/libc.so - ;; - siemens) - lt_cv_deplibs_check_method=pass_all - ;; - pc) - lt_cv_deplibs_check_method=pass_all - ;; - esac - ;; - -tpf*) - lt_cv_deplibs_check_method=pass_all - ;; -esac -]) -file_magic_cmd=$lt_cv_file_magic_cmd -deplibs_check_method=$lt_cv_deplibs_check_method -test -z "$deplibs_check_method" && deplibs_check_method=unknown - -_LT_DECL([], [deplibs_check_method], [1], - [Method to check whether dependent libraries are shared objects]) -_LT_DECL([], [file_magic_cmd], [1], - [Command to use when deplibs_check_method == "file_magic"]) -])# _LT_CHECK_MAGIC_METHOD - - -# LT_PATH_NM -# ---------- -# find the pathname to a BSD- or MS-compatible name lister -AC_DEFUN([LT_PATH_NM], -[AC_REQUIRE([AC_PROG_CC])dnl -AC_CACHE_CHECK([for BSD- or MS-compatible name lister (nm)], lt_cv_path_NM, -[if test -n "$NM"; then - # Let the user override the test. - lt_cv_path_NM="$NM" -else - lt_nm_to_check="${ac_tool_prefix}nm" - if test -n "$ac_tool_prefix" && test "$build" = "$host"; then - lt_nm_to_check="$lt_nm_to_check nm" - fi - for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" - test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then - # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: - # nm: unknown option "B" ignored - # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) - lt_cv_path_NM="$tmp_nm -B" - break - ;; - *) - case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in - */dev/null*) - lt_cv_path_NM="$tmp_nm -p" - break - ;; - *) - lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but - continue # so that we can try to find one that supports BSD flags - ;; - esac - ;; - esac - fi - done - IFS="$lt_save_ifs" - done - : ${lt_cv_path_NM=no} -fi]) -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" -else - # Didn't find any BSD compatible name lister, look for dumpbin. - AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) - AC_SUBST([DUMPBIN]) - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" - fi -fi -test -z "$NM" && NM=nm -AC_SUBST([NM]) -_LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl - -AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], - [lt_cv_nm_interface="BSD nm" - echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) - (eval "$ac_compile" 2>conftest.err) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) - (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) - cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) - cat conftest.out >&AS_MESSAGE_LOG_FD - if $GREP 'External.*some_variable' conftest.out > /dev/null; then - lt_cv_nm_interface="MS dumpbin" - fi - rm -f conftest*]) -])# LT_PATH_NM - -# Old names: -AU_ALIAS([AM_PROG_NM], [LT_PATH_NM]) -AU_ALIAS([AC_PROG_NM], [LT_PATH_NM]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_PROG_NM], []) -dnl AC_DEFUN([AC_PROG_NM], []) - - -# LT_LIB_M -# -------- -# check for math library -AC_DEFUN([LT_LIB_M], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -LIBM= -case $host in -*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) - # These system don't have libm, or don't need it - ;; -*-ncr-sysv4.3*) - AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") - AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") - ;; -*) - AC_CHECK_LIB(m, cos, LIBM="-lm") - ;; -esac -AC_SUBST([LIBM]) -])# LT_LIB_M - -# Old name: -AU_ALIAS([AC_CHECK_LIBM], [LT_LIB_M]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_CHECK_LIBM], []) - - -# _LT_COMPILER_NO_RTTI([TAGNAME]) -# ------------------------------- -m4_defun([_LT_COMPILER_NO_RTTI], -[m4_require([_LT_TAG_COMPILER])dnl - -_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - -if test "$GCC" = yes; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - - _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], - lt_cv_prog_compiler_rtti_exceptions, - [-fno-rtti -fno-exceptions], [], - [_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) -fi -_LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], - [Compiler flag to turn off builtin functions]) -])# _LT_COMPILER_NO_RTTI - - -# _LT_CMD_GLOBAL_SYMBOLS -# ---------------------- -m4_defun([_LT_CMD_GLOBAL_SYMBOLS], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -AC_REQUIRE([AC_PROG_CC])dnl -AC_REQUIRE([LT_PATH_NM])dnl -AC_REQUIRE([LT_PATH_LD])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_TAG_COMPILER])dnl - -# Check for command to grab the raw symbol name followed by C symbol from nm. -AC_MSG_CHECKING([command to parse $NM output from $compiler object]) -AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], -[ -# These are sane defaults that work on at least a few old systems. -# [They come from Ultrix. What could be older than Ultrix?!! ;)] - -# Character class describing NM global symbol codes. -symcode='[[BCDEGRST]]' - -# Regexp to match symbols that can be accessed directly from C. -sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' - -# Define system-specific variables. -case $host_os in -aix*) - symcode='[[BCDT]]' - ;; -cygwin* | mingw* | pw32* | cegcc*) - symcode='[[ABCDGISTW]]' - ;; -hpux*) - if test "$host_cpu" = ia64; then - symcode='[[ABCDEGRST]]' - fi - ;; -irix* | nonstopux*) - symcode='[[BCDEGRST]]' - ;; -osf*) - symcode='[[BCDEGQRST]]' - ;; -solaris*) - symcode='[[BDRT]]' - ;; -sco3.2v5*) - symcode='[[DT]]' - ;; -sysv4.2uw2*) - symcode='[[DT]]' - ;; -sysv5* | sco5v6* | unixware* | OpenUNIX*) - symcode='[[ABDT]]' - ;; -sysv4) - symcode='[[DFNSTU]]' - ;; -esac - -# If we're using GNU nm, then use its standard symbol codes. -case `$NM -V 2>&1` in -*GNU* | *'with BFD'*) - symcode='[[ABCDGIRSTW]]' ;; -esac - -# Transform an extracted symbol line into a proper C declaration. -# Some systems (esp. on ia64) link data and code symbols differently, -# so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" - -# Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \(lib[[^ ]]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"lib\2\", (void *) \&\2},/p'" - -# Handle CRLF in mingw tool chain -opt_cr= -case $build_os in -mingw*) - opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp - ;; -esac - -# Try without a prefix underscore, then with it. -for ac_symprfx in "" "_"; do - - # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. - symxfrm="\\1 $ac_symprfx\\2 \\2" - - # Write the raw and C identifiers. - if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. - # Also find C++ and __fastcall symbols from MSVC++, - # which start with @ or ?. - lt_cv_sys_global_symbol_pipe="$AWK ['"\ -" {last_section=section; section=\$ 3};"\ -" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ -" \$ 0!~/External *\|/{next};"\ -" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ -" {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ -" ' prfx=^$ac_symprfx]" - else - lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" - fi - - # Check to see that the pipe works correctly. - pipe_works=no - - rm -f conftest* - cat > conftest.$ac_ext <<_LT_EOF -#ifdef __cplusplus -extern "C" { -#endif -char nm_test_var; -void nm_test_func(void); -void nm_test_func(void){} -#ifdef __cplusplus -} -#endif -int main(){nm_test_var='a';nm_test_func();return(0);} -_LT_EOF - - if AC_TRY_EVAL(ac_compile); then - # Now try to grab the symbols. - nlist=conftest.nm - if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then - # Try sorting and uniquifying the output. - if sort "$nlist" | uniq > "$nlist"T; then - mv -f "$nlist"T "$nlist" - else - rm -f "$nlist"T - fi - - # Make sure that we snagged all the symbols we need. - if $GREP ' nm_test_var$' "$nlist" >/dev/null; then - if $GREP ' nm_test_func$' "$nlist" >/dev/null; then - cat <<_LT_EOF > conftest.$ac_ext -#ifdef __cplusplus -extern "C" { -#endif - -_LT_EOF - # Now generate the symbol file. - eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' - - cat <<_LT_EOF >> conftest.$ac_ext - -/* The mapping between symbol names and symbols. */ -const struct { - const char *name; - void *address; -} -lt__PROGRAM__LTX_preloaded_symbols[[]] = -{ - { "@PROGRAM@", (void *) 0 }, -_LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext - cat <<\_LT_EOF >> conftest.$ac_ext - {0, (void *) 0} -}; - -/* This works around a problem in FreeBSD linker */ -#ifdef FREEBSD_WORKAROUND -static const void *lt_preloaded_setup() { - return lt__PROGRAM__LTX_preloaded_symbols; -} -#endif - -#ifdef __cplusplus -} -#endif -_LT_EOF - # Now try linking the two files. - mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" - CFLAGS="$CFLAGS$_LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" - if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then - pipe_works=yes - fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" - else - echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD - fi - else - echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD - fi - else - echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD - cat conftest.$ac_ext >&5 - fi - rm -rf conftest* conftst* - - # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then - break - else - lt_cv_sys_global_symbol_pipe= - fi -done -]) -if test -z "$lt_cv_sys_global_symbol_pipe"; then - lt_cv_sys_global_symbol_to_cdecl= -fi -if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then - AC_MSG_RESULT(failed) -else - AC_MSG_RESULT(ok) -fi - -_LT_DECL([global_symbol_pipe], [lt_cv_sys_global_symbol_pipe], [1], - [Take the output of nm and produce a listing of raw symbols and C names]) -_LT_DECL([global_symbol_to_cdecl], [lt_cv_sys_global_symbol_to_cdecl], [1], - [Transform the output of nm in a proper C declaration]) -_LT_DECL([global_symbol_to_c_name_address], - [lt_cv_sys_global_symbol_to_c_name_address], [1], - [Transform the output of nm in a C name address pair]) -_LT_DECL([global_symbol_to_c_name_address_lib_prefix], - [lt_cv_sys_global_symbol_to_c_name_address_lib_prefix], [1], - [Transform the output of nm in a C name address pair when lib prefix is needed]) -]) # _LT_CMD_GLOBAL_SYMBOLS - - -# _LT_COMPILER_PIC([TAGNAME]) -# --------------------------- -m4_defun([_LT_COMPILER_PIC], -[m4_require([_LT_TAG_COMPILER])dnl -_LT_TAGVAR(lt_prog_compiler_wl, $1)= -_LT_TAGVAR(lt_prog_compiler_pic, $1)= -_LT_TAGVAR(lt_prog_compiler_static, $1)= - -AC_MSG_CHECKING([for $compiler option to produce PIC]) -m4_if([$1], [CXX], [ - # C++ specific cases for pic, static, wl, etc. - if test "$GXX" = yes; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - mingw* | cygwin* | os2* | pw32* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - *djgpp*) - # DJGPP does not support shared libraries at all - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - case $host_os in - aix[[4-9]]*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - chorus*) - case $cc_basename in - cxch68*) - # Green Hills C++ Compiler - # _LT_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" - ;; - esac - ;; - dgux*) - case $cc_basename in - ec++*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - ghcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - freebsd* | dragonfly*) - # FreeBSD uses GNU C++ - ;; - hpux9* | hpux10* | hpux11*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - if test "$host_cpu" != ia64; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - fi - ;; - aCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - ;; - *) - ;; - esac - ;; - interix*) - # This is c89, which is MS Visual C++ (no shared libs) - # Anyone wants to do a port? - ;; - irix5* | irix6* | nonstopux*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - # CC pic flag -KPIC is the default. - ;; - *) - ;; - esac - ;; - linux* | k*bsd*-gnu) - case $cc_basename in - KCC*) - # KAI C++ Compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - ecpc* ) - # old Intel C++ for x86_64 which still supported -KPIC. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - icpc* ) - # Intel C++, used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - cxx*) - # Compaq C++ - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xlc* | xlC*) - # IBM XL 8.0 on PPC - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - esac - ;; - esac - ;; - lynxos*) - ;; - m88k*) - ;; - mvs*) - case $cc_basename in - cxx*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' - ;; - *) - ;; - esac - ;; - netbsd*) - ;; - *qnx* | *nto*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' - ;; - RCC*) - # Rational C++ 2.4.1 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - cxx*) - # Digital/Compaq C++ - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # Make sure the PIC flag is empty. It appears that all Alpha - # Linux and Compaq Tru64 Unix objects are PIC. - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - *) - ;; - esac - ;; - psos*) - ;; - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - ;; - *) - ;; - esac - ;; - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - lcc*) - # Lucid - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - ;; - *) - ;; - esac - ;; - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - case $cc_basename in - CC*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - esac - ;; - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - ;; - *) - ;; - esac - ;; - vxworks*) - ;; - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -], -[ - if test "$GCC" = yes; then - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - - case $host_os in - aix*) - # All AIX code is PIC. - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - m68k) - # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' - ;; - esac - ;; - - beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) - # PIC is the default for these OSes. - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - # Although the cygwin gcc ignores -fPIC, still need this for old-style - # (--disable-auto-import) libraries - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - - darwin* | rhapsody*) - # PIC is the default on this platform - # Common symbols not allowed in MH_DYLIB files - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' - ;; - - hpux*) - # PIC is the default for 64-bit PA HP-UX, but not for 32-bit - # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag - # sets the default TLS model and affects inlining. - case $host_cpu in - hppa*64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - ;; - - interix[[3-9]]*) - # Interix 3.x gcc -fpic/-fPIC options generate broken code. - # Instead, we relocate shared libraries at runtime. - ;; - - msdosdjgpp*) - # Just because we use GCC doesn't mean we suddenly get shared libraries - # on systems that don't support them. - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - enable_shared=no - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic - fi - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - ;; - esac - else - # PORTME Check for flag to pass linker flags through the system compiler. - case $host_os in - aix*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - if test "$host_cpu" = ia64; then - # AIX 5 now supports IA64 processor - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - else - _LT_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' - fi - ;; - - mingw* | cygwin* | pw32* | os2* | cegcc*) - # This hack is so that the source file can tell whether it is being - # built for inclusion in a dll (and should export symbols for example). - m4_if([$1], [GCJ], [], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT']) - ;; - - hpux9* | hpux10* | hpux11*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but - # not for PA HP-UX. - case $host_cpu in - hppa*64*|ia64*) - # +Z the default - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='+Z' - ;; - esac - # Is there a better lt_prog_compiler_static that works with the bundled CC? - _LT_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' - ;; - - irix5* | irix6* | nonstopux*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # PIC (with -KPIC) is the default. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - linux* | k*bsd*-gnu) - case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. - ecc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # icc used to be incompatible with GCC. - # ICC 10 doesn't accept -KPIC any more. - icc* | ifort*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-static' - ;; - # Lahey Fortran 8.1. - lf95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' - _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' - ;; - pgcc* | pgf77* | pgf90* | pgf95*) - # Portland Group compilers (*not* the Pentium gcc compiler, - # which looks to be a dead project) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - ccc*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All Alpha code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - xl*) - # IBM XL C 8.0/Fortran 10.1 on PPC - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='' - ;; - esac - ;; - esac - ;; - - newsos6) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *nto* | *qnx*) - # QNX uses GNU C++, but need to define -shared option too, otherwise - # it will coredump. - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC -shared' - ;; - - osf3* | osf4* | osf5*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - # All OSF/1 code is PIC. - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - rdos*) - _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' - ;; - - solaris*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - case $cc_basename in - f77* | f90* | f95*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; - *) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; - esac - ;; - - sunos4*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4 | sysv4.2uw2* | sysv4.3*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - sysv4*MP*) - if test -d /usr/nec ;then - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - fi - ;; - - sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - unicos*) - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - - uts4*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)='-pic' - _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - ;; - - *) - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no - ;; - esac - fi -]) -case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: - *djgpp*) - _LT_TAGVAR(lt_prog_compiler_pic, $1)= - ;; - *) - _LT_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])" - ;; -esac -AC_MSG_RESULT([$_LT_TAGVAR(lt_prog_compiler_pic, $1)]) -_LT_TAGDECL([wl], [lt_prog_compiler_wl], [1], - [How to pass a linker flag through the compiler]) - -# -# Check to make sure the PIC flag actually works. -# -if test -n "$_LT_TAGVAR(lt_prog_compiler_pic, $1)"; then - _LT_COMPILER_OPTION([if $compiler PIC flag $_LT_TAGVAR(lt_prog_compiler_pic, $1) works], - [_LT_TAGVAR(lt_cv_prog_compiler_pic_works, $1)], - [$_LT_TAGVAR(lt_prog_compiler_pic, $1)@&t@m4_if([$1],[],[ -DPIC],[m4_if([$1],[CXX],[ -DPIC],[])])], [], - [case $_LT_TAGVAR(lt_prog_compiler_pic, $1) in - "" | " "*) ;; - *) _LT_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_TAGVAR(lt_prog_compiler_pic, $1)" ;; - esac], - [_LT_TAGVAR(lt_prog_compiler_pic, $1)= - _LT_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) -fi -_LT_TAGDECL([pic_flag], [lt_prog_compiler_pic], [1], - [Additional compiler flags for building library objects]) - -# -# Check to make sure the static flag actually works. -# -wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) eval lt_tmp_static_flag=\"$_LT_TAGVAR(lt_prog_compiler_static, $1)\" -_LT_LINKER_OPTION([if $compiler static flag $lt_tmp_static_flag works], - _LT_TAGVAR(lt_cv_prog_compiler_static_works, $1), - $lt_tmp_static_flag, - [], - [_LT_TAGVAR(lt_prog_compiler_static, $1)=]) -_LT_TAGDECL([link_static_flag], [lt_prog_compiler_static], [1], - [Compiler flag to prevent dynamic linking]) -])# _LT_COMPILER_PIC - - -# _LT_LINKER_SHLIBS([TAGNAME]) -# ---------------------------- -# See if the linker supports building shared libraries. -m4_defun([_LT_LINKER_SHLIBS], -[AC_REQUIRE([LT_PATH_LD])dnl -AC_REQUIRE([LT_PATH_NM])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl -m4_require([_LT_DECL_SED])dnl -m4_require([_LT_CMD_GLOBAL_SYMBOLS])dnl -m4_require([_LT_TAG_COMPILER])dnl -AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) -m4_if([$1], [CXX], [ - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - case $host_os in - aix[[4-9]]*) - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - ;; - pw32*) - _LT_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" - ;; - cygwin* | mingw* | cegcc*) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/;/^.*[[ ]]__nm__/s/^.*[[ ]]__nm__\([[^ ]]*\)[[ ]][[^ ]]*/\1 DATA/;/^I[[ ]]/d;/^[[AITW]][[ ]]/s/.* //'\'' | sort | uniq > $export_symbols' - ;; - *) - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - ;; - esac - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] -], [ - runpath_var= - _LT_TAGVAR(allow_undefined_flag, $1)= - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(archive_cmds, $1)= - _LT_TAGVAR(archive_expsym_cmds, $1)= - _LT_TAGVAR(compiler_needs_object, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' - _LT_TAGVAR(hardcode_automatic, $1)=no - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= - _LT_TAGVAR(hardcode_libdir_separator, $1)= - _LT_TAGVAR(hardcode_minus_L, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(inherit_rpath, $1)=no - _LT_TAGVAR(link_all_deplibs, $1)=unknown - _LT_TAGVAR(module_cmds, $1)= - _LT_TAGVAR(module_expsym_cmds, $1)= - _LT_TAGVAR(old_archive_from_new_cmds, $1)= - _LT_TAGVAR(old_archive_from_expsyms_cmds, $1)= - _LT_TAGVAR(thread_safe_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - # include_expsyms should be a list of space-separated symbols to be *always* - # included in the symbol list - _LT_TAGVAR(include_expsyms, $1)= - # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. - _LT_TAGVAR(exclude_expsyms, $1)=['_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*'] - # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out - # platforms (ab)use it in PIC code, but their linkers get confused if - # the symbol is explicitly referenced. Since portable code cannot - # rely on this symbol name, it's probably fine to never include it in - # preloaded symbol tables. - # Exclude shared library initialization/finalization symbols. -dnl Note also adjust exclude_expsyms for C++ above. - extract_expsyms_cmds= - - case $host_os in - cygwin* | mingw* | pw32* | cegcc*) - # FIXME: the MSVC++ port hasn't been tested in a loooong time - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - if test "$GCC" != yes; then - with_gnu_ld=no - fi - ;; - interix*) - # we just hope/assume this is gcc and not c89 (= MSVC++) - with_gnu_ld=yes - ;; - openbsd*) - with_gnu_ld=no - ;; - esac - - _LT_TAGVAR(ld_shlibs, $1)=yes - if test "$with_gnu_ld" = yes; then - # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' - - # Set some defaults for GNU ld with shared library support. These - # are reset later if shared libraries are not supported. Putting them - # here allows them to be overridden if necessary. - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - # ancient GNU ld didn't support --whole-archive et. al. - if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - supports_anon_versioning=no - case `$LD -v 2>&1` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 - *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... - *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... - *\ 2.11.*) ;; # other 2.11 versions - *) supports_anon_versioning=yes ;; - esac - - # See if GNU ld supports shared libraries. - case $host_os in - aix[[3-9]]*) - # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: the GNU linker, at least up to release 2.9.1, is reported -*** to be unable to reliably create shared libraries on AIX. -*** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. - -_LT_EOF - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - _LT_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGRS]][[ ]]/s/.*[[ ]]\([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]][[ ]]/s/.*[[ ]]//'\'' | sort | uniq > $export_symbols' - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - - gnu* | linux* | tpf* | k*bsd*-gnu) - tmp_diet=no - if test "$host_os" = linux-dietlibc; then - case $cc_basename in - diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) - esac - fi - if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no - then - tmp_addflag= - tmp_sharedflag='-shared' - case $cc_basename,$host_cpu in - pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag' - ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - tmp_addflag=' $pic_flag -Mnomain' ;; - ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 - tmp_addflag=' -i_dynamic' ;; - efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 - tmp_addflag=' -i_dynamic -nofor_main' ;; - ifc* | ifort*) # Intel Fortran compiler - tmp_addflag=' -nofor_main' ;; - lf95*) # Lahey Fortran 8.1 - _LT_TAGVAR(whole_archive_flag_spec, $1)= - tmp_sharedflag='--shared' ;; - xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) - tmp_sharedflag='-qmkshrobj' - tmp_addflag= ;; - esac - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - tmp_sharedflag='-G' ;; - *Sun\ F*) # Sun Fortran 8.3 - tmp_sharedflag='-G' ;; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - - case $cc_basename in - xlf*) - # IBM XL Fortran 10.1 on PPC cannot create shared libs itself - _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' - _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' - fi - ;; - esac - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' - wlarc= - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - fi - ;; - - solaris*) - if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: The releases 2.8.* of the GNU linker cannot reliably -*** create shared libraries on Solaris systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.9.1 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) - case `$LD -v 2>&1` in - *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.1[[0-5]].*) - _LT_TAGVAR(ld_shlibs, $1)=no - cat <<_LT_EOF 1>&2 - -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not -*** reliably create shared libraries on SCO systems. Therefore, libtool -*** is disabling shared libraries support. We urge you to upgrade GNU -*** binutils to release 2.16.91.0.3 or newer. Another option is to modify -*** your PATH or compiler configuration so that the native linker is -*** used, and then restart. - -_LT_EOF - ;; - *) - # For security reasons, it is highly recommended that you always - # use absolute paths for naming shared libraries, and exclude the - # DT_RUNPATH tag from executables and libraries. But doing so - # requires that you compile everything twice, which is a pain. - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - sunos4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - - if test "$_LT_TAGVAR(ld_shlibs, $1)" = no; then - runpath_var= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= - _LT_TAGVAR(export_dynamic_flag_spec, $1)= - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - # PORTME fill in a description of your system's linker (not GNU ld) - case $host_os in - aix3*) - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=yes - _LT_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' - # Note: this linker hardcodes the directories in LIBPATH if there - # are no directories specified by -L. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then - # Neither direct hardcoding nor static linking is supported with a - # broken collect2. - _LT_TAGVAR(hardcode_direct, $1)=unsupported - fi - ;; - - aix[[4-9]]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm - if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - else - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' - fi - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then - aix_use_runtimelinking=yes - break - fi - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' - - if test "$GCC" = yes; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - ;; - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - amigaos*) - case $host_cpu in - powerpc) - # see comment about AmigaOS4 .so support - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='' - ;; - m68k) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - ;; - - bsdi[[45]]*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # When not using gcc, we currently assume that we are using - # Microsoft Visual C++. - # hardcode_libdir_flag_spec is actually meaningless, as there is - # no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' - # FIXME: Should let the user specify the lib program. - _LT_TAGVAR(old_archive_cmds, $1)='lib -OUT:$oldlib$oldobjs$old_deplibs' - _LT_TAGVAR(fix_srcfile_path, $1)='`cygpath -w "$srcfile"`' - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - ;; - - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - dgux*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - freebsd1*) - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor - # support. Future versions do this automatically, but an explicit c++rt0.o - # does not break anything, and helps significantly (at the cost of a little - # extra space). - freebsd2.2*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - # FreeBSD 3 and greater uses gcc -shared to do shared libraries. - freebsd* | dragonfly*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - hpux9*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - - hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' - fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - fi - ;; - - hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - else - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - fi - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - - # hardcode_minus_L: Not really in the search PATH, - # but as the default location of the library. - _LT_TAGVAR(hardcode_minus_L, $1)=yes - ;; - esac - fi - ;; - - irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - # Try to use the -exported_symbol ld option, if it does not - # work, assume that -exports_file does not work either and - # implicitly export all symbols. - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - AC_LINK_IFELSE(int foo(void) {}, - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' - ) - LDFLAGS="$save_LDFLAGS" - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out - else - _LT_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - newsos6) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *nto* | *qnx*) - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - else - case $host_os in - openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - ;; - esac - fi - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - os2*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' - ;; - - osf3*) - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - else - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' - - # Both c and cxx compiler support -rpath directly - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - fi - _LT_TAGVAR(archive_cmds_need_lc, $1)='no' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - ;; - - solaris*) - _LT_TAGVAR(no_undefined_flag, $1)=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - else - case `$CC -V 2>&1` in - *"Compilers 5.0"*) - wlarc='' - _LT_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' - ;; - *) - wlarc='${wl}' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' - ;; - esac - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', - # but is careful enough not to reorder. - # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - fi - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - - sunos4*) - if test "x$host_vendor" = xsequent; then - # Use $CC to link under sequent, because it throws in some extra .o - # files that make .init and .fini sections work. - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' - fi - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4) - case $host_vendor in - sni) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=yes # is this really true??? - ;; - siemens) - ## LD is ld it makes a PLAMLIB - ## CC just makes a GrossModule. - _LT_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' - _LT_TAGVAR(hardcode_direct, $1)=no - ;; - motorola) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie - ;; - esac - runpath_var='LD_RUN_PATH' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - sysv4.3*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' - ;; - - sysv4*MP*) - if test -d /usr/nec; then - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var=LD_RUN_PATH - hardcode_runpath_var=yes - _LT_TAGVAR(ld_shlibs, $1)=yes - fi - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - fi - ;; - - uts4*) - _LT_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - - *) - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - if test x$host_vendor = xsni; then - case $host in - sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Blargedynsym' - ;; - esac - fi - fi -]) -AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) -test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - -_LT_TAGVAR(with_gnu_ld, $1)=$with_gnu_ld - -_LT_DECL([], [libext], [0], [Old archive suffix (normally "a")])dnl -_LT_DECL([], [shrext_cmds], [1], [Shared library suffix (normally ".so")])dnl -_LT_DECL([], [extract_expsyms_cmds], [2], - [The commands to extract the exported symbol list from a shared archive]) - -# -# Do we need to explicitly link libc? -# -case "x$_LT_TAGVAR(archive_cmds_need_lc, $1)" in -x|xyes) - # Assume -lc should be added - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - - if test "$enable_shared" = yes && test "$GCC" = yes; then - case $_LT_TAGVAR(archive_cmds, $1) in - *'~'*) - # FIXME: we may have to deal with multi-command sequences. - ;; - '$CC '*) - # Test whether the compiler implicitly links with -lc since on some - # systems, -lgcc has to come before -lc. If gcc already passes -lc - # to ld, don't add -lc before -lgcc. - AC_MSG_CHECKING([whether -lc should be explicitly linked in]) - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) - pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) - _LT_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) - then - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - else - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) - ;; - esac - fi - ;; -esac - -_LT_TAGDECL([build_libtool_need_lc], [archive_cmds_need_lc], [0], - [Whether or not to add -lc for building shared libraries]) -_LT_TAGDECL([allow_libtool_libs_with_static_runtimes], - [enable_shared_with_static_runtimes], [0], - [Whether or not to disallow shared libs when runtime libs are static]) -_LT_TAGDECL([], [export_dynamic_flag_spec], [1], - [Compiler flag to allow reflexive dlopens]) -_LT_TAGDECL([], [whole_archive_flag_spec], [1], - [Compiler flag to generate shared objects directly from archives]) -_LT_TAGDECL([], [compiler_needs_object], [1], - [Whether the compiler copes with passing no objects directly]) -_LT_TAGDECL([], [old_archive_from_new_cmds], [2], - [Create an old-style archive from a shared archive]) -_LT_TAGDECL([], [old_archive_from_expsyms_cmds], [2], - [Create a temporary old-style archive to link instead of a shared archive]) -_LT_TAGDECL([], [archive_cmds], [2], [Commands used to build a shared archive]) -_LT_TAGDECL([], [archive_expsym_cmds], [2]) -_LT_TAGDECL([], [module_cmds], [2], - [Commands used to build a loadable module if different from building - a shared archive.]) -_LT_TAGDECL([], [module_expsym_cmds], [2]) -_LT_TAGDECL([], [with_gnu_ld], [1], - [Whether we are building with GNU ld or not]) -_LT_TAGDECL([], [allow_undefined_flag], [1], - [Flag that allows shared libraries with undefined symbols to be built]) -_LT_TAGDECL([], [no_undefined_flag], [1], - [Flag that enforces no undefined symbols]) -_LT_TAGDECL([], [hardcode_libdir_flag_spec], [1], - [Flag to hardcode $libdir into a binary during linking. - This must work even if $libdir does not exist]) -_LT_TAGDECL([], [hardcode_libdir_flag_spec_ld], [1], - [[If ld is used when linking, flag to hardcode $libdir into a binary - during linking. This must work even if $libdir does not exist]]) -_LT_TAGDECL([], [hardcode_libdir_separator], [1], - [Whether we need a single "-rpath" flag with a separated argument]) -_LT_TAGDECL([], [hardcode_direct], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes - DIR into the resulting binary]) -_LT_TAGDECL([], [hardcode_direct_absolute], [0], - [Set to "yes" if using DIR/libNAME${shared_ext} during linking hardcodes - DIR into the resulting binary and the resulting library dependency is - "absolute", i.e impossible to change by setting ${shlibpath_var} if the - library is relocated]) -_LT_TAGDECL([], [hardcode_minus_L], [0], - [Set to "yes" if using the -LDIR flag during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_shlibpath_var], [0], - [Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR - into the resulting binary]) -_LT_TAGDECL([], [hardcode_automatic], [0], - [Set to "yes" if building a shared library automatically hardcodes DIR - into the library and all subsequent libraries and executables linked - against it]) -_LT_TAGDECL([], [inherit_rpath], [0], - [Set to yes if linker adds runtime paths of dependent libraries - to runtime path list]) -_LT_TAGDECL([], [link_all_deplibs], [0], - [Whether libtool must link a program against all its dependency libraries]) -_LT_TAGDECL([], [fix_srcfile_path], [1], - [Fix the shell variable $srcfile for the compiler]) -_LT_TAGDECL([], [always_export_symbols], [0], - [Set to "yes" if exported symbols are required]) -_LT_TAGDECL([], [export_symbols_cmds], [2], - [The commands to list exported symbols]) -_LT_TAGDECL([], [exclude_expsyms], [1], - [Symbols that should not be listed in the preloaded symbols]) -_LT_TAGDECL([], [include_expsyms], [1], - [Symbols that must always be exported]) -_LT_TAGDECL([], [prelink_cmds], [2], - [Commands necessary for linking programs (against libraries) with templates]) -_LT_TAGDECL([], [file_list_spec], [1], - [Specify filename containing input files]) -dnl FIXME: Not yet implemented -dnl _LT_TAGDECL([], [thread_safe_flag_spec], [1], -dnl [Compiler flag to generate thread safe objects]) -])# _LT_LINKER_SHLIBS - - -# _LT_LANG_C_CONFIG([TAG]) -# ------------------------ -# Ensure that the configuration variables for a C compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. -m4_defun([_LT_LANG_C_CONFIG], -[m4_require([_LT_DECL_EGREP])dnl -lt_save_CC="$CC" -AC_LANG_PUSH(C) - -# Source file extension for C test sources. -ac_ext=c - -# Object file extension for compiled C test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="int some_variable = 0;" - -# Code to be used in simple link tests -lt_simple_link_test_code='int main(){return(0);}' - -_LT_TAG_COMPILER -# Save the default compiler, since it gets overwritten when the other -# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. -compiler_DEFAULT=$CC - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - LT_SYS_DLOPEN_SELF - _LT_CMD_STRIPLIB - - # Report which library types will actually be built - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_CONFIG($1) -fi -AC_LANG_POP -CC="$lt_save_CC" -])# _LT_LANG_C_CONFIG - - -# _LT_PROG_CXX -# ------------ -# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ -# compiler, we have our own version here. -m4_defun([_LT_PROG_CXX], -[ -pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) -AC_PROG_CXX -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - AC_PROG_CXXCPP -else - _lt_caught_CXX_error=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_CXX - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_CXX], []) - - -# _LT_LANG_CXX_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a C++ compiler are suitably -# defined. These variables are subsequently used by _LT_CONFIG to write -# the compiler configuration to `libtool'. -m4_defun([_LT_LANG_CXX_CONFIG], -[AC_REQUIRE([_LT_PROG_CXX])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl -m4_require([_LT_DECL_EGREP])dnl - -AC_LANG_PUSH(C++) -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(compiler_needs_object, $1)=no -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for C++ test sources. -ac_ext=cpp - -# Object file extension for compiled C++ test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the CXX compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_caught_CXX_error" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="int some_variable = 0;" - - # Code to be used in simple link tests - lt_simple_link_test_code='int main(int, char *[[]]) { return(0); }' - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC=$CC - lt_save_LD=$LD - lt_save_GCC=$GCC - GCC=$GXX - lt_save_with_gnu_ld=$with_gnu_ld - lt_save_path_LD=$lt_cv_path_LD - if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then - lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx - else - $as_unset lt_cv_prog_gnu_ld - fi - if test -n "${lt_cv_path_LDCXX+set}"; then - lt_cv_path_LD=$lt_cv_path_LDCXX - else - $as_unset lt_cv_path_LD - fi - test -z "${LDCXX+set}" || LD=$LDCXX - CC=${CXX-"c++"} - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - # We don't want -fno-exception when compiling C++ code, so set the - # no_builtin_flag separately - if test "$GXX" = yes; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' - else - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= - fi - - if test "$GXX" = yes; then - # Set up default GNU C++ configuration - - LT_PATH_LD - - # Check if GNU C++ uses GNU ld as the underlying linker, since the - # archiving commands below assume that GNU ld is being used. - if test "$with_gnu_ld" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # If archive_cmds runs LD, not CC, wlarc should be empty - # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to - # investigate it a little bit more. (MM) - wlarc='${wl}' - - # ancient GNU ld didn't support --whole-archive et. al. - if eval "`$CC -print-prog-name=ld` --help 2>&1" | - $GREP 'no-whole-archive' > /dev/null; then - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - else - _LT_TAGVAR(whole_archive_flag_spec, $1)= - fi - else - with_gnu_ld=no - wlarc= - - # A generic and very simple default shared library creation - # command for GNU C++ for the case where it uses the native - # linker, instead of GNU ld. If possible, this setting should - # overridden to take advantage of the native linker features on - # the platform it is being used on. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - fi - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' - - else - GXX=no - with_gnu_ld=no - wlarc= - fi - - # PORTME: fill in a description of your system's C++ link characteristics - AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) - _LT_TAGVAR(ld_shlibs, $1)=yes - case $host_os in - aix3*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aix[[4-9]]*) - if test "$host_cpu" = ia64; then - # On IA64, the linker does run time linking by default, so we don't - # have to do anything special. - aix_use_runtimelinking=no - exp_sym_flag='-Bexport' - no_entry_flag="" - else - aix_use_runtimelinking=no - - # Test if we are trying to use run time linking or normal - # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. - case $host_os in aix4.[[23]]|aix4.[[23]].*|aix[[5-9]]*) - for ld_flag in $LDFLAGS; do - case $ld_flag in - *-brtl*) - aix_use_runtimelinking=yes - break - ;; - esac - done - ;; - esac - - exp_sym_flag='-bexport' - no_entry_flag='-bnoentry' - fi - - # When large executables or shared objects are built, AIX ld can - # have problems creating the table of contents. If linking a library - # or program results in "error TOC overflow" add -mminimal-toc to - # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not - # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. - - _LT_TAGVAR(archive_cmds, $1)='' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(file_list_spec, $1)='${wl}-f,' - - if test "$GXX" = yes; then - case $host_os in aix4.[[012]]|aix4.[[012]].*) - # We only want to do this on AIX 4.2 and lower, the check - # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` - if test -f "$collect2name" && - strings "$collect2name" | $GREP resolve_lib_name >/dev/null - then - # We have reworked collect2 - : - else - # We have old collect2 - _LT_TAGVAR(hardcode_direct, $1)=unsupported - # It fails to find uninstalled libraries when the uninstalled - # path is not listed in the libpath. Setting hardcode_minus_L - # to unsupported forces relinking - _LT_TAGVAR(hardcode_minus_L, $1)=yes - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)= - fi - esac - shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' - fi - else - # not using gcc - if test "$host_cpu" = ia64; then - # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release - # chokes on -Wl,-G. The following line is correct: - shared_flag='-G' - else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' - else - shared_flag='${wl}-bM:SRE' - fi - fi - fi - - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-bexpall' - # It seems that -bexpall does not export symbols beginning with - # underscore (_), so it is better to generate a list of symbols to - # export. - _LT_TAGVAR(always_export_symbols, $1)=yes - if test "$aix_use_runtimelinking" = yes; then - # Warning - without using the other runtime loading flags (-brtl), - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(allow_undefined_flag, $1)='-berok' - # Determine the default libpath from the value encoded in an empty - # executable. - _LT_SYS_MODULE_PATH_AIX - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" - else - if test "$host_cpu" = ia64; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' - _LT_TAGVAR(allow_undefined_flag, $1)="-z nodefs" - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" - else - # Determine the default libpath from the value encoded in an - # empty executable. - _LT_SYS_MODULE_PATH_AIX - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - # Warning - without using the other run time loading flags, - # -berok will link without error, but may produce a broken library. - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - # This is similar to how AIX traditionally builds its shared - # libraries. - _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' - fi - fi - ;; - - beos*) - if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - # Joseph Beckenbach says some releases of gcc - # support --undefined. This deserves some investigation. FIXME - _LT_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - chorus*) - case $cc_basename in - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - cygwin* | mingw* | pw32* | cegcc*) - # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, - # as there is no search path for DLLs. - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' - _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(always_export_symbols, $1)=no - _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes - - if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - _LT_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - darwin* | rhapsody*) - _LT_DARWIN_LINKER_FEATURES($1) - ;; - - dgux*) - case $cc_basename in - ec++*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - ghcx*) - # Green Hills C++ Compiler - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - freebsd[[12]]*) - # C++ shared libraries reported to be fairly broken before - # switch to ELF - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - freebsd-elf*) - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - ;; - - freebsd* | dragonfly*) - # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF - # conventions - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - gnu*) - ;; - - hpux9*) - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - ;; - *) - if test "$GXX" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$RM $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - hpux10*|hpux11*) - if test $with_gnu_ld = no; then - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - case $host_cpu in - hppa*64*|ia64*) - ;; - *) - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - ;; - esac - fi - case $host_cpu in - hppa*64*|ia64*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - ;; - *) - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, - # but as the default - # location of the library. - ;; - esac - - case $cc_basename in - CC*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - aCC*) - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - ;; - *) - if test "$GXX" = yes; then - if test $with_gnu_ld = no; then - case $host_cpu in - hppa*64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - ia64*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - ;; - esac - fi - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - interix[[3-9]]*) - _LT_TAGVAR(hardcode_direct, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. - # Instead, shared libraries are loaded at an image base (0x10000000 by - # default) and relocated if they conflict, which is a slow very memory - # consuming and fragmenting process. To avoid this, we pick a random, - # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link - # time. Moving up from 0x10000000 also allows more sbrk(2) space. - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - ;; - irix5* | irix6*) - case $cc_basename in - CC*) - # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - - # Archives containing C++ object files must be created using - # "CC -ar", where "CC" is the IRIX C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' - ;; - *) - if test "$GXX" = yes; then - if test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' - fi - fi - _LT_TAGVAR(link_all_deplibs, $1)=yes - ;; - esac - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - _LT_TAGVAR(inherit_rpath, $1)=yes - ;; - - linux* | k*bsd*-gnu) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - - # Archives containing C++ object files must be created using - # "CC -Bstatic", where "CC" is the KAI C++ compiler. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' - ;; - icpc* | ecpc* ) - # Intel C++ - with_gnu_ld=yes - # version 8.0 and above of icpc choke on multiply defined symbols - # if we add $predep_objects and $postdep_objects, however 7.1 and - # earlier do not add the objects themselves. - case `$CC -V 2>&1` in - *"Version 7."*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - *) # Version 8.0 or newer - tmp_idyn= - case $host_cpu in - ia64*) tmp_idyn=' -i_dynamic';; - esac - _LT_TAGVAR(archive_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' - ;; - esac - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' - ;; - pgCC* | pgcpp*) - # Portland Group C++ compiler - case `$CC -V` in - *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) - _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' - _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ - $RANLIB $oldlib' - _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ - rm -rf $tpldir~ - $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - *) # Version 6 will use weak symbols - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - ;; - cxx*) - # Compaq C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' - - runpath_var=LD_RUN_PATH - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - ;; - xl*) - # IBM XL 8.0 on PPC, with GNU ld - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(archive_cmds, $1)='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' - fi - ;; - *) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' - _LT_TAGVAR(compiler_needs_object, $1)=yes - - # Not sure whether something based on - # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 - # would be better. - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - esac - ;; - esac - ;; - - lynxos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - m88k*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - mvs*) - case $cc_basename in - cxx*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - netbsd*) - if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' - wlarc= - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - fi - # Workaround some broken pre-1.5 toolchains - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' - ;; - - *nto* | *qnx*) - _LT_TAGVAR(ld_shlibs, $1)=yes - ;; - - openbsd2*) - # C++ shared libraries are fairly broken - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - openbsd*) - if test -f /usr/libexec/ld.so; then - _LT_TAGVAR(hardcode_direct, $1)=yes - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_direct_absolute, $1)=yes - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' - _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' - fi - output_verbose_link_cmd=echo - else - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - - osf3* | osf4* | osf5*) - case $cc_basename in - KCC*) - # Kuck and Associates, Inc. (KAI) C++ Compiler - - # KCC will only create a shared library if the output file - # ends with ".so" (or ".sl" for HP-UX), so rename the library - # to its proper name (with version) after linking. - _LT_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Archives containing C++ object files must be created using - # the KAI C++ compiler. - case $host in - osf3*) _LT_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' ;; - *) _LT_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' ;; - esac - ;; - RCC*) - # Rational C++ 2.4.1 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - cxx*) - case $host in - osf3*) - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - ;; - *) - _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ - echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ - $RM $lib.exp' - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - # - # There doesn't appear to be a way to prevent this compiler from - # explicitly linking system object files so we need to strip them - # from the output so that they don't get included in the library - # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' - ;; - *) - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - case $host in - osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - ;; - esac - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=: - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' - - else - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - fi - ;; - esac - ;; - - psos*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - sunos4*) - case $cc_basename in - CC*) - # Sun C++ 4.x - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - lcc*) - # Lucid - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - solaris*) - case $cc_basename in - CC*) - # Sun C++ 4.2, 5.x and Centerline C++ - _LT_TAGVAR(archive_cmds_need_lc,$1)=yes - _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' - _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. - # Supported since Solaris 2.6 (maybe 2.5.1?) - _LT_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' - ;; - esac - _LT_TAGVAR(link_all_deplibs, $1)=yes - - output_verbose_link_cmd='echo' - - # Archives containing C++ object files must be created using - # "CC -xar", where "CC" is the Sun C++ compiler. This is - # necessary to make sure instantiated templates are included - # in the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' - ;; - gcx*) - # Green Hills C++ Compiler - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - - # The C++ compiler must be used to create the archive. - _LT_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' - ;; - *) - # GNU C++ compiler with Solaris linker - if test "$GXX" = yes && test "$with_gnu_ld" = no; then - _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' - if $CC --version | $GREP -v '^2\.7' > /dev/null; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' - else - # g++ 2.7 appears to require `-G' NOT `-shared' on this - # platform. - _LT_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' - - # Commands to make compiler produce verbose output that lists - # what "hidden" libraries, object files and flags are used when - # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' - fi - - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' - case $host_os in - solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; - *) - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' - ;; - esac - fi - ;; - esac - ;; - - sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[[01]].[[10]]* | unixware7* | sco3.2v5.0.[[024]]*) - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not - # link with -lc, and that would cause any symbols used from libc to - # always be unresolved, which means just about no library would - # ever link correctly. If we're not using GNU ld we use -z text - # though, which does catch some bad symbols but isn't as heavy-handed - # as -z defs. - _LT_TAGVAR(no_undefined_flag, $1)='${wl}-z,text' - _LT_TAGVAR(allow_undefined_flag, $1)='${wl}-z,nodefs' - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - _LT_TAGVAR(hardcode_shlibpath_var, $1)=no - _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R,$libdir' - _LT_TAGVAR(hardcode_libdir_separator, $1)=':' - _LT_TAGVAR(link_all_deplibs, $1)=yes - _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' - runpath_var='LD_RUN_PATH' - - case $cc_basename in - CC*) - _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - ;; - esac - ;; - - tandem*) - case $cc_basename in - NCC*) - # NonStop-UX NCC 3.20 - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - ;; - - vxworks*) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - - *) - # FIXME: insert proper C++ library support - _LT_TAGVAR(ld_shlibs, $1)=no - ;; - esac - - AC_MSG_RESULT([$_LT_TAGVAR(ld_shlibs, $1)]) - test "$_LT_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no - - _LT_TAGVAR(GCC, $1)="$GXX" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - CC=$lt_save_CC - LDCXX=$LD - LD=$lt_save_LD - GCC=$lt_save_GCC - with_gnu_ld=$lt_save_with_gnu_ld - lt_cv_path_LDCXX=$lt_cv_path_LD - lt_cv_path_LD=$lt_save_path_LD - lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld - lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld -fi # test "$_lt_caught_CXX_error" != yes - -AC_LANG_POP -])# _LT_LANG_CXX_CONFIG - - -# _LT_SYS_HIDDEN_LIBDEPS([TAGNAME]) -# --------------------------------- -# Figure out "hidden" library dependencies from verbose -# compiler output when linking a shared library. -# Parse the compiler output and extract the necessary -# objects, libraries and library flags. -m4_defun([_LT_SYS_HIDDEN_LIBDEPS], -[m4_require([_LT_FILEUTILS_DEFAULTS])dnl -# Dependencies to place before and after the object being linked: -_LT_TAGVAR(predep_objects, $1)= -_LT_TAGVAR(postdep_objects, $1)= -_LT_TAGVAR(predeps, $1)= -_LT_TAGVAR(postdeps, $1)= -_LT_TAGVAR(compiler_lib_search_path, $1)= - -dnl we can't use the lt_simple_compile_test_code here, -dnl because it contains code intended for an executable, -dnl not a library. It's possible we should let each -dnl tag define a new lt_????_link_test_code variable, -dnl but it's only used here... -m4_if([$1], [], [cat > conftest.$ac_ext <<_LT_EOF -int a; -void foo (void) { a = 0; } -_LT_EOF -], [$1], [CXX], [cat > conftest.$ac_ext <<_LT_EOF -class Foo -{ -public: - Foo (void) { a = 0; } -private: - int a; -}; -_LT_EOF -], [$1], [F77], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer*4 a - a=0 - return - end -_LT_EOF -], [$1], [FC], [cat > conftest.$ac_ext <<_LT_EOF - subroutine foo - implicit none - integer a - a=0 - return - end -_LT_EOF -], [$1], [GCJ], [cat > conftest.$ac_ext <<_LT_EOF -public class foo { - private int a; - public void bar (void) { - a = 0; - } -}; -_LT_EOF -]) -dnl Parse the compiler output and extract the necessary -dnl objects, libraries and library flags. -if AC_TRY_EVAL(ac_compile); then - # Parse the compiler output and extract the necessary - # objects, libraries and library flags. - - # Sentinel used to keep track of whether or not we are before - # the conftest object file. - pre_test_object_deps_done=no - - for p in `eval "$output_verbose_link_cmd"`; do - case $p in - - -L* | -R* | -l*) - # Some compilers place space between "-{L,R}" and the path. - # Remove the space. - if test $p = "-L" || - test $p = "-R"; then - prev=$p - continue - else - prev= - fi - - if test "$pre_test_object_deps_done" = no; then - case $p in - -L* | -R*) - # Internal compiler library paths should come after those - # provided the user. The postdeps already come after the - # user supplied libs so there is no need to process them. - if test -z "$_LT_TAGVAR(compiler_lib_search_path, $1)"; then - _LT_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" - else - _LT_TAGVAR(compiler_lib_search_path, $1)="${_LT_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" - fi - ;; - # The "-l" case would never come before the object being - # linked, so don't bother handling this case. - esac - else - if test -z "$_LT_TAGVAR(postdeps, $1)"; then - _LT_TAGVAR(postdeps, $1)="${prev}${p}" - else - _LT_TAGVAR(postdeps, $1)="${_LT_TAGVAR(postdeps, $1)} ${prev}${p}" - fi - fi - ;; - - *.$objext) - # This assumes that the test object file only shows up - # once in the compiler output. - if test "$p" = "conftest.$objext"; then - pre_test_object_deps_done=yes - continue - fi - - if test "$pre_test_object_deps_done" = no; then - if test -z "$_LT_TAGVAR(predep_objects, $1)"; then - _LT_TAGVAR(predep_objects, $1)="$p" - else - _LT_TAGVAR(predep_objects, $1)="$_LT_TAGVAR(predep_objects, $1) $p" - fi - else - if test -z "$_LT_TAGVAR(postdep_objects, $1)"; then - _LT_TAGVAR(postdep_objects, $1)="$p" - else - _LT_TAGVAR(postdep_objects, $1)="$_LT_TAGVAR(postdep_objects, $1) $p" - fi - fi - ;; - - *) ;; # Ignore the rest. - - esac - done - - # Clean up. - rm -f a.out a.exe -else - echo "libtool.m4: error: problem compiling $1 test program" -fi - -$RM -f confest.$objext - -# PORTME: override above test on systems where it is broken -m4_if([$1], [CXX], -[case $host_os in -interix[[3-9]]*) - # Interix 3.5 installs completely hosed .la files for C++, so rather than - # hack all around it, let's just trust "g++" to DTRT. - _LT_TAGVAR(predep_objects,$1)= - _LT_TAGVAR(postdep_objects,$1)= - _LT_TAGVAR(postdeps,$1)= - ;; - -linux*) - case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C++ 5.9 - - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; - -solaris*) - case $cc_basename in - CC*) - # The more standards-conforming stlport4 library is - # incompatible with the Cstd library. Avoid specifying - # it if it's in CXXFLAGS. Ignore libCrun as - # -library=stlport4 depends on it. - case " $CXX $CXXFLAGS " in - *" -library=stlport4 "*) - solaris_use_stlport4=yes - ;; - esac - - # Adding this requires a known-good setup of shared libraries for - # Sun compiler versions before 5.6, else PIC objects from an old - # archive will be linked into the output, leading to subtle bugs. - if test "$solaris_use_stlport4" != yes; then - _LT_TAGVAR(postdeps,$1)='-library=Cstd -library=Crun' - fi - ;; - esac - ;; -esac -]) - -case " $_LT_TAGVAR(postdeps, $1) " in -*" -lc "*) _LT_TAGVAR(archive_cmds_need_lc, $1)=no ;; -esac - _LT_TAGVAR(compiler_lib_search_dirs, $1)= -if test -n "${_LT_TAGVAR(compiler_lib_search_path, $1)}"; then - _LT_TAGVAR(compiler_lib_search_dirs, $1)=`echo " ${_LT_TAGVAR(compiler_lib_search_path, $1)}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` -fi -_LT_TAGDECL([], [compiler_lib_search_dirs], [1], - [The directories searched by this compiler when creating a shared library]) -_LT_TAGDECL([], [predep_objects], [1], - [Dependencies to place before and after the objects being linked to - create a shared library]) -_LT_TAGDECL([], [postdep_objects], [1]) -_LT_TAGDECL([], [predeps], [1]) -_LT_TAGDECL([], [postdeps], [1]) -_LT_TAGDECL([], [compiler_lib_search_path], [1], - [The library search path used internally by the compiler when linking - a shared library]) -])# _LT_SYS_HIDDEN_LIBDEPS - - -# _LT_PROG_F77 -# ------------ -# Since AC_PROG_F77 is broken, in that it returns the empty string -# if there is no fortran compiler, we have our own version here. -m4_defun([_LT_PROG_F77], -[ -pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) -AC_PROG_F77 -if test -z "$F77" || test "X$F77" = "Xno"; then - _lt_disable_F77=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_F77 - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_F77], []) - - -# _LT_LANG_F77_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for a Fortran 77 compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_F77_CONFIG], -[AC_REQUIRE([_LT_PROG_F77])dnl -AC_LANG_PUSH(Fortran 77) - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for f77 test sources. -ac_ext=f - -# Object file extension for compiled f77 test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the F77 compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_F77" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC="$CC" - lt_save_GCC=$GCC - CC=${F77-"f77"} - compiler=$CC - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - GCC=$G77 - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)="$G77" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC="$lt_save_CC" -fi # test "$_lt_disable_F77" != yes - -AC_LANG_POP -])# _LT_LANG_F77_CONFIG - - -# _LT_PROG_FC -# ----------- -# Since AC_PROG_FC is broken, in that it returns the empty string -# if there is no fortran compiler, we have our own version here. -m4_defun([_LT_PROG_FC], -[ -pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) -AC_PROG_FC -if test -z "$FC" || test "X$FC" = "Xno"; then - _lt_disable_FC=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_FC - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_FC], []) - - -# _LT_LANG_FC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for a Fortran compiler are -# suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_FC_CONFIG], -[AC_REQUIRE([_LT_PROG_FC])dnl -AC_LANG_PUSH(Fortran) - -_LT_TAGVAR(archive_cmds_need_lc, $1)=no -_LT_TAGVAR(allow_undefined_flag, $1)= -_LT_TAGVAR(always_export_symbols, $1)=no -_LT_TAGVAR(archive_expsym_cmds, $1)= -_LT_TAGVAR(export_dynamic_flag_spec, $1)= -_LT_TAGVAR(hardcode_direct, $1)=no -_LT_TAGVAR(hardcode_direct_absolute, $1)=no -_LT_TAGVAR(hardcode_libdir_flag_spec, $1)= -_LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= -_LT_TAGVAR(hardcode_libdir_separator, $1)= -_LT_TAGVAR(hardcode_minus_L, $1)=no -_LT_TAGVAR(hardcode_automatic, $1)=no -_LT_TAGVAR(inherit_rpath, $1)=no -_LT_TAGVAR(module_cmds, $1)= -_LT_TAGVAR(module_expsym_cmds, $1)= -_LT_TAGVAR(link_all_deplibs, $1)=unknown -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds -_LT_TAGVAR(no_undefined_flag, $1)= -_LT_TAGVAR(whole_archive_flag_spec, $1)= -_LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no - -# Source file extension for fc test sources. -ac_ext=${ac_fc_srcext-f} - -# Object file extension for compiled fc test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# No sense in running all these tests if we already determined that -# the FC compiler isn't working. Some variables (like enable_shared) -# are currently assumed to apply to all compilers on this platform, -# and will be corrupted by setting them based on a non-working compiler. -if test "$_lt_disable_FC" != yes; then - # Code to be used in simple compile tests - lt_simple_compile_test_code="\ - subroutine t - return - end -" - - # Code to be used in simple link tests - lt_simple_link_test_code="\ - program t - end -" - - # ltmain only uses $CC for tagged configurations so make sure $CC is set. - _LT_TAG_COMPILER - - # save warnings/boilerplate of simple test code - _LT_COMPILER_BOILERPLATE - _LT_LINKER_BOILERPLATE - - # Allow CC to be a program name with arguments. - lt_save_CC="$CC" - lt_save_GCC=$GCC - CC=${FC-"f95"} - compiler=$CC - GCC=$ac_cv_fc_compiler_gnu - - _LT_TAGVAR(compiler, $1)=$CC - _LT_CC_BASENAME([$compiler]) - - if test -n "$compiler"; then - AC_MSG_CHECKING([if libtool supports shared libraries]) - AC_MSG_RESULT([$can_build_shared]) - - AC_MSG_CHECKING([whether to build shared libraries]) - test "$can_build_shared" = "no" && enable_shared=no - - # On AIX, shared libraries and static libraries use the same namespace, and - # are all built from PIC. - case $host_os in - aix3*) - test "$enable_shared" = yes && enable_static=no - if test -n "$RANLIB"; then - archive_cmds="$archive_cmds~\$RANLIB \$lib" - postinstall_cmds='$RANLIB $lib' - fi - ;; - aix[[4-9]]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no - fi - ;; - esac - AC_MSG_RESULT([$enable_shared]) - - AC_MSG_CHECKING([whether to build static libraries]) - # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes - AC_MSG_RESULT([$enable_static]) - - _LT_TAGVAR(GCC, $1)="$ac_cv_fc_compiler_gnu" - _LT_TAGVAR(LD, $1)="$LD" - - ## CAVEAT EMPTOR: - ## There is no encapsulation within the following macros, do not change - ## the running order or otherwise move them around unless you know exactly - ## what you are doing... - _LT_SYS_HIDDEN_LIBDEPS($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_SYS_DYNAMIC_LINKER($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) - fi # test -n "$compiler" - - GCC=$lt_save_GCC - CC="$lt_save_CC" -fi # test "$_lt_disable_FC" != yes - -AC_LANG_POP -])# _LT_LANG_FC_CONFIG - - -# _LT_LANG_GCJ_CONFIG([TAG]) -# -------------------------- -# Ensure that the configuration variables for the GNU Java Compiler compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_GCJ_CONFIG], -[AC_REQUIRE([LT_PROG_GCJ])dnl -AC_LANG_SAVE - -# Source file extension for Java test sources. -ac_ext=java - -# Object file extension for compiled Java test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code="class foo {}" - -# Code to be used in simple link tests -lt_simple_link_test_code='public class conftest { public static void main(String[[]] argv) {}; }' - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -lt_save_GCC=$GCC -GCC=yes -CC=${GCJ-"gcj"} -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_TAGVAR(LD, $1)="$LD" -_LT_CC_BASENAME([$compiler]) - -# GCJ did not exist at the time GCC didn't implicitly link libc in. -_LT_TAGVAR(archive_cmds_need_lc, $1)=no - -_LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds - -if test -n "$compiler"; then - _LT_COMPILER_NO_RTTI($1) - _LT_COMPILER_PIC($1) - _LT_COMPILER_C_O($1) - _LT_COMPILER_FILE_LOCKS($1) - _LT_LINKER_SHLIBS($1) - _LT_LINKER_HARDCODE_LIBPATH($1) - - _LT_CONFIG($1) -fi - -AC_LANG_RESTORE - -GCC=$lt_save_GCC -CC="$lt_save_CC" -])# _LT_LANG_GCJ_CONFIG - - -# _LT_LANG_RC_CONFIG([TAG]) -# ------------------------- -# Ensure that the configuration variables for the Windows resource compiler -# are suitably defined. These variables are subsequently used by _LT_CONFIG -# to write the compiler configuration to `libtool'. -m4_defun([_LT_LANG_RC_CONFIG], -[AC_REQUIRE([LT_PROG_RC])dnl -AC_LANG_SAVE - -# Source file extension for RC test sources. -ac_ext=rc - -# Object file extension for compiled RC test sources. -objext=o -_LT_TAGVAR(objext, $1)=$objext - -# Code to be used in simple compile tests -lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }' - -# Code to be used in simple link tests -lt_simple_link_test_code="$lt_simple_compile_test_code" - -# ltmain only uses $CC for tagged configurations so make sure $CC is set. -_LT_TAG_COMPILER - -# save warnings/boilerplate of simple test code -_LT_COMPILER_BOILERPLATE -_LT_LINKER_BOILERPLATE - -# Allow CC to be a program name with arguments. -lt_save_CC="$CC" -lt_save_GCC=$GCC -GCC= -CC=${RC-"windres"} -compiler=$CC -_LT_TAGVAR(compiler, $1)=$CC -_LT_CC_BASENAME([$compiler]) -_LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes - -if test -n "$compiler"; then - : - _LT_CONFIG($1) -fi - -GCC=$lt_save_GCC -AC_LANG_RESTORE -CC="$lt_save_CC" -])# _LT_LANG_RC_CONFIG - - -# LT_PROG_GCJ -# ----------- -AC_DEFUN([LT_PROG_GCJ], -[m4_ifdef([AC_PROG_GCJ], [AC_PROG_GCJ], - [m4_ifdef([A][M_PROG_GCJ], [A][M_PROG_GCJ], - [AC_CHECK_TOOL(GCJ, gcj,) - test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" - AC_SUBST(GCJFLAGS)])])[]dnl -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_GCJ], [LT_PROG_GCJ]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_GCJ], []) - - -# LT_PROG_RC -# ---------- -AC_DEFUN([LT_PROG_RC], -[AC_CHECK_TOOL(RC, windres,) -]) - -# Old name: -AU_ALIAS([LT_AC_PROG_RC], [LT_PROG_RC]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_RC], []) - - -# _LT_DECL_EGREP -# -------------- -# If we don't have a new enough Autoconf to choose the best grep -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_EGREP], -[AC_REQUIRE([AC_PROG_EGREP])dnl -AC_REQUIRE([AC_PROG_FGREP])dnl -test -z "$GREP" && GREP=grep -_LT_DECL([], [GREP], [1], [A grep program that handles long lines]) -_LT_DECL([], [EGREP], [1], [An ERE matcher]) -_LT_DECL([], [FGREP], [1], [A literal string matcher]) -dnl Non-bleeding-edge autoconf doesn't subst GREP, so do it here too -AC_SUBST([GREP]) -]) - - -# _LT_DECL_OBJDUMP -# -------------- -# If we don't have a new enough Autoconf to choose the best objdump -# available, choose the one first in the user's PATH. -m4_defun([_LT_DECL_OBJDUMP], -[AC_CHECK_TOOL(OBJDUMP, objdump, false) -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [1], [An object symbol dumper]) -AC_SUBST([OBJDUMP]) -]) - - -# _LT_DECL_SED -# ------------ -# Check for a fully-functional sed program, that truncates -# as few characters as possible. Prefer GNU sed if found. -m4_defun([_LT_DECL_SED], -[AC_PROG_SED -test -z "$SED" && SED=sed -Xsed="$SED -e 1s/^X//" -_LT_DECL([], [SED], [1], [A sed program that does not truncate output]) -_LT_DECL([], [Xsed], ["\$SED -e 1s/^X//"], - [Sed that helps us avoid accidentally triggering echo(1) options like -n]) -])# _LT_DECL_SED - -m4_ifndef([AC_PROG_SED], [ -# NOTE: This macro has been submitted for inclusion into # -# GNU Autoconf as AC_PROG_SED. When it is available in # -# a released version of Autoconf we should remove this # -# macro and use it instead. # - -m4_defun([AC_PROG_SED], -[AC_MSG_CHECKING([for a sed that does not truncate output]) -AC_CACHE_VAL(lt_cv_path_SED, -[# Loop through the user's path and test for sed and gsed. -# Then use that list of sed's as ones to test for truncation. -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for lt_ac_prog in sed gsed; do - for ac_exec_ext in '' $ac_executable_extensions; do - if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then - lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" - fi - done - done -done -IFS=$as_save_IFS -lt_ac_max=0 -lt_ac_count=0 -# Add /usr/xpg4/bin/sed as it is typically found on Solaris -# along with /bin/sed that truncates output. -for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do - test ! -f $lt_ac_sed && continue - cat /dev/null > conftest.in - lt_ac_count=0 - echo $ECHO_N "0123456789$ECHO_C" >conftest.in - # Check for GNU sed and select it if it is found. - if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then - lt_cv_path_SED=$lt_ac_sed - break - fi - while true; do - cat conftest.in conftest.in >conftest.tmp - mv conftest.tmp conftest.in - cp conftest.in conftest.nl - echo >>conftest.nl - $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break - cmp -s conftest.out conftest.nl || break - # 10000 chars as input seems more than enough - test $lt_ac_count -gt 10 && break - lt_ac_count=`expr $lt_ac_count + 1` - if test $lt_ac_count -gt $lt_ac_max; then - lt_ac_max=$lt_ac_count - lt_cv_path_SED=$lt_ac_sed - fi - done -done -]) -SED=$lt_cv_path_SED -AC_SUBST([SED]) -AC_MSG_RESULT([$SED]) -])#AC_PROG_SED -])#m4_ifndef - -# Old name: -AU_ALIAS([LT_AC_PROG_SED], [AC_PROG_SED]) -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([LT_AC_PROG_SED], []) - - -# _LT_CHECK_SHELL_FEATURES -# ------------------------ -# Find out whether the shell is Bourne or XSI compatible, -# or has some other useful features. -m4_defun([_LT_CHECK_SHELL_FEATURES], -[AC_MSG_CHECKING([whether the shell understands some XSI constructs]) -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -AC_MSG_RESULT([$xsi_shell]) -_LT_CONFIG_LIBTOOL_INIT([xsi_shell='$xsi_shell']) - -AC_MSG_CHECKING([whether the shell understands "+="]) -lt_shell_append=no -( foo=bar; set foo baz; eval "$[1]+=\$[2]" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -AC_MSG_RESULT([$lt_shell_append]) -_LT_CONFIG_LIBTOOL_INIT([lt_shell_append='$lt_shell_append']) - -if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then - lt_unset=unset -else - lt_unset=false -fi -_LT_DECL([], [lt_unset], [0], [whether the shell understands "unset"])dnl - -# test EBCDIC or ASCII -case `echo X|tr X '\101'` in - A) # ASCII based system - # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr - lt_SP2NL='tr \040 \012' - lt_NL2SP='tr \015\012 \040\040' - ;; - *) # EBCDIC based system - lt_SP2NL='tr \100 \n' - lt_NL2SP='tr \r\n \100\100' - ;; -esac -_LT_DECL([SP2NL], [lt_SP2NL], [1], [turn spaces into newlines])dnl -_LT_DECL([NL2SP], [lt_NL2SP], [1], [turn newlines into spaces])dnl -])# _LT_CHECK_SHELL_FEATURES - - -# _LT_PROG_XSI_SHELLFNS -# --------------------- -# Bourne and XSI compatible variants of some useful shell functions. -m4_defun([_LT_PROG_XSI_SHELLFNS], -[case $xsi_shell in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac -} - -# func_basename file -func_basename () -{ - func_basename_result="${1##*/}" -} - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}" -} - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -func_stripname () -{ - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"} -} - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=${1%%=*} - func_opt_split_arg=${1#*=} -} - -# func_lo2o object -func_lo2o () -{ - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=${1%.*}.lo -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=$(( $[*] )) -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=${#1} -} - -_LT_EOF - ;; - *) # Bourne compatible functions. - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` -} - -dnl func_dirname_and_basename -dnl A portable version of this function is already defined in general.m4sh -dnl so there is no need for it here. - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; - esac -} - -# sed scripts: -my_sed_long_opt='1s/^\(-[[^=]]*\)=.*/\1/;q' -my_sed_long_arg='1s/^-[[^=]]*=//' - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` - func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` -} - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "$[@]"` -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "$[1]" : ".*" 2>/dev/null || echo $max_cmd_len` -} - -_LT_EOF -esac - -case $lt_shell_append in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$[1]+=\$[2]" -} -_LT_EOF - ;; - *) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$[1]=\$$[1]\$[2]" -} - -_LT_EOF - ;; - esac -]) - -# Helper functions for option handling. -*- Autoconf -*- -# -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 6 ltoptions.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) - - -# _LT_MANGLE_OPTION(MACRO-NAME, OPTION-NAME) -# ------------------------------------------ -m4_define([_LT_MANGLE_OPTION], -[[_LT_OPTION_]m4_bpatsubst($1__$2, [[^a-zA-Z0-9_]], [_])]) - - -# _LT_SET_OPTION(MACRO-NAME, OPTION-NAME) -# --------------------------------------- -# Set option OPTION-NAME for macro MACRO-NAME, and if there is a -# matching handler defined, dispatch to it. Other OPTION-NAMEs are -# saved as a flag. -m4_define([_LT_SET_OPTION], -[m4_define(_LT_MANGLE_OPTION([$1], [$2]))dnl -m4_ifdef(_LT_MANGLE_DEFUN([$1], [$2]), - _LT_MANGLE_DEFUN([$1], [$2]), - [m4_warning([Unknown $1 option `$2'])])[]dnl -]) - - -# _LT_IF_OPTION(MACRO-NAME, OPTION-NAME, IF-SET, [IF-NOT-SET]) -# ------------------------------------------------------------ -# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. -m4_define([_LT_IF_OPTION], -[m4_ifdef(_LT_MANGLE_OPTION([$1], [$2]), [$3], [$4])]) - - -# _LT_UNLESS_OPTIONS(MACRO-NAME, OPTION-LIST, IF-NOT-SET) -# ------------------------------------------------------- -# Execute IF-NOT-SET unless all options in OPTION-LIST for MACRO-NAME -# are set. -m4_define([_LT_UNLESS_OPTIONS], -[m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [m4_ifdef(_LT_MANGLE_OPTION([$1], _LT_Option), - [m4_define([$0_found])])])[]dnl -m4_ifdef([$0_found], [m4_undefine([$0_found])], [$3 -])[]dnl -]) - - -# _LT_SET_OPTIONS(MACRO-NAME, OPTION-LIST) -# ---------------------------------------- -# OPTION-LIST is a space-separated list of Libtool options associated -# with MACRO-NAME. If any OPTION has a matching handler declared with -# LT_OPTION_DEFINE, dispatch to that macro; otherwise complain about -# the unknown option and exit. -m4_defun([_LT_SET_OPTIONS], -[# Set options -m4_foreach([_LT_Option], m4_split(m4_normalize([$2])), - [_LT_SET_OPTION([$1], _LT_Option)]) - -m4_if([$1],[LT_INIT],[ - dnl - dnl Simply set some default values (i.e off) if boolean options were not - dnl specified: - _LT_UNLESS_OPTIONS([LT_INIT], [dlopen], [enable_dlopen=no - ]) - _LT_UNLESS_OPTIONS([LT_INIT], [win32-dll], [enable_win32_dll=no - ]) - dnl - dnl If no reference was made to various pairs of opposing options, then - dnl we run the default mode handler for the pair. For example, if neither - dnl `shared' nor `disable-shared' was passed, we enable building of shared - dnl archives by default: - _LT_UNLESS_OPTIONS([LT_INIT], [shared disable-shared], [_LT_ENABLE_SHARED]) - _LT_UNLESS_OPTIONS([LT_INIT], [static disable-static], [_LT_ENABLE_STATIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [pic-only no-pic], [_LT_WITH_PIC]) - _LT_UNLESS_OPTIONS([LT_INIT], [fast-install disable-fast-install], - [_LT_ENABLE_FAST_INSTALL]) - ]) -])# _LT_SET_OPTIONS - - - -# _LT_MANGLE_DEFUN(MACRO-NAME, OPTION-NAME) -# ----------------------------------------- -m4_define([_LT_MANGLE_DEFUN], -[[_LT_OPTION_DEFUN_]m4_bpatsubst(m4_toupper([$1__$2]), [[^A-Z0-9_]], [_])]) - - -# LT_OPTION_DEFINE(MACRO-NAME, OPTION-NAME, CODE) -# ----------------------------------------------- -m4_define([LT_OPTION_DEFINE], -[m4_define(_LT_MANGLE_DEFUN([$1], [$2]), [$3])[]dnl -])# LT_OPTION_DEFINE - - -# dlopen -# ------ -LT_OPTION_DEFINE([LT_INIT], [dlopen], [enable_dlopen=yes -]) - -AU_DEFUN([AC_LIBTOOL_DLOPEN], -[_LT_SET_OPTION([LT_INIT], [dlopen]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `dlopen' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_DLOPEN], []) - - -# win32-dll -# --------- -# Declare package support for building win32 dll's. -LT_OPTION_DEFINE([LT_INIT], [win32-dll], -[enable_win32_dll=yes - -case $host in -*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) - AC_CHECK_TOOL(AS, as, false) - AC_CHECK_TOOL(DLLTOOL, dlltool, false) - AC_CHECK_TOOL(OBJDUMP, objdump, false) - ;; -esac - -test -z "$AS" && AS=as -_LT_DECL([], [AS], [0], [Assembler program])dnl - -test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl - -test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl -])# win32-dll - -AU_DEFUN([AC_LIBTOOL_WIN32_DLL], -[AC_REQUIRE([AC_CANONICAL_HOST])dnl -_LT_SET_OPTION([LT_INIT], [win32-dll]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `win32-dll' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_WIN32_DLL], []) - - -# _LT_ENABLE_SHARED([DEFAULT]) -# ---------------------------- -# implement the --enable-shared flag, and supports the `shared' and -# `disable-shared' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_SHARED], -[m4_define([_LT_ENABLE_SHARED_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([shared], - [AS_HELP_STRING([--enable-shared@<:@=PKGS@:>@], - [build shared libraries @<:@default=]_LT_ENABLE_SHARED_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_shared=yes ;; - no) enable_shared=no ;; - *) - enable_shared=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_shared=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_shared=]_LT_ENABLE_SHARED_DEFAULT) - - _LT_DECL([build_libtool_libs], [enable_shared], [0], - [Whether or not to build shared libraries]) -])# _LT_ENABLE_SHARED - -LT_OPTION_DEFINE([LT_INIT], [shared], [_LT_ENABLE_SHARED([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-shared], [_LT_ENABLE_SHARED([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[shared]) -]) - -AC_DEFUN([AC_DISABLE_SHARED], -[_LT_SET_OPTION([LT_INIT], [disable-shared]) -]) - -AU_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) -AU_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_SHARED], []) -dnl AC_DEFUN([AM_DISABLE_SHARED], []) - - - -# _LT_ENABLE_STATIC([DEFAULT]) -# ---------------------------- -# implement the --enable-static flag, and support the `static' and -# `disable-static' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_STATIC], -[m4_define([_LT_ENABLE_STATIC_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([static], - [AS_HELP_STRING([--enable-static@<:@=PKGS@:>@], - [build static libraries @<:@default=]_LT_ENABLE_STATIC_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_static=yes ;; - no) enable_static=no ;; - *) - enable_static=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_static=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_static=]_LT_ENABLE_STATIC_DEFAULT) - - _LT_DECL([build_old_libs], [enable_static], [0], - [Whether or not to build static libraries]) -])# _LT_ENABLE_STATIC - -LT_OPTION_DEFINE([LT_INIT], [static], [_LT_ENABLE_STATIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-static], [_LT_ENABLE_STATIC([no])]) - -# Old names: -AC_DEFUN([AC_ENABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[static]) -]) - -AC_DEFUN([AC_DISABLE_STATIC], -[_LT_SET_OPTION([LT_INIT], [disable-static]) -]) - -AU_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) -AU_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AM_ENABLE_STATIC], []) -dnl AC_DEFUN([AM_DISABLE_STATIC], []) - - - -# _LT_ENABLE_FAST_INSTALL([DEFAULT]) -# ---------------------------------- -# implement the --enable-fast-install flag, and support the `fast-install' -# and `disable-fast-install' LT_INIT options. -# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. -m4_define([_LT_ENABLE_FAST_INSTALL], -[m4_define([_LT_ENABLE_FAST_INSTALL_DEFAULT], [m4_if($1, no, no, yes)])dnl -AC_ARG_ENABLE([fast-install], - [AS_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], - [optimize for fast installation @<:@default=]_LT_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], - [p=${PACKAGE-default} - case $enableval in - yes) enable_fast_install=yes ;; - no) enable_fast_install=no ;; - *) - enable_fast_install=no - # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," - for pkg in $enableval; do - IFS="$lt_save_ifs" - if test "X$pkg" = "X$p"; then - enable_fast_install=yes - fi - done - IFS="$lt_save_ifs" - ;; - esac], - [enable_fast_install=]_LT_ENABLE_FAST_INSTALL_DEFAULT) - -_LT_DECL([fast_install], [enable_fast_install], [0], - [Whether or not to optimize for fast installation])dnl -])# _LT_ENABLE_FAST_INSTALL - -LT_OPTION_DEFINE([LT_INIT], [fast-install], [_LT_ENABLE_FAST_INSTALL([yes])]) -LT_OPTION_DEFINE([LT_INIT], [disable-fast-install], [_LT_ENABLE_FAST_INSTALL([no])]) - -# Old names: -AU_DEFUN([AC_ENABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], m4_if([$1], [no], [disable-])[fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `fast-install' option into LT_INIT's first parameter.]) -]) - -AU_DEFUN([AC_DISABLE_FAST_INSTALL], -[_LT_SET_OPTION([LT_INIT], [disable-fast-install]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you put -the `disable-fast-install' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_ENABLE_FAST_INSTALL], []) -dnl AC_DEFUN([AM_DISABLE_FAST_INSTALL], []) - - -# _LT_WITH_PIC([MODE]) -# -------------------- -# implement the --with-pic flag, and support the `pic-only' and `no-pic' -# LT_INIT options. -# MODE is either `yes' or `no'. If omitted, it defaults to `both'. -m4_define([_LT_WITH_PIC], -[AC_ARG_WITH([pic], - [AS_HELP_STRING([--with-pic], - [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], - [pic_mode="$withval"], - [pic_mode=default]) - -test -z "$pic_mode" && pic_mode=m4_default([$1], [default]) - -_LT_DECL([], [pic_mode], [0], [What type of objects to build])dnl -])# _LT_WITH_PIC - -LT_OPTION_DEFINE([LT_INIT], [pic-only], [_LT_WITH_PIC([yes])]) -LT_OPTION_DEFINE([LT_INIT], [no-pic], [_LT_WITH_PIC([no])]) - -# Old name: -AU_DEFUN([AC_LIBTOOL_PICMODE], -[_LT_SET_OPTION([LT_INIT], [pic-only]) -AC_DIAGNOSE([obsolete], -[$0: Remove this warning and the call to _LT_SET_OPTION when you -put the `pic-only' option into LT_INIT's first parameter.]) -]) - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([AC_LIBTOOL_PICMODE], []) - - -m4_define([_LTDL_MODE], []) -LT_OPTION_DEFINE([LTDL_INIT], [nonrecursive], - [m4_define([_LTDL_MODE], [nonrecursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [recursive], - [m4_define([_LTDL_MODE], [recursive])]) -LT_OPTION_DEFINE([LTDL_INIT], [subproject], - [m4_define([_LTDL_MODE], [subproject])]) - -m4_define([_LTDL_TYPE], []) -LT_OPTION_DEFINE([LTDL_INIT], [installable], - [m4_define([_LTDL_TYPE], [installable])]) -LT_OPTION_DEFINE([LTDL_INIT], [convenience], - [m4_define([_LTDL_TYPE], [convenience])]) - -# ltsugar.m4 -- libtool m4 base layer. -*-Autoconf-*- -# -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. -# Written by Gary V. Vaughan, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 6 ltsugar.m4 - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTSUGAR_VERSION], [m4_if([0.1])]) - - -# lt_join(SEP, ARG1, [ARG2...]) -# ----------------------------- -# Produce ARG1SEPARG2...SEPARGn, omitting [] arguments and their -# associated separator. -# Needed until we can rely on m4_join from Autoconf 2.62, since all earlier -# versions in m4sugar had bugs. -m4_define([lt_join], -[m4_if([$#], [1], [], - [$#], [2], [[$2]], - [m4_if([$2], [], [], [[$2]_])$0([$1], m4_shift(m4_shift($@)))])]) -m4_define([_lt_join], -[m4_if([$#$2], [2], [], - [m4_if([$2], [], [], [[$1$2]])$0([$1], m4_shift(m4_shift($@)))])]) - - -# lt_car(LIST) -# lt_cdr(LIST) -# ------------ -# Manipulate m4 lists. -# These macros are necessary as long as will still need to support -# Autoconf-2.59 which quotes differently. -m4_define([lt_car], [[$1]]) -m4_define([lt_cdr], -[m4_if([$#], 0, [m4_fatal([$0: cannot be called without arguments])], - [$#], 1, [], - [m4_dquote(m4_shift($@))])]) -m4_define([lt_unquote], $1) - - -# lt_append(MACRO-NAME, STRING, [SEPARATOR]) -# ------------------------------------------ -# Redefine MACRO-NAME to hold its former content plus `SEPARATOR'`STRING'. -# Note that neither SEPARATOR nor STRING are expanded; they are appended -# to MACRO-NAME as is (leaving the expansion for when MACRO-NAME is invoked). -# No SEPARATOR is output if MACRO-NAME was previously undefined (different -# than defined and empty). -# -# This macro is needed until we can rely on Autoconf 2.62, since earlier -# versions of m4sugar mistakenly expanded SEPARATOR but not STRING. -m4_define([lt_append], -[m4_define([$1], - m4_ifdef([$1], [m4_defn([$1])[$3]])[$2])]) - - - -# lt_combine(SEP, PREFIX-LIST, INFIX, SUFFIX1, [SUFFIX2...]) -# ---------------------------------------------------------- -# Produce a SEP delimited list of all paired combinations of elements of -# PREFIX-LIST with SUFFIX1 through SUFFIXn. Each element of the list -# has the form PREFIXmINFIXSUFFIXn. -# Needed until we can rely on m4_combine added in Autoconf 2.62. -m4_define([lt_combine], -[m4_if(m4_eval([$# > 3]), [1], - [m4_pushdef([_Lt_sep], [m4_define([_Lt_sep], m4_defn([lt_car]))])]]dnl -[[m4_foreach([_Lt_prefix], [$2], - [m4_foreach([_Lt_suffix], - ]m4_dquote(m4_dquote(m4_shift(m4_shift(m4_shift($@)))))[, - [_Lt_sep([$1])[]m4_defn([_Lt_prefix])[$3]m4_defn([_Lt_suffix])])])])]) - - -# lt_if_append_uniq(MACRO-NAME, VARNAME, [SEPARATOR], [UNIQ], [NOT-UNIQ]) -# ----------------------------------------------------------------------- -# Iff MACRO-NAME does not yet contain VARNAME, then append it (delimited -# by SEPARATOR if supplied) and expand UNIQ, else NOT-UNIQ. -m4_define([lt_if_append_uniq], -[m4_ifdef([$1], - [m4_if(m4_index([$3]m4_defn([$1])[$3], [$3$2$3]), [-1], - [lt_append([$1], [$2], [$3])$4], - [$5])], - [lt_append([$1], [$2], [$3])$4])]) - - -# lt_dict_add(DICT, KEY, VALUE) -# ----------------------------- -m4_define([lt_dict_add], -[m4_define([$1($2)], [$3])]) - - -# lt_dict_add_subkey(DICT, KEY, SUBKEY, VALUE) -# -------------------------------------------- -m4_define([lt_dict_add_subkey], -[m4_define([$1($2:$3)], [$4])]) - - -# lt_dict_fetch(DICT, KEY, [SUBKEY]) -# ---------------------------------- -m4_define([lt_dict_fetch], -[m4_ifval([$3], - m4_ifdef([$1($2:$3)], [m4_defn([$1($2:$3)])]), - m4_ifdef([$1($2)], [m4_defn([$1($2)])]))]) - - -# lt_if_dict_fetch(DICT, KEY, [SUBKEY], VALUE, IF-TRUE, [IF-FALSE]) -# ----------------------------------------------------------------- -m4_define([lt_if_dict_fetch], -[m4_if(lt_dict_fetch([$1], [$2], [$3]), [$4], - [$5], - [$6])]) - - -# lt_dict_filter(DICT, [SUBKEY], VALUE, [SEPARATOR], KEY, [...]) -# -------------------------------------------------------------- -m4_define([lt_dict_filter], -[m4_if([$5], [], [], - [lt_join(m4_quote(m4_default([$4], [[, ]])), - lt_unquote(m4_split(m4_normalize(m4_foreach(_Lt_key, lt_car([m4_shiftn(4, $@)]), - [lt_if_dict_fetch([$1], _Lt_key, [$2], [$3], [_Lt_key ])])))))])[]dnl -]) - -# ltversion.m4 -- version numbers -*- Autoconf -*- -# -# Copyright (C) 2004 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004 -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# Generated from ltversion.in. - -# serial 3017 ltversion.m4 -# This file is part of GNU Libtool - -m4_define([LT_PACKAGE_VERSION], [2.2.6b]) -m4_define([LT_PACKAGE_REVISION], [1.3017]) - -AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.2.6b' -macro_revision='1.3017' -_LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) -_LT_DECL(, macro_revision, 0) -]) - -# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- -# -# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. -# Written by Scott James Remnant, 2004. -# -# This file is free software; the Free Software Foundation gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. - -# serial 4 lt~obsolete.m4 - -# These exist entirely to fool aclocal when bootstrapping libtool. -# -# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) -# which have later been changed to m4_define as they aren't part of the -# exported API, or moved to Autoconf or Automake where they belong. -# -# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN -# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us -# using a macro with the same name in our local m4/libtool.m4 it'll -# pull the old libtool.m4 in (it doesn't see our shiny new m4_define -# and doesn't know about Autoconf macros at all.) -# -# So we provide this file, which has a silly filename so it's always -# included after everything else. This provides aclocal with the -# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything -# because those macros already exist, or will be overwritten later. -# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. -# -# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. -# Yes, that means every name once taken will need to remain here until -# we give up compatibility with versions before 1.7, at which point -# we need to keep only those names which we still refer to. - -# This is to help aclocal find these macros, as it can't see m4_define. -AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) - -m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) -m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) -m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) -m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) -m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) -m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) -m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) -m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) -m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) -m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) -m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) -m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) -m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) -m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) -m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) -m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) -m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) -m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) -m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) -m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) -m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) -m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) -m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) -m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) -m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) -m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) -m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) -m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) -m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) -m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) -m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) -m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) -m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) -m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) -m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) -m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) -m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) -m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) -m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) -m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) -m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) -m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) -m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) -m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) -m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) -m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) -m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) -m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) -m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) - -# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2002-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -7977,10 +32,10 @@ m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) # generated from the m4 files accompanying Automake X.Y. # (This private macro should not be called outside this file.) AC_DEFUN([AM_AUTOMAKE_VERSION], -[am__api_version='1.11' +[am__api_version='1.16' dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to dnl require some minimum version. Point them to the right macro. -m4_if([$1], [1.11], [], +m4_if([$1], [1.16.1], [], [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl ]) @@ -7996,22 +51,42 @@ m4_define([_AM_AUTOCONF_VERSION], []) # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. # This function is AC_REQUIREd by AM_INIT_AUTOMAKE. AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], -[AM_AUTOMAKE_VERSION([1.11])dnl +[AM_AUTOMAKE_VERSION([1.16.1])dnl m4_ifndef([AC_AUTOCONF_VERSION], [m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) +# Figure out how to run the assembler. -*- Autoconf -*- + +# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_PROG_AS +# ---------- +AC_DEFUN([AM_PROG_AS], +[# By default we simply use the C compiler to build assembly code. +AC_REQUIRE([AC_PROG_CC]) +test "${CCAS+set}" = set || CCAS=$CC +test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS +AC_ARG_VAR([CCAS], [assembler compiler command (defaults to CC)]) +AC_ARG_VAR([CCASFLAGS], [assembler compiler flags (defaults to CFLAGS)]) +_AM_IF_OPTION([no-dependencies],, [_AM_DEPENDENCIES([CCAS])])dnl +]) + # AM_AUX_DIR_EXPAND -*- Autoconf -*- -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets -# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to -# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# $ac_aux_dir to '$srcdir/foo'. In other projects, it is set to +# '$srcdir', '$srcdir/..', or '$srcdir/../..'. # # Of course, Automake must honor this variable whenever it calls a # tool from the auxiliary directory. The problem is that $srcdir (and @@ -8030,7 +105,7 @@ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # # The reason of the latter failure is that $top_srcdir and $ac_aux_dir # are both prefixed by $srcdir. In an in-source build this is usually -# harmless because $srcdir is `.', but things will broke when you +# harmless because $srcdir is '.', but things will broke when you # start a VPATH build or use an absolute $srcdir. # # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, @@ -8048,30 +123,26 @@ _AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))]) # configured tree to be moved without reconfiguration. AC_DEFUN([AM_AUX_DIR_EXPAND], -[dnl Rely on autoconf to set up CDPATH properly. -AC_PREREQ([2.50])dnl -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +[AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` ]) # AM_CONDITIONAL -*- Autoconf -*- -# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 9 - # AM_CONDITIONAL(NAME, SHELL-CONDITION) # ------------------------------------- # Define a conditional. AC_DEFUN([AM_CONDITIONAL], -[AC_PREREQ(2.52)dnl - ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], - [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +[AC_PREREQ([2.52])dnl + m4_if([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl AC_SUBST([$1_TRUE])dnl AC_SUBST([$1_FALSE])dnl _AM_SUBST_NOTMAKE([$1_TRUE])dnl @@ -8090,16 +161,14 @@ AC_CONFIG_COMMANDS_PRE( Usually this means the macro was only invoked conditionally.]]) fi])]) -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009 -# Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 10 -# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# There are a few dirty hacks below to avoid letting 'AC_PROG_CC' be # written in clear, in which case automake, when reading aclocal.m4, # will think it sees a *use*, and therefore will trigger all it's # C support machinery. Also note that it means that autoscan, seeing @@ -8109,7 +178,7 @@ fi])]) # _AM_DEPENDENCIES(NAME) # ---------------------- # See how the compiler implements dependency checking. -# NAME is "CC", "CXX", "GCJ", or "OBJC". +# NAME is "CC", "CXX", "OBJC", "OBJCXX", "UPC", or "GJC". # We try a few techniques and use that to set a single cache variable. # # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was @@ -8122,12 +191,13 @@ AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl AC_REQUIRE([AM_MAKE_INCLUDE])dnl AC_REQUIRE([AM_DEP_TRACK])dnl -ifelse([$1], CC, [depcc="$CC" am_compiler_list=], - [$1], CXX, [depcc="$CXX" am_compiler_list=], - [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], - [$1], UPC, [depcc="$UPC" am_compiler_list=], - [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], - [depcc="$$1" am_compiler_list=]) +m4_if([$1], [CC], [depcc="$CC" am_compiler_list=], + [$1], [CXX], [depcc="$CXX" am_compiler_list=], + [$1], [OBJC], [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], [OBJCXX], [depcc="$OBJCXX" am_compiler_list='gcc3 gcc'], + [$1], [UPC], [depcc="$UPC" am_compiler_list=], + [$1], [GCJ], [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) AC_CACHE_CHECK([dependency style of $depcc], [am_cv_$1_dependencies_compiler_type], @@ -8135,8 +205,9 @@ AC_CACHE_CHECK([dependency style of $depcc], # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. @@ -8175,16 +246,16 @@ AC_CACHE_CHECK([dependency style of $depcc], : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - # We check with `-c' and `-o' for the sake of the "dashmstdout" + # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in @@ -8193,16 +264,16 @@ AC_CACHE_CHECK([dependency style of $depcc], test "$am__universal" = false || continue ;; nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; - msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} @@ -8250,7 +321,7 @@ AM_CONDITIONAL([am__fastdep$1], [ # AM_SET_DEPDIR # ------------- # Choose a directory name for dependency files. -# This macro is AC_REQUIREd in _AM_DEPENDENCIES +# This macro is AC_REQUIREd in _AM_DEPENDENCIES. AC_DEFUN([AM_SET_DEPDIR], [AC_REQUIRE([AM_SET_LEADING_DOT])dnl AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl @@ -8260,81 +331,75 @@ AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl # AM_DEP_TRACK # ------------ AC_DEFUN([AM_DEP_TRACK], -[AC_ARG_ENABLE(dependency-tracking, -[ --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors]) +[AC_ARG_ENABLE([dependency-tracking], [dnl +AS_HELP_STRING( + [--enable-dependency-tracking], + [do not reject slow dependency extractors]) +AS_HELP_STRING( + [--disable-dependency-tracking], + [speeds up one-time build])]) if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' + am__nodep='_no' fi AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) AC_SUBST([AMDEPBACKSLASH])dnl _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl +AC_SUBST([am__nodep])dnl +_AM_SUBST_NOTMAKE([am__nodep])dnl ]) # Generate code to set up dependency tracking. -*- Autoconf -*- -# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -#serial 5 - # _AM_OUTPUT_DEPENDENCY_COMMANDS # ------------------------------ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], [{ - # Autoconf 2.62 quotes --file arguments for eval, but not when files + # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + AS_CASE([$CONFIG_FILES], + [*\'*], [eval set x "$CONFIG_FILES"], + [*], [set x $CONFIG_FILES]) shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`AS_ECHO(["$am_mf"]) | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`AS_DIRNAME("$mf")` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`AS_DIRNAME(["$file"])` - AS_MKDIR_P([$dirpart/$fdir]) - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`AS_DIRNAME(["$am_mf"])` + am_filepart=`AS_BASENAME(["$am_mf"])` + AM_RUN_LOG([cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles]) || am_rc=$? done + if test $am_rc -ne 0; then + AC_MSG_FAILURE([Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. Try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking).]) + fi + AS_UNSET([am_dirpart]) + AS_UNSET([am_filepart]) + AS_UNSET([am_mf]) + AS_UNSET([am_rc]) + rm -f conftest-deps.mk } ])# _AM_OUTPUT_DEPENDENCY_COMMANDS @@ -8343,41 +408,31 @@ AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], # ----------------------------- # This macro should only be invoked once -- use via AC_REQUIRE. # -# This code is only required when automatic dependency tracking -# is enabled. FIXME. This creates each `.P' file that we will -# need in order to bootstrap the dependency handling code. +# This code is only required when automatic dependency tracking is enabled. +# This creates each '.Po' and '.Plo' makefile fragment that we'll need in +# order to bootstrap the dependency handling code. AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], [AC_CONFIG_COMMANDS([depfiles], [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], - [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) -]) - -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 -# Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# serial 8 - -# AM_CONFIG_HEADER is obsolete. It has been replaced by AC_CONFIG_HEADERS. -AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) + [AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}"])]) # Do all the work for Automake. -*- Autoconf -*- -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, -# 2005, 2006, 2008, 2009 Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 16 - # This macro actually does too much. Some checks are only needed if # your package does certain things. But this isn't really a big deal. +dnl Redefine AC_PROG_CC to automatically invoke _AM_PROG_CC_C_O. +m4_define([AC_PROG_CC], +m4_defn([AC_PROG_CC]) +[_AM_PROG_CC_C_O +]) + # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) # AM_INIT_AUTOMAKE([OPTIONS]) # ----------------------------------------------- @@ -8390,7 +445,7 @@ AU_DEFUN([AM_CONFIG_HEADER], [AC_CONFIG_HEADERS($@)]) # arguments mandatory, and then we can depend on a new Autoconf # release and drop the old call support. AC_DEFUN([AM_INIT_AUTOMAKE], -[AC_PREREQ([2.62])dnl +[AC_PREREQ([2.65])dnl dnl Autoconf wants to disallow AM_ names. We explicitly allow dnl the ones we care about. m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl @@ -8419,33 +474,42 @@ AC_SUBST([CYGPATH_W]) # Define the identity of the package. dnl Distinguish between old-style and new-style calls. m4_ifval([$2], -[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl +[AC_DIAGNOSE([obsolete], + [$0: two- and three-arguments forms are deprecated.]) +m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl AC_SUBST([PACKAGE], [$1])dnl AC_SUBST([VERSION], [$2])], [_AM_SET_OPTIONS([$1])dnl dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. -m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, +m4_if( + m4_ifdef([AC_PACKAGE_NAME], [ok]):m4_ifdef([AC_PACKAGE_VERSION], [ok]), + [ok:ok],, [m4_fatal([AC_INIT should be called with package and version arguments])])dnl AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl _AM_IF_OPTION([no-define],, -[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) - AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl +[AC_DEFINE_UNQUOTED([PACKAGE], ["$PACKAGE"], [Name of package]) + AC_DEFINE_UNQUOTED([VERSION], ["$VERSION"], [Version number of package])])dnl # Some tools Automake needs. AC_REQUIRE([AM_SANITY_CHECK])dnl AC_REQUIRE([AC_ARG_PROGRAM])dnl -AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) -AM_MISSING_PROG(AUTOCONF, autoconf) -AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) -AM_MISSING_PROG(AUTOHEADER, autoheader) -AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG([ACLOCAL], [aclocal-${am__api_version}]) +AM_MISSING_PROG([AUTOCONF], [autoconf]) +AM_MISSING_PROG([AUTOMAKE], [automake-${am__api_version}]) +AM_MISSING_PROG([AUTOHEADER], [autoheader]) +AM_MISSING_PROG([MAKEINFO], [makeinfo]) AC_REQUIRE([AM_PROG_INSTALL_SH])dnl AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl -AC_REQUIRE([AM_PROG_MKDIR_P])dnl -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. +AC_REQUIRE([AC_PROG_MKDIR_P])dnl +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +AC_SUBST([mkdir_p], ['$(MKDIR_P)']) +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([AC_PROG_MAKE_SET])dnl AC_REQUIRE([AM_SET_LEADING_DOT])dnl @@ -8454,34 +518,82 @@ _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], [_AM_PROG_TAR([v7])])]) _AM_IF_OPTION([no-dependencies],, [AC_PROVIDE_IFELSE([AC_PROG_CC], - [_AM_DEPENDENCIES(CC)], - [define([AC_PROG_CC], - defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl + [_AM_DEPENDENCIES([CC])], + [m4_define([AC_PROG_CC], + m4_defn([AC_PROG_CC])[_AM_DEPENDENCIES([CC])])])dnl AC_PROVIDE_IFELSE([AC_PROG_CXX], - [_AM_DEPENDENCIES(CXX)], - [define([AC_PROG_CXX], - defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl + [_AM_DEPENDENCIES([CXX])], + [m4_define([AC_PROG_CXX], + m4_defn([AC_PROG_CXX])[_AM_DEPENDENCIES([CXX])])])dnl AC_PROVIDE_IFELSE([AC_PROG_OBJC], - [_AM_DEPENDENCIES(OBJC)], - [define([AC_PROG_OBJC], - defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl + [_AM_DEPENDENCIES([OBJC])], + [m4_define([AC_PROG_OBJC], + m4_defn([AC_PROG_OBJC])[_AM_DEPENDENCIES([OBJC])])])dnl +AC_PROVIDE_IFELSE([AC_PROG_OBJCXX], + [_AM_DEPENDENCIES([OBJCXX])], + [m4_define([AC_PROG_OBJCXX], + m4_defn([AC_PROG_OBJCXX])[_AM_DEPENDENCIES([OBJCXX])])])dnl ]) -_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl -dnl The `parallel-tests' driver may need to know about EXEEXT, so add the -dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro -dnl is hooked onto _AC_COMPILER_EXEEXT early, see below. +AC_REQUIRE([AM_SILENT_RULES])dnl +dnl The testsuite driver may need to know about EXEEXT, so add the +dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This +dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below. AC_CONFIG_COMMANDS_PRE(dnl [m4_provide_if([_AM_COMPILER_EXEEXT], [AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl + +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + AC_MSG_ERROR([Your 'rm' program is bad, sorry.]) + fi +fi +dnl The trailing newline in this macro's definition is deliberate, for +dnl backward compatibility and to allow trailing 'dnl'-style comments +dnl after the AM_INIT_AUTOMAKE invocation. See automake bug#16841. ]) -dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not +dnl Hook into '_AC_COMPILER_EXEEXT' early to learn its expansion. Do not dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further dnl mangled by Autoconf and run in a shell conditional statement. m4_define([_AC_COMPILER_EXEEXT], m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])]) - # When config.status generates a header, we must update the stamp-h file. # This file resides in the same directory as the config header # that is generated. The stamp files are numbered to have different names. @@ -8503,7 +615,7 @@ for _am_header in $config_headers :; do done echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count]) -# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -8514,7 +626,7 @@ echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_co # Define $install_sh. AC_DEFUN([AM_PROG_INSTALL_SH], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -8522,16 +634,14 @@ if test x"${install_sh}" != xset; then install_sh="\${SHELL} $am_aux_dir/install-sh" esac fi -AC_SUBST(install_sh)]) +AC_SUBST([install_sh])]) -# Copyright (C) 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2003-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 - # Check whether the underlying file-system supports filenames # with a leading dot. For instance MS-DOS doesn't. AC_DEFUN([AM_SET_LEADING_DOT], @@ -8548,20 +658,17 @@ AC_SUBST([am__leading_dot])]) # Add --enable-maintainer-mode option to configure. -*- Autoconf -*- # From Jim Meyering -# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1996-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 5 - # AM_MAINTAINER_MODE([DEFAULT-MODE]) # ---------------------------------- # Control maintainer-specific portions of Makefiles. -# Default is to disable them, unless `enable' is passed literally. -# For symmetry, `disable' may be passed as well. Anyway, the user +# Default is to disable them, unless 'enable' is passed literally. +# For symmetry, 'disable' may be passed as well. Anyway, the user # can override the default with the --enable/--disable switch. AC_DEFUN([AM_MAINTAINER_MODE], [m4_case(m4_default([$1], [disable]), @@ -8569,13 +676,14 @@ AC_DEFUN([AM_MAINTAINER_MODE], [disable], [m4_define([am_maintainer_other], [enable])], [m4_define([am_maintainer_other], [enable]) m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])]) -AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles]) +AC_MSG_CHECKING([whether to enable maintainer-specific portions of Makefiles]) dnl maintainer-mode's default is 'disable' unless 'enable' is passed AC_ARG_ENABLE([maintainer-mode], -[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful - (and sometimes confusing) to the casual installer], - [USE_MAINTAINER_MODE=$enableval], - [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) + [AS_HELP_STRING([--]am_maintainer_other[-maintainer-mode], + am_maintainer_other[ make rules and dependencies not useful + (and sometimes confusing) to the casual installer])], + [USE_MAINTAINER_MODE=$enableval], + [USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes])) AC_MSG_RESULT([$USE_MAINTAINER_MODE]) AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes]) MAINT=$MAINTAINER_MODE_TRUE @@ -8583,71 +691,57 @@ AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of ] ) -AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE]) - # Check to see how 'make' treats includes. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003, 2005, 2009 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 4 - # AM_MAKE_INCLUDE() # ----------------- -# Check to see how make treats includes. +# Check whether make has an 'include' directive that can support all +# the idioms we need for our automatic dependency tracking code. AC_DEFUN([AM_MAKE_INCLUDE], -[am_make=${MAKE-make} -cat > confinc << 'END' +[AC_MSG_CHECKING([whether ${MAKE-make} supports the include directive]) +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -AC_MSG_CHECKING([for style of include used by $am_make]) am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from `make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD - ;; - esac -fi -AC_SUBST([am__include]) -AC_SUBST([am__quote]) -AC_MSG_RESULT([$_am_result]) -rm -f confinc confmf -]) +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + AM_RUN_LOG([${MAKE-make} -f confmf.$s && cat confinc.out]) + AS_CASE([$?:`cat confinc.out 2>/dev/null`], + ['0:this is the am__doit target'], + [AS_CASE([$s], + [BSD], [am__include='.include' am__quote='"'], + [am__include='include' am__quote=''])]) + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +AC_MSG_RESULT([${_am_result}]) +AC_SUBST([am__include])]) +AC_SUBST([am__quote])]) # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- -# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1997-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 6 - # AM_MISSING_PROG(NAME, PROGRAM) # ------------------------------ AC_DEFUN([AM_MISSING_PROG], @@ -8655,11 +749,10 @@ AC_DEFUN([AM_MISSING_PROG], $1=${$1-"${am_missing_run}$2"} AC_SUBST($1)]) - # AM_MISSING_HAS_RUN # ------------------ -# Define MISSING if not defined so far and test if it supports --run. -# If it does, set am_missing_run to use it, otherwise, to nothing. +# Define MISSING if not defined so far and test if it is modern enough. +# If it is, set am_missing_run to use it, otherwise, to nothing. AC_DEFUN([AM_MISSING_HAS_RUN], [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl AC_REQUIRE_AUX_FILE([missing])dnl @@ -8672,63 +765,35 @@ if test x"${MISSING+set}" != xset; then esac fi # Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " else am_missing_run= - AC_MSG_WARN([`missing' script is too old or missing]) + AC_MSG_WARN(['missing' script is too old or missing]) fi ]) -# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. -# -# This file is free software; the Free Software Foundation -# gives unlimited permission to copy and/or distribute it, -# with or without modifications, as long as this notice is preserved. - -# AM_PROG_MKDIR_P -# --------------- -# Check for `mkdir -p'. -AC_DEFUN([AM_PROG_MKDIR_P], -[AC_PREREQ([2.60])dnl -AC_REQUIRE([AC_PROG_MKDIR_P])dnl -dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, -dnl while keeping a definition of mkdir_p for backward compatibility. -dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. -dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of -dnl Makefile.ins that do not define MKDIR_P, so we do our own -dnl adjustment using top_builddir (which is defined more often than -dnl MKDIR_P). -AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl -case $mkdir_p in - [[\\/$]]* | ?:[[\\/]]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac -]) - # Helper functions for option handling. -*- Autoconf -*- -# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc. +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 4 - # _AM_MANGLE_OPTION(NAME) # ----------------------- AC_DEFUN([_AM_MANGLE_OPTION], [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) # _AM_SET_OPTION(NAME) -# ------------------------------ +# -------------------- # Set option NAME. Presently that only means defining a flag for this option. AC_DEFUN([_AM_SET_OPTION], -[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) +[m4_define(_AM_MANGLE_OPTION([$1]), [1])]) # _AM_SET_OPTIONS(OPTIONS) -# ---------------------------------- +# ------------------------ # OPTIONS is a space-separated list of Automake options. AC_DEFUN([_AM_SET_OPTIONS], [m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) @@ -8739,24 +804,82 @@ AC_DEFUN([_AM_SET_OPTIONS], AC_DEFUN([_AM_IF_OPTION], [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) -# Check to make sure that the build environment is sane. -*- Autoconf -*- - -# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008 -# Free Software Foundation, Inc. +# Copyright (C) 1999-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 5 +# _AM_PROG_CC_C_O +# --------------- +# Like AC_PROG_CC_C_O, but changed for automake. We rewrite AC_PROG_CC +# to automatically call this. +AC_DEFUN([_AM_PROG_CC_C_O], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +AC_REQUIRE_AUX_FILE([compile])dnl +AC_LANG_PUSH([C])dnl +AC_CACHE_CHECK( + [whether $CC understands -c and -o together], + [am_cv_prog_cc_c_o], + [AC_LANG_CONFTEST([AC_LANG_PROGRAM([])]) + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if AM_RUN_LOG([$CC -c conftest.$ac_ext -o conftest2.$ac_objext]) \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i]) +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +AC_LANG_POP([C])]) + +# For backward compatibility. +AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])]) + +# Copyright (C) 2001-2018 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_RUN_LOG(COMMAND) +# ------------------- +# Run COMMAND, save the exit status in ac_status, and log it. +# (This has been adapted from Autoconf's _AC_RUN_LOG macro.) +AC_DEFUN([AM_RUN_LOG], +[{ echo "$as_me:$LINENO: $1" >&AS_MESSAGE_LOG_FD + ($1) >&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + (exit $ac_status); }]) + +# Check to make sure that the build environment is sane. -*- Autoconf -*- + +# Copyright (C) 1996-2018 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. # AM_SANITY_CHECK # --------------- AC_DEFUN([AM_SANITY_CHECK], [AC_MSG_CHECKING([whether build environment is sane]) -# Just in case -sleep 1 -echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' @@ -8767,32 +890,40 @@ case `pwd` in esac case $srcdir in *[[\\\"\#\$\&\'\`$am_lf\ \ ]]*) - AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);; + AC_MSG_ERROR([unsafe srcdir value: '$srcdir']);; esac -# Do `set' in a subshell so we don't clobber the current shell's +# Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$[*]" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - rm -f conftest.file - if test "$[*]" != "X $srcdir/configure conftest.file" \ - && test "$[*]" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken -alias in your environment]) - fi + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken + alias in your environment]) + fi + if test "$[2]" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done test "$[2]" = conftest.file ) then @@ -8802,9 +933,85 @@ else AC_MSG_ERROR([newly created file is older than distributed files! Check your system clock]) fi -AC_MSG_RESULT(yes)]) +AC_MSG_RESULT([yes]) +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi +AC_CONFIG_COMMANDS_PRE( + [AC_MSG_CHECKING([that generated files are newer than configure]) + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + AC_MSG_RESULT([done])]) +rm -f conftest.file +]) -# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. +# Copyright (C) 2009-2018 Free Software Foundation, Inc. +# +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# AM_SILENT_RULES([DEFAULT]) +# -------------------------- +# Enable less verbose build rules; with the default set to DEFAULT +# ("yes" being less verbose, "no" or empty being verbose). +AC_DEFUN([AM_SILENT_RULES], +[AC_ARG_ENABLE([silent-rules], [dnl +AS_HELP_STRING( + [--enable-silent-rules], + [less verbose build output (undo: "make V=1")]) +AS_HELP_STRING( + [--disable-silent-rules], + [verbose build output (undo: "make V=0")])dnl +]) +case $enable_silent_rules in @%:@ ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=m4_if([$1], [yes], [0], [1]);; +esac +dnl +dnl A few 'make' implementations (e.g., NonStop OS and NextStep) +dnl do not support nested variable expansions. +dnl See automake bug#9928 and bug#10237. +am_make=${MAKE-make} +AC_CACHE_CHECK([whether $am_make supports nested variables], + [am_cv_make_support_nested_variables], + [if AS_ECHO([['TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit']]) | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi]) +if test $am_cv_make_support_nested_variables = yes; then + dnl Using '$V' instead of '$(V)' breaks IRIX make. + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AC_SUBST([AM_V])dnl +AM_SUBST_NOTMAKE([AM_V])dnl +AC_SUBST([AM_DEFAULT_V])dnl +AM_SUBST_NOTMAKE([AM_DEFAULT_V])dnl +AC_SUBST([AM_DEFAULT_VERBOSITY])dnl +AM_BACKSLASH='\' +AC_SUBST([AM_BACKSLASH])dnl +_AM_SUBST_NOTMAKE([AM_BACKSLASH])dnl +]) + +# Copyright (C) 2001-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, @@ -8812,34 +1019,32 @@ AC_MSG_RESULT(yes)]) # AM_PROG_INSTALL_STRIP # --------------------- -# One issue with vendor `install' (even GNU) is that you can't +# One issue with vendor 'install' (even GNU) is that you can't # specify the program used to strip binaries. This is especially # annoying in cross-compiling environments, where the build's strip # is unlikely to handle the host's binaries. # Fortunately install-sh will honor a STRIPPROG variable, so we -# always use install-sh in `make install-strip', and initialize +# always use install-sh in "make install-strip", and initialize # STRIPPROG with the value of the STRIP variable (set by the user). AC_DEFUN([AM_PROG_INSTALL_STRIP], [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. -dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +# will honor the 'STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be 'maybe'. if test "$cross_compiling" != no; then AC_CHECK_TOOL([STRIP], [strip], :) fi INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" AC_SUBST([INSTALL_STRIP_PROGRAM])]) -# Copyright (C) 2006, 2008 Free Software Foundation, Inc. +# Copyright (C) 2006-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 - # _AM_SUBST_NOTMAKE(VARIABLE) # --------------------------- # Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in. @@ -8847,24 +1052,22 @@ AC_SUBST([INSTALL_STRIP_PROGRAM])]) AC_DEFUN([_AM_SUBST_NOTMAKE]) # AM_SUBST_NOTMAKE(VARIABLE) -# --------------------------- +# -------------------------- # Public sister of _AM_SUBST_NOTMAKE. AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Check how to create a tarball. -*- Autoconf -*- -# Copyright (C) 2004, 2005 Free Software Foundation, Inc. +# Copyright (C) 2004-2018 Free Software Foundation, Inc. # # This file is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. -# serial 2 - # _AM_PROG_TAR(FORMAT) # -------------------- # Check how to create a tarball in format FORMAT. -# FORMAT should be one of `v7', `ustar', or `pax'. +# FORMAT should be one of 'v7', 'ustar', or 'pax'. # # Substitute a variable $(am__tar) that is a command # writing to stdout a FORMAT-tarball containing the directory @@ -8874,76 +1077,120 @@ AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)]) # Substitute a variable $(am__untar) that extract such # a tarball read from stdin. # $(am__untar) < result.tar +# AC_DEFUN([_AM_PROG_TAR], -[# Always define AMTAR for backward compatibility. -AM_MISSING_PROG([AMTAR], [tar]) -m4_if([$1], [v7], - [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], - [m4_case([$1], [ustar],, [pax],, - [m4_fatal([Unknown tar format])]) -AC_MSG_CHECKING([how to create a $1 tar archive]) -# Loop over all known methods to create a tar archive until one works. +[# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AC_SUBST([AMTAR], ['$${TAR-tar}']) + +# We'll loop over all known methods to create a tar archive until one works. _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' -_am_tools=${am_cv_prog_tar_$1-$_am_tools} -# Do not fold the above two line into one, because Tru64 sh and -# Solaris sh will not grok spaces in the rhs of `-'. -for _am_tool in $_am_tools -do - case $_am_tool in - gnutar) - for _am_tar in tar gnutar gtar; - do - AM_RUN_LOG([$_am_tar --version]) && break - done - am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' - am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' - am__untar="$_am_tar -xf -" - ;; - plaintar) - # Must skip GNU tar: if it does not support --format= it doesn't create - # ustar tarball either. - (tar --version) >/dev/null 2>&1 && continue - am__tar='tar chf - "$$tardir"' - am__tar_='tar chf - "$tardir"' - am__untar='tar xf -' - ;; - pax) - am__tar='pax -L -x $1 -w "$$tardir"' - am__tar_='pax -L -x $1 -w "$tardir"' - am__untar='pax -r' - ;; - cpio) - am__tar='find "$$tardir" -print | cpio -o -H $1 -L' - am__tar_='find "$tardir" -print | cpio -o -H $1 -L' - am__untar='cpio -i -H $1 -d' - ;; - none) - am__tar=false - am__tar_=false - am__untar=false - ;; - esac - # If the value was cached, stop now. We just wanted to have am__tar - # and am__untar set. - test -n "${am_cv_prog_tar_$1}" && break +m4_if([$1], [v7], + [am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -'], - # tar/untar a dummy directory, and stop if the command works + [m4_case([$1], + [ustar], + [# The POSIX 1988 'ustar' format is defined with fixed-size fields. + # There is notably a 21 bits limit for the UID and the GID. In fact, + # the 'pax' utility can hang on bigger UID/GID (see automake bug#8343 + # and bug#13588). + am_max_uid=2097151 # 2^21 - 1 + am_max_gid=$am_max_uid + # The $UID and $GID variables are not portable, so we need to resort + # to the POSIX-mandated id(1) utility. Errors in the 'id' calls + # below are definitely unexpected, so allow the users to see them + # (that is, avoid stderr redirection). + am_uid=`id -u || echo unknown` + am_gid=`id -g || echo unknown` + AC_MSG_CHECKING([whether UID '$am_uid' is supported by ustar format]) + if test $am_uid -le $am_max_uid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi + AC_MSG_CHECKING([whether GID '$am_gid' is supported by ustar format]) + if test $am_gid -le $am_max_gid; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + _am_tools=none + fi], + + [pax], + [], + + [m4_fatal([Unknown tar format])]) + + AC_MSG_CHECKING([how to create a $1 tar archive]) + + # Go ahead even if we have the value already cached. We do so because we + # need to set the values for the 'am__tar' and 'am__untar' variables. + _am_tools=${am_cv_prog_tar_$1-$_am_tools} + + for _am_tool in $_am_tools; do + case $_am_tool in + gnutar) + for _am_tar in tar gnutar gtar; do + AM_RUN_LOG([$_am_tar --version]) && break + done + am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' + am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' + am__untar="$_am_tar -xf -" + ;; + plaintar) + # Must skip GNU tar: if it does not support --format= it doesn't create + # ustar tarball either. + (tar --version) >/dev/null 2>&1 && continue + am__tar='tar chf - "$$tardir"' + am__tar_='tar chf - "$tardir"' + am__untar='tar xf -' + ;; + pax) + am__tar='pax -L -x $1 -w "$$tardir"' + am__tar_='pax -L -x $1 -w "$tardir"' + am__untar='pax -r' + ;; + cpio) + am__tar='find "$$tardir" -print | cpio -o -H $1 -L' + am__tar_='find "$tardir" -print | cpio -o -H $1 -L' + am__untar='cpio -i -H $1 -d' + ;; + none) + am__tar=false + am__tar_=false + am__untar=false + ;; + esac + + # If the value was cached, stop now. We just wanted to have am__tar + # and am__untar set. + test -n "${am_cv_prog_tar_$1}" && break + + # tar/untar a dummy directory, and stop if the command works. + rm -rf conftest.dir + mkdir conftest.dir + echo GrepMe > conftest.dir/file + AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) + rm -rf conftest.dir + if test -s conftest.tar; then + AM_RUN_LOG([$am__untar /dev/null 2>&1 && break + fi + done rm -rf conftest.dir - mkdir conftest.dir - echo GrepMe > conftest.dir/file - AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) - rm -rf conftest.dir - if test -s conftest.tar; then - AM_RUN_LOG([$am__untar /dev/null 2>&1 && break - fi -done -rm -rf conftest.dir -AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) -AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) + AC_MSG_RESULT([$am_cv_prog_tar_$1])]) + AC_SUBST([am__tar]) AC_SUBST([am__untar]) ]) # _AM_PROG_TAR +m4_include([scripts/libtool.m4]) +m4_include([scripts/ltoptions.m4]) +m4_include([scripts/ltsugar.m4]) +m4_include([scripts/ltversion.m4]) +m4_include([scripts/lt~obsolete.m4]) diff --git a/libs/libpng-src/arm/arm_init.c b/libs/libpng-src/arm/arm_init.c new file mode 100644 index 000000000..a34ecdbef --- /dev/null +++ b/libs/libpng-src/arm/arm_init.c @@ -0,0 +1,136 @@ + +/* arm_init.c - NEON optimised filter functions + * + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2014,2016 Glenn Randers-Pehrson + * Written by Mans Rullgard, 2011. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are + * called. + */ +#define _POSIX_SOURCE 1 + +#include "../pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +#if PNG_ARM_NEON_OPT > 0 +#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */ +/* WARNING: it is strongly recommended that you do not build libpng with + * run-time checks for CPU features if at all possible. In the case of the ARM + * NEON instructions there is no processor-specific way of detecting the + * presence of the required support, therefore run-time detection is extremely + * OS specific. + * + * You may set the macro PNG_ARM_NEON_FILE to the file name of file containing + * a fragment of C source code which defines the png_have_neon function. There + * are a number of implementations in contrib/arm-neon, but the only one that + * has partial support is contrib/arm-neon/linux.c - a generic Linux + * implementation which reads /proc/cpufino. + */ +#ifndef PNG_ARM_NEON_FILE +# ifdef __linux__ +# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c" +# endif +#endif + +#ifdef PNG_ARM_NEON_FILE + +#include /* for sig_atomic_t */ +static int png_have_neon(png_structp png_ptr); +#include PNG_ARM_NEON_FILE + +#else /* PNG_ARM_NEON_FILE */ +# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks" +#endif /* PNG_ARM_NEON_FILE */ +#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */ + +#ifndef PNG_ALIGNED_MEMORY_SUPPORTED +# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED" +#endif + +void +png_init_filter_functions_neon(png_structp pp, unsigned int bpp) +{ + /* The switch statement is compiled in for ARM_NEON_API, the call to + * png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined + * the check is only performed if the API has not set the NEON option on + * or off explicitly. In this case the check controls what happens. + * + * If the CHECK is not compiled in and the option is UNSET the behavior prior + * to 1.6.7 was to use the NEON code - this was a bug caused by having the + * wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF, + * as documented in png.h + */ + png_debug(1, "in png_init_filter_functions_neon"); +#ifdef PNG_ARM_NEON_API_SUPPORTED + switch ((pp->options >> PNG_ARM_NEON) & 3) + { + case PNG_OPTION_UNSET: + /* Allow the run-time check to execute if it has been enabled - + * thus both API and CHECK can be turned on. If it isn't supported + * this case will fall through to the 'default' below, which just + * returns. + */ +#endif /* PNG_ARM_NEON_API_SUPPORTED */ +#ifdef PNG_ARM_NEON_CHECK_SUPPORTED + { + static volatile sig_atomic_t no_neon = -1; /* not checked */ + + if (no_neon < 0) + no_neon = !png_have_neon(pp); + + if (no_neon) + return; + } +#ifdef PNG_ARM_NEON_API_SUPPORTED + break; +#endif +#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */ + +#ifdef PNG_ARM_NEON_API_SUPPORTED + default: /* OFF or INVALID */ + return; + + case PNG_OPTION_ON: + /* Option turned on */ + break; + } +#endif + + /* IMPORTANT: any new external functions used here must be declared using + * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the + * 'prefix' option to configure works: + * + * ./configure --with-libpng-prefix=foobar_ + * + * Verify you have got this right by running the above command, doing a build + * and examining pngprefix.h; it must contain a #define for every external + * function you add. (Notice that this happens automatically for the + * initialization function.) + */ + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon; + + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth3_neon; + } + + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth4_neon; + } +} +#endif /* PNG_ARM_NEON_OPT > 0 */ +#endif /* READ */ diff --git a/libs/libpng-src/arm/filter_neon.S b/libs/libpng-src/arm/filter_neon.S new file mode 100644 index 000000000..2308aad13 --- /dev/null +++ b/libs/libpng-src/arm/filter_neon.S @@ -0,0 +1,253 @@ + +/* filter_neon.S - NEON optimised filter functions + * + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2014,2017 Glenn Randers-Pehrson + * Written by Mans Rullgard, 2011. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* This is required to get the symbol renames, which are #defines, and the + * definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION. + */ +#define PNG_VERSION_INFO_ONLY +#include "../pngpriv.h" + +#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ +#endif + +#ifdef PNG_READ_SUPPORTED + +/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for + * ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it + * only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h + * for the logic which sets PNG_USE_ARM_NEON_ASM: + */ +#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */ + +#if PNG_ARM_NEON_OPT > 0 + +#ifdef __ELF__ +# define ELF +#else +# define ELF @ +#endif + + .arch armv7-a + .fpu neon + +.macro func name, export=0 + .macro endfunc +ELF .size \name, . - \name + .endfunc + .purgem endfunc + .endm + .text + + /* Explicitly specifying alignment here because some versions of + * GAS don't align code correctly. This is harmless in correctly + * written versions of GAS. + */ + .align 2 + + .if \export + .global \name + .endif +ELF .type \name, STT_FUNC + .func \name +\name: +.endm + +func png_read_filter_row_sub4_neon, export=1 + ldr r3, [r0, #4] @ rowbytes + vmov.i8 d3, #0 +1: + vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] + vadd.u8 d0, d3, d4 + vadd.u8 d1, d0, d5 + vadd.u8 d2, d1, d6 + vadd.u8 d3, d2, d7 + vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! + subs r3, r3, #16 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_sub3_neon, export=1 + ldr r3, [r0, #4] @ rowbytes + vmov.i8 d3, #0 + mov r0, r1 + mov r2, #3 + mov r12, #12 + vld1.8 {q11}, [r0], r12 +1: + vext.8 d5, d22, d23, #3 + vadd.u8 d0, d3, d22 + vext.8 d6, d22, d23, #6 + vadd.u8 d1, d0, d5 + vext.8 d7, d23, d23, #1 + vld1.8 {q11}, [r0], r12 + vst1.32 {d0[0]}, [r1,:32], r2 + vadd.u8 d2, d1, d6 + vst1.32 {d1[0]}, [r1], r2 + vadd.u8 d3, d2, d7 + vst1.32 {d2[0]}, [r1], r2 + vst1.32 {d3[0]}, [r1], r2 + subs r3, r3, #12 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_up_neon, export=1 + ldr r3, [r0, #4] @ rowbytes +1: + vld1.8 {q0}, [r1,:128] + vld1.8 {q1}, [r2,:128]! + vadd.u8 q0, q0, q1 + vst1.8 {q0}, [r1,:128]! + subs r3, r3, #16 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_avg4_neon, export=1 + ldr r12, [r0, #4] @ rowbytes + vmov.i8 d3, #0 +1: + vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] + vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! + vhadd.u8 d0, d3, d16 + vadd.u8 d0, d0, d4 + vhadd.u8 d1, d0, d17 + vadd.u8 d1, d1, d5 + vhadd.u8 d2, d1, d18 + vadd.u8 d2, d2, d6 + vhadd.u8 d3, d2, d19 + vadd.u8 d3, d3, d7 + vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! + subs r12, r12, #16 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_avg3_neon, export=1 + push {r4,lr} + ldr r12, [r0, #4] @ rowbytes + vmov.i8 d3, #0 + mov r0, r1 + mov r4, #3 + mov lr, #12 + vld1.8 {q11}, [r0], lr +1: + vld1.8 {q10}, [r2], lr + vext.8 d5, d22, d23, #3 + vhadd.u8 d0, d3, d20 + vext.8 d17, d20, d21, #3 + vadd.u8 d0, d0, d22 + vext.8 d6, d22, d23, #6 + vhadd.u8 d1, d0, d17 + vext.8 d18, d20, d21, #6 + vadd.u8 d1, d1, d5 + vext.8 d7, d23, d23, #1 + vld1.8 {q11}, [r0], lr + vst1.32 {d0[0]}, [r1,:32], r4 + vhadd.u8 d2, d1, d18 + vst1.32 {d1[0]}, [r1], r4 + vext.8 d19, d21, d21, #1 + vadd.u8 d2, d2, d6 + vhadd.u8 d3, d2, d19 + vst1.32 {d2[0]}, [r1], r4 + vadd.u8 d3, d3, d7 + vst1.32 {d3[0]}, [r1], r4 + subs r12, r12, #12 + bgt 1b + + pop {r4,pc} +endfunc + +.macro paeth rx, ra, rb, rc + vaddl.u8 q12, \ra, \rb @ a + b + vaddl.u8 q15, \rc, \rc @ 2*c + vabdl.u8 q13, \rb, \rc @ pa + vabdl.u8 q14, \ra, \rc @ pb + vabd.u16 q15, q12, q15 @ pc + vcle.u16 q12, q13, q14 @ pa <= pb + vcle.u16 q13, q13, q15 @ pa <= pc + vcle.u16 q14, q14, q15 @ pb <= pc + vand q12, q12, q13 @ pa <= pb && pa <= pc + vmovn.u16 d28, q14 + vmovn.u16 \rx, q12 + vbsl d28, \rb, \rc + vbsl \rx, \ra, d28 +.endm + +func png_read_filter_row_paeth4_neon, export=1 + ldr r12, [r0, #4] @ rowbytes + vmov.i8 d3, #0 + vmov.i8 d20, #0 +1: + vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] + vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! + paeth d0, d3, d16, d20 + vadd.u8 d0, d0, d4 + paeth d1, d0, d17, d16 + vadd.u8 d1, d1, d5 + paeth d2, d1, d18, d17 + vadd.u8 d2, d2, d6 + paeth d3, d2, d19, d18 + vmov d20, d19 + vadd.u8 d3, d3, d7 + vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! + subs r12, r12, #16 + bgt 1b + + bx lr +endfunc + +func png_read_filter_row_paeth3_neon, export=1 + push {r4,lr} + ldr r12, [r0, #4] @ rowbytes + vmov.i8 d3, #0 + vmov.i8 d4, #0 + mov r0, r1 + mov r4, #3 + mov lr, #12 + vld1.8 {q11}, [r0], lr +1: + vld1.8 {q10}, [r2], lr + paeth d0, d3, d20, d4 + vext.8 d5, d22, d23, #3 + vadd.u8 d0, d0, d22 + vext.8 d17, d20, d21, #3 + paeth d1, d0, d17, d20 + vst1.32 {d0[0]}, [r1,:32], r4 + vext.8 d6, d22, d23, #6 + vadd.u8 d1, d1, d5 + vext.8 d18, d20, d21, #6 + paeth d2, d1, d18, d17 + vext.8 d7, d23, d23, #1 + vld1.8 {q11}, [r0], lr + vst1.32 {d1[0]}, [r1], r4 + vadd.u8 d2, d2, d6 + vext.8 d19, d21, d21, #1 + paeth d3, d2, d19, d18 + vst1.32 {d2[0]}, [r1], r4 + vmov d4, d19 + vadd.u8 d3, d3, d7 + vst1.32 {d3[0]}, [r1], r4 + subs r12, r12, #12 + bgt 1b + + pop {r4,pc} +endfunc +#endif /* PNG_ARM_NEON_OPT > 0 */ +#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */ +#endif /* READ */ diff --git a/libs/libpng-src/arm/filter_neon_intrinsics.c b/libs/libpng-src/arm/filter_neon_intrinsics.c new file mode 100644 index 000000000..553c0be21 --- /dev/null +++ b/libs/libpng-src/arm/filter_neon_intrinsics.c @@ -0,0 +1,402 @@ + +/* filter_neon_intrinsics.c - NEON optimised filter functions + * + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2014,2016 Glenn Randers-Pehrson + * Written by James Yu , October 2013. + * Based on filter_neon.S, written by Mans Rullgard, 2011. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../pngpriv.h" + +#ifdef PNG_READ_SUPPORTED + +/* This code requires -mfpu=neon on the command line: */ +#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ + +#if defined(_MSC_VER) && defined(_M_ARM64) +# include +#else +# include +#endif + +/* libpng row pointers are not necessarily aligned to any particular boundary, + * however this code will only work with appropriate alignment. arm/arm_init.c + * checks for this (and will not compile unless it is done). This code uses + * variants of png_aligncast to avoid compiler warnings. + */ +#define png_ptr(type,pointer) png_aligncast(type *,pointer) +#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer) + +/* The following relies on a variable 'temp_pointer' being declared with type + * 'type'. This is written this way just to hide the GCC strict aliasing + * warning; note that the code is safe because there never is an alias between + * the input and output pointers. + * + * When compiling with MSVC ARM64, the png_ldr macro can't be passed directly + * to vst4_lane_u32, because of an internal compiler error inside MSVC. + * To avoid this compiler bug, we use a temporary variable (vdest_val) to store + * the result of png_ldr. + */ +#define png_ldr(type,pointer)\ + (temp_pointer = png_ptr(type,pointer), *temp_pointer) + +#if PNG_ARM_NEON_OPT > 0 + +void +png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + png_const_bytep pp = prev_row; + + png_debug(1, "in png_read_filter_row_up_neon"); + + for (; rp < rp_stop; rp += 16, pp += 16) + { + uint8x16_t qrp, qpp; + + qrp = vld1q_u8(rp); + qpp = vld1q_u8(pp); + qrp = vaddq_u8(qrp, qpp); + vst1q_u8(rp, qrp); + } +} + +void +png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + + uint8x16_t vtmp = vld1q_u8(rp); + uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp); + uint8x8x2_t vrp = *vrpt; + + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + png_debug(1, "in png_read_filter_row_sub3_neon"); + + for (; rp < rp_stop;) + { + uint8x8_t vtmp1, vtmp2; + uint32x2_t *temp_pointer; + + vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3); + vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]); + vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6); + vdest.val[1] = vadd_u8(vdest.val[0], vtmp1); + + vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1); + vdest.val[2] = vadd_u8(vdest.val[1], vtmp2); + vdest.val[3] = vadd_u8(vdest.val[2], vtmp1); + + vtmp = vld1q_u8(rp + 12); + vrpt = png_ptr(uint8x8x2_t, &vtmp); + vrp = *vrpt; + + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0); + rp += 3; + } + + PNG_UNUSED(prev_row) +} + +void +png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + png_debug(1, "in png_read_filter_row_sub4_neon"); + + for (; rp < rp_stop; rp += 16) + { + uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp)); + uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp); + uint8x8x4_t vrp = *vrpt; + uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; + + vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]); + vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]); + vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]); + vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]); + + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); + } + + PNG_UNUSED(prev_row) +} + +void +png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep rp_stop = row + row_info->rowbytes; + + uint8x16_t vtmp; + uint8x8x2_t *vrpt; + uint8x8x2_t vrp; + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + vtmp = vld1q_u8(rp); + vrpt = png_ptr(uint8x8x2_t,&vtmp); + vrp = *vrpt; + + png_debug(1, "in png_read_filter_row_avg3_neon"); + + for (; rp < rp_stop; pp += 12) + { + uint8x8_t vtmp1, vtmp2, vtmp3; + + uint8x8x2_t *vppt; + uint8x8x2_t vpp; + + uint32x2_t *temp_pointer; + + vtmp = vld1q_u8(pp); + vppt = png_ptr(uint8x8x2_t,&vtmp); + vpp = *vppt; + + vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3); + vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]); + vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]); + + vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3); + vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6); + vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2); + vdest.val[1] = vadd_u8(vdest.val[1], vtmp1); + + vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6); + vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1); + + vtmp = vld1q_u8(rp + 12); + vrpt = png_ptr(uint8x8x2_t,&vtmp); + vrp = *vrpt; + + vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2); + vdest.val[2] = vadd_u8(vdest.val[2], vtmp3); + + vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1); + + vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2); + vdest.val[3] = vadd_u8(vdest.val[3], vtmp1); + + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0); + rp += 3; + } +} + +void +png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + png_const_bytep pp = prev_row; + + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + png_debug(1, "in png_read_filter_row_avg4_neon"); + + for (; rp < rp_stop; rp += 16, pp += 16) + { + uint32x2x4_t vtmp; + uint8x8x4_t *vrpt, *vppt; + uint8x8x4_t vrp, vpp; + uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; + + vtmp = vld4_u32(png_ptr(uint32_t,rp)); + vrpt = png_ptr(uint8x8x4_t,&vtmp); + vrp = *vrpt; + vtmp = vld4_u32(png_ptrc(uint32_t,pp)); + vppt = png_ptr(uint8x8x4_t,&vtmp); + vpp = *vppt; + + vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]); + vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]); + vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]); + vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]); + vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]); + vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]); + vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]); + vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]); + + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); + } +} + +static uint8x8_t +paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c) +{ + uint8x8_t d, e; + uint16x8_t p1, pa, pb, pc; + + p1 = vaddl_u8(a, b); /* a + b */ + pc = vaddl_u8(c, c); /* c * 2 */ + pa = vabdl_u8(b, c); /* pa */ + pb = vabdl_u8(a, c); /* pb */ + pc = vabdq_u16(p1, pc); /* pc */ + + p1 = vcleq_u16(pa, pb); /* pa <= pb */ + pa = vcleq_u16(pa, pc); /* pa <= pc */ + pb = vcleq_u16(pb, pc); /* pb <= pc */ + + p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */ + + d = vmovn_u16(pb); + e = vmovn_u16(p1); + + d = vbsl_u8(d, b, c); + e = vbsl_u8(e, a, d); + + return e; +} + +void +png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_const_bytep pp = prev_row; + png_bytep rp_stop = row + row_info->rowbytes; + + uint8x16_t vtmp; + uint8x8x2_t *vrpt; + uint8x8x2_t vrp; + uint8x8_t vlast = vdup_n_u8(0); + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + vtmp = vld1q_u8(rp); + vrpt = png_ptr(uint8x8x2_t,&vtmp); + vrp = *vrpt; + + png_debug(1, "in png_read_filter_row_paeth3_neon"); + + for (; rp < rp_stop; pp += 12) + { + uint8x8x2_t *vppt; + uint8x8x2_t vpp; + uint8x8_t vtmp1, vtmp2, vtmp3; + uint32x2_t *temp_pointer; + + vtmp = vld1q_u8(pp); + vppt = png_ptr(uint8x8x2_t,&vtmp); + vpp = *vppt; + + vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast); + vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]); + + vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3); + vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3); + vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]); + vdest.val[1] = vadd_u8(vdest.val[1], vtmp1); + + vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6); + vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6); + vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2); + vdest.val[2] = vadd_u8(vdest.val[2], vtmp1); + + vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1); + vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1); + + vtmp = vld1q_u8(rp + 12); + vrpt = png_ptr(uint8x8x2_t,&vtmp); + vrp = *vrpt; + + vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3); + vdest.val[3] = vadd_u8(vdest.val[3], vtmp1); + + vlast = vtmp2; + + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0); + rp += 3; + vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0); + rp += 3; + } +} + +void +png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + png_bytep rp = row; + png_bytep rp_stop = row + row_info->rowbytes; + png_const_bytep pp = prev_row; + + uint8x8_t vlast = vdup_n_u8(0); + uint8x8x4_t vdest; + vdest.val[3] = vdup_n_u8(0); + + png_debug(1, "in png_read_filter_row_paeth4_neon"); + + for (; rp < rp_stop; rp += 16, pp += 16) + { + uint32x2x4_t vtmp; + uint8x8x4_t *vrpt, *vppt; + uint8x8x4_t vrp, vpp; + uint32x2x4_t *temp_pointer; + uint32x2x4_t vdest_val; + + vtmp = vld4_u32(png_ptr(uint32_t,rp)); + vrpt = png_ptr(uint8x8x4_t,&vtmp); + vrp = *vrpt; + vtmp = vld4_u32(png_ptrc(uint32_t,pp)); + vppt = png_ptr(uint8x8x4_t,&vtmp); + vpp = *vppt; + + vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast); + vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]); + vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]); + vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]); + vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]); + vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]); + vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]); + vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]); + + vlast = vpp.val[3]; + + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); + } +} + +#endif /* PNG_ARM_NEON_OPT > 0 */ +#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */ +#endif /* READ */ diff --git a/libs/libpng-src/arm/palette_neon_intrinsics.c b/libs/libpng-src/arm/palette_neon_intrinsics.c new file mode 100644 index 000000000..b4d1fd2ab --- /dev/null +++ b/libs/libpng-src/arm/palette_neon_intrinsics.c @@ -0,0 +1,149 @@ + +/* palette_neon_intrinsics.c - NEON optimised palette expansion functions + * + * Copyright (c) 2018-2019 Cosmin Truta + * Copyright (c) 2017-2018 Arm Holdings. All rights reserved. + * Written by Richard Townsend , February 2017. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#include "../pngpriv.h" + +#if PNG_ARM_NEON_IMPLEMENTATION == 1 + +#if defined(_MSC_VER) && defined(_M_ARM64) +# include +#else +# include +#endif + +/* Build an RGBA8 palette from the separate RGB and alpha palettes. */ +void +png_riffle_palette_neon(png_structrp png_ptr) +{ + png_const_colorp palette = png_ptr->palette; + png_bytep riffled_palette = png_ptr->riffled_palette; + png_const_bytep trans_alpha = png_ptr->trans_alpha; + int num_trans = png_ptr->num_trans; + int i; + + png_debug(1, "in png_riffle_palette_neon"); + + /* Initially black, opaque. */ + uint8x16x4_t w = {{ + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0xff), + }}; + + /* First, riffle the RGB colours into an RGBA8 palette. + * The alpha component is set to opaque for now. + */ + for (i = 0; i < 256; i += 16) + { + uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i)); + w.val[0] = v.val[0]; + w.val[1] = v.val[1]; + w.val[2] = v.val[2]; + vst4q_u8(riffled_palette + (i << 2), w); + } + + /* Fix up the missing transparency values. */ + for (i = 0; i < num_trans; i++) + riffled_palette[(i << 2) + 3] = trans_alpha[i]; +} + +/* Expands a palettized row into RGBA8. */ +int +png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info, + png_const_bytep row, png_bytepp ssp, png_bytepp ddp) +{ + png_uint_32 row_width = row_info->width; + const png_uint_32 *riffled_palette = + (const png_uint_32 *)png_ptr->riffled_palette; + const png_int_32 pixels_per_chunk = 4; + int i; + + png_debug(1, "in png_do_expand_palette_rgba8_neon"); + + if (row_width < pixels_per_chunk) + return 0; + + /* This function originally gets the last byte of the output row. + * The NEON part writes forward from a given position, so we have + * to seek this back by 4 pixels x 4 bytes. + */ + *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1); + + for (i = 0; i < row_width; i += pixels_per_chunk) + { + uint32x4_t cur; + png_bytep sp = *ssp - i, dp = *ddp - (i << 2); + cur = vld1q_dup_u32 (riffled_palette + *(sp - 3)); + cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1); + cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2); + cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3); + vst1q_u32((void *)dp, cur); + } + if (i != row_width) + { + /* Remove the amount that wasn't processed. */ + i -= pixels_per_chunk; + } + + /* Decrement output pointers. */ + *ssp = *ssp - i; + *ddp = *ddp - (i << 2); + return i; +} + +/* Expands a palettized row into RGB8. */ +int +png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info, + png_const_bytep row, png_bytepp ssp, png_bytepp ddp) +{ + png_uint_32 row_width = row_info->width; + png_const_bytep palette = (png_const_bytep)png_ptr->palette; + const png_uint_32 pixels_per_chunk = 8; + int i; + + png_debug(1, "in png_do_expand_palette_rgb8_neon"); + + if (row_width <= pixels_per_chunk) + return 0; + + /* Seeking this back by 8 pixels x 3 bytes. */ + *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1); + + for (i = 0; i < row_width; i += pixels_per_chunk) + { + uint8x8x3_t cur; + png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i); + cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7))); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6); + cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7); + vst3_u8((void *)dp, cur); + } + + if (i != row_width) + { + /* Remove the amount that wasn't processed. */ + i -= pixels_per_chunk; + } + + /* Decrement output pointers. */ + *ssp = *ssp - i; + *ddp = *ddp - ((i << 1) + i); + return i; +} + +#endif /* PNG_ARM_NEON_IMPLEMENTATION */ diff --git a/libs/libpng-src/autogen.sh b/libs/libpng-src/autogen.sh index 77b63087c..a46daf65a 100755 --- a/libs/libpng-src/autogen.sh +++ b/libs/libpng-src/autogen.sh @@ -1,25 +1,225 @@ #! /bin/sh -# a quick hack script to generate necessary files from -# auto* tools. # -# WARNING: if you run this you will change the versions -# of the tools which are used and, maybe, required! - touch Makefile.am configure.ac -{ - echo "running libtoolize" >&2 - libtoolize --force --copy --automake -} && { - echo "running aclocal" >&2 - aclocal -} && { - echo "running autoheader [ignore the warnings]" >&2 - autoheader -} && { - echo "running automake" >&2 - automake --force-missing --foreign -a -c -} && { - echo "running autoconf" >&2 - autoconf -} && - echo "autogen complete" >&2 || - echo "ERROR: autogen.sh failed, autogen is incomplete" >&2 +# Run 'autoreconf' to build 'configure', 'Makefile.in' and other configure +# control files. +# +# The first time this is run on a GIT checkout the only files that exist are +# configure.ac and Makefile.am; all of the autotools support scripts are +# missing. They are instantiated with autoreconf --force --install. +# +# For regular ("tarball") distributions all the files should exist. We do not +# want them to be updated *under any circumstances*. It should never be +# necessary to run autogen.sh because ./configure --enable-maintainer-mode says +# what to do if Makefile.am or configure.ac are changed. +# +# It is *probably* OK to update the files on a GIT checkout, because they have +# come from the local tools, but leave that to the user who is assumed to know +# whether it is ok or required. +# +# This script is intended to work without arguments, there are, however, hidden +# arguments (a) for use while testing the script and (b) to fix up systems that +# have been broken. If (b) is required the script prompts for the correct +# options. For this reason the options are *NOT* documented in the help; this +# is deliberate; UTSL. +# +clean= +maintainer= +while test $# -gt 0 +do + case "$1" in + --maintainer) + maintainer=1;; + + --clean) + clean=1;; + + *) + exec >&2 + echo "$0: usage: ./autogen.sh" + if test -d .git + then + echo " ./autogen.sh generates the configure script and" + echo " Makefile.in, or refreshes them after changes to Makefile.am" + echo " or configure.ac. You may prefer to just run autoreconf." + elif test -z "$maintainer" + then + echo " DO NOT RUN THIS SCRIPT." + echo " If you need to change Makefile.am or configure.ac then you" + echo " also need to run ./configure --enable-maintainer-mode and" + echo " use the appropriate autotools, *NOT* this script, to update" + echo " everything, please check the documentation of autoreconf." + echo " WARNING: libpng is intentionally generated with a known," + echo " fixed, set of autotools. It is known *NOT* to work with" + echo " the collection of autotools distributed on highly reputable" + echo " operating systems." + echo " Remember: autotools is GNU software, you are expected to" + echo " pay for support." + else + echo " You have run autogen.sh with --maintainer enabled and you" + echo " are not using a GIT distribution, then you have given an" + echo " unrecognized argument. This is not good. --maintainer" + echo " switches off any assumptions that you might not know what" + echo " you are doing." + fi + exit 1;; + esac + + shift +done +# +# First check for a set of the autotools files; if absent then this is assumed +# to be a GIT version and the local autotools must be used. If present this +# is a tarball distribution and the script should not be used. If partially +# present bad things are happening. +# +# The autotools generated files: +libpng_autotools_files="Makefile.in aclocal.m4 config.guess config.h.in + config.sub configure depcomp install-sh ltmain.sh missing\ + test-driver" +# +# Files generated by versions of configue >2.68 or automake >1.13 (i.e. later +# versions than those required by configure.ac): +libpng_autotools_extra="compile config.h.in~" +# +# These are separate because 'maintainer-clean' does not remove them. +libpng_libtool_files="scripts/libtool.m4 scripts/ltoptions.m4\ + scripts/ltsugar.m4 scripts/ltversion.m4 scripts/lt~obsolete.m4" + +libpng_autotools_dirs="autom4te.cache" # not required +# +# The configure generated files: +libpng_configure_files="Makefile config.h config.log config.status\ + libpng-config libpng.pc libtool stamp-h1" + +libpng_configure_dirs=".deps" +# +# We must remove the configure generated files as well as the autotools +# generated files if autotools are regenerated because otherwise if configure +# has been run without "--enable-maintainer-mode" make can do a partial update +# of Makefile. These functions do the two bits of cleaning. +clean_autotools(){ + rm -rf $libpng_autotools_files $libpng_libtool_files $libpng_autotools_dirs + rm -rf $libpng_autotools_extra +} + +clean_configure(){ + rm -rf $libpng_configure_files $libpng_configure_dirs +} +# +# Clean: remove everything (this is to help with testing) +if test -n "$clean" +then + clean_configure + if test -n "$maintainer" + then + clean_autotools + fi + + exit 0 +fi +# +# Validate the distribution. +libpng_autotools_file_found= +libpng_autotools_file_missing= +for file in $libpng_autotools_files +do + if test -f "$file" + then + libpng_autotools_file_found=1 + else + libpng_autotools_file_missing=1 + fi +done +# +# Presence of one of these does not *invalidate* missing, but absence +# invalidates found. +for file in $libpng_libtool_files +do + if test ! -f "$file" + then + libpng_autotools_file_missing=1 + fi +done +# +# The cache directory doesn't matter - it will be regenerated and does not exist +# anyway in a tarball. +# +# Either everything is missing or everything is there, the --maintainer option +# just changes this so that the mode is set to generate all the files. +mode= +if test -z "$libpng_autotools_file_found" -o -n "$maintainer" +then + mode="autoreconf" +else + if test -n "$libpng_autotools_file_missing" + then + mode="broken" + else + mode="configure" + fi +fi +# +# So: +case "$mode" in + autoreconf) + # Clean in case configure files exist + clean_configure + clean_autotools + # Everything must be initialized, so use --force + if autoreconf --warnings=all --force --install + then + missing= + for file in $libpng_autotools_files + do + test -f "$file" || missing=1 + done + # ignore the cache directory + test -z "$missing" || { + exec >&2 + echo "autoreconf was run, but did not produce all the expected" + echo "files. It is likely that your autotools installation is" + echo "not compatible with that expected by libpng." + exit 1 + } + else + exec >&2 + echo "autoreconf failed: your version of autotools is incompatible" + echo "with this libpng version. Please use a distributed archive" + echo "(which includes the autotools generated files) and run configure" + echo "instead." + exit 1 + fi;; + + configure) + if test -d .git + then + exec >&2 + echo "ERROR: running autoreconf on an initialized system" + echo " This is not necessary; it is only necessary to remake the" + echo " autotools generated files if Makefile.am or configure.ac" + echo " change and make does the right thing with:" + echo + echo " ./configure --enable-maintainer-mode." + echo + echo " You can run autoreconf yourself if you don't like maintainer" + echo " mode and you can also just run autoreconf -f -i to initialize" + echo " everything in the first place; this script is only for" + echo " compatibility with prior releases." + exit 1 + else + exec >&2 + echo "autogen.sh is intended only to generate 'configure' on systems" + echo "that do not have it. You have a complete 'configure', if you" + echo "need to change Makefile.am or configure.ac you also need to" + echo "run configure with the --enable-maintainer-mode option." + exit 1 + fi;; + + broken) + exec >&2 + echo "Your system has a partial set of autotools generated files." + echo "autogen.sh is unable to proceed. The full set of files is" + echo "contained in the libpng 'tar' distribution archive and you do" + echo "not need to run autogen.sh if you use it." + exit 1;; +esac diff --git a/libs/libpng-src/compile b/libs/libpng-src/compile new file mode 100644 index 000000000..99e50524b --- /dev/null +++ b/libs/libpng-src/compile @@ -0,0 +1,348 @@ +#! /bin/sh +# Wrapper for compilers which do not understand '-c -o'. + +scriptversion=2018-03-07.03; # UTC + +# Copyright (C) 1999-2018 Free Software Foundation, Inc. +# Written by Tom Tromey . +# +# 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, 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 to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +nl=' +' + +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent tools from complaining about whitespace usage. +IFS=" "" $nl" + +file_conv= + +# func_file_conv build_file lazy +# Convert a $build file to $host form and store it in $file +# Currently only supports Windows hosts. If the determined conversion +# type is listed in (the comma separated) LAZY, no conversion will +# take place. +func_file_conv () +{ + file=$1 + case $file in + / | /[!/]*) # absolute file, and not a UNC file + if test -z "$file_conv"; then + # lazily determine how to convert abs files + case `uname -s` in + MINGW*) + file_conv=mingw + ;; + CYGWIN*) + file_conv=cygwin + ;; + *) + file_conv=wine + ;; + esac + fi + case $file_conv/,$2, in + *,$file_conv,*) + ;; + mingw/*) + file=`cmd //C echo "$file " | sed -e 's/"\(.*\) " *$/\1/'` + ;; + cygwin/*) + file=`cygpath -m "$file" || echo "$file"` + ;; + wine/*) + file=`winepath -w "$file" || echo "$file"` + ;; + esac + ;; + esac +} + +# func_cl_dashL linkdir +# Make cl look for libraries in LINKDIR +func_cl_dashL () +{ + func_file_conv "$1" + if test -z "$lib_path"; then + lib_path=$file + else + lib_path="$lib_path;$file" + fi + linker_opts="$linker_opts -LIBPATH:$file" +} + +# func_cl_dashl library +# Do a library search-path lookup for cl +func_cl_dashl () +{ + lib=$1 + found=no + save_IFS=$IFS + IFS=';' + for dir in $lib_path $LIB + do + IFS=$save_IFS + if $shared && test -f "$dir/$lib.dll.lib"; then + found=yes + lib=$dir/$lib.dll.lib + break + fi + if test -f "$dir/$lib.lib"; then + found=yes + lib=$dir/$lib.lib + break + fi + if test -f "$dir/lib$lib.a"; then + found=yes + lib=$dir/lib$lib.a + break + fi + done + IFS=$save_IFS + + if test "$found" != yes; then + lib=$lib.lib + fi +} + +# func_cl_wrapper cl arg... +# Adjust compile command to suit cl +func_cl_wrapper () +{ + # Assume a capable shell + lib_path= + shared=: + linker_opts= + for arg + do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + eat=1 + case $2 in + *.o | *.[oO][bB][jJ]) + func_file_conv "$2" + set x "$@" -Fo"$file" + shift + ;; + *) + func_file_conv "$2" + set x "$@" -Fe"$file" + shift + ;; + esac + ;; + -I) + eat=1 + func_file_conv "$2" mingw + set x "$@" -I"$file" + shift + ;; + -I*) + func_file_conv "${1#-I}" mingw + set x "$@" -I"$file" + shift + ;; + -l) + eat=1 + func_cl_dashl "$2" + set x "$@" "$lib" + shift + ;; + -l*) + func_cl_dashl "${1#-l}" + set x "$@" "$lib" + shift + ;; + -L) + eat=1 + func_cl_dashL "$2" + ;; + -L*) + func_cl_dashL "${1#-L}" + ;; + -static) + shared=false + ;; + -Wl,*) + arg=${1#-Wl,} + save_ifs="$IFS"; IFS=',' + for flag in $arg; do + IFS="$save_ifs" + linker_opts="$linker_opts $flag" + done + IFS="$save_ifs" + ;; + -Xlinker) + eat=1 + linker_opts="$linker_opts $2" + ;; + -*) + set x "$@" "$1" + shift + ;; + *.cc | *.CC | *.cxx | *.CXX | *.[cC]++) + func_file_conv "$1" + set x "$@" -Tp"$file" + shift + ;; + *.c | *.cpp | *.CPP | *.lib | *.LIB | *.Lib | *.OBJ | *.obj | *.[oO]) + func_file_conv "$1" mingw + set x "$@" "$file" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift + done + if test -n "$linker_opts"; then + linker_opts="-link$linker_opts" + fi + exec "$@" $linker_opts + exit 1 +} + +eat= + +case $1 in + '') + echo "$0: No command. Try '$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: compile [--help] [--version] PROGRAM [ARGS] + +Wrapper for compilers which do not understand '-c -o'. +Remove '-o dest.o' from ARGS, run PROGRAM with the remaining +arguments, and rename the output as expected. + +If you are trying to build a whole package this is not the +right script to run: please start by reading the file 'INSTALL'. + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "compile $scriptversion" + exit $? + ;; + cl | *[/\\]cl | cl.exe | *[/\\]cl.exe | \ + icl | *[/\\]icl | icl.exe | *[/\\]icl.exe ) + func_cl_wrapper "$@" # Doesn't return... + ;; +esac + +ofile= +cfile= + +for arg +do + if test -n "$eat"; then + eat= + else + case $1 in + -o) + # configure might choose to run compile as 'compile cc -o foo foo.c'. + # So we strip '-o arg' only if arg is an object. + eat=1 + case $2 in + *.o | *.obj) + ofile=$2 + ;; + *) + set x "$@" -o "$2" + shift + ;; + esac + ;; + *.c) + cfile=$1 + set x "$@" "$1" + shift + ;; + *) + set x "$@" "$1" + shift + ;; + esac + fi + shift +done + +if test -z "$ofile" || test -z "$cfile"; then + # If no '-o' option was seen then we might have been invoked from a + # pattern rule where we don't need one. That is ok -- this is a + # normal compilation that the losing compiler can handle. If no + # '.c' file was seen then we are probably linking. That is also + # ok. + exec "$@" +fi + +# Name of file we expect compiler to create. +cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'` + +# Create the lock directory. +# Note: use '[/\\:.-]' here to ensure that we don't use the same name +# that we are using for the .o file. Also, base the name on the expected +# object file name, since that is what matters with a parallel build. +lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d +while true; do + if mkdir "$lockdir" >/dev/null 2>&1; then + break + fi + sleep 1 +done +# FIXME: race condition here if user kills between mkdir and trap. +trap "rmdir '$lockdir'; exit 1" 1 2 15 + +# Run the compile. +"$@" +ret=$? + +if test -f "$cofile"; then + test "$cofile" = "$ofile" || mv "$cofile" "$ofile" +elif test -f "${cofile}bj"; then + test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile" +fi + +rmdir "$lockdir" +exit $ret + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'before-save-hook 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC0" +# time-stamp-end: "; # UTC" +# End: diff --git a/libs/libpng-src/config.guess b/libs/libpng-src/config.guess index da8331460..256083a70 100755 --- a/libs/libpng-src/config.guess +++ b/libs/libpng-src/config.guess @@ -1,14 +1,12 @@ #! /bin/sh # Attempt to guess a canonical system name. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 -# Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2009-04-27' +timestamp='2018-03-08' # This file 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 +# 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 @@ -17,26 +15,22 @@ timestamp='2009-04-27' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - - -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). # -# This script attempts to guess a canonical system name similar to -# config.sub. If it succeeds, it prints the system name on stdout, and -# exits with 0. Otherwise, it exits with 1. +# Originally written by Per Bothner; maintained since 2000 by Ben Elliston. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess +# +# Please send patches to . + me=`echo "$0" | sed -e 's,.*/,,'` @@ -45,7 +39,7 @@ Usage: $0 [OPTION] Output the configuration name of the system \`$me' is run on. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -56,8 +50,7 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -114,9 +107,9 @@ trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; dummy=$tmp/dummy ; tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; case $CC_FOR_BUILD,$HOST_CC,$CC in - ,,) echo "int x;" > $dummy.c ; + ,,) echo "int x;" > "$dummy.c" ; for c in cc gcc c89 c99 ; do - if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then CC_FOR_BUILD="$c"; break ; fi ; done ; @@ -139,12 +132,40 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown +case "$UNAME_SYSTEM" in +Linux|GNU|GNU/*) + # If the system lacks a compiler, then just pick glibc. + # We could probably try harder. + LIBC=gnu + + eval "$set_cc_for_build" + cat <<-EOF > "$dummy.c" + #include + #if defined(__UCLIBC__) + LIBC=uclibc + #elif defined(__dietlibc__) + LIBC=dietlibc + #else + LIBC=gnu + #endif + EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`" + + # If ldd exists, use it to detect musl libc. + if command -v ldd >/dev/null && \ + ldd --version 2>&1 | grep -q ^musl + then + LIBC=musl + fi + ;; +esac + # Note: order is significant - the case branches are not exclusive. -case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in +case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -154,23 +175,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # Note: NetBSD doesn't particularly care about the vendor # portion of the name. We always set it to "unknown". sysctl="sysctl -n hw.machine_arch" - UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ - /usr/sbin/$sysctl 2>/dev/null || echo unknown)` - case "${UNAME_MACHINE_ARCH}" in + UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \ + "/sbin/$sysctl" 2>/dev/null || \ + "/usr/sbin/$sysctl" 2>/dev/null || \ + echo unknown)` + case "$UNAME_MACHINE_ARCH" in armeb) machine=armeb-unknown ;; arm*) machine=arm-unknown ;; sh3el) machine=shl-unknown ;; sh3eb) machine=sh-unknown ;; sh5el) machine=sh5le-unknown ;; - *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + earmv*) + arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'` + endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'` + machine="${arch}${endian}"-unknown + ;; + *) machine="$UNAME_MACHINE_ARCH"-unknown ;; esac # The Operating System including object format, if it has switched - # to ELF recently, or will in the future. - case "${UNAME_MACHINE_ARCH}" in + # to ELF recently (or will in the future) and ABI. + case "$UNAME_MACHINE_ARCH" in + earm*) + os=netbsdelf + ;; arm*|i386|m68k|ns32k|sh3*|sparc|vax) - eval $set_cc_for_build + eval "$set_cc_for_build" if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -180,7 +211,14 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd + ;; + esac + # Determine ABI tags. + case "$UNAME_MACHINE_ARCH" in + earm*) + expr='s/^earmv[0-9]/-eabi/;s/eb$//' + abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"` ;; esac # The OS release @@ -188,42 +226,62 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # thus, need a distinct triplet. However, they do not need # kernel version information, so it can be replaced with a # suitable tag, in the style of linux-gnu. - case "${UNAME_VERSION}" in + case "$UNAME_VERSION" in Debian*) release='-gnu' ;; *) - release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2` ;; esac # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: # contains redundant information, the shorter form: # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. - echo "${machine}-${os}${release}" + echo "$machine-${os}${release}${abi}" + exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE" exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` - echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" + exit ;; + *:LibertyBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" + exit ;; + *:MidnightBSD:*:*) + echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE" exit ;; *:ekkoBSD:*:*) - echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE" exit ;; *:SolidBSD:*:*) - echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE" exit ;; macppc:MirBSD:*:*) - echo powerpc-unknown-mirbsd${UNAME_RELEASE} + echo powerpc-unknown-mirbsd"$UNAME_RELEASE" exit ;; *:MirBSD:*:*) - echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE" exit ;; + *:Sortix:*:*) + echo "$UNAME_MACHINE"-unknown-sortix + exit ;; + *:Redox:*:*) + echo "$UNAME_MACHINE"-unknown-redox + exit ;; + mips:OSF1:*.*) + echo mips-dec-osf1 + exit ;; alpha:OSF1:*:*) case $UNAME_RELEASE in *4.0) UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on @@ -233,60 +291,54 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` case "$ALPHA_CPU_TYPE" in "EV4 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV4.5 (21064)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "LCA4 (21066/21068)") - UNAME_MACHINE="alpha" ;; + UNAME_MACHINE=alpha ;; "EV5 (21164)") - UNAME_MACHINE="alphaev5" ;; + UNAME_MACHINE=alphaev5 ;; "EV5.6 (21164A)") - UNAME_MACHINE="alphaev56" ;; + UNAME_MACHINE=alphaev56 ;; "EV5.6 (21164PC)") - UNAME_MACHINE="alphapca56" ;; + UNAME_MACHINE=alphapca56 ;; "EV5.7 (21164PC)") - UNAME_MACHINE="alphapca57" ;; + UNAME_MACHINE=alphapca57 ;; "EV6 (21264)") - UNAME_MACHINE="alphaev6" ;; + UNAME_MACHINE=alphaev6 ;; "EV6.7 (21264A)") - UNAME_MACHINE="alphaev67" ;; + UNAME_MACHINE=alphaev67 ;; "EV6.8CB (21264C)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8AL (21264B)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.8CX (21264D)") - UNAME_MACHINE="alphaev68" ;; + UNAME_MACHINE=alphaev68 ;; "EV6.9A (21264/EV69A)") - UNAME_MACHINE="alphaev69" ;; + UNAME_MACHINE=alphaev69 ;; "EV7 (21364)") - UNAME_MACHINE="alphaev7" ;; + UNAME_MACHINE=alphaev7 ;; "EV7.9 (21364A)") - UNAME_MACHINE="alphaev79" ;; + UNAME_MACHINE=alphaev79 ;; esac # A Pn.n version is a patched version. # A Vn.n version is a released version. # A Tn.n version is a released field test version. # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. - echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit ;; - Alpha\ *:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # Should we change UNAME_MACHINE based on the output of uname instead - # of the specific Alpha model? - echo alpha-pc-interix - exit ;; - 21064:Windows_NT:50:3) - echo alpha-dec-winnt3.5 - exit ;; + echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`" + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Amiga*:UNIX_System_V:4.0:*) echo m68k-unknown-sysv4 exit ;; *:[Aa]miga[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-amigaos + echo "$UNAME_MACHINE"-unknown-amigaos exit ;; *:[Mm]orph[Oo][Ss]:*:*) - echo ${UNAME_MACHINE}-unknown-morphos + echo "$UNAME_MACHINE"-unknown-morphos exit ;; *:OS/390:*:*) echo i370-ibm-openedition @@ -295,12 +347,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo s390-ibm-zvmoe exit ;; *:OS400:*:*) - echo powerpc-ibm-os400 + echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) - echo arm-acorn-riscix${UNAME_RELEASE} + echo arm-acorn-riscix"$UNAME_RELEASE" exit ;; - arm:riscos:*:*|arm:RISCOS:*:*) + arm*:riscos:*:*|arm*:RISCOS:*:*) echo arm-unknown-riscos exit ;; SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) @@ -325,35 +377,38 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in sparc) echo sparc-icl-nx7; exit ;; esac ;; s390x:SunOS:*:*) - echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" exit ;; sun4H:SunOS:5.*:*) - echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) - echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`" + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux"$UNAME_RELEASE" exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - eval $set_cc_for_build - SUN_ARCH="i386" + eval "$set_cc_for_build" + SUN_ARCH=i386 # If there is a compiler, see if it is configured for 64-bit objects. # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. # This test works for both compilers. - if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ - (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ grep IS_64BIT_ARCH >/dev/null then - SUN_ARCH="x86_64" + SUN_ARCH=x86_64 fi fi - echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize # SunOS6. Hard to guess exactly what SunOS6 will be like, but # it's likely to be more like Solaris than SunOS4. - echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; sun4*:SunOS:*:*) case "`/usr/bin/arch -k`" in @@ -362,25 +417,25 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in ;; esac # Japanese Language versions have a version number like `4.1.3-JL'. - echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`" exit ;; sun3*:SunOS:*:*) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" exit ;; sun*:*:4.2BSD:*) UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` - test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3 case "`/bin/arch`" in sun3) - echo m68k-sun-sunos${UNAME_RELEASE} + echo m68k-sun-sunos"$UNAME_RELEASE" ;; sun4) - echo sparc-sun-sunos${UNAME_RELEASE} + echo sparc-sun-sunos"$UNAME_RELEASE" ;; esac exit ;; aushp:SunOS:*:*) - echo sparc-auspex-sunos${UNAME_RELEASE} + echo sparc-auspex-sunos"$UNAME_RELEASE" exit ;; # The situation for MiNT is a little confusing. The machine name # can be virtually everything (everything which is not @@ -391,44 +446,44 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + echo m68k-atari-mint"$UNAME_RELEASE" + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint"$UNAME_RELEASE" exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; + echo m68k-milan-mint"$UNAME_RELEASE" + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; + echo m68k-hades-mint"$UNAME_RELEASE" + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; + echo m68k-unknown-mint"$UNAME_RELEASE" + exit ;; m68k:machten:*:*) - echo m68k-apple-machten${UNAME_RELEASE} + echo m68k-apple-machten"$UNAME_RELEASE" exit ;; powerpc:machten:*:*) - echo powerpc-apple-machten${UNAME_RELEASE} + echo powerpc-apple-machten"$UNAME_RELEASE" exit ;; RISC*:Mach:*:*) echo mips-dec-mach_bsd4.3 exit ;; RISC*:ULTRIX:*:*) - echo mips-dec-ultrix${UNAME_RELEASE} + echo mips-dec-ultrix"$UNAME_RELEASE" exit ;; VAX*:ULTRIX*:*:*) - echo vax-dec-ultrix${UNAME_RELEASE} + echo vax-dec-ultrix"$UNAME_RELEASE" exit ;; 2020:CLIX:*:* | 2430:CLIX:*:*) - echo clipper-intergraph-clix${UNAME_RELEASE} + echo clipper-intergraph-clix"$UNAME_RELEASE" exit ;; mips:*:*:UMIPS | mips:*:*:RISCos) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #ifdef __cplusplus #include /* for printf() prototype */ int main (int argc, char *argv[]) { @@ -437,23 +492,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in #endif #if defined (host_mips) && defined (MIPSEB) #if defined (SYSTYPE_SYSV) - printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_SVR4) - printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0); #endif #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) - printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0); #endif #endif exit (-1); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && - dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && - SYSTEM_NAME=`$dummy $dummyarg` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && + dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`"$dummy" "$dummyarg"` && { echo "$SYSTEM_NAME"; exit; } - echo mips-mips-riscos${UNAME_RELEASE} + echo mips-mips-riscos"$UNAME_RELEASE" exit ;; Motorola:PowerMAX_OS:*:*) echo powerpc-motorola-powermax @@ -477,21 +532,21 @@ EOF echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` - if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ] then - if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ - [ ${TARGET_BINARY_INTERFACE}x = x ] + if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \ + [ "$TARGET_BINARY_INTERFACE"x = x ] then - echo m88k-dg-dgux${UNAME_RELEASE} + echo m88k-dg-dgux"$UNAME_RELEASE" else - echo m88k-dg-dguxbcs${UNAME_RELEASE} + echo m88k-dg-dguxbcs"$UNAME_RELEASE" fi else - echo i586-dg-dgux${UNAME_RELEASE} + echo i586-dg-dgux"$UNAME_RELEASE" fi - exit ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; @@ -506,7 +561,7 @@ EOF echo m68k-tektronix-bsd exit ;; *:IRIX*:*:*) - echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`" exit ;; ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id @@ -518,14 +573,14 @@ EOF if [ -x /usr/bin/oslevel ] ; then IBM_REV=`/usr/bin/oslevel` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV" exit ;; *:AIX:2:3) if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include main() @@ -536,7 +591,7 @@ EOF exit(0); } EOF - if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` then echo "$SYSTEM_NAME" else @@ -548,28 +603,29 @@ EOF echo rs6000-ibm-aix3.2 fi exit ;; - *:AIX:*:[456]) + *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` - if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 else IBM_ARCH=powerpc fi - if [ -x /usr/bin/oslevel ] ; then - IBM_REV=`/usr/bin/oslevel` + if [ -x /usr/bin/lslpp ] ; then + IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc | + awk -F: '{ print $3 }' | sed s/[0-9]*$/0/` else - IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + IBM_REV="$UNAME_VERSION.$UNAME_RELEASE" fi - echo ${IBM_ARCH}-ibm-aix${IBM_REV} + echo "$IBM_ARCH"-ibm-aix"$IBM_REV" exit ;; *:AIX:*:*) echo rs6000-ibm-aix exit ;; - ibmrt:4.4BSD:*|romp-ibm:BSD:*) + ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*) echo romp-ibm-bsd4.4 exit ;; ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and - echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to exit ;; # report: romp-ibm BSD 4.3 *:BOSX:*:*) echo rs6000-bull-bosx @@ -584,67 +640,67 @@ EOF echo m68k-hp-bsd4.4 exit ;; 9000/[34678]??:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - case "${UNAME_MACHINE}" in - 9000/31? ) HP_ARCH=m68000 ;; - 9000/[34]?? ) HP_ARCH=m68k ;; + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + case "$UNAME_MACHINE" in + 9000/31?) HP_ARCH=m68000 ;; + 9000/[34]??) HP_ARCH=m68k ;; 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; - '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "$sc_cpu_version" in + 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0 + 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "$sc_kernel_bits" in + 32) HP_ARCH=hppa2.0n ;; + 64) HP_ARCH=hppa2.0w ;; + '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20 + esac ;; + esac fi - if [ "${HP_ARCH}" = "" ]; then - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + if [ "$HP_ARCH" = "" ]; then + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF - (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"` test -z "$HP_ARCH" && HP_ARCH=hppa fi ;; esac - if [ ${HP_ARCH} = "hppa2.0w" ] + if [ "$HP_ARCH" = hppa2.0w ] then - eval $set_cc_for_build + eval "$set_cc_for_build" # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler @@ -655,23 +711,23 @@ EOF # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess # => hppa64-hp-hpux11.23 - if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep __LP64__ >/dev/null + if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ then - HP_ARCH="hppa2.0w" + HP_ARCH=hppa2.0w else - HP_ARCH="hppa64" + HP_ARCH=hppa64 fi fi - echo ${HP_ARCH}-hp-hpux${HPUX_REV} + echo "$HP_ARCH"-hp-hpux"$HPUX_REV" exit ;; ia64:HP-UX:*:*) - HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` - echo ia64-hp-hpux${HPUX_REV} + HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux"$HPUX_REV" exit ;; 3050*:HI-UX:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" #include int main () @@ -696,11 +752,11 @@ EOF exit (0); } EOF - $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` && { echo "$SYSTEM_NAME"; exit; } echo unknown-hitachi-hiuxwe2 exit ;; - 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*) echo hppa1.1-hp-bsd exit ;; 9000/8??:4.3bsd:*:*) @@ -709,7 +765,7 @@ EOF *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) echo hppa1.0-hp-mpeix exit ;; - hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*) echo hppa1.1-hp-osf exit ;; hp8??:OSF1:*:*) @@ -717,9 +773,9 @@ EOF exit ;; i*86:OSF1:*:*) if [ -x /usr/sbin/sysversion ] ; then - echo ${UNAME_MACHINE}-unknown-osf1mk + echo "$UNAME_MACHINE"-unknown-osf1mk else - echo ${UNAME_MACHINE}-unknown-osf1 + echo "$UNAME_MACHINE"-unknown-osf1 fi exit ;; parisc*:Lites*:*:*) @@ -727,215 +783,126 @@ EOF exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit ;; + exit ;; CRAY*Y-MP:*:*:*) - echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*[A-Z]90:*:*:*) - echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ -e 's/\.[^.]*$/.X/' exit ;; CRAY*TS:*:*:*) - echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*T3E:*:*:*) - echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; CRAY*SV1:*:*:*) - echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; *:UNICOS/mp:*:*) - echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/' exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) - FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz` + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'` + FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) - echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE" exit ;; sparc*:BSD/OS:*:*) - echo sparc-unknown-bsdi${UNAME_RELEASE} + echo sparc-unknown-bsdi"$UNAME_RELEASE" exit ;; *:BSD/OS:*:*) - echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE" exit ;; *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case "$UNAME_PROCESSOR" in amd64) - echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; - *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=x86_64 ;; + i386) + UNAME_PROCESSOR=i586 ;; esac + echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; i*:CYGWIN*:*) - echo ${UNAME_MACHINE}-pc-cygwin + echo "$UNAME_MACHINE"-pc-cygwin + exit ;; + *:MINGW64*:*) + echo "$UNAME_MACHINE"-pc-mingw64 exit ;; *:MINGW*:*) - echo ${UNAME_MACHINE}-pc-mingw32 + echo "$UNAME_MACHINE"-pc-mingw32 exit ;; - i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + *:MSYS*:*) + echo "$UNAME_MACHINE"-pc-msys exit ;; i*:PW*:*) - echo ${UNAME_MACHINE}-pc-pw32 + echo "$UNAME_MACHINE"-pc-pw32 exit ;; - *:Interix*:[3456]*) - case ${UNAME_MACHINE} in + *:Interix*:*) + case "$UNAME_MACHINE" in x86) - echo i586-pc-interix${UNAME_RELEASE} + echo i586-pc-interix"$UNAME_RELEASE" exit ;; - EM64T | authenticamd | genuineintel) - echo x86_64-unknown-interix${UNAME_RELEASE} + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix"$UNAME_RELEASE" exit ;; IA64) - echo ia64-unknown-interix${UNAME_RELEASE} + echo ia64-unknown-interix"$UNAME_RELEASE" exit ;; esac ;; - [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) - echo i${UNAME_MACHINE}-pc-mks - exit ;; - i*:Windows_NT*:* | Pentium*:Windows_NT*:*) - # How do we know it's Interix rather than the generic POSIX subsystem? - # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we - # UNAME_MACHINE based on the output of uname instead of i386? - echo i586-pc-interix - exit ;; i*:UWIN*:*) - echo ${UNAME_MACHINE}-pc-uwin + echo "$UNAME_MACHINE"-pc-uwin exit ;; amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) echo x86_64-unknown-cygwin exit ;; - p*:CYGWIN*:*) - echo powerpcle-unknown-cygwin - exit ;; prep*:SunOS:5.*:*) - echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`" exit ;; *:GNU:*:*) # the GNU system - echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`" exit ;; *:GNU/*:*:*) # other systems with GNU libc and userland - echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC" exit ;; i*86:Minix:*:*) - echo ${UNAME_MACHINE}-pc-minix + echo "$UNAME_MACHINE"-pc-minix exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - fi + aarch64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - avr32*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - ia64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in @@ -946,106 +913,144 @@ EOF EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null - if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi - echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC=gnulibc1 ; fi + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arc:Linux:*:* | arceb:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + arm*:Linux:*:*) + eval "$set_cc_for_build" + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi + else + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + cris:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + crisv32:Linux:*:*) + echo "$UNAME_MACHINE"-axis-linux-"$LIBC" + exit ;; + e2k:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + frv:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + hexagon:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + i*86:Linux:*:*) + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" + exit ;; + ia64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + k1om:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m32r*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + m68*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval "$set_cc_for_build" + sed 's/^ //' << EOF > "$dummy.c" + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`" + test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; } + ;; + mips64el:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + openrisc*:Linux:*:*) + echo or1k-unknown-linux-"$LIBC" + exit ;; + or32:Linux:*:* | or1k*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; padre:Linux:*:*) - echo sparc-unknown-linux-gnu + echo sparc-unknown-linux-"$LIBC" + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-"$LIBC" exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in - PA7*) echo hppa1.1-unknown-linux-gnu ;; - PA8*) echo hppa2.0-unknown-linux-gnu ;; - *) echo hppa-unknown-linux-gnu ;; + PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;; + PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;; + *) echo hppa-unknown-linux-"$LIBC" ;; esac exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-"$LIBC" + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-"$LIBC" + exit ;; + ppc64le:Linux:*:*) + echo powerpc64le-unknown-linux-"$LIBC" + exit ;; + ppcle:Linux:*:*) + echo powerpcle-unknown-linux-"$LIBC" + exit ;; + riscv32:Linux:*:* | riscv64:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; s390:Linux:*:* | s390x:Linux:*:*) - echo ${UNAME_MACHINE}-ibm-linux + echo "$UNAME_MACHINE"-ibm-linux-"$LIBC" exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sh*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; sparc:Linux:*:* | sparc64:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" + exit ;; + tile*:Linux:*:*) + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; vax:Linux:*:*) - echo ${UNAME_MACHINE}-dec-linux-gnu + echo "$UNAME_MACHINE"-dec-linux-"$LIBC" exit ;; x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu + echo "$UNAME_MACHINE"-pc-linux-"$LIBC" exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^LIBC/{ - s: ::g - p - }'`" - test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit - } - test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } - ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both @@ -1053,54 +1058,54 @@ EOF echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. - echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + # Use sysv4.2uw... so that sysv4* matches it. + echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION" exit ;; i*86:OS/2:*:*) # If we were able to find `uname', then EMX Unix compatibility # is probably installed. - echo ${UNAME_MACHINE}-pc-os2-emx + echo "$UNAME_MACHINE"-pc-os2-emx exit ;; i*86:XTS-300:*:STOP) - echo ${UNAME_MACHINE}-unknown-stop + echo "$UNAME_MACHINE"-unknown-stop exit ;; i*86:atheos:*:*) - echo ${UNAME_MACHINE}-unknown-atheos + echo "$UNAME_MACHINE"-unknown-atheos exit ;; i*86:syllable:*:*) - echo ${UNAME_MACHINE}-pc-syllable + echo "$UNAME_MACHINE"-pc-syllable exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) - echo i386-unknown-lynxos${UNAME_RELEASE} + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos"$UNAME_RELEASE" exit ;; i*86:*DOS:*:*) - echo ${UNAME_MACHINE}-pc-msdosdjgpp + echo "$UNAME_MACHINE"-pc-msdosdjgpp exit ;; - i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) - UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + i*86:*:4.*:*) + UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'` if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then - echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL" fi exit ;; i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; *Pent*|*Celeron) UNAME_MACHINE=i686 ;; esac - echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}" exit ;; i*86:*:3.2:*) if test -f /usr/options/cb.name; then UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 @@ -1110,20 +1115,20 @@ EOF && UNAME_MACHINE=i686 (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ && UNAME_MACHINE=i686 - echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL" else - echo ${UNAME_MACHINE}-pc-sysv32 + echo "$UNAME_MACHINE"-pc-sysv32 fi exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i586. + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. # Note: whatever this is, it MUST be the same as what config.sub - # prints for the "djgpp" host, or else GDB configury will decide that + # prints for the "djgpp" host, or else GDB configure will decide that # this is a cross-build. echo i586-pc-msdosdjgpp - exit ;; + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; @@ -1132,9 +1137,9 @@ EOF exit ;; i860:*:4.*:*) # i860-SVR4 if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then - echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4 else # Add other i860-SVR4 vendors below as they are discovered. - echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4 fi exit ;; mini*:CTIX:SYS*5:*) @@ -1154,39 +1159,39 @@ EOF test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; NCR*:*:4.2:* | MPRAS*:*:4.2:*) OS_REL='.3' test -r /etc/.relid \ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + && { echo i486-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ - && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) - echo m68k-unknown-lynxos${UNAME_RELEASE} + echo m68k-unknown-lynxos"$UNAME_RELEASE" exit ;; mc68030:UNIX_System_V:4.*:*) echo m68k-atari-sysv4 exit ;; TSUNAMI:LynxOS:2.*:*) - echo sparc-unknown-lynxos${UNAME_RELEASE} + echo sparc-unknown-lynxos"$UNAME_RELEASE" exit ;; rs6000:LynxOS:2.*:*) - echo rs6000-unknown-lynxos${UNAME_RELEASE} + echo rs6000-unknown-lynxos"$UNAME_RELEASE" exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) - echo powerpc-unknown-lynxos${UNAME_RELEASE} + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos"$UNAME_RELEASE" exit ;; SM[BE]S:UNIX_SV:*:*) - echo mips-dde-sysv${UNAME_RELEASE} + echo mips-dde-sysv"$UNAME_RELEASE" exit ;; RM*:ReliantUNIX-*:*:*) echo mips-sni-sysv4 @@ -1197,15 +1202,15 @@ EOF *:SINIX-*:*:*) if uname -p 2>/dev/null >/dev/null ; then UNAME_MACHINE=`(uname -p) 2>/dev/null` - echo ${UNAME_MACHINE}-sni-sysv4 + echo "$UNAME_MACHINE"-sni-sysv4 else echo ns32k-sni-sysv fi exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm @@ -1217,25 +1222,25 @@ EOF exit ;; i*86:VOS:*:*) # From Paul.Green@stratus.com. - echo ${UNAME_MACHINE}-stratus-vos + echo "$UNAME_MACHINE"-stratus-vos exit ;; *:VOS:*:*) # From Paul.Green@stratus.com. echo hppa1.1-stratus-vos exit ;; mc68*:A/UX:*:*) - echo m68k-apple-aux${UNAME_RELEASE} + echo m68k-apple-aux"$UNAME_RELEASE" exit ;; news*:NEWS-OS:6*:*) echo mips-sony-newsos6 exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv"$UNAME_RELEASE" else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv"$UNAME_RELEASE" fi - exit ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; @@ -1248,53 +1253,97 @@ EOF BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) - echo sx4-nec-superux${UNAME_RELEASE} + echo sx4-nec-superux"$UNAME_RELEASE" exit ;; SX-5:SUPER-UX:*:*) - echo sx5-nec-superux${UNAME_RELEASE} + echo sx5-nec-superux"$UNAME_RELEASE" exit ;; SX-6:SUPER-UX:*:*) - echo sx6-nec-superux${UNAME_RELEASE} + echo sx6-nec-superux"$UNAME_RELEASE" exit ;; SX-7:SUPER-UX:*:*) - echo sx7-nec-superux${UNAME_RELEASE} + echo sx7-nec-superux"$UNAME_RELEASE" exit ;; SX-8:SUPER-UX:*:*) - echo sx8-nec-superux${UNAME_RELEASE} + echo sx8-nec-superux"$UNAME_RELEASE" exit ;; SX-8R:SUPER-UX:*:*) - echo sx8r-nec-superux${UNAME_RELEASE} + echo sx8r-nec-superux"$UNAME_RELEASE" + exit ;; + SX-ACE:SUPER-UX:*:*) + echo sxace-nec-superux"$UNAME_RELEASE" exit ;; Power*:Rhapsody:*:*) - echo powerpc-apple-rhapsody${UNAME_RELEASE} + echo powerpc-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Rhapsody:*:*) - echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE" exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - case $UNAME_PROCESSOR in - unknown) UNAME_PROCESSOR=powerpc ;; - esac - echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + eval "$set_cc_for_build" + if test "$UNAME_PROCESSOR" = unknown ; then + UNAME_PROCESSOR=powerpc + fi + if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then + if [ "$CC_FOR_BUILD" != no_compiler_found ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + case $UNAME_PROCESSOR in + i386) UNAME_PROCESSOR=x86_64 ;; + powerpc) UNAME_PROCESSOR=powerpc64 ;; + esac + fi + # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc + if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \ + (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_PPC >/dev/null + then + UNAME_PROCESSOR=powerpc + fi + fi + elif test "$UNAME_PROCESSOR" = i386 ; then + # Avoid executing cc on OS X 10.9, as it ships with a stub + # that puts up a graphical alert prompting to install + # developer tools. Any system running Mac OS X 10.7 or + # later (Darwin 11 and later) is required to have a 64-bit + # processor. This is not true of the ARM version of Darwin + # that Apple uses in portable devices. + UNAME_PROCESSOR=x86_64 + fi + echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE" exit ;; *:procnto*:*:* | *:QNX:[0123456789]*:*) UNAME_PROCESSOR=`uname -p` - if test "$UNAME_PROCESSOR" = "x86"; then + if test "$UNAME_PROCESSOR" = x86; then UNAME_PROCESSOR=i386 UNAME_MACHINE=pc fi - echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE" exit ;; *:QNX:*:4*) echo i386-pc-qnx exit ;; - NSE-?:NONSTOP_KERNEL:*:*) - echo nse-tandem-nsk${UNAME_RELEASE} + NEO-*:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk"$UNAME_RELEASE" exit ;; - NSR-?:NONSTOP_KERNEL:*:*) - echo nsr-tandem-nsk${UNAME_RELEASE} + NSE-*:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSR-*:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSV-*:NONSTOP_KERNEL:*:*) + echo nsv-tandem-nsk"$UNAME_RELEASE" + exit ;; + NSX-*:NONSTOP_KERNEL:*:*) + echo nsx-tandem-nsk"$UNAME_RELEASE" exit ;; *:NonStop-UX:*:*) echo mips-compaq-nonstopux @@ -1303,18 +1352,18 @@ EOF echo bs2000-siemens-sysv exit ;; DS/*:UNIX_System_V:*:*) - echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE" exit ;; *:Plan9:*:*) # "uname -m" is not consistent, so use $cputype instead. 386 # is converted to i386 for consistency with other x86 # operating systems. - if test "$cputype" = "386"; then + if test "$cputype" = 386; then UNAME_MACHINE=i386 else UNAME_MACHINE="$cputype" fi - echo ${UNAME_MACHINE}-unknown-plan9 + echo "$UNAME_MACHINE"-unknown-plan9 exit ;; *:TOPS-10:*:*) echo pdp10-unknown-tops10 @@ -1335,14 +1384,14 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux"$UNAME_RELEASE" exit ;; *:DragonFly:*:*) - echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`" exit ;; *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` - case "${UNAME_MACHINE}" in + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "$UNAME_MACHINE" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; V*) echo vax-dec-vms ; exit ;; @@ -1351,182 +1400,48 @@ EOF echo i386-pc-xenix exit ;; i*86:skyos:*:*) - echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`" exit ;; i*86:rdos:*:*) - echo ${UNAME_MACHINE}-pc-rdos + echo "$UNAME_MACHINE"-pc-rdos exit ;; i*86:AROS:*:*) - echo ${UNAME_MACHINE}-pc-aros + echo "$UNAME_MACHINE"-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo "$UNAME_MACHINE"-unknown-esx + exit ;; + amd64:Isilon\ OneFS:*:*) + echo x86_64-unknown-onefs exit ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 +echo "$0: unable to guess system type" >&2 -eval $set_cc_for_build -cat >$dummy.c < -# include -#endif -main () -{ -#if defined (sony) -#if defined (MIPSEB) - /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, - I don't know.... */ - printf ("mips-sony-bsd\n"); exit (0); -#else -#include - printf ("m68k-sony-newsos%s\n", -#ifdef NEWSOS4 - "4" -#else - "" -#endif - ); exit (0); -#endif -#endif +case "$UNAME_MACHINE:$UNAME_SYSTEM" in + mips:Linux | mips64:Linux) + # If we got here on MIPS GNU/Linux, output extra information. + cat >&2 </dev/null`; - if (version < 4) - printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); - else - printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); - exit (0); -#endif - -#if defined (MULTIMAX) || defined (n16) -#if defined (UMAXV) - printf ("ns32k-encore-sysv\n"); exit (0); -#else -#if defined (CMU) - printf ("ns32k-encore-mach\n"); exit (0); -#else - printf ("ns32k-encore-bsd\n"); exit (0); -#endif -#endif -#endif - -#if defined (__386BSD__) - printf ("i386-pc-bsd\n"); exit (0); -#endif - -#if defined (sequent) -#if defined (i386) - printf ("i386-sequent-dynix\n"); exit (0); -#endif -#if defined (ns32000) - printf ("ns32k-sequent-dynix\n"); exit (0); -#endif -#endif - -#if defined (_SEQUENT_) - struct utsname un; - - uname(&un); - - if (strncmp(un.version, "V2", 2) == 0) { - printf ("i386-sequent-ptx2\n"); exit (0); - } - if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ - printf ("i386-sequent-ptx1\n"); exit (0); - } - printf ("i386-sequent-ptx\n"); exit (0); - -#endif - -#if defined (vax) -# if !defined (ultrix) -# include -# if defined (BSD) -# if BSD == 43 - printf ("vax-dec-bsd4.3\n"); exit (0); -# else -# if BSD == 199006 - printf ("vax-dec-bsd4.3reno\n"); exit (0); -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# endif -# else - printf ("vax-dec-bsd\n"); exit (0); -# endif -# else - printf ("vax-dec-ultrix\n"); exit (0); -# endif -#endif - -#if defined (alliant) && defined (i860) - printf ("i860-alliant-bsd\n"); exit (0); -#endif - - exit (1); -} +NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize +the system type. Please install a C compiler and try again. EOF - -$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && - { echo "$SYSTEM_NAME"; exit; } - -# Apollos put the system type in the environment. - -test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } - -# Convex versions that predate uname can use getsysinfo(1) - -if [ -x /usr/convex/getsysinfo ] -then - case `getsysinfo -f cpu_type` in - c1*) - echo c1-convex-bsd - exit ;; - c2*) - if getsysinfo -f scalar_acc - then echo c32-convex-bsd - else echo c2-convex-bsd - fi - exit ;; - c34*) - echo c34-convex-bsd - exit ;; - c38*) - echo c38-convex-bsd - exit ;; - c4*) - echo c4-convex-bsd - exit ;; - esac -fi + ;; +esac cat >&2 < in order to provide the needed -information to handle your system. +If $0 has already been updated, send the following data and any +information you think might be pertinent to config-patches@gnu.org to +provide the necessary information to handle your system. config.guess timestamp = $timestamp @@ -1545,16 +1460,16 @@ hostinfo = `(hostinfo) 2>/dev/null` /usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` -UNAME_MACHINE = ${UNAME_MACHINE} -UNAME_RELEASE = ${UNAME_RELEASE} -UNAME_SYSTEM = ${UNAME_SYSTEM} -UNAME_VERSION = ${UNAME_VERSION} +UNAME_MACHINE = "$UNAME_MACHINE" +UNAME_RELEASE = "$UNAME_RELEASE" +UNAME_SYSTEM = "$UNAME_SYSTEM" +UNAME_VERSION = "$UNAME_VERSION" EOF exit 1 # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/libs/libpng-src/config.h.in b/libs/libpng-src/config.h.in index fb2349568..2931048bf 100644 --- a/libs/libpng-src/config.h.in +++ b/libs/libpng-src/config.h.in @@ -3,6 +3,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the `feenableexcept' function. */ +#undef HAVE_FEENABLEEXCEPT + /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H @@ -12,15 +15,9 @@ /* Define to 1 if you have the `z' library (-lz). */ #undef HAVE_LIBZ -/* Define to 1 if you have the header file. */ -#undef HAVE_MALLOC_H - /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H -/* Define to 1 if you have the `memset' function. */ -#undef HAVE_MEMSET - /* Define to 1 if you have the `pow' function. */ #undef HAVE_POW @@ -45,8 +42,7 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ +/* Define to the sub-directory where libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ @@ -70,6 +66,36 @@ /* Define to the version of this package. */ #undef PACKAGE_VERSION +/* Turn on ARM Neon optimizations at run-time */ +#undef PNG_ARM_NEON_API_SUPPORTED + +/* Check for ARM Neon support at run-time */ +#undef PNG_ARM_NEON_CHECK_SUPPORTED + +/* Enable ARM Neon optimizations */ +#undef PNG_ARM_NEON_OPT + +/* Enable Intel SSE optimizations */ +#undef PNG_INTEL_SSE_OPT + +/* Turn on MIPS MSA optimizations at run-time */ +#undef PNG_MIPS_MSA_API_SUPPORTED + +/* Check for MIPS MSA support at run-time */ +#undef PNG_MIPS_MSA_CHECK_SUPPORTED + +/* Enable MIPS MSA optimizations */ +#undef PNG_MIPS_MSA_OPT + +/* Turn on POWERPC VSX optimizations at run-time */ +#undef PNG_POWERPC_VSX_API_SUPPORTED + +/* Check for POWERPC VSX support at run-time */ +#undef PNG_POWERPC_VSX_CHECK_SUPPORTED + +/* Enable POWERPC VSX optimizations */ +#undef PNG_POWERPC_VSX_OPT + /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS @@ -82,5 +108,19 @@ /* Define to empty if `const' does not conform to ANSI C. */ #undef const +/* Define to the equivalent of the C99 'restrict' keyword, or to + nothing if this is not supported. Do not define if restrict is + supported directly. */ +#undef restrict +/* Work around a bug in Sun C++: it does not support _Restrict or + __restrict__, even though the corresponding Sun C compiler ends up with + "#define restrict _Restrict" or "#define restrict __restrict__" in the + previous line. Perhaps some future version of Sun C++ will work with + restrict; if so, hopefully it defines __RESTRICT like Sun C does. */ +#if defined __SUNPRO_CC && !defined __RESTRICT +# define _Restrict +# define __restrict__ +#endif + /* Define to `unsigned int' if does not define. */ #undef size_t diff --git a/libs/libpng-src/config.sub b/libs/libpng-src/config.sub index a39437d01..9ccf09a7a 100755 --- a/libs/libpng-src/config.sub +++ b/libs/libpng-src/config.sub @@ -1,44 +1,40 @@ #! /bin/sh # Configuration validation subroutine script. -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 -# Free Software Foundation, Inc. +# Copyright 1992-2018 Free Software Foundation, Inc. -timestamp='2009-04-17' +timestamp='2018-03-08' -# This file is (in principle) common to ALL GNU software. -# The presence of a machine in this file suggests that SOME GNU software -# can handle that machine. It does not imply ALL GNU software can. -# -# This file 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 +# This file 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. +# 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, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. +# the same distribution terms that you use for the rest of that +# program. This Exception is an additional permission under section 7 +# of the GNU General Public License, version 3 ("GPLv3"). -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# Please send patches to . # # Configuration subroutine to validate and canonicalize a configuration type. # Supply the specified configuration type as an argument. # If it is invalid, we print an error message on stderr and exit with code 1. # Otherwise, we print the canonical config type on stdout and succeed. +# You can get the latest version of this script from: +# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub + # This file is supposed to be the same for all GNU packages # and recognize all the CPU types, system types and aliases # that are meaningful with *any* GNU software. @@ -57,12 +53,11 @@ timestamp='2009-04-17' me=`echo "$0" | sed -e 's,.*/,,'` usage="\ -Usage: $0 [OPTION] CPU-MFR-OPSYS - $0 [OPTION] ALIAS +Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS Canonicalize a configuration name. -Operation modes: +Options: -h, --help print this help, then exit -t, --time-stamp print date of last modification, then exit -v, --version print version number, then exit @@ -72,8 +67,7 @@ Report bugs and patches to ." version="\ GNU config.sub ($timestamp) -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +Copyright 1992-2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -100,7 +94,7 @@ while test $# -gt 0 ; do *local*) # First pass through any local machine types. - echo $1 + echo "$1" exit ;; * ) @@ -118,19 +112,24 @@ esac # Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). # Here we must recognize all the valid KERNEL-OS combinations. -maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +maybe_os=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` case $maybe_os in - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ - uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ - kopensolaris*-gnu* | \ + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \ + kopensolaris*-gnu* | cloudabi*-eabi* | \ storm-chaos* | os2-emx* | rtmk-nova*) os=-$maybe_os - basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + android-linux) + os=-linux-android + basic_machine=`echo "$1" | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown ;; *) - basic_machine=`echo $1 | sed 's/-[^-]*$//'` - if [ $basic_machine != $1 ] - then os=`echo $1 | sed 's/.*-/-/'` + basic_machine=`echo "$1" | sed 's/-[^-]*$//'` + if [ "$basic_machine" != "$1" ] + then os=`echo "$1" | sed 's/.*-/-/'` else os=; fi ;; esac @@ -149,10 +148,13 @@ case $os in -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ - -apple | -axis | -knuth | -cray) + -apple | -axis | -knuth | -cray | -microblaze*) os= basic_machine=$1 ;; + -bluegene*) + os=-cnk + ;; -sim | -cisco | -oki | -wec | -winbond) os= basic_machine=$1 @@ -167,62 +169,65 @@ case $os in os=-chorusos basic_machine=$1 ;; - -chorusrdb) - os=-chorusrdb + -chorusrdb) + os=-chorusrdb basic_machine=$1 - ;; + ;; -hiux*) os=-hiuxwe2 ;; -sco6) os=-sco5v6 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5) os=-sco3.2v5 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco4) os=-sco3.2v4 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2.[4-9]*) os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco3.2v[4-9]*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco5v6*) # Don't forget version if it is 3.2v4 or newer. - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -sco*) os=-sco3.2v2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -udk*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -isc) os=-isc2.2 - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` ;; -clix*) basic_machine=clipper-intergraph ;; -isc*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*178) + os=-lynxos178 + ;; + -lynx*5) + os=-lynxos5 ;; -lynx*) os=-lynxos ;; -ptx*) - basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` - ;; - -windowsnt*) - os=`echo $os | sed -e 's/windowsnt/winnt/'` + basic_machine=`echo "$1" | sed -e 's/86-.*/86-sequent/'` ;; -psos*) os=-psos @@ -239,20 +244,29 @@ case $basic_machine in # Some are omitted here because they have special meanings below. 1750a | 580 \ | a29k \ + | aarch64 | aarch64_be \ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ | am33_2.0 \ - | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | arc | arceb \ + | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \ + | avr | avr32 \ + | ba \ + | be32 | be64 \ | bfin \ - | c4x | clipper \ + | c4x | c8051 | clipper \ | d10v | d30v | dlx | dsp16xx \ - | fido | fr30 | frv \ + | e2k | epiphany \ + | fido | fr30 | frv | ft32 \ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ - | i370 | i860 | i960 | ia64 \ + | hexagon \ + | i370 | i860 | i960 | ia16 | ia64 \ | ip2k | iq2000 \ + | k1om \ + | le32 | le64 \ | lm32 \ | m32c | m32r | m32rle | m68000 | m68k | m88k \ - | maxq | mb | microblaze | mcore | mep | metag \ + | maxq | mb | microblaze | microblazeel | mcore | mep | metag \ | mips | mipsbe | mipseb | mipsel | mipsle \ | mips16 \ | mips64 | mips64el \ @@ -266,45 +280,80 @@ case $basic_machine in | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ + | mipsr5900 | mipsr5900el \ | mipstx39 | mipstx39el \ | mn10200 | mn10300 \ | moxie \ | mt \ | msp430 \ - | nios | nios2 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 | nios2eb | nios2el \ | ns16k | ns32k \ - | or32 \ - | pdp10 | pdp11 | pj | pjl \ - | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | open8 | or1k | or1knd | or32 \ + | pdp10 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pru \ | pyramid \ + | riscv32 | riscv64 \ + | rl78 | rx \ | score \ - | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | sh64 | sh64le \ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ - | spu | strongarm \ - | tahoe | thumb | tic4x | tic80 | tron \ - | v850 | v850e \ - | we32k \ - | x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | visium \ + | wasm32 \ + | x86 | xc16x | xstormy16 | xtensa \ | z8k | z80) basic_machine=$basic_machine-unknown ;; - m6811 | m68hc11 | m6812 | m68hc12) - # Motorola 68HC11/12. + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + leon|leon[3-9]) + basic_machine=sparc-$basic_machine + ;; + m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip) basic_machine=$basic_machine-unknown os=-none ;; - m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65) ;; ms1) basic_machine=mt-unknown ;; + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + xgate) + basic_machine=$basic_machine-unknown + os=-none + ;; + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + # We use `pc' rather than `unknown' # because (1) that's what they normally are, and # (2) the word "unknown" tends to confuse beginning users. @@ -313,31 +362,38 @@ case $basic_machine in ;; # Object if more than one company name word. *-*-*) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; # Recognize the basic CPU types with company name. 580-* \ | a29k-* \ + | aarch64-* | aarch64_be-* \ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ - | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ | avr-* | avr32-* \ + | ba-* \ + | be32-* | be64-* \ | bfin-* | bs2000-* \ - | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ - | clipper-* | craynv-* | cydra-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | c8051-* | clipper-* | craynv-* | cydra-* \ | d10v-* | d30v-* | dlx-* \ - | elxsi-* \ + | e2k-* | elxsi-* \ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | h8300-* | h8500-* \ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ - | i*86-* | i860-* | i960-* | ia64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia16-* | ia64-* \ | ip2k-* | iq2000-* \ + | k1om-* \ + | le32-* | le64-* \ | lm32-* \ | m32c-* | m32r-* | m32rle-* \ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \ + | microblaze-* | microblazeel-* \ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | mips16-* \ | mips64-* | mips64el-* \ @@ -351,32 +407,45 @@ case $basic_machine in | mips64vr5900-* | mips64vr5900el-* \ | mipsisa32-* | mipsisa32el-* \ | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa32r6-* | mipsisa32r6el-* \ | mipsisa64-* | mipsisa64el-* \ | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64r6-* | mipsisa64r6el-* \ | mipsisa64sb1-* | mipsisa64sb1el-* \ | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipsr5900-* | mipsr5900el-* \ | mipstx39-* | mipstx39el-* \ | mmix-* \ | mt-* \ | msp430-* \ - | nios-* | nios2-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* | nios2eb-* | nios2el-* \ | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | or1k*-* \ | orion-* \ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ - | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pru-* \ | pyramid-* \ - | romp-* | rs6000-* \ + | riscv32-* | riscv64-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | sparclite-* \ - | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ - | tahoe-* | thumb-* \ - | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* | tile-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ | tron-* \ - | v850-* | v850e-* | vax-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | visium-* \ + | wasm32-* \ | we32k-* \ - | x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ | xstormy16-* | xtensa*-* \ | ymp-* \ | z8k-* | z80-*) @@ -388,7 +457,7 @@ case $basic_machine in # Recognize the various machine names and aliases which stand # for a CPU type and a company and sometimes even an OS. 386bsd) - basic_machine=i386-unknown + basic_machine=i386-pc os=-bsd ;; 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) @@ -401,7 +470,7 @@ case $basic_machine in basic_machine=a29k-amd os=-udi ;; - abacus) + abacus) basic_machine=abacus-unknown ;; adobe68k) @@ -422,7 +491,7 @@ case $basic_machine in basic_machine=x86_64-pc ;; amd64-*) - basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; amdahl) basic_machine=580-amdahl @@ -451,6 +520,9 @@ case $basic_machine in basic_machine=i386-pc os=-aros ;; + asmjs) + basic_machine=asmjs-unknown + ;; aux) basic_machine=m68k-apple os=-aux @@ -464,14 +536,27 @@ case $basic_machine in os=-linux ;; blackfin-*) - basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; c90) basic_machine=c90-cray os=-unicos ;; - cegcc) + cegcc) basic_machine=arm-unknown os=-cegcc ;; @@ -503,7 +588,7 @@ case $basic_machine in basic_machine=craynv-cray os=-unicosmp ;; - cr16) + cr16 | cr16-*) basic_machine=cr16-unknown os=-elf ;; @@ -554,10 +639,18 @@ case $basic_machine in basic_machine=rs6000-bull os=-bosx ;; - dpx2* | dpx2*-bull) + dpx2*) basic_machine=m68k-bull os=-sysv3 ;; + e500v[12]) + basic_machine=powerpc-unknown + os=$os"spe" + ;; + e500v[12]-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` + os=$os"spe" + ;; ebmon29k) basic_machine=a29k-amd os=-ebmon @@ -647,9 +740,6 @@ case $basic_machine in hp9k8[0-9][0-9] | hp8[0-9][0-9]) basic_machine=hppa1.0-hp ;; - hppa-next) - os=-nextstep3 - ;; hppaosf) basic_machine=hppa1.1-hp os=-osf @@ -661,28 +751,27 @@ case $basic_machine in i370-ibm* | ibm*) basic_machine=i370-ibm ;; -# I'm not sure what "Sysv32" means. Should this be sysv3.2? i*86v32) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv32 ;; i*86v4*) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv4 ;; i*86v) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-sysv ;; i*86sol2) - basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'` os=-solaris2 ;; i386mach) basic_machine=i386-mach os=-mach ;; - i386-vsta | vsta) + vsta) basic_machine=i386-unknown os=-vsta ;; @@ -700,17 +789,17 @@ case $basic_machine in basic_machine=m68k-isi os=-sysv ;; + leon-*|leon[3-9]-*) + basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'` + ;; m68knommu) basic_machine=m68k-unknown os=-linux ;; m68knommu-*) - basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; - m88k-omron*) - basic_machine=m88k-omron - ;; magnum | m3230) basic_machine=mips-mips os=-sysv @@ -719,8 +808,15 @@ case $basic_machine in basic_machine=ns32k-utek os=-sysv ;; + microblaze*) + basic_machine=microblaze-xilinx + ;; + mingw64) + basic_machine=x86_64-pc + os=-mingw64 + ;; mingw32) - basic_machine=i386-pc + basic_machine=i686-pc os=-mingw32 ;; mingw32ce) @@ -735,10 +831,10 @@ case $basic_machine in os=-mint ;; mips3*-*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'` ;; mips3*) - basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown ;; monitor) basic_machine=m68k-rom68k @@ -748,17 +844,29 @@ case $basic_machine in basic_machine=powerpc-unknown os=-morphos ;; + moxiebox) + basic_machine=moxie-unknown + os=-moxiebox + ;; msdos) basic_machine=i386-pc os=-msdos ;; ms1-*) - basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i686-pc + os=-msys ;; mvs) basic_machine=i370-ibm os=-mvs ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; ncr3000) basic_machine=i486-ncr os=-sysv4 @@ -787,7 +895,7 @@ case $basic_machine in basic_machine=v70-nec os=-sysv ;; - next | m*-next ) + next | m*-next) basic_machine=m68k-next case $os in -nextstep* ) @@ -823,9 +931,21 @@ case $basic_machine in np1) basic_machine=np1-gould ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; nsr-tandem) basic_machine=nsr-tandem ;; + nsv-tandem) + basic_machine=nsv-tandem + ;; + nsx-tandem) + basic_machine=nsx-tandem + ;; op50n-* | op60c-*) basic_machine=hppa1.1-oki os=-proelf @@ -858,7 +978,7 @@ case $basic_machine in os=-linux ;; parisc-*) - basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'` os=-linux ;; pbd) @@ -874,7 +994,7 @@ case $basic_machine in basic_machine=i386-pc ;; pc98-*) - basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium | p5 | k5 | k6 | nexgen | viac3) basic_machine=i586-pc @@ -889,41 +1009,42 @@ case $basic_machine in basic_machine=i786-pc ;; pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) - basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumpro-* | p6-* | 6x86-* | athlon-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) - basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pentium4-*) - basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; pn) basic_machine=pn-gould ;; power) basic_machine=power-ibm ;; - ppc) basic_machine=powerpc-unknown + ppc | ppcbe) basic_machine=powerpc-unknown ;; - ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppcle | powerpclittle | ppc-le | powerpc-little) + ppcle | powerpclittle) basic_machine=powerpcle-unknown ;; ppcle-* | powerpclittle-*) - basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ppc64) basic_machine=powerpc64-unknown ;; - ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; - ppc64le | powerpc64little | ppc64-le | powerpc64-little) + ppc64le | powerpc64little) basic_machine=powerpc64le-unknown ;; ppc64le-* | powerpc64little-*) - basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'` ;; ps2) basic_machine=i386-ibm @@ -932,7 +1053,11 @@ case $basic_machine in basic_machine=i586-unknown os=-pw32 ;; - rdos) + rdos | rdos64) + basic_machine=x86_64-pc + os=-rdos + ;; + rdos32) basic_machine=i386-pc os=-rdos ;; @@ -973,17 +1098,10 @@ case $basic_machine in sequent) basic_machine=i386-sequent ;; - sh) - basic_machine=sh-hitachi - os=-hms - ;; sh5el) basic_machine=sh5le-unknown ;; - sh64) - basic_machine=sh64-unknown - ;; - sparclite-wrs | simso-wrs) + simso-wrs) basic_machine=sparclite-wrs os=-vxworks ;; @@ -1001,6 +1119,9 @@ case $basic_machine in basic_machine=i860-stratus os=-sysv4 ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'` + ;; sun2) basic_machine=m68000-sun ;; @@ -1057,20 +1178,8 @@ case $basic_machine in basic_machine=t90-cray os=-unicos ;; - tic54x | c54x*) - basic_machine=tic54x-unknown - os=-coff - ;; - tic55x | c55x*) - basic_machine=tic55x-unknown - os=-coff - ;; - tic6x | c6x*) - basic_machine=tic6x-unknown - os=-coff - ;; tile*) - basic_machine=tile-unknown + basic_machine=$basic_machine-unknown os=-linux-gnu ;; tx39) @@ -1133,6 +1242,9 @@ case $basic_machine in basic_machine=hppa1.1-winbond os=-proelf ;; + x64) + basic_machine=x86_64-pc + ;; xbox) basic_machine=i686-pc os=-mingw32 @@ -1140,18 +1252,13 @@ case $basic_machine in xps | xps100) basic_machine=xps100-honeywell ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'` + ;; ymp) basic_machine=ymp-cray os=-unicos ;; - z8k-*-coff) - basic_machine=z8k-unknown - os=-sim - ;; - z80-*-coff) - basic_machine=z80-unknown - os=-sim - ;; none) basic_machine=none-none os=-none @@ -1180,10 +1287,6 @@ case $basic_machine in vax) basic_machine=vax-dec ;; - pdp10) - # there are many clones, so DEC is not a safe bet - basic_machine=pdp10-unknown - ;; pdp11) basic_machine=pdp11-dec ;; @@ -1193,9 +1296,6 @@ case $basic_machine in sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) basic_machine=sh-unknown ;; - sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) - basic_machine=sparc-sun - ;; cydra) basic_machine=cydra-cydrome ;; @@ -1215,7 +1315,7 @@ case $basic_machine in # Make sure to match an already-canonicalized machine name. ;; *) - echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2 exit 1 ;; esac @@ -1223,10 +1323,10 @@ esac # Here we canonicalize certain aliases for manufacturers. case $basic_machine in *-digital*) - basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'` ;; *-commodore*) - basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'` ;; *) ;; @@ -1237,53 +1337,60 @@ esac if [ x"$os" != x"" ] then case $os in - # First match some system type aliases - # that might get confused with valid system types. + # First match some system type aliases that might get confused + # with valid system types. # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; -solaris1 | -solaris1.*) os=`echo $os | sed -e 's|solaris1|sunos4|'` ;; -solaris) os=-solaris2 ;; - -svr4*) - os=-sysv4 - ;; -unixware*) os=-sysv4.2uw ;; -gnu/linux*) os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` ;; - # First accept the basic system types. + # es1800 is here to avoid being matched by es* (a different OS) + -es1800*) + os=-ose + ;; + # Now accept the basic system types. # The portable systems comes first. - # Each alternative MUST END IN A *, to match a version number. + # Each alternative MUST end in a * to match a version number. # -sysv* is not here because it comes later, after sysvr4. -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ - | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ - | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ - | -kopensolaris* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* | -plan9* \ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ - | -aos* | -aros* \ + | -aos* | -aros* | -cloudabi* | -sortix* \ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ - | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ - | -openbsd* | -solidbsd* \ + | -hiux* | -knetbsd* | -mirbsd* | -netbsd* \ + | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \ | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ - | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ - | -chorusos* | -chorusrdb* | -cegcc* \ - | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ - | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \ - | -uxpv* | -beos* | -mpeix* | -udk* \ - | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* | -hcos* \ + | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-musl* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* \ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ - | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -morphos* | -superux* | -rtmk* | -windiss* \ | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ - | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \ + | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox* | -bme* \ + | -midnightbsd*) # Remember, each alternative MUST END IN *, to match a version number. ;; -qnx*) @@ -1300,12 +1407,12 @@ case $os in -nto*) os=`echo $os | sed -e 's|nto|nto-qnx|'` ;; - -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ - | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + -sim | -xray | -os68k* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* \ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) ;; -mac*) - os=`echo $os | sed -e 's|mac|macos|'` + os=`echo "$os" | sed -e 's|mac|macos|'` ;; -linux-dietlibc) os=-linux-dietlibc @@ -1314,26 +1421,20 @@ case $os in os=`echo $os | sed -e 's|linux|linux-gnu|'` ;; -sunos5*) - os=`echo $os | sed -e 's|sunos5|solaris2|'` + os=`echo "$os" | sed -e 's|sunos5|solaris2|'` ;; -sunos6*) - os=`echo $os | sed -e 's|sunos6|solaris3|'` + os=`echo "$os" | sed -e 's|sunos6|solaris3|'` ;; -opened*) os=-openedition ;; - -os400*) + -os400*) os=-os400 ;; -wince*) os=-wince ;; - -osfrose*) - os=-osfrose - ;; - -osf*) - os=-osf - ;; -utek*) os=-bsd ;; @@ -1358,7 +1459,7 @@ case $os in -nova*) os=-rtmk-nova ;; - -ns2 ) + -ns2) os=-nextstep2 ;; -nsk*) @@ -1371,7 +1472,7 @@ case $os in -sinix*) os=-sysv4 ;; - -tpf*) + -tpf*) os=-tpf ;; -triton*) @@ -1380,7 +1481,7 @@ case $os in -oss*) os=-sysv3 ;; - -svr4) + -svr4*) os=-sysv4 ;; -svr3) @@ -1395,33 +1496,38 @@ case $os in -ose*) os=-ose ;; - -es1800*) - os=-ose - ;; - -xenix) - os=-xenix - ;; -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) os=-mint ;; - -aros*) - os=-aros - ;; - -kaos*) - os=-kaos - ;; -zvmoe) os=-zvmoe ;; -dicos*) os=-dicos ;; + -pikeos*) + # Until real need of OS specific support for + # particular features comes up, bare metal + # configurations are quite functional. + case $basic_machine in + arm*) + os=-eabi + ;; + *) + os=-elf + ;; + esac + ;; + -nacl*) + ;; + -ios) + ;; -none) ;; *) # Get rid of the `-' at the beginning of $os. os=`echo $os | sed 's/[^-]*-//'` - echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2 exit 1 ;; esac @@ -1438,10 +1544,10 @@ else # system, and we'll never get to this point. case $basic_machine in - score-*) + score-*) os=-elf ;; - spu-*) + spu-*) os=-elf ;; *-acorn) @@ -1453,8 +1559,23 @@ case $basic_machine in arm*-semi) os=-aout ;; - c4x-* | tic4x-*) - os=-coff + c4x-* | tic4x-*) + os=-coff + ;; + c8051-*) + os=-elf + ;; + hexagon-*) + os=-elf + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff ;; # This must come before the *-dec entry. pdp10-*) @@ -1474,14 +1595,11 @@ case $basic_machine in ;; m68000-sun) os=-sunos3 - # This also exists in the configure program, but was not the - # default. - # os=-sunos4 ;; m68*-cisco) os=-aout ;; - mep-*) + mep-*) os=-elf ;; mips*-cisco) @@ -1499,16 +1617,16 @@ case $basic_machine in sparc-* | *-sun) os=-sunos4.1.1 ;; + pru-*) + os=-elf + ;; *-be) os=-beos ;; - *-haiku) - os=-haiku - ;; *-ibm) os=-aix ;; - *-knuth) + *-knuth) os=-mmixware ;; *-wec) @@ -1544,7 +1662,7 @@ case $basic_machine in m88k-omron*) os=-luna ;; - *-next ) + *-next) os=-nextstep ;; *-sequent) @@ -1559,9 +1677,6 @@ case $basic_machine in i370-*) os=-mvs ;; - *-next) - os=-nextstep3 - ;; *-gould) os=-sysv ;; @@ -1613,7 +1728,7 @@ case $basic_machine in -sunos*) vendor=sun ;; - -aix*) + -cnk*|-aix*) vendor=ibm ;; -beos*) @@ -1671,15 +1786,15 @@ case $basic_machine in vendor=stratus ;; esac - basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"` ;; esac -echo $basic_machine$os +echo "$basic_machine$os" exit # Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) +# eval: (add-hook 'before-save-hook 'time-stamp) # time-stamp-start: "timestamp='" # time-stamp-format: "%:y-%02m-%02d" # time-stamp-end: "'" diff --git a/libs/libpng-src/configure b/libs/libpng-src/configure index 89657aae0..1b2c46366 100755 --- a/libs/libpng-src/configure +++ b/libs/libpng-src/configure @@ -1,13 +1,11 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for libpng 1.2.46. +# Generated by GNU Autoconf 2.69 for libpng 1.6.37. # # Report bugs to . # # -# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, -# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, -# Inc. +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation @@ -91,6 +89,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -135,6 +134,31 @@ export LANGUAGE # CDPATH. (unset CDPATH) >/dev/null 2>&1 && unset CDPATH +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} if test "x$CONFIG_SHELL" = x; then as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : emulate sh @@ -168,12 +192,21 @@ if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : else exitcode=1; echo positional parameters were not saved. fi -test x\$exitcode = x0 || exit 1" +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 -test \$(( 1 + 1 )) = 2 || exit 1" +test \$(( 1 + 1 )) = 2 || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes else @@ -213,14 +246,25 @@ IFS=$as_save_IFS if test "x$CONFIG_SHELL" != x; then : - # We cannot yet assume a decent shell, so we have to provide a - # neutralization value for shells without unset; and this also - # works around shells that cannot unset nonexistent variables. - BASH_ENV=/dev/null - ENV=/dev/null - (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV - export CONFIG_SHELL - exec "$CONFIG_SHELL" "$as_myself" ${1+"$@"} + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 fi if test x$as_have_required = xno; then : @@ -319,10 +363,18 @@ $as_echo X"$as_dir" | test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p # as_fn_append VAR VALUE # ---------------------- # Append the text in VALUE to the end of the definition contained in VAR. Take @@ -359,19 +411,19 @@ else fi # as_fn_arith -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. +# script with STATUS, using 1 if that was 0. as_fn_error () { - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $1" >&2 + $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -444,6 +496,10 @@ as_cr_alnum=$as_cr_Letters$as_cr_digits chmod +x "$as_me.lineno" || { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec # Don't try to exec as it changes $[0], causing all sort of problems # (the dirname of $[0] is not the place where we might find the # original and so on. Autoconf is especially sensitive to this). @@ -478,16 +534,16 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -499,28 +555,8 @@ else as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -528,161 +564,14 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} -case X$lt_ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` - ;; -esac - -ECHO=${lt_ECHO-echo} -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then - # Yippee, $ECHO works! - : -else - # Restart under the correct shell. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <<_LT_EOF -$* -_LT_EOF - exit 0 -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test -z "$lt_ECHO"; then - if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if { echo_test_string=`eval $cmd`; } 2>/dev/null && - { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null - then - break - fi - done - fi - - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : - else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$ECHO" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - ECHO='print -r' - elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - ECHO='printf %s\n' - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - ECHO="$CONFIG_SHELL $0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - ECHO=echo - fi - fi - fi - fi - fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -lt_ECHO=$ECHO -if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then - lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" -fi - - - test -n "$DJDIR" || exec 7<&0 &1 # Name of the host. -# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, # so uname gets run too. ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` @@ -701,8 +590,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libpng' PACKAGE_TARNAME='libpng' -PACKAGE_VERSION='1.2.46' -PACKAGE_STRING='libpng 1.2.46' +PACKAGE_VERSION='1.6.37' +PACKAGE_STRING='libpng 1.6.37' PACKAGE_BUGREPORT='png-mng-implement@lists.sourceforge.net' PACKAGE_URL='' @@ -746,7 +635,23 @@ ac_includes_default="\ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS -compatlib +PNG_POWERPC_VSX_FALSE +PNG_POWERPC_VSX_TRUE +PNG_INTEL_SSE_FALSE +PNG_INTEL_SSE_TRUE +PNG_MIPS_MSA_FALSE +PNG_MIPS_MSA_TRUE +PNG_ARM_NEON_FALSE +PNG_ARM_NEON_TRUE +DO_INSTALL_LIBPNG_CONFIG_FALSE +DO_INSTALL_LIBPNG_CONFIG_TRUE +DO_INSTALL_LIBPNG_PC_FALSE +DO_INSTALL_LIBPNG_PC_TRUE +DO_INSTALL_LINKS_FALSE +DO_INSTALL_LINKS_TRUE +DO_PNG_PREFIX_FALSE +DO_PNG_PREFIX_TRUE +PNG_PREFIX binconfigs pkgconfigdir PNGLIB_RELEASE @@ -756,26 +661,32 @@ PNGLIB_VERSION SYMBOL_PREFIX HAVE_LD_VERSION_SCRIPT_FALSE HAVE_LD_VERSION_SCRIPT_TRUE -LIBPNG_NO_MMX -LIBPNG_DEFINES +HAVE_SOLARIS_LD_FALSE +HAVE_SOLARIS_LD_TRUE +HAVE_CLOCK_GETTIME_FALSE +HAVE_CLOCK_GETTIME_TRUE LIBOBJS POW_LIB +PNG_COPTS +DFNCPP +LT_SYS_LIBRARY_PATH OTOOL64 OTOOL LIPO NMEDIT DSYMUTIL -lt_ECHO +MANIFEST_TOOL RANLIB +ac_ct_AR AR NM ac_ct_DUMPBIN DUMPBIN LIBTOOL -LN_S OBJDUMP DLLTOOL AS +LN_S CPP LD FGREP @@ -790,13 +701,18 @@ build_os build_vendor build_cpu build +am__fastdepCCAS_FALSE +am__fastdepCCAS_TRUE +CCASDEPMODE +CCASFLAGS +CCAS am__fastdepCC_FALSE am__fastdepCC_TRUE CCDEPMODE +am__nodep AMDEPBACKSLASH AMDEP_FALSE AMDEP_TRUE -am__quote am__include DEPDIR OBJEXT @@ -809,6 +725,10 @@ CC MAINT MAINTAINER_MODE_FALSE MAINTAINER_MODE_TRUE +AM_BACKSLASH +AM_DEFAULT_VERBOSITY +AM_DEFAULT_V +AM_V am__untar am__tar AMTAR @@ -869,10 +789,12 @@ PACKAGE_VERSION PACKAGE_TARNAME PACKAGE_NAME PATH_SEPARATOR -SHELL' +SHELL +am__quote' ac_subst_files='' ac_user_opts=' enable_option_checking +enable_silent_rules enable_maintainer_mode enable_dependency_tracking with_gnu_ld @@ -880,10 +802,22 @@ enable_shared enable_static with_pic enable_fast_install +with_aix_soname +with_sysroot enable_libtool_lock +enable_werror +with_zlib_prefix with_pkgconfigdir with_binconfigs -with_libpng_compat +with_libpng_prefix +enable_unversioned_links +enable_unversioned_libpng_pc +enable_unversioned_libpng_config +enable_hardware_optimizations +enable_arm_neon +enable_mips_msa +enable_intel_sse +enable_powerpc_vsx ' ac_precious_vars='build_alias host_alias @@ -893,7 +827,11 @@ CFLAGS LDFLAGS LIBS CPPFLAGS -CPP' +CCAS +CCASFLAGS +CPP +LT_SYS_LIBRARY_PATH +PNG_COPTS' # Initialize some variables set by options. @@ -956,8 +894,9 @@ do fi case $ac_option in - *=*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; - *) ac_optarg=yes ;; + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; esac # Accept the important Cygnus configure options, so we can diagnose typos. @@ -1002,7 +941,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1028,7 +967,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid feature name: $ac_useropt" + as_fn_error $? "invalid feature name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1232,7 +1171,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1248,7 +1187,7 @@ do ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` # Reject names that are not valid shell variable names. expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && - as_fn_error "invalid package name: $ac_useropt" + as_fn_error $? "invalid package name: $ac_useropt" ac_useropt_orig=$ac_useropt ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` case $ac_user_opts in @@ -1278,8 +1217,8 @@ do | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) x_libraries=$ac_optarg ;; - -*) as_fn_error "unrecognized option: \`$ac_option' -Try \`$0 --help' for more information." + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" ;; *=*) @@ -1287,7 +1226,7 @@ Try \`$0 --help' for more information." # Reject names that are not valid shell variable names. case $ac_envvar in #( '' | [0-9]* | *[!_$as_cr_alnum]* ) - as_fn_error "invalid variable name: \`$ac_envvar'" ;; + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; esac eval $ac_envvar=\$ac_optarg export $ac_envvar ;; @@ -1297,7 +1236,7 @@ Try \`$0 --help' for more information." $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 - : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" ;; esac @@ -1305,13 +1244,13 @@ done if test -n "$ac_prev"; then ac_option=--`echo $ac_prev | sed 's/_/-/g'` - as_fn_error "missing argument to $ac_option" + as_fn_error $? "missing argument to $ac_option" fi if test -n "$ac_unrecognized_opts"; then case $enable_option_checking in no) ;; - fatal) as_fn_error "unrecognized options: $ac_unrecognized_opts" ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; esac fi @@ -1334,7 +1273,7 @@ do [\\/$]* | ?:[\\/]* ) continue;; NONE | '' ) case $ac_var in *prefix ) continue;; esac;; esac - as_fn_error "expected an absolute directory name for --$ac_var: $ac_val" + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" done # There might be people who depend on the old broken behavior: `$host' @@ -1348,8 +1287,6 @@ target=$target_alias if test "x$host_alias" != x; then if test "x$build_alias" = x; then cross_compiling=maybe - $as_echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. - If a cross compiler is detected then cross compile mode will be used." >&2 elif test "x$build_alias" != "x$host_alias"; then cross_compiling=yes fi @@ -1364,9 +1301,9 @@ test "$silent" = yes && exec 6>/dev/null ac_pwd=`pwd` && test -n "$ac_pwd" && ac_ls_di=`ls -di .` && ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || - as_fn_error "working directory cannot be determined" + as_fn_error $? "working directory cannot be determined" test "X$ac_ls_di" = "X$ac_pwd_ls_di" || - as_fn_error "pwd does not report name of working directory" + as_fn_error $? "pwd does not report name of working directory" # Find the source files, if location was not specified. @@ -1405,11 +1342,11 @@ else fi if test ! -r "$srcdir/$ac_unique_file"; then test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." - as_fn_error "cannot find sources ($ac_unique_file) in $srcdir" + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" fi ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" ac_abs_confdir=`( - cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error "$ac_msg" + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" pwd)` # When building in place, set srcdir=. if test "$ac_abs_confdir" = "$ac_pwd"; then @@ -1435,7 +1372,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures libpng 1.2.46 to adapt to many kinds of systems. +\`configure' configures libpng 1.6.37 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1449,7 +1386,7 @@ Configuration: --help=short display options specific to this package --help=recursive display the short help of all the included packages -V, --version display version information and exit - -q, --quiet, --silent do not print \`checking...' messages + -q, --quiet, --silent do not print \`checking ...' messages --cache-file=FILE cache test results in FILE [disabled] -C, --config-cache alias for \`--cache-file=config.cache' -n, --no-create do not create output files @@ -1505,7 +1442,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libpng 1.2.46:";; + short | recursive ) echo "Configuration of libpng 1.6.37:";; esac cat <<\_ACEOF @@ -1513,28 +1450,95 @@ Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] - --enable-maintainer-mode enable make rules and dependencies not useful - (and sometimes confusing) to the casual installer - --disable-dependency-tracking speeds up one-time build - --enable-dependency-tracking do not reject slow dependency extractors + --enable-silent-rules less verbose build output (undo: "make V=1") + --disable-silent-rules verbose build output (undo: "make V=0") + --enable-maintainer-mode + enable make rules and dependencies not useful (and + sometimes confusing) to the casual installer + --enable-dependency-tracking + do not reject slow dependency extractors + --disable-dependency-tracking + speeds up one-time build --enable-shared[=PKGS] build shared libraries [default=yes] --enable-static[=PKGS] build static libraries [default=yes] --enable-fast-install[=PKGS] optimize for fast installation [default=yes] --disable-libtool-lock avoid locking (might break parallel builds) + --enable-werror[=OPT] Pass -Werror or the given argument to the compiler + if it is supported + --enable-unversioned-links + Installed libpng header files are placed in a + versioned subdirectory and installed libpng library + (including DLL) files are versioned. If this option + is enabled unversioned links will be created + pointing to the corresponding installed files. If + you use libpng.pc or libpng-config for all builds + you do not need these links, but if you compile + programs directly they will typically #include + and link with -lpng; in that case you need + the links. The links can be installed manually using + 'make install-header-links' and 'make + install-library-links' and can be removed using the + corresponding uninstall- targets. If you do enable + this option every libpng 'make install' will + recreate the links to point to the just installed + version of libpng. The default is to create the + links; use --disable-unversioned-links to change + this + --enable-unversioned-libpng-pc + Install the configuration file 'libpng.pc' as a link + to the versioned version. This is done by default - + use --disable-unversioned-libpng-pc to change this. + --enable-unversioned-libpng-config + Install the configuration file 'libpng-config' as a + link to the versioned version. This is done by + default - use --disable-unversioned-libpng-config to + change this. + --enable-hardware-optimizations + Enable hardware optimizations: =no/off, yes/on: + --enable-arm-neon Enable ARM NEON optimizations: =no/off, check, api, + yes/on: no/off: disable the optimizations; check: + use internal checking code (deprecated and poorly + supported); api: disable by default, enable by a + call to png_set_option; yes/on: turn on + unconditionally. If not specified: determined by the + compiler. + --enable-mips-msa Enable MIPS MSA optimizations: =no/off, check, api, + yes/on: no/off: disable the optimizations; check: + use internal checking code (deprecated and poorly + supported); api: disable by default, enable by a + call to png_set_option; yes/on: turn on + unconditionally. If not specified: determined by the + compiler. + --enable-intel-sse Enable Intel SSE optimizations: =no/off, yes/on: + no/off: disable the optimizations; yes/on: enable + the optimizations. If not specified: determined by + the compiler. + --enable-powerpc-vsx Enable POWERPC VSX optimizations: =no/off, check, + api, yes/on: no/off: disable the optimizations; + check: use internal checking code api: disable by + default, enable by a call to png_set_option yes/on: + turn on unconditionally. If not specified: + determined by the compiler. Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-gnu-ld assume the C compiler uses GNU ld [default=no] - --with-pic try to use only PIC/non-PIC objects [default=use + --with-pic[=PKGS] try to use only PIC/non-PIC objects [default=use both] - --with-pkgconfigdir Use the specified pkgconfig dir (default is + --with-aix-soname=aix|svr4|both + shared library versioning (aka "SONAME") variant to + provide on AIX, [default=aix]. + --with-sysroot[=DIR] Search for dependent libraries within DIR (or the + compiler's sysroot if not specified). + --with-zlib-prefix prefix that may have been used in installed zlib + --with-pkgconfigdir Use the specified pkgconfig dir (default is libdir/pkgconfig) - --with-binconfigs Generate shell libpng-config scripts as well as + --with-binconfigs Generate shell libpng-config scripts as well as pkg-config data [default=yes] - --with-libpng-compat Generate the obsolete libpng.so library - [default=yes] + --with-libpng-prefix prefix libpng exported function (API) names with the + given value Some influential environment variables: CC C compiler command @@ -1544,7 +1548,13 @@ Some influential environment variables: LIBS libraries to pass to the linker, e.g. -l CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if you have headers in a nonstandard directory + CCAS assembler compiler command (defaults to CC) + CCASFLAGS assembler compiler flags (defaults to CFLAGS) CPP C preprocessor + LT_SYS_LIBRARY_PATH + User-defined run-time library search path. + PNG_COPTS additional flags for the C compiler, use this for options that + would cause configure itself to fail Use these variables to override the choices made by `configure' or to help it to find libraries and programs with nonstandard names/locations. @@ -1612,10 +1622,10 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libpng configure 1.2.46 -generated by GNU Autoconf 2.65 +libpng configure 1.6.37 +generated by GNU Autoconf 2.69 -Copyright (C) 2009 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF @@ -1659,7 +1669,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_compile @@ -1685,7 +1695,7 @@ $as_echo "$ac_try_echo"; } >&5 mv -f conftest.er1 conftest.err fi $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } >/dev/null && { + test $ac_status = 0; } > conftest.i && { test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || test ! -s conftest.err }; then : @@ -1696,7 +1706,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=1 fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_cpp @@ -1728,7 +1738,7 @@ $as_echo "$ac_try_echo"; } >&5 test ! -s conftest.err } && test -s conftest$ac_exeext && { test "$cross_compiling" = yes || - $as_test_x conftest$ac_exeext + test -x conftest$ac_exeext }; then : ac_retval=0 else @@ -1742,7 +1752,7 @@ fi # interfere with the next link command; also delete a directory that is # left behind by Apple's compiler. We do this before executing the actions. rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_link @@ -1756,7 +1766,7 @@ ac_fn_c_check_header_compile () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1774,7 +1784,7 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_compile @@ -1815,7 +1825,7 @@ sed 's/^/| /' conftest.$ac_ext >&5 ac_retval=$ac_status fi rm -rf conftest.dSYM conftest_ipa8_conftest.oo - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno as_fn_set_status $ac_retval } # ac_fn_c_try_run @@ -1828,7 +1838,7 @@ ac_fn_c_check_func () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -1883,103 +1893,10 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_func -# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES -# ------------------------------------------------------- -# Tests whether HEADER exists, giving a warning if it cannot be compiled using -# the include files in INCLUDES and setting the cache variable VAR -# accordingly. -ac_fn_c_check_header_mongrel () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -else - # Is the header compilable? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 -$as_echo_n "checking $2 usability... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$4 -#include <$2> -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_header_compiler=yes -else - ac_header_compiler=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 -$as_echo "$ac_header_compiler" >&6; } - -# Is the header present? -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 -$as_echo_n "checking $2 presence... " >&6; } -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include <$2> -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : - ac_header_preproc=yes -else - ac_header_preproc=no -fi -rm -f conftest.err conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 -$as_echo "$ac_header_preproc" >&6; } - -# So? What about this header? -case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( - yes:no: ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 -$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} - ;; - no:yes:* ) - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 -$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 -$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 -$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 -$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 -$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} -( cat <<\_ASBOX -## ------------------------------------------------------ ## -## Report this to png-mng-implement@lists.sourceforge.net ## -## ------------------------------------------------------ ## -_ASBOX - ) | sed "s/^/$as_me: WARNING: /" >&2 - ;; -esac - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : - $as_echo_n "(cached) " >&6 -else - eval "$3=\$ac_header_compiler" -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } -fi - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} - -} # ac_fn_c_check_header_mongrel - # ac_fn_c_check_type LINENO TYPE VAR INCLUDES # ------------------------------------------- # Tests whether TYPE exists after having included INCLUDES, setting cache @@ -1989,7 +1906,7 @@ ac_fn_c_check_type () as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 $as_echo_n "checking for $2... " >&6; } -if { as_var=$3; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${$3+:} false; then : $as_echo_n "(cached) " >&6 else eval "$3=no" @@ -2030,15 +1947,15 @@ fi eval ac_res=\$$3 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 $as_echo "$ac_res" >&6; } - eval $as_lineno_stack; test "x$as_lineno_stack" = x && { as_lineno=; unset as_lineno;} + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_type cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libpng $as_me 1.2.46, which was -generated by GNU Autoconf 2.65. Invocation command line was +It was created by libpng $as_me 1.6.37, which was +generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -2148,11 +2065,9 @@ trap 'exit_status=$? { echo - cat <<\_ASBOX -## ---------------- ## + $as_echo "## ---------------- ## ## Cache variables. ## -## ---------------- ## -_ASBOX +## ---------------- ##" echo # The following way of writing the cache mishandles newlines in values, ( @@ -2186,11 +2101,9 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; ) echo - cat <<\_ASBOX -## ----------------- ## + $as_echo "## ----------------- ## ## Output variables. ## -## ----------------- ## -_ASBOX +## ----------------- ##" echo for ac_var in $ac_subst_vars do @@ -2203,11 +2116,9 @@ _ASBOX echo if test -n "$ac_subst_files"; then - cat <<\_ASBOX -## ------------------- ## + $as_echo "## ------------------- ## ## File substitutions. ## -## ------------------- ## -_ASBOX +## ------------------- ##" echo for ac_var in $ac_subst_files do @@ -2221,11 +2132,9 @@ _ASBOX fi if test -s confdefs.h; then - cat <<\_ASBOX -## ----------- ## + $as_echo "## ----------- ## ## confdefs.h. ## -## ----------- ## -_ASBOX +## ----------- ##" echo cat confdefs.h echo @@ -2280,7 +2189,12 @@ _ACEOF ac_site_file1=NONE ac_site_file2=NONE if test -n "$CONFIG_SITE"; then - ac_site_file1=$CONFIG_SITE + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac elif test "x$prefix" != xNONE; then ac_site_file1=$prefix/share/config.site ac_site_file2=$prefix/etc/config.site @@ -2295,7 +2209,11 @@ do { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 $as_echo "$as_me: loading site script $ac_site_file" >&6;} sed 's/^/| /' "$ac_site_file" >&5 - . "$ac_site_file" + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } fi done @@ -2371,7 +2289,7 @@ if $ac_cache_corrupted; then $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 $as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} - as_fn_error "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 fi ## -------------------- ## ## Main body of script. ## @@ -2384,20 +2302,34 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -am__api_version='1.11' + + +# libpng does not follow GNU file name conventions (hence 'foreign') +# color-tests requires automake 1.11 or later +# silent-rules requires automake 1.11 or later +# dist-xz requires automake 1.11 or later +# 1.12.2 fixes a security issue in 1.11.2 and 1.12.1 +# 1.13 is required for parallel tests +am__api_version='1.16' ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do - for ac_t in install-sh install.sh shtool; do - if test -f "$ac_dir/$ac_t"; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/$ac_t -c" - break 2 - fi - done + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi done if test -z "$ac_aux_dir"; then - as_fn_error "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 fi # These three variables are undocumented and unsupported, @@ -2426,7 +2358,7 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 $as_echo_n "checking for a BSD-compatible install... " >&6; } if test -z "$INSTALL"; then -if test "${ac_cv_path_install+set}" = set; then : +if ${ac_cv_path_install+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -2446,7 +2378,7 @@ case $as_dir/ in #(( # by default. for ac_prog in ginstall scoinst install; do for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then if test $ac_prog = install && grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then # AIX install. It has an incompatible calling convention. @@ -2504,56 +2436,71 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether build environment is sane" >&5 $as_echo_n "checking whether build environment is sane... " >&6; } -# Just in case -sleep 1 -echo timestamp > conftest.file # Reject unsafe characters in $srcdir or the absolute working directory # name. Accept space and tab only in the latter. am_lf=' ' case `pwd` in *[\\\"\#\$\&\'\`$am_lf]*) - as_fn_error "unsafe absolute working directory name" "$LINENO" 5;; + as_fn_error $? "unsafe absolute working directory name" "$LINENO" 5;; esac case $srcdir in *[\\\"\#\$\&\'\`$am_lf\ \ ]*) - as_fn_error "unsafe srcdir value: \`$srcdir'" "$LINENO" 5;; + as_fn_error $? "unsafe srcdir value: '$srcdir'" "$LINENO" 5;; esac -# Do `set' in a subshell so we don't clobber the current shell's +# Do 'set' in a subshell so we don't clobber the current shell's # arguments. Must try -L first in case configure is actually a # symlink; some systems play weird games with the mod time of symlinks # (eg FreeBSD returns the mod time of the symlink's containing # directory). if ( - set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` - if test "$*" = "X"; then - # -L didn't work. - set X `ls -t "$srcdir/configure" conftest.file` - fi - rm -f conftest.file - if test "$*" != "X $srcdir/configure conftest.file" \ - && test "$*" != "X conftest.file $srcdir/configure"; then - - # If neither matched, then we have a broken ls. This can happen - # if, for instance, CONFIG_SHELL is bash and it inherits a - # broken ls alias from the environment. This has actually - # happened. Such a system could not be considered "sane". - as_fn_error "ls -t appears to fail. Make sure there is not a broken -alias in your environment" "$LINENO" 5 - fi + am_has_slept=no + for am_try in 1 2; do + echo "timestamp, slept: $am_has_slept" > conftest.file + set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t "$srcdir/configure" conftest.file` + fi + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + as_fn_error $? "ls -t appears to fail. Make sure there is not a broken + alias in your environment" "$LINENO" 5 + fi + if test "$2" = conftest.file || test $am_try -eq 2; then + break + fi + # Just in case. + sleep 1 + am_has_slept=yes + done test "$2" = conftest.file ) then # Ok. : else - as_fn_error "newly created file is older than distributed files! + as_fn_error $? "newly created file is older than distributed files! Check your system clock" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } +# If we didn't sleep, we still need to ensure time stamps of config.status and +# generated files are strictly newer. +am_sleep_pid= +if grep 'slept: no' conftest.file >/dev/null 2>&1; then + ( sleep 1 ) & + am_sleep_pid=$! +fi + +rm -f conftest.file + test "$program_prefix" != NONE && program_transform_name="s&^&$program_prefix&;$program_transform_name" # Use a double $ so make ignores it. @@ -2564,8 +2511,8 @@ test "$program_suffix" != NONE && ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` -# expand $ac_aux_dir to an absolute path -am_aux_dir=`cd $ac_aux_dir && pwd` +# Expand $ac_aux_dir to an absolute path. +am_aux_dir=`cd "$ac_aux_dir" && pwd` if test x"${MISSING+set}" != xset; then case $am_aux_dir in @@ -2576,15 +2523,15 @@ if test x"${MISSING+set}" != xset; then esac fi # Use eval to expand $SHELL -if eval "$MISSING --run true"; then - am_missing_run="$MISSING --run " +if eval "$MISSING --is-lightweight"; then + am_missing_run="$MISSING " else am_missing_run= - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`missing' script is too old or missing" >&5 -$as_echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: 'missing' script is too old or missing" >&5 +$as_echo "$as_me: WARNING: 'missing' script is too old or missing" >&2;} fi -if test x"${install_sh}" != xset; then +if test x"${install_sh+set}" != xset; then case $am_aux_dir in *\ * | *\ *) install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;; @@ -2593,17 +2540,17 @@ if test x"${install_sh}" != xset; then esac fi -# Installed binaries are usually stripped using `strip' when the user -# run `make install-strip'. However `strip' might not be the right +# Installed binaries are usually stripped using 'strip' when the user +# run "make install-strip". However 'strip' might not be the right # tool to use in cross-compilation environments, therefore Automake -# will honor the `STRIP' environment variable to overrule this program. +# will honor the 'STRIP' environment variable to overrule this program. if test "$cross_compiling" != no; then if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then : +if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then @@ -2615,7 +2562,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2643,7 +2590,7 @@ if test -z "$ac_cv_prog_STRIP"; then set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then @@ -2655,7 +2602,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2696,7 +2643,7 @@ INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a thread-safe mkdir -p" >&5 $as_echo_n "checking for a thread-safe mkdir -p... " >&6; } if test -z "$MKDIR_P"; then - if test "${ac_cv_path_mkdir+set}" = set; then : + if ${ac_cv_path_mkdir+:} false; then : $as_echo_n "(cached) " >&6 else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -2706,7 +2653,7 @@ do test -z "$as_dir" && as_dir=. for ac_prog in mkdir gmkdir; do for ac_exec_ext in '' $ac_executable_extensions; do - { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; } || continue + as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext" || continue case `"$as_dir/$ac_prog$ac_exec_ext" --version 2>&1` in #( 'mkdir (GNU coreutils) '* | \ 'mkdir (coreutils) '* | \ @@ -2735,19 +2682,13 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR_P" >&5 $as_echo "$MKDIR_P" >&6; } -mkdir_p="$MKDIR_P" -case $mkdir_p in - [\\/$]* | ?:[\\/]*) ;; - */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; -esac - for ac_prog in gawk mawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AWK+set}" = set; then : +if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AWK"; then @@ -2759,7 +2700,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2787,7 +2728,7 @@ done $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF @@ -2795,7 +2736,7 @@ SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; @@ -2823,13 +2764,52 @@ else fi rmdir .tst 2>/dev/null +# Check whether --enable-silent-rules was given. +if test "${enable_silent_rules+set}" = set; then : + enableval=$enable_silent_rules; +fi + +case $enable_silent_rules in # ((( + yes) AM_DEFAULT_VERBOSITY=0;; + no) AM_DEFAULT_VERBOSITY=1;; + *) AM_DEFAULT_VERBOSITY=1;; +esac +am_make=${MAKE-make} +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $am_make supports nested variables" >&5 +$as_echo_n "checking whether $am_make supports nested variables... " >&6; } +if ${am_cv_make_support_nested_variables+:} false; then : + $as_echo_n "(cached) " >&6 +else + if $as_echo 'TRUE=$(BAR$(V)) +BAR0=false +BAR1=true +V=1 +am__doit: + @$(TRUE) +.PHONY: am__doit' | $am_make -f - >/dev/null 2>&1; then + am_cv_make_support_nested_variables=yes +else + am_cv_make_support_nested_variables=no +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_make_support_nested_variables" >&5 +$as_echo "$am_cv_make_support_nested_variables" >&6; } +if test $am_cv_make_support_nested_variables = yes; then + AM_V='$(V)' + AM_DEFAULT_V='$(AM_DEFAULT_VERBOSITY)' +else + AM_V=$AM_DEFAULT_VERBOSITY + AM_DEFAULT_V=$AM_DEFAULT_VERBOSITY +fi +AM_BACKSLASH='\' + if test "`cd $srcdir && pwd`" != "`pwd`"; then # Use -I$(srcdir) only when $(srcdir) != ., so that make's output # is not polluted with repeated "-I." am__isrc=' -I$(srcdir)' # test to see if srcdir already configured if test -f $srcdir/config.status; then - as_fn_error "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 + as_fn_error $? "source directory already configured; run \"make distclean\" there first" "$LINENO" 5 fi fi @@ -2845,7 +2825,7 @@ fi # Define the identity of the package. PACKAGE='libpng' - VERSION='1.2.46' + VERSION='1.6.37' cat >>confdefs.h <<_ACEOF @@ -2873,19 +2853,75 @@ AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} -# We need awk for the "check" target. The system "awk" is bad on -# some platforms. -# Always define AMTAR for backward compatibility. +# For better backward compatibility. To be removed once Automake 1.9.x +# dies out for good. For more background, see: +# +# +mkdir_p='$(MKDIR_P)' -AMTAR=${AMTAR-"${am_missing_run}tar"} +# We need awk for the "check" target (and possibly the TAP driver). The +# system "awk" is bad on some platforms. +# Always define AMTAR for backward compatibility. Yes, it's still used +# in the wild :-( We should find a proper way to deprecate it ... +AMTAR='$${TAR-tar}' -am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -' + +# We'll loop over all known methods to create a tar archive until one works. +_am_tools='gnutar pax cpio none' + +am__tar='$${TAR-tar} chof - "$$tardir"' am__untar='$${TAR-tar} xf -' +# POSIX will say in a future version that running "rm -f" with no argument +# is OK; and we want to be able to make that assumption in our Makefile +# recipes. So use an aggressive probe to check that the usage we want is +# actually supported "in the wild" to an acceptable degree. +# See automake bug#10828. +# To make any issue more visible, cause the running configure to be aborted +# by default if the 'rm' program in use doesn't match our expectations; the +# user can still override this though. +if rm -f && rm -fr && rm -rf; then : OK; else + cat >&2 <<'END' +Oops! + +Your 'rm' program seems unable to run without file operands specified +on the command line, even when the '-f' option is present. This is contrary +to the behaviour of most rm programs out there, and not conforming with +the upcoming POSIX standard: + +Please tell bug-automake@gnu.org about your system, including the value +of your $PATH and any error possibly output before this message. This +can help us improve future automake versions. + +END + if test x"$ACCEPT_INFERIOR_RM_PROGRAM" = x"yes"; then + echo 'Configuration will proceed anyway, since you have set the' >&2 + echo 'ACCEPT_INFERIOR_RM_PROGRAM variable to "yes"' >&2 + echo >&2 + else + cat >&2 <<'END' +Aborting the configuration process, to ensure you take notice of the issue. + +You can download and install GNU coreutils to get an 'rm' implementation +that behaves properly: . + +If you want to complete the configuration process using your problematic +'rm' anyway, export the environment variable ACCEPT_INFERIOR_RM_PROGRAM +to "yes", and re-run configure. + +END + as_fn_error $? "Your 'rm' program is bad, sorry." "$LINENO" 5 + fi +fi + +# The following line causes --disable-maintainer-mode to be the default to +# configure. This is necessary because libpng distributions cannot rely on the +# time stamps of the autotools generated files being correct + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable maintainer-specific portions of Makefiles" >&5 $as_echo_n "checking whether to enable maintainer-specific portions of Makefiles... " >&6; } # Check whether --enable-maintainer-mode was given. @@ -2909,10 +2945,11 @@ fi -PNGLIB_VERSION=1.2.46 + +PNGLIB_VERSION=1.6.37 PNGLIB_MAJOR=1 -PNGLIB_MINOR=2 -PNGLIB_RELEASE=46 +PNGLIB_MINOR=6 +PNGLIB_RELEASE=37 @@ -2920,6 +2957,12 @@ ac_config_headers="$ac_config_headers config.h" # Checks for programs. +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -2930,7 +2973,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -2942,7 +2985,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -2970,7 +3013,7 @@ if test -z "$ac_cv_prog_CC"; then set dummy gcc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -2982,7 +3025,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="gcc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3023,7 +3066,7 @@ if test -z "$CC"; then set dummy ${ac_tool_prefix}cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -3035,7 +3078,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="${ac_tool_prefix}cc" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3063,7 +3106,7 @@ if test -z "$CC"; then set dummy cc; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -3076,7 +3119,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then ac_prog_rejected=yes continue @@ -3122,7 +3165,7 @@ if test -z "$CC"; then set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_CC+set}" = set; then : +if ${ac_cv_prog_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$CC"; then @@ -3134,7 +3177,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_CC="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3166,7 +3209,7 @@ do set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_CC+set}" = set; then : +if ${ac_cv_prog_ac_ct_CC+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_CC"; then @@ -3178,7 +3221,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_CC="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -3220,8 +3263,8 @@ fi test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "no acceptable C compiler found in \$PATH -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } # Provide some information about the compiler. $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 @@ -3335,9 +3378,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -{ as_fn_set_status 77 -as_fn_error "C compiler cannot create executables -See \`config.log' for more details." "$LINENO" 5; }; } +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } @@ -3379,8 +3421,8 @@ done else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of executables: cannot compile and link -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest conftest$ac_cv_exeext { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 @@ -3437,9 +3479,9 @@ $as_echo "$ac_try_echo"; } >&5 else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot run C compiled programs. +as_fn_error $? "cannot run C compiled programs. If you meant to cross compile, use \`--host'. -See \`config.log' for more details." "$LINENO" 5; } +See \`config.log' for more details" "$LINENO" 5; } fi fi fi @@ -3450,7 +3492,7 @@ rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out ac_clean_files=$ac_clean_files_save { $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 $as_echo_n "checking for suffix of object files... " >&6; } -if test "${ac_cv_objext+set}" = set; then : +if ${ac_cv_objext+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3490,8 +3532,8 @@ sed 's/^/| /' conftest.$ac_ext >&5 { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "cannot compute suffix of object files: cannot compile -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } fi rm -f conftest.$ac_cv_objext conftest.$ac_ext fi @@ -3501,7 +3543,7 @@ OBJEXT=$ac_cv_objext ac_objext=$OBJEXT { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 $as_echo_n "checking whether we are using the GNU C compiler... " >&6; } -if test "${ac_cv_c_compiler_gnu+set}" = set; then : +if ${ac_cv_c_compiler_gnu+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -3538,7 +3580,7 @@ ac_test_CFLAGS=${CFLAGS+set} ac_save_CFLAGS=$CFLAGS { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 $as_echo_n "checking whether $CC accepts -g... " >&6; } -if test "${ac_cv_prog_cc_g+set}" = set; then : +if ${ac_cv_prog_cc_g+:} false; then : $as_echo_n "(cached) " >&6 else ac_save_c_werror_flag=$ac_c_werror_flag @@ -3616,7 +3658,7 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 $as_echo_n "checking for $CC option to accept ISO C89... " >&6; } -if test "${ac_cv_prog_cc_c89+set}" = set; then : +if ${ac_cv_prog_cc_c89+:} false; then : $as_echo_n "(cached) " >&6 else ac_cv_prog_cc_c89=no @@ -3625,8 +3667,7 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include #include -#include -#include +struct stat; /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); @@ -3710,49 +3751,108 @@ ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC understands -c and -o together" >&5 +$as_echo_n "checking whether $CC understands -c and -o together... " >&6; } +if ${am_cv_prog_cc_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF + # Make sure it works both with $CC and with simple cc. + # Following AC_PROG_CC_C_O, we do the test twice because some + # compilers refuse to overwrite an existing .o file with -o, + # though they will create one. + am_cv_prog_cc_c_o=yes + for am_i in 1 2; do + if { echo "$as_me:$LINENO: $CC -c conftest.$ac_ext -o conftest2.$ac_objext" >&5 + ($CC -c conftest.$ac_ext -o conftest2.$ac_objext) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } \ + && test -f conftest2.$ac_objext; then + : OK + else + am_cv_prog_cc_c_o=no + break + fi + done + rm -f core conftest* + unset am_i +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_prog_cc_c_o" >&5 +$as_echo "$am_cv_prog_cc_c_o" >&6; } +if test "$am_cv_prog_cc_c_o" != yes; then + # Losing compiler, so override with the script. + # FIXME: It is wrong to rewrite CC. + # But if we don't then we get into trouble of one sort or another. + # A longer-term fix would be to have automake use am__CC in this case, + # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" + CC="$am_aux_dir/compile $CC" +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + DEPDIR="${am__leading_dot}deps" ac_config_commands="$ac_config_commands depfiles" - -am_make=${MAKE-make} -cat > confinc << 'END' +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} supports the include directive" >&5 +$as_echo_n "checking whether ${MAKE-make} supports the include directive... " >&6; } +cat > confinc.mk << 'END' am__doit: - @echo this is the am__doit target + @echo this is the am__doit target >confinc.out .PHONY: am__doit END -# If we don't find an include directive, just comment out the code. -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for style of include used by $am_make" >&5 -$as_echo_n "checking for style of include used by $am_make... " >&6; } am__include="#" am__quote= -_am_result=none -# First try GNU make style include. -echo "include confinc" > confmf -# Ignore all kinds of additional output from `make'. -case `$am_make -s -f confmf 2> /dev/null` in #( -*the\ am__doit\ target*) - am__include=include - am__quote= - _am_result=GNU - ;; -esac -# Now try BSD make style include. -if test "$am__include" = "#"; then - echo '.include "confinc"' > confmf - case `$am_make -s -f confmf 2> /dev/null` in #( - *the\ am__doit\ target*) - am__include=.include - am__quote="\"" - _am_result=BSD +# BSD make does it like this. +echo '.include "confinc.mk" # ignored' > confmf.BSD +# Other make implementations (GNU, Solaris 10, AIX) do it like this. +echo 'include confinc.mk # ignored' > confmf.GNU +_am_result=no +for s in GNU BSD; do + { echo "$as_me:$LINENO: ${MAKE-make} -f confmf.$s && cat confinc.out" >&5 + (${MAKE-make} -f confmf.$s && cat confinc.out) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + case $?:`cat confinc.out 2>/dev/null` in #( + '0:this is the am__doit target') : + case $s in #( + BSD) : + am__include='.include' am__quote='"' ;; #( + *) : + am__include='include' am__quote='' ;; +esac ;; #( + *) : ;; - esac -fi - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $_am_result" >&5 -$as_echo "$_am_result" >&6; } -rm -f confinc confmf +esac + if test "$am__include" != "#"; then + _am_result="yes ($s style)" + break + fi +done +rm -f confinc.* confmf.* +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${_am_result}" >&5 +$as_echo "${_am_result}" >&6; } # Check whether --enable-dependency-tracking was given. if test "${enable_dependency_tracking+set}" = set; then : @@ -3762,6 +3862,7 @@ fi if test "x$enable_dependency_tracking" != xno; then am_depcomp="$ac_aux_dir/depcomp" AMDEPBACKSLASH='\' + am__nodep='_no' fi if test "x$enable_dependency_tracking" != xno; then AMDEP_TRUE= @@ -3777,15 +3878,16 @@ depcc="$CC" am_compiler_list= { $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 $as_echo_n "checking dependency style of $depcc... " >&6; } -if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then : +if ${am_cv_CC_dependencies_compiler_type+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then # We make a subdir and do the tests there. Otherwise we can end up # making bogus files that we don't know about and never remove. For # instance it was reported that on HP-UX the gcc test will end up - # making a dummy file named `D' -- because `-MD' means `put the output - # in D'. + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir mkdir conftest.dir # Copy depcomp to subdir because otherwise we won't find it if we're # using a relative directory. @@ -3819,16 +3921,16 @@ else : > sub/conftest.c for i in 1 2 3 4 5 6; do echo '#include "conftst'$i'.h"' >> sub/conftest.c - # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with - # Solaris 8's {/usr,}/bin/sh. - touch sub/conftst$i.h + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h done echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf - # We check with `-c' and `-o' for the sake of the "dashmstdout" + # We check with '-c' and '-o' for the sake of the "dashmstdout" # mode. It turns out that the SunPro C++ compiler does not properly - # handle `-M -o', and we need to detect this. Also, some Intel - # versions had trouble with output in subdirs + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. am__obj=sub/conftest.${OBJEXT-o} am__minus_obj="-o $am__obj" case $depmode in @@ -3837,16 +3939,16 @@ else test "$am__universal" = false || continue ;; nosideeffect) - # after this tag, mechanisms are not by side-effect, so they'll - # only be used when explicitly requested + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. if test "x$enable_dependency_tracking" = xyes; then continue else break fi ;; - msvisualcpp | msvcmsys) - # This compiler won't grok `-c -o', but also, the minuso test has + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has # not run yet. These depmodes are late enough in the game, and # so weak that their functioning should not be impacted. am__obj=conftest.${OBJEXT-o} @@ -3900,29 +4002,162 @@ else fi +# By default we simply use the C compiler to build assembly code. + +test "${CCAS+set}" = set || CCAS=$CC +test "${CCASFLAGS+set}" = set || CCASFLAGS=$CFLAGS + + + +depcc="$CCAS" am_compiler_list= + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking dependency style of $depcc" >&5 +$as_echo_n "checking dependency style of $depcc... " >&6; } +if ${am_cv_CCAS_dependencies_compiler_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named 'D' -- because '-MD' means "put the output + # in D". + rm -rf conftest.dir + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + # We will build objects and dependencies in a subdirectory because + # it helps to detect inapplicable dependency modes. For instance + # both Tru64's cc and ICC support -MD to output dependencies as a + # side effect of compilation, but ICC will put the dependencies in + # the current directory while Tru64 will put them in the object + # directory. + mkdir sub + + am_cv_CCAS_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + am__universal=false + + + for depmode in $am_compiler_list; do + # Setup a source with many dependencies, because some compilers + # like to wrap large dependency lists on column 80 (with \), and + # we should not choose a depcomp mode which is confused by this. + # + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + : > sub/conftest.c + for i in 1 2 3 4 5 6; do + echo '#include "conftst'$i'.h"' >> sub/conftest.c + # Using ": > sub/conftst$i.h" creates only sub/conftst1.h with + # Solaris 10 /bin/sh. + echo '/* dummy */' > sub/conftst$i.h + done + echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf + + # We check with '-c' and '-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle '-M -o', and we need to detect this. Also, some Intel + # versions had trouble with output in subdirs. + am__obj=sub/conftest.${OBJEXT-o} + am__minus_obj="-o $am__obj" + case $depmode in + gcc) + # This depmode causes a compiler race in universal mode. + test "$am__universal" = false || continue + ;; + nosideeffect) + # After this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested. + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + msvc7 | msvc7msys | msvisualcpp | msvcmsys) + # This compiler won't grok '-c -o', but also, the minuso test has + # not run yet. These depmodes are late enough in the game, and + # so weak that their functioning should not be impacted. + am__obj=conftest.${OBJEXT-o} + am__minus_obj= + ;; + none) break ;; + esac + if depmode=$depmode \ + source=sub/conftest.c object=$am__obj \ + depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ + $SHELL ./depcomp $depcc -c $am__minus_obj sub/conftest.c \ + >/dev/null 2>conftest.err && + grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && + grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && + grep $am__obj sub/conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + # icc doesn't choke on unknown options, it will just issue warnings + # or remarks (even with -Werror). So we grep stderr for any message + # that says an option was ignored or not supported. + # When given -MP, icc 7.0 and 7.1 complain thusly: + # icc: Command line warning: ignoring option '-M'; no argument required + # The diagnosis changed in icc 8.0: + # icc: Command line remark: option '-MP' not supported + if (grep 'ignoring option' conftest.err || + grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else + am_cv_CCAS_dependencies_compiler_type=$depmode + break + fi + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CCAS_dependencies_compiler_type=none +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_CCAS_dependencies_compiler_type" >&5 +$as_echo "$am_cv_CCAS_dependencies_compiler_type" >&6; } +CCASDEPMODE=depmode=$am_cv_CCAS_dependencies_compiler_type + + if + test "x$enable_dependency_tracking" != xno \ + && test "$am_cv_CCAS_dependencies_compiler_type" = gcc3; then + am__fastdepCCAS_TRUE= + am__fastdepCCAS_FALSE='#' +else + am__fastdepCCAS_TRUE='#' + am__fastdepCCAS_FALSE= +fi + + # Make sure we can run config.sub. $SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || - as_fn_error "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 $as_echo_n "checking build system type... " >&6; } -if test "${ac_cv_build+set}" = set; then : +if ${ac_cv_build+:} false; then : $as_echo_n "(cached) " >&6 else ac_build_alias=$build_alias test "x$ac_build_alias" = x && ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` test "x$ac_build_alias" = x && - as_fn_error "cannot guess build type; you must specify one" "$LINENO" 5 + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 $as_echo "$ac_cv_build" >&6; } case $ac_cv_build in *-*-*) ;; -*) as_fn_error "invalid value of canonical build" "$LINENO" 5;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; esac build=$ac_cv_build ac_save_IFS=$IFS; IFS='-' @@ -3940,14 +4175,14 @@ case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 $as_echo_n "checking host system type... " >&6; } -if test "${ac_cv_host+set}" = set; then : +if ${ac_cv_host+:} false; then : $as_echo_n "(cached) " >&6 else if test "x$host_alias" = x; then ac_cv_host=$ac_cv_build else ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || - as_fn_error "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 fi fi @@ -3955,7 +4190,7 @@ fi $as_echo "$ac_cv_host" >&6; } case $ac_cv_host in *-*-*) ;; -*) as_fn_error "invalid value of canonical host" "$LINENO" 5;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; esac host=$ac_cv_host ac_save_IFS=$IFS; IFS='-' @@ -3973,7 +4208,7 @@ case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } -if test "${ac_cv_path_SED+set}" = set; then : +if ${ac_cv_path_SED+:} false; then : $as_echo_n "(cached) " >&6 else ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ @@ -3993,7 +4228,7 @@ do for ac_prog in sed gsed; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue + as_fn_executable_p "$ac_path_SED" || continue # Check for GNU ac_path_SED and select it if it is found. # Check for GNU $ac_path_SED case `"$ac_path_SED" --version 2>&1` in @@ -4028,7 +4263,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_SED"; then - as_fn_error "no acceptable sed could be found in \$PATH" "$LINENO" 5 + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 fi else ac_cv_path_SED=$SED @@ -4055,7 +4290,7 @@ Xsed="$SED -e 1s/^X//" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 $as_echo_n "checking for grep that handles long lines and -e... " >&6; } -if test "${ac_cv_path_GREP+set}" = set; then : +if ${ac_cv_path_GREP+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$GREP"; then @@ -4069,7 +4304,7 @@ do for ac_prog in grep ggrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue + as_fn_executable_p "$ac_path_GREP" || continue # Check for GNU ac_path_GREP and select it if it is found. # Check for GNU $ac_path_GREP case `"$ac_path_GREP" --version 2>&1` in @@ -4104,7 +4339,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_GREP"; then - as_fn_error "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_GREP=$GREP @@ -4118,7 +4353,7 @@ $as_echo "$ac_cv_path_GREP" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 $as_echo_n "checking for egrep... " >&6; } -if test "${ac_cv_path_EGREP+set}" = set; then : +if ${ac_cv_path_EGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 @@ -4135,7 +4370,7 @@ do for ac_prog in egrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue + as_fn_executable_p "$ac_path_EGREP" || continue # Check for GNU ac_path_EGREP and select it if it is found. # Check for GNU $ac_path_EGREP case `"$ac_path_EGREP" --version 2>&1` in @@ -4170,7 +4405,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_EGREP"; then - as_fn_error "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_EGREP=$EGREP @@ -4185,7 +4420,7 @@ $as_echo "$ac_cv_path_EGREP" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 $as_echo_n "checking for fgrep... " >&6; } -if test "${ac_cv_path_FGREP+set}" = set; then : +if ${ac_cv_path_FGREP+:} false; then : $as_echo_n "(cached) " >&6 else if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 @@ -4202,7 +4437,7 @@ do for ac_prog in fgrep; do for ac_exec_ext in '' $ac_executable_extensions; do ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" - { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue + as_fn_executable_p "$ac_path_FGREP" || continue # Check for GNU ac_path_FGREP and select it if it is found. # Check for GNU $ac_path_FGREP case `"$ac_path_FGREP" --version 2>&1` in @@ -4237,7 +4472,7 @@ esac done IFS=$as_save_IFS if test -z "$ac_cv_path_FGREP"; then - as_fn_error "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 fi else ac_cv_path_FGREP=$FGREP @@ -4268,23 +4503,75 @@ test -z "$GREP" && GREP=grep +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case $ECHO in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + # Check whether --with-gnu-ld was given. if test "${with_gnu_ld+set}" = set; then : - withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes + withval=$with_gnu_ld; test no = "$withval" || with_gnu_ld=yes else with_gnu_ld=no fi ac_prog=ld -if test "$GCC" = yes; then +if test yes = "$GCC"; then # Check if gcc -print-prog-name=ld gives a path. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 $as_echo_n "checking for ld used by $CC... " >&6; } case $host in *-*-mingw*) - # gcc leaves a trailing carriage return which upsets mingw + # gcc leaves a trailing carriage return, which upsets mingw ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; *) ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; @@ -4298,7 +4585,7 @@ $as_echo_n "checking for ld used by $CC... " >&6; } while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` done - test -z "$LD" && LD="$ac_prog" + test -z "$LD" && LD=$ac_prog ;; "") # If it fails, then pretend we aren't using GCC. @@ -4309,43 +4596,43 @@ $as_echo_n "checking for ld used by $CC... " >&6; } with_gnu_ld=unknown ;; esac -elif test "$with_gnu_ld" = yes; then +elif test yes = "$with_gnu_ld"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 $as_echo_n "checking for GNU ld... " >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 $as_echo_n "checking for non-GNU ld... " >&6; } fi -if test "${lt_cv_path_LD+set}" = set; then : +if ${lt_cv_path_LD+:} false; then : $as_echo_n "(cached) " >&6 else if test -z "$LD"; then - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then - lt_cv_path_LD="$ac_dir/$ac_prog" + lt_cv_path_LD=$ac_dir/$ac_prog # Check to see if the program is GNU ld. I'd rather use --version, # but apparently some variants of GNU ld only accept -v. # Break only if it was the GNU/non-GNU ld that we prefer. case `"$lt_cv_path_LD" -v 2>&1 &5 $as_echo "$LD" >&6; } @@ -4353,10 +4640,10 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi -test -z "$LD" && as_fn_error "no acceptable ld found in \$PATH" "$LINENO" 5 +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 $as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } -if test "${lt_cv_prog_gnu_ld+set}" = set; then : +if ${lt_cv_prog_gnu_ld+:} false; then : $as_echo_n "(cached) " >&6 else # I'd rather use --version here, but apparently some GNU lds only accept -v. @@ -4393,7 +4680,7 @@ if test -n "$CPP" && test -d "$CPP"; then CPP= fi if test -z "$CPP"; then - if test "${ac_cv_prog_CPP+set}" = set; then : + if ${ac_cv_prog_CPP+:} false; then : $as_echo_n "(cached) " >&6 else # Double quotes because CPP needs to be expanded @@ -4423,7 +4710,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4439,11 +4726,11 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : break fi @@ -4482,7 +4769,7 @@ else # Broken: fails on valid input. continue fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext # OK, works on sane cases. Now check whether nonexistent headers # can be detected and how. @@ -4498,18 +4785,18 @@ else ac_preproc_ok=: break fi -rm -f conftest.err conftest.$ac_ext +rm -f conftest.err conftest.i conftest.$ac_ext done # Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. -rm -f conftest.err conftest.$ac_ext +rm -f conftest.i conftest.err conftest.$ac_ext if $ac_preproc_ok; then : else { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 $as_echo "$as_me: error: in \`$ac_pwd':" >&2;} -as_fn_error "C preprocessor \"$CPP\" fails sanity check -See \`config.log' for more details." "$LINENO" 5; } +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } fi ac_ext=c @@ -4518,16 +4805,17 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}sed", so it can be a program name with args. -set dummy ${ac_tool_prefix}sed; ac_word=$2 +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_SED+set}" = set; then : +if ${ac_cv_prog_AWK+:} false; then : $as_echo_n "(cached) " >&6 else - if test -n "$SED"; then - ac_cv_prog_SED="$SED" # Let the user override the test. + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. else as_save_IFS=$IFS; IFS=$PATH_SEPARATOR for as_dir in $PATH @@ -4535,8 +4823,8 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_SED="${ac_tool_prefix}sed" + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -4546,372 +4834,18 @@ IFS=$as_save_IFS fi fi -SED=$ac_cv_prog_SED -if test -n "$SED"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 -$as_echo "$SED" >&6; } +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } else { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } fi -fi -if test -z "$ac_cv_prog_SED"; then - ac_ct_SED=$SED - # Extract the first word of "sed", so it can be a program name with args. -set dummy sed; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_SED+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_SED"; then - ac_cv_prog_ac_ct_SED="$ac_ct_SED" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_SED="sed" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi + test -n "$AWK" && break done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_SED=$ac_cv_prog_ac_ct_SED -if test -n "$ac_ct_SED"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_SED" >&5 -$as_echo "$ac_ct_SED" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_SED" = x; then - SED=":" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - SED=$ac_ct_SED - fi -else - SED="$ac_cv_prog_SED" -fi - -enable_win32_dll=yes - -case $host in -*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. -set dummy ${ac_tool_prefix}as; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AS+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$AS"; then - ac_cv_prog_AS="$AS" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AS="${ac_tool_prefix}as" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -AS=$ac_cv_prog_AS -if test -n "$AS"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 -$as_echo "$AS" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_AS"; then - ac_ct_AS=$AS - # Extract the first word of "as", so it can be a program name with args. -set dummy as; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_AS+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_AS"; then - ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_AS="as" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_AS=$ac_cv_prog_ac_ct_AS -if test -n "$ac_ct_AS"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 -$as_echo "$ac_ct_AS" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_AS" = x; then - AS="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - AS=$ac_ct_AS - fi -else - AS="$ac_cv_prog_AS" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. -set dummy ${ac_tool_prefix}dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_DLLTOOL+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$DLLTOOL"; then - ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -DLLTOOL=$ac_cv_prog_DLLTOOL -if test -n "$DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 -$as_echo "$DLLTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_DLLTOOL"; then - ac_ct_DLLTOOL=$DLLTOOL - # Extract the first word of "dlltool", so it can be a program name with args. -set dummy dlltool; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_DLLTOOL+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_DLLTOOL"; then - ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_DLLTOOL="dlltool" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL -if test -n "$ac_ct_DLLTOOL"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 -$as_echo "$ac_ct_DLLTOOL" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_DLLTOOL" = x; then - DLLTOOL="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - DLLTOOL=$ac_ct_DLLTOOL - fi -else - DLLTOOL="$ac_cv_prog_DLLTOOL" -fi - - if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. -set dummy ${ac_tool_prefix}objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OBJDUMP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$OBJDUMP"; then - ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -OBJDUMP=$ac_cv_prog_OBJDUMP -if test -n "$OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 -$as_echo "$OBJDUMP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - -fi -if test -z "$ac_cv_prog_OBJDUMP"; then - ac_ct_OBJDUMP=$OBJDUMP - # Extract the first word of "objdump", so it can be a program name with args. -set dummy objdump; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test -n "$ac_ct_OBJDUMP"; then - ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. -else -as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_OBJDUMP="objdump" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - -fi -fi -ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP -if test -n "$ac_ct_OBJDUMP"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 -$as_echo "$ac_ct_OBJDUMP" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - if test "x$ac_ct_OBJDUMP" = x; then - OBJDUMP="false" - else - case $cross_compiling:$ac_tool_warned in -yes:) -{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 -$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} -ac_tool_warned=yes ;; -esac - OBJDUMP=$ac_ct_OBJDUMP - fi -else - OBJDUMP="$ac_cv_prog_OBJDUMP" -fi - - ;; -esac - -test -z "$AS" && AS=as - - - - - -test -z "$DLLTOOL" && DLLTOOL=dlltool - - - - - -test -z "$OBJDUMP" && OBJDUMP=objdump - - - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 @@ -4929,7 +4863,7 @@ fi $as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; } set x ${MAKE-make} ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'` -if { as_var=ac_cv_prog_make_${ac_make}_set; eval "test \"\${$as_var+set}\" = set"; }; then : +if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then : $as_echo_n "(cached) " >&6 else cat >conftest.make <<\_ACEOF @@ -4937,7 +4871,7 @@ SHELL = /bin/sh all: @echo '@@@%%%=$(MAKE)=@@@%%%' _ACEOF -# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +# GNU make sometimes prints "make[1]: Entering ...", which would confuse us. case `${MAKE-make} -f conftest.make 2>/dev/null` in *@@@%%%=?*=@@@%%%*) eval ac_cv_prog_make_${ac_make}_set=yes;; @@ -4956,6 +4890,7 @@ $as_echo "no" >&6; } SET_MAKE="MAKE=${MAKE-make}" fi + case `pwd` in *\ * | *\ *) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 @@ -4964,8 +4899,8 @@ esac -macro_version='2.2.6b' -macro_revision='1.3017' +macro_version='2.4.6' +macro_revision='2.4.6' @@ -4979,42 +4914,64 @@ macro_revision='1.3017' -ltmain="$ac_aux_dir/ltmain.sh" +ltmain=$ac_aux_dir/ltmain.sh + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 $as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } -if test "${lt_cv_path_NM+set}" = set; then : +if ${lt_cv_path_NM+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NM"; then # Let the user override the test. - lt_cv_path_NM="$NM" + lt_cv_path_NM=$NM else - lt_nm_to_check="${ac_tool_prefix}nm" + lt_nm_to_check=${ac_tool_prefix}nm if test -n "$ac_tool_prefix" && test "$build" = "$host"; then lt_nm_to_check="$lt_nm_to_check nm" fi for lt_tmp_nm in $lt_nm_to_check; do - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - tmp_nm="$ac_dir/$lt_tmp_nm" - if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + tmp_nm=$ac_dir/$lt_tmp_nm + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext"; then # Check to see if the nm accepts a BSD-compat flag. - # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # Adding the 'sed 1q' prevents false positives on HP-UX, which says: # nm: unknown option "B" ignored # Tru64's nm complains that /dev/null is an invalid object file - case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in - */dev/null* | *'Invalid file or object type'*) + # MSYS converts /dev/null to NUL, MinGW nm treats NUL as empty + case $build_os in + mingw*) lt_bad_file=conftest.nm/nofile ;; + *) lt_bad_file=/dev/null ;; + esac + case `"$tmp_nm" -B $lt_bad_file 2>&1 | sed '1q'` in + *$lt_bad_file* | *'Invalid file or object type'*) lt_cv_path_NM="$tmp_nm -B" - break + break 2 ;; *) case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in */dev/null*) lt_cv_path_NM="$tmp_nm -p" - break + break 2 ;; *) lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but @@ -5025,25 +4982,28 @@ else esac fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs done : ${lt_cv_path_NM=no} fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 $as_echo "$lt_cv_path_NM" >&6; } -if test "$lt_cv_path_NM" != "no"; then - NM="$lt_cv_path_NM" +if test no != "$lt_cv_path_NM"; then + NM=$lt_cv_path_NM else # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$ac_tool_prefix"; then - for ac_prog in "dumpbin -symbols" "link -dump -symbols" + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_DUMPBIN+set}" = set; then : +if ${ac_cv_prog_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DUMPBIN"; then @@ -5055,7 +5015,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5081,13 +5041,13 @@ fi fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN - for ac_prog in "dumpbin -symbols" "link -dump -symbols" + for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_DUMPBIN+set}" = set; then : +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DUMPBIN"; then @@ -5099,7 +5059,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5136,9 +5096,18 @@ esac fi fi + case `$DUMPBIN -symbols -headers /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols -headers" + ;; + *) + DUMPBIN=: + ;; + esac + fi - if test "$DUMPBIN" != ":"; then - NM="$DUMPBIN" + if test : != "$DUMPBIN"; then + NM=$DUMPBIN fi fi test -z "$NM" && NM=nm @@ -5150,18 +5119,18 @@ test -z "$NM" && NM=nm { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } -if test "${lt_cv_nm_interface+set}" = set; then : +if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:5158: $ac_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:5161: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:5164: output\"" >&5) + (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -5174,11 +5143,11 @@ $as_echo "$lt_cv_nm_interface" >&6; } # find the maximum length of command line arguments { $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 $as_echo_n "checking the maximum length of command line arguments... " >&6; } -if test "${lt_cv_sys_max_cmd_len+set}" = set; then : +if ${lt_cv_sys_max_cmd_len+:} false; then : $as_echo_n "(cached) " >&6 else i=0 - teststring="ABCD" + teststring=ABCD case $build_os in msdosdjgpp*) @@ -5207,13 +5176,18 @@ else lt_cv_sys_max_cmd_len=8192; ;; + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. lt_cv_sys_max_cmd_len=8192; ;; - netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + bitrig* | darwin* | dragonfly* | freebsd* | netbsd* | openbsd*) # This has been around since 386BSD, at least. Likely further. if test -x /sbin/sysctl; then lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` @@ -5232,6 +5206,11 @@ else lt_cv_sys_max_cmd_len=196608 ;; + os2*) + # The test takes a long time on OS/2. + lt_cv_sys_max_cmd_len=8192 + ;; + osf*) # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not @@ -5258,22 +5237,23 @@ else ;; *) lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` - if test -n "$lt_cv_sys_max_cmd_len"; then + if test -n "$lt_cv_sys_max_cmd_len" && \ + test undefined != "$lt_cv_sys_max_cmd_len"; then lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` else # Make teststring a little bigger before we do anything with it. # a 1K string should be a reasonable start. - for i in 1 2 3 4 5 6 7 8 ; do + for i in 1 2 3 4 5 6 7 8; do teststring=$teststring$teststring done SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ - = "XX$teststring$teststring"; } >/dev/null 2>&1 && - test $i != 17 # 1/2 MB should be enough + while { test X`env echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test 17 != "$i" # 1/2 MB should be enough do i=`expr $i + 1` teststring=$teststring$teststring @@ -5291,7 +5271,7 @@ else fi -if test -n $lt_cv_sys_max_cmd_len ; then +if test -n "$lt_cv_sys_max_cmd_len"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 $as_echo "$lt_cv_sys_max_cmd_len" >&6; } else @@ -5309,30 +5289,6 @@ max_cmd_len=$lt_cv_sys_max_cmd_len : ${MV="mv -f"} : ${RM="rm -f"} -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 -$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } -# Try some XSI features -xsi_shell=no -( _lt_dummy="a/b/c" - test "${_lt_dummy##*/},${_lt_dummy%/*},"${_lt_dummy%"$_lt_dummy"}, \ - = c,a/b,, \ - && eval 'test $(( 1 + 1 )) -eq 2 \ - && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ - && xsi_shell=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 -$as_echo "$xsi_shell" >&6; } - - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 -$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } -lt_shell_append=no -( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ - >/dev/null 2>&1 \ - && lt_shell_append=yes -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 -$as_echo "$lt_shell_append" >&6; } - - if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then lt_unset=unset else @@ -5364,9 +5320,83 @@ esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 $as_echo_n "checking for $LD option to reload object files... " >&6; } -if test "${lt_cv_ld_reload_flag+set}" = set; then : +if ${lt_cv_ld_reload_flag+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_reload_flag='-r' @@ -5380,9 +5410,14 @@ case $reload_flag in esac reload_cmds='$LD$reload_flag -o $output$reload_objs' case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test yes != "$GCC"; then + reload_cmds=false + fi + ;; darwin*) - if test "$GCC" = yes; then - reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + if test yes = "$GCC"; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib $wl-r -o $output$reload_objs' else reload_cmds='$LD$reload_flag -o $output$reload_objs' fi @@ -5402,7 +5437,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OBJDUMP+set}" = set; then : +if ${ac_cv_prog_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OBJDUMP"; then @@ -5414,7 +5449,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5442,7 +5477,7 @@ if test -z "$ac_cv_prog_OBJDUMP"; then set dummy objdump; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OBJDUMP+set}" = set; then : +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OBJDUMP"; then @@ -5454,7 +5489,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OBJDUMP="objdump" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5498,7 +5533,7 @@ test -z "$OBJDUMP" && OBJDUMP=objdump { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 $as_echo_n "checking how to recognize dependent libraries... " >&6; } -if test "${lt_cv_deplibs_check_method+set}" = set; then : +if ${lt_cv_deplibs_check_method+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_file_magic_cmd='$MAGIC_CMD' @@ -5507,13 +5542,13 @@ lt_cv_deplibs_check_method='unknown' # Need to set the preceding variable on all platforms that support # interlibrary dependencies. # 'none' -- dependencies not supported. -# `unknown' -- same as none, but documents that we really don't know. +# 'unknown' -- same as none, but documents that we really don't know. # 'pass_all' -- all dependencies passed with no checks. # 'test_compile' -- check by making test program. # 'file_magic [[regex]]' -- check by looking for files in library path -# which responds to the $file_magic_cmd with a given extended regex. -# If you have `file' or equivalent on your system and you're not sure -# whether `pass_all' will *always* work, you probably want this one. +# that responds to the $file_magic_cmd with a given extended regex. +# If you have 'file' or equivalent on your system and you're not sure +# whether 'pass_all' will *always* work, you probably want this one. case $host_os in aix[4-9]*) @@ -5544,12 +5579,13 @@ mingw* | pw32*) lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; -cegcc) +cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' @@ -5575,7 +5611,7 @@ freebsd* | dragonfly*) fi ;; -gnu*) +haiku*) lt_cv_deplibs_check_method=pass_all ;; @@ -5587,11 +5623,11 @@ hpux10.20* | hpux11*) lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac @@ -5612,8 +5648,8 @@ irix5* | irix6* | nonstopux*) lt_cv_deplibs_check_method=pass_all ;; -# This must be Linux ELF. -linux* | k*bsd*-gnu) +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) lt_cv_deplibs_check_method=pass_all ;; @@ -5635,8 +5671,8 @@ newos6*) lt_cv_deplibs_check_method=pass_all ;; -openbsd*) - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then +openbsd* | bitrig*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' else lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' @@ -5689,11 +5725,29 @@ sysv4 | sysv4.3*) tpf*) lt_cv_deplibs_check_method=pass_all ;; +os2*) + lt_cv_deplibs_check_method=pass_all + ;; esac fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 $as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + file_magic_cmd=$lt_cv_file_magic_cmd deplibs_check_method=$lt_cv_deplibs_check_method test -z "$deplibs_check_method" && deplibs_check_method=unknown @@ -5707,14 +5761,165 @@ test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + if test -n "$ac_tool_prefix"; then - # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. -set dummy ${ac_tool_prefix}ar; ac_word=$2 + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_AR+set}" = set; then : +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh; + # decide which one to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd=$ECHO + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$AR"; then @@ -5726,8 +5931,8 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_AR="${ac_tool_prefix}ar" + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5747,14 +5952,18 @@ $as_echo "no" >&6; } fi + test -n "$AR" && break + done fi -if test -z "$ac_cv_prog_AR"; then +if test -z "$AR"; then ac_ct_AR=$AR - # Extract the first word of "ar", so it can be a program name with args. -set dummy ar; ac_word=$2 + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_AR+set}" = set; then : +if ${ac_cv_prog_ac_ct_AR+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_AR"; then @@ -5766,8 +5975,8 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_prog_ac_ct_AR="ar" + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="$ac_prog" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 fi @@ -5786,6 +5995,10 @@ else $as_echo "no" >&6; } fi + + test -n "$ac_ct_AR" && break +done + if test "x$ac_ct_AR" = x; then AR="false" else @@ -5797,12 +6010,10 @@ ac_tool_warned=yes ;; esac AR=$ac_ct_AR fi -else - AR="$ac_cv_prog_AR" fi -test -z "$AR" && AR=ar -test -z "$AR_FLAGS" && AR_FLAGS=cru +: ${AR=ar} +: ${AR_FLAGS=cru} @@ -5814,12 +6025,70 @@ test -z "$AR_FLAGS" && AR_FLAGS=cru +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -eq "$ac_status"; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test 0 -ne "$ac_status"; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test no = "$lt_cv_ar_at_file"; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. set dummy ${ac_tool_prefix}strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_STRIP+set}" = set; then : +if ${ac_cv_prog_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$STRIP"; then @@ -5831,7 +6100,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_STRIP="${ac_tool_prefix}strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5859,7 +6128,7 @@ if test -z "$ac_cv_prog_STRIP"; then set dummy strip; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then : +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_STRIP"; then @@ -5871,7 +6140,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_STRIP="strip" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5918,7 +6187,7 @@ if test -n "$ac_tool_prefix"; then set dummy ${ac_tool_prefix}ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_RANLIB+set}" = set; then : +if ${ac_cv_prog_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$RANLIB"; then @@ -5930,7 +6199,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -5958,7 +6227,7 @@ if test -z "$ac_cv_prog_RANLIB"; then set dummy ranlib; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then : +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_RANLIB"; then @@ -5970,7 +6239,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_RANLIB="ranlib" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6019,16 +6288,28 @@ old_postuninstall_cmds= if test -n "$RANLIB"; then case $host_os in - openbsd*) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + bitrig* | openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$tool_oldlib" ;; *) - old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$tool_oldlib" ;; esac - old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" + old_archive_cmds="$old_archive_cmds~\$RANLIB \$tool_oldlib" fi +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + @@ -6075,7 +6356,7 @@ compiler=$CC # Check for command to grab the raw symbol name followed by C symbol from nm. { $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 $as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } -if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then : +if ${lt_cv_sys_global_symbol_pipe+:} false; then : $as_echo_n "(cached) " >&6 else @@ -6097,7 +6378,7 @@ cygwin* | mingw* | pw32* | cegcc*) symcode='[ABCDGISTW]' ;; hpux*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then symcode='[ABCDEGRST]' fi ;; @@ -6130,14 +6411,44 @@ case `$NM -V 2>&1` in symcode='[ABCDGIRSTW]' ;; esac +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Gets list of data symbols to import. + lt_cv_sys_global_symbol_to_import="sed -n -e 's/^I .* \(.*\)$/\1/p'" + # Adjust the below global symbol transforms to fixup imported variables. + lt_cdecl_hook=" -e 's/^I .* \(.*\)$/extern __declspec(dllimport) char \1;/p'" + lt_c_name_hook=" -e 's/^I .* \(.*\)$/ {\"\1\", (void *) 0},/p'" + lt_c_name_lib_hook="\ + -e 's/^I .* \(lib.*\)$/ {\"\1\", (void *) 0},/p'\ + -e 's/^I .* \(.*\)$/ {\"lib\1\", (void *) 0},/p'" +else + # Disable hooks by default. + lt_cv_sys_global_symbol_to_import= + lt_cdecl_hook= + lt_c_name_hook= + lt_c_name_lib_hook= +fi + # Transform an extracted symbol line into a proper C declaration. # Some systems (esp. on ia64) link data and code symbols differently, # so use this general approach. -lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" +lt_cv_sys_global_symbol_to_cdecl="sed -n"\ +$lt_cdecl_hook\ +" -e 's/^T .* \(.*\)$/extern int \1();/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/extern char \1;/p'" # Transform an extracted symbol line into symbol name and symbol address -lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address="sed -n"\ +$lt_c_name_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/p'" + +# Transform an extracted symbol line into symbol name with lib prefix and +# symbol address. +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n"\ +$lt_c_name_lib_hook\ +" -e 's/^: \(.*\) .*$/ {\"\1\", (void *) 0},/p'"\ +" -e 's/^$symcode$symcode* .* \(lib.*\)$/ {\"\1\", (void *) \&\1},/p'"\ +" -e 's/^$symcode$symcode* .* \(.*\)$/ {\"lib\1\", (void *) \&\1},/p'" # Handle CRLF in mingw tool chain opt_cr= @@ -6155,24 +6466,29 @@ for ac_symprfx in "" "_"; do # Write the raw and C identifiers. if test "$lt_cv_nm_interface" = "MS dumpbin"; then - # Fake it for dumpbin and say T for any non-static function - # and D for any global variable. + # Fake it for dumpbin and say T for any non-static function, + # D for any global variable and I for any imported variable. # Also find C++ and __fastcall symbols from MSVC++, # which start with @ or ?. lt_cv_sys_global_symbol_pipe="$AWK '"\ " {last_section=section; section=\$ 3};"\ +" /^COFF SYMBOL TABLE/{for(i in hide) delete hide[i]};"\ " /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" /^ *Symbol name *: /{split(\$ 0,sn,\":\"); si=substr(sn[2],2)};"\ +" /^ *Type *: code/{print \"T\",si,substr(si,length(prfx))};"\ +" /^ *Type *: data/{print \"I\",si,substr(si,length(prfx))};"\ " \$ 0!~/External *\|/{next};"\ " / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ " {if(hide[section]) next};"\ -" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ -" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ -" s[1]~/^[@?]/{print s[1], s[1]; next};"\ -" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" {f=\"D\"}; \$ 0~/\(\).*\|/{f=\"T\"};"\ +" {split(\$ 0,a,/\||\r/); split(a[2],s)};"\ +" s[1]~/^[@?]/{print f,s[1],s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print f,t[1],substr(t[1],length(prfx))}"\ " ' prfx=^$ac_symprfx" else lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" # Check to see that the pipe works correctly. pipe_works=no @@ -6198,8 +6514,8 @@ _LT_EOF test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then @@ -6214,6 +6530,18 @@ _LT_EOF if $GREP ' nm_test_var$' "$nlist" >/dev/null; then if $GREP ' nm_test_func$' "$nlist" >/dev/null; then cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined _WIN32 || defined __CYGWIN__ || defined _WIN32_WCE +/* DATA imports from DLLs on WIN32 can't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined __osf__ +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + #ifdef __cplusplus extern "C" { #endif @@ -6225,7 +6553,7 @@ _LT_EOF cat <<_LT_EOF >> conftest.$ac_ext /* The mapping between symbol names and symbols. */ -const struct { +LT_DLSYM_CONST struct { const char *name; void *address; } @@ -6233,7 +6561,7 @@ lt__PROGRAM__LTX_preloaded_symbols[] = { { "@PROGRAM@", (void *) 0 }, _LT_EOF - $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + $SED "s/^$symcode$symcode* .* \(.*\)$/ {\"\1\", (void *) \&\1},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext cat <<\_LT_EOF >> conftest.$ac_ext {0, (void *) 0} }; @@ -6251,19 +6579,19 @@ static const void *lt_preloaded_setup() { _LT_EOF # Now try linking the two files. mv conftest.$ac_objext conftstm.$ac_objext - lt_save_LIBS="$LIBS" - lt_save_CFLAGS="$CFLAGS" - LIBS="conftstm.$ac_objext" + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS=conftstm.$ac_objext CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext}; then + test $ac_status = 0; } && test -s conftest$ac_exeext; then pipe_works=yes fi - LIBS="$lt_save_LIBS" - CFLAGS="$lt_save_CFLAGS" + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS else echo "cannot find nm_test_func in $nlist" >&5 fi @@ -6280,7 +6608,7 @@ _LT_EOF rm -rf conftest* conftst* # Do not use the global_symbol_pipe unless it works. - if test "$pipe_works" = yes; then + if test yes = "$pipe_works"; then break else lt_cv_sys_global_symbol_pipe= @@ -6300,6 +6628,12 @@ else $as_echo "ok" >&6; } fi +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi @@ -6321,19 +6655,152 @@ fi + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case $with_sysroot in #( + yes) + if test yes = "$GCC"; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_sysroot" >&5 +$as_echo "$with_sysroot" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a working dd" >&5 +$as_echo_n "checking for a working dd... " >&6; } +if ${ac_cv_path_lt_DD+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +: ${lt_DD:=$DD} +if test -z "$lt_DD"; then + ac_path_lt_DD_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in dd; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_lt_DD="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_lt_DD" || continue +if "$ac_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && ac_cv_path_lt_DD="$ac_path_lt_DD" ac_path_lt_DD_found=: +fi + $ac_path_lt_DD_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_lt_DD"; then + : + fi +else + ac_cv_path_lt_DD=$lt_DD +fi + +rm -f conftest.i conftest2.i conftest.out +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_lt_DD" >&5 +$as_echo "$ac_cv_path_lt_DD" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to truncate binary pipes" >&5 +$as_echo_n "checking how to truncate binary pipes... " >&6; } +if ${lt_cv_truncate_bin+:} false; then : + $as_echo_n "(cached) " >&6 +else + printf 0123456789abcdef0123456789abcdef >conftest.i +cat conftest.i conftest.i >conftest2.i +lt_cv_truncate_bin= +if "$ac_cv_path_lt_DD" bs=32 count=1 conftest.out 2>/dev/null; then + cmp -s conftest.i conftest.out \ + && lt_cv_truncate_bin="$ac_cv_path_lt_DD bs=4096 count=1" +fi +rm -f conftest.i conftest2.i conftest.out +test -z "$lt_cv_truncate_bin" && lt_cv_truncate_bin="$SED -e 4q" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_truncate_bin" >&5 +$as_echo "$lt_cv_truncate_bin" >&6; } + + + + + + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} # Check whether --enable-libtool-lock was given. if test "${enable_libtool_lock+set}" = set; then : enableval=$enable_libtool_lock; fi -test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes +test no = "$enable_libtool_lock" || enable_libtool_lock=yes # Some flags need to be propagated to the compiler or linker for good # libtool support. case $host in ia64-*-hpux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set mode + # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -6342,24 +6809,25 @@ ia64-*-hpux*) test $ac_status = 0; }; then case `/usr/bin/file conftest.$ac_objext` in *ELF-32*) - HPUX_IA64_MODE="32" + HPUX_IA64_MODE=32 ;; *ELF-64*) - HPUX_IA64_MODE="64" + HPUX_IA64_MODE=64 ;; esac fi rm -rf conftest* ;; *-*-irix6*) - # Find out which ABI we are using. - echo '#line 6356 "configure"' > conftest.$ac_ext + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then - if test "$lt_cv_prog_gnu_ld" = yes; then + if test yes = "$lt_cv_prog_gnu_ld"; then case `/usr/bin/file conftest.$ac_objext` in *32-bit*) LD="${LD-ld} -melf32bsmip" @@ -6388,9 +6856,50 @@ ia64-*-hpux*) rm -rf conftest* ;; -x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +mips64*-*linux*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + emul=elf + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + emul="${emul}32" + ;; + *64-bit*) + emul="${emul}64" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *MSB*) + emul="${emul}btsmip" + ;; + *LSB*) + emul="${emul}ltsmip" + ;; + esac + case `/usr/bin/file conftest.$ac_objext` in + *N32*) + emul="${emul}n32" + ;; + esac + LD="${LD-ld} -m $emul" + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|powerpc*-*linux*| \ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) - # Find out which ABI we are using. + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. Note that the listed cases only cover the + # situations where additional linker options are needed (such as when + # doing 32-bit compilation for a host where ld defaults to 64-bit, or + # vice versa); the common cases where no linker options are needed do + # not appear in the list. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -6404,9 +6913,19 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) LD="${LD-ld} -m elf_i386_fbsd" ;; x86_64-*linux*) - LD="${LD-ld} -m elf_i386" + case `/usr/bin/file conftest.o` in + *x86-64*) + LD="${LD-ld} -m elf32_x86_64" + ;; + *) + LD="${LD-ld} -m elf_i386" + ;; + esac ;; - ppc64-*linux*|powerpc64-*linux*) + powerpc64le-*linux*) + LD="${LD-ld} -m elf32lppclinux" + ;; + powerpc64-*linux*) LD="${LD-ld} -m elf32ppclinux" ;; s390x-*linux*) @@ -6425,7 +6944,10 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) x86_64-*linux*) LD="${LD-ld} -m elf_x86_64" ;; - ppc*-*linux*|powerpc*-*linux*) + powerpcle-*linux*) + LD="${LD-ld} -m elf64lppc" + ;; + powerpc-*linux*) LD="${LD-ld} -m elf64ppc" ;; s390*-*linux*|s390*-*tpf*) @@ -6443,11 +6965,11 @@ s390*-*linux*|s390*-*tpf*|sparc*-*linux*) *-*-sco3.2v5*) # On SCO OpenServer 5, we need -belf to get full-featured binaries. - SAVE_CFLAGS="$CFLAGS" + SAVE_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -belf" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 $as_echo_n "checking whether the C compiler needs -belf... " >&6; } -if test "${lt_cv_cc_needs_belf+set}" = set; then : +if ${lt_cv_cc_needs_belf+:} false; then : $as_echo_n "(cached) " >&6 else ac_ext=c @@ -6483,13 +7005,14 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 $as_echo "$lt_cv_cc_needs_belf" >&6; } - if test x"$lt_cv_cc_needs_belf" != x"yes"; then + if test yes != "$lt_cv_cc_needs_belf"; then # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf - CFLAGS="$SAVE_CFLAGS" + CFLAGS=$SAVE_CFLAGS fi ;; -sparc*-*solaris*) - # Find out which ABI we are using. +*-*solaris*) + # Find out what ABI is being produced by ac_compile, and set linker + # options accordingly. echo 'int i;' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 @@ -6499,7 +7022,20 @@ sparc*-*solaris*) case `/usr/bin/file conftest.o` in *64-bit*) case $lt_cv_prog_gnu_ld in - yes*) LD="${LD-ld} -m elf64_sparc" ;; + yes*) + case $host in + i?86-*-solaris*|x86_64-*-solaris*) + LD="${LD-ld} -m elf_x86_64" + ;; + sparc*-*-solaris*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + # GNU ld 2.21 introduced _sol2 emulations. Use them if available. + if ${LD-ld} -V | grep _sol2 >/dev/null 2>&1; then + LD=${LD-ld}_sol2 + fi + ;; *) if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then LD="${LD-ld} -64" @@ -6513,7 +7049,124 @@ sparc*-*solaris*) ;; esac -need_locks="$enable_libtool_lock" +need_locks=$enable_libtool_lock + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test yes != "$lt_cv_path_mainfest_tool"; then + MANIFEST_TOOL=: +fi + + + + case $host_os in @@ -6523,7 +7176,7 @@ need_locks="$enable_libtool_lock" set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_DSYMUTIL+set}" = set; then : +if ${ac_cv_prog_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$DSYMUTIL"; then @@ -6535,7 +7188,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6563,7 +7216,7 @@ if test -z "$ac_cv_prog_DSYMUTIL"; then set dummy dsymutil; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_DSYMUTIL+set}" = set; then : +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_DSYMUTIL"; then @@ -6575,7 +7228,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6615,7 +7268,7 @@ fi set dummy ${ac_tool_prefix}nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_NMEDIT+set}" = set; then : +if ${ac_cv_prog_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$NMEDIT"; then @@ -6627,7 +7280,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6655,7 +7308,7 @@ if test -z "$ac_cv_prog_NMEDIT"; then set dummy nmedit; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_NMEDIT+set}" = set; then : +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_NMEDIT"; then @@ -6667,7 +7320,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_NMEDIT="nmedit" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6707,7 +7360,7 @@ fi set dummy ${ac_tool_prefix}lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_LIPO+set}" = set; then : +if ${ac_cv_prog_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$LIPO"; then @@ -6719,7 +7372,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_LIPO="${ac_tool_prefix}lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6747,7 +7400,7 @@ if test -z "$ac_cv_prog_LIPO"; then set dummy lipo; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_LIPO+set}" = set; then : +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_LIPO"; then @@ -6759,7 +7412,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_LIPO="lipo" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6799,7 +7452,7 @@ fi set dummy ${ac_tool_prefix}otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OTOOL+set}" = set; then : +if ${ac_cv_prog_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL"; then @@ -6811,7 +7464,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL="${ac_tool_prefix}otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6839,7 +7492,7 @@ if test -z "$ac_cv_prog_OTOOL"; then set dummy otool; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OTOOL+set}" = set; then : +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL"; then @@ -6851,7 +7504,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL="otool" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6891,7 +7544,7 @@ fi set dummy ${ac_tool_prefix}otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_OTOOL64+set}" = set; then : +if ${ac_cv_prog_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$OTOOL64"; then @@ -6903,7 +7556,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -6931,7 +7584,7 @@ if test -z "$ac_cv_prog_OTOOL64"; then set dummy otool64; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 $as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_prog_ac_ct_OTOOL64+set}" = set; then : +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : $as_echo_n "(cached) " >&6 else if test -n "$ac_ct_OTOOL64"; then @@ -6943,7 +7596,7 @@ do IFS=$as_save_IFS test -z "$as_dir" && as_dir=. for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then ac_cv_prog_ac_ct_OTOOL64="otool64" $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 break 2 @@ -7006,11 +7659,11 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 $as_echo_n "checking for -single_module linker flag... " >&6; } -if test "${lt_cv_apple_cc_single_mod+set}" = set; then : +if ${lt_cv_apple_cc_single_mod+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_apple_cc_single_mod=no - if test -z "${LT_MULTI_MODULE}"; then + if test -z "$LT_MULTI_MODULE"; then # By default we will add the -single_module flag. You can override # by either setting the environment variable LT_MULTI_MODULE # non-empty at configure time, or by adding -multi_module to the @@ -7022,7 +7675,13 @@ else $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ -dynamiclib -Wl,-single_module conftest.c 2>conftest.err _lt_result=$? - if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + # If there is a non-empty error log, and "single_module" + # appears in it, assume the flag caused a linker warning + if test -s conftest.err && $GREP single_module conftest.err; then + cat conftest.err >&5 + # Otherwise, if the output was created with a 0 exit code from + # the compiler, it worked. + elif test -f libconftest.dylib && test 0 = "$_lt_result"; then lt_cv_apple_cc_single_mod=yes else cat conftest.err >&5 @@ -7033,9 +7692,10 @@ else fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 $as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 $as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } -if test "${lt_cv_ld_exported_symbols_list+set}" = set; then : +if ${lt_cv_ld_exported_symbols_list+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_ld_exported_symbols_list=no @@ -7060,39 +7720,74 @@ else fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -s conftest.err && $GREP force_load conftest.err; then + cat conftest.err >&5 + elif test -f conftest && test 0 = "$_lt_result" && $GREP forced_load conftest >/dev/null 2>&1; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) - _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}suppress' ;; darwin1.*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; darwin*) # darwin 5.x on # if running on 10.5 or later, the deployment target defaults # to the OS version, if on x86, and 10.4, the deployment # target defaults to 10.4. Don't you love it? case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in 10.0,*86*-darwin8*|10.0,*-darwin[91]*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; - 10.[012]*) - _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; + 10.[012][,.]*) + _lt_dar_allow_undefined='$wl-flat_namespace $wl-undefined ${wl}suppress' ;; 10.*) - _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + _lt_dar_allow_undefined='$wl-undefined ${wl}dynamic_lookup' ;; esac ;; esac - if test "$lt_cv_apple_cc_single_mod" = "yes"; then + if test yes = "$lt_cv_apple_cc_single_mod"; then _lt_dar_single_mod='$single_module' fi - if test "$lt_cv_ld_exported_symbols_list" = "yes"; then - _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + if test yes = "$lt_cv_ld_exported_symbols_list"; then + _lt_dar_export_syms=' $wl-exported_symbols_list,$output_objdir/$libname-symbols.expsym' else - _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/$libname-symbols.expsym $lib' fi - if test "$DSYMUTIL" != ":"; then + if test : != "$DSYMUTIL" && test no = "$lt_cv_ld_force_load"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -7100,10 +7795,45 @@ $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } ;; esac +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -7220,8 +7950,7 @@ do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default " -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : cat >>confdefs.h <<_ACEOF #define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 _ACEOF @@ -7235,7 +7964,7 @@ for ac_header in dlfcn.h do : ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default " -if test "x$ac_cv_header_dlfcn_h" = x""yes; then : +if test "x$ac_cv_header_dlfcn_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_DLFCN_H 1 _ACEOF @@ -7246,7 +7975,309 @@ done + + # Set options +enable_win32_dll=yes + +case $host in +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}as", so it can be a program name with args. +set dummy ${ac_tool_prefix}as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AS"; then + ac_cv_prog_AS="$AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AS="${ac_tool_prefix}as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AS=$ac_cv_prog_AS +if test -n "$AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AS" >&5 +$as_echo "$AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_AS"; then + ac_ct_AS=$AS + # Extract the first word of "as", so it can be a program name with args. +set dummy as; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AS+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AS"; then + ac_cv_prog_ac_ct_AS="$ac_ct_AS" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AS="as" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AS=$ac_cv_prog_ac_ct_AS +if test -n "$ac_ct_AS"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AS" >&5 +$as_echo "$ac_ct_AS" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_AS" = x; then + AS="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AS=$ac_ct_AS + fi +else + AS="$ac_cv_prog_AS" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + + ;; +esac + +test -z "$AS" && AS=as + + + + + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + @@ -7263,14 +8294,14 @@ if test "${enable_shared+set}" = set; then : *) enable_shared=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_shared=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -7294,14 +8325,14 @@ if test "${enable_static+set}" = set; then : *) enable_static=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_static=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -7319,14 +8350,27 @@ fi # Check whether --with-pic was given. if test "${with_pic+set}" = set; then : - withval=$with_pic; pic_mode="$withval" + withval=$with_pic; lt_p=${PACKAGE-default} + case $withval in + yes|no) pic_mode=$withval ;; + *) + pic_mode=default + # Look at the argument we got. We use all the common list separators. + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, + for lt_pkg in $withval; do + IFS=$lt_save_ifs + if test "X$lt_pkg" = "X$lt_p"; then + pic_mode=yes + fi + done + IFS=$lt_save_ifs + ;; + esac else pic_mode=default fi -test -z "$pic_mode" && pic_mode=default - @@ -7342,14 +8386,14 @@ if test "${enable_fast_install+set}" = set; then : *) enable_fast_install=no # Look at the argument we got. We use all the common list separators. - lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + lt_save_ifs=$IFS; IFS=$IFS$PATH_SEPARATOR, for pkg in $enableval; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs if test "X$pkg" = "X$p"; then enable_fast_install=yes fi done - IFS="$lt_save_ifs" + IFS=$lt_save_ifs ;; esac else @@ -7363,11 +8407,63 @@ fi + shared_archive_member_spec= +case $host,$enable_shared in +power*-*-aix[5-9]*,yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking which variant of shared library versioning to provide" >&5 +$as_echo_n "checking which variant of shared library versioning to provide... " >&6; } + +# Check whether --with-aix-soname was given. +if test "${with_aix_soname+set}" = set; then : + withval=$with_aix_soname; case $withval in + aix|svr4|both) + ;; + *) + as_fn_error $? "Unknown argument to --with-aix-soname" "$LINENO" 5 + ;; + esac + lt_cv_with_aix_soname=$with_aix_soname +else + if ${lt_cv_with_aix_soname+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_with_aix_soname=aix +fi + + with_aix_soname=$lt_cv_with_aix_soname +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_aix_soname" >&5 +$as_echo "$with_aix_soname" >&6; } + if test aix != "$with_aix_soname"; then + # For the AIX way of multilib, we name the shared archive member + # based on the bitwidth used, traditionally 'shr.o' or 'shr_64.o', + # and 'shr.imp' or 'shr_64.imp', respectively, for the Import File. + # Even when GNU compilers ignore OBJECT_MODE but need '-maix64' flag, + # the AIX toolchain works better with OBJECT_MODE set (default 32). + if test 64 = "${OBJECT_MODE-32}"; then + shared_archive_member_spec=shr_64 + else + shared_archive_member_spec=shr + fi + fi + ;; +*) + with_aix_soname=aix + ;; +esac + + + + + + + # This can be used to rebuild libtool when needed -LIBTOOL_DEPS="$ltmain" +LIBTOOL_DEPS=$ltmain # Always use our own libtool. LIBTOOL='$(SHELL) $(top_builddir)/libtool' @@ -7390,6 +8486,11 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + @@ -7411,13 +8512,13 @@ test -z "$LN_S" && LN_S="ln -s" -if test -n "${ZSH_VERSION+set}" ; then +if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 $as_echo_n "checking for objdir... " >&6; } -if test "${lt_cv_objdir+set}" = set; then : +if ${lt_cv_objdir+:} false; then : $as_echo_n "(cached) " >&6 else rm -f .libs 2>/dev/null @@ -7445,60 +8546,30 @@ _ACEOF - - - - - - - - - - - - - case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. - if test "X${COLLECT_NAMES+set}" != Xset; then + if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi ;; esac -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - # Global variables: ofile=libtool can_build_shared=yes -# All known linkers require a `.a' archive for static linking (except MSVC, +# All known linkers require a '.a' archive for static linking (except MSVC, # which needs '.lib'). libext=a -with_gnu_ld="$lt_cv_prog_gnu_ld" +with_gnu_ld=$lt_cv_prog_gnu_ld -old_CC="$CC" -old_CFLAGS="$CFLAGS" +old_CC=$CC +old_CFLAGS=$CFLAGS # Set sane defaults for various variables test -z "$CC" && CC=cc @@ -7507,15 +8578,8 @@ test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS test -z "$LD" && LD=ld test -z "$ac_objext" && ac_objext=o -for cc_temp in $compiler""; do - case $cc_temp in - compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; - distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; - \-*) ;; - *) break;; - esac -done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +func_cc_basename $compiler +cc_basename=$func_cc_basename_result # Only perform the check for file, if the check method requires it @@ -7525,27 +8589,27 @@ file_magic*) if test "$file_magic_cmd" = '$MAGIC_CMD'; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 $as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : +if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/${ac_tool_prefix}file; then - lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -f "$ac_dir/${ac_tool_prefix}file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"${ac_tool_prefix}file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -7568,13 +8632,13 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -7591,27 +8655,27 @@ if test -z "$lt_cv_path_MAGIC_CMD"; then if test -n "$ac_tool_prefix"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 $as_echo_n "checking for file... " >&6; } -if test "${lt_cv_path_MAGIC_CMD+set}" = set; then : +if ${lt_cv_path_MAGIC_CMD+:} false; then : $as_echo_n "(cached) " >&6 else case $MAGIC_CMD in [\\/*] | ?:[\\/]*) - lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + lt_cv_path_MAGIC_CMD=$MAGIC_CMD # Let the user override the test with a path. ;; *) - lt_save_MAGIC_CMD="$MAGIC_CMD" - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + lt_save_MAGIC_CMD=$MAGIC_CMD + lt_save_ifs=$IFS; IFS=$PATH_SEPARATOR ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" for ac_dir in $ac_dummy; do - IFS="$lt_save_ifs" + IFS=$lt_save_ifs test -z "$ac_dir" && ac_dir=. - if test -f $ac_dir/file; then - lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -f "$ac_dir/file"; then + lt_cv_path_MAGIC_CMD=$ac_dir/"file" if test -n "$file_magic_test_file"; then case $deplibs_check_method in "file_magic "*) file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` - MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + MAGIC_CMD=$lt_cv_path_MAGIC_CMD if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | $EGREP "$file_magic_regex" > /dev/null; then : @@ -7634,13 +8698,13 @@ _LT_EOF break fi done - IFS="$lt_save_ifs" - MAGIC_CMD="$lt_save_MAGIC_CMD" + IFS=$lt_save_ifs + MAGIC_CMD=$lt_save_MAGIC_CMD ;; esac fi -MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +MAGIC_CMD=$lt_cv_path_MAGIC_CMD if test -n "$MAGIC_CMD"; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 $as_echo "$MAGIC_CMD" >&6; } @@ -7661,7 +8725,7 @@ esac # Use C for the default configuration in the libtool script -lt_save_CC="$CC" +lt_save_CC=$CC ac_ext=c ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' @@ -7715,22 +8779,31 @@ _lt_linker_boilerplate=`cat conftest.err` $RM -r conftest* +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= -if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag=' -fno-builtin' +if test yes = "$GCC"; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } -if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then : +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_rtti_exceptions=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="-fno-rtti -fno-exceptions" + lt_compiler_flag="-fno-rtti -fno-exceptions" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -7740,15 +8813,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:7743: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:7747: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes @@ -7760,7 +8833,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 $as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } -if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then +if test yes = "$lt_cv_prog_compiler_rtti_exceptions"; then lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" else : @@ -7777,20 +8850,19 @@ fi lt_prog_compiler_pic= lt_prog_compiler_static= -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 -$as_echo_n "checking for $compiler option to produce PIC... " >&6; } - if test "$GCC" = yes; then + if test yes = "$GCC"; then lt_prog_compiler_wl='-Wl,' lt_prog_compiler_static='-static' case $host_os in aix*) # All AIX code is PIC. - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' fi + lt_prog_compiler_pic='-fPIC' ;; amigaos*) @@ -7801,8 +8873,8 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } ;; m68k) # FIXME: we need at least 68020 code to build shared libraries, but - # adding the `-m68020' flag to GCC prevents building anything better, - # like `-m68040'. + # adding the '-m68020' flag to GCC prevents building anything better, + # like '-m68040'. lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' ;; esac @@ -7818,6 +8890,11 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # Although the cygwin gcc ignores -fPIC, still need this for old-style # (--disable-auto-import) libraries lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac ;; darwin* | rhapsody*) @@ -7826,6 +8903,12 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-fno-common' ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag @@ -7868,12 +8951,21 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-fPIC' ;; esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + if test -n "$lt_prog_compiler_pic"; then + lt_prog_compiler_pic="-Xcompiler $lt_prog_compiler_pic" + fi + ;; + esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in aix*) lt_prog_compiler_wl='-Wl,' - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 now supports IA64 processor lt_prog_compiler_static='-Bstatic' else @@ -7881,10 +8973,29 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } fi ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + case $cc_basename in + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + esac + ;; + mingw* | cygwin* | pw32* | os2* | cegcc*) # This hack is so that the source file can tell whether it is being # built for inclusion in a dll (and should export symbols for example). lt_prog_compiler_pic='-DDLL_EXPORT' + case $host_os in + os2*) + lt_prog_compiler_static='$wl-static' + ;; + esac ;; hpux9* | hpux10* | hpux11*) @@ -7900,7 +9011,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } ;; esac # Is there a better lt_prog_compiler_static that works with the bundled CC? - lt_prog_compiler_static='${wl}-a ${wl}archive' + lt_prog_compiler_static='$wl-a ${wl}archive' ;; irix5* | irix6* | nonstopux*) @@ -7909,9 +9020,9 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_static='-non_shared' ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) case $cc_basename in - # old Intel for x86_64 which still supported -KPIC. + # old Intel for x86_64, which still supported -KPIC. ecc*) lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-KPIC' @@ -7930,7 +9041,19 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; - pgcc* | pgf77* | pgf90* | pgf95*) + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' @@ -7942,25 +9065,40 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; - xl*) - # IBM XL C 8.0/Fortran 10.1 on PPC + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in + *Sun\ Ceres\ Fortran* | *Sun*Fortran*\ [1-7].* | *Sun*Fortran*\ 8.[0-3]*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ F* | *Sun*Fortran*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Qoption ld ' + ;; *Sun\ C*) # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' lt_prog_compiler_wl='-Wl,' ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker - lt_prog_compiler_pic='-KPIC' + *Intel*\ [CF]*Compiler*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + *Portland\ Group*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='' ;; esac ;; @@ -7992,7 +9130,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in - f77* | f90* | f95*) + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; @@ -8012,7 +9150,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } ;; sysv4*MP*) - if test -d /usr/nec ;then + if test -d /usr/nec; then lt_prog_compiler_pic='-Kconform_pic' lt_prog_compiler_static='-Bstatic' fi @@ -8041,7 +9179,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } fi case $host_os in - # For platforms which do not support PIC, -DPIC is meaningless: + # For platforms that do not support PIC, -DPIC is meaningless: *djgpp*) lt_prog_compiler_pic= ;; @@ -8049,13 +9187,17 @@ case $host_os in lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" ;; esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_prog_compiler_pic" >&5 -$as_echo "$lt_prog_compiler_pic" >&6; } - - - - +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic # # Check to make sure the PIC flag actually works. @@ -8063,13 +9205,13 @@ $as_echo "$lt_prog_compiler_pic" >&6; } if test -n "$lt_prog_compiler_pic"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 $as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } -if test "${lt_cv_prog_compiler_pic_works+set}" = set; then : +if ${lt_cv_prog_compiler_pic_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_pic_works=no ac_outfile=conftest.$ac_objext echo "$lt_simple_compile_test_code" > conftest.$ac_ext - lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" ## exclude from sc_useless_quotes_in_assignment # Insert the option either (1) after the last *FLAGS variable, or # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins @@ -8079,15 +9221,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8082: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:8086: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes @@ -8099,7 +9241,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 $as_echo "$lt_cv_prog_compiler_pic_works" >&6; } -if test x"$lt_cv_prog_compiler_pic_works" = xyes; then +if test yes = "$lt_cv_prog_compiler_pic_works"; then case $lt_prog_compiler_pic in "" | " "*) ;; *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; @@ -8116,17 +9258,22 @@ fi + + + + + # # Check to make sure the static flag actually works. # wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 $as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } -if test "${lt_cv_prog_compiler_static_works+set}" = set; then : +if ${lt_cv_prog_compiler_static_works+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_static_works=no - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS LDFLAGS="$LDFLAGS $lt_tmp_static_flag" echo "$lt_simple_link_test_code" > conftest.$ac_ext if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then @@ -8135,7 +9282,7 @@ else if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes @@ -8145,13 +9292,13 @@ else fi fi $RM -r conftest* - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 $as_echo "$lt_cv_prog_compiler_static_works" >&6; } -if test x"$lt_cv_prog_compiler_static_works" = xyes; then +if test yes = "$lt_cv_prog_compiler_static_works"; then : else lt_prog_compiler_static= @@ -8165,7 +9312,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if test "${lt_cv_prog_compiler_c_o+set}" = set; then : +if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no @@ -8184,16 +9331,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8187: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8191: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes @@ -8220,7 +9367,7 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 $as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } -if test "${lt_cv_prog_compiler_c_o+set}" = set; then : +if ${lt_cv_prog_compiler_c_o+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_prog_compiler_c_o=no @@ -8239,16 +9386,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:8242: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:8246: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes @@ -8271,8 +9418,8 @@ $as_echo "$lt_cv_prog_compiler_c_o" >&6; } -hard_links="nottested" -if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then +hard_links=nottested +if test no = "$lt_cv_prog_compiler_c_o" && test no != "$need_locks"; then # do not overwrite the value of need_locks provided by the user { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 $as_echo_n "checking if we can lock with hard links... " >&6; } @@ -8284,9 +9431,9 @@ $as_echo_n "checking if we can lock with hard links... " >&6; } ln conftest.a conftest.b 2>/dev/null && hard_links=no { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 $as_echo "$hard_links" >&6; } - if test "$hard_links" = no; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 -$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + if test no = "$hard_links"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: '$CC' does not support '-c -o', so 'make -j' may be unsafe" >&2;} need_locks=warn fi else @@ -8314,7 +9461,6 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie hardcode_direct=no hardcode_direct_absolute=no hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld= hardcode_libdir_separator= hardcode_minus_L=no hardcode_shlibpath_var=unsupported @@ -8330,9 +9476,9 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # included in the symbol list include_expsyms= # exclude_expsyms can be an extended regexp of symbols to exclude - # it will be wrapped by ` (' and `)$', so one must not match beginning or - # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', - # as well as any symbol that contains `d'. + # it will be wrapped by ' (' and ')$', so one must not match beginning or + # end of line. Example: 'a|bc|.*d.*' will exclude the symbols 'a' and 'bc', + # as well as any symbol that contains 'd'. exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out # platforms (ab)use it in PIC code, but their linkers get confused if @@ -8347,7 +9493,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # FIXME: the MSVC++ port hasn't been tested in a loooong time # When not using gcc, we currently assume that we are using # Microsoft Visual C++. - if test "$GCC" != yes; then + if test yes != "$GCC"; then with_gnu_ld=no fi ;; @@ -8355,30 +9501,57 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie # we just hope/assume this is gcc and not c89 (= MSVC++) with_gnu_ld=yes ;; - openbsd*) + openbsd* | bitrig*) with_gnu_ld=no ;; esac ld_shlibs=yes - if test "$with_gnu_ld" = yes; then + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test yes = "$with_gnu_ld"; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test yes = "$lt_use_gnu_ld_interface"; then # If archive_cmds runs LD, not CC, wlarc should be empty - wlarc='${wl}' + wlarc='$wl' # Set some defaults for GNU ld with shared library support. These # are reset later if shared libraries are not supported. Putting them # here allows them to be overridden if necessary. runpath_var=LD_RUN_PATH - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - export_dynamic_flag_spec='${wl}--export-dynamic' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + export_dynamic_flag_spec='$wl--export-dynamic' # ancient GNU ld didn't support --whole-archive et. al. if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then - whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + whole_archive_flag_spec=$wlarc'--whole-archive$convenience '$wlarc'--no-whole-archive' else whole_archive_flag_spec= fi supports_anon_versioning=no - case `$LD -v 2>&1` in + case `$LD -v | $SED -e 's/(^)\+)\s\+//' 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... @@ -8390,15 +9563,16 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie case $host_os in aix[3-9]*) # On AIX/PPC, the GNU linker is very broken - if test "$host_cpu" != ia64; then + if test ia64 != "$host_cpu"; then ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. _LT_EOF fi @@ -8408,7 +9582,7 @@ _LT_EOF case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -8424,7 +9598,7 @@ _LT_EOF allow_undefined_flag=unsupported # Joseph Beckenbach says some releases of gcc # support --undefined. This deserves some investigation. FIXME - archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' else ld_shlibs=no fi @@ -8434,61 +9608,97 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='$wl--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes - export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' - # If the export-symbols file already is a .def file (1st line - # is EXPORTS), use it as is; otherwise, prepend... - archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then - cp $export_symbols $output_objdir/$soname.def; - else - echo EXPORTS > $output_objdir/$soname.def; - cat $export_symbols >> $output_objdir/$soname.def; - fi~ - $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file, use it as + # is; otherwise, prepend EXPORTS... + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname $wl--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' else ld_shlibs=no fi ;; + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes + ;; + interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. # Instead, shared libraries are loaded at an image base (0x10000000 by # default) and relocated if they conflict, which is a slow very memory # consuming and fragmenting process. To avoid this, we pick a random, # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link # time. Moving up from 0x10000000 also allows more sbrk(2) space. - archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' - archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s|^|_|" $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-h,$soname $wl--retain-symbols-file,$output_objdir/$soname.expsym $wl--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - gnu* | linux* | tpf* | k*bsd*-gnu) + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no - if test "$host_os" = linux-dietlibc; then + if test linux-dietlibc = "$host_os"; then case $cc_basename in diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) esac fi if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ - && test "$tmp_diet" = no + && test no = "$tmp_diet" then - tmp_addflag= + tmp_addflag=' $pic_flag' tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag' ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -8499,39 +9709,47 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; - xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + nagfor*) # NAGFOR 5.3 + tmp_sharedflag='-Wl,-shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='$wl--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' + compiler_needs_object=yes + ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='$wl--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` $wl--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 tmp_sharedflag='-G' ;; esac - archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-version-script $wl$output_objdir/$libname.ver -o $lib' fi case $cc_basename in - xlf*) + tcc*) + export_dynamic_flag_spec='-rdynamic' + ;; + xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' - hardcode_libdir_flag_spec= - hardcode_libdir_flag_spec_ld='-rpath $libdir' - archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' - if test "x$supports_anon_versioning" = xyes; then + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test yes = "$supports_anon_versioning"; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ - cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ - echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -8545,8 +9763,8 @@ _LT_EOF archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' wlarc= else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' fi ;; @@ -8564,8 +9782,8 @@ _LT_EOF _LT_EOF elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -8577,7 +9795,7 @@ _LT_EOF ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 cannot *** reliably create shared libraries on SCO systems. Therefore, libtool *** is disabling shared libraries support. We urge you to upgrade GNU *** binutils to release 2.16.91.0.3 or newer. Another option is to modify @@ -8592,9 +9810,9 @@ _LT_EOF # DT_RUNPATH tag from executables and libraries. But doing so # requires that you compile everything twice, which is a pain. if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi @@ -8611,15 +9829,15 @@ _LT_EOF *) if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname $wl-retain-symbols-file $wl$export_symbols -o $lib' else ld_shlibs=no fi ;; esac - if test "$ld_shlibs" = no; then + if test no = "$ld_shlibs"; then runpath_var= hardcode_libdir_flag_spec= export_dynamic_flag_spec= @@ -8635,7 +9853,7 @@ _LT_EOF # Note: this linker hardcodes the directories in LIBPATH if there # are no directories specified by -L. hardcode_minus_L=yes - if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + if test yes = "$GCC" && test -z "$lt_prog_compiler_static"; then # Neither direct hardcoding nor static linking is supported with a # broken collect2. hardcode_direct=unsupported @@ -8643,32 +9861,57 @@ _LT_EOF ;; aix[4-9]*) - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # On IA64, the linker does run time linking by default, so we don't # have to do anything special. aix_use_runtimelinking=no exp_sym_flag='-Bexport' - no_entry_flag="" + no_entry_flag= else # If we're using GNU nm, then we don't want the "-C" option. - # -C means demangle to AIX nm, but means don't demangle with GNU nm + # -C means demangle to GNU nm, but means don't demangle to AIX nm. + # Without the "-l" option, or with the "-B" option, AIX nm treats + # weak defined symbols like other global defined symbols, whereas + # GNU nm marks them as "W". + # While the 'weak' keyword is ignored in the Export File, we need + # it in the Import File for the 'aix-soname' feature, so we have + # to replace the "-B" option with "-P" for AIX nm. if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { if (\$ 2 == "W") { print \$ 3 " weak" } else { print \$ 3 } } }'\'' | sort -u > $export_symbols' else - export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='`func_echo_all $NM | $SED -e '\''s/B\([^B]*\)$/P\1/'\''` -PCpgl $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) && (substr(\$ 1,1,1) != ".")) { if ((\$ 2 == "W") || (\$ 2 == "V") || (\$ 2 == "Z")) { print \$ 1 " weak" } else { print \$ 1 } } }'\'' | sort -u > $export_symbols' fi aix_use_runtimelinking=no # Test if we are trying to use run time linking or normal # AIX style linking. If -brtl is somewhere in LDFLAGS, we - # need to do runtime linking. + # have runtime linking enabled, and use it for executables. + # For shared libraries, we enable/disable runtime linking + # depending on the kind of the shared library created - + # when "with_aix_soname,aix_use_runtimelinking" is: + # "aix,no" lib.a(lib.so.V) shared, rtl:no, for executables + # "aix,yes" lib.so shared, rtl:yes, for executables + # lib.a static archive + # "both,no" lib.so.V(shr.o) shared, rtl:yes + # lib.a(lib.so.V) shared, rtl:no, for executables + # "both,yes" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a(lib.so.V) shared, rtl:no + # "svr4,*" lib.so.V(shr.o) shared, rtl:yes, for executables + # lib.a static archive case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) for ld_flag in $LDFLAGS; do - if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + if (test x-brtl = "x$ld_flag" || test x-Wl,-brtl = "x$ld_flag"); then aix_use_runtimelinking=yes break fi done + if test svr4,no = "$with_aix_soname,$aix_use_runtimelinking"; then + # With aix-soname=svr4, we create the lib.so.V shared archives only, + # so we don't have lib.a shared libs to link our executables. + # We have to force runtime linking in this case. + aix_use_runtimelinking=yes + LDFLAGS="$LDFLAGS -Wl,-brtl" + fi ;; esac @@ -8687,13 +9930,21 @@ _LT_EOF hardcode_direct_absolute=yes hardcode_libdir_separator=':' link_all_deplibs=yes - file_list_spec='${wl}-f,' + file_list_spec='$wl-f,' + case $with_aix_soname,$aix_use_runtimelinking in + aix,*) ;; # traditional, no import file + svr4,* | *,yes) # use import file + # The Import File defines what to hardcode. + hardcode_direct=no + hardcode_direct_absolute=no + ;; + esac - if test "$GCC" = yes; then + if test yes = "$GCC"; then case $host_os in aix4.[012]|aix4.[012].*) # We only want to do this on AIX 4.2 and lower, the check # below for broken collect2 doesn't work under 4.3+ - collect2name=`${CC} -print-prog-name=collect2` + collect2name=`$CC -print-prog-name=collect2` if test -f "$collect2name" && strings "$collect2name" | $GREP resolve_lib_name >/dev/null then @@ -8712,35 +9963,48 @@ _LT_EOF ;; esac shared_flag='-shared' - if test "$aix_use_runtimelinking" = yes; then - shared_flag="$shared_flag "'${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag="$shared_flag "'$wl-G' fi + # Need to ensure runtime linking is disabled for the traditional + # shared library, or the linker may eventually find shared libraries + # /with/ Import File - we do not want to mix them. + shared_flag_aix='-shared' + shared_flag_svr4='-shared $wl-G' else # not using gcc - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release # chokes on -Wl,-G. The following line is correct: shared_flag='-G' else - if test "$aix_use_runtimelinking" = yes; then - shared_flag='${wl}-G' + if test yes = "$aix_use_runtimelinking"; then + shared_flag='$wl-G' else - shared_flag='${wl}-bM:SRE' + shared_flag='$wl-bM:SRE' fi + shared_flag_aix='$wl-bM:SRE' + shared_flag_svr4='$wl-G' fi fi - export_dynamic_flag_spec='${wl}-bexpall' + export_dynamic_flag_spec='$wl-bexpall' # It seems that -bexpall does not export symbols beginning with # underscore (_), so it is better to generate a list of symbols to export. always_export_symbols=yes - if test "$aix_use_runtimelinking" = yes; then + if test aix,yes = "$with_aix_soname,$aix_use_runtimelinking"; then # Warning - without using the other runtime loading flags (-brtl), # -berok will link without error, but may produce a broken library. allow_undefined_flag='-berok' # Determine the default libpath from the value encoded in an # empty executable. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -8753,34 +10017,47 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs $wl'$no_entry_flag' $compiler_flags `if test -n "$allow_undefined_flag"; then func_echo_all "$wl$allow_undefined_flag"; else :; fi` $wl'$exp_sym_flag:\$export_symbols' '$shared_flag else - if test "$host_cpu" = ia64; then - hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + if test ia64 = "$host_cpu"; then + hardcode_libdir_flag_spec='$wl-R $libdir:/usr/lib:/lib' allow_undefined_flag="-z nodefs" - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\$wl$no_entry_flag"' $compiler_flags $wl$allow_undefined_flag '"\$wl$exp_sym_flag:\$export_symbols" else # Determine the default libpath from the value encoded in an # empty executable. - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test set = "${lt_cv_aix_libpath+set}"; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -8793,33 +10070,57 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : -lt_aix_libpath_sed=' - /Import File Strings/,/^$/ { - /^0/ { - s/^0 *\(.*\)$/\1/ - p - } - }' -aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -# Check for a 64-bit object if we didn't find anything. -if test -z "$aix_libpath"; then - aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` -fi + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext -if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=/usr/lib:/lib + fi - hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='$wl-blibpath:$libdir:'"$aix_libpath" # Warning - without using the other run time loading flags, # -berok will link without error, but may produce a broken library. - no_undefined_flag=' ${wl}-bernotok' - allow_undefined_flag=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' + no_undefined_flag=' $wl-bernotok' + allow_undefined_flag=' $wl-berok' + if test yes = "$with_gnu_ld"; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='$wl--whole-archive$convenience $wl--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi archive_cmds_need_lc=yes - # This is similar to how AIX traditionally builds its shared libraries. - archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + archive_expsym_cmds='$RM -r $output_objdir/$realname.d~$MKDIR $output_objdir/$realname.d' + # -brtl affects multiple linker settings, -berok does not and is overridden later + compiler_flags_filtered='`func_echo_all "$compiler_flags " | $SED -e "s%-brtl\\([, ]\\)%-berok\\1%g"`' + if test svr4 != "$with_aix_soname"; then + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_aix' -o $output_objdir/$realname.d/$soname $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$realname.d/$soname' + fi + if test aix != "$with_aix_soname"; then + archive_expsym_cmds="$archive_expsym_cmds"'~$CC '$shared_flag_svr4' -o $output_objdir/$realname.d/$shared_archive_member_spec.o $libobjs $deplibs $wl-bnoentry '$compiler_flags_filtered'$wl-bE:$export_symbols$allow_undefined_flag~$STRIP -e $output_objdir/$realname.d/$shared_archive_member_spec.o~( func_echo_all "#! $soname($shared_archive_member_spec.o)"; if test shr_64 = "$shared_archive_member_spec"; then func_echo_all "# 64"; else func_echo_all "# 32"; fi; cat $export_symbols ) > $output_objdir/$realname.d/$shared_archive_member_spec.imp~$AR $AR_FLAGS $output_objdir/$soname $output_objdir/$realname.d/$shared_archive_member_spec.o $output_objdir/$realname.d/$shared_archive_member_spec.imp' + else + # used by -dlpreopen to get the symbols + archive_expsym_cmds="$archive_expsym_cmds"'~$MV $output_objdir/$realname.d/$soname $output_objdir' + fi + archive_expsym_cmds="$archive_expsym_cmds"'~$RM -r $output_objdir/$realname.d' fi fi ;; @@ -8828,7 +10129,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi case $host_cpu in powerpc) # see comment about AmigaOS4 .so support - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags $wl-soname $wl$soname -o $lib' archive_expsym_cmds='' ;; m68k) @@ -8848,20 +10149,65 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # Microsoft Visual C++. # hardcode_libdir_flag_spec is actually meaningless, as there is # no search path for DLLs. - hardcode_libdir_flag_spec=' ' - allow_undefined_flag=unsupported - # Tell ltmain to make .lib files, not .a files. - libext=lib - # Tell ltmain to make .dll files, not .so files. - shrext_cmds=".dll" - # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' - # The linker will automatically build a .lib file if we build a DLL. - old_archive_from_new_cmds='true' - # FIXME: Should let the user specify the lib program. - old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' - fix_srcfile_path='`cygpath -w "$srcfile"`' - enable_shared_with_static_runtimes=yes + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~linknames=' + archive_expsym_cmds='if test DEF = "`$SED -n -e '\''s/^[ ]*//'\'' -e '\''/^\(;.*\)*$/d'\'' -e '\''s/^\(EXPORTS\|LIBRARY\)\([ ].*\)*$/DEF/p'\'' -e q $export_symbols`" ; then + cp "$export_symbols" "$output_objdir/$soname.def"; + echo "$tool_output_objdir$soname.def" > "$output_objdir/$soname.exp"; + else + $SED -e '\''s/^/-link -EXPORT:/'\'' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + exclude_expsyms='_NULL_IMPORT_DESCRIPTOR|_IMPORT_DESCRIPTOR_.*' + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile=$lt_outputfile.exe + lt_tool_outputfile=$lt_tool_outputfile.exe + ;; + esac~ + if test : != "$MANIFEST_TOOL" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=.dll + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac ;; darwin* | rhapsody*) @@ -8871,19 +10217,24 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='' + if test yes = "$lt_cv_ld_force_load"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience $wl-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + + else + whole_archive_flag_spec='' + fi link_all_deplibs=yes - allow_undefined_flag="$_lt_dar_allow_undefined" + allow_undefined_flag=$_lt_dar_allow_undefined case $cc_basename in - ifort*) _lt_dar_can_shared=yes ;; + ifort*|nagfor*) _lt_dar_can_shared=yes ;; *) _lt_dar_can_shared=$GCC ;; esac - if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=echo - archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" - module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" - archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" - module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + if test yes = "$_lt_dar_can_shared"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dsymutil" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dsymutil" + archive_expsym_cmds="sed 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod$_lt_dar_export_syms$_lt_dsymutil" + module_expsym_cmds="sed -e 's|^|_|' < \$export_symbols > \$output_objdir/\$libname-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags$_lt_dar_export_syms$_lt_dsymutil" else ld_shlibs=no @@ -8897,10 +10248,6 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_shlibpath_var=no ;; - freebsd1*) - ld_shlibs=no - ;; - # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor # support. Future versions do this automatically, but an explicit c++rt0.o # does not break anything, and helps significantly (at the cost of a little @@ -8913,7 +10260,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; # Unfortunately, older versions of FreeBSD 2 do not have this feature. - freebsd2*) + freebsd2.*) archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes hardcode_minus_L=yes @@ -8922,41 +10269,40 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # FreeBSD 3 and greater uses gcc -shared to do shared libraries. freebsd* | dragonfly*) - archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' hardcode_libdir_flag_spec='-R$libdir' hardcode_direct=yes hardcode_shlibpath_var=no ;; hpux9*) - if test "$GCC" = yes; then - archive_cmds='$RM $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + if test yes = "$GCC"; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag $wl+b $wl$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' else - archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test "x$output_objdir/$soname" = "x$lib" || mv $output_objdir/$soname $lib' fi - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' ;; hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + if test yes,no = "$GCC,$with_gnu_ld"; then + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' - hardcode_libdir_flag_spec_ld='+b $libdir' + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. hardcode_minus_L=yes @@ -8964,33 +10310,72 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then + if test yes,no = "$GCC,$with_gnu_ld"; then case $host_cpu in hppa*64*) - archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -shared $pic_flag $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' ;; esac else case $host_cpu in hppa*64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b $wl+h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' ;; ia64*) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -b $wl+h $wl$soname $wl+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS=$save_LDFLAGS + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test yes = "$lt_cv_prog_compiler__b"; then + archive_cmds='$CC -b $wl+h $wl$soname $wl+b $wl$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + ;; esac fi - if test "$with_gnu_ld" = no; then - hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + if test no = "$with_gnu_ld"; then + hardcode_libdir_flag_spec='$wl+b $wl$libdir' hardcode_libdir_separator=: case $host_cpu in @@ -9001,7 +10386,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi *) hardcode_direct=yes hardcode_direct_absolute=yes - export_dynamic_flag_spec='${wl}-E' + export_dynamic_flag_spec='$wl-E' # hardcode_minus_L: Not really in the search PATH, # but as the default location of the library. @@ -9012,35 +10397,58 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; irix5* | irix6* | nonstopux*) - if test "$GCC" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. - save_LDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS=$LDFLAGS + LDFLAGS="$LDFLAGS -shared $wl-exported_symbol ${wl}foo $wl-update_registry $wl/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -int foo(void) {} +int foo (void) { return 0; } _ACEOF if ac_fn_c_try_link "$LINENO"; then : - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' - + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS="$save_LDFLAGS" + LDFLAGS=$save_LDFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test yes = "$lt_cv_irix_exported_symbol"; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations $wl-exports_file $wl$export_symbols -o $lib' + fi else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: inherit_rpath=yes link_all_deplibs=yes ;; + linux*) + case $cc_basename in + tcc*) + # Fabrice Bellard et al's Tiny C Compiler + ld_shlibs=yes + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + netbsd*) if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out @@ -9055,7 +10463,7 @@ rm -f core conftest.err conftest.$ac_objext \ newsos6) archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' hardcode_direct=yes - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: hardcode_shlibpath_var=no ;; @@ -9063,27 +10471,19 @@ rm -f core conftest.err conftest.$ac_objext \ *nto* | *qnx*) ;; - openbsd*) + openbsd* | bitrig*) if test -f /usr/libexec/ld.so; then hardcode_direct=yes hardcode_shlibpath_var=no hardcode_direct_absolute=yes - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - export_dynamic_flag_spec='${wl}-E' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags $wl-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' + export_dynamic_flag_spec='$wl-E' else - case $host_os in - openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) - archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' - hardcode_libdir_flag_spec='-R$libdir' - ;; - *) - archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' - hardcode_libdir_flag_spec='${wl}-rpath,$libdir' - ;; - esac + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='$wl-rpath,$libdir' fi else ld_shlibs=no @@ -9094,33 +10494,53 @@ rm -f core conftest.err conftest.$ac_objext \ hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported - archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' - old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + shrext_cmds=.dll + archive_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + emxexp $libobjs | $SED /"_DLL_InitTerm"/d >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + archive_expsym_cmds='$ECHO "LIBRARY ${soname%$shared_ext} INITINSTANCE TERMINSTANCE" > $output_objdir/$libname.def~ + $ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~ + $ECHO "DATA MULTIPLE NONSHARED" >> $output_objdir/$libname.def~ + $ECHO EXPORTS >> $output_objdir/$libname.def~ + prefix_cmds="$SED"~ + if test EXPORTS = "`$SED 1q $export_symbols`"; then + prefix_cmds="$prefix_cmds -e 1d"; + fi~ + prefix_cmds="$prefix_cmds -e \"s/^\(.*\)$/_\1/g\""~ + cat $export_symbols | $prefix_cmds >> $output_objdir/$libname.def~ + $CC -Zdll -Zcrtdll -o $output_objdir/$soname $libobjs $deplibs $compiler_flags $output_objdir/$libname.def~ + emximp -o $lib $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/${libname}_dll.a $output_objdir/$libname.def' + enable_shared_with_static_runtimes=yes ;; osf3*) - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' fi archive_cmds_need_lc='no' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' hardcode_libdir_separator=: ;; osf4* | osf5*) # as osf3* with the addition of -msym flag - if test "$GCC" = yes; then - allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' - hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + if test yes = "$GCC"; then + allow_undefined_flag=' $wl-expect_unresolved $wl\*' + archive_cmds='$CC -shared$allow_undefined_flag $pic_flag $libobjs $deplibs $compiler_flags $wl-msym $wl-soname $wl$soname `test -n "$verstring" && func_echo_all "$wl-set_version $wl$verstring"` $wl-update_registry $wl$output_objdir/so_locations -o $lib' + hardcode_libdir_flag_spec='$wl-rpath $wl$libdir' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared$allow_undefined_flag $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared$allow_undefined_flag $wl-input $wl$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry $output_objdir/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -9131,24 +10551,24 @@ rm -f core conftest.err conftest.$ac_objext \ solaris*) no_undefined_flag=' -z defs' - if test "$GCC" = yes; then - wlarc='${wl}' - archive_cmds='$CC -shared ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + wlarc='$wl' + archive_cmds='$CC -shared $pic_flag $wl-z ${wl}text $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -shared ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -shared $pic_flag $wl-z ${wl}text $wl-M $wl$lib.exp $wl-h $wl$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' else case `$CC -V 2>&1` in *"Compilers 5.0"*) wlarc='' - archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_cmds='$LD -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $linker_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + $LD -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' ;; *) - wlarc='${wl}' - archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + wlarc='$wl' + archive_cmds='$CC -G$allow_undefined_flag -h $soname -o $lib $libobjs $deplibs $compiler_flags' archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ - $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + $CC -G$allow_undefined_flag -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' ;; esac fi @@ -9158,11 +10578,11 @@ rm -f core conftest.err conftest.$ac_objext \ solaris2.[0-5] | solaris2.[0-5].*) ;; *) # The compiler driver will combine and reorder linker options, - # but understands `-z linker_flag'. GCC discards it without `$wl', + # but understands '-z linker_flag'. GCC discards it without '$wl', # but is careful enough not to reorder. # Supported since Solaris 2.6 (maybe 2.5.1?) - if test "$GCC" = yes; then - whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + if test yes = "$GCC"; then + whole_archive_flag_spec='$wl-z ${wl}allextract$convenience $wl-z ${wl}defaultextract' else whole_archive_flag_spec='-z allextract$convenience -z defaultextract' fi @@ -9172,10 +10592,10 @@ rm -f core conftest.err conftest.$ac_objext \ ;; sunos4*) - if test "x$host_vendor" = xsequent; then + if test sequent = "$host_vendor"; then # Use $CC to link under sequent, because it throws in some extra .o # files that make .init and .fini sections work. - archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h $soname -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' fi @@ -9224,43 +10644,43 @@ rm -f core conftest.err conftest.$ac_objext \ ;; sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) - no_undefined_flag='${wl}-z,text' + no_undefined_flag='$wl-z,text' archive_cmds_need_lc=no hardcode_shlibpath_var=no runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; sysv5* | sco3.2v5* | sco5v6*) - # Note: We can NOT use -z defs as we might desire, because we do not + # Note: We CANNOT use -z defs as we might desire, because we do not # link with -lc, and that would cause any symbols used from libc to # always be unresolved, which means just about no library would # ever link correctly. If we're not using GNU ld we use -z text # though, which does catch some bad symbols but isn't as heavy-handed # as -z defs. - no_undefined_flag='${wl}-z,text' - allow_undefined_flag='${wl}-z,nodefs' + no_undefined_flag='$wl-z,text' + allow_undefined_flag='$wl-z,nodefs' archive_cmds_need_lc=no hardcode_shlibpath_var=no - hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_flag_spec='$wl-R,$libdir' hardcode_libdir_separator=':' link_all_deplibs=yes - export_dynamic_flag_spec='${wl}-Bexport' + export_dynamic_flag_spec='$wl-Bexport' runpath_var='LD_RUN_PATH' - if test "$GCC" = yes; then - archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + if test yes = "$GCC"; then + archive_cmds='$CC -shared $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' else - archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' - archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_cmds='$CC -G $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G $wl-Bexport:$export_symbols $wl-h,$soname -o $lib $libobjs $deplibs $compiler_flags' fi ;; @@ -9275,10 +10695,10 @@ rm -f core conftest.err conftest.$ac_objext \ ;; esac - if test x$host_vendor = xsni; then + if test sni = "$host_vendor"; then case $host in sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) - export_dynamic_flag_spec='${wl}-Blargedynsym' + export_dynamic_flag_spec='$wl-Blargedynsym' ;; esac fi @@ -9286,7 +10706,7 @@ rm -f core conftest.err conftest.$ac_objext \ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 $as_echo "$ld_shlibs" >&6; } -test "$ld_shlibs" = no && can_build_shared=no +test no = "$ld_shlibs" && can_build_shared=no with_gnu_ld=$with_gnu_ld @@ -9312,7 +10732,7 @@ x|xyes) # Assume -lc should be added archive_cmds_need_lc=yes - if test "$enable_shared" = yes && test "$GCC" = yes; then + if test yes,yes = "$GCC,$enable_shared"; then case $archive_cmds in *'~'*) # FIXME: we may have to deal with multi-command sequences. @@ -9323,44 +10743,50 @@ x|xyes) # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - then - archive_cmds_need_lc=no - else - archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 -$as_echo "$archive_cmds_need_lc" >&6; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi @@ -9512,11 +10938,6 @@ esac - - - - - @@ -9526,44 +10947,58 @@ esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 $as_echo_n "checking dynamic linker characteristics... " >&6; } -if test "$GCC" = yes; then +if test yes = "$GCC"; then case $host_os in - darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; - *) lt_awk_arg="/^libraries:/" ;; + darwin*) lt_awk_arg='/^libraries:/,/LR/' ;; + *) lt_awk_arg='/^libraries:/' ;; esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq='s|=\([A-Za-z]:\)|\1|g' ;; + *) lt_sed_strip_eq='s|=/|/|g' ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac # Ok, now we have the path, separated by spaces, we can step through it - # and add multilib dir if necessary. + # and add multilib dir if necessary... lt_tmp_lt_search_path_spec= - lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + lt_multi_os_dir=/`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + # ...but if some path component already ends with the multilib dir we assume + # that all is fine and trust -print-search-dirs as is (GCC 4.2? or newer). + case "$lt_multi_os_dir; $lt_search_path_spec " in + "/; "* | "/.; "* | "/./; "* | *"$lt_multi_os_dir "* | *"$lt_multi_os_dir/ "*) + lt_multi_os_dir= + ;; + esac for lt_sys_path in $lt_search_path_spec; do - if test -d "$lt_sys_path/$lt_multi_os_dir"; then - lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" - else + if test -d "$lt_sys_path$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path$lt_multi_os_dir" + elif test -n "$lt_multi_os_dir"; then test -d "$lt_sys_path" && \ lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done - lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' -BEGIN {RS=" "; FS="/|\n";} { - lt_foo=""; - lt_count=0; + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS = " "; FS = "/|\n";} { + lt_foo = ""; + lt_count = 0; for (lt_i = NF; lt_i > 0; lt_i--) { if ($lt_i != "" && $lt_i != ".") { if ($lt_i == "..") { lt_count++; } else { if (lt_count == 0) { - lt_foo="/" $lt_i lt_foo; + lt_foo = "/" $lt_i lt_foo; } else { lt_count--; } @@ -9573,14 +11008,20 @@ BEGIN {RS=" "; FS="/|\n";} { if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` - sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's|/\([A-Za-z]:\)|\1|g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi library_names_spec= libname_spec='lib$name' soname_spec= -shrext_cmds=".so" +shrext_cmds=.so postinstall_cmds= postuninstall_cmds= finish_cmds= @@ -9597,56 +11038,108 @@ hardcode_into_libs=no # flags to be left without arguments need_version=unknown + + case $host_os in aix3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname.a' shlibpath_var=LIBPATH # AIX 3 has no versioning support, so we append a major version to the name. - soname_spec='${libname}${release}${shared_ext}$major' + soname_spec='$libname$release$shared_ext$major' ;; aix[4-9]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no hardcode_into_libs=yes - if test "$host_cpu" = ia64; then + if test ia64 = "$host_cpu"; then # AIX 5 supports IA64 - library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$major $libname$release$shared_ext$versuffix $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH else # With GCC up to 2.95.x, collect2 would create an import file # for dependence libraries. The import file would start with - # the line `#! .'. This would cause the generated library to - # depend on `.', always an invalid library. This was fixed in + # the line '#! .'. This would cause the generated library to + # depend on '.', always an invalid library. This was fixed in # development snapshots of GCC prior to 3.0. case $host_os in aix4 | aix4.[01] | aix4.[01].*) if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' echo ' yes ' - echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + echo '#endif'; } | $CC -E - | $GREP yes > /dev/null; then : else can_build_shared=no fi ;; esac - # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # Using Import Files as archive members, it is possible to support + # filename-based versioning of shared library archives on AIX. While + # this would work for both with and without runtime linking, it will + # prevent static linking of such archives. So we do filename-based + # shared library versioning with .so extension only, which is used + # when both runtime linking and shared linking is enabled. + # Unfortunately, runtime linking may impact performance, so we do + # not want this to be the default eventually. Also, we use the + # versioned .so libs for executables only if there is the -brtl + # linker flag in LDFLAGS as well, or --with-aix-soname=svr4 only. + # To allow for filename-based versioning support, we need to create + # libNAME.so.V as an archive file, containing: + # *) an Import File, referring to the versioned filename of the + # archive as well as the shared archive member, telling the + # bitwidth (32 or 64) of that shared object, and providing the + # list of exported symbols of that shared object, eventually + # decorated with the 'weak' keyword + # *) the shared object with the F_LOADONLY flag set, to really avoid + # it being seen by the linker. + # At run time we better use the real file rather than another symlink, + # but for link time we create the symlink libNAME.so -> libNAME.so.V + + case $with_aix_soname,$aix_use_runtimelinking in + # AIX (on Power*) has no versioning support, so currently we cannot hardcode correct # soname into executable. Probably we can add versioning support to # collect2, so additional links can be useful in future. - if test "$aix_use_runtimelinking" = yes; then + aix,yes) # traditional libtool + dynamic_linker='AIX unversionable lib.so' # If using run time linking (on AIX 4.2 or later) use lib.so # instead of lib.a to let people know that these are not # typical AIX shared libraries. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - else + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + ;; + aix,no) # traditional AIX only + dynamic_linker='AIX lib.a(lib.so.V)' # We preserve .a as extension for shared libraries through AIX4.2 # and later when we are not doing run time linking. - library_names_spec='${libname}${release}.a $libname.a' - soname_spec='${libname}${release}${shared_ext}$major' - fi + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + ;; + svr4,*) # full svr4 only + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,yes) # both, prefer svr4 + dynamic_linker="AIX lib.so.V($shared_archive_member_spec.o), lib.a(lib.so.V)" + library_names_spec='$libname$release$shared_ext$major $libname$shared_ext' + # unpreferred sharedlib libNAME.a needs extra handling + postinstall_cmds='test -n "$linkname" || linkname="$realname"~func_stripname "" ".so" "$linkname"~$install_shared_prog "$dir/$func_stripname_result.$libext" "$destdir/$func_stripname_result.$libext"~test -z "$tstripme" || test -z "$striplib" || $striplib "$destdir/$func_stripname_result.$libext"' + postuninstall_cmds='for n in $library_names $old_library; do :; done~func_stripname "" ".so" "$n"~test "$func_stripname_result" = "$n" || func_append rmfiles " $odir/$func_stripname_result.$libext"' + # We do not specify a path in Import Files, so LIBPATH fires. + shlibpath_overrides_runpath=yes + ;; + *,no) # both, prefer aix + dynamic_linker="AIX lib.a(lib.so.V), lib.so.V($shared_archive_member_spec.o)" + library_names_spec='$libname$release.a $libname.a' + soname_spec='$libname$release$shared_ext$major' + # unpreferred sharedlib libNAME.so.V and symlink libNAME.so need extra handling + postinstall_cmds='test -z "$dlname" || $install_shared_prog $dir/$dlname $destdir/$dlname~test -z "$tstripme" || test -z "$striplib" || $striplib $destdir/$dlname~test -n "$linkname" || linkname=$realname~func_stripname "" ".a" "$linkname"~(cd "$destdir" && $LN_S -f $dlname $func_stripname_result.so)' + postuninstall_cmds='test -z "$dlname" || func_append rmfiles " $odir/$dlname"~for n in $old_library $library_names; do :; done~func_stripname "" ".a" "$n"~func_append rmfiles " $odir/$func_stripname_result.so"' + ;; + esac shlibpath_var=LIBPATH fi ;; @@ -9656,27 +11149,27 @@ amigaos*) powerpc) # Since July 2007 AmigaOS4 officially supports .so libraries. # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' ;; m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; beos*) - library_names_spec='${libname}${shared_ext}' + library_names_spec='$libname$shared_ext' dynamic_linker="$host_os ld.so" shlibpath_var=LIBRARY_PATH ;; bsdi[45]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" @@ -9688,16 +11181,17 @@ bsdi[45]*) cygwin* | mingw* | pw32* | cegcc*) version_type=windows - shrext_cmds=".dll" + shrext_cmds=.dll need_version=no need_lib_prefix=no - case $GCC,$host_os in - yes,cygwin* | yes,mingw* | yes,pw32* | yes,cegcc*) + case $GCC,$cc_basename in + yes,*) + # gcc library_names_spec='$libname.dll.a' # DLL is installed to $(libdir)/../bin by postinstall_cmds - postinstall_cmds='base_file=`basename \${file}`~ - dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ dldir=$destdir/`dirname \$dlpath`~ test -d \$dldir || mkdir -p \$dldir~ $install_prog $dir/$dlname \$dldir/$dlname~ @@ -9713,37 +11207,84 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + soname_spec='`echo $libname | sed -e 's/^lib/cyg/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' - library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='`echo $libname | sed -e 's/^lib/pw/'``echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' ;; esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext' + library_names_spec='$libname.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec=$LIB + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' ;; *) - library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + # Assume MSVC wrapper + library_names_spec='$libname`echo $release | $SED -e 's/[.]/-/g'`$versuffix$shared_ext $libname.lib' + dynamic_linker='Win32 ld.exe' ;; esac - dynamic_linker='Win32 ld.exe' # FIXME: first we should search . and the directory the executable is in shlibpath_var=PATH ;; @@ -9753,8 +11294,8 @@ darwin* | rhapsody*) version_type=darwin need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' - soname_spec='${libname}${release}${major}$shared_ext' + library_names_spec='$libname$release$major$shared_ext $libname$shared_ext' + soname_spec='$libname$release$major$shared_ext' shlibpath_overrides_runpath=yes shlibpath_var=DYLD_LIBRARY_PATH shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' @@ -9764,18 +11305,14 @@ darwin* | rhapsody*) ;; dgux*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; -freebsd1*) - dynamic_linker=no - ;; - freebsd* | dragonfly*) # DragonFly does not have aout. When/if they implement a new # versioning mechanism, adjust this. @@ -9783,25 +11320,26 @@ freebsd* | dragonfly*) objformat=`/usr/bin/objformat` else case $host_os in - freebsd[123]*) objformat=aout ;; + freebsd[23].*) objformat=aout ;; *) objformat=elf ;; esac fi version_type=freebsd-$objformat case $version_type in freebsd-elf*) - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' need_version=no need_lib_prefix=no ;; freebsd-*) - library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' need_version=yes ;; esac shlibpath_var=LD_LIBRARY_PATH case $host_os in - freebsd2*) + freebsd2.*) shlibpath_overrides_runpath=yes ;; freebsd3.[01]* | freebsdelf3.[01]*) @@ -9820,13 +11358,16 @@ freebsd* | dragonfly*) esac ;; -gnu*) - version_type=linux +haiku*) + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - shlibpath_var=LD_LIBRARY_PATH + dynamic_linker="$host_os runtime_loader" + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=no + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' hardcode_into_libs=yes ;; @@ -9843,14 +11384,15 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.so" shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' - if test "X$HPUX_IA64_MODE" = X32; then + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' + if test 32 = "$HPUX_IA64_MODE"; then sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + sys_lib_dlsearch_path_spec=/usr/lib/hpux32 else sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + sys_lib_dlsearch_path_spec=/usr/lib/hpux64 fi - sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; hppa*64*) shrext_cmds='.sl' @@ -9858,8 +11400,8 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; @@ -9868,20 +11410,22 @@ hpux9* | hpux10* | hpux11*) dynamic_linker="$host_os dld.sl" shlibpath_var=SHLIB_PATH shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' ;; esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 ;; interix[3-9]*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no @@ -9892,16 +11436,16 @@ irix5* | irix6* | nonstopux*) case $host_os in nonstopux*) version_type=nonstopux ;; *) - if test "$lt_cv_prog_gnu_ld" = yes; then - version_type=linux + if test yes = "$lt_cv_prog_gnu_ld"; then + version_type=linux # correct to gnu/linux during the next big refactor else version_type=irix fi ;; esac need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$release$shared_ext $libname$shared_ext' case $host_os in irix5* | nonstopux*) libsuff= shlibsuff= @@ -9920,8 +11464,8 @@ irix5* | irix6* | nonstopux*) esac shlibpath_var=LD_LIBRARY${shlibsuff}_PATH shlibpath_overrides_runpath=no - sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" - sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + sys_lib_search_path_spec="/usr/lib$libsuff /lib$libsuff /usr/local/lib$libsuff" + sys_lib_dlsearch_path_spec="/usr/lib$libsuff /lib$libsuff" hardcode_into_libs=yes ;; @@ -9930,22 +11474,47 @@ linux*oldld* | linux*aout* | linux*coff*) dynamic_linker=no ;; -# This must be Linux ELF. -linux* | k*bsd*-gnu) - version_type=linux +linux*android*) + version_type=none # Android doesn't support versioned libraries. need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext' + soname_spec='$libname$release$shared_ext' + finish_cmds= + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + dynamic_linker='Android linker' + # Don't embed -rpath directories since the linker doesn't support them. + hardcode_libdir_flag_spec='-L$libdir' + ;; + +# This must be glibc/ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu | gnu*) + version_type=linux # correct to gnu/linux during the next big refactor + need_lib_prefix=no + need_version=no + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -9958,22 +11527,31 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - shlibpath_overrides_runpath=yes + lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install # before this can be enabled. hardcode_into_libs=yes - # Append ld.so.conf contents to the search path + # Ideally, we could use ldconfig to report *all* directores which are + # searched for libraries, however this is still not possible. Aside from not + # being certain /sbin/ldconfig is available, command + # 'ldconfig -N -X -v | grep ^/' on 64bit Fedora does not report /usr/lib64, + # even though it is searched at run-time. Try to do the best guess by + # appending ld.so.conf contents (and includes) to the search path. if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi @@ -9991,12 +11569,12 @@ netbsd*) need_lib_prefix=no need_version=no if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' dynamic_linker='NetBSD (a.out) ld.so' else - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' dynamic_linker='NetBSD ld.elf_so' fi shlibpath_var=LD_LIBRARY_PATH @@ -10005,8 +11583,8 @@ netbsd*) ;; newsos6) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes ;; @@ -10015,58 +11593,68 @@ newsos6) version_type=qnx need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes dynamic_linker='ldqnx.so' ;; -openbsd*) +openbsd* | bitrig*) version_type=sunos - sys_lib_dlsearch_path_spec="/usr/lib" + sys_lib_dlsearch_path_spec=/usr/lib need_lib_prefix=no - # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. - case $host_os in - openbsd3.3 | openbsd3.3.*) need_version=yes ;; - *) need_version=no ;; - esac - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`"; then + need_version=no + else + need_version=yes + fi + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' shlibpath_var=LD_LIBRARY_PATH - if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then - case $host_os in - openbsd2.[89] | openbsd2.[89].*) - shlibpath_overrides_runpath=no - ;; - *) - shlibpath_overrides_runpath=yes - ;; - esac - else - shlibpath_overrides_runpath=yes - fi + shlibpath_overrides_runpath=yes ;; os2*) libname_spec='$name' - shrext_cmds=".dll" + version_type=windows + shrext_cmds=.dll + need_version=no need_lib_prefix=no - library_names_spec='$libname${shared_ext} $libname.a' + # OS/2 can only load a DLL with a base name of 8 characters or less. + soname_spec='`test -n "$os2dllname" && libname="$os2dllname"; + v=$($ECHO $release$versuffix | tr -d .-); + n=$($ECHO $libname | cut -b -$((8 - ${#v})) | tr . _); + $ECHO $n$v`$shared_ext' + library_names_spec='${libname}_dll.$libext' dynamic_linker='OS/2 ld.exe' - shlibpath_var=LIBPATH + shlibpath_var=BEGINLIBPATH + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + postinstall_cmds='base_file=`basename \$file`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\$base_file'\''i; $ECHO \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; $ECHO \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' ;; osf3* | osf4* | osf5*) version_type=osf need_lib_prefix=no need_version=no - soname_spec='${libname}${release}${shared_ext}$major' - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='$libname$release$shared_ext$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" - sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec ;; rdos*) @@ -10074,11 +11662,11 @@ rdos*) ;; solaris*) - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes @@ -10088,20 +11676,20 @@ solaris*) sunos4*) version_type=sunos - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + library_names_spec='$libname$release$shared_ext$versuffix $libname$shared_ext$versuffix' finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then need_lib_prefix=no fi need_version=yes ;; sysv4 | sysv4.3*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH case $host_vendor in sni) @@ -10122,24 +11710,24 @@ sysv4 | sysv4.3*) ;; sysv4*MP*) - if test -d /usr/nec ;then - version_type=linux - library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' - soname_spec='$libname${shared_ext}.$major' + if test -d /usr/nec; then + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$shared_ext.$versuffix $libname$shared_ext.$major $libname$shared_ext' + soname_spec='$libname$shared_ext.$major' shlibpath_var=LD_LIBRARY_PATH fi ;; sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) - version_type=freebsd-elf + version_type=sco need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=yes hardcode_into_libs=yes - if test "$with_gnu_ld" = yes; then + if test yes = "$with_gnu_ld"; then sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' else sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' @@ -10154,19 +11742,19 @@ sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) tpf*) # TPF is a cross-target only. Preferred cross-host = GNU/Linux. - version_type=linux + version_type=linux # correct to gnu/linux during the next big refactor need_lib_prefix=no need_version=no - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no hardcode_into_libs=yes ;; uts4*) - version_type=linux - library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' - soname_spec='${libname}${release}${shared_ext}$major' + version_type=linux # correct to gnu/linux during the next big refactor + library_names_spec='$libname$release$shared_ext$versuffix $libname$release$shared_ext$major $libname$shared_ext' + soname_spec='$libname$release$shared_ext$major' shlibpath_var=LD_LIBRARY_PATH ;; @@ -10176,20 +11764,40 @@ uts4*) esac { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 $as_echo "$dynamic_linker" >&6; } -test "$dynamic_linker" = no && can_build_shared=no +test no = "$dynamic_linker" && can_build_shared=no variables_saved_for_relink="PATH $shlibpath_var $runpath_var" -if test "$GCC" = yes; then +if test yes = "$GCC"; then variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" fi -if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then - sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +if test set = "${lt_cv_sys_lib_search_path_spec+set}"; then + sys_lib_search_path_spec=$lt_cv_sys_lib_search_path_spec fi -if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then - sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" + +if test set = "${lt_cv_sys_lib_dlsearch_path_spec+set}"; then + sys_lib_dlsearch_path_spec=$lt_cv_sys_lib_dlsearch_path_spec fi +# remember unaugmented sys_lib_dlsearch_path content for libtool script decls... +configure_time_dlsearch_path=$sys_lib_dlsearch_path_spec + +# ... but it needs LT_SYS_LIBRARY_PATH munging for other configure-time code +func_munge_path_list sys_lib_dlsearch_path_spec "$LT_SYS_LIBRARY_PATH" + +# to be used as default LT_SYS_LIBRARY_PATH value in generated libtool +configure_time_lt_sys_library_path=$LT_SYS_LIBRARY_PATH + + + + + + + + + + + @@ -10281,15 +11889,15 @@ $as_echo_n "checking how to hardcode library paths into programs... " >&6; } hardcode_action= if test -n "$hardcode_libdir_flag_spec" || test -n "$runpath_var" || - test "X$hardcode_automatic" = "Xyes" ; then + test yes = "$hardcode_automatic"; then # We can hardcode non-existent directories. - if test "$hardcode_direct" != no && + if test no != "$hardcode_direct" && # If the only mechanism to avoid hardcoding is shlibpath_var, we # have to relink, otherwise we might link with an installed library # when we should be linking with a yet-to-be-installed one - ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && - test "$hardcode_minus_L" != no; then + ## test no != "$_LT_TAGVAR(hardcode_shlibpath_var, )" && + test no != "$hardcode_minus_L"; then # Linking always hardcodes the temporary library directory. hardcode_action=relink else @@ -10304,12 +11912,12 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 $as_echo "$hardcode_action" >&6; } -if test "$hardcode_action" = relink || - test "$inherit_rpath" = yes; then +if test relink = "$hardcode_action" || + test yes = "$inherit_rpath"; then # Fast installation is not supported enable_fast_install=no -elif test "$shlibpath_overrides_runpath" = yes || - test "$enable_shared" = no; then +elif test yes = "$shlibpath_overrides_runpath" || + test no = "$enable_shared"; then # Fast installation is not necessary enable_fast_install=needless fi @@ -10319,7 +11927,7 @@ fi - if test "x$enable_dlopen" != xyes; then + if test yes != "$enable_dlopen"; then enable_dlopen=unknown enable_dlopen_self=unknown enable_dlopen_self_static=unknown @@ -10329,26 +11937,26 @@ else case $host_os in beos*) - lt_cv_dlopen="load_add_on" + lt_cv_dlopen=load_add_on lt_cv_dlopen_libs= lt_cv_dlopen_self=yes ;; mingw* | pw32* | cegcc*) - lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen=LoadLibrary lt_cv_dlopen_libs= ;; cygwin*) - lt_cv_dlopen="dlopen" + lt_cv_dlopen=dlopen lt_cv_dlopen_libs= ;; darwin*) - # if libdl is installed we need to link against it + # if libdl is installed we need to link against it { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then : +if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -10382,11 +11990,11 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else - lt_cv_dlopen="dyld" + lt_cv_dlopen=dyld lt_cv_dlopen_libs= lt_cv_dlopen_self=yes @@ -10394,14 +12002,22 @@ fi ;; + tpf*) + # Don't try to run any link tests for TPF. We know it's impossible + # because TPF is a cross-compiler, and we know how we open DSOs. + lt_cv_dlopen=dlopen + lt_cv_dlopen_libs= + lt_cv_dlopen_self=no + ;; + *) ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" -if test "x$ac_cv_func_shl_load" = x""yes; then : - lt_cv_dlopen="shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen=shl_load else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 $as_echo_n "checking for shl_load in -ldld... " >&6; } -if test "${ac_cv_lib_dld_shl_load+set}" = set; then : +if ${ac_cv_lib_dld_shl_load+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -10435,16 +12051,16 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 $as_echo "$ac_cv_lib_dld_shl_load" >&6; } -if test "x$ac_cv_lib_dld_shl_load" = x""yes; then : - lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen=shl_load lt_cv_dlopen_libs=-ldld else ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" -if test "x$ac_cv_func_dlopen" = x""yes; then : - lt_cv_dlopen="dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen=dlopen else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 $as_echo_n "checking for dlopen in -ldl... " >&6; } -if test "${ac_cv_lib_dl_dlopen+set}" = set; then : +if ${ac_cv_lib_dl_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -10478,12 +12094,12 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 $as_echo "$ac_cv_lib_dl_dlopen" >&6; } -if test "x$ac_cv_lib_dl_dlopen" = x""yes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-ldl else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 $as_echo_n "checking for dlopen in -lsvld... " >&6; } -if test "${ac_cv_lib_svld_dlopen+set}" = set; then : +if ${ac_cv_lib_svld_dlopen+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -10517,12 +12133,12 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 $as_echo "$ac_cv_lib_svld_dlopen" >&6; } -if test "x$ac_cv_lib_svld_dlopen" = x""yes; then : - lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen=dlopen lt_cv_dlopen_libs=-lsvld else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 $as_echo_n "checking for dld_link in -ldld... " >&6; } -if test "${ac_cv_lib_dld_dld_link+set}" = set; then : +if ${ac_cv_lib_dld_dld_link+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -10556,8 +12172,8 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 $as_echo "$ac_cv_lib_dld_dld_link" >&6; } -if test "x$ac_cv_lib_dld_dld_link" = x""yes; then : - lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen=dld_link lt_cv_dlopen_libs=-ldld fi @@ -10578,35 +12194,35 @@ fi ;; esac - if test "x$lt_cv_dlopen" != xno; then - enable_dlopen=yes - else + if test no = "$lt_cv_dlopen"; then enable_dlopen=no + else + enable_dlopen=yes fi case $lt_cv_dlopen in dlopen) - save_CPPFLAGS="$CPPFLAGS" - test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + save_CPPFLAGS=$CPPFLAGS + test yes = "$ac_cv_header_dlfcn_h" && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" - save_LDFLAGS="$LDFLAGS" + save_LDFLAGS=$LDFLAGS wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" - save_LIBS="$LIBS" + save_LIBS=$LIBS LIBS="$lt_cv_dlopen_libs $LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 $as_echo_n "checking whether a program can dlopen itself... " >&6; } -if test "${lt_cv_dlopen_self+set}" = set; then : +if ${lt_cv_dlopen_self+:} false; then : $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes; then : + if test yes = "$cross_compiling"; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10609 "configure" +#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10647,7 +12263,13 @@ else # endif #endif -void fnord() { int i=42;} +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -10656,7 +12278,11 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } /* dlclose (self); */ } else @@ -10669,7 +12295,7 @@ _LT_EOF (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -10689,20 +12315,20 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 $as_echo "$lt_cv_dlopen_self" >&6; } - if test "x$lt_cv_dlopen_self" = xyes; then + if test yes = "$lt_cv_dlopen_self"; then wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 $as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } -if test "${lt_cv_dlopen_self_static+set}" = set; then : +if ${lt_cv_dlopen_self_static+:} false; then : $as_echo_n "(cached) " >&6 else - if test "$cross_compiling" = yes; then : + if test yes = "$cross_compiling"; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 10705 "configure" +#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -10743,7 +12369,13 @@ else # endif #endif -void fnord() { int i=42;} +/* When -fvisibility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined __GNUC__ && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -10752,7 +12384,11 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } /* dlclose (self); */ } else @@ -10765,7 +12401,7 @@ _LT_EOF (eval $ac_link) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 - test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + test $ac_status = 0; } && test -s "conftest$ac_exeext" 2>/dev/null; then (./conftest; exit; ) >&5 2>/dev/null lt_status=$? case x$lt_status in @@ -10786,9 +12422,9 @@ fi $as_echo "$lt_cv_dlopen_self_static" >&6; } fi - CPPFLAGS="$save_CPPFLAGS" - LDFLAGS="$save_LDFLAGS" - LIBS="$save_LIBS" + CPPFLAGS=$save_CPPFLAGS + LDFLAGS=$save_LDFLAGS + LIBS=$save_LIBS ;; esac @@ -10832,7 +12468,7 @@ else # FIXME - insert some real tests, host_os isn't really good enough case $host_os in darwin*) - if test -n "$STRIP" ; then + if test -n "$STRIP"; then striplib="$STRIP -x" old_striplib="$STRIP -S" { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 @@ -10860,7 +12496,7 @@ fi - # Report which library types will actually be built + # Report what library types will actually be built { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 $as_echo_n "checking if libtool supports shared libraries... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 @@ -10868,13 +12504,13 @@ $as_echo "$can_build_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 $as_echo_n "checking whether to build shared libraries... " >&6; } - test "$can_build_shared" = "no" && enable_shared=no + test no = "$can_build_shared" && enable_shared=no # On AIX, shared libraries and static libraries use the same namespace, and # are all built from PIC. case $host_os in aix3*) - test "$enable_shared" = yes && enable_static=no + test yes = "$enable_shared" && enable_static=no if test -n "$RANLIB"; then archive_cmds="$archive_cmds~\$RANLIB \$lib" postinstall_cmds='$RANLIB $lib' @@ -10882,8 +12518,12 @@ $as_echo_n "checking whether to build shared libraries... " >&6; } ;; aix[4-9]*) - if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then - test "$enable_shared" = yes && enable_static=no + if test ia64 != "$host_cpu"; then + case $enable_shared,$with_aix_soname,$aix_use_runtimelinking in + yes,aix,yes) ;; # shared object as lib.so file only + yes,svr4,*) ;; # shared object as lib.so archive member only + yes,*) enable_static=no ;; # shared object in lib.a archive as well + esac fi ;; esac @@ -10893,7 +12533,7 @@ $as_echo "$enable_shared" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 $as_echo_n "checking whether to build static libraries... " >&6; } # Make sure either enable_shared or enable_static is yes. - test "$enable_shared" = yes || enable_static=yes + test yes = "$enable_shared" || enable_static=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 $as_echo "$enable_static" >&6; } @@ -10907,7 +12547,9 @@ ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu -CC="$lt_save_CC" +CC=$lt_save_CC + + @@ -10930,10 +12572,101 @@ CC="$lt_save_CC" + +# Some awks crash when confronted with pnglibconf.dfa, do a test run now +# to make sure this doesn't happen +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that AWK works" >&5 +$as_echo_n "checking that AWK works... " >&6; } +if ${AWK} -f ${srcdir}/scripts/options.awk out="/dev/null" version=search\ + ${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\ + ${srcdir}/pngusr.dfa 1>&2 +then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 1 "failed +See \`config.log' for more details" "$LINENO" 5; } +fi + +# This is a remnant of the old cc -E validation, where it may have been +# necessary to use a different preprocessor for .dfn files +DFNCPP="$CPP" + + +# -Werror cannot be passed to GCC in CFLAGS because configure will fail (it +# checks the compiler with a program that generates a warning), add the +# following option to deal with this + +# Check whether --enable-werror was given. +if test "${enable_werror+set}" = set; then : + enableval=$enable_werror; test "$enable_werror" = "yes" && enable_werror="-Werror" + if test "$enable_werror" != "no"; then + sav_CFLAGS="$CFLAGS" + CFLAGS="$enable_werror $CFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the compiler allows $enable_werror" >&5 +$as_echo_n "checking if the compiler allows $enable_werror... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + int main(int argc, char **argv){ + return argv[argc-1][0]; + } +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + PNG_COPTS="$PNG_COPTS $enable_werror" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$sav_CFLAGS" + fi +fi + + +# For GCC 5 the default mode for C is -std=gnu11 instead of -std=gnu89 +# In pngpriv.h we request just the POSIX 1003.1 and C89 APIs by defining _POSIX_SOURCE to 1 +# This is incompatible with the new default mode, so we test for that and force the +# "-std=c89" compiler option: +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if we need to force back C standard to C89" >&5 +$as_echo_n "checking if we need to force back C standard to C89... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #define _POSIX_SOURCE 1 + #include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +else + + if test "x$GCC" != "xyes"; then + as_fn_error $? "Forcing back to C89 is required but the flags are only known for GCC" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + CFLAGS="$CFLAGS -std=c89" + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + # Checks for header files. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } -if test "${ac_cv_header_stdc+set}" = set; then : +if ${ac_cv_header_stdc+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11043,25 +12776,11 @@ $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi -for ac_header in malloc.h stdlib.h string.h strings.h -do : - as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` -ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" -eval as_val=\$$as_ac_Header - if test "x$as_val" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 -_ACEOF - -fi - -done - # Checks for typedefs, structures, and compiler characteristics. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 $as_echo_n "checking for an ANSI C-conforming const... " >&6; } -if test "${ac_cv_c_const+set}" = set; then : +if ${ac_cv_c_const+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11070,11 +12789,11 @@ else int main () { -/* FIXME: Include the comments suggested by Paul. */ + #ifndef __cplusplus - /* Ultrix mips cc rejects this. */ + /* Ultrix mips cc rejects this sort of thing. */ typedef int charset[2]; - const charset cs; + const charset cs = { 0, 0 }; /* SunOS 4.1.1 cc rejects this. */ char const *const *pcpcc; char **ppc; @@ -11091,8 +12810,9 @@ main () ++pcpcc; ppc = (char**) pcpcc; pcpcc = (char const *const *) ppc; - { /* SCO 3.2v4 cc rejects this. */ - char *t; + { /* SCO 3.2v4 cc rejects this sort of thing. */ + char tx; + char *t = &tx; char const *s = 0 ? (char *) 0 : (char const *) 0; *t++ = 0; @@ -11108,10 +12828,10 @@ main () iptr p = 0; ++p; } - { /* AIX XL C 1.02.0.0 rejects this saying + { /* AIX XL C 1.02.0.0 rejects this sort of thing, saying "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ - struct s { int j; const int *ap[3]; }; - struct s *b; b->j = 5; + struct s { int j; const int *ap[3]; } bx; + struct s *b = &bx; b->j = 5; } { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ const int foo = 10; @@ -11140,7 +12860,7 @@ $as_echo "#define const /**/" >>confdefs.h fi ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" -if test "x$ac_cv_type_size_t" = x""yes; then : +if test "x$ac_cv_type_size_t" = xyes; then : else @@ -11152,7 +12872,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether struct tm is in sys/time.h or time.h" >&5 $as_echo_n "checking whether struct tm is in sys/time.h or time.h... " >&6; } -if test "${ac_cv_struct_tm+set}" = set; then : +if ${ac_cv_struct_tm+:} false; then : $as_echo_n "(cached) " >&6 else cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -11185,11 +12905,57 @@ $as_echo "#define TM_IN_SYS_TIME 1" >>confdefs.h fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C/C++ restrict keyword" >&5 +$as_echo_n "checking for C/C++ restrict keyword... " >&6; } +if ${ac_cv_c_restrict+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_restrict=no + # The order here caters to the fact that C++ does not require restrict. + for ac_kw in __restrict __restrict__ _Restrict restrict; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +typedef int * int_ptr; + int foo (int_ptr $ac_kw ip) { + return ip[0]; + } +int +main () +{ +int s[1]; + int * $ac_kw t = s; + t[0] = 0; + return foo(t) + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_restrict=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_restrict" != no && break + done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_restrict" >&5 +$as_echo "$ac_cv_c_restrict" >&6; } + + case $ac_cv_c_restrict in + restrict) ;; + no) $as_echo "#define restrict /**/" >>confdefs.h + ;; + *) cat >>confdefs.h <<_ACEOF +#define restrict $ac_cv_c_restrict +_ACEOF + ;; + esac + # Checks for library functions. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for working strtod" >&5 $as_echo_n "checking for working strtod... " >&6; } -if test "${ac_cv_func_strtod+set}" = set; then : +if ${ac_cv_func_strtod+:} false; then : $as_echo_n "(cached) " >&6 else if test "$cross_compiling" = yes; then : @@ -11248,14 +13014,14 @@ if test $ac_cv_func_strtod = no; then esac ac_fn_c_check_func "$LINENO" "pow" "ac_cv_func_pow" -if test "x$ac_cv_func_pow" = x""yes; then : +if test "x$ac_cv_func_pow" = xyes; then : fi if test $ac_cv_func_pow = no; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 $as_echo_n "checking for pow in -lm... " >&6; } -if test "${ac_cv_lib_m_pow+set}" = set; then : +if ${ac_cv_lib_m_pow+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -11289,7 +13055,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 $as_echo "$ac_cv_lib_m_pow" >&6; } -if test "x$ac_cv_lib_m_pow" = x""yes; then : +if test "x$ac_cv_lib_m_pow" = xyes; then : POW_LIB=-lm else { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot find library containing definition of pow" >&5 @@ -11300,23 +13066,10 @@ fi fi -for ac_func in memset -do : - ac_fn_c_check_func "$LINENO" "memset" "ac_cv_func_memset" -if test "x$ac_cv_func_memset" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_MEMSET 1 -_ACEOF - -else - as_fn_error "memset not found in libc" "$LINENO" 5 -fi -done - for ac_func in pow do : ac_fn_c_check_func "$LINENO" "pow" "ac_cv_func_pow" -if test "x$ac_cv_func_pow" = x""yes; then : +if test "x$ac_cv_func_pow" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_POW 1 _ACEOF @@ -11324,7 +13077,7 @@ _ACEOF else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pow in -lm" >&5 $as_echo_n "checking for pow in -lm... " >&6; } -if test "${ac_cv_lib_m_pow+set}" = set; then : +if ${ac_cv_lib_m_pow+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -11358,7 +13111,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_pow" >&5 $as_echo "$ac_cv_lib_m_pow" >&6; } -if test "x$ac_cv_lib_m_pow" = x""yes; then : +if test "x$ac_cv_lib_m_pow" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBM 1 _ACEOF @@ -11366,15 +13119,43 @@ _ACEOF LIBS="-lm $LIBS" else - as_fn_error "cannot find pow" "$LINENO" 5 + as_fn_error $? "cannot find pow" "$LINENO" 5 fi fi done + +# Some later POSIX 1003.1 functions are required for test programs, failure here +# is soft (the corresponding test program is not built). +ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" +if test "x$ac_cv_func_clock_gettime" = xyes; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: not building timepng" >&5 +$as_echo "$as_me: WARNING: not building timepng" >&2;} +fi + + if test "$ac_cv_func_clock_gettime" = "yes"; then + HAVE_CLOCK_GETTIME_TRUE= + HAVE_CLOCK_GETTIME_FALSE='#' +else + HAVE_CLOCK_GETTIME_TRUE='#' + HAVE_CLOCK_GETTIME_FALSE= +fi + + + +# Check whether --with-zlib-prefix was given. +if test "${with_zlib_prefix+set}" = set; then : + withval=$with_zlib_prefix; ZPREFIX=${withval} +else + ZPREFIX='z_' +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for zlibVersion in -lz" >&5 $as_echo_n "checking for zlibVersion in -lz... " >&6; } -if test "${ac_cv_lib_z_zlibVersion+set}" = set; then : +if ${ac_cv_lib_z_zlibVersion+:} false; then : $as_echo_n "(cached) " >&6 else ac_check_lib_save_LIBS=$LIBS @@ -11408,7 +13189,7 @@ LIBS=$ac_check_lib_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_zlibVersion" >&5 $as_echo "$ac_cv_lib_z_zlibVersion" >&6; } -if test "x$ac_cv_lib_z_zlibVersion" = x""yes; then : +if test "x$ac_cv_lib_z_zlibVersion" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_LIBZ 1 _ACEOF @@ -11416,46 +13197,158 @@ _ACEOF LIBS="-lz $LIBS" else - as_fn_error "zlib not installed" "$LINENO" 5 -fi - - -case $host_os in - aix*) - LIBPNG_DEFINES=-DPNG_CONFIGURE_LIBPNG -D_ALL_SOURCE;; - *) - LIBPNG_DEFINES=-DPNG_CONFIGURE_LIBPNG;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if assembler code in pnggccrd.c can be compiled without PNG_NO_MMX_CODE" >&5 -$as_echo_n "checking if assembler code in pnggccrd.c can be compiled without PNG_NO_MMX_CODE... " >&6; } + as_ac_Lib=`$as_echo "ac_cv_lib_z_${ZPREFIX}zlibVersion" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ZPREFIX}zlibVersion in -lz" >&5 +$as_echo_n "checking for ${ZPREFIX}zlibVersion in -lz... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ -#include "$srcdir/pnggccrd.c" + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char ${ZPREFIX}zlibVersion (); int main () { -return 0; +return ${ZPREFIX}zlibVersion (); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - LIBPNG_NO_MMX="" +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - LIBPNG_NO_MMX=-DPNG_NO_MMX_CODE + eval "$as_ac_Lib=no" fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -LIBPNG_DEFINES=$LIBPNG_DEFINES\ $LIBPNG_NO_MMX +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + LIBS="-lz $LIBS" + +else + as_fn_error $? "zlib not installed" "$LINENO" 5 +fi + +fi + + +# The following is for pngvalid, to ensure it catches FP errors even on +# platforms that don't enable FP exceptions, the function appears in the math +# library (typically), it's not an error if it is not found. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for feenableexcept in -lm" >&5 +$as_echo_n "checking for feenableexcept in -lm... " >&6; } +if ${ac_cv_lib_m_feenableexcept+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char feenableexcept (); +int +main () +{ +return feenableexcept (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_feenableexcept=yes +else + ac_cv_lib_m_feenableexcept=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_feenableexcept" >&5 +$as_echo "$ac_cv_lib_m_feenableexcept" >&6; } +if test "x$ac_cv_lib_m_feenableexcept" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBM 1 +_ACEOF + + LIBS="-lm $LIBS" + +fi + +for ac_func in feenableexcept +do : + ac_fn_c_check_func "$LINENO" "feenableexcept" "ac_cv_func_feenableexcept" +if test "x$ac_cv_func_feenableexcept" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FEENABLEEXCEPT 1 +_ACEOF + +fi +done + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if using Solaris linker" >&5 +$as_echo_n "checking if using Solaris linker... " >&6; } +SLD=`$LD --version 2>&1 | grep Solaris` +if test "$SLD"; then + have_solaris_ld=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + have_solaris_ld=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + if test "$have_solaris_ld" = "yes"; then + HAVE_SOLARIS_LD_TRUE= + HAVE_SOLARIS_LD_FALSE='#' +else + HAVE_SOLARIS_LD_TRUE='#' + HAVE_SOLARIS_LD_FALSE= +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libraries can be versioned" >&5 $as_echo_n "checking if libraries can be versioned... " >&6; } -GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script` +# Special case for PE/COFF platforms: ld reports +# support for version-script, but doesn't actually +# DO anything with it. +case $host in +*cygwin* | *mingw32* | *interix* ) + have_ld_version_script=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +;; +* ) + +if test "$have_solaris_ld" = "yes"; then + GLD=`$LD --help < /dev/null 2>&1 | grep 'M mapfile'` +else + GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script` +fi + if test "$GLD"; then have_ld_version_script=yes { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 @@ -11467,6 +13360,9 @@ $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: *** You have not enabled versioned symbols." >&5 $as_echo "$as_me: WARNING: *** You have not enabled versioned symbols." >&2;} fi +;; +esac + if test "$have_ld_version_script" = "yes"; then HAVE_LD_VERSION_SCRIPT_TRUE= HAVE_LD_VERSION_SCRIPT_FALSE='#' @@ -11480,9 +13376,9 @@ if test "$have_ld_version_script" = "yes"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for symbol prefix" >&5 $as_echo_n "checking for symbol prefix... " >&6; } SYMBOL_PREFIX=`echo "PREFIX=__USER_LABEL_PREFIX__" \ - | ${CPP-${CC-gcc} -E} - 2>&1 \ - | ${EGREP-grep} "^PREFIX=" \ - | ${SED-sed} "s:^PREFIX=::"` + | ${CPP-${CC-gcc} -E} - 2>&1 \ + | ${EGREP-grep} "^PREFIX=" \ + | ${SED-sed} -e "s:^PREFIX=::" -e "s:__USER_LABEL_PREFIX__::"` { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SYMBOL_PREFIX" >&5 $as_echo "$SYMBOL_PREFIX" >&6; } @@ -11514,40 +13410,366 @@ $as_echo "$as_me: pkgconfig directory is ${pkgconfigdir}" >&6;} # Check whether --with-binconfigs was given. if test "${with_binconfigs+set}" = set; then : withval=$with_binconfigs; if test "${withval}" = no; then - binconfigs= - { $as_echo "$as_me:${as_lineno-$LINENO}: libpng-config scripts will not be built" >&5 + binconfigs= + { $as_echo "$as_me:${as_lineno-$LINENO}: libpng-config scripts will not be built" >&5 $as_echo "$as_me: libpng-config scripts will not be built" >&6;} - else - binconfigs='${binconfigs}' - fi + else + binconfigs='${binconfigs}' + fi else binconfigs='${binconfigs}' fi -# Allow the old version number library, libpng.so, to be removed from -# the build +# Support for prefixes to the API function names; this will generate defines +# at the start of the build to rename exported library functions -# Check whether --with-libpng-compat was given. -if test "${with_libpng_compat+set}" = set; then : - withval=$with_libpng_compat; if test "${withval}" = no; then - compatlib= - { $as_echo "$as_me:${as_lineno-$LINENO}: libpng.so will not be built" >&5 -$as_echo "$as_me: libpng.so will not be built" >&6;} - else - compatlib=libpng.la - fi +# Check whether --with-libpng-prefix was given. +if test "${with_libpng_prefix+set}" = set; then : + withval=$with_libpng_prefix; if test "${withval:-no}" != "no"; then + PNG_PREFIX=${withval} + + fi +fi + + if test "${with_libpng_prefix:-no}" != "no"; then + DO_PNG_PREFIX_TRUE= + DO_PNG_PREFIX_FALSE='#' else - compatlib=libpng.la + DO_PNG_PREFIX_TRUE='#' + DO_PNG_PREFIX_FALSE= +fi + + +# Control over what links are made for installed files. Versioned files are +# always installed, when the following options are turned on corresponding +# unversioned links are also created (normally as symbolic links): +# Check whether --enable-unversioned-links was given. +if test "${enable_unversioned_links+set}" = set; then : + enableval=$enable_unversioned_links; +fi + + +# The AM_CONDITIONAL test is written so that the default is enabled; +# --disable-unversioned-links must be given to turn the option off. + if test "$enable_unversioned_links" != "no"; then + DO_INSTALL_LINKS_TRUE= + DO_INSTALL_LINKS_FALSE='#' +else + DO_INSTALL_LINKS_TRUE='#' + DO_INSTALL_LINKS_FALSE= +fi + + +# Check whether --enable-unversioned-libpng-pc was given. +if test "${enable_unversioned_libpng_pc+set}" = set; then : + enableval=$enable_unversioned_libpng_pc; +fi + + if test "$enable_unversioned_libpng_pc" != "no"; then + DO_INSTALL_LIBPNG_PC_TRUE= + DO_INSTALL_LIBPNG_PC_FALSE='#' +else + DO_INSTALL_LIBPNG_PC_TRUE='#' + DO_INSTALL_LIBPNG_PC_FALSE= +fi + + +# Check whether --enable-unversioned-libpng-config was given. +if test "${enable_unversioned_libpng_config+set}" = set; then : + enableval=$enable_unversioned_libpng_config; +fi + + if test "$enable_unversioned_libpng_config" != "no"; then + DO_INSTALL_LIBPNG_CONFIG_TRUE= + DO_INSTALL_LIBPNG_CONFIG_FALSE='#' +else + DO_INSTALL_LIBPNG_CONFIG_TRUE='#' + DO_INSTALL_LIBPNG_CONFIG_FALSE= +fi + + +# HOST SPECIFIC OPTIONS +# ===================== +# +# DEFAULT +# ======= +# +# Check whether --enable-hardware-optimizations was given. +if test "${enable_hardware_optimizations+set}" = set; then : + enableval=$enable_hardware_optimizations; case "$enableval" in + no|off) + # disable hardware optimization on all systems: + enable_arm_neon=no + +$as_echo "#define PNG_ARM_NEON_OPT 0" >>confdefs.h + + enable_mips_msa=no + +$as_echo "#define PNG_MIPS_MSA_OPT 0" >>confdefs.h + + enable_powerpc_vsx=no + +$as_echo "#define PNG_POWERPC_VSX_OPT 0" >>confdefs.h + + enable_intel_sse=no + +$as_echo "#define PNG_INTEL_SSE_OPT 0" >>confdefs.h + + ;; + *) + # allow enabling hardware optimization on any system: + case "$host_cpu" in + arm*|aarch64*) + enable_arm_neon=yes + +$as_echo "#define PNG_ARM_NEON_OPT 0" >>confdefs.h + + ;; + mipsel*|mips64el*) + enable_mips_msa=yes + +$as_echo "#define PNG_MIPS_MSA_OPT 0" >>confdefs.h + + ;; + i?86|x86_64) + enable_intel_sse=yes + +$as_echo "#define PNG_INTEL_SSE_OPT 1" >>confdefs.h + + ;; + powerpc*|ppc64*) + enable_powerpc_vsx=yes + +$as_echo "#define PNG_POWERPC_VSX_OPT 2" >>confdefs.h + + ;; + esac + ;; + esac +fi + + +# ARM +# === +# +# ARM NEON (SIMD) support. + +# Check whether --enable-arm-neon was given. +if test "${enable_arm_neon+set}" = set; then : + enableval=$enable_arm_neon; case "$enableval" in + no|off) + # disable the default enabling on __ARM_NEON__ systems: + +$as_echo "#define PNG_ARM_NEON_OPT 0" >>confdefs.h + + # Prevent inclusion of the assembler files below: + enable_arm_neon=no;; + check) + +$as_echo "#define PNG_ARM_NEON_CHECK_SUPPORTED /**/" >>confdefs.h +;; + api) + +$as_echo "#define PNG_ARM_NEON_API_SUPPORTED /**/" >>confdefs.h +;; + yes|on) + +$as_echo "#define PNG_ARM_NEON_OPT 2" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-arm-neon: please specify 'check' or 'api', if + you want the optimizations unconditionally pass -mfpu=neon + to the compiler." >&5 +$as_echo "$as_me: WARNING: --enable-arm-neon: please specify 'check' or 'api', if + you want the optimizations unconditionally pass -mfpu=neon + to the compiler." >&2;};; + *) + as_fn_error $? "--enable-arm-neon=${enable_arm_neon}: invalid value" "$LINENO" 5 + esac +fi + + +# Add ARM specific files to all builds where the host_cpu is arm ('arm*') or +# where ARM optimizations were explicitly requested (this allows a fallback if a +# future host CPU does not match 'arm*') + + if test "$enable_arm_neon" != 'no' && + case "$host_cpu" in + arm*|aarch64*) :;; + *) test "$enable_arm_neon" != '';; + esac; then + PNG_ARM_NEON_TRUE= + PNG_ARM_NEON_FALSE='#' +else + PNG_ARM_NEON_TRUE='#' + PNG_ARM_NEON_FALSE= +fi + + +# MIPS +# === +# +# MIPS MSA (SIMD) support. + +# Check whether --enable-mips-msa was given. +if test "${enable_mips_msa+set}" = set; then : + enableval=$enable_mips_msa; case "$enableval" in + no|off) + # disable the default enabling on __mips_msa systems: + +$as_echo "#define PNG_MIPS_MSA_OPT 0" >>confdefs.h + + # Prevent inclusion of the assembler files below: + enable_mips_msa=no;; + check) + +$as_echo "#define PNG_MIPS_MSA_CHECK_SUPPORTED /**/" >>confdefs.h +;; + api) + +$as_echo "#define PNG_MIPS_MSA_API_SUPPORTED /**/" >>confdefs.h +;; + yes|on) + +$as_echo "#define PNG_MIPS_MSA_OPT 2" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-mips-msa: please specify 'check' or 'api', if + you want the optimizations unconditionally pass '-mmsa -mfp64' + to the compiler." >&5 +$as_echo "$as_me: WARNING: --enable-mips-msa: please specify 'check' or 'api', if + you want the optimizations unconditionally pass '-mmsa -mfp64' + to the compiler." >&2;};; + *) + as_fn_error $? "--enable-mips-msa=${enable_mips_msa}: invalid value" "$LINENO" 5 + esac +fi + + +# Add MIPS specific files to all builds where the host_cpu is mips ('mips*') or +# where MIPS optimizations were explicitly requested (this allows a fallback if a +# future host CPU does not match 'mips*') + + if test "$enable_mips_msa" != 'no' && + case "$host_cpu" in + mipsel*|mips64el*) :;; + esac; then + PNG_MIPS_MSA_TRUE= + PNG_MIPS_MSA_FALSE='#' +else + PNG_MIPS_MSA_TRUE='#' + PNG_MIPS_MSA_FALSE= +fi + + +# INTEL +# ===== +# +# INTEL SSE (SIMD) support. + +# Check whether --enable-intel-sse was given. +if test "${enable_intel_sse+set}" = set; then : + enableval=$enable_intel_sse; case "$enableval" in + no|off) + # disable the default enabling: + +$as_echo "#define PNG_INTEL_SSE_OPT 0" >>confdefs.h + + # Prevent inclusion of the assembler files below: + enable_intel_sse=no;; + yes|on) + +$as_echo "#define PNG_INTEL_SSE_OPT 1" >>confdefs.h +;; + *) + as_fn_error $? "--enable-intel-sse=${enable_intel_sse}: invalid value" "$LINENO" 5 + esac +fi + + +# Add Intel specific files to all builds where the host_cpu is Intel ('x86*') +# or where Intel optimizations were explicitly requested (this allows a +# fallback if a future host CPU does not match 'x86*') + if test "$enable_intel_sse" != 'no' && + case "$host_cpu" in + i?86|x86_64) :;; + *) test "$enable_intel_sse" != '';; + esac; then + PNG_INTEL_SSE_TRUE= + PNG_INTEL_SSE_FALSE='#' +else + PNG_INTEL_SSE_TRUE='#' + PNG_INTEL_SSE_FALSE= +fi + + +# PowerPC +# === +# +# PowerPC VSX (SIMD) support. + +# Check whether --enable-powerpc-vsx was given. +if test "${enable_powerpc_vsx+set}" = set; then : + enableval=$enable_powerpc_vsx; case "$enableval" in + no|off) + # disable the default enabling on __ppc64__ systems: + +$as_echo "#define PNG_POWERPC_VSX_OPT 0" >>confdefs.h + + # Prevent inclusion of the platform specific files below: + enable_powerpc_vsx=no;; + check) + +$as_echo "#define PNG_POWERPC_VSX_CHECK_SUPPORTED /**/" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-powerpc-vsx Please check contrib/powerpc/README file + for the list of supported OSes." >&5 +$as_echo "$as_me: WARNING: --enable-powerpc-vsx Please check contrib/powerpc/README file + for the list of supported OSes." >&2;};; + api) + +$as_echo "#define PNG_POWERPC_VSX_API_SUPPORTED /**/" >>confdefs.h +;; + yes|on) + +$as_echo "#define PNG_POWERPC_VSX_OPT 2" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-powerpc-vsx: please specify 'check' or 'api', if + you want the optimizations unconditionally pass '-maltivec -mvsx' + or '-mcpu=power8'to the compiler." >&5 +$as_echo "$as_me: WARNING: --enable-powerpc-vsx: please specify 'check' or 'api', if + you want the optimizations unconditionally pass '-maltivec -mvsx' + or '-mcpu=power8'to the compiler." >&2;};; + *) + as_fn_error $? "--enable-powerpc-vsx=${enable_powerpc_vsx}: invalid value" "$LINENO" 5 + esac +fi + + +# Add PowerPC specific files to all builds where the host_cpu is powerpc('powerpc*') or +# where POWERPC optimizations were explicitly requested (this allows a fallback if a +# future host CPU does not match 'powerpc*') + + if test "$enable_powerpc_vsx" != 'no' && + case "$host_cpu" in + powerpc*|ppc64*) :;; + esac; then + PNG_POWERPC_VSX_TRUE= + PNG_POWERPC_VSX_FALSE='#' +else + PNG_POWERPC_VSX_TRUE='#' + PNG_POWERPC_VSX_FALSE= fi -# Config files, substituting as above -ac_config_files="$ac_config_files Makefile libpng.pc:scripts/libpng.pc-configure.in" +{ $as_echo "$as_me:${as_lineno-$LINENO}: Extra options for compiler: $PNG_COPTS" >&5 +$as_echo "$as_me: Extra options for compiler: $PNG_COPTS" >&6;} -ac_config_files="$ac_config_files libpng-config:scripts/libpng-config.in" +# Config files, substituting as above +ac_config_files="$ac_config_files Makefile libpng.pc:libpng.pc.in" + +ac_config_files="$ac_config_files libpng-config:libpng-config.in" cat >confcache <<\_ACEOF @@ -11614,10 +13836,21 @@ $as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; :end' >>confcache if diff "$cache_file" confcache >/dev/null 2>&1; then :; else if test -w "$cache_file"; then - test "x$cache_file" != "x/dev/null" && + if test "x$cache_file" != "x/dev/null"; then { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 $as_echo "$as_me: updating cache $cache_file" >&6;} - cat confcache >$cache_file + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi else { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 $as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} @@ -11633,6 +13866,7 @@ DEFS=-DHAVE_CONFIG_H ac_libobjs= ac_ltlibobjs= +U= for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue # 1. Remove the extension, and $U if already installed. ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' @@ -11647,6 +13881,14 @@ LIBOBJS=$ac_libobjs LTLIBOBJS=$ac_ltlibobjs +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that generated files are newer than configure" >&5 +$as_echo_n "checking that generated files are newer than configure... " >&6; } + if test -n "$am_sleep_pid"; then + # Hide warnings about reused PIDs. + wait $am_sleep_pid 2>/dev/null + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } if test -n "$EXEEXT"; then am__EXEEXT_TRUE= am__EXEEXT_FALSE='#' @@ -11656,23 +13898,67 @@ else fi if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; then - as_fn_error "conditional \"MAINTAINER_MODE\" was never defined. + as_fn_error $? "conditional \"MAINTAINER_MODE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then - as_fn_error "conditional \"AMDEP\" was never defined. + as_fn_error $? "conditional \"AMDEP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${am__fastdepCC_TRUE}" && test -z "${am__fastdepCC_FALSE}"; then - as_fn_error "conditional \"am__fastdepCC\" was never defined. + as_fn_error $? "conditional \"am__fastdepCC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${am__fastdepCCAS_TRUE}" && test -z "${am__fastdepCCAS_FALSE}"; then + as_fn_error $? "conditional \"am__fastdepCCAS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_CLOCK_GETTIME_TRUE}" && test -z "${HAVE_CLOCK_GETTIME_FALSE}"; then + as_fn_error $? "conditional \"HAVE_CLOCK_GETTIME\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${HAVE_SOLARIS_LD_TRUE}" && test -z "${HAVE_SOLARIS_LD_FALSE}"; then + as_fn_error $? "conditional \"HAVE_SOLARIS_LD\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi if test -z "${HAVE_LD_VERSION_SCRIPT_TRUE}" && test -z "${HAVE_LD_VERSION_SCRIPT_FALSE}"; then - as_fn_error "conditional \"HAVE_LD_VERSION_SCRIPT\" was never defined. + as_fn_error $? "conditional \"HAVE_LD_VERSION_SCRIPT\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DO_PNG_PREFIX_TRUE}" && test -z "${DO_PNG_PREFIX_FALSE}"; then + as_fn_error $? "conditional \"DO_PNG_PREFIX\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DO_INSTALL_LINKS_TRUE}" && test -z "${DO_INSTALL_LINKS_FALSE}"; then + as_fn_error $? "conditional \"DO_INSTALL_LINKS\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DO_INSTALL_LIBPNG_PC_TRUE}" && test -z "${DO_INSTALL_LIBPNG_PC_FALSE}"; then + as_fn_error $? "conditional \"DO_INSTALL_LIBPNG_PC\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${DO_INSTALL_LIBPNG_CONFIG_TRUE}" && test -z "${DO_INSTALL_LIBPNG_CONFIG_FALSE}"; then + as_fn_error $? "conditional \"DO_INSTALL_LIBPNG_CONFIG\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PNG_ARM_NEON_TRUE}" && test -z "${PNG_ARM_NEON_FALSE}"; then + as_fn_error $? "conditional \"PNG_ARM_NEON\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PNG_MIPS_MSA_TRUE}" && test -z "${PNG_MIPS_MSA_FALSE}"; then + as_fn_error $? "conditional \"PNG_MIPS_MSA\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PNG_INTEL_SSE_TRUE}" && test -z "${PNG_INTEL_SSE_FALSE}"; then + as_fn_error $? "conditional \"PNG_INTEL_SSE\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi +if test -z "${PNG_POWERPC_VSX_TRUE}" && test -z "${PNG_POWERPC_VSX_FALSE}"; then + as_fn_error $? "conditional \"PNG_POWERPC_VSX\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -: ${CONFIG_STATUS=./config.status} +: "${CONFIG_STATUS=./config.status}" ac_write_fail=0 ac_clean_files_save=$ac_clean_files ac_clean_files="$ac_clean_files $CONFIG_STATUS" @@ -11773,6 +14059,7 @@ fi IFS=" "" $as_nl" # Find who we are. Look in the path if we contain no directory separator. +as_myself= case $0 in #(( *[\\/]* ) as_myself=$0 ;; *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR @@ -11818,19 +14105,19 @@ export LANGUAGE (unset CDPATH) >/dev/null 2>&1 && unset CDPATH -# as_fn_error ERROR [LINENO LOG_FD] -# --------------------------------- +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- # Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are # provided, also output the error to LOG_FD, referencing LINENO. Then exit the -# script with status $?, using 1 if that was 0. +# script with STATUS, using 1 if that was 0. as_fn_error () { - as_status=$?; test $as_status -eq 0 && as_status=1 - if test "$3"; then - as_lineno=${as_lineno-"$2"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - $as_echo "$as_me:${as_lineno-$LINENO}: error: $1" >&$3 + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 fi - $as_echo "$as_me: error: $1" >&2 + $as_echo "$as_me: error: $2" >&2 as_fn_exit $as_status } # as_fn_error @@ -11968,16 +14255,16 @@ if (echo >conf$$.file) 2>/dev/null; then # ... but there are two gotchas: # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. - # In both cases, we have to default to `cp -p'. + # In both cases, we have to default to `cp -pR'. ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || - as_ln_s='cp -p' + as_ln_s='cp -pR' elif ln conf$$.file conf$$ 2>/dev/null; then as_ln_s=ln else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi else - as_ln_s='cp -p' + as_ln_s='cp -pR' fi rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file rmdir conf$$.dir 2>/dev/null @@ -12026,7 +14313,7 @@ $as_echo X"$as_dir" | test -d "$as_dir" && break done test -z "$as_dirs" || eval "mkdir $as_dirs" - } || test -d "$as_dir" || as_fn_error "cannot create directory $as_dir" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" } # as_fn_mkdir_p @@ -12037,28 +14324,16 @@ else as_mkdir_p=false fi -if test -x / >/dev/null 2>&1; then - as_test_x='test -x' -else - if ls -dL / >/dev/null 2>&1; then - as_ls_L_option=L - else - as_ls_L_option= - fi - as_test_x=' - eval sh -c '\'' - if test -d "$1"; then - test -d "$1/."; - else - case $1 in #( - -*)set "./$1";; - esac; - case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( - ???[sx]*):;;*)false;;esac;fi - '\'' sh - ' -fi -as_executable_p=$as_test_x + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p # Sed expression to map a string onto a valid CPP name. as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" @@ -12079,8 +14354,8 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libpng $as_me 1.2.46, which was -generated by GNU Autoconf 2.65. Invocation command line was +This file was extended by libpng $as_me 1.6.37, which was +generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS @@ -12145,11 +14420,11 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -libpng config.status 1.2.46 -configured by $0, generated by GNU Autoconf 2.65, +libpng config.status 1.6.37 +configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" -Copyright (C) 2009 Free Software Foundation, Inc. +Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." @@ -12167,11 +14442,16 @@ ac_need_defaults=: while test $# != 0 do case $1 in - --*=*) + --*=?*) ac_option=`expr "X$1" : 'X\([^=]*\)='` ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` ac_shift=: ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; *) ac_option=$1 ac_optarg=$2 @@ -12193,6 +14473,7 @@ do $ac_shift case $ac_optarg in *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; esac as_fn_append CONFIG_FILES " '$ac_optarg'" ac_need_defaults=false;; @@ -12205,7 +14486,7 @@ do ac_need_defaults=false;; --he | --h) # Conflict between --help and --header - as_fn_error "ambiguous option: \`$1' + as_fn_error $? "ambiguous option: \`$1' Try \`$0 --help' for more information.";; --help | --hel | -h ) $as_echo "$ac_cs_usage"; exit ;; @@ -12214,7 +14495,7 @@ Try \`$0 --help' for more information.";; ac_cs_silent=: ;; # This is an error. - -*) as_fn_error "unrecognized option: \`$1' + -*) as_fn_error $? "unrecognized option: \`$1' Try \`$0 --help' for more information." ;; *) as_fn_append ac_config_targets " $1" @@ -12234,7 +14515,7 @@ fi _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 if \$ac_cs_recheck; then - set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion shift \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 CONFIG_SHELL='$SHELL' @@ -12258,7 +14539,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 # # INIT-COMMANDS # -AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" +AMDEP_TRUE="$AMDEP_TRUE" MAKE="${MAKE-make}" # The HP-UX ksh and POSIX shell print the target directory to stdout @@ -12268,137 +14549,167 @@ AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' -SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' -Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' -GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' -EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' -FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' -LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' -AS='`$ECHO "X$AS" | $Xsed -e "$delay_single_quote_subst"`' -DLLTOOL='`$ECHO "X$DLLTOOL" | $Xsed -e "$delay_single_quote_subst"`' -OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' -macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' -macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' -enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' -pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' -enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' -host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' -host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' -host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' -build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' -build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' -build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' -NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' -LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' -max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' -ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' -exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' -lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' -lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' -lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' -reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' -reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' -deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' -file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' -AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' -AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' -STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' -RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' -old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' -CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' -CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' -compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' -GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' -objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' -SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' -ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' -MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' -need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' -DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' -NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' -LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' -OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' -OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' -libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' -shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' -extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' -export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' -module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' -module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' -with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' -allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' -no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' -inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' -link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' -fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' -always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' -export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' -exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' -include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' -prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' -file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' -variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' -need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' -need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' -version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' -runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' -shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' -shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' -libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' -library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' -soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' -postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' -finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' -sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' -sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' -old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' -striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +AS='`$ECHO "$AS" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +shared_archive_member_spec='`$ECHO "$shared_archive_member_spec" | $SED "$delay_single_quote_subst"`' +PATH_SEPARATOR='`$ECHO "$PATH_SEPARATOR" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_import='`$ECHO "$lt_cv_sys_global_symbol_to_import" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +lt_cv_nm_interface='`$ECHO "$lt_cv_nm_interface" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +lt_cv_truncate_bin='`$ECHO "$lt_cv_truncate_bin" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +configure_time_dlsearch_path='`$ECHO "$configure_time_dlsearch_path" | $SED "$delay_single_quote_subst"`' +configure_time_lt_sys_library_path='`$ECHO "$configure_time_lt_sys_library_path" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + # Quote evaled strings. for var in SED \ GREP \ EGREP \ FGREP \ +SHELL \ +ECHO \ LD \ +AS \ +DLLTOOL \ +OBJDUMP \ +PATH_SEPARATOR \ NM \ LN_S \ lt_SP2NL \ @@ -12406,8 +14717,12 @@ lt_NL2SP \ reload_flag \ deplibs_check_method \ file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +sharedlib_from_linklib_cmd \ AR \ AR_FLAGS \ +archiver_list_spec \ STRIP \ RANLIB \ CC \ @@ -12415,16 +14730,19 @@ CFLAGS \ compiler \ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_import \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ -SHELL \ -ECHO \ +lt_cv_nm_interface \ +nm_file_list_spec \ +lt_cv_truncate_bin \ lt_prog_compiler_no_builtin_flag \ -lt_prog_compiler_wl \ lt_prog_compiler_pic \ +lt_prog_compiler_wl \ lt_prog_compiler_static \ lt_cv_prog_compiler_c_o \ need_locks \ +MANIFEST_TOOL \ DSYMUTIL \ NMEDIT \ LIPO \ @@ -12438,9 +14756,7 @@ with_gnu_ld \ allow_undefined_flag \ no_undefined_flag \ hardcode_libdir_flag_spec \ -hardcode_libdir_flag_spec_ld \ hardcode_libdir_separator \ -fix_srcfile_path \ exclude_expsyms \ include_expsyms \ file_list_spec \ @@ -12448,12 +14764,13 @@ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ +install_override_mode \ finish_eval \ old_striplib \ striplib; do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -12475,14 +14792,16 @@ module_cmds \ module_expsym_cmds \ export_symbols_cmds \ prelink_cmds \ +postlink_cmds \ postinstall_cmds \ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ -sys_lib_dlsearch_path_spec; do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in +configure_time_dlsearch_path \ +configure_time_lt_sys_library_path; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ## exclude from sc_prohibit_nested_quotes ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -12490,26 +14809,17 @@ sys_lib_dlsearch_path_spec; do esac done -# Fix-up fallback echo if it was mangled by the above quoting rules. -case \$lt_ECHO in -*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` - ;; -esac - ac_aux_dir='$ac_aux_dir' -xsi_shell='$xsi_shell' -lt_shell_append='$lt_shell_append' -# See if we are running on zsh, and set the options which allow our +# See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes INIT. -if test -n "\${ZSH_VERSION+set}" ; then +if test -n "\${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi PACKAGE='$PACKAGE' VERSION='$VERSION' - TIMESTAMP='$TIMESTAMP' RM='$RM' ofile='$ofile' @@ -12528,10 +14838,10 @@ do "depfiles") CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "libpng.pc") CONFIG_FILES="$CONFIG_FILES libpng.pc:scripts/libpng.pc-configure.in" ;; - "libpng-config") CONFIG_FILES="$CONFIG_FILES libpng-config:scripts/libpng-config.in" ;; + "libpng.pc") CONFIG_FILES="$CONFIG_FILES libpng.pc:libpng.pc.in" ;; + "libpng-config") CONFIG_FILES="$CONFIG_FILES libpng-config:libpng-config.in" ;; - *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac done @@ -12554,9 +14864,10 @@ fi # after its creation but before its name has been assigned to `$tmp'. $debug || { - tmp= + tmp= ac_tmp= trap 'exit_status=$? - { test -z "$tmp" || test ! -d "$tmp" || rm -fr "$tmp"; } && exit $exit_status + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status ' 0 trap 'as_fn_exit 1' 1 2 13 15 } @@ -12564,12 +14875,13 @@ $debug || { tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && - test -n "$tmp" && test -d "$tmp" + test -d "$tmp" } || { tmp=./conf$$-$RANDOM (umask 077 && mkdir "$tmp") -} || as_fn_error "cannot create a temporary directory in ." "$LINENO" 5 +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp # Set up the scripts for CONFIG_FILES section. # No need to generate them if there are no CONFIG_FILES. @@ -12586,12 +14898,12 @@ if test "x$ac_cr" = x; then fi ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then - ac_cs_awk_cr='\r' + ac_cs_awk_cr='\\r' else ac_cs_awk_cr=$ac_cr fi -echo 'BEGIN {' >"$tmp/subs1.awk" && +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && _ACEOF @@ -12600,18 +14912,18 @@ _ACEOF echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && echo "_ACEOF" } >conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 -ac_delim_num=`echo "$ac_subst_vars" | grep -c '$'` + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` ac_delim='%!_!# ' for ac_last_try in false false false false false :; do . ./conf$$subs.sh || - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` if test $ac_delim_n = $ac_delim_num; then break elif $ac_last_try; then - as_fn_error "could not make $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -12619,7 +14931,7 @@ done rm -f conf$$subs.sh cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 -cat >>"\$tmp/subs1.awk" <<\\_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && _ACEOF sed -n ' h @@ -12667,7 +14979,7 @@ t delim rm -f conf$$subs.awk cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK -cat >>"\$tmp/subs1.awk" <<_ACAWK && +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && for (key in S) S_is_set[key] = 1 FS = "" @@ -12699,21 +15011,29 @@ if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" else cat -fi < "$tmp/subs1.awk" > "$tmp/subs.awk" \ - || as_fn_error "could not setup config files machinery" "$LINENO" 5 +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 _ACEOF -# VPATH may cause trouble with some makes, so we remove $(srcdir), -# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and # trailing colons and then remove the whole line if VPATH becomes empty # (actually we leave an empty line to preserve line numbers). if test "x$srcdir" = x.; then - ac_vpsub='/^[ ]*VPATH[ ]*=/{ -s/:*\$(srcdir):*/:/ -s/:*\${srcdir}:*/:/ -s/:*@srcdir@:*/:/ -s/^\([^=]*=[ ]*\):*/\1/ + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// s/^[^=]*=[ ]*$// }' fi @@ -12725,7 +15045,7 @@ fi # test -n "$CONFIG_FILES" # No need to generate them if there are no CONFIG_HEADERS. # This happens for instance with `./config.status Makefile'. if test -n "$CONFIG_HEADERS"; then -cat >"$tmp/defines.awk" <<\_ACAWK || +cat >"$ac_tmp/defines.awk" <<\_ACAWK || BEGIN { _ACEOF @@ -12737,11 +15057,11 @@ _ACEOF # handling of long lines. ac_delim='%!_!# ' for ac_last_try in false false :; do - ac_t=`sed -n "/$ac_delim/p" confdefs.h` - if test -z "$ac_t"; then + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then break elif $ac_last_try; then - as_fn_error "could not make $CONFIG_HEADERS" "$LINENO" 5 + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 else ac_delim="$ac_delim!$ac_delim _$ac_delim!! " fi @@ -12826,7 +15146,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 _ACAWK _ACEOF cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 - as_fn_error "could not setup config headers machinery" "$LINENO" 5 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 fi # test -n "$CONFIG_HEADERS" @@ -12839,7 +15159,7 @@ do esac case $ac_mode$ac_tag in :[FHL]*:*);; - :L* | :C*:*) as_fn_error "invalid tag \`$ac_tag'" "$LINENO" 5;; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; :[FH]-) ac_tag=-:-;; :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; esac @@ -12858,7 +15178,7 @@ do for ac_f do case $ac_f in - -) ac_f="$tmp/stdin";; + -) ac_f="$ac_tmp/stdin";; *) # Look for the file first in the build tree, then in the source tree # (if the path is not absolute). The absolute path cannot be DOS-style, # because $ac_f cannot contain `:'. @@ -12867,7 +15187,7 @@ do [\\/$]*) false;; *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; esac || - as_fn_error "cannot find input file: \`$ac_f'" "$LINENO" 5;; + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; esac case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac as_fn_append ac_file_inputs " '$ac_f'" @@ -12893,8 +15213,8 @@ $as_echo "$as_me: creating $ac_file" >&6;} esac case $ac_tag in - *:-:* | *:-) cat >"$tmp/stdin" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 ;; + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; esac ;; esac @@ -13030,23 +15350,24 @@ s&@INSTALL@&$ac_INSTALL&;t t s&@MKDIR_P@&$ac_MKDIR_P&;t t $ac_datarootdir_hack " -eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$tmp/subs.awk" >$tmp/out \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && - { ac_out=`sed -n '/\${datarootdir}/p' "$tmp/out"`; test -n "$ac_out"; } && - { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' "$tmp/out"`; test -z "$ac_out"; } && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&5 +which seems to be undefined. Please make sure it is defined" >&5 $as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' -which seems to be undefined. Please make sure it is defined." >&2;} +which seems to be undefined. Please make sure it is defined" >&2;} - rm -f "$tmp/stdin" + rm -f "$ac_tmp/stdin" case $ac_file in - -) cat "$tmp/out" && rm -f "$tmp/out";; - *) rm -f "$ac_file" && mv "$tmp/out" "$ac_file";; + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; esac \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; :H) # @@ -13055,21 +15376,21 @@ which seems to be undefined. Please make sure it is defined." >&2;} if test x"$ac_file" != x-; then { $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" - } >"$tmp/config.h" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 - if diff "$ac_file" "$tmp/config.h" >/dev/null 2>&1; then + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 $as_echo "$as_me: $ac_file is unchanged" >&6;} else rm -f "$ac_file" - mv "$tmp/config.h" "$ac_file" \ - || as_fn_error "could not create $ac_file" "$LINENO" 5 + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 fi else $as_echo "/* $configure_input */" \ - && eval '$AWK -f "$tmp/defines.awk"' "$ac_file_inputs" \ - || as_fn_error "could not create -" "$LINENO" 5 + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 fi # Compute "$ac_file"'s index in $config_headers. _am_arg="$ac_file" @@ -13115,32 +15436,38 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} case $ac_file$ac_mode in "depfiles":C) test x"$AMDEP_TRUE" != x"" || { - # Autoconf 2.62 quotes --file arguments for eval, but not when files + # Older Autoconf quotes --file arguments for eval, but not when files # are listed without --file. Let's play safe and only enable the eval # if we detect the quoting. - case $CONFIG_FILES in - *\'*) eval set x "$CONFIG_FILES" ;; - *) set x $CONFIG_FILES ;; - esac + # TODO: see whether this extra hack can be removed once we start + # requiring Autoconf 2.70 or later. + case $CONFIG_FILES in #( + *\'*) : + eval set x "$CONFIG_FILES" ;; #( + *) : + set x $CONFIG_FILES ;; #( + *) : + ;; +esac shift - for mf + # Used to flag and report bootstrapping failures. + am_rc=0 + for am_mf do # Strip MF so we end up with the name of the file. - mf=`echo "$mf" | sed -e 's/:.*$//'` - # Check whether this is an Automake generated Makefile or not. - # We used to match only the files named `Makefile.in', but - # some people rename them; so instead we look at the file content. - # Grep'ing the first line is not enough: some people post-process - # each Makefile.in and add a new line on top of each file to say so. - # Grep'ing the whole file is not good either: AIX grep has a line + am_mf=`$as_echo "$am_mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile which includes + # dependency-tracking related rules and includes. + # Grep'ing the whole file directly is not great: AIX grep has a line # limit of 2048, but all sed's we know have understand at least 4000. - if sed -n 's,^#.*generated by automake.*,X,p' "$mf" | grep X >/dev/null 2>&1; then - dirpart=`$as_dirname -- "$mf" || -$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$mf" : 'X\(//\)[^/]' \| \ - X"$mf" : 'X\(//\)$' \| \ - X"$mf" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$mf" | + sed -n 's,^am--depfiles:.*,X,p' "$am_mf" | grep X >/dev/null 2>&1 \ + || continue + am_dirpart=`$as_dirname -- "$am_mf" || +$as_expr X"$am_mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$am_mf" : 'X\(//\)[^/]' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$am_mf" | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/ q @@ -13158,107 +15485,99 @@ $as_echo X"$mf" | q } s/.*/./; q'` - else - continue - fi - # Extract the definition of DEPDIR, am__include, and am__quote - # from the Makefile without running `make'. - DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` - test -z "$DEPDIR" && continue - am__include=`sed -n 's/^am__include = //p' < "$mf"` - test -z "am__include" && continue - am__quote=`sed -n 's/^am__quote = //p' < "$mf"` - # When using ansi2knr, U may be empty or an underscore; expand it - U=`sed -n 's/^U = //p' < "$mf"` - # Find all dependency output files, they are included files with - # $(DEPDIR) in their names. We invoke sed twice because it is the - # simplest approach to changing $(DEPDIR) to its actual value in the - # expansion. - for file in `sed -n " - s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ - sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do - # Make sure the directory exists. - test -f "$dirpart/$file" && continue - fdir=`$as_dirname -- "$file" || -$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ - X"$file" : 'X\(//\)[^/]' \| \ - X"$file" : 'X\(//\)$' \| \ - X"$file" : 'X\(/\)' \| . 2>/dev/null || -$as_echo X"$file" | - sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + am_filepart=`$as_basename -- "$am_mf" || +$as_expr X/"$am_mf" : '.*/\([^/][^/]*\)/*$' \| \ + X"$am_mf" : 'X\(//\)$' \| \ + X"$am_mf" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$am_mf" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/ q } - /^X\(\/\/\)[^/].*/{ + /^X\/\(\/\/\)$/{ s//\1/ q } - /^X\(\/\/\)$/{ - s//\1/ - q - } - /^X\(\/\).*/{ + /^X\/\(\/\).*/{ s//\1/ q } s/.*/./; q'` - as_dir=$dirpart/$fdir; as_fn_mkdir_p - # echo "creating $dirpart/$file" - echo '# dummy' > "$dirpart/$file" - done + { echo "$as_me:$LINENO: cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles" >&5 + (cd "$am_dirpart" \ + && sed -e '/# am--include-marker/d' "$am_filepart" \ + | $MAKE -f - am--depfiles) >&5 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } || am_rc=$? done + if test $am_rc -ne 0; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "Something went wrong bootstrapping makefile fragments + for automatic dependency tracking. Try re-running configure with the + '--disable-dependency-tracking' option to at least be able to build + the package (albeit without support for automatic dependency tracking). +See \`config.log' for more details" "$LINENO" 5; } + fi + { am_dirpart=; unset am_dirpart;} + { am_filepart=; unset am_filepart;} + { am_mf=; unset am_mf;} + { am_rc=; unset am_rc;} + rm -f conftest-deps.mk } ;; "libtool":C) - # See if we are running on zsh, and set the options which allow our + # See if we are running on zsh, and set the options that allow our # commands through without removal of \ escapes. - if test -n "${ZSH_VERSION+set}" ; then + if test -n "${ZSH_VERSION+set}"; then setopt NO_GLOB_SUBST fi - cfgfile="${ofile}T" + cfgfile=${ofile}T trap "$RM \"$cfgfile\"; exit 1" 1 2 15 $RM "$cfgfile" cat <<_LT_EOF >> "$cfgfile" #! $SHELL - -# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. -# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Generated automatically by $as_me ($PACKAGE) $VERSION # Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: # NOTE: Changes made to this file will be lost: look at ltmain.sh. + +# Provide generalized library-building support services. +# Written by Gordon Matzigkeit, 1996 + +# Copyright (C) 2014 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool 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 of the License, or +# (at your option) any later version. # -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. -# Written by Gordon Matzigkeit, 1996 +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program or library that is built +# using GNU Libtool, you may include this file under the same +# distribution terms that you use for the rest of that program. # -# This file is part of GNU Libtool. -# -# GNU Libtool 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. -# -# As a special exception to the GNU General Public License, -# if you distribute this file as part of a program or library that -# is built using GNU Libtool, you may include this file under the -# same distribution terms that you use for the rest of that program. -# -# GNU Libtool is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU Libtool 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 GNU Libtool; see the file COPYING. If not, a copy -# can be downloaded from http://www.gnu.org/licenses/gpl.html, or -# obtained by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# along with this program. If not, see . # The names of the tagged configurations supported by this script. -available_tags="" +available_tags='' + +# Configured defaults for sys_lib_dlsearch_path munging. +: \${LT_SYS_LIBRARY_PATH="$configure_time_lt_sys_library_path"} # ### BEGIN LIBTOOL CONFIG @@ -13277,19 +15596,25 @@ EGREP=$lt_EGREP # A literal string matcher. FGREP=$lt_FGREP -# Assembler program. -AS=$AS +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL -# DLL creation program. -DLLTOOL=$DLLTOOL - -# Object dumper program. -OBJDUMP=$OBJDUMP +# An echo program that protects backslashes. +ECHO=$lt_ECHO # Which release of libtool.m4 was used? macro_version=$macro_version macro_revision=$macro_revision +# Assembler program. +AS=$lt_AS + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Object dumper program. +OBJDUMP=$lt_OBJDUMP + # Whether or not to build shared libraries. build_libtool_libs=$enable_shared @@ -13302,6 +15627,12 @@ pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install +# Shared archive member basename,for filename based shared library versioning on AIX. +shared_archive_member_spec=$shared_archive_member_spec + +# The PATH separator for the build system. +PATH_SEPARATOR=$lt_PATH_SEPARATOR + # The host system. host_alias=$host_alias host=$host @@ -13336,20 +15667,36 @@ SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd # Method to check whether dependent libraries are shared objects. deplibs_check_method=$lt_deplibs_check_method -# Command to use when deplibs_check_method == "file_magic". +# Command to use when deplibs_check_method = "file_magic". file_magic_cmd=$lt_file_magic_cmd +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + # The archiver. AR=$lt_AR + +# Flags to create an archive. AR_FLAGS=$lt_AR_FLAGS +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + # A symbol stripping program. STRIP=$lt_STRIP @@ -13358,6 +15705,9 @@ RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + # A C compiler. LTCC=$lt_CC @@ -13370,27 +15720,39 @@ global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe # Transform the output of nm in a proper C declaration. global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl +# Transform the output of nm into a list of symbols to manually relocate. +global_symbol_to_import=$lt_lt_cv_sys_global_symbol_to_import + # Transform the output of nm in a C name address pair. global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address # Transform the output of nm in a C name address pair when lib prefix is needed. global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix +# The name lister interface. +nm_interface=$lt_lt_cv_nm_interface + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and where our libraries should be installed. +lt_sysroot=$lt_sysroot + +# Command to truncate a binary pipe. +lt_truncate_bin=$lt_lt_cv_truncate_bin + # The name of the directory that contains temporary libtool files. objdir=$objdir -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# An echo program that does not interpret backslashes. -ECHO=$lt_ECHO - # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD # Must we lock files when doing compilation? need_locks=$lt_need_locks +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + # Tool to manipulate archived DWARF debug symbol files on Mac OS X. DSYMUTIL=$lt_DSYMUTIL @@ -13447,6 +15809,9 @@ library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds @@ -13466,8 +15831,11 @@ hardcode_into_libs=$hardcode_into_libs # Compile-time system search path for libraries. sys_lib_search_path_spec=$lt_sys_lib_search_path_spec -# Run-time system search path for libraries. -sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec +# Detected run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_configure_time_dlsearch_path + +# Explicit LT_SYS_LIBRARY_PATH set during ./configure time. +configure_time_lt_sys_library_path=$lt_configure_time_lt_sys_library_path # Whether dlopen is supported. dlopen_support=$enable_dlopen @@ -13486,6 +15854,10 @@ striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds @@ -13498,12 +15870,12 @@ with_gcc=$GCC # Compiler flag to turn off builtin functions. no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag -# How to pass a linker flag through the compiler. -wl=$lt_lt_prog_compiler_wl - # Additional compiler flags for building library objects. pic_flag=$lt_lt_prog_compiler_pic +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + # Compiler flag to prevent dynamic linking. link_static_flag=$lt_lt_prog_compiler_static @@ -13553,20 +15925,16 @@ no_undefined_flag=$lt_no_undefined_flag # This must work even if \$libdir does not exist hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec -# If ld is used when linking, flag to hardcode \$libdir into a binary -# during linking. This must work even if \$libdir does not exist. -hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld - # Whether we need a single "-rpath" flag with a separated argument. hardcode_libdir_separator=$lt_hardcode_libdir_separator -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary. hardcode_direct=$hardcode_direct -# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# Set to "yes" if using DIR/libNAME\$shared_ext during linking hardcodes # DIR into the resulting binary and the resulting library dependency is -# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# "absolute",i.e impossible to change by setting \$shlibpath_var if the # library is relocated. hardcode_direct_absolute=$hardcode_direct_absolute @@ -13590,9 +15958,6 @@ inherit_rpath=$inherit_rpath # Whether libtool must link a program against all its dependency libraries. link_all_deplibs=$link_all_deplibs -# Fix the shell variable \$srcfile for the compiler. -fix_srcfile_path=$lt_fix_srcfile_path - # Set to "yes" if exported symbols are required. always_export_symbols=$always_export_symbols @@ -13608,6 +15973,9 @@ include_expsyms=$lt_include_expsyms # Commands necessary for linking programs (against libraries) with templates. prelink_cmds=$lt_prelink_cmds +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + # Specify filename containing input files. file_list_spec=$lt_file_list_spec @@ -13616,6 +15984,65 @@ hardcode_action=$hardcode_action # ### END LIBTOOL CONFIG +_LT_EOF + + cat <<'_LT_EOF' >> "$cfgfile" + +# ### BEGIN FUNCTIONS SHARED WITH CONFIGURE + +# func_munge_path_list VARIABLE PATH +# ----------------------------------- +# VARIABLE is name of variable containing _space_ separated list of +# directories to be munged by the contents of PATH, which is string +# having a format: +# "DIR[:DIR]:" +# string "DIR[ DIR]" will be prepended to VARIABLE +# ":DIR[:DIR]" +# string "DIR[ DIR]" will be appended to VARIABLE +# "DIRP[:DIRP]::[DIRA:]DIRA" +# string "DIRP[ DIRP]" will be prepended to VARIABLE and string +# "DIRA[ DIRA]" will be appended to VARIABLE +# "DIR[:DIR]" +# VARIABLE will be replaced by "DIR[ DIR]" +func_munge_path_list () +{ + case x$2 in + x) + ;; + *:) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'` \$$1\" + ;; + x:*) + eval $1=\"\$$1 `$ECHO $2 | $SED 's/:/ /g'`\" + ;; + *::*) + eval $1=\"\$$1\ `$ECHO $2 | $SED -e 's/.*:://' -e 's/:/ /g'`\" + eval $1=\"`$ECHO $2 | $SED -e 's/::.*//' -e 's/:/ /g'`\ \$$1\" + ;; + *) + eval $1=\"`$ECHO $2 | $SED 's/:/ /g'`\" + ;; + esac +} + + +# Calculate cc_basename. Skip known compiler wrappers and cross-prefix. +func_cc_basename () +{ + for cc_temp in $*""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac + done + func_cc_basename_result=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` +} + + +# ### END FUNCTIONS SHARED WITH CONFIGURE + _LT_EOF case $host_os in @@ -13624,7 +16051,7 @@ _LT_EOF # AIX sometimes has problems with the GCC collect2 program. For some # reason, if we set the COLLECT_NAMES environment variable, the problems # vanish in a puff of smoke. -if test "X${COLLECT_NAMES+set}" != Xset; then +if test set != "${COLLECT_NAMES+set}"; then COLLECT_NAMES= export COLLECT_NAMES fi @@ -13633,219 +16060,17 @@ _LT_EOF esac -ltmain="$ac_aux_dir/ltmain.sh" +ltmain=$ac_aux_dir/ltmain.sh # We use sed instead of cat because bash on DJGPP gets confused if # if finds mixed CR/LF and LF-only lines. Since sed operates in # text mode, it properly converts lines to CR/LF. This bash problem # is reportedly fixed, but why not run on old versions too? - sed '/^# Generated shell functions inserted here/q' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) - case $xsi_shell in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac -} - -# func_basename file -func_basename () -{ - func_basename_result="${1##*/}" -} - -# func_dirname_and_basename file append nondir_replacement -# perform func_basename and func_dirname in a single function -# call: -# dirname: Compute the dirname of FILE. If nonempty, -# add APPEND to the result, otherwise set result -# to NONDIR_REPLACEMENT. -# value returned in "$func_dirname_result" -# basename: Compute filename of FILE. -# value retuned in "$func_basename_result" -# Implementation must be kept synchronized with func_dirname -# and func_basename. For efficiency, we do not delegate to -# those functions but instead duplicate the functionality here. -func_dirname_and_basename () -{ - case ${1} in - */*) func_dirname_result="${1%/*}${2}" ;; - * ) func_dirname_result="${3}" ;; - esac - func_basename_result="${1##*/}" -} - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -func_stripname () -{ - # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are - # positional parameters, so assign one to ordinary parameter first. - func_stripname_result=${3} - func_stripname_result=${func_stripname_result#"${1}"} - func_stripname_result=${func_stripname_result%"${2}"} -} - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=${1%%=*} - func_opt_split_arg=${1#*=} -} - -# func_lo2o object -func_lo2o () -{ - case ${1} in - *.lo) func_lo2o_result=${1%.lo}.${objext} ;; - *) func_lo2o_result=${1} ;; - esac -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=${1%.*}.lo -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=$(( $* )) -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=${#1} -} - -_LT_EOF - ;; - *) # Bourne compatible functions. - cat << \_LT_EOF >> "$cfgfile" - -# func_dirname file append nondir_replacement -# Compute the dirname of FILE. If nonempty, add APPEND to the result, -# otherwise set result to NONDIR_REPLACEMENT. -func_dirname () -{ - # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` - if test "X$func_dirname_result" = "X${1}"; then - func_dirname_result="${3}" - else - func_dirname_result="$func_dirname_result${2}" - fi -} - -# func_basename file -func_basename () -{ - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` -} - - -# func_stripname prefix suffix name -# strip PREFIX and SUFFIX off of NAME. -# PREFIX and SUFFIX must not contain globbing or regex special -# characters, hashes, percent signs, but SUFFIX may contain a leading -# dot (in which case that matches only a dot). -# func_strip_suffix prefix name -func_stripname () -{ - case ${2} in - .*) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; - esac -} - -# sed scripts: -my_sed_long_opt='1s/^\(-[^=]*\)=.*/\1/;q' -my_sed_long_arg='1s/^-[^=]*=//' - -# func_opt_split -func_opt_split () -{ - func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` - func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` -} - -# func_lo2o object -func_lo2o () -{ - func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` -} - -# func_xform libobj-or-source -func_xform () -{ - func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` -} - -# func_arith arithmetic-term... -func_arith () -{ - func_arith_result=`expr "$@"` -} - -# func_len string -# STRING may not start with a hyphen. -func_len () -{ - func_len_result=`expr "$1" : ".*" 2>/dev/null || echo $max_cmd_len` -} - -_LT_EOF -esac - -case $lt_shell_append in - yes) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$1+=\$2" -} -_LT_EOF - ;; - *) - cat << \_LT_EOF >> "$cfgfile" - -# func_append var value -# Append VALUE to the end of shell variable VAR. -func_append () -{ - eval "$1=\$$1\$2" -} - -_LT_EOF - ;; - esac - - - sed -n '/^# Generated shell functions inserted here/,$p' "$ltmain" >> "$cfgfile" \ - || (rm -f "$cfgfile"; exit 1) - - mv -f "$cfgfile" "$ofile" || + mv -f "$cfgfile" "$ofile" || (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") chmod +x "$ofile" @@ -13861,7 +16086,7 @@ _ACEOF ac_clean_files=$ac_clean_files_save test $ac_write_fail = 0 || - as_fn_error "write failure creating $CONFIG_STATUS" "$LINENO" 5 + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 # configure is writing to config.log, and then calls config.status. @@ -13882,7 +16107,7 @@ if test "$no_create" != yes; then exec 5>>config.log # Use ||, not &&, to avoid exiting from the if with $? = 1, which # would make configure fail if this is the last instruction. - $ac_cs_success || as_fn_exit $? + $ac_cs_success || as_fn_exit 1 fi if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 diff --git a/libs/libpng-src/configure.ac b/libs/libpng-src/configure.ac index bfdbf7a0c..52dba94b4 100644 --- a/libs/libpng-src/configure.ac +++ b/libs/libpng-src/configure.ac @@ -1,5 +1,12 @@ # configure.ac +# Copyright (c) 2018 Cosmin Truta +# Copyright (c) 2004-2016 Glenn Randers-Pehrson + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + dnl Process this file with autoconf to produce a configure script. dnl dnl Minor upgrades (compatible ABI): increment the package version @@ -14,72 +21,178 @@ dnl Makefile.am to upgrade the package name. dnl This is here to prevent earlier autoconf from being used, it dnl should not be necessary to regenerate configure if the time dnl stamps are correct -AC_PREREQ(2.59) +AC_PREREQ([2.68]) dnl Version number stuff here: -AC_INIT([libpng], [1.2.46], [png-mng-implement@lists.sourceforge.net]) -AM_INIT_AUTOMAKE -dnl stop configure from automagically running automake +AC_INIT([libpng],[1.6.37],[png-mng-implement@lists.sourceforge.net]) +AC_CONFIG_MACRO_DIR([scripts]) + +# libpng does not follow GNU file name conventions (hence 'foreign') +# color-tests requires automake 1.11 or later +# silent-rules requires automake 1.11 or later +# dist-xz requires automake 1.11 or later +# 1.12.2 fixes a security issue in 1.11.2 and 1.12.1 +# 1.13 is required for parallel tests +AM_INIT_AUTOMAKE([1.13 foreign dist-xz color-tests silent-rules subdir-objects]) +# The following line causes --disable-maintainer-mode to be the default to +# configure. This is necessary because libpng distributions cannot rely on the +# time stamps of the autotools generated files being correct AM_MAINTAINER_MODE -PNGLIB_VERSION=1.2.46 +dnl configure.ac and Makefile.am expect automake 1.11.2 or a compatible later +dnl version; aclocal.m4 will generate a failure if you use a prior version of +dnl automake, so the following is not necessary (and is not defined anyway): +dnl AM_PREREQ([1.11.2]) +dnl stop configure from automagically running automake + +PNGLIB_VERSION=1.6.37 PNGLIB_MAJOR=1 -PNGLIB_MINOR=2 -PNGLIB_RELEASE=46 +PNGLIB_MINOR=6 +PNGLIB_RELEASE=37 dnl End of version number stuff AC_CONFIG_SRCDIR([pngget.c]) -AM_CONFIG_HEADER(config.h) +AC_CONFIG_HEADERS([config.h]) # Checks for programs. +AC_LANG([C]) AC_PROG_CC -AC_PROG_LD +AM_PROG_AS +LT_PATH_LD AC_PROG_CPP -AC_CHECK_TOOL(SED, sed, :) -AC_LIBTOOL_WIN32_DLL +AC_PROG_AWK AC_PROG_INSTALL AC_PROG_LN_S AC_PROG_MAKE_SET -AC_PROG_LIBTOOL + +dnl libtool/libtoolize; version 2.4.2 is the tested version. This or any +dnl compatible later version may be used +LT_INIT([win32-dll]) +LT_PREREQ([2.4.2]) + +# Some awks crash when confronted with pnglibconf.dfa, do a test run now +# to make sure this doesn't happen +AC_MSG_CHECKING([that AWK works]) +if ${AWK} -f ${srcdir}/scripts/options.awk out="/dev/null" version=search\ + ${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\ + ${srcdir}/pngusr.dfa 1>&2 +then + AC_MSG_RESULT([ok]) +else + AC_MSG_FAILURE([failed], 1) +fi + +# This is a remnant of the old cc -E validation, where it may have been +# necessary to use a different preprocessor for .dfn files +DFNCPP="$CPP" +AC_SUBST(DFNCPP) + +# -Werror cannot be passed to GCC in CFLAGS because configure will fail (it +# checks the compiler with a program that generates a warning), add the +# following option to deal with this +AC_ARG_VAR(PNG_COPTS, + [additional flags for the C compiler, use this for options that would] + [cause configure itself to fail]) +AC_ARG_ENABLE(werror, + AS_HELP_STRING([[[--enable-werror[=OPT]]]], + [Pass -Werror or the given argument to the compiler if it is supported]), + [test "$enable_werror" = "yes" && enable_werror="-Werror" + if test "$enable_werror" != "no"; then + sav_CFLAGS="$CFLAGS" + CFLAGS="$enable_werror $CFLAGS" + AC_MSG_CHECKING([if the compiler allows $enable_werror]) + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([ + [int main(int argc, char **argv){] + [return argv[argc-1][0];] + [}]])], + AC_MSG_RESULT(yes) + PNG_COPTS="$PNG_COPTS $enable_werror", + AC_MSG_RESULT(no)) + CFLAGS="$sav_CFLAGS" + fi],) + +# For GCC 5 the default mode for C is -std=gnu11 instead of -std=gnu89 +# In pngpriv.h we request just the POSIX 1003.1 and C89 APIs by defining _POSIX_SOURCE to 1 +# This is incompatible with the new default mode, so we test for that and force the +# "-std=c89" compiler option: +AC_MSG_CHECKING([if we need to force back C standard to C89]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([ + [#define _POSIX_SOURCE 1] + [#include ] + ])], + AC_MSG_RESULT(no),[ + if test "x$GCC" != "xyes"; then + AC_MSG_ERROR( + [Forcing back to C89 is required but the flags are only known for GCC]) + fi + AC_MSG_RESULT(yes) + CFLAGS="$CFLAGS -std=c89" +]) # Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS([malloc.h stdlib.h string.h strings.h]) # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T AC_STRUCT_TM +AC_C_RESTRICT # Checks for library functions. AC_FUNC_STRTOD -AC_CHECK_FUNCS([memset], , AC_ERROR([memset not found in libc])) -AC_CHECK_FUNCS([pow], , AC_CHECK_LIB(m, pow, , AC_ERROR([cannot find pow])) ) -AC_CHECK_LIB(z, zlibVersion, , AC_ERROR([zlib not installed])) +AC_CHECK_FUNCS([pow], , AC_CHECK_LIB(m, pow, , AC_MSG_ERROR(cannot find pow)) ) -case $host_os in - aix*) - LIBPNG_DEFINES=-DPNG_CONFIGURE_LIBPNG -D_ALL_SOURCE;; - *) - LIBPNG_DEFINES=-DPNG_CONFIGURE_LIBPNG;; -esac -AC_MSG_CHECKING( - [if assembler code in pnggccrd.c can be compiled without PNG_NO_MMX_CODE]) -AC_TRY_COMPILE( - [#include "$srcdir/pnggccrd.c"], - [return 0;], - AC_MSG_RESULT(yes) - LIBPNG_NO_MMX="", - AC_MSG_RESULT(no) - LIBPNG_NO_MMX=-DPNG_NO_MMX_CODE) -LIBPNG_DEFINES=$LIBPNG_DEFINES\ $LIBPNG_NO_MMX -AC_SUBST(LIBPNG_DEFINES) -AC_SUBST(LIBPNG_NO_MMX) +# Some later POSIX 1003.1 functions are required for test programs, failure here +# is soft (the corresponding test program is not built). +AC_CHECK_FUNC([clock_gettime],,[AC_MSG_WARN([not building timepng])]) +AM_CONDITIONAL([HAVE_CLOCK_GETTIME], [test "$ac_cv_func_clock_gettime" = "yes"]) + +AC_ARG_WITH(zlib-prefix, + AS_HELP_STRING([[[--with-zlib-prefix]]], + [prefix that may have been used in installed zlib]), + [ZPREFIX=${withval}], + [ZPREFIX='z_']) +AC_CHECK_LIB(z, zlibVersion, , + AC_CHECK_LIB(z, ${ZPREFIX}zlibVersion, , AC_MSG_ERROR(zlib not installed))) + +# The following is for pngvalid, to ensure it catches FP errors even on +# platforms that don't enable FP exceptions, the function appears in the math +# library (typically), it's not an error if it is not found. +AC_CHECK_LIB([m], [feenableexcept]) +AC_CHECK_FUNCS([feenableexcept]) + +AC_MSG_CHECKING([if using Solaris linker]) +SLD=`$LD --version 2>&1 | grep Solaris` +if test "$SLD"; then + have_solaris_ld=yes + AC_MSG_RESULT(yes) +else + have_solaris_ld=no + AC_MSG_RESULT(no) +fi +AM_CONDITIONAL(HAVE_SOLARIS_LD, test "$have_solaris_ld" = "yes") AC_MSG_CHECKING([if libraries can be versioned]) -GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script` +# Special case for PE/COFF platforms: ld reports +# support for version-script, but doesn't actually +# DO anything with it. +case $host in +*cygwin* | *mingw32* | *interix* ) + have_ld_version_script=no + AC_MSG_RESULT(no) +;; +* ) + +if test "$have_solaris_ld" = "yes"; then + GLD=`$LD --help < /dev/null 2>&1 | grep 'M mapfile'` +else + GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script` +fi + if test "$GLD"; then have_ld_version_script=yes AC_MSG_RESULT(yes) @@ -88,14 +201,17 @@ else AC_MSG_RESULT(no) AC_MSG_WARN(*** You have not enabled versioned symbols.) fi +;; +esac + AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes") if test "$have_ld_version_script" = "yes"; then AC_MSG_CHECKING([for symbol prefix]) SYMBOL_PREFIX=`echo "PREFIX=__USER_LABEL_PREFIX__" \ - | ${CPP-${CC-gcc} -E} - 2>&1 \ - | ${EGREP-grep} "^PREFIX=" \ - | ${SED-sed} "s:^PREFIX=::"` + | ${CPP-${CC-gcc} -E} - 2>&1 \ + | ${EGREP-grep} "^PREFIX=" \ + | ${SED-sed} -e "s:^PREFIX=::" -e "s:__USER_LABEL_PREFIX__::"` AC_SUBST(SYMBOL_PREFIX) AC_MSG_RESULT($SYMBOL_PREFIX) fi @@ -109,45 +225,308 @@ AC_SUBST(PNGLIB_RELEASE) # Additional arguments (and substitutions) # Allow the pkg-config directory to be set AC_ARG_WITH(pkgconfigdir, - AC_HELP_STRING([--with-pkgconfigdir], - [Use the specified pkgconfig dir (default is libdir/pkgconfig)]), - [pkgconfigdir=${withval}], - [pkgconfigdir='${libdir}/pkgconfig']) + AS_HELP_STRING([[[--with-pkgconfigdir]]], + [Use the specified pkgconfig dir (default is libdir/pkgconfig)]), + [pkgconfigdir=${withval}], + [pkgconfigdir='${libdir}/pkgconfig']) AC_SUBST([pkgconfigdir]) -AC_MSG_NOTICE([pkgconfig directory is ${pkgconfigdir}]) +AC_MSG_NOTICE([[pkgconfig directory is ${pkgconfigdir}]]) # Make the *-config binary config scripts optional AC_ARG_WITH(binconfigs, - AC_HELP_STRING([--with-binconfigs], - [Generate shell libpng-config scripts as well as pkg-config data] - [@<:@default=yes@:>@]), - [if test "${withval}" = no; then - binconfigs= - AC_MSG_NOTICE([libpng-config scripts will not be built]) - else - binconfigs='${binconfigs}' - fi], - [binconfigs='${binconfigs}']) + AS_HELP_STRING([[[--with-binconfigs]]], + [Generate shell libpng-config scripts as well as pkg-config data] + [@<:@default=yes@:>@]), + [if test "${withval}" = no; then + binconfigs= + AC_MSG_NOTICE([[libpng-config scripts will not be built]]) + else + binconfigs='${binconfigs}' + fi], + [binconfigs='${binconfigs}']) AC_SUBST([binconfigs]) -# Allow the old version number library, libpng.so, to be removed from -# the build -AC_ARG_WITH(libpng-compat, - AC_HELP_STRING([--with-libpng-compat], - [Generate the obsolete libpng.so library @<:@default=yes@:>@]), - [if test "${withval}" = no; then - compatlib= - AC_MSG_NOTICE([libpng.so will not be built]) - else - compatlib=libpng.la - fi], - [compatlib=libpng.la]) -AC_SUBST([compatlib]) +# Support for prefixes to the API function names; this will generate defines +# at the start of the build to rename exported library functions +AC_ARG_WITH(libpng-prefix, + AS_HELP_STRING([[[--with-libpng-prefix]]], + [prefix libpng exported function (API) names with the given value]), + [if test "${withval:-no}" != "no"; then + AC_SUBST([PNG_PREFIX], [${withval}]) + fi]) +AM_CONDITIONAL([DO_PNG_PREFIX], [test "${with_libpng_prefix:-no}" != "no"]) + +# Control over what links are made for installed files. Versioned files are +# always installed, when the following options are turned on corresponding +# unversioned links are also created (normally as symbolic links): +AC_ARG_ENABLE([unversioned-links], + AS_HELP_STRING([[[--enable-unversioned-links]]], + [Installed libpng header files are placed in a versioned subdirectory] + [and installed libpng library (including DLL) files are versioned.] + [If this option is enabled unversioned links will be created pointing to] + [the corresponding installed files. If you use libpng.pc or] + [libpng-config for all builds you do not need these links, but if you] + [compile programs directly they will typically #include and] + [link with -lpng; in that case you need the links.] + [The links can be installed manually using 'make install-header-links'] + [and 'make install-library-links' and can be removed using the] + [corresponding uninstall- targets. If you do enable this option every] + [libpng 'make install' will recreate the links to point to the just] + [installed version of libpng. The default is to create the links;] + [use --disable-unversioned-links to change this])) + +# The AM_CONDITIONAL test is written so that the default is enabled; +# --disable-unversioned-links must be given to turn the option off. +AM_CONDITIONAL([DO_INSTALL_LINKS],[test "$enable_unversioned_links" != "no"]) + +AC_ARG_ENABLE([unversioned-libpng-pc], + AS_HELP_STRING([[[--enable-unversioned-libpng-pc]]], + [Install the configuration file 'libpng.pc' as a link to the versioned] + [version. This is done by default - use --disable-unversioned-libpng-pc] + [to change this.])) +AM_CONDITIONAL([DO_INSTALL_LIBPNG_PC], + [test "$enable_unversioned_libpng_pc" != "no"]) + +AC_ARG_ENABLE([unversioned-libpng-config], + AS_HELP_STRING([[[--enable-unversioned-libpng-config]]], + [Install the configuration file 'libpng-config' as a link to the] + [versioned version. This is done by default - use] + [--disable-unversioned-libpng-config to change this.])) +AM_CONDITIONAL([DO_INSTALL_LIBPNG_CONFIG], + [test "$enable_unversioned_libpng_config" != "no"]) + +# HOST SPECIFIC OPTIONS +# ===================== +# +# DEFAULT +# ======= +# +AC_ARG_ENABLE([hardware-optimizations], + AS_HELP_STRING([[[--enable-hardware-optimizations]]], + [Enable hardware optimizations: =no/off, yes/on:]), + [case "$enableval" in + no|off) + # disable hardware optimization on all systems: + enable_arm_neon=no + AC_DEFINE([PNG_ARM_NEON_OPT], [0], + [Disable ARM_NEON optimizations]) + enable_mips_msa=no + AC_DEFINE([PNG_MIPS_MSA_OPT], [0], + [Disable MIPS_MSA optimizations]) + enable_powerpc_vsx=no + AC_DEFINE([PNG_POWERPC_VSX_OPT], [0], + [Disable POWERPC VSX optimizations]) + enable_intel_sse=no + AC_DEFINE([PNG_INTEL_SSE_OPT], [0], + [Disable INTEL_SSE optimizations]) + ;; + *) + # allow enabling hardware optimization on any system: + case "$host_cpu" in + arm*|aarch64*) + enable_arm_neon=yes + AC_DEFINE([PNG_ARM_NEON_OPT], [0], + [Enable ARM_NEON optimizations]) + ;; + mipsel*|mips64el*) + enable_mips_msa=yes + AC_DEFINE([PNG_MIPS_MSA_OPT], [0], + [Enable MIPS_MSA optimizations]) + ;; + i?86|x86_64) + enable_intel_sse=yes + AC_DEFINE([PNG_INTEL_SSE_OPT], [1], + [Enable Intel SSE optimizations]) + ;; + powerpc*|ppc64*) + enable_powerpc_vsx=yes + AC_DEFINE([PNG_POWERPC_VSX_OPT], [2], + [Enable POWERPC VSX optimizations]) + ;; + esac + ;; + esac]) + +# ARM +# === +# +# ARM NEON (SIMD) support. + +AC_ARG_ENABLE([arm-neon], + AS_HELP_STRING([[[--enable-arm-neon]]], + [Enable ARM NEON optimizations: =no/off, check, api, yes/on:] + [no/off: disable the optimizations; check: use internal checking code] + [(deprecated and poorly supported); api: disable by default, enable by] + [a call to png_set_option; yes/on: turn on unconditionally.] + [If not specified: determined by the compiler.]), + [case "$enableval" in + no|off) + # disable the default enabling on __ARM_NEON__ systems: + AC_DEFINE([PNG_ARM_NEON_OPT], [0], + [Disable ARM Neon optimizations]) + # Prevent inclusion of the assembler files below: + enable_arm_neon=no;; + check) + AC_DEFINE([PNG_ARM_NEON_CHECK_SUPPORTED], [], + [Check for ARM Neon support at run-time]);; + api) + AC_DEFINE([PNG_ARM_NEON_API_SUPPORTED], [], + [Turn on ARM Neon optimizations at run-time]);; + yes|on) + AC_DEFINE([PNG_ARM_NEON_OPT], [2], + [Enable ARM Neon optimizations]) + AC_MSG_WARN([--enable-arm-neon: please specify 'check' or 'api', if] + [you want the optimizations unconditionally pass -mfpu=neon] + [to the compiler.]);; + *) + AC_MSG_ERROR([--enable-arm-neon=${enable_arm_neon}: invalid value]) + esac]) + +# Add ARM specific files to all builds where the host_cpu is arm ('arm*') or +# where ARM optimizations were explicitly requested (this allows a fallback if a +# future host CPU does not match 'arm*') + +AM_CONDITIONAL([PNG_ARM_NEON], + [test "$enable_arm_neon" != 'no' && + case "$host_cpu" in + arm*|aarch64*) :;; + *) test "$enable_arm_neon" != '';; + esac]) + +# MIPS +# === +# +# MIPS MSA (SIMD) support. + +AC_ARG_ENABLE([mips-msa], + AS_HELP_STRING([[[--enable-mips-msa]]], + [Enable MIPS MSA optimizations: =no/off, check, api, yes/on:] + [no/off: disable the optimizations; check: use internal checking code] + [(deprecated and poorly supported); api: disable by default, enable by] + [a call to png_set_option; yes/on: turn on unconditionally.] + [If not specified: determined by the compiler.]), + [case "$enableval" in + no|off) + # disable the default enabling on __mips_msa systems: + AC_DEFINE([PNG_MIPS_MSA_OPT], [0], + [Disable MIPS MSA optimizations]) + # Prevent inclusion of the assembler files below: + enable_mips_msa=no;; + check) + AC_DEFINE([PNG_MIPS_MSA_CHECK_SUPPORTED], [], + [Check for MIPS MSA support at run-time]);; + api) + AC_DEFINE([PNG_MIPS_MSA_API_SUPPORTED], [], + [Turn on MIPS MSA optimizations at run-time]);; + yes|on) + AC_DEFINE([PNG_MIPS_MSA_OPT], [2], + [Enable MIPS MSA optimizations]) + AC_MSG_WARN([--enable-mips-msa: please specify 'check' or 'api', if] + [you want the optimizations unconditionally pass '-mmsa -mfp64'] + [to the compiler.]);; + *) + AC_MSG_ERROR([--enable-mips-msa=${enable_mips_msa}: invalid value]) + esac]) + +# Add MIPS specific files to all builds where the host_cpu is mips ('mips*') or +# where MIPS optimizations were explicitly requested (this allows a fallback if a +# future host CPU does not match 'mips*') + +AM_CONDITIONAL([PNG_MIPS_MSA], + [test "$enable_mips_msa" != 'no' && + case "$host_cpu" in + mipsel*|mips64el*) :;; + esac]) + +# INTEL +# ===== +# +# INTEL SSE (SIMD) support. + +AC_ARG_ENABLE([intel-sse], + AS_HELP_STRING([[[--enable-intel-sse]]], + [Enable Intel SSE optimizations: =no/off, yes/on:] + [no/off: disable the optimizations;] + [yes/on: enable the optimizations.] + [If not specified: determined by the compiler.]), + [case "$enableval" in + no|off) + # disable the default enabling: + AC_DEFINE([PNG_INTEL_SSE_OPT], [0], + [Disable Intel SSE optimizations]) + # Prevent inclusion of the assembler files below: + enable_intel_sse=no;; + yes|on) + AC_DEFINE([PNG_INTEL_SSE_OPT], [1], + [Enable Intel SSE optimizations]);; + *) + AC_MSG_ERROR([--enable-intel-sse=${enable_intel_sse}: invalid value]) + esac]) + +# Add Intel specific files to all builds where the host_cpu is Intel ('x86*') +# or where Intel optimizations were explicitly requested (this allows a +# fallback if a future host CPU does not match 'x86*') +AM_CONDITIONAL([PNG_INTEL_SSE], + [test "$enable_intel_sse" != 'no' && + case "$host_cpu" in + i?86|x86_64) :;; + *) test "$enable_intel_sse" != '';; + esac]) + +# PowerPC +# === +# +# PowerPC VSX (SIMD) support. + +AC_ARG_ENABLE([powerpc-vsx], +AS_HELP_STRING([[[--enable-powerpc-vsx]]], + [Enable POWERPC VSX optimizations: =no/off, check, api, yes/on:] + [no/off: disable the optimizations; check: use internal checking code] + [api: disable by default, enable by a call to png_set_option] + [yes/on: turn on unconditionally.] + [If not specified: determined by the compiler.]), + [case "$enableval" in + no|off) + # disable the default enabling on __ppc64__ systems: + AC_DEFINE([PNG_POWERPC_VSX_OPT], [0], + [Disable POWERPC VSX optimizations]) + # Prevent inclusion of the platform specific files below: + enable_powerpc_vsx=no;; + check) + AC_DEFINE([PNG_POWERPC_VSX_CHECK_SUPPORTED], [], + [Check for POWERPC VSX support at run-time]) + AC_MSG_WARN([--enable-powerpc-vsx Please check contrib/powerpc/README file] + [for the list of supported OSes.]);; + api) + AC_DEFINE([PNG_POWERPC_VSX_API_SUPPORTED], [], + [Turn on POWERPC VSX optimizations at run-time]);; + yes|on) + AC_DEFINE([PNG_POWERPC_VSX_OPT], [2], + [Enable POWERPC VSX optimizations]) + AC_MSG_WARN([--enable-powerpc-vsx: please specify 'check' or 'api', if] + [you want the optimizations unconditionally pass '-maltivec -mvsx'] + [or '-mcpu=power8'to the compiler.]);; + *) + AC_MSG_ERROR([--enable-powerpc-vsx=${enable_powerpc_vsx}: invalid value]) + esac]) + +# Add PowerPC specific files to all builds where the host_cpu is powerpc('powerpc*') or +# where POWERPC optimizations were explicitly requested (this allows a fallback if a +# future host CPU does not match 'powerpc*') + +AM_CONDITIONAL([PNG_POWERPC_VSX], + [test "$enable_powerpc_vsx" != 'no' && + case "$host_cpu" in + powerpc*|ppc64*) :;; + esac]) + + +AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]]) # Config files, substituting as above -AC_CONFIG_FILES([Makefile libpng.pc:scripts/libpng.pc-configure.in]) -AC_CONFIG_FILES([libpng-config:scripts/libpng-config.in], - [chmod +x libpng-config]) +AC_CONFIG_FILES([Makefile libpng.pc:libpng.pc.in]) +AC_CONFIG_FILES([libpng-config:libpng-config.in], + [chmod +x libpng-config]) AC_OUTPUT diff --git a/libs/libpng-src/contrib/README.txt b/libs/libpng-src/contrib/README.txt new file mode 100644 index 000000000..97963c6d5 --- /dev/null +++ b/libs/libpng-src/contrib/README.txt @@ -0,0 +1,5 @@ + +This "contrib" directory contains contributions which are not necessarily under +the libpng license, although all are open source. They are not part of +libpng proper and are not used for building the library, although some are used +for testing the library via "make check". diff --git a/libs/libpng-src/contrib/arm-neon/README b/libs/libpng-src/contrib/arm-neon/README new file mode 100644 index 000000000..b4248cf28 --- /dev/null +++ b/libs/libpng-src/contrib/arm-neon/README @@ -0,0 +1,83 @@ +OPERATING SYSTEM SPECIFIC ARM NEON DETECTION +-------------------------------------------- + +Detection of the ability to execute ARM NEON on an ARM processor requires +operating system support. (The information is not available in user mode.) + +HOW TO USE THIS +--------------- + +This directory contains C code fragments that can be included in arm/arm_init.c +by setting the macro PNG_ARM_NEON_FILE to the file name in "" or <> at build +time. This setting is not recorded in pnglibconf.h and can be changed simply by +rebuilding arm/arm_init.o with the required macro definition. + +For any of this code to be used the ARM NEON code must be enabled and run time +checks must be supported. I.e.: + +#if PNG_ARM_NEON_OPT > 0 +#ifdef PNG_ARM_NEON_CHECK_SUPPORTED + +This is done in a 'configure' build by passing configure the argument: + + --enable-arm-neon=check + +Apart from the basic Linux implementation in contrib/arm-neon/linux.c this code +is unsupported. That means that it is not even compiled on a regular basis and +may be broken in any given minor release. + +FILE FORMAT +----------- + +Each file documents its testing status as of the last time it was tested (which +may have been a long time ago): + +STATUS: one of: + SUPPORTED: This indicates that the file is included in the regularly + performed test builds and bugs are fixed when discovered. + COMPILED: This indicates that the code did compile at least once. See the + more detailed description for the extent to which the result was + successful. + TESTED: This means the code was fully compiled into the libpng test programs + and these were run at least once. + +BUG REPORTS: an email address to which to send reports of problems + +The file is a fragment of C code. It should not define any 'extern' symbols; +everything should be static. It must define the function: + +static int png_have_neon(png_structp png_ptr); + +That function must return 1 if ARM NEON instructions are supported, 0 if not. +It must not execute png_error unless it detects a bug. A png_error will prevent +the reading of the PNG and in the future, writing too. + +BUG REPORTS +----------- + +If you mail a bug report for any file that is not SUPPORTED there may only be +limited response. Consider fixing it and sending a patch to fix the problem - +this is more likely to result in action. + +CONTRIBUTIONS +------------- + +You may send contributions of new implementations to +png-mng-implement@sourceforge.net. Please write code in strict C90 C where +possible. Obviously OS dependencies are to be expected. If you submit code you +must have the authors permission and it must have a license that is acceptable +to the current maintainer; in particular that license must permit modification +and redistribution. + +Please try to make the contribution a single file and give the file a clear and +unambiguous name that identifies the target OS. If multiple files really are +required put them all in a sub-directory. + +You must also be prepared to handle bug reports from users of the code, either +by joining the png-mng-implement mailing list or by providing an email for the +"BUG REPORTS" entry or both. Please make sure that the header of the file +contains the STATUS and BUG REPORTS fields as above. + +Please list the OS requirements as precisely as possible. Ideally you should +also list the environment in which the code has been tested and certainly list +any environments where you suspect it might not work. diff --git a/libs/libpng-src/contrib/arm-neon/android-ndk.c b/libs/libpng-src/contrib/arm-neon/android-ndk.c new file mode 100644 index 000000000..fb3a4898d --- /dev/null +++ b/libs/libpng-src/contrib/arm-neon/android-ndk.c @@ -0,0 +1,39 @@ +/* contrib/arm-neon/android-ndk.c + * + * Copyright (c) 2014 Glenn Randers-Pehrson + * Written by John Bowler, 2014. + * Last changed in libpng 1.6.10 [March 6, 2014] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * SEE contrib/arm-neon/README before reporting bugs + * + * STATUS: COMPILED, UNTESTED + * BUG REPORTS: png-mng-implement@sourceforge.net + * + * png_have_neon implemented for the Android NDK, see: + * + * Documentation: + * http://www.kandroid.org/ndk/docs/CPU-ARM-NEON.html + * https://code.google.com/p/android/issues/detail?id=49065 + * + * NOTE: this requires that libpng is built against the Android NDK and linked + * with an implementation of the Android ARM 'cpu-features' library. The code + * has been compiled only, not linked: no version of the library has been found, + * only the header files exist in the NDK. + */ +#include + +static int +png_have_neon(png_structp png_ptr) +{ + /* This is a whole lot easier than the linux code, however it is probably + * implemented as below, therefore it is better to cache the result (these + * function calls may be slow!) + */ + PNG_UNUSED(png_ptr) + return android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM && + (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0; +} diff --git a/libs/libpng-src/contrib/arm-neon/linux-auxv.c b/libs/libpng-src/contrib/arm-neon/linux-auxv.c new file mode 100644 index 000000000..4d26bd3b3 --- /dev/null +++ b/libs/libpng-src/contrib/arm-neon/linux-auxv.c @@ -0,0 +1,120 @@ +/* contrib/arm-neon/linux-auxv.c + * + * Copyright (c) 2014 Glenn Randers-Pehrson + * Written by Mans Rullgard, 2011. + * Last changed in libpng 1.6.10 [March 6, 2014] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * SEE contrib/arm-neon/README before reporting bugs + * + * STATUS: COMPILED, TESTED + * BUG REPORTS: png-mng-implement@sourceforge.net + * + * png_have_neon implemented for Linux versions which allow access to + * /proc/self/auxv. This is probably faster, cleaner and safer than the code to + * read /proc/cpuinfo in contrib/arm-neon/linux, however it is yet another piece + * of potentially untested code and has more complex dependencies than the code + * to read cpuinfo. + * + * This generic __linux__ implementation requires reading /proc/self/auxv and + * looking at each element for one that records NEON capabilities. + */ +#include /* for POSIX 1003.1 */ +#include /* for EINTR */ + +#include +#include +#include +#include +#include + +/* A read call may be interrupted, in which case it returns -1 and sets errno to + * EINTR if nothing was done, otherwise (if something was done) a partial read + * may result. + */ +static size_t +safe_read(png_structp png_ptr, int fd, void *buffer_in, size_t nbytes) +{ + size_t ntotal = 0; + char *buffer = png_voidcast(char*, buffer_in); + + while (nbytes > 0) + { + unsigned int nread; + int iread; + + /* Passing nread > INT_MAX to read is implementation defined in POSIX + * 1003.1, therefore despite the unsigned argument portable code must + * limit the value to INT_MAX! + */ + if (nbytes > INT_MAX) + nread = INT_MAX; + + else + nread = (unsigned int)/*SAFE*/nbytes; + + iread = read(fd, buffer, nread); + + if (iread == -1) + { + /* This is the devil in the details, a read can terminate early with 0 + * bytes read because of EINTR, yet it still returns -1 otherwise end + * of file cannot be distinguished. + */ + if (errno != EINTR) + { + png_warning(png_ptr, "/proc read failed"); + return 0; /* I.e., a permanent failure */ + } + } + + else if (iread < 0) + { + /* Not a valid 'read' result: */ + png_warning(png_ptr, "OS /proc read bug"); + return 0; + } + + else if (iread > 0) + { + /* Continue reading until a permanent failure, or EOF */ + buffer += iread; + nbytes -= (unsigned int)/*SAFE*/iread; + ntotal += (unsigned int)/*SAFE*/iread; + } + + else + return ntotal; + } + + return ntotal; /* nbytes == 0 */ +} + +static int +png_have_neon(png_structp png_ptr) +{ + int fd = open("/proc/self/auxv", O_RDONLY); + Elf32_auxv_t aux; + + /* Failsafe: failure to open means no NEON */ + if (fd == -1) + { + png_warning(png_ptr, "/proc/self/auxv open failed"); + return 0; + } + + while (safe_read(png_ptr, fd, &aux, sizeof aux) == sizeof aux) + { + if (aux.a_type == AT_HWCAP && (aux.a_un.a_val & HWCAP_NEON) != 0) + { + close(fd); + return 1; + } + } + + close(fd); + return 0; +} diff --git a/libs/libpng-src/contrib/arm-neon/linux.c b/libs/libpng-src/contrib/arm-neon/linux.c new file mode 100644 index 000000000..a9bc360dd --- /dev/null +++ b/libs/libpng-src/contrib/arm-neon/linux.c @@ -0,0 +1,161 @@ +/* contrib/arm-neon/linux.c + * + * Last changed in libpng 1.6.31 [July 27, 2017] + * Copyright (c) 2014, 2017 Glenn Randers-Pehrson + * Written by John Bowler, 2014, 2017. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * SEE contrib/arm-neon/README before reporting bugs + * + * STATUS: SUPPORTED + * BUG REPORTS: png-mng-implement@sourceforge.net + * + * png_have_neon implemented for Linux by reading the widely available + * pseudo-file /proc/cpuinfo. + * + * This code is strict ANSI-C and is probably moderately portable; it does + * however use and it assumes that /proc/cpuinfo is never localized. + */ +#include + +static int +png_have_neon(png_structp png_ptr) +{ + FILE *f = fopen("/proc/cpuinfo", "rb"); + + if (f != NULL) + { + /* This is a simple state machine which reads the input byte-by-byte until + * it gets a match on the 'neon' feature or reaches the end of the stream. + */ + static const char ch_feature[] = { 70, 69, 65, 84, 85, 82, 69, 83 }; + static const char ch_neon[] = { 78, 69, 79, 78 }; + + enum + { + StartLine, Feature, Colon, StartTag, Neon, HaveNeon, SkipTag, SkipLine + } state; + int counter; + + for (state=StartLine, counter=0;;) + { + int ch = fgetc(f); + + if (ch == EOF) + { + /* EOF means error or end-of-file, return false; neon at EOF is + * assumed to be a mistake. + */ + fclose(f); + return 0; + } + + switch (state) + { + case StartLine: + /* Match spaces at the start of line */ + if (ch <= 32) /* skip control characters and space */ + break; + + counter=0; + state = Feature; + /* FALLTHROUGH */ + + case Feature: + /* Match 'FEATURE', ASCII case insensitive. */ + if ((ch & ~0x20) == ch_feature[counter]) + { + if (++counter == (sizeof ch_feature)) + state = Colon; + break; + } + + /* did not match 'feature' */ + state = SkipLine; + /* FALLTHROUGH */ + + case SkipLine: + skipLine: + /* Skip everything until we see linefeed or carriage return */ + if (ch != 10 && ch != 13) + break; + + state = StartLine; + break; + + case Colon: + /* Match any number of space or tab followed by ':' */ + if (ch == 32 || ch == 9) + break; + + if (ch == 58) /* i.e. ':' */ + { + state = StartTag; + break; + } + + /* Either a bad line format or a 'feature' prefix followed by + * other characters. + */ + state = SkipLine; + goto skipLine; + + case StartTag: + /* Skip space characters before a tag */ + if (ch == 32 || ch == 9) + break; + + state = Neon; + counter = 0; + /* FALLTHROUGH */ + + case Neon: + /* Look for 'neon' tag */ + if ((ch & ~0x20) == ch_neon[counter]) + { + if (++counter == (sizeof ch_neon)) + state = HaveNeon; + break; + } + + state = SkipTag; + /* FALLTHROUGH */ + + case SkipTag: + /* Skip non-space characters */ + if (ch == 10 || ch == 13) + state = StartLine; + + else if (ch == 32 || ch == 9) + state = StartTag; + break; + + case HaveNeon: + /* Have seen a 'neon' prefix, but there must be a space or new + * line character to terminate it. + */ + if (ch == 10 || ch == 13 || ch == 32 || ch == 9) + { + fclose(f); + return 1; + } + + state = SkipTag; + break; + + default: + png_error(png_ptr, "png_have_neon: internal error (bug)"); + } + } + } + +#ifdef PNG_WARNINGS_SUPPORTED + else + png_warning(png_ptr, "/proc/cpuinfo open failed"); +#endif + + return 0; +} diff --git a/libs/libpng-src/contrib/conftest/README b/libs/libpng-src/contrib/conftest/README new file mode 100644 index 000000000..0f472791f --- /dev/null +++ b/libs/libpng-src/contrib/conftest/README @@ -0,0 +1,49 @@ +This directory contains test configuration files, currently always '.dfa' files +intended to be used in the build by setting the make macro DFA_XTRA to the name +of the file. + +These files are used in release validation of the 'configure' builds of libpng +by building 'make check', or 'make all-am' for cross-builds, with each .dfa +file. + +The files in this directory may change between minor releases, however +contributions describing specific builds of libpng are welcomed. There is no +guarantee that libpng will continue to build with such configurations; support +for given configurations can be, and has been, dropped between successive minor +releases. However if a .dfa file describing a configuration is not in this +directory it is very unlikely that it will be tested before a minor release! + +You can use these .dfa files as the basis of new configurations. Files in this +directory should not have any use restrictions or restrictive licenses. + +This directory is not included in the .zip and .7z distributions, which do +not contain 'configure' scripts. + +DOCUMENTATION +============= + +Examples: + ${srcdir}/pngusr.dfa + ${srcdir}/contrib/pngminim/*/pngusr.dfa + +Documentation of the options: + ${srcdir}/scripts/pnglibconf.dfa + +Documentation of the file format: + ${srcdir}/scripts/options.awk + +FILE NAMING +=========== + +File names in this directory may NOT contain any of the five characters: + + - , + * ? + +Neither may they contain any space character. + +While other characters may be used it is strongly suggested that file names be +limited to lower case Latiin alphabetic characters (a-z), digits (0-9) and, if +necessary the underscore (_) character. File names should be about 8 characters +long (excluding the .dfa extension). Submitted .dfa files should have names +between 7 and 16 characters long, shorter names (6 characters or less) are +reserved for standard tests. diff --git a/libs/libpng-src/contrib/conftest/pngcp.dfa b/libs/libpng-src/contrib/conftest/pngcp.dfa new file mode 100644 index 000000000..31c411d5f --- /dev/null +++ b/libs/libpng-src/contrib/conftest/pngcp.dfa @@ -0,0 +1,57 @@ +# pngcp.dfa +# Build time configuration of libpng +# +# Author: John Bowler +# Copyright: (c) John Bowler, 2016 +# Usage rights: +# To the extent possible under law, the author has waived all copyright and +# related or neighboring rights to this work. This work is published from: +# United States. +# +# Build libpng with support for pngcp. This means just png_read_png, +# png_write_png and small number of configuration settings. +# +everything = off + +# This option is specific to this configuration; it adds a #define to the +# generated pnglibconf.h which turns on the (not portable) timing option for +# pngcp. Note that any option is automatically preceded by PNG_; there is no +# way round this and this is deliberate. +option PNGCP_TIMING + +# Because of the everything off above the option must also be turned on. This +# may not be done in one step because it is safer and avoids mis-spelled options +# in user .dfa files to error out if an unrecognized option is turned on. +option PNGCP_TIMING on + +# Options to turn on png_read_png and png_write_png: +option INFO_IMAGE on +option SEQUENTIAL_READ on +option EASY_ACCESS on +option WRITE on +option WRITE_16BIT on +option WRITE_FILTER on + +# pngcp needs this to preserve unknown chunks, switching all these on means that +# pngcp can work without explicit known chunk reading support +option UNKNOWN_CHUNKS on +option SET_UNKNOWN_CHUNKS on +option HANDLE_AS_UNKNOWN on +option SAVE_UNKNOWN_CHUNKS on +option WRITE_UNKNOWN_CHUNKS on + +# pngcp needs this to handle palette files with invalid indices: +option CHECK_FOR_INVALID_INDEX on +option GET_PALETTE_MAX on + +# Pre-libpng 1.7 pngcp has to stash text chunks manually, post 1.7 without this +# text chunks should be handled as unknown ok. +option TEXT on + +# this is used to turn off limits: +option USER_LIMITS on +option SET_USER_LIMITS on + +# these are just required for specific customizations +option WRITE_CUSTOMIZE_ZTXT_COMPRESSION on +option WRITE_CUSTOMIZE_COMPRESSION on diff --git a/libs/libpng-src/contrib/conftest/read.dfa b/libs/libpng-src/contrib/conftest/read.dfa new file mode 100644 index 000000000..21e88d01a --- /dev/null +++ b/libs/libpng-src/contrib/conftest/read.dfa @@ -0,0 +1,58 @@ +# read.dfa +# Build time configuration of libpng +# +# Author: John Bowler +# Copyright: (c) John Bowler, 2013 +# Usage rights: +# To the extent possible under law, the author has waived all copyright and +# related or neighboring rights to this work. This work is published from: +# United States. +# +# Build libpng with basic read support. This enables the lowest level libpng +# read API - the one where the calling code has to use a loop to read each row. +# At present this is the API used by most programs. +# +# Support is enabled only for those chunks and transformations that are +# typically required - others can be added easily. +# + +everything = off + +# The sequential read code is enabled here; the progressive code can be used +# instead but there is no point enabling both. + +option SEQUENTIAL_READ on + +# Likewise it is pointless enabling both fixed and floating point APIs. Choose +# one or the other for both the API and the internal math. + +#Fixed point: +#option FIXED_POINT on +#option FLOATING_ARITHMETIC off + +#Floating point: +option FLOATING_POINT on +option FLOATING_ARITHMETIC on + +# Basic error handling, IO and user memory support. The latter allows the +# application program to provide its own implementations of 'malloc' and 'free'. +option SETJMP on +option STDIO on +option USER_MEM on + +# To read the full set of PNG images correctly interlace, transparency and +# 16-bit support is required. The application can implement interlace itself, +# but very few do and it's no longer possible to disable it when READ is +# enabled. +option READ_tRNS on +option READ_16BIT on + +# Everything else is application dependent. This file assumes the app handles +# all the native PNG bit layouts, so it doesn't need any of layout change +# transforms, but needs libpng to perform gamma correction. It doesn't do any +# colorspace stuff and ignores the 'significant bit' information. +# +# If your app always expands the image to a limited set of bit layouts you +# probably want to consider using the simplified API instead of the low level +# one - see png.h and s_read.dfa. +option READ_GAMMA on diff --git a/libs/libpng-src/contrib/conftest/s_read.dfa b/libs/libpng-src/contrib/conftest/s_read.dfa new file mode 100644 index 000000000..cb1ce0ba6 --- /dev/null +++ b/libs/libpng-src/contrib/conftest/s_read.dfa @@ -0,0 +1,35 @@ +# s_read.dfa +# Build time configuration of libpng +# +# Author: John Bowler +# Copyright: (c) John Bowler, 2013 +# Usage rights: +# To the extent possible under law, the author has waived all copyright and +# related or neighboring rights to this work. This work is published from: +# United States. +# +# Build libpng with simplified read support (only). This builds a minimal +# libpng able to read all PNG formats and convert them into a small number of +# well understood memory formats. +# + +everything = off + +option SIMPLIFIED_READ on + +# It isn't necessary to chose fixed or floating point for the APIs because the +# simplified API doesn't need fixed or floating point numbers. It is necessary +# to chose an internal math implementation. The default (because of 'everything +# = off') is fixed point - turn the floating point implementation on if you have +# hardware floating point or prefer your software floating point implementation. +option FLOATING_ARITHMETIC on + +# This is not strictly necessary, but without it the message strings in the API +# will not be filled in +option ERROR_TEXT on + +# Switching these options on enables the 'AFIRST' and 'BGR' formats - you don't +# need this if you don't use them, they just allow the in-memory layout to be +# changed to match common hardware formats. +option SIMPLIFIED_READ_AFIRST on +option SIMPLIFIED_READ_BGR on diff --git a/libs/libpng-src/contrib/conftest/s_write.dfa b/libs/libpng-src/contrib/conftest/s_write.dfa new file mode 100644 index 000000000..e540a46dc --- /dev/null +++ b/libs/libpng-src/contrib/conftest/s_write.dfa @@ -0,0 +1,33 @@ +# s_write.dfa +# Build time configuration of libpng +# +# Author: John Bowler +# Copyright: (c) John Bowler, 2013 +# Usage rights: +# To the extent possible under law, the author has waived all copyright and +# related or neighboring rights to this work. This work is published from: +# United States. +# +# Build libpng with (just) simplified write support +# + +everything = off + +option SIMPLIFIED_WRITE on + +# It isn't necessary to chose fixed or floating point for the APIs because the +# simplified API doesn't need fixed or floating point numbers. It is necessary +# to chose an internal math implementation. The default (because of 'everything +# = off') is fixed point - turn the floating point implementation on if you have +# hardware floating point or prefer your software floating point implementation. +option FLOATING_ARITHMETIC on + +# This is not strictly necessary, but without it the message strings in the API +# will not be filled in +option ERROR_TEXT on + +# Switching these options on enables the 'AFIRST' and 'BGR' formats - you don't +# need this if you don't use them, they just allow the in-memory layout to be +# changed to match common hardware formats. +option SIMPLIFIED_WRITE_AFIRST on +option SIMPLIFIED_WRITE_BGR on diff --git a/libs/libpng-src/contrib/conftest/simple.dfa b/libs/libpng-src/contrib/conftest/simple.dfa new file mode 100644 index 000000000..041933344 --- /dev/null +++ b/libs/libpng-src/contrib/conftest/simple.dfa @@ -0,0 +1,36 @@ +# simple.dfa +# Build time configuration of libpng +# +# Author: John Bowler +# Copyright: (c) John Bowler, 2013 +# Usage rights: +# To the extent possible under law, the author has waived all copyright and +# related or neighboring rights to this work. This work is published from: +# United States. +# +# Build libpng with just the simplified APIs (read and write). +# + +everything = off + +option SIMPLIFIED_WRITE on +option SIMPLIFIED_READ on + +# It isn't necessary to chose fixed or floating point for the APIs because the +# simplified API doesn't need fixed or floating point numbers. It is necessary +# to chose an internal math implementation. The default (because of 'everything +# = off') is fixed point - turn the floating point implementation on if you have +# hardware floating point or prefer your software floating point implementation. +option FLOATING_ARITHMETIC on + +# This is not strictly necessary, but without it the message strings in the API +# will not be filled in +option ERROR_TEXT on + +# Switching these options on enables the 'AFIRST' and 'BGR' formats - you don't +# need this if you don't use them, they just allow the in-memory layout to be +# changed to match common hardware formats. +option SIMPLIFIED_READ_AFIRST on +option SIMPLIFIED_READ_BGR on +option SIMPLIFIED_WRITE_AFIRST on +option SIMPLIFIED_WRITE_BGR on diff --git a/libs/libpng-src/contrib/conftest/write.dfa b/libs/libpng-src/contrib/conftest/write.dfa new file mode 100644 index 000000000..3319aabee --- /dev/null +++ b/libs/libpng-src/contrib/conftest/write.dfa @@ -0,0 +1,45 @@ +# write.dfa +# Build time configuration of libpng +# +# Author: John Bowler +# Copyright: (c) John Bowler, 2013 +# Usage rights: +# To the extent possible under law, the author has waived all copyright and +# related or neighboring rights to this work. This work is published from: +# United States. +# +# Build libpng with no read support and minimal write support. +# + +everything = off + +# Switch on the write code - this makes a minimalist encoder + +option WRITE on + +# Choose fixed or floating point APIs and arithmetic. The choices are +# independent but normally they will match. It is typically better to use the +# floating point if you have floating point hardware. If you don't know, or +# (perhaps) to make libpng smaller used fixed point throughout. + +#Fixed point: +#option FIXED_POINT on +#option FLOATING_ARITHMETIC off + +#Floating point: +option FLOATING_POINT on +option FLOATING_ARITHMETIC on + +# Basic error handling, IO and user memory support. The latter allows the +# application program to provide its own implementations of 'malloc' and 'free'. +option SETJMP on +option STDIO on +option USER_MEM on + +# Everything else is optional. Unlike the read code in libpng the write code +# does not need to deal with arbitrary formats, so only add support for things +# you really do write! For example you might only write sRGB images, sometimes +# with transparency and never write 16 bit images, so: +option WRITE_sRGB on +option WRITE_tRNS on +#option WRITE_16BIT off (this is the default with 'everything = off') diff --git a/libs/libpng-src/contrib/examples/README.txt b/libs/libpng-src/contrib/examples/README.txt new file mode 100644 index 000000000..48dab4f0f --- /dev/null +++ b/libs/libpng-src/contrib/examples/README.txt @@ -0,0 +1,24 @@ + +This directory (contrib/examples) contains examples of libpng usage. + +NO COPYRIGHT RIGHTS ARE CLAIMED TO ANY OF THE FILES IN THIS DIRECTORY. + +To the extent possible under law, the authors have waived all copyright and +related or neighboring rights to this work. This work is published from: +United States. + +The files may be used freely in any way. The intention is that appropriate +parts of the files be used in other libpng-using programs without any need for +the authors of the using code to seek copyright or license from the original +authors. + +The source code and comments in this directory are the original work of the +people named below. No other person or organization has made contributions to +the work in this directory. + +ORIGINAL AUTHORS + The following people have contributed to the code in this directory. None + of the people below claim any rights with regard to the contents of this + directory. + + John Bowler diff --git a/libs/libpng-src/contrib/examples/iccfrompng.c b/libs/libpng-src/contrib/examples/iccfrompng.c new file mode 100644 index 000000000..00056abfd --- /dev/null +++ b/libs/libpng-src/contrib/examples/iccfrompng.c @@ -0,0 +1,185 @@ +/*- iccfrompng + * + * COPYRIGHT: Written by John Cunningham Bowler, 2011. + * To the extent possible under law, the author has waived all copyright and + * related or neighboring rights to this work. This work is published from: + * United States. + * + * Extract any icc profiles found in the given PNG files. This is a simple + * example of a program that extracts information from the header of a PNG file + * without processing the image. Notice that some header information may occur + * after the image data. Textual data and comments are an example; the approach + * in this file won't work reliably for such data because it only looks for the + * information in the section of the file that precedes the image data. + * + * Compile and link against libpng and zlib, plus anything else required on the + * system you use. + * + * To use supply a list of PNG files containing iCCP chunks, the chunks will be + * extracted to a similarly named file with the extension replaced by 'icc', + * which will be overwritten without warning. + */ +#include +#include +#include +#include + +#include + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) && \ + defined (PNG_iCCP_SUPPORTED) + + +static int verbose = 1; +static png_byte no_profile[] = "no profile"; + +static png_bytep +extract(FILE *fp, png_uint_32 *proflen) +{ + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); + png_infop info_ptr = NULL; + png_bytep result = NULL; + + /* Initialize for error or no profile: */ + *proflen = 0; + + if (png_ptr == NULL) + { + fprintf(stderr, "iccfrompng: version library mismatch?\n"); + return 0; + } + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return 0; + } + + png_init_io(png_ptr, fp); + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + png_error(png_ptr, "OOM allocating info structure"); + + png_read_info(png_ptr, info_ptr); + + { + png_charp name; + int compression_type; + png_bytep profile; + + if (png_get_iCCP(png_ptr, info_ptr, &name, &compression_type, &profile, + proflen) & PNG_INFO_iCCP) + { + result = malloc(*proflen); + if (result != NULL) + memcpy(result, profile, *proflen); + + else + png_error(png_ptr, "OOM allocating profile buffer"); + } + + else + result = no_profile; + } + + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + return result; +} + +static int +extract_one_file(const char *filename) +{ + int result = 0; + FILE *fp = fopen(filename, "rb"); + + if (fp != NULL) + { + png_uint_32 proflen = 0; + png_bytep profile = extract(fp, &proflen); + + if (profile != NULL && profile != no_profile) + { + size_t len; + char *output; + + { + const char *ep = strrchr(filename, '.'); + + if (ep != NULL) + len = ep-filename; + + else + len = strlen(filename); + } + + output = malloc(len + 5); + if (output != NULL) + { + FILE *of; + + memcpy(output, filename, len); + strcpy(output+len, ".icc"); + + of = fopen(output, "wb"); + if (of != NULL) + { + if (fwrite(profile, proflen, 1, of) == 1 && + fflush(of) == 0 && + fclose(of) == 0) + { + if (verbose) + printf("%s -> %s\n", filename, output); + /* Success return */ + result = 1; + } + + else + { + fprintf(stderr, "%s: error writing profile\n", output); + if (remove(output)) + fprintf(stderr, "%s: could not remove file\n", output); + } + } + + else + fprintf(stderr, "%s: failed to open output file\n", output); + + free(output); + } + + else + fprintf(stderr, "%s: OOM allocating string!\n", filename); + + free(profile); + } + + else if (verbose && profile == no_profile) + printf("%s has no profile\n", filename); + } + + else + fprintf(stderr, "%s: could not open file\n", filename); + + return result; +} + +int +main(int argc, char **argv) +{ + int i; + int extracted = 0; + + for (i=1; i +#include +#include /* required for error handling */ + +/* Normally use here to get the installed libpng, but this is done to + * ensure the code picks up the local libpng implementation: + */ +#include "../../png.h" + +#if defined(PNG_READ_SUPPORTED) && defined(PNG_SEQUENTIAL_READ_SUPPORTED) + +/* Return component 'c' of pixel 'x' from the given row. */ +static unsigned int +component(png_const_bytep row, png_uint_32 x, unsigned int c, + unsigned int bit_depth, unsigned int channels) +{ + /* PNG images can be up to 2^31 pixels wide, but this means they can be up to + * 2^37 bits wide (for a 64-bit pixel - the largest possible) and hence 2^34 + * bytes wide. Since the row fitted into memory, however, the following must + * work: + */ + png_uint_32 bit_offset_hi = bit_depth * ((x >> 6) * channels); + png_uint_32 bit_offset_lo = bit_depth * ((x & 0x3f) * channels + c); + + row = (png_const_bytep)(((const png_byte (*)[8])row) + bit_offset_hi); + row += bit_offset_lo >> 3; + bit_offset_lo &= 0x07; + + /* PNG pixels are packed into bytes to put the first pixel in the highest + * bits of the byte and into two bytes for 16-bit values with the high 8 bits + * first, so: + */ + switch (bit_depth) + { + case 1: return (row[0] >> (7-bit_offset_lo)) & 0x01; + case 2: return (row[0] >> (6-bit_offset_lo)) & 0x03; + case 4: return (row[0] >> (4-bit_offset_lo)) & 0x0f; + case 8: return row[0]; + case 16: return (row[0] << 8) + row[1]; + default: + /* This should never happen; it indicates a bug in this program or in + * libpng itself: + */ + fprintf(stderr, "pngpixel: invalid bit depth %u\n", bit_depth); + exit(1); + } +} + +/* Print a pixel from a row returned by libpng; determine the row format, find + * the pixel, and print the relevant information to stdout. + */ +static void +print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row, + png_uint_32 x) +{ + unsigned int bit_depth = png_get_bit_depth(png_ptr, info_ptr); + + switch (png_get_color_type(png_ptr, info_ptr)) + { + case PNG_COLOR_TYPE_GRAY: + printf("GRAY %u\n", component(row, x, 0, bit_depth, 1)); + return; + + /* The palette case is slightly more difficult - the palette and, if + * present, the tRNS ('transparency', though the values are really + * opacity) data must be read to give the full picture: + */ + case PNG_COLOR_TYPE_PALETTE: + { + int index = component(row, x, 0, bit_depth, 1); + png_colorp palette = NULL; + int num_palette = 0; + + if ((png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) & + PNG_INFO_PLTE) && num_palette > 0 && palette != NULL) + { + png_bytep trans_alpha = NULL; + int num_trans = 0; + if ((png_get_tRNS(png_ptr, info_ptr, &trans_alpha, &num_trans, + NULL) & PNG_INFO_tRNS) && num_trans > 0 && + trans_alpha != NULL) + printf("INDEXED %u = %d %d %d %d\n", index, + palette[index].red, palette[index].green, + palette[index].blue, + index < num_trans ? trans_alpha[index] : 255); + + else /* no transparency */ + printf("INDEXED %u = %d %d %d\n", index, + palette[index].red, palette[index].green, + palette[index].blue); + } + + else + printf("INDEXED %u = invalid index\n", index); + } + return; + + case PNG_COLOR_TYPE_RGB: + printf("RGB %u %u %u\n", component(row, x, 0, bit_depth, 3), + component(row, x, 1, bit_depth, 3), + component(row, x, 2, bit_depth, 3)); + return; + + case PNG_COLOR_TYPE_GRAY_ALPHA: + printf("GRAY+ALPHA %u %u\n", component(row, x, 0, bit_depth, 2), + component(row, x, 1, bit_depth, 2)); + return; + + case PNG_COLOR_TYPE_RGB_ALPHA: + printf("RGBA %u %u %u %u\n", component(row, x, 0, bit_depth, 4), + component(row, x, 1, bit_depth, 4), + component(row, x, 2, bit_depth, 4), + component(row, x, 3, bit_depth, 4)); + return; + + default: + png_error(png_ptr, "pngpixel: invalid color type"); + } +} + +int main(int argc, const char **argv) +{ + /* This program uses the default, based, libpng error handling + * mechanism, therefore any local variable that exists before the call to + * setjmp and is changed after the call to setjmp returns successfully must + * be declared with 'volatile' to ensure that their values don't get + * destroyed by longjmp: + */ + volatile int result = 1/*fail*/; + + if (argc == 4) + { + long x = atol(argv[1]); + long y = atol(argv[2]); + FILE *f = fopen(argv[3], "rb"); + volatile png_bytep row = NULL; + + if (f != NULL) + { + /* libpng requires a callback function for handling errors; this + * callback must not return. The default callback function uses a + * stored style jmp_buf which is held in a png_struct and + * writes error messages to stderr. Creating the png_struct is a + * little tricky; just copy the following code. + */ + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + NULL, NULL, NULL); + + if (png_ptr != NULL) + { + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr != NULL) + { + /* Declare stack variables to hold pointers to locally allocated + * data. + */ + + /* Initialize the error control buffer: */ + if (setjmp(png_jmpbuf(png_ptr)) == 0) + { + png_uint_32 width, height; + int bit_depth, color_type, interlace_method, + compression_method, filter_method; + png_bytep row_tmp; + + /* Now associate the recently opened (FILE*) with the default + * libpng initialization functions. Sometimes libpng is + * compiled without stdio support (it can be difficult to do + * in some environments); in that case you will have to write + * your own read callback to read data from the (FILE*). + */ + png_init_io(png_ptr, f); + + /* And read the first part of the PNG file - the header and + * all the information up to the first pixel. + */ + png_read_info(png_ptr, info_ptr); + + /* This fills in enough information to tell us the width of + * each row in bytes, allocate the appropriate amount of + * space. In this case png_malloc is used - it will not + * return if memory isn't available. + */ + row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, + info_ptr)); + + /* To avoid the overhead of using a volatile auto copy row_tmp + * to a local here - just use row for the png_free below. + */ + row_tmp = row; + + /* All the information we need is in the header is returned by + * png_get_IHDR, if this fails we can now use 'png_error' to + * signal the error and return control to the setjmp above. + */ + if (png_get_IHDR(png_ptr, info_ptr, &width, &height, + &bit_depth, &color_type, &interlace_method, + &compression_method, &filter_method)) + { + int passes, pass; + + /* png_set_interlace_handling returns the number of + * passes required as well as turning on libpng's + * handling, but since we do it ourselves this is + * necessary: + */ + switch (interlace_method) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + png_error(png_ptr, "pngpixel: unknown interlace"); + } + + /* Now read the pixels, pass-by-pass, row-by-row: */ + png_start_read_image(png_ptr); + + for (pass=0; pass +#include +#include +#include + +/* Normally use here to get the installed libpng, but this is done to + * ensure the code picks up the local libpng implementation: + */ +#include "../../png.h" +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + +int main(int argc, const char **argv) +{ + int result = 1; + + if (argc == 3) + { + png_image image; + + /* Only the image structure version number needs to be set. */ + memset(&image, 0, sizeof image); + image.version = PNG_IMAGE_VERSION; + + if (png_image_begin_read_from_file(&image, argv[1])) + { + png_bytep buffer; + + /* Change this to try different formats! If you set a colormap format + * then you must also supply a colormap below. + */ + image.format = PNG_FORMAT_RGBA; + + buffer = malloc(PNG_IMAGE_SIZE(image)); + + if (buffer != NULL) + { + if (png_image_finish_read(&image, NULL/*background*/, buffer, + 0/*row_stride*/, NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP */)) + { + if (png_image_write_to_file(&image, argv[2], + 0/*convert_to_8bit*/, buffer, 0/*row_stride*/, + NULL/*colormap*/)) + result = 0; + + else + fprintf(stderr, "pngtopng: write %s: %s\n", argv[2], + image.message); + } + + else + fprintf(stderr, "pngtopng: read %s: %s\n", argv[1], + image.message); + + free(buffer); + } + + else + { + fprintf(stderr, "pngtopng: out of memory: %lu bytes\n", + (unsigned long)PNG_IMAGE_SIZE(image)); + + /* This is the only place where a 'free' is required; libpng does + * the cleanup on error and success, but in this case we couldn't + * complete the read because of running out of memory and so libpng + * has not got to the point where it can do cleanup. + */ + png_image_free(&image); + } + } + + else + /* Failed to read the first argument: */ + fprintf(stderr, "pngtopng: %s: %s\n", argv[1], image.message); + } + + else + /* Wrong number of arguments */ + fprintf(stderr, "pngtopng: usage: pngtopng input-file output-file\n"); + + return result; +} +#endif /* READ && WRITE */ diff --git a/libs/libpng-src/contrib/examples/simpleover.c b/libs/libpng-src/contrib/examples/simpleover.c new file mode 100644 index 000000000..59dd31368 --- /dev/null +++ b/libs/libpng-src/contrib/examples/simpleover.c @@ -0,0 +1,648 @@ +/*- simpleover + * + * COPYRIGHT: Written by John Cunningham Bowler, 2015. + * To the extent possible under law, the author has waived all copyright and + * related or neighboring rights to this work. This work is published from: + * United States. + * + * Read several PNG files, which should have an alpha channel or transparency + * information, and composite them together to produce one or more 16-bit linear + * RGBA intermediates. This involves doing the correct 'over' composition to + * combine the alpha channels and corresponding data. + * + * Finally read an output (background) PNG using the 24-bit RGB format (the + * PNG will be composited on green (#00ff00) by default if it has an alpha + * channel), and apply the intermediate image generated above to specified + * locations in the image. + * + * The command line has the general format: + * + * simpleover [output.png] + * {--sprite=width,height,name {[--at=x,y] {sprite.png}}} + * {--add=name {x,y}} + * + * The --sprite and --add options may occur multiple times. They are executed + * in order. --add may refer to any sprite already read. + * + * This code is intended to show how to composite multiple images together + * correctly. Apart from the libpng Simplified API the only work done in here + * is to combine multiple input PNG images into a single sprite; this involves + * a Porter-Duff 'over' operation and the input PNG images may, as a result, + * be regarded as being layered one on top of the other with the first (leftmost + * on the command line) being at the bottom and the last on the top. + */ +#include +#include +#include +#include +#include + +/* Normally use here to get the installed libpng, but this is done to + * ensure the code picks up the local libpng implementation, so long as this + * file is linked against a sufficiently recent libpng (1.6+) it is ok to + * change this to : + */ +#include "../../png.h" + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED + +#define sprite_name_chars 15 +struct sprite { + FILE *file; + png_uint_16p buffer; + unsigned int width; + unsigned int height; + char name[sprite_name_chars+1]; +}; + +#if 0 /* div by 65535 test program */ +#include +#include + +int main(void) { + double err = 0; + unsigned int xerr = 0; + unsigned int r = 32769; + { + unsigned int x = 0; + + do { + unsigned int t = x + (x >> 16) /*+ (x >> 31)*/ + r; + double v = x, errtest; + + if (t < x) { + fprintf(stderr, "overflow: %u+%u -> %u\n", x, r, t); + return 1; + } + + v /= 65535; + errtest = v; + t >>= 16; + errtest -= t; + + if (errtest > err) { + err = errtest; + xerr = x; + + if (errtest >= .5) { + fprintf(stderr, "error: %u/65535 = %f, not %u, error %f\n", + x, v, t, errtest); + return 0; + } + } + } while (++x <= 65535U*65535U); + } + + printf("error %f @ %u\n", err, xerr); + + return 0; +} +#endif /* div by 65535 test program */ + +static void +sprite_op(const struct sprite *sprite, int x_offset, int y_offset, + png_imagep image, const png_uint_16 *buffer) +{ + /* This is where the Porter-Duff 'Over' operator is evaluated; change this + * code to change the operator (this could be parameterized). Any other + * image processing operation could be used here. + */ + + + /* Check for an x or y offset that pushes any part of the image beyond the + * right or bottom of the sprite: + */ + if ((y_offset < 0 || (unsigned)/*SAFE*/y_offset < sprite->height) && + (x_offset < 0 || (unsigned)/*SAFE*/x_offset < sprite->width)) + { + unsigned int y = 0; + + if (y_offset < 0) + y = -y_offset; /* Skip to first visible row */ + + do + { + unsigned int x = 0; + + if (x_offset < 0) + x = -x_offset; + + do + { + /* In and out are RGBA values, so: */ + const png_uint_16 *in_pixel = buffer + (y * image->width + x)*4; + png_uint_32 in_alpha = in_pixel[3]; + + /* This is the optimized Porter-Duff 'Over' operation, when the + * input alpha is 0 the output is not changed. + */ + if (in_alpha > 0) + { + png_uint_16 *out_pixel = sprite->buffer + + ((y+y_offset) * sprite->width + (x+x_offset))*4; + + /* This is the weight to apply to the output: */ + in_alpha = 65535-in_alpha; + + if (in_alpha > 0) + { + /* The input must be composed onto the output. This means + * multiplying the current output pixel value by the inverse + * of the input alpha (1-alpha). A division is required but + * it is by the constant 65535. Approximate this as: + * + * (x + (x >> 16) + 32769) >> 16; + * + * This is exact (and does not overflow) for all values of + * x in the range 0..65535*65535. (Note that the calculation + * produces the closest integer; the maximum error is <0.5). + */ + png_uint_32 tmp; + +# define compose(c)\ + tmp = out_pixel[c] * in_alpha;\ + tmp = (tmp + (tmp >> 16) + 32769) >> 16;\ + out_pixel[c] = tmp + in_pixel[c] + + /* The following is very vectorizable... */ + compose(0); + compose(1); + compose(2); + compose(3); + } + + else + out_pixel[0] = in_pixel[0], + out_pixel[1] = in_pixel[1], + out_pixel[2] = in_pixel[2], + out_pixel[3] = in_pixel[3]; + } + } + while (++x < image->width); + } + while (++y < image->height); + } +} + +static int +create_sprite(struct sprite *sprite, int *argc, const char ***argv) +{ + /* Read the arguments and create this sprite. The sprite buffer has already + * been allocated. This reads the input PNGs one by one in linear format, + * composes them onto the sprite buffer (the code in the function above) + * then saves the result, converting it on the fly to PNG RGBA 8-bit format. + */ + while (*argc > 0) + { + char tombstone; + int x = 0, y = 0; + + if ((*argv)[0][0] == '-' && (*argv)[0][1] == '-') + { + /* The only supported option is --at. */ + if (sscanf((*argv)[0], "--at=%d,%d%c", &x, &y, &tombstone) != 2) + break; /* success; caller will parse this option */ + + ++*argv, --*argc; + } + + else + { + /* The argument has to be a file name */ + png_image image; + + image.version = PNG_IMAGE_VERSION; + image.opaque = NULL; + + if (png_image_begin_read_from_file(&image, (*argv)[0])) + { + png_uint_16p buffer; + + image.format = PNG_FORMAT_LINEAR_RGB_ALPHA; + + buffer = malloc(PNG_IMAGE_SIZE(image)); + + if (buffer != NULL) + { + if (png_image_finish_read(&image, NULL/*background*/, buffer, + 0/*row_stride*/, + NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP*/)) + { + /* This is the place where the Porter-Duff 'Over' operator + * needs to be done by this code. In fact, any image + * processing required can be done here; the data is in + * the correct format (linear, 16-bit) and source and + * destination are in memory. + */ + sprite_op(sprite, x, y, &image, buffer); + free(buffer); + ++*argv, --*argc; + /* And continue to the next argument */ + continue; + } + + else + { + free(buffer); + fprintf(stderr, "simpleover: read %s: %s\n", (*argv)[0], + image.message); + } + } + + else + { + fprintf(stderr, "simpleover: out of memory: %lu bytes\n", + (unsigned long)PNG_IMAGE_SIZE(image)); + + /* png_image_free must be called if we abort the Simplified API + * read because of a problem detected in this code. If problems + * are detected in the Simplified API it cleans up itself. + */ + png_image_free(&image); + } + } + + else + { + /* Failed to read the first argument: */ + fprintf(stderr, "simpleover: %s: %s\n", (*argv)[0], image.message); + } + + return 0; /* failure */ + } + } + + /* All the sprite operations have completed successfully. Save the RGBA + * buffer as a PNG using the simplified write API. + */ + sprite->file = tmpfile(); + + if (sprite->file != NULL) + { + png_image save; + + memset(&save, 0, sizeof save); + save.version = PNG_IMAGE_VERSION; + save.opaque = NULL; + save.width = sprite->width; + save.height = sprite->height; + save.format = PNG_FORMAT_LINEAR_RGB_ALPHA; + save.flags = PNG_IMAGE_FLAG_FAST; + save.colormap_entries = 0; + + if (png_image_write_to_stdio(&save, sprite->file, 1/*convert_to_8_bit*/, + sprite->buffer, 0/*row_stride*/, NULL/*colormap*/)) + { + /* Success; the buffer is no longer needed: */ + free(sprite->buffer); + sprite->buffer = NULL; + return 1; /* ok */ + } + + else + fprintf(stderr, "simpleover: write sprite %s: %s\n", sprite->name, + save.message); + } + + else + fprintf(stderr, "simpleover: sprite %s: could not allocate tmpfile: %s\n", + sprite->name, strerror(errno)); + + return 0; /* fail */ +} + +static int +add_sprite(png_imagep output, png_bytep out_buf, struct sprite *sprite, + int *argc, const char ***argv) +{ + /* Given a --add argument naming this sprite, perform the operations listed + * in the following arguments. The arguments are expected to have the form + * (x,y), which is just an offset at which to add the sprite to the + * output. + */ + while (*argc > 0) + { + char tombstone; + int x, y; + + if ((*argv)[0][0] == '-' && (*argv)[0][1] == '-') + return 1; /* success */ + + if (sscanf((*argv)[0], "%d,%d%c", &x, &y, &tombstone) == 2) + { + /* Now add the new image into the sprite data, but only if it + * will fit. + */ + if (x < 0 || y < 0 || + (unsigned)/*SAFE*/x >= output->width || + (unsigned)/*SAFE*/y >= output->height || + sprite->width > output->width-x || + sprite->height > output->height-y) + { + fprintf(stderr, "simpleover: sprite %s @ (%d,%d) outside image\n", + sprite->name, x, y); + /* Could just skip this, but for the moment it is an error */ + return 0; /* error */ + } + + else + { + /* Since we know the sprite fits we can just read it into the + * output using the simplified API. + */ + png_image in; + + in.version = PNG_IMAGE_VERSION; + rewind(sprite->file); + + if (png_image_begin_read_from_stdio(&in, sprite->file)) + { + in.format = PNG_FORMAT_RGB; /* force compose */ + + if (png_image_finish_read(&in, NULL/*background*/, + out_buf + (y*output->width + x)*3/*RGB*/, + output->width*3/*row_stride*/, + NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP*/)) + { + ++*argv, --*argc; + continue; + } + } + + /* The read failed: */ + fprintf(stderr, "simpleover: add sprite %s: %s\n", sprite->name, + in.message); + return 0; /* error */ + } + } + + else + { + fprintf(stderr, "simpleover: --add='%s': invalid position %s\n", + sprite->name, (*argv)[0]); + return 0; /* error */ + } + } + + return 1; /* ok */ +} + +static int +simpleover_process(png_imagep output, png_bytep out_buf, int argc, + const char **argv) +{ + int result = 1; /* success */ +# define csprites 10/*limit*/ +# define str(a) #a + int nsprites = 0; + struct sprite sprites[csprites]; + + while (argc > 0) + { + result = 0; /* fail */ + + if (strncmp(argv[0], "--sprite=", 9) == 0) + { + char tombstone; + + if (nsprites < csprites) + { + int n; + + sprites[nsprites].width = sprites[nsprites].height = 0; + sprites[nsprites].name[0] = 0; + + n = sscanf(argv[0], "--sprite=%u,%u,%" str(sprite_name_chars) "s%c", + &sprites[nsprites].width, &sprites[nsprites].height, + sprites[nsprites].name, &tombstone); + + if ((n == 2 || n == 3) && + sprites[nsprites].width > 0 && sprites[nsprites].height > 0) + { + size_t buf_size, tmp; + + /* Default a name if not given. */ + if (sprites[nsprites].name[0] == 0) + sprintf(sprites[nsprites].name, "sprite-%d", nsprites+1); + + /* Allocate a buffer for the sprite and calculate the buffer + * size: + */ + buf_size = sizeof (png_uint_16 [4]); + buf_size *= sprites[nsprites].width; + buf_size *= sprites[nsprites].height; + + /* This can overflow a (size_t); check for this: */ + tmp = buf_size; + tmp /= sprites[nsprites].width; + tmp /= sprites[nsprites].height; + + if (tmp == sizeof (png_uint_16 [4])) + { + sprites[nsprites].buffer = malloc(buf_size); + /* This buffer must be initialized to transparent: */ + memset(sprites[nsprites].buffer, 0, buf_size); + + if (sprites[nsprites].buffer != NULL) + { + sprites[nsprites].file = NULL; + ++argv, --argc; + + if (create_sprite(sprites+nsprites++, &argc, &argv)) + { + result = 1; /* still ok */ + continue; + } + + break; /* error */ + } + } + + /* Overflow, or OOM */ + fprintf(stderr, "simpleover: %s: sprite too large\n", argv[0]); + break; + } + + else + { + fprintf(stderr, "simpleover: %s: invalid sprite (%u,%u)\n", + argv[0], sprites[nsprites].width, sprites[nsprites].height); + break; + } + } + + else + { + fprintf(stderr, "simpleover: %s: too many sprites\n", argv[0]); + break; + } + } + + else if (strncmp(argv[0], "--add=", 6) == 0) + { + const char *name = argv[0]+6; + int isprite = nsprites; + + ++argv, --argc; + + while (--isprite >= 0) + { + if (strcmp(sprites[isprite].name, name) == 0) + { + if (!add_sprite(output, out_buf, sprites+isprite, &argc, &argv)) + goto out; /* error in add_sprite */ + + break; + } + } + + if (isprite < 0) /* sprite not found */ + { + fprintf(stderr, "simpleover: --add='%s': sprite not found\n", name); + break; + } + } + + else + { + fprintf(stderr, "simpleover: %s: unrecognized operation\n", argv[0]); + break; + } + + result = 1; /* ok */ + } + + /* Clean up the cache of sprites: */ +out: + while (--nsprites >= 0) + { + if (sprites[nsprites].buffer != NULL) + free(sprites[nsprites].buffer); + + if (sprites[nsprites].file != NULL) + (void)fclose(sprites[nsprites].file); + } + + return result; +} + +int main(int argc, const char **argv) +{ + int result = 1; /* default to fail */ + + if (argc >= 2) + { + int argi = 2; + const char *output = NULL; + png_image image; + + if (argc > 2 && argv[2][0] != '-'/*an operation*/) + { + output = argv[2]; + argi = 3; + } + + image.version = PNG_IMAGE_VERSION; + image.opaque = NULL; + + if (png_image_begin_read_from_file(&image, argv[1])) + { + png_bytep buffer; + + image.format = PNG_FORMAT_RGB; /* 24-bit RGB */ + + buffer = malloc(PNG_IMAGE_SIZE(image)); + + if (buffer != NULL) + { + png_color background = {0, 0xff, 0}; /* fully saturated green */ + + if (png_image_finish_read(&image, &background, buffer, + 0/*row_stride*/, NULL/*colormap for PNG_FORMAT_FLAG_COLORMAP */)) + { + /* At this point png_image_finish_read has cleaned up the + * allocated data in png_image, and only the buffer needs to be + * freed. + * + * Perform the remaining operations: + */ + if (simpleover_process(&image, buffer, argc-argi, argv+argi)) + { + /* Write the output: */ + if ((output != NULL && + png_image_write_to_file(&image, output, + 0/*convert_to_8bit*/, buffer, 0/*row_stride*/, + NULL/*colormap*/)) || + (output == NULL && + png_image_write_to_stdio(&image, stdout, + 0/*convert_to_8bit*/, buffer, 0/*row_stride*/, + NULL/*colormap*/))) + result = 0; + + else + fprintf(stderr, "simpleover: write %s: %s\n", + output == NULL ? "stdout" : output, image.message); + } + + /* else simpleover_process writes an error message */ + } + + else + fprintf(stderr, "simpleover: read %s: %s\n", argv[1], + image.message); + + free(buffer); + } + + else + { + fprintf(stderr, "simpleover: out of memory: %lu bytes\n", + (unsigned long)PNG_IMAGE_SIZE(image)); + + /* This is the only place where a 'free' is required; libpng does + * the cleanup on error and success, but in this case we couldn't + * complete the read because of running out of memory. + */ + png_image_free(&image); + } + } + + else + { + /* Failed to read the first argument: */ + fprintf(stderr, "simpleover: %s: %s\n", argv[1], image.message); + } + } + + else + { + /* Usage message */ + fprintf(stderr, + "simpleover: usage: simpleover background.png [output.png]\n" + " Output 'background.png' as a 24-bit RGB PNG file in 'output.png'\n" + " or, if not given, stdout. 'background.png' will be composited\n" + " on fully saturated green.\n" + "\n" + " Optionally, before output, process additional PNG files:\n" + "\n" + " --sprite=width,height,name {[--at=x,y] {sprite.png}}\n" + " Produce a transparent sprite of size (width,height) and with\n" + " name 'name'.\n" + " For each sprite.png composite it using a Porter-Duff 'Over'\n" + " operation at offset (x,y) in the sprite (defaulting to (0,0)).\n" + " Input PNGs will be truncated to the area of the sprite.\n" + "\n" + " --add='name' {x,y}\n" + " Optionally, before output, composite a sprite, 'name', which\n" + " must have been previously produced using --sprite, at each\n" + " offset (x,y) in the output image. Each sprite must fit\n" + " completely within the output image.\n" + "\n" + " PNG files are processed in the order they occur on the command\n" + " line and thus the first PNG processed appears as the bottommost\n" + " in the output image.\n"); + } + + return result; +} +#endif /* SIMPLIFIED_READ */ diff --git a/libs/libpng-src/contrib/gregbook/COPYING b/libs/libpng-src/contrib/gregbook/COPYING index d60c31a97..a3e977479 100644 --- a/libs/libpng-src/contrib/gregbook/COPYING +++ b/libs/libpng-src/contrib/gregbook/COPYING @@ -1,12 +1,12 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. - Preamble + Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public @@ -56,7 +56,7 @@ patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. - GNU GENERAL PUBLIC LICENSE + GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains @@ -255,7 +255,7 @@ 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 + NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN @@ -277,9 +277,9 @@ 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. - END OF TERMS AND CONDITIONS + END OF TERMS AND CONDITIONS - How to Apply These Terms to Your New Programs + How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it diff --git a/libs/libpng-src/contrib/gregbook/Makefile.mingw32 b/libs/libpng-src/contrib/gregbook/Makefile.mingw32 index e70a59aef..3a3ff607e 100644 --- a/libs/libpng-src/contrib/gregbook/Makefile.mingw32 +++ b/libs/libpng-src/contrib/gregbook/Makefile.mingw32 @@ -47,7 +47,8 @@ CC = gcc #CC = i386-mingw32msvc-gcc # e.g., Linux -> Win32 cross-compilation LD = $(CC) RM = rm -f -CFLAGS = -O -Wall $(INCS) $(MINGW_CCFLAGS) +CPPFLAGS = $(INCS) +CFLAGS = -O -Wall $(MINGW_CCFLAGS) # [note that -Wall is a gcc-specific compilation flag ("most warnings on")] # [-ansi, -pedantic and -W can also be used] LDFLAGS = $(MINGW_LDFLAGS) @@ -85,10 +86,10 @@ EXES = $(STATIC_EXES) $(DYNAMIC_EXES) # implicit make rules ------------------------------------------------------- .c$(O): - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< %.pic$(O): %.c - $(CC) -c $(CFLAGS) -DPNG_BUILD_DLL -o $@ $< + $(CC) -c $(CPPFLAGS) $(CFLAGS) -DPNG_BUILD_DLL -o $@ $< # dependencies -------------------------------------------------------------- diff --git a/libs/libpng-src/contrib/gregbook/Makefile.sgi b/libs/libpng-src/contrib/gregbook/Makefile.sgi index e3ca6ce4c..94d61b465 100644 --- a/libs/libpng-src/contrib/gregbook/Makefile.sgi +++ b/libs/libpng-src/contrib/gregbook/Makefile.sgi @@ -23,9 +23,9 @@ # macros -------------------------------------------------------------------- -PNGINC = -I/usr/local/include/libpng12 -PNGLIB = -L/usr/local/lib -lpng12 # dynamically linked against libpng -#PNGLIB = /usr/local/lib/libpng12.a # statically linked against libpng +PNGINC = -I/usr/local/include/libpng16 +PNGLIB = -L/usr/local/lib -lpng16 # dynamically linked against libpng +#PNGLIB = /usr/local/lib/libpng16.a # statically linked against libpng # or: #PNGINC = -I../.. #PNGLIB = -L../.. -lpng @@ -53,7 +53,8 @@ CC = cc LD = cc RM = rm -f # ABI must be the same as that used to build libpng. -ABI= +ABI = +CPPFLAGS = CFLAGS = $(ABI) -O -fullwarn $(INCS) LDFLAGS = $(ABI) O = .o @@ -73,7 +74,7 @@ EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E) # implicit make rules ------------------------------------------------------- .c$(O): - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< # dependencies -------------------------------------------------------------- diff --git a/libs/libpng-src/contrib/gregbook/Makefile.unx b/libs/libpng-src/contrib/gregbook/Makefile.unx index 7ff65bfb7..1a73e03bf 100644 --- a/libs/libpng-src/contrib/gregbook/Makefile.unx +++ b/libs/libpng-src/contrib/gregbook/Makefile.unx @@ -26,14 +26,14 @@ # macros -------------------------------------------------------------------- #PNGDIR = /usr/local/lib -#PNGINC = -I/usr/local/include/libpng12 -#PNGLIBd = -L$(PNGDIR) -lpng12 # dynamically linked, installed libpng -#PNGLIBs = $(PNGDIR)/libpng12.a # statically linked, installed libpng +#PNGINC = -I/usr/local/include/libpng16 +#PNGLIBd = -L$(PNGDIR) -lpng16 # dynamically linked, installed libpng +#PNGLIBs = $(PNGDIR)/libpng16.a # statically linked, installed libpng # or: PNGDIR = ../..# this one is for libpng-x.y.z/contrib/gregbook builds #PNGDIR = ../libpng PNGINC = -I$(PNGDIR) -PNGLIBd = -Wl,-rpath,$(PNGDIR) -L$(PNGDIR) -lpng12 # dynamically linked +PNGLIBd = -Wl,-rpath,$(PNGDIR) -L$(PNGDIR) -lpng16 # dynamically linked PNGLIBs = $(PNGDIR)/libpng.a # statically linked, local libpng ZDIR = /usr/local/lib @@ -59,14 +59,16 @@ INCS = $(PNGINC) $(ZINC) $(XINC) RLIBSd = $(PNGLIBd) $(ZLIBd) $(XLIB) -lm RLIBSs = $(PNGLIBs) $(ZLIBs) $(XLIB) -lm WLIBSd = $(PNGLIBd) $(ZLIBd) -lm -WLIBSs = $(PNGLIBs) $(ZLIBs) +WLIBSs = $(PNGLIBs) $(ZLIBs) -lm CC = gcc LD = gcc RM = rm -f -CFLAGS = -O -Wall $(INCS) -DFEATURE_LOOP +CPPFLAGS = $(INCS) -DFEATURE_LOOP +CFLAGS = -O -Wall +#CFLAGS = -O -W -Wall -Wextra -pedantic -ansi # [note that -Wall is a gcc-specific compilation flag ("most warnings on")] -# [-ansi, -pedantic and -W can also be used] +# [-ansi, -pedantic, -Wextra, and -W can also be used] LDFLAGS = O = .o E = @@ -92,7 +94,7 @@ EXES = $(STATIC_EXES) $(DYNAMIC_EXES) # implicit make rules ------------------------------------------------------- .c$(O): - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< # dependencies -------------------------------------------------------------- diff --git a/libs/libpng-src/contrib/gregbook/Makefile.w32 b/libs/libpng-src/contrib/gregbook/Makefile.w32 index 3c0808593..ab7dcf7ca 100644 --- a/libs/libpng-src/contrib/gregbook/Makefile.w32 +++ b/libs/libpng-src/contrib/gregbook/Makefile.w32 @@ -18,7 +18,7 @@ # "c:\windows\command.com /e:4096" as the program command line and set the # working directory to this directory. Then double-click to open the new # DOS-prompt window with a bigger environment and retry the commands above. -# +# # This makefile assumes libpng and zlib have already been built or downloaded # and are in subdirectories at the same level as the current subdirectory # (as indicated by the PNGPATH and ZPATH macros below). Edit as appropriate. @@ -53,7 +53,8 @@ WLIBS = $(PNGLIB) $(ZLIB) CC = cl LD = link RM = del -CFLAGS = -nologo -O -W3 $(INCS) $(cvars) +CPPFLAGS = $(INCS) +CFLAGS = -nologo -O -W3 $(cvars) # [note that -W3 is an MSVC-specific compilation flag ("all warnings on")] # [see %devstudio%\vc\include\win32.mak for cvars macro definition] O = .obj @@ -76,7 +77,7 @@ EXES = $(RPNG)$(E) $(RPNG2)$(E) $(WPNG)$(E) # implicit make rules ------------------------------------------------------- .c$(O): - $(CC) -c $(CFLAGS) $< + $(CC) -c $(CPPFLAGS) $(CFLAGS) $< # dependencies -------------------------------------------------------------- diff --git a/libs/libpng-src/contrib/gregbook/README b/libs/libpng-src/contrib/gregbook/README index cb6e5257e..90e28f7ce 100644 --- a/libs/libpng-src/contrib/gregbook/README +++ b/libs/libpng-src/contrib/gregbook/README @@ -15,7 +15,7 @@ of PBMPLUS/NetPBM) and converts them to PNG. The source code for all three demo programs currently compiles under Unix, OpenVMS, and 32-bit Windows. (Special thanks to Martin Zinser, -zinser@decus.de, for making the necessary changes for OpenVMS and for +zinser at decus.de, for making the necessary changes for OpenVMS and for providing an appropriate build script.) Build instructions can be found below. @@ -55,7 +55,7 @@ mation and links to the latest version of the source code, and Chapters 13-15 of the book for detailed discussion of the three programs. Greg Roelofs -http://pobox.com/~newt/greg_contact.html +https://pobox.com/~newt/greg_contact.html 16 March 2008 @@ -63,9 +63,9 @@ BUILD INSTRUCTIONS - Prerequisites (in order of compilation): - - zlib http://zlib.net/ - - libpng http://www.libpng.org/pub/png/libpng.html - - pngbook http://www.libpng.org/pub/png/book/sources.html + - zlib https://zlib.net/ + - libpng http://www.libpng.org/pub/png/libpng.html + - pngbook http://www.libpng.org/pub/png/book/sources.html The pngbook demo programs are explicitly designed to demonstrate proper coding techniques for using the libpng reference library. As a result, @@ -104,7 +104,7 @@ BUILD INSTRUCTIONS unpacked the source code. For MSVC, set up the necessary environment variables by invoking - + %devstudio%\vc\bin\vcvars32.bat where where %devstudio% is the installation directory for MSVC / @@ -165,19 +165,19 @@ RUNNING THE PROGRAMS: (VERY) BRIEF INTRO rpng is a simple PNG viewer that can display transparent PNGs with a specified background color; for example, - rpng -bgcolor #ff0000 toucan.png + rpng -bgcolor \#ff0000 toucan.png would display the image with a red background. rpng2 is a progressive viewer that simulates a web browser in some respects; it can display images against either a background color or a dynamically generated background image. For example: - rpng2 -bgpat 16 toucan.png + rpng2 -bgpat 16 toucan.png wpng is a purely command-line image converter from binary PBMPLUS/NetPBM format (.pgm or .ppm) to PNG; for example, - wpng -time < toucan-notrans.ppm > toucan-notrans.png + wpng -time < toucan-notrans.ppm > toucan-notrans.png would convert the specified PPM file (using redirection) to PNG, auto- matically setting the PNG modification-time chunk. diff --git a/libs/libpng-src/contrib/gregbook/makevms.com b/libs/libpng-src/contrib/gregbook/makevms.com index bd37dc0d7..f32bcaba7 100644 --- a/libs/libpng-src/contrib/gregbook/makevms.com +++ b/libs/libpng-src/contrib/gregbook/makevms.com @@ -20,13 +20,13 @@ $ if zpath .eqs. "" $ then $ write sys$output "zlib include not found. Exiting..." $ exit 2 -$ endif +$ endif $! $ if pngpath .eqs. "" $ then $ write sys$output "libpng include not found. Exiting..." $ exit 2 -$ endif +$ endif $! $! Look for the compiler used. $! diff --git a/libs/libpng-src/contrib/gregbook/readpng.c b/libs/libpng-src/contrib/gregbook/readpng.c index abfc1fb4c..fad9b536a 100644 --- a/libs/libpng-src/contrib/gregbook/readpng.c +++ b/libs/libpng-src/contrib/gregbook/readpng.c @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2007,2017 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -55,8 +55,9 @@ #include #include +#include -#include "png.h" /* libpng header; includes zlib.h */ +#include "png.h" /* libpng header */ #include "readpng.h" /* typedefs, common macros, public prototypes */ /* future versions of libpng will provide this macro: */ @@ -99,7 +100,8 @@ int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) /* could pass pointers to user-defined error handlers instead of NULLs: */ - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + png_ptr = png_create_read_struct(png_get_libpng_ver(NULL), NULL, NULL, + NULL); if (!png_ptr) return 4; /* out of memory */ @@ -214,6 +216,10 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) * libpng function */ if (setjmp(png_jmpbuf(png_ptr))) { + free(image_data); + image_data = NULL; + free(row_pointers); + row_pointers = NULL; png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } @@ -229,8 +235,14 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); +#ifdef PNG_READ_16_TO_8_SUPPORTED if (bit_depth == 16) +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_set_scale_16(png_ptr); +# else png_set_strip_16(png_ptr); +# endif +#endif if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); @@ -252,6 +264,12 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); *pChannels = (int)png_get_channels(png_ptr, info_ptr); + /* Guard against integer overflow */ + if (height > ((size_t)(-1))/rowbytes) { + fprintf(stderr, "readpng: image_data buffer would be too large\n", + return NULL; + } + if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; @@ -263,7 +281,8 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) return NULL; } - Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height)); + Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", + *pChannels, rowbytes, height)); /* set the individual row_pointers to point at the correct offsets */ diff --git a/libs/libpng-src/contrib/gregbook/readpng2.c b/libs/libpng-src/contrib/gregbook/readpng2.c index 2ee6b681f..610b3cd87 100644 --- a/libs/libpng-src/contrib/gregbook/readpng2.c +++ b/libs/libpng-src/contrib/gregbook/readpng2.c @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2015 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -51,12 +51,20 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + --------------------------------------------------------------------------- + + Changelog: + 2015-11-12 - Check return value of png_get_bKGD() (Glenn R-P) + 2017-04-22 - Guard against integer overflow (Glenn R-P) + ---------------------------------------------------------------------------*/ #include /* for exit() prototype */ +#include -#include "png.h" /* libpng header; includes zlib.h and setjmp.h */ +#include +#include "png.h" /* libpng header from the local directory */ #include "readpng2.h" /* typedefs, common macros, public prototypes */ @@ -67,90 +75,17 @@ static void readpng2_row_callback(png_structp png_ptr, png_bytep new_row, png_uint_32 row_num, int pass); static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr); static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg); +static void readpng2_warning_handler(png_structp png_ptr, png_const_charp msg); void readpng2_version_info(void) { -#if defined(PNG_ASSEMBLER_CODE_SUPPORTED) && \ - (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) && \ - defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) - /* - * WARNING: This preprocessor approach means that the following code - * cannot be used with a libpng DLL older than 1.2.0--the - * compiled-in symbols for the new functions will not exist. - * (Could use dlopen() and dlsym() on Unix and corresponding - * calls for Windows, but not portable...) - */ - { - int mmxsupport = png_mmx_support(); - if (mmxsupport < 0) - fprintf(stderr, " Compiled with libpng %s; using libpng %s " - "without MMX support.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver); - else { - int compilerID; - png_uint_32 mmx_mask = png_get_mmx_flagmask( - PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID); + fprintf(stderr, " Compiled with libpng %s; using libpng %s\n", + PNG_LIBPNG_VER_STRING, png_libpng_ver); - fprintf(stderr, " Compiled with libpng %s; using libpng %s " - "with MMX support\n (%s version).", PNG_LIBPNG_VER_STRING, - png_libpng_ver, compilerID == 1? "MSVC++" : - (compilerID == 2? "GNU C" : "unknown")); - fprintf(stderr, " Processor (x86%s) %s MMX instructions.\n", -#if defined(__x86_64__) - "_64", -#else - "", -#endif - mmxsupport? "supports" : "does not support"); - if (mmxsupport > 0) { - int num_optims = 0; - - fprintf(stderr, - " Potential MMX optimizations supported by libpng:\n"); - if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_SUB) - ++num_optims; - if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_UP) - ++num_optims; - if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_AVG) - ++num_optims; - if (mmx_mask & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH) - ++num_optims; - if (num_optims) - fprintf(stderr, - " decoding %s row filters (reading)\n", - (num_optims == 4)? "all non-trivial" : "some"); - if (mmx_mask & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW) { - fprintf(stderr, " combining rows (reading)\n"); - ++num_optims; - } - if (mmx_mask & PNG_ASM_FLAG_MMX_READ_INTERLACE) { - fprintf(stderr, - " expanding interlacing (reading)\n"); - ++num_optims; - } - mmx_mask &= ~( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ - | PNG_ASM_FLAG_MMX_READ_INTERLACE \ - | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ - | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ - | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ - | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ); - if (mmx_mask) { - fprintf(stderr, " other (unknown)\n"); - ++num_optims; - } - if (num_optims == 0) - fprintf(stderr, " (none)\n"); - } - } - } -#else - fprintf(stderr, " Compiled with libpng %s; using libpng %s " - "without MMX support.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver); -#endif - - fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", + fprintf(stderr, " and with zlib %s; using zlib %s.\n", ZLIB_VERSION, zlib_version); } @@ -175,8 +110,8 @@ int readpng2_init(mainprog_info *mainprog_ptr) /* could also replace libpng warning-handler (final NULL), but no need: */ - png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, - readpng2_error_handler, NULL); + png_ptr = png_create_read_struct(png_get_libpng_ver(NULL), mainprog_ptr, + readpng2_error_handler, readpng2_warning_handler); if (!png_ptr) return 4; /* out of memory */ @@ -203,36 +138,30 @@ int readpng2_init(mainprog_info *mainprog_ptr) } -#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED +#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED /* prepare the reader to ignore all recognized chunks whose data won't be * used, i.e., all chunks recognized by libpng except for IHDR, PLTE, IDAT, * IEND, tRNS, bKGD, gAMA, and sRGB (small performance improvement) */ { - /* These byte strings were copied from png.h. If a future libpng - * version recognizes more chunks, add them to this list. If a - * future version of readpng2.c recognizes more chunks, delete them - * from this list. */ - static const png_byte chunks_to_ignore[] = { - 99, 72, 82, 77, '\0', /* cHRM */ - 104, 73, 83, 84, '\0', /* hIST */ - 105, 67, 67, 80, '\0', /* iCCP */ - 105, 84, 88, 116, '\0', /* iTXt */ - 111, 70, 70, 115, '\0', /* oFFs */ - 112, 67, 65, 76, '\0', /* pCAL */ - 112, 72, 89, 115, '\0', /* pHYs */ - 115, 66, 73, 84, '\0', /* sBIT */ - 115, 67, 65, 76, '\0', /* sCAL */ - 115, 80, 76, 84, '\0', /* sPLT */ - 115, 84, 69, 82, '\0', /* sTER */ - 116, 69, 88, 116, '\0', /* tEXt */ - 116, 73, 77, 69, '\0', /* tIME */ - 122, 84, 88, 116, '\0' /* zTXt */ - }; + /* These byte strings were copied from png.h. If a future version + * of readpng2.c recognizes more chunks, add them to this list. + */ + static const png_byte chunks_to_process[] = { + 98, 75, 71, 68, '\0', /* bKGD */ + 103, 65, 77, 65, '\0', /* gAMA */ + 115, 82, 71, 66, '\0', /* sRGB */ + }; - png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */, - chunks_to_ignore, sizeof(chunks_to_ignore)/5); + /* Ignore all chunks except for IHDR, PLTE, tRNS, IDAT, and IEND */ + png_set_keep_unknown_chunks(png_ptr, -1 /* PNG_HANDLE_CHUNK_NEVER */, + NULL, -1); + + /* But do not ignore chunks in the "chunks_to_process" list */ + png_set_keep_unknown_chunks(png_ptr, + 0 /* PNG_HANDLE_CHUNK_AS_DEFAULT */, chunks_to_process, + sizeof(chunks_to_process)/5); } -#endif /* PNG_UNKNOWN_CHUNKS_SUPPORTED */ +#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ /* instead of doing png_init_io() here, now we set up our callback @@ -242,96 +171,6 @@ int readpng2_init(mainprog_info *mainprog_ptr) readpng2_info_callback, readpng2_row_callback, readpng2_end_callback); - /* - * may as well enable or disable MMX routines here, if supported; - * - * to enable all: mask = png_get_mmx_flagmask ( - * PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID); - * flags = png_get_asm_flags (png_ptr); - * flags |= mask; - * png_set_asm_flags (png_ptr, flags); - * - * to disable all: mask = png_get_mmx_flagmask ( - * PNG_SELECT_READ | PNG_SELECT_WRITE, &compilerID); - * flags = png_get_asm_flags (png_ptr); - * flags &= ~mask; - * png_set_asm_flags (png_ptr, flags); - */ - -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) && \ - defined(PNG_LIBPNG_VER) && (PNG_LIBPNG_VER >= 10200) - /* - * WARNING: This preprocessor approach means that the following code - * cannot be used with a libpng DLL older than 1.2.0--the - * compiled-in symbols for the new functions will not exist. - * (Could use dlopen() and dlsym() on Unix and corresponding - * calls for Windows, but not portable...) - */ - { -#ifdef PNG_ASSEMBLER_CODE_SUPPORTED - png_uint_32 mmx_disable_mask = 0; - png_uint_32 asm_flags, mmx_mask; - int compilerID; - - if (mainprog_ptr->nommxfilters) - mmx_disable_mask |= ( PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ - | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ - | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ - | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH ); - if (mainprog_ptr->nommxcombine) - mmx_disable_mask |= PNG_ASM_FLAG_MMX_READ_COMBINE_ROW; - if (mainprog_ptr->nommxinterlace) - mmx_disable_mask |= PNG_ASM_FLAG_MMX_READ_INTERLACE; - asm_flags = png_get_asm_flags(png_ptr); - png_set_asm_flags(png_ptr, asm_flags & ~mmx_disable_mask); - - - /* Now query libpng's asm settings, just for yuks. Note that this - * differs from the querying of its *potential* MMX capabilities - * in readpng2_version_info(); this is true runtime verification. */ - - asm_flags = png_get_asm_flags(png_ptr); - mmx_mask = png_get_mmx_flagmask(PNG_SELECT_READ | PNG_SELECT_WRITE, - &compilerID); - if (asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_COMPILED) - fprintf(stderr, - " MMX support (%s version) is compiled into libpng\n", - compilerID == 1? "MSVC++" : - (compilerID == 2? "GNU C" : "unknown")); - else - fprintf(stderr, " MMX support is not compiled into libpng\n"); - fprintf(stderr, " MMX instructions are %ssupported by CPU\n", - (asm_flags & PNG_ASM_FLAG_MMX_SUPPORT_IN_CPU)? "" : "not "); - fprintf(stderr, " MMX read support for combining rows is %sabled\n", - (asm_flags & PNG_ASM_FLAG_MMX_READ_COMBINE_ROW)? "en" : "dis"); - fprintf(stderr, - " MMX read support for expanding interlacing is %sabled\n", - (asm_flags & PNG_ASM_FLAG_MMX_READ_INTERLACE)? "en" : "dis"); - fprintf(stderr, " MMX read support for \"sub\" filter is %sabled\n", - (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_SUB)? "en" : "dis"); - fprintf(stderr, " MMX read support for \"up\" filter is %sabled\n", - (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_UP)? "en" : "dis"); - fprintf(stderr, " MMX read support for \"avg\" filter is %sabled\n", - (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_AVG)? "en" : "dis"); - fprintf(stderr, " MMX read support for \"Paeth\" filter is %sabled\n", - (asm_flags & PNG_ASM_FLAG_MMX_READ_FILTER_PAETH)? "en" : "dis"); - asm_flags &= (mmx_mask & ~( PNG_ASM_FLAG_MMX_READ_COMBINE_ROW \ - | PNG_ASM_FLAG_MMX_READ_INTERLACE \ - | PNG_ASM_FLAG_MMX_READ_FILTER_SUB \ - | PNG_ASM_FLAG_MMX_READ_FILTER_UP \ - | PNG_ASM_FLAG_MMX_READ_FILTER_AVG \ - | PNG_ASM_FLAG_MMX_READ_FILTER_PAETH )); - if (asm_flags) - fprintf(stderr, - " additional MMX support is also enabled (0x%02lx)\n", - asm_flags); -#else /* !PNG_ASSEMBLER_CODE_SUPPORTED */ - fprintf(stderr, " MMX querying is disabled in libpng.\n"); -#endif /* ?PNG_ASSEMBLER_CODE_SUPPORTED */ - } -#endif - - /* make sure we save our pointers for use in readpng2_decode_data() */ mainprog_ptr->png_ptr = png_ptr; @@ -380,7 +219,11 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) mainprog_info *mainprog_ptr; int color_type, bit_depth; png_uint_32 width, height; +#ifdef PNG_FLOATING_POINT_SUPPORTED double gamma; +#else + png_fixed_point gamma; +#endif /* setjmp() doesn't make sense here, because we'd either have to exit(), @@ -424,36 +267,38 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) /* since we know we've read all of the PNG file's "header" (i.e., up * to IDAT), we can check for a background color here */ - if (mainprog_ptr->need_bgcolor && - png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) + if (mainprog_ptr->need_bgcolor) { png_color_16p pBackground; /* it is not obvious from the libpng documentation, but this function * takes a pointer to a pointer, and it always returns valid red, * green and blue values, regardless of color_type: */ - png_get_bKGD(png_ptr, info_ptr, &pBackground); + if (png_get_bKGD(png_ptr, info_ptr, &pBackground)) + { - /* however, it always returns the raw bKGD data, regardless of any - * bit-depth transformations, so check depth and adjust if necessary */ - if (bit_depth == 16) { - mainprog_ptr->bg_red = pBackground->red >> 8; - mainprog_ptr->bg_green = pBackground->green >> 8; - mainprog_ptr->bg_blue = pBackground->blue >> 8; - } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { - if (bit_depth == 1) - mainprog_ptr->bg_red = mainprog_ptr->bg_green = - mainprog_ptr->bg_blue = pBackground->gray? 255 : 0; - else if (bit_depth == 2) - mainprog_ptr->bg_red = mainprog_ptr->bg_green = - mainprog_ptr->bg_blue = (255/3) * pBackground->gray; - else /* bit_depth == 4 */ - mainprog_ptr->bg_red = mainprog_ptr->bg_green = - mainprog_ptr->bg_blue = (255/15) * pBackground->gray; - } else { - mainprog_ptr->bg_red = (uch)pBackground->red; - mainprog_ptr->bg_green = (uch)pBackground->green; - mainprog_ptr->bg_blue = (uch)pBackground->blue; + /* however, it always returns the raw bKGD data, regardless of any + * bit-depth transformations, so check depth and adjust if necessary + */ + if (bit_depth == 16) { + mainprog_ptr->bg_red = pBackground->red >> 8; + mainprog_ptr->bg_green = pBackground->green >> 8; + mainprog_ptr->bg_blue = pBackground->blue >> 8; + } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { + if (bit_depth == 1) + mainprog_ptr->bg_red = mainprog_ptr->bg_green = + mainprog_ptr->bg_blue = pBackground->gray? 255 : 0; + else if (bit_depth == 2) + mainprog_ptr->bg_red = mainprog_ptr->bg_green = + mainprog_ptr->bg_blue = (255/3) * pBackground->gray; + else /* bit_depth == 4 */ + mainprog_ptr->bg_red = mainprog_ptr->bg_green = + mainprog_ptr->bg_blue = (255/15) * pBackground->gray; + } else { + mainprog_ptr->bg_red = (uch)pBackground->red; + mainprog_ptr->bg_green = (uch)pBackground->green; + mainprog_ptr->bg_blue = (uch)pBackground->blue; + } } } @@ -469,8 +314,14 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); +#ifdef PNG_READ_16_TO_8_SUPPORTED if (bit_depth == 16) +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_set_scale_16(png_ptr); +# else png_set_strip_16(png_ptr); +# endif +#endif if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); @@ -491,11 +342,19 @@ static void readpng2_info_callback(png_structp png_ptr, png_infop info_ptr) * "gamma" value for the entire display system, i.e., the product of * LUT_exponent and CRT_exponent. */ +#ifdef PNG_FLOATING_POINT_SUPPORTED if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, mainprog_ptr->display_exponent, gamma); else png_set_gamma(png_ptr, mainprog_ptr->display_exponent, 0.45455); - +#else + if (png_get_gAMA_fixed(png_ptr, info_ptr, &gamma)) + png_set_gamma_fixed(png_ptr, + (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), gamma); + else + png_set_gamma_fixed(png_ptr, + (png_fixed_point)(100000*mainprog_ptr->display_exponent+.5), 45455); +#endif /* we'll let libpng expand interlaced images, too */ @@ -597,6 +456,8 @@ static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr) /* all done */ + (void)info_ptr; /* Unused */ + return; } @@ -617,7 +478,12 @@ void readpng2_cleanup(mainprog_info *mainprog_ptr) } - +static void readpng2_warning_handler(png_structp png_ptr, png_const_charp msg) +{ + fprintf(stderr, "readpng2 libpng warning: %s\n", msg); + fflush(stderr); + (void)png_ptr; /* Unused */ +} static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg) @@ -644,5 +510,12 @@ static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg) exit(99); } + /* Now we have our data structure we can use the information in it + * to return control to our own higher level code (all the points + * where 'setjmp' is called in this file.) This will work with other + * error handling mechanisms as well - libpng always calls png_error + * when it can proceed no further, thus, so long as the error handler + * is intercepted, application code can do its own error recovery. + */ longjmp(mainprog_ptr->jmpbuf, 1); } diff --git a/libs/libpng-src/contrib/gregbook/readpng2.h b/libs/libpng-src/contrib/gregbook/readpng2.h index fbfffb4ba..6b3660d7c 100644 --- a/libs/libpng-src/contrib/gregbook/readpng2.h +++ b/libs/libpng-src/contrib/gregbook/readpng2.h @@ -96,11 +96,6 @@ typedef struct _mainprog_info { int rowbytes; int channels; int need_bgcolor; -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) - int nommxfilters; - int nommxcombine; - int nommxinterlace; -#endif int state; uch bg_red; uch bg_green; diff --git a/libs/libpng-src/contrib/gregbook/readppm.c b/libs/libpng-src/contrib/gregbook/readppm.c index be9a56d95..52e702777 100644 --- a/libs/libpng-src/contrib/gregbook/readppm.c +++ b/libs/libpng-src/contrib/gregbook/readppm.c @@ -9,7 +9,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2007,2017 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -154,17 +154,26 @@ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes) *pRowbytes = rowbytes = channels*width; *pChannels = channels; + Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height)); + + /* Guard against integer overflow */ + if (height > ((size_t)(-1))/rowbytes) { + fprintf(stderr, PROGNAME ": image_data buffer would be too large\n", + return NULL; + } + if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { return NULL; } - Trace((stderr, "readpng_get_image: rowbytes = %ld, height = %ld\n", rowbytes, height)); - - /* now we can go ahead and just read the whole image */ - fread(image_data, 1L, rowbytes*height, saved_infile); - + if (fread(image_data, 1L, rowbytes*height, saved_infile) < + rowbytes*height) { + free (image_data); + image_data = NULL; + return NULL; + } return image_data; } diff --git a/libs/libpng-src/contrib/gregbook/rpng-win.c b/libs/libpng-src/contrib/gregbook/rpng-win.c index 20209611e..1a6f87615 100644 --- a/libs/libpng-src/contrib/gregbook/rpng-win.c +++ b/libs/libpng-src/contrib/gregbook/rpng-win.c @@ -24,10 +24,11 @@ - 1.10: enabled "message window"/console (thanks to David Geldreich) - 2.00: dual-licensed (added GNU GPL) - 2.01: fixed improper display of usage screen on PNG error(s) + - 2.02: check for integer overflow (Glenn R-P) --------------------------------------------------------------------------- - Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2008, 2017 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -85,7 +86,33 @@ #include #include #include +#ifdef __CYGWIN__ +/* getch replacement. Turns out, we don't really need this, + * but leave it here if we ever enable any of the uses of + * _getch in the main code + */ +#include +#include +#include +int repl_getch( void ) +{ + char ch; + int fd = fileno(stdin); + struct termio old_tty, new_tty; + + ioctl(fd, TCGETA, &old_tty); + new_tty = old_tty; + new_tty.c_lflag &= ~(ICANON | ECHO | ISIG); + ioctl(fd, TCSETA, &new_tty); + fread(&ch, 1, sizeof(ch), stdin); + ioctl(fd, TCSETA, &old_tty); + + return ch; +} +#define _getch repl_getch +#else #include /* only for _getch() */ +#endif /* #define DEBUG : this enables the Trace() macros */ @@ -153,15 +180,16 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) filename = (char *)NULL; - +#ifndef __CYGWIN__ /* First reenable console output, which normally goes to the bit bucket * for windowed apps. Closing the console window will terminate the - * app. Thanks to David.Geldreich@realviz.com for supplying the magical + * app. Thanks to David.Geldreich at realviz.com for supplying the magical * incantation. */ AllocConsole(); freopen("CONOUT$", "a", stderr); freopen("CONOUT$", "a", stdout); +#endif /* Next set the default value for our display-system exponent, i.e., @@ -279,7 +307,9 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) /* print usage screen if any errors up to this point */ if (error) { +#ifndef __CYGWIN__ int ch; +#endif fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname); readpng_version_info(); @@ -293,11 +323,15 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" "\t\t used with transparent images\n" "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" +#ifndef __CYGWIN__ "Press Q or Esc to quit this usage screen.\n" +#endif "\n", PROGNAME, default_display_exponent); +#ifndef __CYGWIN__ do ch = _getch(); while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif exit(1); } @@ -333,18 +367,24 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) if (error) { +#ifndef __CYGWIN__ int ch; +#endif fprintf(stderr, PROGNAME ": aborting.\n"); +#ifndef __CYGWIN__ do ch = _getch(); while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif exit(2); } else { fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); +#ifndef __CYGWIN__ fprintf(stderr, "\n [console window: closing this window will terminate %s]\n\n", PROGNAME); +#endif } @@ -417,7 +457,12 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) /* wait for the user to tell us when to quit */ printf( - "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"); +#ifndef __CYGWIN__ + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n" +#else + "Done. Press mouse button 1 (within image window) to quit.\n" +#endif + ); fflush(stdout); while (GetMessage(&msg, NULL, 0, 0)) { @@ -452,6 +497,12 @@ static int rpng_win_create_window(HINSTANCE hInst, int showmode) wimage_rowbytes = ((3*image_width + 3L) >> 2) << 2; + /* Guard against integer overflow */ + if (image_height > ((size_t)(-1))/wimage_rowbytes) { + fprintf(stderr, PROGNAME ": image_data buffer would be too large\n"); + return 4; /* fail */ + } + if (!(dib = (uch *)malloc(sizeof(BITMAPINFOHEADER) + wimage_rowbytes*image_height))) { diff --git a/libs/libpng-src/contrib/gregbook/rpng-x.c b/libs/libpng-src/contrib/gregbook/rpng-x.c index 0a9817029..92effaa6d 100644 --- a/libs/libpng-src/contrib/gregbook/rpng-x.c +++ b/libs/libpng-src/contrib/gregbook/rpng-x.c @@ -26,10 +26,13 @@ - 1.14: added support for X resources (thanks to Gerhard Niklasch) - 2.00: dual-licensed (added GNU GPL) - 2.01: fixed improper display of usage screen on PNG error(s) + - 2.02: Added "void(argc);" statement to quiet pedantic compiler warnings + about unused variable (GR-P) + - 2.03: check for integer overflow (Glenn R-P) --------------------------------------------------------------------------- - Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2008, 2017 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -80,9 +83,9 @@ #define PROGNAME "rpng-x" #define LONGNAME "Simple PNG Viewer for X" -#define VERSION "2.01 of 16 March 2008" -#define RESNAME "rpng" /* our X resource application name */ -#define RESCLASS "Rpng" /* our X resource class name */ +#define VERSION "2.02 of 15 June 2014" +#define RESNAME "rpng" /* our X resource application name */ +#define RESCLASS "Rpng" /* our X resource class name */ #include #include @@ -252,8 +255,8 @@ int main(int argc, char **argv) else { bgstr = *argv; if (strlen(bgstr) != 7 || bgstr[0] != '#') - ++error; - else + ++error; + else have_bg = TRUE; } } else { @@ -279,15 +282,17 @@ int main(int argc, char **argv) "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n" " xdpy\tname of the target X display (e.g., ``hostname:0'')\n" " exp \ttransfer-function exponent (``gamma'') of the display\n" - "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" + "\t\t system in floating-point format (e.g., ``%.1f''); equal\n", + PROGNAME, default_display_exponent); + + fprintf(stderr, "\n" "\t\t to the product of the lookup-table exponent (varies)\n" "\t\t and the CRT exponent (usually 2.2); must be positive\n" " bg \tdesired background color in 7-character hex RGB format\n" "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" "\t\t used with transparent images\n" "\nPress Q, Esc or mouse button 1 (within image window, after image\n" - "is displayed) to quit.\n" - "\n", PROGNAME, default_display_exponent); + "is displayed) to quit.\n"); exit(1); } @@ -419,6 +424,8 @@ int main(int argc, char **argv) rpng_x_cleanup(); + (void)argc; /* Unused */ + return 0; } diff --git a/libs/libpng-src/contrib/gregbook/rpng2-win.c b/libs/libpng-src/contrib/gregbook/rpng2-win.c index 9f7ad78dd..ed6b526ec 100644 --- a/libs/libpng-src/contrib/gregbook/rpng2-win.c +++ b/libs/libpng-src/contrib/gregbook/rpng2-win.c @@ -32,10 +32,12 @@ - 2.01: fixed 64-bit typo in readpng2.c - 2.02: fixed improper display of usage screen on PNG error(s); fixed unexpected-EOF and file-read-error cases + - 2.03: removed runtime MMX-enabling/disabling and obsolete -mmx* options + - 2.04: check for integer overflow (Glenn R-P) --------------------------------------------------------------------------- - Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2008, 2017 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -95,7 +97,33 @@ #include #include /* only for PvdM background code */ #include +#ifdef __CYGWIN__ +/* getch replacement. Turns out, we don't really need this, + * but leave it here if we ever enable any of the uses of + * _getch in the main code + */ +#include +#include +#include +int repl_getch( void ) +{ + char ch; + int fd = fileno(stdin); + struct termio old_tty, new_tty; + + ioctl(fd, TCGETA, &old_tty); + new_tty = old_tty; + new_tty.c_lflag &= ~(ICANON | ECHO | ISIG); + ioctl(fd, TCSETA, &new_tty); + fread(&ch, 1, sizeof(ch), stdin); + ioctl(fd, TCSETA, &old_tty); + + return ch; +} +#define _getch repl_getch +#else #include /* only for _getch() */ +#endif /* all for PvdM background code: */ #ifndef PI @@ -269,16 +297,16 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) filename = (char *)NULL; memset(&rpng2_info, 0, sizeof(mainprog_info)); - +#ifndef __CYGWIN__ /* Next reenable console output, which normally goes to the bit bucket * for windowed apps. Closing the console window will terminate the - * app. Thanks to David.Geldreich@realviz.com for supplying the magical + * app. Thanks to David.Geldreich at realviz.com for supplying the magical * incantation. */ AllocConsole(); freopen("CONOUT$", "a", stderr); freopen("CONOUT$", "a", stdout); - +#endif /* Set the default value for our display-system exponent, i.e., the * product of the CRT exponent and the exponent corresponding to @@ -395,18 +423,6 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) } } else if (!strncmp(*argv, "-timing", 2)) { timing = TRUE; -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) - } else if (!strncmp(*argv, "-nommxfilters", 7)) { - rpng2_info.nommxfilters = TRUE; - } else if (!strncmp(*argv, "-nommxcombine", 7)) { - rpng2_info.nommxcombine = TRUE; - } else if (!strncmp(*argv, "-nommxinterlace", 7)) { - rpng2_info.nommxinterlace = TRUE; - } else if (!strcmp(*argv, "-nommx")) { - rpng2_info.nommxfilters = TRUE; - rpng2_info.nommxcombine = TRUE; - rpng2_info.nommxinterlace = TRUE; -#endif } else { if (**argv != '-') { filename = *argv; @@ -424,15 +440,14 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) /* print usage screen if any errors up to this point */ if (error) { +#ifndef __CYGWIN__ int ch; +#endif fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname); readpng2_version_info(); fprintf(stderr, "\n" "Usage: %s [-gamma exp] [-bgcolor bg | -bgpat pat] [-timing]\n" -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) - " %*s [[-nommxfilters] [-nommxcombine] [-nommxinterlace] | -nommx]\n" -#endif " %*s file.png\n\n" " exp \ttransfer-function exponent (``gamma'') of the display\n" "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" @@ -445,21 +460,24 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) "\t\t transparent images; overrides -bgcolor option\n" " -timing\tenables delay for every block read, to simulate modem\n" "\t\t download of image (~36 Kbps)\n" -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) - " -nommx*\tdisable optimized MMX routines for decoding row filters,\n" - "\t\t combining rows, and expanding interlacing, respectively\n" -#endif "\nPress Q, Esc or mouse button 1 after image is displayed to quit.\n" +#ifndef __CYGWIN__ "Press Q or Esc to quit this usage screen. ", +#else + , +#endif PROGNAME, -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) +#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) && \ + !(defined(__CYGWIN__) || defined(__MINGW32__)) (int)strlen(PROGNAME), " ", #endif (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat); fflush(stderr); +#ifndef __CYGWIN__ do ch = _getch(); while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif exit(1); } @@ -496,18 +514,24 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) if (error) { +#ifndef __CYGWIN__ int ch; +#endif fprintf(stderr, PROGNAME ": aborting.\n"); +#ifndef __CYGWIN__ do ch = _getch(); while (ch != 'q' && ch != 'Q' && ch != 0x1B); +#endif exit(2); } else { fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname); +#ifndef __CYGWIN__ fprintf(stderr, "\n [console window: closing this window will terminate %s]\n\n", PROGNAME); +#endif fflush(stderr); } @@ -567,7 +591,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, PSTR cmd, int showmode) "(unexpectedly) while reading PNG image file\n"); exit(3); } else /* if (error) */ { - // will print error message below + /* will print error message below */ } break; } @@ -625,6 +649,13 @@ static void rpng2_win_init() Trace((stderr, " width = %ld\n", rpng2_info.width)) Trace((stderr, " height = %ld\n", rpng2_info.height)) + /* Guard against integer overflow */ + if (rpng2_info.height > ((size_t)(-1))/rowbytes) { + fprintf(stderr, PROGNAME ": image_data buffer would be too large\n", + readpng2_cleanup(&rpng2_info); + return; + } + rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height); if (!rpng2_info.image_data) { readpng2_cleanup(&rpng2_info); @@ -1150,7 +1181,12 @@ static void rpng2_win_finish_display() rpng2_info.state = kDone; printf( - "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n"); +#ifndef __CYGWIN__ + "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n" +#else + "Done. Press mouse button 1 (within image window) to quit.\n" +#endif + ); fflush(stdout); } diff --git a/libs/libpng-src/contrib/gregbook/rpng2-x.c b/libs/libpng-src/contrib/gregbook/rpng2-x.c index 873af2335..af944c0f2 100644 --- a/libs/libpng-src/contrib/gregbook/rpng2-x.c +++ b/libs/libpng-src/contrib/gregbook/rpng2-x.c @@ -40,10 +40,15 @@ - 2.02: fixed improper display of usage screen on PNG error(s); fixed unexpected-EOF and file-read-error cases; fixed Trace() cut-and- paste bugs - + - 2.03: deleted runtime MMX-enabling/disabling and obsolete -mmx* options + - 2.04: Added "void(foo);" statements to quiet pedantic compiler warnings + about unused variables (GR-P) + - 2.05: Use nanosleep() instead of usleep(), which is deprecated (GR-P). + - 2.06: check for integer overflow (Glenn R-P) --------------------------------------------------------------------------- - Copyright (c) 1998-2008 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2010, 2014-2015, 2017 Greg Roelofs. All rights + reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -94,9 +99,9 @@ #define PROGNAME "rpng2-x" #define LONGNAME "Progressive PNG Viewer for X" -#define VERSION "2.02 of 16 March 2008" -#define RESNAME "rpng2" /* our X resource application name */ -#define RESCLASS "Rpng" /* our X resource class name */ +#define VERSION "2.04 of 15 June 2014" +#define RESNAME "rpng2" /* our X resource application name */ +#define RESCLASS "Rpng" /* our X resource class name */ #include #include @@ -110,6 +115,19 @@ #include #include /* defines XK_* macros */ +#if _POSIX_C_SOURCE >= 199309L /* have nanosleep() */ +# undef usleep +# define usleep(usec) { \ + struct timespec ts; \ + ts.tv_sec = 0; \ + ts.tv_nsec = (usec) * 1000; \ + nanosleep(&ts, NULL); } +# endif + +#ifndef usleep /* have neither nanosleep() nor usleep() */ +# define usleep(x) sleep(((x)+499999)/1000000) +#endif + #ifdef VMS # include #endif @@ -131,7 +149,7 @@ (e.type == KeyPress && /* v--- or 1 for shifted keys */ \ ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape))) -#define NO_24BIT_MASKS /* undef case not fully written--only for redisplay() */ +#define NO_24BIT_MASKS /* undef case not fully written--only for redisplay() */ #define rgb1_max bg_freq #define rgb1_min bg_gray @@ -301,7 +319,7 @@ int main(int argc, char **argv) int have_bg = FALSE; #ifdef FEATURE_LOOP int loop = FALSE; - long loop_interval = -1; /* seconds (100,000 max) */ + long loop_interval = -1; /* seconds (100,000 max) */ #endif double LUT_exponent; /* just the lookup table */ double CRT_exponent = 2.2; /* just the monitor */ @@ -434,18 +452,6 @@ int main(int argc, char **argv) else if (loop_interval > 100000) /* bit more than one day */ loop_interval = 100000; } -#endif -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) - } else if (!strncmp(*argv, "-nommxfilters", 7)) { - rpng2_info.nommxfilters = TRUE; - } else if (!strncmp(*argv, "-nommxcombine", 7)) { - rpng2_info.nommxcombine = TRUE; - } else if (!strncmp(*argv, "-nommxinterlace", 7)) { - rpng2_info.nommxinterlace = TRUE; - } else if (!strcmp(*argv, "-nommx")) { - rpng2_info.nommxfilters = TRUE; - rpng2_info.nommxcombine = TRUE; - rpng2_info.nommxinterlace = TRUE; #endif } else { if (**argv != '-') { @@ -467,50 +473,47 @@ int main(int argc, char **argv) fprintf(stderr, "\n%s %s: %s\n\n", PROGNAME, VERSION, appname); readpng2_version_info(); fprintf(stderr, "\n" - "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg | -bgpat pat]\n" -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) - " %*s [[-nommxfilters] [-nommxcombine] [-nommxinterlace] | -nommx]\n" -#endif + "Usage: "); + fprintf(stderr, + "%s [-display xdpy] [-gamma exp] [-bgcolor bg | -bgpat pat]\n" + " %*s [-usleep dur | -timing] [-pause]\n", + PROGNAME, (int)strlen(PROGNAME), " "); + fprintf(stderr, #ifdef FEATURE_LOOP - " %*s [-usleep dur | -timing] [-pause] [-loop [sec]] file.png\n\n" -#else - " %*s [-usleep dur | -timing] [-pause] file.png\n\n" + " [-loop [sec]]" #endif + " file.png\n\n"); + fprintf(stderr, " xdpy\tname of the target X display (e.g., ``hostname:0'')\n" " exp \ttransfer-function exponent (``gamma'') of the display\n" "\t\t system in floating-point format (e.g., ``%.1f''); equal\n" - "\t\t to the product of the lookup-table exponent (varies)\n" + "\t\t to the product of the lookup-table exponent (varies)\n", + default_display_exponent); + fprintf(stderr, "\t\t and the CRT exponent (usually 2.2); must be positive\n" " bg \tdesired background color in 7-character hex RGB format\n" "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n" "\t\t used with transparent images; overrides -bgpat\n" " pat \tdesired background pattern number (0-%d); used with\n" - "\t\t transparent images; overrides -bgcolor\n" + "\t\t transparent images; overrides -bgcolor\n", + num_bgpat-1); #ifdef FEATURE_LOOP + fprintf(stderr, " -loop\tloops through background images after initial display\n" "\t\t is complete (depends on -bgpat)\n" - " sec \tseconds to display each background image (default = 2)\n" -#endif -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) - " -nommx*\tdisable optimized MMX routines for decoding row filters,\n" - "\t\t combining rows, and expanding interlacing, respectively\n" + " sec \tseconds to display each background image (default = 2)\n"); #endif + fprintf(stderr, " dur \tduration in microseconds to wait after displaying each\n" "\t\t row (for demo purposes)\n" " -timing\tenables delay for every block read, to simulate modem\n" "\t\t download of image (~36 Kbps)\n" " -pause\tpauses after displaying each pass until mouse clicked\n" "\nPress Q, Esc or mouse button 1 (within image window, after image\n" - "is displayed) to quit.\n" - "\n", PROGNAME, -#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__)) - (int)strlen(PROGNAME), " ", -#endif - (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat-1); + "is displayed) to quit.\n"); exit(1); } - if (!(infile = fopen(filename, "rb"))) { fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename); ++error; @@ -612,7 +615,7 @@ int main(int argc, char **argv) "(unexpectedly) while reading PNG image file\n"); exit(3); } else /* if (error) */ { - // will print error message below + /* will print error message below */ } break; } @@ -756,6 +759,8 @@ int main(int argc, char **argv) Trace((stderr, "about to call rpng2_x_cleanup()\n")) rpng2_x_cleanup(); + (void)argc; /* Unused */ + return 0; } @@ -777,6 +782,13 @@ static void rpng2_x_init(void) Trace((stderr, " width = %ld\n", rpng2_info.width)) Trace((stderr, " height = %ld\n", rpng2_info.height)) + /* Guard against integer overflow */ + if (rpng2_info.height > ((size_t)(-1))/rpng2_info.rowbytes) { + fprintf(stderr, PROGNAME ": image_data buffer would be too large\n"); + readpng2_cleanup(&rpng2_info); + return; + } + rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height); if (!rpng2_info.image_data) { readpng2_cleanup(&rpng2_info); @@ -802,8 +814,9 @@ static void rpng2_x_init(void) if (rpng2_x_create_window()) { /* GRR TEMPORARY HACK: this is fundamentally no different from cases - * above; libpng should longjmp() back to us when png_ptr goes away. - * If we/it segfault instead, seems like a libpng bug... */ + * above; libpng should call our error handler to longjmp() back to us + * when png_ptr goes away. If we/it segfault instead, seems like a + * libpng bug... */ /* we're here via libpng callback, so if window fails, clean and bail */ readpng2_cleanup(&rpng2_info); @@ -1297,7 +1310,7 @@ static int rpng2_x_load_bg_image(void) for (row = 0; row < rpng2_info.height; ++row) { src = bg_data + row*bg_rowbytes; dest = ximage->data + row*ximage_rowbytes; - if (bpp == 32) { /* slightly optimized version */ + if (bpp == 32) { /* slightly optimized version */ for (i = rpng2_info.width; i > 0; --i) { red = *src++; green = *src++; @@ -1846,6 +1859,9 @@ static void rpng2_x_redisplay_image(ulg startcol, ulg startrow, XFlush(display); } + (void)startcol; + (void)width; + } /* end function rpng2_x_redisplay_image() */ diff --git a/libs/libpng-src/contrib/gregbook/wpng.c b/libs/libpng-src/contrib/gregbook/wpng.c index a06e3529e..a8f367fb8 100644 --- a/libs/libpng-src/contrib/gregbook/wpng.c +++ b/libs/libpng-src/contrib/gregbook/wpng.c @@ -29,6 +29,7 @@ - 1.04: fixed DOS/OS2/Win32 detection, including partial Cygwin fix (see http://home.att.net/~perlspinr/diffs/GregBook_cygwin.diff) - 2.00: dual-licensed (added GNU GPL) + - 2.01: check for integer overflow (Glenn R-P) [REPORTED BUG (win32 only): "contrib/gregbook/wpng.c - cmd line dose not work! In order to do something useful I needed to redirect @@ -38,7 +39,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2007, 2017 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -702,7 +703,18 @@ int main(int argc, char **argv) if (wpng_info.interlaced) { long i; ulg bytes; - ulg image_bytes = rowbytes * wpng_info.height; /* overflow? */ + ulg image_bytes; + + /* Guard against integer overflow */ + if (wpng_info_height > ((size_t)(-1)/rowbytes || + wpng_info_height > ((ulg)(-1)/rowbytes) { + fprintf(stderr, PROGNAME ": image_data buffer too large\n"); + writepng_cleanup(&wpng_info); + wpng_cleanup(); + exit(5); + } + + image_bytes = rowbytes * wpng_info.height; wpng_info.image_data = (uch *)malloc(image_bytes); wpng_info.row_pointers = (uch **)malloc(wpng_info.height*sizeof(uch *)); diff --git a/libs/libpng-src/contrib/gregbook/writepng.c b/libs/libpng-src/contrib/gregbook/writepng.c index e6d81ea40..055c74374 100644 --- a/libs/libpng-src/contrib/gregbook/writepng.c +++ b/libs/libpng-src/contrib/gregbook/writepng.c @@ -4,7 +4,7 @@ --------------------------------------------------------------------------- - Copyright (c) 1998-2007 Greg Roelofs. All rights reserved. + Copyright (c) 1998-2007, 2017 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors @@ -55,8 +55,9 @@ #include /* for exit() prototype */ +#include -#include "png.h" /* libpng header; includes zlib.h and setjmp.h */ +#include "png.h" /* libpng header, includes setjmp.h */ #include "writepng.h" /* typedefs, common macros, public prototypes */ @@ -89,7 +90,7 @@ int writepng_init(mainprog_info *mainprog_ptr) /* could also replace libpng warning-handler (final NULL), but no need: */ - png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr, + png_ptr = png_create_write_struct(png_get_libpng_ver(NULL), mainprog_ptr, writepng_error_handler, NULL); if (!png_ptr) return 4; /* out of memory */ @@ -104,7 +105,8 @@ int writepng_init(mainprog_info *mainprog_ptr) /* setjmp() must be called in every function that calls a PNG-writing * libpng function, unless an alternate error handler was installed-- * but compatible error handlers must either use longjmp() themselves - * (as in this program) or exit immediately, so here we go: */ + * (as in this program) or some other method to return control to + * application code, so here we go: */ if (setjmp(mainprog_ptr->jmpbuf)) { png_destroy_write_struct(&png_ptr, &info_ptr); @@ -388,5 +390,12 @@ static void writepng_error_handler(png_structp png_ptr, png_const_charp msg) exit(99); } + /* Now we have our data structure we can use the information in it + * to return control to our own higher level code (all the points + * where 'setjmp' is called in this file.) This will work with other + * error handling mechanisms as well - libpng always calls png_error + * when it can proceed no further, thus, so long as the error handler + * is intercepted, application code can do its own error recovery. + */ longjmp(mainprog_ptr->jmpbuf, 1); } diff --git a/libs/libpng-src/contrib/libtests/fakepng.c b/libs/libpng-src/contrib/libtests/fakepng.c new file mode 100644 index 000000000..6512c1401 --- /dev/null +++ b/libs/libpng-src/contrib/libtests/fakepng.c @@ -0,0 +1,65 @@ +/* Fake a PNG - just write it out directly. + * + * COPYRIGHT: Written by John Cunningham Bowler, 2014. + * To the extent possible under law, the author has waived all copyright and + * related or neighboring rights to this work. This work is published from: + * United States. + * + */ + +#include +#include /* for crc32 */ + +void +put_uLong(uLong val) +{ + putchar(val >> 24); + putchar(val >> 16); + putchar(val >> 8); + putchar(val >> 0); +} + +void +put_chunk(const unsigned char *chunk, uInt length) +{ + uLong crc; + + put_uLong(length-4); /* Exclude the tag */ + + fwrite(chunk, length, 1, stdout); + + crc = crc32(0, Z_NULL, 0); + put_uLong(crc32(crc, chunk, length)); +} + +const unsigned char signature[] = +{ + 137, 80, 78, 71, 13, 10, 26, 10 +}; + +const unsigned char IHDR[] = +{ + 73, 72, 68, 82, /* IHDR */ + 0, 0, 0, 1, /* width */ + 0, 0, 0, 1, /* height */ + 1, /* bit depth */ + 0, /* color type: greyscale */ + 0, /* compression method */ + 0, /* filter method */ + 0 /* interlace method: none */ +}; + +const unsigned char unknown[] = +{ + 'u', 'n', 'K', 'n' /* "unKn" - private safe to copy */ +}; + +int +main(void) +{ + fwrite(signature, sizeof signature, 1, stdout); + put_chunk(IHDR, sizeof IHDR); + + for (;;) + put_chunk(unknown, sizeof unknown); +} diff --git a/libs/libpng-src/contrib/libtests/gentests.sh b/libs/libpng-src/contrib/libtests/gentests.sh new file mode 100644 index 000000000..f0f8d2395 --- /dev/null +++ b/libs/libpng-src/contrib/libtests/gentests.sh @@ -0,0 +1,102 @@ +#!/bin/sh +# +# Copyright (c) 2013 John Cunningham Bowler +# +# Last changed in libpng 1.6.0 [February 14, 2013] +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h +# +# Generate a set of PNG test images. The images are generated in a +# sub-directory called 'tests' by default, however a command line argument will +# change that name. The generation requires a built version of makepng in the +# current directory. +# +usage(){ + exec >&2 + echo "$0 []" + echo ' Generate a set of PNG test files in "directory" ("tests" by default)' + exit 1 +} + +mp="$PWD/makepng" +test -x "$mp" || { + exec >&2 + echo "$0: the 'makepng' program must exist" + echo " in the directory within which this program:" + echo " $mp" + echo " is executed" + usage +} + +# Just one argument: the directory +testdir="tests" +test $# -gt 1 && { + testdir="$1" + shift +} +test $# -eq 0 || usage + +# Take care not to clobber something +if test -e "$testdir" +then + test -d "$testdir" || usage +else + # mkdir -p isn't portable, so do the following + mkdir "$testdir" 2>/dev/null || mkdir -p "$testdir" || usage +fi + +# This fails in a very satisfactory way if it's not accessible +cd "$testdir" +:>"test$$.png" || { + exec >&2 + echo "$testdir: directory not writable" + usage +} +rm "test$$.png" || { + exec >&2 + echo "$testdir: you have create but not write privileges here." + echo " This is unexpected. You have a spurion; "'"'"test$$.png"'"'"." + echo " You need to remove this yourself. Try a different directory." + exit 1 +} + +# Now call makepng ($mp) to create every file we can think of with a +# reasonable name +doit(){ + for gamma in "" --sRGB --linear --1.8 + do + case "$gamma" in + "") + gname=;; + --sRGB) + gname="-srgb";; + --linear) + gname="-lin";; + --1.8) + gname="-18";; + *) + gname="-$gamma";; + esac + "$mp" $gamma "$1" "$2" "test-$1-$2$gname.png" + done +} +# +for ct in gray palette +do + for bd in 1 2 4 8 + do + doit "$ct" "$bd" + done +done +# +doit "gray" "16" +# +for ct in gray-alpha rgb rgb-alpha +do + for bd in 8 16 + do + doit "$ct" "$bd" + done +done diff --git a/libs/libpng-src/contrib/libtests/makepng.c b/libs/libpng-src/contrib/libtests/makepng.c new file mode 100644 index 000000000..312062bda --- /dev/null +++ b/libs/libpng-src/contrib/libtests/makepng.c @@ -0,0 +1,1941 @@ +/* makepng.c */ +#define _ISOC99_SOURCE +/* Copyright: */ +#define COPYRIGHT "\251 2013,2015 John Cunningham Bowler" +/* + * Last changed in libpng 1.6.20 [November 24, 2015] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Make a test PNG image. The arguments are as follows: + * + * makepng [--sRGB|--linear|--1.8] [--tRNS] [--nofilters] \ + * color-type bit-depth [file-name] + * + * The color-type may be numeric (and must match the numbers used by the PNG + * specification) or one of the format names listed below. The bit-depth is the + * component bit depth, or the pixel bit-depth for a color-mapped image. + * + * Without any options no color-space information is written, with the options + * an sRGB or the appropriate gAMA chunk is written. "1.8" refers to the + * display system used on older Apple computers to correct for high ambient + * light levels in the viewing environment; it applies a transform of + * approximately value^(1/1.45) to the color values and so a gAMA chunk of 65909 + * is written (1.45/2.2). + * + * The image data is generated internally. Unless --color is given the images + * used are as follows: + * + * 1 channel: a square image with a diamond, the least luminous colors are on + * the edge of the image, the most luminous in the center. + * + * 2 channels: the color channel increases in luminosity from top to bottom, the + * alpha channel increases in opacity from left to right. + * + * 3 channels: linear combinations of, from the top-left corner clockwise, + * black, green, white, red. + * + * 4 channels: linear combinations of, from the top-left corner clockwise, + * transparent, red, green, blue. + * + * For color-mapped images a four channel color-map is used and if --tRNS is + * given the PNG file has a tRNS chunk, as follows: + * + * 1-bit: entry 0 is transparent-red, entry 1 is opaque-white + * 2-bit: entry 0: transparent-green + * entry 1: 40%-red + * entry 2: 80%-blue + * entry 3: opaque-white + * 4-bit: the 16 combinations of the 2-bit case + * 8-bit: the 256 combinations of the 4-bit case + * + * The palette always has 2^bit-depth entries and the tRNS chunk one fewer. The + * image is the 1-channel diamond, but using palette index, not luminosity. + * + * For formats other than color-mapped ones if --tRNS is specified a tRNS chunk + * is generated with all channels equal to the low bits of 0x0101. + * + * Image size is determined by the final pixel depth in bits, i.e. channels x + * bit-depth, as follows: + * + * 8 bits or less: 64x64 + * 16 bits: 256x256 + * More than 16 bits: 1024x1024 + * + * Row filtering is the libpng default but may be turned off (the 'none' filter + * is used on every row) with the --nofilters option. + * + * The images are not interlaced. + * + * If file-name is given then the PNG is written to that file, else it is + * written to stdout. Notice that stdout is not supported on systems where, by + * default, it assumes text output; this program makes no attempt to change the + * text mode of stdout! + * + * makepng --color= ... + * + * If --color is given then the whole image has that color, color-mapped images + * will have exactly one palette entry and all image files with be 16x16 in + * size. The color value is 1 to 4 decimal numbers as appropriate for the color + * type. + * + * makepng --small ... + * + * If --small is given the images are no larger than required to include every + * possible pixel value for the format. + * + * For formats with pixels 8 bits or fewer in size the images consist of a + * single row with 2^pixel-depth pixels, one of every possible value. + * + * For formats with 16-bit pixels a 256x256 image is generated containing every + * possible pixel value. + * + * For larger pixel sizes a 256x256 image is generated where the first row + * consists of each pixel that has identical byte values throughout the pixel + * followed by rows where the byte values differ within the pixel. + * + * In all cases the pixel values are arranged in such a way that the SUB and UP + * filters give byte sequences for maximal zlib compression. By default (if + * --nofilters is not given) the SUB filter is used on the first row and the UP + * filter on all following rows. + * + * The --small option is meant to provide good test-case coverage, however the + * images are not easy to examine visually. Without the --small option the + * images contain identical color values; the pixel values are adjusted + * according to the gamma encoding with no gamma encoding being interpreted as + * sRGB. + * + * LICENSING + * ========= + * + * This code is copyright of the authors, see the COPYRIGHT define above. The + * code is licensed as above, using the libpng license. The code generates + * images which are solely the product of the code; the options choose which of + * the many possibilities to generate. The images that result (but not the code + * which generates them) are licensed as defined here: + * + * IMPORTANT: the COPYRIGHT #define must contain ISO-Latin-1 characters, the + * IMAGE_LICENSING #define must contain UTF-8 characters. The 'copyright' + * symbol 0xA9U (\251) in ISO-Latin-1 encoding and 0xC20xA9 (\302\251) in UTF-8. + */ +#define IMAGE_LICENSING "Dedicated to the public domain per Creative Commons "\ + "license \"CC0 1.0\"; https://creativecommons.org/publicdomain/zero/1.0/" + +#include /* for offsetof */ +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) +# include +#endif + +/* Define the following to use this test against your installed libpng, rather + * than the one being built here: + */ +#ifdef PNG_FREESTANDING_TESTS +# include +#else +# include "../../png.h" +#endif + +#include + +/* Work round for GCC complaints about casting a (double) function result to + * an unsigned: + */ +static unsigned int +flooru(double d) +{ + d = floor(d); + return (unsigned int)d; +} + +static png_byte +floorb(double d) +{ + d = floor(d); + return (png_byte)d; +} + +/* This structure is used for inserting extra chunks (the --insert argument, not + * documented above.) + */ +typedef struct chunk_insert +{ + struct chunk_insert *next; + void (*insert)(png_structp, png_infop, int, png_charpp); + int nparams; + png_charp parameters[1]; +} chunk_insert; + +static unsigned int +channels_of_type(int color_type) +{ + if (color_type & PNG_COLOR_MASK_PALETTE) + return 1; + + else + { + int channels = 1; + + if (color_type & PNG_COLOR_MASK_COLOR) + channels = 3; + + if (color_type & PNG_COLOR_MASK_ALPHA) + return channels + 1; + + else + return channels; + } +} + +static unsigned int +pixel_depth_of_type(int color_type, int bit_depth) +{ + return channels_of_type(color_type) * bit_depth; +} + +static unsigned int +image_size_of_type(int color_type, int bit_depth, unsigned int *colors, + int small) +{ + if (*colors) + return 16; + + else + { + int pixel_depth = pixel_depth_of_type(color_type, bit_depth); + + if (small) + { + if (pixel_depth <= 8) /* there will be one row */ + return 1 << pixel_depth; + + else + return 256; + } + + else if (pixel_depth < 8) + return 64; + + else if (pixel_depth > 16) + return 1024; + + else + return 256; + } +} + +static void +set_color(png_colorp color, png_bytep trans, unsigned int red, + unsigned int green, unsigned int blue, unsigned int alpha, + png_const_bytep gamma_table) +{ + color->red = gamma_table[red]; + color->green = gamma_table[green]; + color->blue = gamma_table[blue]; + *trans = (png_byte)alpha; +} + +static int +generate_palette(png_colorp palette, png_bytep trans, int bit_depth, + png_const_bytep gamma_table, unsigned int *colors) +{ + /* + * 1-bit: entry 0 is transparent-red, entry 1 is opaque-white + * 2-bit: entry 0: transparent-green + * entry 1: 40%-red + * entry 2: 80%-blue + * entry 3: opaque-white + * 4-bit: the 16 combinations of the 2-bit case + * 8-bit: the 256 combinations of the 4-bit case + */ + switch (colors[0]) + { + default: + fprintf(stderr, "makepng: --colors=...: invalid count %u\n", + colors[0]); + exit(1); + + case 1: + set_color(palette+0, trans+0, colors[1], colors[1], colors[1], 255, + gamma_table); + return 1; + + case 2: + set_color(palette+0, trans+0, colors[1], colors[1], colors[1], + colors[2], gamma_table); + return 1; + + case 3: + set_color(palette+0, trans+0, colors[1], colors[2], colors[3], 255, + gamma_table); + return 1; + + case 4: + set_color(palette+0, trans+0, colors[1], colors[2], colors[3], + colors[4], gamma_table); + return 1; + + case 0: + if (bit_depth == 1) + { + set_color(palette+0, trans+0, 255, 0, 0, 0, gamma_table); + set_color(palette+1, trans+1, 255, 255, 255, 255, gamma_table); + return 2; + } + + else + { + unsigned int size = 1U << (bit_depth/2); /* 2, 4 or 16 */ + unsigned int x, y; + volatile unsigned int ip = 0; + + for (x=0; x> 3; + + if (offset < rowbytes && (bit_depth < 16 || offset+1 < rowbytes)) + { + row += offset; + + switch (bit_depth) + { + case 1: + case 2: + case 4: + /* Don't gamma correct - values get smashed */ + { + unsigned int shift = (8 - bit_depth) - (x & 0x7U); + + mask <<= shift; + value = (value << shift) & mask; + *row = (png_byte)((*row & ~mask) | value); + } + return; + + default: + fprintf(stderr, "makepng: bad bit depth (internal error)\n"); + exit(1); + + case 16: + value = flooru(65535*pow(value/65535.,conv)+.5); + *row++ = (png_byte)(value >> 8); + *row = (png_byte)value; + return; + + case 8: + *row = gamma_table[value]; + return; + } + } + + else + { + fprintf(stderr, "makepng: row buffer overflow (internal error)\n"); + exit(1); + } + } + + else + { + fprintf(stderr, "makepng: component overflow (internal error)\n"); + exit(1); + } +} + +static int /* filter mask for row */ +generate_row(png_bytep row, size_t rowbytes, unsigned int y, int color_type, + int bit_depth, png_const_bytep gamma_table, double conv, + unsigned int *colors, int small) +{ + int filters = 0; /* file *MASK*, 0 means the default, not NONE */ + png_uint_32 size_max = + image_size_of_type(color_type, bit_depth, colors, small)-1; + png_uint_32 depth_max = (1U << bit_depth)-1; /* up to 65536 */ + + if (colors[0] == 0) if (small) + { + unsigned int pixel_depth = pixel_depth_of_type(color_type, bit_depth); + + /* For pixel depths less than 16 generate a single row containing all the + * possible pixel values. For 16 generate all 65536 byte pair + * combinations in a 256x256 pixel array. + */ + switch (pixel_depth) + { + case 1: + assert(y == 0 && rowbytes == 1 && size_max == 1); + row[0] = 0x6CU; /* binary: 01101100, only top 2 bits used */ + filters = PNG_FILTER_NONE; + break; + + case 2: + assert(y == 0 && rowbytes == 1 && size_max == 3); + row[0] = 0x1BU; /* binary 00011011, all bits used */ + filters = PNG_FILTER_NONE; + break; + + case 4: + assert(y == 0 && rowbytes == 8 && size_max == 15); + row[0] = 0x01U; + row[1] = 0x23U; /* SUB gives 0x22U for all following bytes */ + row[2] = 0x45U; + row[3] = 0x67U; + row[4] = 0x89U; + row[5] = 0xABU; + row[6] = 0xCDU; + row[7] = 0xEFU; + filters = PNG_FILTER_SUB; + break; + + case 8: + /* The row will have all the pixel values in order starting with + * '1', the SUB filter will change every byte into '1' (including + * the last, which generates pixel value '0'). Since the SUB filter + * has value 1 this should result in maximum compression. + */ + assert(y == 0 && rowbytes == 256 && size_max == 255); + for (;;) + { + row[size_max] = 0xFFU & (size_max+1); + if (size_max == 0) + break; + --size_max; + } + filters = PNG_FILTER_SUB; + break; + + case 16: + /* Rows are generated such that each row has a constant difference + * between the first and second byte of each pixel and so that the + * difference increases by 1 at each row. The rows start with the + * first byte value of 0 and the value increases to 255 across the + * row. + * + * The difference starts at 1, so the first row is: + * + * 0 1 1 2 2 3 3 4 ... 254 255 255 0 + * + * This means that running the SUB filter on the first row produces: + * + * [SUB==1] 0 1 0 1 0 1... + * + * Then the difference is 2 on the next row, giving: + * + * 0 2 1 3 2 4 3 5 ... 254 0 255 1 + * + * When the UP filter is run on this libpng produces: + * + * [UP ==2] 0 1 0 1 0 1... + * + * And so on for all the remain rows to the final two * rows: + * + * row 254: 0 255 1 0 2 1 3 2 4 3 ... 254 253 255 254 + * row 255: 0 0 1 1 2 2 3 3 4 4 ... 254 254 255 255 + */ + assert(rowbytes == 512 && size_max == 255); + for (;;) + { + row[2*size_max ] = 0xFFU & size_max; + row[2*size_max+1] = 0xFFU & (size_max+y+1); + if (size_max == 0) + break; + --size_max; + } + /* The first row must include PNG_FILTER_UP so that libpng knows we + * need to keep it for the following row: + */ + filters = (y == 0 ? PNG_FILTER_SUB+PNG_FILTER_UP : PNG_FILTER_UP); + break; + + case 24: + case 32: + case 48: + case 64: + /* The rows are filled by an alogorithm similar to the above, in the + * first row pixel bytes are all equal, increasing from 0 by 1 for + * each pixel. In the second row the bytes within a pixel are + * incremented 1,3,5,7,... from the previous row byte. Using an odd + * number ensures all the possible byte values are used. + */ + assert(size_max == 255 && rowbytes == 256*(pixel_depth>>3)); + pixel_depth >>= 3; /* now in bytes */ + while (rowbytes > 0) + { + const size_t pixel_index = --rowbytes/pixel_depth; + + if (y == 0) + row[rowbytes] = 0xFFU & pixel_index; + + else + { + const size_t byte_offset = + rowbytes - pixel_index * pixel_depth; + + row[rowbytes] = + 0xFFU & (pixel_index + (byte_offset * 2*y) + 1); + } + } + filters = (y == 0 ? PNG_FILTER_SUB+PNG_FILTER_UP : PNG_FILTER_UP); + break; + + default: + assert(0/*NOT REACHED*/); + } + } + + else switch (channels_of_type(color_type)) + { + /* 1 channel: a square image with a diamond, the least luminous colors are on + * the edge of the image, the most luminous in the center. + */ + case 1: + { + png_uint_32 x; + png_uint_32 base = 2*size_max - abs(2*y-size_max); + + for (x=0; x<=size_max; ++x) + { + png_uint_32 luma = base - abs(2*x-size_max); + + /* 'luma' is now in the range 0..2*size_max, we need + * 0..depth_max + */ + luma = (luma*depth_max + size_max) / (2*size_max); + set_value(row, rowbytes, x, bit_depth, luma, gamma_table, conv); + } + } + break; + + /* 2 channels: the color channel increases in luminosity from top to bottom, + * the alpha channel increases in opacity from left to right. + */ + case 2: + { + png_uint_32 alpha = (depth_max * y * 2 + size_max) / (2 * size_max); + png_uint_32 x; + + for (x=0; x<=size_max; ++x) + { + set_value(row, rowbytes, 2*x, bit_depth, + (depth_max * x * 2 + size_max) / (2 * size_max), gamma_table, + conv); + set_value(row, rowbytes, 2*x+1, bit_depth, alpha, gamma_table, + conv); + } + } + break; + + /* 3 channels: linear combinations of, from the top-left corner clockwise, + * black, green, white, red. + */ + case 3: + { + /* x0: the black->red scale (the value of the red component) at the + * start of the row (blue and green are 0). + * x1: the green->white scale (the value of the red and blue + * components at the end of the row; green is depth_max). + */ + png_uint_32 Y = (depth_max * y * 2 + size_max) / (2 * size_max); + png_uint_32 x; + + /* Interpolate x/depth_max from start to end: + * + * start end difference + * red: Y Y 0 + * green: 0 depth_max depth_max + * blue: 0 Y Y + */ + for (x=0; x<=size_max; ++x) + { + set_value(row, rowbytes, 3*x+0, bit_depth, /* red */ Y, + gamma_table, conv); + set_value(row, rowbytes, 3*x+1, bit_depth, /* green */ + (depth_max * x * 2 + size_max) / (2 * size_max), + gamma_table, conv); + set_value(row, rowbytes, 3*x+2, bit_depth, /* blue */ + (Y * x * 2 + size_max) / (2 * size_max), + gamma_table, conv); + } + } + break; + + /* 4 channels: linear combinations of, from the top-left corner clockwise, + * transparent, red, green, blue. + */ + case 4: + { + /* x0: the transparent->blue scale (the value of the blue and alpha + * components) at the start of the row (red and green are 0). + * x1: the red->green scale (the value of the red and green + * components at the end of the row; blue is 0 and alpha is + * depth_max). + */ + png_uint_32 Y = (depth_max * y * 2 + size_max) / (2 * size_max); + png_uint_32 x; + + /* Interpolate x/depth_max from start to end: + * + * start end difference + * red: 0 depth_max-Y depth_max-Y + * green: 0 Y Y + * blue: Y 0 -Y + * alpha: Y depth_max depth_max-Y + */ + for (x=0; x<=size_max; ++x) + { + set_value(row, rowbytes, 4*x+0, bit_depth, /* red */ + ((depth_max-Y) * x * 2 + size_max) / (2 * size_max), + gamma_table, conv); + set_value(row, rowbytes, 4*x+1, bit_depth, /* green */ + (Y * x * 2 + size_max) / (2 * size_max), + gamma_table, conv); + set_value(row, rowbytes, 4*x+2, bit_depth, /* blue */ + Y - (Y * x * 2 + size_max) / (2 * size_max), + gamma_table, conv); + set_value(row, rowbytes, 4*x+3, bit_depth, /* alpha */ + Y + ((depth_max-Y) * x * 2 + size_max) / (2 * size_max), + gamma_table, conv); + } + } + break; + + default: + fprintf(stderr, "makepng: internal bad channel count\n"); + exit(2); + } + + else if (color_type & PNG_COLOR_MASK_PALETTE) + { + /* Palette with fixed color: the image rows are all 0 and the image width + * is 16. + */ + memset(row, 0, rowbytes); + } + + else if (colors[0] == channels_of_type(color_type)) + switch (channels_of_type(color_type)) + { + case 1: + { + png_uint_32 luma = colors[1]; + png_uint_32 x; + + for (x=0; x<=size_max; ++x) + set_value(row, rowbytes, x, bit_depth, luma, gamma_table, + conv); + } + break; + + case 2: + { + png_uint_32 luma = colors[1]; + png_uint_32 alpha = colors[2]; + png_uint_32 x; + + for (x=0; x 0 && gamma < 1000) + gamma = PNG_FP_1; + + if (gamma > 0) + real_gamma = gamma; + + { + unsigned int i; + + if (real_gamma == 45455) for (i=0; i<256; ++i) + { + gamma_table[i] = (png_byte)i; + conv = 1.; + } + + else + { + /* Convert 'i' from sRGB (45455) to real_gamma, this makes + * the images look the same regardless of the gAMA chunk. + */ + conv = real_gamma; + conv /= 45455; + + gamma_table[0] = 0; + + for (i=1; i<255; ++i) + gamma_table[i] = floorb(pow(i/255.,conv) * 255 + .5); + + gamma_table[255] = 255; + } + } + + png_set_IHDR(png_ptr, info_ptr, size, ysize, bit_depth, color_type, + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if (color_type & PNG_COLOR_MASK_PALETTE) + { + int npalette; + png_color palette[256]; + png_byte trans[256]; + + npalette = generate_palette(palette, trans, bit_depth, gamma_table, + colors); + png_set_PLTE(png_ptr, info_ptr, palette, npalette); + + if (tRNS) + png_set_tRNS(png_ptr, info_ptr, trans, npalette-1, + NULL/*transparent color*/); + + /* Reset gamma_table to prevent the image rows being changed */ + for (npalette=0; npalette<256; ++npalette) + gamma_table[npalette] = (png_byte)npalette; + } + + else if (tRNS) + { + png_color_16 col; + + col.red = col.green = col.blue = col.gray = + 0x0101U & ((1U< 0) /* Else don't set color space information */ + { + png_set_gAMA_fixed(png_ptr, info_ptr, real_gamma); + + /* Just use the sRGB values here. */ + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270, 32900, + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000 + ); + } + + /* Insert extra information. */ + while (insert != NULL) + { + insert->insert(png_ptr, info_ptr, insert->nparams, insert->parameters); + insert = insert->next; + } + + /* Write the file header. */ + png_write_info(png_ptr, info_ptr); + + /* Restrict the filters */ + png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, filters); + + { +# ifdef PNG_WRITE_INTERLACING_SUPPORTED + int passes = png_set_interlace_handling(png_ptr); +# else /* !WRITE_INTERLACING */ + int passes = 1; +# endif /* !WRITE_INTERLACING */ + int pass; + size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + row = malloc(rowbytes); + + if (row == NULL) + png_error(png_ptr, "OOM allocating row buffer"); + + for (pass = 0; pass < passes; ++pass) + { + unsigned int y; + + for (y=0; y 0) + { + /* Round up to a multiple of 4 here to allow an iCCP profile + * to be padded to a 4x boundary. + */ + png_bytep data = malloc((total+3)&~3); + + if (data != NULL) + { + size_t new_size = 0; + + for (;;) + { + ch = getc(fp); + if (ch == EOF) break; + data[new_size++] = (png_byte)ch; + } + + if (ferror(fp) || new_size != total) + { + perror("temporary file"); + fprintf(stderr, "temporary file read error\n"); + free(data); + } + + else + { + (void)fclose(fp); + *result = data; + return total; + } + } + + else + fprintf(stderr, "%s: out of memory loading file\n", name); + } + + else + fprintf(stderr, "%s: empty file\n", name); + } + } + } + + else + { + perror(name); + fprintf(stderr, "%s: open failed\n", name); + } + + fclose(fp); + } + + else + fprintf(stderr, "makepng: %s: could not open temporary file\n", name); + + exit(1); + return 0; +} + +static size_t +load_fake(png_charp param, png_bytepp profile) +{ + char *endptr = NULL; + uint64_t size = strtoull(param, &endptr, 0/*base*/); + + /* The 'fake' format is *[string] */ + if (endptr != NULL && *endptr == '*') + { + size_t len = strlen(++endptr); + size_t result = (size_t)size; + + if (len == 0) len = 1; /* capture the terminating '\0' */ + + /* Now repeat that string to fill 'size' bytes. */ + if (result == size && (*profile = malloc(result)) != NULL) + { + png_bytep out = *profile; + + if (len == 1) + memset(out, *endptr, result); + + else + { + while (size >= len) + { + memcpy(out, endptr, len); + out += len; + size -= len; + } + memcpy(out, endptr, size); + } + + return result; + } + + else + { + fprintf(stderr, "%s: size exceeds system limits\n", param); + exit(1); + } + } + + return 0; +} + +static void +check_param_count(int nparams, int expect) +{ + if (nparams != expect) + { + fprintf(stderr, "bad parameter count (internal error)\n"); + exit(1); + } +} + +static void +insert_iCCP(png_structp png_ptr, png_infop info_ptr, int nparams, + png_charpp params) +{ + png_bytep profile = NULL; + png_uint_32 proflen = 0; + int result; + + check_param_count(nparams, 2); + + switch (params[1][0]) + { + case '<': + { + size_t filelen = load_file(params[1]+1, &profile); + if (filelen > 0xfffffffc) /* Maximum profile length */ + { + fprintf(stderr, "%s: file too long (%lu) for an ICC profile\n", + params[1]+1, (unsigned long)filelen); + exit(1); + } + + proflen = (png_uint_32)filelen; + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + size_t fake_len = load_fake(params[1], &profile); + + if (fake_len > 0) /* else a simple parameter */ + { + if (fake_len > 0xffffffff) /* Maximum profile length */ + { + fprintf(stderr, + "%s: fake data too long (%lu) for an ICC profile\n", + params[1], (unsigned long)fake_len); + exit(1); + } + proflen = (png_uint_32)(fake_len & ~3U); + /* Always fix up the profile length. */ + png_save_uint_32(profile, proflen); + break; + } + } + + default: + fprintf(stderr, "--insert iCCP \"%s\": unrecognized\n", params[1]); + fprintf(stderr, " use '<' to read a file: \" 3) + { + png_uint_32 prof_header = png_get_uint_32(profile); + + if (prof_header != proflen) + { + fprintf(stderr, "--insert iCCP %s: profile length field wrong:\n", + params[1]); + fprintf(stderr, " actual %lu, recorded value %lu (corrected)\n", + (unsigned long)proflen, (unsigned long)prof_header); + png_save_uint_32(profile, proflen); + } + } + + if (result && profile != NULL && proflen >=4) + png_set_iCCP(png_ptr, info_ptr, params[0], PNG_COMPRESSION_TYPE_BASE, + profile, proflen); + + if (profile) + free(profile); + + if (!result) + exit(1); +} + +static void +clear_text(png_text *text, png_charp keyword) +{ + text->compression = -1; /* none */ + text->key = keyword; + text->text = NULL; + text->text_length = 0; /* libpng calculates this */ + text->itxt_length = 0; /* libpng calculates this */ + text->lang = NULL; + text->lang_key = NULL; +} + +static void +set_text(png_structp png_ptr, png_infop info_ptr, png_textp text, + png_charp param) +{ + switch (param[0]) + { + case '<': + { + png_bytep file = NULL; + + text->text_length = load_file(param+1, &file); + text->text = (png_charp)file; + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + { + png_bytep data = NULL; + size_t fake_len = load_fake(param, &data); + + if (fake_len > 0) /* else a simple parameter */ + { + text->text_length = fake_len; + text->text = (png_charp)data; + break; + } + } + + default: + text->text = param; + break; + } + + png_set_text(png_ptr, info_ptr, text, 1); + + if (text->text != param) + free(text->text); +} + +static void +insert_tEXt(png_structp png_ptr, png_infop info_ptr, int nparams, + png_charpp params) +{ + png_text text; + + check_param_count(nparams, 2); + clear_text(&text, params[0]); + set_text(png_ptr, info_ptr, &text, params[1]); +} + +static void +insert_zTXt(png_structp png_ptr, png_infop info_ptr, int nparams, + png_charpp params) +{ + png_text text; + + check_param_count(nparams, 2); + clear_text(&text, params[0]); + text.compression = 0; /* deflate */ + set_text(png_ptr, info_ptr, &text, params[1]); +} + +static void +insert_iTXt(png_structp png_ptr, png_infop info_ptr, int nparams, + png_charpp params) +{ + png_text text; + + check_param_count(nparams, 4); + clear_text(&text, params[0]); + text.compression = 2; /* iTXt + deflate */ + text.lang = params[1];/* language tag */ + text.lang_key = params[2]; /* translated keyword */ + set_text(png_ptr, info_ptr, &text, params[3]); +} + +static void +insert_hIST(png_structp png_ptr, png_infop info_ptr, int nparams, + png_charpp params) +{ + int i; + png_uint_16 freq[256]; + + /* libpng takes the count from the PLTE count; we don't check it here but we + * do set the array to 0 for unspecified entries. + */ + memset(freq, 0, sizeof freq); + for (i=0; inext = NULL; + cip->insert = insert; + cip->nparams = nparams; + for (i=0; iparameters[i] = list[i]; + + return cip; +} + +static chunk_insert * +find_insert(png_const_charp what, png_charp param) +{ + png_uint_32 chunk = 0; + png_charp parameter_list[1024]; + int i, nparams; + + /* Assemble the chunk name */ + for (i=0; i<4; ++i) + { + char ch = what[i]; + + if ((ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122)) + chunk = (chunk << 8) + what[i]; + + else + break; + } + + if (i < 4 || what[4] != 0) + { + fprintf(stderr, "makepng --insert \"%s\": invalid chunk name\n", what); + exit(1); + } + + /* Assemble the parameter list. */ + nparams = find_parameters(what, param, parameter_list, 1024); + +# define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d)) + + switch (chunk) + { + case CHUNK(105,67,67,80): /* iCCP */ + if (nparams == 2) + return make_insert(what, insert_iCCP, nparams, parameter_list); + break; + + case CHUNK(116,69,88,116): /* tEXt */ + if (nparams == 2) + return make_insert(what, insert_tEXt, nparams, parameter_list); + break; + + case CHUNK(122,84,88,116): /* zTXt */ + if (nparams == 2) + return make_insert(what, insert_zTXt, nparams, parameter_list); + break; + + case CHUNK(105,84,88,116): /* iTXt */ + if (nparams == 4) + return make_insert(what, insert_iTXt, nparams, parameter_list); + break; + + case CHUNK(104,73,83,84): /* hIST */ + if (nparams <= 256) + return make_insert(what, insert_hIST, nparams, parameter_list); + break; + + case CHUNK(115,66,73,84): /* sBIT */ + if (nparams <= 4) + return make_insert(what, insert_sBIT, nparams, parameter_list); + break; + +#if 0 + case CHUNK(115,80,76,84): /* sPLT */ + return make_insert(what, insert_sPLT, nparams, parameter_list); +#endif + + default: + fprintf(stderr, "makepng --insert \"%s\": unrecognized chunk name\n", + what); + exit(1); + } + + bad_parameter_count(what, nparams); + return NULL; +} + +/* This is necessary because libpng expects writeable strings for things like + * text chunks (maybe this should be fixed...) + */ +static png_charp +strstash(png_const_charp foo) +{ + /* The program indicates a memory allocation error by crashing, this is by + * design. + */ + if (foo != NULL) + { + png_charp bar = malloc(strlen(foo)+1); + return strcpy(bar, foo); + } + + return NULL; +} + +static png_charp +strstash_list(const png_const_charp *text) +{ + size_t foo = 0; + png_charp result, bar; + const png_const_charp *line = text; + + while (*line != NULL) + foo += strlen(*line++); + + result = bar = malloc(foo+1); + + line = text; + while (*line != NULL) + { + foo = strlen(*line); + memcpy(bar, *line++, foo); + bar += foo; + } + + *bar = 0; + return result; +} + +/* These are used to insert Copyright and Licence fields, they allow the text to + * have \n unlike the --insert option. + */ +static chunk_insert * +add_tEXt(const char *key, const png_const_charp *text) +{ + static char what[5] = { 116, 69, 88, 116, 0 }; + png_charp parameter_list[3]; + + parameter_list[0] = strstash(key); + parameter_list[1] = strstash_list(text); + parameter_list[2] = NULL; + + return make_insert(what, insert_tEXt, 2, parameter_list); +} + +static chunk_insert * +add_iTXt(const char *key, const char *language, const char *language_key, + const png_const_charp *text) +{ + static char what[5] = { 105, 84, 88, 116, 0 }; + png_charp parameter_list[5]; + + parameter_list[0] = strstash(key); + parameter_list[1] = strstash(language); + parameter_list[2] = strstash(language_key); + parameter_list[3] = strstash_list(text); + parameter_list[4] = NULL; + + return make_insert(what, insert_iTXt, 4, parameter_list); +} + +/* This is a not-very-good parser for a sequence of numbers (including 0). It + * doesn't accept some apparently valid things, but it accepts all the sensible + * combinations. + */ +static void +parse_color(char *arg, unsigned int *colors) +{ + unsigned int ncolors = 0; + + while (*arg && ncolors < 4) + { + char *ep = arg; + + unsigned long ul = strtoul(arg, &ep, 0); + + if (ul > 65535) + { + fprintf(stderr, "makepng --color=...'%s': too big\n", arg); + exit(1); + } + + if (ep == arg) + { + fprintf(stderr, "makepng --color=...'%s': not a valid color\n", arg); + exit(1); + } + + if (*ep) ++ep; /* skip a separator */ + arg = ep; + + colors[++ncolors] = (unsigned int)ul; /* checked above */ + } + + if (*arg) + { + fprintf(stderr, "makepng --color=...'%s': too many values\n", arg); + exit(1); + } + + *colors = ncolors; +} + +int +main(int argc, char **argv) +{ + FILE *fp = stdout; + const char *file_name = NULL; + int color_type = 8; /* invalid */ + int bit_depth = 32; /* invalid */ + int small = 0; /* make full size images */ + int tRNS = 0; /* don't output a tRNS chunk */ + unsigned int colors[5]; + unsigned int filters = PNG_ALL_FILTERS; + png_fixed_point gamma = 0; /* not set */ + chunk_insert *head_insert = NULL; + chunk_insert **insert_ptr = &head_insert; + + memset(colors, 0, sizeof colors); + + while (--argc > 0) + { + char *arg = *++argv; + + if (strcmp(arg, "--small") == 0) + { + small = 1; + continue; + } + + if (strcmp(arg, "--tRNS") == 0) + { + tRNS = 1; + continue; + } + + if (strcmp(arg, "--sRGB") == 0) + { + gamma = PNG_DEFAULT_sRGB; + continue; + } + + if (strcmp(arg, "--linear") == 0) + { + gamma = PNG_FP_1; + continue; + } + + if (strcmp(arg, "--1.8") == 0) + { + gamma = PNG_GAMMA_MAC_18; + continue; + } + + if (strcmp(arg, "--nofilters") == 0) + { + filters = PNG_FILTER_NONE; + continue; + } + + if (strncmp(arg, "--color=", 8) == 0) + { + parse_color(arg+8, colors); + continue; + } + + if (argc >= 3 && strcmp(arg, "--insert") == 0) + { + png_const_charp what = *++argv; + png_charp param = *++argv; + chunk_insert *new_insert; + + argc -= 2; + + new_insert = find_insert(what, param); + + if (new_insert != NULL) + { + *insert_ptr = new_insert; + insert_ptr = &new_insert->next; + } + + continue; + } + + if (arg[0] == '-') + { + fprintf(stderr, "makepng: %s: invalid option\n", arg); + exit(1); + } + + if (strcmp(arg, "palette") == 0) + { + color_type = PNG_COLOR_TYPE_PALETTE; + continue; + } + + if (strncmp(arg, "gray", 4) == 0) + { + if (arg[4] == 0) + { + color_type = PNG_COLOR_TYPE_GRAY; + continue; + } + + else if (strcmp(arg+4, "a") == 0 || + strcmp(arg+4, "alpha") == 0 || + strcmp(arg+4, "-alpha") == 0) + { + color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + continue; + } + } + + if (strncmp(arg, "rgb", 3) == 0) + { + if (arg[3] == 0) + { + color_type = PNG_COLOR_TYPE_RGB; + continue; + } + + else if (strcmp(arg+3, "a") == 0 || + strcmp(arg+3, "alpha") == 0 || + strcmp(arg+3, "-alpha") == 0) + { + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + continue; + } + } + + if (color_type == 8 && isdigit(arg[0])) + { + color_type = atoi(arg); + if (color_type < 0 || color_type > 6 || color_type == 1 || + color_type == 5) + { + fprintf(stderr, "makepng: %s: not a valid color type\n", arg); + exit(1); + } + + continue; + } + + if (bit_depth == 32 && isdigit(arg[0])) + { + bit_depth = atoi(arg); + if (bit_depth <= 0 || bit_depth > 16 || + (bit_depth & -bit_depth) != bit_depth) + { + fprintf(stderr, "makepng: %s: not a valid bit depth\n", arg); + exit(1); + } + + continue; + } + + if (argc == 1) /* It's the file name */ + { + fp = fopen(arg, "wb"); + if (fp == NULL) + { + fprintf(stderr, "%s: %s: could not open\n", arg, strerror(errno)); + exit(1); + } + + file_name = arg; + continue; + } + + fprintf(stderr, "makepng: %s: unknown argument\n", arg); + exit(1); + } /* argument while loop */ + + if (color_type == 8 || bit_depth == 32) + { + fprintf(stderr, "usage: makepng [--small] [--sRGB|--linear|--1.8] " + "[--color=...] color-type bit-depth [file-name]\n" + " Make a test PNG file, by default writes to stdout.\n" + " Other options are available, UTSL.\n"); + exit(1); + } + + /* Check the colors */ + { + unsigned int lim = (color_type == PNG_COLOR_TYPE_PALETTE ? 255U : + (1U< lim) + { + fprintf(stderr, "makepng: --color=...: %u out of range [0..%u]\n", + colors[i], lim); + exit(1); + } + } + + /* small and colors are incomparible (will probably crash if both are used at + * the same time!) + */ + if (small && colors[0] != 0) + { + fprintf(stderr, "makepng: --color --small: only one at a time!\n"); + exit(1); + } + + /* Restrict the filters for more speed to those we know are used for the + * generated images. + */ + if (filters == PNG_ALL_FILTERS && !small/*small provides defaults*/) + { + if ((color_type & PNG_COLOR_MASK_PALETTE) != 0 || bit_depth < 8) + filters = PNG_FILTER_NONE; + + else if (color_type & PNG_COLOR_MASK_COLOR) /* rgb */ + { + if (bit_depth == 8) + filters &= ~(PNG_FILTER_NONE | PNG_FILTER_AVG); + + else + filters = PNG_FILTER_SUB | PNG_FILTER_PAETH; + } + + else /* gray 8 or 16-bit */ + filters &= ~PNG_FILTER_NONE; + } + + /* Insert standard copyright and licence text. */ + { + static png_const_charp copyright[] = + { + COPYRIGHT, /* ISO-Latin-1 */ + NULL + }; + static png_const_charp licensing[] = + { + IMAGE_LICENSING, /* UTF-8 */ + NULL + }; + + chunk_insert *new_insert; + + new_insert = add_tEXt("Copyright", copyright); + if (new_insert != NULL) + { + *insert_ptr = new_insert; + insert_ptr = &new_insert->next; + } + + new_insert = add_iTXt("Licensing", "en", NULL, licensing); + if (new_insert != NULL) + { + *insert_ptr = new_insert; + insert_ptr = &new_insert->next; + } + } + + { + int ret = write_png(&file_name, fp, color_type, bit_depth, gamma, + head_insert, filters, colors, small, tRNS); + + if (ret != 0 && file_name != NULL) + remove(file_name); + + return ret; + } +} diff --git a/libs/libpng-src/contrib/libtests/pngimage.c b/libs/libpng-src/contrib/libtests/pngimage.c new file mode 100644 index 000000000..f130c043d --- /dev/null +++ b/libs/libpng-src/contrib/libtests/pngimage.c @@ -0,0 +1,1712 @@ +/* pngimage.c + * + * Copyright (c) 2015,2016 John Cunningham Bowler + * + * Last changed in libpng 1.6.24 [August 4, 2016] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * Test the png_read_png and png_write_png interfaces. Given a PNG file load it + * using png_read_png and then write with png_write_png. Test all possible + * transforms. + */ +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) +# include +#endif + +/* Define the following to use this test against your installed libpng, rather + * than the one being built here: + */ +#ifdef PNG_FREESTANDING_TESTS +# include +#else +# include "../../png.h" +#endif + +#ifndef PNG_SETJMP_SUPPORTED +# include /* because png.h did *not* include this */ +#endif + +/* 1.6.1 added support for the configure test harness, which uses 77 to indicate + * a skipped test, in earlier versions we need to succeed on a skipped test, so: + */ +#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H) +# define SKIP 77 +#else +# define SKIP 0 +#endif + +#if PNG_LIBPNG_VER < 10700 + /* READ_PNG and WRITE_PNG were not defined, so: */ +# ifdef PNG_INFO_IMAGE_SUPPORTED +# ifdef PNG_SEQUENTIAL_READ_SUPPORTED +# define PNG_READ_PNG_SUPPORTED +# endif /* SEQUENTIAL_READ */ +# ifdef PNG_WRITE_SUPPORTED +# define PNG_WRITE_PNG_SUPPORTED +# endif /* WRITE */ +# endif /* INFO_IMAGE */ +#endif /* pre 1.7.0 */ + +#ifdef PNG_READ_PNG_SUPPORTED +/* If a transform is valid on both read and write this implies that if the + * transform is applied to read it must also be applied on write to produce + * meaningful data. This is because these transforms when performed on read + * produce data with a memory format that does not correspond to a PNG format. + * + * Most of these transforms are invertible; after applying the transform on + * write the result is the original PNG data that would have would have been + * read if no transform were applied. + * + * The exception is _SHIFT, which destroys the low order bits marked as not + * significant in a PNG with the sBIT chunk. + * + * The following table lists, for each transform, the conditions under which it + * is expected to do anything. Conditions are defined as follows: + * + * 1) Color mask bits required - simply a mask to AND with color_type; one of + * these must be present for the transform to fire, except that 0 means + * 'always'. + * 2) Color mask bits which must be absent - another mask - none of these must + * be present. + * 3) Bit depths - a mask of component bit depths for the transform to fire. + * 4) 'read' - the transform works in png_read_png. + * 5) 'write' - the transform works in png_write_png. + * 6) PNG_INFO_chunk; a mask of the chunks that must be present for the + * transform to fire. All must be present - the requirement is that + * png_get_valid() & mask == mask, so if mask is 0 there is no requirement. + * + * The condition refers to the original image state - if multiple transforms are + * used together it is possible to cause a transform that wouldn't fire on the + * original image to fire. + */ +static struct transform_info +{ + const char *name; + int transform; + png_uint_32 valid_chunks; +# define CHUNK_NONE 0 +# define CHUNK_sBIT PNG_INFO_sBIT +# define CHUNK_tRNS PNG_INFO_tRNS + png_byte color_mask_required; + png_byte color_mask_absent; +# define COLOR_MASK_X 0 +# define COLOR_MASK_P PNG_COLOR_MASK_PALETTE +# define COLOR_MASK_C PNG_COLOR_MASK_COLOR +# define COLOR_MASK_A PNG_COLOR_MASK_ALPHA +# define COLOR_MASK_ALL (PALETTE+COLOR+ALPHA) /* absent = gray, no alpha */ + png_byte bit_depths; +# define BD_ALL (1 + 2 + 4 + 8 + 16) +# define BD_PAL (1 + 2 + 4 + 8) +# define BD_LOW (1 + 2 + 4) +# define BD_16 16 +# define BD_TRUE (8+16) /* i.e. true-color depths */ + png_byte when; +# define TRANSFORM_R 1 +# define TRANSFORM_W 2 +# define TRANSFORM_RW 3 + png_byte tested; /* the transform was tested somewhere */ +} transform_info[] = +{ + /* List ALL the PNG_TRANSFORM_ macros here. Check for support using the READ + * macros; even if the transform is supported on write it cannot be tested + * without the read support. + */ +# define T(name,chunk,cm_required,cm_absent,bd,when)\ + { #name, PNG_TRANSFORM_ ## name, CHUNK_ ## chunk,\ + COLOR_MASK_ ## cm_required, COLOR_MASK_ ## cm_absent, BD_ ## bd,\ + TRANSFORM_ ## when, 0/*!tested*/ } + +#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED + T(STRIP_16, NONE, X, X, 16, R), + /* drops the bottom 8 bits when bit depth is 16 */ +#endif +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED + T(STRIP_ALPHA, NONE, A, X, ALL, R), + /* removes the alpha channel if present */ +#endif +#ifdef PNG_WRITE_PACK_SUPPORTED +# define TRANSFORM_RW_PACK TRANSFORM_RW +#else +# define TRANSFORM_RW_PACK TRANSFORM_R +#endif +#ifdef PNG_READ_PACK_SUPPORTED + T(PACKING, NONE, X, X, LOW, RW_PACK), + /* unpacks low-bit-depth components into 1 byte per component on read, + * reverses this on write. + */ +#endif +#ifdef PNG_WRITE_PACKSWAP_SUPPORTED +# define TRANSFORM_RW_PACKSWAP TRANSFORM_RW +#else +# define TRANSFORM_RW_PACKSWAP TRANSFORM_R +#endif +#ifdef PNG_READ_PACKSWAP_SUPPORTED + T(PACKSWAP, NONE, X, X, LOW, RW_PACKSWAP), + /* reverses the order of low-bit-depth components packed into a byte */ +#endif +#ifdef PNG_READ_EXPAND_SUPPORTED + T(EXPAND, NONE, P, X, ALL, R), + /* expands PLTE PNG files to RGB (no tRNS) or RGBA (tRNS) * + * Note that the 'EXPAND' transform does lots of different things: */ + T(EXPAND, NONE, X, C, ALL, R), + /* expands grayscale PNG files to RGB, or RGBA */ + T(EXPAND, tRNS, X, A, ALL, R), + /* expands the tRNS chunk in files without alpha */ +#endif +#ifdef PNG_WRITE_INVERT_SUPPORTED +# define TRANSFORM_RW_INVERT TRANSFORM_RW +#else +# define TRANSFORM_RW_INVERT TRANSFORM_R +#endif +#ifdef PNG_READ_INVERT_SUPPORTED + T(INVERT_MONO, NONE, X, C, ALL, RW_INVERT), + /* converts gray-scale components to 1..0 from 0..1 */ +#endif +#ifdef PNG_WRITE_SHIFT_SUPPORTED +# define TRANSFORM_RW_SHIFT TRANSFORM_RW +#else +# define TRANSFORM_RW_SHIFT TRANSFORM_R +#endif +#ifdef PNG_READ_SHIFT_SUPPORTED + T(SHIFT, sBIT, X, X, ALL, RW_SHIFT), + /* reduces component values to the original range based on the sBIT chunk, + * this is only partially reversible - the low bits are lost and cannot be + * recovered on write. In fact write code replicates the bits to generate + * new low-order bits. + */ +#endif +#ifdef PNG_WRITE_BGR_SUPPORTED +# define TRANSFORM_RW_BGR TRANSFORM_RW +#else +# define TRANSFORM_RW_BGR TRANSFORM_R +#endif +#ifdef PNG_READ_BGR_SUPPORTED + T(BGR, NONE, C, P, TRUE, RW_BGR), + /* reverses the rgb component values of true-color pixels */ +#endif +#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED +# define TRANSFORM_RW_SWAP_ALPHA TRANSFORM_RW +#else +# define TRANSFORM_RW_SWAP_ALPHA TRANSFORM_R +#endif +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED + T(SWAP_ALPHA, NONE, A, X, TRUE, RW_SWAP_ALPHA), + /* swaps the alpha channel of RGBA or GA pixels to the front - ARGB or + * AG, on write reverses the process. + */ +#endif +#ifdef PNG_WRITE_SWAP_SUPPORTED +# define TRANSFORM_RW_SWAP TRANSFORM_RW +#else +# define TRANSFORM_RW_SWAP TRANSFORM_R +#endif +#ifdef PNG_READ_SWAP_SUPPORTED + T(SWAP_ENDIAN, NONE, X, P, 16, RW_SWAP), + /* byte-swaps 16-bit component values */ +#endif +#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED +# define TRANSFORM_RW_INVERT_ALPHA TRANSFORM_RW +#else +# define TRANSFORM_RW_INVERT_ALPHA TRANSFORM_R +#endif +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED + T(INVERT_ALPHA, NONE, A, X, TRUE, RW_INVERT_ALPHA), + /* converts an alpha channel from 0..1 to 1..0 */ +#endif +#ifdef PNG_WRITE_FILLER_SUPPORTED + T(STRIP_FILLER_BEFORE, NONE, A, P, TRUE, W), /* 'A' for a filler! */ + /* on write skips a leading filler channel; testing requires data with a + * filler channel so this is produced from RGBA or GA images by removing + * the 'alpha' flag from the color type in place. + */ + T(STRIP_FILLER_AFTER, NONE, A, P, TRUE, W), + /* on write strips a trailing filler channel */ +#endif +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED + T(GRAY_TO_RGB, NONE, X, C, ALL, R), + /* expands grayscale images to RGB, also causes the palette part of + * 'EXPAND' to happen. Low bit depth grayscale images are expanded to + * 8-bits per component and no attempt is made to convert the image to a + * palette image. While this transform is partially reversible + * png_write_png does not currently support this. + */ + T(GRAY_TO_RGB, NONE, P, X, ALL, R), + /* The 'palette' side effect mentioned above; a bit bogus but this is the + * way the libpng code works. + */ +#endif +#ifdef PNG_READ_EXPAND_16_SUPPORTED + T(EXPAND_16, NONE, X, X, PAL, R), + /* expands images to 16-bits per component, as a side effect expands + * palette images to RGB and expands the tRNS chunk if present, so it can + * modify 16-bit per component images as well: + */ + T(EXPAND_16, tRNS, X, A, 16, R), + /* side effect of EXPAND_16 - expands the tRNS chunk in an RGB or G 16-bit + * image. + */ +#endif +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + T(SCALE_16, NONE, X, X, 16, R), + /* scales 16-bit components to 8-bits. */ +#endif + + { NULL /*name*/, 0, 0, 0, 0, 0, 0, 0/*!tested*/ } + +#undef T +}; + +#define ARRAY_SIZE(a) ((sizeof a)/(sizeof a[0])) +#define TTABLE_SIZE ARRAY_SIZE(transform_info) + +/* Some combinations of options that should be reversible are not; these cases + * are bugs. + */ +static int known_bad_combos[][2] = +{ + /* problem, antidote */ + { PNG_TRANSFORM_SHIFT | PNG_TRANSFORM_INVERT_ALPHA, 0/*antidote*/ } +}; + +static int +is_combo(int transforms) +{ + return transforms & (transforms-1); /* non-zero if more than one set bit */ +} + +static int +first_transform(int transforms) +{ + return transforms & -transforms; /* lowest set bit */ +} + +static int +is_bad_combo(int transforms) +{ + unsigned int i; + + for (i=0; ifirst.next = NULL; + buffer->last = NULL; + buffer->current = NULL; +} + +static void +buffer_destroy_list(struct buffer_list *list) +{ + if (list != NULL) + { + struct buffer_list *next = list->next; + DELETE(list); + buffer_destroy_list(next); + } +} + +static void +buffer_destroy(struct buffer *buffer) +{ + struct buffer_list *list = buffer->first.next; + buffer_init(buffer); + buffer_destroy_list(list); +} + +#ifdef PNG_WRITE_PNG_SUPPORTED +static void +buffer_start_write(struct buffer *buffer) +{ + buffer->last = &buffer->first; + buffer->end_count = 0; + buffer->current = NULL; +} +#endif + +static void +buffer_start_read(struct buffer *buffer) +{ + buffer->current = &buffer->first; + buffer->read_count = 0; +} + +#ifdef ENOMEM /* required by POSIX 1003.1 */ +# define MEMORY ENOMEM +#else +# define MEMORY ERANGE /* required by ANSI-C */ +#endif +static struct buffer * +get_buffer(png_structp pp) + /* Used from libpng callbacks to get the current buffer */ +{ + return (struct buffer*)png_get_io_ptr(pp); +} + +static struct buffer_list * +buffer_extend(struct buffer_list *current) +{ + struct buffer_list *add; + + assert(current->next == NULL); + + add = NEW(struct buffer_list); + if (add == NULL) + return NULL; + + add->next = NULL; + current->next = add; + + return add; +} + +/* Load a buffer from a file; does the equivalent of buffer_start_write. On a + * read error returns an errno value, else returns 0. + */ +static int +buffer_from_file(struct buffer *buffer, FILE *fp) +{ + struct buffer_list *last = &buffer->first; + size_t count = 0; + + for (;;) + { + size_t r = fread(last->buffer+count, 1/*size*/, + (sizeof last->buffer)-count, fp); + + if (r > 0) + { + count += r; + + if (count >= sizeof last->buffer) + { + assert(count == sizeof last->buffer); + count = 0; + + if (last->next == NULL) + { + last = buffer_extend(last); + if (last == NULL) + return MEMORY; + } + + else + last = last->next; + } + } + + else /* fread failed - probably end of file */ + { + if (feof(fp)) + { + buffer->last = last; + buffer->end_count = count; + return 0; /* no error */ + } + + /* Some kind of funky error; errno should be non-zero */ + return errno == 0 ? ERANGE : errno; + } + } +} + +/* This structure is used to control the test of a single file. */ +typedef enum +{ + VERBOSE, /* switches on all messages */ + INFORMATION, + WARNINGS, /* switches on warnings */ + LIBPNG_WARNING, + APP_WARNING, + ERRORS, /* just errors */ + APP_FAIL, /* continuable error - no need to longjmp */ + LIBPNG_ERROR, /* this and higher cause a longjmp */ + LIBPNG_BUG, /* erroneous behavior in libpng */ + APP_ERROR, /* such as out-of-memory in a callback */ + QUIET, /* no normal messages */ + USER_ERROR, /* such as file-not-found */ + INTERNAL_ERROR +} error_level; +#define LEVEL_MASK 0xf /* where the level is in 'options' */ + +#define EXHAUSTIVE 0x010 /* Test all combinations of active options */ +#define STRICT 0x020 /* Fail on warnings as well as errors */ +#define LOG 0x040 /* Log pass/fail to stdout */ +#define CONTINUE 0x080 /* Continue on APP_FAIL errors */ +#define SKIP_BUGS 0x100 /* Skip over known bugs */ +#define LOG_SKIPPED 0x200 /* Log skipped bugs */ +#define FIND_BAD_COMBOS 0x400 /* Attempt to deduce bad combos */ +#define LIST_COMBOS 0x800 /* List combos by name */ + +/* Result masks apply to the result bits in the 'results' field below; these + * bits are simple 1U<options = WARNINGS; /* default to !verbose, !quiet */ + dp->filename = NULL; + dp->operation = NULL; + dp->original_pp = NULL; + dp->original_ip = NULL; + dp->original_rows = NULL; + dp->read_pp = NULL; + dp->read_ip = NULL; + buffer_init(&dp->original_file); + +# ifdef PNG_WRITE_PNG_SUPPORTED + dp->write_pp = NULL; + buffer_init(&dp->written_file); +# endif +} + +static void +display_clean_read(struct display *dp) +{ + if (dp->read_pp != NULL) + png_destroy_read_struct(&dp->read_pp, &dp->read_ip, NULL); +} + +#ifdef PNG_WRITE_PNG_SUPPORTED +static void +display_clean_write(struct display *dp) +{ + if (dp->write_pp != NULL) + png_destroy_write_struct(&dp->write_pp, NULL); +} +#endif + +static void +display_clean(struct display *dp) +{ +# ifdef PNG_WRITE_PNG_SUPPORTED + display_clean_write(dp); +# endif + display_clean_read(dp); + + dp->original_rowbytes = 0; + dp->original_rows = NULL; + dp->chunks = 0; + + png_destroy_read_struct(&dp->original_pp, &dp->original_ip, NULL); + /* leave the filename for error detection */ + dp->results = 0; /* reset for next time */ +} + +static void +display_destroy(struct display *dp) +{ + /* Release any memory held in the display. */ +# ifdef PNG_WRITE_PNG_SUPPORTED + buffer_destroy(&dp->written_file); +# endif + + buffer_destroy(&dp->original_file); +} + +static struct display * +get_dp(png_structp pp) + /* The display pointer is always stored in the png_struct error pointer */ +{ + struct display *dp = (struct display*)png_get_error_ptr(pp); + + if (dp == NULL) + { + fprintf(stderr, "pngimage: internal error (no display)\n"); + exit(99); /* prevents a crash */ + } + + return dp; +} + +/* error handling */ +#ifdef __GNUC__ +# define VGATTR __attribute__((__format__ (__printf__,3,4))) + /* Required to quiet GNUC warnings when the compiler sees a stdarg function + * that calls one of the stdio v APIs. + */ +#else +# define VGATTR +#endif +static void VGATTR +display_log(struct display *dp, error_level level, const char *fmt, ...) + /* 'level' is as above, fmt is a stdio style format string. This routine + * does not return if level is above LIBPNG_WARNING + */ +{ + dp->results |= 1U << level; + + if (level > (error_level)(dp->options & LEVEL_MASK)) + { + const char *lp; + va_list ap; + + switch (level) + { + case INFORMATION: lp = "information"; break; + case LIBPNG_WARNING: lp = "warning(libpng)"; break; + case APP_WARNING: lp = "warning(pngimage)"; break; + case APP_FAIL: lp = "error(continuable)"; break; + case LIBPNG_ERROR: lp = "error(libpng)"; break; + case LIBPNG_BUG: lp = "bug(libpng)"; break; + case APP_ERROR: lp = "error(pngimage)"; break; + case USER_ERROR: lp = "error(user)"; break; + + case INTERNAL_ERROR: /* anything unexpected is an internal error: */ + case VERBOSE: case WARNINGS: case ERRORS: case QUIET: + default: lp = "bug(pngimage)"; break; + } + + fprintf(stderr, "%s: %s: %s", + dp->filename != NULL ? dp->filename : "", lp, dp->operation); + + if (dp->transforms != 0) + { + int tr = dp->transforms; + + if (is_combo(tr)) + { + if (dp->options & LIST_COMBOS) + { + int trx = tr; + + fprintf(stderr, "("); + if (trx) + { + int start = 0; + + while (trx) + { + int trz = trx & -trx; + + if (start) fprintf(stderr, "+"); + fprintf(stderr, "%s", transform_name(trz)); + start = 1; + trx &= ~trz; + } + } + + else + fprintf(stderr, "-"); + fprintf(stderr, ")"); + } + + else + fprintf(stderr, "(0x%x)", tr); + } + + else + fprintf(stderr, "(%s)", transform_name(tr)); + } + + fprintf(stderr, ": "); + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); + + fputc('\n', stderr); + } + /* else do not output any message */ + + /* Errors cause this routine to exit to the fail code */ + if (level > APP_FAIL || (level > ERRORS && !(dp->options & CONTINUE))) + longjmp(dp->error_return, level); +} + +/* error handler callbacks for libpng */ +static void PNGCBAPI +display_warning(png_structp pp, png_const_charp warning) +{ + display_log(get_dp(pp), LIBPNG_WARNING, "%s", warning); +} + +static void PNGCBAPI +display_error(png_structp pp, png_const_charp error) +{ + struct display *dp = get_dp(pp); + + display_log(dp, LIBPNG_ERROR, "%s", error); +} + +static void +display_cache_file(struct display *dp, const char *filename) + /* Does the initial cache of the file. */ +{ + FILE *fp; + int ret; + + dp->filename = filename; + + if (filename != NULL) + { + fp = fopen(filename, "rb"); + if (fp == NULL) + display_log(dp, USER_ERROR, "open failed: %s", strerror(errno)); + } + + else + fp = stdin; + + ret = buffer_from_file(&dp->original_file, fp); + + fclose(fp); + + if (ret != 0) + display_log(dp, APP_ERROR, "read failed: %s", strerror(ret)); +} + +static void +buffer_read(struct display *dp, struct buffer *bp, png_bytep data, + size_t size) +{ + struct buffer_list *last = bp->current; + size_t read_count = bp->read_count; + + while (size > 0) + { + size_t avail; + + if (last == NULL || + (last == bp->last && read_count >= bp->end_count)) + { + display_log(dp, USER_ERROR, "file truncated (%lu bytes)", + (unsigned long)size); + /*NOTREACHED*/ + break; + } + + else if (read_count >= sizeof last->buffer) + { + /* Move to the next buffer: */ + last = last->next; + read_count = 0; + bp->current = last; /* Avoid update outside the loop */ + + /* And do a sanity check (the EOF case is caught above) */ + if (last == NULL) + { + display_log(dp, INTERNAL_ERROR, "damaged buffer list"); + /*NOTREACHED*/ + break; + } + } + + avail = (sizeof last->buffer) - read_count; + if (avail > size) + avail = size; + + memcpy(data, last->buffer + read_count, avail); + read_count += avail; + size -= avail; + data += avail; + } + + bp->read_count = read_count; +} + +static void PNGCBAPI +read_function(png_structp pp, png_bytep data, size_t size) +{ + buffer_read(get_dp(pp), get_buffer(pp), data, size); +} + +static void +read_png(struct display *dp, struct buffer *bp, const char *operation, + int transforms) +{ + png_structp pp; + png_infop ip; + + /* This cleans out any previous read and sets operation and transforms to + * empty. + */ + display_clean_read(dp); + + if (operation != NULL) /* else this is a verify and do not overwrite info */ + { + dp->operation = operation; + dp->transforms = transforms; + } + + dp->read_pp = pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, dp, + display_error, display_warning); + if (pp == NULL) + display_log(dp, LIBPNG_ERROR, "failed to create read struct"); + + /* The png_read_png API requires us to make the info struct, but it does the + * call to png_read_info. + */ + dp->read_ip = ip = png_create_info_struct(pp); + if (ip == NULL) + display_log(dp, LIBPNG_ERROR, "failed to create info struct"); + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + /* Remove the user limits, if any */ + png_set_user_limits(pp, 0x7fffffff, 0x7fffffff); +# endif + + /* Set the IO handling */ + buffer_start_read(bp); + png_set_read_fn(pp, bp, read_function); + + png_read_png(pp, ip, transforms, NULL/*params*/); + +#if 0 /* crazy debugging */ + { + png_bytep pr = png_get_rows(pp, ip)[0]; + size_t rb = png_get_rowbytes(pp, ip); + size_t cb; + char c = ' '; + + fprintf(stderr, "%.4x %2d (%3lu bytes):", transforms, png_get_bit_depth(pp,ip), (unsigned long)rb); + + for (cb=0; cboriginal_file, "original read", 0/*no transform*/); + + /* Move the result to the 'original' fields */ + dp->original_pp = pp = dp->read_pp, dp->read_pp = NULL; + dp->original_ip = ip = dp->read_ip, dp->read_ip = NULL; + + dp->original_rowbytes = png_get_rowbytes(pp, ip); + if (dp->original_rowbytes == 0) + display_log(dp, LIBPNG_BUG, "png_get_rowbytes returned 0"); + + dp->chunks = png_get_valid(pp, ip, 0xffffffff); + if ((dp->chunks & PNG_INFO_IDAT) == 0) /* set by png_read_png */ + display_log(dp, LIBPNG_BUG, "png_read_png did not set IDAT flag"); + + dp->original_rows = png_get_rows(pp, ip); + if (dp->original_rows == NULL) + display_log(dp, LIBPNG_BUG, "png_read_png did not create row buffers"); + + if (!png_get_IHDR(pp, ip, + &dp->width, &dp->height, &dp->bit_depth, &dp->color_type, + &dp->interlace_method, &dp->compression_method, &dp->filter_method)) + display_log(dp, LIBPNG_BUG, "png_get_IHDR failed"); + + /* 'active' transforms are discovered based on the original image format; + * running one active transform can activate others. At present the code + * does not attempt to determine the closure. + */ + { + png_uint_32 chunks = dp->chunks; + int active = 0, inactive = 0; + int ct = dp->color_type; + int bd = dp->bit_depth; + unsigned int i; + + for (i=0; iactive_transforms = active; + dp->ignored_transforms = inactive; /* excluding write-only transforms */ + } +} + +static int +compare_read(struct display *dp, int applied_transforms) +{ + /* Compare the png_info from read_ip with original_info */ + size_t rowbytes; + png_uint_32 width, height; + int bit_depth, color_type; + int interlace_method, compression_method, filter_method; + const char *e = NULL; + + png_get_IHDR(dp->read_pp, dp->read_ip, &width, &height, &bit_depth, + &color_type, &interlace_method, &compression_method, &filter_method); + +# define C(item) if (item != dp->item) \ + display_log(dp, APP_WARNING, "IHDR " #item "(%lu) changed to %lu",\ + (unsigned long)dp->item, (unsigned long)item), e = #item + + /* The IHDR should be identical: */ + C(width); + C(height); + C(bit_depth); + C(color_type); + C(interlace_method); + C(compression_method); + C(filter_method); + + /* 'e' remains set to the name of the last thing changed: */ + if (e) + display_log(dp, APP_ERROR, "IHDR changed (%s)", e); + + /* All the chunks from the original PNG should be preserved in the output PNG + * because the PNG format has not been changed. + */ + { + unsigned long chunks = + png_get_valid(dp->read_pp, dp->read_ip, 0xffffffff); + + if (chunks != dp->chunks) + display_log(dp, APP_FAIL, "PNG chunks changed from 0x%lx to 0x%lx", + (unsigned long)dp->chunks, chunks); + } + + /* rowbytes should be the same */ + rowbytes = png_get_rowbytes(dp->read_pp, dp->read_ip); + + /* NOTE: on 64-bit systems this may trash the top bits of rowbytes, + * which could lead to weird error messages. + */ + if (rowbytes != dp->original_rowbytes) + display_log(dp, APP_ERROR, "PNG rowbytes changed from %lu to %lu", + (unsigned long)dp->original_rowbytes, (unsigned long)rowbytes); + + /* The rows should be the same too, unless the applied transforms includes + * the shift transform, in which case low bits may have been lost. + */ + { + png_bytepp rows = png_get_rows(dp->read_pp, dp->read_ip); + unsigned int mask; /* mask (if not zero) for the final byte */ + + if (bit_depth < 8) + { + /* Need the stray bits at the end, this depends only on the low bits + * of the image width; overflow does not matter. If the width is an + * exact multiple of 8 bits this gives a mask of 0, not 0xff. + */ + mask = 0xff & (0xff00 >> ((bit_depth * width) & 7)); + } + + else + mask = 0; + + if (rows == NULL) + display_log(dp, LIBPNG_BUG, "png_get_rows returned NULL"); + + if ((applied_transforms & PNG_TRANSFORM_SHIFT) == 0 || + (dp->active_transforms & PNG_TRANSFORM_SHIFT) == 0 || + color_type == PNG_COLOR_TYPE_PALETTE) + { + unsigned long y; + + for (y=0; yoriginal_rows[y]; + + if (memcmp(row, orig, rowbytes-(mask != 0)) != 0 || (mask != 0 && + ((row[rowbytes-1] & mask) != (orig[rowbytes-1] & mask)))) + { + size_t x; + + /* Find the first error */ + for (x=0; x 0x%.2x", + (unsigned long)x, (unsigned long)y, orig[x], row[x]); + return 0; /* don't keep reporting failed rows on 'continue' */ + } + } + } + + else +# ifdef PNG_sBIT_SUPPORTED + { + unsigned long y; + int bpp; /* bits-per-pixel then bytes-per-pixel */ + /* components are up to 8 bytes in size */ + png_byte sig_bits[8]; + png_color_8p sBIT; + + if (png_get_sBIT(dp->read_pp, dp->read_ip, &sBIT) != PNG_INFO_sBIT) + display_log(dp, INTERNAL_ERROR, + "active shift transform but no sBIT in file"); + + switch (color_type) + { + case PNG_COLOR_TYPE_GRAY: + sig_bits[0] = sBIT->gray; + bpp = bit_depth; + break; + + case PNG_COLOR_TYPE_GA: + sig_bits[0] = sBIT->gray; + sig_bits[1] = sBIT->alpha; + bpp = 2 * bit_depth; + break; + + case PNG_COLOR_TYPE_RGB: + sig_bits[0] = sBIT->red; + sig_bits[1] = sBIT->green; + sig_bits[2] = sBIT->blue; + bpp = 3 * bit_depth; + break; + + case PNG_COLOR_TYPE_RGBA: + sig_bits[0] = sBIT->red; + sig_bits[1] = sBIT->green; + sig_bits[2] = sBIT->blue; + sig_bits[3] = sBIT->alpha; + bpp = 4 * bit_depth; + break; + + default: + display_log(dp, LIBPNG_ERROR, "invalid colour type %d", + color_type); + /*NOTREACHED*/ + bpp = 0; + break; + } + + { + int b; + + for (b=0; 8*b bit_depth/*!palette*/) + display_log(dp, LIBPNG_BUG, + "invalid sBIT[%u] value %d returned for PNG bit depth %d", + b, sig_bits[b], bit_depth); + } + } + + if (bpp < 8 && bpp != bit_depth) + { + /* sanity check; this is a grayscale PNG; something is wrong in the + * code above. + */ + display_log(dp, INTERNAL_ERROR, "invalid bpp %u for bit_depth %u", + bpp, bit_depth); + } + + switch (bit_depth) + { + int b; + + case 16: /* Two bytes per component, big-endian */ + for (b = (bpp >> 4); b > 0; --b) + { + unsigned int sig = (unsigned int)(0xffff0000 >> sig_bits[b]); + + sig_bits[2*b+1] = (png_byte)sig; + sig_bits[2*b+0] = (png_byte)(sig >> 8); /* big-endian */ + } + break; + + case 8: /* One byte per component */ + for (b=0; b*8 < bpp; ++b) + sig_bits[b] = (png_byte)(0xff00 >> sig_bits[b]); + break; + + case 1: /* allowed, but dumb */ + /* Value is 1 */ + sig_bits[0] = 0xff; + break; + + case 2: /* Replicate 4 times */ + /* Value is 1 or 2 */ + b = 0x3 & ((0x3<<2) >> sig_bits[0]); + b |= b << 2; + b |= b << 4; + sig_bits[0] = (png_byte)b; + break; + + case 4: /* Relicate twice */ + /* Value is 1, 2, 3 or 4 */ + b = 0xf & ((0xf << 4) >> sig_bits[0]); + b |= b << 4; + sig_bits[0] = (png_byte)b; + break; + + default: + display_log(dp, LIBPNG_BUG, "invalid bit depth %d", bit_depth); + break; + } + + /* Convert bpp to bytes; this gives '1' for low-bit depth grayscale, + * where there are multiple pixels per byte. + */ + bpp = (bpp+7) >> 3; + + /* The mask can be combined with sig_bits[0] */ + if (mask != 0) + { + mask &= sig_bits[0]; + + if (bpp != 1 || mask == 0) + display_log(dp, INTERNAL_ERROR, "mask calculation error %u, %u", + bpp, mask); + } + + for (y=0; yoriginal_rows[y]; + unsigned long x; + + for (x=0; x<(width-(mask!=0)); ++x) + { + int b; + + for (b=0; b%.2x", + x, b, y, orig[-1], row[-1]); + return 0; + } + } + } + + if (mask != 0 && (*row & mask) != (*orig & mask)) + { + display_log(dp, APP_FAIL, + "significant bits at (%lu[end],%lu) changed", x, y); + return 0; + } + } /* for y */ + } +# else /* !sBIT */ + display_log(dp, INTERNAL_ERROR, + "active shift transform but no sBIT support"); +# endif /* !sBIT */ + } + + return 1; /* compare succeeded */ +} + +#ifdef PNG_WRITE_PNG_SUPPORTED +static void +buffer_write(struct display *dp, struct buffer *buffer, png_bytep data, + size_t size) + /* Generic write function used both from the write callback provided to + * libpng and from the generic read code. + */ +{ + /* Write the data into the buffer, adding buffers as required */ + struct buffer_list *last = buffer->last; + size_t end_count = buffer->end_count; + + while (size > 0) + { + size_t avail; + + if (end_count >= sizeof last->buffer) + { + if (last->next == NULL) + { + last = buffer_extend(last); + + if (last == NULL) + display_log(dp, APP_ERROR, "out of memory saving file"); + } + + else + last = last->next; + + buffer->last = last; /* avoid the need to rewrite every time */ + end_count = 0; + } + + avail = (sizeof last->buffer) - end_count; + if (avail > size) + avail = size; + + memcpy(last->buffer + end_count, data, avail); + end_count += avail; + size -= avail; + data += avail; + } + + buffer->end_count = end_count; +} + +static void PNGCBAPI +write_function(png_structp pp, png_bytep data, size_t size) +{ + buffer_write(get_dp(pp), get_buffer(pp), data, size); +} + +static void +write_png(struct display *dp, png_infop ip, int transforms) +{ + display_clean_write(dp); /* safety */ + + buffer_start_write(&dp->written_file); + dp->operation = "write"; + dp->transforms = transforms; + + dp->write_pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, dp, + display_error, display_warning); + + if (dp->write_pp == NULL) + display_log(dp, APP_ERROR, "failed to create write png_struct"); + + png_set_write_fn(dp->write_pp, &dp->written_file, write_function, + NULL/*flush*/); + +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + /* Remove the user limits, if any */ + png_set_user_limits(dp->write_pp, 0x7fffffff, 0x7fffffff); +# endif + + /* Certain transforms require the png_info to be zapped to allow the + * transform to work correctly. + */ + if (transforms & (PNG_TRANSFORM_PACKING| + PNG_TRANSFORM_STRIP_FILLER| + PNG_TRANSFORM_STRIP_FILLER_BEFORE)) + { + int ct = dp->color_type; + + if (transforms & (PNG_TRANSFORM_STRIP_FILLER| + PNG_TRANSFORM_STRIP_FILLER_BEFORE)) + ct &= ~PNG_COLOR_MASK_ALPHA; + + png_set_IHDR(dp->write_pp, ip, dp->width, dp->height, dp->bit_depth, ct, + dp->interlace_method, dp->compression_method, dp->filter_method); + } + + png_write_png(dp->write_pp, ip, transforms, NULL/*params*/); + + /* Clean it on the way out - if control returns to the caller then the + * written_file contains the required data. + */ + display_clean_write(dp); +} +#endif /* WRITE_PNG */ + +static int +skip_transform(struct display *dp, int tr) + /* Helper to test for a bad combo and log it if it is skipped */ +{ + if ((dp->options & SKIP_BUGS) != 0 && is_bad_combo(tr)) + { + /* Log this to stdout if logging is on, otherwise just do an information + * display_log. + */ + if ((dp->options & LOG_SKIPPED) != 0) + { + printf("SKIP: %s transforms ", dp->filename); + + while (tr != 0) + { + int next = first_transform(tr); + tr &= ~next; + + printf("%s", transform_name(next)); + if (tr != 0) + putchar('+'); + } + + putchar('\n'); + } + + else + display_log(dp, INFORMATION, "%s: skipped known bad combo 0x%x", + dp->filename, tr); + + return 1; /* skip */ + } + + return 0; /* don't skip */ +} + +static void +test_one_file(struct display *dp, const char *filename) +{ + /* First cache the file and update the display original file + * information for the new file. + */ + dp->operation = "cache file"; + dp->transforms = 0; + display_cache_file(dp, filename); + update_display(dp); + + /* First test: if there are options that should be ignored for this file + * verify that they really are ignored. + */ + if (dp->ignored_transforms != 0) + { + read_png(dp, &dp->original_file, "ignored transforms", + dp->ignored_transforms); + + /* The result should be identical to the original_rows */ + if (!compare_read(dp, 0/*transforms applied*/)) + return; /* no point testing more */ + } + +#ifdef PNG_WRITE_PNG_SUPPORTED + /* Second test: write the original PNG data out to a new file (to test the + * write side) then read the result back in and make sure that it hasn't + * changed. + */ + dp->operation = "write"; + write_png(dp, dp->original_ip, 0/*transforms*/); + read_png(dp, &dp->written_file, NULL, 0/*transforms*/); + if (!compare_read(dp, 0/*transforms applied*/)) + return; +#endif + + /* Third test: the active options. Test each in turn, or, with the + * EXHAUSTIVE option, test all possible combinations. + */ + { + /* Use unsigned int here because the code below to increment through all + * the possibilities exhaustively has to use a compare and that must be + * unsigned, because some transforms are negative on a 16-bit system. + */ + unsigned int active = dp->active_transforms; + int exhaustive = (dp->options & EXHAUSTIVE) != 0; + unsigned int current = first_transform(active); + unsigned int bad_transforms = 0; + unsigned int bad_combo = ~0U; /* bitwise AND of failing transforms */ + unsigned int bad_combo_list = 0; /* bitwise OR of failures */ + + for (;;) + { + read_png(dp, &dp->original_file, "active transforms", current); + + /* If this involved any irreversible transformations then if we write + * it out with just the reversible transformations and read it in again + * with the same transforms we should get the same thing. At present + * this isn't done - it just seems like a waste of time and it would + * require two sets of read png_struct/png_info. + * + * If there were no irreversible transformations then if we write it + * out and read it back in again (without the reversible transforms) + * we should get back to the place where we started. + */ +#ifdef PNG_WRITE_PNG_SUPPORTED + if ((current & write_transforms) == current) + { + /* All transforms reversible: write the PNG with the transformations + * reversed, then read it back in with no transformations. The + * result should be the same as the original apart from the loss of + * low order bits because of the SHIFT/sBIT transform. + */ + dp->operation = "reversible transforms"; + write_png(dp, dp->read_ip, current); + + /* And if this is read back in, because all the transformations were + * reversible, the result should be the same. + */ + read_png(dp, &dp->written_file, NULL, 0); + if (!compare_read(dp, current/*for the SHIFT/sBIT transform*/)) + { + /* This set of transforms failed. If a single bit is set - if + * there is just one transform - don't include this in further + * 'exhaustive' tests. Notice that each transform is tested on + * its own before testing combos in the exhaustive case. + */ + if (is_combo(current)) + { + bad_combo &= current; + bad_combo_list |= current; + } + + else + bad_transforms |= current; + } + } +#endif + + /* Now move to the next transform */ + if (exhaustive) /* all combinations */ + { + unsigned int next = current; + + do + { + if (next == read_transforms) /* Everything tested */ + goto combo; + + ++next; + } /* skip known bad combos if the relevant option is set; skip + * combos involving known bad single transforms in all cases. + */ + while ( (next & read_transforms) <= current + || (next & active) == 0 /* skip cases that do nothing */ + || (next & bad_transforms) != 0 + || skip_transform(dp, next)); + + assert((next & read_transforms) == next); + current = next; + } + + else /* one at a time */ + { + active &= ~current; + + if (active == 0) + goto combo; + + current = first_transform(active); + } + } + +combo: + if (dp->options & FIND_BAD_COMBOS) + { + /* bad_combos identifies the combos that occur in all failing cases; + * bad_combo_list identifies transforms that do not prevent the + * failure. + */ + if (bad_combo != ~0U) + printf("%s[0x%x]: PROBLEM: 0x%x[0x%x] ANTIDOTE: 0x%x\n", + dp->filename, active, bad_combo, bad_combo_list, + rw_transforms & ~bad_combo_list); + + else + printf("%s: no %sbad combos found\n", dp->filename, + (dp->options & SKIP_BUGS) ? "additional " : ""); + } + } +} + +static int +do_test(struct display *dp, const char *file) + /* Exists solely to isolate the setjmp clobbers */ +{ + int ret = setjmp(dp->error_return); + + if (ret == 0) + { + test_one_file(dp, file); + return 0; + } + + else if (ret < ERRORS) /* shouldn't longjmp on warnings */ + display_log(dp, INTERNAL_ERROR, "unexpected return code %d", ret); + + return ret; +} + +int +main(int argc, char **argv) +{ + /* For each file on the command line test it with a range of transforms */ + int option_end, ilog = 0; + struct display d; + + validate_T(); + display_init(&d); + + for (option_end=1; option_end QUIET) /* abort on user or internal error */ + return 99; + } + + /* Here on any return, including failures, except user/internal issues + */ + { + int pass = (d.options & STRICT) ? + RESULT_STRICT(d.results) : RESULT_RELAXED(d.results); + + if (!pass) + ++errors; + + if (d.options & LOG) + { + int j; + + printf("%s: pngimage ", pass ? "PASS" : "FAIL"); + + for (j=1; j +#include +#include +#include +#include +#include +#include + +#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) +# include +#endif + +/* Define the following to use this test against your installed libpng, rather + * than the one being built here: + */ +#ifdef PNG_FREESTANDING_TESTS +# include +#else +# include "../../png.h" +#endif + +/* 1.6.1 added support for the configure test harness, which uses 77 to indicate + * a skipped test, in earlier versions we need to succeed on a skipped test, so: + */ +#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H) +# define SKIP 77 +#else +# define SKIP 0 +#endif + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED /* Else nothing can be done */ +#include "../tools/sRGB.h" + +/* KNOWN ISSUES + * + * These defines switch on alternate algorithms for format conversions to match + * the current libpng implementation; they are set to allow pngstest to pass + * even though libpng is producing answers that are not as correct as they + * should be. + */ +#define ALLOW_UNUSED_GPC 0 + /* If true include unused static GPC functions and declare an external array + * of them to hide the fact that they are unused. This is for development + * use while testing the correct function to use to take into account libpng + * misbehavior, such as using a simple power law to correct sRGB to linear. + */ + +/* The following is to support direct compilation of this file as C++ */ +#ifdef __cplusplus +# define voidcast(type, value) static_cast(value) +# define aligncastconst(type, value) \ + static_cast(static_cast(value)) +#else +# define voidcast(type, value) (value) +# define aligncastconst(type, value) ((const void*)(value)) +#endif /* __cplusplus */ + +/* During parallel runs of pngstest each temporary file needs a unique name, + * this is used to permit uniqueness using a command line argument which can be + * up to 22 characters long. + */ +static char tmpf[23] = "TMP"; + +/* Generate random bytes. This uses a boring repeatable algorithm and it + * is implemented here so that it gives the same set of numbers on every + * architecture. It's a linear congruential generator (Knuth or Sedgewick + * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and + * Hill, "The Art of Electronics". + */ +static void +make_random_bytes(png_uint_32* seed, void* pv, size_t size) +{ + png_uint_32 u0 = seed[0], u1 = seed[1]; + png_bytep bytes = voidcast(png_bytep, pv); + + /* There are thirty three bits, the next bit in the sequence is bit-33 XOR + * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. + */ + size_t i; + for (i=0; i> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; + u1 <<= 8; + u1 |= u0 >> 24; + u0 <<= 8; + u0 |= u; + *bytes++ = (png_byte)u; + } + + seed[0] = u0; + seed[1] = u1; +} + +static png_uint_32 color_seed[2]; + +static void +reseed(void) +{ + color_seed[0] = 0x12345678U; + color_seed[1] = 0x9abcdefU; +} + +static void +random_color(png_colorp color) +{ + make_random_bytes(color_seed, color, sizeof *color); +} + +/* Math support - neither Cygwin nor Visual Studio have C99 support and we need + * a predictable rounding function, so make one here: + */ +static double +closestinteger(double x) +{ + return floor(x + .5); +} + +/* Cast support: remove GCC whines. */ +static png_byte +u8d(double d) +{ + d = closestinteger(d); + return (png_byte)d; +} + +static png_uint_16 +u16d(double d) +{ + d = closestinteger(d); + return (png_uint_16)d; +} + +/* sRGB support: use exact calculations rounded to the nearest int, see the + * fesetround() call in main(). sRGB_to_d optimizes the 8 to 16-bit conversion. + */ +static double sRGB_to_d[256]; +static double g22_to_d[256]; + +static void +init_sRGB_to_d(void) +{ + int i; + + sRGB_to_d[0] = 0; + for (i=1; i<255; ++i) + sRGB_to_d[i] = linear_from_sRGB(i/255.); + sRGB_to_d[255] = 1; + + g22_to_d[0] = 0; + for (i=1; i<255; ++i) + g22_to_d[i] = pow(i/255., 1/.45455); + g22_to_d[255] = 1; +} + +static png_byte +sRGB(double linear /*range 0.0 .. 1.0*/) +{ + return u8d(255 * sRGB_from_linear(linear)); +} + +static png_byte +isRGB(int fixed_linear) +{ + return sRGB(fixed_linear / 65535.); +} + +#if 0 /* not used */ +static png_byte +unpremultiply(int component, int alpha) +{ + if (alpha <= component) + return 255; /* Arbitrary, but consistent with the libpng code */ + + else if (alpha >= 65535) + return isRGB(component); + + else + return sRGB((double)component / alpha); +} +#endif + +static png_uint_16 +ilinear(int fixed_srgb) +{ + return u16d(65535 * sRGB_to_d[fixed_srgb]); +} + +static png_uint_16 +ilineara(int fixed_srgb, int alpha) +{ + return u16d((257 * alpha) * sRGB_to_d[fixed_srgb]); +} + +static png_uint_16 +ilinear_g22(int fixed_srgb) +{ + return u16d(65535 * g22_to_d[fixed_srgb]); +} + +#if ALLOW_UNUSED_GPC +static png_uint_16 +ilineara_g22(int fixed_srgb, int alpha) +{ + return u16d((257 * alpha) * g22_to_d[fixed_srgb]); +} +#endif + +static double +YfromRGBint(int ir, int ig, int ib) +{ + double r = ir; + double g = ig; + double b = ib; + return YfromRGB(r, g, b); +} + +#if 0 /* unused */ +/* The error that results from using a 2.2 power law in place of the correct + * sRGB transform, given an 8-bit value which might be either sRGB or power-law. + */ +static int +power_law_error8(int value) +{ + if (value > 0 && value < 255) + { + double vd = value / 255.; + double e = fabs( + pow(sRGB_to_d[value], 1/2.2) - sRGB_from_linear(pow(vd, 2.2))); + + /* Always allow an extra 1 here for rounding errors */ + e = 1+floor(255 * e); + return (int)e; + } + + return 0; +} + +static int error_in_sRGB_roundtrip = 56; /* by experiment */ +static int +power_law_error16(int value) +{ + if (value > 0 && value < 65535) + { + /* Round trip the value through an 8-bit representation but using + * non-matching to/from conversions. + */ + double vd = value / 65535.; + double e = fabs( + pow(sRGB_from_linear(vd), 2.2) - linear_from_sRGB(pow(vd, 1/2.2))); + + /* Always allow an extra 1 here for rounding errors */ + e = error_in_sRGB_roundtrip+floor(65535 * e); + return (int)e; + } + + return 0; +} + +static int +compare_8bit(int v1, int v2, int error_limit, int multiple_algorithms) +{ + int e = abs(v1-v2); + int ev1, ev2; + + if (e <= error_limit) + return 1; + + if (!multiple_algorithms) + return 0; + + ev1 = power_law_error8(v1); + if (e <= ev1) + return 1; + + ev2 = power_law_error8(v2); + if (e <= ev2) + return 1; + + return 0; +} + +static int +compare_16bit(int v1, int v2, int error_limit, int multiple_algorithms) +{ + int e = abs(v1-v2); + int ev1, ev2; + + if (e <= error_limit) + return 1; + + /* "multiple_algorithms" in this case means that a color-map has been + * involved somewhere, so we can deduce that the values were forced to 8-bit + * (like the via_linear case for 8-bit.) + */ + if (!multiple_algorithms) + return 0; + + ev1 = power_law_error16(v1); + if (e <= ev1) + return 1; + + ev2 = power_law_error16(v2); + if (e <= ev2) + return 1; + + return 0; +} +#endif /* unused */ + +#define USE_FILE 1 /* else memory */ +#define USE_STDIO 2 /* else use file name */ +#define STRICT 4 /* fail on warnings too */ +#define VERBOSE 8 +#define KEEP_TMPFILES 16 /* else delete temporary files */ +#define KEEP_GOING 32 +#define ACCUMULATE 64 +#define FAST_WRITE 128 +#define sRGB_16BIT 256 +#define NO_RESEED 512 /* do not reseed on each new file */ +#define GBG_ERROR 1024 /* do not ignore the gamma+background_rgb_to_gray + * libpng warning. */ + +static void +print_opts(png_uint_32 opts) +{ + if (opts & USE_FILE) + printf(" --file"); + if (opts & USE_STDIO) + printf(" --stdio"); + if (!(opts & STRICT)) + printf(" --nostrict"); + if (opts & VERBOSE) + printf(" --verbose"); + if (opts & KEEP_TMPFILES) + printf(" --preserve"); + if (opts & KEEP_GOING) + printf(" --keep-going"); + if (opts & ACCUMULATE) + printf(" --accumulate"); + if (!(opts & FAST_WRITE)) /* --fast is currently the default */ + printf(" --slow"); + if (opts & sRGB_16BIT) + printf(" --sRGB-16bit"); + if (opts & NO_RESEED) + printf(" --noreseed"); +#if PNG_LIBPNG_VER < 10700 /* else on by default */ + if (opts & GBG_ERROR) + printf(" --fault-gbg-warning"); +#endif +} + +#define FORMAT_NO_CHANGE 0x80000000 /* additional flag */ + +/* A name table for all the formats - defines the format of the '+' arguments to + * pngstest. + */ +#define FORMAT_COUNT 64 +#define FORMAT_MASK 0x3f +static const char * const format_names[FORMAT_COUNT] = +{ + "sRGB-gray", + "sRGB-gray+alpha", + "sRGB-rgb", + "sRGB-rgb+alpha", + "linear-gray", + "linear-gray+alpha", + "linear-rgb", + "linear-rgb+alpha", + + "color-mapped-sRGB-gray", + "color-mapped-sRGB-gray+alpha", + "color-mapped-sRGB-rgb", + "color-mapped-sRGB-rgb+alpha", + "color-mapped-linear-gray", + "color-mapped-linear-gray+alpha", + "color-mapped-linear-rgb", + "color-mapped-linear-rgb+alpha", + + "sRGB-gray", + "sRGB-gray+alpha", + "sRGB-bgr", + "sRGB-bgr+alpha", + "linear-gray", + "linear-gray+alpha", + "linear-bgr", + "linear-bgr+alpha", + + "color-mapped-sRGB-gray", + "color-mapped-sRGB-gray+alpha", + "color-mapped-sRGB-bgr", + "color-mapped-sRGB-bgr+alpha", + "color-mapped-linear-gray", + "color-mapped-linear-gray+alpha", + "color-mapped-linear-bgr", + "color-mapped-linear-bgr+alpha", + + "sRGB-gray", + "alpha+sRGB-gray", + "sRGB-rgb", + "alpha+sRGB-rgb", + "linear-gray", + "alpha+linear-gray", + "linear-rgb", + "alpha+linear-rgb", + + "color-mapped-sRGB-gray", + "color-mapped-alpha+sRGB-gray", + "color-mapped-sRGB-rgb", + "color-mapped-alpha+sRGB-rgb", + "color-mapped-linear-gray", + "color-mapped-alpha+linear-gray", + "color-mapped-linear-rgb", + "color-mapped-alpha+linear-rgb", + + "sRGB-gray", + "alpha+sRGB-gray", + "sRGB-bgr", + "alpha+sRGB-bgr", + "linear-gray", + "alpha+linear-gray", + "linear-bgr", + "alpha+linear-bgr", + + "color-mapped-sRGB-gray", + "color-mapped-alpha+sRGB-gray", + "color-mapped-sRGB-bgr", + "color-mapped-alpha+sRGB-bgr", + "color-mapped-linear-gray", + "color-mapped-alpha+linear-gray", + "color-mapped-linear-bgr", + "color-mapped-alpha+linear-bgr", +}; + +/* Decode an argument to a format number. */ +static png_uint_32 +formatof(const char *arg) +{ + char *ep; + unsigned long format = strtoul(arg, &ep, 0); + + if (ep > arg && *ep == 0 && format < FORMAT_COUNT) + return (png_uint_32)format; + + else for (format=0; format < FORMAT_COUNT; ++format) + { + if (strcmp(format_names[format], arg) == 0) + return (png_uint_32)format; + } + + fprintf(stderr, "pngstest: format name '%s' invalid\n", arg); + return FORMAT_COUNT; +} + +/* Bitset/test functions for formats */ +#define FORMAT_SET_COUNT (FORMAT_COUNT / 32) +typedef struct +{ + png_uint_32 bits[FORMAT_SET_COUNT]; +} +format_list; + +static void format_init(format_list *pf) +{ + int i; + for (i=0; ibits[i] = 0; /* All off */ +} + +#if 0 /* currently unused */ +static void format_clear(format_list *pf) +{ + int i; + for (i=0; ibits[i] = 0; +} +#endif + +static int format_is_initial(format_list *pf) +{ + int i; + for (i=0; ibits[i] != 0) + return 0; + + return 1; +} + +static int format_set(format_list *pf, png_uint_32 format) +{ + if (format < FORMAT_COUNT) + return pf->bits[format >> 5] |= ((png_uint_32)1) << (format & 31); + + return 0; +} + +#if 0 /* currently unused */ +static int format_unset(format_list *pf, png_uint_32 format) +{ + if (format < FORMAT_COUNT) + return pf->bits[format >> 5] &= ~((png_uint_32)1) << (format & 31); + + return 0; +} +#endif + +static int format_isset(format_list *pf, png_uint_32 format) +{ + return format < FORMAT_COUNT && + (pf->bits[format >> 5] & (((png_uint_32)1) << (format & 31))) != 0; +} + +static void format_default(format_list *pf, int redundant) +{ + if (redundant) + { + int i; + + /* set everything, including flags that are pointless */ + for (i=0; ibits[i] = ~(png_uint_32)0; + } + + else + { + png_uint_32 f; + + for (f=0; finput_file != NULL) + rewind(image->input_file); +} + +/* Free the image buffer; the buffer is re-used on a re-read, this is just for + * cleanup. + */ +static void +freebuffer(Image *image) +{ + if (image->buffer) free(image->buffer); + image->buffer = NULL; + image->bufsize = 0; + image->allocsize = 0; +} + +/* Delete function; cleans out all the allocated data and the temporary file in + * the image. + */ +static void +freeimage(Image *image) +{ + freebuffer(image); + png_image_free(&image->image); + + if (image->input_file != NULL) + { + fclose(image->input_file); + image->input_file = NULL; + } + + if (image->input_memory != NULL) + { + free(image->input_memory); + image->input_memory = NULL; + image->input_memory_size = 0; + } + + if (image->tmpfile_name[0] != 0 && (image->opts & KEEP_TMPFILES) == 0) + { + (void)remove(image->tmpfile_name); + image->tmpfile_name[0] = 0; + } +} + +/* This is actually a re-initializer; allows an image structure to be re-used by + * freeing everything that relates to an old image. + */ +static void initimage(Image *image, png_uint_32 opts, const char *file_name, + int stride_extra) +{ + freeimage(image); + memset(&image->image, 0, sizeof image->image); + image->opts = opts; + image->file_name = file_name; + image->stride_extra = stride_extra; +} + +/* Make sure the image buffer is big enough; allows re-use of the buffer if the + * image is re-read. + */ +#define BUFFER_INIT8 73 +static void +allocbuffer(Image *image) +{ + size_t size = PNG_IMAGE_BUFFER_SIZE(image->image, image->stride); + + if (size+32 > image->bufsize) + { + freebuffer(image); + image->buffer = voidcast(png_bytep, malloc(size+32)); + if (image->buffer == NULL) + { + fflush(stdout); + fprintf(stderr, + "simpletest: out of memory allocating %lu(+32) byte buffer\n", + (unsigned long)size); + exit(1); + } + image->bufsize = size+32; + } + + memset(image->buffer, 95, image->bufsize); + memset(image->buffer+16, BUFFER_INIT8, size); + image->allocsize = size; +} + +/* Make sure 16 bytes match the given byte. */ +static int +check16(png_const_bytep bp, int b) +{ + int i = 16; + + do + if (*bp != b) return 1; + while (--i); + + return 0; +} + +/* Check for overwrite in the image buffer. */ +static void +checkbuffer(Image *image, const char *arg) +{ + if (check16(image->buffer, 95)) + { + fflush(stdout); + fprintf(stderr, "%s: overwrite at start of image buffer\n", arg); + exit(1); + } + + if (check16(image->buffer+16+image->allocsize, 95)) + { + fflush(stdout); + fprintf(stderr, "%s: overwrite at end of image buffer\n", arg); + exit(1); + } +} + +/* ERROR HANDLING */ +/* Log a terminal error, also frees the libpng part of the image if necessary. + */ +static int +logerror(Image *image, const char *a1, const char *a2, const char *a3) +{ + fflush(stdout); + if (image->image.warning_or_error) + fprintf(stderr, "%s%s%s: %s\n", a1, a2, a3, image->image.message); + + else + fprintf(stderr, "%s%s%s\n", a1, a2, a3); + + if (image->image.opaque != NULL) + { + fprintf(stderr, "%s: image opaque pointer non-NULL on error\n", + image->file_name); + png_image_free(&image->image); + } + + return 0; +} + +/* Log an error and close a file (just a utility to do both things in one + * function call.) + */ +static int +logclose(Image *image, FILE *f, const char *name, const char *operation) +{ + int e = errno; + + fclose(f); + return logerror(image, name, operation, strerror(e)); +} + +/* Make sure the png_image has been freed - validates that libpng is doing what + * the spec says and freeing the image. + */ +static int +checkopaque(Image *image) +{ + if (image->image.opaque != NULL) + { + png_image_free(&image->image); + return logerror(image, image->file_name, ": opaque not NULL", ""); + } + + /* Separate out the gamma+background_rgb_to_gray warning because it may + * produce opaque component errors: + */ + else if (image->image.warning_or_error != 0 && + (strcmp(image->image.message, + "libpng does not support gamma+background+rgb_to_gray") == 0 ? + (image->opts & GBG_ERROR) != 0 : (image->opts & STRICT) != 0)) + return logerror(image, image->file_name, (image->opts & GBG_ERROR) != 0 ? + " --fault-gbg-warning" : " --strict", ""); + + else + return 1; +} + +/* IMAGE COMPARISON/CHECKING */ +/* Compare the pixels of two images, which should be the same but aren't. The + * images must have been checked for a size match. + */ +typedef struct +{ + /* The components, for grayscale images the gray value is in 'g' and if alpha + * is not present 'a' is set to 255 or 65535 according to format. + */ + int r, g, b, a; +} Pixel; + +typedef struct +{ + /* The background as the original sRGB 8-bit value converted to the final + * integer format and as a double precision linear value in the range 0..1 + * for with partially transparent pixels. + */ + int ir, ig, ib; + double dr, dg, db; /* linear r,g,b scaled to 0..1 */ +} Background; + +/* Basic image formats; control the data but not the layout thereof. */ +#define BASE_FORMATS\ + (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_LINEAR) + +/* Read a Pixel from a buffer. The code below stores the correct routine for + * the format in a function pointer, these are the routines: + */ +static void +gp_g8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = p->g = p->b = pp[0]; + p->a = 255; +} + +static void +gp_ga8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = p->g = p->b = pp[0]; + p->a = pp[1]; +} + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +static void +gp_ag8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = p->g = p->b = pp[1]; + p->a = pp[0]; +} +#endif + +static void +gp_rgb8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = pp[0]; + p->g = pp[1]; + p->b = pp[2]; + p->a = 255; +} + +#ifdef PNG_FORMAT_BGR_SUPPORTED +static void +gp_bgr8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = pp[2]; + p->g = pp[1]; + p->b = pp[0]; + p->a = 255; +} +#endif + +static void +gp_rgba8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = pp[0]; + p->g = pp[1]; + p->b = pp[2]; + p->a = pp[3]; +} + +#ifdef PNG_FORMAT_BGR_SUPPORTED +static void +gp_bgra8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = pp[2]; + p->g = pp[1]; + p->b = pp[0]; + p->a = pp[3]; +} +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +static void +gp_argb8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = pp[1]; + p->g = pp[2]; + p->b = pp[3]; + p->a = pp[0]; +} +#endif + +#if defined(PNG_FORMAT_AFIRST_SUPPORTED) && defined(PNG_FORMAT_BGR_SUPPORTED) +static void +gp_abgr8(Pixel *p, png_const_voidp pb) +{ + png_const_bytep pp = voidcast(png_const_bytep, pb); + + p->r = pp[3]; + p->g = pp[2]; + p->b = pp[1]; + p->a = pp[0]; +} +#endif + +static void +gp_g16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = p->g = p->b = pp[0]; + p->a = 65535; +} + +static void +gp_ga16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = p->g = p->b = pp[0]; + p->a = pp[1]; +} + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +static void +gp_ag16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = p->g = p->b = pp[1]; + p->a = pp[0]; +} +#endif + +static void +gp_rgb16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = pp[0]; + p->g = pp[1]; + p->b = pp[2]; + p->a = 65535; +} + +#ifdef PNG_FORMAT_BGR_SUPPORTED +static void +gp_bgr16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = pp[2]; + p->g = pp[1]; + p->b = pp[0]; + p->a = 65535; +} +#endif + +static void +gp_rgba16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = pp[0]; + p->g = pp[1]; + p->b = pp[2]; + p->a = pp[3]; +} + +#ifdef PNG_FORMAT_BGR_SUPPORTED +static void +gp_bgra16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = pp[2]; + p->g = pp[1]; + p->b = pp[0]; + p->a = pp[3]; +} +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +static void +gp_argb16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = pp[1]; + p->g = pp[2]; + p->b = pp[3]; + p->a = pp[0]; +} +#endif + +#if defined(PNG_FORMAT_AFIRST_SUPPORTED) && defined(PNG_FORMAT_BGR_SUPPORTED) +static void +gp_abgr16(Pixel *p, png_const_voidp pb) +{ + png_const_uint_16p pp = voidcast(png_const_uint_16p, pb); + + p->r = pp[3]; + p->g = pp[2]; + p->b = pp[1]; + p->a = pp[0]; +} +#endif + +/* Given a format, return the correct one of the above functions. */ +static void (* +get_pixel(png_uint_32 format))(Pixel *p, png_const_voidp pb) +{ + /* The color-map flag is irrelevant here - the caller of the function + * returned must either pass the buffer or, for a color-mapped image, the + * correct entry in the color-map. + */ + if (format & PNG_FORMAT_FLAG_LINEAR) + { + if (format & PNG_FORMAT_FLAG_COLOR) + { +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (format & PNG_FORMAT_FLAG_BGR) + { + if (format & PNG_FORMAT_FLAG_ALPHA) + { +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + return gp_abgr16; + + else +# endif + return gp_bgra16; + } + + else + return gp_bgr16; + } + + else +# endif + { + if (format & PNG_FORMAT_FLAG_ALPHA) + { +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + return gp_argb16; + + else +# endif + return gp_rgba16; + } + + else + return gp_rgb16; + } + } + + else + { + if (format & PNG_FORMAT_FLAG_ALPHA) + { +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + return gp_ag16; + + else +# endif + return gp_ga16; + } + + else + return gp_g16; + } + } + + else + { + if (format & PNG_FORMAT_FLAG_COLOR) + { +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (format & PNG_FORMAT_FLAG_BGR) + { + if (format & PNG_FORMAT_FLAG_ALPHA) + { +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + return gp_abgr8; + + else +# endif + return gp_bgra8; + } + + else + return gp_bgr8; + } + + else +# endif + { + if (format & PNG_FORMAT_FLAG_ALPHA) + { +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + return gp_argb8; + + else +# endif + return gp_rgba8; + } + + else + return gp_rgb8; + } + } + + else + { + if (format & PNG_FORMAT_FLAG_ALPHA) + { +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + return gp_ag8; + + else +# endif + return gp_ga8; + } + + else + return gp_g8; + } + } +} + +/* Conversion between pixel formats. The code above effectively eliminates the + * component ordering changes leaving three basic changes: + * + * 1) Remove an alpha channel by pre-multiplication or compositing on a + * background color. (Adding an alpha channel is a no-op.) + * + * 2) Remove color by mapping to grayscale. (Grayscale to color is a no-op.) + * + * 3) Convert between 8-bit and 16-bit components. (Both directtions are + * relevant.) + * + * This gives the following base format conversion matrix: + * + * OUT: ----- 8-bit ----- ----- 16-bit ----- + * IN G GA RGB RGBA G GA RGB RGBA + * 8 G . . . . lin lin lin lin + * 8 GA bckg . bckc . pre' pre pre' pre + * 8 RGB g8 g8 . . glin glin lin lin + * 8 RGBA g8b g8 bckc . gpr' gpre pre' pre + * 16 G sRGB sRGB sRGB sRGB . . . . + * 16 GA b16g unpg b16c unpc A . A . + * 16 RGB sG sG sRGB sRGB g16 g16 . . + * 16 RGBA gb16 sGp cb16 sCp g16 g16' A . + * + * 8-bit to 8-bit: + * bckg: composite on gray background + * bckc: composite on color background + * g8: convert sRGB components to sRGB grayscale + * g8b: convert sRGB components to grayscale and composite on gray background + * + * 8-bit to 16-bit: + * lin: make sRGB components linear, alpha := 65535 + * pre: make sRGB components linear and premultiply by alpha (scale alpha) + * pre': as 'pre' but alpha := 65535 + * glin: make sRGB components linear, convert to grayscale, alpha := 65535 + * gpre: make sRGB components grayscale and linear and premultiply by alpha + * gpr': as 'gpre' but alpha := 65535 + * + * 16-bit to 8-bit: + * sRGB: convert linear components to sRGB, alpha := 255 + * unpg: unpremultiply gray component and convert to sRGB (scale alpha) + * unpc: unpremultiply color components and convert to sRGB (scale alpha) + * b16g: composite linear onto gray background and convert the result to sRGB + * b16c: composite linear onto color background and convert the result to sRGB + * sG: convert linear RGB to sRGB grayscale + * sGp: unpremultiply RGB then convert to sRGB grayscale + * sCp: unpremultiply RGB then convert to sRGB + * gb16: composite linear onto background and convert to sRGB grayscale + * (order doesn't matter, the composite and grayscale operations permute) + * cb16: composite linear onto background and convert to sRGB + * + * 16-bit to 16-bit: + * A: set alpha to 65535 + * g16: convert linear RGB to linear grayscale (alpha := 65535) + * g16': as 'g16' but alpha is unchanged + */ +/* Simple copy: */ +static void +gpc_noop(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + out->r = in->r; + out->g = in->g; + out->b = in->b; + out->a = in->a; +} + +#if ALLOW_UNUSED_GPC +static void +gpc_nop8(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + if (in->a == 0) + out->r = out->g = out->b = 255; + + else + { + out->r = in->r; + out->g = in->g; + out->b = in->b; + } + + out->a = in->a; +} +#endif + +#if ALLOW_UNUSED_GPC +static void +gpc_nop6(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + if (in->a == 0) + out->r = out->g = out->b = 65535; + + else + { + out->r = in->r; + out->g = in->g; + out->b = in->b; + } + + out->a = in->a; +} +#endif + +/* 8-bit to 8-bit conversions */ +/* bckg: composite on gray background */ +static void +gpc_bckg(Pixel *out, const Pixel *in, const Background *back) +{ + if (in->a <= 0) + out->r = out->g = out->b = back->ig; + + else if (in->a >= 255) + out->r = out->g = out->b = in->g; + + else + { + double a = in->a / 255.; + + out->r = out->g = out->b = sRGB(sRGB_to_d[in->g] * a + back->dg * (1-a)); + } + + out->a = 255; +} + +/* bckc: composite on color background */ +static void +gpc_bckc(Pixel *out, const Pixel *in, const Background *back) +{ + if (in->a <= 0) + { + out->r = back->ir; + out->g = back->ig; + out->b = back->ib; + } + + else if (in->a >= 255) + { + out->r = in->r; + out->g = in->g; + out->b = in->b; + } + + else + { + double a = in->a / 255.; + + out->r = sRGB(sRGB_to_d[in->r] * a + back->dr * (1-a)); + out->g = sRGB(sRGB_to_d[in->g] * a + back->dg * (1-a)); + out->b = sRGB(sRGB_to_d[in->b] * a + back->db * (1-a)); + } + + out->a = 255; +} + +/* g8: convert sRGB components to sRGB grayscale */ +static void +gpc_g8(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->r == in->g && in->g == in->b) + out->r = out->g = out->b = in->g; + + else + out->r = out->g = out->b = + sRGB(YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); + + out->a = in->a; +} + +/* g8b: convert sRGB components to grayscale and composite on gray background */ +static void +gpc_g8b(Pixel *out, const Pixel *in, const Background *back) +{ + if (in->a <= 0) + out->r = out->g = out->b = back->ig; + + else if (in->a >= 255) + { + if (in->r == in->g && in->g == in->b) + out->r = out->g = out->b = in->g; + + else + out->r = out->g = out->b = sRGB(YfromRGB( + sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); + } + + else + { + double a = in->a/255.; + + out->r = out->g = out->b = sRGB(a * YfromRGB(sRGB_to_d[in->r], + sRGB_to_d[in->g], sRGB_to_d[in->b]) + back->dg * (1-a)); + } + + out->a = 255; +} + +/* 8-bit to 16-bit conversions */ +/* lin: make sRGB components linear, alpha := 65535 */ +static void +gpc_lin(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + out->r = ilinear(in->r); + + if (in->g == in->r) + { + out->g = out->r; + + if (in->b == in->r) + out->b = out->r; + + else + out->b = ilinear(in->b); + } + + else + { + out->g = ilinear(in->g); + + if (in->b == in->r) + out->b = out->r; + + else if (in->b == in->g) + out->b = out->g; + + else + out->b = ilinear(in->b); + } + + out->a = 65535; +} + +/* pre: make sRGB components linear and premultiply by alpha (scale alpha) */ +static void +gpc_pre(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + out->r = ilineara(in->r, in->a); + + if (in->g == in->r) + { + out->g = out->r; + + if (in->b == in->r) + out->b = out->r; + + else + out->b = ilineara(in->b, in->a); + } + + else + { + out->g = ilineara(in->g, in->a); + + if (in->b == in->r) + out->b = out->r; + + else if (in->b == in->g) + out->b = out->g; + + else + out->b = ilineara(in->b, in->a); + } + + out->a = in->a * 257; +} + +/* pre': as 'pre' but alpha := 65535 */ +static void +gpc_preq(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + out->r = ilineara(in->r, in->a); + + if (in->g == in->r) + { + out->g = out->r; + + if (in->b == in->r) + out->b = out->r; + + else + out->b = ilineara(in->b, in->a); + } + + else + { + out->g = ilineara(in->g, in->a); + + if (in->b == in->r) + out->b = out->r; + + else if (in->b == in->g) + out->b = out->g; + + else + out->b = ilineara(in->b, in->a); + } + + out->a = 65535; +} + +/* glin: make sRGB components linear, convert to grayscale, alpha := 65535 */ +static void +gpc_glin(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->r == in->g && in->g == in->b) + out->r = out->g = out->b = ilinear(in->g); + + else + out->r = out->g = out->b = u16d(65535 * + YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); + + out->a = 65535; +} + +/* gpre: make sRGB components grayscale and linear and premultiply by alpha */ +static void +gpc_gpre(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->r == in->g && in->g == in->b) + out->r = out->g = out->b = ilineara(in->g, in->a); + + else + out->r = out->g = out->b = u16d(in->a * 257 * + YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); + + out->a = 257 * in->a; +} + +/* gpr': as 'gpre' but alpha := 65535 */ +static void +gpc_gprq(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->r == in->g && in->g == in->b) + out->r = out->g = out->b = ilineara(in->g, in->a); + + else + out->r = out->g = out->b = u16d(in->a * 257 * + YfromRGB(sRGB_to_d[in->r], sRGB_to_d[in->g], sRGB_to_d[in->b])); + + out->a = 65535; +} + +/* 8-bit to 16-bit conversions for gAMA 45455 encoded values */ +/* Lin: make gAMA 45455 components linear, alpha := 65535 */ +static void +gpc_Lin(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + out->r = ilinear_g22(in->r); + + if (in->g == in->r) + { + out->g = out->r; + + if (in->b == in->r) + out->b = out->r; + + else + out->b = ilinear_g22(in->b); + } + + else + { + out->g = ilinear_g22(in->g); + + if (in->b == in->r) + out->b = out->r; + + else if (in->b == in->g) + out->b = out->g; + + else + out->b = ilinear_g22(in->b); + } + + out->a = 65535; +} + +#if ALLOW_UNUSED_GPC +/* Pre: make gAMA 45455 components linear and premultiply by alpha (scale alpha) + */ +static void +gpc_Pre(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + out->r = ilineara_g22(in->r, in->a); + + if (in->g == in->r) + { + out->g = out->r; + + if (in->b == in->r) + out->b = out->r; + + else + out->b = ilineara_g22(in->b, in->a); + } + + else + { + out->g = ilineara_g22(in->g, in->a); + + if (in->b == in->r) + out->b = out->r; + + else if (in->b == in->g) + out->b = out->g; + + else + out->b = ilineara_g22(in->b, in->a); + } + + out->a = in->a * 257; +} +#endif + +#if ALLOW_UNUSED_GPC +/* Pre': as 'Pre' but alpha := 65535 */ +static void +gpc_Preq(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + out->r = ilineara_g22(in->r, in->a); + + if (in->g == in->r) + { + out->g = out->r; + + if (in->b == in->r) + out->b = out->r; + + else + out->b = ilineara_g22(in->b, in->a); + } + + else + { + out->g = ilineara_g22(in->g, in->a); + + if (in->b == in->r) + out->b = out->r; + + else if (in->b == in->g) + out->b = out->g; + + else + out->b = ilineara_g22(in->b, in->a); + } + + out->a = 65535; +} +#endif + +#if ALLOW_UNUSED_GPC +/* Glin: make gAMA 45455 components linear, convert to grayscale, alpha := 65535 + */ +static void +gpc_Glin(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->r == in->g && in->g == in->b) + out->r = out->g = out->b = ilinear_g22(in->g); + + else + out->r = out->g = out->b = u16d(65535 * + YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); + + out->a = 65535; +} +#endif + +#if ALLOW_UNUSED_GPC +/* Gpre: make gAMA 45455 components grayscale and linear and premultiply by + * alpha. + */ +static void +gpc_Gpre(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->r == in->g && in->g == in->b) + out->r = out->g = out->b = ilineara_g22(in->g, in->a); + + else + out->r = out->g = out->b = u16d(in->a * 257 * + YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); + + out->a = 257 * in->a; +} +#endif + +#if ALLOW_UNUSED_GPC +/* Gpr': as 'Gpre' but alpha := 65535 */ +static void +gpc_Gprq(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->r == in->g && in->g == in->b) + out->r = out->g = out->b = ilineara_g22(in->g, in->a); + + else + out->r = out->g = out->b = u16d(in->a * 257 * + YfromRGB(g22_to_d[in->r], g22_to_d[in->g], g22_to_d[in->b])); + + out->a = 65535; +} +#endif + +/* 16-bit to 8-bit conversions */ +/* sRGB: convert linear components to sRGB, alpha := 255 */ +static void +gpc_sRGB(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + out->r = isRGB(in->r); + + if (in->g == in->r) + { + out->g = out->r; + + if (in->b == in->r) + out->b = out->r; + + else + out->b = isRGB(in->b); + } + + else + { + out->g = isRGB(in->g); + + if (in->b == in->r) + out->b = out->r; + + else if (in->b == in->g) + out->b = out->g; + + else + out->b = isRGB(in->b); + } + + out->a = 255; +} + +/* unpg: unpremultiply gray component and convert to sRGB (scale alpha) */ +static void +gpc_unpg(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->a <= 128) + { + out->r = out->g = out->b = 255; + out->a = 0; + } + + else + { + out->r = out->g = out->b = sRGB((double)in->g / in->a); + out->a = u8d(in->a / 257.); + } +} + +/* unpc: unpremultiply color components and convert to sRGB (scale alpha) */ +static void +gpc_unpc(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->a <= 128) + { + out->r = out->g = out->b = 255; + out->a = 0; + } + + else + { + out->r = sRGB((double)in->r / in->a); + out->g = sRGB((double)in->g / in->a); + out->b = sRGB((double)in->b / in->a); + out->a = u8d(in->a / 257.); + } +} + +/* b16g: composite linear onto gray background and convert the result to sRGB */ +static void +gpc_b16g(Pixel *out, const Pixel *in, const Background *back) +{ + if (in->a <= 0) + out->r = out->g = out->b = back->ig; + + else + { + double a = in->a/65535.; + double a1 = 1-a; + + a /= 65535; + out->r = out->g = out->b = sRGB(in->g * a + back->dg * a1); + } + + out->a = 255; +} + +/* b16c: composite linear onto color background and convert the result to sRGB*/ +static void +gpc_b16c(Pixel *out, const Pixel *in, const Background *back) +{ + if (in->a <= 0) + { + out->r = back->ir; + out->g = back->ig; + out->b = back->ib; + } + + else + { + double a = in->a/65535.; + double a1 = 1-a; + + a /= 65535; + out->r = sRGB(in->r * a + back->dr * a1); + out->g = sRGB(in->g * a + back->dg * a1); + out->b = sRGB(in->b * a + back->db * a1); + } + + out->a = 255; +} + +/* sG: convert linear RGB to sRGB grayscale */ +static void +gpc_sG(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + out->r = out->g = out->b = sRGB(YfromRGBint(in->r, in->g, in->b)/65535); + out->a = 255; +} + +/* sGp: unpremultiply RGB then convert to sRGB grayscale */ +static void +gpc_sGp(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->a <= 128) + { + out->r = out->g = out->b = 255; + out->a = 0; + } + + else + { + out->r = out->g = out->b = sRGB(YfromRGBint(in->r, in->g, in->b)/in->a); + out->a = u8d(in->a / 257.); + } +} + +/* sCp: unpremultiply RGB then convert to sRGB */ +static void +gpc_sCp(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + + if (in->a <= 128) + { + out->r = out->g = out->b = 255; + out->a = 0; + } + + else + { + out->r = sRGB((double)in->r / in->a); + out->g = sRGB((double)in->g / in->a); + out->b = sRGB((double)in->b / in->a); + out->a = u8d(in->a / 257.); + } +} + +/* gb16: composite linear onto background and convert to sRGB grayscale */ +/* (order doesn't matter, the composite and grayscale operations permute) */ +static void +gpc_gb16(Pixel *out, const Pixel *in, const Background *back) +{ + if (in->a <= 0) + out->r = out->g = out->b = back->ig; + + else if (in->a >= 65535) + out->r = out->g = out->b = isRGB(in->g); + + else + { + double a = in->a / 65535.; + double a1 = 1-a; + + a /= 65535; + out->r = out->g = out->b = sRGB(in->g * a + back->dg * a1); + } + + out->a = 255; +} + +/* cb16: composite linear onto background and convert to sRGB */ +static void +gpc_cb16(Pixel *out, const Pixel *in, const Background *back) +{ + if (in->a <= 0) + { + out->r = back->ir; + out->g = back->ig; + out->b = back->ib; + } + + else if (in->a >= 65535) + { + out->r = isRGB(in->r); + out->g = isRGB(in->g); + out->b = isRGB(in->b); + } + + else + { + double a = in->a / 65535.; + double a1 = 1-a; + + a /= 65535; + out->r = sRGB(in->r * a + back->dr * a1); + out->g = sRGB(in->g * a + back->dg * a1); + out->b = sRGB(in->b * a + back->db * a1); + } + + out->a = 255; +} + +/* 16-bit to 16-bit conversions */ +/* A: set alpha to 65535 */ +static void +gpc_A(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + out->r = in->r; + out->g = in->g; + out->b = in->b; + out->a = 65535; +} + +/* g16: convert linear RGB to linear grayscale (alpha := 65535) */ +static void +gpc_g16(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + out->r = out->g = out->b = u16d(YfromRGBint(in->r, in->g, in->b)); + out->a = 65535; +} + +/* g16': as 'g16' but alpha is unchanged */ +static void +gpc_g16q(Pixel *out, const Pixel *in, const Background *back) +{ + (void)back; + out->r = out->g = out->b = u16d(YfromRGBint(in->r, in->g, in->b)); + out->a = in->a; +} + +#if ALLOW_UNUSED_GPC +/* Unused functions (to hide them from GCC unused function warnings) */ +void (* const gpc_unused[]) + (Pixel *out, const Pixel *in, const Background *back) = +{ + gpc_Pre, gpc_Preq, gpc_Glin, gpc_Gpre, gpc_Gprq, gpc_nop8, gpc_nop6 +}; +#endif + +/* OUT: ----- 8-bit ----- ----- 16-bit ----- + * IN G GA RGB RGBA G GA RGB RGBA + * 8 G . . . . lin lin lin lin + * 8 GA bckg . bckc . pre' pre pre' pre + * 8 RGB g8 g8 . . glin glin lin lin + * 8 RGBA g8b g8 bckc . gpr' gpre pre' pre + * 16 G sRGB sRGB sRGB sRGB . . . . + * 16 GA b16g unpg b16c unpc A . A . + * 16 RGB sG sG sRGB sRGB g16 g16 . . + * 16 RGBA gb16 sGp cb16 sCp g16 g16' A . + * + * The matrix is held in an array indexed thus: + * + * gpc_fn[out_format & BASE_FORMATS][in_format & BASE_FORMATS]; + */ +/* This will produce a compile time error if the FORMAT_FLAG values don't + * match the above matrix! + */ +#if PNG_FORMAT_FLAG_ALPHA == 1 && PNG_FORMAT_FLAG_COLOR == 2 &&\ + PNG_FORMAT_FLAG_LINEAR == 4 +static void (* const gpc_fn[8/*in*/][8/*out*/]) + (Pixel *out, const Pixel *in, const Background *back) = +{ +/*out: G-8 GA-8 RGB-8 RGBA-8 G-16 GA-16 RGB-16 RGBA-16 */ + {gpc_noop,gpc_noop,gpc_noop,gpc_noop, gpc_Lin, gpc_Lin, gpc_Lin, gpc_Lin }, + {gpc_bckg,gpc_noop,gpc_bckc,gpc_noop, gpc_preq,gpc_pre, gpc_preq,gpc_pre }, + {gpc_g8, gpc_g8, gpc_noop,gpc_noop, gpc_glin,gpc_glin,gpc_lin, gpc_lin }, + {gpc_g8b, gpc_g8, gpc_bckc,gpc_noop, gpc_gprq,gpc_gpre,gpc_preq,gpc_pre }, + {gpc_sRGB,gpc_sRGB,gpc_sRGB,gpc_sRGB, gpc_noop,gpc_noop,gpc_noop,gpc_noop}, + {gpc_b16g,gpc_unpg,gpc_b16c,gpc_unpc, gpc_A, gpc_noop,gpc_A, gpc_noop}, + {gpc_sG, gpc_sG, gpc_sRGB,gpc_sRGB, gpc_g16, gpc_g16, gpc_noop,gpc_noop}, + {gpc_gb16,gpc_sGp, gpc_cb16,gpc_sCp, gpc_g16, gpc_g16q,gpc_A, gpc_noop} +}; + +/* The array is repeated for the cases where both the input and output are color + * mapped because then different algorithms are used. + */ +static void (* const gpc_fn_colormapped[8/*in*/][8/*out*/]) + (Pixel *out, const Pixel *in, const Background *back) = +{ +/*out: G-8 GA-8 RGB-8 RGBA-8 G-16 GA-16 RGB-16 RGBA-16 */ + {gpc_noop,gpc_noop,gpc_noop,gpc_noop, gpc_lin, gpc_lin, gpc_lin, gpc_lin }, + {gpc_bckg,gpc_noop,gpc_bckc,gpc_noop, gpc_preq,gpc_pre, gpc_preq,gpc_pre }, + {gpc_g8, gpc_g8, gpc_noop,gpc_noop, gpc_glin,gpc_glin,gpc_lin, gpc_lin }, + {gpc_g8b, gpc_g8, gpc_bckc,gpc_noop, gpc_gprq,gpc_gpre,gpc_preq,gpc_pre }, + {gpc_sRGB,gpc_sRGB,gpc_sRGB,gpc_sRGB, gpc_noop,gpc_noop,gpc_noop,gpc_noop}, + {gpc_b16g,gpc_unpg,gpc_b16c,gpc_unpc, gpc_A, gpc_noop,gpc_A, gpc_noop}, + {gpc_sG, gpc_sG, gpc_sRGB,gpc_sRGB, gpc_g16, gpc_g16, gpc_noop,gpc_noop}, + {gpc_gb16,gpc_sGp, gpc_cb16,gpc_sCp, gpc_g16, gpc_g16q,gpc_A, gpc_noop} +}; + +/* The error arrays record the error in the same matrix; 64 entries, however + * the different algorithms used in libpng for colormap and direct conversions + * mean that four separate matrices are used (for each combination of + * colormapped and direct.) + * + * In some cases the conversion between sRGB formats goes via a linear + * intermediate; an sRGB to linear conversion (as above) is followed by a simple + * linear to sRGB step with no other conversions. This is done by a separate + * error array from an arbitrary 'in' format to one of the four basic outputs + * (since final output is always sRGB not colormapped). + * + * These arrays may be modified if the --accumulate flag is set during the run; + * then instead of logging errors they are simply added in. + * + * The three entries are currently for transparent, partially transparent and + * opaque input pixel values. Notice that alpha should be exact in each case. + * + * Errors in alpha should only occur when converting from a direct format + * to a colormapped format, when alpha is effectively smashed (so large + * errors can occur.) There should be no error in the '0' and 'opaque' + * values. The fourth entry in the array is used for the alpha error (and it + * should always be zero for the 'via linear' case since this is never color + * mapped.) + * + * Mapping to a colormap smashes the colors, it is necessary to have separate + * values for these cases because they are much larger; it is very much + * impossible to obtain a reasonable result, these are held in + * gpc_error_to_colormap. + */ +#if PNG_FORMAT_FLAG_COLORMAP == 8 /* extra check also required */ +# include "pngstest-errors.h" /* machine generated */ +#endif /* COLORMAP flag check */ +#endif /* flag checks */ + +typedef struct +{ + /* Basic pixel information: */ + Image* in_image; /* Input image */ + const Image* out_image; /* Output image */ + + /* 'background' is the value passed to the gpc_ routines, it may be NULL if + * it should not be used (*this* program has an error if it crashes as a + * result!) + */ + Background background_color; + const Background* background; + + /* Precalculated values: */ + int in_opaque; /* Value of input alpha that is opaque */ + int is_palette; /* Sample values come from the palette */ + int accumulate; /* Accumulate component errors (don't log) */ + int output_8bit; /* Output is 8-bit (else 16-bit) */ + + void (*in_gp)(Pixel*, png_const_voidp); + void (*out_gp)(Pixel*, png_const_voidp); + + void (*transform)(Pixel *out, const Pixel *in, const Background *back); + /* A function to perform the required transform */ + + void (*from_linear)(Pixel *out, const Pixel *in, const Background *back); + /* For 'via_linear' transforms the final, from linear, step, else NULL */ + + png_uint_16 error[4]; + /* Three error values for transparent, partially transparent and opaque + * input pixels (in turn). + */ + + png_uint_16 *error_ptr; + /* Where these are stored in the static array (for 'accumulate') */ +} +Transform; + +/* Return a 'transform' as above for the given format conversion. */ +static void +transform_from_formats(Transform *result, Image *in_image, + const Image *out_image, png_const_colorp background, int via_linear) +{ + png_uint_32 in_format, out_format; + png_uint_32 in_base, out_base; + + memset(result, 0, sizeof *result); + + /* Store the original images for error messages */ + result->in_image = in_image; + result->out_image = out_image; + + in_format = in_image->image.format; + out_format = out_image->image.format; + + if (in_format & PNG_FORMAT_FLAG_LINEAR) + result->in_opaque = 65535; + else + result->in_opaque = 255; + + result->output_8bit = (out_format & PNG_FORMAT_FLAG_LINEAR) == 0; + + result->is_palette = 0; /* set by caller if required */ + result->accumulate = (in_image->opts & ACCUMULATE) != 0; + + /* The loaders (which need the ordering information) */ + result->in_gp = get_pixel(in_format); + result->out_gp = get_pixel(out_format); + + /* Remove the ordering information: */ + in_format &= BASE_FORMATS | PNG_FORMAT_FLAG_COLORMAP; + in_base = in_format & BASE_FORMATS; + out_format &= BASE_FORMATS | PNG_FORMAT_FLAG_COLORMAP; + out_base = out_format & BASE_FORMATS; + + if (via_linear) + { + /* Check for an error in this program: */ + if (out_format & (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLORMAP)) + { + fprintf(stderr, "internal transform via linear error 0x%x->0x%x\n", + in_format, out_format); + exit(1); + } + + result->transform = gpc_fn[in_base][out_base | PNG_FORMAT_FLAG_LINEAR]; + result->from_linear = gpc_fn[out_base | PNG_FORMAT_FLAG_LINEAR][out_base]; + result->error_ptr = gpc_error_via_linear[in_format][out_format]; + } + + else if (~in_format & out_format & PNG_FORMAT_FLAG_COLORMAP) + { + /* The input is not colormapped but the output is, the errors will + * typically be large (only the grayscale-no-alpha case permits preserving + * even 8-bit values.) + */ + result->transform = gpc_fn[in_base][out_base]; + result->from_linear = NULL; + result->error_ptr = gpc_error_to_colormap[in_base][out_base]; + } + + else + { + /* The caller handles the colormap->pixel value conversion, so the + * transform function just gets a pixel value, however because libpng + * currently contains a different implementation for mapping a colormap if + * both input and output are colormapped we need different conversion + * functions to deal with errors in the libpng implementation. + */ + if (in_format & out_format & PNG_FORMAT_FLAG_COLORMAP) + result->transform = gpc_fn_colormapped[in_base][out_base]; + else + result->transform = gpc_fn[in_base][out_base]; + result->from_linear = NULL; + result->error_ptr = gpc_error[in_format][out_format]; + } + + /* Follow the libpng simplified API rules to work out what to pass to the gpc + * routines as a background value, if one is not required pass NULL so that + * this program crashes in the even of a programming error. + */ + result->background = NULL; /* default: not required */ + + /* Rule 1: background only need be supplied if alpha is to be removed */ + if (in_format & ~out_format & PNG_FORMAT_FLAG_ALPHA) + { + /* The input value is 'NULL' to use the background and (otherwise) an sRGB + * background color (to use a solid color). The code above uses a fixed + * byte value, BUFFER_INIT8, for buffer even for 16-bit output. For + * linear (16-bit) output the sRGB background color is ignored; the + * composition is always on the background (so BUFFER_INIT8 * 257), except + * that for the colormap (i.e. linear colormapped output) black is used. + */ + result->background = &result->background_color; + + if (out_format & PNG_FORMAT_FLAG_LINEAR || via_linear) + { + if (out_format & PNG_FORMAT_FLAG_COLORMAP) + { + result->background_color.ir = + result->background_color.ig = + result->background_color.ib = 0; + result->background_color.dr = + result->background_color.dg = + result->background_color.db = 0; + } + + else + { + result->background_color.ir = + result->background_color.ig = + result->background_color.ib = BUFFER_INIT8 * 257; + result->background_color.dr = + result->background_color.dg = + result->background_color.db = 0; + } + } + + else /* sRGB output */ + { + if (background != NULL) + { + if (out_format & PNG_FORMAT_FLAG_COLOR) + { + result->background_color.ir = background->red; + result->background_color.ig = background->green; + result->background_color.ib = background->blue; + /* TODO: sometimes libpng uses the power law conversion here, how + * to handle this? + */ + result->background_color.dr = sRGB_to_d[background->red]; + result->background_color.dg = sRGB_to_d[background->green]; + result->background_color.db = sRGB_to_d[background->blue]; + } + + else /* grayscale: libpng only looks at 'g' */ + { + result->background_color.ir = + result->background_color.ig = + result->background_color.ib = background->green; + /* TODO: sometimes libpng uses the power law conversion here, how + * to handle this? + */ + result->background_color.dr = + result->background_color.dg = + result->background_color.db = sRGB_to_d[background->green]; + } + } + + else if ((out_format & PNG_FORMAT_FLAG_COLORMAP) == 0) + { + result->background_color.ir = + result->background_color.ig = + result->background_color.ib = BUFFER_INIT8; + /* TODO: sometimes libpng uses the power law conversion here, how + * to handle this? + */ + result->background_color.dr = + result->background_color.dg = + result->background_color.db = sRGB_to_d[BUFFER_INIT8]; + } + + /* Else the output is colormapped and a background color must be + * provided; if pngstest crashes then that is a bug in this program + * (though libpng should png_error as well.) + */ + else + result->background = NULL; + } + } + + if (result->background == NULL) + { + result->background_color.ir = + result->background_color.ig = + result->background_color.ib = -1; /* not used */ + result->background_color.dr = + result->background_color.dg = + result->background_color.db = 1E30; /* not used */ + } + + + /* Copy the error values into the Transform: */ + result->error[0] = result->error_ptr[0]; + result->error[1] = result->error_ptr[1]; + result->error[2] = result->error_ptr[2]; + result->error[3] = result->error_ptr[3]; +} + + +/* Compare two pixels. + * + * OLD error values: +static int error_to_linear = 811; * by experiment * +static int error_to_linear_grayscale = 424; * by experiment * +static int error_to_sRGB = 6; * by experiment * +static int error_to_sRGB_grayscale = 17; * libpng error by calculation + + 2 by experiment * +static int error_in_compose = 2; * by experiment * +static int error_in_premultiply = 1; + * + * The following is *just* the result of a round trip from 8-bit sRGB to linear + * then back to 8-bit sRGB when it is done by libpng. There are two problems: + * + * 1) libpng currently uses a 2.2 power law with no linear segment, this results + * in instability in the low values and even with 16-bit precision sRGB(1) ends + * up mapping to sRGB(0) as a result of rounding in the 16-bit representation. + * This gives an error of 1 in the handling of value 1 only. + * + * 2) libpng currently uses an intermediate 8-bit linear value in gamma + * correction of 8-bit values. This results in many more errors, the worse of + * which is mapping sRGB(14) to sRGB(0). + * + * The general 'error_via_linear' is more complex because of pre-multiplication, + * this compounds the 8-bit errors according to the alpha value of the pixel. + * As a result 256 values are pre-calculated for error_via_linear. + */ +#if 0 +static int error_in_libpng_gamma; +static int error_via_linear[256]; /* Indexed by 8-bit alpha */ + +static void +init_error_via_linear(void) +{ + int alpha; + + error_via_linear[0] = 255; /* transparent pixel */ + + for (alpha=1; alpha<=255; ++alpha) + { + /* 16-bit values less than 128.5 get rounded to 8-bit 0 and so the worst + * case error arises with 16-bit 128.5, work out what sRGB + * (non-associated) value generates 128.5; any value less than this is + * going to map to 0, so the worst error is floor(value). + * + * Note that errors are considerably higher (more than a factor of 2) + * because libpng uses a simple power law for sRGB data at present. + * + * Add .1 for arithmetic errors inside libpng. + */ + double v = floor(255*pow(.5/*(128.5 * 255 / 65535)*/ / alpha, 1/2.2)+.1); + + error_via_linear[alpha] = (int)v; + } + + /* This is actually 14.99, but, despite the closeness to 15, 14 seems to work + * ok in this case. + */ + error_in_libpng_gamma = 14; +} +#endif + +static void +print_pixel(char string[64], const Pixel *pixel, png_uint_32 format) +{ + switch (format & (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR)) + { + case 0: + sprintf(string, "%s(%d)", format_names[format], pixel->g); + break; + + case PNG_FORMAT_FLAG_ALPHA: + sprintf(string, "%s(%d,%d)", format_names[format], pixel->g, + pixel->a); + break; + + case PNG_FORMAT_FLAG_COLOR: + sprintf(string, "%s(%d,%d,%d)", format_names[format], + pixel->r, pixel->g, pixel->b); + break; + + case PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA: + sprintf(string, "%s(%d,%d,%d,%d)", format_names[format], + pixel->r, pixel->g, pixel->b, pixel->a); + break; + + default: + sprintf(string, "invalid-format"); + break; + } +} + +static int +logpixel(const Transform *transform, png_uint_32 x, png_uint_32 y, + const Pixel *in, const Pixel *calc, const Pixel *out, const char *reason) +{ + png_uint_32 in_format = transform->in_image->image.format; + png_uint_32 out_format = transform->out_image->image.format; + + png_uint_32 back_format = out_format & ~PNG_FORMAT_FLAG_ALPHA; + const char *via_linear = ""; + + char pixel_in[64], pixel_calc[64], pixel_out[64], pixel_loc[64]; + char background_info[100]; + + print_pixel(pixel_in, in, in_format); + print_pixel(pixel_calc, calc, out_format); + print_pixel(pixel_out, out, out_format); + + if (transform->is_palette) + sprintf(pixel_loc, "palette: %lu", (unsigned long)y); + else + sprintf(pixel_loc, "%lu,%lu", (unsigned long)x, (unsigned long)y); + + if (transform->from_linear != NULL) + { + via_linear = " (via linear)"; + /* And as a result the *read* format which did any background processing + * was itself linear, so the background color information is also + * linear. + */ + back_format |= PNG_FORMAT_FLAG_LINEAR; + } + + if (transform->background != NULL) + { + Pixel back; + char pixel_back[64]; + + back.r = transform->background->ir; + back.g = transform->background->ig; + back.b = transform->background->ib; + back.a = -1; /* not used */ + + print_pixel(pixel_back, &back, back_format); + sprintf(background_info, " on background %s", pixel_back); + } + + else + background_info[0] = 0; + + if (transform->in_image->file_name != transform->out_image->file_name) + { + char error_buffer[512]; + sprintf(error_buffer, + "(%s) %s error%s:\n %s%s ->\n %s\n not: %s.\n" + "Use --preserve and examine: ", pixel_loc, reason, via_linear, + pixel_in, background_info, pixel_out, pixel_calc); + return logerror(transform->in_image, transform->in_image->file_name, + error_buffer, transform->out_image->file_name); + } + + else + { + char error_buffer[512]; + sprintf(error_buffer, + "(%s) %s error%s:\n %s%s ->\n %s\n not: %s.\n" + " The error happened when reading the original file with this format.", + pixel_loc, reason, via_linear, pixel_in, background_info, pixel_out, + pixel_calc); + return logerror(transform->in_image, transform->in_image->file_name, + error_buffer, ""); + } +} + +static int +cmppixel(Transform *transform, png_const_voidp in, png_const_voidp out, + png_uint_32 x, png_uint_32 y/*or palette index*/) +{ + int maxerr; + png_const_charp errmsg; + Pixel pixel_in, pixel_calc, pixel_out; + + transform->in_gp(&pixel_in, in); + + if (transform->from_linear == NULL) + transform->transform(&pixel_calc, &pixel_in, transform->background); + + else + { + transform->transform(&pixel_out, &pixel_in, transform->background); + transform->from_linear(&pixel_calc, &pixel_out, NULL); + } + + transform->out_gp(&pixel_out, out); + + /* Eliminate the case where the input and output values match exactly. */ + if (pixel_calc.a == pixel_out.a && pixel_calc.r == pixel_out.r && + pixel_calc.g == pixel_out.g && pixel_calc.b == pixel_out.b) + return 1; + + /* Eliminate the case where the output pixel is transparent and the output + * is 8-bit - any component values are valid. Don't check the input alpha + * here to also skip the 16-bit small alpha cases. + */ + if (transform->output_8bit && pixel_calc.a == 0 && pixel_out.a == 0) + return 1; + + /* Check for alpha errors first; an alpha error can damage the components too + * so avoid spurious checks on components if one is found. + */ + errmsg = NULL; + { + int err_a = abs(pixel_calc.a-pixel_out.a); + + if (err_a > transform->error[3]) + { + /* If accumulating check the components too */ + if (transform->accumulate) + transform->error[3] = (png_uint_16)err_a; + + else + errmsg = "alpha"; + } + } + + /* Now if *either* of the output alphas are 0 but alpha is within tolerance + * eliminate the 8-bit component comparison. + */ + if (errmsg == NULL && transform->output_8bit && + (pixel_calc.a == 0 || pixel_out.a == 0)) + return 1; + + if (errmsg == NULL) /* else just signal an alpha error */ + { + int err_r = abs(pixel_calc.r - pixel_out.r); + int err_g = abs(pixel_calc.g - pixel_out.g); + int err_b = abs(pixel_calc.b - pixel_out.b); + int limit; + + if ((err_r | err_g | err_b) == 0) + return 1; /* exact match */ + + /* Mismatch on a component, check the input alpha */ + if (pixel_in.a >= transform->in_opaque) + { + errmsg = "opaque component"; + limit = 2; /* opaque */ + } + + else if (pixel_in.a > 0) + { + errmsg = "alpha component"; + limit = 1; /* partially transparent */ + } + + else + { + errmsg = "transparent component (background)"; + limit = 0; /* transparent */ + } + + maxerr = err_r; + if (maxerr < err_g) maxerr = err_g; + if (maxerr < err_b) maxerr = err_b; + + if (maxerr <= transform->error[limit]) + return 1; /* within the error limits */ + + /* Handle a component mis-match; log it, just return an error code, or + * accumulate it. + */ + if (transform->accumulate) + { + transform->error[limit] = (png_uint_16)maxerr; + return 1; /* to cause the caller to keep going */ + } + } + + /* Failure to match and not accumulating, so the error must be logged. */ + return logpixel(transform, x, y, &pixel_in, &pixel_calc, &pixel_out, errmsg); +} + +static png_byte +component_loc(png_byte loc[4], png_uint_32 format) +{ + /* Given a format return the number of channels and the location of + * each channel. + * + * The mask 'loc' contains the component offset of the channels in the + * following order. Note that if 'format' is grayscale the entries 1-3 must + * all contain the location of the gray channel. + * + * 0: alpha + * 1: red or gray + * 2: green or gray + * 3: blue or gray + */ + png_byte channels; + + if (format & PNG_FORMAT_FLAG_COLOR) + { + channels = 3; + + loc[2] = 1; + +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (format & PNG_FORMAT_FLAG_BGR) + { + loc[1] = 2; + loc[3] = 0; + } + + else +# endif + { + loc[1] = 0; + loc[3] = 2; + } + } + + else + { + channels = 1; + loc[1] = loc[2] = loc[3] = 0; + } + + if (format & PNG_FORMAT_FLAG_ALPHA) + { +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + { + loc[0] = 0; + ++loc[1]; + ++loc[2]; + ++loc[3]; + } + + else +# endif + loc[0] = channels; + + ++channels; + } + + else + loc[0] = 4; /* not present */ + + return channels; +} + +/* Compare two images, the original 'a', which was written out then read back in + * to * give image 'b'. The formats may have been changed. + */ +static int +compare_two_images(Image *a, Image *b, int via_linear, + png_const_colorp background) +{ + ptrdiff_t stridea = a->stride; + ptrdiff_t strideb = b->stride; + png_const_bytep rowa = a->buffer+16; + png_const_bytep rowb = b->buffer+16; + png_uint_32 width = a->image.width; + png_uint_32 height = a->image.height; + png_uint_32 formata = a->image.format; + png_uint_32 formatb = b->image.format; + unsigned int a_sample = PNG_IMAGE_SAMPLE_SIZE(formata); + unsigned int b_sample = PNG_IMAGE_SAMPLE_SIZE(formatb); + int alpha_added, alpha_removed; + int bchannels; + png_uint_32 y; + Transform tr; + int btoa[4]={0,0,0,0}; + + /* This should never happen: */ + if (width != b->image.width || height != b->image.height) + return logerror(a, a->file_name, ": width x height changed: ", + b->file_name); + + /* Set up the background and the transform */ + transform_from_formats(&tr, a, b, background, via_linear); + + /* Find the first row and inter-row space. */ + if (!(formata & PNG_FORMAT_FLAG_COLORMAP) && + (formata & PNG_FORMAT_FLAG_LINEAR)) + stridea *= 2; + + if (!(formatb & PNG_FORMAT_FLAG_COLORMAP) && + (formatb & PNG_FORMAT_FLAG_LINEAR)) + strideb *= 2; + + if (stridea < 0) rowa += (height-1) * (-stridea); + if (strideb < 0) rowb += (height-1) * (-strideb); + + /* First shortcut the two colormap case by comparing the image data; if it + * matches then we expect the colormaps to match, although this is not + * absolutely necessary for an image match. If the colormaps fail to match + * then there is a problem in libpng. + */ + if (formata & formatb & PNG_FORMAT_FLAG_COLORMAP) + { + /* Only check colormap entries that actually exist; */ + png_const_bytep ppa, ppb; + int match; + png_byte in_use[256], amax = 0, bmax = 0; + + memset(in_use, 0, sizeof in_use); + + ppa = rowa; + ppb = rowb; + + /* Do this the slow way to accumulate the 'in_use' flags, don't break out + * of the loop until the end; this validates the color-mapped data to + * ensure all pixels are valid color-map indexes. + */ + for (y=0, match=1; y bmax) + bmax = bval; + + if (bval != aval) + match = 0; + + in_use[aval] = 1; + if (aval > amax) + amax = aval; + } + } + + /* If the buffers match then the colormaps must too. */ + if (match) + { + /* Do the color-maps match, entry by entry? Only check the 'in_use' + * entries. An error here should be logged as a color-map error. + */ + png_const_bytep a_cmap = (png_const_bytep)a->colormap; + png_const_bytep b_cmap = (png_const_bytep)b->colormap; + int result = 1; /* match by default */ + + /* This is used in logpixel to get the error message correct. */ + tr.is_palette = 1; + + for (y=0; y<256; ++y, a_cmap += a_sample, b_cmap += b_sample) + if (in_use[y]) + { + /* The colormap entries should be valid, but because libpng doesn't + * do any checking at present the original image may contain invalid + * pixel values. These cause an error here (at present) unless + * accumulating errors in which case the program just ignores them. + */ + if (y >= a->image.colormap_entries) + { + if ((a->opts & ACCUMULATE) == 0) + { + char pindex[9]; + sprintf(pindex, "%lu[%lu]", (unsigned long)y, + (unsigned long)a->image.colormap_entries); + logerror(a, a->file_name, ": bad pixel index: ", pindex); + } + result = 0; + } + + else if (y >= b->image.colormap_entries) + { + if ((b->opts & ACCUMULATE) == 0) + { + char pindex[9]; + sprintf(pindex, "%lu[%lu]", (unsigned long)y, + (unsigned long)b->image.colormap_entries); + logerror(b, b->file_name, ": bad pixel index: ", pindex); + } + result = 0; + } + + /* All the mismatches are logged here; there can only be 256! */ + else if (!cmppixel(&tr, a_cmap, b_cmap, 0, y)) + result = 0; + } + + /* If requested, copy the error values back from the Transform. */ + if (a->opts & ACCUMULATE) + { + tr.error_ptr[0] = tr.error[0]; + tr.error_ptr[1] = tr.error[1]; + tr.error_ptr[2] = tr.error[2]; + tr.error_ptr[3] = tr.error[3]; + result = 1; /* force a continue */ + } + + return result; + } + + /* else the image buffers don't match pixel-wise so compare sample values + * instead, but first validate that the pixel indexes are in range (but + * only if not accumulating, when the error is ignored.) + */ + else if ((a->opts & ACCUMULATE) == 0) + { +# ifdef __GNUC__ +# define BYTE_CHARS 20 /* 2^32: GCC sprintf warning */ +# else +# define BYTE_CHARS 3 /* 2^8: real maximum value */ +# endif + /* Check the original image first, + * TODO: deal with input images with bad pixel values? + */ + if (amax >= a->image.colormap_entries) + { + char pindex[3+2*BYTE_CHARS]; + sprintf(pindex, "%d[%u]", amax, + (png_byte)/*SAFE*/a->image.colormap_entries); + return logerror(a, a->file_name, ": bad pixel index: ", pindex); + } + + else if (bmax >= b->image.colormap_entries) + { + char pindex[3+2*BYTE_CHARS]; + sprintf(pindex, "%d[%u]", bmax, + (png_byte)/*SAFE*/b->image.colormap_entries); + return logerror(b, b->file_name, ": bad pixel index: ", pindex); + } + } + } + + /* We can directly compare pixel values without the need to use the read + * or transform support (i.e. a memory compare) if: + * + * 1) The bit depth has not changed. + * 2) RGB to grayscale has not been done (the reverse is ok; we just compare + * the three RGB values to the original grayscale.) + * 3) An alpha channel has not been removed from an 8-bit format, or the + * 8-bit alpha value of the pixel was 255 (opaque). + * + * If an alpha channel has been *added* then it must have the relevant opaque + * value (255 or 65535). + * + * The fist two the tests (in the order given above) (using the boolean + * equivalence !a && !b == !(a || b)) + */ + if (!(((formata ^ formatb) & PNG_FORMAT_FLAG_LINEAR) | + (formata & (formatb ^ PNG_FORMAT_FLAG_COLOR) & PNG_FORMAT_FLAG_COLOR))) + { + /* Was an alpha channel changed? */ + png_uint_32 alpha_changed = (formata ^ formatb) & PNG_FORMAT_FLAG_ALPHA; + + /* Was an alpha channel removed? (The third test.) If so the direct + * comparison is only possible if the input alpha is opaque. + */ + alpha_removed = (formata & alpha_changed) != 0; + + /* Was an alpha channel added? */ + alpha_added = (formatb & alpha_changed) != 0; + + /* The channels may have been moved between input and output, this finds + * out how, recording the result in the btoa array, which says where in + * 'a' to find each channel of 'b'. If alpha was added then btoa[alpha] + * ends up as 4 (and is not used.) + */ + { + int i; + png_byte aloc[4]; + png_byte bloc[4]; + + /* The following are used only if the formats match, except that + * 'bchannels' is a flag for matching formats. btoa[x] says, for each + * channel in b, where to find the corresponding value in a, for the + * bchannels. achannels may be different for a gray to rgb transform + * (a will be 1 or 2, b will be 3 or 4 channels.) + */ + (void)component_loc(aloc, formata); + bchannels = component_loc(bloc, formatb); + + /* Hence the btoa array. */ + for (i=0; i<4; ++i) if (bloc[i] < 4) + btoa[bloc[i]] = aloc[i]; /* may be '4' for alpha */ + + if (alpha_added) + alpha_added = bloc[0]; /* location of alpha channel in image b */ + + else + alpha_added = 4; /* Won't match an image b channel */ + + if (alpha_removed) + alpha_removed = aloc[0]; /* location of alpha channel in image a */ + + else + alpha_removed = 4; + } + } + + else + { + /* Direct compare is not possible, cancel out all the corresponding local + * variables. + */ + bchannels = 0; + alpha_removed = alpha_added = 4; + btoa[3] = btoa[2] = btoa[1] = btoa[0] = 4; /* 4 == not present */ + } + + for (y=0; ycolormap + a_sample * *ppa++; + else + psa = ppa, ppa += a_sample; + + if (formatb & PNG_FORMAT_FLAG_COLORMAP) + psb = (png_const_bytep)b->colormap + b_sample * *ppb++; + else + psb = ppb, ppb += b_sample; + + /* Do the fast test if possible. */ + if (bchannels) + { + /* Check each 'b' channel against either the corresponding 'a' + * channel or the opaque alpha value, as appropriate. If + * alpha_removed value is set (not 4) then also do this only if the + * 'a' alpha channel (alpha_removed) is opaque; only relevant for + * the 8-bit case. + */ + if (formatb & PNG_FORMAT_FLAG_LINEAR) /* 16-bit checks */ + { + png_const_uint_16p pua = aligncastconst(png_const_uint_16p, psa); + png_const_uint_16p pub = aligncastconst(png_const_uint_16p, psb); + + switch (bchannels) + { + case 4: + if (pua[btoa[3]] != pub[3]) break; + /* FALLTHROUGH */ + case 3: + if (pua[btoa[2]] != pub[2]) break; + /* FALLTHROUGH */ + case 2: + if (pua[btoa[1]] != pub[1]) break; + /* FALLTHROUGH */ + case 1: + if (pua[btoa[0]] != pub[0]) break; + if (alpha_added != 4 && pub[alpha_added] != 65535) break; + continue; /* x loop */ + default: + break; /* impossible */ + } + } + + else if (alpha_removed == 4 || psa[alpha_removed] == 255) + { + switch (bchannels) + { + case 4: + if (psa[btoa[3]] != psb[3]) break; + /* FALLTHROUGH */ + case 3: + if (psa[btoa[2]] != psb[2]) break; + /* FALLTHROUGH */ + case 2: + if (psa[btoa[1]] != psb[1]) break; + /* FALLTHROUGH */ + case 1: + if (psa[btoa[0]] != psb[0]) break; + if (alpha_added != 4 && psb[alpha_added] != 255) break; + continue; /* x loop */ + default: + break; /* impossible */ + } + } + } + + /* If we get to here the fast match failed; do the slow match for this + * pixel. + */ + if (!cmppixel(&tr, psa, psb, x, y) && (a->opts & KEEP_GOING) == 0) + return 0; /* error case */ + } + } + + /* If requested, copy the error values back from the Transform. */ + if (a->opts & ACCUMULATE) + { + tr.error_ptr[0] = tr.error[0]; + tr.error_ptr[1] = tr.error[1]; + tr.error_ptr[2] = tr.error[2]; + tr.error_ptr[3] = tr.error[3]; + } + + return 1; +} + +/* Read the file; how the read gets done depends on which of input_file and + * input_memory have been set. + */ +static int +read_file(Image *image, png_uint_32 format, png_const_colorp background) +{ + memset(&image->image, 0, sizeof image->image); + image->image.version = PNG_IMAGE_VERSION; + + if (image->input_memory != NULL) + { + if (!png_image_begin_read_from_memory(&image->image, image->input_memory, + image->input_memory_size)) + return logerror(image, "memory init: ", image->file_name, ""); + } + +# ifdef PNG_STDIO_SUPPORTED + else if (image->input_file != NULL) + { + if (!png_image_begin_read_from_stdio(&image->image, image->input_file)) + return logerror(image, "stdio init: ", image->file_name, ""); + } + + else + { + if (!png_image_begin_read_from_file(&image->image, image->file_name)) + return logerror(image, "file init: ", image->file_name, ""); + } +# else + else + { + return logerror(image, "unsupported file/stdio init: ", + image->file_name, ""); + } +# endif + + /* This must be set after the begin_read call: */ + if (image->opts & sRGB_16BIT) + image->image.flags |= PNG_IMAGE_FLAG_16BIT_sRGB; + + /* Have an initialized image with all the data we need plus, maybe, an + * allocated file (myfile) or buffer (mybuffer) that need to be freed. + */ + { + int result; + png_uint_32 image_format; + + /* Print both original and output formats. */ + image_format = image->image.format; + + if (image->opts & VERBOSE) + { + printf("%s %lu x %lu %s -> %s", image->file_name, + (unsigned long)image->image.width, + (unsigned long)image->image.height, + format_names[image_format & FORMAT_MASK], + (format & FORMAT_NO_CHANGE) != 0 || image->image.format == format + ? "no change" : format_names[format & FORMAT_MASK]); + + if (background != NULL) + printf(" background(%d,%d,%d)\n", background->red, + background->green, background->blue); + else + printf("\n"); + + fflush(stdout); + } + + /* 'NO_CHANGE' combined with the color-map flag forces the base format + * flags to be set on read to ensure that the original representation is + * not lost in the pass through a colormap format. + */ + if ((format & FORMAT_NO_CHANGE) != 0) + { + if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0 && + (image_format & PNG_FORMAT_FLAG_COLORMAP) != 0) + format = (image_format & ~BASE_FORMATS) | (format & BASE_FORMATS); + + else + format = image_format; + } + + image->image.format = format; + + image->stride = PNG_IMAGE_ROW_STRIDE(image->image) + image->stride_extra; + allocbuffer(image); + + result = png_image_finish_read(&image->image, background, + image->buffer+16, (png_int_32)image->stride, image->colormap); + + checkbuffer(image, image->file_name); + + if (result) + return checkopaque(image); + + else + return logerror(image, image->file_name, ": image read failed", ""); + } +} + +/* Reads from a filename, which must be in image->file_name, but uses + * image->opts to choose the method. The file is always read in its native + * format (the one the simplified API suggests). + */ +static int +read_one_file(Image *image) +{ + if (!(image->opts & USE_FILE) || (image->opts & USE_STDIO)) + { + /* memory or stdio. */ + FILE *f = fopen(image->file_name, "rb"); + + if (f != NULL) + { + if (image->opts & USE_FILE) + image->input_file = f; + + else /* memory */ + { + if (fseek(f, 0, SEEK_END) == 0) + { + long int cb = ftell(f); + + if (cb > 0) + { +#ifndef __COVERITY__ + if ((unsigned long int)cb <= (size_t)~(size_t)0) +#endif + { + png_bytep b = voidcast(png_bytep, malloc((size_t)cb)); + + if (b != NULL) + { + rewind(f); + + if (fread(b, (size_t)cb, 1, f) == 1) + { + fclose(f); + image->input_memory_size = cb; + image->input_memory = b; + } + + else + { + free(b); + return logclose(image, f, image->file_name, + ": read failed: "); + } + } + + else + return logclose(image, f, image->file_name, + ": out of memory: "); + } + + else + return logclose(image, f, image->file_name, + ": file too big for this architecture: "); + /* cb is the length of the file as a (long) and + * this is greater than the maximum amount of + * memory that can be requested from malloc. + */ + } + + else if (cb == 0) + return logclose(image, f, image->file_name, + ": zero length: "); + + else + return logclose(image, f, image->file_name, + ": tell failed: "); + } + + else + return logclose(image, f, image->file_name, ": seek failed: "); + } + } + + else + return logerror(image, image->file_name, ": open failed: ", + strerror(errno)); + } + + return read_file(image, FORMAT_NO_CHANGE, NULL); +} + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +static int +write_one_file(Image *output, Image *image, int convert_to_8bit) +{ + if (image->opts & FAST_WRITE) + image->image.flags |= PNG_IMAGE_FLAG_FAST; + + if (image->opts & USE_STDIO) + { +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#ifndef __COVERITY__ + FILE *f = tmpfile(); +#else + /* Experimental. Coverity says tmpfile() is insecure because it + * generates predictable names. + * + * It is possible to satisfy Coverity by using mkstemp(); however, + * any platform supporting mkstemp() undoubtedly has a secure tmpfile() + * implementation as well, and doesn't need the fix. Note that + * the fix won't work on platforms that don't support mkstemp(). + * + * https://www.securecoding.cert.org/confluence/display/c/ + * FIO21-C.+Do+not+create+temporary+files+in+shared+directories + * says that most historic implementations of tmpfile() provide + * only a limited number of possible temporary file names + * (usually 26) before file names are recycled. That article also + * provides a secure solution that unfortunately depends upon mkstemp(). + */ + char tmpfile[] = "pngstest-XXXXXX"; + int filedes; + FILE *f; + umask(0177); + filedes = mkstemp(tmpfile); + if (filedes < 0) + f = NULL; + else + { + f = fdopen(filedes,"w+"); + /* Hide the filename immediately and ensure that the file does + * not exist after the program ends + */ + (void) unlink(tmpfile); + } +#endif + + if (f != NULL) + { + if (png_image_write_to_stdio(&image->image, f, convert_to_8bit, + image->buffer+16, (png_int_32)image->stride, image->colormap)) + { + if (fflush(f) == 0) + { + rewind(f); + initimage(output, image->opts, "tmpfile", image->stride_extra); + output->input_file = f; + if (!checkopaque(image)) + return 0; + } + + else + return logclose(image, f, "tmpfile", ": flush: "); + } + + else + { + fclose(f); + return logerror(image, "tmpfile", ": write failed", ""); + } + } + + else + return logerror(image, "tmpfile", ": open: ", strerror(errno)); +#else /* SIMPLIFIED_WRITE_STDIO */ + return logerror(image, "tmpfile", ": open: unsupported", ""); +#endif /* SIMPLIFIED_WRITE_STDIO */ + } + + else if (image->opts & USE_FILE) + { +#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED + static int counter = 0; + char name[32]; + + sprintf(name, "%s%d.png", tmpf, ++counter); + + if (png_image_write_to_file(&image->image, name, convert_to_8bit, + image->buffer+16, (png_int_32)image->stride, image->colormap)) + { + initimage(output, image->opts, output->tmpfile_name, + image->stride_extra); + /* Afterwards, or freeimage will delete it! */ + strcpy(output->tmpfile_name, name); + + if (!checkopaque(image)) + return 0; + } + + else + return logerror(image, name, ": write failed", ""); +#else /* SIMPLIFIED_WRITE_STDIO */ + return logerror(image, "stdio", ": open: unsupported", ""); +#endif /* SIMPLIFIED_WRITE_STDIO */ + } + + else /* use memory */ + { + png_alloc_size_t size; + + if (png_image_write_get_memory_size(image->image, size, convert_to_8bit, + image->buffer+16, (png_int_32)image->stride, image->colormap)) + { + /* This is non-fatal but ignoring it was causing serious problems in + * the macro to be ignored: + */ + if (size > PNG_IMAGE_PNG_SIZE_MAX(image->image)) + return logerror(image, "memory", ": PNG_IMAGE_SIZE_MAX wrong", ""); + + initimage(output, image->opts, "memory", image->stride_extra); + output->input_memory = malloc(size); + + if (output->input_memory != NULL) + { + output->input_memory_size = size; + + if (png_image_write_to_memory(&image->image, output->input_memory, + &output->input_memory_size, convert_to_8bit, image->buffer+16, + (png_int_32)image->stride, image->colormap)) + { + /* This is also non-fatal but it safes safer to error out anyway: + */ + if (size != output->input_memory_size) + return logerror(image, "memory", ": memory size wrong", ""); + } + + else + return logerror(image, "memory", ": write failed", ""); + } + + else + return logerror(image, "memory", ": out of memory", ""); + } + + else + return logerror(image, "memory", ": get size:", ""); + } + + /* 'output' has an initialized temporary image, read this back in and compare + * this against the original: there should be no change since the original + * format was written unmodified unless 'convert_to_8bit' was specified. + * However, if the original image was color-mapped, a simple read will zap + * the linear, color and maybe alpha flags, this will cause spurious failures + * under some circumstances. + */ + if (read_file(output, image->image.format | FORMAT_NO_CHANGE, NULL)) + { + png_uint_32 original_format = image->image.format; + + if (convert_to_8bit) + original_format &= ~PNG_FORMAT_FLAG_LINEAR; + + if ((output->image.format & BASE_FORMATS) != + (original_format & BASE_FORMATS)) + return logerror(image, image->file_name, ": format changed on read: ", + output->file_name); + + return compare_two_images(image, output, 0/*via linear*/, NULL); + } + + else + return logerror(output, output->tmpfile_name, + ": read of new file failed", ""); +} +#endif + +static int +testimage(Image *image, png_uint_32 opts, format_list *pf) +{ + int result; + Image copy; + + /* Copy the original data, stealing it from 'image' */ + checkopaque(image); + copy = *image; + + copy.opts = opts; + copy.buffer = NULL; + copy.bufsize = 0; + copy.allocsize = 0; + + image->input_file = NULL; + image->input_memory = NULL; + image->input_memory_size = 0; + image->tmpfile_name[0] = 0; + + { + png_uint_32 counter; + Image output; + + newimage(&output); + + result = 1; + + /* Use the low bit of 'counter' to indicate whether or not to do alpha + * removal with a background color or by composting onto the image; this + * step gets skipped if it isn't relevant + */ + for (counter=0; counter<2*FORMAT_COUNT; ++counter) + if (format_isset(pf, counter >> 1)) + { + png_uint_32 format = counter >> 1; + + png_color background_color; + png_colorp background = NULL; + + /* If there is a format change that removes the alpha channel then + * the background is relevant. If the output is 8-bit color-mapped + * then a background color *must* be provided, otherwise there are + * two tests to do - one with a color, the other with NULL. The + * NULL test happens second. + */ + if ((counter & 1) == 0) + { + if ((format & PNG_FORMAT_FLAG_ALPHA) == 0 && + (image->image.format & PNG_FORMAT_FLAG_ALPHA) != 0) + { + /* Alpha/transparency will be removed, the background is + * relevant: make it a color the first time + */ + random_color(&background_color); + background = &background_color; + + /* BUT if the output is to a color-mapped 8-bit format then + * the background must always be a color, so increment 'counter' + * to skip the NULL test. + */ + if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0 && + (format & PNG_FORMAT_FLAG_LINEAR) == 0) + ++counter; + } + + /* Otherwise an alpha channel is not being eliminated, just leave + * background NULL and skip the (counter & 1) NULL test. + */ + else + ++counter; + } + /* else just use NULL for background */ + + resetimage(©); + copy.opts = opts; /* in case read_file needs to change it */ + + result = read_file(©, format, background); + if (!result) + break; + + /* Make sure the file just read matches the original file. */ + result = compare_two_images(image, ©, 0/*via linear*/, background); + if (!result) + break; + +# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED + /* Write the *copy* just made to a new file to make sure the write + * side works ok. Check the conversion to sRGB if the copy is + * linear. + */ + output.opts = opts; + result = write_one_file(&output, ©, 0/*convert to 8bit*/); + if (!result) + break; + + /* Validate against the original too; the background is needed here + * as well so that compare_two_images knows what color was used. + */ + result = compare_two_images(image, &output, 0, background); + if (!result) + break; + + if ((format & PNG_FORMAT_FLAG_LINEAR) != 0 && + (format & PNG_FORMAT_FLAG_COLORMAP) == 0) + { + /* 'output' is linear, convert to the corresponding sRGB format. + */ + output.opts = opts; + result = write_one_file(&output, ©, 1/*convert to 8bit*/); + if (!result) + break; + + /* This may involve a conversion via linear; in the ideal world + * this would round-trip correctly, but libpng 1.5.7 is not the + * ideal world so allow a drift (error_via_linear). + * + * 'image' has an alpha channel but 'output' does not then there + * will a strip-alpha-channel operation (because 'output' is + * linear), handle this by composing on black when doing the + * comparison. + */ + result = compare_two_images(image, &output, 1/*via_linear*/, + background); + if (!result) + break; + } +# endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */ + } + + freeimage(&output); + } + + freeimage(©); + + return result; +} + +static int +test_one_file(const char *file_name, format_list *formats, png_uint_32 opts, + int stride_extra, int log_pass) +{ + int result; + Image image; + + if (!(opts & NO_RESEED)) + reseed(); /* ensure that the random numbers don't depend on file order */ + newimage(&image); + initimage(&image, opts, file_name, stride_extra); + result = read_one_file(&image); + if (result) + result = testimage(&image, opts, formats); + freeimage(&image); + + /* Ensure that stderr is flushed into any log file */ + fflush(stderr); + + if (log_pass) + { + if (result) + printf("PASS:"); + + else + printf("FAIL:"); + +# ifndef PNG_SIMPLIFIED_WRITE_SUPPORTED + printf(" (no write)"); +# endif + + print_opts(opts); + printf(" %s\n", file_name); + /* stdout may not be line-buffered if it is piped to a file, so: */ + fflush(stdout); + } + + else if (!result) + exit(1); + + return result; +} + +int +main(int argc, char **argv) +{ + png_uint_32 opts = FAST_WRITE | STRICT; + format_list formats; + const char *touch = NULL; + int log_pass = 0; + int redundant = 0; + int stride_extra = 0; + int retval = 0; + int c; + +#if PNG_LIBPNG_VER >= 10700 + /* This error should not exist in 1.7 or later: */ + opts |= GBG_ERROR; +#endif + + init_sRGB_to_d(); +#if 0 + init_error_via_linear(); +#endif + format_init(&formats); + reseed(); /* initialize random number seeds */ + + for (c=1; c= sizeof tmpf) + { + fflush(stdout); + fprintf(stderr, "%s: %s is too long for a temp file prefix\n", + argv[0], argv[c]); + exit(99); + } + + /* Safe: checked above */ + strncpy(tmpf, argv[c], sizeof (tmpf)-1); + } + + else + { + fflush(stdout); + fprintf(stderr, "%s: %s requires a temporary file prefix\n", + argv[0], arg); + exit(99); + } + } + else if (strcmp(arg, "--touch") == 0) + { + if (c+1 < argc) + touch = argv[++c]; + + else + { + fflush(stdout); + fprintf(stderr, "%s: %s requires a file name argument\n", + argv[0], arg); + exit(99); + } + } + else if (arg[0] == '+') + { + png_uint_32 format = formatof(arg+1); + + if (format > FORMAT_COUNT) + exit(99); + + format_set(&formats, format); + } + else if (arg[0] == '-' && arg[1] != 0 && (arg[1] != '0' || arg[2] != 0)) + { + fflush(stdout); + fprintf(stderr, "%s: unknown option: %s\n", argv[0], arg); + exit(99); + } + else + { + if (format_is_initial(&formats)) + format_default(&formats, redundant); + + if (arg[0] == '-') + { + int term = (arg[1] == '0' ? 0 : '\n'); + unsigned int ich = 0; + + /* Loop reading files, use a static buffer to simplify this and just + * stop if the name gets to long. + */ + static char buffer[4096]; + + do + { + int ch = getchar(); + + /* Don't allow '\0' in file names, and terminate with '\n' or, + * for -0, just '\0' (use -print0 to find to make this work!) + */ + if (ch == EOF || ch == term || ch == 0) + { + buffer[ich] = 0; + + if (ich > 0 && !test_one_file(buffer, &formats, opts, + stride_extra, log_pass)) + retval = 1; + + if (ch == EOF) + break; + + ich = 0; + --ich; /* so that the increment below sets it to 0 again */ + } + + else + buffer[ich] = (char)ch; + } while (++ich < sizeof buffer); + + if (ich) + { + buffer[32] = 0; + buffer[4095] = 0; + fprintf(stderr, "%s...%s: file name too long\n", buffer, + buffer+(4096-32)); + exit(99); + } + } + + else if (!test_one_file(arg, &formats, opts, stride_extra, log_pass)) + retval = 1; + } + } + + if (opts & ACCUMULATE) + { + unsigned int in; + + printf("/* contrib/libtests/pngstest-errors.h\n"); + printf(" *\n"); + printf(" * BUILT USING:" PNG_HEADER_VERSION_STRING); + printf(" *\n"); + printf(" * This code is released under the libpng license.\n"); + printf(" * For conditions of distribution and use, see the disclaimer\n"); + printf(" * and license in png.h\n"); + printf(" *\n"); + printf(" * THIS IS A MACHINE GENERATED FILE: do not edit it directly!\n"); + printf(" * Instead run:\n"); + printf(" *\n"); + printf(" * pngstest --accumulate\n"); + printf(" *\n"); + printf(" * on as many PNG files as possible; at least PNGSuite and\n"); + printf(" * contrib/libtests/testpngs.\n"); + printf(" */\n"); + + printf("static png_uint_16 gpc_error[16/*in*/][16/*out*/][4/*a*/] =\n"); + printf("{\n"); + for (in=0; in<16; ++in) + { + unsigned int out; + printf(" { /* input: %s */\n ", format_names[in]); + for (out=0; out<16; ++out) + { + unsigned int alpha; + printf(" {"); + for (alpha=0; alpha<4; ++alpha) + { + printf(" %d", gpc_error[in][out][alpha]); + if (alpha < 3) putchar(','); + } + printf(" }"); + if (out < 15) + { + putchar(','); + if (out % 4 == 3) printf("\n "); + } + } + printf("\n }"); + + if (in < 15) + putchar(','); + else + putchar('\n'); + } + printf("};\n"); + + printf("static png_uint_16 gpc_error_via_linear[16][4/*out*/][4] =\n"); + printf("{\n"); + for (in=0; in<16; ++in) + { + unsigned int out; + printf(" { /* input: %s */\n ", format_names[in]); + for (out=0; out<4; ++out) + { + unsigned int alpha; + printf(" {"); + for (alpha=0; alpha<4; ++alpha) + { + printf(" %d", gpc_error_via_linear[in][out][alpha]); + if (alpha < 3) putchar(','); + } + printf(" }"); + if (out < 3) + putchar(','); + } + printf("\n }"); + + if (in < 15) + putchar(','); + else + putchar('\n'); + } + printf("};\n"); + + printf("static png_uint_16 gpc_error_to_colormap[8/*i*/][8/*o*/][4] =\n"); + printf("{\n"); + for (in=0; in<8; ++in) + { + unsigned int out; + printf(" { /* input: %s */\n ", format_names[in]); + for (out=0; out<8; ++out) + { + unsigned int alpha; + printf(" {"); + for (alpha=0; alpha<4; ++alpha) + { + printf(" %d", gpc_error_to_colormap[in][out][alpha]); + if (alpha < 3) putchar(','); + } + printf(" }"); + if (out < 7) + { + putchar(','); + if (out % 4 == 3) printf("\n "); + } + } + printf("\n }"); + + if (in < 7) + putchar(','); + else + putchar('\n'); + } + printf("};\n"); + printf("/* END MACHINE GENERATED */\n"); + } + + if (retval == 0 && touch != NULL) + { + FILE *fsuccess = fopen(touch, "wt"); + + if (fsuccess != NULL) + { + int error = 0; + fprintf(fsuccess, "PNG simple API tests succeeded\n"); + fflush(fsuccess); + error = ferror(fsuccess); + + if (fclose(fsuccess) || error) + { + fflush(stdout); + fprintf(stderr, "%s: write failed\n", touch); + exit(99); + } + } + + else + { + fflush(stdout); + fprintf(stderr, "%s: open failed\n", touch); + exit(99); + } + } + + return retval; +} + +#else /* !PNG_SIMPLIFIED_READ_SUPPORTED */ +int main(void) +{ + fprintf(stderr, "pngstest: no read support in libpng, test skipped\n"); + /* So the test is skipped: */ + return SKIP; +} +#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ diff --git a/libs/libpng-src/contrib/libtests/pngunknown.c b/libs/libpng-src/contrib/libtests/pngunknown.c new file mode 100644 index 000000000..05bdd833d --- /dev/null +++ b/libs/libpng-src/contrib/libtests/pngunknown.c @@ -0,0 +1,1294 @@ + +/* pngunknown.c - test the read side unknown chunk handling + * + * Last changed in libpng 1.6.32 [August 24, 2017] + * Copyright (c) 2015,2017 Glenn Randers-Pehrson + * Written by John Cunningham Bowler + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * NOTES: + * This is a C program that is intended to be linked against libpng. It + * allows the libpng unknown handling code to be tested by interpreting + * arguments to save or discard combinations of chunks. The program is + * currently just a minimal validation for the built-in libpng facilities. + */ + +#include +#include +#include +#include + +/* Define the following to use this test against your installed libpng, rather + * than the one being built here: + */ +#ifdef PNG_FREESTANDING_TESTS +# include +#else +# include "../../png.h" +#endif + +/* 1.6.1 added support for the configure test harness, which uses 77 to indicate + * a skipped test, in earlier versions we need to succeed on a skipped test, so: + */ +#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H) +# define SKIP 77 +#else +# define SKIP 0 +#endif + + +/* Since this program tests the ability to change the unknown chunk handling + * these must be defined: + */ +#if defined(PNG_SET_UNKNOWN_CHUNKS_SUPPORTED) &&\ + defined(PNG_STDIO_SUPPORTED) &&\ + defined(PNG_READ_SUPPORTED) + +/* One of these must be defined to allow us to find out what happened. It is + * still useful to set unknown chunk handling without either of these in order + * to cause *known* chunks to be discarded. This can be a significant + * efficiency gain, but it can't really be tested here. + */ +#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) ||\ + defined(PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED) + +#if PNG_LIBPNG_VER < 10500 +/* This deliberately lacks the const. */ +typedef png_byte *png_const_bytep; + +/* This is copied from 1.5.1 png.h: */ +#define PNG_INTERLACE_ADAM7_PASSES 7 +#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ + ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +/* These are needed too for the default build: */ +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED + +/* This comes from pnglibconf.h after 1.5: */ +#define PNG_FP_1 100000 +#define PNG_GAMMA_THRESHOLD_FIXED\ + ((png_fixed_point)(PNG_GAMMA_THRESHOLD * PNG_FP_1)) +#endif + +#if PNG_LIBPNG_VER < 10600 + /* 1.6.0 constifies many APIs. The following exists to allow pngvalid to be + * compiled against earlier versions. + */ +# define png_const_structp png_structp +#endif + +#if PNG_LIBPNG_VER < 10700 + /* Copied from libpng 1.7.0 png.h */ +#define PNG_u2(b1, b2) (((unsigned int)(b1) << 8) + (b2)) + +#define PNG_U16(b1, b2) ((png_uint_16)PNG_u2(b1, b2)) +#define PNG_U32(b1, b2, b3, b4)\ + (((png_uint_32)PNG_u2(b1, b2) << 16) + PNG_u2(b3, b4)) + +/* Constants for known chunk types. + */ +#define png_IDAT PNG_U32( 73, 68, 65, 84) +#define png_IEND PNG_U32( 73, 69, 78, 68) +#define png_IHDR PNG_U32( 73, 72, 68, 82) +#define png_PLTE PNG_U32( 80, 76, 84, 69) +#define png_bKGD PNG_U32( 98, 75, 71, 68) +#define png_cHRM PNG_U32( 99, 72, 82, 77) +#define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */ +#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ +#define png_gAMA PNG_U32(103, 65, 77, 65) +#define png_gIFg PNG_U32(103, 73, 70, 103) +#define png_gIFt PNG_U32(103, 73, 70, 116) /* deprecated */ +#define png_gIFx PNG_U32(103, 73, 70, 120) +#define png_hIST PNG_U32(104, 73, 83, 84) +#define png_iCCP PNG_U32(105, 67, 67, 80) +#define png_iTXt PNG_U32(105, 84, 88, 116) +#define png_oFFs PNG_U32(111, 70, 70, 115) +#define png_pCAL PNG_U32(112, 67, 65, 76) +#define png_pHYs PNG_U32(112, 72, 89, 115) +#define png_sBIT PNG_U32(115, 66, 73, 84) +#define png_sCAL PNG_U32(115, 67, 65, 76) +#define png_sPLT PNG_U32(115, 80, 76, 84) +#define png_sRGB PNG_U32(115, 82, 71, 66) +#define png_sTER PNG_U32(115, 84, 69, 82) +#define png_tEXt PNG_U32(116, 69, 88, 116) +#define png_tIME PNG_U32(116, 73, 77, 69) +#define png_tRNS PNG_U32(116, 82, 78, 83) +#define png_zTXt PNG_U32(122, 84, 88, 116) + +/* Test on flag values as defined in the spec (section 5.4): */ +#define PNG_CHUNK_ANCILLARY(c) (1 & ((c) >> 29)) +#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLARY(c)) +#define PNG_CHUNK_PRIVATE(c) (1 & ((c) >> 21)) +#define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13)) +#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5)) + +#endif /* PNG_LIBPNG_VER < 10700 */ + +#ifdef __cplusplus +# define this not_the_cpp_this +# define new not_the_cpp_new +# define voidcast(type, value) static_cast(value) +#else +# define voidcast(type, value) (value) +#endif /* __cplusplus */ + +/* Unused formal parameter errors are removed using the following macro which is + * expected to have no bad effects on performance. + */ +#ifndef UNUSED +# if defined(__GNUC__) || defined(_MSC_VER) +# define UNUSED(param) (void)param; +# else +# define UNUSED(param) +# endif +#endif + +/* Types of chunks not known to libpng */ +#define png_vpAg PNG_U32(118, 112, 65, 103) + +/* Chunk information */ +#define PNG_INFO_tEXt 0x10000000U +#define PNG_INFO_iTXt 0x20000000U +#define PNG_INFO_zTXt 0x40000000U + +#define PNG_INFO_sTER 0x01000000U +#define PNG_INFO_vpAg 0x02000000U + +#define ABSENT 0 +#define START 1 +#define END 2 + +static struct +{ + char name[5]; + png_uint_32 flag; + png_uint_32 tag; + int unknown; /* Chunk not known to libpng */ + int all; /* Chunk set by the '-1' option */ + int position; /* position in pngtest.png */ + int keep; /* unknown handling setting */ +} chunk_info[] = { + /* Critical chunks */ + { "IDAT", PNG_INFO_IDAT, png_IDAT, 0, 0, START, 0 }, /* must be [0] */ + { "PLTE", PNG_INFO_PLTE, png_PLTE, 0, 0, ABSENT, 0 }, + + /* Non-critical chunks that libpng handles */ + /* This is a mess but it seems to be the only way to do it - there is no way + * to check for a definition outside a #if. + */ + { "bKGD", PNG_INFO_bKGD, png_bKGD, +# ifdef PNG_READ_bKGD_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "cHRM", PNG_INFO_cHRM, png_cHRM, +# ifdef PNG_READ_cHRM_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "eXIf", PNG_INFO_eXIf, png_eXIf, +# ifdef PNG_READ_eXIf_SUPPORTED + 0, +# else + 1, +# endif + 1, END, 0 }, + { "gAMA", PNG_INFO_gAMA, png_gAMA, +# ifdef PNG_READ_gAMA_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "hIST", PNG_INFO_hIST, png_hIST, +# ifdef PNG_READ_hIST_SUPPORTED + 0, +# else + 1, +# endif + 1, ABSENT, 0 }, + { "iCCP", PNG_INFO_iCCP, png_iCCP, +# ifdef PNG_READ_iCCP_SUPPORTED + 0, +# else + 1, +# endif + 1, ABSENT, 0 }, + { "iTXt", PNG_INFO_iTXt, png_iTXt, +# ifdef PNG_READ_iTXt_SUPPORTED + 0, +# else + 1, +# endif + 1, ABSENT, 0 }, + { "oFFs", PNG_INFO_oFFs, png_oFFs, +# ifdef PNG_READ_oFFs_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "pCAL", PNG_INFO_pCAL, png_pCAL, +# ifdef PNG_READ_pCAL_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "pHYs", PNG_INFO_pHYs, png_pHYs, +# ifdef PNG_READ_pHYs_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "sBIT", PNG_INFO_sBIT, png_sBIT, +# ifdef PNG_READ_sBIT_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "sCAL", PNG_INFO_sCAL, png_sCAL, +# ifdef PNG_READ_sCAL_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "sPLT", PNG_INFO_sPLT, png_sPLT, +# ifdef PNG_READ_sPLT_SUPPORTED + 0, +# else + 1, +# endif + 1, ABSENT, 0 }, + { "sRGB", PNG_INFO_sRGB, png_sRGB, +# ifdef PNG_READ_sRGB_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "tEXt", PNG_INFO_tEXt, png_tEXt, +# ifdef PNG_READ_tEXt_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "tIME", PNG_INFO_tIME, png_tIME, +# ifdef PNG_READ_tIME_SUPPORTED + 0, +# else + 1, +# endif + 1, START, 0 }, + { "tRNS", PNG_INFO_tRNS, png_tRNS, +# ifdef PNG_READ_tRNS_SUPPORTED + 0, +# else + 1, +# endif + 0, ABSENT, 0 }, + { "zTXt", PNG_INFO_zTXt, png_zTXt, +# ifdef PNG_READ_zTXt_SUPPORTED + 0, +# else + 1, +# endif + 1, END, 0 }, + + /* No libpng handling */ + { "sTER", PNG_INFO_sTER, png_sTER, 1, 1, START, 0 }, + { "vpAg", PNG_INFO_vpAg, png_vpAg, 1, 0, START, 0 }, +}; + +#define NINFO ((int)((sizeof chunk_info)/(sizeof chunk_info[0]))) + +static void +clear_keep(void) +{ + int i = NINFO; + while (--i >= 0) + chunk_info[i].keep = 0; +} + +static int +find(const char *name) +{ + int i = NINFO; + while (--i >= 0) + { + if (memcmp(chunk_info[i].name, name, 4) == 0) + break; + } + + return i; +} + +static int +findb(const png_byte *name) +{ + int i = NINFO; + while (--i >= 0) + { + if (memcmp(chunk_info[i].name, name, 4) == 0) + break; + } + + return i; +} + +static int +find_by_flag(png_uint_32 flag) +{ + int i = NINFO; + + while (--i >= 0) if (chunk_info[i].flag == flag) return i; + + fprintf(stderr, "pngunknown: internal error\n"); + exit(4); +} + +static int +ancillary(const char *name) +{ + return PNG_CHUNK_ANCILLARY(PNG_U32(name[0], name[1], name[2], name[3])); +} + +#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +static int +ancillaryb(const png_byte *name) +{ + return PNG_CHUNK_ANCILLARY(PNG_U32(name[0], name[1], name[2], name[3])); +} +#endif + +/* Type of an error_ptr */ +typedef struct +{ + jmp_buf error_return; + png_structp png_ptr; + png_infop info_ptr, end_ptr; + png_uint_32 before_IDAT; + png_uint_32 after_IDAT; + int error_count; + int warning_count; + int keep; /* the default value */ + const char *program; + const char *file; + const char *test; +} display; + +static const char init[] = "initialization"; +static const char cmd[] = "command line"; + +static void +init_display(display *d, const char *program) +{ + memset(d, 0, sizeof *d); + d->png_ptr = NULL; + d->info_ptr = d->end_ptr = NULL; + d->error_count = d->warning_count = 0; + d->program = program; + d->file = program; + d->test = init; +} + +static void +clean_display(display *d) +{ + png_destroy_read_struct(&d->png_ptr, &d->info_ptr, &d->end_ptr); + + /* This must not happen - it might cause an app crash */ + if (d->png_ptr != NULL || d->info_ptr != NULL || d->end_ptr != NULL) + { + fprintf(stderr, "%s(%s): png_destroy_read_struct error\n", d->file, + d->test); + exit(1); + } +} + +PNG_FUNCTION(void, display_exit, (display *d), static PNG_NORETURN) +{ + ++(d->error_count); + + if (d->png_ptr != NULL) + clean_display(d); + + /* During initialization and if this is a single command line argument set + * exit now - there is only one test, otherwise longjmp to do the next test. + */ + if (d->test == init || d->test == cmd) + exit(1); + + longjmp(d->error_return, 1); +} + +static int +display_rc(const display *d, int strict) +{ + return d->error_count + (strict ? d->warning_count : 0); +} + +/* libpng error and warning callbacks */ +PNG_FUNCTION(void, (PNGCBAPI error), (png_structp png_ptr, const char *message), + static PNG_NORETURN) +{ + display *d = (display*)png_get_error_ptr(png_ptr); + + fprintf(stderr, "%s(%s): libpng error: %s\n", d->file, d->test, message); + display_exit(d); +} + +static void PNGCBAPI +warning(png_structp png_ptr, const char *message) +{ + display *d = (display*)png_get_error_ptr(png_ptr); + + fprintf(stderr, "%s(%s): libpng warning: %s\n", d->file, d->test, message); + ++(d->warning_count); +} + +static png_uint_32 +get_valid(display *d, png_infop info_ptr) +{ + png_uint_32 flags = png_get_valid(d->png_ptr, info_ptr, (png_uint_32)~0); + + /* Map the text chunks back into the flags */ + { + png_textp text; + png_uint_32 ntext = png_get_text(d->png_ptr, info_ptr, &text, NULL); + + while (ntext > 0) switch (text[--ntext].compression) + { + case -1: + flags |= PNG_INFO_tEXt; + break; + case 0: + flags |= PNG_INFO_zTXt; + break; + case 1: + case 2: + flags |= PNG_INFO_iTXt; + break; + default: + fprintf(stderr, "%s(%s): unknown text compression %d\n", d->file, + d->test, text[ntext].compression); + display_exit(d); + } + } + + return flags; +} + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +static int PNGCBAPI +read_callback(png_structp pp, png_unknown_chunkp pc) +{ + /* This function mimics the behavior of png_set_keep_unknown_chunks by + * returning '0' to keep the chunk and '1' to discard it. + */ + display *d = voidcast(display*, png_get_user_chunk_ptr(pp)); + int chunk = findb(pc->name); + int keep, discard; + + if (chunk < 0) /* not one in our list, so not a known chunk */ + keep = d->keep; + + else + { + keep = chunk_info[chunk].keep; + if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT) + { + /* See the comments in png.h - use the default for unknown chunks, + * do not keep known chunks. + */ + if (chunk_info[chunk].unknown) + keep = d->keep; + + else + keep = PNG_HANDLE_CHUNK_NEVER; + } + } + + switch (keep) + { + default: + fprintf(stderr, "%s(%s): %d: unrecognized chunk option\n", d->file, + d->test, chunk_info[chunk].keep); + display_exit(d); + + case PNG_HANDLE_CHUNK_AS_DEFAULT: + case PNG_HANDLE_CHUNK_NEVER: + discard = 1/*handled; discard*/; + break; + + case PNG_HANDLE_CHUNK_IF_SAFE: + case PNG_HANDLE_CHUNK_ALWAYS: + discard = 0/*not handled; keep*/; + break; + } + + /* Also store information about this chunk in the display, the relevant flag + * is set if the chunk is to be kept ('not handled'.) + */ + if (chunk >= 0) if (!discard) /* stupidity to stop a GCC warning */ + { + png_uint_32 flag = chunk_info[chunk].flag; + + if (pc->location & PNG_AFTER_IDAT) + d->after_IDAT |= flag; + + else + d->before_IDAT |= flag; + } + + /* However if there is no support to store unknown chunks don't ask libpng to + * do it; there will be an png_error. + */ +# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + return discard; +# else + return 1; /*handled; discard*/ +# endif +} +#endif /* READ_USER_CHUNKS_SUPPORTED */ + +#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +static png_uint_32 +get_unknown(display *d, png_infop info_ptr, int after_IDAT) +{ + /* Create corresponding 'unknown' flags */ + png_uint_32 flags = 0; + + UNUSED(after_IDAT) + + { + png_unknown_chunkp unknown; + int num_unknown = png_get_unknown_chunks(d->png_ptr, info_ptr, &unknown); + + while (--num_unknown >= 0) + { + int chunk = findb(unknown[num_unknown].name); + + /* Chunks not known to pngunknown must be validated here; since they + * must also be unknown to libpng the 'display->keep' behavior should + * have been used. + */ + if (chunk < 0) switch (d->keep) + { + default: /* impossible */ + case PNG_HANDLE_CHUNK_AS_DEFAULT: + case PNG_HANDLE_CHUNK_NEVER: + fprintf(stderr, "%s(%s): %s: %s: unknown chunk saved\n", + d->file, d->test, d->keep ? "discard" : "default", + unknown[num_unknown].name); + ++(d->error_count); + break; + + case PNG_HANDLE_CHUNK_IF_SAFE: + if (!ancillaryb(unknown[num_unknown].name)) + { + fprintf(stderr, + "%s(%s): if-safe: %s: unknown critical chunk saved\n", + d->file, d->test, unknown[num_unknown].name); + ++(d->error_count); + break; + } + /* FALLTHROUGH */ /* (safe) */ + case PNG_HANDLE_CHUNK_ALWAYS: + break; + } + + else + flags |= chunk_info[chunk].flag; + } + } + + return flags; +} +#else /* SAVE_UNKNOWN_CHUNKS */ +static png_uint_32 +get_unknown(display *d, png_infop info_ptr, int after_IDAT) + /* Otherwise this will return the cached values set by any user callback */ +{ + UNUSED(info_ptr); + + if (after_IDAT) + return d->after_IDAT; + + else + return d->before_IDAT; +} + +# ifndef PNG_READ_USER_CHUNKS_SUPPORTED + /* The #defines above should mean this is never reached, it's just here as + * a check to ensure the logic is correct. + */ +# error No store support and no user chunk support, this will not work +# endif /* READ_USER_CHUNKS */ +#endif /* SAVE_UNKNOWN_CHUNKS */ + +static int +check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/, + display *d, int set_callback) +{ + int i, npasses, ipass; + png_uint_32 height; + + d->keep = PNG_HANDLE_CHUNK_AS_DEFAULT; + d->before_IDAT = 0; + d->after_IDAT = 0; + + /* Some of these errors are permanently fatal and cause an exit here, others + * are per-test and cause an error return. + */ + d->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, d, error, + warning); + if (d->png_ptr == NULL) + { + fprintf(stderr, "%s(%s): could not allocate png struct\n", d->file, + d->test); + /* Terminate here, this error is not test specific. */ + exit(1); + } + + d->info_ptr = png_create_info_struct(d->png_ptr); + d->end_ptr = png_create_info_struct(d->png_ptr); + if (d->info_ptr == NULL || d->end_ptr == NULL) + { + fprintf(stderr, "%s(%s): could not allocate png info\n", d->file, + d->test); + clean_display(d); + exit(1); + } + + png_init_io(d->png_ptr, fp); + +# ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* This is only done if requested by the caller; it interferes with the + * standard store/save mechanism. + */ + if (set_callback) + png_set_read_user_chunk_fn(d->png_ptr, d, read_callback); +# else + UNUSED(set_callback) +# endif + + /* Handle each argument in turn; multiple settings are possible for the same + * chunk and multiple calls will occur (the last one should override all + * preceding ones). + */ + for (i=0; i= 10700 &&\ + !defined(PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED) + if (option < PNG_HANDLE_CHUNK_IF_SAFE) +# endif /* 1.7+ SAVE_UNKNOWN_CHUNKS */ + { + png_byte name[5]; + + memcpy(name, chunk_info[chunk].name, 5); + png_set_keep_unknown_chunks(d->png_ptr, option, name, 1); + chunk_info[chunk].keep = option; + } + continue; + } + + break; + + case 7: /* default */ + if (memcmp(argv[i], "default", 7) == 0) + { +# if PNG_LIBPNG_VER >= 10700 &&\ + !defined(PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED) + if (option < PNG_HANDLE_CHUNK_IF_SAFE) +# endif /* 1.7+ SAVE_UNKNOWN_CHUNKS */ + png_set_keep_unknown_chunks(d->png_ptr, option, NULL, 0); + + d->keep = option; + continue; + } + + break; + + case 3: /* all */ + if (memcmp(argv[i], "all", 3) == 0) + { +# if PNG_LIBPNG_VER >= 10700 &&\ + !defined(PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED) + if (option < PNG_HANDLE_CHUNK_IF_SAFE) +# endif /* 1.7+ SAVE_UNKNOWN_CHUNKS */ + png_set_keep_unknown_chunks(d->png_ptr, option, NULL, -1); + + d->keep = option; + + for (chunk = 0; chunk < NINFO; ++chunk) + if (chunk_info[chunk].all) + chunk_info[chunk].keep = option; + continue; + } + + break; + + default: /* some misplaced = */ + + break; + } + } + + fprintf(stderr, "%s(%s): %s: unrecognized chunk argument\n", d->file, + d->test, argv[i]); + display_exit(d); + } + + png_read_info(d->png_ptr, d->info_ptr); + + switch (png_get_interlace_type(d->png_ptr, d->info_ptr)) + { + case PNG_INTERLACE_NONE: + npasses = 1; + break; + + case PNG_INTERLACE_ADAM7: + npasses = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + /* Hard error because it is not test specific */ + fprintf(stderr, "%s(%s): invalid interlace type\n", d->file, d->test); + clean_display(d); + exit(1); + } + + /* Skip the image data, if IDAT is not being handled then don't do this + * because it will cause a CRC error. + */ + if (chunk_info[0/*IDAT*/].keep == PNG_HANDLE_CHUNK_AS_DEFAULT) + { + png_start_read_image(d->png_ptr); + height = png_get_image_height(d->png_ptr, d->info_ptr); + + if (npasses > 1) + { + png_uint_32 width = png_get_image_width(d->png_ptr, d->info_ptr); + + for (ipass=0; ipass 0) + { + png_uint_32 y; + + for (y=0; ypng_ptr, NULL, NULL); + } + } + } /* interlaced */ + + else /* not interlaced */ + { + png_uint_32 y; + + for (y=0; ypng_ptr, NULL, NULL); + } + } + + png_read_end(d->png_ptr, d->end_ptr); + + flags[0] = get_valid(d, d->info_ptr); + flags[1] = get_unknown(d, d->info_ptr, 0/*before IDAT*/); + + /* Only png_read_png sets PNG_INFO_IDAT! */ + flags[chunk_info[0/*IDAT*/].keep != PNG_HANDLE_CHUNK_AS_DEFAULT] |= + PNG_INFO_IDAT; + + flags[2] = get_valid(d, d->end_ptr); + flags[3] = get_unknown(d, d->end_ptr, 1/*after IDAT*/); + + clean_display(d); + + return d->keep; +} + +static void +check_error(display *d, png_uint_32 flags, const char *message) +{ + while (flags) + { + png_uint_32 flag = flags & -(png_int_32)flags; + int i = find_by_flag(flag); + + fprintf(stderr, "%s(%s): chunk %s: %s\n", d->file, d->test, + chunk_info[i].name, message); + ++(d->error_count); + + flags &= ~flag; + } +} + +static void +check_handling(display *d, int def, png_uint_32 chunks, png_uint_32 known, + png_uint_32 unknown, const char *position, int set_callback) +{ + while (chunks) + { + png_uint_32 flag = chunks & -(png_int_32)chunks; + int i = find_by_flag(flag); + int keep = chunk_info[i].keep; + const char *type; + const char *errorx = NULL; + + if (chunk_info[i].unknown) + { + if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT) + { + type = "UNKNOWN (default)"; + keep = def; + } + + else + type = "UNKNOWN (specified)"; + + if (flag & known) + errorx = "chunk processed"; + + else switch (keep) + { + case PNG_HANDLE_CHUNK_AS_DEFAULT: + if (flag & unknown) + errorx = "DEFAULT: unknown chunk saved"; + break; + + case PNG_HANDLE_CHUNK_NEVER: + if (flag & unknown) + errorx = "DISCARD: unknown chunk saved"; + break; + + case PNG_HANDLE_CHUNK_IF_SAFE: + if (ancillary(chunk_info[i].name)) + { + if (!(flag & unknown)) + errorx = "IF-SAFE: unknown ancillary chunk lost"; + } + + else if (flag & unknown) + errorx = "IF-SAFE: unknown critical chunk saved"; + break; + + case PNG_HANDLE_CHUNK_ALWAYS: + if (!(flag & unknown)) + errorx = "SAVE: unknown chunk lost"; + break; + + default: + errorx = "internal error: bad keep"; + break; + } + } /* unknown chunk */ + + else /* known chunk */ + { + type = "KNOWN"; + + if (flag & known) + { + /* chunk was processed, it won't have been saved because that is + * caught below when checking for inconsistent processing. + */ + if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT) + errorx = "!DEFAULT: known chunk processed"; + } + + else /* not processed */ switch (keep) + { + case PNG_HANDLE_CHUNK_AS_DEFAULT: + errorx = "DEFAULT: known chunk not processed"; + break; + + case PNG_HANDLE_CHUNK_NEVER: + if (flag & unknown) + errorx = "DISCARD: known chunk saved"; + break; + + case PNG_HANDLE_CHUNK_IF_SAFE: + if (ancillary(chunk_info[i].name)) + { + if (!(flag & unknown)) + errorx = "IF-SAFE: known ancillary chunk lost"; + } + + else if (flag & unknown) + errorx = "IF-SAFE: known critical chunk saved"; + break; + + case PNG_HANDLE_CHUNK_ALWAYS: + if (!(flag & unknown)) + errorx = "SAVE: known chunk lost"; + break; + + default: + errorx = "internal error: bad keep (2)"; + break; + } + } + + if (errorx != NULL) + { + ++(d->error_count); + fprintf(stderr, "%s(%s%s): %s %s %s: %s\n", d->file, d->test, + set_callback ? ",callback" : "", + type, chunk_info[i].name, position, errorx); + } + + chunks &= ~flag; + } +} + +static void +perform_one_test(FILE *fp, int argc, const char **argv, + png_uint_32 *default_flags, display *d, int set_callback) +{ + int def; + png_uint_32 flags[2][4]; + + rewind(fp); + clear_keep(); + memcpy(flags[0], default_flags, sizeof flags[0]); + + def = check(fp, argc, argv, flags[1], d, set_callback); + + /* If IDAT is being handled as unknown the image read is skipped and all the + * IDATs after the first end up in the end info struct, so in this case add + * IDAT to the list of unknowns. (Do this after 'check' above sets the + * chunk_info 'keep' fields.) + * + * Note that the flag setting has to be in the 'known' field to avoid + * triggering the consistency check below and the flag must only be set if + * there are multiple IDATs, so if the check above did find an unknown IDAT + * after IDAT. + */ + if (chunk_info[0/*IDAT*/].keep != PNG_HANDLE_CHUNK_AS_DEFAULT && + (flags[1][3] & PNG_INFO_IDAT) != 0) + flags[0][2] |= PNG_INFO_IDAT; + + /* Chunks should either be known or unknown, never both and this should apply + * whether the chunk is before or after the IDAT (actually, the app can + * probably change this by swapping the handling after the image, but this + * test does not do that.) + */ + check_error(d, (flags[0][0]|flags[0][2]) & (flags[0][1]|flags[0][3]), + "chunk handled inconsistently in count tests"); + check_error(d, (flags[1][0]|flags[1][2]) & (flags[1][1]|flags[1][3]), + "chunk handled inconsistently in option tests"); + + /* Now find out what happened to each chunk before and after the IDAT and + * determine if the behavior was correct. First some basic sanity checks, + * any known chunk should be known in the original count, any unknown chunk + * should be either known or unknown in the original. + */ + { + png_uint_32 test; + + test = flags[1][0] & ~flags[0][0]; + check_error(d, test, "new known chunk before IDAT"); + test = flags[1][1] & ~(flags[0][0] | flags[0][1]); + check_error(d, test, "new unknown chunk before IDAT"); + test = flags[1][2] & ~flags[0][2]; + check_error(d, test, "new known chunk after IDAT"); + test = flags[1][3] & ~(flags[0][2] | flags[0][3]); + check_error(d, test, "new unknown chunk after IDAT"); + } + + /* Now each chunk in the original list should have been handled according to + * the options set for that chunk, regardless of whether libpng knows about + * it or not. + */ + check_handling(d, def, flags[0][0] | flags[0][1], flags[1][0], flags[1][1], + "before IDAT", set_callback); + check_handling(d, def, flags[0][2] | flags[0][3], flags[1][2], flags[1][3], + "after IDAT", set_callback); +} + +static void +perform_one_test_safe(FILE *fp, int argc, const char **argv, + png_uint_32 *default_flags, display *d, const char *test) +{ + if (setjmp(d->error_return) == 0) + { + d->test = test; /* allow use of d->error_return */ +# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + perform_one_test(fp, argc, argv, default_flags, d, 0); +# endif +# ifdef PNG_READ_USER_CHUNKS_SUPPORTED + perform_one_test(fp, argc, argv, default_flags, d, 1); +# endif + d->test = init; /* prevent use of d->error_return */ + } +} + +static const char *standard_tests[] = +{ + "discard", "default=discard", 0, + "save", "default=save", 0, + "if-safe", "default=if-safe", 0, + "vpAg", "vpAg=if-safe", 0, + "sTER", "sTER=if-safe", 0, + "IDAT", "default=discard", "IDAT=save", 0, + "sAPI", "bKGD=save", "cHRM=save", "gAMA=save", "all=discard", "iCCP=save", + "sBIT=save", "sRGB=save", "eXIf=save", 0, + 0/*end*/ +}; + +static PNG_NORETURN void +usage(const char *program, const char *reason) +{ + fprintf(stderr, "pngunknown: %s: usage:\n %s [--strict] " + "--default|{(CHNK|default|all)=(default|discard|if-safe|save)} " + "testfile.png\n", reason, program); + exit(99); +} + +int +main(int argc, const char **argv) +{ + FILE *fp; + png_uint_32 default_flags[4/*valid,unknown{before,after}*/]; + int strict = 0, default_tests = 0; + const char *count_argv = "default=save"; + const char *touch_file = NULL; + display d; + + init_display(&d, argv[0]); + + while (++argv, --argc > 0) + { + if (strcmp(*argv, "--strict") == 0) + strict = 1; + + else if (strcmp(*argv, "--default") == 0) + default_tests = 1; + + else if (strcmp(*argv, "--touch") == 0) + { + if (argc > 1) + touch_file = *++argv, --argc; + + else + usage(d.program, "--touch: missing file name"); + } + + else + break; + } + + /* A file name is required, but there should be no other arguments if + * --default was specified. + */ + if (argc <= 0) + usage(d.program, "missing test file"); + + /* GCC BUG: if (default_tests && argc != 1) triggers some weird GCC argc + * optimization which causes warnings with -Wstrict-overflow! + */ + else if (default_tests) if (argc != 1) + usage(d.program, "extra arguments"); + + /* The name of the test file is the last argument; remove it. */ + d.file = argv[--argc]; + + fp = fopen(d.file, "rb"); + if (fp == NULL) + { + perror(d.file); + exit(99); + } + + /* First find all the chunks, known and unknown, in the test file, a failure + * here aborts the whole test. + * + * If 'save' is supported then the normal saving method should happen, + * otherwise if 'read' is supported then the read callback will do the + * same thing. If both are supported the 'read' callback won't be + * instantiated by default. If 'save' is *not* supported then a user + * callback is required even though we can call png_get_unknown_chunks. + */ + if (check(fp, 1, &count_argv, default_flags, &d, +# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + 0 +# else + 1 +# endif + ) != PNG_HANDLE_CHUNK_ALWAYS) + { + fprintf(stderr, "%s: %s: internal error\n", d.program, d.file); + exit(99); + } + + /* Now find what the various supplied options cause to change: */ + if (!default_tests) + { + d.test = cmd; /* acts as a flag to say exit, do not longjmp */ +# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + perform_one_test(fp, argc, argv, default_flags, &d, 0); +# endif +# ifdef PNG_READ_USER_CHUNKS_SUPPORTED + perform_one_test(fp, argc, argv, default_flags, &d, 1); +# endif + d.test = init; + } + + else + { + const char **test = standard_tests; + + /* Set the exit_test pointer here so we can continue after a libpng error. + * NOTE: this leaks memory because the png_struct data from the failing + * test is never freed. + */ + while (*test) + { + const char *this_test = *test++; + const char **next = test; + int count = display_rc(&d, strict), new_count; + const char *result; + int arg_count = 0; + + while (*next) ++next, ++arg_count; + + perform_one_test_safe(fp, arg_count, test, default_flags, &d, + this_test); + + new_count = display_rc(&d, strict); + + if (new_count == count) + result = "PASS"; + + else + result = "FAIL"; + + printf("%s: %s %s\n", result, d.program, this_test); + + test = next+1; + } + } + + fclose(fp); + + if (display_rc(&d, strict) == 0) + { + /* Success, touch the success file if appropriate */ + if (touch_file != NULL) + { + FILE *fsuccess = fopen(touch_file, "wt"); + + if (fsuccess != NULL) + { + int err = 0; + fprintf(fsuccess, "PNG unknown tests succeeded\n"); + fflush(fsuccess); + err = ferror(fsuccess); + + if (fclose(fsuccess) || err) + { + fprintf(stderr, "%s: write failed\n", touch_file); + exit(99); + } + } + + else + { + fprintf(stderr, "%s: open failed\n", touch_file); + exit(99); + } + } + + return 0; + } + + return 1; +} + +#else /* !(READ_USER_CHUNKS || SAVE_UNKNOWN_CHUNKS) */ +int +main(void) +{ + fprintf(stderr, + " test ignored: no support to find out about unknown chunks\n"); + /* So the test is skipped: */ + return SKIP; +} +#endif /* READ_USER_CHUNKS || SAVE_UNKNOWN_CHUNKS */ + +#else /* !(SET_UNKNOWN_CHUNKS && READ) */ +int +main(void) +{ + fprintf(stderr, + " test ignored: no support to modify unknown chunk handling\n"); + /* So the test is skipped: */ + return SKIP; +} +#endif /* SET_UNKNOWN_CHUNKS && READ*/ diff --git a/libs/libpng-src/contrib/libtests/pngvalid.c b/libs/libpng-src/contrib/libtests/pngvalid.c new file mode 100644 index 000000000..d800110c7 --- /dev/null +++ b/libs/libpng-src/contrib/libtests/pngvalid.c @@ -0,0 +1,12230 @@ + +/* pngvalid.c - validate libpng by constructing then reading png files. + * + * Last changed in libpng 1.6.31 [July 27, 2017] + * Copyright (c) 2014-2017 John Cunningham Bowler + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * NOTES: + * This is a C program that is intended to be linked against libpng. It + * generates bitmaps internally, stores them as PNG files (using the + * sequential write code) then reads them back (using the sequential + * read code) and validates that the result has the correct data. + * + * The program can be modified and extended to test the correctness of + * transformations performed by libpng. + */ + +#define _POSIX_SOURCE 1 +#define _ISOC99_SOURCE 1 /* For floating point */ +#define _GNU_SOURCE 1 /* For the floating point exception extension */ +#define _BSD_SOURCE 1 /* For the floating point exception extension */ + +#include +#include + +#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) +# include +#endif + +#ifdef HAVE_FEENABLEEXCEPT /* from config.h, if included */ +# include +#endif + +#ifndef FE_DIVBYZERO +# define FE_DIVBYZERO 0 +#endif +#ifndef FE_INVALID +# define FE_INVALID 0 +#endif +#ifndef FE_OVERFLOW +# define FE_OVERFLOW 0 +#endif + +/* Define the following to use this test against your installed libpng, rather + * than the one being built here: + */ +#ifdef PNG_FREESTANDING_TESTS +# include +#else +# include "../../png.h" +#endif + +#ifdef PNG_ZLIB_HEADER +# include PNG_ZLIB_HEADER +#else +# include /* For crc32 */ +#endif + +/* 1.6.1 added support for the configure test harness, which uses 77 to indicate + * a skipped test, in earlier versions we need to succeed on a skipped test, so: + */ +#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H) +# define SKIP 77 +#else +# define SKIP 0 +#endif + +/* pngvalid requires write support and one of the fixed or floating point APIs. + */ +#if defined(PNG_WRITE_SUPPORTED) &&\ + (defined(PNG_FIXED_POINT_SUPPORTED) || defined(PNG_FLOATING_POINT_SUPPORTED)) + +#if PNG_LIBPNG_VER < 10500 +/* This deliberately lacks the const. */ +typedef png_byte *png_const_bytep; + +/* This is copied from 1.5.1 png.h: */ +#define PNG_INTERLACE_ADAM7_PASSES 7 +#define PNG_PASS_START_ROW(pass) (((1U&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1U& (pass))<<(3-(((pass)+1)>>1)))&7) +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<>PNG_PASS_COL_SHIFT(pass)) +#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \ + (((yIn)<>(((7-(off))-(pass))<<2)) & 0xFU) | \ + ((0x01145AF0U>>(((7-(off))-(pass))<<2)) & 0xF0U)) +#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \ + ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1) +#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ + ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) + +/* These are needed too for the default build: */ +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED + +/* This comes from pnglibconf.h after 1.5: */ +#define PNG_FP_1 100000 +#define PNG_GAMMA_THRESHOLD_FIXED\ + ((png_fixed_point)(PNG_GAMMA_THRESHOLD * PNG_FP_1)) +#endif + +#if PNG_LIBPNG_VER < 10600 + /* 1.6.0 constifies many APIs, the following exists to allow pngvalid to be + * compiled against earlier versions. + */ +# define png_const_structp png_structp +#endif + +#ifndef RELEASE_BUILD + /* RELEASE_BUILD is true for releases and release candidates: */ +# define RELEASE_BUILD (PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC) +#endif +#if RELEASE_BUILD +# define debugonly(something) +#else /* !RELEASE_BUILD */ +# define debugonly(something) something +#endif /* !RELEASE_BUILD */ + +#include /* For floating point constants */ +#include /* For malloc */ +#include /* For memcpy, memset */ +#include /* For floor */ + +/* Convenience macros. */ +#define CHUNK(a,b,c,d) (((a)<<24)+((b)<<16)+((c)<<8)+(d)) +#define CHUNK_IHDR CHUNK(73,72,68,82) +#define CHUNK_PLTE CHUNK(80,76,84,69) +#define CHUNK_IDAT CHUNK(73,68,65,84) +#define CHUNK_IEND CHUNK(73,69,78,68) +#define CHUNK_cHRM CHUNK(99,72,82,77) +#define CHUNK_gAMA CHUNK(103,65,77,65) +#define CHUNK_sBIT CHUNK(115,66,73,84) +#define CHUNK_sRGB CHUNK(115,82,71,66) + +/* Unused formal parameter errors are removed using the following macro which is + * expected to have no bad effects on performance. + */ +#ifndef UNUSED +# if defined(__GNUC__) || defined(_MSC_VER) +# define UNUSED(param) (void)param; +# else +# define UNUSED(param) +# endif +#endif + +/***************************** EXCEPTION HANDLING *****************************/ +#ifdef PNG_FREESTANDING_TESTS +# include +#else +# include "../visupng/cexcept.h" +#endif + +#ifdef __cplusplus +# define this not_the_cpp_this +# define new not_the_cpp_new +# define voidcast(type, value) static_cast(value) +#else +# define voidcast(type, value) (value) +#endif /* __cplusplus */ + +struct png_store; +define_exception_type(struct png_store*); + +/* The following are macros to reduce typing everywhere where the well known + * name 'the_exception_context' must be defined. + */ +#define anon_context(ps) struct exception_context *the_exception_context = \ + &(ps)->exception_context +#define context(ps,fault) anon_context(ps); png_store *fault + +/* This macro returns the number of elements in an array as an (unsigned int), + * it is necessary to avoid the inability of certain versions of GCC to use + * the value of a compile-time constant when performing range checks. It must + * be passed an array name. + */ +#define ARRAY_SIZE(a) ((unsigned int)((sizeof (a))/(sizeof (a)[0]))) + +/* GCC BUG 66447 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66447) requires + * some broken GCC versions to be fixed up to avoid invalid whining about auto + * variables that are *not* changed within the scope of a setjmp being changed. + * + * Feel free to extend the list of broken versions. + */ +#define is_gnu(major,minor)\ + (defined __GNUC__) && __GNUC__ == (major) && __GNUC_MINOR__ == (minor) +#define is_gnu_patch(major,minor,patch)\ + is_gnu(major,minor) && __GNUC_PATCHLEVEL__ == 0 +/* For the moment just do it always; all versions of GCC seem to be broken: */ +#ifdef __GNUC__ + const void * volatile make_volatile_for_gnu; +# define gnu_volatile(x) make_volatile_for_gnu = &x; +#else /* !GNUC broken versions */ +# define gnu_volatile(x) +#endif /* !GNUC broken versions */ + +/******************************* UTILITIES ************************************/ +/* Error handling is particularly problematic in production code - error + * handlers often themselves have bugs which lead to programs that detect + * minor errors crashing. The following functions deal with one very + * common class of errors in error handlers - attempting to format error or + * warning messages into buffers that are too small. + */ +static size_t safecat(char *buffer, size_t bufsize, size_t pos, + const char *cat) +{ + while (pos < bufsize && cat != NULL && *cat != 0) + buffer[pos++] = *cat++; + + if (pos >= bufsize) + pos = bufsize-1; + + buffer[pos] = 0; + return pos; +} + +static size_t safecatn(char *buffer, size_t bufsize, size_t pos, int n) +{ + char number[64]; + sprintf(number, "%d", n); + return safecat(buffer, bufsize, pos, number); +} + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +static size_t safecatd(char *buffer, size_t bufsize, size_t pos, double d, + int precision) +{ + char number[64]; + sprintf(number, "%.*f", precision, d); + return safecat(buffer, bufsize, pos, number); +} +#endif + +static const char invalid[] = "invalid"; +static const char sep[] = ": "; + +static const char *colour_types[8] = +{ + "grayscale", invalid, "truecolour", "indexed-colour", + "grayscale with alpha", invalid, "truecolour with alpha", invalid +}; + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* Convert a double precision value to fixed point. */ +static png_fixed_point +fix(double d) +{ + d = floor(d * PNG_FP_1 + .5); + return (png_fixed_point)d; +} +#endif /* PNG_READ_SUPPORTED */ + +/* Generate random bytes. This uses a boring repeatable algorithm and it + * is implemented here so that it gives the same set of numbers on every + * architecture. It's a linear congruential generator (Knuth or Sedgewick + * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and + * Hill, "The Art of Electronics" (Pseudo-Random Bit Sequences and Noise + * Generation.) + */ +static void +make_random_bytes(png_uint_32* seed, void* pv, size_t size) +{ + png_uint_32 u0 = seed[0], u1 = seed[1]; + png_bytep bytes = voidcast(png_bytep, pv); + + /* There are thirty three bits, the next bit in the sequence is bit-33 XOR + * bit-20. The top 1 bit is in u1, the bottom 32 are in u0. + */ + size_t i; + for (i=0; i> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff; + u1 <<= 8; + u1 |= u0 >> 24; + u0 <<= 8; + u0 |= u; + *bytes++ = (png_byte)u; + } + + seed[0] = u0; + seed[1] = u1; +} + +static void +make_four_random_bytes(png_uint_32* seed, png_bytep bytes) +{ + make_random_bytes(seed, bytes, 4); +} + +#if defined PNG_READ_SUPPORTED || defined PNG_WRITE_tRNS_SUPPORTED ||\ + defined PNG_WRITE_FILTER_SUPPORTED +static void +randomize(void *pv, size_t size) +{ + static png_uint_32 random_seed[2] = {0x56789abc, 0xd}; + make_random_bytes(random_seed, pv, size); +} + +#define R8(this) randomize(&(this), sizeof (this)) + +#ifdef PNG_READ_SUPPORTED +static png_byte +random_byte(void) +{ + unsigned char b1[1]; + randomize(b1, sizeof b1); + return b1[0]; +} +#endif /* READ */ + +static png_uint_16 +random_u16(void) +{ + unsigned char b2[2]; + randomize(b2, sizeof b2); + return png_get_uint_16(b2); +} + +#if defined PNG_READ_RGB_TO_GRAY_SUPPORTED ||\ + defined PNG_READ_FILLER_SUPPORTED +static png_uint_32 +random_u32(void) +{ + unsigned char b4[4]; + randomize(b4, sizeof b4); + return png_get_uint_32(b4); +} +#endif /* READ_FILLER || READ_RGB_TO_GRAY */ + +#endif /* READ || WRITE_tRNS || WRITE_FILTER */ + +#if defined PNG_READ_TRANSFORMS_SUPPORTED ||\ + defined PNG_WRITE_FILTER_SUPPORTED +static unsigned int +random_mod(unsigned int max) +{ + return random_u16() % max; /* 0 .. max-1 */ +} +#endif /* READ_TRANSFORMS || WRITE_FILTER */ + +#if (defined PNG_READ_RGB_TO_GRAY_SUPPORTED) ||\ + (defined PNG_READ_FILLER_SUPPORTED) +static int +random_choice(void) +{ + return random_byte() & 1; +} +#endif /* READ_RGB_TO_GRAY || READ_FILLER */ + +/* A numeric ID based on PNG file characteristics. The 'do_interlace' field + * simply records whether pngvalid did the interlace itself or whether it + * was done by libpng. Width and height must be less than 256. 'palette' is an + * index of the palette to use for formats with a palette otherwise a boolean + * indicating if a tRNS chunk was generated. + */ +#define FILEID(col, depth, palette, interlace, width, height, do_interlace) \ + ((png_uint_32)((col) + ((depth)<<3) + ((palette)<<8) + ((interlace)<<13) + \ + (((do_interlace)!=0)<<15) + ((width)<<16) + ((height)<<24))) + +#define COL_FROM_ID(id) ((png_byte)((id)& 0x7U)) +#define DEPTH_FROM_ID(id) ((png_byte)(((id) >> 3) & 0x1fU)) +#define PALETTE_FROM_ID(id) (((id) >> 8) & 0x1f) +#define INTERLACE_FROM_ID(id) ((png_byte)(((id) >> 13) & 0x3)) +#define DO_INTERLACE_FROM_ID(id) ((int)(((id)>>15) & 1)) +#define WIDTH_FROM_ID(id) (((id)>>16) & 0xff) +#define HEIGHT_FROM_ID(id) (((id)>>24) & 0xff) + +/* Utility to construct a standard name for a standard image. */ +static size_t +standard_name(char *buffer, size_t bufsize, size_t pos, png_byte colour_type, + int bit_depth, unsigned int npalette, int interlace_type, + png_uint_32 w, png_uint_32 h, int do_interlace) +{ + pos = safecat(buffer, bufsize, pos, colour_types[colour_type]); + if (colour_type == 3) /* must have a palette */ + { + pos = safecat(buffer, bufsize, pos, "["); + pos = safecatn(buffer, bufsize, pos, npalette); + pos = safecat(buffer, bufsize, pos, "]"); + } + + else if (npalette != 0) + pos = safecat(buffer, bufsize, pos, "+tRNS"); + + pos = safecat(buffer, bufsize, pos, " "); + pos = safecatn(buffer, bufsize, pos, bit_depth); + pos = safecat(buffer, bufsize, pos, " bit"); + + if (interlace_type != PNG_INTERLACE_NONE) + { + pos = safecat(buffer, bufsize, pos, " interlaced"); + if (do_interlace) + pos = safecat(buffer, bufsize, pos, "(pngvalid)"); + else + pos = safecat(buffer, bufsize, pos, "(libpng)"); + } + + if (w > 0 || h > 0) + { + pos = safecat(buffer, bufsize, pos, " "); + pos = safecatn(buffer, bufsize, pos, w); + pos = safecat(buffer, bufsize, pos, "x"); + pos = safecatn(buffer, bufsize, pos, h); + } + + return pos; +} + +static size_t +standard_name_from_id(char *buffer, size_t bufsize, size_t pos, png_uint_32 id) +{ + return standard_name(buffer, bufsize, pos, COL_FROM_ID(id), + DEPTH_FROM_ID(id), PALETTE_FROM_ID(id), INTERLACE_FROM_ID(id), + WIDTH_FROM_ID(id), HEIGHT_FROM_ID(id), DO_INTERLACE_FROM_ID(id)); +} + +/* Convenience API and defines to list valid formats. Note that 16 bit read and + * write support is required to do 16 bit read tests (we must be able to make a + * 16 bit image to test!) + */ +#ifdef PNG_WRITE_16BIT_SUPPORTED +# define WRITE_BDHI 4 +# ifdef PNG_READ_16BIT_SUPPORTED +# define READ_BDHI 4 +# define DO_16BIT +# endif +#else +# define WRITE_BDHI 3 +#endif +#ifndef DO_16BIT +# define READ_BDHI 3 +#endif + +/* The following defines the number of different palettes to generate for + * each log bit depth of a colour type 3 standard image. + */ +#define PALETTE_COUNT(bit_depth) ((bit_depth) > 4 ? 1U : 16U) + +static int +next_format(png_bytep colour_type, png_bytep bit_depth, + unsigned int* palette_number, int low_depth_gray, int tRNS) +{ + if (*bit_depth == 0) + { + *colour_type = 0; + if (low_depth_gray) + *bit_depth = 1; + else + *bit_depth = 8; + *palette_number = 0; + return 1; + } + + if (*colour_type < 4/*no alpha channel*/) + { + /* Add multiple palettes for colour type 3, one image with tRNS + * and one without for other non-alpha formats: + */ + unsigned int pn = ++*palette_number; + png_byte ct = *colour_type; + + if (((ct == 0/*GRAY*/ || ct/*RGB*/ == 2) && tRNS && pn < 2) || + (ct == 3/*PALETTE*/ && pn < PALETTE_COUNT(*bit_depth))) + return 1; + + /* No: next bit depth */ + *palette_number = 0; + } + + *bit_depth = (png_byte)(*bit_depth << 1); + + /* Palette images are restricted to 8 bit depth */ + if (*bit_depth <= 8 +#ifdef DO_16BIT + || (*colour_type != 3 && *bit_depth <= 16) +#endif + ) + return 1; + + /* Move to the next color type, or return 0 at the end. */ + switch (*colour_type) + { + case 0: + *colour_type = 2; + *bit_depth = 8; + return 1; + + case 2: + *colour_type = 3; + *bit_depth = 1; + return 1; + + case 3: + *colour_type = 4; + *bit_depth = 8; + return 1; + + case 4: + *colour_type = 6; + *bit_depth = 8; + return 1; + + default: + return 0; + } +} + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +static unsigned int +sample(png_const_bytep row, png_byte colour_type, png_byte bit_depth, + png_uint_32 x, unsigned int sample_index, int swap16, int littleendian) +{ + png_uint_32 bit_index, result; + + /* Find a sample index for the desired sample: */ + x *= bit_depth; + bit_index = x; + + if ((colour_type & 1) == 0) /* !palette */ + { + if (colour_type & 2) + bit_index *= 3; + + if (colour_type & 4) + bit_index += x; /* Alpha channel */ + + /* Multiple channels; select one: */ + if (colour_type & (2+4)) + bit_index += sample_index * bit_depth; + } + + /* Return the sample from the row as an integer. */ + row += bit_index >> 3; + result = *row; + + if (bit_depth == 8) + return result; + + else if (bit_depth > 8) + { + if (swap16) + return (*++row << 8) + result; + else + return (result << 8) + *++row; + } + + /* Less than 8 bits per sample. By default PNG has the big end of + * the egg on the left of the screen, but if littleendian is set + * then the big end is on the right. + */ + bit_index &= 7; + + if (!littleendian) + bit_index = 8-bit_index-bit_depth; + + return (result >> bit_index) & ((1U<> 3] & ~destMask; + unsigned int sourceByte = fromBuffer[fromIndex >> 3]; + + /* Don't rely on << or >> supporting '0' here, just in case: */ + fromIndex &= 7; + if (littleendian) + { + if (fromIndex > 0) sourceByte >>= fromIndex; + if ((toIndex & 7) > 0) sourceByte <<= toIndex & 7; + } + + else + { + if (fromIndex > 0) sourceByte <<= fromIndex; + if ((toIndex & 7) > 0) sourceByte >>= toIndex & 7; + } + + toBuffer[toIndex >> 3] = (png_byte)(destByte | (sourceByte & destMask)); + } + else /* One or more bytes */ + memmove(toBuffer+(toIndex>>3), fromBuffer+(fromIndex>>3), pixelSize>>3); +} + +#ifdef PNG_READ_SUPPORTED +/* Copy a complete row of pixels, taking into account potential partial + * bytes at the end. + */ +static void +row_copy(png_bytep toBuffer, png_const_bytep fromBuffer, unsigned int bitWidth, + int littleendian) +{ + memcpy(toBuffer, fromBuffer, bitWidth >> 3); + + if ((bitWidth & 7) != 0) + { + unsigned int mask; + + toBuffer += bitWidth >> 3; + fromBuffer += bitWidth >> 3; + if (littleendian) + mask = 0xff << (bitWidth & 7); + else + mask = 0xff >> (bitWidth & 7); + *toBuffer = (png_byte)((*toBuffer & mask) | (*fromBuffer & ~mask)); + } +} + +/* Compare pixels - they are assumed to start at the first byte in the + * given buffers. + */ +static int +pixel_cmp(png_const_bytep pa, png_const_bytep pb, png_uint_32 bit_width) +{ +#if PNG_LIBPNG_VER < 10506 + if (memcmp(pa, pb, bit_width>>3) == 0) + { + png_uint_32 p; + + if ((bit_width & 7) == 0) return 0; + + /* Ok, any differences? */ + p = pa[bit_width >> 3]; + p ^= pb[bit_width >> 3]; + + if (p == 0) return 0; + + /* There are, but they may not be significant, remove the bits + * after the end (the low order bits in PNG.) + */ + bit_width &= 7; + p >>= 8-bit_width; + + if (p == 0) return 0; + } +#else + /* From libpng-1.5.6 the overwrite should be fixed, so compare the trailing + * bits too: + */ + if (memcmp(pa, pb, (bit_width+7)>>3) == 0) + return 0; +#endif + + /* Return the index of the changed byte. */ + { + png_uint_32 where = 0; + + while (pa[where] == pb[where]) ++where; + return 1+where; + } +} +#endif /* PNG_READ_SUPPORTED */ + +/*************************** BASIC PNG FILE WRITING ***************************/ +/* A png_store takes data from the sequential writer or provides data + * to the sequential reader. It can also store the result of a PNG + * write for later retrieval. + */ +#define STORE_BUFFER_SIZE 500 /* arbitrary */ +typedef struct png_store_buffer +{ + struct png_store_buffer* prev; /* NOTE: stored in reverse order */ + png_byte buffer[STORE_BUFFER_SIZE]; +} png_store_buffer; + +#define FILE_NAME_SIZE 64 + +typedef struct store_palette_entry /* record of a single palette entry */ +{ + png_byte red; + png_byte green; + png_byte blue; + png_byte alpha; +} store_palette_entry, store_palette[256]; + +typedef struct png_store_file +{ + struct png_store_file* next; /* as many as you like... */ + char name[FILE_NAME_SIZE]; + unsigned int IDAT_bits; /* Number of bits in IDAT size */ + png_uint_32 IDAT_size; /* Total size of IDAT data */ + png_uint_32 id; /* must be correct (see FILEID) */ + size_t datacount; /* In this (the last) buffer */ + png_store_buffer data; /* Last buffer in file */ + int npalette; /* Number of entries in palette */ + store_palette_entry* palette; /* May be NULL */ +} png_store_file; + +/* The following is a pool of memory allocated by a single libpng read or write + * operation. + */ +typedef struct store_pool +{ + struct png_store *store; /* Back pointer */ + struct store_memory *list; /* List of allocated memory */ + png_byte mark[4]; /* Before and after data */ + + /* Statistics for this run. */ + png_alloc_size_t max; /* Maximum single allocation */ + png_alloc_size_t current; /* Current allocation */ + png_alloc_size_t limit; /* Highest current allocation */ + png_alloc_size_t total; /* Total allocation */ + + /* Overall statistics (retained across successive runs). */ + png_alloc_size_t max_max; + png_alloc_size_t max_limit; + png_alloc_size_t max_total; +} store_pool; + +typedef struct png_store +{ + /* For cexcept.h exception handling - simply store one of these; + * the context is a self pointer but it may point to a different + * png_store (in fact it never does in this program.) + */ + struct exception_context + exception_context; + + unsigned int verbose :1; + unsigned int treat_warnings_as_errors :1; + unsigned int expect_error :1; + unsigned int expect_warning :1; + unsigned int saw_warning :1; + unsigned int speed :1; + unsigned int progressive :1; /* use progressive read */ + unsigned int validated :1; /* used as a temporary flag */ + int nerrors; + int nwarnings; + int noptions; /* number of options below: */ + struct { + unsigned char option; /* option number, 0..30 */ + unsigned char setting; /* setting (unset,invalid,on,off) */ + } options[16]; + char test[128]; /* Name of test */ + char error[256]; + + /* Share fields */ + png_uint_32 chunklen; /* Length of chunk+overhead (chunkpos >= 8) */ + png_uint_32 chunktype;/* Type of chunk (valid if chunkpos >= 4) */ + png_uint_32 chunkpos; /* Position in chunk */ + png_uint_32 IDAT_size;/* Accumulated IDAT size in .new */ + unsigned int IDAT_bits;/* Cache of the file store value */ + + /* Read fields */ + png_structp pread; /* Used to read a saved file */ + png_infop piread; + png_store_file* current; /* Set when reading */ + png_store_buffer* next; /* Set when reading */ + size_t readpos; /* Position in *next */ + png_byte* image; /* Buffer for reading interlaced images */ + size_t cb_image; /* Size of this buffer */ + size_t cb_row; /* Row size of the image(s) */ + uLong IDAT_crc; + png_uint_32 IDAT_len; /* Used when re-chunking IDAT chunks */ + png_uint_32 IDAT_pos; /* Used when re-chunking IDAT chunks */ + png_uint_32 image_h; /* Number of rows in a single image */ + store_pool read_memory_pool; + + /* Write fields */ + png_store_file* saved; + png_structp pwrite; /* Used when writing a new file */ + png_infop piwrite; + size_t writepos; /* Position in .new */ + char wname[FILE_NAME_SIZE]; + png_store_buffer new; /* The end of the new PNG file being written. */ + store_pool write_memory_pool; + store_palette_entry* palette; + int npalette; +} png_store; + +/* Initialization and cleanup */ +static void +store_pool_mark(png_bytep mark) +{ + static png_uint_32 store_seed[2] = { 0x12345678, 1}; + + make_four_random_bytes(store_seed, mark); +} + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* Use this for random 32 bit values; this function makes sure the result is + * non-zero. + */ +static png_uint_32 +random_32(void) +{ + + for (;;) + { + png_byte mark[4]; + png_uint_32 result; + + store_pool_mark(mark); + result = png_get_uint_32(mark); + + if (result != 0) + return result; + } +} +#endif /* PNG_READ_SUPPORTED */ + +static void +store_pool_init(png_store *ps, store_pool *pool) +{ + memset(pool, 0, sizeof *pool); + + pool->store = ps; + pool->list = NULL; + pool->max = pool->current = pool->limit = pool->total = 0; + pool->max_max = pool->max_limit = pool->max_total = 0; + store_pool_mark(pool->mark); +} + +static void +store_init(png_store* ps) +{ + memset(ps, 0, sizeof *ps); + init_exception_context(&ps->exception_context); + store_pool_init(ps, &ps->read_memory_pool); + store_pool_init(ps, &ps->write_memory_pool); + ps->verbose = 0; + ps->treat_warnings_as_errors = 0; + ps->expect_error = 0; + ps->expect_warning = 0; + ps->saw_warning = 0; + ps->speed = 0; + ps->progressive = 0; + ps->validated = 0; + ps->nerrors = ps->nwarnings = 0; + ps->pread = NULL; + ps->piread = NULL; + ps->saved = ps->current = NULL; + ps->next = NULL; + ps->readpos = 0; + ps->image = NULL; + ps->cb_image = 0; + ps->cb_row = 0; + ps->image_h = 0; + ps->pwrite = NULL; + ps->piwrite = NULL; + ps->writepos = 0; + ps->chunkpos = 8; + ps->chunktype = 0; + ps->chunklen = 16; + ps->IDAT_size = 0; + ps->IDAT_bits = 0; + ps->new.prev = NULL; + ps->palette = NULL; + ps->npalette = 0; + ps->noptions = 0; +} + +static void +store_freebuffer(png_store_buffer* psb) +{ + if (psb->prev) + { + store_freebuffer(psb->prev); + free(psb->prev); + psb->prev = NULL; + } +} + +static void +store_freenew(png_store *ps) +{ + store_freebuffer(&ps->new); + ps->writepos = 0; + ps->chunkpos = 8; + ps->chunktype = 0; + ps->chunklen = 16; + ps->IDAT_size = 0; + ps->IDAT_bits = 0; + if (ps->palette != NULL) + { + free(ps->palette); + ps->palette = NULL; + ps->npalette = 0; + } +} + +static void +store_storenew(png_store *ps) +{ + png_store_buffer *pb; + + pb = voidcast(png_store_buffer*, malloc(sizeof *pb)); + + if (pb == NULL) + png_error(ps->pwrite, "store new: OOM"); + + *pb = ps->new; + ps->new.prev = pb; + ps->writepos = 0; +} + +static void +store_freefile(png_store_file **ppf) +{ + if (*ppf != NULL) + { + store_freefile(&(*ppf)->next); + + store_freebuffer(&(*ppf)->data); + (*ppf)->datacount = 0; + if ((*ppf)->palette != NULL) + { + free((*ppf)->palette); + (*ppf)->palette = NULL; + (*ppf)->npalette = 0; + } + free(*ppf); + *ppf = NULL; + } +} + +static unsigned int +bits_of(png_uint_32 num) +{ + /* Return the number of bits in 'num' */ + unsigned int b = 0; + + if (num & 0xffff0000U) b += 16U, num >>= 16; + if (num & 0xff00U) b += 8U, num >>= 8; + if (num & 0xf0U) b += 4U, num >>= 4; + if (num & 0xcU) b += 2U, num >>= 2; + if (num & 0x2U) ++b, num >>= 1; + if (num) ++b; + + return b; /* 0..32 */ +} + +/* Main interface to file storage, after writing a new PNG file (see the API + * below) call store_storefile to store the result with the given name and id. + */ +static void +store_storefile(png_store *ps, png_uint_32 id) +{ + png_store_file *pf; + + if (ps->chunkpos != 0U || ps->chunktype != 0U || ps->chunklen != 0U || + ps->IDAT_size == 0) + png_error(ps->pwrite, "storefile: incomplete write"); + + pf = voidcast(png_store_file*, malloc(sizeof *pf)); + if (pf == NULL) + png_error(ps->pwrite, "storefile: OOM"); + safecat(pf->name, sizeof pf->name, 0, ps->wname); + pf->id = id; + pf->data = ps->new; + pf->datacount = ps->writepos; + pf->IDAT_size = ps->IDAT_size; + pf->IDAT_bits = bits_of(ps->IDAT_size); + /* Because the IDAT always has zlib header stuff this must be true: */ + if (pf->IDAT_bits == 0U) + png_error(ps->pwrite, "storefile: 0 sized IDAT"); + ps->new.prev = NULL; + ps->writepos = 0; + ps->chunkpos = 8; + ps->chunktype = 0; + ps->chunklen = 16; + ps->IDAT_size = 0; + pf->palette = ps->palette; + pf->npalette = ps->npalette; + ps->palette = 0; + ps->npalette = 0; + + /* And save it. */ + pf->next = ps->saved; + ps->saved = pf; +} + +/* Generate an error message (in the given buffer) */ +static size_t +store_message(png_store *ps, png_const_structp pp, char *buffer, size_t bufsize, + size_t pos, const char *msg) +{ + if (pp != NULL && pp == ps->pread) + { + /* Reading a file */ + pos = safecat(buffer, bufsize, pos, "read: "); + + if (ps->current != NULL) + { + pos = safecat(buffer, bufsize, pos, ps->current->name); + pos = safecat(buffer, bufsize, pos, sep); + } + } + + else if (pp != NULL && pp == ps->pwrite) + { + /* Writing a file */ + pos = safecat(buffer, bufsize, pos, "write: "); + pos = safecat(buffer, bufsize, pos, ps->wname); + pos = safecat(buffer, bufsize, pos, sep); + } + + else + { + /* Neither reading nor writing (or a memory error in struct delete) */ + pos = safecat(buffer, bufsize, pos, "pngvalid: "); + } + + if (ps->test[0] != 0) + { + pos = safecat(buffer, bufsize, pos, ps->test); + pos = safecat(buffer, bufsize, pos, sep); + } + pos = safecat(buffer, bufsize, pos, msg); + return pos; +} + +/* Verbose output to the error stream: */ +static void +store_verbose(png_store *ps, png_const_structp pp, png_const_charp prefix, + png_const_charp message) +{ + char buffer[512]; + + if (prefix) + fputs(prefix, stderr); + + (void)store_message(ps, pp, buffer, sizeof buffer, 0, message); + fputs(buffer, stderr); + fputc('\n', stderr); +} + +/* Log an error or warning - the relevant count is always incremented. */ +static void +store_log(png_store* ps, png_const_structp pp, png_const_charp message, + int is_error) +{ + /* The warning is copied to the error buffer if there are no errors and it is + * the first warning. The error is copied to the error buffer if it is the + * first error (overwriting any prior warnings). + */ + if (is_error ? (ps->nerrors)++ == 0 : + (ps->nwarnings)++ == 0 && ps->nerrors == 0) + store_message(ps, pp, ps->error, sizeof ps->error, 0, message); + + if (ps->verbose) + store_verbose(ps, pp, is_error ? "error: " : "warning: ", message); +} + +#ifdef PNG_READ_SUPPORTED +/* Internal error function, called with a png_store but no libpng stuff. */ +static void +internal_error(png_store *ps, png_const_charp message) +{ + store_log(ps, NULL, message, 1 /* error */); + + /* And finally throw an exception. */ + { + struct exception_context *the_exception_context = &ps->exception_context; + Throw ps; + } +} +#endif /* PNG_READ_SUPPORTED */ + +/* Functions to use as PNG callbacks. */ +static void PNGCBAPI +store_error(png_structp ppIn, png_const_charp message) /* PNG_NORETURN */ +{ + png_const_structp pp = ppIn; + png_store *ps = voidcast(png_store*, png_get_error_ptr(pp)); + + if (!ps->expect_error) + store_log(ps, pp, message, 1 /* error */); + + /* And finally throw an exception. */ + { + struct exception_context *the_exception_context = &ps->exception_context; + Throw ps; + } +} + +static void PNGCBAPI +store_warning(png_structp ppIn, png_const_charp message) +{ + png_const_structp pp = ppIn; + png_store *ps = voidcast(png_store*, png_get_error_ptr(pp)); + + if (!ps->expect_warning) + store_log(ps, pp, message, 0 /* warning */); + else + ps->saw_warning = 1; +} + +/* These somewhat odd functions are used when reading an image to ensure that + * the buffer is big enough, the png_structp is for errors. + */ +/* Return a single row from the correct image. */ +static png_bytep +store_image_row(const png_store* ps, png_const_structp pp, int nImage, + png_uint_32 y) +{ + size_t coffset = (nImage * ps->image_h + y) * (ps->cb_row + 5) + 2; + + if (ps->image == NULL) + png_error(pp, "no allocated image"); + + if (coffset + ps->cb_row + 3 > ps->cb_image) + png_error(pp, "image too small"); + + return ps->image + coffset; +} + +static void +store_image_free(png_store *ps, png_const_structp pp) +{ + if (ps->image != NULL) + { + png_bytep image = ps->image; + + if (image[-1] != 0xed || image[ps->cb_image] != 0xfe) + { + if (pp != NULL) + png_error(pp, "png_store image overwrite (1)"); + else + store_log(ps, NULL, "png_store image overwrite (2)", 1); + } + + ps->image = NULL; + ps->cb_image = 0; + --image; + free(image); + } +} + +static void +store_ensure_image(png_store *ps, png_const_structp pp, int nImages, + size_t cbRow, png_uint_32 cRows) +{ + size_t cb = nImages * cRows * (cbRow + 5); + + if (ps->cb_image < cb) + { + png_bytep image; + + store_image_free(ps, pp); + + /* The buffer is deliberately mis-aligned. */ + image = voidcast(png_bytep, malloc(cb+2)); + if (image == NULL) + { + /* Called from the startup - ignore the error for the moment. */ + if (pp == NULL) + return; + + png_error(pp, "OOM allocating image buffer"); + } + + /* These magic tags are used to detect overwrites above. */ + ++image; + image[-1] = 0xed; + image[cb] = 0xfe; + + ps->image = image; + ps->cb_image = cb; + } + + /* We have an adequate sized image; lay out the rows. There are 2 bytes at + * the start and three at the end of each (this ensures that the row + * alignment starts out odd - 2+1 and changes for larger images on each row.) + */ + ps->cb_row = cbRow; + ps->image_h = cRows; + + /* For error checking, the whole buffer is set to 10110010 (0xb2 - 178). + * This deliberately doesn't match the bits in the size test image which are + * outside the image; these are set to 0xff (all 1). To make the row + * comparison work in the 'size' test case the size rows are pre-initialized + * to the same value prior to calling 'standard_row'. + */ + memset(ps->image, 178, cb); + + /* Then put in the marks. */ + while (--nImages >= 0) + { + png_uint_32 y; + + for (y=0; yimage; + + if (image[-1] != 0xed || image[ps->cb_image] != 0xfe) + png_error(pp, "image overwrite"); + else + { + size_t cbRow = ps->cb_row; + png_uint_32 rows = ps->image_h; + + image += iImage * (cbRow+5) * ps->image_h; + + image += 2; /* skip image first row markers */ + + for (; rows > 0; --rows) + { + if (image[-2] != 190 || image[-1] != 239) + png_error(pp, "row start overwritten"); + + if (image[cbRow] != 222 || image[cbRow+1] != 173 || + image[cbRow+2] != 17) + png_error(pp, "row end overwritten"); + + image += cbRow+5; + } + } +} +#endif /* PNG_READ_SUPPORTED */ + +static int +valid_chunktype(png_uint_32 chunktype) +{ + /* Each byte in the chunk type must be in one of the ranges 65..90, 97..122 + * (both inclusive), so: + */ + unsigned int i; + + for (i=0; i<4; ++i) + { + unsigned int c = chunktype & 0xffU; + + if (!((c >= 65U && c <= 90U) || (c >= 97U && c <= 122U))) + return 0; + + chunktype >>= 8; + } + + return 1; /* It's valid */ +} + +static void PNGCBAPI +store_write(png_structp ppIn, png_bytep pb, size_t st) +{ + png_const_structp pp = ppIn; + png_store *ps = voidcast(png_store*, png_get_io_ptr(pp)); + size_t writepos = ps->writepos; + png_uint_32 chunkpos = ps->chunkpos; + png_uint_32 chunktype = ps->chunktype; + png_uint_32 chunklen = ps->chunklen; + + if (ps->pwrite != pp) + png_error(pp, "store state damaged"); + + /* Technically this is legal, but in practice libpng never writes more than + * the maximum chunk size at once so if it happens something weird has + * changed inside libpng (probably). + */ + if (st > 0x7fffffffU) + png_error(pp, "unexpected write size"); + + /* Now process the bytes to be written. Do this in units of the space in the + * output (write) buffer or, at the start 4 bytes for the chunk type and + * length limited in any case by the amount of data. + */ + while (st > 0) + { + if (writepos >= STORE_BUFFER_SIZE) + store_storenew(ps), writepos = 0; + + if (chunkpos < 4) + { + png_byte b = *pb++; + --st; + chunklen = (chunklen << 8) + b; + ps->new.buffer[writepos++] = b; + ++chunkpos; + } + + else if (chunkpos < 8) + { + png_byte b = *pb++; + --st; + chunktype = (chunktype << 8) + b; + ps->new.buffer[writepos++] = b; + + if (++chunkpos == 8) + { + chunklen &= 0xffffffffU; + if (chunklen > 0x7fffffffU) + png_error(pp, "chunk length too great"); + + chunktype &= 0xffffffffU; + if (chunktype == CHUNK_IDAT) + { + if (chunklen > ~ps->IDAT_size) + png_error(pp, "pngvalid internal image too large"); + + ps->IDAT_size += chunklen; + } + + else if (!valid_chunktype(chunktype)) + png_error(pp, "invalid chunk type"); + + chunklen += 12; /* for header and CRC */ + } + } + + else /* chunkpos >= 8 */ + { + size_t cb = st; + + if (cb > STORE_BUFFER_SIZE - writepos) + cb = STORE_BUFFER_SIZE - writepos; + + if (cb > chunklen - chunkpos/* bytes left in chunk*/) + cb = (size_t)/*SAFE*/(chunklen - chunkpos); + + memcpy(ps->new.buffer + writepos, pb, cb); + chunkpos += (png_uint_32)/*SAFE*/cb; + pb += cb; + writepos += cb; + st -= cb; + + if (chunkpos >= chunklen) /* must be equal */ + chunkpos = chunktype = chunklen = 0; + } + } /* while (st > 0) */ + + ps->writepos = writepos; + ps->chunkpos = chunkpos; + ps->chunktype = chunktype; + ps->chunklen = chunklen; +} + +static void PNGCBAPI +store_flush(png_structp ppIn) +{ + UNUSED(ppIn) /*DOES NOTHING*/ +} + +#ifdef PNG_READ_SUPPORTED +static size_t +store_read_buffer_size(png_store *ps) +{ + /* Return the bytes available for read in the current buffer. */ + if (ps->next != &ps->current->data) + return STORE_BUFFER_SIZE; + + return ps->current->datacount; +} + +/* Return total bytes available for read. */ +static size_t +store_read_buffer_avail(png_store *ps) +{ + if (ps->current != NULL && ps->next != NULL) + { + png_store_buffer *next = &ps->current->data; + size_t cbAvail = ps->current->datacount; + + while (next != ps->next && next != NULL) + { + next = next->prev; + cbAvail += STORE_BUFFER_SIZE; + } + + if (next != ps->next) + png_error(ps->pread, "buffer read error"); + + if (cbAvail > ps->readpos) + return cbAvail - ps->readpos; + } + + return 0; +} + +static int +store_read_buffer_next(png_store *ps) +{ + png_store_buffer *pbOld = ps->next; + png_store_buffer *pbNew = &ps->current->data; + if (pbOld != pbNew) + { + while (pbNew != NULL && pbNew->prev != pbOld) + pbNew = pbNew->prev; + + if (pbNew != NULL) + { + ps->next = pbNew; + ps->readpos = 0; + return 1; + } + + png_error(ps->pread, "buffer lost"); + } + + return 0; /* EOF or error */ +} + +/* Need separate implementation and callback to allow use of the same code + * during progressive read, where the io_ptr is set internally by libpng. + */ +static void +store_read_imp(png_store *ps, png_bytep pb, size_t st) +{ + if (ps->current == NULL || ps->next == NULL) + png_error(ps->pread, "store state damaged"); + + while (st > 0) + { + size_t cbAvail = store_read_buffer_size(ps) - ps->readpos; + + if (cbAvail > 0) + { + if (cbAvail > st) cbAvail = st; + memcpy(pb, ps->next->buffer + ps->readpos, cbAvail); + st -= cbAvail; + pb += cbAvail; + ps->readpos += cbAvail; + } + + else if (!store_read_buffer_next(ps)) + png_error(ps->pread, "read beyond end of file"); + } +} + +static size_t +store_read_chunk(png_store *ps, png_bytep pb, size_t max, size_t min) +{ + png_uint_32 chunklen = ps->chunklen; + png_uint_32 chunktype = ps->chunktype; + png_uint_32 chunkpos = ps->chunkpos; + size_t st = max; + + if (st > 0) do + { + if (chunkpos >= chunklen) /* end of last chunk */ + { + png_byte buffer[8]; + + /* Read the header of the next chunk: */ + store_read_imp(ps, buffer, 8U); + chunklen = png_get_uint_32(buffer) + 12U; + chunktype = png_get_uint_32(buffer+4U); + chunkpos = 0U; /* Position read so far */ + } + + if (chunktype == CHUNK_IDAT) + { + png_uint_32 IDAT_pos = ps->IDAT_pos; + png_uint_32 IDAT_len = ps->IDAT_len; + png_uint_32 IDAT_size = ps->IDAT_size; + + /* The IDAT headers are constructed here; skip the input header. */ + if (chunkpos < 8U) + chunkpos = 8U; + + if (IDAT_pos == IDAT_len) + { + png_byte random = random_byte(); + + /* Make a new IDAT chunk, if IDAT_len is 0 this is the first IDAT, + * if IDAT_size is 0 this is the end. At present this is set up + * using a random number so that there is a 25% chance before + * the start of the first IDAT chunk being 0 length. + */ + if (IDAT_len == 0U) /* First IDAT */ + { + switch (random & 3U) + { + case 0U: IDAT_len = 12U; break; /* 0 bytes */ + case 1U: IDAT_len = 13U; break; /* 1 byte */ + default: IDAT_len = random_u32(); + IDAT_len %= IDAT_size; + IDAT_len += 13U; /* 1..IDAT_size bytes */ + break; + } + } + + else if (IDAT_size == 0U) /* all IDAT data read */ + { + /* The last (IDAT) chunk should be positioned at the CRC now: */ + if (chunkpos != chunklen-4U) + png_error(ps->pread, "internal: IDAT size mismatch"); + + /* The only option here is to add a zero length IDAT, this + * happens 25% of the time. Because of the check above + * chunklen-4U-chunkpos must be zero, we just need to skip the + * CRC now. + */ + if ((random & 3U) == 0U) + IDAT_len = 12U; /* Output another 0 length IDAT */ + + else + { + /* End of IDATs, skip the CRC to make the code above load the + * next chunk header next time round. + */ + png_byte buffer[4]; + + store_read_imp(ps, buffer, 4U); + chunkpos += 4U; + ps->IDAT_pos = IDAT_pos; + ps->IDAT_len = IDAT_len; + ps->IDAT_size = 0U; + continue; /* Read the next chunk */ + } + } + + else + { + /* Middle of IDATs, use 'random' to determine the number of bits + * to use in the IDAT length. + */ + IDAT_len = random_u32(); + IDAT_len &= (1U << (1U + random % ps->IDAT_bits)) - 1U; + if (IDAT_len > IDAT_size) + IDAT_len = IDAT_size; + IDAT_len += 12U; /* zero bytes may occur */ + } + + IDAT_pos = 0U; + ps->IDAT_crc = 0x35af061e; /* Ie: crc32(0UL, "IDAT", 4) */ + } /* IDAT_pos == IDAT_len */ + + if (IDAT_pos < 8U) /* Return the header */ do + { + png_uint_32 b; + unsigned int shift; + + if (IDAT_pos < 4U) + b = IDAT_len - 12U; + + else + b = CHUNK_IDAT; + + shift = 3U & IDAT_pos; + ++IDAT_pos; + + if (shift < 3U) + b >>= 8U*(3U-shift); + + *pb++ = 0xffU & b; + } + while (--st > 0 && IDAT_pos < 8); + + else if (IDAT_pos < IDAT_len - 4U) /* I.e not the CRC */ + { + if (chunkpos < chunklen-4U) + { + uInt avail = (uInt)-1; + + if (avail > (IDAT_len-4U) - IDAT_pos) + avail = (uInt)/*SAFE*/((IDAT_len-4U) - IDAT_pos); + + if (avail > st) + avail = (uInt)/*SAFE*/st; + + if (avail > (chunklen-4U) - chunkpos) + avail = (uInt)/*SAFE*/((chunklen-4U) - chunkpos); + + store_read_imp(ps, pb, avail); + ps->IDAT_crc = crc32(ps->IDAT_crc, pb, avail); + pb += (size_t)/*SAFE*/avail; + st -= (size_t)/*SAFE*/avail; + chunkpos += (png_uint_32)/*SAFE*/avail; + IDAT_size -= (png_uint_32)/*SAFE*/avail; + IDAT_pos += (png_uint_32)/*SAFE*/avail; + } + + else /* skip the input CRC */ + { + png_byte buffer[4]; + + store_read_imp(ps, buffer, 4U); + chunkpos += 4U; + } + } + + else /* IDAT crc */ do + { + uLong b = ps->IDAT_crc; + unsigned int shift = (IDAT_len - IDAT_pos); /* 4..1 */ + ++IDAT_pos; + + if (shift > 1U) + b >>= 8U*(shift-1U); + + *pb++ = 0xffU & b; + } + while (--st > 0 && IDAT_pos < IDAT_len); + + ps->IDAT_pos = IDAT_pos; + ps->IDAT_len = IDAT_len; + ps->IDAT_size = IDAT_size; + } + + else /* !IDAT */ + { + /* If there is still some pending IDAT data after the IDAT chunks have + * been processed there is a problem: + */ + if (ps->IDAT_len > 0 && ps->IDAT_size > 0) + png_error(ps->pread, "internal: missing IDAT data"); + + if (chunktype == CHUNK_IEND && ps->IDAT_len == 0U) + png_error(ps->pread, "internal: missing IDAT"); + + if (chunkpos < 8U) /* Return the header */ do + { + png_uint_32 b; + unsigned int shift; + + if (chunkpos < 4U) + b = chunklen - 12U; + + else + b = chunktype; + + shift = 3U & chunkpos; + ++chunkpos; + + if (shift < 3U) + b >>= 8U*(3U-shift); + + *pb++ = 0xffU & b; + } + while (--st > 0 && chunkpos < 8); + + else /* Return chunk bytes, including the CRC */ + { + size_t avail = st; + + if (avail > chunklen - chunkpos) + avail = (size_t)/*SAFE*/(chunklen - chunkpos); + + store_read_imp(ps, pb, avail); + pb += avail; + st -= avail; + chunkpos += (png_uint_32)/*SAFE*/avail; + + /* Check for end of chunk and end-of-file; don't try to read a new + * chunk header at this point unless instructed to do so by 'min'. + */ + if (chunkpos >= chunklen && max-st >= min && + store_read_buffer_avail(ps) == 0) + break; + } + } /* !IDAT */ + } + while (st > 0); + + ps->chunklen = chunklen; + ps->chunktype = chunktype; + ps->chunkpos = chunkpos; + + return st; /* space left */ +} + +static void PNGCBAPI +store_read(png_structp ppIn, png_bytep pb, size_t st) +{ + png_const_structp pp = ppIn; + png_store *ps = voidcast(png_store*, png_get_io_ptr(pp)); + + if (ps == NULL || ps->pread != pp) + png_error(pp, "bad store read call"); + + store_read_chunk(ps, pb, st, st); +} + +static void +store_progressive_read(png_store *ps, png_structp pp, png_infop pi) +{ + if (ps->pread != pp || ps->current == NULL || ps->next == NULL) + png_error(pp, "store state damaged (progressive)"); + + /* This is another Horowitz and Hill random noise generator. In this case + * the aim is to stress the progressive reader with truly horrible variable + * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers + * is generated. We could probably just count from 1 to 32767 and get as + * good a result. + */ + while (store_read_buffer_avail(ps) > 0) + { + static png_uint_32 noise = 2; + size_t cb; + png_byte buffer[512]; + + /* Generate 15 more bits of stuff: */ + noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff); + cb = noise & 0x1ff; + cb -= store_read_chunk(ps, buffer, cb, 1); + png_process_data(pp, pi, buffer, cb); + } +} +#endif /* PNG_READ_SUPPORTED */ + +/* The caller must fill this in: */ +static store_palette_entry * +store_write_palette(png_store *ps, int npalette) +{ + if (ps->pwrite == NULL) + store_log(ps, NULL, "attempt to write palette without write stream", 1); + + if (ps->palette != NULL) + png_error(ps->pwrite, "multiple store_write_palette calls"); + + /* This function can only return NULL if called with '0'! */ + if (npalette > 0) + { + ps->palette = voidcast(store_palette_entry*, malloc(npalette * + sizeof *ps->palette)); + + if (ps->palette == NULL) + png_error(ps->pwrite, "store new palette: OOM"); + + ps->npalette = npalette; + } + + return ps->palette; +} + +#ifdef PNG_READ_SUPPORTED +static store_palette_entry * +store_current_palette(png_store *ps, int *npalette) +{ + /* This is an internal error (the call has been made outside a read + * operation.) + */ + if (ps->current == NULL) + { + store_log(ps, ps->pread, "no current stream for palette", 1); + return NULL; + } + + /* The result may be null if there is no palette. */ + *npalette = ps->current->npalette; + return ps->current->palette; +} +#endif /* PNG_READ_SUPPORTED */ + +/***************************** MEMORY MANAGEMENT*** ***************************/ +#ifdef PNG_USER_MEM_SUPPORTED +/* A store_memory is simply the header for an allocated block of memory. The + * pointer returned to libpng is just after the end of the header block, the + * allocated memory is followed by a second copy of the 'mark'. + */ +typedef struct store_memory +{ + store_pool *pool; /* Originating pool */ + struct store_memory *next; /* Singly linked list */ + png_alloc_size_t size; /* Size of memory allocated */ + png_byte mark[4]; /* ID marker */ +} store_memory; + +/* Handle a fatal error in memory allocation. This calls png_error if the + * libpng struct is non-NULL, else it outputs a message and returns. This means + * that a memory problem while libpng is running will abort (png_error) the + * handling of particular file while one in cleanup (after the destroy of the + * struct has returned) will simply keep going and free (or attempt to free) + * all the memory. + */ +static void +store_pool_error(png_store *ps, png_const_structp pp, const char *msg) +{ + if (pp != NULL) + png_error(pp, msg); + + /* Else we have to do it ourselves. png_error eventually calls store_log, + * above. store_log accepts a NULL png_structp - it just changes what gets + * output by store_message. + */ + store_log(ps, pp, msg, 1 /* error */); +} + +static void +store_memory_free(png_const_structp pp, store_pool *pool, store_memory *memory) +{ + /* Note that pp may be NULL (see store_pool_delete below), the caller has + * found 'memory' in pool->list *and* unlinked this entry, so this is a valid + * pointer (for sure), but the contents may have been trashed. + */ + if (memory->pool != pool) + store_pool_error(pool->store, pp, "memory corrupted (pool)"); + + else if (memcmp(memory->mark, pool->mark, sizeof memory->mark) != 0) + store_pool_error(pool->store, pp, "memory corrupted (start)"); + + /* It should be safe to read the size field now. */ + else + { + png_alloc_size_t cb = memory->size; + + if (cb > pool->max) + store_pool_error(pool->store, pp, "memory corrupted (size)"); + + else if (memcmp((png_bytep)(memory+1)+cb, pool->mark, sizeof pool->mark) + != 0) + store_pool_error(pool->store, pp, "memory corrupted (end)"); + + /* Finally give the library a chance to find problems too: */ + else + { + pool->current -= cb; + free(memory); + } + } +} + +static void +store_pool_delete(png_store *ps, store_pool *pool) +{ + if (pool->list != NULL) + { + fprintf(stderr, "%s: %s %s: memory lost (list follows):\n", ps->test, + pool == &ps->read_memory_pool ? "read" : "write", + pool == &ps->read_memory_pool ? (ps->current != NULL ? + ps->current->name : "unknown file") : ps->wname); + ++ps->nerrors; + + do + { + store_memory *next = pool->list; + pool->list = next->next; + next->next = NULL; + + fprintf(stderr, "\t%lu bytes @ %p\n", + (unsigned long)next->size, (const void*)(next+1)); + /* The NULL means this will always return, even if the memory is + * corrupted. + */ + store_memory_free(NULL, pool, next); + } + while (pool->list != NULL); + } + + /* And reset the other fields too for the next time. */ + if (pool->max > pool->max_max) pool->max_max = pool->max; + pool->max = 0; + if (pool->current != 0) /* unexpected internal error */ + fprintf(stderr, "%s: %s %s: memory counter mismatch (internal error)\n", + ps->test, pool == &ps->read_memory_pool ? "read" : "write", + pool == &ps->read_memory_pool ? (ps->current != NULL ? + ps->current->name : "unknown file") : ps->wname); + pool->current = 0; + + if (pool->limit > pool->max_limit) + pool->max_limit = pool->limit; + + pool->limit = 0; + + if (pool->total > pool->max_total) + pool->max_total = pool->total; + + pool->total = 0; + + /* Get a new mark too. */ + store_pool_mark(pool->mark); +} + +/* The memory callbacks: */ +static png_voidp PNGCBAPI +store_malloc(png_structp ppIn, png_alloc_size_t cb) +{ + png_const_structp pp = ppIn; + store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp)); + store_memory *new = voidcast(store_memory*, malloc(cb + (sizeof *new) + + (sizeof pool->mark))); + + if (new != NULL) + { + if (cb > pool->max) + pool->max = cb; + + pool->current += cb; + + if (pool->current > pool->limit) + pool->limit = pool->current; + + pool->total += cb; + + new->size = cb; + memcpy(new->mark, pool->mark, sizeof new->mark); + memcpy((png_byte*)(new+1) + cb, pool->mark, sizeof pool->mark); + new->pool = pool; + new->next = pool->list; + pool->list = new; + ++new; + } + + else + { + /* NOTE: the PNG user malloc function cannot use the png_ptr it is passed + * other than to retrieve the allocation pointer! libpng calls the + * store_malloc callback in two basic cases: + * + * 1) From png_malloc; png_malloc will do a png_error itself if NULL is + * returned. + * 2) From png_struct or png_info structure creation; png_malloc is + * to return so cleanup can be performed. + * + * To handle this store_malloc can log a message, but can't do anything + * else. + */ + store_log(pool->store, pp, "out of memory", 1 /* is_error */); + } + + return new; +} + +static void PNGCBAPI +store_free(png_structp ppIn, png_voidp memory) +{ + png_const_structp pp = ppIn; + store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp)); + store_memory *this = voidcast(store_memory*, memory), **test; + + /* Because libpng calls store_free with a dummy png_struct when deleting + * png_struct or png_info via png_destroy_struct_2 it is necessary to check + * the passed in png_structp to ensure it is valid, and not pass it to + * png_error if it is not. + */ + if (pp != pool->store->pread && pp != pool->store->pwrite) + pp = NULL; + + /* First check that this 'memory' really is valid memory - it must be in the + * pool list. If it is, use the shared memory_free function to free it. + */ + --this; + for (test = &pool->list; *test != this; test = &(*test)->next) + { + if (*test == NULL) + { + store_pool_error(pool->store, pp, "bad pointer to free"); + return; + } + } + + /* Unlink this entry, *test == this. */ + *test = this->next; + this->next = NULL; + store_memory_free(pp, pool, this); +} +#endif /* PNG_USER_MEM_SUPPORTED */ + +/* Setup functions. */ +/* Cleanup when aborting a write or after storing the new file. */ +static void +store_write_reset(png_store *ps) +{ + if (ps->pwrite != NULL) + { + anon_context(ps); + + Try + png_destroy_write_struct(&ps->pwrite, &ps->piwrite); + + Catch_anonymous + { + /* memory corruption: continue. */ + } + + ps->pwrite = NULL; + ps->piwrite = NULL; + } + + /* And make sure that all the memory has been freed - this will output + * spurious errors in the case of memory corruption above, but this is safe. + */ +# ifdef PNG_USER_MEM_SUPPORTED + store_pool_delete(ps, &ps->write_memory_pool); +# endif + + store_freenew(ps); +} + +/* The following is the main write function, it returns a png_struct and, + * optionally, a png_info suitable for writiing a new PNG file. Use + * store_storefile above to record this file after it has been written. The + * returned libpng structures as destroyed by store_write_reset above. + */ +static png_structp +set_store_for_write(png_store *ps, png_infopp ppi, const char *name) +{ + anon_context(ps); + + Try + { + if (ps->pwrite != NULL) + png_error(ps->pwrite, "write store already in use"); + + store_write_reset(ps); + safecat(ps->wname, sizeof ps->wname, 0, name); + + /* Don't do the slow memory checks if doing a speed test, also if user + * memory is not supported we can't do it anyway. + */ +# ifdef PNG_USER_MEM_SUPPORTED + if (!ps->speed) + ps->pwrite = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, + ps, store_error, store_warning, &ps->write_memory_pool, + store_malloc, store_free); + + else +# endif + ps->pwrite = png_create_write_struct(PNG_LIBPNG_VER_STRING, + ps, store_error, store_warning); + + png_set_write_fn(ps->pwrite, ps, store_write, store_flush); + +# ifdef PNG_SET_OPTION_SUPPORTED + { + int opt; + for (opt=0; optnoptions; ++opt) + if (png_set_option(ps->pwrite, ps->options[opt].option, + ps->options[opt].setting) == PNG_OPTION_INVALID) + png_error(ps->pwrite, "png option invalid"); + } +# endif + + if (ppi != NULL) + *ppi = ps->piwrite = png_create_info_struct(ps->pwrite); + } + + Catch_anonymous + return NULL; + + return ps->pwrite; +} + +/* Cleanup when finished reading (either due to error or in the success case). + * This routine exists even when there is no read support to make the code + * tidier (avoid a mass of ifdefs) and so easier to maintain. + */ +static void +store_read_reset(png_store *ps) +{ +# ifdef PNG_READ_SUPPORTED + if (ps->pread != NULL) + { + anon_context(ps); + + Try + png_destroy_read_struct(&ps->pread, &ps->piread, NULL); + + Catch_anonymous + { + /* error already output: continue */ + } + + ps->pread = NULL; + ps->piread = NULL; + } +# endif + +# ifdef PNG_USER_MEM_SUPPORTED + /* Always do this to be safe. */ + store_pool_delete(ps, &ps->read_memory_pool); +# endif + + ps->current = NULL; + ps->next = NULL; + ps->readpos = 0; + ps->validated = 0; + + ps->chunkpos = 8; + ps->chunktype = 0; + ps->chunklen = 16; + ps->IDAT_size = 0; +} + +#ifdef PNG_READ_SUPPORTED +static void +store_read_set(png_store *ps, png_uint_32 id) +{ + png_store_file *pf = ps->saved; + + while (pf != NULL) + { + if (pf->id == id) + { + ps->current = pf; + ps->next = NULL; + ps->IDAT_size = pf->IDAT_size; + ps->IDAT_bits = pf->IDAT_bits; /* just a cache */ + ps->IDAT_len = 0; + ps->IDAT_pos = 0; + ps->IDAT_crc = 0UL; + store_read_buffer_next(ps); + return; + } + + pf = pf->next; + } + + { + size_t pos; + char msg[FILE_NAME_SIZE+64]; + + pos = standard_name_from_id(msg, sizeof msg, 0, id); + pos = safecat(msg, sizeof msg, pos, ": file not found"); + png_error(ps->pread, msg); + } +} + +/* The main interface for reading a saved file - pass the id number of the file + * to retrieve. Ids must be unique or the earlier file will be hidden. The API + * returns a png_struct and, optionally, a png_info. Both of these will be + * destroyed by store_read_reset above. + */ +static png_structp +set_store_for_read(png_store *ps, png_infopp ppi, png_uint_32 id, + const char *name) +{ + /* Set the name for png_error */ + safecat(ps->test, sizeof ps->test, 0, name); + + if (ps->pread != NULL) + png_error(ps->pread, "read store already in use"); + + store_read_reset(ps); + + /* Both the create APIs can return NULL if used in their default mode + * (because there is no other way of handling an error because the jmp_buf + * by default is stored in png_struct and that has not been allocated!) + * However, given that store_error works correctly in these circumstances + * we don't ever expect NULL in this program. + */ +# ifdef PNG_USER_MEM_SUPPORTED + if (!ps->speed) + ps->pread = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, ps, + store_error, store_warning, &ps->read_memory_pool, store_malloc, + store_free); + + else +# endif + ps->pread = png_create_read_struct(PNG_LIBPNG_VER_STRING, ps, store_error, + store_warning); + + if (ps->pread == NULL) + { + struct exception_context *the_exception_context = &ps->exception_context; + + store_log(ps, NULL, "png_create_read_struct returned NULL (unexpected)", + 1 /*error*/); + + Throw ps; + } + +# ifdef PNG_SET_OPTION_SUPPORTED + { + int opt; + for (opt=0; optnoptions; ++opt) + if (png_set_option(ps->pread, ps->options[opt].option, + ps->options[opt].setting) == PNG_OPTION_INVALID) + png_error(ps->pread, "png option invalid"); + } +# endif + + store_read_set(ps, id); + + if (ppi != NULL) + *ppi = ps->piread = png_create_info_struct(ps->pread); + + return ps->pread; +} +#endif /* PNG_READ_SUPPORTED */ + +/* The overall cleanup of a store simply calls the above then removes all the + * saved files. This does not delete the store itself. + */ +static void +store_delete(png_store *ps) +{ + store_write_reset(ps); + store_read_reset(ps); + store_freefile(&ps->saved); + store_image_free(ps, NULL); +} + +/*********************** PNG FILE MODIFICATION ON READ ************************/ +/* Files may be modified on read. The following structure contains a complete + * png_store together with extra members to handle modification and a special + * read callback for libpng. To use this the 'modifications' field must be set + * to a list of png_modification structures that actually perform the + * modification, otherwise a png_modifier is functionally equivalent to a + * png_store. There is a special read function, set_modifier_for_read, which + * replaces set_store_for_read. + */ +typedef enum modifier_state +{ + modifier_start, /* Initial value */ + modifier_signature, /* Have a signature */ + modifier_IHDR /* Have an IHDR */ +} modifier_state; + +typedef struct CIE_color +{ + /* A single CIE tristimulus value, representing the unique response of a + * standard observer to a variety of light spectra. The observer recognizes + * all spectra that produce this response as the same color, therefore this + * is effectively a description of a color. + */ + double X, Y, Z; +} CIE_color; + +typedef struct color_encoding +{ + /* A description of an (R,G,B) encoding of color (as defined above); this + * includes the actual colors of the (R,G,B) triples (1,0,0), (0,1,0) and + * (0,0,1) plus an encoding value that is used to encode the linear + * components R, G and B to give the actual values R^gamma, G^gamma and + * B^gamma that are stored. + */ + double gamma; /* Encoding (file) gamma of space */ + CIE_color red, green, blue; /* End points */ +} color_encoding; + +#ifdef PNG_READ_SUPPORTED +#if defined PNG_READ_TRANSFORMS_SUPPORTED && defined PNG_READ_cHRM_SUPPORTED +static double +chromaticity_x(CIE_color c) +{ + return c.X / (c.X + c.Y + c.Z); +} + +static double +chromaticity_y(CIE_color c) +{ + return c.Y / (c.X + c.Y + c.Z); +} + +static CIE_color +white_point(const color_encoding *encoding) +{ + CIE_color white; + + white.X = encoding->red.X + encoding->green.X + encoding->blue.X; + white.Y = encoding->red.Y + encoding->green.Y + encoding->blue.Y; + white.Z = encoding->red.Z + encoding->green.Z + encoding->blue.Z; + + return white; +} +#endif /* READ_TRANSFORMS && READ_cHRM */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +static void +normalize_color_encoding(color_encoding *encoding) +{ + const double whiteY = encoding->red.Y + encoding->green.Y + + encoding->blue.Y; + + if (whiteY != 1) + { + encoding->red.X /= whiteY; + encoding->red.Y /= whiteY; + encoding->red.Z /= whiteY; + encoding->green.X /= whiteY; + encoding->green.Y /= whiteY; + encoding->green.Z /= whiteY; + encoding->blue.X /= whiteY; + encoding->blue.Y /= whiteY; + encoding->blue.Z /= whiteY; + } +} +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +static size_t +safecat_color_encoding(char *buffer, size_t bufsize, size_t pos, + const color_encoding *e, double encoding_gamma) +{ + if (e != 0) + { + if (encoding_gamma != 0) + pos = safecat(buffer, bufsize, pos, "("); + pos = safecat(buffer, bufsize, pos, "R("); + pos = safecatd(buffer, bufsize, pos, e->red.X, 4); + pos = safecat(buffer, bufsize, pos, ","); + pos = safecatd(buffer, bufsize, pos, e->red.Y, 4); + pos = safecat(buffer, bufsize, pos, ","); + pos = safecatd(buffer, bufsize, pos, e->red.Z, 4); + pos = safecat(buffer, bufsize, pos, "),G("); + pos = safecatd(buffer, bufsize, pos, e->green.X, 4); + pos = safecat(buffer, bufsize, pos, ","); + pos = safecatd(buffer, bufsize, pos, e->green.Y, 4); + pos = safecat(buffer, bufsize, pos, ","); + pos = safecatd(buffer, bufsize, pos, e->green.Z, 4); + pos = safecat(buffer, bufsize, pos, "),B("); + pos = safecatd(buffer, bufsize, pos, e->blue.X, 4); + pos = safecat(buffer, bufsize, pos, ","); + pos = safecatd(buffer, bufsize, pos, e->blue.Y, 4); + pos = safecat(buffer, bufsize, pos, ","); + pos = safecatd(buffer, bufsize, pos, e->blue.Z, 4); + pos = safecat(buffer, bufsize, pos, ")"); + if (encoding_gamma != 0) + pos = safecat(buffer, bufsize, pos, ")"); + } + + if (encoding_gamma != 0) + { + pos = safecat(buffer, bufsize, pos, "^"); + pos = safecatd(buffer, bufsize, pos, encoding_gamma, 5); + } + + return pos; +} +#endif /* READ_TRANSFORMS */ +#endif /* PNG_READ_SUPPORTED */ + +typedef struct png_modifier +{ + png_store this; /* I am a png_store */ + struct png_modification *modifications; /* Changes to make */ + + modifier_state state; /* My state */ + + /* Information from IHDR: */ + png_byte bit_depth; /* From IHDR */ + png_byte colour_type; /* From IHDR */ + + /* While handling PLTE, IDAT and IEND these chunks may be pended to allow + * other chunks to be inserted. + */ + png_uint_32 pending_len; + png_uint_32 pending_chunk; + + /* Test values */ + double *gammas; + unsigned int ngammas; + unsigned int ngamma_tests; /* Number of gamma tests to run*/ + double current_gamma; /* 0 if not set */ + const color_encoding *encodings; + unsigned int nencodings; + const color_encoding *current_encoding; /* If an encoding has been set */ + unsigned int encoding_counter; /* For iteration */ + int encoding_ignored; /* Something overwrote it */ + + /* Control variables used to iterate through possible encodings, the + * following must be set to 0 and tested by the function that uses the + * png_modifier because the modifier only sets it to 1 (true.) + */ + unsigned int repeat :1; /* Repeat this transform test. */ + unsigned int test_uses_encoding :1; + + /* Lowest sbit to test (pre-1.7 libpng fails for sbit < 8) */ + png_byte sbitlow; + + /* Error control - these are the limits on errors accepted by the gamma tests + * below. + */ + double maxout8; /* Maximum output value error */ + double maxabs8; /* Absolute sample error 0..1 */ + double maxcalc8; /* Absolute sample error 0..1 */ + double maxpc8; /* Percentage sample error 0..100% */ + double maxout16; /* Maximum output value error */ + double maxabs16; /* Absolute sample error 0..1 */ + double maxcalc16;/* Absolute sample error 0..1 */ + double maxcalcG; /* Absolute sample error 0..1 */ + double maxpc16; /* Percentage sample error 0..100% */ + + /* This is set by transforms that need to allow a higher limit, it is an + * internal check on pngvalid to ensure that the calculated error limits are + * not ridiculous; without this it is too easy to make a mistake in pngvalid + * that allows any value through. + * + * NOTE: this is not checked in release builds. + */ + double limit; /* limit on error values, normally 4E-3 */ + + /* Log limits - values above this are logged, but not necessarily + * warned. + */ + double log8; /* Absolute error in 8 bits to log */ + double log16; /* Absolute error in 16 bits to log */ + + /* Logged 8 and 16 bit errors ('output' values): */ + double error_gray_2; + double error_gray_4; + double error_gray_8; + double error_gray_16; + double error_color_8; + double error_color_16; + double error_indexed; + + /* Flags: */ + /* Whether to call png_read_update_info, not png_read_start_image, and how + * many times to call it. + */ + int use_update_info; + + /* Whether or not to interlace. */ + int interlace_type :9; /* int, but must store '1' */ + + /* Run the standard tests? */ + unsigned int test_standard :1; + + /* Run the odd-sized image and interlace read/write tests? */ + unsigned int test_size :1; + + /* Run tests on reading with a combination of transforms, */ + unsigned int test_transform :1; + unsigned int test_tRNS :1; /* Includes tRNS images */ + + /* When to use the use_input_precision option, this controls the gamma + * validation code checks. If set any value that is within the transformed + * range input-.5 to input+.5 will be accepted, otherwise the value must be + * within the normal limits. It should not be necessary to set this; the + * result should always be exact within the permitted error limits. + */ + unsigned int use_input_precision :1; + unsigned int use_input_precision_sbit :1; + unsigned int use_input_precision_16to8 :1; + + /* If set assume that the calculation bit depth is set by the input + * precision, not the output precision. + */ + unsigned int calculations_use_input_precision :1; + + /* If set assume that the calculations are done in 16 bits even if the sample + * depth is 8 bits. + */ + unsigned int assume_16_bit_calculations :1; + + /* Which gamma tests to run: */ + unsigned int test_gamma_threshold :1; + unsigned int test_gamma_transform :1; /* main tests */ + unsigned int test_gamma_sbit :1; + unsigned int test_gamma_scale16 :1; + unsigned int test_gamma_background :1; + unsigned int test_gamma_alpha_mode :1; + unsigned int test_gamma_expand16 :1; + unsigned int test_exhaustive :1; + + /* Whether or not to run the low-bit-depth grayscale tests. This fails on + * gamma images in some cases because of gross inaccuracies in the grayscale + * gamma handling for low bit depth. + */ + unsigned int test_lbg :1; + unsigned int test_lbg_gamma_threshold :1; + unsigned int test_lbg_gamma_transform :1; + unsigned int test_lbg_gamma_sbit :1; + unsigned int test_lbg_gamma_composition :1; + + unsigned int log :1; /* Log max error */ + + /* Buffer information, the buffer size limits the size of the chunks that can + * be modified - they must fit (including header and CRC) into the buffer! + */ + size_t flush; /* Count of bytes to flush */ + size_t buffer_count; /* Bytes in buffer */ + size_t buffer_position; /* Position in buffer */ + png_byte buffer[1024]; +} png_modifier; + +/* This returns true if the test should be stopped now because it has already + * failed and it is running silently. + */ +static int fail(png_modifier *pm) +{ + return !pm->log && !pm->this.verbose && (pm->this.nerrors > 0 || + (pm->this.treat_warnings_as_errors && pm->this.nwarnings > 0)); +} + +static void +modifier_init(png_modifier *pm) +{ + memset(pm, 0, sizeof *pm); + store_init(&pm->this); + pm->modifications = NULL; + pm->state = modifier_start; + pm->sbitlow = 1U; + pm->ngammas = 0; + pm->ngamma_tests = 0; + pm->gammas = 0; + pm->current_gamma = 0; + pm->encodings = 0; + pm->nencodings = 0; + pm->current_encoding = 0; + pm->encoding_counter = 0; + pm->encoding_ignored = 0; + pm->repeat = 0; + pm->test_uses_encoding = 0; + pm->maxout8 = pm->maxpc8 = pm->maxabs8 = pm->maxcalc8 = 0; + pm->maxout16 = pm->maxpc16 = pm->maxabs16 = pm->maxcalc16 = 0; + pm->maxcalcG = 0; + pm->limit = 4E-3; + pm->log8 = pm->log16 = 0; /* Means 'off' */ + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = 0; + pm->error_gray_16 = pm->error_color_8 = pm->error_color_16 = 0; + pm->error_indexed = 0; + pm->use_update_info = 0; + pm->interlace_type = PNG_INTERLACE_NONE; + pm->test_standard = 0; + pm->test_size = 0; + pm->test_transform = 0; +# ifdef PNG_WRITE_tRNS_SUPPORTED + pm->test_tRNS = 1; +# else + pm->test_tRNS = 0; +# endif + pm->use_input_precision = 0; + pm->use_input_precision_sbit = 0; + pm->use_input_precision_16to8 = 0; + pm->calculations_use_input_precision = 0; + pm->assume_16_bit_calculations = 0; + pm->test_gamma_threshold = 0; + pm->test_gamma_transform = 0; + pm->test_gamma_sbit = 0; + pm->test_gamma_scale16 = 0; + pm->test_gamma_background = 0; + pm->test_gamma_alpha_mode = 0; + pm->test_gamma_expand16 = 0; + pm->test_lbg = 1; + pm->test_lbg_gamma_threshold = 1; + pm->test_lbg_gamma_transform = 1; + pm->test_lbg_gamma_sbit = 1; + pm->test_lbg_gamma_composition = 1; + pm->test_exhaustive = 0; + pm->log = 0; + + /* Rely on the memset for all the other fields - there are no pointers */ +} + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + +/* This controls use of checks that explicitly know how libpng digitizes the + * samples in calculations; setting this circumvents simple error limit checking + * in the rgb_to_gray check, replacing it with an exact copy of the libpng 1.5 + * algorithm. + */ +#define DIGITIZE PNG_LIBPNG_VER < 10700 + +/* If pm->calculations_use_input_precision is set then operations will happen + * with the precision of the input, not the precision of the output depth. + * + * If pm->assume_16_bit_calculations is set then even 8 bit calculations use 16 + * bit precision. This only affects those of the following limits that pertain + * to a calculation - not a digitization operation - unless the following API is + * called directly. + */ +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +#if DIGITIZE +static double digitize(double value, int depth, int do_round) +{ + /* 'value' is in the range 0 to 1, the result is the same value rounded to a + * multiple of the digitization factor - 8 or 16 bits depending on both the + * sample depth and the 'assume' setting. Digitization is normally by + * rounding and 'do_round' should be 1, if it is 0 the digitized value will + * be truncated. + */ + unsigned int digitization_factor = (1U << depth) - 1; + + /* Limiting the range is done as a convenience to the caller - it's easier to + * do it once here than every time at the call site. + */ + if (value <= 0) + value = 0; + + else if (value >= 1) + value = 1; + + value *= digitization_factor; + if (do_round) value += .5; + return floor(value)/digitization_factor; +} +#endif +#endif /* RGB_TO_GRAY */ + +#ifdef PNG_READ_GAMMA_SUPPORTED +static double abserr(const png_modifier *pm, int in_depth, int out_depth) +{ + /* Absolute error permitted in linear values - affected by the bit depth of + * the calculations. + */ + if (pm->assume_16_bit_calculations || + (pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + return pm->maxabs16; + else + return pm->maxabs8; +} + +static double calcerr(const png_modifier *pm, int in_depth, int out_depth) +{ + /* Error in the linear composition arithmetic - only relevant when + * composition actually happens (0 < alpha < 1). + */ + if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + return pm->maxcalc16; + else if (pm->assume_16_bit_calculations) + return pm->maxcalcG; + else + return pm->maxcalc8; +} + +static double pcerr(const png_modifier *pm, int in_depth, int out_depth) +{ + /* Percentage error permitted in the linear values. Note that the specified + * value is a percentage but this routine returns a simple number. + */ + if (pm->assume_16_bit_calculations || + (pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + return pm->maxpc16 * .01; + else + return pm->maxpc8 * .01; +} + +/* Output error - the error in the encoded value. This is determined by the + * digitization of the output so can be +/-0.5 in the actual output value. In + * the expand_16 case with the current code in libpng the expand happens after + * all the calculations are done in 8 bit arithmetic, so even though the output + * depth is 16 the output error is determined by the 8 bit calculation. + * + * This limit is not determined by the bit depth of internal calculations. + * + * The specified parameter does *not* include the base .5 digitization error but + * it is added here. + */ +static double outerr(const png_modifier *pm, int in_depth, int out_depth) +{ + /* There is a serious error in the 2 and 4 bit grayscale transform because + * the gamma table value (8 bits) is simply shifted, not rounded, so the + * error in 4 bit grayscale gamma is up to the value below. This is a hack + * to allow pngvalid to succeed: + * + * TODO: fix this in libpng + */ + if (out_depth == 2) + return .73182-.5; + + if (out_depth == 4) + return .90644-.5; + + if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + return pm->maxout16; + + /* This is the case where the value was calculated at 8-bit precision then + * scaled to 16 bits. + */ + else if (out_depth == 16) + return pm->maxout8 * 257; + + else + return pm->maxout8; +} + +/* This does the same thing as the above however it returns the value to log, + * rather than raising a warning. This is useful for debugging to track down + * exactly what set of parameters cause high error values. + */ +static double outlog(const png_modifier *pm, int in_depth, int out_depth) +{ + /* The command line parameters are either 8 bit (0..255) or 16 bit (0..65535) + * and so must be adjusted for low bit depth grayscale: + */ + if (out_depth <= 8) + { + if (pm->log8 == 0) /* switched off */ + return 256; + + if (out_depth < 8) + return pm->log8 / 255 * ((1<log8; + } + + if ((pm->calculations_use_input_precision ? in_depth : out_depth) == 16) + { + if (pm->log16 == 0) + return 65536; + + return pm->log16; + } + + /* This is the case where the value was calculated at 8-bit precision then + * scaled to 16 bits. + */ + if (pm->log8 == 0) + return 65536; + + return pm->log8 * 257; +} + +/* This complements the above by providing the appropriate quantization for the + * final value. Normally this would just be quantization to an integral value, + * but in the 8 bit calculation case it's actually quantization to a multiple of + * 257! + */ +static int output_quantization_factor(const png_modifier *pm, int in_depth, + int out_depth) +{ + if (out_depth == 16 && in_depth != 16 && + pm->calculations_use_input_precision) + return 257; + else + return 1; +} +#endif /* PNG_READ_GAMMA_SUPPORTED */ + +/* One modification structure must be provided for each chunk to be modified (in + * fact more than one can be provided if multiple separate changes are desired + * for a single chunk.) Modifications include adding a new chunk when a + * suitable chunk does not exist. + * + * The caller of modify_fn will reset the CRC of the chunk and record 'modified' + * or 'added' as appropriate if the modify_fn returns 1 (true). If the + * modify_fn is NULL the chunk is simply removed. + */ +typedef struct png_modification +{ + struct png_modification *next; + png_uint_32 chunk; + + /* If the following is NULL all matching chunks will be removed: */ + int (*modify_fn)(struct png_modifier *pm, + struct png_modification *me, int add); + + /* If the following is set to PLTE, IDAT or IEND and the chunk has not been + * found and modified (and there is a modify_fn) the modify_fn will be called + * to add the chunk before the relevant chunk. + */ + png_uint_32 add; + unsigned int modified :1; /* Chunk was modified */ + unsigned int added :1; /* Chunk was added */ + unsigned int removed :1; /* Chunk was removed */ +} png_modification; + +static void +modification_reset(png_modification *pmm) +{ + if (pmm != NULL) + { + pmm->modified = 0; + pmm->added = 0; + pmm->removed = 0; + modification_reset(pmm->next); + } +} + +static void +modification_init(png_modification *pmm) +{ + memset(pmm, 0, sizeof *pmm); + pmm->next = NULL; + pmm->chunk = 0; + pmm->modify_fn = NULL; + pmm->add = 0; + modification_reset(pmm); +} + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +static void +modifier_current_encoding(const png_modifier *pm, color_encoding *ce) +{ + if (pm->current_encoding != 0) + *ce = *pm->current_encoding; + + else + memset(ce, 0, sizeof *ce); + + ce->gamma = pm->current_gamma; +} +#endif + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +static size_t +safecat_current_encoding(char *buffer, size_t bufsize, size_t pos, + const png_modifier *pm) +{ + pos = safecat_color_encoding(buffer, bufsize, pos, pm->current_encoding, + pm->current_gamma); + + if (pm->encoding_ignored) + pos = safecat(buffer, bufsize, pos, "[overridden]"); + + return pos; +} +#endif + +/* Iterate through the usefully testable color encodings. An encoding is one + * of: + * + * 1) Nothing (no color space, no gamma). + * 2) Just a gamma value from the gamma array (including 1.0) + * 3) A color space from the encodings array with the corresponding gamma. + * 4) The same, but with gamma 1.0 (only really useful with 16 bit calculations) + * + * The iterator selects these in turn, the randomizer selects one at random, + * which is used depends on the setting of the 'test_exhaustive' flag. Notice + * that this function changes the colour space encoding so it must only be + * called on completion of the previous test. This is what 'modifier_reset' + * does, below. + * + * After the function has been called the 'repeat' flag will still be set; the + * caller of modifier_reset must reset it at the start of each run of the test! + */ +static unsigned int +modifier_total_encodings(const png_modifier *pm) +{ + return 1 + /* (1) nothing */ + pm->ngammas + /* (2) gamma values to test */ + pm->nencodings + /* (3) total number of encodings */ + /* The following test only works after the first time through the + * png_modifier code because 'bit_depth' is set when the IHDR is read. + * modifier_reset, below, preserves the setting until after it has called + * the iterate function (also below.) + * + * For this reason do not rely on this function outside a call to + * modifier_reset. + */ + ((pm->bit_depth == 16 || pm->assume_16_bit_calculations) ? + pm->nencodings : 0); /* (4) encodings with gamma == 1.0 */ +} + +static void +modifier_encoding_iterate(png_modifier *pm) +{ + if (!pm->repeat && /* Else something needs the current encoding again. */ + pm->test_uses_encoding) /* Some transform is encoding dependent */ + { + if (pm->test_exhaustive) + { + if (++pm->encoding_counter >= modifier_total_encodings(pm)) + pm->encoding_counter = 0; /* This will stop the repeat */ + } + + else + { + /* Not exhaustive - choose an encoding at random; generate a number in + * the range 1..(max-1), so the result is always non-zero: + */ + if (pm->encoding_counter == 0) + pm->encoding_counter = random_mod(modifier_total_encodings(pm)-1)+1; + else + pm->encoding_counter = 0; + } + + if (pm->encoding_counter > 0) + pm->repeat = 1; + } + + else if (!pm->repeat) + pm->encoding_counter = 0; +} + +static void +modifier_reset(png_modifier *pm) +{ + store_read_reset(&pm->this); + pm->limit = 4E-3; + pm->pending_len = pm->pending_chunk = 0; + pm->flush = pm->buffer_count = pm->buffer_position = 0; + pm->modifications = NULL; + pm->state = modifier_start; + modifier_encoding_iterate(pm); + /* The following must be set in the next run. In particular + * test_uses_encodings must be set in the _ini function of each transform + * that looks at the encodings. (Not the 'add' function!) + */ + pm->test_uses_encoding = 0; + pm->current_gamma = 0; + pm->current_encoding = 0; + pm->encoding_ignored = 0; + /* These only become value after IHDR is read: */ + pm->bit_depth = pm->colour_type = 0; +} + +/* The following must be called before anything else to get the encoding set up + * on the modifier. In particular it must be called before the transform init + * functions are called. + */ +static void +modifier_set_encoding(png_modifier *pm) +{ + /* Set the encoding to the one specified by the current encoding counter, + * first clear out all the settings - this corresponds to an encoding_counter + * of 0. + */ + pm->current_gamma = 0; + pm->current_encoding = 0; + pm->encoding_ignored = 0; /* not ignored yet - happens in _ini functions. */ + + /* Now, if required, set the gamma and encoding fields. */ + if (pm->encoding_counter > 0) + { + /* The gammas[] array is an array of screen gammas, not encoding gammas, + * so we need the inverse: + */ + if (pm->encoding_counter <= pm->ngammas) + pm->current_gamma = 1/pm->gammas[pm->encoding_counter-1]; + + else + { + unsigned int i = pm->encoding_counter - pm->ngammas; + + if (i >= pm->nencodings) + { + i %= pm->nencodings; + pm->current_gamma = 1; /* Linear, only in the 16 bit case */ + } + + else + pm->current_gamma = pm->encodings[i].gamma; + + pm->current_encoding = pm->encodings + i; + } + } +} + +/* Enquiry functions to find out what is set. Notice that there is an implicit + * assumption below that the first encoding in the list is the one for sRGB. + */ +static int +modifier_color_encoding_is_sRGB(const png_modifier *pm) +{ + return pm->current_encoding != 0 && pm->current_encoding == pm->encodings && + pm->current_encoding->gamma == pm->current_gamma; +} + +static int +modifier_color_encoding_is_set(const png_modifier *pm) +{ + return pm->current_gamma != 0; +} + +/* The guts of modification are performed during a read. */ +static void +modifier_crc(png_bytep buffer) +{ + /* Recalculate the chunk CRC - a complete chunk must be in + * the buffer, at the start. + */ + uInt datalen = png_get_uint_32(buffer); + uLong crc = crc32(0, buffer+4, datalen+4); + /* The cast to png_uint_32 is safe because a crc32 is always a 32 bit value. + */ + png_save_uint_32(buffer+datalen+8, (png_uint_32)crc); +} + +static void +modifier_setbuffer(png_modifier *pm) +{ + modifier_crc(pm->buffer); + pm->buffer_count = png_get_uint_32(pm->buffer)+12; + pm->buffer_position = 0; +} + +/* Separate the callback into the actual implementation (which is passed the + * png_modifier explicitly) and the callback, which gets the modifier from the + * png_struct. + */ +static void +modifier_read_imp(png_modifier *pm, png_bytep pb, size_t st) +{ + while (st > 0) + { + size_t cb; + png_uint_32 len, chunk; + png_modification *mod; + + if (pm->buffer_position >= pm->buffer_count) switch (pm->state) + { + static png_byte sign[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; + case modifier_start: + store_read_chunk(&pm->this, pm->buffer, 8, 8); /* signature. */ + pm->buffer_count = 8; + pm->buffer_position = 0; + + if (memcmp(pm->buffer, sign, 8) != 0) + png_error(pm->this.pread, "invalid PNG file signature"); + pm->state = modifier_signature; + break; + + case modifier_signature: + store_read_chunk(&pm->this, pm->buffer, 13+12, 13+12); /* IHDR */ + pm->buffer_count = 13+12; + pm->buffer_position = 0; + + if (png_get_uint_32(pm->buffer) != 13 || + png_get_uint_32(pm->buffer+4) != CHUNK_IHDR) + png_error(pm->this.pread, "invalid IHDR"); + + /* Check the list of modifiers for modifications to the IHDR. */ + mod = pm->modifications; + while (mod != NULL) + { + if (mod->chunk == CHUNK_IHDR && mod->modify_fn && + (*mod->modify_fn)(pm, mod, 0)) + { + mod->modified = 1; + modifier_setbuffer(pm); + } + + /* Ignore removal or add if IHDR! */ + mod = mod->next; + } + + /* Cache information from the IHDR (the modified one.) */ + pm->bit_depth = pm->buffer[8+8]; + pm->colour_type = pm->buffer[8+8+1]; + + pm->state = modifier_IHDR; + pm->flush = 0; + break; + + case modifier_IHDR: + default: + /* Read a new chunk and process it until we see PLTE, IDAT or + * IEND. 'flush' indicates that there is still some data to + * output from the preceding chunk. + */ + if ((cb = pm->flush) > 0) + { + if (cb > st) cb = st; + pm->flush -= cb; + store_read_chunk(&pm->this, pb, cb, cb); + pb += cb; + st -= cb; + if (st == 0) return; + } + + /* No more bytes to flush, read a header, or handle a pending + * chunk. + */ + if (pm->pending_chunk != 0) + { + png_save_uint_32(pm->buffer, pm->pending_len); + png_save_uint_32(pm->buffer+4, pm->pending_chunk); + pm->pending_len = 0; + pm->pending_chunk = 0; + } + else + store_read_chunk(&pm->this, pm->buffer, 8, 8); + + pm->buffer_count = 8; + pm->buffer_position = 0; + + /* Check for something to modify or a terminator chunk. */ + len = png_get_uint_32(pm->buffer); + chunk = png_get_uint_32(pm->buffer+4); + + /* Terminators first, they may have to be delayed for added + * chunks + */ + if (chunk == CHUNK_PLTE || chunk == CHUNK_IDAT || + chunk == CHUNK_IEND) + { + mod = pm->modifications; + + while (mod != NULL) + { + if ((mod->add == chunk || + (mod->add == CHUNK_PLTE && chunk == CHUNK_IDAT)) && + mod->modify_fn != NULL && !mod->modified && !mod->added) + { + /* Regardless of what the modify function does do not run + * this again. + */ + mod->added = 1; + + if ((*mod->modify_fn)(pm, mod, 1 /*add*/)) + { + /* Reset the CRC on a new chunk */ + if (pm->buffer_count > 0) + modifier_setbuffer(pm); + + else + { + pm->buffer_position = 0; + mod->removed = 1; + } + + /* The buffer has been filled with something (we assume) + * so output this. Pend the current chunk. + */ + pm->pending_len = len; + pm->pending_chunk = chunk; + break; /* out of while */ + } + } + + mod = mod->next; + } + + /* Don't do any further processing if the buffer was modified - + * otherwise the code will end up modifying a chunk that was + * just added. + */ + if (mod != NULL) + break; /* out of switch */ + } + + /* If we get to here then this chunk may need to be modified. To + * do this it must be less than 1024 bytes in total size, otherwise + * it just gets flushed. + */ + if (len+12 <= sizeof pm->buffer) + { + size_t s = len+12-pm->buffer_count; + store_read_chunk(&pm->this, pm->buffer+pm->buffer_count, s, s); + pm->buffer_count = len+12; + + /* Check for a modification, else leave it be. */ + mod = pm->modifications; + while (mod != NULL) + { + if (mod->chunk == chunk) + { + if (mod->modify_fn == NULL) + { + /* Remove this chunk */ + pm->buffer_count = pm->buffer_position = 0; + mod->removed = 1; + break; /* Terminate the while loop */ + } + + else if ((*mod->modify_fn)(pm, mod, 0)) + { + mod->modified = 1; + /* The chunk may have been removed: */ + if (pm->buffer_count == 0) + { + pm->buffer_position = 0; + break; + } + modifier_setbuffer(pm); + } + } + + mod = mod->next; + } + } + + else + pm->flush = len+12 - pm->buffer_count; /* data + crc */ + + /* Take the data from the buffer (if there is any). */ + break; + } + + /* Here to read from the modifier buffer (not directly from + * the store, as in the flush case above.) + */ + cb = pm->buffer_count - pm->buffer_position; + + if (cb > st) + cb = st; + + memcpy(pb, pm->buffer + pm->buffer_position, cb); + st -= cb; + pb += cb; + pm->buffer_position += cb; + } +} + +/* The callback: */ +static void PNGCBAPI +modifier_read(png_structp ppIn, png_bytep pb, size_t st) +{ + png_const_structp pp = ppIn; + png_modifier *pm = voidcast(png_modifier*, png_get_io_ptr(pp)); + + if (pm == NULL || pm->this.pread != pp) + png_error(pp, "bad modifier_read call"); + + modifier_read_imp(pm, pb, st); +} + +/* Like store_progressive_read but the data is getting changed as we go so we + * need a local buffer. + */ +static void +modifier_progressive_read(png_modifier *pm, png_structp pp, png_infop pi) +{ + if (pm->this.pread != pp || pm->this.current == NULL || + pm->this.next == NULL) + png_error(pp, "store state damaged (progressive)"); + + /* This is another Horowitz and Hill random noise generator. In this case + * the aim is to stress the progressive reader with truly horrible variable + * buffer sizes in the range 1..500, so a sequence of 9 bit random numbers + * is generated. We could probably just count from 1 to 32767 and get as + * good a result. + */ + for (;;) + { + static png_uint_32 noise = 1; + size_t cb, cbAvail; + png_byte buffer[512]; + + /* Generate 15 more bits of stuff: */ + noise = (noise << 9) | ((noise ^ (noise >> (9-5))) & 0x1ff); + cb = noise & 0x1ff; + + /* Check that this number of bytes are available (in the current buffer.) + * (This doesn't quite work - the modifier might delete a chunk; unlikely + * but possible, it doesn't happen at present because the modifier only + * adds chunks to standard images.) + */ + cbAvail = store_read_buffer_avail(&pm->this); + if (pm->buffer_count > pm->buffer_position) + cbAvail += pm->buffer_count - pm->buffer_position; + + if (cb > cbAvail) + { + /* Check for EOF: */ + if (cbAvail == 0) + break; + + cb = cbAvail; + } + + modifier_read_imp(pm, buffer, cb); + png_process_data(pp, pi, buffer, cb); + } + + /* Check the invariants at the end (if this fails it's a problem in this + * file!) + */ + if (pm->buffer_count > pm->buffer_position || + pm->this.next != &pm->this.current->data || + pm->this.readpos < pm->this.current->datacount) + png_error(pp, "progressive read implementation error"); +} + +/* Set up a modifier. */ +static png_structp +set_modifier_for_read(png_modifier *pm, png_infopp ppi, png_uint_32 id, + const char *name) +{ + /* Do this first so that the modifier fields are cleared even if an error + * happens allocating the png_struct. No allocation is done here so no + * cleanup is required. + */ + pm->state = modifier_start; + pm->bit_depth = 0; + pm->colour_type = 255; + + pm->pending_len = 0; + pm->pending_chunk = 0; + pm->flush = 0; + pm->buffer_count = 0; + pm->buffer_position = 0; + + return set_store_for_read(&pm->this, ppi, id, name); +} + + +/******************************** MODIFICATIONS *******************************/ +/* Standard modifications to add chunks. These do not require the _SUPPORTED + * macros because the chunks can be there regardless of whether this specific + * libpng supports them. + */ +typedef struct gama_modification +{ + png_modification this; + png_fixed_point gamma; +} gama_modification; + +static int +gama_modify(png_modifier *pm, png_modification *me, int add) +{ + UNUSED(add) + /* This simply dumps the given gamma value into the buffer. */ + png_save_uint_32(pm->buffer, 4); + png_save_uint_32(pm->buffer+4, CHUNK_gAMA); + png_save_uint_32(pm->buffer+8, ((gama_modification*)me)->gamma); + return 1; +} + +static void +gama_modification_init(gama_modification *me, png_modifier *pm, double gammad) +{ + double g; + + modification_init(&me->this); + me->this.chunk = CHUNK_gAMA; + me->this.modify_fn = gama_modify; + me->this.add = CHUNK_PLTE; + g = fix(gammad); + me->gamma = (png_fixed_point)g; + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +typedef struct chrm_modification +{ + png_modification this; + const color_encoding *encoding; + png_fixed_point wx, wy, rx, ry, gx, gy, bx, by; +} chrm_modification; + +static int +chrm_modify(png_modifier *pm, png_modification *me, int add) +{ + UNUSED(add) + /* As with gAMA this just adds the required cHRM chunk to the buffer. */ + png_save_uint_32(pm->buffer , 32); + png_save_uint_32(pm->buffer+ 4, CHUNK_cHRM); + png_save_uint_32(pm->buffer+ 8, ((chrm_modification*)me)->wx); + png_save_uint_32(pm->buffer+12, ((chrm_modification*)me)->wy); + png_save_uint_32(pm->buffer+16, ((chrm_modification*)me)->rx); + png_save_uint_32(pm->buffer+20, ((chrm_modification*)me)->ry); + png_save_uint_32(pm->buffer+24, ((chrm_modification*)me)->gx); + png_save_uint_32(pm->buffer+28, ((chrm_modification*)me)->gy); + png_save_uint_32(pm->buffer+32, ((chrm_modification*)me)->bx); + png_save_uint_32(pm->buffer+36, ((chrm_modification*)me)->by); + return 1; +} + +static void +chrm_modification_init(chrm_modification *me, png_modifier *pm, + const color_encoding *encoding) +{ + CIE_color white = white_point(encoding); + + /* Original end points: */ + me->encoding = encoding; + + /* Chromaticities (in fixed point): */ + me->wx = fix(chromaticity_x(white)); + me->wy = fix(chromaticity_y(white)); + + me->rx = fix(chromaticity_x(encoding->red)); + me->ry = fix(chromaticity_y(encoding->red)); + me->gx = fix(chromaticity_x(encoding->green)); + me->gy = fix(chromaticity_y(encoding->green)); + me->bx = fix(chromaticity_x(encoding->blue)); + me->by = fix(chromaticity_y(encoding->blue)); + + modification_init(&me->this); + me->this.chunk = CHUNK_cHRM; + me->this.modify_fn = chrm_modify; + me->this.add = CHUNK_PLTE; + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +typedef struct srgb_modification +{ + png_modification this; + png_byte intent; +} srgb_modification; + +static int +srgb_modify(png_modifier *pm, png_modification *me, int add) +{ + UNUSED(add) + /* As above, ignore add and just make a new chunk */ + png_save_uint_32(pm->buffer, 1); + png_save_uint_32(pm->buffer+4, CHUNK_sRGB); + pm->buffer[8] = ((srgb_modification*)me)->intent; + return 1; +} + +static void +srgb_modification_init(srgb_modification *me, png_modifier *pm, png_byte intent) +{ + modification_init(&me->this); + me->this.chunk = CHUNK_sBIT; + + if (intent <= 3) /* if valid, else *delete* sRGB chunks */ + { + me->this.modify_fn = srgb_modify; + me->this.add = CHUNK_PLTE; + me->intent = intent; + } + + else + { + me->this.modify_fn = 0; + me->this.add = 0; + me->intent = 0; + } + + me->this.next = pm->modifications; + pm->modifications = &me->this; +} + +#ifdef PNG_READ_GAMMA_SUPPORTED +typedef struct sbit_modification +{ + png_modification this; + png_byte sbit; +} sbit_modification; + +static int +sbit_modify(png_modifier *pm, png_modification *me, int add) +{ + png_byte sbit = ((sbit_modification*)me)->sbit; + if (pm->bit_depth > sbit) + { + int cb = 0; + switch (pm->colour_type) + { + case 0: + cb = 1; + break; + + case 2: + case 3: + cb = 3; + break; + + case 4: + cb = 2; + break; + + case 6: + cb = 4; + break; + + default: + png_error(pm->this.pread, + "unexpected colour type in sBIT modification"); + } + + png_save_uint_32(pm->buffer, cb); + png_save_uint_32(pm->buffer+4, CHUNK_sBIT); + + while (cb > 0) + (pm->buffer+8)[--cb] = sbit; + + return 1; + } + else if (!add) + { + /* Remove the sBIT chunk */ + pm->buffer_count = pm->buffer_position = 0; + return 1; + } + else + return 0; /* do nothing */ +} + +static void +sbit_modification_init(sbit_modification *me, png_modifier *pm, png_byte sbit) +{ + modification_init(&me->this); + me->this.chunk = CHUNK_sBIT; + me->this.modify_fn = sbit_modify; + me->this.add = CHUNK_PLTE; + me->sbit = sbit; + me->this.next = pm->modifications; + pm->modifications = &me->this; +} +#endif /* PNG_READ_GAMMA_SUPPORTED */ +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +/***************************** STANDARD PNG FILES *****************************/ +/* Standard files - write and save standard files. */ +/* There are two basic forms of standard images. Those which attempt to have + * all the possible pixel values (not possible for 16bpp images, but a range of + * values are produced) and those which have a range of image sizes. The former + * are used for testing transforms, in particular gamma correction and bit + * reduction and increase. The latter are reserved for testing the behavior of + * libpng with respect to 'odd' image sizes - particularly small images where + * rows become 1 byte and interlace passes disappear. + * + * The first, most useful, set are the 'transform' images, the second set of + * small images are the 'size' images. + * + * The transform files are constructed with rows which fit into a 1024 byte row + * buffer. This makes allocation easier below. Further regardless of the file + * format every row has 128 pixels (giving 1024 bytes for 64bpp formats). + * + * Files are stored with no gAMA or sBIT chunks, with a PLTE only when needed + * and with an ID derived from the colour type, bit depth and interlace type + * as above (FILEID). The width (128) and height (variable) are not stored in + * the FILEID - instead the fields are set to 0, indicating a transform file. + * + * The size files ar constructed with rows a maximum of 128 bytes wide, allowing + * a maximum width of 16 pixels (for the 64bpp case.) They also have a maximum + * height of 16 rows. The width and height are stored in the FILEID and, being + * non-zero, indicate a size file. + * + * Because the PNG filter code is typically the largest CPU consumer within + * libpng itself there is a tendency to attempt to optimize it. This results in + * special case code which needs to be validated. To cause this to happen the + * 'size' images are made to use each possible filter, in so far as this is + * possible for smaller images. + * + * For palette image (colour type 3) multiple transform images are stored with + * the same bit depth to allow testing of more colour combinations - + * particularly important for testing the gamma code because libpng uses a + * different code path for palette images. For size images a single palette is + * used. + */ + +/* Make a 'standard' palette. Because there are only 256 entries in a palette + * (maximum) this actually makes a random palette in the hope that enough tests + * will catch enough errors. (Note that the same palette isn't produced every + * time for the same test - it depends on what previous tests have been run - + * but a given set of arguments to pngvalid will always produce the same palette + * at the same test! This is why pseudo-random number generators are useful for + * testing.) + * + * The store must be open for write when this is called, otherwise an internal + * error will occur. This routine contains its own magic number seed, so the + * palettes generated don't change if there are intervening errors (changing the + * calls to the store_mark seed.) + */ +static store_palette_entry * +make_standard_palette(png_store* ps, int npalette, int do_tRNS) +{ + static png_uint_32 palette_seed[2] = { 0x87654321, 9 }; + + int i = 0; + png_byte values[256][4]; + + /* Always put in black and white plus the six primary and secondary colors. + */ + for (; i<8; ++i) + { + values[i][1] = (png_byte)((i&1) ? 255U : 0U); + values[i][2] = (png_byte)((i&2) ? 255U : 0U); + values[i][3] = (png_byte)((i&4) ? 255U : 0U); + } + + /* Then add 62 grays (one quarter of the remaining 256 slots). */ + { + int j = 0; + png_byte random_bytes[4]; + png_byte need[256]; + + need[0] = 0; /*got black*/ + memset(need+1, 1, (sizeof need)-2); /*need these*/ + need[255] = 0; /*but not white*/ + + while (i<70) + { + png_byte b; + + if (j==0) + { + make_four_random_bytes(palette_seed, random_bytes); + j = 4; + } + + b = random_bytes[--j]; + if (need[b]) + { + values[i][1] = b; + values[i][2] = b; + values[i++][3] = b; + } + } + } + + /* Finally add 192 colors at random - don't worry about matches to things we + * already have, chance is less than 1/65536. Don't worry about grays, + * chance is the same, so we get a duplicate or extra gray less than 1 time + * in 170. + */ + for (; i<256; ++i) + make_four_random_bytes(palette_seed, values[i]); + + /* Fill in the alpha values in the first byte. Just use all possible values + * (0..255) in an apparently random order: + */ + { + store_palette_entry *palette; + png_byte selector[4]; + + make_four_random_bytes(palette_seed, selector); + + if (do_tRNS) + for (i=0; i<256; ++i) + values[i][0] = (png_byte)(i ^ selector[0]); + + else + for (i=0; i<256; ++i) + values[i][0] = 255; /* no transparency/tRNS chunk */ + + /* 'values' contains 256 ARGB values, but we only need 'npalette'. + * 'npalette' will always be a power of 2: 2, 4, 16 or 256. In the low + * bit depth cases select colors at random, else it is difficult to have + * a set of low bit depth palette test with any chance of a reasonable + * range of colors. Do this by randomly permuting values into the low + * 'npalette' entries using an XOR mask generated here. This also + * permutes the npalette == 256 case in a potentially useful way (there is + * no relationship between palette index and the color value therein!) + */ + palette = store_write_palette(ps, npalette); + + for (i=0; i 0) + png_set_tRNS(pp, pi, tRNS, j, 0/*color*/); +#endif + } +} + +#ifdef PNG_WRITE_tRNS_SUPPORTED +static void +set_random_tRNS(png_structp pp, png_infop pi, png_byte colour_type, + int bit_depth) +{ + /* To make this useful the tRNS color needs to match at least one pixel. + * Random values are fine for gray, including the 16-bit case where we know + * that the test image contains all the gray values. For RGB we need more + * method as only 65536 different RGB values are generated. + */ + png_color_16 tRNS; + png_uint_16 mask = (png_uint_16)((1U << bit_depth)-1); + + R8(tRNS); /* makes unset fields random */ + + if (colour_type & 2/*RGB*/) + { + if (bit_depth == 8) + { + tRNS.red = random_u16(); + tRNS.green = random_u16(); + tRNS.blue = tRNS.red ^ tRNS.green; + tRNS.red &= mask; + tRNS.green &= mask; + tRNS.blue &= mask; + } + + else /* bit_depth == 16 */ + { + tRNS.red = random_u16(); + tRNS.green = (png_uint_16)(tRNS.red * 257); + tRNS.blue = (png_uint_16)(tRNS.green * 17); + } + } + + else + { + tRNS.gray = random_u16(); + tRNS.gray &= mask; + } + + png_set_tRNS(pp, pi, NULL, 0, &tRNS); +} +#endif + +/* The number of passes is related to the interlace type. There was no libpng + * API to determine this prior to 1.5, so we need an inquiry function: + */ +static int +npasses_from_interlace_type(png_const_structp pp, int interlace_type) +{ + switch (interlace_type) + { + default: + png_error(pp, "invalid interlace type"); + + case PNG_INTERLACE_NONE: + return 1; + + case PNG_INTERLACE_ADAM7: + return PNG_INTERLACE_ADAM7_PASSES; + } +} + +static unsigned int +bit_size(png_const_structp pp, png_byte colour_type, png_byte bit_depth) +{ + switch (colour_type) + { + default: png_error(pp, "invalid color type"); + + case 0: return bit_depth; + + case 2: return 3*bit_depth; + + case 3: return bit_depth; + + case 4: return 2*bit_depth; + + case 6: return 4*bit_depth; + } +} + +#define TRANSFORM_WIDTH 128U +#define TRANSFORM_ROWMAX (TRANSFORM_WIDTH*8U) +#define SIZE_ROWMAX (16*8U) /* 16 pixels, max 8 bytes each - 128 bytes */ +#define STANDARD_ROWMAX TRANSFORM_ROWMAX /* The larger of the two */ +#define SIZE_HEIGHTMAX 16 /* Maximum range of size images */ + +static size_t +transform_rowsize(png_const_structp pp, png_byte colour_type, + png_byte bit_depth) +{ + return (TRANSFORM_WIDTH * bit_size(pp, colour_type, bit_depth)) / 8; +} + +/* transform_width(pp, colour_type, bit_depth) current returns the same number + * every time, so just use a macro: + */ +#define transform_width(pp, colour_type, bit_depth) TRANSFORM_WIDTH + +static png_uint_32 +transform_height(png_const_structp pp, png_byte colour_type, png_byte bit_depth) +{ + switch (bit_size(pp, colour_type, bit_depth)) + { + case 1: + case 2: + case 4: + return 1; /* Total of 128 pixels */ + + case 8: + return 2; /* Total of 256 pixels/bytes */ + + case 16: + return 512; /* Total of 65536 pixels */ + + case 24: + case 32: + return 512; /* 65536 pixels */ + + case 48: + case 64: + return 2048;/* 4 x 65536 pixels. */ +# define TRANSFORM_HEIGHTMAX 2048 + + default: + return 0; /* Error, will be caught later */ + } +} + +#ifdef PNG_READ_SUPPORTED +/* The following can only be defined here, now we have the definitions + * of the transform image sizes. + */ +static png_uint_32 +standard_width(png_const_structp pp, png_uint_32 id) +{ + png_uint_32 width = WIDTH_FROM_ID(id); + UNUSED(pp) + + if (width == 0) + width = transform_width(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + + return width; +} + +static png_uint_32 +standard_height(png_const_structp pp, png_uint_32 id) +{ + png_uint_32 height = HEIGHT_FROM_ID(id); + + if (height == 0) + height = transform_height(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + + return height; +} + +static png_uint_32 +standard_rowsize(png_const_structp pp, png_uint_32 id) +{ + png_uint_32 width = standard_width(pp, id); + + /* This won't overflow: */ + width *= bit_size(pp, COL_FROM_ID(id), DEPTH_FROM_ID(id)); + return (width + 7) / 8; +} +#endif /* PNG_READ_SUPPORTED */ + +static void +transform_row(png_const_structp pp, png_byte buffer[TRANSFORM_ROWMAX], + png_byte colour_type, png_byte bit_depth, png_uint_32 y) +{ + png_uint_32 v = y << 7; + png_uint_32 i = 0; + + switch (bit_size(pp, colour_type, bit_depth)) + { + case 1: + while (i<128/8) buffer[i] = (png_byte)(v & 0xff), v += 17, ++i; + return; + + case 2: + while (i<128/4) buffer[i] = (png_byte)(v & 0xff), v += 33, ++i; + return; + + case 4: + while (i<128/2) buffer[i] = (png_byte)(v & 0xff), v += 65, ++i; + return; + + case 8: + /* 256 bytes total, 128 bytes in each row set as follows: */ + while (i<128) buffer[i] = (png_byte)(v & 0xff), ++v, ++i; + return; + + case 16: + /* Generate all 65536 pixel values in order, which includes the 8 bit + * GA case as well as the 16 bit G case. + */ + while (i<128) + { + buffer[2*i] = (png_byte)((v>>8) & 0xff); + buffer[2*i+1] = (png_byte)(v & 0xff); + ++v; + ++i; + } + + return; + + case 24: + /* 65535 pixels, but rotate the values. */ + while (i<128) + { + /* Three bytes per pixel, r, g, b, make b by r^g */ + buffer[3*i+0] = (png_byte)((v >> 8) & 0xff); + buffer[3*i+1] = (png_byte)(v & 0xff); + buffer[3*i+2] = (png_byte)(((v >> 8) ^ v) & 0xff); + ++v; + ++i; + } + + return; + + case 32: + /* 65535 pixels, r, g, b, a; just replicate */ + while (i<128) + { + buffer[4*i+0] = (png_byte)((v >> 8) & 0xff); + buffer[4*i+1] = (png_byte)(v & 0xff); + buffer[4*i+2] = (png_byte)((v >> 8) & 0xff); + buffer[4*i+3] = (png_byte)(v & 0xff); + ++v; + ++i; + } + + return; + + case 48: + /* y is maximum 2047, giving 4x65536 pixels, make 'r' increase by 1 at + * each pixel, g increase by 257 (0x101) and 'b' by 0x1111: + */ + while (i<128) + { + png_uint_32 t = v++; + buffer[6*i+0] = (png_byte)((t >> 8) & 0xff); + buffer[6*i+1] = (png_byte)(t & 0xff); + t *= 257; + buffer[6*i+2] = (png_byte)((t >> 8) & 0xff); + buffer[6*i+3] = (png_byte)(t & 0xff); + t *= 17; + buffer[6*i+4] = (png_byte)((t >> 8) & 0xff); + buffer[6*i+5] = (png_byte)(t & 0xff); + ++i; + } + + return; + + case 64: + /* As above in the 32 bit case. */ + while (i<128) + { + png_uint_32 t = v++; + buffer[8*i+0] = (png_byte)((t >> 8) & 0xff); + buffer[8*i+1] = (png_byte)(t & 0xff); + buffer[8*i+4] = (png_byte)((t >> 8) & 0xff); + buffer[8*i+5] = (png_byte)(t & 0xff); + t *= 257; + buffer[8*i+2] = (png_byte)((t >> 8) & 0xff); + buffer[8*i+3] = (png_byte)(t & 0xff); + buffer[8*i+6] = (png_byte)((t >> 8) & 0xff); + buffer[8*i+7] = (png_byte)(t & 0xff); + ++i; + } + return; + + default: + break; + } + + png_error(pp, "internal error"); +} + +/* This is just to do the right cast - could be changed to a function to check + * 'bd' but there isn't much point. + */ +#define DEPTH(bd) ((png_byte)(1U << (bd))) + +/* This is just a helper for compiling on minimal systems with no write + * interlacing support. If there is no write interlacing we can't generate test + * cases with interlace: + */ +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +# define INTERLACE_LAST PNG_INTERLACE_LAST +# define check_interlace_type(type) ((void)(type)) +# define set_write_interlace_handling(pp,type) png_set_interlace_handling(pp) +# define do_own_interlace 0 +#elif PNG_LIBPNG_VER < 10700 +# define set_write_interlace_handling(pp,type) (1) +static void +check_interlace_type(int const interlace_type) +{ + /* Prior to 1.7.0 libpng does not support the write of an interlaced image + * unless PNG_WRITE_INTERLACING_SUPPORTED, even with do_interlace so the + * code here does the pixel interlace itself, so: + */ + if (interlace_type != PNG_INTERLACE_NONE) + { + /* This is an internal error - --interlace tests should be skipped, not + * attempted. + */ + fprintf(stderr, "pngvalid: no interlace support\n"); + exit(99); + } +} +# define INTERLACE_LAST (PNG_INTERLACE_NONE+1) +# define do_own_interlace 0 +#else /* libpng 1.7+ */ +# define set_write_interlace_handling(pp,type)\ + npasses_from_interlace_type(pp,type) +# define check_interlace_type(type) ((void)(type)) +# define INTERLACE_LAST PNG_INTERLACE_LAST +# define do_own_interlace 1 +#endif /* WRITE_INTERLACING tests */ + +#if PNG_LIBPNG_VER >= 10700 || defined PNG_WRITE_INTERLACING_SUPPORTED +# define CAN_WRITE_INTERLACE 1 +#else +# define CAN_WRITE_INTERLACE 0 +#endif + +/* Do the same thing for read interlacing; this controls whether read tests do + * their own de-interlace or use libpng. + */ +#ifdef PNG_READ_INTERLACING_SUPPORTED +# define do_read_interlace 0 +#else /* no libpng read interlace support */ +# define do_read_interlace 1 +#endif +/* The following two routines use the PNG interlace support macros from + * png.h to interlace or deinterlace rows. + */ +static void +interlace_row(png_bytep buffer, png_const_bytep imageRow, + unsigned int pixel_size, png_uint_32 w, int pass, int littleendian) +{ + png_uint_32 xin, xout, xstep; + + /* Note that this can, trivially, be optimized to a memcpy on pass 7, the + * code is presented this way to make it easier to understand. In practice + * consult the code in the libpng source to see other ways of doing this. + * + * It is OK for buffer and imageRow to be identical, because 'xin' moves + * faster than 'xout' and we copy up. + */ + xin = PNG_PASS_START_COL(pass); + xstep = 1U<wname); + text.text = copy; + text.text_length = pos; + text.itxt_length = 0; + text.lang = 0; + text.lang_key = 0; + + png_set_text(pp, pi, &text, 1); + } +#endif + + if (colour_type == 3) /* palette */ + init_standard_palette(ps, pp, pi, 1U << bit_depth, 1/*do tRNS*/); + +# ifdef PNG_WRITE_tRNS_SUPPORTED + else if (palette_number) + set_random_tRNS(pp, pi, colour_type, bit_depth); +# endif + + png_write_info(pp, pi); + + if (png_get_rowbytes(pp, pi) != + transform_rowsize(pp, colour_type, bit_depth)) + png_error(pp, "transform row size incorrect"); + + else + { + /* Somewhat confusingly this must be called *after* png_write_info + * because if it is called before, the information in *pp has not been + * updated to reflect the interlaced image. + */ + int npasses = set_write_interlace_handling(pp, interlace_type); + int pass; + + if (npasses != npasses_from_interlace_type(pp, interlace_type)) + png_error(pp, "write: png_set_interlace_handling failed"); + + for (pass=0; pass 0) + interlace_row(buffer, buffer, + bit_size(pp, colour_type, bit_depth), w, pass, + 0/*data always bigendian*/); + else + continue; + } +# endif /* do_own_interlace */ + + choose_random_filter(pp, pass == 0 && y == 0); + png_write_row(pp, buffer); + } + } + } + +#ifdef PNG_TEXT_SUPPORTED + { + static char key[] = "end marker"; + static char comment[] = "end"; + png_text text; + + /* Use a compressed text string to test the correct interaction of text + * compression and IDAT compression. + */ + text.compression = TEXT_COMPRESSION; + text.key = key; + text.text = comment; + text.text_length = (sizeof comment)-1; + text.itxt_length = 0; + text.lang = 0; + text.lang_key = 0; + + png_set_text(pp, pi, &text, 1); + } +#endif + + png_write_end(pp, pi); + + /* And store this under the appropriate id, then clean up. */ + store_storefile(ps, FILEID(colour_type, bit_depth, palette_number, + interlace_type, 0, 0, 0)); + + store_write_reset(ps); + } + + Catch(fault) + { + /* Use the png_store returned by the exception. This may help the compiler + * because 'ps' is not used in this branch of the setjmp. Note that fault + * and ps will always be the same value. + */ + store_write_reset(fault); + } +} + +static void +make_transform_images(png_modifier *pm) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + unsigned int palette_number = 0; + + /* This is in case of errors. */ + safecat(pm->this.test, sizeof pm->this.test, 0, "make standard images"); + + /* Use next_format to enumerate all the combinations we test, including + * generating multiple low bit depth palette images. Non-A images (palette + * and direct) are created with and without tRNS chunks. + */ + while (next_format(&colour_type, &bit_depth, &palette_number, 1, 1)) + { + int interlace_type; + + for (interlace_type = PNG_INTERLACE_NONE; + interlace_type < INTERLACE_LAST; ++interlace_type) + { + char name[FILE_NAME_SIZE]; + + standard_name(name, sizeof name, 0, colour_type, bit_depth, + palette_number, interlace_type, 0, 0, do_own_interlace); + make_transform_image(&pm->this, colour_type, bit_depth, palette_number, + interlace_type, name); + } + } +} + +/* Build a single row for the 'size' test images; this fills in only the + * first bit_width bits of the sample row. + */ +static void +size_row(png_byte buffer[SIZE_ROWMAX], png_uint_32 bit_width, png_uint_32 y) +{ + /* height is in the range 1 to 16, so: */ + y = ((y & 1) << 7) + ((y & 2) << 6) + ((y & 4) << 5) + ((y & 8) << 4); + /* the following ensures bits are set in small images: */ + y ^= 0xA5; + + while (bit_width >= 8) + *buffer++ = (png_byte)y++, bit_width -= 8; + + /* There may be up to 7 remaining bits, these go in the most significant + * bits of the byte. + */ + if (bit_width > 0) + { + png_uint_32 mask = (1U<<(8-bit_width))-1; + *buffer = (png_byte)((*buffer & mask) | (y & ~mask)); + } +} + +static void +make_size_image(png_store* const ps, png_byte const colour_type, + png_byte const bit_depth, int const interlace_type, + png_uint_32 const w, png_uint_32 const h, + int const do_interlace) +{ + context(ps, fault); + + check_interlace_type(interlace_type); + + Try + { + png_infop pi; + png_structp pp; + unsigned int pixel_size; + + /* Make a name and get an appropriate id for the store: */ + char name[FILE_NAME_SIZE]; + png_uint_32 id = FILEID(colour_type, bit_depth, 0/*palette*/, + interlace_type, w, h, do_interlace); + + standard_name_from_id(name, sizeof name, 0, id); + pp = set_store_for_write(ps, &pi, name); + + /* In the event of a problem return control to the Catch statement below + * to do the clean up - it is not possible to 'return' directly from a Try + * block. + */ + if (pp == NULL) + Throw ps; + + png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + +#ifdef PNG_TEXT_SUPPORTED + { + static char key[] = "image name"; /* must be writeable */ + size_t pos; + png_text text; + char copy[FILE_NAME_SIZE]; + + /* Use a compressed text string to test the correct interaction of text + * compression and IDAT compression. + */ + text.compression = TEXT_COMPRESSION; + text.key = key; + /* Yuck: the text must be writable! */ + pos = safecat(copy, sizeof copy, 0, ps->wname); + text.text = copy; + text.text_length = pos; + text.itxt_length = 0; + text.lang = 0; + text.lang_key = 0; + + png_set_text(pp, pi, &text, 1); + } +#endif + + if (colour_type == 3) /* palette */ + init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/); + + png_write_info(pp, pi); + + /* Calculate the bit size, divide by 8 to get the byte size - this won't + * overflow because we know the w values are all small enough even for + * a system where 'unsigned int' is only 16 bits. + */ + pixel_size = bit_size(pp, colour_type, bit_depth); + if (png_get_rowbytes(pp, pi) != ((w * pixel_size) + 7) / 8) + png_error(pp, "size row size incorrect"); + + else + { + int npasses = npasses_from_interlace_type(pp, interlace_type); + png_uint_32 y; + int pass; + png_byte image[16][SIZE_ROWMAX]; + + /* To help consistent error detection make the parts of this buffer + * that aren't set below all '1': + */ + memset(image, 0xff, sizeof image); + + if (!do_interlace && + npasses != set_write_interlace_handling(pp, interlace_type)) + png_error(pp, "write: png_set_interlace_handling failed"); + + /* Prepare the whole image first to avoid making it 7 times: */ + for (y=0; y 0) + { + /* Set to all 1's for error detection (libpng tends to + * set unset things to 0). + */ + memset(tempRow, 0xff, sizeof tempRow); + interlace_row(tempRow, row, pixel_size, w, pass, + 0/*data always bigendian*/); + row = tempRow; + } + else + continue; + } + +# ifdef PNG_WRITE_FILTER_SUPPORTED + /* Only get to here if the row has some pixels in it, set the + * filters to 'all' for the very first row and thereafter to a + * single filter. It isn't well documented, but png_set_filter + * does accept a filter number (per the spec) as well as a bit + * mask. + * + * The code now uses filters at random, except that on the first + * row of an image it ensures that a previous row filter is in + * the set so that libpng allocates the row buffer. + */ + { + int filters = 8 << random_mod(PNG_FILTER_VALUE_LAST); + + if (pass == 0 && y == 0 && + (filters < PNG_FILTER_UP || w == 1U)) + filters |= PNG_FILTER_UP; + + png_set_filter(pp, 0/*method*/, filters); + } +# endif + + png_write_row(pp, row); + } + } + } + +#ifdef PNG_TEXT_SUPPORTED + { + static char key[] = "end marker"; + static char comment[] = "end"; + png_text text; + + /* Use a compressed text string to test the correct interaction of text + * compression and IDAT compression. + */ + text.compression = TEXT_COMPRESSION; + text.key = key; + text.text = comment; + text.text_length = (sizeof comment)-1; + text.itxt_length = 0; + text.lang = 0; + text.lang_key = 0; + + png_set_text(pp, pi, &text, 1); + } +#endif + + png_write_end(pp, pi); + + /* And store this under the appropriate id, then clean up. */ + store_storefile(ps, id); + + store_write_reset(ps); + } + + Catch(fault) + { + /* Use the png_store returned by the exception. This may help the compiler + * because 'ps' is not used in this branch of the setjmp. Note that fault + * and ps will always be the same value. + */ + store_write_reset(fault); + } +} + +static void +make_size(png_store* const ps, png_byte const colour_type, int bdlo, + int const bdhi) +{ + for (; bdlo <= bdhi; ++bdlo) + { + png_uint_32 width; + + for (width = 1; width <= 16; ++width) + { + png_uint_32 height; + + for (height = 1; height <= 16; ++height) + { + /* The four combinations of DIY interlace and interlace or not - + * no interlace + DIY should be identical to no interlace with + * libpng doing it. + */ + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, + width, height, 0); + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_NONE, + width, height, 1); +# ifdef PNG_WRITE_INTERLACING_SUPPORTED + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, + width, height, 0); +# endif +# if CAN_WRITE_INTERLACE + /* 1.7.0 removes the hack that prevented app write of an interlaced + * image if WRITE_INTERLACE was not supported + */ + make_size_image(ps, colour_type, DEPTH(bdlo), PNG_INTERLACE_ADAM7, + width, height, 1); +# endif + } + } + } +} + +static void +make_size_images(png_store *ps) +{ + /* This is in case of errors. */ + safecat(ps->test, sizeof ps->test, 0, "make size images"); + + /* Arguments are colour_type, low bit depth, high bit depth + */ + make_size(ps, 0, 0, WRITE_BDHI); + make_size(ps, 2, 3, WRITE_BDHI); + make_size(ps, 3, 0, 3 /*palette: max 8 bits*/); + make_size(ps, 4, 3, WRITE_BDHI); + make_size(ps, 6, 3, WRITE_BDHI); +} + +#ifdef PNG_READ_SUPPORTED +/* Return a row based on image id and 'y' for checking: */ +static void +standard_row(png_const_structp pp, png_byte std[STANDARD_ROWMAX], + png_uint_32 id, png_uint_32 y) +{ + if (WIDTH_FROM_ID(id) == 0) + transform_row(pp, std, COL_FROM_ID(id), DEPTH_FROM_ID(id), y); + else + size_row(std, WIDTH_FROM_ID(id) * bit_size(pp, COL_FROM_ID(id), + DEPTH_FROM_ID(id)), y); +} +#endif /* PNG_READ_SUPPORTED */ + +/* Tests - individual test cases */ +/* Like 'make_standard' but errors are deliberately introduced into the calls + * to ensure that they get detected - it should not be possible to write an + * invalid image with libpng! + */ +/* TODO: the 'set' functions can probably all be made to take a + * png_const_structp rather than a modifiable one. + */ +#ifdef PNG_WARNINGS_SUPPORTED +static void +sBIT0_error_fn(png_structp pp, png_infop pi) +{ + /* 0 is invalid... */ + png_color_8 bad; + bad.red = bad.green = bad.blue = bad.gray = bad.alpha = 0; + png_set_sBIT(pp, pi, &bad); +} + +static void +sBIT_error_fn(png_structp pp, png_infop pi) +{ + png_byte bit_depth; + png_color_8 bad; + + if (png_get_color_type(pp, pi) == PNG_COLOR_TYPE_PALETTE) + bit_depth = 8; + + else + bit_depth = png_get_bit_depth(pp, pi); + + /* Now we know the bit depth we can easily generate an invalid sBIT entry */ + bad.red = bad.green = bad.blue = bad.gray = bad.alpha = + (png_byte)(bit_depth+1); + png_set_sBIT(pp, pi, &bad); +} + +static const struct +{ + void (*fn)(png_structp, png_infop); + const char *msg; + unsigned int warning :1; /* the error is a warning... */ +} error_test[] = + { + /* no warnings makes these errors undetectable prior to 1.7.0 */ + { sBIT0_error_fn, "sBIT(0): failed to detect error", + PNG_LIBPNG_VER < 10700 }, + + { sBIT_error_fn, "sBIT(too big): failed to detect error", + PNG_LIBPNG_VER < 10700 }, + }; + +static void +make_error(png_store* const ps, png_byte const colour_type, + png_byte bit_depth, int interlace_type, int test, png_const_charp name) +{ + context(ps, fault); + + check_interlace_type(interlace_type); + + Try + { + png_infop pi; + png_structp pp = set_store_for_write(ps, &pi, name); + png_uint_32 w, h; + gnu_volatile(pp) + + if (pp == NULL) + Throw ps; + + w = transform_width(pp, colour_type, bit_depth); + gnu_volatile(w) + h = transform_height(pp, colour_type, bit_depth); + gnu_volatile(h) + png_set_IHDR(pp, pi, w, h, bit_depth, colour_type, interlace_type, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + if (colour_type == 3) /* palette */ + init_standard_palette(ps, pp, pi, 1U << bit_depth, 0/*do tRNS*/); + + /* Time for a few errors; these are in various optional chunks, the + * standard tests test the standard chunks pretty well. + */ +# define exception__prev exception_prev_1 +# define exception__env exception_env_1 + Try + { + gnu_volatile(exception__prev) + + /* Expect this to throw: */ + ps->expect_error = !error_test[test].warning; + ps->expect_warning = error_test[test].warning; + ps->saw_warning = 0; + error_test[test].fn(pp, pi); + + /* Normally the error is only detected here: */ + png_write_info(pp, pi); + + /* And handle the case where it was only a warning: */ + if (ps->expect_warning && ps->saw_warning) + Throw ps; + + /* If we get here there is a problem, we have success - no error or + * no warning - when we shouldn't have success. Log an error. + */ + store_log(ps, pp, error_test[test].msg, 1 /*error*/); + } + + Catch (fault) + { /* expected exit */ + } +#undef exception__prev +#undef exception__env + + /* And clear these flags */ + ps->expect_warning = 0; + + if (ps->expect_error) + ps->expect_error = 0; + + else + { + /* Now write the whole image, just to make sure that the detected, or + * undetected, error has not created problems inside libpng. This + * doesn't work if there was a png_error in png_write_info because that + * can abort before PLTE was written. + */ + if (png_get_rowbytes(pp, pi) != + transform_rowsize(pp, colour_type, bit_depth)) + png_error(pp, "row size incorrect"); + + else + { + int npasses = set_write_interlace_handling(pp, interlace_type); + int pass; + + if (npasses != npasses_from_interlace_type(pp, interlace_type)) + png_error(pp, "write: png_set_interlace_handling failed"); + + for (pass=0; pass 0) + interlace_row(buffer, buffer, + bit_size(pp, colour_type, bit_depth), w, pass, + 0/*data always bigendian*/); + else + continue; + } +# endif /* do_own_interlace */ + + png_write_row(pp, buffer); + } + } + } /* image writing */ + + png_write_end(pp, pi); + } + + /* The following deletes the file that was just written. */ + store_write_reset(ps); + } + + Catch(fault) + { + store_write_reset(fault); + } +} + +static int +make_errors(png_modifier* const pm, png_byte const colour_type, + int bdlo, int const bdhi) +{ + for (; bdlo <= bdhi; ++bdlo) + { + int interlace_type; + + for (interlace_type = PNG_INTERLACE_NONE; + interlace_type < INTERLACE_LAST; ++interlace_type) + { + unsigned int test; + char name[FILE_NAME_SIZE]; + + standard_name(name, sizeof name, 0, colour_type, 1<this, colour_type, DEPTH(bdlo), interlace_type, + test, name); + + if (fail(pm)) + return 0; + } + } + } + + return 1; /* keep going */ +} +#endif /* PNG_WARNINGS_SUPPORTED */ + +static void +perform_error_test(png_modifier *pm) +{ +#ifdef PNG_WARNINGS_SUPPORTED /* else there are no cases that work! */ + /* Need to do this here because we just write in this test. */ + safecat(pm->this.test, sizeof pm->this.test, 0, "error test"); + + if (!make_errors(pm, 0, 0, WRITE_BDHI)) + return; + + if (!make_errors(pm, 2, 3, WRITE_BDHI)) + return; + + if (!make_errors(pm, 3, 0, 3)) + return; + + if (!make_errors(pm, 4, 3, WRITE_BDHI)) + return; + + if (!make_errors(pm, 6, 3, WRITE_BDHI)) + return; +#else + UNUSED(pm) +#endif +} + +/* This is just to validate the internal PNG formatting code - if this fails + * then the warning messages the library outputs will probably be garbage. + */ +static void +perform_formatting_test(png_store *ps) +{ +#ifdef PNG_TIME_RFC1123_SUPPORTED + /* The handle into the formatting code is the RFC1123 support; this test does + * nothing if that is compiled out. + */ + context(ps, fault); + + Try + { + png_const_charp correct = "29 Aug 2079 13:53:60 +0000"; + png_const_charp result; +# if PNG_LIBPNG_VER >= 10600 + char timestring[29]; +# endif + png_structp pp; + png_time pt; + + pp = set_store_for_write(ps, NULL, "libpng formatting test"); + + if (pp == NULL) + Throw ps; + + + /* Arbitrary settings: */ + pt.year = 2079; + pt.month = 8; + pt.day = 29; + pt.hour = 13; + pt.minute = 53; + pt.second = 60; /* a leap second */ + +# if PNG_LIBPNG_VER < 10600 + result = png_convert_to_rfc1123(pp, &pt); +# else + if (png_convert_to_rfc1123_buffer(timestring, &pt)) + result = timestring; + + else + result = NULL; +# endif + + if (result == NULL) + png_error(pp, "png_convert_to_rfc1123 failed"); + + if (strcmp(result, correct) != 0) + { + size_t pos = 0; + char msg[128]; + + pos = safecat(msg, sizeof msg, pos, "png_convert_to_rfc1123("); + pos = safecat(msg, sizeof msg, pos, correct); + pos = safecat(msg, sizeof msg, pos, ") returned: '"); + pos = safecat(msg, sizeof msg, pos, result); + pos = safecat(msg, sizeof msg, pos, "'"); + + png_error(pp, msg); + } + + store_write_reset(ps); + } + + Catch(fault) + { + store_write_reset(fault); + } +#else + UNUSED(ps) +#endif +} + +#ifdef PNG_READ_SUPPORTED +/* Because we want to use the same code in both the progressive reader and the + * sequential reader it is necessary to deal with the fact that the progressive + * reader callbacks only have one parameter (png_get_progressive_ptr()), so this + * must contain all the test parameters and all the local variables directly + * accessible to the sequential reader implementation. + * + * The technique adopted is to reinvent part of what Dijkstra termed a + * 'display'; an array of pointers to the stack frames of enclosing functions so + * that a nested function definition can access the local (C auto) variables of + * the functions that contain its definition. In fact C provides the first + * pointer (the local variables - the stack frame pointer) and the last (the + * global variables - the BCPL global vector typically implemented as global + * addresses), this code requires one more pointer to make the display - the + * local variables (and function call parameters) of the function that actually + * invokes either the progressive or sequential reader. + * + * Perhaps confusingly this technique is confounded with classes - the + * 'standard_display' defined here is sub-classed as the 'gamma_display' below. + * A gamma_display is a standard_display, taking advantage of the ANSI-C + * requirement that the pointer to the first member of a structure must be the + * same as the pointer to the structure. This allows us to reuse standard_ + * functions in the gamma test code; something that could not be done with + * nested functions! + */ +typedef struct standard_display +{ + png_store* ps; /* Test parameters (passed to the function) */ + png_byte colour_type; + png_byte bit_depth; + png_byte red_sBIT; /* Input data sBIT values. */ + png_byte green_sBIT; + png_byte blue_sBIT; + png_byte alpha_sBIT; + png_byte interlace_type; + png_byte filler; /* Output has a filler */ + png_uint_32 id; /* Calculated file ID */ + png_uint_32 w; /* Width of image */ + png_uint_32 h; /* Height of image */ + int npasses; /* Number of interlaced passes */ + png_uint_32 pixel_size; /* Width of one pixel in bits */ + png_uint_32 bit_width; /* Width of output row in bits */ + size_t cbRow; /* Bytes in a row of the output image */ + int do_interlace; /* Do interlacing internally */ + int littleendian; /* App (row) data is little endian */ + int is_transparent; /* Transparency information was present. */ + int has_tRNS; /* color type GRAY or RGB with a tRNS chunk. */ + int speed; /* Doing a speed test */ + int use_update_info;/* Call update_info, not start_image */ + struct + { + png_uint_16 red; + png_uint_16 green; + png_uint_16 blue; + } transparent; /* The transparent color, if set. */ + int npalette; /* Number of entries in the palette. */ + store_palette + palette; +} standard_display; + +static void +standard_display_init(standard_display *dp, png_store* ps, png_uint_32 id, + int do_interlace, int use_update_info) +{ + memset(dp, 0, sizeof *dp); + + dp->ps = ps; + dp->colour_type = COL_FROM_ID(id); + dp->bit_depth = DEPTH_FROM_ID(id); + if (dp->bit_depth < 1 || dp->bit_depth > 16) + internal_error(ps, "internal: bad bit depth"); + if (dp->colour_type == 3) + dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8; + else + dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = + dp->bit_depth; + dp->interlace_type = INTERLACE_FROM_ID(id); + check_interlace_type(dp->interlace_type); + dp->id = id; + /* All the rest are filled in after the read_info: */ + dp->w = 0; + dp->h = 0; + dp->npasses = 0; + dp->pixel_size = 0; + dp->bit_width = 0; + dp->cbRow = 0; + dp->do_interlace = do_interlace; + dp->littleendian = 0; + dp->is_transparent = 0; + dp->speed = ps->speed; + dp->use_update_info = use_update_info; + dp->npalette = 0; + /* Preset the transparent color to black: */ + memset(&dp->transparent, 0, sizeof dp->transparent); + /* Preset the palette to full intensity/opaque throughout: */ + memset(dp->palette, 0xff, sizeof dp->palette); +} + +/* Initialize the palette fields - this must be done later because the palette + * comes from the particular png_store_file that is selected. + */ +static void +standard_palette_init(standard_display *dp) +{ + store_palette_entry *palette = store_current_palette(dp->ps, &dp->npalette); + + /* The remaining entries remain white/opaque. */ + if (dp->npalette > 0) + { + int i = dp->npalette; + memcpy(dp->palette, palette, i * sizeof *palette); + + /* Check for a non-opaque palette entry: */ + while (--i >= 0) + if (palette[i].alpha < 255) + break; + +# ifdef __GNUC__ + /* GCC can't handle the more obviously optimizable version. */ + if (i >= 0) + dp->is_transparent = 1; + else + dp->is_transparent = 0; +# else + dp->is_transparent = (i >= 0); +# endif + } +} + +/* Utility to read the palette from the PNG file and convert it into + * store_palette format. This returns 1 if there is any transparency in the + * palette (it does not check for a transparent colour in the non-palette case.) + */ +static int +read_palette(store_palette palette, int *npalette, png_const_structp pp, + png_infop pi) +{ + png_colorp pal; + png_bytep trans_alpha; + int num; + + pal = 0; + *npalette = -1; + + if (png_get_PLTE(pp, pi, &pal, npalette) & PNG_INFO_PLTE) + { + int i = *npalette; + + if (i <= 0 || i > 256) + png_error(pp, "validate: invalid PLTE count"); + + while (--i >= 0) + { + palette[i].red = pal[i].red; + palette[i].green = pal[i].green; + palette[i].blue = pal[i].blue; + } + + /* Mark the remainder of the entries with a flag value (other than + * white/opaque which is the flag value stored above.) + */ + memset(palette + *npalette, 126, (256-*npalette) * sizeof *palette); + } + + else /* !png_get_PLTE */ + { + if (*npalette != (-1)) + png_error(pp, "validate: invalid PLTE result"); + /* But there is no palette, so record this: */ + *npalette = 0; + memset(palette, 113, sizeof (store_palette)); + } + + trans_alpha = 0; + num = 2; /* force error below */ + if ((png_get_tRNS(pp, pi, &trans_alpha, &num, 0) & PNG_INFO_tRNS) != 0 && + (trans_alpha != NULL || num != 1/*returns 1 for a transparent color*/) && + /* Oops, if a palette tRNS gets expanded png_read_update_info (at least so + * far as 1.5.4) does not remove the trans_alpha pointer, only num_trans, + * so in the above call we get a success, we get a pointer (who knows what + * to) and we get num_trans == 0: + */ + !(trans_alpha != NULL && num == 0)) /* TODO: fix this in libpng. */ + { + int i; + + /* Any of these are crash-worthy - given the implementation of + * png_get_tRNS up to 1.5 an app won't crash if it just checks the + * result above and fails to check that the variables it passed have + * actually been filled in! Note that if the app were to pass the + * last, png_color_16p, variable too it couldn't rely on this. + */ + if (trans_alpha == NULL || num <= 0 || num > 256 || num > *npalette) + png_error(pp, "validate: unexpected png_get_tRNS (palette) result"); + + for (i=0; iis_transparent) + png_error(pp, "validate: palette transparency changed"); + + if (npalette != dp->npalette) + { + size_t pos = 0; + char msg[64]; + + pos = safecat(msg, sizeof msg, pos, "validate: palette size changed: "); + pos = safecatn(msg, sizeof msg, pos, dp->npalette); + pos = safecat(msg, sizeof msg, pos, " -> "); + pos = safecatn(msg, sizeof msg, pos, npalette); + png_error(pp, msg); + } + + { + int i = npalette; /* npalette is aliased */ + + while (--i >= 0) + if (palette[i].red != dp->palette[i].red || + palette[i].green != dp->palette[i].green || + palette[i].blue != dp->palette[i].blue || + palette[i].alpha != dp->palette[i].alpha) + png_error(pp, "validate: PLTE or tRNS chunk changed"); + } +} + +/* By passing a 'standard_display' the progressive callbacks can be used + * directly by the sequential code, the functions suffixed "_imp" are the + * implementations, the functions without the suffix are the callbacks. + * + * The code for the info callback is split into two because this callback calls + * png_read_update_info or png_start_read_image and what gets called depends on + * whether the info needs updating (we want to test both calls in pngvalid.) + */ +static void +standard_info_part1(standard_display *dp, png_structp pp, png_infop pi) +{ + if (png_get_bit_depth(pp, pi) != dp->bit_depth) + png_error(pp, "validate: bit depth changed"); + + if (png_get_color_type(pp, pi) != dp->colour_type) + png_error(pp, "validate: color type changed"); + + if (png_get_filter_type(pp, pi) != PNG_FILTER_TYPE_BASE) + png_error(pp, "validate: filter type changed"); + + if (png_get_interlace_type(pp, pi) != dp->interlace_type) + png_error(pp, "validate: interlacing changed"); + + if (png_get_compression_type(pp, pi) != PNG_COMPRESSION_TYPE_BASE) + png_error(pp, "validate: compression type changed"); + + dp->w = png_get_image_width(pp, pi); + + if (dp->w != standard_width(pp, dp->id)) + png_error(pp, "validate: image width changed"); + + dp->h = png_get_image_height(pp, pi); + + if (dp->h != standard_height(pp, dp->id)) + png_error(pp, "validate: image height changed"); + + /* Record (but don't check at present) the input sBIT according to the colour + * type information. + */ + { + png_color_8p sBIT = 0; + + if (png_get_sBIT(pp, pi, &sBIT) & PNG_INFO_sBIT) + { + int sBIT_invalid = 0; + + if (sBIT == 0) + png_error(pp, "validate: unexpected png_get_sBIT result"); + + if (dp->colour_type & PNG_COLOR_MASK_COLOR) + { + if (sBIT->red == 0 || sBIT->red > dp->bit_depth) + sBIT_invalid = 1; + else + dp->red_sBIT = sBIT->red; + + if (sBIT->green == 0 || sBIT->green > dp->bit_depth) + sBIT_invalid = 1; + else + dp->green_sBIT = sBIT->green; + + if (sBIT->blue == 0 || sBIT->blue > dp->bit_depth) + sBIT_invalid = 1; + else + dp->blue_sBIT = sBIT->blue; + } + + else /* !COLOR */ + { + if (sBIT->gray == 0 || sBIT->gray > dp->bit_depth) + sBIT_invalid = 1; + else + dp->blue_sBIT = dp->green_sBIT = dp->red_sBIT = sBIT->gray; + } + + /* All 8 bits in tRNS for a palette image are significant - see the + * spec. + */ + if (dp->colour_type & PNG_COLOR_MASK_ALPHA) + { + if (sBIT->alpha == 0 || sBIT->alpha > dp->bit_depth) + sBIT_invalid = 1; + else + dp->alpha_sBIT = sBIT->alpha; + } + + if (sBIT_invalid) + png_error(pp, "validate: sBIT value out of range"); + } + } + + /* Important: this is validating the value *before* any transforms have been + * put in place. It doesn't matter for the standard tests, where there are + * no transforms, but it does for other tests where rowbytes may change after + * png_read_update_info. + */ + if (png_get_rowbytes(pp, pi) != standard_rowsize(pp, dp->id)) + png_error(pp, "validate: row size changed"); + + /* Validate the colour type 3 palette (this can be present on other color + * types.) + */ + standard_palette_validate(dp, pp, pi); + + /* In any case always check for a transparent color (notice that the + * colour type 3 case must not give a successful return on the get_tRNS call + * with these arguments!) + */ + { + png_color_16p trans_color = 0; + + if (png_get_tRNS(pp, pi, 0, 0, &trans_color) & PNG_INFO_tRNS) + { + if (trans_color == 0) + png_error(pp, "validate: unexpected png_get_tRNS (color) result"); + + switch (dp->colour_type) + { + case 0: + dp->transparent.red = dp->transparent.green = dp->transparent.blue = + trans_color->gray; + dp->has_tRNS = 1; + break; + + case 2: + dp->transparent.red = trans_color->red; + dp->transparent.green = trans_color->green; + dp->transparent.blue = trans_color->blue; + dp->has_tRNS = 1; + break; + + case 3: + /* Not expected because it should result in the array case + * above. + */ + png_error(pp, "validate: unexpected png_get_tRNS result"); + break; + + default: + png_error(pp, "validate: invalid tRNS chunk with alpha image"); + } + } + } + + /* Read the number of passes - expected to match the value used when + * creating the image (interlaced or not). This has the side effect of + * turning on interlace handling (if do_interlace is not set.) + */ + dp->npasses = npasses_from_interlace_type(pp, dp->interlace_type); + if (!dp->do_interlace) + { +# ifdef PNG_READ_INTERLACING_SUPPORTED + if (dp->npasses != png_set_interlace_handling(pp)) + png_error(pp, "validate: file changed interlace type"); +# else /* !READ_INTERLACING */ + /* This should never happen: the relevant tests (!do_interlace) should + * not be run. + */ + if (dp->npasses > 1) + png_error(pp, "validate: no libpng interlace support"); +# endif /* !READ_INTERLACING */ + } + + /* Caller calls png_read_update_info or png_start_read_image now, then calls + * part2. + */ +} + +/* This must be called *after* the png_read_update_info call to get the correct + * 'rowbytes' value, otherwise png_get_rowbytes will refer to the untransformed + * image. + */ +static void +standard_info_part2(standard_display *dp, png_const_structp pp, + png_const_infop pi, int nImages) +{ + /* Record cbRow now that it can be found. */ + { + png_byte ct = png_get_color_type(pp, pi); + png_byte bd = png_get_bit_depth(pp, pi); + + if (bd >= 8 && (ct == PNG_COLOR_TYPE_RGB || ct == PNG_COLOR_TYPE_GRAY) && + dp->filler) + ct |= 4; /* handle filler as faked alpha channel */ + + dp->pixel_size = bit_size(pp, ct, bd); + } + dp->bit_width = png_get_image_width(pp, pi) * dp->pixel_size; + dp->cbRow = png_get_rowbytes(pp, pi); + + /* Validate the rowbytes here again. */ + if (dp->cbRow != (dp->bit_width+7)/8) + png_error(pp, "bad png_get_rowbytes calculation"); + + /* Then ensure there is enough space for the output image(s). */ + store_ensure_image(dp->ps, pp, nImages, dp->cbRow, dp->h); +} + +static void +standard_info_imp(standard_display *dp, png_structp pp, png_infop pi, + int nImages) +{ + /* Note that the validation routine has the side effect of turning on + * interlace handling in the subsequent code. + */ + standard_info_part1(dp, pp, pi); + + /* And the info callback has to call this (or png_read_update_info - see + * below in the png_modifier code for that variant. + */ + if (dp->use_update_info) + { + /* For debugging the effect of multiple calls: */ + int i = dp->use_update_info; + while (i-- > 0) + png_read_update_info(pp, pi); + } + + else + png_start_read_image(pp); + + /* Validate the height, width and rowbytes plus ensure that sufficient buffer + * exists for decoding the image. + */ + standard_info_part2(dp, pp, pi, nImages); +} + +static void PNGCBAPI +standard_info(png_structp pp, png_infop pi) +{ + standard_display *dp = voidcast(standard_display*, + png_get_progressive_ptr(pp)); + + /* Call with nImages==1 because the progressive reader can only produce one + * image. + */ + standard_info_imp(dp, pp, pi, 1 /*only one image*/); +} + +static void PNGCBAPI +progressive_row(png_structp ppIn, png_bytep new_row, png_uint_32 y, int pass) +{ + png_const_structp pp = ppIn; + const standard_display *dp = voidcast(standard_display*, + png_get_progressive_ptr(pp)); + + /* When handling interlacing some rows will be absent in each pass, the + * callback still gets called, but with a NULL pointer. This is checked + * in the 'else' clause below. We need our own 'cbRow', but we can't call + * png_get_rowbytes because we got no info structure. + */ + if (new_row != NULL) + { + png_bytep row; + + /* In the case where the reader doesn't do the interlace it gives + * us the y in the sub-image: + */ + if (dp->do_interlace && dp->interlace_type == PNG_INTERLACE_ADAM7) + { +#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED + /* Use this opportunity to validate the png 'current' APIs: */ + if (y != png_get_current_row_number(pp)) + png_error(pp, "png_get_current_row_number is broken"); + + if (pass != png_get_current_pass_number(pp)) + png_error(pp, "png_get_current_pass_number is broken"); +#endif /* USER_TRANSFORM_INFO */ + + y = PNG_ROW_FROM_PASS_ROW(y, pass); + } + + /* Validate this just in case. */ + if (y >= dp->h) + png_error(pp, "invalid y to progressive row callback"); + + row = store_image_row(dp->ps, pp, 0, y); + + /* Combine the new row into the old: */ +#ifdef PNG_READ_INTERLACING_SUPPORTED + if (dp->do_interlace) +#endif /* READ_INTERLACING */ + { + if (dp->interlace_type == PNG_INTERLACE_ADAM7) + deinterlace_row(row, new_row, dp->pixel_size, dp->w, pass, + dp->littleendian); + else + row_copy(row, new_row, dp->pixel_size * dp->w, dp->littleendian); + } +#ifdef PNG_READ_INTERLACING_SUPPORTED + else + png_progressive_combine_row(pp, row, new_row); +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + } + + else if (dp->interlace_type == PNG_INTERLACE_ADAM7 && + PNG_ROW_IN_INTERLACE_PASS(y, pass) && + PNG_PASS_COLS(dp->w, pass) > 0) + png_error(pp, "missing row in progressive de-interlacing"); +} + +static void +sequential_row(standard_display *dp, png_structp pp, png_infop pi, + int iImage, int iDisplay) +{ + int npasses = dp->npasses; + int do_interlace = dp->do_interlace && + dp->interlace_type == PNG_INTERLACE_ADAM7; + png_uint_32 height = standard_height(pp, dp->id); + png_uint_32 width = standard_width(pp, dp->id); + const png_store* ps = dp->ps; + int pass; + + for (pass=0; pass 0 && PNG_ROW_IN_INTERLACE_PASS(y, pass)) + { + /* Read the row into a pair of temporary buffers, then do the + * merge here into the output rows. + */ + png_byte row[STANDARD_ROWMAX], display[STANDARD_ROWMAX]; + + /* The following aids (to some extent) error detection - we can + * see where png_read_row wrote. Use opposite values in row and + * display to make this easier. Don't use 0xff (which is used in + * the image write code to fill unused bits) or 0 (which is a + * likely value to overwrite unused bits with). + */ + memset(row, 0xc5, sizeof row); + memset(display, 0x5c, sizeof display); + + png_read_row(pp, row, display); + + if (iImage >= 0) + deinterlace_row(store_image_row(ps, pp, iImage, y), row, + dp->pixel_size, dp->w, pass, dp->littleendian); + + if (iDisplay >= 0) + deinterlace_row(store_image_row(ps, pp, iDisplay, y), display, + dp->pixel_size, dp->w, pass, dp->littleendian); + } + } + else + png_read_row(pp, + iImage >= 0 ? store_image_row(ps, pp, iImage, y) : NULL, + iDisplay >= 0 ? store_image_row(ps, pp, iDisplay, y) : NULL); + } + } + + /* And finish the read operation (only really necessary if the caller wants + * to find additional data in png_info from chunks after the last IDAT.) + */ + png_read_end(pp, pi); +} + +#ifdef PNG_TEXT_SUPPORTED +static void +standard_check_text(png_const_structp pp, png_const_textp tp, + png_const_charp keyword, png_const_charp text) +{ + char msg[1024]; + size_t pos = safecat(msg, sizeof msg, 0, "text: "); + size_t ok; + + pos = safecat(msg, sizeof msg, pos, keyword); + pos = safecat(msg, sizeof msg, pos, ": "); + ok = pos; + + if (tp->compression != TEXT_COMPRESSION) + { + char buf[64]; + + sprintf(buf, "compression [%d->%d], ", TEXT_COMPRESSION, + tp->compression); + pos = safecat(msg, sizeof msg, pos, buf); + } + + if (tp->key == NULL || strcmp(tp->key, keyword) != 0) + { + pos = safecat(msg, sizeof msg, pos, "keyword \""); + if (tp->key != NULL) + { + pos = safecat(msg, sizeof msg, pos, tp->key); + pos = safecat(msg, sizeof msg, pos, "\", "); + } + + else + pos = safecat(msg, sizeof msg, pos, "null, "); + } + + if (tp->text == NULL) + pos = safecat(msg, sizeof msg, pos, "text lost, "); + + else + { + if (tp->text_length != strlen(text)) + { + char buf[64]; + sprintf(buf, "text length changed[%lu->%lu], ", + (unsigned long)strlen(text), (unsigned long)tp->text_length); + pos = safecat(msg, sizeof msg, pos, buf); + } + + if (strcmp(tp->text, text) != 0) + { + pos = safecat(msg, sizeof msg, pos, "text becomes \""); + pos = safecat(msg, sizeof msg, pos, tp->text); + pos = safecat(msg, sizeof msg, pos, "\" (was \""); + pos = safecat(msg, sizeof msg, pos, text); + pos = safecat(msg, sizeof msg, pos, "\"), "); + } + } + + if (tp->itxt_length != 0) + pos = safecat(msg, sizeof msg, pos, "iTXt length set, "); + + if (tp->lang != NULL) + { + pos = safecat(msg, sizeof msg, pos, "iTXt language \""); + pos = safecat(msg, sizeof msg, pos, tp->lang); + pos = safecat(msg, sizeof msg, pos, "\", "); + } + + if (tp->lang_key != NULL) + { + pos = safecat(msg, sizeof msg, pos, "iTXt keyword \""); + pos = safecat(msg, sizeof msg, pos, tp->lang_key); + pos = safecat(msg, sizeof msg, pos, "\", "); + } + + if (pos > ok) + { + msg[pos-2] = '\0'; /* Remove the ", " at the end */ + png_error(pp, msg); + } +} + +static void +standard_text_validate(standard_display *dp, png_const_structp pp, + png_infop pi, int check_end) +{ + png_textp tp = NULL; + png_uint_32 num_text = png_get_text(pp, pi, &tp, NULL); + + if (num_text == 2 && tp != NULL) + { + standard_check_text(pp, tp, "image name", dp->ps->current->name); + + /* This exists because prior to 1.5.18 the progressive reader left the + * png_struct z_stream unreset at the end of the image, so subsequent + * attempts to use it simply returns Z_STREAM_END. + */ + if (check_end) + standard_check_text(pp, tp+1, "end marker", "end"); + } + + else + { + char msg[64]; + + sprintf(msg, "expected two text items, got %lu", + (unsigned long)num_text); + png_error(pp, msg); + } +} +#else +# define standard_text_validate(dp,pp,pi,check_end) ((void)0) +#endif + +static void +standard_row_validate(standard_display *dp, png_const_structp pp, + int iImage, int iDisplay, png_uint_32 y) +{ + int where; + png_byte std[STANDARD_ROWMAX]; + + /* The row must be pre-initialized to the magic number here for the size + * tests to pass: + */ + memset(std, 178, sizeof std); + standard_row(pp, std, dp->id, y); + + /* At the end both the 'row' and 'display' arrays should end up identical. + * In earlier passes 'row' will be partially filled in, with only the pixels + * that have been read so far, but 'display' will have those pixels + * replicated to fill the unread pixels while reading an interlaced image. + */ + if (iImage >= 0 && + (where = pixel_cmp(std, store_image_row(dp->ps, pp, iImage, y), + dp->bit_width)) != 0) + { + char msg[64]; + sprintf(msg, "PNG image row[%lu][%d] changed from %.2x to %.2x", + (unsigned long)y, where-1, std[where-1], + store_image_row(dp->ps, pp, iImage, y)[where-1]); + png_error(pp, msg); + } + + if (iDisplay >= 0 && + (where = pixel_cmp(std, store_image_row(dp->ps, pp, iDisplay, y), + dp->bit_width)) != 0) + { + char msg[64]; + sprintf(msg, "display row[%lu][%d] changed from %.2x to %.2x", + (unsigned long)y, where-1, std[where-1], + store_image_row(dp->ps, pp, iDisplay, y)[where-1]); + png_error(pp, msg); + } +} + +static void +standard_image_validate(standard_display *dp, png_const_structp pp, int iImage, + int iDisplay) +{ + png_uint_32 y; + + if (iImage >= 0) + store_image_check(dp->ps, pp, iImage); + + if (iDisplay >= 0) + store_image_check(dp->ps, pp, iDisplay); + + for (y=0; yh; ++y) + standard_row_validate(dp, pp, iImage, iDisplay, y); + + /* This avoids false positives if the validation code is never called! */ + dp->ps->validated = 1; +} + +static void PNGCBAPI +standard_end(png_structp ppIn, png_infop pi) +{ + png_const_structp pp = ppIn; + standard_display *dp = voidcast(standard_display*, + png_get_progressive_ptr(pp)); + + UNUSED(pi) + + /* Validate the image - progressive reading only produces one variant for + * interlaced images. + */ + standard_text_validate(dp, pp, pi, + PNG_LIBPNG_VER >= 10518/*check_end: see comments above*/); + standard_image_validate(dp, pp, 0, -1); +} + +/* A single test run checking the standard image to ensure it is not damaged. */ +static void +standard_test(png_store* const psIn, png_uint_32 const id, + int do_interlace, int use_update_info) +{ + standard_display d; + context(psIn, fault); + + /* Set up the display (stack frame) variables from the arguments to the + * function and initialize the locals that are filled in later. + */ + standard_display_init(&d, psIn, id, do_interlace, use_update_info); + + /* Everything is protected by a Try/Catch. The functions called also + * typically have local Try/Catch blocks. + */ + Try + { + png_structp pp; + png_infop pi; + + /* Get a png_struct for reading the image. This will throw an error if it + * fails, so we don't need to check the result. + */ + pp = set_store_for_read(d.ps, &pi, d.id, + d.do_interlace ? (d.ps->progressive ? + "pngvalid progressive deinterlacer" : + "pngvalid sequential deinterlacer") : (d.ps->progressive ? + "progressive reader" : "sequential reader")); + + /* Initialize the palette correctly from the png_store_file. */ + standard_palette_init(&d); + + /* Introduce the correct read function. */ + if (d.ps->progressive) + { + png_set_progressive_read_fn(pp, &d, standard_info, progressive_row, + standard_end); + + /* Now feed data into the reader until we reach the end: */ + store_progressive_read(d.ps, pp, pi); + } + else + { + /* Note that this takes the store, not the display. */ + png_set_read_fn(pp, d.ps, store_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* The code tests both versions of the images that the sequential + * reader can produce. + */ + standard_info_imp(&d, pp, pi, 2 /*images*/); + + /* Need the total bytes in the image below; we can't get to this point + * unless the PNG file values have been checked against the expected + * values. + */ + { + sequential_row(&d, pp, pi, 0, 1); + + /* After the last pass loop over the rows again to check that the + * image is correct. + */ + if (!d.speed) + { + standard_text_validate(&d, pp, pi, 1/*check_end*/); + standard_image_validate(&d, pp, 0, 1); + } + else + d.ps->validated = 1; + } + } + + /* Check for validation. */ + if (!d.ps->validated) + png_error(pp, "image read failed silently"); + + /* Successful completion. */ + } + + Catch(fault) + d.ps = fault; /* make sure this hasn't been clobbered. */ + + /* In either case clean up the store. */ + store_read_reset(d.ps); +} + +static int +test_standard(png_modifier* const pm, png_byte const colour_type, + int bdlo, int const bdhi) +{ + for (; bdlo <= bdhi; ++bdlo) + { + int interlace_type; + + for (interlace_type = PNG_INTERLACE_NONE; + interlace_type < INTERLACE_LAST; ++interlace_type) + { + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, + interlace_type, 0, 0, 0), do_read_interlace, pm->use_update_info); + + if (fail(pm)) + return 0; + } + } + + return 1; /* keep going */ +} + +static void +perform_standard_test(png_modifier *pm) +{ + /* Test each colour type over the valid range of bit depths (expressed as + * log2(bit_depth) in turn, stop as soon as any error is detected. + */ + if (!test_standard(pm, 0, 0, READ_BDHI)) + return; + + if (!test_standard(pm, 2, 3, READ_BDHI)) + return; + + if (!test_standard(pm, 3, 0, 3)) + return; + + if (!test_standard(pm, 4, 3, READ_BDHI)) + return; + + if (!test_standard(pm, 6, 3, READ_BDHI)) + return; +} + + +/********************************** SIZE TESTS ********************************/ +static int +test_size(png_modifier* const pm, png_byte const colour_type, + int bdlo, int const bdhi) +{ + /* Run the tests on each combination. + * + * NOTE: on my 32 bit x86 each of the following blocks takes + * a total of 3.5 seconds if done across every combo of bit depth + * width and height. This is a waste of time in practice, hence the + * hinc and winc stuff: + */ + static const png_byte hinc[] = {1, 3, 11, 1, 5}; + static const png_byte winc[] = {1, 9, 5, 7, 1}; + int save_bdlo = bdlo; + + for (; bdlo <= bdhi; ++bdlo) + { + png_uint_32 h, w; + + for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo]) + { + /* First test all the 'size' images against the sequential + * reader using libpng to deinterlace (where required.) This + * validates the write side of libpng. There are four possibilities + * to validate. + */ + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, + PNG_INTERLACE_NONE, w, h, 0), 0/*do_interlace*/, + pm->use_update_info); + + if (fail(pm)) + return 0; + + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, + PNG_INTERLACE_NONE, w, h, 1), 0/*do_interlace*/, + pm->use_update_info); + + if (fail(pm)) + return 0; + + /* Now validate the interlaced read side - do_interlace true, + * in the progressive case this does actually make a difference + * to the code used in the non-interlaced case too. + */ + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, + PNG_INTERLACE_NONE, w, h, 0), 1/*do_interlace*/, + pm->use_update_info); + + if (fail(pm)) + return 0; + +# if CAN_WRITE_INTERLACE + /* Validate the pngvalid code itself: */ + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, + PNG_INTERLACE_ADAM7, w, h, 1), 1/*do_interlace*/, + pm->use_update_info); + + if (fail(pm)) + return 0; +# endif + } + } + + /* Now do the tests of libpng interlace handling, after we have made sure + * that the pngvalid version works: + */ + for (bdlo = save_bdlo; bdlo <= bdhi; ++bdlo) + { + png_uint_32 h, w; + + for (h=1; h<=16; h+=hinc[bdlo]) for (w=1; w<=16; w+=winc[bdlo]) + { +# ifdef PNG_READ_INTERLACING_SUPPORTED + /* Test with pngvalid generated interlaced images first; we have + * already verify these are ok (unless pngvalid has self-consistent + * read/write errors, which is unlikely), so this detects errors in the + * read side first: + */ +# if CAN_WRITE_INTERLACE + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, + PNG_INTERLACE_ADAM7, w, h, 1), 0/*do_interlace*/, + pm->use_update_info); + + if (fail(pm)) + return 0; +# endif +# endif /* READ_INTERLACING */ + +# ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Test the libpng write side against the pngvalid read side: */ + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, + PNG_INTERLACE_ADAM7, w, h, 0), 1/*do_interlace*/, + pm->use_update_info); + + if (fail(pm)) + return 0; +# endif + +# ifdef PNG_READ_INTERLACING_SUPPORTED +# ifdef PNG_WRITE_INTERLACING_SUPPORTED + /* Test both together: */ + standard_test(&pm->this, FILEID(colour_type, DEPTH(bdlo), 0/*palette*/, + PNG_INTERLACE_ADAM7, w, h, 0), 0/*do_interlace*/, + pm->use_update_info); + + if (fail(pm)) + return 0; +# endif +# endif /* READ_INTERLACING */ + } + } + + return 1; /* keep going */ +} + +static void +perform_size_test(png_modifier *pm) +{ + /* Test each colour type over the valid range of bit depths (expressed as + * log2(bit_depth) in turn, stop as soon as any error is detected. + */ + if (!test_size(pm, 0, 0, READ_BDHI)) + return; + + if (!test_size(pm, 2, 3, READ_BDHI)) + return; + + /* For the moment don't do the palette test - it's a waste of time when + * compared to the grayscale test. + */ +#if 0 + if (!test_size(pm, 3, 0, 3)) + return; +#endif + + if (!test_size(pm, 4, 3, READ_BDHI)) + return; + + if (!test_size(pm, 6, 3, READ_BDHI)) + return; +} + + +/******************************* TRANSFORM TESTS ******************************/ +#ifdef PNG_READ_TRANSFORMS_SUPPORTED +/* A set of tests to validate libpng image transforms. The possibilities here + * are legion because the transforms can be combined in a combinatorial + * fashion. To deal with this some measure of restraint is required, otherwise + * the tests would take forever. + */ +typedef struct image_pixel +{ + /* A local (pngvalid) representation of a PNG pixel, in all its + * various forms. + */ + unsigned int red, green, blue, alpha; /* For non-palette images. */ + unsigned int palette_index; /* For a palette image. */ + png_byte colour_type; /* As in the spec. */ + png_byte bit_depth; /* Defines bit size in row */ + png_byte sample_depth; /* Scale of samples */ + unsigned int have_tRNS :1; /* tRNS chunk may need processing */ + unsigned int swap_rgb :1; /* RGB swapped to BGR */ + unsigned int alpha_first :1; /* Alpha at start, not end */ + unsigned int alpha_inverted :1; /* Alpha channel inverted */ + unsigned int mono_inverted :1; /* Gray channel inverted */ + unsigned int swap16 :1; /* Byte swap 16-bit components */ + unsigned int littleendian :1; /* High bits on right */ + unsigned int sig_bits :1; /* Pixel shifted (sig bits only) */ + + /* For checking the code calculates double precision floating point values + * along with an error value, accumulated from the transforms. Because an + * sBIT setting allows larger error bounds (indeed, by the spec, apparently + * up to just less than +/-1 in the scaled value) the *lowest* sBIT for each + * channel is stored. This sBIT value is folded in to the stored error value + * at the end of the application of the transforms to the pixel. + * + * If sig_bits is set above the red, green, blue and alpha values have been + * scaled so they only contain the significant bits of the component values. + */ + double redf, greenf, bluef, alphaf; + double rede, greene, bluee, alphae; + png_byte red_sBIT, green_sBIT, blue_sBIT, alpha_sBIT; +} image_pixel; + +/* Shared utility function, see below. */ +static void +image_pixel_setf(image_pixel *this, unsigned int rMax, unsigned int gMax, + unsigned int bMax, unsigned int aMax) +{ + this->redf = this->red / (double)rMax; + this->greenf = this->green / (double)gMax; + this->bluef = this->blue / (double)bMax; + this->alphaf = this->alpha / (double)aMax; + + if (this->red < rMax) + this->rede = this->redf * DBL_EPSILON; + else + this->rede = 0; + if (this->green < gMax) + this->greene = this->greenf * DBL_EPSILON; + else + this->greene = 0; + if (this->blue < bMax) + this->bluee = this->bluef * DBL_EPSILON; + else + this->bluee = 0; + if (this->alpha < aMax) + this->alphae = this->alphaf * DBL_EPSILON; + else + this->alphae = 0; +} + +/* Initialize the structure for the next pixel - call this before doing any + * transforms and call it for each pixel since all the fields may need to be + * reset. + */ +static void +image_pixel_init(image_pixel *this, png_const_bytep row, png_byte colour_type, + png_byte bit_depth, png_uint_32 x, store_palette palette, + const image_pixel *format /*from pngvalid transform of input*/) +{ + png_byte sample_depth = + (png_byte)(colour_type == PNG_COLOR_TYPE_PALETTE ? 8 : bit_depth); + unsigned int max = (1U<swap16); + int littleendian = (format != 0 && format->littleendian); + int sig_bits = (format != 0 && format->sig_bits); + + /* Initially just set everything to the same number and the alpha to opaque. + * Note that this currently assumes a simple palette where entry x has colour + * rgb(x,x,x)! + */ + this->palette_index = this->red = this->green = this->blue = + sample(row, colour_type, bit_depth, x, 0, swap16, littleendian); + this->alpha = max; + this->red_sBIT = this->green_sBIT = this->blue_sBIT = this->alpha_sBIT = + sample_depth; + + /* Then override as appropriate: */ + if (colour_type == 3) /* palette */ + { + /* This permits the caller to default to the sample value. */ + if (palette != 0) + { + unsigned int i = this->palette_index; + + this->red = palette[i].red; + this->green = palette[i].green; + this->blue = palette[i].blue; + this->alpha = palette[i].alpha; + } + } + + else /* not palette */ + { + unsigned int i = 0; + + if ((colour_type & 4) != 0 && format != 0 && format->alpha_first) + { + this->alpha = this->red; + /* This handles the gray case for 'AG' pixels */ + this->palette_index = this->red = this->green = this->blue = + sample(row, colour_type, bit_depth, x, 1, swap16, littleendian); + i = 1; + } + + if (colour_type & 2) + { + /* Green is second for both BGR and RGB: */ + this->green = sample(row, colour_type, bit_depth, x, ++i, swap16, + littleendian); + + if (format != 0 && format->swap_rgb) /* BGR */ + this->red = sample(row, colour_type, bit_depth, x, ++i, swap16, + littleendian); + else + this->blue = sample(row, colour_type, bit_depth, x, ++i, swap16, + littleendian); + } + + else /* grayscale */ if (format != 0 && format->mono_inverted) + this->red = this->green = this->blue = this->red ^ max; + + if ((colour_type & 4) != 0) /* alpha */ + { + if (format == 0 || !format->alpha_first) + this->alpha = sample(row, colour_type, bit_depth, x, ++i, swap16, + littleendian); + + if (format != 0 && format->alpha_inverted) + this->alpha ^= max; + } + } + + /* Calculate the scaled values, these are simply the values divided by + * 'max' and the error is initialized to the double precision epsilon value + * from the header file. + */ + image_pixel_setf(this, + sig_bits ? (1U << format->red_sBIT)-1 : max, + sig_bits ? (1U << format->green_sBIT)-1 : max, + sig_bits ? (1U << format->blue_sBIT)-1 : max, + sig_bits ? (1U << format->alpha_sBIT)-1 : max); + + /* Store the input information for use in the transforms - these will + * modify the information. + */ + this->colour_type = colour_type; + this->bit_depth = bit_depth; + this->sample_depth = sample_depth; + this->have_tRNS = 0; + this->swap_rgb = 0; + this->alpha_first = 0; + this->alpha_inverted = 0; + this->mono_inverted = 0; + this->swap16 = 0; + this->littleendian = 0; + this->sig_bits = 0; +} + +#if defined PNG_READ_EXPAND_SUPPORTED || defined PNG_READ_GRAY_TO_RGB_SUPPORTED\ + || defined PNG_READ_EXPAND_SUPPORTED || defined PNG_READ_EXPAND_16_SUPPORTED\ + || defined PNG_READ_BACKGROUND_SUPPORTED +/* Convert a palette image to an rgb image. This necessarily converts the tRNS + * chunk at the same time, because the tRNS will be in palette form. The way + * palette validation works means that the original palette is never updated, + * instead the image_pixel value from the row contains the RGB of the + * corresponding palette entry and *this* is updated. Consequently this routine + * only needs to change the colour type information. + */ +static void +image_pixel_convert_PLTE(image_pixel *this) +{ + if (this->colour_type == PNG_COLOR_TYPE_PALETTE) + { + if (this->have_tRNS) + { + this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; + this->have_tRNS = 0; + } + else + this->colour_type = PNG_COLOR_TYPE_RGB; + + /* The bit depth of the row changes at this point too (notice that this is + * the row format, not the sample depth, which is separate.) + */ + this->bit_depth = 8; + } +} + +/* Add an alpha channel; this will import the tRNS information because tRNS is + * not valid in an alpha image. The bit depth will invariably be set to at + * least 8 prior to 1.7.0. Palette images will be converted to alpha (using + * the above API). With png_set_background the alpha channel is never expanded + * but this routine is used by pngvalid to simplify code; 'for_background' + * records this. + */ +static void +image_pixel_add_alpha(image_pixel *this, const standard_display *display, + int for_background) +{ + if (this->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(this); + + if ((this->colour_type & PNG_COLOR_MASK_ALPHA) == 0) + { + if (this->colour_type == PNG_COLOR_TYPE_GRAY) + { +# if PNG_LIBPNG_VER < 10700 + if (!for_background && this->bit_depth < 8) + this->bit_depth = this->sample_depth = 8; +# endif + + if (this->have_tRNS) + { + /* After 1.7 the expansion of bit depth only happens if there is a + * tRNS chunk to expand at this point. + */ +# if PNG_LIBPNG_VER >= 10700 + if (!for_background && this->bit_depth < 8) + this->bit_depth = this->sample_depth = 8; +# endif + + this->have_tRNS = 0; + + /* Check the input, original, channel value here against the + * original tRNS gray chunk valie. + */ + if (this->red == display->transparent.red) + this->alphaf = 0; + else + this->alphaf = 1; + } + else + this->alphaf = 1; + + this->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; + } + + else if (this->colour_type == PNG_COLOR_TYPE_RGB) + { + if (this->have_tRNS) + { + this->have_tRNS = 0; + + /* Again, check the exact input values, not the current transformed + * value! + */ + if (this->red == display->transparent.red && + this->green == display->transparent.green && + this->blue == display->transparent.blue) + this->alphaf = 0; + else + this->alphaf = 1; + } + else + this->alphaf = 1; + + this->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; + } + + /* The error in the alpha is zero and the sBIT value comes from the + * original sBIT data (actually it will always be the original bit depth). + */ + this->alphae = 0; + this->alpha_sBIT = display->alpha_sBIT; + } +} +#endif /* transforms that need image_pixel_add_alpha */ + +struct transform_display; +typedef struct image_transform +{ + /* The name of this transform: a string. */ + const char *name; + + /* Each transform can be disabled from the command line: */ + int enable; + + /* The global list of transforms; read only. */ + struct image_transform *const list; + + /* The global count of the number of times this transform has been set on an + * image. + */ + unsigned int global_use; + + /* The local count of the number of times this transform has been set. */ + unsigned int local_use; + + /* The next transform in the list, each transform must call its own next + * transform after it has processed the pixel successfully. + */ + const struct image_transform *next; + + /* A single transform for the image, expressed as a series of function + * callbacks and some space for values. + * + * First a callback to add any required modifications to the png_modifier; + * this gets called just before the modifier is set up for read. + */ + void (*ini)(const struct image_transform *this, + struct transform_display *that); + + /* And a callback to set the transform on the current png_read_struct: + */ + void (*set)(const struct image_transform *this, + struct transform_display *that, png_structp pp, png_infop pi); + + /* Then a transform that takes an input pixel in one PNG format or another + * and modifies it by a pngvalid implementation of the transform (thus + * duplicating the libpng intent without, we hope, duplicating the bugs + * in the libpng implementation!) The png_structp is solely to allow error + * reporting via png_error and png_warning. + */ + void (*mod)(const struct image_transform *this, image_pixel *that, + png_const_structp pp, const struct transform_display *display); + + /* Add this transform to the list and return true if the transform is + * meaningful for this colour type and bit depth - if false then the + * transform should have no effect on the image so there's not a lot of + * point running it. + */ + int (*add)(struct image_transform *this, + const struct image_transform **that, png_byte colour_type, + png_byte bit_depth); +} image_transform; + +typedef struct transform_display +{ + standard_display this; + + /* Parameters */ + png_modifier* pm; + const image_transform* transform_list; + unsigned int max_gamma_8; + + /* Local variables */ + png_byte output_colour_type; + png_byte output_bit_depth; + png_byte unpacked; + + /* Modifications (not necessarily used.) */ + gama_modification gama_mod; + chrm_modification chrm_mod; + srgb_modification srgb_mod; +} transform_display; + +/* Set sRGB, cHRM and gAMA transforms as required by the current encoding. */ +static void +transform_set_encoding(transform_display *this) +{ + /* Set up the png_modifier '_current' fields then use these to determine how + * to add appropriate chunks. + */ + png_modifier *pm = this->pm; + + modifier_set_encoding(pm); + + if (modifier_color_encoding_is_set(pm)) + { + if (modifier_color_encoding_is_sRGB(pm)) + srgb_modification_init(&this->srgb_mod, pm, PNG_sRGB_INTENT_ABSOLUTE); + + else + { + /* Set gAMA and cHRM separately. */ + gama_modification_init(&this->gama_mod, pm, pm->current_gamma); + + if (pm->current_encoding != 0) + chrm_modification_init(&this->chrm_mod, pm, pm->current_encoding); + } + } +} + +/* Three functions to end the list: */ +static void +image_transform_ini_end(const image_transform *this, + transform_display *that) +{ + UNUSED(this) + UNUSED(that) +} + +static void +image_transform_set_end(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + UNUSED(this) + UNUSED(that) + UNUSED(pp) + UNUSED(pi) +} + +/* At the end of the list recalculate the output image pixel value from the + * double precision values set up by the preceding 'mod' calls: + */ +static unsigned int +sample_scale(double sample_value, unsigned int scale) +{ + sample_value = floor(sample_value * scale + .5); + + /* Return NaN as 0: */ + if (!(sample_value > 0)) + sample_value = 0; + else if (sample_value > scale) + sample_value = scale; + + return (unsigned int)sample_value; +} + +static void +image_transform_mod_end(const image_transform *this, image_pixel *that, + png_const_structp pp, const transform_display *display) +{ + unsigned int scale = (1U<sample_depth)-1; + int sig_bits = that->sig_bits; + + UNUSED(this) + UNUSED(pp) + UNUSED(display) + + /* At the end recalculate the digitized red green and blue values according + * to the current sample_depth of the pixel. + * + * The sample value is simply scaled to the maximum, checking for over + * and underflow (which can both happen for some image transforms, + * including simple size scaling, though libpng doesn't do that at present. + */ + that->red = sample_scale(that->redf, scale); + + /* This is a bit bogus; really the above calculation should use the red_sBIT + * value, not sample_depth, but because libpng does png_set_shift by just + * shifting the bits we get errors if we don't do it the same way. + */ + if (sig_bits && that->red_sBIT < that->sample_depth) + that->red >>= that->sample_depth - that->red_sBIT; + + /* The error value is increased, at the end, according to the lowest sBIT + * value seen. Common sense tells us that the intermediate integer + * representations are no more accurate than +/- 0.5 in the integral values, + * the sBIT allows the implementation to be worse than this. In addition the + * PNG specification actually permits any error within the range (-1..+1), + * but that is ignored here. Instead the final digitized value is compared, + * below to the digitized value of the error limits - this has the net effect + * of allowing (almost) +/-1 in the output value. It's difficult to see how + * any algorithm that digitizes intermediate results can be more accurate. + */ + that->rede += 1./(2*((1U<red_sBIT)-1)); + + if (that->colour_type & PNG_COLOR_MASK_COLOR) + { + that->green = sample_scale(that->greenf, scale); + if (sig_bits && that->green_sBIT < that->sample_depth) + that->green >>= that->sample_depth - that->green_sBIT; + + that->blue = sample_scale(that->bluef, scale); + if (sig_bits && that->blue_sBIT < that->sample_depth) + that->blue >>= that->sample_depth - that->blue_sBIT; + + that->greene += 1./(2*((1U<green_sBIT)-1)); + that->bluee += 1./(2*((1U<blue_sBIT)-1)); + } + else + { + that->blue = that->green = that->red; + that->bluef = that->greenf = that->redf; + that->bluee = that->greene = that->rede; + } + + if ((that->colour_type & PNG_COLOR_MASK_ALPHA) || + that->colour_type == PNG_COLOR_TYPE_PALETTE) + { + that->alpha = sample_scale(that->alphaf, scale); + that->alphae += 1./(2*((1U<alpha_sBIT)-1)); + } + else + { + that->alpha = scale; /* opaque */ + that->alphaf = 1; /* Override this. */ + that->alphae = 0; /* It's exact ;-) */ + } + + if (sig_bits && that->alpha_sBIT < that->sample_depth) + that->alpha >>= that->sample_depth - that->alpha_sBIT; +} + +/* Static 'end' structure: */ +static image_transform image_transform_end = +{ + "(end)", /* name */ + 1, /* enable */ + 0, /* list */ + 0, /* global_use */ + 0, /* local_use */ + 0, /* next */ + image_transform_ini_end, + image_transform_set_end, + image_transform_mod_end, + 0 /* never called, I want it to crash if it is! */ +}; + +/* Reader callbacks and implementations, where they differ from the standard + * ones. + */ +static void +transform_display_init(transform_display *dp, png_modifier *pm, png_uint_32 id, + const image_transform *transform_list) +{ + memset(dp, 0, sizeof *dp); + + /* Standard fields */ + standard_display_init(&dp->this, &pm->this, id, do_read_interlace, + pm->use_update_info); + + /* Parameter fields */ + dp->pm = pm; + dp->transform_list = transform_list; + dp->max_gamma_8 = 16; + + /* Local variable fields */ + dp->output_colour_type = 255; /* invalid */ + dp->output_bit_depth = 255; /* invalid */ + dp->unpacked = 0; /* not unpacked */ +} + +static void +transform_info_imp(transform_display *dp, png_structp pp, png_infop pi) +{ + /* Reuse the standard stuff as appropriate. */ + standard_info_part1(&dp->this, pp, pi); + + /* Now set the list of transforms. */ + dp->transform_list->set(dp->transform_list, dp, pp, pi); + + /* Update the info structure for these transforms: */ + { + int i = dp->this.use_update_info; + /* Always do one call, even if use_update_info is 0. */ + do + png_read_update_info(pp, pi); + while (--i > 0); + } + + /* And get the output information into the standard_display */ + standard_info_part2(&dp->this, pp, pi, 1/*images*/); + + /* Plus the extra stuff we need for the transform tests: */ + dp->output_colour_type = png_get_color_type(pp, pi); + dp->output_bit_depth = png_get_bit_depth(pp, pi); + + /* If png_set_filler is in action then fake the output color type to include + * an alpha channel where appropriate. + */ + if (dp->output_bit_depth >= 8 && + (dp->output_colour_type == PNG_COLOR_TYPE_RGB || + dp->output_colour_type == PNG_COLOR_TYPE_GRAY) && dp->this.filler) + dp->output_colour_type |= 4; + + /* Validate the combination of colour type and bit depth that we are getting + * out of libpng; the semantics of something not in the PNG spec are, at + * best, unclear. + */ + switch (dp->output_colour_type) + { + case PNG_COLOR_TYPE_PALETTE: + if (dp->output_bit_depth > 8) goto error; + /* FALLTHROUGH */ + case PNG_COLOR_TYPE_GRAY: + if (dp->output_bit_depth == 1 || dp->output_bit_depth == 2 || + dp->output_bit_depth == 4) + break; + /* FALLTHROUGH */ + default: + if (dp->output_bit_depth == 8 || dp->output_bit_depth == 16) + break; + /* FALLTHROUGH */ + error: + { + char message[128]; + size_t pos; + + pos = safecat(message, sizeof message, 0, + "invalid final bit depth: colour type("); + pos = safecatn(message, sizeof message, pos, dp->output_colour_type); + pos = safecat(message, sizeof message, pos, ") with bit depth: "); + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + + png_error(pp, message); + } + } + + /* Use a test pixel to check that the output agrees with what we expect - + * this avoids running the whole test if the output is unexpected. This also + * checks for internal errors. + */ + { + image_pixel test_pixel; + + memset(&test_pixel, 0, sizeof test_pixel); + test_pixel.colour_type = dp->this.colour_type; /* input */ + test_pixel.bit_depth = dp->this.bit_depth; + if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) + test_pixel.sample_depth = 8; + else + test_pixel.sample_depth = test_pixel.bit_depth; + /* Don't need sBIT here, but it must be set to non-zero to avoid + * arithmetic overflows. + */ + test_pixel.have_tRNS = dp->this.is_transparent != 0; + test_pixel.red_sBIT = test_pixel.green_sBIT = test_pixel.blue_sBIT = + test_pixel.alpha_sBIT = test_pixel.sample_depth; + + dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp); + + if (test_pixel.colour_type != dp->output_colour_type) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, "colour type "); + + pos = safecatn(message, sizeof message, pos, dp->output_colour_type); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.colour_type); + + png_error(pp, message); + } + + if (test_pixel.bit_depth != dp->output_bit_depth) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, "bit depth "); + + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); + + png_error(pp, message); + } + + /* If both bit depth and colour type are correct check the sample depth. + */ + if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE && + test_pixel.sample_depth != 8) /* oops - internal error! */ + png_error(pp, "pngvalid: internal: palette sample depth not 8"); + else if (dp->unpacked && test_pixel.bit_depth != 8) + png_error(pp, "pngvalid: internal: bad unpacked pixel depth"); + else if (!dp->unpacked && test_pixel.colour_type != PNG_COLOR_TYPE_PALETTE + && test_pixel.bit_depth != test_pixel.sample_depth) + { + char message[128]; + size_t pos = safecat(message, sizeof message, 0, + "internal: sample depth "); + + /* Because unless something has set 'unpacked' or the image is palette + * mapped we expect the transform to keep sample depth and bit depth + * the same. + */ + pos = safecatn(message, sizeof message, pos, test_pixel.sample_depth); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); + + png_error(pp, message); + } + else if (test_pixel.bit_depth != dp->output_bit_depth) + { + /* This could be a libpng error too; libpng has not produced what we + * expect for the output bit depth. + */ + char message[128]; + size_t pos = safecat(message, sizeof message, 0, + "internal: bit depth "); + + pos = safecatn(message, sizeof message, pos, dp->output_bit_depth); + pos = safecat(message, sizeof message, pos, " expected "); + pos = safecatn(message, sizeof message, pos, test_pixel.bit_depth); + + png_error(pp, message); + } + } +} + +static void PNGCBAPI +transform_info(png_structp pp, png_infop pi) +{ + transform_info_imp(voidcast(transform_display*, png_get_progressive_ptr(pp)), + pp, pi); +} + +static void +transform_range_check(png_const_structp pp, unsigned int r, unsigned int g, + unsigned int b, unsigned int a, unsigned int in_digitized, double in, + unsigned int out, png_byte sample_depth, double err, double limit, + const char *name, double digitization_error) +{ + /* Compare the scaled, digitzed, values of our local calculation (in+-err) + * with the digitized values libpng produced; 'sample_depth' is the actual + * digitization depth of the libpng output colors (the bit depth except for + * palette images where it is always 8.) The check on 'err' is to detect + * internal errors in pngvalid itself. + */ + unsigned int max = (1U< limit ||) !(out >= in_min && out <= in_max)) + { + char message[256]; + size_t pos; + + pos = safecat(message, sizeof message, 0, name); + pos = safecat(message, sizeof message, pos, " output value error: rgba("); + pos = safecatn(message, sizeof message, pos, r); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, g); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, b); + pos = safecat(message, sizeof message, pos, ","); + pos = safecatn(message, sizeof message, pos, a); + pos = safecat(message, sizeof message, pos, "): "); + pos = safecatn(message, sizeof message, pos, out); + pos = safecat(message, sizeof message, pos, " expected: "); + pos = safecatn(message, sizeof message, pos, in_digitized); + pos = safecat(message, sizeof message, pos, " ("); + pos = safecatd(message, sizeof message, pos, (in-err)*max, 3); + pos = safecat(message, sizeof message, pos, ".."); + pos = safecatd(message, sizeof message, pos, (in+err)*max, 3); + pos = safecat(message, sizeof message, pos, ")"); + + png_error(pp, message); + } + + UNUSED(limit) +} + +static void +transform_image_validate(transform_display *dp, png_const_structp pp, + png_infop pi) +{ + /* Constants for the loop below: */ + const png_store* const ps = dp->this.ps; + png_byte in_ct = dp->this.colour_type; + png_byte in_bd = dp->this.bit_depth; + png_uint_32 w = dp->this.w; + png_uint_32 h = dp->this.h; + png_byte out_ct = dp->output_colour_type; + png_byte out_bd = dp->output_bit_depth; + png_byte sample_depth = + (png_byte)(out_ct == PNG_COLOR_TYPE_PALETTE ? 8 : out_bd); + png_byte red_sBIT = dp->this.red_sBIT; + png_byte green_sBIT = dp->this.green_sBIT; + png_byte blue_sBIT = dp->this.blue_sBIT; + png_byte alpha_sBIT = dp->this.alpha_sBIT; + int have_tRNS = dp->this.is_transparent; + double digitization_error; + + store_palette out_palette; + png_uint_32 y; + + UNUSED(pi) + + /* Check for row overwrite errors */ + store_image_check(dp->this.ps, pp, 0); + + /* Read the palette corresponding to the output if the output colour type + * indicates a palette, otherwise set out_palette to garbage. + */ + if (out_ct == PNG_COLOR_TYPE_PALETTE) + { + /* Validate that the palette count itself has not changed - this is not + * expected. + */ + int npalette = (-1); + + (void)read_palette(out_palette, &npalette, pp, pi); + if (npalette != dp->this.npalette) + png_error(pp, "unexpected change in palette size"); + + digitization_error = .5; + } + else + { + png_byte in_sample_depth; + + memset(out_palette, 0x5e, sizeof out_palette); + + /* use-input-precision means assume that if the input has 8 bit (or less) + * samples and the output has 16 bit samples the calculations will be done + * with 8 bit precision, not 16. + */ + if (in_ct == PNG_COLOR_TYPE_PALETTE || in_bd < 16) + in_sample_depth = 8; + else + in_sample_depth = in_bd; + + if (sample_depth != 16 || in_sample_depth > 8 || + !dp->pm->calculations_use_input_precision) + digitization_error = .5; + + /* Else calculations are at 8 bit precision, and the output actually + * consists of scaled 8-bit values, so scale .5 in 8 bits to the 16 bits: + */ + else + digitization_error = .5 * 257; + } + + for (y=0; ythis.palette, + NULL); + + in_pixel.red_sBIT = red_sBIT; + in_pixel.green_sBIT = green_sBIT; + in_pixel.blue_sBIT = blue_sBIT; + in_pixel.alpha_sBIT = alpha_sBIT; + in_pixel.have_tRNS = have_tRNS != 0; + + /* For error detection, below. */ + r = in_pixel.red; + g = in_pixel.green; + b = in_pixel.blue; + a = in_pixel.alpha; + + /* This applies the transforms to the input data, including output + * format operations which must be used when reading the output + * pixel that libpng produces. + */ + dp->transform_list->mod(dp->transform_list, &in_pixel, pp, dp); + + /* Read the output pixel and compare it to what we got, we don't + * use the error field here, so no need to update sBIT. in_pixel + * says whether we expect libpng to change the output format. + */ + image_pixel_init(&out_pixel, pRow, out_ct, out_bd, x, out_palette, + &in_pixel); + + /* We don't expect changes to the index here even if the bit depth is + * changed. + */ + if (in_ct == PNG_COLOR_TYPE_PALETTE && + out_ct == PNG_COLOR_TYPE_PALETTE) + { + if (in_pixel.palette_index != out_pixel.palette_index) + png_error(pp, "unexpected transformed palette index"); + } + + /* Check the colours for palette images too - in fact the palette could + * be separately verified itself in most cases. + */ + if (in_pixel.red != out_pixel.red) + transform_range_check(pp, r, g, b, a, in_pixel.red, in_pixel.redf, + out_pixel.red, sample_depth, in_pixel.rede, + dp->pm->limit + 1./(2*((1U<pm->limit + 1./(2*((1U<pm->limit + 1./(2*((1U<pm->limit + 1./(2*((1U<this.ps->validated = 1; +} + +static void PNGCBAPI +transform_end(png_structp ppIn, png_infop pi) +{ + png_const_structp pp = ppIn; + transform_display *dp = voidcast(transform_display*, + png_get_progressive_ptr(pp)); + + if (!dp->this.speed) + transform_image_validate(dp, pp, pi); + else + dp->this.ps->validated = 1; +} + +/* A single test run. */ +static void +transform_test(png_modifier *pmIn, png_uint_32 idIn, + const image_transform* transform_listIn, const char * const name) +{ + transform_display d; + context(&pmIn->this, fault); + + transform_display_init(&d, pmIn, idIn, transform_listIn); + + Try + { + size_t pos = 0; + png_structp pp; + png_infop pi; + char full_name[256]; + + /* Make sure the encoding fields are correct and enter the required + * modifications. + */ + transform_set_encoding(&d); + + /* Add any modifications required by the transform list. */ + d.transform_list->ini(d.transform_list, &d); + + /* Add the color space information, if any, to the name. */ + pos = safecat(full_name, sizeof full_name, pos, name); + pos = safecat_current_encoding(full_name, sizeof full_name, pos, d.pm); + + /* Get a png_struct for reading the image. */ + pp = set_modifier_for_read(d.pm, &pi, d.this.id, full_name); + standard_palette_init(&d.this); + +# if 0 + /* Logging (debugging only) */ + { + char buffer[256]; + + (void)store_message(&d.pm->this, pp, buffer, sizeof buffer, 0, + "running test"); + + fprintf(stderr, "%s\n", buffer); + } +# endif + + /* Introduce the correct read function. */ + if (d.pm->this.progressive) + { + /* Share the row function with the standard implementation. */ + png_set_progressive_read_fn(pp, &d, transform_info, progressive_row, + transform_end); + + /* Now feed data into the reader until we reach the end: */ + modifier_progressive_read(d.pm, pp, pi); + } + else + { + /* modifier_read expects a png_modifier* */ + png_set_read_fn(pp, d.pm, modifier_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* Process the 'info' requirements. Only one image is generated */ + transform_info_imp(&d, pp, pi); + + sequential_row(&d.this, pp, pi, -1, 0); + + if (!d.this.speed) + transform_image_validate(&d, pp, pi); + else + d.this.ps->validated = 1; + } + + modifier_reset(d.pm); + } + + Catch(fault) + { + modifier_reset(voidcast(png_modifier*,(void*)fault)); + } +} + +/* The transforms: */ +#define ITSTRUCT(name) image_transform_##name +#define ITDATA(name) image_transform_data_##name +#define image_transform_ini image_transform_default_ini +#define IT(name)\ +static image_transform ITSTRUCT(name) =\ +{\ + #name,\ + 1, /*enable*/\ + &PT, /*list*/\ + 0, /*global_use*/\ + 0, /*local_use*/\ + 0, /*next*/\ + image_transform_ini,\ + image_transform_png_set_##name##_set,\ + image_transform_png_set_##name##_mod,\ + image_transform_png_set_##name##_add\ +} +#define PT ITSTRUCT(end) /* stores the previous transform */ + +/* To save code: */ +extern void image_transform_default_ini(const image_transform *this, + transform_display *that); /* silence GCC warnings */ + +void /* private, but almost always needed */ +image_transform_default_ini(const image_transform *this, + transform_display *that) +{ + this->next->ini(this->next, that); +} + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +static int +image_transform_default_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return 1; +} +#endif + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* png_set_palette_to_rgb */ +static void +image_transform_png_set_palette_to_rgb_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_palette_to_rgb(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_palette_to_rgb_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that); + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_palette_to_rgb_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return colour_type == PNG_COLOR_TYPE_PALETTE; +} + +IT(palette_to_rgb); +#undef PT +#define PT ITSTRUCT(palette_to_rgb) +#endif /* PNG_READ_EXPAND_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* png_set_tRNS_to_alpha */ +static void +image_transform_png_set_tRNS_to_alpha_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_tRNS_to_alpha(pp); + + /* If there was a tRNS chunk that would get expanded and add an alpha + * channel is_transparent must be updated: + */ + if (that->this.has_tRNS) + that->this.is_transparent = 1; + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_tRNS_to_alpha_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ +#if PNG_LIBPNG_VER < 10700 + /* LIBPNG BUG: this always forces palette images to RGB. */ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that); +#endif + + /* This effectively does an 'expand' only if there is some transparency to + * convert to an alpha channel. + */ + if (that->have_tRNS) +# if PNG_LIBPNG_VER >= 10700 + if (that->colour_type != PNG_COLOR_TYPE_PALETTE && + (that->colour_type & PNG_COLOR_MASK_ALPHA) == 0) +# endif + image_pixel_add_alpha(that, &display->this, 0/*!for background*/); + +#if PNG_LIBPNG_VER < 10700 + /* LIBPNG BUG: otherwise libpng still expands to 8 bits! */ + else + { + if (that->bit_depth < 8) + that->bit_depth =8; + if (that->sample_depth < 8) + that->sample_depth = 8; + } +#endif + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_tRNS_to_alpha_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* We don't know yet whether there will be a tRNS chunk, but we know that + * this transformation should do nothing if there already is an alpha + * channel. In addition, after the bug fix in 1.7.0, there is no longer + * any action on a palette image. + */ + return +# if PNG_LIBPNG_VER >= 10700 + colour_type != PNG_COLOR_TYPE_PALETTE && +# endif + (colour_type & PNG_COLOR_MASK_ALPHA) == 0; +} + +IT(tRNS_to_alpha); +#undef PT +#define PT ITSTRUCT(tRNS_to_alpha) +#endif /* PNG_READ_EXPAND_SUPPORTED */ + +#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED +/* png_set_gray_to_rgb */ +static void +image_transform_png_set_gray_to_rgb_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_gray_to_rgb(pp); + /* NOTE: this doesn't result in tRNS expansion. */ + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_gray_to_rgb_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + /* NOTE: we can actually pend the tRNS processing at this point because we + * can correctly recognize the original pixel value even though we have + * mapped the one gray channel to the three RGB ones, but in fact libpng + * doesn't do this, so we don't either. + */ + if ((that->colour_type & PNG_COLOR_MASK_COLOR) == 0 && that->have_tRNS) + image_pixel_add_alpha(that, &display->this, 0/*!for background*/); + + /* Simply expand the bit depth and alter the colour type as required. */ + if (that->colour_type == PNG_COLOR_TYPE_GRAY) + { + /* RGB images have a bit depth at least equal to '8' */ + if (that->bit_depth < 8) + that->sample_depth = that->bit_depth = 8; + + /* And just changing the colour type works here because the green and blue + * channels are being maintained in lock-step with the red/gray: + */ + that->colour_type = PNG_COLOR_TYPE_RGB; + } + + else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB_ALPHA; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_gray_to_rgb_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_COLOR) == 0; +} + +IT(gray_to_rgb); +#undef PT +#define PT ITSTRUCT(gray_to_rgb) +#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* png_set_expand */ +static void +image_transform_png_set_expand_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_expand(pp); + + if (that->this.has_tRNS) + that->this.is_transparent = 1; + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_expand_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + /* The general expand case depends on what the colour type is: */ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that); + else if (that->bit_depth < 8) /* grayscale */ + that->sample_depth = that->bit_depth = 8; + + if (that->have_tRNS) + image_pixel_add_alpha(that, &display->this, 0/*!for background*/); + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_expand_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* 'expand' should do nothing for RGBA or GA input - no tRNS and the bit + * depth is at least 8 already. + */ + return (colour_type & PNG_COLOR_MASK_ALPHA) == 0; +} + +IT(expand); +#undef PT +#define PT ITSTRUCT(expand) +#endif /* PNG_READ_EXPAND_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_SUPPORTED +/* png_set_expand_gray_1_2_4_to_8 + * Pre 1.7.0 LIBPNG BUG: this just does an 'expand' + */ +static void +image_transform_png_set_expand_gray_1_2_4_to_8_set( + const image_transform *this, transform_display *that, png_structp pp, + png_infop pi) +{ + png_set_expand_gray_1_2_4_to_8(pp); + /* NOTE: don't expect this to expand tRNS */ + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_expand_gray_1_2_4_to_8_mod( + const image_transform *this, image_pixel *that, png_const_structp pp, + const transform_display *display) +{ +#if PNG_LIBPNG_VER < 10700 + image_transform_png_set_expand_mod(this, that, pp, display); +#else + /* Only expand grayscale of bit depth less than 8: */ + if (that->colour_type == PNG_COLOR_TYPE_GRAY && + that->bit_depth < 8) + that->sample_depth = that->bit_depth = 8; + + this->next->mod(this->next, that, pp, display); +#endif /* 1.7 or later */ +} + +static int +image_transform_png_set_expand_gray_1_2_4_to_8_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ +#if PNG_LIBPNG_VER < 10700 + return image_transform_png_set_expand_add(this, that, colour_type, + bit_depth); +#else + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* This should do nothing unless the color type is gray and the bit depth is + * less than 8: + */ + return colour_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8; +#endif /* 1.7 or later */ +} + +IT(expand_gray_1_2_4_to_8); +#undef PT +#define PT ITSTRUCT(expand_gray_1_2_4_to_8) +#endif /* PNG_READ_EXPAND_SUPPORTED */ + +#ifdef PNG_READ_EXPAND_16_SUPPORTED +/* png_set_expand_16 */ +static void +image_transform_png_set_expand_16_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_expand_16(pp); + + /* NOTE: prior to 1.7 libpng does SET_EXPAND as well, so tRNS is expanded. */ +# if PNG_LIBPNG_VER < 10700 + if (that->this.has_tRNS) + that->this.is_transparent = 1; +# endif + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_expand_16_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + /* Expect expand_16 to expand everything to 16 bits as a result of also + * causing 'expand' to happen. + */ + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that); + + if (that->have_tRNS) + image_pixel_add_alpha(that, &display->this, 0/*!for background*/); + + if (that->bit_depth < 16) + that->sample_depth = that->bit_depth = 16; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_expand_16_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + /* expand_16 does something unless the bit depth is already 16. */ + return bit_depth < 16; +} + +IT(expand_16); +#undef PT +#define PT ITSTRUCT(expand_16) +#endif /* PNG_READ_EXPAND_16_SUPPORTED */ + +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* API added in 1.5.4 */ +/* png_set_scale_16 */ +static void +image_transform_png_set_scale_16_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_scale_16(pp); +# if PNG_LIBPNG_VER < 10700 + /* libpng will limit the gamma table size: */ + that->max_gamma_8 = PNG_MAX_GAMMA_8; +# endif + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_scale_16_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->bit_depth == 16) + { + that->sample_depth = that->bit_depth = 8; + if (that->red_sBIT > 8) that->red_sBIT = 8; + if (that->green_sBIT > 8) that->green_sBIT = 8; + if (that->blue_sBIT > 8) that->blue_sBIT = 8; + if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_scale_16_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + return bit_depth > 8; +} + +IT(scale_16); +#undef PT +#define PT ITSTRUCT(scale_16) +#endif /* PNG_READ_SCALE_16_TO_8_SUPPORTED (1.5.4 on) */ + +#ifdef PNG_READ_16_TO_8_SUPPORTED /* the default before 1.5.4 */ +/* png_set_strip_16 */ +static void +image_transform_png_set_strip_16_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_strip_16(pp); +# if PNG_LIBPNG_VER < 10700 + /* libpng will limit the gamma table size: */ + that->max_gamma_8 = PNG_MAX_GAMMA_8; +# endif + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_strip_16_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->bit_depth == 16) + { + that->sample_depth = that->bit_depth = 8; + if (that->red_sBIT > 8) that->red_sBIT = 8; + if (that->green_sBIT > 8) that->green_sBIT = 8; + if (that->blue_sBIT > 8) that->blue_sBIT = 8; + if (that->alpha_sBIT > 8) that->alpha_sBIT = 8; + + /* Prior to 1.5.4 png_set_strip_16 would use an 'accurate' method if this + * configuration option is set. From 1.5.4 the flag is never set and the + * 'scale' API (above) must be used. + */ +# ifdef PNG_READ_ACCURATE_SCALE_SUPPORTED +# if PNG_LIBPNG_VER >= 10504 +# error PNG_READ_ACCURATE_SCALE should not be set +# endif + + /* The strip 16 algorithm drops the low 8 bits rather than calculating + * 1/257, so we need to adjust the permitted errors appropriately: + * Notice that this is only relevant prior to the addition of the + * png_set_scale_16 API in 1.5.4 (but 1.5.4+ always defines the above!) + */ + { + const double d = (255-128.5)/65535; + that->rede += d; + that->greene += d; + that->bluee += d; + that->alphae += d; + } +# endif + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_strip_16_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + return bit_depth > 8; +} + +IT(strip_16); +#undef PT +#define PT ITSTRUCT(strip_16) +#endif /* PNG_READ_16_TO_8_SUPPORTED */ + +#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED +/* png_set_strip_alpha */ +static void +image_transform_png_set_strip_alpha_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_strip_alpha(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_strip_alpha_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY; + else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB; + + that->have_tRNS = 0; + that->alphaf = 1; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_strip_alpha_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_ALPHA) != 0; +} + +IT(strip_alpha); +#undef PT +#define PT ITSTRUCT(strip_alpha) +#endif /* PNG_READ_STRIP_ALPHA_SUPPORTED */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* png_set_rgb_to_gray(png_structp, int err_action, double red, double green) + * png_set_rgb_to_gray_fixed(png_structp, int err_action, png_fixed_point red, + * png_fixed_point green) + * png_get_rgb_to_gray_status + * + * The 'default' test here uses values known to be used inside libpng prior to + * 1.7.0: + * + * red: 6968 + * green: 23434 + * blue: 2366 + * + * These values are being retained for compatibility, along with the somewhat + * broken truncation calculation in the fast-and-inaccurate code path. Older + * versions of libpng will fail the accuracy tests below because they use the + * truncation algorithm everywhere. + */ +#define data ITDATA(rgb_to_gray) +static struct +{ + double gamma; /* File gamma to use in processing */ + + /* The following are the parameters for png_set_rgb_to_gray: */ +# ifdef PNG_FLOATING_POINT_SUPPORTED + double red_to_set; + double green_to_set; +# else + png_fixed_point red_to_set; + png_fixed_point green_to_set; +# endif + + /* The actual coefficients: */ + double red_coefficient; + double green_coefficient; + double blue_coefficient; + + /* Set if the coeefficients have been overridden. */ + int coefficients_overridden; +} data; + +#undef image_transform_ini +#define image_transform_ini image_transform_png_set_rgb_to_gray_ini +static void +image_transform_png_set_rgb_to_gray_ini(const image_transform *this, + transform_display *that) +{ + png_modifier *pm = that->pm; + const color_encoding *e = pm->current_encoding; + + UNUSED(this) + + /* Since we check the encoding this flag must be set: */ + pm->test_uses_encoding = 1; + + /* If 'e' is not NULL chromaticity information is present and either a cHRM + * or an sRGB chunk will be inserted. + */ + if (e != 0) + { + /* Coefficients come from the encoding, but may need to be normalized to a + * white point Y of 1.0 + */ + const double whiteY = e->red.Y + e->green.Y + e->blue.Y; + + data.red_coefficient = e->red.Y; + data.green_coefficient = e->green.Y; + data.blue_coefficient = e->blue.Y; + + if (whiteY != 1) + { + data.red_coefficient /= whiteY; + data.green_coefficient /= whiteY; + data.blue_coefficient /= whiteY; + } + } + + else + { + /* The default (built in) coeffcients, as above: */ +# if PNG_LIBPNG_VER < 10700 + data.red_coefficient = 6968 / 32768.; + data.green_coefficient = 23434 / 32768.; + data.blue_coefficient = 2366 / 32768.; +# else + data.red_coefficient = .2126; + data.green_coefficient = .7152; + data.blue_coefficient = .0722; +# endif + } + + data.gamma = pm->current_gamma; + + /* If not set then the calculations assume linear encoding (implicitly): */ + if (data.gamma == 0) + data.gamma = 1; + + /* The arguments to png_set_rgb_to_gray can override the coefficients implied + * by the color space encoding. If doing exhaustive checks do the override + * in each case, otherwise do it randomly. + */ + if (pm->test_exhaustive) + { + /* First time in coefficients_overridden is 0, the following sets it to 1, + * so repeat if it is set. If a test fails this may mean we subsequently + * skip a non-override test, ignore that. + */ + data.coefficients_overridden = !data.coefficients_overridden; + pm->repeat = data.coefficients_overridden != 0; + } + + else + data.coefficients_overridden = random_choice(); + + if (data.coefficients_overridden) + { + /* These values override the color encoding defaults, simply use random + * numbers. + */ + png_uint_32 ru; + double total; + + ru = random_u32(); + data.green_coefficient = total = (ru & 0xffff) / 65535.; + ru >>= 16; + data.red_coefficient = (1 - total) * (ru & 0xffff) / 65535.; + total += data.red_coefficient; + data.blue_coefficient = 1 - total; + +# ifdef PNG_FLOATING_POINT_SUPPORTED + data.red_to_set = data.red_coefficient; + data.green_to_set = data.green_coefficient; +# else + data.red_to_set = fix(data.red_coefficient); + data.green_to_set = fix(data.green_coefficient); +# endif + + /* The following just changes the error messages: */ + pm->encoding_ignored = 1; + } + + else + { + data.red_to_set = -1; + data.green_to_set = -1; + } + + /* Adjust the error limit in the png_modifier because of the larger errors + * produced in the digitization during the gamma handling. + */ + if (data.gamma != 1) /* Use gamma tables */ + { + if (that->this.bit_depth == 16 || pm->assume_16_bit_calculations) + { + /* The computations have the form: + * + * r * rc + g * gc + b * bc + * + * Each component of which is +/-1/65535 from the gamma_to_1 table + * lookup, resulting in a base error of +/-6. The gamma_from_1 + * conversion adds another +/-2 in the 16-bit case and + * +/-(1<<(15-PNG_MAX_GAMMA_8)) in the 8-bit case. + */ +# if PNG_LIBPNG_VER < 10700 + if (that->this.bit_depth < 16) + that->max_gamma_8 = PNG_MAX_GAMMA_8; +# endif + that->pm->limit += pow( + (that->this.bit_depth == 16 || that->max_gamma_8 > 14 ? + 8. : + 6. + (1<<(15-that->max_gamma_8)) + )/65535, data.gamma); + } + + else + { + /* Rounding to 8 bits in the linear space causes massive errors which + * will trigger the error check in transform_range_check. Fix that + * here by taking the gamma encoding into account. + * + * When DIGITIZE is set because a pre-1.7 version of libpng is being + * tested allow a bigger slack. + * + * NOTE: this number only affects the internal limit check in pngvalid, + * it has no effect on the limits applied to the libpng values. + */ +#if DIGITIZE + that->pm->limit += pow( 2.0/255, data.gamma); +#else + that->pm->limit += pow( 1.0/255, data.gamma); +#endif + } + } + + else + { + /* With no gamma correction a large error comes from the truncation of the + * calculation in the 8 bit case, allow for that here. + */ + if (that->this.bit_depth != 16 && !pm->assume_16_bit_calculations) + that->pm->limit += 4E-3; + } +} + +static void +image_transform_png_set_rgb_to_gray_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + int error_action = 1; /* no error, no defines in png.h */ + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_rgb_to_gray(pp, error_action, data.red_to_set, data.green_to_set); +# else + png_set_rgb_to_gray_fixed(pp, error_action, data.red_to_set, + data.green_to_set); +# endif + +# ifdef PNG_READ_cHRM_SUPPORTED + if (that->pm->current_encoding != 0) + { + /* We have an encoding so a cHRM chunk may have been set; if so then + * check that the libpng APIs give the correct (X,Y,Z) values within + * some margin of error for the round trip through the chromaticity + * form. + */ +# ifdef PNG_FLOATING_POINT_SUPPORTED +# define API_function png_get_cHRM_XYZ +# define API_form "FP" +# define API_type double +# define API_cvt(x) (x) +# else +# define API_function png_get_cHRM_XYZ_fixed +# define API_form "fixed" +# define API_type png_fixed_point +# define API_cvt(x) ((double)(x)/PNG_FP_1) +# endif + + API_type rX, gX, bX; + API_type rY, gY, bY; + API_type rZ, gZ, bZ; + + if ((API_function(pp, pi, &rX, &rY, &rZ, &gX, &gY, &gZ, &bX, &bY, &bZ) + & PNG_INFO_cHRM) != 0) + { + double maxe; + const char *el; + color_encoding e, o; + + /* Expect libpng to return a normalized result, but the original + * color space encoding may not be normalized. + */ + modifier_current_encoding(that->pm, &o); + normalize_color_encoding(&o); + + /* Sanity check the pngvalid code - the coefficients should match + * the normalized Y values of the encoding unless they were + * overridden. + */ + if (data.red_to_set == -1 && data.green_to_set == -1 && + (fabs(o.red.Y - data.red_coefficient) > DBL_EPSILON || + fabs(o.green.Y - data.green_coefficient) > DBL_EPSILON || + fabs(o.blue.Y - data.blue_coefficient) > DBL_EPSILON)) + png_error(pp, "internal pngvalid cHRM coefficient error"); + + /* Generate a colour space encoding. */ + e.gamma = o.gamma; /* not used */ + e.red.X = API_cvt(rX); + e.red.Y = API_cvt(rY); + e.red.Z = API_cvt(rZ); + e.green.X = API_cvt(gX); + e.green.Y = API_cvt(gY); + e.green.Z = API_cvt(gZ); + e.blue.X = API_cvt(bX); + e.blue.Y = API_cvt(bY); + e.blue.Z = API_cvt(bZ); + + /* This should match the original one from the png_modifier, within + * the range permitted by the libpng fixed point representation. + */ + maxe = 0; + el = "-"; /* Set to element name with error */ + +# define CHECK(col,x)\ + {\ + double err = fabs(o.col.x - e.col.x);\ + if (err > maxe)\ + {\ + maxe = err;\ + el = #col "(" #x ")";\ + }\ + } + + CHECK(red,X) + CHECK(red,Y) + CHECK(red,Z) + CHECK(green,X) + CHECK(green,Y) + CHECK(green,Z) + CHECK(blue,X) + CHECK(blue,Y) + CHECK(blue,Z) + + /* Here in both fixed and floating cases to check the values read + * from the cHRm chunk. PNG uses fixed point in the cHRM chunk, so + * we can't expect better than +/-.5E-5 on the result, allow 1E-5. + */ + if (maxe >= 1E-5) + { + size_t pos = 0; + char buffer[256]; + + pos = safecat(buffer, sizeof buffer, pos, API_form); + pos = safecat(buffer, sizeof buffer, pos, " cHRM "); + pos = safecat(buffer, sizeof buffer, pos, el); + pos = safecat(buffer, sizeof buffer, pos, " error: "); + pos = safecatd(buffer, sizeof buffer, pos, maxe, 7); + pos = safecat(buffer, sizeof buffer, pos, " "); + /* Print the color space without the gamma value: */ + pos = safecat_color_encoding(buffer, sizeof buffer, pos, &o, 0); + pos = safecat(buffer, sizeof buffer, pos, " -> "); + pos = safecat_color_encoding(buffer, sizeof buffer, pos, &e, 0); + + png_error(pp, buffer); + } + } + } +# endif /* READ_cHRM */ + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_rgb_to_gray_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if ((that->colour_type & PNG_COLOR_MASK_COLOR) != 0) + { + double gray, err; + +# if PNG_LIBPNG_VER < 10700 + if (that->colour_type == PNG_COLOR_TYPE_PALETTE) + image_pixel_convert_PLTE(that); +# endif + + /* Image now has RGB channels... */ +# if DIGITIZE + { + png_modifier *pm = display->pm; + unsigned int sample_depth = that->sample_depth; + unsigned int calc_depth = (pm->assume_16_bit_calculations ? 16 : + sample_depth); + unsigned int gamma_depth = + (sample_depth == 16 ? + display->max_gamma_8 : + (pm->assume_16_bit_calculations ? + display->max_gamma_8 : + sample_depth)); + int isgray; + double r, g, b; + double rlo, rhi, glo, ghi, blo, bhi, graylo, grayhi; + + /* Do this using interval arithmetic, otherwise it is too difficult to + * handle the errors correctly. + * + * To handle the gamma correction work out the upper and lower bounds + * of the digitized value. Assume rounding here - normally the values + * will be identical after this operation if there is only one + * transform, feel free to delete the png_error checks on this below in + * the future (this is just me trying to ensure it works!) + * + * Interval arithmetic is exact, but to implement it it must be + * possible to control the floating point implementation rounding mode. + * This cannot be done in ANSI-C, so instead I reduce the 'lo' values + * by DBL_EPSILON and increase the 'hi' values by the same. + */ +# define DD(v,d,r) (digitize(v*(1-DBL_EPSILON), d, r) * (1-DBL_EPSILON)) +# define DU(v,d,r) (digitize(v*(1+DBL_EPSILON), d, r) * (1+DBL_EPSILON)) + + r = rlo = rhi = that->redf; + rlo -= that->rede; + rlo = DD(rlo, calc_depth, 1/*round*/); + rhi += that->rede; + rhi = DU(rhi, calc_depth, 1/*round*/); + + g = glo = ghi = that->greenf; + glo -= that->greene; + glo = DD(glo, calc_depth, 1/*round*/); + ghi += that->greene; + ghi = DU(ghi, calc_depth, 1/*round*/); + + b = blo = bhi = that->bluef; + blo -= that->bluee; + blo = DD(blo, calc_depth, 1/*round*/); + bhi += that->bluee; + bhi = DU(bhi, calc_depth, 1/*round*/); + + isgray = r==g && g==b; + + if (data.gamma != 1) + { + const double power = 1/data.gamma; + const double abse = .5/(sample_depth == 16 ? 65535 : 255); + + /* If a gamma calculation is done it is done using lookup tables of + * precision gamma_depth, so the already digitized value above may + * need to be further digitized here. + */ + if (gamma_depth != calc_depth) + { + rlo = DD(rlo, gamma_depth, 0/*truncate*/); + rhi = DU(rhi, gamma_depth, 0/*truncate*/); + glo = DD(glo, gamma_depth, 0/*truncate*/); + ghi = DU(ghi, gamma_depth, 0/*truncate*/); + blo = DD(blo, gamma_depth, 0/*truncate*/); + bhi = DU(bhi, gamma_depth, 0/*truncate*/); + } + + /* 'abse' is the error in the gamma table calculation itself. */ + r = pow(r, power); + rlo = DD(pow(rlo, power)-abse, calc_depth, 1); + rhi = DU(pow(rhi, power)+abse, calc_depth, 1); + + g = pow(g, power); + glo = DD(pow(glo, power)-abse, calc_depth, 1); + ghi = DU(pow(ghi, power)+abse, calc_depth, 1); + + b = pow(b, power); + blo = DD(pow(blo, power)-abse, calc_depth, 1); + bhi = DU(pow(bhi, power)+abse, calc_depth, 1); + } + + /* Now calculate the actual gray values. Although the error in the + * coefficients depends on whether they were specified on the command + * line (in which case truncation to 15 bits happened) or not (rounding + * was used) the maximum error in an individual coefficient is always + * 2/32768, because even in the rounding case the requirement that + * coefficients add up to 32768 can cause a larger rounding error. + * + * The only time when rounding doesn't occur in 1.5.5 and later is when + * the non-gamma code path is used for less than 16 bit data. + */ + gray = r * data.red_coefficient + g * data.green_coefficient + + b * data.blue_coefficient; + + { + int do_round = data.gamma != 1 || calc_depth == 16; + const double ce = 2. / 32768; + + graylo = DD(rlo * (data.red_coefficient-ce) + + glo * (data.green_coefficient-ce) + + blo * (data.blue_coefficient-ce), calc_depth, do_round); + if (graylo > gray) /* always accept the right answer */ + graylo = gray; + + grayhi = DU(rhi * (data.red_coefficient+ce) + + ghi * (data.green_coefficient+ce) + + bhi * (data.blue_coefficient+ce), calc_depth, do_round); + if (grayhi < gray) + grayhi = gray; + } + + /* And invert the gamma. */ + if (data.gamma != 1) + { + const double power = data.gamma; + + /* And this happens yet again, shifting the values once more. */ + if (gamma_depth != sample_depth) + { + rlo = DD(rlo, gamma_depth, 0/*truncate*/); + rhi = DU(rhi, gamma_depth, 0/*truncate*/); + glo = DD(glo, gamma_depth, 0/*truncate*/); + ghi = DU(ghi, gamma_depth, 0/*truncate*/); + blo = DD(blo, gamma_depth, 0/*truncate*/); + bhi = DU(bhi, gamma_depth, 0/*truncate*/); + } + + gray = pow(gray, power); + graylo = DD(pow(graylo, power), sample_depth, 1); + grayhi = DU(pow(grayhi, power), sample_depth, 1); + } + +# undef DD +# undef DU + + /* Now the error can be calculated. + * + * If r==g==b because there is no overall gamma correction libpng + * currently preserves the original value. + */ + if (isgray) + err = (that->rede + that->greene + that->bluee)/3; + + else + { + err = fabs(grayhi-gray); + + if (fabs(gray - graylo) > err) + err = fabs(graylo-gray); + +#if !RELEASE_BUILD + /* Check that this worked: */ + if (err > pm->limit) + { + size_t pos = 0; + char buffer[128]; + + pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); + pos = safecatd(buffer, sizeof buffer, pos, err, 6); + pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); + pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6); + png_warning(pp, buffer); + pm->limit = err; + } +#endif /* !RELEASE_BUILD */ + } + } +# else /* !DIGITIZE */ + { + double r = that->redf; + double re = that->rede; + double g = that->greenf; + double ge = that->greene; + double b = that->bluef; + double be = that->bluee; + +# if PNG_LIBPNG_VER < 10700 + /* The true gray case involves no math in earlier versions (not + * true, there was some if gamma correction was happening too.) + */ + if (r == g && r == b) + { + gray = r; + err = re; + if (err < ge) err = ge; + if (err < be) err = be; + } + + else +# endif /* before 1.7 */ + if (data.gamma == 1) + { + /* There is no need to do the conversions to and from linear space, + * so the calculation should be a lot more accurate. There is a + * built in error in the coefficients because they only have 15 bits + * and are adjusted to make sure they add up to 32768. This + * involves a integer calculation with truncation of the form: + * + * ((int)(coefficient * 100000) * 32768)/100000 + * + * This is done to the red and green coefficients (the ones + * provided to the API) then blue is calculated from them so the + * result adds up to 32768. In the worst case this can result in + * a -1 error in red and green and a +2 error in blue. Consequently + * the worst case in the calculation below is 2/32768 error. + * + * TODO: consider fixing this in libpng by rounding the calculation + * limiting the error to 1/32768. + * + * Handling this by adding 2/32768 here avoids needing to increase + * the global error limits to take this into account.) + */ + gray = r * data.red_coefficient + g * data.green_coefficient + + b * data.blue_coefficient; + err = re * data.red_coefficient + ge * data.green_coefficient + + be * data.blue_coefficient + 2./32768 + gray * 5 * DBL_EPSILON; + } + + else + { + /* The calculation happens in linear space, and this produces much + * wider errors in the encoded space. These are handled here by + * factoring the errors in to the calculation. There are two table + * lookups in the calculation and each introduces a quantization + * error defined by the table size. + */ + png_modifier *pm = display->pm; + double in_qe = (that->sample_depth > 8 ? .5/65535 : .5/255); + double out_qe = (that->sample_depth > 8 ? .5/65535 : + (pm->assume_16_bit_calculations ? .5/(1<max_gamma_8) : + .5/255)); + double rhi, ghi, bhi, grayhi; + double g1 = 1/data.gamma; + + rhi = r + re + in_qe; if (rhi > 1) rhi = 1; + r -= re + in_qe; if (r < 0) r = 0; + ghi = g + ge + in_qe; if (ghi > 1) ghi = 1; + g -= ge + in_qe; if (g < 0) g = 0; + bhi = b + be + in_qe; if (bhi > 1) bhi = 1; + b -= be + in_qe; if (b < 0) b = 0; + + r = pow(r, g1)*(1-DBL_EPSILON); rhi = pow(rhi, g1)*(1+DBL_EPSILON); + g = pow(g, g1)*(1-DBL_EPSILON); ghi = pow(ghi, g1)*(1+DBL_EPSILON); + b = pow(b, g1)*(1-DBL_EPSILON); bhi = pow(bhi, g1)*(1+DBL_EPSILON); + + /* Work out the lower and upper bounds for the gray value in the + * encoded space, then work out an average and error. Remove the + * previously added input quantization error at this point. + */ + gray = r * data.red_coefficient + g * data.green_coefficient + + b * data.blue_coefficient - 2./32768 - out_qe; + if (gray <= 0) + gray = 0; + else + { + gray *= (1 - 6 * DBL_EPSILON); + gray = pow(gray, data.gamma) * (1-DBL_EPSILON); + } + + grayhi = rhi * data.red_coefficient + ghi * data.green_coefficient + + bhi * data.blue_coefficient + 2./32768 + out_qe; + grayhi *= (1 + 6 * DBL_EPSILON); + if (grayhi >= 1) + grayhi = 1; + else + grayhi = pow(grayhi, data.gamma) * (1+DBL_EPSILON); + + err = (grayhi - gray) / 2; + gray = (grayhi + gray) / 2; + + if (err <= in_qe) + err = gray * DBL_EPSILON; + + else + err -= in_qe; + +#if !RELEASE_BUILD + /* Validate that the error is within limits (this has caused + * problems before, it's much easier to detect them here.) + */ + if (err > pm->limit) + { + size_t pos = 0; + char buffer[128]; + + pos = safecat(buffer, sizeof buffer, pos, "rgb_to_gray error "); + pos = safecatd(buffer, sizeof buffer, pos, err, 6); + pos = safecat(buffer, sizeof buffer, pos, " exceeds limit "); + pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6); + png_warning(pp, buffer); + pm->limit = err; + } +#endif /* !RELEASE_BUILD */ + } + } +# endif /* !DIGITIZE */ + + that->bluef = that->greenf = that->redf = gray; + that->bluee = that->greene = that->rede = err; + + /* The sBIT is the minimum of the three colour channel sBITs. */ + if (that->red_sBIT > that->green_sBIT) + that->red_sBIT = that->green_sBIT; + if (that->red_sBIT > that->blue_sBIT) + that->red_sBIT = that->blue_sBIT; + that->blue_sBIT = that->green_sBIT = that->red_sBIT; + + /* And remove the colour bit in the type: */ + if (that->colour_type == PNG_COLOR_TYPE_RGB) + that->colour_type = PNG_COLOR_TYPE_GRAY; + else if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY_ALPHA; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_rgb_to_gray_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return (colour_type & PNG_COLOR_MASK_COLOR) != 0; +} + +#undef data +IT(rgb_to_gray); +#undef PT +#define PT ITSTRUCT(rgb_to_gray) +#undef image_transform_ini +#define image_transform_ini image_transform_default_ini +#endif /* PNG_READ_RGB_TO_GRAY_SUPPORTED */ + +#ifdef PNG_READ_BACKGROUND_SUPPORTED +/* png_set_background(png_structp, png_const_color_16p background_color, + * int background_gamma_code, int need_expand, double background_gamma) + * png_set_background_fixed(png_structp, png_const_color_16p background_color, + * int background_gamma_code, int need_expand, + * png_fixed_point background_gamma) + * + * This ignores the gamma (at present.) +*/ +#define data ITDATA(background) +static image_pixel data; + +static void +image_transform_png_set_background_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_byte colour_type, bit_depth; + png_byte random_bytes[8]; /* 8 bytes - 64 bits - the biggest pixel */ + int expand; + png_color_16 back; + + /* We need a background colour, because we don't know exactly what transforms + * have been set we have to supply the colour in the original file format and + * so we need to know what that is! The background colour is stored in the + * transform_display. + */ + R8(random_bytes); + + /* Read the random value, for colour type 3 the background colour is actually + * expressed as a 24bit rgb, not an index. + */ + colour_type = that->this.colour_type; + if (colour_type == 3) + { + colour_type = PNG_COLOR_TYPE_RGB; + bit_depth = 8; + expand = 0; /* passing in an RGB not a pixel index */ + } + + else + { + if (that->this.has_tRNS) + that->this.is_transparent = 1; + + bit_depth = that->this.bit_depth; + expand = 1; + } + + image_pixel_init(&data, random_bytes, colour_type, + bit_depth, 0/*x*/, 0/*unused: palette*/, NULL/*format*/); + + /* Extract the background colour from this image_pixel, but make sure the + * unused fields of 'back' are garbage. + */ + R8(back); + + if (colour_type & PNG_COLOR_MASK_COLOR) + { + back.red = (png_uint_16)data.red; + back.green = (png_uint_16)data.green; + back.blue = (png_uint_16)data.blue; + } + + else + back.gray = (png_uint_16)data.red; + +#ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_background(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0); +#else + png_set_background_fixed(pp, &back, PNG_BACKGROUND_GAMMA_FILE, expand, 0); +#endif + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_background_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + /* Check for tRNS first: */ + if (that->have_tRNS && that->colour_type != PNG_COLOR_TYPE_PALETTE) + image_pixel_add_alpha(that, &display->this, 1/*for background*/); + + /* This is only necessary if the alpha value is less than 1. */ + if (that->alphaf < 1) + { + /* Now we do the background calculation without any gamma correction. */ + if (that->alphaf <= 0) + { + that->redf = data.redf; + that->greenf = data.greenf; + that->bluef = data.bluef; + + that->rede = data.rede; + that->greene = data.greene; + that->bluee = data.bluee; + + that->red_sBIT= data.red_sBIT; + that->green_sBIT= data.green_sBIT; + that->blue_sBIT= data.blue_sBIT; + } + + else /* 0 < alpha < 1 */ + { + double alf = 1 - that->alphaf; + + that->redf = that->redf * that->alphaf + data.redf * alf; + that->rede = that->rede * that->alphaf + data.rede * alf + + DBL_EPSILON; + that->greenf = that->greenf * that->alphaf + data.greenf * alf; + that->greene = that->greene * that->alphaf + data.greene * alf + + DBL_EPSILON; + that->bluef = that->bluef * that->alphaf + data.bluef * alf; + that->bluee = that->bluee * that->alphaf + data.bluee * alf + + DBL_EPSILON; + } + + /* Remove the alpha type and set the alpha (not in that order.) */ + that->alphaf = 1; + that->alphae = 0; + } + + if (that->colour_type == PNG_COLOR_TYPE_RGB_ALPHA) + that->colour_type = PNG_COLOR_TYPE_RGB; + else if (that->colour_type == PNG_COLOR_TYPE_GRAY_ALPHA) + that->colour_type = PNG_COLOR_TYPE_GRAY; + /* PNG_COLOR_TYPE_PALETTE is not changed */ + + this->next->mod(this->next, that, pp, display); +} + +#define image_transform_png_set_background_add image_transform_default_add + +#undef data +IT(background); +#undef PT +#define PT ITSTRUCT(background) +#endif /* PNG_READ_BACKGROUND_SUPPORTED */ + +/* png_set_quantize(png_structp, png_colorp palette, int num_palette, + * int maximum_colors, png_const_uint_16p histogram, int full_quantize) + * + * Very difficult to validate this! + */ +/*NOTE: TBD NYI */ + +/* The data layout transforms are handled by swapping our own channel data, + * necessarily these need to happen at the end of the transform list because the + * semantic of the channels changes after these are executed. Some of these, + * like set_shift and set_packing, can't be done at present because they change + * the layout of the data at the sub-sample level so sample() won't get the + * right answer. + */ +/* png_set_invert_alpha */ +#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED +/* Invert the alpha channel + * + * png_set_invert_alpha(png_structrp png_ptr) + */ +static void +image_transform_png_set_invert_alpha_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_invert_alpha(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_invert_alpha_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->colour_type & 4) + that->alpha_inverted = 1; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_invert_alpha_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* Only has an effect on pixels with alpha: */ + return (colour_type & 4) != 0; +} + +IT(invert_alpha); +#undef PT +#define PT ITSTRUCT(invert_alpha) + +#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */ + +/* png_set_bgr */ +#ifdef PNG_READ_BGR_SUPPORTED +/* Swap R,G,B channels to order B,G,R. + * + * png_set_bgr(png_structrp png_ptr) + * + * This only has an effect on RGB and RGBA pixels. + */ +static void +image_transform_png_set_bgr_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_bgr(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_bgr_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->colour_type == PNG_COLOR_TYPE_RGB || + that->colour_type == PNG_COLOR_TYPE_RGBA) + that->swap_rgb = 1; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_bgr_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return colour_type == PNG_COLOR_TYPE_RGB || + colour_type == PNG_COLOR_TYPE_RGBA; +} + +IT(bgr); +#undef PT +#define PT ITSTRUCT(bgr) + +#endif /* PNG_READ_BGR_SUPPORTED */ + +/* png_set_swap_alpha */ +#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED +/* Put the alpha channel first. + * + * png_set_swap_alpha(png_structrp png_ptr) + * + * This only has an effect on GA and RGBA pixels. + */ +static void +image_transform_png_set_swap_alpha_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_swap_alpha(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_swap_alpha_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->colour_type == PNG_COLOR_TYPE_GA || + that->colour_type == PNG_COLOR_TYPE_RGBA) + that->alpha_first = 1; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_swap_alpha_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return colour_type == PNG_COLOR_TYPE_GA || + colour_type == PNG_COLOR_TYPE_RGBA; +} + +IT(swap_alpha); +#undef PT +#define PT ITSTRUCT(swap_alpha) + +#endif /* PNG_READ_SWAP_ALPHA_SUPPORTED */ + +/* png_set_swap */ +#ifdef PNG_READ_SWAP_SUPPORTED +/* Byte swap 16-bit components. + * + * png_set_swap(png_structrp png_ptr) + */ +static void +image_transform_png_set_swap_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_swap(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_swap_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->bit_depth == 16) + that->swap16 = 1; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_swap_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + return bit_depth == 16; +} + +IT(swap); +#undef PT +#define PT ITSTRUCT(swap) + +#endif /* PNG_READ_SWAP_SUPPORTED */ + +#ifdef PNG_READ_FILLER_SUPPORTED +/* Add a filler byte to 8-bit Gray or 24-bit RGB images. + * + * png_set_filler, (png_structp png_ptr, png_uint_32 filler, int flags)); + * + * Flags: + * + * PNG_FILLER_BEFORE + * PNG_FILLER_AFTER + */ +#define data ITDATA(filler) +static struct +{ + png_uint_32 filler; + int flags; +} data; + +static void +image_transform_png_set_filler_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + /* Need a random choice for 'before' and 'after' as well as for the + * filler. The 'filler' value has all 32 bits set, but only bit_depth + * will be used. At this point we don't know bit_depth. + */ + data.filler = random_u32(); + data.flags = random_choice(); + + png_set_filler(pp, data.filler, data.flags); + + /* The standard display handling stuff also needs to know that + * there is a filler, so set that here. + */ + that->this.filler = 1; + + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_filler_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->bit_depth >= 8 && + (that->colour_type == PNG_COLOR_TYPE_RGB || + that->colour_type == PNG_COLOR_TYPE_GRAY)) + { + unsigned int max = (1U << that->bit_depth)-1; + that->alpha = data.filler & max; + that->alphaf = ((double)that->alpha) / max; + that->alphae = 0; + + /* The filler has been stored in the alpha channel, we must record + * that this has been done for the checking later on, the color + * type is faked to have an alpha channel, but libpng won't report + * this; the app has to know the extra channel is there and this + * was recording in standard_display::filler above. + */ + that->colour_type |= 4; /* alpha added */ + that->alpha_first = data.flags == PNG_FILLER_BEFORE; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_filler_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + this->next = *that; + *that = this; + + return bit_depth >= 8 && (colour_type == PNG_COLOR_TYPE_RGB || + colour_type == PNG_COLOR_TYPE_GRAY); +} + +#undef data +IT(filler); +#undef PT +#define PT ITSTRUCT(filler) + +/* png_set_add_alpha, (png_structp png_ptr, png_uint_32 filler, int flags)); */ +/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +#define data ITDATA(add_alpha) +static struct +{ + png_uint_32 filler; + int flags; +} data; + +static void +image_transform_png_set_add_alpha_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + /* Need a random choice for 'before' and 'after' as well as for the + * filler. The 'filler' value has all 32 bits set, but only bit_depth + * will be used. At this point we don't know bit_depth. + */ + data.filler = random_u32(); + data.flags = random_choice(); + + png_set_add_alpha(pp, data.filler, data.flags); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_add_alpha_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->bit_depth >= 8 && + (that->colour_type == PNG_COLOR_TYPE_RGB || + that->colour_type == PNG_COLOR_TYPE_GRAY)) + { + unsigned int max = (1U << that->bit_depth)-1; + that->alpha = data.filler & max; + that->alphaf = ((double)that->alpha) / max; + that->alphae = 0; + + that->colour_type |= 4; /* alpha added */ + that->alpha_first = data.flags == PNG_FILLER_BEFORE; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_add_alpha_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + this->next = *that; + *that = this; + + return bit_depth >= 8 && (colour_type == PNG_COLOR_TYPE_RGB || + colour_type == PNG_COLOR_TYPE_GRAY); +} + +#undef data +IT(add_alpha); +#undef PT +#define PT ITSTRUCT(add_alpha) + +#endif /* PNG_READ_FILLER_SUPPORTED */ + +/* png_set_packing */ +#ifdef PNG_READ_PACK_SUPPORTED +/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. + * + * png_set_packing(png_structrp png_ptr) + * + * This should only affect grayscale and palette images with less than 8 bits + * per pixel. + */ +static void +image_transform_png_set_packing_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_packing(pp); + that->unpacked = 1; + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_packing_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + /* The general expand case depends on what the colour type is, + * low bit-depth pixel values are unpacked into bytes without + * scaling, so sample_depth is not changed. + */ + if (that->bit_depth < 8) /* grayscale or palette */ + that->bit_depth = 8; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_packing_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + /* Nothing should happen unless the bit depth is less than 8: */ + return bit_depth < 8; +} + +IT(packing); +#undef PT +#define PT ITSTRUCT(packing) + +#endif /* PNG_READ_PACK_SUPPORTED */ + +/* png_set_packswap */ +#ifdef PNG_READ_PACKSWAP_SUPPORTED +/* Swap pixels packed into bytes; reverses the order on screen so that + * the high order bits correspond to the rightmost pixels. + * + * png_set_packswap(png_structrp png_ptr) + */ +static void +image_transform_png_set_packswap_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_packswap(pp); + that->this.littleendian = 1; + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_packswap_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->bit_depth < 8) + that->littleendian = 1; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_packswap_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(colour_type) + + this->next = *that; + *that = this; + + return bit_depth < 8; +} + +IT(packswap); +#undef PT +#define PT ITSTRUCT(packswap) + +#endif /* PNG_READ_PACKSWAP_SUPPORTED */ + + +/* png_set_invert_mono */ +#ifdef PNG_READ_INVERT_MONO_SUPPORTED +/* Invert the gray channel + * + * png_set_invert_mono(png_structrp png_ptr) + */ +static void +image_transform_png_set_invert_mono_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_invert_mono(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_invert_mono_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + if (that->colour_type & 4) + that->mono_inverted = 1; + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_invert_mono_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + /* Only has an effect on pixels with no colour: */ + return (colour_type & 2) == 0; +} + +IT(invert_mono); +#undef PT +#define PT ITSTRUCT(invert_mono) + +#endif /* PNG_READ_INVERT_MONO_SUPPORTED */ + +#ifdef PNG_READ_SHIFT_SUPPORTED +/* png_set_shift(png_structp, png_const_color_8p true_bits) + * + * The output pixels will be shifted by the given true_bits + * values. + */ +#define data ITDATA(shift) +static png_color_8 data; + +static void +image_transform_png_set_shift_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + /* Get a random set of shifts. The shifts need to do something + * to test the transform, so they are limited to the bit depth + * of the input image. Notice that in the following the 'gray' + * field is randomized independently. This acts as a check that + * libpng does use the correct field. + */ + unsigned int depth = that->this.bit_depth; + + data.red = (png_byte)/*SAFE*/(random_mod(depth)+1); + data.green = (png_byte)/*SAFE*/(random_mod(depth)+1); + data.blue = (png_byte)/*SAFE*/(random_mod(depth)+1); + data.gray = (png_byte)/*SAFE*/(random_mod(depth)+1); + data.alpha = (png_byte)/*SAFE*/(random_mod(depth)+1); + + png_set_shift(pp, &data); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_shift_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + /* Copy the correct values into the sBIT fields, libpng does not do + * anything to palette data: + */ + if (that->colour_type != PNG_COLOR_TYPE_PALETTE) + { + that->sig_bits = 1; + + /* The sBIT fields are reset to the values previously sent to + * png_set_shift according to the colour type. + * does. + */ + if (that->colour_type & 2) /* RGB channels */ + { + that->red_sBIT = data.red; + that->green_sBIT = data.green; + that->blue_sBIT = data.blue; + } + + else /* One grey channel */ + that->red_sBIT = that->green_sBIT = that->blue_sBIT = data.gray; + + that->alpha_sBIT = data.alpha; + } + + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_shift_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + UNUSED(bit_depth) + + this->next = *that; + *that = this; + + return colour_type != PNG_COLOR_TYPE_PALETTE; +} + +IT(shift); +#undef PT +#define PT ITSTRUCT(shift) + +#endif /* PNG_READ_SHIFT_SUPPORTED */ + +#ifdef THIS_IS_THE_PROFORMA +static void +image_transform_png_set_@_set(const image_transform *this, + transform_display *that, png_structp pp, png_infop pi) +{ + png_set_@(pp); + this->next->set(this->next, that, pp, pi); +} + +static void +image_transform_png_set_@_mod(const image_transform *this, + image_pixel *that, png_const_structp pp, + const transform_display *display) +{ + this->next->mod(this->next, that, pp, display); +} + +static int +image_transform_png_set_@_add(image_transform *this, + const image_transform **that, png_byte colour_type, png_byte bit_depth) +{ + this->next = *that; + *that = this; + + return 1; +} + +IT(@); +#endif + + +/* This may just be 'end' if all the transforms are disabled! */ +static image_transform *const image_transform_first = &PT; + +static void +transform_enable(const char *name) +{ + /* Everything starts out enabled, so if we see an 'enable' disabled + * everything else the first time round. + */ + static int all_disabled = 0; + int found_it = 0; + image_transform *list = image_transform_first; + + while (list != &image_transform_end) + { + if (strcmp(list->name, name) == 0) + { + list->enable = 1; + found_it = 1; + } + else if (!all_disabled) + list->enable = 0; + + list = list->list; + } + + all_disabled = 1; + + if (!found_it) + { + fprintf(stderr, "pngvalid: --transform-enable=%s: unknown transform\n", + name); + exit(99); + } +} + +static void +transform_disable(const char *name) +{ + image_transform *list = image_transform_first; + + while (list != &image_transform_end) + { + if (strcmp(list->name, name) == 0) + { + list->enable = 0; + return; + } + + list = list->list; + } + + fprintf(stderr, "pngvalid: --transform-disable=%s: unknown transform\n", + name); + exit(99); +} + +static void +image_transform_reset_count(void) +{ + image_transform *next = image_transform_first; + int count = 0; + + while (next != &image_transform_end) + { + next->local_use = 0; + next->next = 0; + next = next->list; + ++count; + } + + /* This can only happen if we every have more than 32 transforms (excluding + * the end) in the list. + */ + if (count > 32) abort(); +} + +static int +image_transform_test_counter(png_uint_32 counter, unsigned int max) +{ + /* Test the list to see if there is any point contining, given a current + * counter and a 'max' value. + */ + image_transform *next = image_transform_first; + + while (next != &image_transform_end) + { + /* For max 0 or 1 continue until the counter overflows: */ + counter >>= 1; + + /* Continue if any entry hasn't reacked the max. */ + if (max > 1 && next->local_use < max) + return 1; + next = next->list; + } + + return max <= 1 && counter == 0; +} + +static png_uint_32 +image_transform_add(const image_transform **this, unsigned int max, + png_uint_32 counter, char *name, size_t sizeof_name, size_t *pos, + png_byte colour_type, png_byte bit_depth) +{ + for (;;) /* until we manage to add something */ + { + png_uint_32 mask; + image_transform *list; + + /* Find the next counter value, if the counter is zero this is the start + * of the list. This routine always returns the current counter (not the + * next) so it returns 0 at the end and expects 0 at the beginning. + */ + if (counter == 0) /* first time */ + { + image_transform_reset_count(); + if (max <= 1) + counter = 1; + else + counter = random_32(); + } + else /* advance the counter */ + { + switch (max) + { + case 0: ++counter; break; + case 1: counter <<= 1; break; + default: counter = random_32(); break; + } + } + + /* Now add all these items, if possible */ + *this = &image_transform_end; + list = image_transform_first; + mask = 1; + + /* Go through the whole list adding anything that the counter selects: */ + while (list != &image_transform_end) + { + if ((counter & mask) != 0 && list->enable && + (max == 0 || list->local_use < max)) + { + /* Candidate to add: */ + if (list->add(list, this, colour_type, bit_depth) || max == 0) + { + /* Added, so add to the name too. */ + *pos = safecat(name, sizeof_name, *pos, " +"); + *pos = safecat(name, sizeof_name, *pos, list->name); + } + + else + { + /* Not useful and max>0, so remove it from *this: */ + *this = list->next; + list->next = 0; + + /* And, since we know it isn't useful, stop it being added again + * in this run: + */ + list->local_use = max; + } + } + + mask <<= 1; + list = list->list; + } + + /* Now if anything was added we have something to do. */ + if (*this != &image_transform_end) + return counter; + + /* Nothing added, but was there anything in there to add? */ + if (!image_transform_test_counter(counter, max)) + return 0; + } +} + +static void +perform_transform_test(png_modifier *pm) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + unsigned int palette_number = 0; + + while (next_format(&colour_type, &bit_depth, &palette_number, pm->test_lbg, + pm->test_tRNS)) + { + png_uint_32 counter = 0; + size_t base_pos; + char name[64]; + + base_pos = safecat(name, sizeof name, 0, "transform:"); + + for (;;) + { + size_t pos = base_pos; + const image_transform *list = 0; + + /* 'max' is currently hardwired to '1'; this should be settable on the + * command line. + */ + counter = image_transform_add(&list, 1/*max*/, counter, + name, sizeof name, &pos, colour_type, bit_depth); + + if (counter == 0) + break; + + /* The command line can change this to checking interlaced images. */ + do + { + pm->repeat = 0; + transform_test(pm, FILEID(colour_type, bit_depth, palette_number, + pm->interlace_type, 0, 0, 0), list, name); + + if (fail(pm)) + return; + } + while (pm->repeat); + } + } +} +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + +/********************************* GAMMA TESTS ********************************/ +#ifdef PNG_READ_GAMMA_SUPPORTED +/* Reader callbacks and implementations, where they differ from the standard + * ones. + */ +typedef struct gamma_display +{ + standard_display this; + + /* Parameters */ + png_modifier* pm; + double file_gamma; + double screen_gamma; + double background_gamma; + png_byte sbit; + int threshold_test; + int use_input_precision; + int scale16; + int expand16; + int do_background; + png_color_16 background_color; + + /* Local variables */ + double maxerrout; + double maxerrpc; + double maxerrabs; +} gamma_display; + +#define ALPHA_MODE_OFFSET 4 + +static void +gamma_display_init(gamma_display *dp, png_modifier *pm, png_uint_32 id, + double file_gamma, double screen_gamma, png_byte sbit, int threshold_test, + int use_input_precision, int scale16, int expand16, + int do_background, const png_color_16 *pointer_to_the_background_color, + double background_gamma) +{ + /* Standard fields */ + standard_display_init(&dp->this, &pm->this, id, do_read_interlace, + pm->use_update_info); + + /* Parameter fields */ + dp->pm = pm; + dp->file_gamma = file_gamma; + dp->screen_gamma = screen_gamma; + dp->background_gamma = background_gamma; + dp->sbit = sbit; + dp->threshold_test = threshold_test; + dp->use_input_precision = use_input_precision; + dp->scale16 = scale16; + dp->expand16 = expand16; + dp->do_background = do_background; + if (do_background && pointer_to_the_background_color != 0) + dp->background_color = *pointer_to_the_background_color; + else + memset(&dp->background_color, 0, sizeof dp->background_color); + + /* Local variable fields */ + dp->maxerrout = dp->maxerrpc = dp->maxerrabs = 0; +} + +static void +gamma_info_imp(gamma_display *dp, png_structp pp, png_infop pi) +{ + /* Reuse the standard stuff as appropriate. */ + standard_info_part1(&dp->this, pp, pi); + + /* If requested strip 16 to 8 bits - this is handled automagically below + * because the output bit depth is read from the library. Note that there + * are interactions with sBIT but, internally, libpng makes sbit at most + * PNG_MAX_GAMMA_8 prior to 1.7 when doing the following. + */ + if (dp->scale16) +# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_set_scale_16(pp); +# else + /* The following works both in 1.5.4 and earlier versions: */ +# ifdef PNG_READ_16_TO_8_SUPPORTED + png_set_strip_16(pp); +# else + png_error(pp, "scale16 (16 to 8 bit conversion) not supported"); +# endif +# endif + + if (dp->expand16) +# ifdef PNG_READ_EXPAND_16_SUPPORTED + png_set_expand_16(pp); +# else + png_error(pp, "expand16 (8 to 16 bit conversion) not supported"); +# endif + + if (dp->do_background >= ALPHA_MODE_OFFSET) + { +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + { + /* This tests the alpha mode handling, if supported. */ + int mode = dp->do_background - ALPHA_MODE_OFFSET; + + /* The gamma value is the output gamma, and is in the standard, + * non-inverted, representation. It provides a default for the PNG file + * gamma, but since the file has a gAMA chunk this does not matter. + */ + const double sg = dp->screen_gamma; +# ifndef PNG_FLOATING_POINT_SUPPORTED + png_fixed_point g = fix(sg); +# endif + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_alpha_mode(pp, mode, sg); +# else + png_set_alpha_mode_fixed(pp, mode, g); +# endif + + /* However, for the standard Porter-Duff algorithm the output defaults + * to be linear, so if the test requires non-linear output it must be + * corrected here. + */ + if (mode == PNG_ALPHA_STANDARD && sg != 1) + { +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_gamma(pp, sg, dp->file_gamma); +# else + png_fixed_point f = fix(dp->file_gamma); + png_set_gamma_fixed(pp, g, f); +# endif + } + } +# else + png_error(pp, "alpha mode handling not supported"); +# endif + } + + else + { + /* Set up gamma processing. */ +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_gamma(pp, dp->screen_gamma, dp->file_gamma); +# else + { + png_fixed_point s = fix(dp->screen_gamma); + png_fixed_point f = fix(dp->file_gamma); + png_set_gamma_fixed(pp, s, f); + } +# endif + + if (dp->do_background) + { +# ifdef PNG_READ_BACKGROUND_SUPPORTED + /* NOTE: this assumes the caller provided the correct background gamma! + */ + const double bg = dp->background_gamma; +# ifndef PNG_FLOATING_POINT_SUPPORTED + png_fixed_point g = fix(bg); +# endif + +# ifdef PNG_FLOATING_POINT_SUPPORTED + png_set_background(pp, &dp->background_color, dp->do_background, + 0/*need_expand*/, bg); +# else + png_set_background_fixed(pp, &dp->background_color, + dp->do_background, 0/*need_expand*/, g); +# endif +# else + png_error(pp, "png_set_background not supported"); +# endif + } + } + + { + int i = dp->this.use_update_info; + /* Always do one call, even if use_update_info is 0. */ + do + png_read_update_info(pp, pi); + while (--i > 0); + } + + /* Now we may get a different cbRow: */ + standard_info_part2(&dp->this, pp, pi, 1 /*images*/); +} + +static void PNGCBAPI +gamma_info(png_structp pp, png_infop pi) +{ + gamma_info_imp(voidcast(gamma_display*, png_get_progressive_ptr(pp)), pp, + pi); +} + +/* Validate a single component value - the routine gets the input and output + * sample values as unscaled PNG component values along with a cache of all the + * information required to validate the values. + */ +typedef struct validate_info +{ + png_const_structp pp; + gamma_display *dp; + png_byte sbit; + int use_input_precision; + int do_background; + int scale16; + unsigned int sbit_max; + unsigned int isbit_shift; + unsigned int outmax; + + double gamma_correction; /* Overall correction required. */ + double file_inverse; /* Inverse of file gamma. */ + double screen_gamma; + double screen_inverse; /* Inverse of screen gamma. */ + + double background_red; /* Linear background value, red or gray. */ + double background_green; + double background_blue; + + double maxabs; + double maxpc; + double maxcalc; + double maxout; + double maxout_total; /* Total including quantization error */ + double outlog; + int outquant; +} +validate_info; + +static void +init_validate_info(validate_info *vi, gamma_display *dp, png_const_structp pp, + int in_depth, int out_depth) +{ + unsigned int outmax = (1U<pp = pp; + vi->dp = dp; + + if (dp->sbit > 0 && dp->sbit < in_depth) + { + vi->sbit = dp->sbit; + vi->isbit_shift = in_depth - dp->sbit; + } + + else + { + vi->sbit = (png_byte)in_depth; + vi->isbit_shift = 0; + } + + vi->sbit_max = (1U << vi->sbit)-1; + + /* This mimics the libpng threshold test, '0' is used to prevent gamma + * correction in the validation test. + */ + vi->screen_gamma = dp->screen_gamma; + if (fabs(vi->screen_gamma-1) < PNG_GAMMA_THRESHOLD) + vi->screen_gamma = vi->screen_inverse = 0; + else + vi->screen_inverse = 1/vi->screen_gamma; + + vi->use_input_precision = dp->use_input_precision; + vi->outmax = outmax; + vi->maxabs = abserr(dp->pm, in_depth, out_depth); + vi->maxpc = pcerr(dp->pm, in_depth, out_depth); + vi->maxcalc = calcerr(dp->pm, in_depth, out_depth); + vi->maxout = outerr(dp->pm, in_depth, out_depth); + vi->outquant = output_quantization_factor(dp->pm, in_depth, out_depth); + vi->maxout_total = vi->maxout + vi->outquant * .5; + vi->outlog = outlog(dp->pm, in_depth, out_depth); + + if ((dp->this.colour_type & PNG_COLOR_MASK_ALPHA) != 0 || + (dp->this.colour_type == 3 && dp->this.is_transparent) || + ((dp->this.colour_type == 0 || dp->this.colour_type == 2) && + dp->this.has_tRNS)) + { + vi->do_background = dp->do_background; + + if (vi->do_background != 0) + { + const double bg_inverse = 1/dp->background_gamma; + double r, g, b; + + /* Caller must at least put the gray value into the red channel */ + r = dp->background_color.red; r /= outmax; + g = dp->background_color.green; g /= outmax; + b = dp->background_color.blue; b /= outmax; + +# if 0 + /* libpng doesn't do this optimization, if we do pngvalid will fail. + */ + if (fabs(bg_inverse-1) >= PNG_GAMMA_THRESHOLD) +# endif + { + r = pow(r, bg_inverse); + g = pow(g, bg_inverse); + b = pow(b, bg_inverse); + } + + vi->background_red = r; + vi->background_green = g; + vi->background_blue = b; + } + } + else /* Do not expect any background processing */ + vi->do_background = 0; + + if (vi->do_background == 0) + vi->background_red = vi->background_green = vi->background_blue = 0; + + vi->gamma_correction = 1/(dp->file_gamma*dp->screen_gamma); + if (fabs(vi->gamma_correction-1) < PNG_GAMMA_THRESHOLD) + vi->gamma_correction = 0; + + vi->file_inverse = 1/dp->file_gamma; + if (fabs(vi->file_inverse-1) < PNG_GAMMA_THRESHOLD) + vi->file_inverse = 0; + + vi->scale16 = dp->scale16; +} + +/* This function handles composition of a single non-alpha component. The + * argument is the input sample value, in the range 0..1, and the alpha value. + * The result is the composed, linear, input sample. If alpha is less than zero + * this is the alpha component and the function should not be called! + */ +static double +gamma_component_compose(int do_background, double input_sample, double alpha, + double background, int *compose) +{ + switch (do_background) + { +#ifdef PNG_READ_BACKGROUND_SUPPORTED + case PNG_BACKGROUND_GAMMA_SCREEN: + case PNG_BACKGROUND_GAMMA_FILE: + case PNG_BACKGROUND_GAMMA_UNIQUE: + /* Standard PNG background processing. */ + if (alpha < 1) + { + if (alpha > 0) + { + input_sample = input_sample * alpha + background * (1-alpha); + if (compose != NULL) + *compose = 1; + } + + else + input_sample = background; + } + break; +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: + case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: + /* The components are premultiplied in either case and the output is + * gamma encoded (to get standard Porter-Duff we expect the output + * gamma to be set to 1.0!) + */ + case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: + /* The optimization is that the partial-alpha entries are linear + * while the opaque pixels are gamma encoded, but this only affects the + * output encoding. + */ + if (alpha < 1) + { + if (alpha > 0) + { + input_sample *= alpha; + if (compose != NULL) + *compose = 1; + } + + else + input_sample = 0; + } + break; +#endif + + default: + /* Standard cases where no compositing is done (so the component + * value is already correct.) + */ + UNUSED(alpha) + UNUSED(background) + UNUSED(compose) + break; + } + + return input_sample; +} + +/* This API returns the encoded *input* component, in the range 0..1 */ +static double +gamma_component_validate(const char *name, const validate_info *vi, + unsigned int id, unsigned int od, + const double alpha /* <0 for the alpha channel itself */, + const double background /* component background value */) +{ + unsigned int isbit = id >> vi->isbit_shift; + unsigned int sbit_max = vi->sbit_max; + unsigned int outmax = vi->outmax; + int do_background = vi->do_background; + + double i; + + /* First check on the 'perfect' result obtained from the digitized input + * value, id, and compare this against the actual digitized result, 'od'. + * 'i' is the input result in the range 0..1: + */ + i = isbit; i /= sbit_max; + + /* Check for the fast route: if we don't do any background composition or if + * this is the alpha channel ('alpha' < 0) or if the pixel is opaque then + * just use the gamma_correction field to correct to the final output gamma. + */ + if (alpha == 1 /* opaque pixel component */ || !do_background +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + || do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_PNG +#endif + || (alpha < 0 /* alpha channel */ +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + && do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN +#endif + )) + { + /* Then get the gamma corrected version of 'i' and compare to 'od', any + * error less than .5 is insignificant - just quantization of the output + * value to the nearest digital value (nevertheless the error is still + * recorded - it's interesting ;-) + */ + double encoded_sample = i; + double encoded_error; + + /* alpha less than 0 indicates the alpha channel, which is always linear + */ + if (alpha >= 0 && vi->gamma_correction > 0) + encoded_sample = pow(encoded_sample, vi->gamma_correction); + encoded_sample *= outmax; + + encoded_error = fabs(od-encoded_sample); + + if (encoded_error > vi->dp->maxerrout) + vi->dp->maxerrout = encoded_error; + + if (encoded_error < vi->maxout_total && encoded_error < vi->outlog) + return i; + } + + /* The slow route - attempt to do linear calculations. */ + /* There may be an error, or background processing is required, so calculate + * the actual sample values - unencoded light intensity values. Note that in + * practice these are not completely unencoded because they include a + * 'viewing correction' to decrease or (normally) increase the perceptual + * contrast of the image. There's nothing we can do about this - we don't + * know what it is - so assume the unencoded value is perceptually linear. + */ + { + double input_sample = i; /* In range 0..1 */ + double output, error, encoded_sample, encoded_error; + double es_lo, es_hi; + int compose = 0; /* Set to one if composition done */ + int output_is_encoded; /* Set if encoded to screen gamma */ + int log_max_error = 1; /* Check maximum error values */ + png_const_charp pass = 0; /* Reason test passes (or 0 for fail) */ + + /* Convert to linear light (with the above caveat.) The alpha channel is + * already linear. + */ + if (alpha >= 0) + { + int tcompose; + + if (vi->file_inverse > 0) + input_sample = pow(input_sample, vi->file_inverse); + + /* Handle the compose processing: */ + tcompose = 0; + input_sample = gamma_component_compose(do_background, input_sample, + alpha, background, &tcompose); + + if (tcompose) + compose = 1; + } + + /* And similarly for the output value, but we need to check the background + * handling to linearize it correctly. + */ + output = od; + output /= outmax; + + output_is_encoded = vi->screen_gamma > 0; + + if (alpha < 0) /* The alpha channel */ + { +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if (do_background != ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN) +#endif + { + /* In all other cases the output alpha channel is linear already, + * don't log errors here, they are much larger in linear data. + */ + output_is_encoded = 0; + log_max_error = 0; + } + } + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + else /* A component */ + { + if (do_background == ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED && + alpha < 1) /* the optimized case - linear output */ + { + if (alpha > 0) log_max_error = 0; + output_is_encoded = 0; + } + } +#endif + + if (output_is_encoded) + output = pow(output, vi->screen_gamma); + + /* Calculate (or recalculate) the encoded_sample value and repeat the + * check above (unnecessary if we took the fast route, but harmless.) + */ + encoded_sample = input_sample; + if (output_is_encoded) + encoded_sample = pow(encoded_sample, vi->screen_inverse); + encoded_sample *= outmax; + + encoded_error = fabs(od-encoded_sample); + + /* Don't log errors in the alpha channel, or the 'optimized' case, + * neither are significant to the overall perception. + */ + if (log_max_error && encoded_error > vi->dp->maxerrout) + vi->dp->maxerrout = encoded_error; + + if (encoded_error < vi->maxout_total) + { + if (encoded_error < vi->outlog) + return i; + + /* Test passed but error is bigger than the log limit, record why the + * test passed: + */ + pass = "less than maxout:\n"; + } + + /* i: the original input value in the range 0..1 + * + * pngvalid calculations: + * input_sample: linear result; i linearized and composed, range 0..1 + * encoded_sample: encoded result; input_sample scaled to output bit depth + * + * libpng calculations: + * output: linear result; od scaled to 0..1 and linearized + * od: encoded result from libpng + */ + + /* Now we have the numbers for real errors, both absolute values as as a + * percentage of the correct value (output): + */ + error = fabs(input_sample-output); + + if (log_max_error && error > vi->dp->maxerrabs) + vi->dp->maxerrabs = error; + + /* The following is an attempt to ignore the tendency of quantization to + * dominate the percentage errors for lower result values: + */ + if (log_max_error && input_sample > .5) + { + double percentage_error = error/input_sample; + if (percentage_error > vi->dp->maxerrpc) + vi->dp->maxerrpc = percentage_error; + } + + /* Now calculate the digitization limits for 'encoded_sample' using the + * 'max' values. Note that maxout is in the encoded space but maxpc and + * maxabs are in linear light space. + * + * First find the maximum error in linear light space, range 0..1: + */ + { + double tmp = input_sample * vi->maxpc; + if (tmp < vi->maxabs) tmp = vi->maxabs; + /* If 'compose' is true the composition was done in linear space using + * integer arithmetic. This introduces an extra error of +/- 0.5 (at + * least) in the integer space used. 'maxcalc' records this, taking + * into account the possibility that even for 16 bit output 8 bit space + * may have been used. + */ + if (compose && tmp < vi->maxcalc) tmp = vi->maxcalc; + + /* The 'maxout' value refers to the encoded result, to compare with + * this encode input_sample adjusted by the maximum error (tmp) above. + */ + es_lo = encoded_sample - vi->maxout; + + if (es_lo > 0 && input_sample-tmp > 0) + { + double low_value = input_sample-tmp; + if (output_is_encoded) + low_value = pow(low_value, vi->screen_inverse); + low_value *= outmax; + if (low_value < es_lo) es_lo = low_value; + + /* Quantize this appropriately: */ + es_lo = ceil(es_lo / vi->outquant - .5) * vi->outquant; + } + + else + es_lo = 0; + + es_hi = encoded_sample + vi->maxout; + + if (es_hi < outmax && input_sample+tmp < 1) + { + double high_value = input_sample+tmp; + if (output_is_encoded) + high_value = pow(high_value, vi->screen_inverse); + high_value *= outmax; + if (high_value > es_hi) es_hi = high_value; + + es_hi = floor(es_hi / vi->outquant + .5) * vi->outquant; + } + + else + es_hi = outmax; + } + + /* The primary test is that the final encoded value returned by the + * library should be between the two limits (inclusive) that were + * calculated above. + */ + if (od >= es_lo && od <= es_hi) + { + /* The value passes, but we may need to log the information anyway. */ + if (encoded_error < vi->outlog) + return i; + + if (pass == 0) + pass = "within digitization limits:\n"; + } + + { + /* There has been an error in processing, or we need to log this + * value. + */ + double is_lo, is_hi; + + /* pass is set at this point if either of the tests above would have + * passed. Don't do these additional tests here - just log the + * original [es_lo..es_hi] values. + */ + if (pass == 0 && vi->use_input_precision && vi->dp->sbit) + { + /* Ok, something is wrong - this actually happens in current libpng + * 16-to-8 processing. Assume that the input value (id, adjusted + * for sbit) can be anywhere between value-.5 and value+.5 - quite a + * large range if sbit is low. + * + * NOTE: at present because the libpng gamma table stuff has been + * changed to use a rounding algorithm to correct errors in 8-bit + * calculations the precise sbit calculation (a shift) has been + * lost. This can result in up to a +/-1 error in the presence of + * an sbit less than the bit depth. + */ +# if PNG_LIBPNG_VER < 10700 +# define SBIT_ERROR .5 +# else +# define SBIT_ERROR 1. +# endif + double tmp = (isbit - SBIT_ERROR)/sbit_max; + + if (tmp <= 0) + tmp = 0; + + else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) + tmp = pow(tmp, vi->file_inverse); + + tmp = gamma_component_compose(do_background, tmp, alpha, background, + NULL); + + if (output_is_encoded && tmp > 0 && tmp < 1) + tmp = pow(tmp, vi->screen_inverse); + + is_lo = ceil(outmax * tmp - vi->maxout_total); + + if (is_lo < 0) + is_lo = 0; + + tmp = (isbit + SBIT_ERROR)/sbit_max; + + if (tmp >= 1) + tmp = 1; + + else if (alpha >= 0 && vi->file_inverse > 0 && tmp < 1) + tmp = pow(tmp, vi->file_inverse); + + tmp = gamma_component_compose(do_background, tmp, alpha, background, + NULL); + + if (output_is_encoded && tmp > 0 && tmp < 1) + tmp = pow(tmp, vi->screen_inverse); + + is_hi = floor(outmax * tmp + vi->maxout_total); + + if (is_hi > outmax) + is_hi = outmax; + + if (!(od < is_lo || od > is_hi)) + { + if (encoded_error < vi->outlog) + return i; + + pass = "within input precision limits:\n"; + } + + /* One last chance. If this is an alpha channel and the 16to8 + * option has been used and 'inaccurate' scaling is used then the + * bit reduction is obtained by simply using the top 8 bits of the + * value. + * + * This is only done for older libpng versions when the 'inaccurate' + * (chop) method of scaling was used. + */ +# ifndef PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED +# if PNG_LIBPNG_VER < 10504 + /* This may be required for other components in the future, + * but at present the presence of gamma correction effectively + * prevents the errors in the component scaling (I don't quite + * understand why, but since it's better this way I care not + * to ask, JB 20110419.) + */ + if (pass == 0 && alpha < 0 && vi->scale16 && vi->sbit > 8 && + vi->sbit + vi->isbit_shift == 16) + { + tmp = ((id >> 8) - .5)/255; + + if (tmp > 0) + { + is_lo = ceil(outmax * tmp - vi->maxout_total); + if (is_lo < 0) is_lo = 0; + } + + else + is_lo = 0; + + tmp = ((id >> 8) + .5)/255; + + if (tmp < 1) + { + is_hi = floor(outmax * tmp + vi->maxout_total); + if (is_hi > outmax) is_hi = outmax; + } + + else + is_hi = outmax; + + if (!(od < is_lo || od > is_hi)) + { + if (encoded_error < vi->outlog) + return i; + + pass = "within 8 bit limits:\n"; + } + } +# endif +# endif + } + else /* !use_input_precision */ + is_lo = es_lo, is_hi = es_hi; + + /* Attempt to output a meaningful error/warning message: the message + * output depends on the background/composite operation being performed + * because this changes what parameters were actually used above. + */ + { + size_t pos = 0; + /* Need either 1/255 or 1/65535 precision here; 3 or 6 decimal + * places. Just use outmax to work out which. + */ + int precision = (outmax >= 1000 ? 6 : 3); + int use_input=1, use_background=0, do_compose=0; + char msg[256]; + + if (pass != 0) + pos = safecat(msg, sizeof msg, pos, "\n\t"); + + /* Set up the various flags, the output_is_encoded flag above + * is also used below. do_compose is just a double check. + */ + switch (do_background) + { +# ifdef PNG_READ_BACKGROUND_SUPPORTED + case PNG_BACKGROUND_GAMMA_SCREEN: + case PNG_BACKGROUND_GAMMA_FILE: + case PNG_BACKGROUND_GAMMA_UNIQUE: + use_background = (alpha >= 0 && alpha < 1); +# endif +# ifdef PNG_READ_ALPHA_MODE_SUPPORTED + /* FALLTHROUGH */ + case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: + case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: + case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: +# endif /* ALPHA_MODE_SUPPORTED */ + do_compose = (alpha > 0 && alpha < 1); + use_input = (alpha != 0); + break; + + default: + break; + } + + /* Check the 'compose' flag */ + if (compose != do_compose) + png_error(vi->pp, "internal error (compose)"); + + /* 'name' is the component name */ + pos = safecat(msg, sizeof msg, pos, name); + pos = safecat(msg, sizeof msg, pos, "("); + pos = safecatn(msg, sizeof msg, pos, id); + if (use_input || pass != 0/*logging*/) + { + if (isbit != id) + { + /* sBIT has reduced the precision of the input: */ + pos = safecat(msg, sizeof msg, pos, ", sbit("); + pos = safecatn(msg, sizeof msg, pos, vi->sbit); + pos = safecat(msg, sizeof msg, pos, "): "); + pos = safecatn(msg, sizeof msg, pos, isbit); + } + pos = safecat(msg, sizeof msg, pos, "/"); + /* The output is either "id/max" or "id sbit(sbit): isbit/max" */ + pos = safecatn(msg, sizeof msg, pos, vi->sbit_max); + } + pos = safecat(msg, sizeof msg, pos, ")"); + + /* A component may have been multiplied (in linear space) by the + * alpha value, 'compose' says whether this is relevant. + */ + if (compose || pass != 0) + { + /* If any form of composition is being done report our + * calculated linear value here (the code above doesn't record + * the input value before composition is performed, so what + * gets reported is the value after composition.) + */ + if (use_input || pass != 0) + { + if (vi->file_inverse > 0) + { + pos = safecat(msg, sizeof msg, pos, "^"); + pos = safecatd(msg, sizeof msg, pos, vi->file_inverse, 2); + } + + else + pos = safecat(msg, sizeof msg, pos, "[linear]"); + + pos = safecat(msg, sizeof msg, pos, "*(alpha)"); + pos = safecatd(msg, sizeof msg, pos, alpha, precision); + } + + /* Now record the *linear* background value if it was used + * (this function is not passed the original, non-linear, + * value but it is contained in the test name.) + */ + if (use_background) + { + pos = safecat(msg, sizeof msg, pos, use_input ? "+" : " "); + pos = safecat(msg, sizeof msg, pos, "(background)"); + pos = safecatd(msg, sizeof msg, pos, background, precision); + pos = safecat(msg, sizeof msg, pos, "*"); + pos = safecatd(msg, sizeof msg, pos, 1-alpha, precision); + } + } + + /* Report the calculated value (input_sample) and the linearized + * libpng value (output) unless this is just a component gamma + * correction. + */ + if (compose || alpha < 0 || pass != 0) + { + pos = safecat(msg, sizeof msg, pos, + pass != 0 ? " =\n\t" : " = "); + pos = safecatd(msg, sizeof msg, pos, input_sample, precision); + pos = safecat(msg, sizeof msg, pos, " (libpng: "); + pos = safecatd(msg, sizeof msg, pos, output, precision); + pos = safecat(msg, sizeof msg, pos, ")"); + + /* Finally report the output gamma encoding, if any. */ + if (output_is_encoded) + { + pos = safecat(msg, sizeof msg, pos, " ^"); + pos = safecatd(msg, sizeof msg, pos, vi->screen_inverse, 2); + pos = safecat(msg, sizeof msg, pos, "(to screen) ="); + } + + else + pos = safecat(msg, sizeof msg, pos, " [screen is linear] ="); + } + + if ((!compose && alpha >= 0) || pass != 0) + { + if (pass != 0) /* logging */ + pos = safecat(msg, sizeof msg, pos, "\n\t[overall:"); + + /* This is the non-composition case, the internal linear + * values are irrelevant (though the log below will reveal + * them.) Output a much shorter warning/error message and report + * the overall gamma correction. + */ + if (vi->gamma_correction > 0) + { + pos = safecat(msg, sizeof msg, pos, " ^"); + pos = safecatd(msg, sizeof msg, pos, vi->gamma_correction, 2); + pos = safecat(msg, sizeof msg, pos, "(gamma correction) ="); + } + + else + pos = safecat(msg, sizeof msg, pos, + " [no gamma correction] ="); + + if (pass != 0) + pos = safecat(msg, sizeof msg, pos, "]"); + } + + /* This is our calculated encoded_sample which should (but does + * not) match od: + */ + pos = safecat(msg, sizeof msg, pos, pass != 0 ? "\n\t" : " "); + pos = safecatd(msg, sizeof msg, pos, is_lo, 1); + pos = safecat(msg, sizeof msg, pos, " < "); + pos = safecatd(msg, sizeof msg, pos, encoded_sample, 1); + pos = safecat(msg, sizeof msg, pos, " (libpng: "); + pos = safecatn(msg, sizeof msg, pos, od); + pos = safecat(msg, sizeof msg, pos, ")"); + pos = safecat(msg, sizeof msg, pos, "/"); + pos = safecatn(msg, sizeof msg, pos, outmax); + pos = safecat(msg, sizeof msg, pos, " < "); + pos = safecatd(msg, sizeof msg, pos, is_hi, 1); + + if (pass == 0) /* The error condition */ + { +# ifdef PNG_WARNINGS_SUPPORTED + png_warning(vi->pp, msg); +# else + store_warning(vi->pp, msg); +# endif + } + + else /* logging this value */ + store_verbose(&vi->dp->pm->this, vi->pp, pass, msg); + } + } + } + + return i; +} + +static void +gamma_image_validate(gamma_display *dp, png_const_structp pp, + png_infop pi) +{ + /* Get some constants derived from the input and output file formats: */ + const png_store* const ps = dp->this.ps; + png_byte in_ct = dp->this.colour_type; + png_byte in_bd = dp->this.bit_depth; + png_uint_32 w = dp->this.w; + png_uint_32 h = dp->this.h; + const size_t cbRow = dp->this.cbRow; + png_byte out_ct = png_get_color_type(pp, pi); + png_byte out_bd = png_get_bit_depth(pp, pi); + + /* There are three sources of error, firstly the quantization in the + * file encoding, determined by sbit and/or the file depth, secondly + * the output (screen) gamma and thirdly the output file encoding. + * + * Since this API receives the screen and file gamma in double + * precision it is possible to calculate an exact answer given an input + * pixel value. Therefore we assume that the *input* value is exact - + * sample/maxsample - calculate the corresponding gamma corrected + * output to the limits of double precision arithmetic and compare with + * what libpng returns. + * + * Since the library must quantize the output to 8 or 16 bits there is + * a fundamental limit on the accuracy of the output of +/-.5 - this + * quantization limit is included in addition to the other limits + * specified by the parameters to the API. (Effectively, add .5 + * everywhere.) + * + * The behavior of the 'sbit' parameter is defined by section 12.5 + * (sample depth scaling) of the PNG spec. That section forces the + * decoder to assume that the PNG values have been scaled if sBIT is + * present: + * + * png-sample = floor( input-sample * (max-out/max-in) + .5); + * + * This means that only a subset of the possible PNG values should + * appear in the input. However, the spec allows the encoder to use a + * variety of approximations to the above and doesn't require any + * restriction of the values produced. + * + * Nevertheless the spec requires that the upper 'sBIT' bits of the + * value stored in a PNG file be the original sample bits. + * Consequently the code below simply scales the top sbit bits by + * (1<this.palette; + int in_is_transparent = dp->this.is_transparent; + int process_tRNS; + int out_npalette = -1; + int out_is_transparent = 0; /* Just refers to the palette case */ + store_palette out_palette; + validate_info vi; + + /* Check for row overwrite errors */ + store_image_check(dp->this.ps, pp, 0); + + /* Supply the input and output sample depths here - 8 for an indexed image, + * otherwise the bit depth. + */ + init_validate_info(&vi, dp, pp, in_ct==3?8:in_bd, out_ct==3?8:out_bd); + + processing = (vi.gamma_correction > 0 && !dp->threshold_test) + || in_bd != out_bd || in_ct != out_ct || vi.do_background; + process_tRNS = dp->this.has_tRNS && vi.do_background; + + /* TODO: FIX THIS: MAJOR BUG! If the transformations all happen inside + * the palette there is no way of finding out, because libpng fails to + * update the palette on png_read_update_info. Indeed, libpng doesn't + * even do the required work until much later, when it doesn't have any + * info pointer. Oops. For the moment 'processing' is turned off if + * out_ct is palette. + */ + if (in_ct == 3 && out_ct == 3) + processing = 0; + + if (processing && out_ct == 3) + out_is_transparent = read_palette(out_palette, &out_npalette, pp, pi); + + for (y=0; ythis.palette[in_index].alpha : + sample(std, in_ct, in_bd, x, samples_per_pixel, 0, 0); + + unsigned int output_alpha = 65536 /* as a flag value */; + + if (out_ct == 3) + { + if (out_is_transparent) + output_alpha = out_palette[out_index].alpha; + } + + else if ((out_ct & PNG_COLOR_MASK_ALPHA) != 0) + output_alpha = sample(pRow, out_ct, out_bd, x, + samples_per_pixel, 0, 0); + + if (output_alpha != 65536) + alpha = gamma_component_validate("alpha", &vi, input_alpha, + output_alpha, -1/*alpha*/, 0/*background*/); + + else /* no alpha in output */ + { + /* This is a copy of the calculation of 'i' above in order to + * have the alpha value to use in the background calculation. + */ + alpha = input_alpha >> vi.isbit_shift; + alpha /= vi.sbit_max; + } + } + + else if (process_tRNS) + { + /* alpha needs to be set appropriately for this pixel, it is + * currently 1 and needs to be 0 for an input pixel which matches + * the values in tRNS. + */ + switch (in_ct) + { + case 0: /* gray */ + if (sample(std, in_ct, in_bd, x, 0, 0, 0) == + dp->this.transparent.red) + alpha = 0; + break; + + case 2: /* RGB */ + if (sample(std, in_ct, in_bd, x, 0, 0, 0) == + dp->this.transparent.red && + sample(std, in_ct, in_bd, x, 1, 0, 0) == + dp->this.transparent.green && + sample(std, in_ct, in_bd, x, 2, 0, 0) == + dp->this.transparent.blue) + alpha = 0; + break; + + default: + break; + } + } + + /* Handle grayscale or RGB components. */ + if ((in_ct & PNG_COLOR_MASK_COLOR) == 0) /* grayscale */ + (void)gamma_component_validate("gray", &vi, + sample(std, in_ct, in_bd, x, 0, 0, 0), + sample(pRow, out_ct, out_bd, x, 0, 0, 0), + alpha/*component*/, vi.background_red); + else /* RGB or palette */ + { + (void)gamma_component_validate("red", &vi, + in_ct == 3 ? in_palette[in_index].red : + sample(std, in_ct, in_bd, x, 0, 0, 0), + out_ct == 3 ? out_palette[out_index].red : + sample(pRow, out_ct, out_bd, x, 0, 0, 0), + alpha/*component*/, vi.background_red); + + (void)gamma_component_validate("green", &vi, + in_ct == 3 ? in_palette[in_index].green : + sample(std, in_ct, in_bd, x, 1, 0, 0), + out_ct == 3 ? out_palette[out_index].green : + sample(pRow, out_ct, out_bd, x, 1, 0, 0), + alpha/*component*/, vi.background_green); + + (void)gamma_component_validate("blue", &vi, + in_ct == 3 ? in_palette[in_index].blue : + sample(std, in_ct, in_bd, x, 2, 0, 0), + out_ct == 3 ? out_palette[out_index].blue : + sample(pRow, out_ct, out_bd, x, 2, 0, 0), + alpha/*component*/, vi.background_blue); + } + } + } + + else if (memcmp(std, pRow, cbRow) != 0) + { + char msg[64]; + + /* No transform is expected on the threshold tests. */ + sprintf(msg, "gamma: below threshold row %lu changed", + (unsigned long)y); + + png_error(pp, msg); + } + } /* row (y) loop */ + + dp->this.ps->validated = 1; +} + +static void PNGCBAPI +gamma_end(png_structp ppIn, png_infop pi) +{ + png_const_structp pp = ppIn; + gamma_display *dp = voidcast(gamma_display*, png_get_progressive_ptr(pp)); + + if (!dp->this.speed) + gamma_image_validate(dp, pp, pi); + else + dp->this.ps->validated = 1; +} + +/* A single test run checking a gamma transformation. + * + * maxabs: maximum absolute error as a fraction + * maxout: maximum output error in the output units + * maxpc: maximum percentage error (as a percentage) + */ +static void +gamma_test(png_modifier *pmIn, png_byte colour_typeIn, + png_byte bit_depthIn, int palette_numberIn, + int interlace_typeIn, + const double file_gammaIn, const double screen_gammaIn, + png_byte sbitIn, int threshold_testIn, + const char *name, + int use_input_precisionIn, int scale16In, + int expand16In, int do_backgroundIn, + const png_color_16 *bkgd_colorIn, double bkgd_gammaIn) +{ + gamma_display d; + context(&pmIn->this, fault); + + gamma_display_init(&d, pmIn, FILEID(colour_typeIn, bit_depthIn, + palette_numberIn, interlace_typeIn, 0, 0, 0), + file_gammaIn, screen_gammaIn, sbitIn, + threshold_testIn, use_input_precisionIn, scale16In, + expand16In, do_backgroundIn, bkgd_colorIn, bkgd_gammaIn); + + Try + { + png_structp pp; + png_infop pi; + gama_modification gama_mod; + srgb_modification srgb_mod; + sbit_modification sbit_mod; + + /* For the moment don't use the png_modifier support here. */ + d.pm->encoding_counter = 0; + modifier_set_encoding(d.pm); /* Just resets everything */ + d.pm->current_gamma = d.file_gamma; + + /* Make an appropriate modifier to set the PNG file gamma to the + * given gamma value and the sBIT chunk to the given precision. + */ + d.pm->modifications = NULL; + gama_modification_init(&gama_mod, d.pm, d.file_gamma); + srgb_modification_init(&srgb_mod, d.pm, 127 /*delete*/); + if (d.sbit > 0) + sbit_modification_init(&sbit_mod, d.pm, d.sbit); + + modification_reset(d.pm->modifications); + + /* Get a png_struct for reading the image. */ + pp = set_modifier_for_read(d.pm, &pi, d.this.id, name); + standard_palette_init(&d.this); + + /* Introduce the correct read function. */ + if (d.pm->this.progressive) + { + /* Share the row function with the standard implementation. */ + png_set_progressive_read_fn(pp, &d, gamma_info, progressive_row, + gamma_end); + + /* Now feed data into the reader until we reach the end: */ + modifier_progressive_read(d.pm, pp, pi); + } + else + { + /* modifier_read expects a png_modifier* */ + png_set_read_fn(pp, d.pm, modifier_read); + + /* Check the header values: */ + png_read_info(pp, pi); + + /* Process the 'info' requirements. Only one image is generated */ + gamma_info_imp(&d, pp, pi); + + sequential_row(&d.this, pp, pi, -1, 0); + + if (!d.this.speed) + gamma_image_validate(&d, pp, pi); + else + d.this.ps->validated = 1; + } + + modifier_reset(d.pm); + + if (d.pm->log && !d.threshold_test && !d.this.speed) + fprintf(stderr, "%d bit %s %s: max error %f (%.2g, %2g%%)\n", + d.this.bit_depth, colour_types[d.this.colour_type], name, + d.maxerrout, d.maxerrabs, 100*d.maxerrpc); + + /* Log the summary values too. */ + if (d.this.colour_type == 0 || d.this.colour_type == 4) + { + switch (d.this.bit_depth) + { + case 1: + break; + + case 2: + if (d.maxerrout > d.pm->error_gray_2) + d.pm->error_gray_2 = d.maxerrout; + + break; + + case 4: + if (d.maxerrout > d.pm->error_gray_4) + d.pm->error_gray_4 = d.maxerrout; + + break; + + case 8: + if (d.maxerrout > d.pm->error_gray_8) + d.pm->error_gray_8 = d.maxerrout; + + break; + + case 16: + if (d.maxerrout > d.pm->error_gray_16) + d.pm->error_gray_16 = d.maxerrout; + + break; + + default: + png_error(pp, "bad bit depth (internal: 1)"); + } + } + + else if (d.this.colour_type == 2 || d.this.colour_type == 6) + { + switch (d.this.bit_depth) + { + case 8: + + if (d.maxerrout > d.pm->error_color_8) + d.pm->error_color_8 = d.maxerrout; + + break; + + case 16: + + if (d.maxerrout > d.pm->error_color_16) + d.pm->error_color_16 = d.maxerrout; + + break; + + default: + png_error(pp, "bad bit depth (internal: 2)"); + } + } + + else if (d.this.colour_type == 3) + { + if (d.maxerrout > d.pm->error_indexed) + d.pm->error_indexed = d.maxerrout; + } + } + + Catch(fault) + modifier_reset(voidcast(png_modifier*,(void*)fault)); +} + +static void gamma_threshold_test(png_modifier *pm, png_byte colour_type, + png_byte bit_depth, int interlace_type, double file_gamma, + double screen_gamma) +{ + size_t pos = 0; + char name[64]; + pos = safecat(name, sizeof name, pos, "threshold "); + pos = safecatd(name, sizeof name, pos, file_gamma, 3); + pos = safecat(name, sizeof name, pos, "/"); + pos = safecatd(name, sizeof name, pos, screen_gamma, 3); + + (void)gamma_test(pm, colour_type, bit_depth, 0/*palette*/, interlace_type, + file_gamma, screen_gamma, 0/*sBIT*/, 1/*threshold test*/, name, + 0 /*no input precision*/, + 0 /*no scale16*/, 0 /*no expand16*/, 0 /*no background*/, 0 /*hence*/, + 0 /*no background gamma*/); +} + +static void +perform_gamma_threshold_tests(png_modifier *pm) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + unsigned int palette_number = 0; + + /* Don't test more than one instance of each palette - it's pointless, in + * fact this test is somewhat excessive since libpng doesn't make this + * decision based on colour type or bit depth! + * + * CHANGED: now test two palettes and, as a side effect, images with and + * without tRNS. + */ + while (next_format(&colour_type, &bit_depth, &palette_number, + pm->test_lbg_gamma_threshold, pm->test_tRNS)) + if (palette_number < 2) + { + double test_gamma = 1.0; + while (test_gamma >= .4) + { + /* There's little point testing the interlacing vs non-interlacing, + * but this can be set from the command line. + */ + gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, + test_gamma, 1/test_gamma); + test_gamma *= .95; + } + + /* And a special test for sRGB */ + gamma_threshold_test(pm, colour_type, bit_depth, pm->interlace_type, + .45455, 2.2); + + if (fail(pm)) + return; + } +} + +static void gamma_transform_test(png_modifier *pm, + png_byte colour_type, png_byte bit_depth, + int palette_number, + int interlace_type, const double file_gamma, + const double screen_gamma, png_byte sbit, + int use_input_precision, int scale16) +{ + size_t pos = 0; + char name[64]; + + if (sbit != bit_depth && sbit != 0) + { + pos = safecat(name, sizeof name, pos, "sbit("); + pos = safecatn(name, sizeof name, pos, sbit); + pos = safecat(name, sizeof name, pos, ") "); + } + + else + pos = safecat(name, sizeof name, pos, "gamma "); + + if (scale16) + pos = safecat(name, sizeof name, pos, "16to8 "); + + pos = safecatd(name, sizeof name, pos, file_gamma, 3); + pos = safecat(name, sizeof name, pos, "->"); + pos = safecatd(name, sizeof name, pos, screen_gamma, 3); + + gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type, + file_gamma, screen_gamma, sbit, 0, name, use_input_precision, + scale16, pm->test_gamma_expand16, 0 , 0, 0); +} + +static void perform_gamma_transform_tests(png_modifier *pm) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + unsigned int palette_number = 0; + + while (next_format(&colour_type, &bit_depth, &palette_number, + pm->test_lbg_gamma_transform, pm->test_tRNS)) + { + unsigned int i, j; + + for (i=0; ingamma_tests; ++i) for (j=0; jngamma_tests; ++j) + if (i != j) + { + gamma_transform_test(pm, colour_type, bit_depth, palette_number, + pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], 0/*sBIT*/, + pm->use_input_precision, 0 /*do not scale16*/); + + if (fail(pm)) + return; + } + } +} + +static void perform_gamma_sbit_tests(png_modifier *pm) +{ + png_byte sbit; + + /* The only interesting cases are colour and grayscale, alpha is ignored here + * for overall speed. Only bit depths where sbit is less than the bit depth + * are tested. + */ + for (sbit=pm->sbitlow; sbit<(1<test_lbg_gamma_sbit, pm->test_tRNS)) + if ((colour_type & PNG_COLOR_MASK_ALPHA) == 0 && + ((colour_type == 3 && sbit < 8) || + (colour_type != 3 && sbit < bit_depth))) + { + unsigned int i; + + for (i=0; ingamma_tests; ++i) + { + unsigned int j; + + for (j=0; jngamma_tests; ++j) if (i != j) + { + gamma_transform_test(pm, colour_type, bit_depth, npalette, + pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], + sbit, pm->use_input_precision_sbit, 0 /*scale16*/); + + if (fail(pm)) + return; + } + } + } + } +} + +/* Note that this requires a 16 bit source image but produces 8 bit output, so + * we only need the 16bit write support, but the 16 bit images are only + * generated if DO_16BIT is defined. + */ +#ifdef DO_16BIT +static void perform_gamma_scale16_tests(png_modifier *pm) +{ +# ifndef PNG_MAX_GAMMA_8 +# define PNG_MAX_GAMMA_8 11 +# endif +# if defined PNG_MAX_GAMMA_8 || PNG_LIBPNG_VER < 10700 +# define SBIT_16_TO_8 PNG_MAX_GAMMA_8 +# else +# define SBIT_16_TO_8 16 +# endif + /* Include the alpha cases here. Note that sbit matches the internal value + * used by the library - otherwise we will get spurious errors from the + * internal sbit style approximation. + * + * The threshold test is here because otherwise the 16 to 8 conversion will + * proceed *without* gamma correction, and the tests above will fail (but not + * by much) - this could be fixed, it only appears with the -g option. + */ + unsigned int i, j; + for (i=0; ingamma_tests; ++i) + { + for (j=0; jngamma_tests; ++j) + { + if (i != j && + fabs(pm->gammas[j]/pm->gammas[i]-1) >= PNG_GAMMA_THRESHOLD) + { + gamma_transform_test(pm, 0, 16, 0, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 2, 16, 0, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 4, 16, 0, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + + gamma_transform_test(pm, 6, 16, 0, pm->interlace_type, + 1/pm->gammas[i], pm->gammas[j], SBIT_16_TO_8, + pm->use_input_precision_16to8, 1 /*scale16*/); + + if (fail(pm)) + return; + } + } + } +} +#endif /* 16 to 8 bit conversion */ + +#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) +static void gamma_composition_test(png_modifier *pm, + png_byte colour_type, png_byte bit_depth, + int palette_number, + int interlace_type, const double file_gamma, + const double screen_gamma, + int use_input_precision, int do_background, + int expand_16) +{ + size_t pos = 0; + png_const_charp base; + double bg; + char name[128]; + png_color_16 background; + + /* Make up a name and get an appropriate background gamma value. */ + switch (do_background) + { + default: + base = ""; + bg = 4; /* should not be used */ + break; + case PNG_BACKGROUND_GAMMA_SCREEN: + base = " bckg(Screen):"; + bg = 1/screen_gamma; + break; + case PNG_BACKGROUND_GAMMA_FILE: + base = " bckg(File):"; + bg = file_gamma; + break; + case PNG_BACKGROUND_GAMMA_UNIQUE: + base = " bckg(Unique):"; + /* This tests the handling of a unique value, the math is such that the + * value tends to be <1, but is neither screen nor file (even if they + * match!) + */ + bg = (file_gamma + screen_gamma) / 3; + break; +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + case ALPHA_MODE_OFFSET + PNG_ALPHA_PNG: + base = " alpha(PNG)"; + bg = 4; /* should not be used */ + break; + case ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD: + base = " alpha(Porter-Duff)"; + bg = 4; /* should not be used */ + break; + case ALPHA_MODE_OFFSET + PNG_ALPHA_OPTIMIZED: + base = " alpha(Optimized)"; + bg = 4; /* should not be used */ + break; + case ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN: + base = " alpha(Broken)"; + bg = 4; /* should not be used */ + break; +#endif + } + + /* Use random background values - the background is always presented in the + * output space (8 or 16 bit components). + */ + if (expand_16 || bit_depth == 16) + { + png_uint_32 r = random_32(); + + background.red = (png_uint_16)r; + background.green = (png_uint_16)(r >> 16); + r = random_32(); + background.blue = (png_uint_16)r; + background.gray = (png_uint_16)(r >> 16); + + /* In earlier libpng versions, those where DIGITIZE is set, any background + * gamma correction in the expand16 case was done using 8-bit gamma + * correction tables, resulting in larger errors. To cope with those + * cases use a 16-bit background value which will handle this gamma + * correction. + */ +# if DIGITIZE + if (expand_16 && (do_background == PNG_BACKGROUND_GAMMA_UNIQUE || + do_background == PNG_BACKGROUND_GAMMA_FILE) && + fabs(bg*screen_gamma-1) > PNG_GAMMA_THRESHOLD) + { + /* The background values will be looked up in an 8-bit table to do + * the gamma correction, so only select values which are an exact + * match for the 8-bit table entries: + */ + background.red = (png_uint_16)((background.red >> 8) * 257); + background.green = (png_uint_16)((background.green >> 8) * 257); + background.blue = (png_uint_16)((background.blue >> 8) * 257); + background.gray = (png_uint_16)((background.gray >> 8) * 257); + } +# endif + } + + else /* 8 bit colors */ + { + png_uint_32 r = random_32(); + + background.red = (png_byte)r; + background.green = (png_byte)(r >> 8); + background.blue = (png_byte)(r >> 16); + background.gray = (png_byte)(r >> 24); + } + + background.index = 193; /* rgb(193,193,193) to detect errors */ + + if (!(colour_type & PNG_COLOR_MASK_COLOR)) + { + /* Because, currently, png_set_background is always called with + * 'need_expand' false in this case and because the gamma test itself + * doesn't cause an expand to 8-bit for lower bit depths the colour must + * be reduced to the correct range. + */ + if (bit_depth < 8) + background.gray &= (png_uint_16)((1U << bit_depth)-1); + + /* Grayscale input, we do not convert to RGB (TBD), so we must set the + * background to gray - else libpng seems to fail. + */ + background.red = background.green = background.blue = background.gray; + } + + pos = safecat(name, sizeof name, pos, "gamma "); + pos = safecatd(name, sizeof name, pos, file_gamma, 3); + pos = safecat(name, sizeof name, pos, "->"); + pos = safecatd(name, sizeof name, pos, screen_gamma, 3); + + pos = safecat(name, sizeof name, pos, base); + if (do_background < ALPHA_MODE_OFFSET) + { + /* Include the background color and gamma in the name: */ + pos = safecat(name, sizeof name, pos, "("); + /* This assumes no expand gray->rgb - the current code won't handle that! + */ + if (colour_type & PNG_COLOR_MASK_COLOR) + { + pos = safecatn(name, sizeof name, pos, background.red); + pos = safecat(name, sizeof name, pos, ","); + pos = safecatn(name, sizeof name, pos, background.green); + pos = safecat(name, sizeof name, pos, ","); + pos = safecatn(name, sizeof name, pos, background.blue); + } + else + pos = safecatn(name, sizeof name, pos, background.gray); + pos = safecat(name, sizeof name, pos, ")^"); + pos = safecatd(name, sizeof name, pos, bg, 3); + } + + gamma_test(pm, colour_type, bit_depth, palette_number, interlace_type, + file_gamma, screen_gamma, 0/*sBIT*/, 0, name, use_input_precision, + 0/*strip 16*/, expand_16, do_background, &background, bg); +} + + +static void +perform_gamma_composition_tests(png_modifier *pm, int do_background, + int expand_16) +{ + png_byte colour_type = 0; + png_byte bit_depth = 0; + unsigned int palette_number = 0; + + /* Skip the non-alpha cases - there is no setting of a transparency colour at + * present. + * + * TODO: incorrect; the palette case sets tRNS and, now RGB and gray do, + * however the palette case fails miserably so is commented out below. + */ + while (next_format(&colour_type, &bit_depth, &palette_number, + pm->test_lbg_gamma_composition, pm->test_tRNS)) + if ((colour_type & PNG_COLOR_MASK_ALPHA) != 0 +#if 0 /* TODO: FIXME */ + /*TODO: FIXME: this should work */ + || colour_type == 3 +#endif + || (colour_type != 3 && palette_number != 0)) + { + unsigned int i, j; + + /* Don't skip the i==j case here - it's relevant. */ + for (i=0; ingamma_tests; ++i) for (j=0; jngamma_tests; ++j) + { + gamma_composition_test(pm, colour_type, bit_depth, palette_number, + pm->interlace_type, 1/pm->gammas[i], pm->gammas[j], + pm->use_input_precision, do_background, expand_16); + + if (fail(pm)) + return; + } + } +} +#endif /* READ_BACKGROUND || READ_ALPHA_MODE */ + +static void +init_gamma_errors(png_modifier *pm) +{ + /* Use -1 to catch tests that were not actually run */ + pm->error_gray_2 = pm->error_gray_4 = pm->error_gray_8 = -1.; + pm->error_color_8 = -1.; + pm->error_indexed = -1.; + pm->error_gray_16 = pm->error_color_16 = -1.; +} + +static void +print_one(const char *leader, double err) +{ + if (err != -1.) + printf(" %s %.5f\n", leader, err); +} + +static void +summarize_gamma_errors(png_modifier *pm, png_const_charp who, int low_bit_depth, + int indexed) +{ + fflush(stderr); + + if (who) + printf("\nGamma correction with %s:\n", who); + + else + printf("\nBasic gamma correction:\n"); + + if (low_bit_depth) + { + print_one(" 2 bit gray: ", pm->error_gray_2); + print_one(" 4 bit gray: ", pm->error_gray_4); + print_one(" 8 bit gray: ", pm->error_gray_8); + print_one(" 8 bit color:", pm->error_color_8); + if (indexed) + print_one(" indexed: ", pm->error_indexed); + } + + print_one("16 bit gray: ", pm->error_gray_16); + print_one("16 bit color:", pm->error_color_16); + + fflush(stdout); +} + +static void +perform_gamma_test(png_modifier *pm, int summary) +{ + /*TODO: remove this*/ + /* Save certain values for the temporary overrides below. */ + unsigned int calculations_use_input_precision = + pm->calculations_use_input_precision; +# ifdef PNG_READ_BACKGROUND_SUPPORTED + double maxout8 = pm->maxout8; +# endif + + /* First some arbitrary no-transform tests: */ + if (!pm->this.speed && pm->test_gamma_threshold) + { + perform_gamma_threshold_tests(pm); + + if (fail(pm)) + return; + } + + /* Now some real transforms. */ + if (pm->test_gamma_transform) + { + if (summary) + { + fflush(stderr); + printf("Gamma correction error summary\n\n"); + printf("The printed value is the maximum error in the pixel values\n"); + printf("calculated by the libpng gamma correction code. The error\n"); + printf("is calculated as the difference between the output pixel\n"); + printf("value (always an integer) and the ideal value from the\n"); + printf("libpng specification (typically not an integer).\n\n"); + + printf("Expect this value to be less than .5 for 8 bit formats,\n"); + printf("less than 1 for formats with fewer than 8 bits and a small\n"); + printf("number (typically less than 5) for the 16 bit formats.\n"); + printf("For performance reasons the value for 16 bit formats\n"); + printf("increases when the image file includes an sBIT chunk.\n"); + fflush(stdout); + } + + init_gamma_errors(pm); + /*TODO: remove this. Necessary because the current libpng + * implementation works in 8 bits: + */ + if (pm->test_gamma_expand16) + pm->calculations_use_input_precision = 1; + perform_gamma_transform_tests(pm); + if (!calculations_use_input_precision) + pm->calculations_use_input_precision = 0; + + if (summary) + summarize_gamma_errors(pm, 0/*who*/, 1/*low bit depth*/, 1/*indexed*/); + + if (fail(pm)) + return; + } + + /* The sbit tests produce much larger errors: */ + if (pm->test_gamma_sbit) + { + init_gamma_errors(pm); + perform_gamma_sbit_tests(pm); + + if (summary) + summarize_gamma_errors(pm, "sBIT", pm->sbitlow < 8U, 1/*indexed*/); + + if (fail(pm)) + return; + } + +#ifdef DO_16BIT /* Should be READ_16BIT_SUPPORTED */ + if (pm->test_gamma_scale16) + { + /* The 16 to 8 bit strip operations: */ + init_gamma_errors(pm); + perform_gamma_scale16_tests(pm); + + if (summary) + { + fflush(stderr); + printf("\nGamma correction with 16 to 8 bit reduction:\n"); + printf(" 16 bit gray: %.5f\n", pm->error_gray_16); + printf(" 16 bit color: %.5f\n", pm->error_color_16); + fflush(stdout); + } + + if (fail(pm)) + return; + } +#endif + +#ifdef PNG_READ_BACKGROUND_SUPPORTED + if (pm->test_gamma_background) + { + init_gamma_errors(pm); + + /*TODO: remove this. Necessary because the current libpng + * implementation works in 8 bits: + */ + if (pm->test_gamma_expand16) + { + pm->calculations_use_input_precision = 1; + pm->maxout8 = .499; /* because the 16 bit background is smashed */ + } + perform_gamma_composition_tests(pm, PNG_BACKGROUND_GAMMA_UNIQUE, + pm->test_gamma_expand16); + if (!calculations_use_input_precision) + pm->calculations_use_input_precision = 0; + pm->maxout8 = maxout8; + + if (summary) + summarize_gamma_errors(pm, "background", 1, 0/*indexed*/); + + if (fail(pm)) + return; + } +#endif + +#ifdef PNG_READ_ALPHA_MODE_SUPPORTED + if (pm->test_gamma_alpha_mode) + { + int do_background; + + init_gamma_errors(pm); + + /*TODO: remove this. Necessary because the current libpng + * implementation works in 8 bits: + */ + if (pm->test_gamma_expand16) + pm->calculations_use_input_precision = 1; + for (do_background = ALPHA_MODE_OFFSET + PNG_ALPHA_STANDARD; + do_background <= ALPHA_MODE_OFFSET + PNG_ALPHA_BROKEN && !fail(pm); + ++do_background) + perform_gamma_composition_tests(pm, do_background, + pm->test_gamma_expand16); + if (!calculations_use_input_precision) + pm->calculations_use_input_precision = 0; + + if (summary) + summarize_gamma_errors(pm, "alpha mode", 1, 0/*indexed*/); + + if (fail(pm)) + return; + } +#endif +} +#endif /* PNG_READ_GAMMA_SUPPORTED */ +#endif /* PNG_READ_SUPPORTED */ + +/* INTERLACE MACRO VALIDATION */ +/* This is copied verbatim from the specification, it is simply the pass + * number in which each pixel in each 8x8 tile appears. The array must + * be indexed adam7[y][x] and notice that the pass numbers are based at + * 1, not 0 - the base libpng uses. + */ +static const +png_byte adam7[8][8] = +{ + { 1,6,4,6,2,6,4,6 }, + { 7,7,7,7,7,7,7,7 }, + { 5,6,5,6,5,6,5,6 }, + { 7,7,7,7,7,7,7,7 }, + { 3,6,4,6,3,6,4,6 }, + { 7,7,7,7,7,7,7,7 }, + { 5,6,5,6,5,6,5,6 }, + { 7,7,7,7,7,7,7,7 } +}; + +/* This routine validates all the interlace support macros in png.h for + * a variety of valid PNG widths and heights. It uses a number of similarly + * named internal routines that feed off the above array. + */ +static png_uint_32 +png_pass_start_row(int pass) +{ + int x, y; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + return y; + return 0xf; +} + +static png_uint_32 +png_pass_start_col(int pass) +{ + int x, y; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + return x; + return 0xf; +} + +static int +png_pass_row_shift(int pass) +{ + int x, y, base=(-1), inc=8; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + { + if (base == (-1)) + base = y; + else if (base == y) + {} + else if (inc == y-base) + base=y; + else if (inc == 8) + inc = y-base, base=y; + else if (inc != y-base) + return 0xff; /* error - more than one 'inc' value! */ + } + + if (base == (-1)) return 0xfe; /* error - no row in pass! */ + + /* The shift is always 1, 2 or 3 - no pass has all the rows! */ + switch (inc) + { +case 2: return 1; +case 4: return 2; +case 8: return 3; +default: break; + } + + /* error - unrecognized 'inc' */ + return (inc << 8) + 0xfd; +} + +static int +png_pass_col_shift(int pass) +{ + int x, y, base=(-1), inc=8; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + { + if (base == (-1)) + base = x; + else if (base == x) + {} + else if (inc == x-base) + base=x; + else if (inc == 8) + inc = x-base, base=x; + else if (inc != x-base) + return 0xff; /* error - more than one 'inc' value! */ + } + + if (base == (-1)) return 0xfe; /* error - no row in pass! */ + + /* The shift is always 1, 2 or 3 - no pass has all the rows! */ + switch (inc) + { +case 1: return 0; /* pass 7 has all the columns */ +case 2: return 1; +case 4: return 2; +case 8: return 3; +default: break; + } + + /* error - unrecognized 'inc' */ + return (inc << 8) + 0xfd; +} + +static png_uint_32 +png_row_from_pass_row(png_uint_32 yIn, int pass) +{ + /* By examination of the array: */ + switch (pass) + { +case 0: return yIn * 8; +case 1: return yIn * 8; +case 2: return yIn * 8 + 4; +case 3: return yIn * 4; +case 4: return yIn * 4 + 2; +case 5: return yIn * 2; +case 6: return yIn * 2 + 1; +default: break; + } + + return 0xff; /* bad pass number */ +} + +static png_uint_32 +png_col_from_pass_col(png_uint_32 xIn, int pass) +{ + /* By examination of the array: */ + switch (pass) + { +case 0: return xIn * 8; +case 1: return xIn * 8 + 4; +case 2: return xIn * 4; +case 3: return xIn * 4 + 2; +case 4: return xIn * 2; +case 5: return xIn * 2 + 1; +case 6: return xIn; +default: break; + } + + return 0xff; /* bad pass number */ +} + +static int +png_row_in_interlace_pass(png_uint_32 y, int pass) +{ + /* Is row 'y' in pass 'pass'? */ + int x; + y &= 7; + ++pass; + for (x=0; x<8; ++x) if (adam7[y][x] == pass) + return 1; + + return 0; +} + +static int +png_col_in_interlace_pass(png_uint_32 x, int pass) +{ + /* Is column 'x' in pass 'pass'? */ + int y; + x &= 7; + ++pass; + for (y=0; y<8; ++y) if (adam7[y][x] == pass) + return 1; + + return 0; +} + +static png_uint_32 +png_pass_rows(png_uint_32 height, int pass) +{ + png_uint_32 tiles = height>>3; + png_uint_32 rows = 0; + unsigned int x, y; + + height &= 7; + ++pass; + for (y=0; y<8; ++y) for (x=0; x<8; ++x) if (adam7[y][x] == pass) + { + rows += tiles; + if (y < height) ++rows; + break; /* i.e. break the 'x', column, loop. */ + } + + return rows; +} + +static png_uint_32 +png_pass_cols(png_uint_32 width, int pass) +{ + png_uint_32 tiles = width>>3; + png_uint_32 cols = 0; + unsigned int x, y; + + width &= 7; + ++pass; + for (x=0; x<8; ++x) for (y=0; y<8; ++y) if (adam7[y][x] == pass) + { + cols += tiles; + if (x < width) ++cols; + break; /* i.e. break the 'y', row, loop. */ + } + + return cols; +} + +static void +perform_interlace_macro_validation(void) +{ + /* The macros to validate, first those that depend only on pass: + * + * PNG_PASS_START_ROW(pass) + * PNG_PASS_START_COL(pass) + * PNG_PASS_ROW_SHIFT(pass) + * PNG_PASS_COL_SHIFT(pass) + */ + int pass; + + for (pass=0; pass<7; ++pass) + { + png_uint_32 m, f, v; + + m = PNG_PASS_START_ROW(pass); + f = png_pass_start_row(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_START_ROW(%d) = %u != %x\n", pass, m, f); + exit(99); + } + + m = PNG_PASS_START_COL(pass); + f = png_pass_start_col(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_START_COL(%d) = %u != %x\n", pass, m, f); + exit(99); + } + + m = PNG_PASS_ROW_SHIFT(pass); + f = png_pass_row_shift(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_ROW_SHIFT(%d) = %u != %x\n", pass, m, f); + exit(99); + } + + m = PNG_PASS_COL_SHIFT(pass); + f = png_pass_col_shift(pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_COL_SHIFT(%d) = %u != %x\n", pass, m, f); + exit(99); + } + + /* Macros that depend on the image or sub-image height too: + * + * PNG_PASS_ROWS(height, pass) + * PNG_PASS_COLS(width, pass) + * PNG_ROW_FROM_PASS_ROW(yIn, pass) + * PNG_COL_FROM_PASS_COL(xIn, pass) + * PNG_ROW_IN_INTERLACE_PASS(y, pass) + * PNG_COL_IN_INTERLACE_PASS(x, pass) + */ + for (v=0;;) + { + /* The first two tests overflow if the pass row or column is outside + * the possible range for a 32-bit result. In fact the values should + * never be outside the range for a 31-bit result, but checking for 32 + * bits here ensures that if an app uses a bogus pass row or column + * (just so long as it fits in a 32 bit integer) it won't get a + * possibly dangerous overflow. + */ + /* First the base 0 stuff: */ + if (v < png_pass_rows(0xFFFFFFFFU, pass)) + { + m = PNG_ROW_FROM_PASS_ROW(v, pass); + f = png_row_from_pass_row(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_ROW_FROM_PASS_ROW(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(99); + } + } + + if (v < png_pass_cols(0xFFFFFFFFU, pass)) + { + m = PNG_COL_FROM_PASS_COL(v, pass); + f = png_col_from_pass_col(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_COL_FROM_PASS_COL(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(99); + } + } + + m = PNG_ROW_IN_INTERLACE_PASS(v, pass); + f = png_row_in_interlace_pass(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_ROW_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(99); + } + + m = PNG_COL_IN_INTERLACE_PASS(v, pass); + f = png_col_in_interlace_pass(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_COL_IN_INTERLACE_PASS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(99); + } + + /* Then the base 1 stuff: */ + ++v; + m = PNG_PASS_ROWS(v, pass); + f = png_pass_rows(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_ROWS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(99); + } + + m = PNG_PASS_COLS(v, pass); + f = png_pass_cols(v, pass); + if (m != f) + { + fprintf(stderr, "PNG_PASS_COLS(%u, %d) = %u != %x\n", + v, pass, m, f); + exit(99); + } + + /* Move to the next v - the stepping algorithm starts skipping + * values above 1024. + */ + if (v > 1024) + { + if (v == PNG_UINT_31_MAX) + break; + + v = (v << 1) ^ v; + if (v >= PNG_UINT_31_MAX) + v = PNG_UINT_31_MAX-1; + } + } + } +} + +/* Test color encodings. These values are back-calculated from the published + * chromaticities. The values are accurate to about 14 decimal places; 15 are + * given. These values are much more accurate than the ones given in the spec, + * which typically don't exceed 4 decimal places. This allows testing of the + * libpng code to its theoretical accuracy of 4 decimal places. (If pngvalid + * used the published errors the 'slack' permitted would have to be +/-.5E-4 or + * more.) + * + * The png_modifier code assumes that encodings[0] is sRGB and treats it + * specially: do not change the first entry in this list! + */ +static const color_encoding test_encodings[] = +{ +/* sRGB: must be first in this list! */ +/*gamma:*/ { 1/2.2, +/*red: */ { 0.412390799265959, 0.212639005871510, 0.019330818715592 }, +/*green:*/ { 0.357584339383878, 0.715168678767756, 0.119194779794626 }, +/*blue: */ { 0.180480788401834, 0.072192315360734, 0.950532152249660} }, +/* Kodak ProPhoto (wide gamut) */ +/*gamma:*/ { 1/1.6 /*approximate: uses 1.8 power law compared to sRGB 2.4*/, +/*red: */ { 0.797760489672303, 0.288071128229293, 0.000000000000000 }, +/*green:*/ { 0.135185837175740, 0.711843217810102, 0.000000000000000 }, +/*blue: */ { 0.031349349581525, 0.000085653960605, 0.825104602510460} }, +/* Adobe RGB (1998) */ +/*gamma:*/ { 1/(2+51./256), +/*red: */ { 0.576669042910131, 0.297344975250536, 0.027031361386412 }, +/*green:*/ { 0.185558237906546, 0.627363566255466, 0.070688852535827 }, +/*blue: */ { 0.188228646234995, 0.075291458493998, 0.991337536837639} }, +/* Adobe Wide Gamut RGB */ +/*gamma:*/ { 1/(2+51./256), +/*red: */ { 0.716500716779386, 0.258728243040113, 0.000000000000000 }, +/*green:*/ { 0.101020574397477, 0.724682314948566, 0.051211818965388 }, +/*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} }, +/* Fake encoding which selects just the green channel */ +/*gamma:*/ { 1.45/2.2, /* the 'Mac' gamma */ +/*red: */ { 0.716500716779386, 0.000000000000000, 0.000000000000000 }, +/*green:*/ { 0.101020574397477, 1.000000000000000, 0.051211818965388 }, +/*blue: */ { 0.146774385252705, 0.000000000000000, 0.773892783545073} }, +}; + +/* signal handler + * + * This attempts to trap signals and escape without crashing. It needs a + * context pointer so that it can throw an exception (call longjmp) to recover + * from the condition; this is handled by making the png_modifier used by 'main' + * into a global variable. + */ +static png_modifier pm; + +static void signal_handler(int signum) +{ + + size_t pos = 0; + char msg[64]; + + pos = safecat(msg, sizeof msg, pos, "caught signal: "); + + switch (signum) + { + case SIGABRT: + pos = safecat(msg, sizeof msg, pos, "abort"); + break; + + case SIGFPE: + pos = safecat(msg, sizeof msg, pos, "floating point exception"); + break; + + case SIGILL: + pos = safecat(msg, sizeof msg, pos, "illegal instruction"); + break; + + case SIGINT: + pos = safecat(msg, sizeof msg, pos, "interrupt"); + break; + + case SIGSEGV: + pos = safecat(msg, sizeof msg, pos, "invalid memory access"); + break; + + case SIGTERM: + pos = safecat(msg, sizeof msg, pos, "termination request"); + break; + + default: + pos = safecat(msg, sizeof msg, pos, "unknown "); + pos = safecatn(msg, sizeof msg, pos, signum); + break; + } + + store_log(&pm.this, NULL/*png_structp*/, msg, 1/*error*/); + + /* And finally throw an exception so we can keep going, unless this is + * SIGTERM in which case stop now. + */ + if (signum != SIGTERM) + { + struct exception_context *the_exception_context = + &pm.this.exception_context; + + Throw &pm.this; + } + + else + exit(1); +} + +/* main program */ +int main(int argc, char **argv) +{ + int summary = 1; /* Print the error summary at the end */ + int memstats = 0; /* Print memory statistics at the end */ + + /* Create the given output file on success: */ + const char *touch = NULL; + + /* This is an array of standard gamma values (believe it or not I've seen + * every one of these mentioned somewhere.) + * + * In the following list the most useful values are first! + */ + static double + gammas[]={2.2, 1.0, 2.2/1.45, 1.8, 1.5, 2.4, 2.5, 2.62, 2.9}; + + /* This records the command and arguments: */ + size_t cp = 0; + char command[1024]; + + anon_context(&pm.this); + + gnu_volatile(summary) + gnu_volatile(memstats) + gnu_volatile(touch) + + /* Add appropriate signal handlers, just the ANSI specified ones: */ + signal(SIGABRT, signal_handler); + signal(SIGFPE, signal_handler); + signal(SIGILL, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGSEGV, signal_handler); + signal(SIGTERM, signal_handler); + +#ifdef HAVE_FEENABLEEXCEPT + /* Only required to enable FP exceptions on platforms where they start off + * disabled; this is not necessary but if it is not done pngvalid will likely + * end up ignoring FP conditions that other platforms fault. + */ + feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); +#endif + + modifier_init(&pm); + + /* Preallocate the image buffer, because we know how big it needs to be, + * note that, for testing purposes, it is deliberately mis-aligned by tag + * bytes either side. All rows have an additional five bytes of padding for + * overwrite checking. + */ + store_ensure_image(&pm.this, NULL, 2, TRANSFORM_ROWMAX, TRANSFORM_HEIGHTMAX); + + /* Don't give argv[0], it's normally some horrible libtool string: */ + cp = safecat(command, sizeof command, cp, "pngvalid"); + + /* Default to error on warning: */ + pm.this.treat_warnings_as_errors = 1; + + /* Default assume_16_bit_calculations appropriately; this tells the checking + * code that 16-bit arithmetic is used for 8-bit samples when it would make a + * difference. + */ + pm.assume_16_bit_calculations = PNG_LIBPNG_VER >= 10700; + + /* Currently 16 bit expansion happens at the end of the pipeline, so the + * calculations are done in the input bit depth not the output. + * + * TODO: fix this + */ + pm.calculations_use_input_precision = 1U; + + /* Store the test gammas */ + pm.gammas = gammas; + pm.ngammas = ARRAY_SIZE(gammas); + pm.ngamma_tests = 0; /* default to off */ + + /* Low bit depth gray images don't do well in the gamma tests, until + * this is fixed turn them off for some gamma cases: + */ +# ifdef PNG_WRITE_tRNS_SUPPORTED + pm.test_tRNS = 1; +# endif + pm.test_lbg = PNG_LIBPNG_VER >= 10600; + pm.test_lbg_gamma_threshold = 1; + pm.test_lbg_gamma_transform = PNG_LIBPNG_VER >= 10600; + pm.test_lbg_gamma_sbit = 1; + pm.test_lbg_gamma_composition = PNG_LIBPNG_VER >= 10700; + + /* And the test encodings */ + pm.encodings = test_encodings; + pm.nencodings = ARRAY_SIZE(test_encodings); + +# if PNG_LIBPNG_VER < 10700 + pm.sbitlow = 8U; /* because libpng doesn't do sBIT below 8! */ +# else + pm.sbitlow = 1U; +# endif + + /* The following allows results to pass if they correspond to anything in the + * transformed range [input-.5,input+.5]; this is is required because of the + * way libpng treates the 16_TO_8 flag when building the gamma tables in + * releases up to 1.6.0. + * + * TODO: review this + */ + pm.use_input_precision_16to8 = 1U; + pm.use_input_precision_sbit = 1U; /* because libpng now rounds sBIT */ + + /* Some default values (set the behavior for 'make check' here). + * These values simply control the maximum error permitted in the gamma + * transformations. The practical limits for human perception are described + * below (the setting for maxpc16), however for 8 bit encodings it isn't + * possible to meet the accepted capabilities of human vision - i.e. 8 bit + * images can never be good enough, regardless of encoding. + */ + pm.maxout8 = .1; /* Arithmetic error in *encoded* value */ + pm.maxabs8 = .00005; /* 1/20000 */ + pm.maxcalc8 = 1./255; /* +/-1 in 8 bits for compose errors */ + pm.maxpc8 = .499; /* I.e., .499% fractional error */ + pm.maxout16 = .499; /* Error in *encoded* value */ + pm.maxabs16 = .00005;/* 1/20000 */ + pm.maxcalc16 =1./65535;/* +/-1 in 16 bits for compose errors */ +# if PNG_LIBPNG_VER < 10700 + pm.maxcalcG = 1./((1<38149 by the following: + */ + pm.maxpc16 = .005; /* I.e., 1/200% - 1/20000 */ + + /* Now parse the command line options. */ + while (--argc >= 1) + { + int catmore = 0; /* Set if the argument has an argument. */ + + /* Record each argument for posterity: */ + cp = safecat(command, sizeof command, cp, " "); + cp = safecat(command, sizeof command, cp, *++argv); + + if (strcmp(*argv, "-v") == 0) + pm.this.verbose = 1; + + else if (strcmp(*argv, "-l") == 0) + pm.log = 1; + + else if (strcmp(*argv, "-q") == 0) + summary = pm.this.verbose = pm.log = 0; + + else if (strcmp(*argv, "-w") == 0 || + strcmp(*argv, "--strict") == 0) + pm.this.treat_warnings_as_errors = 1; /* NOTE: this is the default! */ + + else if (strcmp(*argv, "--nostrict") == 0) + pm.this.treat_warnings_as_errors = 0; + + else if (strcmp(*argv, "--speed") == 0) + pm.this.speed = 1, pm.ngamma_tests = pm.ngammas, pm.test_standard = 0, + summary = 0; + + else if (strcmp(*argv, "--memory") == 0) + memstats = 1; + + else if (strcmp(*argv, "--size") == 0) + pm.test_size = 1; + + else if (strcmp(*argv, "--nosize") == 0) + pm.test_size = 0; + + else if (strcmp(*argv, "--standard") == 0) + pm.test_standard = 1; + + else if (strcmp(*argv, "--nostandard") == 0) + pm.test_standard = 0; + + else if (strcmp(*argv, "--transform") == 0) + pm.test_transform = 1; + + else if (strcmp(*argv, "--notransform") == 0) + pm.test_transform = 0; + +#ifdef PNG_READ_TRANSFORMS_SUPPORTED + else if (strncmp(*argv, "--transform-disable=", + sizeof "--transform-disable") == 0) + { + pm.test_transform = 1; + transform_disable(*argv + sizeof "--transform-disable"); + } + + else if (strncmp(*argv, "--transform-enable=", + sizeof "--transform-enable") == 0) + { + pm.test_transform = 1; + transform_enable(*argv + sizeof "--transform-enable"); + } +#endif /* PNG_READ_TRANSFORMS_SUPPORTED */ + + else if (strcmp(*argv, "--gamma") == 0) + { + /* Just do two gamma tests here (2.2 and linear) for speed: */ + pm.ngamma_tests = 2U; + pm.test_gamma_threshold = 1; + pm.test_gamma_transform = 1; + pm.test_gamma_sbit = 1; + pm.test_gamma_scale16 = 1; + pm.test_gamma_background = 1; /* composition */ + pm.test_gamma_alpha_mode = 1; + } + + else if (strcmp(*argv, "--nogamma") == 0) + pm.ngamma_tests = 0; + + else if (strcmp(*argv, "--gamma-threshold") == 0) + pm.ngamma_tests = 2U, pm.test_gamma_threshold = 1; + + else if (strcmp(*argv, "--nogamma-threshold") == 0) + pm.test_gamma_threshold = 0; + + else if (strcmp(*argv, "--gamma-transform") == 0) + pm.ngamma_tests = 2U, pm.test_gamma_transform = 1; + + else if (strcmp(*argv, "--nogamma-transform") == 0) + pm.test_gamma_transform = 0; + + else if (strcmp(*argv, "--gamma-sbit") == 0) + pm.ngamma_tests = 2U, pm.test_gamma_sbit = 1; + + else if (strcmp(*argv, "--nogamma-sbit") == 0) + pm.test_gamma_sbit = 0; + + else if (strcmp(*argv, "--gamma-16-to-8") == 0) + pm.ngamma_tests = 2U, pm.test_gamma_scale16 = 1; + + else if (strcmp(*argv, "--nogamma-16-to-8") == 0) + pm.test_gamma_scale16 = 0; + + else if (strcmp(*argv, "--gamma-background") == 0) + pm.ngamma_tests = 2U, pm.test_gamma_background = 1; + + else if (strcmp(*argv, "--nogamma-background") == 0) + pm.test_gamma_background = 0; + + else if (strcmp(*argv, "--gamma-alpha-mode") == 0) + pm.ngamma_tests = 2U, pm.test_gamma_alpha_mode = 1; + + else if (strcmp(*argv, "--nogamma-alpha-mode") == 0) + pm.test_gamma_alpha_mode = 0; + + else if (strcmp(*argv, "--expand16") == 0) + pm.test_gamma_expand16 = 1; + + else if (strcmp(*argv, "--noexpand16") == 0) + pm.test_gamma_expand16 = 0; + + else if (strcmp(*argv, "--low-depth-gray") == 0) + pm.test_lbg = pm.test_lbg_gamma_threshold = + pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit = + pm.test_lbg_gamma_composition = 1; + + else if (strcmp(*argv, "--nolow-depth-gray") == 0) + pm.test_lbg = pm.test_lbg_gamma_threshold = + pm.test_lbg_gamma_transform = pm.test_lbg_gamma_sbit = + pm.test_lbg_gamma_composition = 0; + +# ifdef PNG_WRITE_tRNS_SUPPORTED + else if (strcmp(*argv, "--tRNS") == 0) + pm.test_tRNS = 1; +# endif + + else if (strcmp(*argv, "--notRNS") == 0) + pm.test_tRNS = 0; + + else if (strcmp(*argv, "--more-gammas") == 0) + pm.ngamma_tests = 3U; + + else if (strcmp(*argv, "--all-gammas") == 0) + pm.ngamma_tests = pm.ngammas; + + else if (strcmp(*argv, "--progressive-read") == 0) + pm.this.progressive = 1; + + else if (strcmp(*argv, "--use-update-info") == 0) + ++pm.use_update_info; /* Can call multiple times */ + + else if (strcmp(*argv, "--interlace") == 0) + { +# if CAN_WRITE_INTERLACE + pm.interlace_type = PNG_INTERLACE_ADAM7; +# else /* !CAN_WRITE_INTERLACE */ + fprintf(stderr, "pngvalid: no write interlace support\n"); + return SKIP; +# endif /* !CAN_WRITE_INTERLACE */ + } + + else if (strcmp(*argv, "--use-input-precision") == 0) + pm.use_input_precision = 1U; + + else if (strcmp(*argv, "--use-calculation-precision") == 0) + pm.use_input_precision = 0; + + else if (strcmp(*argv, "--calculations-use-input-precision") == 0) + pm.calculations_use_input_precision = 1U; + + else if (strcmp(*argv, "--assume-16-bit-calculations") == 0) + pm.assume_16_bit_calculations = 1U; + + else if (strcmp(*argv, "--calculations-follow-bit-depth") == 0) + pm.calculations_use_input_precision = + pm.assume_16_bit_calculations = 0; + + else if (strcmp(*argv, "--exhaustive") == 0) + pm.test_exhaustive = 1; + + else if (argc > 1 && strcmp(*argv, "--sbitlow") == 0) + --argc, pm.sbitlow = (png_byte)atoi(*++argv), catmore = 1; + + else if (argc > 1 && strcmp(*argv, "--touch") == 0) + --argc, touch = *++argv, catmore = 1; + + else if (argc > 1 && strncmp(*argv, "--max", 5) == 0) + { + --argc; + + if (strcmp(5+*argv, "abs8") == 0) + pm.maxabs8 = atof(*++argv); + + else if (strcmp(5+*argv, "abs16") == 0) + pm.maxabs16 = atof(*++argv); + + else if (strcmp(5+*argv, "calc8") == 0) + pm.maxcalc8 = atof(*++argv); + + else if (strcmp(5+*argv, "calc16") == 0) + pm.maxcalc16 = atof(*++argv); + + else if (strcmp(5+*argv, "out8") == 0) + pm.maxout8 = atof(*++argv); + + else if (strcmp(5+*argv, "out16") == 0) + pm.maxout16 = atof(*++argv); + + else if (strcmp(5+*argv, "pc8") == 0) + pm.maxpc8 = atof(*++argv); + + else if (strcmp(5+*argv, "pc16") == 0) + pm.maxpc16 = atof(*++argv); + + else + { + fprintf(stderr, "pngvalid: %s: unknown 'max' option\n", *argv); + exit(99); + } + + catmore = 1; + } + + else if (strcmp(*argv, "--log8") == 0) + --argc, pm.log8 = atof(*++argv), catmore = 1; + + else if (strcmp(*argv, "--log16") == 0) + --argc, pm.log16 = atof(*++argv), catmore = 1; + +#ifdef PNG_SET_OPTION_SUPPORTED + else if (strncmp(*argv, "--option=", 9) == 0) + { + /* Syntax of the argument is
@@ -214,19 +220,19 @@ /MACHINE:I386 %(AdditionalOptions) ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll true .\zlibvc.def true - $(OutDir)zlibwapi.pdb true - $(OutDir)zlibwapi.map Windows false - $(OutDir)zlibwapi.lib + + cd ..\..\masmx86 +bld_ml32.bat + @@ -262,18 +268,14 @@ /MACHINE:I386 %(AdditionalOptions) - $(OutDir)zlibwapi.dll true false .\zlibvc.def - $(OutDir)zlibwapi.pdb true - $(OutDir)zlibwapi.map Windows false - $(OutDir)zlibwapi.lib @@ -311,19 +313,19 @@ /MACHINE:I386 %(AdditionalOptions) ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll true false .\zlibvc.def - $(OutDir)zlibwapi.pdb true - $(OutDir)zlibwapi.map Windows false - $(OutDir)zlibwapi.lib + + cd ..\..\masmx86 +bld_ml32.bat + @@ -357,17 +359,17 @@ ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll true .\zlibvc.def true - $(OutDir)zlibwapi.pdb true - $(OutDir)zlibwapi.map Windows - $(OutDir)zlibwapi.lib MachineX64 + + cd ..\..\masmx64 +bld_ml64.bat + @@ -445,15 +447,11 @@ 0x040c - $(OutDir)zlibwapi.dll true false .\zlibvc.def - $(OutDir)zlibwapi.pdb true - $(OutDir)zlibwapi.map Windows - $(OutDir)zlibwapi.lib MachineX64 @@ -536,17 +534,17 @@ ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) - $(OutDir)zlibwapi.dll true false .\zlibvc.def - $(OutDir)zlibwapi.pdb true - $(OutDir)zlibwapi.map Windows - $(OutDir)zlibwapi.lib MachineX64 + + cd ..\..\masmx64 +bld_ml64.bat + diff --git a/libs/zlib/contrib/vstudio/vc11/miniunz.vcxproj b/libs/zlib/contrib/vstudio/vc11/miniunz.vcxproj new file mode 100644 index 000000000..8f9f20bd3 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/miniunz.vcxproj @@ -0,0 +1,314 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc11/minizip.vcxproj b/libs/zlib/contrib/vstudio/vc11/minizip.vcxproj new file mode 100644 index 000000000..c93d9e6ff --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/minizip.vcxproj @@ -0,0 +1,311 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc11/testzlib.vcxproj b/libs/zlib/contrib/vstudio/vc11/testzlib.vcxproj new file mode 100644 index 000000000..6d5595401 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/testzlib.vcxproj @@ -0,0 +1,426 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v110 + + + Application + MultiByte + true + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + true + + + Application + MultiByte + true + + + Application + MultiByte + + + Application + true + v110 + + + Application + true + v110 + + + Application + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj b/libs/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj new file mode 100644 index 000000000..9f20c78f6 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/testzlibdll.vcxproj @@ -0,0 +1,314 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v110 + + + Application + Unicode + v110 + + + Application + MultiByte + + + Application + MultiByte + + + Application + MultiByte + v110 + + + Application + MultiByte + v110 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc11/zlib.rc b/libs/zlib/contrib/vstudio/vc11/zlib.rc new file mode 100644 index 000000000..c4e4b016e --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/libs/zlib/contrib/vstudio/vc11/zlibstat.vcxproj b/libs/zlib/contrib/vstudio/vc11/zlibstat.vcxproj new file mode 100644 index 000000000..806b76a88 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/zlibstat.vcxproj @@ -0,0 +1,464 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + Unicode + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + StaticLibrary + false + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc11/zlibvc.def b/libs/zlib/contrib/vstudio/vc11/zlibvc.def new file mode 100644 index 000000000..f876c3bca --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/libs/zlib/contrib/vstudio/vc11/zlibvc.sln b/libs/zlib/contrib/vstudio/vc11/zlibvc.sln new file mode 100644 index 000000000..9fcbafdd0 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/zlibvc.sln @@ -0,0 +1,117 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/zlib/contrib/vstudio/vc11/zlibvc.vcxproj b/libs/zlib/contrib/vstudio/vc11/zlibvc.vcxproj new file mode 100644 index 000000000..c65b95fdb --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc11/zlibvc.vcxproj @@ -0,0 +1,688 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + v110 + Unicode + + + DynamicLibrary + false + true + + + DynamicLibrary + false + true + + + DynamicLibrary + false + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + true + v110 + + + DynamicLibrary + false + v110 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc12/miniunz.vcxproj b/libs/zlib/contrib/vstudio/vc12/miniunz.vcxproj new file mode 100644 index 000000000..d88ac7fc7 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/miniunz.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc12/minizip.vcxproj b/libs/zlib/contrib/vstudio/vc12/minizip.vcxproj new file mode 100644 index 000000000..f1f239c9e --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/minizip.vcxproj @@ -0,0 +1,313 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc12/testzlib.vcxproj b/libs/zlib/contrib/vstudio/vc12/testzlib.vcxproj new file mode 100644 index 000000000..64b2cbe34 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/testzlib.vcxproj @@ -0,0 +1,430 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v120 + + + Application + MultiByte + true + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + true + v120 + + + Application + MultiByte + true + v120 + + + Application + MultiByte + v120 + + + Application + true + v120 + + + Application + true + v120 + + + Application + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + false + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj b/libs/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj new file mode 100644 index 000000000..c66573a8b --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/testzlibdll.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v120 + + + Application + Unicode + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + Application + MultiByte + v120 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc12/zlib.rc b/libs/zlib/contrib/vstudio/vc12/zlib.rc new file mode 100644 index 000000000..c4e4b016e --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/libs/zlib/contrib/vstudio/vc12/zlibstat.vcxproj b/libs/zlib/contrib/vstudio/vc12/zlibstat.vcxproj new file mode 100644 index 000000000..3fdee7c50 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/zlibstat.vcxproj @@ -0,0 +1,467 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + Unicode + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + StaticLibrary + false + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc12/zlibvc.def b/libs/zlib/contrib/vstudio/vc12/zlibvc.def new file mode 100644 index 000000000..f876c3bca --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/libs/zlib/contrib/vstudio/vc12/zlibvc.sln b/libs/zlib/contrib/vstudio/vc12/zlibvc.sln new file mode 100644 index 000000000..dcda22984 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/zlibvc.sln @@ -0,0 +1,119 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/zlib/contrib/vstudio/vc12/zlibvc.vcxproj b/libs/zlib/contrib/vstudio/vc12/zlibvc.vcxproj new file mode 100644 index 000000000..ab2b6c360 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc12/zlibvc.vcxproj @@ -0,0 +1,692 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + Unicode + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + true + v120 + + + DynamicLibrary + false + v120 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + false + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc14/miniunz.vcxproj b/libs/zlib/contrib/vstudio/vc14/miniunz.vcxproj new file mode 100644 index 000000000..9b5c07587 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/miniunz.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694382A} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + true + false + x86\MiniUnzip$(Configuration)\ + x86\MiniUnzip$(Configuration)\Tmp\ + false + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + true + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + true + false + x64\MiniUnzip$(Configuration)\ + x64\MiniUnzip$(Configuration)\Tmp\ + false + false + ia64\MiniUnzip$(Configuration)\ + ia64\MiniUnzip$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + $(OutDir)miniunz.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)miniunz.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc14/minizip.vcxproj b/libs/zlib/contrib/vstudio/vc14/minizip.vcxproj new file mode 100644 index 000000000..968a410a1 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/minizip.vcxproj @@ -0,0 +1,313 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + true + false + x86\MiniZip$(Configuration)\ + x86\MiniZip$(Configuration)\Tmp\ + false + x64\$(Configuration)\ + x64\$(Configuration)\ + true + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + true + false + x64\$(Configuration)\ + x64\$(Configuration)\ + false + ia64\$(Configuration)\ + ia64\$(Configuration)\ + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + $(OutDir)minizip.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)minizip.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc14/testzlib.vcxproj b/libs/zlib/contrib/vstudio/vc14/testzlib.vcxproj new file mode 100644 index 000000000..2c371252a --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/testzlib.vcxproj @@ -0,0 +1,430 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B} + testzlib + Win32Proj + + + + Application + MultiByte + true + v140 + + + Application + MultiByte + true + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + true + v140 + + + Application + MultiByte + true + v140 + + + Application + MultiByte + v140 + + + Application + true + v140 + + + Application + true + v140 + + + Application + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + true + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x86\TestZlib$(Configuration)\ + x86\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + true + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + x64\TestZlib$(Configuration)\ + x64\TestZlib$(Configuration)\Tmp\ + false + ia64\TestZlib$(Configuration)\ + ia64\TestZlib$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)testzlib.exe + true + Console + true + true + false + + + MachineX86 + false + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDebugDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + Disabled + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + AssemblyAndSourceCode + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + %(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + ..\..\..;%(AdditionalIncludeDirectories) + ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + Default + MultiThreadedDLL + false + $(IntDir) + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + $(OutDir)testzlib.exe + true + Console + true + true + MachineIA64 + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj b/libs/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj new file mode 100644 index 000000000..d87474dec --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/testzlibdll.vcxproj @@ -0,0 +1,316 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {C52F9E7B-498A-42BE-8DB4-85A15694366A} + Win32Proj + + + + Application + MultiByte + v140 + + + Application + Unicode + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + Application + MultiByte + v140 + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + true + false + x86\TestZlibDll$(Configuration)\ + x86\TestZlibDll$(Configuration)\Tmp\ + false + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + true + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + true + false + x64\TestZlibDll$(Configuration)\ + x64\TestZlibDll$(Configuration)\Tmp\ + false + false + ia64\TestZlibDll$(Configuration)\ + ia64\TestZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + false + + + MachineX86 + + + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + Default + MultiThreaded + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x86\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + false + + + MachineX86 + + + + + X64 + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineX64 + + + + + Itanium + + + Disabled + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;_DEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDebugDLL + false + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllDebug\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + $(OutDir)testzlib.pdb + Console + MachineIA64 + + + + + X64 + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + x64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineX64 + + + + + Itanium + + + MaxSpeed + OnlyExplicitInline + true + ..\..\..;..\..\minizip;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;ZLIB_WINAPI;NDEBUG;_CONSOLE;WIN64;%(PreprocessorDefinitions) + true + Default + MultiThreadedDLL + false + true + + + $(IntDir) + Level3 + ProgramDatabase + + + ia64\ZlibDllRelease\zlibwapi.lib;%(AdditionalDependencies) + $(OutDir)testzlibdll.exe + true + Console + true + true + MachineIA64 + + + + + + + + {8fd826f8-3739-44e6-8cc8-997122e53b8d} + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc14/zlib.rc b/libs/zlib/contrib/vstudio/vc14/zlib.rc new file mode 100644 index 000000000..c4e4b016e --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/zlib.rc @@ -0,0 +1,32 @@ +#include + +#define IDR_VERSION1 1 +IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK + FILEFLAGS 0 + FILEOS VOS_DOS_WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0 // not used +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + //language ID = U.S. English, char set = Windows, Multilingual + + BEGIN + VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" + VALUE "FileVersion", "1.2.11\0" + VALUE "InternalName", "zlib\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" + VALUE "ProductName", "ZLib.DLL\0" + VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END diff --git a/libs/zlib/contrib/vstudio/vc14/zlibstat.vcxproj b/libs/zlib/contrib/vstudio/vc14/zlibstat.vcxproj new file mode 100644 index 000000000..3e4b98639 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/zlibstat.vcxproj @@ -0,0 +1,467 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8} + + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + Unicode + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + StaticLibrary + false + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x86\ZlibStat$(Configuration)\ + x86\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + x64\ZlibStat$(Configuration)\ + x64\ZlibStat$(Configuration)\Tmp\ + ia64\ZlibStat$(Configuration)\ + ia64\ZlibStat$(Configuration)\Tmp\ + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:X86 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + OldStyle + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + X64 + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:AMD64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + Itanium + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + ZLIB_WINAPI;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibstat.pch + $(IntDir) + $(IntDir) + $(OutDir) + Level3 + true + + + 0x040c + + + /MACHINE:IA64 /NODEFAULTLIB %(AdditionalOptions) + $(OutDir)zlibstat.lib + true + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc14/zlibvc.def b/libs/zlib/contrib/vstudio/vc14/zlibvc.def new file mode 100644 index 000000000..f876c3bca --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/zlibvc.def @@ -0,0 +1,153 @@ +LIBRARY +; zlib data compression and ZIP file I/O library + +VERSION 1.2 + +EXPORTS + adler32 @1 + compress @2 + crc32 @3 + deflate @4 + deflateCopy @5 + deflateEnd @6 + deflateInit2_ @7 + deflateInit_ @8 + deflateParams @9 + deflateReset @10 + deflateSetDictionary @11 + gzclose @12 + gzdopen @13 + gzerror @14 + gzflush @15 + gzopen @16 + gzread @17 + gzwrite @18 + inflate @19 + inflateEnd @20 + inflateInit2_ @21 + inflateInit_ @22 + inflateReset @23 + inflateSetDictionary @24 + inflateSync @25 + uncompress @26 + zlibVersion @27 + gzprintf @28 + gzputc @29 + gzgetc @30 + gzseek @31 + gzrewind @32 + gztell @33 + gzeof @34 + gzsetparams @35 + zError @36 + inflateSyncPoint @37 + get_crc_table @38 + compress2 @39 + gzputs @40 + gzgets @41 + inflateCopy @42 + inflateBackInit_ @43 + inflateBack @44 + inflateBackEnd @45 + compressBound @46 + deflateBound @47 + gzclearerr @48 + gzungetc @49 + zlibCompileFlags @50 + deflatePrime @51 + deflatePending @52 + + unzOpen @61 + unzClose @62 + unzGetGlobalInfo @63 + unzGetCurrentFileInfo @64 + unzGoToFirstFile @65 + unzGoToNextFile @66 + unzOpenCurrentFile @67 + unzReadCurrentFile @68 + unzOpenCurrentFile3 @69 + unztell @70 + unzeof @71 + unzCloseCurrentFile @72 + unzGetGlobalComment @73 + unzStringFileNameCompare @74 + unzLocateFile @75 + unzGetLocalExtrafield @76 + unzOpen2 @77 + unzOpenCurrentFile2 @78 + unzOpenCurrentFilePassword @79 + + zipOpen @80 + zipOpenNewFileInZip @81 + zipWriteInFileInZip @82 + zipCloseFileInZip @83 + zipClose @84 + zipOpenNewFileInZip2 @86 + zipCloseFileInZipRaw @87 + zipOpen2 @88 + zipOpenNewFileInZip3 @89 + + unzGetFilePos @100 + unzGoToFilePos @101 + + fill_win32_filefunc @110 + +; zlibwapi v1.2.4 added: + fill_win32_filefunc64 @111 + fill_win32_filefunc64A @112 + fill_win32_filefunc64W @113 + + unzOpen64 @120 + unzOpen2_64 @121 + unzGetGlobalInfo64 @122 + unzGetCurrentFileInfo64 @124 + unzGetCurrentFileZStreamPos64 @125 + unztell64 @126 + unzGetFilePos64 @127 + unzGoToFilePos64 @128 + + zipOpen64 @130 + zipOpen2_64 @131 + zipOpenNewFileInZip64 @132 + zipOpenNewFileInZip2_64 @133 + zipOpenNewFileInZip3_64 @134 + zipOpenNewFileInZip4_64 @135 + zipCloseFileInZipRaw64 @136 + +; zlib1 v1.2.4 added: + adler32_combine @140 + crc32_combine @142 + deflateSetHeader @144 + deflateTune @145 + gzbuffer @146 + gzclose_r @147 + gzclose_w @148 + gzdirect @149 + gzoffset @150 + inflateGetHeader @156 + inflateMark @157 + inflatePrime @158 + inflateReset2 @159 + inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/libs/zlib/contrib/vstudio/vc14/zlibvc.sln b/libs/zlib/contrib/vstudio/vc14/zlibvc.sln new file mode 100644 index 000000000..6f4a1076a --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/zlibvc.sln @@ -0,0 +1,119 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibvc", "zlibvc.vcxproj", "{8FD826F8-3739-44E6-8CC8-997122E53B8D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlibstat", "zlibstat.vcxproj", "{745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib", "testzlib.vcxproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlibdll", "testzlibdll.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694366A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "minizip", "minizip.vcxproj", "{48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "miniunz", "miniunz.vcxproj", "{C52F9E7B-498A-42BE-8DB4-85A15694382A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Itanium = Debug|Itanium + Debug|Win32 = Debug|Win32 + Debug|x64 = Debug|x64 + Release|Itanium = Release|Itanium + Release|Win32 = Release|Win32 + Release|x64 = Release|x64 + ReleaseWithoutAsm|Itanium = ReleaseWithoutAsm|Itanium + ReleaseWithoutAsm|Win32 = ReleaseWithoutAsm|Win32 + ReleaseWithoutAsm|x64 = ReleaseWithoutAsm|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Itanium.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|Win32.Build.0 = Debug|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.ActiveCfg = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Debug|x64.Build.0 = Debug|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Itanium.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.ActiveCfg = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|Win32.Build.0 = Release|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.ActiveCfg = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.Release|x64.Build.0 = Release|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {8FD826F8-3739-44E6-8CC8-997122E53B8D}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Itanium.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.ActiveCfg = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|Win32.Build.0 = Debug|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.ActiveCfg = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Debug|x64.Build.0 = Debug|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Itanium.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.ActiveCfg = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|Win32.Build.0 = Release|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.ActiveCfg = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.Release|x64.Build.0 = Release|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {745DEC58-EBB3-47A9-A9B8-4C6627C01BF8}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.Build.0 = ReleaseWithoutAsm|Win32 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = ReleaseWithoutAsm|x64 + {AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.Build.0 = ReleaseWithoutAsm|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694366A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Itanium.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.ActiveCfg = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Debug|x64.Build.0 = Debug|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.ActiveCfg = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.Release|x64.Build.0 = Release|x64 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {48CDD9DC-E09F-4135-9C0C-4FE50C3C654B}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Itanium.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.ActiveCfg = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|Win32.Build.0 = Debug|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.ActiveCfg = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Debug|x64.Build.0 = Debug|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|Win32.Build.0 = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.ActiveCfg = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.Release|x64.Build.0 = Release|x64 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Itanium.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|Win32.ActiveCfg = Release|Win32 + {C52F9E7B-498A-42BE-8DB4-85A15694382A}.ReleaseWithoutAsm|x64.ActiveCfg = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/libs/zlib/contrib/vstudio/vc14/zlibvc.vcxproj b/libs/zlib/contrib/vstudio/vc14/zlibvc.vcxproj new file mode 100644 index 000000000..f8f673cb0 --- /dev/null +++ b/libs/zlib/contrib/vstudio/vc14/zlibvc.vcxproj @@ -0,0 +1,692 @@ + + + + + Debug + Itanium + + + Debug + Win32 + + + Debug + x64 + + + ReleaseWithoutAsm + Itanium + + + ReleaseWithoutAsm + Win32 + + + ReleaseWithoutAsm + x64 + + + Release + Itanium + + + Release + Win32 + + + Release + x64 + + + + {8FD826F8-3739-44E6-8CC8-997122E53B8D} + + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + Unicode + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + true + v140 + + + DynamicLibrary + false + v140 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30128.1 + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + true + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x86\ZlibDll$(Configuration)\ + x86\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + true + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + true + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + x64\ZlibDll$(Configuration)\ + x64\ZlibDll$(Configuration)\Tmp\ + false + false + ia64\ZlibDll$(Configuration)\ + ia64\ZlibDll$(Configuration)\Tmp\ + false + false + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + AllRules.ruleset + + + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + zlibwapi + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Win32 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;%(PreprocessorDefinitions) + true + + + MultiThreaded + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + /MACHINE:I386 %(AdditionalOptions) + ..\..\masmx86\match686.obj;..\..\masmx86\inffas32.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + false + + + $(OutDir)zlibwapi.lib + false + + + cd ..\..\masmx86 +bld_ml32.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\contrib\masmx64 +bld_ml64.bat + + + + + _DEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + Disabled + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + + + MultiThreadedDebugDLL + false + $(IntDir)zlibvc.pch + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + ProgramDatabase + + + _DEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + .\zlibvc.def + true + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + WIN32;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + X64 + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;ASMV;ASMINF;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + ..\..\masmx64\gvmat64.obj;..\..\masmx64\inffasx64.obj;%(AdditionalDependencies) + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineX64 + + + cd ..\..\masmx64 +bld_ml64.bat + + + + + NDEBUG;%(PreprocessorDefinitions) + true + true + Itanium + $(OutDir)zlibvc.tlb + + + OnlyExplicitInline + ..\..\..;..\..\masmx86;%(AdditionalIncludeDirectories) + _CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_WARNINGS;ZLIB_WINAPI;WIN64;%(PreprocessorDefinitions) + true + + + MultiThreadedDLL + false + true + $(IntDir)zlibvc.pch + All + $(IntDir) + $(IntDir) + $(OutDir) + + + Level3 + true + + + NDEBUG;%(PreprocessorDefinitions) + 0x040c + + + $(OutDir)zlibwapi.dll + true + false + .\zlibvc.def + $(OutDir)zlibwapi.pdb + true + $(OutDir)zlibwapi.map + Windows + $(OutDir)zlibwapi.lib + MachineIA64 + + + + + + + + + + + + + + true + true + true + true + true + true + + + + + + + + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) + ZLIB_INTERNAL;%(PreprocessorDefinitions) + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libs/zlib/contrib/vstudio/vc9/zlib.rc b/libs/zlib/contrib/vstudio/vc9/zlib.rc index 863b59c78..c4e4b016e 100644 --- a/libs/zlib/contrib/vstudio/vc9/zlib.rc +++ b/libs/zlib/contrib/vstudio/vc9/zlib.rc @@ -2,8 +2,8 @@ #define IDR_VERSION1 1 IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE - FILEVERSION 1,2,5,0 - PRODUCTVERSION 1,2,5,0 + FILEVERSION 1, 2, 11, 0 + PRODUCTVERSION 1, 2, 11, 0 FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGS 0 FILEOS VOS_DOS_WINDOWS32 @@ -17,12 +17,12 @@ BEGIN BEGIN VALUE "FileDescription", "zlib data compression and ZIP file I/O library\0" - VALUE "FileVersion", "1.2.5.0\0" + VALUE "FileVersion", "1.2.11\0" VALUE "InternalName", "zlib\0" - VALUE "OriginalFilename", "zlib.dll\0" + VALUE "OriginalFilename", "zlibwapi.dll\0" VALUE "ProductName", "ZLib.DLL\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" - VALUE "LegalCopyright", "(C) 1995-2010 Jean-loup Gailly & Mark Adler\0" + VALUE "LegalCopyright", "(C) 1995-2017 Jean-loup Gailly & Mark Adler\0" END END BLOCK "VarFileInfo" diff --git a/libs/zlib/contrib/vstudio/vc9/zlibvc.def b/libs/zlib/contrib/vstudio/vc9/zlibvc.def index fa171ae92..f876c3bca 100644 --- a/libs/zlib/contrib/vstudio/vc9/zlibvc.def +++ b/libs/zlib/contrib/vstudio/vc9/zlibvc.def @@ -1,7 +1,7 @@ LIBRARY ; zlib data compression and ZIP file I/O library -VERSION 1.24 +VERSION 1.2 EXPORTS adler32 @1 @@ -55,6 +55,7 @@ EXPORTS gzungetc @49 zlibCompileFlags @50 deflatePrime @51 + deflatePending @52 unzOpen @61 unzClose @62 @@ -128,3 +129,25 @@ EXPORTS inflatePrime @158 inflateReset2 @159 inflateUndermine @160 + +; zlib1 v1.2.6 added: + gzgetc_ @161 + inflateResetKeep @163 + deflateResetKeep @164 + +; zlib1 v1.2.7 added: + gzopen_w @165 + +; zlib1 v1.2.8 added: + inflateGetDictionary @166 + gzvprintf @167 + +; zlib1 v1.2.9 added: + inflateCodesUsed @168 + inflateValidate @169 + uncompress2 @170 + gzfread @171 + gzfwrite @172 + deflateGetDictionary @173 + adler32_z @174 + crc32_z @175 diff --git a/libs/zlib/crc32.c b/libs/zlib/crc32.c index c12471e61..9580440c0 100644 --- a/libs/zlib/crc32.c +++ b/libs/zlib/crc32.c @@ -1,5 +1,5 @@ /* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2006, 2010, 2011 Mark Adler + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h * * Thanks to Rodney Brown for his contribution of faster @@ -30,41 +30,17 @@ #include "zutil.h" /* for STDC and FAR definitions */ -#define local static - -/* Find a four-byte integer type for crc32_little() and crc32_big(). */ -#ifndef NOBYFOUR -# ifdef STDC /* need ANSI C limits.h to determine sizes */ -# include -# define BYFOUR -# if (UINT_MAX == 0xffffffffUL) - typedef unsigned int u4; -# else -# if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long u4; -# else -# if (USHRT_MAX == 0xffffffffUL) - typedef unsigned short u4; -# else -# undef BYFOUR /* can't find a four-byte integer type! */ -# endif -# endif -# endif -# endif /* STDC */ -#endif /* !NOBYFOUR */ - /* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif #ifdef BYFOUR - typedef u4 crc_table_t; -# define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ - (((w)&0xff00)<<8)+(((w)&0xff)<<24)) local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, z_size_t)); local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); + const unsigned char FAR *, z_size_t)); # define TBLS 8 #else - typedef unsigned long crc_table_t; # define TBLS 1 #endif /* BYFOUR */ @@ -78,10 +54,10 @@ local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); #ifdef DYNAMIC_CRC_TABLE local volatile int crc_table_empty = 1; -local crc_table_t FAR crc_table[TBLS][256]; +local z_crc_t FAR crc_table[TBLS][256]; local void make_crc_table OF((void)); #ifdef MAKECRCH - local void write_table OF((FILE *, const crc_table_t FAR *)); + local void write_table OF((FILE *, const z_crc_t FAR *)); #endif /* MAKECRCH */ /* Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: @@ -111,9 +87,9 @@ local void make_crc_table OF((void)); */ local void make_crc_table() { - crc_table_t c; + z_crc_t c; int n, k; - crc_table_t poly; /* polynomial exclusive-or pattern */ + 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}; @@ -127,11 +103,11 @@ local void make_crc_table() /* make exclusive-or pattern from polynomial (0xedb88320UL) */ poly = 0; for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) - poly |= (crc_table_t)1 << (31 - p[n]); + poly |= (z_crc_t)1 << (31 - p[n]); /* generate a crc for every 8-bit value */ for (n = 0; n < 256; n++) { - c = (crc_table_t)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; @@ -142,11 +118,11 @@ local void make_crc_table() 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] = REV(c); + 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] = REV(c); + crc_table[k + 4][n] = ZSWAP32(c); } } #endif /* BYFOUR */ @@ -168,7 +144,7 @@ local void make_crc_table() 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 crc_table_t FAR "); + 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 @@ -188,7 +164,7 @@ local void make_crc_table() #ifdef MAKECRCH local void write_table(out, table) FILE *out; - const crc_table_t FAR *table; + const z_crc_t FAR *table; { int n; @@ -209,13 +185,13 @@ local void write_table(out, table) /* ========================================================================= * This function can be used by asm versions of crc32() */ -const unsigned long FAR * ZEXPORT get_crc_table() +const z_crc_t FAR * ZEXPORT get_crc_table() { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif /* DYNAMIC_CRC_TABLE */ - return (const unsigned long FAR *)crc_table; + return (const z_crc_t FAR *)crc_table; } /* ========================================================================= */ @@ -223,10 +199,10 @@ const unsigned long FAR * ZEXPORT get_crc_table() #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 /* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) +unsigned long ZEXPORT crc32_z(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - uInt len; + z_size_t len; { if (buf == Z_NULL) return 0UL; @@ -237,7 +213,7 @@ unsigned long ZEXPORT crc32(crc, buf, len) #ifdef BYFOUR if (sizeof(void *) == sizeof(ptrdiff_t)) { - u4 endian; + z_crc_t endian; endian = 1; if (*((unsigned char *)(&endian))) @@ -257,8 +233,29 @@ unsigned long ZEXPORT crc32(crc, buf, len) return crc ^ 0xffffffffUL; } +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt 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] ^ \ @@ -269,19 +266,19 @@ unsigned long ZEXPORT crc32(crc, buf, len) local unsigned long crc32_little(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + z_size_t len; { - register u4 c; - register const u4 FAR *buf4; + register z_crc_t c; + register const z_crc_t FAR *buf4; - c = (u4)crc; + 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 u4 FAR *)(const void FAR *)buf; + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; while (len >= 32) { DOLIT32; len -= 32; @@ -300,7 +297,7 @@ local unsigned long crc32_little(crc, buf, len) } /* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ +#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 @@ -309,20 +306,19 @@ local unsigned long crc32_little(crc, buf, len) local unsigned long crc32_big(crc, buf, len) unsigned long crc; const unsigned char FAR *buf; - unsigned len; + z_size_t len; { - register u4 c; - register const u4 FAR *buf4; + register z_crc_t c; + register const z_crc_t FAR *buf4; - c = REV((u4)crc); + 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 u4 FAR *)(const void FAR *)buf; - buf4--; + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; while (len >= 32) { DOBIG32; len -= 32; @@ -331,14 +327,13 @@ local unsigned long crc32_big(crc, buf, len) DOBIG4; len -= 4; } - buf4++; 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)(REV(c)); + return (unsigned long)(ZSWAP32(c)); } #endif /* BYFOUR */ diff --git a/libs/zlib/crc32.h b/libs/zlib/crc32.h index c3e7171c5..9e0c77810 100644 --- a/libs/zlib/crc32.h +++ b/libs/zlib/crc32.h @@ -2,7 +2,7 @@ * Generated automatically by crc32.c */ -local const crc_table_t FAR crc_table[TBLS][256] = +local const z_crc_t FAR crc_table[TBLS][256] = { { 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, diff --git a/libs/zlib/deflate.c b/libs/zlib/deflate.c index 8bd480eb6..1ec761448 100644 --- a/libs/zlib/deflate.c +++ b/libs/zlib/deflate.c @@ -1,5 +1,5 @@ /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2017 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.6 Copyright 1995-2012 Jean-loup Gailly and Mark Adler "; + " deflate 1.2.11 Copyright 1995-2017 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 @@ -73,6 +73,8 @@ typedef enum { typedef block_state (*compress_func) OF((deflate_state *s, int flush)); /* Compression function. Returns the block state after the call. */ +local int deflateStateCheck OF((z_streamp strm)); +local void slide_hash OF((deflate_state *s)); local void fill_window OF((deflate_state *s)); local block_state deflate_stored OF((deflate_state *s, int flush)); local block_state deflate_fast OF((deflate_state *s, int flush)); @@ -84,15 +86,16 @@ local block_state deflate_huff OF((deflate_state *s, int flush)); local void lm_init OF((deflate_state *s)); local void putShortMSB OF((deflate_state *s, uInt b)); local void flush_pending OF((z_streamp strm)); -local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +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 DEBUG +#ifdef ZLIB_DEBUG local void check_match OF((deflate_state *s, IPos start, IPos match, int length)); #endif @@ -148,21 +151,14 @@ local const config configuration_table[10] = { * meaning. */ -#define EQUAL 0 -/* result of memcmp for equal strings */ - -#ifndef NO_DUMMY_DECL -struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ -#endif - /* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ -#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) +#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) /* =========================================================================== * Update a hash value with the given input byte - * IN assertion: all calls to to UPDATE_HASH are made with consecutive - * input characters, so that a running hash key can be computed from the - * previous key instead of complete recalculation each time. + * IN assertion: all calls to UPDATE_HASH are made with consecutive input + * characters, so that a running hash key can be computed from the previous + * key instead of complete recalculation each time. */ #define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) @@ -173,9 +169,9 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ * the previous length of the hash chain. * If this file is compiled with -DFASTEST, the compression level is forced * to 1, and no hash chains are maintained. - * IN assertion: all calls to to INSERT_STRING are made with consecutive - * input characters and the first MIN_MATCH bytes of str are valid - * (except for the last MIN_MATCH-1 bytes of the input file). + * IN assertion: all calls to INSERT_STRING are made with consecutive input + * characters and the first MIN_MATCH bytes of str are valid (except for + * the last MIN_MATCH-1 bytes of the input file). */ #ifdef FASTEST #define INSERT_STRING(s, str, match_head) \ @@ -197,6 +193,37 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ s->head[s->hash_size-1] = NIL; \ zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); +/* =========================================================================== + * Slide the hash table when sliding the window down (could be avoided with 32 + * bit values at the expense of memory usage). We slide even when level == 0 to + * keep the hash table consistent if we switch back to level > 0 later. + */ +local void slide_hash(s) + deflate_state *s; +{ + unsigned n, m; + Posf *p; + uInt wsize = s->w_size; + + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + } while (--n); + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m - wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif +} + /* ========================================================================= */ int ZEXPORT deflateInit_(strm, level, version, stream_size) z_streamp strm; @@ -270,7 +297,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, #endif if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || - strategy < 0 || strategy > Z_FIXED) { + strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { return Z_STREAM_ERROR; } if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ @@ -278,14 +305,15 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (s == Z_NULL) return Z_MEM_ERROR; strm->state = (struct internal_state FAR *)s; s->strm = strm; + s->status = INIT_STATE; /* to pass state test in deflateReset() */ s->wrap = wrap; s->gzhead = Z_NULL; - s->w_bits = windowBits; + s->w_bits = (uInt)windowBits; s->w_size = 1 << s->w_bits; s->w_mask = s->w_size - 1; - s->hash_bits = memLevel + 7; + 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); @@ -305,7 +333,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || s->pending_buf == Z_NULL) { s->status = FINISH_STATE; - strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + strm->msg = ERR_MSG(Z_MEM_ERROR); deflateEnd (strm); return Z_MEM_ERROR; } @@ -319,6 +347,31 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, return deflateReset(strm); } +/* ========================================================================= + * Check for a valid deflate stream state. Return 0 if ok, 1 if not. + */ +local int deflateStateCheck (strm) + z_streamp strm; +{ + deflate_state *s; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + s = strm->state; + if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && +#ifdef GZIP + s->status != GZIP_STATE && +#endif + s->status != EXTRA_STATE && + s->status != NAME_STATE && + s->status != COMMENT_STATE && + s->status != HCRC_STATE && + s->status != BUSY_STATE && + s->status != FINISH_STATE)) + return 1; + return 0; +} + /* ========================================================================= */ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) z_streamp strm; @@ -329,9 +382,9 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) uInt str, n; int wrap; unsigned avail; - unsigned char *next; + z_const unsigned char *next; - if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) + if (deflateStateCheck(strm) || dictionary == Z_NULL) return Z_STREAM_ERROR; s = strm->state; wrap = s->wrap; @@ -359,7 +412,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) avail = strm->avail_in; next = strm->next_in; strm->avail_in = dictLength; - strm->next_in = (Bytef *)dictionary; + strm->next_in = (z_const Bytef *)dictionary; fill_window(s); while (s->lookahead >= MIN_MATCH) { str = s->strstart; @@ -388,14 +441,35 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) return Z_OK; } +/* ========================================================================= */ +int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) + z_streamp strm; + Bytef *dictionary; + uInt *dictLength; +{ + deflate_state *s; + uInt len; + + if (deflateStateCheck(strm)) + return Z_STREAM_ERROR; + s = strm->state; + len = s->strstart + s->lookahead; + if (len > s->w_size) + len = s->w_size; + if (dictionary != Z_NULL && len) + zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); + if (dictLength != Z_NULL) + *dictLength = len; + return Z_OK; +} + /* ========================================================================= */ int ZEXPORT deflateResetKeep (strm) z_streamp strm; { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { + if (deflateStateCheck(strm)) { return Z_STREAM_ERROR; } @@ -410,7 +484,11 @@ int ZEXPORT deflateResetKeep (strm) if (s->wrap < 0) { s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ } - s->status = s->wrap ? INIT_STATE : BUSY_STATE; + s->status = +#ifdef GZIP + s->wrap == 2 ? GZIP_STATE : +#endif + s->wrap ? INIT_STATE : BUSY_STATE; strm->adler = #ifdef GZIP s->wrap == 2 ? crc32(0L, Z_NULL, 0) : @@ -440,8 +518,8 @@ int ZEXPORT deflateSetHeader (strm, head) z_streamp strm; gz_headerp head; { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - if (strm->state->wrap != 2) return Z_STREAM_ERROR; + if (deflateStateCheck(strm) || strm->state->wrap != 2) + return Z_STREAM_ERROR; strm->state->gzhead = head; return Z_OK; } @@ -452,7 +530,7 @@ int ZEXPORT deflatePending (strm, pending, bits) int *bits; z_streamp strm; { - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; if (pending != Z_NULL) *pending = strm->state->pending; if (bits != Z_NULL) @@ -469,7 +547,7 @@ int ZEXPORT deflatePrime (strm, bits, value) deflate_state *s; int put; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) return Z_BUF_ERROR; @@ -494,9 +572,8 @@ int ZEXPORT deflateParams(strm, level, strategy) { deflate_state *s; compress_func func; - int err = Z_OK; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; #ifdef FASTEST @@ -510,11 +587,22 @@ int ZEXPORT deflateParams(strm, level, strategy) func = configuration_table[s->level].func; if ((strategy != s->strategy || func != configuration_table[level].func) && - strm->total_in != 0) { + s->high_water) { /* Flush the last buffer: */ - err = deflate(strm, Z_BLOCK); + int err = deflate(strm, Z_BLOCK); + if (err == Z_STREAM_ERROR) + return err; + if (strm->avail_out == 0) + return Z_BUF_ERROR; } if (s->level != level) { + if (s->level == 0 && s->matches != 0) { + if (s->matches == 1) + slide_hash(s); + else + CLEAR_HASH(s); + s->matches = 0; + } s->level = level; s->max_lazy_match = configuration_table[level].max_lazy; s->good_match = configuration_table[level].good_length; @@ -522,7 +610,7 @@ int ZEXPORT deflateParams(strm, level, strategy) s->max_chain_length = configuration_table[level].max_chain; } s->strategy = strategy; - return err; + return Z_OK; } /* ========================================================================= */ @@ -535,12 +623,12 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) { deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; s = strm->state; - s->good_match = good_length; - s->max_lazy_match = max_lazy; + s->good_match = (uInt)good_length; + s->max_lazy_match = (uInt)max_lazy; s->nice_match = nice_length; - s->max_chain_length = max_chain; + s->max_chain_length = (uInt)max_chain; return Z_OK; } @@ -567,14 +655,13 @@ uLong ZEXPORT deflateBound(strm, sourceLen) { deflate_state *s; uLong complen, wraplen; - Bytef *str; /* conservative upper bound for compressed data */ complen = sourceLen + ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; /* if can't get parameters, return conservative bound plus zlib wrapper */ - if (strm == Z_NULL || strm->state == Z_NULL) + if (deflateStateCheck(strm)) return complen + 6; /* compute wrapper length */ @@ -586,9 +673,11 @@ uLong ZEXPORT deflateBound(strm, sourceLen) case 1: /* zlib wrapper */ wraplen = 6 + (s->strstart ? 4 : 0); break; +#ifdef GZIP case 2: /* gzip wrapper */ wraplen = 18; if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ + Bytef *str; if (s->gzhead->extra != Z_NULL) wraplen += 2 + s->gzhead->extra_len; str = s->gzhead->name; @@ -605,6 +694,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) wraplen += 2; } break; +#endif default: /* for compiler happiness */ wraplen = 6; } @@ -632,10 +722,10 @@ local void putShortMSB (s, b) } /* ========================================================================= - * Flush as much pending output as possible. All deflate() output goes - * through this function so some applications may wish to modify it - * to avoid allocating a large strm->next_out buffer and copying into it. - * (See also read_buf()). + * Flush as much pending output as possible. All deflate() output, except for + * some deflate_stored() output, goes through this function so some + * applications may wish to modify it to avoid allocating a large + * strm->next_out buffer and copying into it. (See also read_buf()). */ local void flush_pending(strm) z_streamp strm; @@ -652,13 +742,23 @@ local void flush_pending(strm) strm->next_out += len; s->pending_out += len; strm->total_out += len; - strm->avail_out -= len; - s->pending -= len; + strm->avail_out -= len; + s->pending -= len; if (s->pending == 0) { s->pending_out = s->pending_buf; } } +/* =========================================================================== + * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. + */ +#define HCRC_UPDATE(beg) \ + do { \ + if (s->gzhead->hcrc && s->pending > (beg)) \ + strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ + s->pending - (beg)); \ + } while (0) + /* ========================================================================= */ int ZEXPORT deflate (strm, flush) z_streamp strm; @@ -667,203 +767,21 @@ int ZEXPORT deflate (strm, flush) int old_flush; /* value of flush param for previous deflate call */ deflate_state *s; - if (strm == Z_NULL || strm->state == Z_NULL || - flush > Z_BLOCK || flush < 0) { + if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { return Z_STREAM_ERROR; } s = strm->state; if (strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0) || + (strm->avail_in != 0 && strm->next_in == Z_NULL) || (s->status == FINISH_STATE && flush != Z_FINISH)) { ERR_RETURN(strm, Z_STREAM_ERROR); } if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); - s->strm = strm; /* just in case */ old_flush = s->last_flush; s->last_flush = flush; - /* Write the header */ - if (s->status == INIT_STATE) { -#ifdef GZIP - if (s->wrap == 2) { - strm->adler = crc32(0L, Z_NULL, 0); - put_byte(s, 31); - put_byte(s, 139); - put_byte(s, 8); - if (s->gzhead == Z_NULL) { - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, 0); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, OS_CODE); - s->status = BUSY_STATE; - } - else { - put_byte(s, (s->gzhead->text ? 1 : 0) + - (s->gzhead->hcrc ? 2 : 0) + - (s->gzhead->extra == Z_NULL ? 0 : 4) + - (s->gzhead->name == Z_NULL ? 0 : 8) + - (s->gzhead->comment == Z_NULL ? 0 : 16) - ); - put_byte(s, (Byte)(s->gzhead->time & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); - put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); - put_byte(s, s->level == 9 ? 2 : - (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? - 4 : 0)); - put_byte(s, s->gzhead->os & 0xff); - if (s->gzhead->extra != Z_NULL) { - put_byte(s, s->gzhead->extra_len & 0xff); - put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); - } - if (s->gzhead->hcrc) - strm->adler = crc32(strm->adler, s->pending_buf, - s->pending); - s->gzindex = 0; - s->status = EXTRA_STATE; - } - } - else -#endif - { - uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; - uInt level_flags; - - if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) - level_flags = 0; - else if (s->level < 6) - level_flags = 1; - else if (s->level == 6) - level_flags = 2; - else - level_flags = 3; - header |= (level_flags << 6); - if (s->strstart != 0) header |= PRESET_DICT; - header += 31 - (header % 31); - - s->status = BUSY_STATE; - putShortMSB(s, header); - - /* Save the adler32 of the preset dictionary: */ - if (s->strstart != 0) { - putShortMSB(s, (uInt)(strm->adler >> 16)); - putShortMSB(s, (uInt)(strm->adler & 0xffff)); - } - strm->adler = adler32(0L, Z_NULL, 0); - } - } -#ifdef GZIP - if (s->status == EXTRA_STATE) { - if (s->gzhead->extra != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - - while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) - break; - } - put_byte(s, s->gzhead->extra[s->gzindex]); - s->gzindex++; - } - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (s->gzindex == s->gzhead->extra_len) { - s->gzindex = 0; - s->status = NAME_STATE; - } - } - else - s->status = NAME_STATE; - } - if (s->status == NAME_STATE) { - if (s->gzhead->name != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->name[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) { - s->gzindex = 0; - s->status = COMMENT_STATE; - } - } - else - s->status = COMMENT_STATE; - } - if (s->status == COMMENT_STATE) { - if (s->gzhead->comment != Z_NULL) { - uInt beg = s->pending; /* start of bytes to update crc */ - int val; - - do { - if (s->pending == s->pending_buf_size) { - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - flush_pending(strm); - beg = s->pending; - if (s->pending == s->pending_buf_size) { - val = 1; - break; - } - } - val = s->gzhead->comment[s->gzindex++]; - put_byte(s, val); - } while (val != 0); - if (s->gzhead->hcrc && s->pending > beg) - strm->adler = crc32(strm->adler, s->pending_buf + beg, - s->pending - beg); - if (val == 0) - s->status = HCRC_STATE; - } - else - s->status = HCRC_STATE; - } - if (s->status == HCRC_STATE) { - if (s->gzhead->hcrc) { - if (s->pending + 2 > s->pending_buf_size) - flush_pending(strm); - if (s->pending + 2 <= s->pending_buf_size) { - put_byte(s, (Byte)(strm->adler & 0xff)); - put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); - strm->adler = crc32(0L, Z_NULL, 0); - s->status = BUSY_STATE; - } - } - else - s->status = BUSY_STATE; - } -#endif - /* Flush as much pending output as possible */ if (s->pending != 0) { flush_pending(strm); @@ -892,15 +810,197 @@ int ZEXPORT deflate (strm, flush) ERR_RETURN(strm, Z_BUF_ERROR); } + /* Write the header */ + if (s->status == INIT_STATE) { + /* zlib header */ + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags; + + if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) + level_flags = 0; + else if (s->level < 6) + level_flags = 1; + else if (s->level == 6) + level_flags = 2; + else + level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = adler32(0L, Z_NULL, 0); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#ifdef GZIP + if (s->status == GZIP_STATE) { + /* gzip header */ + strm->adler = crc32(0L, Z_NULL, 0); + put_byte(s, 31); + put_byte(s, 139); + put_byte(s, 8); + if (s->gzhead == Z_NULL) { + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, 0); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, OS_CODE); + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + else { + put_byte(s, (s->gzhead->text ? 1 : 0) + + (s->gzhead->hcrc ? 2 : 0) + + (s->gzhead->extra == Z_NULL ? 0 : 4) + + (s->gzhead->name == Z_NULL ? 0 : 8) + + (s->gzhead->comment == Z_NULL ? 0 : 16) + ); + put_byte(s, (Byte)(s->gzhead->time & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); + put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); + put_byte(s, s->level == 9 ? 2 : + (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? + 4 : 0)); + put_byte(s, s->gzhead->os & 0xff); + if (s->gzhead->extra != Z_NULL) { + put_byte(s, s->gzhead->extra_len & 0xff); + put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); + } + if (s->gzhead->hcrc) + strm->adler = crc32(strm->adler, s->pending_buf, + s->pending); + s->gzindex = 0; + s->status = EXTRA_STATE; + } + } + if (s->status == EXTRA_STATE) { + if (s->gzhead->extra != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; + while (s->pending + left > s->pending_buf_size) { + uInt copy = s->pending_buf_size - s->pending; + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, copy); + s->pending = s->pending_buf_size; + HCRC_UPDATE(beg); + s->gzindex += copy; + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + left -= copy; + } + zmemcpy(s->pending_buf + s->pending, + s->gzhead->extra + s->gzindex, left); + s->pending += left; + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = NAME_STATE; + } + if (s->status == NAME_STATE) { + if (s->gzhead->name != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->name[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + s->gzindex = 0; + } + s->status = COMMENT_STATE; + } + if (s->status == COMMENT_STATE) { + if (s->gzhead->comment != Z_NULL) { + ulg beg = s->pending; /* start of bytes to update crc */ + int val; + do { + if (s->pending == s->pending_buf_size) { + HCRC_UPDATE(beg); + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + beg = 0; + } + val = s->gzhead->comment[s->gzindex++]; + put_byte(s, val); + } while (val != 0); + HCRC_UPDATE(beg); + } + s->status = HCRC_STATE; + } + if (s->status == HCRC_STATE) { + if (s->gzhead->hcrc) { + if (s->pending + 2 > s->pending_buf_size) { + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } + put_byte(s, (Byte)(strm->adler & 0xff)); + put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); + strm->adler = crc32(0L, Z_NULL, 0); + } + s->status = BUSY_STATE; + + /* Compression must start with an empty pending buffer */ + flush_pending(strm); + if (s->pending != 0) { + s->last_flush = -1; + return Z_OK; + } + } +#endif + /* Start a new block or continue the current one. */ if (strm->avail_in != 0 || s->lookahead != 0 || (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { block_state bstate; - bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : - (s->strategy == Z_RLE ? deflate_rle(s, flush) : - (*(configuration_table[s->level].func))(s, flush)); + bstate = s->level == 0 ? deflate_stored(s, flush) : + s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : + s->strategy == Z_RLE ? deflate_rle(s, flush) : + (*(configuration_table[s->level].func))(s, flush); if (bstate == finish_started || bstate == finish_done) { s->status = FINISH_STATE; @@ -942,7 +1042,6 @@ int ZEXPORT deflate (strm, flush) } } } - Assert(strm->avail_out > 0, "bug2"); if (flush != Z_FINISH) return Z_OK; if (s->wrap <= 0) return Z_STREAM_END; @@ -979,18 +1078,9 @@ int ZEXPORT deflateEnd (strm) { int status; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (deflateStateCheck(strm)) return Z_STREAM_ERROR; status = strm->state->status; - if (status != INIT_STATE && - status != EXTRA_STATE && - status != NAME_STATE && - status != COMMENT_STATE && - status != HCRC_STATE && - status != BUSY_STATE && - status != FINISH_STATE) { - return Z_STREAM_ERROR; - } /* Deallocate in reverse order of allocations: */ TRY_FREE(strm, strm->state->pending_buf); @@ -1021,7 +1111,7 @@ int ZEXPORT deflateCopy (dest, source) ushf *overlay; - if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + if (deflateStateCheck(source) || dest == Z_NULL) { return Z_STREAM_ERROR; } @@ -1071,7 +1161,7 @@ int ZEXPORT deflateCopy (dest, source) * allocating a large strm->next_in buffer and copying from it. * (See also flush_pending()). */ -local int read_buf(strm, buf, size) +local unsigned read_buf(strm, buf, size) z_streamp strm; Bytef *buf; unsigned size; @@ -1095,7 +1185,7 @@ local int read_buf(strm, buf, size) strm->next_in += len; strm->total_in += len; - return (int)len; + return len; } /* =========================================================================== @@ -1149,9 +1239,9 @@ local uInt longest_match(s, cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ + register Bytef *match; /* matched string */ register int len; /* length of current match */ - int best_len = s->prev_length; /* best match length so far */ + int best_len = (int)s->prev_length; /* best match length so far */ int nice_match = s->nice_match; /* stop if match long enough */ IPos limit = s->strstart > (IPos)MAX_DIST(s) ? s->strstart - (IPos)MAX_DIST(s) : NIL; @@ -1186,7 +1276,7 @@ local uInt longest_match(s, cur_match) /* Do not look for matches beyond the end of the input. This is necessary * to make deflate deterministic. */ - if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); @@ -1347,7 +1437,11 @@ local uInt longest_match(s, cur_match) #endif /* FASTEST */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG + +#define EQUAL 0 +/* result of memcmp for equal strings */ + /* =========================================================================== * Check that the match at match_start is indeed a match. */ @@ -1373,7 +1467,7 @@ local void check_match(s, start, match, length) } #else # define check_match(s, start, match, length) -#endif /* DEBUG */ +#endif /* ZLIB_DEBUG */ /* =========================================================================== * Fill the window when the lookahead becomes insufficient. @@ -1388,8 +1482,7 @@ local void check_match(s, start, match, length) local void fill_window(s) deflate_state *s; { - register unsigned n, m; - register Posf *p; + unsigned n; unsigned more; /* Amount of free space at the end of the window. */ uInt wsize = s->w_size; @@ -1416,35 +1509,11 @@ local void fill_window(s) */ if (s->strstart >= wsize+MAX_DIST(s)) { - zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + 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; - - /* Slide the hash table (could be avoided with 32 bit values - at the expense of memory usage). We slide even when level == 0 - to keep the hash table consistent if we switch back to level > 0 - later. (Using level 0 permanently is not an optimal usage of - zlib, so we don't care about this pathological case.) - */ - n = s->hash_size; - p = &s->head[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - } while (--n); - - n = wsize; -#ifndef FASTEST - p = &s->prev[n]; - do { - m = *--p; - *p = (Pos)(m >= wsize ? m-wsize : NIL); - /* If n is not on any hash chain, prev[n] is garbage but - * its value will never be used. - */ - } while (--n); -#endif + slide_hash(s); more += wsize; } if (s->strm->avail_in == 0) break; @@ -1550,70 +1619,199 @@ local void fill_window(s) if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ } +/* Maximum stored block length in deflate format (not including header). */ +#define MAX_STORED 65535 + +/* Minimum of a and b. */ +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + /* =========================================================================== * Copy without compression as much as possible from the input stream, return * the current block state. - * This function does not insert new strings in the dictionary since - * uncompressible data is probably not useful. This function is used - * only for the level=0 compression option. - * NOTE: this function should be optimized to avoid extra copying from - * window to pending_buf. + * + * In case deflateParams() is used to later switch to a non-zero compression + * level, s->matches (otherwise unused when storing) keeps track of the number + * of hash table slides to perform. If s->matches is 1, then one hash table + * slide will be done when switching. If s->matches is 2, the maximum value + * allowed here, then the hash table will be cleared, since two or more slides + * is the same as a clear. + * + * deflate_stored() is written to minimize the number of times an input byte is + * copied. It is most efficient with large input and output buffers, which + * maximizes the opportunites to have a single copy from next_in to next_out. */ local block_state deflate_stored(s, flush) deflate_state *s; int flush; { - /* Stored blocks are limited to 0xffff bytes, pending_buf is limited - * to pending_buf_size, and each stored block has a 5 byte header: + /* Smallest worthy block size when not flushing or finishing. By default + * this is 32K. This can be as small as 507 bytes for memLevel == 1. For + * large input and output buffers, the stored block size will be larger. */ - ulg max_block_size = 0xffff; - ulg max_start; + unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); - if (max_block_size > s->pending_buf_size - 5) { - max_block_size = s->pending_buf_size - 5; - } - - /* Copy as much as possible from input to output: */ - for (;;) { - /* Fill the window as much as possible: */ - if (s->lookahead <= 1) { - - Assert(s->strstart < s->w_size+MAX_DIST(s) || - s->block_start >= (long)s->w_size, "slide too late"); - - fill_window(s); - if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; - - if (s->lookahead == 0) break; /* flush the current block */ - } - Assert(s->block_start >= 0L, "block gone"); - - s->strstart += s->lookahead; - s->lookahead = 0; - - /* Emit a stored block if pending_buf will be full: */ - max_start = s->block_start + max_block_size; - if (s->strstart == 0 || (ulg)s->strstart >= max_start) { - /* strstart == 0 is possible when wraparound on 16-bit machine */ - s->lookahead = (uInt)(s->strstart - max_start); - s->strstart = (uInt)max_start; - FLUSH_BLOCK(s, 0); - } - /* Flush if we may have to slide, otherwise block_start may become - * negative and the data will be gone: + /* Copy as many min_block or larger stored blocks directly to next_out as + * possible. If flushing, copy the remaining available input to next_out as + * stored blocks, if there is enough space. + */ + unsigned len, left, have, last = 0; + unsigned used = s->strm->avail_in; + do { + /* Set len to the maximum size block that we can copy directly with the + * available input data and output space. Set left to how much of that + * would be copied from what's left in the window. */ - if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { - FLUSH_BLOCK(s, 0); + len = MAX_STORED; /* maximum deflate stored block length */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + if (s->strm->avail_out < have) /* need room for header */ + break; + /* maximum stored block length that will fit in avail_out: */ + have = s->strm->avail_out - have; + left = s->strstart - s->block_start; /* bytes left in window */ + if (len > (ulg)left + s->strm->avail_in) + len = left + s->strm->avail_in; /* limit len to the input */ + if (len > have) + len = have; /* limit len to the output */ + + /* If the stored block would be less than min_block in length, or if + * unable to copy all of the available input when flushing, then try + * copying to the window and the pending buffer instead. Also don't + * write an empty block when flushing -- deflate() does that. + */ + if (len < min_block && ((len == 0 && flush != Z_FINISH) || + flush == Z_NO_FLUSH || + len != left + s->strm->avail_in)) + break; + + /* Make a dummy stored block in pending to get the header bytes, + * including any pending bits. This also updates the debugging counts. + */ + last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; + _tr_stored_block(s, (char *)0, 0L, last); + + /* Replace the lengths in the dummy stored block with len. */ + s->pending_buf[s->pending - 4] = len; + s->pending_buf[s->pending - 3] = len >> 8; + s->pending_buf[s->pending - 2] = ~len; + s->pending_buf[s->pending - 1] = ~len >> 8; + + /* Write the stored block header bytes. */ + flush_pending(s->strm); + +#ifdef ZLIB_DEBUG + /* Update debugging counts for the data about to be copied. */ + s->compressed_len += len << 3; + s->bits_sent += len << 3; +#endif + + /* Copy uncompressed bytes from the window to next_out. */ + if (left) { + if (left > len) + left = len; + zmemcpy(s->strm->next_out, s->window + s->block_start, left); + s->strm->next_out += left; + s->strm->avail_out -= left; + s->strm->total_out += left; + s->block_start += left; + len -= left; } + + /* Copy uncompressed bytes directly from next_in to next_out, updating + * the check value. + */ + if (len) { + read_buf(s->strm, s->strm->next_out, len); + s->strm->next_out += len; + s->strm->avail_out -= len; + s->strm->total_out += len; + } + } while (last == 0); + + /* Update the sliding window with the last s->w_size bytes of the copied + * data, or append all of the copied data to the existing window if less + * than s->w_size bytes were copied. Also update the number of bytes to + * insert in the hash tables, in the event that deflateParams() switches to + * a non-zero compression level. + */ + used -= s->strm->avail_in; /* number of input bytes directly copied */ + if (used) { + /* If any input was used, then no unused input remains in the window, + * therefore s->block_start == s->strstart. + */ + if (used >= s->w_size) { /* supplant the previous history */ + s->matches = 2; /* clear hash */ + zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); + s->strstart = s->w_size; + } + else { + if (s->window_size - s->strstart <= used) { + /* Slide the window down. */ + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + } + zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); + s->strstart += used; + } + s->block_start = s->strstart; + s->insert += MIN(used, s->w_size - s->insert); } - s->insert = 0; - if (flush == Z_FINISH) { - FLUSH_BLOCK(s, 1); + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* If the last block was written to next_out, then done. */ + if (last) return finish_done; + + /* If flushing and all input has been consumed, then done. */ + if (flush != Z_NO_FLUSH && flush != Z_FINISH && + s->strm->avail_in == 0 && (long)s->strstart == s->block_start) + return block_done; + + /* Fill the window with any remaining input. */ + have = s->window_size - s->strstart - 1; + if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { + /* Slide the window down. */ + s->block_start -= s->w_size; + s->strstart -= s->w_size; + zmemcpy(s->window, s->window + s->w_size, s->strstart); + if (s->matches < 2) + s->matches++; /* add a pending slide_hash() */ + have += s->w_size; /* more space now */ } - if ((long)s->strstart > s->block_start) - FLUSH_BLOCK(s, 0); - return block_done; + 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; + } + if (s->high_water < s->strstart) + s->high_water = s->strstart; + + /* There was not enough avail_out to write a complete worthy or flushed + * stored block to next_out. Write a stored block to pending instead, if we + * have enough input for a worthy block, or if flushing and there is enough + * room for the remaining input as a stored block in the pending buffer. + */ + have = (s->bi_valid + 42) >> 3; /* number of header bytes */ + /* maximum stored block length that will fit in pending: */ + have = MIN(s->pending_buf_size - have, MAX_STORED); + min_block = MIN(have, s->w_size); + left = s->strstart - s->block_start; + if (left >= min_block || + ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && + s->strm->avail_in == 0 && left <= have)) { + len = MIN(left, have); + last = flush == Z_FINISH && s->strm->avail_in == 0 && + len == left ? 1 : 0; + _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); + s->block_start += len; + flush_pending(s->strm); + } + + /* We've done all we can with the available input and output. */ + return last ? finish_started : need_more; } /* =========================================================================== @@ -1890,7 +2088,7 @@ local block_state deflate_rle(s, flush) prev == *++scan && prev == *++scan && prev == *++scan && prev == *++scan && scan < strend); - s->match_length = MAX_MATCH - (int)(strend - scan); + s->match_length = MAX_MATCH - (uInt)(strend - scan); if (s->match_length > s->lookahead) s->match_length = s->lookahead; } diff --git a/libs/zlib/deflate.h b/libs/zlib/deflate.h index fbac44d90..23ecdd312 100644 --- a/libs/zlib/deflate.h +++ b/libs/zlib/deflate.h @@ -1,5 +1,5 @@ /* deflate.h -- internal compression state - * Copyright (C) 1995-2012 Jean-loup Gailly + * Copyright (C) 1995-2016 Jean-loup Gailly * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -51,13 +51,16 @@ #define Buf_size 16 /* size of bit buffer in bi_buf */ -#define INIT_STATE 42 -#define EXTRA_STATE 69 -#define NAME_STATE 73 -#define COMMENT_STATE 91 -#define HCRC_STATE 103 -#define BUSY_STATE 113 -#define FINISH_STATE 666 +#define INIT_STATE 42 /* zlib header -> BUSY_STATE */ +#ifdef GZIP +# define GZIP_STATE 57 /* gzip header -> BUSY_STATE | EXTRA_STATE */ +#endif +#define EXTRA_STATE 69 /* gzip extra block -> NAME_STATE */ +#define NAME_STATE 73 /* gzip file name -> COMMENT_STATE */ +#define COMMENT_STATE 91 /* gzip comment -> HCRC_STATE */ +#define HCRC_STATE 103 /* gzip header CRC -> BUSY_STATE */ +#define BUSY_STATE 113 /* deflate -> FINISH_STATE */ +#define FINISH_STATE 666 /* stream complete */ /* Stream status */ @@ -83,7 +86,7 @@ typedef struct static_tree_desc_s static_tree_desc; typedef struct tree_desc_s { ct_data *dyn_tree; /* the dynamic tree */ int max_code; /* largest code with non zero frequency */ - static_tree_desc *stat_desc; /* the corresponding static tree */ + const static_tree_desc *stat_desc; /* the corresponding static tree */ } FAR tree_desc; typedef ush Pos; @@ -100,11 +103,11 @@ typedef struct internal_state { Bytef *pending_buf; /* output still pending */ ulg pending_buf_size; /* size of pending_buf */ Bytef *pending_out; /* next pending byte to output to the stream */ - uInt pending; /* nb of bytes in the pending buffer */ + ulg pending; /* nb of bytes in the pending buffer */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ gz_headerp gzhead; /* gzip header information to write */ - uInt gzindex; /* where in extra, name, or comment */ - Byte method; /* STORED (for zip only) or DEFLATED */ + ulg gzindex; /* where in extra, name, or comment */ + Byte method; /* can only be DEFLATED */ int last_flush; /* value of flush param for previous deflate call */ /* used by deflate.c: */ @@ -249,7 +252,7 @@ typedef struct internal_state { uInt matches; /* number of string matches in current block */ uInt insert; /* bytes at end of window left to insert */ -#ifdef DEBUG +#ifdef ZLIB_DEBUG ulg compressed_len; /* total bit length of compressed file mod 2^32 */ ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ #endif @@ -275,7 +278,7 @@ typedef struct internal_state { /* Output a byte on the stream. * IN assertion: there is enough room in pending_buf. */ -#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} +#define put_byte(s, c) {s->pending_buf[s->pending++] = (Bytef)(c);} #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) @@ -309,7 +312,7 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, * used. */ -#ifndef DEBUG +#ifndef ZLIB_DEBUG /* Inline versions of _tr_tally for speed: */ #if defined(GEN_TREES_H) || !defined(STDC) @@ -328,8 +331,8 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, flush = (s->last_lit == s->lit_bufsize-1); \ } # define _tr_tally_dist(s, distance, length, flush) \ - { uch len = (length); \ - ush dist = (distance); \ + { uch len = (uch)(length); \ + ush dist = (ush)(distance); \ s->d_buf[s->last_lit] = dist; \ s->l_buf[s->last_lit++] = len; \ dist--; \ diff --git a/libs/zlib/doc/algorithm.txt b/libs/zlib/doc/algorithm.txt index 34960bdda..c97f49502 100644 --- a/libs/zlib/doc/algorithm.txt +++ b/libs/zlib/doc/algorithm.txt @@ -206,4 +206,4 @@ Compression,'' IEEE Transactions on Information Theory, Vol. 23, No. 3, pp. 337-343. ``DEFLATE Compressed Data Format Specification'' available in -http://www.ietf.org/rfc/rfc1951.txt +http://tools.ietf.org/html/rfc1951 diff --git a/libs/zlib/examples/enough.c b/libs/zlib/examples/enough.c index c40410bad..b99114430 100644 --- a/libs/zlib/examples/enough.c +++ b/libs/zlib/examples/enough.c @@ -1,7 +1,7 @@ /* enough.c -- determine the maximum size of inflate's Huffman code tables over * all possible valid and complete Huffman codes, subject to a length limit. - * Copyright (C) 2007, 2008 Mark Adler - * Version 1.3 17 February 2008 Mark Adler + * Copyright (C) 2007, 2008, 2012 Mark Adler + * Version 1.4 18 August 2012 Mark Adler */ /* Version history: @@ -14,6 +14,9 @@ 1.3 17 Feb 2008 Add argument for initial root table size Fix bug for initial root table size == max - 1 Use a macro to compute the history index + 1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!) + Clean up comparisons of different types + Clean up code indentation */ /* @@ -236,8 +239,8 @@ local big_t count(int syms, int len, int left) for (use = least; use <= most; use++) { got = count(syms - use, len + 1, (left - use) << 1); sum += got; - if (got == -1 || sum < got) /* overflow */ - return -1; + if (got == (big_t)0 - 1 || sum < got) /* overflow */ + return (big_t)0 - 1; } /* verify that all recursive calls are productive */ @@ -458,6 +461,7 @@ int main(int argc, char **argv) int n; /* number of symbols to code for this run */ big_t got; /* return value of count() */ big_t sum; /* accumulated number of codes over n */ + code_t word; /* for counting bits in code_t */ /* set up globals for cleanup() */ code = NULL; @@ -466,19 +470,19 @@ int main(int argc, char **argv) /* get arguments -- default to the deflate literal/length code */ syms = 286; - root = 9; + root = 9; max = 15; if (argc > 1) { syms = atoi(argv[1]); if (argc > 2) { root = atoi(argv[2]); - if (argc > 3) - max = atoi(argv[3]); - } + if (argc > 3) + max = atoi(argv[3]); + } } if (argc > 4 || syms < 2 || root < 1 || max < 1) { fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n", - stderr); + stderr); return 1; } @@ -487,18 +491,17 @@ int main(int argc, char **argv) max = syms - 1; /* determine the number of bits in a code_t */ - n = 0; - while (((code_t)1 << n) != 0) - n++; + for (n = 0, word = 1; word; n++, word <<= 1) + ; /* make sure that the calculation of most will not overflow */ - if (max > n || syms - 2 >= (((code_t)0 - 1) >> (max - 1))) { + if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) { fputs("abort: code length too long for internal types\n", stderr); return 1; } /* reject impossible code requests */ - if (syms - 1 > ((code_t)1 << max) - 1) { + if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) { fprintf(stderr, "%d symbols cannot be coded in %d bits\n", syms, max); return 1; @@ -532,7 +535,7 @@ int main(int argc, char **argv) for (n = 2; n <= syms; n++) { got = count(n, 1, 2); sum += got; - if (got == -1 || sum < got) { /* overflow */ + if (got == (big_t)0 - 1 || sum < got) { /* overflow */ fputs("abort: can't count that high!\n", stderr); cleanup(); return 1; @@ -556,9 +559,9 @@ int main(int argc, char **argv) } /* find and show maximum inflate table usage */ - if (root > max) /* reduce root to max length */ - root = max; - if (syms < ((code_t)1 << (root + 1))) + if (root > max) /* reduce root to max length */ + root = max; + if ((code_t)syms < ((code_t)1 << (root + 1))) enough(syms); else puts("cannot handle minimum code lengths > root"); diff --git a/libs/zlib/examples/gun.c b/libs/zlib/examples/gun.c index 72b0882ab..be44fa51f 100644 --- a/libs/zlib/examples/gun.c +++ b/libs/zlib/examples/gun.c @@ -1,7 +1,7 @@ /* gun.c -- simple gunzip to give an example of the use of inflateBack() - * Copyright (C) 2003, 2005, 2008, 2010 Mark Adler + * Copyright (C) 2003, 2005, 2008, 2010, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h - Version 1.6 17 January 2010 Mark Adler */ + Version 1.7 12 August 2012 Mark Adler */ /* Version history: 1.0 16 Feb 2003 First version for testing of inflateBack() @@ -18,6 +18,7 @@ 1.4 8 Dec 2006 LZW decompression speed improvements 1.5 9 Feb 2008 Avoid warning in latest version of gcc 1.6 17 Jan 2010 Avoid signed/unsigned comparison warnings + 1.7 12 Aug 2012 Update for z_const usage in zlib 1.2.8 */ /* @@ -45,7 +46,7 @@ end-of-file, they cannot be concantenated. If a Unix compress stream is encountered in an input file, it is the last stream in that file. - Like gunzip and uncompress, the file attributes of the orignal compressed + Like gunzip and uncompress, the file attributes of the original compressed file are maintained in the final uncompressed file, to the extent that the user permissions allow it. @@ -85,7 +86,7 @@ struct ind { /* Load input buffer, assumed to be empty, and return bytes loaded and a pointer to them. read() is called until the buffer is full, or until it returns end-of-file or error. Return 0 on error. */ -local unsigned in(void *in_desc, unsigned char **buf) +local unsigned in(void *in_desc, z_const unsigned char **buf) { int ret; unsigned len; @@ -196,7 +197,7 @@ unsigned char match[65280 + 2]; /* buffer for reversed match or gzip file, read error, or write error (a write error indicated by strm->next_in not equal to Z_NULL), or Z_DATA_ERROR for invalid input. */ -local int lunpipe(unsigned have, unsigned char *next, struct ind *indp, +local int lunpipe(unsigned have, z_const unsigned char *next, struct ind *indp, int outfile, z_stream *strm) { int last; /* last byte read by NEXT(), or -1 if EOF */ @@ -383,7 +384,7 @@ local int gunpipe(z_stream *strm, int infile, int outfile) { int ret, first, last; unsigned have, flags, len; - unsigned char *next = NULL; + z_const unsigned char *next = NULL; struct ind ind, *indp; struct outd outd; diff --git a/libs/zlib/examples/gzappend.c b/libs/zlib/examples/gzappend.c index e9e878e11..662dec379 100644 --- a/libs/zlib/examples/gzappend.c +++ b/libs/zlib/examples/gzappend.c @@ -1,7 +1,7 @@ /* gzappend -- command to append to a gzip file - Copyright (C) 2003 Mark Adler, all rights reserved - version 1.1, 4 Nov 2003 + Copyright (C) 2003, 2012 Mark Adler, all rights reserved + version 1.2, 11 Oct 2012 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages @@ -39,6 +39,8 @@ * - Keep gzip file clean on appended file read errors * - Use in-place rotate instead of auxiliary buffer * (Why you ask? Because it was fun to write!) + * 1.2 11 Oct 2012 - Fix for proper z_const usage + * - Check for input buffer malloc failure */ /* @@ -170,7 +172,7 @@ typedef struct { int size; /* 1 << size is bytes in buf */ unsigned left; /* bytes available at next */ unsigned char *buf; /* buffer */ - unsigned char *next; /* next byte in buffer */ + z_const unsigned char *next; /* next byte in buffer */ char *name; /* file name for error messages */ } file; @@ -399,14 +401,14 @@ local void gztack(char *name, int gd, z_stream *strm, int last) } /* allocate buffers */ - in = fd == -1 ? NULL : malloc(CHUNK); + in = malloc(CHUNK); out = malloc(CHUNK); - if (out == NULL) bye("out of memory", ""); + if (in == NULL || out == NULL) bye("out of memory", ""); /* compress input file and append to gzip file */ do { /* get more input */ - len = fd == -1 ? 0 : read(fd, in, CHUNK); + len = read(fd, in, CHUNK); if (len == -1) { fprintf(stderr, "gzappend warning: error reading %s, skipping rest ...\n", @@ -453,7 +455,7 @@ local void gztack(char *name, int gd, z_stream *strm, int last) /* clean up and return */ free(out); - if (in != NULL) free(in); + free(in); if (fd > 0) close(fd); } @@ -467,11 +469,13 @@ int main(int argc, char **argv) z_stream strm; /* ignore command name */ - argv++; + argc--; argv++; /* provide usage if no arguments */ if (*argv == NULL) { - printf("gzappend 1.1 (4 Nov 2003) Copyright (C) 2003 Mark Adler\n"); + printf( + "gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n" + ); printf( "usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n"); return 0; diff --git a/libs/zlib/examples/gzjoin.c b/libs/zlib/examples/gzjoin.c index 129347ce3..89e809844 100644 --- a/libs/zlib/examples/gzjoin.c +++ b/libs/zlib/examples/gzjoin.c @@ -1,7 +1,7 @@ /* gzjoin -- command to join gzip files into one gzip file - Copyright (C) 2004 Mark Adler, all rights reserved - version 1.0, 11 Dec 2004 + Copyright (C) 2004, 2005, 2012 Mark Adler, all rights reserved + version 1.2, 14 Aug 2012 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages @@ -27,6 +27,7 @@ * * 1.0 11 Dec 2004 - First version * 1.1 12 Jun 2005 - Changed ssize_t to long for portability + * 1.2 14 Aug 2012 - Clean up for z_const usage */ /* @@ -308,7 +309,7 @@ local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot, /* inflate and copy compressed data, clear last-block bit if requested */ len = 0; zpull(&strm, in); - start = strm.next_in; + start = in->next; last = start[0] & 1; if (last && clr) start[0] &= ~1; @@ -351,7 +352,7 @@ local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot, pos = 0x100 >> pos; last = strm.next_in[-1] & pos; if (last && clr) - strm.next_in[-1] &= ~pos; + in->buf[strm.next_in - in->buf - 1] &= ~pos; } else { /* next last-block bit is in next unused byte */ @@ -364,14 +365,14 @@ local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot, } last = strm.next_in[0] & 1; if (last && clr) - strm.next_in[0] &= ~1; + in->buf[strm.next_in - in->buf] &= ~1; } } } /* update buffer with unused input */ in->left = strm.avail_in; - in->next = strm.next_in; + in->next = in->buf + (strm.next_in - in->buf); /* copy used input, write empty blocks to get to byte boundary */ pos = strm.data_type & 7; diff --git a/libs/zlib/examples/gzlog.c b/libs/zlib/examples/gzlog.c index d70aacaba..b8c29274e 100644 --- a/libs/zlib/examples/gzlog.c +++ b/libs/zlib/examples/gzlog.c @@ -1,8 +1,8 @@ /* * gzlog.c - * Copyright (C) 2004, 2008 Mark Adler, all rights reserved + * Copyright (C) 2004, 2008, 2012, 2016 Mark Adler, all rights reserved * For conditions of distribution and use, see copyright notice in gzlog.h - * version 2.0, 25 Apr 2008 + * version 2.2, 14 Aug 2012 */ /* @@ -243,7 +243,7 @@ typedef unsigned int uint; typedef unsigned long ulong; /* Macro for debugging to deterministically force recovery operations */ -#ifdef DEBUG +#ifdef GZLOG_DEBUG #include /* longjmp */ jmp_buf gzlog_jump; /* where to go back to */ int gzlog_bail = 0; /* which point to bail at (1..8) */ @@ -750,7 +750,8 @@ local int log_recover(struct log *log, int op) strcpy(log->end, ".add"); if (stat(log->path, &st) == 0 && st.st_size) { len = (size_t)(st.st_size); - if (len != st.st_size || (data = malloc(st.st_size)) == NULL) { + if ((off_t)len != st.st_size || + (data = malloc(st.st_size)) == NULL) { log_log(log, op, "allocation failure"); return -2; } @@ -758,7 +759,7 @@ local int log_recover(struct log *log, int op) log_log(log, op, ".add file read failure"); return -1; } - ret = read(fd, data, len) != len; + ret = (size_t)read(fd, data, len) != len; close(fd); if (ret) { log_log(log, op, ".add file read failure"); @@ -913,7 +914,7 @@ int gzlog_compress(gzlog *logd) struct log *log = logd; /* check arguments */ - if (log == NULL || strcmp(log->id, LOGID) || len < 0) + if (log == NULL || strcmp(log->id, LOGID)) return -3; /* see if we lost the lock -- if so get it again and reload the extra @@ -952,7 +953,7 @@ int gzlog_compress(gzlog *logd) fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) break; - ret = write(fd, data, len) != len; + ret = (size_t)write(fd, data, len) != len; if (ret | close(fd)) break; log_touch(log); @@ -963,7 +964,7 @@ int gzlog_compress(gzlog *logd) if (fd < 0) break; next = DICT > len ? len : DICT; - ret = write(fd, (char *)data + len - next, next) != next; + ret = (size_t)write(fd, (char *)data + len - next, next) != next; if (ret | close(fd)) break; log_touch(log); @@ -997,9 +998,9 @@ int gzlog_write(gzlog *logd, void *data, size_t len) struct log *log = logd; /* check arguments */ - if (log == NULL || strcmp(log->id, LOGID) || len < 0) + if (log == NULL || strcmp(log->id, LOGID)) return -3; - if (data == NULL || len == 0) + if (data == NULL || len <= 0) return 0; /* see if we lost the lock -- if so get it again and reload the extra @@ -1013,7 +1014,7 @@ int gzlog_write(gzlog *logd, void *data, size_t len) fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (fd < 0) return -1; - ret = write(fd, data, len) != len; + ret = (size_t)write(fd, data, len) != len; if (ret | close(fd)) return -1; log_touch(log); diff --git a/libs/zlib/examples/gzlog.h b/libs/zlib/examples/gzlog.h index c46142673..86f0cecba 100644 --- a/libs/zlib/examples/gzlog.h +++ b/libs/zlib/examples/gzlog.h @@ -1,6 +1,6 @@ /* gzlog.h - Copyright (C) 2004, 2008 Mark Adler, all rights reserved - version 2.0, 25 Apr 2008 + Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved + version 2.2, 14 Aug 2012 This software is provided 'as-is', without any express or implied warranty. In no event will the author be held liable for any damages @@ -27,6 +27,8 @@ Interface changed slightly in that now path is a prefix Compression now occurs as needed during gzlog_write() gzlog_write() now always leaves the log file as valid gzip + 2.1 8 Jul 2012 Fix argument checks in gzlog_compress() and gzlog_write() + 2.2 14 Aug 2012 Clean up signed comparisons */ /* diff --git a/libs/zlib/examples/zran.c b/libs/zlib/examples/zran.c index 617a13086..4fec6594a 100644 --- a/libs/zlib/examples/zran.c +++ b/libs/zlib/examples/zran.c @@ -1,7 +1,12 @@ /* zran.c -- example of zlib/gzip stream indexing and random access - * Copyright (C) 2005 Mark Adler + * Copyright (C) 2005, 2012 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h - Version 1.0 29 May 2005 Mark Adler */ + Version 1.1 29 Sep 2012 Mark Adler */ + +/* Version History: + 1.0 29 May 2005 First version + 1.1 29 Sep 2012 Fix memory reallocation error + */ /* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary() for random access of a compressed file. A file containing a zlib or gzip @@ -22,7 +27,7 @@ grows as needed to accommodate the points. To use the index, an offset in the uncompressed data is provided, for which - the latest accees point at or preceding that offset is located in the index. + the latest access point at or preceding that offset is located in the index. The input file is positioned to the specified location in the index, and if necessary the first few bits of the compressed data is read from the file. inflate is initialized with those bits and the 32K of uncompressed data, and @@ -221,7 +226,7 @@ local int build_index(FILE *in, off_t span, struct access **built) /* clean up and return index (release unused entries in list) */ (void)inflateEnd(&strm); - index = realloc(index, sizeof(struct point) * index->have); + index->list = realloc(index->list, sizeof(struct point) * index->have); index->size = index->have; *built = index; return index->size; diff --git a/libs/zlib/gzguts.h b/libs/zlib/gzguts.h index 6154b062c..990a4d251 100644 --- a/libs/zlib/gzguts.h +++ b/libs/zlib/gzguts.h @@ -1,5 +1,5 @@ /* gzguts.h -- zlib internal header definitions for gz* operations - * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,7 +12,7 @@ # endif #endif -#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ) +#ifdef HAVE_HIDDEN # define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) #else # define ZLIB_INTERNAL @@ -25,15 +25,31 @@ # include # include #endif -#ifdef _MSC_VER -#include + +#ifndef _POSIX_SOURCE +# define _POSIX_SOURCE #endif #include -#ifdef __TURBOC__ +#ifdef _WIN32 +# include +#endif + +#if defined(__TURBOC__) || defined(_MSC_VER) || defined(_WIN32) # include #endif +#if defined(_WIN32) || defined(__CYGWIN__) +# define WIDECHAR +#endif + +#ifdef WINAPI_FAMILY +# define open _open +# define read _read +# define write _write +# define close _close +#endif + #ifdef NO_DEFLATE /* for compatibility with old definition */ # define NO_GZCOMPRESS #endif @@ -59,7 +75,7 @@ #ifndef HAVE_VSNPRINTF # ifdef MSDOS /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ + but for now we just assume it doesn't. */ # define NO_vsnprintf # endif # ifdef __TURBOC__ @@ -87,10 +103,19 @@ # endif #endif +/* unlike snprintf (which is required in C99), _snprintf does not guarantee + null termination of the result -- however this is only used in gzlib.c where + the result is assured to fit in the space provided */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + #ifndef local # define local static #endif -/* compile with -Dlocal if your debugger can't find static symbols */ +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ /* gz* functions always use library allocation functions */ #ifndef STDC @@ -103,7 +128,7 @@ # include # define zstrerror() gz_strwinerror((DWORD)GetLastError()) #else -# ifdef STDC +# ifndef NO_STRERROR # include # define zstrerror() strerror(errno) # else @@ -126,7 +151,8 @@ # define DEF_MEM_LEVEL MAX_MEM_LEVEL #endif -/* default i/o buffer size -- double this for output when reading */ +/* default i/o buffer size -- double this for output when reading (this and + twice this must be able to fit in an unsigned type) */ #define GZBUFSIZE 8192 /* gzip modes, also provide a little integrity check on the passed structure */ @@ -153,7 +179,7 @@ typedef struct { char *path; /* path or fd for error messages */ unsigned size; /* buffer size, zero if not allocated yet */ unsigned want; /* requested buffer size, default is GZBUFSIZE */ - unsigned char *in; /* input buffer */ + unsigned char *in; /* input buffer (double-sized when writing) */ unsigned char *out; /* output buffer (double-sized when reading) */ int direct; /* 0 if processing gzip, 1 if transparent */ /* just for reading */ diff --git a/libs/zlib/gzlib.c b/libs/zlib/gzlib.c index 7aedab8e2..4105e6aff 100644 --- a/libs/zlib/gzlib.c +++ b/libs/zlib/gzlib.c @@ -1,11 +1,11 @@ /* gzlib.c -- zlib functions common to reading and writing gzip files - * Copyright (C) 2004, 2010, 2011 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ #include "gzguts.h" -#if defined(_WIN32) && !defined(__BORLANDC__) +#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__) # define LSEEK _lseeki64 #else #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 @@ -17,7 +17,7 @@ /* Local functions */ local void gz_reset OF((gz_statep)); -local gzFile gz_open OF((const char *, int, const char *)); +local gzFile gz_open OF((const void *, int, const char *)); #if defined UNDER_CE @@ -89,18 +89,26 @@ local void gz_reset(state) /* Open a gzip file either by name or file descriptor. */ local gzFile gz_open(path, fd, mode) - const char *path; + const void *path; int fd; const char *mode; { gz_statep state; + z_size_t len; + int oflag; +#ifdef O_CLOEXEC + int cloexec = 0; +#endif +#ifdef O_EXCL + int exclusive = 0; +#endif /* check input */ if (path == NULL) return NULL; /* allocate gzFile structure to return */ - state = malloc(sizeof(gz_state)); + state = (gz_statep)malloc(sizeof(gz_state)); if (state == NULL) return NULL; state->size = 0; /* no buffers allocated yet */ @@ -133,6 +141,16 @@ local gzFile gz_open(path, fd, mode) return NULL; case 'b': /* ignore -- will request binary anyway */ break; +#ifdef O_CLOEXEC + case 'e': + cloexec = 1; + break; +#endif +#ifdef O_EXCL + case 'x': + exclusive = 1; + break; +#endif case 'f': state->strategy = Z_FILTERED; break; @@ -144,8 +162,10 @@ local gzFile gz_open(path, fd, mode) break; case 'F': state->strategy = Z_FIXED; + break; case 'T': state->direct = 1; + break; default: /* could consider as an error, but just ignore */ ; } @@ -168,36 +188,70 @@ local gzFile gz_open(path, fd, mode) } /* save the path name for error messages */ - state->path = malloc(strlen(path) + 1); +#ifdef WIDECHAR + if (fd == -2) { + len = wcstombs(NULL, path, 0); + if (len == (z_size_t)-1) + len = 0; + } + else +#endif + len = strlen((const char *)path); + state->path = (char *)malloc(len + 1); if (state->path == NULL) { free(state); return NULL; } - strcpy(state->path, path); +#ifdef WIDECHAR + if (fd == -2) + if (len) + wcstombs(state->path, path, len + 1); + else + *(state->path) = 0; + else +#endif +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->path, len + 1, "%s", (const char *)path); +#else + strcpy(state->path, path); +#endif - /* open the file with the appropriate mode (or just use fd) */ - state->fd = fd != -1 ? fd : - open(path, + /* compute the flags for open() */ + oflag = #ifdef O_LARGEFILE - O_LARGEFILE | + O_LARGEFILE | #endif #ifdef O_BINARY - O_BINARY | + O_BINARY | #endif - (state->mode == GZ_READ ? - O_RDONLY : - (O_WRONLY | O_CREAT | ( - state->mode == GZ_WRITE ? - O_TRUNC : - O_APPEND))), - 0666); +#ifdef O_CLOEXEC + (cloexec ? O_CLOEXEC : 0) | +#endif + (state->mode == GZ_READ ? + O_RDONLY : + (O_WRONLY | O_CREAT | +#ifdef O_EXCL + (exclusive ? O_EXCL : 0) | +#endif + (state->mode == GZ_WRITE ? + O_TRUNC : + O_APPEND))); + + /* open the file with the appropriate flags (or just use fd) */ + state->fd = fd > -1 ? fd : ( +#ifdef WIDECHAR + fd == -2 ? _wopen(path, oflag, 0666) : +#endif + open((const char *)path, oflag, 0666)); if (state->fd == -1) { free(state->path); free(state); return NULL; } - if (state->mode == GZ_APPEND) + if (state->mode == GZ_APPEND) { + LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */ state->mode = GZ_WRITE; /* simplify later checks */ + } /* save the current position for rewinding (only if reading) */ if (state->mode == GZ_READ) { @@ -236,14 +290,28 @@ gzFile ZEXPORT gzdopen(fd, mode) char *path; /* identifier for error messages */ gzFile gz; - if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) + if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL) return NULL; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(path, 7 + 3 * sizeof(int), "", fd); +#else sprintf(path, "", fd); /* for debugging */ +#endif gz = gz_open(path, fd, mode); free(path); return gz; } +/* -- see zlib.h -- */ +#ifdef WIDECHAR +gzFile ZEXPORT gzopen_w(path, mode) + const wchar_t *path; + const char *mode; +{ + return gz_open(path, -2, mode); +} +#endif + /* -- see zlib.h -- */ int ZEXPORT gzbuffer(file, size) gzFile file; @@ -263,6 +331,8 @@ int ZEXPORT gzbuffer(file, size) return -1; /* check and set requested size */ + if ((size << 1) < size) + return -1; /* need to be able to double it */ if (size < 2) size = 2; /* need two bytes to check magic header */ state->want = size; @@ -475,7 +545,8 @@ const char * ZEXPORT gzerror(file, errnum) /* return error information */ if (errnum != NULL) *errnum = state->err; - return state->msg == NULL ? "" : state->msg; + return state->err == Z_MEM_ERROR ? "out of memory" : + (state->msg == NULL ? "" : state->msg); } /* -- see zlib.h -- */ @@ -526,22 +597,24 @@ void ZLIB_INTERNAL gz_error(state, err, msg) if (msg == NULL) return; - /* for an out of memory error, save as static string */ - if (err == Z_MEM_ERROR) { - state->msg = (char *)msg; + /* for an out of memory error, return literal string when requested */ + if (err == Z_MEM_ERROR) return; - } /* construct error message with path */ - if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { + if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) == + NULL) { state->err = Z_MEM_ERROR; - state->msg = (char *)"out of memory"; return; } +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3, + "%s%s%s", state->path, ": ", msg); +#else strcpy(state->msg, state->path); strcat(state->msg, ": "); strcat(state->msg, msg); - return; +#endif } #ifndef INT_MAX diff --git a/libs/zlib/gzread.c b/libs/zlib/gzread.c index 46d40e0bb..956b91ea7 100644 --- a/libs/zlib/gzread.c +++ b/libs/zlib/gzread.c @@ -1,5 +1,5 @@ /* gzread.c -- zlib functions for reading gzip files - * Copyright (C) 2004, 2005, 2010, 2011 Mark Adler + * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -12,6 +12,7 @@ local int gz_look OF((gz_statep)); local int gz_decomp OF((gz_statep)); local int gz_fetch OF((gz_statep)); local int gz_skip OF((gz_statep, z_off64_t)); +local z_size_t gz_read OF((gz_statep, voidp, z_size_t)); /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from state->fd, and update state->eof, state->err, and state->msg as appropriate. @@ -24,13 +25,17 @@ local int gz_load(state, buf, len, have) unsigned *have; { int ret; + unsigned get, max = ((unsigned)-1 >> 2) + 1; *have = 0; do { - ret = read(state->fd, buf + *have, len - *have); + get = len - *have; + if (get > max) + get = max; + ret = read(state->fd, buf + *have, get); if (ret <= 0) break; - *have += ret; + *have += (unsigned)ret; } while (*have < len); if (ret < 0) { gz_error(state, Z_ERRNO, zstrerror()); @@ -57,8 +62,14 @@ local int gz_avail(state) if (state->err != Z_OK && state->err != Z_BUF_ERROR) return -1; if (state->eof == 0) { - if (strm->avail_in) - memmove(state->in, strm->next_in, strm->avail_in); + if (strm->avail_in) { /* copy what's there to the start */ + unsigned char *p = state->in; + unsigned const char *q = strm->next_in; + unsigned n = strm->avail_in; + do { + *p++ = *q++; + } while (--n); + } if (gz_load(state, state->in + strm->avail_in, state->size - strm->avail_in, &got) == -1) return -1; @@ -85,13 +96,11 @@ local int gz_look(state) /* allocate read buffers and inflate memory */ if (state->size == 0) { /* allocate buffers */ - state->in = malloc(state->want); - state->out = malloc(state->want << 1); + state->in = (unsigned char *)malloc(state->want); + state->out = (unsigned char *)malloc(state->want << 1); if (state->in == NULL || state->out == NULL) { - if (state->out != NULL) - free(state->out); - if (state->in != NULL) - free(state->in); + free(state->out); + free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } @@ -278,33 +287,17 @@ local int gz_skip(state, len) return 0; } -/* -- see zlib.h -- */ -int ZEXPORT gzread(file, buf, len) - gzFile file; - voidp buf; - unsigned len; -{ - unsigned got, n; +/* Read len bytes into buf from file, or less than len up to the end of the + input. Return the number of bytes read. If zero is returned, either the + end of file was reached, or there was an error. state->err must be + consulted in that case to determine which. */ +local z_size_t gz_read(state, buf, len) gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return -1; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're reading and that there's no (serious) error */ - if (state->mode != GZ_READ || - (state->err != Z_OK && state->err != Z_BUF_ERROR)) - return -1; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return -1; - } + voidp buf; + z_size_t len; +{ + z_size_t got; + unsigned n; /* if len is zero, avoid unnecessary operations */ if (len == 0) @@ -314,49 +307,55 @@ int ZEXPORT gzread(file, buf, len) if (state->seek) { state->seek = 0; if (gz_skip(state, state->skip) == -1) - return -1; + return 0; } /* get len bytes to buf, or less than len if at the end */ got = 0; do { + /* set n to the maximum amount of len that fits in an unsigned int */ + n = -1; + if (n > len) + n = len; + /* first just try copying data from the output buffer */ if (state->x.have) { - n = state->x.have > len ? len : state->x.have; + if (state->x.have < n) + n = state->x.have; memcpy(buf, state->x.next, n); state->x.next += n; state->x.have -= n; } /* output buffer empty -- return if we're at the end of the input */ - else if (state->eof && strm->avail_in == 0) { + else if (state->eof && state->strm.avail_in == 0) { state->past = 1; /* tried to read past end */ break; } /* need output data -- for small len or new stream load up our output buffer */ - else if (state->how == LOOK || len < (state->size << 1)) { + else if (state->how == LOOK || n < (state->size << 1)) { /* get more output, looking for header if required */ if (gz_fetch(state) == -1) - return -1; - continue; /* no progress yet -- go back to memcpy() above */ + return 0; + continue; /* no progress yet -- go back to copy above */ /* the copy above assures that we will leave with space in the output buffer, allowing at least one gzungetc() to succeed */ } /* large len -- read directly into user buffer */ else if (state->how == COPY) { /* read directly */ - if (gz_load(state, buf, len, &n) == -1) - return -1; + if (gz_load(state, (unsigned char *)buf, n, &n) == -1) + return 0; } /* large len -- decompress directly into user buffer */ else { /* state->how == GZIP */ - strm->avail_out = len; - strm->next_out = buf; + state->strm.avail_out = n; + state->strm.next_out = (unsigned char *)buf; if (gz_decomp(state) == -1) - return -1; + return 0; n = state->x.have; state->x.have = 0; } @@ -368,12 +367,84 @@ int ZEXPORT gzread(file, buf, len) state->x.pos += n; } while (len); - /* return number of bytes read into user buffer (will fit in int) */ - return (int)got; + /* return number of bytes read into user buffer */ + return got; } /* -- see zlib.h -- */ -int ZEXPORT gzgetc_(file) +int ZEXPORT gzread(file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return -1; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in an int"); + return -1; + } + + /* read len or fewer bytes to buf */ + len = gz_read(state, buf, len); + + /* check for an error */ + if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) + return -1; + + /* return the number of bytes read (this is assured to fit in an int) */ + return (int)len; +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfread(buf, size, nitems, file) + voidp buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're reading and that there's no (serious) error */ + if (state->mode != GZ_READ || + (state->err != Z_OK && state->err != Z_BUF_ERROR)) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* read len or fewer bytes to buf, return the number of full items read */ + return len ? gz_read(state, buf, len) / size : 0; +} + +/* -- see zlib.h -- */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +#else +# undef gzgetc +#endif +int ZEXPORT gzgetc(file) gzFile file; { int ret; @@ -397,17 +468,16 @@ int ZEXPORT gzgetc_(file) return *(state->x.next)++; } - /* nothing there -- try gzread() */ - ret = gzread(file, buf, 1); + /* nothing there -- try gz_read() */ + ret = gz_read(state, buf, 1); return ret < 1 ? -1 : buf[0]; } -#undef gzgetc -int ZEXPORT gzgetc(file) +int ZEXPORT gzgetc_(file) gzFile file; { - return gzgetc_(file); -} + return gzgetc(file); +} /* -- see zlib.h -- */ int ZEXPORT gzungetc(c, file) @@ -441,7 +511,7 @@ int ZEXPORT gzungetc(c, file) if (state->x.have == 0) { state->x.have = 1; state->x.next = state->out + (state->size << 1) - 1; - state->x.next[0] = c; + state->x.next[0] = (unsigned char)c; state->x.pos--; state->past = 0; return c; @@ -463,7 +533,7 @@ int ZEXPORT gzungetc(c, file) } state->x.have++; state->x.next--; - state->x.next[0] = c; + state->x.next[0] = (unsigned char)c; state->x.pos--; state->past = 0; return c; @@ -513,7 +583,7 @@ char * ZEXPORT gzgets(file, buf, len) /* look for end-of-line in current output buffer */ n = state->x.have > left ? left : state->x.have; - eol = memchr(state->x.next, '\n', n); + eol = (unsigned char *)memchr(state->x.next, '\n', n); if (eol != NULL) n = (unsigned)(eol - state->x.next) + 1; diff --git a/libs/zlib/gzwrite.c b/libs/zlib/gzwrite.c index caa35b61a..c7b5651d7 100644 --- a/libs/zlib/gzwrite.c +++ b/libs/zlib/gzwrite.c @@ -1,5 +1,5 @@ /* gzwrite.c -- zlib functions for writing gzip files - * Copyright (C) 2004, 2005, 2010, 2011, 2012 Mark Adler + * Copyright (C) 2004-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -9,17 +9,19 @@ local int gz_init OF((gz_statep)); local int gz_comp OF((gz_statep, int)); local int gz_zero OF((gz_statep, z_off64_t)); +local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); /* Initialize state for writing a gzip file. Mark initialization by setting - state->size to non-zero. Return -1 on failure or 0 on success. */ + state->size to non-zero. Return -1 on a memory allocation failure, or 0 on + success. */ local int gz_init(state) gz_statep state; { int ret; z_streamp strm = &(state->strm); - /* allocate input buffer */ - state->in = malloc(state->want); + /* allocate input buffer (double size for gzprintf) */ + state->in = (unsigned char *)malloc(state->want << 1); if (state->in == NULL) { gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; @@ -28,7 +30,7 @@ local int gz_init(state) /* only need output buffer and deflate state if compressing */ if (!state->direct) { /* allocate output buffer */ - state->out = malloc(state->want); + state->out = (unsigned char *)malloc(state->want); if (state->out == NULL) { free(state->in); gz_error(state, Z_MEM_ERROR, "out of memory"); @@ -47,6 +49,7 @@ local int gz_init(state) gz_error(state, Z_MEM_ERROR, "out of memory"); return -1; } + strm->next_in = NULL; } /* mark state as initialized */ @@ -62,17 +65,17 @@ local int gz_init(state) } /* Compress whatever is at avail_in and next_in and write to the output file. - Return -1 if there is an error writing to the output file, otherwise 0. - flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, - then the deflate() state is reset to start a new gzip stream. If gz->direct - is true, then simply write to the output file without compressing, and - ignore flush. */ + Return -1 if there is an error writing to the output file or if gz_init() + fails to allocate memory, otherwise 0. flush is assumed to be a valid + deflate() flush value. If flush is Z_FINISH, then the deflate() state is + reset to start a new gzip stream. If gz->direct is true, then simply write + to the output file without compressing, and ignore flush. */ local int gz_comp(state, flush) gz_statep state; int flush; { - int ret, got; - unsigned have; + int ret, writ; + unsigned have, put, max = ((unsigned)-1 >> 2) + 1; z_streamp strm = &(state->strm); /* allocate memory if this is the first time through */ @@ -81,12 +84,16 @@ local int gz_comp(state, flush) /* write directly if requested */ if (state->direct) { - got = write(state->fd, strm->next_in, strm->avail_in); - if (got < 0 || (unsigned)got != strm->avail_in) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; + while (strm->avail_in) { + put = strm->avail_in > max ? max : strm->avail_in; + writ = write(state->fd, strm->next_in, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + strm->avail_in -= (unsigned)writ; + strm->next_in += writ; } - strm->avail_in = 0; return 0; } @@ -97,17 +104,21 @@ local int gz_comp(state, flush) doing Z_FINISH then don't write until we get to Z_STREAM_END */ if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && (flush != Z_FINISH || ret == Z_STREAM_END))) { - have = (unsigned)(strm->next_out - state->x.next); - if (have && ((got = write(state->fd, state->x.next, have)) < 0 || - (unsigned)got != have)) { - gz_error(state, Z_ERRNO, zstrerror()); - return -1; + while (strm->next_out > state->x.next) { + put = strm->next_out - state->x.next > (int)max ? max : + (unsigned)(strm->next_out - state->x.next); + writ = write(state->fd, state->x.next, put); + if (writ < 0) { + gz_error(state, Z_ERRNO, zstrerror()); + return -1; + } + state->x.next += writ; } if (strm->avail_out == 0) { strm->avail_out = state->size; strm->next_out = state->out; + state->x.next = state->out; } - state->x.next = strm->next_out; } /* compress */ @@ -129,7 +140,8 @@ local int gz_comp(state, flush) return 0; } -/* Compress len zeros to output. Return -1 on error, 0 on success. */ +/* Compress len zeros to output. Return -1 on a write error or memory + allocation failure by gz_comp(), or 0 on success. */ local int gz_zero(state, len) gz_statep state; z_off64_t len; @@ -161,33 +173,14 @@ local int gz_zero(state, len) return 0; } -/* -- see zlib.h -- */ -int ZEXPORT gzwrite(file, buf, len) - gzFile file; - voidpc buf; - unsigned len; -{ - unsigned put = len; - unsigned n; +/* Write len bytes from buf to file. Return the number of bytes written. If + the returned value is less than len, then there was an error. */ +local z_size_t gz_write(state, buf, len) gz_statep state; - z_streamp strm; - - /* get internal structure */ - if (file == NULL) - return 0; - state = (gz_statep)file; - strm = &(state->strm); - - /* check that we're writing and that there's no error */ - if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; - - /* since an int is returned, make sure len fits in one, otherwise return - with an error (this avoids the flaw in the interface) */ - if ((int)len < 0) { - gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); - return 0; - } + voidpc buf; + z_size_t len; +{ + z_size_t put = len; /* if len is zero, avoid unnecessary operations */ if (len == 0) @@ -208,35 +201,103 @@ int ZEXPORT gzwrite(file, buf, len) if (len < state->size) { /* copy to input buffer, compress when full */ do { - if (strm->avail_in == 0) - strm->next_in = state->in; - n = state->size - strm->avail_in; - if (n > len) - n = len; - memcpy(strm->next_in + strm->avail_in, buf, n); - strm->avail_in += n; - state->x.pos += n; - buf = (char *)buf + n; - len -= n; + unsigned have, copy; + + if (state->strm.avail_in == 0) + state->strm.next_in = state->in; + have = (unsigned)((state->strm.next_in + state->strm.avail_in) - + state->in); + copy = state->size - have; + if (copy > len) + copy = len; + memcpy(state->in + have, buf, copy); + state->strm.avail_in += copy; + state->x.pos += copy; + buf = (const char *)buf + copy; + len -= copy; if (len && gz_comp(state, Z_NO_FLUSH) == -1) return 0; } while (len); } else { /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) + if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) return 0; /* directly compress user buffer to file */ - strm->avail_in = len; - strm->next_in = (voidp)buf; - state->x.pos += len; - if (gz_comp(state, Z_NO_FLUSH) == -1) - return 0; + state->strm.next_in = (z_const Bytef *)buf; + do { + unsigned n = (unsigned)-1; + if (n > len) + n = len; + state->strm.avail_in = n; + state->x.pos += n; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return 0; + len -= n; + } while (len); } - /* input was all buffered or compressed (put will fit in int) */ - return (int)put; + /* input was all buffered or compressed */ + return put; +} + +/* -- see zlib.h -- */ +int ZEXPORT gzwrite(file, buf, len) + gzFile file; + voidpc buf; + unsigned len; +{ + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* since an int is returned, make sure len fits in one, otherwise return + with an error (this avoids a flaw in the interface) */ + if ((int)len < 0) { + gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); + return 0; + } + + /* write len bytes from buf (the return value will fit in an int) */ + return (int)gz_write(state, buf, len); +} + +/* -- see zlib.h -- */ +z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) + voidpc buf; + z_size_t size; + z_size_t nitems; + gzFile file; +{ + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return 0; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return 0; + + /* compute bytes to read -- error on overflow */ + len = nitems * size; + if (size && len / size != nitems) { + gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); + return 0; + } + + /* write len bytes to buf, return the number of full items written */ + return len ? gz_write(state, buf, len) / size : 0; } /* -- see zlib.h -- */ @@ -244,6 +305,7 @@ int ZEXPORT gzputc(file, c) gzFile file; int c; { + unsigned have; unsigned char buf[1]; gz_statep state; z_streamp strm; @@ -267,17 +329,21 @@ int ZEXPORT gzputc(file, c) /* try writing to input buffer for speed (state->size == 0 if buffer not initialized) */ - if (strm->avail_in < state->size) { + if (state->size) { if (strm->avail_in == 0) strm->next_in = state->in; - strm->next_in[strm->avail_in++] = c; - state->x.pos++; - return c & 0xff; + have = (unsigned)((strm->next_in + strm->avail_in) - state->in); + if (have < state->size) { + state->in[have] = (unsigned char)c; + strm->avail_in++; + state->x.pos++; + return c & 0xff; + } } /* no room in buffer or not initialized, use gz_write() */ - buf[0] = c; - if (gzwrite(file, buf, 1) != 1) + buf[0] = (unsigned char)c; + if (gz_write(state, buf, 1) != 1) return -1; return c & 0xff; } @@ -288,11 +354,21 @@ int ZEXPORT gzputs(file, str) const char *str; { int ret; - unsigned len; + z_size_t len; + gz_statep state; + + /* get internal structure */ + if (file == NULL) + return -1; + state = (gz_statep)file; + + /* check that we're writing and that there's no error */ + if (state->mode != GZ_WRITE || state->err != Z_OK) + return -1; /* write string */ - len = (unsigned)strlen(str); - ret = gzwrite(file, str, len); + len = strlen(str); + ret = gz_write(state, str, len); return ret == 0 && len != 0 ? -1 : ret; } @@ -300,74 +376,89 @@ int ZEXPORT gzputs(file, str) #include /* -- see zlib.h -- */ -int ZEXPORTVA gzprintf (gzFile file, const char *format, ...) +int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) { - int size, len; + int len; + unsigned left; + char *next; gz_statep state; z_streamp strm; - va_list va; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; + return Z_STREAM_ERROR; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) - return 0; + return state->err; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return 0; + return state->err; } - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; - va_start(va, format); + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); + next[state->size - 1] = 0; #ifdef NO_vsnprintf # ifdef HAS_vsprintf_void - (void)vsprintf(state->in, format, va); - va_end(va); - for (len = 0; len < size; len++) - if (state->in[len] == 0) break; + (void)vsprintf(next, format, va); + for (len = 0; len < state->size; len++) + if (next[len] == 0) break; # else - len = vsprintf(state->in, format, va); - va_end(va); + len = vsprintf(next, format, va); # endif #else # ifdef HAS_vsnprintf_void - (void)vsnprintf(state->in, size, format, va); - va_end(va); - len = strlen(state->in); + (void)vsnprintf(next, state->size, format, va); + len = strlen(next); # else - len = vsnprintf((char *)(state->in), size, format, va); - va_end(va); + len = vsnprintf(next, state->size, format, va); # endif #endif /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) return 0; - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; + /* update buffer and position, compress first half if past that */ + strm->avail_in += (unsigned)len; state->x.pos += len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } return len; } +int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) +{ + va_list va; + int ret; + + va_start(va, format); + ret = gzvprintf(file, format, va); + va_end(va); + return ret; +} + #else /* !STDC && !Z_HAVE_STDARG_H */ /* -- see zlib.h -- */ @@ -378,72 +469,82 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; { - int size, len; + unsigned len, left; + char *next; gz_statep state; z_streamp strm; /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; strm = &(state->strm); /* check that can really pass pointer in ints */ if (sizeof(int) != sizeof(void *)) - return 0; + return Z_STREAM_ERROR; /* check that we're writing and that there's no error */ if (state->mode != GZ_WRITE || state->err != Z_OK) - return 0; + return Z_STREAM_ERROR; /* make sure we have some buffer space */ if (state->size == 0 && gz_init(state) == -1) - return 0; + return state->error; /* check for seek request */ if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return 0; + return state->error; } - /* consume whatever's left in the input buffer */ - if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) - return 0; - - /* do the printf() into the input buffer, put length in len */ - size = (int)(state->size); - state->in[size - 1] = 0; + /* do the printf() into the input buffer, put length in len -- the input + buffer is double-sized just for this function, so there is guaranteed to + be state->size bytes available after the current contents */ + if (strm->avail_in == 0) + strm->next_in = state->in; + next = (char *)(strm->next_in + strm->avail_in); + next[state->size - 1] = 0; #ifdef NO_snprintf # ifdef HAS_sprintf_void - sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, + a13, a14, a15, a16, a17, a18, a19, a20); for (len = 0; len < size; len++) - if (state->in[len] == 0) break; + if (next[len] == 0) + break; # else - len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, + a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #else # ifdef HAS_snprintf_void - snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); - len = strlen(state->in); + snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, + a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(next); # else - len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); # endif #endif /* check that printf() results fit in buffer */ - if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) + if (len == 0 || len >= state->size || next[state->size - 1] != 0) return 0; - /* update buffer and position, defer compression until needed */ - strm->avail_in = (unsigned)len; - strm->next_in = state->in; + /* update buffer and position, compress first half if past that */ + strm->avail_in += len; state->x.pos += len; - return len; + if (strm->avail_in >= state->size) { + left = strm->avail_in - state->size; + strm->avail_in = state->size; + if (gz_comp(state, Z_NO_FLUSH) == -1) + return state->err; + memcpy(state->in, state->in + state->size, left); + strm->next_in = state->in; + strm->avail_in = left; + } + return (int)len; } #endif @@ -457,7 +558,7 @@ int ZEXPORT gzflush(file, flush) /* get internal structure */ if (file == NULL) - return -1; + return Z_STREAM_ERROR; state = (gz_statep)file; /* check that we're writing and that there's no error */ @@ -472,11 +573,11 @@ int ZEXPORT gzflush(file, flush) if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return -1; + return state->err; } /* compress remaining data with requested flush */ - gz_comp(state, flush); + (void)gz_comp(state, flush); return state->err; } @@ -507,13 +608,13 @@ int ZEXPORT gzsetparams(file, level, strategy) if (state->seek) { state->seek = 0; if (gz_zero(state, state->skip) == -1) - return -1; + return state->err; } /* change compression parameters for subsequent input */ if (state->size) { /* flush previous input with previous parameters before changing */ - if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) + if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) return state->err; deflateParams(strm, level, strategy); } @@ -548,11 +649,13 @@ int ZEXPORT gzclose_w(file) /* flush, free memory, and close file */ if (gz_comp(state, Z_FINISH) == -1) ret = state->err; - if (!state->direct) { - (void)deflateEnd(&(state->strm)); - free(state->out); + if (state->size) { + if (!state->direct) { + (void)deflateEnd(&(state->strm)); + free(state->out); + } + free(state->in); } - free(state->in); gz_error(state, Z_OK, NULL); free(state->path); if (close(state->fd) == -1) @@ -560,34 +663,3 @@ int ZEXPORT gzclose_w(file) free(state); return ret; } - -/* used by zlibVersion() to get the vsnprintf story from the horse's mouth */ -unsigned long ZEXPORT gzflags() -{ - unsigned long flags = 0; -#if defined(STDC) || defined(Z_HAVE_STDARG_H) -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -} diff --git a/libs/zlib/infback.c b/libs/zlib/infback.c index 981aff17c..59679ecbf 100644 --- a/libs/zlib/infback.c +++ b/libs/zlib/infback.c @@ -1,5 +1,5 @@ /* infback.c -- inflate using a call-back interface - * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -61,7 +61,7 @@ int stream_size; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; state->dmax = 32768U; - state->wbits = windowBits; + state->wbits = (uInt)windowBits; state->wsize = 1U << windowBits; state->window = window; state->wnext = 0; @@ -255,7 +255,7 @@ out_func out; void FAR *out_desc; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ diff --git a/libs/zlib/inffast.c b/libs/zlib/inffast.c index 2f1d60b43..0dbd1dbc0 100644 --- a/libs/zlib/inffast.c +++ b/libs/zlib/inffast.c @@ -1,5 +1,5 @@ /* inffast.c -- fast decoding - * Copyright (C) 1995-2008, 2010 Mark Adler + * Copyright (C) 1995-2017 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -8,26 +8,9 @@ #include "inflate.h" #include "inffast.h" -#ifndef ASMINF - -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") #else -# define OFF 1 -# define PUP(a) *++(a) -#endif /* Decode literal, length, and distance codes and write out the resulting @@ -69,8 +52,8 @@ z_streamp strm; unsigned start; /* inflate()'s starting value for strm->avail_out */ { struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *end; /* while out < end, enough space available */ @@ -96,9 +79,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ /* copy state to local variables */ state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; + in = strm->next_in; last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; + out = strm->next_out; beg = out - (start - strm->avail_out); end = out + (strm->avail_out - 257); #ifdef INFLATE_STRICT @@ -119,9 +102,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ input data or output space */ do { if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } here = lcode[hold & lmask]; @@ -134,14 +117,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? "inflate: literal '%c'\n" : "inflate: literal 0x%02x\n", here.val)); - PUP(out) = (unsigned char)(here.val); + *out++ = (unsigned char)(here.val); } else if (op & 16) { /* length base */ len = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (op) { if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } len += (unsigned)hold & ((1U << op) - 1); @@ -150,9 +133,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ } Tracevv((stderr, "inflate: length %u\n", len)); if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } here = dcode[hold & dmask]; @@ -165,10 +148,10 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ dist = (unsigned)(here.val); op &= 15; /* number of extra bits */ if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; + hold += (unsigned long)(*in++) << bits; bits += 8; } } @@ -196,30 +179,30 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR if (len <= op - whave) { do { - PUP(out) = 0; + *out++ = 0; } while (--len); continue; } len -= op - whave; do { - PUP(out) = 0; + *out++ = 0; } while (--op > whave); if (op == 0) { from = out - dist; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--len); continue; } #endif } - from = window - OFF; + from = window; if (wnext == 0) { /* very common case */ from += wsize - op; if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -230,14 +213,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op < len) { /* some from end of window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); - from = window - OFF; + from = window; if (wnext < len) { /* some from start of window */ op = wnext; len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } @@ -248,35 +231,35 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ if (op < len) { /* some from window */ len -= op; do { - PUP(out) = PUP(from); + *out++ = *from++; } while (--op); from = out - dist; /* rest from output */ } } while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } else { from = out - dist; /* copy direct from output */ do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; len -= 3; } while (len > 2); if (len) { - PUP(out) = PUP(from); + *out++ = *from++; if (len > 1) - PUP(out) = PUP(from); + *out++ = *from++; } } } @@ -313,8 +296,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ hold &= (1U << bits) - 1; /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; + strm->next_in = in; + strm->next_out = out; strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); strm->avail_out = (unsigned)(out < end ? 257 + (end - out) : 257 - (out - end)); diff --git a/libs/zlib/inflate.c b/libs/zlib/inflate.c index cc89517bc..ac333e8c2 100644 --- a/libs/zlib/inflate.c +++ b/libs/zlib/inflate.c @@ -1,5 +1,5 @@ /* inflate.c -- zlib decompression - * Copyright (C) 1995-2011 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -92,20 +92,36 @@ #endif /* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, unsigned out)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); #ifdef BUILDFIXED void makefixed OF((void)); #endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, unsigned len)); +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + int ZEXPORT inflateResetKeep(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; strm->total_in = strm->total_out = state->total = 0; strm->msg = Z_NULL; @@ -130,7 +146,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; state->wsize = 0; state->whave = 0; @@ -146,7 +162,7 @@ int windowBits; struct inflate_state FAR *state; /* get the state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; /* extract wrap request from windowBits parameter */ @@ -155,7 +171,7 @@ int windowBits; windowBits = -windowBits; } else { - wrap = (windowBits >> 4) + 1; + wrap = (windowBits >> 4) + 5; #ifdef GUNZIP if (windowBits < 48) windowBits &= 15; @@ -209,7 +225,9 @@ int stream_size; if (state == Z_NULL) return Z_MEM_ERROR; Tracev((stderr, "inflate: allocated\n")); strm->state = (struct internal_state FAR *)state; + state->strm = strm; state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ ret = inflateReset2(strm, windowBits); if (ret != Z_OK) { ZFREE(strm, state); @@ -233,17 +251,17 @@ int value; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (bits < 0) { state->hold = 0; state->bits = 0; return Z_OK; } - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; return Z_OK; } @@ -375,12 +393,13 @@ void makefixed() output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -local int updatewindow(strm, out) +local int updatewindow(strm, end, copy) z_streamp strm; -unsigned out; +const Bytef *end; +unsigned copy; { struct inflate_state FAR *state; - unsigned copy, dist; + unsigned dist; state = (struct inflate_state FAR *)strm->state; @@ -400,19 +419,18 @@ unsigned out; } /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); + zmemcpy(state->window, end - state->wsize, state->wsize); state->wnext = 0; state->whave = state->wsize; } else { dist = state->wsize - state->wnext; if (dist > copy) dist = copy; - zmemcpy(state->window + state->wnext, strm->next_out - copy, dist); + zmemcpy(state->window + state->wnext, end - copy, dist); copy -= dist; if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); + zmemcpy(state->window, end - copy, copy); state->wnext = copy; state->whave = state->wsize; } @@ -519,11 +537,6 @@ unsigned out; bits -= bits & 7; \ } while (0) -/* Reverse the bytes in a 32-bit value */ -#define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - /* inflate() uses a state machine to process as much input data and generate as much output data as possible before returning. The state machine is @@ -611,7 +624,7 @@ z_streamp strm; int flush; { struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ + z_const unsigned char FAR *next; /* next input */ unsigned char FAR *put; /* next output */ unsigned have, left; /* available input and output */ unsigned long hold; /* bit buffer */ @@ -629,7 +642,7 @@ int flush; static const unsigned short order[19] = /* permutation of code lengths */ {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || (strm->next_in == Z_NULL && strm->avail_in != 0)) return Z_STREAM_ERROR; @@ -649,6 +662,8 @@ int flush; NEEDBITS(16); #ifdef GUNZIP if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; state->check = crc32(0L, Z_NULL, 0); CRC2(state->check, hold); INITBITS(); @@ -676,7 +691,7 @@ int flush; len = BITS(4) + 8; if (state->wbits == 0) state->wbits = len; - else if (len > state->wbits) { + if (len > 15 || len > state->wbits) { strm->msg = (char *)"invalid window size"; state->mode = BAD; break; @@ -703,14 +718,16 @@ int flush; } if (state->head != Z_NULL) state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = TIME; case TIME: NEEDBITS(32); if (state->head != Z_NULL) state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); INITBITS(); state->mode = OS; case OS: @@ -719,7 +736,8 @@ int flush; state->head->xflags = (int)(hold & 0xff); state->head->os = (int)(hold >> 8); } - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); state->mode = EXLEN; case EXLEN: @@ -728,7 +746,8 @@ int flush; state->length = (unsigned)(hold); if (state->head != Z_NULL) state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); INITBITS(); } else if (state->head != Z_NULL) @@ -746,7 +765,7 @@ int flush; len + copy > state->head->extra_max ? state->head->extra_max - len : copy); } - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -765,9 +784,9 @@ int flush; if (state->head != Z_NULL && state->head->name != Z_NULL && state->length < state->head->name_max) - state->head->name[state->length++] = len; + state->head->name[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -786,9 +805,9 @@ int flush; if (state->head != Z_NULL && state->head->comment != Z_NULL && state->length < state->head->comm_max) - state->head->comment[state->length++] = len; + state->head->comment[state->length++] = (Bytef)len; } while (len && copy < have); - if (state->flags & 0x0200) + if ((state->flags & 0x0200) && (state->wrap & 4)) state->check = crc32(state->check, next, copy); have -= copy; next += copy; @@ -800,7 +819,7 @@ int flush; case HCRC: if (state->flags & 0x0200) { NEEDBITS(16); - if (hold != (state->check & 0xffff)) { + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { strm->msg = (char *)"header crc mismatch"; state->mode = BAD; break; @@ -817,7 +836,7 @@ int flush; #endif case DICTID: NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); + strm->adler = state->check = ZSWAP32(hold); INITBITS(); state->mode = DICT; case DICT: @@ -925,7 +944,7 @@ int flush; while (state->have < 19) state->lens[order[state->have++]] = 0; state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 7; ret = inflate_table(CODES, state->lens, 19, &(state->next), &(state->lenbits), state->work); @@ -999,7 +1018,7 @@ int flush; values here (9 and 6) without reading the comments in inftrees.h concerning the ENOUGH constants, which depend on those values */ state->next = state->codes; - state->lencode = (code const FAR *)(state->next); + state->lencode = (const code FAR *)(state->next); state->lenbits = 9; ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), &(state->lenbits), state->work); @@ -1008,7 +1027,7 @@ int flush; state->mode = BAD; break; } - state->distcode = (code const FAR *)(state->next); + state->distcode = (const code FAR *)(state->next); state->distbits = 6; ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, &(state->next), &(state->distbits), state->work); @@ -1181,15 +1200,15 @@ int flush; out -= left; strm->total_out += out; state->total += out; - if (out) + if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE(state->check, put - out, out); out = left; - if (( + if ((state->wrap & 4) && ( #ifdef GUNZIP state->flags ? hold : #endif - REVERSE(hold)) != state->check) { + ZSWAP32(hold)) != state->check) { strm->msg = (char *)"incorrect data check"; state->mode = BAD; break; @@ -1235,7 +1254,7 @@ int flush; RESTORE(); if (state->wsize || (out != strm->avail_out && state->mode < BAD && (state->mode < CHECK || flush != Z_FINISH))) - if (updatewindow(strm, out)) { + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { state->mode = MEM; return Z_MEM_ERROR; } @@ -1244,10 +1263,10 @@ int flush; strm->total_in += in; strm->total_out += out; state->total += out; - if (state->wrap && out) + if ((state->wrap & 4) && out) strm->adler = state->check = UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + (state->mode == TYPE ? 128 : 0) + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) @@ -1259,7 +1278,7 @@ int ZEXPORT inflateEnd(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->window != Z_NULL) ZFREE(strm, state->window); @@ -1269,40 +1288,55 @@ z_streamp strm; return Z_OK; } +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) z_streamp strm; const Bytef *dictionary; uInt dictLength; { struct inflate_state FAR *state; - unsigned long id; - unsigned char *next; - unsigned avail; + unsigned long dictid; int ret; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (state->wrap != 0 && state->mode != DICT) return Z_STREAM_ERROR; - /* check for correct dictionary id */ + /* check for correct dictionary identifier */ if (state->mode == DICT) { - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) return Z_DATA_ERROR; } /* copy dictionary to window using updatewindow(), which will amend the existing dictionary if appropriate */ - next = strm->next_out; - avail = strm->avail_out; - strm->next_out = (Bytef *)dictionary + dictLength; - strm->avail_out = 0; - ret = updatewindow(strm, dictLength); - strm->avail_out = avail; - strm->next_out = next; + ret = updatewindow(strm, dictionary + dictLength, dictLength); if (ret) { state->mode = MEM; return Z_MEM_ERROR; @@ -1319,7 +1353,7 @@ gz_headerp head; struct inflate_state FAR *state; /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; @@ -1342,7 +1376,7 @@ gz_headerp head; */ local unsigned syncsearch(have, buf, len) unsigned FAR *have; -unsigned char FAR *buf; +const unsigned char FAR *buf; unsigned len; { unsigned got; @@ -1372,7 +1406,7 @@ z_streamp strm; struct inflate_state FAR *state; /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; @@ -1419,7 +1453,7 @@ z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; return state->mode == STORED && state->bits == 0; } @@ -1434,8 +1468,7 @@ z_streamp source; unsigned wsize; /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) + if (inflateStateCheck(source) || dest == Z_NULL) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)source->state; @@ -1456,6 +1489,7 @@ z_streamp source; /* copy state */ zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; if (state->lencode >= state->codes && state->lencode <= state->codes + ENOUGH - 1) { copy->lencode = copy->codes + (state->lencode - state->codes); @@ -1477,25 +1511,51 @@ int subvert; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; state = (struct inflate_state FAR *)strm->state; - state->sane = !subvert; #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; return Z_OK; #else + (void)subvert; state->sane = 1; return Z_DATA_ERROR; #endif } +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + long ZEXPORT inflateMark(strm) z_streamp strm; { struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; + if (inflateStateCheck(strm)) + return -(1L << 16); state = (struct inflate_state FAR *)strm->state; - return ((long)(state->back) << 16) + + return (long)(((unsigned long)((long)state->back)) << 16) + (state->mode == COPY ? state->length : (state->mode == MATCH ? state->was - state->length : 0)); } + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/libs/zlib/inflate.h b/libs/zlib/inflate.h index 95f4986d4..a46cce6b6 100644 --- a/libs/zlib/inflate.h +++ b/libs/zlib/inflate.h @@ -1,5 +1,5 @@ /* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2009 Mark Adler + * Copyright (C) 1995-2016 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ @@ -18,7 +18,7 @@ /* Possible inflate modes between inflate() calls */ typedef enum { - HEAD, /* i: waiting for magic header */ + HEAD = 16180, /* i: waiting for magic header */ FLAGS, /* i: waiting for method and flags (gzip) */ TIME, /* i: waiting for modification time (gzip) */ OS, /* i: waiting for extra flags and operating system (gzip) */ @@ -77,11 +77,14 @@ typedef enum { CHECK -> LENGTH -> DONE */ -/* state maintained between inflate() calls. Approximately 10K bytes. */ +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ inflate_mode mode; /* current inflate mode */ int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ + 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) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ diff --git a/libs/zlib/inftrees.c b/libs/zlib/inftrees.c index 60bbd58bf..2ea08fc13 100644 --- a/libs/zlib/inftrees.c +++ b/libs/zlib/inftrees.c @@ -1,5 +1,5 @@ /* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2012 Mark Adler + * Copyright (C) 1995-2017 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.6 Copyright 1995-2012 Mark Adler "; + " inflate 1.2.11 Copyright 1995-2017 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 @@ -54,7 +54,7 @@ unsigned short FAR *work; code FAR *next; /* next available space in table */ const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ + unsigned match; /* use base and extra for symbol >= match */ unsigned short count[MAXBITS+1]; /* number of codes of each length */ unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ static const unsigned short lbase[31] = { /* Length codes 257..285 base */ @@ -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, 203, 69}; + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; 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, @@ -181,19 +181,17 @@ unsigned short FAR *work; switch (type) { case CODES: base = extra = work; /* dummy value--not used */ - end = 19; + match = 20; break; case LENS: base = lbase; - base -= 257; extra = lext; - extra -= 257; - end = 256; + match = 257; break; - default: /* DISTS */ + default: /* DISTS */ base = dbase; extra = dext; - end = -1; + match = 0; } /* initialize state for loop */ @@ -208,21 +206,21 @@ unsigned short FAR *work; mask = used - 1; /* mask for comparing low */ /* check available table space */ - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* process all codes and make table entries */ for (;;) { /* create table entry */ here.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { + if (work[sym] + 1U < match) { here.op = (unsigned char)0; here.val = work[sym]; } - else if ((int)(work[sym]) > end) { - here.op = (unsigned char)(extra[work[sym]]); - here.val = base[work[sym]]; + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; } else { here.op = (unsigned char)(32 + 64); /* end of block */ @@ -277,8 +275,8 @@ unsigned short FAR *work; /* check for enough space */ used += 1U << curr; - if ((type == LENS && used >= ENOUGH_LENS) || - (type == DISTS && used >= ENOUGH_DISTS)) + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) return 1; /* point entry in root table to sub-table */ diff --git a/libs/zlib/make_vms.com b/libs/zlib/make_vms.com index 11be527f0..65e9d0cbc 100644 --- a/libs/zlib/make_vms.com +++ b/libs/zlib/make_vms.com @@ -3,7 +3,7 @@ $! Martin P.J. Zinser $! $! In case of problems with the install you might contact me at $! zinser@zinser.no-ip.info(preferred) or -$! zinser@sysdev.deutsche-boerse.com (work) +$! martin.zinser@eurexchange.com (work) $! $! Make procedure history for Zlib $! @@ -14,9 +14,16 @@ $! 0.02 20061008 Adapt to new Makefile.in $! 0.03 20091224 Add support for large file check $! 0.04 20100110 Add new gzclose, gzlib, gzread, gzwrite $! 0.05 20100221 Exchange zlibdefs.h by zconf.h.in +$! 0.06 20120111 Fix missing amiss_err, update zconf_h.in, fix new exmples +$! subdir path, update module search in makefile.in +$! 0.07 20120115 Triggered by work done by Alexey Chupahin completly redesigned +$! shared image creation +$! 0.08 20120219 Make it work on VAX again, pre-load missing symbols to shared +$! image +$! 0.09 20120305 SMS. P1 sets builder ("MMK", "MMS", " " (built-in)). +$! "" -> automatic, preference: MMK, MMS, built-in. $! $ on error then goto err_exit -$ set proc/parse=ext $! $ true = 1 $ false = 0 @@ -32,31 +39,43 @@ $ s_case = False $! $! Setup variables holding "config" information $! -$ Make = "" +$ Make = "''p1'" $ name = "Zlib" $ version = "?.?.?" $ v_string = "ZLIB_VERSION" $ v_file = "zlib.h" -$ ccopt = "" +$ ccopt = "/include = []" $ lopts = "" $ dnsrl = "" -$ aconf_in_file = "zconf.h.in#zconf.h_in" +$ aconf_in_file = "zconf.h.in#zconf.h_in#zconf_h.in" $ conf_check_string = "" $ linkonly = false $ optfile = name + ".opt" +$ mapfile = name + ".map" $ libdefs = "" +$ vax = f$getsyi("HW_MODEL").lt.1024 $ axp = f$getsyi("HW_MODEL").ge.1024 .and. f$getsyi("HW_MODEL").lt.4096 +$ ia64 = f$getsyi("HW_MODEL").ge.4096 $! -$ whoami = f$parse(f$enviornment("Procedure"),,,,"NO_CONCEAL") +$! 2012-03-05 SMS. +$! Why is this needed? And if it is needed, why not simply ".not. vax"? +$! +$!!! if axp .or. ia64 then set proc/parse=extended +$! +$ whoami = f$parse(f$environment("Procedure"),,,,"NO_CONCEAL") $ mydef = F$parse(whoami,,,"DEVICE") $ mydir = f$parse(whoami,,,"DIRECTORY") - "][" $ myproc = f$parse(whoami,,,"Name") + f$parse(whoami,,,"type") $! $! Check for MMK/MMS $! -$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" -$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" -$! +$ if (Make .eqs. "") +$ then +$ If F$Search ("Sys$System:MMS.EXE") .nes. "" Then Make = "MMS" +$ If F$Type (MMK) .eqs. "STRING" Then Make = "MMK" +$ else +$ Make = f$edit( Make, "trim") +$ endif $! $ gosub find_version $! @@ -69,6 +88,7 @@ $! Look for the compiler used $! $ gosub check_compiler $ close topt +$ close optf $! $ if its_decc $ then @@ -83,6 +103,15 @@ $ ccopt = "/decc" + ccopt $ define sys decc$library_include: $ endif $ endif +$! +$! 2012-03-05 SMS. +$! Why /NAMES = AS_IS? Why not simply ".not. vax"? And why not on VAX? +$! +$ if axp .or. ia64 +$ then +$ ccopt = ccopt + "/name=as_is/opt=(inline=speed)" +$ s_case = true +$ endif $ endif $ if its_vaxc .or. its_gnuc $ then @@ -122,15 +151,20 @@ $ gosub check_config $ endif $ goto aconf_loop $ACONF_EXIT: +$ write aconf "" +$ write aconf "/* VMS specifics added by make_vms.com: */" $ write aconf "#define VMS 1" $ write aconf "#include " $ write aconf "#include " $ write aconf "#ifdef _LARGEFILE" -$ write aconf "#define off64_t __off64_t" -$ write aconf "#define fopen64 fopen" -$ write aconf "#define fseeko64 fseeko" -$ write aconf "#define lseek64 lseek" -$ write aconf "#define ftello64 ftell" +$ write aconf "# define off64_t __off64_t" +$ write aconf "# define fopen64 fopen" +$ write aconf "# define fseeko64 fseeko" +$ write aconf "# define lseek64 lseek" +$ write aconf "# define ftello64 ftell" +$ write aconf "#endif" +$ write aconf "#if !defined( __VAX) && (__CRTL_VER >= 70312000)" +$ write aconf "# define HAVE_VSNPRINTF" $ write aconf "#endif" $ close aconf_in $ close aconf @@ -139,8 +173,9 @@ $! Build the thing plain or with mms $! $ write sys$output "Compiling Zlib sources ..." $ if make.eqs."" -$ then -$ dele example.obj;*,minigzip.obj;* +$ then +$ if (f$search( "example.obj;*") .nes. "") then delete example.obj;* +$ if (f$search( "minigzip.obj;*") .nes. "") then delete minigzip.obj;* $ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" - adler32.c zlib.h zconf.h $ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - @@ -174,41 +209,34 @@ $ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - $ write sys$output "Building Zlib ..." $ CALL MAKE libz.OLB "lib/crea libz.olb *.obj" *.OBJ $ write sys$output "Building example..." -$ CALL MAKE example.OBJ "CC ''CCOPT' example" - - test/example.c zlib.h zconf.h +$ CALL MAKE example.OBJ "CC ''CCOPT' [.test]example" - + [.test]example.c zlib.h zconf.h $ call make example.exe "LINK example,libz.olb/lib" example.obj libz.olb -$ if f$search("x11vms:xvmsutils.olb") .nes. "" -$ then -$ write sys$output "Building minigzip..." -$ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" - - test/minigzip.c zlib.h zconf.h -$ call make minigzip.exe - - "LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" - - minigzip.obj libz.olb -$ endif -$ else +$ write sys$output "Building minigzip..." +$ CALL MAKE minigzip.OBJ "CC ''CCOPT' [.test]minigzip" - + [.test]minigzip.c zlib.h zconf.h +$ call make minigzip.exe - + "LINK minigzip,libz.olb/lib" - + minigzip.obj libz.olb +$ else $ gosub crea_mms $ write sys$output "Make ''name' ''version' with ''Make' " $ 'make' -$ endif -$! -$! Alpha gets a shareable image -$! -$ If axp -$ Then -$ gosub crea_olist -$ write sys$output "Creating libzshr.exe" -$ call anal_obj_axp modules.opt _link.opt -$ if s_case -$ then -$ open/append optf modules.opt -$ write optf "case_sensitive=YES" -$ close optf -$ endif -$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,_link.opt/opt $ endif +$! +$! Create shareable image +$! +$ gosub crea_olist +$ write sys$output "Creating libzshr.exe" +$ call map_2_shopt 'mapfile' 'optfile' +$ LINK_'lopts'/SHARE=libzshr.exe modules.opt/opt,'optfile'/opt $ write sys$output "Zlib build completed" +$ delete/nolog tmp.opt;* $ exit +$AMISS_ERR: +$ write sys$output "No source for config.hin found." +$ write sys$output "Tried any of ''aconf_in_file'" +$ goto err_exit $CC_ERR: $ write sys$output "C compiler required to build ''name'" $ goto err_exit @@ -216,7 +244,6 @@ $ERR_EXIT: $ set message/facil/ident/sever/text $ close/nolog optf $ close/nolog topt -$ close/nolog conf_hin $ close/nolog aconf_in $ close/nolog aconf $ close/nolog out @@ -397,7 +424,7 @@ $ copy sys$input: out $ deck # descrip.mms: MMS description file for building zlib on VMS # written by Martin P.J. Zinser -# +# OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\ gzread.obj, gzwrite.obj, uncompr.obj, infback.obj\ @@ -407,10 +434,9 @@ OBJS = adler32.obj, compress.obj, crc32.obj, gzclose.obj, gzlib.obj\ $ eod $ write out "CFLAGS=", ccopt $ write out "LOPTS=", lopts +$ write out "all : example.exe minigzip.exe libz.olb" $ copy sys$input: out $ deck - -all : example.exe minigzip.exe libz.olb @ write sys$output " Example applications available" libz.olb : libz.olb($(OBJS)) @@ -420,7 +446,7 @@ example.exe : example.obj libz.olb link $(LOPTS) example,libz.olb/lib minigzip.exe : minigzip.obj libz.olb - link $(LOPTS) minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib + link $(LOPTS) minigzip,libz.olb/lib clean : delete *.obj;*,libz.olb;*,*.opt;*,*.exe;* @@ -431,7 +457,7 @@ adler32.obj : adler32.c zutil.h zlib.h zconf.h compress.obj : compress.c zlib.h zconf.h crc32.obj : crc32.c zutil.h zlib.h zconf.h deflate.obj : deflate.c deflate.h zutil.h zlib.h zconf.h -example.obj : test/example.c zlib.h zconf.h +example.obj : [.test]example.c zlib.h zconf.h gzclose.obj : gzclose.c zutil.h zlib.h zconf.h gzlib.obj : gzlib.c zutil.h zlib.h zconf.h gzread.obj : gzread.c zutil.h zlib.h zconf.h @@ -439,7 +465,7 @@ gzwrite.obj : gzwrite.c zutil.h zlib.h zconf.h inffast.obj : inffast.c zutil.h zlib.h zconf.h inftrees.h inffast.h inflate.obj : inflate.c zutil.h zlib.h zconf.h inftrees.obj : inftrees.c zutil.h zlib.h zconf.h inftrees.h -minigzip.obj : test/minigzip.c zlib.h zconf.h +minigzip.obj : [.test]minigzip.c zlib.h zconf.h trees.obj : trees.c deflate.h zutil.h zlib.h zconf.h uncompr.obj : uncompr.c zlib.h zconf.h zutil.obj : zutil.c zutil.h zlib.h zconf.h @@ -455,13 +481,18 @@ $! $CREA_OLIST: $ open/read min makefile.in $ open/write mod modules.opt -$ src_check = "OBJC =" +$ src_check_list = "OBJZ =#OBJG =" $MRLOOP: $ read/end=mrdone min rec -$ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop +$ i = 0 +$SRC_CHECK_LOOP: +$ src_check = f$element(i, "#", src_check_list) +$ i = i+1 +$ if src_check .eqs. "#" then goto mrloop +$ if (f$extract(0,6,rec) .nes. src_check) then goto src_check_loop $ rec = rec - src_check $ gosub extra_filnam -$ if (f$element(1,"\",rec) .eqs. "\") then goto mrdone +$ if (f$element(1,"\",rec) .eqs. "\") then goto mrloop $MRSLOOP: $ read/end=mrdone min rec $ gosub extra_filnam @@ -672,124 +703,6 @@ $ endif $ return $!------------------------------------------------------------------------------ $! -$! Analyze Object files for OpenVMS AXP to extract Procedure and Data -$! information to build a symbol vector for a shareable image -$! All the "brains" of this logic was suggested by Hartmut Becker -$! (Hartmut.Becker@compaq.com). All the bugs were introduced by me -$! (zinser@zinser.no-ip.info), so if you do have problem reports please do not -$! bother Hartmut/HP, but get in touch with me -$! -$! Version history -$! 0.01 20040406 Skip over shareable images in option file -$! 0.02 20041109 Fix option file for shareable images with case_sensitive=YES -$! 0.03 20050107 Skip over Identification labels in option file -$! 0.04 20060117 Add uppercase alias to code compiled with /name=as_is -$! -$ ANAL_OBJ_AXP: Subroutine -$ V = 'F$Verify(0) -$ SAY := "WRITE_ SYS$OUTPUT" -$ -$ IF F$SEARCH("''P1'") .EQS. "" -$ THEN -$ SAY "ANAL_OBJ_AXP-E-NOSUCHFILE: Error, inputfile ''p1' not available" -$ goto exit_aa -$ ENDIF -$ IF "''P2'" .EQS. "" -$ THEN -$ SAY "ANAL_OBJ_AXP: Error, no output file provided" -$ goto exit_aa -$ ENDIF -$ -$ open/read in 'p1 -$ create a.tmp -$ open/append atmp a.tmp -$ loop: -$ read/end=end_loop in line -$ if f$locate("/SHARE",f$edit(line,"upcase")) .lt. f$length(line) -$ then -$ write sys$output "ANAL_SKP_SHR-i-skipshare, ''line'" -$ goto loop -$ endif -$ if f$locate("IDENTIFICATION=",f$edit(line,"upcase")) .lt. f$length(line) -$ then -$ write sys$output "ANAL_OBJ_AXP-i-ident: Identification ", - - f$element(1,"=",line) -$ goto loop -$ endif -$ f= f$search(line) -$ if f .eqs. "" -$ then -$ write sys$output "ANAL_OBJ_AXP-w-nosuchfile, ''line'" -$ goto loop -$ endif -$ define/user sys$output nl: -$ define/user sys$error nl: -$ anal/obj/gsd 'f /out=x.tmp -$ open/read xtmp x.tmp -$ XLOOP: -$ read/end=end_xloop xtmp xline -$ xline = f$edit(xline,"compress") -$ write atmp xline -$ goto xloop -$ END_XLOOP: -$ close xtmp -$ goto loop -$ end_loop: -$ close in -$ close atmp -$ if f$search("a.tmp") .eqs. "" - - then $ exit -$ ! all global definitions -$ search a.tmp "symbol:","EGSY$V_DEF 1","EGSY$V_NORM 1"/out=b.tmp -$ ! all procedures -$ search b.tmp "EGSY$V_NORM 1"/wind=(0,1) /out=c.tmp -$ search c.tmp "symbol:"/out=d.tmp -$ define/user sys$output nl: -$ edito/edt/command=sys$input d.tmp -sub/symbol: "/symbol_vector=(/whole -sub/"/=PROCEDURE)/whole -exit -$ ! all data -$ search b.tmp "EGSY$V_DEF 1"/wind=(0,1) /out=e.tmp -$ search e.tmp "symbol:"/out=f.tmp -$ define/user sys$output nl: -$ edito/edt/command=sys$input f.tmp -sub/symbol: "/symbol_vector=(/whole -sub/"/=DATA)/whole -exit -$ sort/nodupl d.tmp,f.tmp g.tmp -$ open/read raw_vector g.tmp -$ open/write case_vector 'p2' -$ RAWLOOP: -$ read/end=end_rawloop raw_vector raw_element -$ write case_vector raw_element -$ if f$locate("=PROCEDURE)",raw_element) .lt. f$length(raw_element) -$ then -$ name = f$element(1,"=",raw_element) - "(" -$ if f$edit(name,"UPCASE") .nes. name then - - write case_vector f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)", - - f$edit(name,"UPCASE"), name) -$ endif -$ if f$locate("=DATA)",raw_element) .lt. f$length(raw_element) -$ then -$ name = f$element(1,"=",raw_element) - "(" -$ if f$edit(name,"UPCASE") .nes. name then - - write case_vector f$fao(" symbol_vector=(!AS/!AS=DATA)", - - f$edit(name,"UPCASE"), name) -$ endif -$ goto rawloop -$ END_RAWLOOP: -$ close raw_vector -$ close case_vector -$ delete a.tmp;*,b.tmp;*,c.tmp;*,d.tmp;*,e.tmp;*,f.tmp;*,g.tmp;* -$ if f$search("x.tmp") .nes. "" - - then $ delete x.tmp;* -$! -$ EXIT_AA: -$ if V then set verify -$ endsubroutine -$!------------------------------------------------------------------------------ -$! $! Write configuration to both permanent and temporary config file $! $! Version history @@ -802,3 +715,153 @@ $ write confh 'p1' $ close confh $ENDSUBROUTINE $!------------------------------------------------------------------------------ +$! +$! Analyze the project map file and create the symbol vector for a shareable +$! image from it +$! +$! Version history +$! 0.01 20120128 First version +$! 0.02 20120226 Add pre-load logic +$! +$ MAP_2_SHOPT: Subroutine +$! +$ SAY := "WRITE_ SYS$OUTPUT" +$! +$ IF F$SEARCH("''P1'") .EQS. "" +$ THEN +$ SAY "MAP_2_SHOPT-E-NOSUCHFILE: Error, inputfile ''p1' not available" +$ goto exit_m2s +$ ENDIF +$ IF "''P2'" .EQS. "" +$ THEN +$ SAY "MAP_2_SHOPT: Error, no output file provided" +$ goto exit_m2s +$ ENDIF +$! +$ module1 = "deflate#deflateEnd#deflateInit_#deflateParams#deflateSetDictionary" +$ module2 = "gzclose#gzerror#gzgetc#gzgets#gzopen#gzprintf#gzputc#gzputs#gzread" +$ module3 = "gzseek#gztell#inflate#inflateEnd#inflateInit_#inflateSetDictionary" +$ module4 = "inflateSync#uncompress#zlibVersion#compress" +$ open/read map 'p1 +$ if axp .or. ia64 +$ then +$ open/write aopt a.opt +$ open/write bopt b.opt +$ write aopt " CASE_SENSITIVE=YES" +$ write bopt "SYMBOL_VECTOR= (-" +$ mod_sym_num = 1 +$ MOD_SYM_LOOP: +$ if f$type(module'mod_sym_num') .nes. "" +$ then +$ mod_in = 0 +$ MOD_SYM_IN: +$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') +$ if shared_proc .nes. "#" +$ then +$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- + f$edit(shared_proc,"upcase"),shared_proc) +$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) +$ mod_in = mod_in + 1 +$ goto mod_sym_in +$ endif +$ mod_sym_num = mod_sym_num + 1 +$ goto mod_sym_loop +$ endif +$MAP_LOOP: +$ read/end=map_end map line +$ if (f$locate("{",line).lt. f$length(line)) .or. - + (f$locate("global:", line) .lt. f$length(line)) +$ then +$ proc = true +$ goto map_loop +$ endif +$ if f$locate("}",line).lt. f$length(line) then proc = false +$ if f$locate("local:", line) .lt. f$length(line) then proc = false +$ if proc +$ then +$ shared_proc = f$edit(line,"collapse") +$ chop_semi = f$locate(";", shared_proc) +$ if chop_semi .lt. f$length(shared_proc) then - + shared_proc = f$extract(0, chop_semi, shared_proc) +$ write aopt f$fao(" symbol_vector=(!AS/!AS=PROCEDURE)",- + f$edit(shared_proc,"upcase"),shared_proc) +$ write bopt f$fao("!AS=PROCEDURE,-",shared_proc) +$ endif +$ goto map_loop +$MAP_END: +$ close/nolog aopt +$ close/nolog bopt +$ open/append libopt 'p2' +$ open/read aopt a.opt +$ open/read bopt b.opt +$ALOOP: +$ read/end=aloop_end aopt line +$ write libopt line +$ goto aloop +$ALOOP_END: +$ close/nolog aopt +$ sv = "" +$BLOOP: +$ read/end=bloop_end bopt svn +$ if (svn.nes."") +$ then +$ if (sv.nes."") then write libopt sv +$ sv = svn +$ endif +$ goto bloop +$BLOOP_END: +$ write libopt f$extract(0,f$length(sv)-2,sv), "-" +$ write libopt ")" +$ close/nolog bopt +$ delete/nolog/noconf a.opt;*,b.opt;* +$ else +$ if vax +$ then +$ open/append libopt 'p2' +$ mod_sym_num = 1 +$ VMOD_SYM_LOOP: +$ if f$type(module'mod_sym_num') .nes. "" +$ then +$ mod_in = 0 +$ VMOD_SYM_IN: +$ shared_proc = f$element(mod_in, "#", module'mod_sym_num') +$ if shared_proc .nes. "#" +$ then +$ write libopt f$fao("UNIVERSAL=!AS",- + f$edit(shared_proc,"upcase")) +$ mod_in = mod_in + 1 +$ goto vmod_sym_in +$ endif +$ mod_sym_num = mod_sym_num + 1 +$ goto vmod_sym_loop +$ endif +$VMAP_LOOP: +$ read/end=vmap_end map line +$ if (f$locate("{",line).lt. f$length(line)) .or. - + (f$locate("global:", line) .lt. f$length(line)) +$ then +$ proc = true +$ goto vmap_loop +$ endif +$ if f$locate("}",line).lt. f$length(line) then proc = false +$ if f$locate("local:", line) .lt. f$length(line) then proc = false +$ if proc +$ then +$ shared_proc = f$edit(line,"collapse") +$ chop_semi = f$locate(";", shared_proc) +$ if chop_semi .lt. f$length(shared_proc) then - + shared_proc = f$extract(0, chop_semi, shared_proc) +$ write libopt f$fao("UNIVERSAL=!AS",- + f$edit(shared_proc,"upcase")) +$ endif +$ goto vmap_loop +$VMAP_END: +$ else +$ write sys$output "Unknown Architecture (Not VAX, AXP, or IA64)" +$ write sys$output "No options file created" +$ endif +$ endif +$ EXIT_M2S: +$ close/nolog map +$ close/nolog libopt +$ endsubroutine diff --git a/libs/zlib/msdos/Makefile.bor b/libs/zlib/msdos/Makefile.bor index 0c1b99c9b..3d12a2c25 100644 --- a/libs/zlib/msdos/Makefile.bor +++ b/libs/zlib/msdos/Makefile.bor @@ -86,9 +86,9 @@ uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h -example.obj: example.c zlib.h zconf.h +example.obj: test/example.c zlib.h zconf.h -minigzip.obj: minigzip.c zlib.h zconf.h +minigzip.obj: test/minigzip.c zlib.h zconf.h # the command line is cut to fit in the MS-DOS 128 byte limit: diff --git a/libs/zlib/msdos/Makefile.dj2 b/libs/zlib/msdos/Makefile.dj2 index 29b03954d..59d2037d6 100644 --- a/libs/zlib/msdos/Makefile.dj2 +++ b/libs/zlib/msdos/Makefile.dj2 @@ -29,7 +29,7 @@ CC=gcc #CFLAGS=-MMD -O #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-MMD -g -DDEBUG +#CFLAGS=-MMD -g -DZLIB_DEBUG CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -Wstrict-prototypes -Wmissing-prototypes diff --git a/libs/zlib/msdos/Makefile.emx b/libs/zlib/msdos/Makefile.emx index 9c1b57a58..e30f67bed 100644 --- a/libs/zlib/msdos/Makefile.emx +++ b/libs/zlib/msdos/Makefile.emx @@ -11,7 +11,7 @@ CC=gcc #CFLAGS=-MMD -O #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-MMD -g -DDEBUG +#CFLAGS=-MMD -g -DZLIB_DEBUG CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ -Wstrict-prototypes -Wmissing-prototypes diff --git a/libs/zlib/msdos/Makefile.msc b/libs/zlib/msdos/Makefile.msc index cd2816fbf..ae8378615 100644 --- a/libs/zlib/msdos/Makefile.msc +++ b/libs/zlib/msdos/Makefile.msc @@ -80,10 +80,10 @@ uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h -example.obj: example.c zlib.h zconf.h +example.obj: test/example.c zlib.h zconf.h $(CC) -c $(CFLAGS) $*.c -minigzip.obj: minigzip.c zlib.h zconf.h +minigzip.obj: test/minigzip.c zlib.h zconf.h $(CC) -c $(CFLAGS) $*.c diff --git a/libs/zlib/msdos/Makefile.tc b/libs/zlib/msdos/Makefile.tc index bcd0d1889..5aec82a9d 100644 --- a/libs/zlib/msdos/Makefile.tc +++ b/libs/zlib/msdos/Makefile.tc @@ -71,9 +71,9 @@ uncompr.obj: uncompr.c zlib.h zconf.h zutil.obj: zutil.c zutil.h zlib.h zconf.h -example.obj: example.c zlib.h zconf.h +example.obj: test/example.c zlib.h zconf.h -minigzip.obj: minigzip.c zlib.h zconf.h +minigzip.obj: test/minigzip.c zlib.h zconf.h # the command line is cut to fit in the MS-DOS 128 byte limit: diff --git a/libs/zlib/old/Makefile.emx b/libs/zlib/old/Makefile.emx new file mode 100644 index 000000000..612b03791 --- /dev/null +++ b/libs/zlib/old/Makefile.emx @@ -0,0 +1,69 @@ +# Makefile for zlib. Modified for emx/rsxnt by Chr. Spieler, 6/16/98. +# Copyright (C) 1995-1998 Jean-loup Gailly. +# For conditions of distribution and use, see copyright notice in zlib.h + +# To compile, or to compile and test, type: +# +# make -fmakefile.emx; make test -fmakefile.emx +# + +CC=gcc -Zwin32 + +#CFLAGS=-MMD -O +#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 +#CFLAGS=-MMD -g -DZLIB_DEBUG +CFLAGS=-MMD -O3 $(BUTT) -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ + -Wstrict-prototypes -Wmissing-prototypes + +# If cp.exe is available, replace "copy /Y" with "cp -fp" . +CP=copy /Y +# If gnu install.exe is available, replace $(CP) with ginstall. +INSTALL=$(CP) +# The default value of RM is "rm -f." If "rm.exe" is found, comment out: +RM=del +LDLIBS=-L. -lzlib +LD=$(CC) -s -o +LDSHARED=$(CC) + +INCL=zlib.h zconf.h +LIBS=zlib.a + +AR=ar rcs + +prefix=/usr/local +exec_prefix = $(prefix) + +OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o gzread.o \ + gzwrite.o infback.o inffast.o inflate.o inftrees.o trees.o uncompr.o zutil.o + +TEST_OBJS = example.o minigzip.o + +all: example.exe minigzip.exe + +test: all + ./example + echo hello world | .\minigzip | .\minigzip -d + +%.o : %.c + $(CC) $(CFLAGS) -c $< -o $@ + +zlib.a: $(OBJS) + $(AR) $@ $(OBJS) + +%.exe : %.o $(LIBS) + $(LD) $@ $< $(LDLIBS) + + +.PHONY : clean + +clean: + $(RM) *.d + $(RM) *.o + $(RM) *.exe + $(RM) zlib.a + $(RM) foo.gz + +DEPS := $(wildcard *.d) +ifneq ($(DEPS),) +include $(DEPS) +endif diff --git a/libs/zlib/old/os2/Makefile.os2 b/libs/zlib/old/os2/Makefile.os2 index a105aaa5b..bb426c0d8 100644 --- a/libs/zlib/old/os2/Makefile.os2 +++ b/libs/zlib/old/os2/Makefile.os2 @@ -14,7 +14,7 @@ CC=gcc -Zomf -s CFLAGS=-O6 -Wall #CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7 -#CFLAGS=-g -DDEBUG +#CFLAGS=-g -DZLIB_DEBUG #CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \ # -Wstrict-prototypes -Wmissing-prototypes diff --git a/libs/zlib/os400/README400 b/libs/zlib/os400/README400 new file mode 100644 index 000000000..4f98334f5 --- /dev/null +++ b/libs/zlib/os400/README400 @@ -0,0 +1,48 @@ + ZLIB version 1.2.11 for OS/400 installation instructions + +1) Download and unpack the zlib tarball to some IFS directory. + (i.e.: /path/to/the/zlib/ifs/source/directory) + + If the installed IFS command suppors gzip format, this is straightforward, +else you have to unpack first to some directory on a system supporting it, +then move the whole directory to the IFS via the network (via SMB or FTP). + +2) Edit the configuration parameters in the compilation script. + + EDTF STMF('/path/to/the/zlib/ifs/source/directory/os400/make.sh') + +Tune the parameters according to your needs if not matching the defaults. +Save the file and exit after edition. + +3) Enter qshell, then work in the zlib OS/400 specific directory. + + QSH + cd /path/to/the/zlib/ifs/source/directory/os400 + +4) Compile and install + + sh make.sh + +The script will: +- create the libraries, objects and IFS directories for the zlib environment, +- compile all modules, +- create a service program, +- create a static and a dynamic binding directory, +- install header files for C/C++ and for ILE/RPG, both for compilation in + DB2 and IFS environments. + +That's all. + + +Notes: For OS/400 ILE RPG programmers, a /copy member defining the ZLIB + API prototypes for ILE RPG can be found in ZLIB/H(ZLIB.INC). + In the ILE environment, the same definitions are available from + file zlib.inc located in the same IFS include directory as the + C/C++ header files. + Please read comments in this member for more information. + + Remember that most foreign textual data are ASCII coded: this + implementation does not handle conversion from/to ASCII, so + text data code conversions must be done explicitely. + + Mainly for the reason above, always open zipped files in binary mode. diff --git a/libs/zlib/os400/bndsrc b/libs/zlib/os400/bndsrc new file mode 100644 index 000000000..5e6e0a2f0 --- /dev/null +++ b/libs/zlib/os400/bndsrc @@ -0,0 +1,119 @@ +STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB') + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.1.3 entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32") + EXPORT SYMBOL("compress") + EXPORT SYMBOL("compress2") + EXPORT SYMBOL("crc32") + EXPORT SYMBOL("get_crc_table") + EXPORT SYMBOL("deflate") + EXPORT SYMBOL("deflateEnd") + EXPORT SYMBOL("deflateSetDictionary") + EXPORT SYMBOL("deflateCopy") + EXPORT SYMBOL("deflateReset") + EXPORT SYMBOL("deflateParams") + EXPORT SYMBOL("deflatePrime") + EXPORT SYMBOL("deflateInit_") + EXPORT SYMBOL("deflateInit2_") + EXPORT SYMBOL("gzopen") + EXPORT SYMBOL("gzdopen") + EXPORT SYMBOL("gzsetparams") + EXPORT SYMBOL("gzread") + EXPORT SYMBOL("gzwrite") + EXPORT SYMBOL("gzprintf") + EXPORT SYMBOL("gzputs") + EXPORT SYMBOL("gzgets") + EXPORT SYMBOL("gzputc") + EXPORT SYMBOL("gzgetc") + EXPORT SYMBOL("gzflush") + EXPORT SYMBOL("gzseek") + EXPORT SYMBOL("gzrewind") + EXPORT SYMBOL("gztell") + EXPORT SYMBOL("gzeof") + EXPORT SYMBOL("gzclose") + EXPORT SYMBOL("gzerror") + EXPORT SYMBOL("inflate") + EXPORT SYMBOL("inflateEnd") + EXPORT SYMBOL("inflateSetDictionary") + EXPORT SYMBOL("inflateSync") + EXPORT SYMBOL("inflateReset") + EXPORT SYMBOL("inflateInit_") + EXPORT SYMBOL("inflateInit2_") + EXPORT SYMBOL("inflateSyncPoint") + EXPORT SYMBOL("uncompress") + EXPORT SYMBOL("zlibVersion") + EXPORT SYMBOL("zError") + EXPORT SYMBOL("z_errmsg") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.1 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("compressBound") + EXPORT SYMBOL("deflateBound") + EXPORT SYMBOL("deflatePending") + EXPORT SYMBOL("gzungetc") + EXPORT SYMBOL("gzclearerr") + EXPORT SYMBOL("inflateBack") + EXPORT SYMBOL("inflateBackEnd") + EXPORT SYMBOL("inflateBackInit_") + EXPORT SYMBOL("inflateCopy") + EXPORT SYMBOL("zlibCompileFlags") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.4 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32_combine") + EXPORT SYMBOL("adler32_combine64") + EXPORT SYMBOL("crc32_combine") + EXPORT SYMBOL("crc32_combine64") + EXPORT SYMBOL("deflateSetHeader") + EXPORT SYMBOL("deflateTune") + EXPORT SYMBOL("gzbuffer") + EXPORT SYMBOL("gzclose_r") + EXPORT SYMBOL("gzclose_w") + EXPORT SYMBOL("gzdirect") + EXPORT SYMBOL("gzoffset") + EXPORT SYMBOL("gzoffset64") + EXPORT SYMBOL("gzopen64") + EXPORT SYMBOL("gzseek64") + EXPORT SYMBOL("gztell64") + EXPORT SYMBOL("inflateGetHeader") + EXPORT SYMBOL("inflateMark") + EXPORT SYMBOL("inflatePrime") + EXPORT SYMBOL("inflateReset2") + EXPORT SYMBOL("inflateUndermine") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.6 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("deflateResetKeep") + EXPORT SYMBOL("gzgetc_") + EXPORT SYMBOL("inflateResetKeep") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.8 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("gzvprintf") + EXPORT SYMBOL("inflateGetDictionary") + +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ +/* Version 1.2.9 additional entry points. */ +/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/ + + EXPORT SYMBOL("adler32_z") + EXPORT SYMBOL("crc32_z") + EXPORT SYMBOL("deflateGetDictionary") + EXPORT SYMBOL("gzfread") + EXPORT SYMBOL("gzfwrite") + EXPORT SYMBOL("inflateCodesUsed") + EXPORT SYMBOL("inflateValidate") + EXPORT SYMBOL("uncompress2") + +ENDPGMEXP diff --git a/libs/zlib/os400/make.sh b/libs/zlib/os400/make.sh new file mode 100644 index 000000000..19eec117a --- /dev/null +++ b/libs/zlib/os400/make.sh @@ -0,0 +1,366 @@ +#!/bin/sh +# +# ZLIB compilation script for the OS/400. +# +# +# This is a shell script since make is not a standard component of OS/400. + + +################################################################################ +# +# Tunable configuration parameters. +# +################################################################################ + +TARGETLIB='ZLIB' # Target OS/400 program library +STATBNDDIR='ZLIB_A' # Static binding directory. +DYNBNDDIR='ZLIB' # Dynamic binding directory. +SRVPGM="ZLIB" # Service program. +IFSDIR='/zlib' # IFS support base directory. +TGTCCSID='500' # Target CCSID of objects +DEBUG='*NONE' # Debug level +OPTIMIZE='40' # Optimisation level +OUTPUT='*NONE' # Compilation output option. +TGTRLS='V6R1M0' # Target OS release + +export TARGETLIB STATBNDDIR DYNBNDDIR SRVPGM IFSDIR +export TGTCCSID DEBUG OPTIMIZE OUTPUT TGTRLS + + +################################################################################ +# +# OS/400 specific definitions. +# +################################################################################ + +LIBIFSNAME="/QSYS.LIB/${TARGETLIB}.LIB" + + +################################################################################ +# +# Procedures. +# +################################################################################ + +# action_needed dest [src] +# +# dest is an object to build +# if specified, src is an object on which dest depends. +# +# exit 0 (succeeds) if some action has to be taken, else 1. + +action_needed() + +{ + [ ! -e "${1}" ] && return 0 + [ "${2}" ] || return 1 + [ "${1}" -ot "${2}" ] && return 0 + return 1 +} + + +# make_module module_name source_name [additional_definitions] +# +# Compile source name into module if needed. +# As side effect, append the module name to variable MODULES. +# Set LINK to "YES" if the module has been compiled. + +make_module() + +{ + MODULES="${MODULES} ${1}" + MODIFSNAME="${LIBIFSNAME}/${1}.MODULE" + CSRC="`basename \"${2}\"`" + + if action_needed "${MODIFSNAME}" "${2}" + then : + elif [ ! "`sed -e \"//,/<\\\\/source>/!d\" \ + -e '/ tmphdrfile + + # Need to translate to target CCSID. + + CMD="CPY OBJ('`pwd`/tmphdrfile') TOOBJ('${DEST}')" + CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" + system "${CMD}" + # touch -r "${HFILE}" "${DEST}" + rm -f tmphdrfile + fi + + IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" + + if action_needed "${IFSFILE}" "${DEST}" + then rm -f "${IFSFILE}" + ln -s "${DEST}" "${IFSFILE}" + fi +done + + +# Install the ILE/RPG header file. + + +HFILE="${SCRIPTDIR}/zlib.inc" +DEST="${SRCPF}/ZLIB.INC.MBR" + +if action_needed "${DEST}" "${HFILE}" +then CMD="CPY OBJ('${HFILE}') TOOBJ('${DEST}')" + CMD="${CMD} TOCCSID(${TGTCCSID}) DTAFMT(*TEXT) REPLACE(*YES)" + system "${CMD}" + # touch -r "${HFILE}" "${DEST}" +fi + +IFSFILE="${IFSDIR}/include/`basename \"${HFILE}\"`" + +if action_needed "${IFSFILE}" "${DEST}" +then rm -f "${IFSFILE}" + ln -s "${DEST}" "${IFSFILE}" +fi + + +# Create and compile the identification source file. + +echo '#pragma comment(user, "ZLIB version '"${VERSION}"'")' > os400.c +echo '#pragma comment(user, __DATE__)' >> os400.c +echo '#pragma comment(user, __TIME__)' >> os400.c +echo '#pragma comment(copyright, "Copyright (C) 1995-2017 Jean-Loup Gailly, Mark Adler. OS/400 version by P. Monnerat.")' >> os400.c +make_module OS400 os400.c +LINK= # No need to rebuild service program yet. +MODULES= + + +# Get source list. + +CSOURCES=`sed -e '/ Disabled - WIN32;_DEBUG;ASMV;ASMINF;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true Default MultiThreadedDebugDLL @@ -267,7 +267,7 @@ MaxSpeed OnlyExplicitInline - WIN32;NDEBUG;ASMV;ASMINF;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS;%(PreprocessorDefinitions) true MultiThreadedDLL true @@ -570,6 +570,8 @@ true true true + true + true true @@ -578,6 +580,8 @@ true true true + true + true true diff --git a/libs/zlib/qnx/package.qpg b/libs/zlib/qnx/package.qpg index 2bc63b21a..31e8e90db 100644 --- a/libs/zlib/qnx/package.qpg +++ b/libs/zlib/qnx/package.qpg @@ -25,10 +25,10 @@ - - - - + + + + @@ -63,7 +63,7 @@ - 1.2.5 + 1.2.11 Medium Stable diff --git a/libs/zlib/test/example.c b/libs/zlib/test/example.c new file mode 100644 index 000000000..eee17ce7c --- /dev/null +++ b/libs/zlib/test/example.c @@ -0,0 +1,602 @@ +/* example.c -- usage example of the zlib compression library + * Copyright (C) 1995-2006, 2011, 2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include + +#ifdef STDC +# include +# include +#endif + +#if defined(VMS) || defined(RISCOS) +# define TESTFILE "foo-gz" +#else +# define TESTFILE "foo.gz" +#endif + +#define CHECK_ERR(err, msg) { \ + if (err != Z_OK) { \ + fprintf(stderr, "%s error: %d\n", msg, err); \ + exit(1); \ + } \ +} + +static z_const char hello[] = "hello, hello!"; +/* "hello world" would be more standard, but the repeated "hello" + * stresses the compression code better, sorry... + */ + +static const char dictionary[] = "hello"; +static uLong dictId; /* Adler32 value of the dictionary */ + +void test_deflate OF((Byte *compr, uLong comprLen)); +void test_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_deflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_large_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_flush OF((Byte *compr, uLong *comprLen)); +void test_sync OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_dict_deflate OF((Byte *compr, uLong comprLen)); +void test_dict_inflate OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +int main OF((int argc, char *argv[])); + + +#ifdef Z_SOLO + +void *myalloc OF((void *, unsigned, unsigned)); +void myfree OF((void *, void *)); + +void *myalloc(q, n, m) + void *q; + unsigned n, m; +{ + (void)q; + return calloc(n, m); +} + +void myfree(void *q, void *p) +{ + (void)q; + free(p); +} + +static alloc_func zalloc = myalloc; +static free_func zfree = myfree; + +#else /* !Z_SOLO */ + +static alloc_func zalloc = (alloc_func)0; +static free_func zfree = (free_func)0; + +void test_compress OF((Byte *compr, uLong comprLen, + Byte *uncompr, uLong uncomprLen)); +void test_gzio OF((const char *fname, + Byte *uncompr, uLong uncomprLen)); + +/* =========================================================================== + * Test compress() and uncompress() + */ +void test_compress(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + uLong len = (uLong)strlen(hello)+1; + + err = compress(compr, &comprLen, (const Bytef*)hello, len); + CHECK_ERR(err, "compress"); + + strcpy((char*)uncompr, "garbage"); + + err = uncompress(uncompr, &uncomprLen, compr, comprLen); + CHECK_ERR(err, "uncompress"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad uncompress\n"); + exit(1); + } else { + printf("uncompress(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test read/write of .gz files + */ +void test_gzio(fname, uncompr, uncomprLen) + const char *fname; /* compressed file name */ + Byte *uncompr; + uLong uncomprLen; +{ +#ifdef NO_GZCOMPRESS + fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n"); +#else + int err; + int len = (int)strlen(hello)+1; + gzFile file; + z_off_t pos; + + file = gzopen(fname, "wb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + gzputc(file, 'h'); + if (gzputs(file, "ello") != 4) { + fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err)); + exit(1); + } + if (gzprintf(file, ", %s!", "hello") != 8) { + fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err)); + exit(1); + } + gzseek(file, 1L, SEEK_CUR); /* add one zero byte */ + gzclose(file); + + file = gzopen(fname, "rb"); + if (file == NULL) { + fprintf(stderr, "gzopen error\n"); + exit(1); + } + strcpy((char*)uncompr, "garbage"); + + if (gzread(file, uncompr, (unsigned)uncomprLen) != len) { + fprintf(stderr, "gzread err: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad gzread: %s\n", (char*)uncompr); + exit(1); + } else { + printf("gzread(): %s\n", (char*)uncompr); + } + + pos = gzseek(file, -8L, SEEK_CUR); + if (pos != 6 || gztell(file) != pos) { + fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n", + (long)pos, (long)gztell(file)); + exit(1); + } + + if (gzgetc(file) != ' ') { + fprintf(stderr, "gzgetc error\n"); + exit(1); + } + + if (gzungetc(' ', file) != ' ') { + fprintf(stderr, "gzungetc error\n"); + exit(1); + } + + gzgets(file, (char*)uncompr, (int)uncomprLen); + if (strlen((char*)uncompr) != 7) { /* " hello!" */ + fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err)); + exit(1); + } + if (strcmp((char*)uncompr, hello + 6)) { + fprintf(stderr, "bad gzgets after gzseek\n"); + exit(1); + } else { + printf("gzgets() after gzseek: %s\n", (char*)uncompr); + } + + gzclose(file); +#endif +} + +#endif /* Z_SOLO */ + +/* =========================================================================== + * Test deflate() with small buffers + */ +void test_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uLong len = (uLong)strlen(hello)+1; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + + while (c_stream.total_in != len && c_stream.total_out < comprLen) { + c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */ + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + } + /* Finish the stream, still forcing small buffers: */ + for (;;) { + c_stream.avail_out = 1; + err = deflate(&c_stream, Z_FINISH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "deflate"); + } + + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with small buffers + */ +void test_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 0; + d_stream.next_out = uncompr; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) { + d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */ + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate\n"); + exit(1); + } else { + printf("inflate(): %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Test deflate() with large buffers and dynamic change of compression level + */ +void test_large_deflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_SPEED); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + /* At this point, uncompr is still mostly zeroes, so it should compress + * very well: + */ + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + if (c_stream.avail_in != 0) { + fprintf(stderr, "deflate not greedy\n"); + exit(1); + } + + /* Feed in already compressed data and switch to no compression: */ + deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY); + c_stream.next_in = compr; + c_stream.avail_in = (uInt)comprLen/2; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + /* Switch back to compressing mode: */ + deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED); + c_stream.next_in = uncompr; + c_stream.avail_in = (uInt)uncomprLen; + err = deflate(&c_stream, Z_NO_FLUSH); + CHECK_ERR(err, "deflate"); + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with large buffers + */ +void test_large_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + for (;;) { + d_stream.next_out = uncompr; /* discard the output */ + d_stream.avail_out = (uInt)uncomprLen; + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + CHECK_ERR(err, "large inflate"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (d_stream.total_out != 2*uncomprLen + comprLen/2) { + fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out); + exit(1); + } else { + printf("large_inflate(): OK\n"); + } +} + +/* =========================================================================== + * Test deflate() with full flush + */ +void test_flush(compr, comprLen) + Byte *compr; + uLong *comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + uInt len = (uInt)strlen(hello)+1; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.next_out = compr; + c_stream.avail_in = 3; + c_stream.avail_out = (uInt)*comprLen; + err = deflate(&c_stream, Z_FULL_FLUSH); + CHECK_ERR(err, "deflate"); + + compr[3]++; /* force an error in first compressed block */ + c_stream.avail_in = len - 3; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + CHECK_ERR(err, "deflate"); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); + + *comprLen = c_stream.total_out; +} + +/* =========================================================================== + * Test inflateSync() + */ +void test_sync(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = 2; /* just read the zlib header */ + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + err = inflate(&d_stream, Z_NO_FLUSH); + CHECK_ERR(err, "inflate"); + + d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ + err = inflateSync(&d_stream); /* but skip the damaged part */ + CHECK_ERR(err, "inflateSync"); + + err = inflate(&d_stream, Z_FINISH); + if (err != Z_DATA_ERROR) { + fprintf(stderr, "inflate should report DATA_ERROR\n"); + /* Because of incorrect adler32 */ + exit(1); + } + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + printf("after inflateSync(): hel%s\n", (char *)uncompr); +} + +/* =========================================================================== + * Test deflate() with preset dictionary + */ +void test_dict_deflate(compr, comprLen) + Byte *compr; + uLong comprLen; +{ + z_stream c_stream; /* compression stream */ + int err; + + c_stream.zalloc = zalloc; + c_stream.zfree = zfree; + c_stream.opaque = (voidpf)0; + + err = deflateInit(&c_stream, Z_BEST_COMPRESSION); + CHECK_ERR(err, "deflateInit"); + + err = deflateSetDictionary(&c_stream, + (const Bytef*)dictionary, (int)sizeof(dictionary)); + CHECK_ERR(err, "deflateSetDictionary"); + + dictId = c_stream.adler; + c_stream.next_out = compr; + c_stream.avail_out = (uInt)comprLen; + + c_stream.next_in = (z_const unsigned char *)hello; + c_stream.avail_in = (uInt)strlen(hello)+1; + + err = deflate(&c_stream, Z_FINISH); + if (err != Z_STREAM_END) { + fprintf(stderr, "deflate should report Z_STREAM_END\n"); + exit(1); + } + err = deflateEnd(&c_stream); + CHECK_ERR(err, "deflateEnd"); +} + +/* =========================================================================== + * Test inflate() with a preset dictionary + */ +void test_dict_inflate(compr, comprLen, uncompr, uncomprLen) + Byte *compr, *uncompr; + uLong comprLen, uncomprLen; +{ + int err; + z_stream d_stream; /* decompression stream */ + + strcpy((char*)uncompr, "garbage"); + + d_stream.zalloc = zalloc; + d_stream.zfree = zfree; + d_stream.opaque = (voidpf)0; + + d_stream.next_in = compr; + d_stream.avail_in = (uInt)comprLen; + + err = inflateInit(&d_stream); + CHECK_ERR(err, "inflateInit"); + + d_stream.next_out = uncompr; + d_stream.avail_out = (uInt)uncomprLen; + + for (;;) { + err = inflate(&d_stream, Z_NO_FLUSH); + if (err == Z_STREAM_END) break; + if (err == Z_NEED_DICT) { + if (d_stream.adler != dictId) { + fprintf(stderr, "unexpected dictionary"); + exit(1); + } + err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, + (int)sizeof(dictionary)); + } + CHECK_ERR(err, "inflate with dict"); + } + + err = inflateEnd(&d_stream); + CHECK_ERR(err, "inflateEnd"); + + if (strcmp((char*)uncompr, hello)) { + fprintf(stderr, "bad inflate with dict\n"); + exit(1); + } else { + printf("inflate with dictionary: %s\n", (char *)uncompr); + } +} + +/* =========================================================================== + * Usage: example [output.gz [input.gz]] + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + Byte *compr, *uncompr; + uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */ + uLong uncomprLen = comprLen; + static const char* myVersion = ZLIB_VERSION; + + if (zlibVersion()[0] != myVersion[0]) { + fprintf(stderr, "incompatible zlib version\n"); + exit(1); + + } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { + fprintf(stderr, "warning: different zlib version\n"); + } + + printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", + ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); + + compr = (Byte*)calloc((uInt)comprLen, 1); + uncompr = (Byte*)calloc((uInt)uncomprLen, 1); + /* compr and uncompr are cleared to avoid reading uninitialized + * data and to ensure that uncompr compresses well. + */ + if (compr == Z_NULL || uncompr == Z_NULL) { + printf("out of memory\n"); + exit(1); + } + +#ifdef Z_SOLO + (void)argc; + (void)argv; +#else + test_compress(compr, comprLen, uncompr, uncomprLen); + + test_gzio((argc > 1 ? argv[1] : TESTFILE), + uncompr, uncomprLen); +#endif + + test_deflate(compr, comprLen); + test_inflate(compr, comprLen, uncompr, uncomprLen); + + test_large_deflate(compr, comprLen, uncompr, uncomprLen); + test_large_inflate(compr, comprLen, uncompr, uncomprLen); + + test_flush(compr, &comprLen); + test_sync(compr, comprLen, uncompr, uncomprLen); + comprLen = uncomprLen; + + test_dict_deflate(compr, comprLen); + test_dict_inflate(compr, comprLen, uncompr, uncomprLen); + + free(compr); + free(uncompr); + + return 0; +} diff --git a/libs/zlib/test/infcover.c b/libs/zlib/test/infcover.c new file mode 100644 index 000000000..2be01646c --- /dev/null +++ b/libs/zlib/test/infcover.c @@ -0,0 +1,671 @@ +/* infcover.c -- test zlib's inflate routines with full code coverage + * Copyright (C) 2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* to use, do: ./configure --cover && make cover */ + +#include +#include +#include +#include +#include "zlib.h" + +/* get definition of internal structure so we can mess with it (see pull()), + and so we can call inflate_trees() (see cover5()) */ +#define ZLIB_INTERNAL +#include "inftrees.h" +#include "inflate.h" + +#define local static + +/* -- memory tracking routines -- */ + +/* + These memory tracking routines are provided to zlib and track all of zlib's + allocations and deallocations, check for LIFO operations, keep a current + and high water mark of total bytes requested, optionally set a limit on the + total memory that can be allocated, and when done check for memory leaks. + + They are used as follows: + + z_stream strm; + mem_setup(&strm) initializes the memory tracking and sets the + zalloc, zfree, and opaque members of strm to use + memory tracking for all zlib operations on strm + mem_limit(&strm, limit) sets a limit on the total bytes requested -- a + request that exceeds this limit will result in an + allocation failure (returns NULL) -- setting the + limit to zero means no limit, which is the default + after mem_setup() + mem_used(&strm, "msg") prints to stderr "msg" and the total bytes used + mem_high(&strm, "msg") prints to stderr "msg" and the high water mark + mem_done(&strm, "msg") ends memory tracking, releases all allocations + for the tracking as well as leaked zlib blocks, if + any. If there was anything unusual, such as leaked + blocks, non-FIFO frees, or frees of addresses not + allocated, then "msg" and information about the + problem is printed to stderr. If everything is + normal, nothing is printed. mem_done resets the + strm members to Z_NULL to use the default memory + allocation routines on the next zlib initialization + using strm. + */ + +/* these items are strung together in a linked list, one for each allocation */ +struct mem_item { + void *ptr; /* pointer to allocated memory */ + size_t size; /* requested size of allocation */ + struct mem_item *next; /* pointer to next item in list, or NULL */ +}; + +/* this structure is at the root of the linked list, and tracks statistics */ +struct mem_zone { + struct mem_item *first; /* pointer to first item in list, or NULL */ + size_t total, highwater; /* total allocations, and largest total */ + size_t limit; /* memory allocation limit, or 0 if no limit */ + int notlifo, rogue; /* counts of non-LIFO frees and rogue frees */ +}; + +/* memory allocation routine to pass to zlib */ +local void *mem_alloc(void *mem, unsigned count, unsigned size) +{ + void *ptr; + struct mem_item *item; + struct mem_zone *zone = mem; + size_t len = count * (size_t)size; + + /* induced allocation failure */ + if (zone == NULL || (zone->limit && zone->total + len > zone->limit)) + return NULL; + + /* perform allocation using the standard library, fill memory with a + non-zero value to make sure that the code isn't depending on zeros */ + ptr = malloc(len); + if (ptr == NULL) + return NULL; + memset(ptr, 0xa5, len); + + /* create a new item for the list */ + item = malloc(sizeof(struct mem_item)); + if (item == NULL) { + free(ptr); + return NULL; + } + item->ptr = ptr; + item->size = len; + + /* insert item at the beginning of the list */ + item->next = zone->first; + zone->first = item; + + /* update the statistics */ + zone->total += item->size; + if (zone->total > zone->highwater) + zone->highwater = zone->total; + + /* return the allocated memory */ + return ptr; +} + +/* memory free routine to pass to zlib */ +local void mem_free(void *mem, void *ptr) +{ + struct mem_item *item, *next; + struct mem_zone *zone = mem; + + /* if no zone, just do a free */ + if (zone == NULL) { + free(ptr); + return; + } + + /* point next to the item that matches ptr, or NULL if not found -- remove + the item from the linked list if found */ + next = zone->first; + if (next) { + if (next->ptr == ptr) + zone->first = next->next; /* first one is it, remove from list */ + else { + do { /* search the linked list */ + item = next; + next = item->next; + } while (next != NULL && next->ptr != ptr); + if (next) { /* if found, remove from linked list */ + item->next = next->next; + zone->notlifo++; /* not a LIFO free */ + } + + } + } + + /* if found, update the statistics and free the item */ + if (next) { + zone->total -= next->size; + free(next); + } + + /* if not found, update the rogue count */ + else + zone->rogue++; + + /* in any case, do the requested free with the standard library function */ + free(ptr); +} + +/* set up a controlled memory allocation space for monitoring, set the stream + parameters to the controlled routines, with opaque pointing to the space */ +local void mem_setup(z_stream *strm) +{ + struct mem_zone *zone; + + zone = malloc(sizeof(struct mem_zone)); + assert(zone != NULL); + zone->first = NULL; + zone->total = 0; + zone->highwater = 0; + zone->limit = 0; + zone->notlifo = 0; + zone->rogue = 0; + strm->opaque = zone; + strm->zalloc = mem_alloc; + strm->zfree = mem_free; +} + +/* set a limit on the total memory allocation, or 0 to remove the limit */ +local void mem_limit(z_stream *strm, size_t limit) +{ + struct mem_zone *zone = strm->opaque; + + zone->limit = limit; +} + +/* show the current total requested allocations in bytes */ +local void mem_used(z_stream *strm, char *prefix) +{ + struct mem_zone *zone = strm->opaque; + + fprintf(stderr, "%s: %lu allocated\n", prefix, zone->total); +} + +/* show the high water allocation in bytes */ +local void mem_high(z_stream *strm, char *prefix) +{ + struct mem_zone *zone = strm->opaque; + + fprintf(stderr, "%s: %lu high water mark\n", prefix, zone->highwater); +} + +/* release the memory allocation zone -- if there are any surprises, notify */ +local void mem_done(z_stream *strm, char *prefix) +{ + int count = 0; + struct mem_item *item, *next; + struct mem_zone *zone = strm->opaque; + + /* show high water mark */ + mem_high(strm, prefix); + + /* free leftover allocations and item structures, if any */ + item = zone->first; + while (item != NULL) { + free(item->ptr); + next = item->next; + free(item); + item = next; + count++; + } + + /* issue alerts about anything unexpected */ + if (count || zone->total) + fprintf(stderr, "** %s: %lu bytes in %d blocks not freed\n", + prefix, zone->total, count); + if (zone->notlifo) + fprintf(stderr, "** %s: %d frees not LIFO\n", prefix, zone->notlifo); + if (zone->rogue) + fprintf(stderr, "** %s: %d frees not recognized\n", + prefix, zone->rogue); + + /* free the zone and delete from the stream */ + free(zone); + strm->opaque = Z_NULL; + strm->zalloc = Z_NULL; + strm->zfree = Z_NULL; +} + +/* -- inflate test routines -- */ + +/* Decode a hexadecimal string, set *len to length, in[] to the bytes. This + decodes liberally, in that hex digits can be adjacent, in which case two in + a row writes a byte. Or they can be delimited by any non-hex character, + where the delimiters are ignored except when a single hex digit is followed + by a delimiter, where that single digit writes a byte. The returned data is + allocated and must eventually be freed. NULL is returned if out of memory. + If the length is not needed, then len can be NULL. */ +local unsigned char *h2b(const char *hex, unsigned *len) +{ + unsigned char *in, *re; + unsigned next, val; + + in = malloc((strlen(hex) + 1) >> 1); + if (in == NULL) + return NULL; + next = 0; + val = 1; + do { + if (*hex >= '0' && *hex <= '9') + val = (val << 4) + *hex - '0'; + else if (*hex >= 'A' && *hex <= 'F') + val = (val << 4) + *hex - 'A' + 10; + else if (*hex >= 'a' && *hex <= 'f') + val = (val << 4) + *hex - 'a' + 10; + else if (val != 1 && val < 32) /* one digit followed by delimiter */ + val += 240; /* make it look like two digits */ + if (val > 255) { /* have two digits */ + in[next++] = val & 0xff; /* save the decoded byte */ + val = 1; /* start over */ + } + } while (*hex++); /* go through the loop with the terminating null */ + if (len != NULL) + *len = next; + re = realloc(in, next); + return re == NULL ? in : re; +} + +/* generic inflate() run, where hex is the hexadecimal input data, what is the + text to include in an error message, step is how much input data to feed + inflate() on each call, or zero to feed it all, win is the window bits + parameter to inflateInit2(), len is the size of the output buffer, and err + is the error code expected from the first inflate() call (the second + inflate() call is expected to return Z_STREAM_END). If win is 47, then + header information is collected with inflateGetHeader(). If a zlib stream + is looking for a dictionary, then an empty dictionary is provided. + inflate() is run until all of the input data is consumed. */ +local void inf(char *hex, char *what, unsigned step, int win, unsigned len, + int err) +{ + int ret; + unsigned have; + unsigned char *in, *out; + z_stream strm, copy; + gz_header head; + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, win); + if (ret != Z_OK) { + mem_done(&strm, what); + return; + } + out = malloc(len); assert(out != NULL); + if (win == 47) { + head.extra = out; + head.extra_max = len; + head.name = out; + head.name_max = len; + head.comment = out; + head.comm_max = len; + ret = inflateGetHeader(&strm, &head); assert(ret == Z_OK); + } + in = h2b(hex, &have); assert(in != NULL); + if (step == 0 || step > have) + step = have; + strm.avail_in = step; + have -= step; + strm.next_in = in; + do { + strm.avail_out = len; + strm.next_out = out; + ret = inflate(&strm, Z_NO_FLUSH); assert(err == 9 || ret == err); + if (ret != Z_OK && ret != Z_BUF_ERROR && ret != Z_NEED_DICT) + break; + if (ret == Z_NEED_DICT) { + ret = inflateSetDictionary(&strm, in, 1); + assert(ret == Z_DATA_ERROR); + mem_limit(&strm, 1); + ret = inflateSetDictionary(&strm, out, 0); + assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + ((struct inflate_state *)strm.state)->mode = DICT; + ret = inflateSetDictionary(&strm, out, 0); + assert(ret == Z_OK); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_BUF_ERROR); + } + ret = inflateCopy(©, &strm); assert(ret == Z_OK); + ret = inflateEnd(©); assert(ret == Z_OK); + err = 9; /* don't care next time around */ + have += strm.avail_in; + strm.avail_in = step > have ? have : step; + have -= strm.avail_in; + } while (strm.avail_in); + free(in); + free(out); + ret = inflateReset2(&strm, -8); assert(ret == Z_OK); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, what); +} + +/* cover all of the lines in inflate.c up to inflate() */ +local void cover_support(void) +{ + int ret; + z_stream strm; + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); assert(ret == Z_OK); + mem_used(&strm, "inflate init"); + ret = inflatePrime(&strm, 5, 31); assert(ret == Z_OK); + ret = inflatePrime(&strm, -1, 0); assert(ret == Z_OK); + ret = inflateSetDictionary(&strm, Z_NULL, 0); + assert(ret == Z_STREAM_ERROR); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "prime"); + + inf("63 0", "force window allocation", 0, -15, 1, Z_OK); + inf("63 18 5", "force window replacement", 0, -8, 259, Z_OK); + inf("63 18 68 30 d0 0 0", "force split window update", 4, -8, 259, Z_OK); + inf("3 0", "use fixed blocks", 0, -15, 1, Z_STREAM_END); + inf("", "bad window size", 0, 1, 0, Z_STREAM_ERROR); + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit_(&strm, ZLIB_VERSION - 1, (int)sizeof(z_stream)); + assert(ret == Z_VERSION_ERROR); + mem_done(&strm, "wrong version"); + + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit(&strm); assert(ret == Z_OK); + ret = inflateEnd(&strm); assert(ret == Z_OK); + fputs("inflate built-in memory routines\n", stderr); +} + +/* cover all inflate() header and trailer cases and code after inflate() */ +local void cover_wrap(void) +{ + int ret; + z_stream strm, copy; + unsigned char dict[257]; + + ret = inflate(Z_NULL, 0); assert(ret == Z_STREAM_ERROR); + ret = inflateEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); + ret = inflateCopy(Z_NULL, Z_NULL); assert(ret == Z_STREAM_ERROR); + fputs("inflate bad parameters\n", stderr); + + inf("1f 8b 0 0", "bad gzip method", 0, 31, 0, Z_DATA_ERROR); + inf("1f 8b 8 80", "bad gzip flags", 0, 31, 0, Z_DATA_ERROR); + inf("77 85", "bad zlib method", 0, 15, 0, Z_DATA_ERROR); + inf("8 99", "set window size from header", 0, 0, 0, Z_OK); + inf("78 9c", "bad zlib window size", 0, 8, 0, Z_DATA_ERROR); + inf("78 9c 63 0 0 0 1 0 1", "check adler32", 0, 15, 1, Z_STREAM_END); + inf("1f 8b 8 1e 0 0 0 0 0 0 1 0 0 0 0 0 0", "bad header crc", 0, 47, 1, + Z_DATA_ERROR); + inf("1f 8b 8 2 0 0 0 0 0 0 1d 26 3 0 0 0 0 0 0 0 0 0", "check gzip length", + 0, 47, 0, Z_STREAM_END); + inf("78 90", "bad zlib header check", 0, 47, 0, Z_DATA_ERROR); + inf("8 b8 0 0 0 1", "need dictionary", 0, 8, 0, Z_NEED_DICT); + inf("78 9c 63 0", "compute adler32", 0, 15, 1, Z_OK); + + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, -8); + strm.avail_in = 2; + strm.next_in = (void *)"\x63"; + strm.avail_out = 1; + strm.next_out = (void *)&ret; + mem_limit(&strm, 1); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + memset(dict, 0, 257); + ret = inflateSetDictionary(&strm, dict, 257); + assert(ret == Z_OK); + mem_limit(&strm, (sizeof(struct inflate_state) << 1) + 256); + ret = inflatePrime(&strm, 16, 0); assert(ret == Z_OK); + strm.avail_in = 2; + strm.next_in = (void *)"\x80"; + ret = inflateSync(&strm); assert(ret == Z_DATA_ERROR); + ret = inflate(&strm, Z_NO_FLUSH); assert(ret == Z_STREAM_ERROR); + strm.avail_in = 4; + strm.next_in = (void *)"\0\0\xff\xff"; + ret = inflateSync(&strm); assert(ret == Z_OK); + (void)inflateSyncPoint(&strm); + ret = inflateCopy(©, &strm); assert(ret == Z_MEM_ERROR); + mem_limit(&strm, 0); + ret = inflateUndermine(&strm, 1); assert(ret == Z_DATA_ERROR); + (void)inflateMark(&strm); + ret = inflateEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "miscellaneous, force memory errors"); +} + +/* input and output functions for inflateBack() */ +local unsigned pull(void *desc, unsigned char **buf) +{ + static unsigned int next = 0; + static unsigned char dat[] = {0x63, 0, 2, 0}; + struct inflate_state *state; + + if (desc == Z_NULL) { + next = 0; + return 0; /* no input (already provided at next_in) */ + } + state = (void *)((z_stream *)desc)->state; + if (state != Z_NULL) + state->mode = SYNC; /* force an otherwise impossible situation */ + return next < sizeof(dat) ? (*buf = dat + next++, 1) : 0; +} + +local int push(void *desc, unsigned char *buf, unsigned len) +{ + buf += len; + return desc != Z_NULL; /* force error if desc not null */ +} + +/* cover inflateBack() up to common deflate data cases and after those */ +local void cover_back(void) +{ + int ret; + z_stream strm; + unsigned char win[32768]; + + ret = inflateBackInit_(Z_NULL, 0, win, 0, 0); + assert(ret == Z_VERSION_ERROR); + ret = inflateBackInit(Z_NULL, 0, win); assert(ret == Z_STREAM_ERROR); + ret = inflateBack(Z_NULL, Z_NULL, Z_NULL, Z_NULL, Z_NULL); + assert(ret == Z_STREAM_ERROR); + ret = inflateBackEnd(Z_NULL); assert(ret == Z_STREAM_ERROR); + fputs("inflateBack bad parameters\n", stderr); + + mem_setup(&strm); + ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); + strm.avail_in = 2; + strm.next_in = (void *)"\x03"; + ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); + assert(ret == Z_STREAM_END); + /* force output error */ + strm.avail_in = 3; + strm.next_in = (void *)"\x63\x00"; + ret = inflateBack(&strm, pull, Z_NULL, push, &strm); + assert(ret == Z_BUF_ERROR); + /* force mode error by mucking with state */ + ret = inflateBack(&strm, pull, &strm, push, Z_NULL); + assert(ret == Z_STREAM_ERROR); + ret = inflateBackEnd(&strm); assert(ret == Z_OK); + mem_done(&strm, "inflateBack bad state"); + + ret = inflateBackInit(&strm, 15, win); assert(ret == Z_OK); + ret = inflateBackEnd(&strm); assert(ret == Z_OK); + fputs("inflateBack built-in memory routines\n", stderr); +} + +/* do a raw inflate of data in hexadecimal with both inflate and inflateBack */ +local int try(char *hex, char *id, int err) +{ + int ret; + unsigned len, size; + unsigned char *in, *out, *win; + char *prefix; + z_stream strm; + + /* convert to hex */ + in = h2b(hex, &len); + assert(in != NULL); + + /* allocate work areas */ + size = len << 3; + out = malloc(size); + assert(out != NULL); + win = malloc(32768); + assert(win != NULL); + prefix = malloc(strlen(id) + 6); + assert(prefix != NULL); + + /* first with inflate */ + strcpy(prefix, id); + strcat(prefix, "-late"); + mem_setup(&strm); + strm.avail_in = 0; + strm.next_in = Z_NULL; + ret = inflateInit2(&strm, err < 0 ? 47 : -15); + assert(ret == Z_OK); + strm.avail_in = len; + strm.next_in = in; + do { + strm.avail_out = size; + strm.next_out = out; + ret = inflate(&strm, Z_TREES); + assert(ret != Z_STREAM_ERROR && ret != Z_MEM_ERROR); + if (ret == Z_DATA_ERROR || ret == Z_NEED_DICT) + break; + } while (strm.avail_in || strm.avail_out == 0); + if (err) { + assert(ret == Z_DATA_ERROR); + assert(strcmp(id, strm.msg) == 0); + } + inflateEnd(&strm); + mem_done(&strm, prefix); + + /* then with inflateBack */ + if (err >= 0) { + strcpy(prefix, id); + strcat(prefix, "-back"); + mem_setup(&strm); + ret = inflateBackInit(&strm, 15, win); + assert(ret == Z_OK); + strm.avail_in = len; + strm.next_in = in; + ret = inflateBack(&strm, pull, Z_NULL, push, Z_NULL); + assert(ret != Z_STREAM_ERROR); + if (err) { + assert(ret == Z_DATA_ERROR); + assert(strcmp(id, strm.msg) == 0); + } + inflateBackEnd(&strm); + mem_done(&strm, prefix); + } + + /* clean up */ + free(prefix); + free(win); + free(out); + free(in); + return ret; +} + +/* cover deflate data cases in both inflate() and inflateBack() */ +local void cover_inflate(void) +{ + try("0 0 0 0 0", "invalid stored block lengths", 1); + try("3 0", "fixed", 0); + try("6", "invalid block type", 1); + try("1 1 0 fe ff 0", "stored", 0); + try("fc 0 0", "too many length or distance symbols", 1); + try("4 0 fe ff", "invalid code lengths set", 1); + try("4 0 24 49 0", "invalid bit length repeat", 1); + try("4 0 24 e9 ff ff", "invalid bit length repeat", 1); + try("4 0 24 e9 ff 6d", "invalid code -- missing end-of-block", 1); + try("4 80 49 92 24 49 92 24 71 ff ff 93 11 0", + "invalid literal/lengths set", 1); + try("4 80 49 92 24 49 92 24 f b4 ff ff c3 84", "invalid distances set", 1); + try("4 c0 81 8 0 0 0 0 20 7f eb b 0 0", "invalid literal/length code", 1); + try("2 7e ff ff", "invalid distance code", 1); + try("c c0 81 0 0 0 0 0 90 ff 6b 4 0", "invalid distance too far back", 1); + + /* also trailer mismatch just in inflate() */ + try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1", "incorrect data check", -1); + try("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1", + "incorrect length check", -1); + try("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c", "pull 17", 0); + try("5 e0 81 91 24 cb b2 2c 49 e2 f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f", + "long code", 0); + try("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f", "length extra", 0); + try("ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c", + "long distance and extra", 0); + try("ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 " + "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 6", "window end", 0); + inf("2 8 20 80 0 3 0", "inflate_fast TYPE return", 0, -15, 258, + Z_STREAM_END); + inf("63 18 5 40 c 0", "window wrap", 3, -8, 300, Z_OK); +} + +/* cover remaining lines in inftrees.c */ +local void cover_trees(void) +{ + int ret; + unsigned bits; + unsigned short lens[16], work[16]; + code *next, table[ENOUGH_DISTS]; + + /* we need to call inflate_table() directly in order to manifest not- + enough errors, since zlib insures that enough is always enough */ + for (bits = 0; bits < 15; bits++) + lens[bits] = (unsigned short)(bits + 1); + lens[15] = 15; + next = table; + bits = 15; + ret = inflate_table(DISTS, lens, 16, &next, &bits, work); + assert(ret == 1); + next = table; + bits = 1; + ret = inflate_table(DISTS, lens, 16, &next, &bits, work); + assert(ret == 1); + fputs("inflate_table not enough errors\n", stderr); +} + +/* cover remaining inffast.c decoding and window copying */ +local void cover_fast(void) +{ + inf("e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68" + " ff 7f 0f 0 0 0", "fast length extra bits", 0, -8, 258, Z_DATA_ERROR); + inf("25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49" + " 50 fe ff ff 3f 0 0", "fast distance extra bits", 0, -8, 258, + Z_DATA_ERROR); + inf("3 7e 0 0 0 0 0", "fast invalid distance code", 0, -8, 258, + Z_DATA_ERROR); + inf("1b 7 0 0 0 0 0", "fast invalid literal/length code", 0, -8, 258, + Z_DATA_ERROR); + inf("d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0", + "fast 2nd level codes and too far back", 0, -8, 258, Z_DATA_ERROR); + inf("63 18 5 8c 10 8 0 0 0 0", "very common case", 0, -8, 259, Z_OK); + inf("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0", + "contiguous and wrap around window", 6, -8, 259, Z_OK); + inf("63 0 3 0 0 0 0 0", "copy direct from output", 0, -8, 259, + Z_STREAM_END); +} + +int main(void) +{ + fprintf(stderr, "%s\n", zlibVersion()); + cover_support(); + cover_wrap(); + cover_back(); + cover_inflate(); + cover_trees(); + cover_fast(); + return 0; +} diff --git a/libs/zlib/test/minigzip.c b/libs/zlib/test/minigzip.c new file mode 100644 index 000000000..e22fb08c0 --- /dev/null +++ b/libs/zlib/test/minigzip.c @@ -0,0 +1,651 @@ +/* minigzip.c -- simulate gzip using the zlib compression library + * Copyright (C) 1995-2006, 2010, 2011, 2016 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * minigzip is a minimal implementation of the gzip utility. This is + * only an example of using zlib and isn't meant to replace the + * full-featured gzip. No attempt is made to deal with file systems + * limiting names to 14 or 8+3 characters, etc... Error checking is + * very limited. So use minigzip only for testing; use gzip for the + * real thing. On MSDOS, use only on file names without extension + * or in pipe mode. + */ + +/* @(#) $Id$ */ + +#include "zlib.h" +#include + +#ifdef STDC +# include +# include +#endif + +#ifdef USE_MMAP +# include +# include +# include +#endif + +#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) +# include +# include +# ifdef UNDER_CE +# include +# endif +# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) +#else +# define SET_BINARY_MODE(file) +#endif + +#if defined(_MSC_VER) && _MSC_VER < 1900 +# define snprintf _snprintf +#endif + +#ifdef VMS +# define unlink delete +# define GZ_SUFFIX "-gz" +#endif +#ifdef RISCOS +# define unlink remove +# define GZ_SUFFIX "-gz" +# define fileno(file) file->__file +#endif +#if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fileno */ +#endif + +#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) +#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ + extern int unlink OF((const char *)); +#endif +#endif + +#if defined(UNDER_CE) +# include +# define perror(s) pwinerror(s) + +/* Map the Windows error number in ERROR to a locale-dependent error + message string and return a pointer to it. Typically, the values + for ERROR come from GetLastError. + + The string pointed to shall not be modified by the application, + but may be overwritten by a subsequent call to strwinerror + + The strwinerror function does not change the current setting + of GetLastError. */ + +static char *strwinerror (error) + DWORD error; +{ + static char buf[1024]; + + wchar_t *msgbuf; + DWORD lasterr = GetLastError(); + DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_ALLOCATE_BUFFER, + NULL, + error, + 0, /* Default language */ + (LPVOID)&msgbuf, + 0, + NULL); + if (chars != 0) { + /* If there is an \r\n appended, zap it. */ + if (chars >= 2 + && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { + chars -= 2; + msgbuf[chars] = 0; + } + + if (chars > sizeof (buf) - 1) { + chars = sizeof (buf) - 1; + msgbuf[chars] = 0; + } + + wcstombs(buf, msgbuf, chars + 1); + LocalFree(msgbuf); + } + else { + sprintf(buf, "unknown win32 error (%ld)", error); + } + + SetLastError(lasterr); + return buf; +} + +static void pwinerror (s) + const char *s; +{ + if (s && *s) + fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); + else + fprintf(stderr, "%s\n", strwinerror(GetLastError ())); +} + +#endif /* UNDER_CE */ + +#ifndef GZ_SUFFIX +# define GZ_SUFFIX ".gz" +#endif +#define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) + +#define BUFLEN 16384 +#define MAX_NAME_LEN 1024 + +#ifdef MAXSEG_64K +# define local static + /* Needed for systems with limitation on stack size. */ +#else +# define local +#endif + +#ifdef Z_SOLO +/* for Z_SOLO, create simplified gz* functions using deflate and inflate */ + +#if defined(Z_HAVE_UNISTD_H) || defined(Z_LARGE) +# include /* for unlink() */ +#endif + +void *myalloc OF((void *, unsigned, unsigned)); +void myfree OF((void *, void *)); + +void *myalloc(q, n, m) + void *q; + unsigned n, m; +{ + (void)q; + return calloc(n, m); +} + +void myfree(q, p) + void *q, *p; +{ + (void)q; + free(p); +} + +typedef struct gzFile_s { + FILE *file; + int write; + int err; + char *msg; + z_stream strm; +} *gzFile; + +gzFile gzopen OF((const char *, const char *)); +gzFile gzdopen OF((int, const char *)); +gzFile gz_open OF((const char *, int, const char *)); + +gzFile gzopen(path, mode) +const char *path; +const char *mode; +{ + return gz_open(path, -1, mode); +} + +gzFile gzdopen(fd, mode) +int fd; +const char *mode; +{ + return gz_open(NULL, fd, mode); +} + +gzFile gz_open(path, fd, mode) + const char *path; + int fd; + const char *mode; +{ + gzFile gz; + int ret; + + gz = malloc(sizeof(struct gzFile_s)); + if (gz == NULL) + return NULL; + gz->write = strchr(mode, 'w') != NULL; + gz->strm.zalloc = myalloc; + gz->strm.zfree = myfree; + gz->strm.opaque = Z_NULL; + if (gz->write) + ret = deflateInit2(&(gz->strm), -1, 8, 15 + 16, 8, 0); + else { + gz->strm.next_in = 0; + gz->strm.avail_in = Z_NULL; + ret = inflateInit2(&(gz->strm), 15 + 16); + } + if (ret != Z_OK) { + free(gz); + return NULL; + } + gz->file = path == NULL ? fdopen(fd, gz->write ? "wb" : "rb") : + fopen(path, gz->write ? "wb" : "rb"); + if (gz->file == NULL) { + gz->write ? deflateEnd(&(gz->strm)) : inflateEnd(&(gz->strm)); + free(gz); + return NULL; + } + gz->err = 0; + gz->msg = ""; + return gz; +} + +int gzwrite OF((gzFile, const void *, unsigned)); + +int gzwrite(gz, buf, len) + gzFile gz; + const void *buf; + unsigned len; +{ + z_stream *strm; + unsigned char out[BUFLEN]; + + if (gz == NULL || !gz->write) + return 0; + strm = &(gz->strm); + strm->next_in = (void *)buf; + strm->avail_in = len; + do { + strm->next_out = out; + strm->avail_out = BUFLEN; + (void)deflate(strm, Z_NO_FLUSH); + fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); + } while (strm->avail_out == 0); + return len; +} + +int gzread OF((gzFile, void *, unsigned)); + +int gzread(gz, buf, len) + gzFile gz; + void *buf; + unsigned len; +{ + int ret; + unsigned got; + unsigned char in[1]; + z_stream *strm; + + if (gz == NULL || gz->write) + return 0; + if (gz->err) + return 0; + strm = &(gz->strm); + strm->next_out = (void *)buf; + strm->avail_out = len; + do { + got = fread(in, 1, 1, gz->file); + if (got == 0) + break; + strm->next_in = in; + strm->avail_in = 1; + ret = inflate(strm, Z_NO_FLUSH); + if (ret == Z_DATA_ERROR) { + gz->err = Z_DATA_ERROR; + gz->msg = strm->msg; + return 0; + } + if (ret == Z_STREAM_END) + inflateReset(strm); + } while (strm->avail_out); + return len - strm->avail_out; +} + +int gzclose OF((gzFile)); + +int gzclose(gz) + gzFile gz; +{ + z_stream *strm; + unsigned char out[BUFLEN]; + + if (gz == NULL) + return Z_STREAM_ERROR; + strm = &(gz->strm); + if (gz->write) { + strm->next_in = Z_NULL; + strm->avail_in = 0; + do { + strm->next_out = out; + strm->avail_out = BUFLEN; + (void)deflate(strm, Z_FINISH); + fwrite(out, 1, BUFLEN - strm->avail_out, gz->file); + } while (strm->avail_out == 0); + deflateEnd(strm); + } + else + inflateEnd(strm); + fclose(gz->file); + free(gz); + return Z_OK; +} + +const char *gzerror OF((gzFile, int *)); + +const char *gzerror(gz, err) + gzFile gz; + int *err; +{ + *err = gz->err; + return gz->msg; +} + +#endif + +static char *prog; + +void error OF((const char *msg)); +void gz_compress OF((FILE *in, gzFile out)); +#ifdef USE_MMAP +int gz_compress_mmap OF((FILE *in, gzFile out)); +#endif +void gz_uncompress OF((gzFile in, FILE *out)); +void file_compress OF((char *file, char *mode)); +void file_uncompress OF((char *file)); +int main OF((int argc, char *argv[])); + +/* =========================================================================== + * Display error message and exit + */ +void error(msg) + const char *msg; +{ + fprintf(stderr, "%s: %s\n", prog, msg); + exit(1); +} + +/* =========================================================================== + * Compress input to output then close both files. + */ + +void gz_compress(in, out) + FILE *in; + gzFile out; +{ + local char buf[BUFLEN]; + int len; + int err; + +#ifdef USE_MMAP + /* Try first compressing with mmap. If mmap fails (minigzip used in a + * pipe), use the normal fread loop. + */ + if (gz_compress_mmap(in, out) == Z_OK) return; +#endif + for (;;) { + len = (int)fread(buf, 1, sizeof(buf), in); + if (ferror(in)) { + perror("fread"); + exit(1); + } + if (len == 0) break; + + if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); + } + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); +} + +#ifdef USE_MMAP /* MMAP version, Miguel Albrecht */ + +/* Try compressing the input file at once using mmap. Return Z_OK if + * if success, Z_ERRNO otherwise. + */ +int gz_compress_mmap(in, out) + FILE *in; + gzFile out; +{ + int len; + int err; + int ifd = fileno(in); + caddr_t buf; /* mmap'ed buffer for the entire input file */ + off_t buf_len; /* length of the input file */ + struct stat sb; + + /* Determine the size of the file, needed for mmap: */ + if (fstat(ifd, &sb) < 0) return Z_ERRNO; + buf_len = sb.st_size; + if (buf_len <= 0) return Z_ERRNO; + + /* Now do the actual mmap: */ + buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); + if (buf == (caddr_t)(-1)) return Z_ERRNO; + + /* Compress the whole file at once: */ + len = gzwrite(out, (char *)buf, (unsigned)buf_len); + + if (len != (int)buf_len) error(gzerror(out, &err)); + + munmap(buf, buf_len); + fclose(in); + if (gzclose(out) != Z_OK) error("failed gzclose"); + return Z_OK; +} +#endif /* USE_MMAP */ + +/* =========================================================================== + * Uncompress input to output then close both files. + */ +void gz_uncompress(in, out) + gzFile in; + FILE *out; +{ + local char buf[BUFLEN]; + int len; + int err; + + for (;;) { + len = gzread(in, buf, sizeof(buf)); + if (len < 0) error (gzerror(in, &err)); + if (len == 0) break; + + if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { + error("failed fwrite"); + } + } + if (fclose(out)) error("failed fclose"); + + if (gzclose(in) != Z_OK) error("failed gzclose"); +} + + +/* =========================================================================== + * Compress the given file: create a corresponding .gz file and remove the + * original. + */ +void file_compress(file, mode) + char *file; + char *mode; +{ + local char outfile[MAX_NAME_LEN]; + FILE *in; + gzFile out; + + if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(outfile, sizeof(outfile), "%s%s", file, GZ_SUFFIX); +#else + strcpy(outfile, file); + strcat(outfile, GZ_SUFFIX); +#endif + + in = fopen(file, "rb"); + if (in == NULL) { + perror(file); + exit(1); + } + out = gzopen(outfile, mode); + if (out == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); + exit(1); + } + gz_compress(in, out); + + unlink(file); +} + + +/* =========================================================================== + * Uncompress the given file and remove the original. + */ +void file_uncompress(file) + char *file; +{ + local char buf[MAX_NAME_LEN]; + char *infile, *outfile; + FILE *out; + gzFile in; + unsigned len = strlen(file); + + if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { + fprintf(stderr, "%s: filename too long\n", prog); + exit(1); + } + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(buf, sizeof(buf), "%s", file); +#else + strcpy(buf, file); +#endif + + if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { + infile = file; + outfile = buf; + outfile[len-3] = '\0'; + } else { + outfile = file; + infile = buf; +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(buf + len, sizeof(buf) - len, "%s", GZ_SUFFIX); +#else + strcat(infile, GZ_SUFFIX); +#endif + } + in = gzopen(infile, "rb"); + if (in == NULL) { + fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); + exit(1); + } + out = fopen(outfile, "wb"); + if (out == NULL) { + perror(file); + exit(1); + } + + gz_uncompress(in, out); + + unlink(infile); +} + + +/* =========================================================================== + * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] + * -c : write to standard output + * -d : decompress + * -f : compress with Z_FILTERED + * -h : compress with Z_HUFFMAN_ONLY + * -r : compress with Z_RLE + * -1 to -9 : compression level + */ + +int main(argc, argv) + int argc; + char *argv[]; +{ + int copyout = 0; + int uncompr = 0; + gzFile file; + char *bname, outmode[20]; + +#if !defined(NO_snprintf) && !defined(NO_vsnprintf) + snprintf(outmode, sizeof(outmode), "%s", "wb6 "); +#else + strcpy(outmode, "wb6 "); +#endif + + prog = argv[0]; + bname = strrchr(argv[0], '/'); + if (bname) + bname++; + else + bname = argv[0]; + argc--, argv++; + + if (!strcmp(bname, "gunzip")) + uncompr = 1; + else if (!strcmp(bname, "zcat")) + copyout = uncompr = 1; + + while (argc > 0) { + if (strcmp(*argv, "-c") == 0) + copyout = 1; + else if (strcmp(*argv, "-d") == 0) + uncompr = 1; + else if (strcmp(*argv, "-f") == 0) + outmode[3] = 'f'; + else if (strcmp(*argv, "-h") == 0) + outmode[3] = 'h'; + else if (strcmp(*argv, "-r") == 0) + outmode[3] = 'R'; + else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && + (*argv)[2] == 0) + outmode[2] = (*argv)[1]; + else + break; + argc--, argv++; + } + if (outmode[3] == ' ') + outmode[3] = 0; + if (argc == 0) { + SET_BINARY_MODE(stdin); + SET_BINARY_MODE(stdout); + if (uncompr) { + file = gzdopen(fileno(stdin), "rb"); + if (file == NULL) error("can't gzdopen stdin"); + gz_uncompress(file, stdout); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + gz_compress(stdin, file); + } + } else { + if (copyout) { + SET_BINARY_MODE(stdout); + } + do { + if (uncompr) { + if (copyout) { + file = gzopen(*argv, "rb"); + if (file == NULL) + fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); + else + gz_uncompress(file, stdout); + } else { + file_uncompress(*argv); + } + } else { + if (copyout) { + FILE * in = fopen(*argv, "rb"); + + if (in == NULL) { + perror(*argv); + } else { + file = gzdopen(fileno(stdout), outmode); + if (file == NULL) error("can't gzdopen stdout"); + + gz_compress(in, file); + } + + } else { + file_compress(*argv, outmode); + } + } + } while (argv++, --argc); + } + return 0; +} diff --git a/libs/zlib/treebuild.xml b/libs/zlib/treebuild.xml index 89963a0ce..fd75525f9 100644 --- a/libs/zlib/treebuild.xml +++ b/libs/zlib/treebuild.xml @@ -1,6 +1,6 @@ - - + + zip compression library @@ -101,7 +101,7 @@ \t"\1", // \2 static const char *const MOBJFLAG2_LIST[] = { - "AXIS", // It's a NiGHTS axis! (For faster checking) - "TWOD", // Moves like it's in a 2D level - "DONTRESPAWN", // Don't respawn this object! - "\x01", // free: 1<<3 (name un-matchable) - "AUTOMATIC", // Thrown ring has automatic properties - "RAILRING", // Thrown ring has rail properties - "BOUNCERING", // Thrown ring has bounce properties - "EXPLOSION", // Thrown ring has explosive properties - "SCATTER", // Thrown ring has scatter properties - "BEYONDTHEGRAVE",// Source of this missile has died and has since respawned. - "PUSHED", // Mobj was already pushed this tic - "SLIDEPUSH", // MF_PUSHABLE that pushes continuously. - "CLASSICPUSH", // Drops straight down when object has negative Z. - "STANDONME", // While not pushable, stand on me anyway. - "INFLOAT", // Floating to a height for a move, don't auto float to target's height. - "DEBRIS", // Splash ring from explosion ring - "NIGHTSPULL", // Attracted from a paraloop - "JUSTATTACKED", // can be pushed by other moving mobjs - "FIRING", // turret fire - "SUPERFIRE", // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it. - "\x01", // free: 1<<20 (name un-matchable) - "STRONGBOX", // Flag used for "strong" random monitors. - "OBJECTFLIP", // Flag for objects that always have flipped gravity. - "SKULLFLY", // Special handling: skull in flight. - "FRET", // Flashing from a previous hit - "BOSSNOTRAP", // No Egg Trap after boss - "BOSSFLEE", // Boss is fleeing! - "BOSSDEAD", // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.) - "AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH + "AXIS", // It's a NiGHTS axis! (For faster checking) + "TWOD", // Moves like it's in a 2D level + "DONTRESPAWN", // Don't respawn this object! + "\x01", // free: 1<<3 (name un-matchable) + "AUTOMATIC", // Thrown ring has automatic properties + "RAILRING", // Thrown ring has rail properties + "BOUNCERING", // Thrown ring has bounce properties + "EXPLOSION", // Thrown ring has explosive properties + "SCATTER", // Thrown ring has scatter properties + "BEYONDTHEGRAVE", // Source of this missile has died and has since respawned. + "SLIDEPUSH", // MF_PUSHABLE that pushes continuously. + "CLASSICPUSH", // Drops straight down when object has negative momz. + "INVERTAIMABLE", // Flips whether it's targetable by A_LookForEnemies (enemies no, decoys yes) + "INFLOAT", // Floating to a height for a move, don't auto float to target's height. + "DEBRIS", // Splash ring from explosion ring + "NIGHTSPULL", // Attracted from a paraloop + "JUSTATTACKED", // can be pushed by other moving mobjs + "FIRING", // turret fire + "SUPERFIRE", // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it. + "\x01", // free: 1<<20 (name un-matchable) + "STRONGBOX", // Flag used for "strong" random monitors. + "OBJECTFLIP", // Flag for objects that always have flipped gravity. + "SKULLFLY", // Special handling: skull in flight. + "FRET", // Flashing from a previous hit + "BOSSNOTRAP", // No Egg Trap after boss + "BOSSFLEE", // Boss is fleeing! + "BOSSDEAD", // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.) + "AMBUSH", // Alternate behaviour typically set by MTF_AMBUSH + "LINKDRAW", // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) + "SHIELD", // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) NULL }; @@ -8496,24 +10478,27 @@ static const char *const MOBJEFLAG_LIST[] = { "JUSTSTEPPEDDOWN", // used for ramp sectors "VERTICALFLIP", // Vertically flip sprite/allow upside-down physics "GOOWATER", // Goo water - "JUSTBOUNCEDWALL", // SRB2Kart: Mobj already bounced off a wall this tic + "TOUCHLAVA", // The mobj is touching a lava block + "PUSHED", // Mobj was already pushed this tic "SPRUNG", // Mobj was already sprung this tic "APPLYPMOMZ", // Platform movement + "TRACERANGLE", // Compute and trigger on mobj angle relative to tracer + "JUSTBOUNCEDWALL", NULL }; -#ifdef HAVE_BLUA static const char *const MAPTHINGFLAG_LIST[4] = { - NULL, + "EXTRA", // Extra flag for objects. "OBJECTFLIP", // Reverse gravity flag for objects. "OBJECTSPECIAL", // Special flag used with certain objects. "AMBUSH" // Deaf monsters/do not react to sound. }; -#endif static const char *const PLAYERFLAG_LIST[] = { - // Flip camera angle with gravity flip prefrence. - "FLIPCAM", + "FAULT", + "ANALOGMODE", // Analog mode? + "DIRECTIONCHAR", // Directional character sprites? + "AUTOBRAKE", // Autobrake? // Cheats "GODMODE", @@ -8522,7 +10507,7 @@ static const char *const PLAYERFLAG_LIST[] = { // True if button down last tic. "ATTACKDOWN", - "USEDOWN", + "SPINDOWN", "JUMPDOWN", "WPNDOWN", @@ -8538,51 +10523,73 @@ static const char *const PLAYERFLAG_LIST[] = { "WANTSTOJOIN", // Character action status + "STARTJUMP", "JUMPED", + "NOJUMPDAMAGE", + "SPINNING", "STARTDASH", + "THOKKED", - - // Are you gliding? + "SHIELDABILITY", "GLIDING", - - // Tails pickup! - "CARRIED", + "BOUNCING", // Sliding (usually in water) like Labyrinth/Oil Ocean "SLIDING", - // Hanging on a rope - "ROPEHANG", - - // Hanging on an item of some kind - zipline, chain, etc. (->tracer) - "ITEMHANG", - - // On the mace chain spinning around (->tracer) - "MACESPIN", - - /*** NIGHTS STUFF ***/ - // Is the player in NiGHTS mode? - "NIGHTSMODE", + // NiGHTS stuff "TRANSFERTOCLOSEST", - - // Spill rings after falling - "NIGHTSFALL", "DRILLING", - "SKIDDOWN", - /*** TAG STUFF ***/ - "TAGGED", // Player has been tagged and awaits the next round in hide and seek. + // Gametype-specific stuff + "GAMETYPEOVER", // Race time over, or H&S out-of-game "TAGIT", // The player is it! For Tag Mode /*** misc ***/ "FORCESTRAFE", // Translate turn inputs into strafe inputs "HITFINISHLINE", // Already hit the finish line this tic + "FINISHED", NULL // stop loop here. }; -#ifdef HAVE_BLUA +static const char *const GAMETYPERULE_LIST[] = { + "CAMPAIGN", + "RINGSLINGER", + "SPECTATORS", + "LIVES", + "TEAMS", + "FIRSTPERSON", + "POWERSTONES", + "TEAMFLAGS", + "FRIENDLY", + "SPECIALSTAGES", + "EMERALDTOKENS", + "EMERALDHUNT", + "RACE", + "TAG", + "POINTLIMIT", + "TIMELIMIT", + "OVERTIME", + "HURTMESSAGES", + "FRIENDLYFIRE", + "STARTCOUNTDOWN", + "HIDEFROZEN", + "BLINDFOLDED", + "RESPAWNDELAY", + "PITYSHIELD", + "DEATHPENALTY", + "NOSPECTATORSPAWN", + "DEATHMATCHSTARTS", + "SPAWNINVUL", + "SPAWNENEMIES", + "ALLOWEXIT", + "NOTITLECARD", + "CUTSCENES", + NULL +}; + // Linedef flags static const char *const ML_LIST[16] = { "IMPASSABLE", @@ -8602,7 +10609,6 @@ static const char *const ML_LIST[16] = { "BOUNCY", "TFERLINE" }; -#endif // This DOES differ from r_draw's Color_Names, unfortunately. // Also includes Super colors @@ -8779,10 +10785,14 @@ static const char *const POWERS_LIST[] = { "SNEAKERS", "FLASHING", "SHIELD", + "CARRY", "TAILSFLY", // tails flying "UNDERWATER", // underwater timer "SPACETIME", // In space, no one can hear you spin! "EXTRALIFE", // Extra Life timer + "PUSHING", + "JUSTSPRUNG", + "NOAUTOBRAKE", "SUPER", // Are you super? "GRAVITYBOOTS", // gravity boots @@ -8806,10 +10816,15 @@ static const char *const POWERS_LIST[] = { //for linedef exec 427 "NOCONTROL", - "INGOOP" // In goop + + //for dyes + "DYE", + + "JUSTLAUNCHED", + + "IGNORELATCH" }; -#ifdef HAVE_BLUA static const char *const KARTSTUFF_LIST[] = { "POSITION", "OLDPOSITION", @@ -8903,35 +10918,25 @@ static const char *const KARTSTUFF_LIST[] = { "KILLFIELD", "WRONGWAY" }; -#endif static const char *const HUDITEMS_LIST[] = { - "LIVESNAME", - "LIVESPIC", - "LIVESNUM", - "LIVESX", + "LIVES", "RINGS", - "RINGSSPLIT", "RINGSNUM", - "RINGSNUMSPLIT", + "RINGSNUMTICS", "SCORE", "SCORENUM", "TIME", - "TIMESPLIT", "MINUTES", - "MINUTESSPLIT", "TIMECOLON", - "TIMECOLONSPLIT", "SECONDS", - "SECONDSSPLIT", "TIMETICCOLON", "TICS", "SS_TOTALRINGS", - "SS_TOTALRINGS_SPLIT", "GETRINGS", "GETRINGSNUM", @@ -8939,18 +10944,108 @@ static const char *const HUDITEMS_LIST[] = { "TIMELEFTNUM", "TIMEUP", "HUNTPICS", - "GRAVBOOTSICO", - "LAP" + "POWERUPS" +}; + +static const char *const MENUTYPES_LIST[] = { + "NONE", + + "MAIN", + + // Single Player + "SP_MAIN", + + "SP_LOAD", + "SP_PLAYER", + + "SP_LEVELSELECT", + "SP_LEVELSTATS", + + "SP_TIMEATTACK", + "SP_TIMEATTACK_LEVELSELECT", + "SP_GUESTREPLAY", + "SP_REPLAY", + "SP_GHOST", + + "SP_NIGHTSATTACK", + "SP_NIGHTS_LEVELSELECT", + "SP_NIGHTS_GUESTREPLAY", + "SP_NIGHTS_REPLAY", + "SP_NIGHTS_GHOST", + + // Multiplayer + "MP_MAIN", + "MP_SPLITSCREEN", // SplitServer + "MP_SERVER", + "MP_CONNECT", + "MP_ROOM", + "MP_PLAYERSETUP", // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET + "MP_SERVER_OPTIONS", + + // Options + "OP_MAIN", + + "OP_P1CONTROLS", + "OP_CHANGECONTROLS", // OP_ChangeControlsDef shared with P2 + "OP_P1MOUSE", + "OP_P1JOYSTICK", + "OP_JOYSTICKSET", // OP_JoystickSetDef shared with P2 + "OP_P1CAMERA", + + "OP_P2CONTROLS", + "OP_P2MOUSE", + "OP_P2JOYSTICK", + "OP_P2CAMERA", + + "OP_PLAYSTYLE", + + "OP_VIDEO", + "OP_VIDEOMODE", + "OP_COLOR", + "OP_OPENGL", + "OP_OPENGL_LIGHTING", + + "OP_SOUND", + + "OP_SERVER", + "OP_MONITORTOGGLE", + + "OP_DATA", + "OP_ADDONS", + "OP_SCREENSHOTS", + "OP_ERASEDATA", + + // Extras + "SR_MAIN", + "SR_PANDORA", + "SR_LEVELSELECT", + "SR_UNLOCKCHECKLIST", + "SR_EMBLEMHINT", + "SR_PLAYER", + "SR_SOUNDTEST", + + // Addons (Part of MISC, but let's make it our own) + "AD_MAIN", + + // MISC + // "MESSAGE", + // "SPAUSE", + + // "MPAUSE", + // "SCRAMBLETEAM", + // "CHANGETEAM", + // "CHANGELEVEL", + + // "MAPAUSE", + // "HELP", + + "SPECIAL" }; struct { const char *n; // has to be able to hold both fixed_t and angle_t, so drastic measure!! -#ifdef HAVE_BLUA lua_Integer v; -#else - INT64 v; -#endif } const INT_CONST[] = { // If a mod removes some variables here, // please leave the names in-tact and just set @@ -8980,9 +11075,10 @@ struct { {"RING_DIST",RING_DIST}, {"PUSHACCEL",PUSHACCEL}, {"MODID",MODID}, // I don't know, I just thought it would be cool for a wad to potentially know what mod it was loaded into. + {"MODVERSION",MODVERSION}, // or what version of the mod this is. {"CODEBASE",CODEBASE}, // or what release of SRB2 this is. - {"VERSION",VERSION}, // Grab the game's version! - {"SUBVERSION",SUBVERSION}, // more precise version number + {"NEWTICRATE",NEWTICRATE}, // TICRATE*NEWTICRATERATIO + {"NEWTICRATERATIO",NEWTICRATERATIO}, // Special linedef executor tag numbers! {"LE_PINCHPHASE",LE_PINCHPHASE}, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) @@ -8990,11 +11086,22 @@ struct { {"LE_BOSSDEAD",LE_BOSSDEAD}, // A boss in the map died (Chaos mode boss tally) {"LE_BOSS4DROP",LE_BOSS4DROP}, // CEZ boss dropped its cage {"LE_BRAKVILEATACK",LE_BRAKVILEATACK}, // Brak's doing his LOS attack, oh noes + {"LE_TURRET",LE_TURRET}, // THZ turret + {"LE_BRAKPLATFORM",LE_BRAKPLATFORM}, // v2.0 Black Eggman destroys platform + {"LE_CAPSULE2",LE_CAPSULE2}, // Egg Capsule + {"LE_CAPSULE1",LE_CAPSULE1}, // Egg Capsule + {"LE_CAPSULE0",LE_CAPSULE0}, // Egg Capsule + {"LE_KOOPA",LE_KOOPA}, // Distant cousin to Gay Bowser + {"LE_AXE",LE_AXE}, // MKB Axe object + {"LE_PARAMWIDTH",LE_PARAMWIDTH}, // If an object that calls LinedefExecute has a nonzero parameter value, this times the parameter will be subtracted. (Mostly for the purpose of coexisting bosses...) /// \todo Get all this stuff into its own sections, maybe. Maybe. // Frame settings {"FF_FRAMEMASK",FF_FRAMEMASK}, + {"FF_SPR2SUPER",FF_SPR2SUPER}, + {"FF_SPR2ENDSTATE",FF_SPR2ENDSTATE}, + {"FF_SPR2MIDSTART",FF_SPR2MIDSTART}, {"FF_ANIMATE",FF_ANIMATE}, {"FF_RANDOMANIM",FF_RANDOMANIM}, {"FF_GLOBALANIM",FF_GLOBALANIM}, @@ -9002,6 +11109,8 @@ struct { {"FF_SEMIBRIGHT",FF_SEMIBRIGHT}, {"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_VERTICALFLIP",FF_VERTICALFLIP}, + {"FF_HORIZONTALFLIP",FF_HORIZONTALFLIP}, + {"FF_PAPERSPRITE",FF_PAPERSPRITE}, {"FF_TRANSMASK",FF_TRANSMASK}, {"FF_TRANSSHIFT",FF_TRANSSHIFT}, // new preshifted translucency (used in source) @@ -9014,6 +11123,8 @@ struct { {"FF_TRANS70",FF_TRANS70}, {"FF_TRANS80",FF_TRANS80}, {"FF_TRANS90",FF_TRANS90}, + {"FF_TRANSADD",FF_TRANSADD}, + {"FF_TRANSSUB",FF_TRANSSUB}, // compatibility // Transparency for SOCs is pre-shifted {"TR_TRANS10",tr_trans10<gotflag! // Used to be MF_ for some stupid reason, now they're GF_ to stop them looking like mobjflags @@ -9238,11 +11382,11 @@ struct { {"FF_CUTEXTRA",FF_CUTEXTRA}, ///< Cuts out hidden translucent pixels. {"FF_CUTLEVEL",FF_CUTLEVEL}, ///< Cuts out all hidden pixels. {"FF_CUTSPRITES",FF_CUTSPRITES}, ///< Final step in making 3D water. - {"FF_BOTHPLANES",FF_BOTHPLANES}, ///< Renders both planes all the time. + {"FF_BOTHPLANES",FF_BOTHPLANES}, ///< Render inside and outside planes. {"FF_EXTRA",FF_EXTRA}, ///< Gets cut by ::FF_CUTEXTRA. {"FF_TRANSLUCENT",FF_TRANSLUCENT}, ///< See through! {"FF_FOG",FF_FOG}, ///< Fog "brush." - {"FF_INVERTPLANES",FF_INVERTPLANES}, ///< Reverse the plane visibility rules. + {"FF_INVERTPLANES",FF_INVERTPLANES}, ///< Only render inside planes. {"FF_ALLSIDES",FF_ALLSIDES}, ///< Render inside and outside sides. {"FF_INVERTSIDES",FF_INVERTSIDES}, ///< Only render inside sides. {"FF_DOUBLESHADOW",FF_DOUBLESHADOW}, ///< Make two lightlist entries to reset light? @@ -9255,22 +11399,43 @@ struct { {"FF_QUICKSAND",FF_QUICKSAND}, ///< Quicksand! {"FF_PLATFORM",FF_PLATFORM}, ///< You can jump up through this to the top. {"FF_REVERSEPLATFORM",FF_REVERSEPLATFORM}, ///< A fall-through floor in normal gravity, a platform in reverse gravity. - {"FF_INTANGABLEFLATS",FF_INTANGABLEFLATS}, ///< Both flats are intangable, but the sides are still solid. - {"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Thinks everyone's Knuckles. - {"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Jump or fall onto it while curled in a ball. - {"FF_ONLYKNUX",FF_ONLYKNUX}, ///< Used with ::FF_BUSTUP. Only Knuckles can break this rock. + {"FF_INTANGIBLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangible, but the sides are still solid. + {"FF_INTANGABLEFLATS",FF_INTANGIBLEFLATS}, ///< Both flats are intangable, but the sides are still solid. + {"FF_SHATTER",FF_SHATTER}, ///< Used with ::FF_BUSTUP. Bustable on mere touch. + {"FF_SPINBUST",FF_SPINBUST}, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. + {"FF_STRONGBUST",FF_STRONGBUST}, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). {"FF_RIPPLE",FF_RIPPLE}, ///< Ripple the flats {"FF_COLORMAPONLY",FF_COLORMAPONLY}, ///< Only copy the colormap, not the lightlevel {"FF_GOOWATER",FF_GOOWATER}, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. -#ifdef ESLOPE - // Slope flags - {"SL_NOPHYSICS",SL_NOPHYSICS}, // Don't do momentum adjustment with this slope - {"SL_NODYNAMIC",SL_NODYNAMIC}, // Slope will never need to move during the level, so don't fuss with recalculating it - {"SL_ANCHORVERTEX",SL_ANCHORVERTEX},// Slope is using a Slope Vertex Thing to anchor its position - {"SL_VERTEXSLOPE",SL_VERTEXSLOPE}, // Slope is built from three Slope Vertex Things + // PolyObject flags + {"POF_CLIPLINES",POF_CLIPLINES}, ///< Test against lines for collision + {"POF_CLIPPLANES",POF_CLIPPLANES}, ///< Test against tops and bottoms for collision + {"POF_SOLID",POF_SOLID}, ///< Clips things. + {"POF_TESTHEIGHT",POF_TESTHEIGHT}, ///< Test line collision with heights + {"POF_RENDERSIDES",POF_RENDERSIDES}, ///< Renders the sides. + {"POF_RENDERTOP",POF_RENDERTOP}, ///< Renders the top. + {"POF_RENDERBOTTOM",POF_RENDERBOTTOM}, ///< Renders the bottom. + {"POF_RENDERPLANES",POF_RENDERPLANES}, ///< Renders top and bottom. + {"POF_RENDERALL",POF_RENDERALL}, ///< Renders everything. + {"POF_INVERT",POF_INVERT}, ///< Inverts collision (like a cage). + {"POF_INVERTPLANES",POF_INVERTPLANES}, ///< Render inside planes. + {"POF_INVERTPLANESONLY",POF_INVERTPLANESONLY}, ///< Only render inside planes. + {"POF_PUSHABLESTOP",POF_PUSHABLESTOP}, ///< Pushables will stop movement. + {"POF_LDEXEC",POF_LDEXEC}, ///< This PO triggers a linedef executor. + {"POF_ONESIDE",POF_ONESIDE}, ///< Only use the first side of the linedef. + {"POF_NOSPECIALS",POF_NOSPECIALS}, ///< Don't apply sector specials. + {"POF_SPLAT",POF_SPLAT}, ///< Use splat flat renderer (treat cyan pixels as invisible). + +#ifdef HAVE_LUA_SEGS + // Node flags + {"NF_SUBSECTOR",NF_SUBSECTOR}, // Indicate a leaf. #endif + // Slope flags + {"SL_NOPHYSICS",SL_NOPHYSICS}, + {"SL_DYNAMIC",SL_DYNAMIC}, + // Angles {"ANG1",ANG1}, {"ANG2",ANG2}, @@ -9315,6 +11480,11 @@ struct { {"DI_SOUTHEAST",DI_SOUTHEAST}, {"NUMDIRS",NUMDIRS}, + // Sprite rotation axis (rotaxis_t) + {"ROTAXIS_X",ROTAXIS_X}, + {"ROTAXIS_Y",ROTAXIS_Y}, + {"ROTAXIS_Z",ROTAXIS_Z}, + // Buttons (ticcmd_t) // SRB2kart {"BT_ACCELERATE",BT_ACCELERATE}, {"BT_DRIFT",BT_DRIFT}, @@ -9326,6 +11496,15 @@ struct { {"BT_CUSTOM2",BT_CUSTOM2}, // Lua customizable {"BT_CUSTOM3",BT_CUSTOM3}, // Lua customizable + // Lua command registration flags + {"COM_ADMIN",COM_ADMIN}, + {"COM_LOCAL",COM_LOCAL}, + {"COM_PLAYER2",COM_PLAYER2}, + {"COM_PLAYER3",COM_PLAYER3}, + {"COM_PLAYER4",COM_PLAYER4}, + {"COM_SPLITSCREEN",COM_SPLITSCREEN}, + {"COM_SSSHIFT",COM_SSSHIFT}, + // cvflags_t {"CV_SAVE",CV_SAVE}, {"CV_CALL",CV_CALL}, @@ -9340,6 +11519,7 @@ struct { {"CV_HIDEN",CV_HIDEN}, {"CV_HIDDEN",CV_HIDEN}, {"CV_CHEAT",CV_CHEAT}, + {"CV_NOLUA",CV_NOLUA}, // v_video flags {"V_NOSCALEPATCH",V_NOSCALEPATCH}, @@ -9348,6 +11528,7 @@ struct { {"V_6WIDTHSPACE",V_6WIDTHSPACE}, {"V_OLDSPACING",V_OLDSPACING}, {"V_MONOSPACE",V_MONOSPACE}, + {"V_PURPLEMAP",V_PURPLEMAP}, {"V_YELLOWMAP",V_YELLOWMAP}, {"V_GREENMAP",V_GREENMAP}, @@ -9363,6 +11544,7 @@ struct { {"V_PINKMAP",V_PINKMAP}, {"V_BROWNMAP",V_BROWNMAP}, {"V_TANMAP",V_TANMAP}, + {"V_TRANSLUCENT",V_TRANSLUCENT}, {"V_10TRANS",V_10TRANS}, {"V_20TRANS",V_20TRANS}, @@ -9375,7 +11557,6 @@ struct { {"V_90TRANS",V_90TRANS}, {"V_HUDTRANSHALF",V_HUDTRANSHALF}, {"V_HUDTRANS",V_HUDTRANS}, - {"V_AUTOFADEOUT",V_AUTOFADEOUT}, {"V_RETURN8",V_RETURN8}, {"V_OFFSET",V_OFFSET}, {"V_ALLOWLOWERCASE",V_ALLOWLOWERCASE}, @@ -9407,6 +11588,21 @@ struct { {"KR_BAN",KR_BAN}, {"KR_LEAVE",KR_LEAVE}, + // translation colormaps + {"TC_DEFAULT",TC_DEFAULT}, + {"TC_BOSS",TC_BOSS}, + {"TC_METALSONIC",TC_METALSONIC}, + {"TC_ALLWHITE",TC_ALLWHITE}, + {"TC_RAINBOW",TC_RAINBOW}, + {"TC_BLINK",TC_BLINK}, + {"TC_DASHMODE",TC_DASHMODE}, + + // marathonmode flags + {"MA_INIT",MA_INIT}, + {"MA_RUNNING",MA_RUNNING}, + {"MA_NOCUTSCENES",MA_NOCUTSCENES}, + {"MA_INGAME",MA_INGAME}, + // SRB2Kart // kartitems_t #define FOREACH( name, n ) { #name, KITEM_ ## name } @@ -9429,6 +11625,19 @@ struct { {"KSHIELD_FLAME",KSHIELD_FLAME}, {"NUMKARTSHIELDS",NUMKARTSHIELDS}, + // kartspinoutflags_t + {"KSPIN_THRUST",KSPIN_THRUST}, + {"KSPIN_IFRAMES",KSPIN_IFRAMES}, + {"KSPIN_AIRTIMER",KSPIN_AIRTIMER}, + + {"KSPIN_TYPEBIT",KSPIN_TYPEBIT}, + {"KSPIN_TYPEMASK",KSPIN_TYPEMASK}, + + {"KSPIN_SPINOUT",KSPIN_SPINOUT}, + {"KSPIN_WIPEOUT",KSPIN_WIPEOUT}, + {"KSPIN_STUNG",KSPIN_STUNG}, + {"KSPIN_EXPLOSION",KSPIN_EXPLOSION}, + // translation colormaps {"TC_DEFAULT",TC_DEFAULT}, {"TC_BOSS",TC_BOSS}, @@ -9451,6 +11660,8 @@ struct { {"MFD_TRANS70",MFD_TRANS70}, {"MFD_TRANS80",MFD_TRANS80}, {"MFD_TRANS90",MFD_TRANS90}, + {"MFD_TRANSADD",MFD_TRANSADD}, + {"MFD_TRANSSUB",MFD_TRANSSUB}, {"MFD_TRANSMASK",MFD_TRANSMASK}, {"MFD_FULLBRIGHT",MFD_FULLBRIGHT}, {"MFD_SEMIBRIGHT",MFD_SEMIBRIGHT}, @@ -9459,13 +11670,12 @@ struct { {"MFD_DONTDRAW",MFD_DONTDRAW}, {"MFD_SHADOW",MFD_SHADOW}, {"MFD_TRANSSHIFT",MFD_TRANSSHIFT}, -#endif {NULL,0} }; static mobjtype_t get_mobjtype(const char *word) -{ // Returns the vlaue of MT_ enumerations +{ // Returns the value of MT_ enumerations mobjtype_t i; if (*word >= '0' && *word <= '9') return atoi(word); @@ -9481,7 +11691,7 @@ static mobjtype_t get_mobjtype(const char *word) if (fastcmp(word, MOBJTYPE_LIST[i]+3)) return i; deh_warning("Couldn't find mobjtype named 'MT_%s'",word); - return MT_BLUECRAWLA; + return MT_NULL; } static statenum_t get_state(const char *word) @@ -9504,6 +11714,26 @@ static statenum_t get_state(const char *word) return S_NULL; } +skincolornum_t get_skincolor(const char *word) +{ // Returns the value of SKINCOLOR_ enumerations + skincolornum_t i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("SKINCOLOR_",word,10)) + word += 10; // take off the SKINCOLOR_ + for (i = 0; i < NUMCOLORFREESLOTS; i++) { + if (!FREE_SKINCOLORS[i]) + break; + if (fastcmp(word, FREE_SKINCOLORS[i])) + return SKINCOLOR_FIRSTFREESLOT+i; + } + for (i = 0; i < SKINCOLOR_FIRSTFREESLOT; i++) + if (fastcmp(word, COLOR_ENUMS[i])) + return i; + deh_warning("Couldn't find skincolor named 'SKINCOLOR_%s'",word); + return SKINCOLOR_GREEN; +} + static spritenum_t get_sprite(const char *word) { // Returns the value of SPR_ enumerations spritenum_t i; @@ -9518,6 +11748,20 @@ static spritenum_t get_sprite(const char *word) return SPR_NULL; } +static playersprite_t get_sprite2(const char *word) +{ // Returns the value of SPR2_ enumerations + playersprite_t i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("SPR2_",word,5)) + word += 5; // take off the SPR2_ + for (i = 0; i < NUMPLAYERSPRITES; i++) + if (!spr2names[i][4] && memcmp(word,spr2names[i],4)==0) + return i; + deh_warning("Couldn't find sprite named 'SPR2_%s'",word); + return SPR2_STIL; +} + static sfxenum_t get_sfx(const char *word) { // Returns the value of SFX_ enumerations sfxenum_t i; @@ -9585,12 +11829,40 @@ static hudnum_t get_huditem(const char *word) if (fastcmp(word, HUDITEMS_LIST[i])) return i; deh_warning("Couldn't find huditem named 'HUD_%s'",word); - return HUD_LIVESNAME; + return HUD_LIVES; +} + +static menutype_t get_menutype(const char *word) +{ // Returns the value of MN_ enumerations + menutype_t i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("MN_",word,3)) + word += 3; // take off the MN_ + for (i = 0; i < NUMMENUTYPES; i++) + if (fastcmp(word, MENUTYPES_LIST[i])) + return i; + deh_warning("Couldn't find menutype named 'MN_%s'",word); + return MN_NONE; +} + +/* +static INT16 get_gametype(const char *word) +{ // Returns the value of GT_ enumerations + INT16 i; + if (*word >= '0' && *word <= '9') + return atoi(word); + if (fastncmp("GT_",word,3)) + word += 3; // take off the GT_ + for (i = 0; i < NUMGAMETYPES; i++) + if (fastcmp(word, Gametype_ConstantNames[i]+3)) + return i; + deh_warning("Couldn't find gametype named 'GT_%s'",word); + return GT_COOP; } -#ifndef HAVE_BLUA static powertype_t get_power(const char *word) -{ // Returns the vlaue of pw_ enumerations +{ // Returns the value of pw_ enumerations powertype_t i; if (*word >= '0' && *word <= '9') return atoi(word); @@ -9602,6 +11874,7 @@ static powertype_t get_power(const char *word) deh_warning("Couldn't find power named 'pw_%s'",word); return pw_invulnerability; } +*/ /// \todo Make ANY of this completely over-the-top math craziness obey the order of operations. static fixed_t op_mul(fixed_t a, fixed_t b) { return a*b; } @@ -9629,6 +11902,7 @@ struct { }; // Returns the full word, cut at the first symbol or whitespace +/* static char *read_word(const char *line) { // Part 1: You got the start of the word, now find the end. @@ -9757,6 +12031,11 @@ static fixed_t find_const(const char **rword) free(word); return r; } + else if (fastncmp("SKINCOLOR_",word,10)) { + r = get_skincolor(word); + free(word); + return r; + } else if (fastncmp("MT_",word,3)) { r = get_mobjtype(word); free(word); @@ -9784,19 +12063,57 @@ static fixed_t find_const(const char **rword) free(word); return r; } + else if (fastncmp("MN_",word,3)) { + r = get_menutype(word); + free(word); + return r; + } + else if (fastncmp("GT_",word,3)) { + r = get_gametype(word); + free(word); + return r; + } + else if (fastncmp("GTR_", word, 4)) { + char *p = word+4; + for (i = 0; GAMETYPERULE_LIST[i]; i++) + if (fastcmp(p, GAMETYPERULE_LIST[i])) { + free(word); + return (1< 0) - { + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + + while (n-- > 0) + { s = Z_StrDup(luaL_checkstring(L,1)); type = strtok(s, "_"); if (type) @@ -9902,7 +12218,7 @@ static inline int lib_freeslot(lua_State *L) lua_pushinteger(L, sfx); r++; } else - return r; + CONS_Alert(CONS_WARNING, "Ran out of free SFX slots!\n"); } else if (fastcmp(type, "SPR")) { @@ -9929,7 +12245,7 @@ static inline int lib_freeslot(lua_State *L) break; } if (j > SPR_LASTFREESLOT) - return r; + CONS_Alert(CONS_WARNING, "Ran out of free sprite slots!\n"); } else if (fastcmp(type, "S")) { @@ -9940,12 +12256,12 @@ static inline int lib_freeslot(lua_State *L) FREE_STATES[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); strcpy(FREE_STATES[i],word); freeslotusage[0][0]++; - lua_pushinteger(L, i); + lua_pushinteger(L, S_FIRSTFREESLOT + i); r++; break; } if (i == NUMSTATEFREESLOTS) - return r; + CONS_Alert(CONS_WARNING, "Ran out of free State slots!\n"); } else if (fastcmp(type, "MT")) { @@ -9956,12 +12272,70 @@ static inline int lib_freeslot(lua_State *L) FREE_MOBJS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); strcpy(FREE_MOBJS[i],word); freeslotusage[1][0]++; - lua_pushinteger(L, i); + lua_pushinteger(L, MT_FIRSTFREESLOT + i); r++; break; } if (i == NUMMOBJFREESLOTS) - return r; + CONS_Alert(CONS_WARNING, "Ran out of free MobjType slots!\n"); + } + else if (fastcmp(type, "SKINCOLOR")) + { + skincolornum_t i; + for (i = 0; i < NUMCOLORFREESLOTS; i++) + if (!FREE_SKINCOLORS[i]) { + CONS_Printf("Skincolor SKINCOLOR_%s allocated.\n",word); + FREE_SKINCOLORS[i] = Z_Malloc(strlen(word)+1, PU_STATIC, NULL); + strcpy(FREE_SKINCOLORS[i],word); + M_AddMenuColor(numskincolors++); + lua_pushinteger(L, SKINCOLOR_FIRSTFREESLOT + i); + r++; + break; + } + if (i == NUMCOLORFREESLOTS) + CONS_Alert(CONS_WARNING, "Ran out of free skincolor slots!\n"); + } + else if (fastcmp(type, "SPR2")) + { + // Search if we already have an SPR2 by that name... + playersprite_t i; + for (i = SPR2_FIRSTFREESLOT; i < free_spr2; i++) + if (memcmp(spr2names[i],word,4) == 0) + break; + // We don't, so allocate a new one. + if (i >= free_spr2) { + if (free_spr2 < NUMPLAYERSPRITES) + { + CONS_Printf("Sprite SPR2_%s allocated.\n",word); + strncpy(spr2names[free_spr2],word,4); + spr2defaults[free_spr2] = 0; + lua_pushinteger(L, free_spr2); + r++; + spr2names[free_spr2++][4] = 0; + } else + CONS_Alert(CONS_WARNING, "Ran out of free SPR2 slots!\n"); + } + } + else if (fastcmp(type, "TOL")) + { + // Search if we already have a typeoflevel by that name... + int i; + for (i = 0; TYPEOFLEVEL[i].name; i++) + if (fastcmp(word, TYPEOFLEVEL[i].name)) + break; + + // We don't, so allocate a new one. + if (TYPEOFLEVEL[i].name == NULL) { + if (lastcustomtol == (UINT32)MAXTOL) // Unless you have way too many, since they're flags. + CONS_Alert(CONS_WARNING, "Ran out of free typeoflevel slots!\n"); + else { + CONS_Printf("TypeOfLevel TOL_%s allocated.\n",word); + G_AddTOL(lastcustomtol, word); + lua_pushinteger(L, lastcustomtol); + lastcustomtol <<= 1; + r++; + } + } } Z_Free(s); lua_remove(L, 1); @@ -9971,14 +12345,14 @@ static inline int lib_freeslot(lua_State *L) } // Wrapper for ALL A_Action functions. -// Upvalue: actionf_t to represent // Arguments: mobj_t actor, int var1, int var2 -static inline int lib_action(lua_State *L) +static int action_call(lua_State *L) { - actionf_t *action = lua_touserdata(L,lua_upvalueindex(1)); - mobj_t *actor = *((mobj_t **)luaL_checkudata(L,1,META_MOBJ)); - var1 = (INT32)luaL_optinteger(L,2,0); - var2 = (INT32)luaL_optinteger(L,3,0); + //actionf_t *action = lua_touserdata(L,lua_upvalueindex(1)); + actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION)); + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + var1 = (INT32)luaL_optinteger(L, 3, 0); + var2 = (INT32)luaL_optinteger(L, 4, 0); if (!actor) return LUA_ErrInvalid(L, "mobj_t"); action->acp1(actor); @@ -10064,9 +12438,44 @@ static inline int lib_getenum(lua_State *L) lua_pushinteger(L, (lua_Integer)PF_FULLSTASIS); return 1; } + else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release... + { + lua_pushinteger(L, (lua_Integer)PF_SPINDOWN); + return 1; + } if (mathlib) return luaL_error(L, "playerflag '%s' could not be found.\n", word); return 0; } + else if (fastncmp("GT_", word, 3)) { + p = word; + for (i = 0; Gametype_ConstantNames[i]; i++) + if (fastcmp(p, Gametype_ConstantNames[i])) { + lua_pushinteger(L, i); + return 1; + } + if (mathlib) return luaL_error(L, "gametype '%s' could not be found.\n", word); + return 0; + } + else if (fastncmp("GTR_", word, 4)) { + p = word+4; + for (i = 0; GAMETYPERULE_LIST[i]; i++) + if (fastcmp(p, GAMETYPERULE_LIST[i])) { + lua_pushinteger(L, ((lua_Integer)1< return action's string name +static int lib_getActionName(lua_State *L) +{ + if (lua_isuserdata(L, 1)) // arg 1 is built-in action, expect action userdata + { + actionf_t *action = *((actionf_t **)luaL_checkudata(L, 1, META_ACTION)); + const char *name = NULL; + if (!action) + return luaL_error(L, "not a valid action?"); + name = LUA_GetActionName(action); + if (!name) // that can't be right? + return luaL_error(L, "no name string could be found for this action"); + lua_pushstring(L, name); + return 1; + } + else if (lua_isfunction(L, 1)) // arg 1 is a function (either C or Lua) + { + lua_settop(L, 1); // set top of stack to 1 (removing any extra args, which there shouldn't be) + // get the name for this action, if possible. + lua_getfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS); + lua_pushnil(L); + // Lua stack at this point: + // 1 ... -2 -1 + // arg ... LREG_ACTIONS nil + while (lua_next(L, -2)) + { + // Lua stack at this point: + // 1 ... -3 -2 -1 + // arg ... LREG_ACTIONS "A_ACTION" function + if (lua_rawequal(L, -1, 1)) // is this the same as the arg? + { + // make sure the key (i.e. "A_ACTION") is a string first + // (note: we don't use lua_isstring because it also returns true for numbers) + if (lua_type(L, -2) == LUA_TSTRING) + { + lua_pushvalue(L, -2); // push "A_ACTION" string to top of stack + return 1; + } + lua_pop(L, 2); // pop the name and function + break; // probably should have succeeded but we didn't, so end the loop + } + lua_pop(L, 1); + } + lua_pop(L, 1); // pop LREG_ACTIONS + return 0; // return nothing (don't error) + } + + return luaL_typerror(L, 1, "action userdata or Lua function"); +} + + + int LUA_SOCLib(lua_State *L) { lua_register(L,"freeslot",lib_freeslot); + lua_register(L,"getActionName",lib_getActionName); + + luaL_newmetatable(L, META_ACTION); + lua_pushcfunction(L, action_call); + lua_setfield(L, -2, "__call"); + lua_pop(L, 1); + return 0; } @@ -10472,5 +12845,3 @@ void LUA_SetActionByName(void *state, const char *actiontocompare) } } } - -#endif // HAVE_BLUA diff --git a/src/dehacked.h b/src/dehacked.h index 0d6cc9022..f1b989c2b 100644 --- a/src/dehacked.h +++ b/src/dehacked.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,15 +27,8 @@ typedef enum UNDO_DONE = 0, } undotype_f; -#ifdef DELFILE -void DEH_WriteUndoline(const char *value, const char *data, undotype_f flags); -void DEH_UnloadDehackedWad(UINT16 wad); -#else // null the undo lines -#define DEH_WriteUndoline(a,b,c) -#endif - void DEH_LoadDehackedLump(lumpnum_t lumpnum); -void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump); +void DEH_LoadDehackedLumpPwad(UINT16 wad, UINT16 lump, boolean mainfile); void DEH_UpdateMaxFreeslots(void); @@ -43,11 +36,9 @@ void DEH_Check(void); fixed_t get_number(const char *word); -#ifdef HAVE_BLUA boolean LUA_SetLuaAction(void *state, const char *actiontocompare); const char *LUA_GetActionName(void *action); void LUA_SetActionByName(void *state, const char *actiontocompare); -#endif extern boolean deh_loaded; @@ -56,7 +47,7 @@ extern const char *superactions[MAXRECURSION]; extern UINT8 superstack; // If the dehacked patch does not match this version, we throw a warning -#define PATCHVERSION 1 +#define PATCHVERSION 2 #define MAXLINELEN 1024 diff --git a/src/discord.c b/src/discord.c new file mode 100644 index 000000000..42b4d91e4 --- /dev/null +++ b/src/discord.c @@ -0,0 +1,712 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour. +// Copyright (C) 2018-2020 by Kart Krew. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file discord.h +/// \brief Discord Rich Presence handling + +#ifdef HAVE_DISCORDRPC + +#ifdef HAVE_CURL +#include +#endif // HAVE_CURL + +#include "i_system.h" +#include "d_clisrv.h" +#include "d_netcmd.h" +#include "i_net.h" +#include "g_game.h" +#include "p_tick.h" +#include "m_menu.h" // gametype_cons_t +#include "r_things.h" // skins +#include "mserv.h" // cv_advertise +#include "z_zone.h" +#include "byteptr.h" + +#include "discord.h" +#include "doomdef.h" + +// Feel free to provide your own, if you care enough to create another Discord app for this :P +#define DISCORD_APPID "503531144395096085" + +// length of IP strings +#define IP_SIZE 21 + +consvar_t cv_discordrp = CVAR_INIT ("discordrp", "On", CV_SAVE|CV_CALL, CV_OnOff, DRPC_UpdatePresence); +consvar_t cv_discordstreamer = CVAR_INIT ("discordstreamer", "Off", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_discordasks = CVAR_INIT ("discordasks", "Yes", CV_SAVE|CV_CALL, CV_YesNo, DRPC_UpdatePresence); + +struct discordInfo_s discordInfo; + +discordRequest_t *discordRequestList = NULL; + +#ifdef HAVE_CURL +struct SelfIPbuffer +{ + CURL *curl; + char *pointer; + size_t length; +}; + +static char self_ip[IP_SIZE]; +#endif // HAVE_CURL + +/*-------------------------------------------------- + static char *DRPC_XORIPString(const char *input) + + Simple XOR encryption/decryption. Not complex or + very secretive because we aren't sending anything + that isn't easily accessible via our Master Server anyway. +--------------------------------------------------*/ +static char *DRPC_XORIPString(const char *input) +{ + const UINT8 xor[IP_SIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21}; + char *output = malloc(sizeof(char) * (IP_SIZE+1)); + UINT8 i; + + for (i = 0; i < IP_SIZE; i++) + { + char xorinput; + + if (!input[i]) + break; + + xorinput = input[i] ^ xor[i]; + + if (xorinput < 32 || xorinput > 126) + { + xorinput = input[i]; + } + + output[i] = xorinput; + } + + output[i] = '\0'; + + return output; +} + +/*-------------------------------------------------- + static void DRPC_HandleReady(const DiscordUser *user) + + Callback function, ran when the game connects to Discord. + + Input Arguments:- + user - Struct containing Discord user info. + + Return:- + None +--------------------------------------------------*/ +static void DRPC_HandleReady(const DiscordUser *user) +{ + if (cv_discordstreamer.value) + { + CONS_Printf("Discord: connected to %s\n", user->username); + } + else + { + CONS_Printf("Discord: connected to %s#%s (%s)\n", user->username, user->discriminator, user->userId); + } +} + +/*-------------------------------------------------- + static void DRPC_HandleDisconnect(int err, const char *msg) + + Callback function, ran when disconnecting from Discord. + + Input Arguments:- + err - Error type + msg - Error message + + Return:- + None +--------------------------------------------------*/ +static void DRPC_HandleDisconnect(int err, const char *msg) +{ + CONS_Printf("Discord: disconnected (%d: %s)\n", err, msg); +} + +/*-------------------------------------------------- + static void DRPC_HandleError(int err, const char *msg) + + Callback function, ran when Discord outputs an error. + + Input Arguments:- + err - Error type + msg - Error message + + Return:- + None +--------------------------------------------------*/ +static void DRPC_HandleError(int err, const char *msg) +{ + CONS_Alert(CONS_WARNING, "Discord error (%d: %s)\n", err, msg); +} + +/*-------------------------------------------------- + static void DRPC_HandleJoin(const char *secret) + + Callback function, ran when Discord wants to + connect a player to the game via a channel invite + or a join request. + + Input Arguments:- + secret - Value that links you to the server. + + Return:- + None +--------------------------------------------------*/ +static void DRPC_HandleJoin(const char *secret) +{ + char *ip = DRPC_XORIPString(secret); + CONS_Printf("Connecting to %s via Discord\n", ip); + COM_BufAddText(va("connect \"%s\"\n", ip)); + free(ip); +} + +/*-------------------------------------------------- + static boolean DRPC_InvitesAreAllowed(void) + + Determines whenever or not invites or + ask to join requests are allowed. + + Input Arguments:- + None + + Return:- + true if invites are allowed, false otherwise. +--------------------------------------------------*/ +static boolean DRPC_InvitesAreAllowed(void) +{ + if (!Playing()) + { + // We're not playing, so we should not be getting invites. + return false; + } + + if (cv_discordasks.value == 0) + { + // Client has the CVar set to off, so never allow invites from this client. + return false; + } + + if (discordInfo.joinsAllowed == true) + { + if (discordInfo.everyoneCanInvite == true) + { + // Everyone's allowed! + return true; + } + else if (consoleplayer == serverplayer || IsPlayerAdmin(consoleplayer)) + { + // Only admins are allowed! + return true; + } + } + + // Did not pass any of the checks + return false; +} + +/*-------------------------------------------------- + static void DRPC_HandleJoinRequest(const DiscordUser *requestUser) + + Callback function, ran when Discord wants to + ask the player if another Discord user can join + or not. + + Input Arguments:- + requestUser - DiscordUser struct for the user trying to connect. + + Return:- + None +--------------------------------------------------*/ +static void DRPC_HandleJoinRequest(const DiscordUser *requestUser) +{ + discordRequest_t *append = discordRequestList; + discordRequest_t *newRequest; + + if (DRPC_InvitesAreAllowed() == false) + { + // Something weird happened if this occurred... + Discord_Respond(requestUser->userId, DISCORD_REPLY_IGNORE); + return; + } + + newRequest = Z_Calloc(sizeof(discordRequest_t), PU_STATIC, NULL); + + newRequest->username = Z_Calloc(344, PU_STATIC, NULL); + snprintf(newRequest->username, 344, "%s", requestUser->username); + + newRequest->discriminator = Z_Calloc(8, PU_STATIC, NULL); + snprintf(newRequest->discriminator, 8, "%s", requestUser->discriminator); + + newRequest->userID = Z_Calloc(32, PU_STATIC, NULL); + snprintf(newRequest->userID, 32, "%s", requestUser->userId); + + if (append != NULL) + { + discordRequest_t *prev = NULL; + + while (append != NULL) + { + // CHECK FOR DUPES!! Ignore any that already exist from the same user. + if (!strcmp(newRequest->userID, append->userID)) + { + Discord_Respond(newRequest->userID, DISCORD_REPLY_IGNORE); + DRPC_RemoveRequest(newRequest); + return; + } + + prev = append; + append = append->next; + } + + newRequest->prev = prev; + prev->next = newRequest; + } + else + { + discordRequestList = newRequest; + M_RefreshPauseMenu(); + } + + // Made it to the end, request was valid, so play the request sound :) + S_StartSound(NULL, sfx_requst); +} + +/*-------------------------------------------------- + void DRPC_RemoveRequest(discordRequest_t *removeRequest) + + See header file for description. +--------------------------------------------------*/ +void DRPC_RemoveRequest(discordRequest_t *removeRequest) +{ + if (removeRequest->prev != NULL) + { + removeRequest->prev->next = removeRequest->next; + } + + if (removeRequest->next != NULL) + { + removeRequest->next->prev = removeRequest->prev; + + if (removeRequest == discordRequestList) + { + discordRequestList = removeRequest->next; + } + } + else + { + if (removeRequest == discordRequestList) + { + discordRequestList = NULL; + } + } + + Z_Free(removeRequest->username); + Z_Free(removeRequest->userID); + Z_Free(removeRequest); +} + +/*-------------------------------------------------- + void DRPC_Init(void) + + See header file for description. +--------------------------------------------------*/ +void DRPC_Init(void) +{ + DiscordEventHandlers handlers; + memset(&handlers, 0, sizeof(handlers)); + + handlers.ready = DRPC_HandleReady; + handlers.disconnected = DRPC_HandleDisconnect; + handlers.errored = DRPC_HandleError; + handlers.joinGame = DRPC_HandleJoin; + handlers.joinRequest = DRPC_HandleJoinRequest; + + Discord_Initialize(DISCORD_APPID, &handlers, 1, NULL); + I_AddExitFunc(Discord_Shutdown); + DRPC_UpdatePresence(); +} + +#ifdef HAVE_CURL +/*-------------------------------------------------- + static size_t DRPC_WriteServerIP(char *s, size_t size, size_t n, void *userdata) + + Writing function for use with curl. Only intended to be used with simple text. + + Input Arguments:- + s - Data to write + size - Always 1. + n - Length of data + userdata - Passed in from CURLOPT_WRITEDATA, intended to be SelfIPbuffer + + Return:- + Number of bytes wrote in this pass. +--------------------------------------------------*/ +static size_t DRPC_WriteServerIP(char *s, size_t size, size_t n, void *userdata) +{ + struct SelfIPbuffer *buffer; + size_t newlength; + + buffer = userdata; + + newlength = buffer->length + size*n; + buffer->pointer = realloc(buffer->pointer, newlength+1); + + memcpy(buffer->pointer + buffer->length, s, size*n); + + buffer->pointer[newlength] = '\0'; + buffer->length = newlength; + + return size*n; +} +#endif // HAVE_CURL + +/*-------------------------------------------------- + static const char *DRPC_GetServerIP(void) + + Retrieves the IP address of the server that you're + connected to. Will attempt to use curl for getting your + own IP address, if it's not yours. +--------------------------------------------------*/ +static const char *DRPC_GetServerIP(void) +{ + const char *address; + + // If you're connected + if (I_GetNodeAddress && (address = I_GetNodeAddress(servernode)) != NULL) + { + if (strcmp(address, "self")) + { + // We're not the server, so we could successfully get the IP! + // No need to do anything else :) + return address; + } + } + +#ifdef HAVE_CURL + // This is a little bit goofy, but + // there's practically no good way to get your own public IP address, + // so we've gotta break out curl for this :V + if (!self_ip[0]) + { + CURL *curl; + + curl_global_init(CURL_GLOBAL_ALL); + curl = curl_easy_init(); + + if (curl) + { + // The API to get your public IP address from. + // Picked because it's stupid simple and it's been up for a long time. + const char *api = "http://ip4only.me/api/"; + + struct SelfIPbuffer buffer; + CURLcode success; + + buffer.length = 0; + buffer.pointer = malloc(buffer.length+1); + buffer.pointer[0] = '\0'; + + curl_easy_setopt(curl, CURLOPT_URL, api); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DRPC_WriteServerIP); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer); + + success = curl_easy_perform(curl); + + if (success == CURLE_OK) + { + char *tmp; + tmp = strtok(buffer.pointer, ","); + + if (!strcmp(tmp, "IPv4")) // ensure correct type of IP + { + tmp = strtok(NULL, ","); + strncpy(self_ip, tmp, IP_SIZE); // Yay, we have the IP :) + } + } + + free(buffer.pointer); + curl_easy_cleanup(curl); + } + + curl_global_cleanup(); + } + + if (self_ip[0]) + return self_ip; + else +#endif // HAVE_CURL + return NULL; // Could not get your IP for whatever reason, so we cannot do Discord invites +} + +/*-------------------------------------------------- + void DRPC_EmptyRequests(void) + + Empties the request list. Any existing requests + will get an ignore reply. +--------------------------------------------------*/ +static void DRPC_EmptyRequests(void) +{ + while (discordRequestList != NULL) + { + Discord_Respond(discordRequestList->userID, DISCORD_REPLY_IGNORE); + DRPC_RemoveRequest(discordRequestList); + } +} + +/*-------------------------------------------------- + void DRPC_UpdatePresence(void) + + See header file for description. +--------------------------------------------------*/ +void DRPC_UpdatePresence(void) +{ + char detailstr[48+1]; + + char mapimg[8+1]; + char mapname[5+21+21+2+1]; + + char charimg[4+SKINNAMESIZE+1]; + char charname[11+SKINNAMESIZE+1]; + + boolean joinSecretSet = false; + + DiscordRichPresence discordPresence; + memset(&discordPresence, 0, sizeof(discordPresence)); + + if (dedicated) + { + return; + } + + if (!cv_discordrp.value) + { + // User doesn't want to show their game information, so update with empty presence. + // This just shows that they're playing SRB2Kart. (If that's too much, then they should disable game activity :V) + DRPC_EmptyRequests(); + Discord_UpdatePresence(&discordPresence); + return; + } + +#ifdef DEVELOP + // This way, we can use the invite feature in-dev, but not have snoopers seeing any potential secrets! :P + discordPresence.largeImageKey = "miscdevelop"; + discordPresence.largeImageText = "No peeking!"; + discordPresence.state = "Development EXE"; + + DRPC_EmptyRequests(); + Discord_UpdatePresence(&discordPresence); + return; +#endif // DEVELOP + + // Server info + if (netgame) + { + if (cv_advertise.value) + { + discordPresence.state = "Public"; + } + else + { + discordPresence.state = "Private"; + } + + discordPresence.partyId = server_context; // Thanks, whoever gave us Mumble support, for implementing the EXACT thing Discord wanted for this field! + discordPresence.partySize = D_NumPlayers(); // Players in server + discordPresence.partyMax = discordInfo.maxPlayers; // Max players + + if (DRPC_InvitesAreAllowed() == true) + { + const char *join; + + // Grab the host's IP for joining. + if ((join = DRPC_GetServerIP()) != NULL) + { + char *xorjoin = DRPC_XORIPString(join); + discordPresence.joinSecret = xorjoin; + free(xorjoin); + + joinSecretSet = true; + } + } + } + else + { + // Reset discord info if you're not in a place that uses it! + // Important for if you join a server that compiled without HAVE_DISCORDRPC, + // so that you don't ever end up using bad information from another server. + memset(&discordInfo, 0, sizeof(discordInfo)); + + // Offline info + if (Playing()) + discordPresence.state = "Offline"; + else if (demo.playback && !demo.title) + discordPresence.state = "Watching Replay"; + else + discordPresence.state = "Menu"; + } + + // Gametype info + if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING) && Playing()) + { + if (modeattacking) + discordPresence.details = "Time Attack"; + else + { + snprintf(detailstr, 48, "%s%s%s", + gametype_cons_t[gametype].strvalue, + (gametype == GT_RACE) ? va(" | %s", kartspeed_cons_t[gamespeed].strvalue) : "", + (encoremode == true) ? " | Encore" : "" + ); + discordPresence.details = detailstr; + } + } + + if ((gamestate == GS_LEVEL || gamestate == GS_INTERMISSION) // Map info + && !(demo.playback && demo.title)) + { + if ((gamemap >= 1 && gamemap <= 60) // supported race maps + || (gamemap >= 136 && gamemap <= 164)) // supported battle maps + { + snprintf(mapimg, 8, "%s", G_BuildMapName(gamemap)); + strlwr(mapimg); + discordPresence.largeImageKey = mapimg; // Map image + } + else if (mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU) + { + // Hell map, use the method that got you here :P + discordPresence.largeImageKey = "miscdice"; + } + else + { + // This is probably a custom map! + discordPresence.largeImageKey = "mapcustom"; + } + + if (mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU) + { + // Hell map, hide the name + discordPresence.largeImageText = "Map: ???"; + } + else + { + // Map name on tool tip + snprintf(mapname, 48, "Map: %s", G_BuildMapTitle(gamemap)); + discordPresence.largeImageText = mapname; + } + + if (gamestate == GS_LEVEL && Playing()) + { + const time_t currentTime = time(NULL); + const time_t mapTimeStart = currentTime - ((leveltime + (modeattacking ? starttime : 0)) / TICRATE); + + discordPresence.startTimestamp = mapTimeStart; + + if (timelimitintics > 0) + { + const time_t mapTimeEnd = mapTimeStart + ((timelimitintics + starttime + 1) / TICRATE); + discordPresence.endTimestamp = mapTimeEnd; + } + } + } + else if (gamestate == GS_VOTING) + { + discordPresence.largeImageKey = ((gametype == GT_BATTLE) ? "miscredplanet" : "miscblueplanet"); + discordPresence.largeImageText = "Voting"; + } + else + { + discordPresence.largeImageKey = "misctitle"; + discordPresence.largeImageText = "Title Screen"; + } + + // Character info + if (Playing() && playeringame[consoleplayer] && !players[consoleplayer].spectator) + { + // Supported skin names + static const char *supportedSkins[] = { + // base game + "sonic", + "tails", + "knuckles", + "eggman", + "metalsonic", + // bonus chars + "flicky", + "motobug", + "amy", + "mighty", + "ray", + "espio", + "vector", + "chao", + "gamma", + "chaos", + "shadow", + "rouge", + "herochao", + "darkchao", + "cream", + "omega", + "blaze", + "silver", + "wonderboy", + "arle", + "nights", + "sakura", + "ulala", + "beat", + "vyse", + "aiai", + "kiryu", + "aigis", + "miku", + "doom", + NULL + }; + + boolean customChar = true; + UINT8 checkSkin = 0; + + // Character image + while (supportedSkins[checkSkin] != NULL) + { + if (!strcmp(skins[players[consoleplayer].skin].name, supportedSkins[checkSkin])) + { + snprintf(charimg, 21, "char%s", supportedSkins[checkSkin]); + discordPresence.smallImageKey = charimg; + customChar = false; + break; + } + + checkSkin++; + } + + if (customChar == true) + { + // Use the custom character icon! + discordPresence.smallImageKey = "charcustom"; + } + + snprintf(charname, 28, "Character: %s", skins[players[consoleplayer].skin].realname); + discordPresence.smallImageText = charname; // Character name + } + + if (joinSecretSet == false) + { + // Not able to join? Flush the request list, if it exists. + DRPC_EmptyRequests(); + } + + Discord_UpdatePresence(&discordPresence); +} + +#endif // HAVE_DISCORDRPC diff --git a/src/discord.h b/src/discord.h new file mode 100644 index 000000000..a6bb1134a --- /dev/null +++ b/src/discord.h @@ -0,0 +1,80 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2018-2020 by Sally "TehRealSalt" Cochenour. +// Copyright (C) 2018-2020 by Kart Krew. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file discord.h +/// \brief Discord Rich Presence handling + +#ifndef __DISCORD__ +#define __DISCORD__ + +#ifdef HAVE_DISCORDRPC + +#include "discord_rpc.h" + +extern consvar_t cv_discordrp; +extern consvar_t cv_discordstreamer; +extern consvar_t cv_discordasks; + +extern struct discordInfo_s { + UINT8 maxPlayers; + boolean joinsAllowed; + boolean everyoneCanInvite; +} discordInfo; + +typedef struct discordRequest_s { + char *username; // Discord user name. + char *discriminator; // Discord discriminator (The little hashtag thing after the username). Separated for a "hide discriminators" cvar. + char *userID; // The ID of the Discord user, gets used with Discord_Respond() + + // HAHAHA, no. + // *Maybe* if it was only PNG I would boot up curl just to get AND convert this to Doom GFX, + // but it can *also* be a JEPG, WebP, or GIF :) + // Hey, wanna add ImageMagick as a dependency? :dying: + //patch_t *avatar; + + struct discordRequest_s *next; // Next request in the list. + struct discordRequest_s *prev; // Previous request in the list. Not used normally, but just in case something funky happens, this should repair the list. +} discordRequest_t; + +extern discordRequest_t *discordRequestList; + + +/*-------------------------------------------------- + void DRPC_RemoveRequest(void); + + Removes an invite from the list. +--------------------------------------------------*/ + +void DRPC_RemoveRequest(discordRequest_t *removeRequest); + + +/*-------------------------------------------------- + void DRPC_Init(void); + + Initalizes Discord Rich Presence by linking the Application ID + and setting the callback functions. +--------------------------------------------------*/ + +void DRPC_Init(void); + + +/*-------------------------------------------------- + void DRPC_UpdatePresence(void); + + Updates what is displayed by Rich Presence on the user's profile. + Should be called whenever something that is displayed is + changed in-game. +--------------------------------------------------*/ + +void DRPC_UpdatePresence(void); + + +#endif // HAVE_DISCORDRPC + +#endif // __DISCORD__ diff --git a/src/djgppdos/Makefile.cfg b/src/djgppdos/Makefile.cfg deleted file mode 100644 index 857a7267b..000000000 --- a/src/djgppdos/Makefile.cfg +++ /dev/null @@ -1,48 +0,0 @@ -# -# djgppdos/makefile.cfg for SRB2/DOS -# - -# -#now for the DOS stuff, go DOS! -# - - # options - OPTS=-DPC_DOS - WFLAGS+=-Wno-cast-qual - NOHW=1 - NOHS=1 - PNG_CFLAGS= - PNG_LDFLAGS=-lpng -lz - -ifdef WATTCP - OPTS+=-DWATTCP - NOOBJDUMP=1 -endif - -#ifdef DEBUGMODE - LIBS=-lalld -#else -# LIBS=-lalleg -#endif - -ifndef NONET -ifdef WATTCP - LIBS+=-lwatt -else - LIBS+=-lsocket -endif -endif - -ifdef RDB - LIBS+=-lgdbst -ldzcom - OPTS+=-DREMOTE_DEBUGGING -endif - - OBJS=$(OBJDIR)/i_video.o $(OBJDIR)/vid_vesa.o - - # name of the exefile -ifdef WATTCP - EXENAME?=srb2dos.exe -else - EXENAME?=srb2w16.exe -endif diff --git a/src/djgppdos/bcd.c b/src/djgppdos/bcd.c deleted file mode 100644 index 6a91c707f..000000000 --- a/src/djgppdos/bcd.c +++ /dev/null @@ -1,755 +0,0 @@ -/* bcd.c -- Brennan's CD-ROM Audio Playing Library - by Brennan Underwood, http://brennan.home.ml.org/ */ -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef STANDALONE -#include /* for getch() */ -#endif - -#include "bcd.h" - -typedef struct { - int is_audio; - int start, end, len; -} Track; - -static int mscdex_version; -static int first_drive; -static int num_tracks; -static int lowest_track, highest_track; -static int audio_length; - -#ifdef STATIC_TRACKS -static Track tracks[99]; -#else -static Track *tracks; -#endif - -static int dos_mem_segment, dos_mem_selector = -1; - -int _status, _error, _error_code; -const char *_bcd_error = NULL; - -#define RESET_ERROR (_error = _error_code = 0) -#define ERROR_BIT (1 << 15) -#define BUSY_BIT (1 << 9) -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif - -#pragma pack(1) - -/* I know 'typedef struct {} bleh' is a bad habit, but... */ -typedef struct { - unsigned char len; - unsigned char unit; - unsigned char command; - unsigned short status; - unsigned char reserved[8]; -} ATTRPACK RequestHeader; - -typedef struct { - RequestHeader request_header; - unsigned char descriptor; - unsigned long address; - unsigned short len; - unsigned short secnum; - unsigned long ptr; -} ATTRPACK IOCTLI; - -typedef struct { - unsigned char control; - unsigned char lowest; - unsigned char highest; - char total[4]; -} ATTRPACK DiskInfo; - -typedef struct { - unsigned char control; - unsigned char track_number; - char start[4]; - unsigned char info; -} ATTRPACK TrackInfo; - -typedef struct { - RequestHeader request; - unsigned char mode; - unsigned long start; - unsigned long len; -} ATTRPACK PlayRequest; - -typedef struct { - RequestHeader request; -} ATTRPACK StopRequest; - -typedef struct { - RequestHeader request; -} ATTRPACK ResumeRequest; - -typedef struct { - unsigned char control; - unsigned char input0; - unsigned char volume0; - unsigned char input1; - unsigned char volume1; - unsigned char input2; - unsigned char volume2; - unsigned char input3; - unsigned char volume3; -} ATTRPACK VolumeRequest; - -typedef struct { - unsigned char control; - unsigned char fn; -} ATTRPACK LockRequest; - -typedef struct { - unsigned char control; - unsigned char mbyte; -} ATTRPACK MediaChangedRequest; - -typedef struct { - unsigned char control; - unsigned long status; -} ATTRPACK StatusRequest; - -typedef struct { - unsigned char control; - unsigned char mode; - unsigned long loc; -} ATTRPACK PositionRequest; - -#pragma pack() - -#ifdef __cplusplus -extern "C" { -#endif - -const char *bcd_error(void) { - static char retstr[132]; - const char *errorcodes[] = { - "Write-protect violation", - "Unknown unit", - "Drive not ready", - "Unknown command", - "CRC error", - "Bad drive request structure length", - "Seek error", - "Unknown media", - "Sector not found", - "Printer out of paper: world coming to an end",/* I mean really, on a CD? */ - "Write fault", - "Read fault", - "General failure", - "Reserved", - "Reserved", - "Invalid disk change" - }; - *retstr = 0; - if (_error != 0) { - strcat(retstr, "Device error: "); - if (_error_code < 0 || _error_code > 0xf) - strcat(retstr, "Invalid error"); - else - strcat(retstr, errorcodes[_error_code]); - strcat(retstr, " "); - } - if (_bcd_error != NULL) { - if (*retstr) strcat(retstr, ", "); - strcat(retstr, "BCD error: "); - strcat(retstr, _bcd_error); - } - return retstr; -} - -/* DOS IOCTL w/ command block */ -static void bcd_ioctl(IOCTLI *ioctli, void *command, int len) { - int ioctli_len = sizeof (IOCTLI); - unsigned long command_address = dos_mem_segment << 4; - __dpmi_regs regs; - - memset(®s, 0, sizeof regs); - regs.x.es = (__tb >> 4) & 0xffff; - regs.x.ax = 0x1510; - regs.x.bx = __tb & 0xf; - regs.x.cx = first_drive; - ioctli->address = dos_mem_segment << 16; - ioctli->len = len; - dosmemput(ioctli, ioctli_len, __tb); /* put ioctl into dos area */ - dosmemput(command, len, command_address); /* and command too */ - if (__dpmi_int(0x2f, ®s) == -1) { - _bcd_error = "__dpmi_int() failed"; - return; - } - dosmemget(__tb, ioctli_len, ioctli); /* retrieve results */ - dosmemget(command_address, len, command); - _status = ioctli->request_header.status; - if (_status & ERROR_BIT) { - _error = TRUE; - _error_code = _status & 0xff; - } else { - _error = FALSE; - _error_code = 0; - } -} - -/* no command block */ -FUNCINLINE static ATTRINLINE void bcd_ioctl2(void *cmd, int len) { - __dpmi_regs regs; - memset(®s, 0, sizeof regs); - regs.x.es = (__tb >> 4) & 0xffff; - regs.x.ax = 0x1510; - regs.x.bx = __tb & 0xf; - regs.x.cx = first_drive; - dosmemput(cmd, len, __tb); /* put ioctl block in dos arena */ - if (__dpmi_int(0x2f, ®s) == -1) { - _bcd_error = "__dpmi_int() failed"; - return; - } - /* I hate to have no error capability for ioctl2 but the command block - doesn't necessarily have a status field */ - RESET_ERROR; -} - -FUNCINLINE static ATTRINLINE int red2hsg(char *r) { - return r[0] + r[1]*75 + r[2]*4500 - 150; -} - -int bcd_now_playing(void) { - int i, loc = bcd_audio_position(); - _bcd_error = NULL; - if (!bcd_audio_busy()) { - _bcd_error = "Audio not playing"; - return 0; - } - if ( -#ifndef STATIC_TRACKS - tracks == NULL && -#endif - !bcd_get_audio_info()) - return 0; - for (i = lowest_track; i <= highest_track; i++) { - if (loc >= tracks[i].start && loc <= tracks[i].end) return i; - } - /* some bizarre location? */ - _bcd_error = "Head outside of bounds"; - return 0; -} - -/* handles the setup for CD-ROM audio interface */ -int bcd_open(void) { - __dpmi_regs regs; - _bcd_error = NULL; - - /* disk I/O wouldn't work anyway if you set sizeof tb this low, but... */ - if (_go32_info_block.size_of_transfer_buffer < 4096) { - _bcd_error = "Transfer buffer too small"; - return 0; - } - - memset(®s, 0, sizeof regs); - regs.x.ax = 0x1500; - regs.x.bx = 0x0; - __dpmi_int(0x2f, ®s); - if (regs.x.bx == 0) { /* abba no longer lives */ - _bcd_error = "MSCDEX not found"; - return 0; - } - - first_drive = regs.x.cx; /* use the first drive */ - - /* check for mscdex at least 2.0 */ - memset(®s, 0, sizeof regs); - regs.x.ax = 0x150C; - __dpmi_int(0x2f, ®s); - if (regs.x.bx == 0) { - _bcd_error = "MSCDEX version < 2.0"; - return 0; - } - mscdex_version = regs.x.bx; - - /* allocate 256 bytes of dos memory for the command blocks */ - if ((dos_mem_segment = __dpmi_allocate_dos_memory(16, &dos_mem_selector))<0) { - _bcd_error = "Could not allocate 256 bytes of DOS memory"; - return 0; - } - - return mscdex_version; -} - -/* Shuts down CD-ROM audio interface */ -int bcd_close(void) { - _bcd_error = NULL; - if (dos_mem_selector != -1) { - __dpmi_free_dos_memory(dos_mem_selector); - dos_mem_selector = -1; - } -#ifndef STATIC_TRACKS - if (tracks) free(tracks); - tracks = NULL; -#endif - RESET_ERROR; - return 1; -} - -int bcd_open_door(void) { - IOCTLI ioctli; - char eject = 0; - _bcd_error = NULL; - memset(&ioctli, 0, sizeof ioctli); - ioctli.request_header.len = sizeof ioctli; - ioctli.request_header.command = 12; - ioctli.len = 1; - bcd_ioctl(&ioctli, &eject, sizeof eject); - if (_error) return 0; - return 1; -} - -int bcd_close_door(void) { - IOCTLI ioctli; - char closeit = 5; - _bcd_error = NULL; - memset(&ioctli, 0, sizeof ioctli); - ioctli.request_header.len = sizeof ioctli; - ioctli.request_header.command = 12; - ioctli.len = 1; - bcd_ioctl(&ioctli, &closeit, sizeof closeit); - if (_error) return 0; - return 1; -} - -int bcd_lock(int fn) { - IOCTLI ioctli; - LockRequest req; - _bcd_error = NULL; - memset(&ioctli, 0, sizeof ioctli); - memset(&req, 0, sizeof req); - ioctli.request_header.len = sizeof ioctli; - ioctli.request_header.command = 12; - ioctli.len = sizeof req; - req.control = 1; - req.fn = fn ? 1 : 0; - bcd_ioctl(&ioctli, &req, sizeof req); - if (_error) return 0; - return 1; -} - - -int bcd_disc_changed(void) { - IOCTLI ioctli; - MediaChangedRequest req; - _bcd_error = NULL; - memset(&ioctli, 0, sizeof ioctli); - memset(&req, 0, sizeof req); - ioctli.request_header.len = sizeof ioctli; - ioctli.request_header.command = 3; - ioctli.len = sizeof req; - req.control = 9; - bcd_ioctl(&ioctli, &req, sizeof req); - return req.mbyte; -} - -int bcd_reset(void) { - IOCTLI ioctli; - char reset = 2; - _bcd_error = NULL; - - memset(&ioctli, 0, sizeof ioctli); - ioctli.request_header.len = sizeof ioctli; - ioctli.request_header.command = 12; - ioctli.len = 1; - bcd_ioctl(&ioctli, &reset, sizeof reset); - if (_error) return 0; - return 1; -} - -int bcd_device_status(void) { - IOCTLI ioctli; - StatusRequest req; - _bcd_error = NULL; - memset(&ioctli, 0, sizeof ioctli); - memset(&req, 0, sizeof req); - ioctli.request_header.len = sizeof ioctli; // ok - ioctli.request_header.command = 3; - ioctli.len = sizeof req; - req.control = 6; - bcd_ioctl(&ioctli, &req, sizeof req); - return req.status; -} - -static inline int bcd_get_status_word(void) { - IOCTLI ioctli; - DiskInfo disk_info; - - /* get cd info as an excuse to get a look at the status word */ - memset(&disk_info, 0, sizeof disk_info); - memset(&ioctli, 0, sizeof ioctli); - - ioctli.request_header.len = 26; - ioctli.request_header.command = 3; - ioctli.len = 7; - disk_info.control = 10; - bcd_ioctl(&ioctli, &disk_info, sizeof disk_info); - return _status; -} - -int bcd_audio_busy(void) { - _bcd_error = NULL; - /* If the door is open, then the head is busy, and so the busy bit is - on. It is not, however, playing audio. */ - if (bcd_device_status() & BCD_DOOR_OPEN) - return 0; - - bcd_get_status_word(); - if (_error) return -1; - return (_status & BUSY_BIT) ? 1 : 0; -} - -int bcd_audio_position(void) { - IOCTLI ioctli; - PositionRequest req; - _bcd_error = NULL; - memset(&ioctli, 0, sizeof ioctli); - memset(&req, 0, sizeof req); - ioctli.request_header.len = sizeof ioctli; - ioctli.request_header.command = 3; - ioctli.len = sizeof req; - req.control = 1; - bcd_ioctl(&ioctli, &req, sizeof req); - return req.loc; -} - -/* Internal function to get track info */ -static inline void bcd_get_track_info(int n, Track *t) { - IOCTLI ioctli; - TrackInfo info; - - memset(&ioctli, 0, sizeof ioctli); - memset(&info, 0, sizeof info); - ioctli.request_header.len = sizeof ioctli; - ioctli.request_header.command = 3; - info.control = 11; - info.track_number = n; - bcd_ioctl(&ioctli, &info, sizeof info); - t->start = red2hsg(info.start); - if (info.info & 64) - t->is_audio = 0; - else - t->is_audio = 1; -} - -int bcd_get_audio_info(void) { - IOCTLI ioctli; - DiskInfo disk_info; - int i; - - - _bcd_error = NULL; -#ifndef STATIC_TRACKS - if (tracks) free(tracks); - tracks = NULL; -#endif - - memset(&disk_info, 0, sizeof disk_info); - memset(&ioctli, 0, sizeof ioctli); - - ioctli.request_header.len = 26; - ioctli.request_header.command = 3; - ioctli.len = 7; - disk_info.control = 10; - bcd_ioctl(&ioctli, &disk_info, sizeof disk_info); - if (_error) return 0; - - lowest_track = disk_info.lowest; - highest_track = disk_info.highest; - num_tracks = disk_info.highest - disk_info.lowest + 1; - -#ifndef STATIC_TRACKS - //tracks = calloc(num_tracks, sizeof (Track)); - /* alloc max space in order to attempt to avoid possible overrun bug */ - tracks = calloc(highest_track+1, sizeof (Track)); - if (tracks == NULL) { - _bcd_error = "Out of memory allocating tracks\n"; - return 0; - } -#endif - - /* get track starts */ - for (i = lowest_track; i <= highest_track; i++) - bcd_get_track_info(i, tracks+i); - - /* figure out track ends */ - for (i = lowest_track; i < highest_track; i++) - tracks[i].end = tracks[i+1].start-1; - audio_length = red2hsg(disk_info.total); - tracks[i].end = audio_length; - for (i = lowest_track; i <= highest_track; i++) - tracks[i].len = tracks[i].end - tracks[i].start; - - return num_tracks; -} - -int bcd_get_track_address(int trackno, int *start, int *len) { - _bcd_error = NULL; - //if (trackno >= num_tracks+1 || trackno <= 0) { - if (trackno < lowest_track || trackno > highest_track) { - _bcd_error = "Track out of range"; - *start = *len = 0; - return 0; - } - *start = tracks[trackno].start; - *len = tracks[trackno].len; - return 1; -} - -int bcd_track_is_audio(int trackno) { - //if (trackno >= num_tracks+1 || trackno <= 0) { - if (trackno < lowest_track || trackno > highest_track) { - _bcd_error = "Track out of range"; - return 0; - } - return tracks[trackno].is_audio; -} - -int bcd_set_volume(int volume) { - IOCTLI ioctli; - VolumeRequest v; - - _bcd_error = NULL; - if (volume > 255) volume = 255; - else if (volume < 0) volume = 0; - memset(&ioctli, 0, sizeof ioctli); - ioctli.request_header.len = sizeof ioctli; - ioctli.request_header.command = 12; - ioctli.len = sizeof v; - v.control = 3; - v.volume0 = volume; - v.input0 = 0; - v.volume1 = volume; - v.input1 = 1; - v.volume2 = volume; - v.input2 = 2; - v.volume3 = volume; - v.input3 = 3; - - bcd_ioctl(&ioctli, &v, sizeof v); - if (_error) return 0; - return 1; -} - -int bcd_play(int location, int frames) { - PlayRequest cmd; - memset(&cmd, 0, sizeof cmd); - - _bcd_error = NULL; - /* the following should be in user code, but it'll fail otherwise */ - if (bcd_audio_busy()) - bcd_stop(); - - cmd.request.len = sizeof cmd; - cmd.request.command = 132; - cmd.start = location; - cmd.len = frames; - bcd_ioctl2(&cmd, sizeof cmd); - if (_error) return 0; - return 1; -} - -int bcd_play_track(int trackno) { - _bcd_error = NULL; - if (!bcd_get_audio_info()) return 0; - - if (trackno < lowest_track || trackno > highest_track) { - _bcd_error = "Track out of range"; - return 0; - } - - if (! tracks[trackno].is_audio) { - _bcd_error = "Not an audio track"; - return 0; - } - - return bcd_play(tracks[trackno].start, tracks[trackno].len); -} - -int bcd_stop(void) { - StopRequest cmd; - _bcd_error = NULL; - memset(&cmd, 0, sizeof cmd); - cmd.request.len = sizeof cmd; - cmd.request.command = 133; - bcd_ioctl2(&cmd, sizeof cmd); - if (_error) return 0; - return 1; -} - -int bcd_resume(void) { - ResumeRequest cmd; - _bcd_error = NULL; - memset(&cmd, 0, sizeof cmd); - cmd.request.len = sizeof cmd; - cmd.request.command = 136; - bcd_ioctl2(&cmd, sizeof cmd); - if (_error) return 0; - return 1; -} - -#ifdef __cplusplus -} -#endif - -#ifdef STANDALONE -static char *card(int c) { - return c == 1 ? "" : "s"; -} - -static void print_hsg(int hsg) { - int hours, minutes, seconds; - seconds = hsg / 75; - minutes = seconds / 60; - seconds %= 60; - hours = minutes / 60; - minutes %= 60; - printf("%2d:%02d:%02d", hours, minutes, seconds); -} - -static void print_binary(int v, int len) { - for (;len;len--) - printf("%d", (v & (1 << len)) ? 1 : 0); -} - -int main(int argc, char *argv[]) { - int i, n1, n2, t; - - if (!bcd_open()) { - fprintf(stderr, "Couldn't open CD-ROM drive. %s\n", bcd_error()); - exit(0); - } - - for (i = 1; i < argc; i++) { - if (*argv[i] == '-') strcpy(argv[i], argv[i]+1); - if (!strcmp(argv[i], "open") || !strcmp(argv[i], "eject")) { - bcd_open_door(); - } else if (!strcmp(argv[i], "close")) { - bcd_close_door(); - } else if (!strcmp(argv[i], "sleep")) { - if (++i >= argc) break; - sleep(atoi(argv[i])); - } else if (!strcmp(argv[i], "list")) { - int nd = 0, na = 0, audio_time = 0; - if (!bcd_get_audio_info()) { - printf("Error getting audio info\n"); - } else if (lowest_track == 0) { - printf("No audio tracks\n"); - } else { - for (t = lowest_track; t <= highest_track; t++) { - printf("Track %2d: ", t); - print_hsg(tracks[t].start); - printf(" -> "); - print_hsg(tracks[t].end); - printf(" ("); - print_hsg(tracks[t].len); - if (tracks[t].is_audio) { - na++; - printf(") audio"); - audio_time += tracks[t].len; - } else { - nd++; - printf(") data "); - } - printf(" (HSG: %06d->%06d)\n", tracks[t].start, tracks[t].end); - } - printf("%d audio track%s, %d data track%s\n", na, card(na), nd, card(nd)); - if (audio_time) { - printf("Audio time: "); - print_hsg(audio_time); - printf("\n"); - } - } - } else if (!strcmp(argv[i], "lock")) { - bcd_lock(1); - } else if (!strcmp(argv[i], "pladdr")) { - if (++i >= argc) break; - n1 = atoi(argv[i]); - if (++i >= argc) break; - n2 = atoi(argv[i]); - printf("Playing frame %d to frame %d\n", n1, n2); - bcd_play(n1, n2-n1); - } else if (!strcmp(argv[i], "play")) { - if (++i >= argc) break; - if (bcd_audio_busy()) { - bcd_stop(); - delay(1000); - } - n1 = atoi(argv[i]); - printf("Playing track %d\n", n1); - bcd_play_track(n1); - } else if (!strcmp(argv[i], "reset")) { - bcd_reset(); - } else if (!strcmp(argv[i], "resume")) { - bcd_resume(); - } else if (!strcmp(argv[i], "status")) { - int s; - s = bcd_device_status(); - printf("MSCDEX version %d.%d\n", mscdex_version >> 8, - mscdex_version & 0xff); - printf("Device status word '"); - print_binary(s, 16); - printf("'\nDoor is %sopen\n", s & BCD_DOOR_OPEN ? "" : "not "); - printf("Door is %slocked\n", s & BCD_DOOR_UNLOCKED ? "not " : ""); - printf("Audio is %sbusy\n", bcd_audio_busy() ? "" : "not "); - s = bcd_disc_changed(); - if (s == BCD_DISC_UNKNOWN) printf("Media change status unknown\n"); - else printf("Media has %schanged\n", - (s == BCD_DISC_CHANGED) ? "" : "not "); - } else if (!strcmp(argv[i], "stop")) { - bcd_stop(); - } else if (!strcmp(argv[i], "unlock")) { - bcd_lock(0); - } else if (!strcmp(argv[i], "volume")) { - bcd_set_volume(atoi(argv[++i])); - } else if (!strcmp(argv[i], "wait")) { - while (bcd_audio_busy()) { - int n = bcd_now_playing(); - if (n == 0) break; - printf("%2d: ", n); - print_hsg(bcd_audio_position() - tracks[n].start); - printf("\r"); - fflush(stdout); - delay(100); - if (kbhit() && getch() == 27) break; - } - printf("\n"); - } else if (!strcmp(argv[i], "help") || !strcmp(argv[i], "usage")) { - printf("BCD version %x.%x\n" \ - "Usage: BCD {commands}\n" \ - "Valid commands:\n" \ - "\tclose - close door/tray\n" \ - "\tdelay {n} - delay {n} seconds\n" \ - "\tlist - list track info\n" \ - "\tlock - lock door/tray\n" \ - "\topen - open door/tray\n" \ - "\tpladdr {n1} {n2}- play frame {n1} to {n2}\n" \ - "\tplay {n} - play track {n}\n" \ - "\treset - reset the drive\n" \ - "\tresume - resume from last stop\n" \ - "\tstatus - show drive status\n" \ - "\tstop - stop audio playback\n" \ - "\tunlock - unlock door/tray\n" \ - "\tvolume {n} - set volume to {n} where 0 <= {n} <= 255\n", - BCD_VERSION >> 8, BCD_VERSION & 0xff); - } else - printf("Unknown command '%s'\n", argv[i]); - if (_error || _bcd_error) printf("%s\n", bcd_error()); - } - bcd_close(); - exit(0); -} -#endif diff --git a/src/djgppdos/bcd.h b/src/djgppdos/bcd.h deleted file mode 100644 index 3997128a2..000000000 --- a/src/djgppdos/bcd.h +++ /dev/null @@ -1,90 +0,0 @@ -/* bcd.h -- header file for BCD, a CD-ROM audio playing library for DJGPP - by Brennan Underwood, http://brennan.home.ml.org/ */ -#ifndef _BCD_H -#define _BCD_H - -#define BCD_VERSION 0x0103 - -/* Installation and setup functions */ -/* Call this first! */ -int bcd_open(void); -/* Call before exit. */ -int bcd_close(void); - -/* open door, unlocking first if necessary */ -int bcd_open_door(void); -/* close door */ -int bcd_close_door(void); - -/* pass 1 to lock door, 0 to unlock */ -int bcd_lock(int); - -/* returns one of the following 3 #defined symbols */ -int bcd_disc_changed(void); -#define BCD_DISC_CHANGED 0xff -#define BCD_DISC_NOT_CHANGED 1 -#define BCD_DISC_UNKNOWN 0 - -/* perform a device reset */ -int bcd_reset(void); - -/* compare the returned status int to the following bits */ -int bcd_device_status(void); -#define BCD_DOOR_OPEN 1 -#define BCD_DOOR_UNLOCKED 2 -#define BCD_SUPPORT_COOKED 4 -#define BCD_READ_ONLY 8 -#define BCD_DATA_READ_ONLY 16 -#define BCD_SUPPORT_INTERLEAVE 32 - -/* returns 1 if audio is currently playing, 0 otherwise. -1 on error */ -int bcd_audio_busy(void); -/* current head position in frames */ -int bcd_audio_position(void); -/* convenience function, if audio busy, returns track# playing now */ -int bcd_now_playing(void); - -/* query MSCDEX for track list when disc changed or just starting up */ -int bcd_get_audio_info(void); -/* get a particular track's info */ -int bcd_get_track_address(int trackno, int *start, int *len); -/* check for track's audio/data status */ -int bcd_track_is_audio(int trackno); -/* play a particular track from beginning to end */ -int bcd_play_track(int tracknum); -/* play an arbitrary section of audio for an arbitrary length of time */ -int bcd_play(int start, int len); -/* set the output volume. pass a parameter from 0-255 */ -int bcd_set_volume(int); -/* stop and pause are equivalent */ -int bcd_stop(void); -#define bcd_pause bcd_stop -int bcd_resume(void); - -/* Troubleshooting */ -/* Returns a human readable description of the last error encountered */ -const char *bcd_error(void); -extern int _error_code; -/* If you are mad enough play the Rach 3, I mean parse _error_code yourself */ -#define BCD_DE_WRITE_PROTECT 0 -#define BCD_DE_UNKNOWN_UNIT 1 -#define BCD_DE_DRIVE_NOT_READY 2 -#define BCD_DE_UNKNOWN_COMMAND 3 -#define BCD_DE_CRC_ERROR 4 -#define BCD_DE_STRUCT_LEN 5 -#define BCD_DE_SEEK_ERROR 6 -#define BCD_DE_UNKNOWN_MEDIA 7 -#define BCD_DE_SECTOR_NOT_FOUND 8 -#define BCD_DE_OUT_OF_PAPER 9 -#define BCD_DE_WRITE_FAULT 10 -#define BCD_DE_READ_FAULT 11 -#define BCD_DE_GENERAL_FAILURE 12 -#define BCD_DE_INVALID_DISK_CHANGE 15 -/* set by BCD itself, for stuff like "Out of memory" */ -extern const char *_bcd_error; - -/* uncomment this line to force BCD to use a statically allocated - Track array instead of using malloc */ -#define STATIC_TRACKS - -#endif diff --git a/src/djgppdos/i_cdmus.c b/src/djgppdos/i_cdmus.c deleted file mode 100644 index 2a629ca17..000000000 --- a/src/djgppdos/i_cdmus.c +++ /dev/null @@ -1,445 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief cd music interface (uses bcd library) - -// Alam_GBC: I hate you, Brennan Underwood :) -#include "../doomtype.h" -#include "bcd.c" -//#include "bcd.h" // CD-Audio library by Brennan Underwood - -#include "../doomdef.h" -#include "../i_sound.h" -#include "../command.h" -#include "../i_system.h" -#include "../s_sound.h" - -// ------ -// protos -// ------ -static void Command_Cd_f (void); - - -//====================================================================== -// CD AUDIO MUSIC SUBSYSTEM -//====================================================================== - -UINT8 cdaudio_started=0; // for system startup/shutdown - -#define MAX_CD_TRACKS 256 -static boolean cdPlaying = false; -static int cdPlayTrack; // when cdPlaying is true -static boolean cdLooping = false; -static UINT8 cdRemap[MAX_CD_TRACKS]; -static boolean cdEnabled=true; // cd info available -static boolean cdValid; // true when last cd audio info was ok -static boolean wasPlaying; -static int cdVolume=0; // current cd volume (0-31) - -// 0-31 like Music & Sfx, though CD hardware volume is 0-255. -consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - -// allow Update for next/loop track -// some crap cd drivers take up to -// a second for a simple 'busy' check.. -// (on those Update can be disabled) -consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; - - -// hour,minutes,seconds -FUNCINLINE static ATTRINLINE char *hms(int hsg) -{ - int hours, minutes, seconds; - static char s[9]; - - seconds = hsg / 75; - minutes = seconds / 60; - seconds %= 60; - hours = minutes / 60; - minutes %= 60; - if (hours>0) - sprintf (s, "%d:%02d:%02d", hours, minutes, seconds); - else - sprintf (s, "%2d:%02d", minutes, seconds); - return s; -} - -static void Command_Cd_f (void) -{ - const char * s; - int i,j; - - if (!cdaudio_started) - return; - - if (COM_Argc()<2) - { - CONS_Printf ("cd [on] [off] [remap] [reset] [open]\n" - " [info] [play ] [loop ]\n" - " [stop] [resume]\n"); - return; - } - - s = COM_Argv(1); - - // activate cd music - if (!strncmp(s,"on",2)) - { - cdEnabled = true; - return; - } - - // stop/deactivate cd music - if (!strncmp(s,"off",3)) - { - if (cdPlaying) - I_StopCD (); - cdEnabled = false; - return; - } - - // remap tracks - if (!strncmp(s,"remap",5)) - { - i = COM_Argc() - 2; - if (i <= 0) - { - CONS_Printf ("CD tracks remapped in that order :\n"); - for (j = 1; j < MAX_CD_TRACKS; j++) - if (cdRemap[j] != j) - CONS_Printf (" %2d -> %2d\n", j, cdRemap[j]); - return; - } - for (j = 1; j <= i; j++) - cdRemap[j] = atoi (COM_Argv (j+1)); - return; - } - - // reset the CD driver, useful on some odd cd's - if (!strncmp(s,"reset",5)) - { - cdEnabled = true; - if (cdPlaying) - I_StopCD (); - for (i = 0; i < MAX_CD_TRACKS; i++) - cdRemap[i] = i; - bcd_reset (); - cdValid = bcd_get_audio_info (); - return; - } - - // any other command is not allowed until we could retrieve cd information - if (!cdValid) - { - CONS_Printf ("CD is not ready.\n"); - return; - } - - if (!strncmp(s,"open",4)) - { - if (cdPlaying) - I_StopCD (); - bcd_open_door(); - cdValid = false; - return; - } - - if (!strncmp(s,"info",4)) - { - int totaltime = 0; - - if (!bcd_get_audio_info()) - { - CONS_Printf ("Error getting audio info: %s\n",bcd_error()); - cdValid = false; - return; - } - - cdValid = true; - - if (lowest_track == 0) - CONS_Printf ("No audio tracks\n"); - else - { - // display list of tracks - // highlight current playing track - for (i=lowest_track; i <= highest_track; i++) - { - CONS_Printf ("%s%2d. %s %s\n", - cdPlaying && (cdPlayTrack == i) ? "\2 " : " ", - i, tracks[i].is_audio ? "audio" : "data ", - hms(tracks[i].len)); - if (tracks[i].is_audio) - totaltime += tracks[i].len; - } - - if (totaltime) - CONS_Printf ("\2Total time : %s\n", hms(totaltime)); - } - if (cdPlaying) - { - CONS_Printf ("%s track : %d\n", cdLooping ? "looping" : "playing", - cdPlayTrack); - } - return; - } - - if (!strncmp(s,"play",4)) - { - I_PlayCD ((UINT8)atoi (COM_Argv (2)), false); - return; - } - - if (!strncmp(s,"stop",4)) - { - I_StopCD (); - return; - } - - if (!strncmp(s,"loop",4)) - { - I_PlayCD ((UINT8)atoi (COM_Argv (2)), true); - return; - } - - if (!strncmp(s,"resume",4)) - { - I_ResumeCD (); - return; - } - - CONS_Printf ("cd command '%s' unknown\n", s); -} - - -// pause cd music -void I_StopCD (void) -{ - if (!cdaudio_started || !cdEnabled) - return; - - bcd_stop(); - - wasPlaying = cdPlaying; - cdPlaying = false; -} - -// continue after a pause -void I_ResumeCD (void) -{ - if (!cdaudio_started || !cdEnabled) - return; - - if (!cdValid) - return; - - if (!wasPlaying) - return; - - bcd_resume (); - cdPlaying = true; -} - - -void I_ShutdownCD (void) -{ - int rc; - - if (!cdaudio_started) - return; - - I_StopCD (); - - rc = bcd_close (); - if (!rc) - CONS_Printf ("Error shuting down cd\n"); -} - -void I_InitCD (void) -{ - int rc; - int i; - - rc = bcd_open (); - - if (rc>=0x200) - { - CONS_Printf ("MSCDEX version %d.%d\n", rc>>8, rc&255); - - I_AddExitFunc (I_ShutdownCD); - cdaudio_started = true; - } - else - { - if (!rc) - CONS_Printf ("%s\n", bcd_error() ); - - cdaudio_started = false; - return; - } - - // last saved in config.cfg - i = cd_volume.value; - I_SetVolumeCD (0); // initialize to 0 for some odd cd drivers - I_SetVolumeCD (i); // now set the last saved volume - - for (i = 0; i < MAX_CD_TRACKS; i++) - cdRemap[i] = i; - - if (!bcd_get_audio_info()) - { - CONS_Printf("\2CD Init: No CD in player.\n"); - cdEnabled = false; - cdValid = false; - } - else - { - cdEnabled = true; - cdValid = true; - } - - COM_AddCommand ("cd", Command_Cd_f); -} - - - -// loop/go to next track when track is finished (if cd_update var is true) -// update the volume when it has changed (from console/menu) -/// \todo check for cd change and restart music ? - -void I_UpdateCD (void) -{ - int newVolume; - int now; - static int last; //game tics (35th of second) - - if (!cdaudio_started) - return; - - now = I_GetTime (); - if ((now - last) < 10) // about 1/4 second - return; - last = now; - - // update cd volume changed at console/menu - newVolume = cd_volume.value & 31; - - if (cdVolume != newVolume) - I_SetVolumeCD (newVolume); - - // slow drivers exit here - if (!cdUpdate.value) - return; - - if (cdPlaying) - { - if (!bcd_audio_busy()) - { - cdPlaying = false; - if (cdLooping) - I_PlayCD (cdPlayTrack, true); - else - { - // play the next cd track, or restart the first - cdPlayTrack++; - if (cdPlayTrack > highest_track) - cdPlayTrack = lowest_track; - while (!tracks[cdPlayTrack].is_audio && cdPlayTrack highest_track) - { - //CONS_Printf ("\2CD Audio: wrong track number %d\n", track); - // suppose there are not enough tracks for game levels.. - // then do a modulo so we always get something to hear - track = (track % (highest_track-lowest_track+1)) + 1; - //return; - } - - cdPlayTrack = track; - - if (!tracks[track].is_audio) - { - CONS_Printf ("\2CD Play: not an audio track\n"); - return; - } - - cdLooping = looping; - - if (!bcd_play_track (track)) - { - CONS_Printf ("CD Play: could not play track %d\n", track); - cdValid = false; - cdPlaying = false; - return; - } - - cdPlaying = true; - -} - - -// volume : logical cd audio volume 0-31 (hardware is 0-255) -boolean I_SetVolumeCD (INT32 volume) -{ - int hardvol; - - if (!cdaudio_started || !cdEnabled) - return false; - - // translate to hardware volume - volume &= 31; - - hardvol = ((volume+1)<<3)-1; //highest volume is 255 - if (hardvol<=8) - hardvol=0; //lowest volume is ZERO - - cdVolume = volume; - - if (bcd_set_volume (hardvol)) - { - CV_SetValue (&cd_volume, volume); - - return true; - } - else - return false; -} diff --git a/src/djgppdos/i_main.c b/src/djgppdos/i_main.c deleted file mode 100644 index 1b8894470..000000000 --- a/src/djgppdos/i_main.c +++ /dev/null @@ -1,78 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Main program, simply calls D_SRB2Main high level loop. - -#include "../doomdef.h" - -#include "../m_argv.h" -#include "../d_main.h" - -#include "../i_system.h" - -#ifdef REMOTE_DEBUGGING -#include -#include "rdb.h" -#endif - -//### let's try with Allegro ### -#define alleg_mouse_unused -#define alleg_timer_unused -#define ALLEGRO_NO_KEY_DEFINES -#define alleg_keyboard_unused -#define alleg_joystick_unused -#define alleg_gfx_driver_unused -#define alleg_palette_unused -#define alleg_graphics_unused -#define alleg_vidmem_unused -#define alleg_flic_unused -#define alleg_sound_unused -#define alleg_file_unused -#define alleg_datafile_unused -#define alleg_math_unused -#define alleg_gui_unused -#include -//### end of Allegro include ### - -int main (int argc, char **argv) -{ - myargc = argc; - myargv = argv; - - { - //added:03-01-98: - // Setup signal handlers and other stuff BEFORE ANYTHING ELSE! - I_StartupSystem(); -#ifdef REMOTE_DEBUGGING - /* Only setup if remote debugging is to be done, Muhahahaha!*/ - gdb_serial_init(DEBUG_COM_PORT,DEBUG_COM_PORT_SPEED); - gdb_target_init(); - breakpoint(); -#endif - - D_SRB2Main(); - D_SRB2Loop(); - - } - //added:03-01-98: - // hmmm... it will never go here. - - return 0; -} -#if ALLEGRO_VERSION == 4 -END_OF_MAIN() -#endif diff --git a/src/djgppdos/i_net.c b/src/djgppdos/i_net.c deleted file mode 100644 index 866aa8d8b..000000000 --- a/src/djgppdos/i_net.c +++ /dev/null @@ -1,113 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief doomcom network interface - - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../doomdef.h" - -#include "../i_system.h" -#include "../d_event.h" -#include "../d_net.h" -#include "../m_argv.h" - -#include "../doomstat.h" -#include "../z_zone.h" -#include "../i_net.h" -#include "../i_tcp.h" - -// -// NETWORKING -// - -typedef enum -{ - CMD_SEND = 1, - CMD_GET = 2, -} command_t; - -static void External_Driver_Get(void); -static void External_Driver_Send(void); -static void External_Driver_FreeNode(INT32 nodenum); - -static inline boolean External_Driver_OpenSocket(void) -{ - I_NetGet = External_Driver_Get; - I_NetSend = External_Driver_Send; - I_NetCloseSocket = NULL; - I_NetFreeNodenum = External_Driver_FreeNode; - - return true; -} - -// -// I_InitNetwork -// -boolean I_InitNetwork (void) -{ - int netgamepar; - - netgamepar = M_CheckParm ("-net"); - if (!netgamepar) - return false; - - // externals drivers specific - - __djgpp_nearptr_enable(); - - // set up for network - doomcom=(doomcom_t *)(__djgpp_conventional_base+atoi(myargv[netgamepar+1])); - CONS_Printf("I_DosNet : Using int 0x%x for communication\n",doomcom->intnum); - - server = (doomcom->consoleplayer == 0); - if (!server) - COM_BufAddText("connect any\n"); - - // ipx + time + 4 (padding) - packetheaderlength=30+4+4; - - hardware_MAXPACKETLENGTH = 512; - - I_NetOpenSocket = External_Driver_OpenSocket; - return true; -} - -FUNCNORETURN static ATTRNORETURN void External_Driver_Get(void) -{ - I_Error("External_Driver_Get not supported at this time"); -} - -FUNCNORETURN static ATTRNORETURN void External_Driver_Send(void) -{ - I_Error("External_Driver_Send not supported at this time"); -} - -FUNCNORETURN static ATTRNORETURN void External_Driver_FreeNode(INT32 nodenum) -{ - nodenum = 0; - I_Error("External_Driver_FreeNode not supported at this time"); -} diff --git a/src/djgppdos/i_sound.c b/src/djgppdos/i_sound.c deleted file mode 100644 index 88b598622..000000000 --- a/src/djgppdos/i_sound.c +++ /dev/null @@ -1,619 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief interface level code for sound - -#include -#include -#include - -#include - -#include "../doomdef.h" -#include "../doomstat.h" -#include "../i_system.h" -#include "../i_sound.h" -#include "../z_zone.h" -#include "../m_argv.h" -#include "../m_misc.h" -#include "../w_wad.h" -#include "../s_sound.h" -#include "../console.h" - -//### let's try with Allegro ### -#define alleg_mouse_unused -#define alleg_timer_unused -#define ALLEGRO_NO_KEY_DEFINES -#define alleg_keyboard_unused -#define alleg_joystick_unused -#define alleg_gfx_driver_unused -#define alleg_palette_unused -#define alleg_graphics_unused -#define alleg_vidmem_unused -#define alleg_flic_unused -//#define alleg_sound_unused we use it -#define alleg_file_unused -#define alleg_datafile_unused -#define alleg_math_unused -#define alleg_gui_unused -#include -//### end of Allegro include ### - -//allegro has 256 virtual voices -// warning should by a power of 2 -#define VIRTUAL_VOICES 256 -#define VOICESSHIFT 8 - -// Needed for calling the actual sound output. -#define SAMPLECOUNT 512 - - - -// -// this function converts raw 11khz, 8-bit data to a SAMPLE* that allegro uses -// it is need cuz allegro only loads samples from wavs and vocs -//added:11-01-98: now reads the frequency from the rawdata header. -// dsdata points a 4 UINT16 header: -// +0 : value 3 what does it mean? -// +2 : sample rate, either 11025 or 22050. -// +4 : number of samples, each sample is a single byte since it's 8bit -// +6 : value 0 -static inline SAMPLE *raw2SAMPLE(UINT8 *dsdata, size_t len) -{ - SAMPLE *spl; - - spl=Z_Malloc(sizeof (SAMPLE),PU_SOUND,NULL); - if (spl==NULL) - I_Error("Raw2Sample : no more free mem"); - spl->bits = 8; - spl->stereo = 0; - spl->freq = *((UINT16 *)dsdata+1); //mostly 11025, but some at 22050. - spl->len = len-8; - spl->priority = 255; //priority; - spl->loop_start = 0; - spl->loop_end = len-8; - spl->param = -1; - spl->data=(void *)(dsdata+8); //skip the 8bytes header - - return spl; -} - - -// This function loads the sound data from the WAD lump, -// for single sound. -// -void *I_GetSfx (sfxinfo_t * sfx) -{ - UINT8 *dssfx; - - if (sfx->lumpnum == LUMPERROR) - sfx->lumpnum = S_GetSfxLumpNum (sfx); - - sfx->length = W_LumpLength (sfx->lumpnum); - - dssfx = (UINT8 *) W_CacheLumpNum (sfx->lumpnum, PU_SOUND); - //_go32_dpmi_lock_data(dssfx,size); - - // convert raw data and header from Doom sfx to a SAMPLE for Allegro - return (void *)raw2SAMPLE (dssfx, sfx->length); -} - - -void I_FreeSfx (sfxinfo_t *sfx) -{ - if (sfx->lumpnum == LUMPERROR) - return; - - // free sample data - if ( sfx->data ) - Z_Free((UINT8 *) ((SAMPLE *)sfx->data)->data - 8); - Z_Free(sfx->data); // Allegro SAMPLE structure - sfx->data = NULL; - sfx->lumpnum = LUMPERROR; -} - -FUNCINLINE static ATTRINLINE int Volset(int vol) -{ - return (vol*255/31); -} - - -void I_SetSfxVolume(INT32 volume) -{ - if (sound_disabled) - return; - - set_volume (Volset(volume),-1); -} - -// -// Starting a sound means adding it -// to the current list of active sounds -// in the internal channels. -// As the SFX info struct contains -// e.g. a pointer to the raw data, -// it is ignored. -// As our sound handling does not handle -// priority, it is ignored. -// Pitching (that is, increased speed of playback) -// is set, but currently not used by mixing. -// -INT32 I_StartSound ( sfxenum_t id, - INT32 vol, - INT32 sep, - INT32 pitch, - INT32 priority, - INT32 channel) -{ - int voice; - (void)channel; - - if (sound_disabled) - return 0; - - // UNUSED - priority = 0; - - pitch = (pitch-128)/2+128; - voice = play_sample(S_sfx[id].data,vol,sep,(pitch*1000)/128,0); - - // Returns a handle - return (id<>VOICESSHIFT].data) - deallocate_voice(voice); -} - -INT32 I_SoundIsPlaying(INT32 handle) -{ - if (sound_disabled) - return FALSE; - - if (voice_check(handle & (VIRTUAL_VOICES-1))==S_sfx[handle>>VOICESSHIFT].data) - return TRUE; - - return FALSE; -} - -// cut and past from ALLEGRO he don't share it :( -static inline int absolute_freq(int freq, SAMPLE *spl) -{ - if (freq == 1000) - return spl->freq; - else - return (spl->freq * freq) / 1000; -} - -void I_UpdateSoundParams( INT32 handle, - INT32 vol, - INT32 sep, - INT32 pitch) -{ - // I fail too see that this is used. - // Would be using the handle to identify - // on which channel the sound might be active, - // and resetting the channel parameters. - int voice=handle & (VIRTUAL_VOICES-1); - int numsfx=handle>>VOICESSHIFT; - - if (sound_disabled) - return; - - if (voice_check(voice)==S_sfx[numsfx].data) - { - voice_set_volume(voice, vol); - voice_set_pan(voice, sep); - voice_set_frequency(voice, absolute_freq(pitch*1000/128, - S_sfx[numsfx].data)); - } -} - - -void I_ShutdownSound(void) -{ - // Wait till all pending sounds are finished. - - //added:03-01-98: - if ( !sound_started ) - return; - - //added:08-01-98: remove_sound() explicitly because we don't use - // Allegro's allegro_exit(); - remove_sound(); - sound_started = false; -} - -static char soundheader[] = "sound"; -#if ALLEGRO_VERSION == 3 -static char soundvar[] = "sb_freq"; -#else -static char soundvar[] = "sound_freq"; -#endif - -void I_StartupSound(void) -{ - int sfxcard,midicard; -#if ALLEGRO_VERSION == 3 - char err[255]; -#endif - - if (sound_disabled) - sfxcard=DIGI_NONE; - else - sfxcard=DIGI_AUTODETECT; - - if (midi_disabled) - midicard=MIDI_NONE; - else - midicard=MIDI_AUTODETECT; //DetectMusicCard(); - - digital_disabled=true; //Alam: No OGG/MP3/IT/MOD support - - // Secure and configure sound device first. - CONS_Printf("I_StartupSound: "); - - //Fab:25-04-98:note:install_sound will check for sound settings - // in the sound.cfg or allegro.cfg, in the current directory, - // or the directory pointed by 'ALLEGRO' env var. -#if ALLEGRO_VERSION == 3 - if (install_sound(sfxcard,midicard,NULL)!=0) - { - sprintf (err,"Sound init error : %s\n",allegro_error); - CONS_Error (err); - sound_disabled=true; - midi_disabled=true; - } - else - { - CONS_Printf(" configured audio device\n" ); - } - - //added:08-01-98:we use a similar startup/shutdown scheme as Allegro. - I_AddExitFunc(I_ShutdownSound); -#endif - sound_started = true; - CV_SetValue(&cv_samplerate,get_config_int(soundheader,soundvar,cv_samplerate.value)); -} - - - - -// -// MUSIC API. -// Still no music done. -// Remains. Dummies. -// - -static MIDI* currsong; //im assuming only 1 song will be played at once -static int islooping=0; -static int musicdies=-1; -UINT8 music_started=0; -boolean songpaused=false; - -/// ------------------------ -// MUSIC SYSTEM -/// ------------------------ - -/* load_midi_mem: - * Loads a standard MIDI file from memory, returning a pointer to - * a MIDI structure, * or NULL on error. - * It is the load_midi from Allegro modified to load it from memory - */ -static MIDI *load_midi_mem(char *mempointer,int *e) -{ - int c = *e; - long data=0; - unsigned char *fp; - MIDI *midi; - int num_tracks=0; - - fp = (void *)mempointer; - if (!fp) - return NULL; - - midi = malloc(sizeof (MIDI)); /* get some memory */ - if (!midi) - return NULL; - - for (c=0; ctrack[c].data = NULL; - midi->track[c].len = 0; - } - - fp+=4+4; // header size + 'chunk' size - - swab(fp,&data,2); // convert to intel-endian - fp+=2; /* MIDI file type */ - if ((data != 0) && (data != 1)) // only type 0 and 1 are suported - return NULL; - - swab(fp,&num_tracks,2); /* number of tracks */ - fp+=2; - if ((num_tracks < 1) || (num_tracks > MIDI_TRACKS)) - return NULL; - - swab(fp,&data,2); /* beat divisions */ - fp+=2; - midi->divisions = ABS(data); - - for (c=0; ctrack[c].len = data; - - midi->track[c].data = fp; - fp+=data; - } - - lock_midi(midi); - return midi; -} - -void I_InitMusic(void) -{ - if (midi_disabled) - return; - - I_AddExitFunc(I_ShutdownMusic); - music_started = true; - songpaused = false; -} - -void I_ShutdownMusic(void) -{ - if ( !music_started ) - return; - - I_StopSong(); - - music_started=false; -} - -/// ------------------------ -// MUSIC PROPERTIES -/// ------------------------ - -musictype_t I_SongType(void) -{ - if (currsong) - return MU_MID; - else - return MU_NONE; -} - -boolean I_SongPlaying() -{ - return (boolean)currsong; -} - -boolean I_SongPaused() -{ - return songpaused; -} - -/// ------------------------ -// MUSIC EFFECTS -/// ------------------------ - -boolean I_SetSongSpeed(float speed) -{ - (void)speed; - return false; -} - -/// ------------------------ -// MUSIC SEEKING -/// ------------------------ - -UINT32 I_GetSongLength(void) -{ - return 0; -} - -boolean I_SetSongLoopPoint(UINT32 looppoint) -{ - (void)looppoint; - return false; -} - -UINT32 I_GetSongLoopPoint(void) -{ - return 0; -} - -boolean I_SetSongPosition(UINT32 position) -{ - (void)position; - return false; -} - -UINT32 I_GetSongPosition(void) -{ - return 0; -} - -/// ------------------------ -// MUSIC PLAYBACK -/// ------------------------ - -boolean I_LoadSong(char *data, size_t len) -{ - int e = len; //Alam: For error - if (midi_disabled) - return 0; - - if (memcmp(data,"MThd",4)==0) // support mid file in WAD !!! - { - currsong=load_midi_mem(data,&e); - } - else - { - CONS_Printf("Music Lump is not a MIDI lump\n"); - return 0; - } - - if (currsong==NULL) - { - CONS_Printf("Not a valid mid file : %d\n",e); - return 0; - } - - return 1; -} - -void I_UnloadSong(void) -{ - handle = 0; - if (midi_disabled) - return; - - //destroy_midi(currsong); -} - -boolean I_PlaySong(boolean looping) -{ - handle = 0; - if (midi_disabled) - return false; - - islooping = looping; - musicdies = gametic + NEWTICRATE*30; - if (play_midi(currsong,looping)==0) - return true; - return false; -} - -void I_StopSong(void) -{ - handle = 0; - if (midi_disabled) - return; - - islooping = 0; - musicdies = 0; - stop_midi(); - songpaused = false; -} - -void I_PauseSong (INT32 handle) -{ - handle = 0; - if (midi_disabled) - return; - midi_pause(); - songpaused = true; -} - -void I_ResumeSong (INT32 handle) -{ - handle = 0; - if (midi_disabled) - return; - midi_resume(); - songpaused = false; -} - -void I_SetMusicVolume(INT32 volume) -{ - if (midi_disabled) - return; - - // Now set volume on output device. - set_volume (-1, Volset(volume)); -} - -boolean I_SetSongTrack(INT32 track) -{ - (void)track; - return false; -} - -// Is the song playing? -#if 0 -int I_QrySongPlaying(int handle) -{ - if (midi_disabled) - return 0; - - //return islooping || musicdies > gametic; - return (midi_pos==-1); -} -#endif - -/// ------------------------ -// MUSIC FADING -/// ------------------------ - -void I_SetInternalMusicVolume(UINT8 volume) -{ - (void)volume; -} - -void I_StopFadingSong(void) -{ -} - -boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)); -{ - (void)target_volume; - (void)source_volume; - (void)ms; - return false; -} - -boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); -{ - (void)target_volume; - (void)ms; - return false; -} - -boolean I_FadeOutStopSong(UINT32 ms) -{ - (void)ms; - return false; -} - -boolean I_FadeInPlaySong(UINT32 ms, boolean looping) -{ - (void)ms; - (void)looping; - return false; -} diff --git a/src/djgppdos/i_system.c b/src/djgppdos/i_system.c deleted file mode 100644 index b5785bb36..000000000 --- a/src/djgppdos/i_system.c +++ /dev/null @@ -1,1775 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Misc. stuff -/// -/// Startup & Shutdown routines for music,sound,timer,keyboard, -/// Signal handler to trap errors and exit cleanly. - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef DJGPP - #include - #include - #include - #include - #include - #include - #include - - #include -#endif - - -#include "../doomdef.h" -#include "../m_misc.h" -#include "../i_video.h" -#include "../i_sound.h" -#include "../i_system.h" -#include "../d_net.h" -#include "../g_game.h" - -#include "../d_main.h" - -#include "../m_argv.h" - -#include "../w_wad.h" -#include "../z_zone.h" -#include "../g_input.h" - -#include "../k_pwrlv.h" - -#include "../console.h" - -#ifdef __GNUG__ - #pragma implementation "../i_system.h" -#endif - -#include "../i_joy.h" - -//### let's try with Allegro ### -#define alleg_mouse_unused -//#define alleg_timer_unused -#define alleg_keyboard_unused -#define ALLEGRO_NO_KEY_DEFINES -//#define alleg_joystick_unused -#define alleg_gfx_driver_unused -#define alleg_palette_unused -#define alleg_graphics_unused -#define alleg_vidmem_unused -#define alleg_flic_unused -#define alleg_sound_unused -#define alleg_file_unused -#define alleg_datafile_unused -#define alleg_math_unused -#define alleg_gui_unused -#include -//### end of Allegro include ### - -#ifndef DOXYGEN - -#ifndef MAX_JOYSTICKS -#define MAX_JOYSTICKS 4 -#endif - -#ifndef MAX_JOYSTICK_AXIS -#define MAX_JOYSTICK_AXIS 3 -#endif - -#ifndef MAX_JOYSTICK_STICKS -#define MAX_JOYSTICK_STICKS 4 -#endif - -#ifndef MAX_JOYSTICK_BUTTONS -#define MAX_JOYSTICK_BUTTONS 12 -#endif - -#endif - -#if ALLEGRO_VERSION == 4 -static char JOYFILE[] = "allegro4.cfg"; -#elif ALLEGRO_VERSION == 3 -static char JOYFILE[] = "allegro.cfg"; -#endif - -/// \brief max number of joystick buttons -#define JOYBUTTONS_MAX MAX_JOYSTICK_BUTTONS // -/// \brief max number of joystick button events -#define JOYBUTTONS_MIN min((JOYBUTTONS),(JOYBUTTONS_MAX)) - -/// \brief max number of joysick axies -#define JOYAXISSET_MAX MAX_JOYSTICK_STICKS -// \brief max number ofjoystick axis events -#define JOYAXISSET_MIN min((JOYAXISSET),(JOYAXISSET_MAX)) - -/// \brief max number of joystick hats -#define JOYHATS_MAX MAX_JOYSTICK_STICKS -/// \brief max number of joystick hat events -#define JOYHATS_MIN min((JOYHATS),(JOYHATS_MAX)) - -/// \brief max number of mouse buttons -#define MOUSEBUTTONS_MAX 16 // 16 bit of BL -/// \brief max number of muse button events -#define MOUSEBUTTONS_MIN min((MOUSEBUTTONS),(MOUSEBUTTONS_MAX)) - -// Do not execute cleanup code more than once. See Shutdown_xxx() routines. -UINT8 graphics_started = false; -UINT8 keyboard_started = false; -UINT8 sound_started = false; -static UINT8 timer_started = false; - -/* Mouse stuff */ -static UINT8 mouse_detected = false; -static UINT8 wheel_detected = false; - -static volatile tic_t ticcount; //returned by I_GetTime(), updated by timer interrupt - - -void I_Tactile(FFType Type, const JoyFF_t *Effect) -{ - // UNUSED. - Type = EvilForce; - Effect = NULL; -} - -void I_Tactile2(FFType Type, const JoyFF_t *Effect) -{ - // UNUSED. - Type = EvilForce; - Effect = NULL; -} - -static ticcmd_t emptycmd; -ticcmd_t * I_BaseTiccmd(void) -{ - return &emptycmd; -} - -static ticcmd_t emptycmd2; -ticcmd_t * I_BaseTiccmd2(void) -{ - return &emptycmd2; -} - -void I_SetupMumble(void) -{ -} - -#ifndef NOMUMBLE -void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) -{ - (void)mobj; - (void)listener; -} -#endif - -// -// Allocates the base zone memory, -// this function returns a valid pointer and size, -// else it should interrupt the program immediately. -// -//added:11-02-98: now checks if mem could be allocated, this is still -// prehistoric... there's a lot to do here: memory locking, detection -// of win95 etc... -// - -#if ALLEGRO_VERSION == 3 -extern int os_type; -extern int windows_version; -extern int windows_sub_version; -extern int i_love_bill; -#elif ALLEGRO_VERSION == 4 -#endif - -static void I_DetectOS (void) -{ -#if ALLEGRO_VERSION == 3 - char buf[16]; - __dpmi_regs r; - union REGS regs; - - /* check which OS we are running under */ - r.x.ax = 0x1600; - __dpmi_int(0x2F, &r); - if ((r.h.al != 0) && (r.h.al != 1) && (r.h.al != 0x80) && (r.h.al != 0xFF)) - { - /* win 3.1 or 95 */ - if (r.h.al == 4) - { - if (r.h.ah < 10) - { - os_type = OSTYPE_WIN95; - } - else - { - os_type = OSTYPE_WIN98; - } - } - else - { - os_type = OSTYPE_WIN3; - } - - windows_version = r.h.al; - windows_sub_version = r.h.ah; - i_love_bill = TRUE; - } - else - { - if (_get_dos_version(1) == 0x0532) - { - /* win NT */ - os_type = OSTYPE_WINNT; - windows_version = 0x100; - windows_sub_version = 0; - i_love_bill = TRUE; - } - else - { - /* see if OS/2 is present */ - r.x.ax = 0x4010; - __dpmi_int(0x2F, &r); - if (r.x.ax != 0x4010) - { - if (r.x.ax == 0x0000) - { - /* OS/2 Warp 3 */ - os_type = OSTYPE_WARP; - i_love_bill = TRUE; - } - else - { - /* no Warp, but previous OS/2 is available */ - os_type = OSTYPE_OS2; - i_love_bill = TRUE; - } - } - else - { - /* check if running under Linux DOSEMU */ - dosmemget(0xFFFF5, 10, buf); - buf[8] = 0; - if (!strcmp(buf, "02/25/93")) - { - regs.x.ax = 0; - int86(0xE6, ®s, ®s); - if (regs.x.ax == 0xAA55) - { - os_type = OSTYPE_DOSEMU; - windows_version = -1; - windows_sub_version = -1; - i_love_bill = TRUE; /* (evil chortle) */ - } - } - else - { - /* check if running under OpenDOS */ - r.x.ax = 0x4452; - __dpmi_int(0x21, &r); - if ((r.x.ax >= 0x1072) && !(r.x.flags & 1)) - { - os_type = OSTYPE_OPENDOS; - /* now check for OpenDOS EMM386.EXE */ - r.x.ax = 0x12FF; - r.x.bx = 0x0106; - __dpmi_int(0x2F, &r); - if ((r.x.ax == 0x0) && (r.x.bx == 0xEDC0)) - { - i_love_bill = TRUE; - } - } - } - } - } - } -#elif ALLEGRO_VERSION == 4 -/// \todo: add Allegro 4 version -#endif -} - -UINT32 I_GetFreeMem(UINT32 *total) -{ - __dpmi_free_mem_info info; - - __dpmi_get_free_memory_information(&info); - if ( total ) - *total = info.total_number_of_physical_pages<<12; // <<12 for convert page to byte - return info.total_number_of_free_pages<<12; -} - - -/*==========================================================================*/ -// I_GetTime () -/*==========================================================================*/ -tic_t I_GetTime (void) -{ - return ticcount; -} - - -void I_Sleep(void) -{ - if (cv_sleep.value > 0) - rest(cv_sleep.value); -} - - -static UINT8 joystick_detected = false; -static UINT8 joystick2_detected = false; - -// -// I_Init -// - - -FUNCINLINE static ATTRINLINE int I_WaitJoyButton (int js) -{ - CON_Drawer (); - I_FinishUpdate (); // page flip or blit buffer - - do - { - if (I_GetKey()) - return false; - poll_joystick(); - } while (!(joy[js].button[0].b || joy[js].button[1].b)); - - return true; -} - -/** \brief Joystick 1 buttons states -*/ -static INT64 lastjoybuttons = 0; -/** \brief Joystick 1 hats state -*/ -static INT64 lastjoyhats = 0; - -void I_InitJoystick (void) -{ - //init the joystick - if (joystick_detected && !joystick2_detected) - remove_joystick(); - joystick_detected=0; - if (M_CheckParm("-nojoy")) - return; - load_joystick_data(JOYFILE); - if (cv_usejoystick.value) - { - if (cv_usejoystick.value > MAX_JOYSTICKS) - cv_usejoystick.value = MAX_JOYSTICKS; - if (install_joystick(JOY_TYPE_AUTODETECT) == 0) - { - int js = cv_usejoystick.value -1; - // only gamepadstyle joysticks - if (joy[js].stick[0].flags & JOYFLAG_DIGITAL) Joystick.bGamepadStyle=true; - - while (joy[js].flags & JOYFLAG_CALIBRATE) - { - const char *msg = calibrate_joystick_name(js); - CONS_Printf("%s, and press a button\n", msg); - if (I_WaitJoyButton(js)) - calibrate_joystick(js); - else - { - if (joystick_detected && !joystick2_detected) - remove_joystick(); - joystick_detected=0; - CV_SetValue(&cv_usejoystick, 0); - return; - } - } - joystick_detected=1; - save_joystick_data(JOYFILE); - } - else - { - CONS_Printf("\2No Joystick detected.\n"); - } - } - else - { - int i; - event_t event; - event.type=ev_keyup; - event.data2 = 0; - event.data3 = 0; - - lastjoybuttons = lastjoyhats = 0; - - // emulate the up of all joystick buttons - for (i=0;i MAX_JOYSTICKS) - cv_usejoystick2.value = MAX_JOYSTICKS; - if (install_joystick(JOY_TYPE_AUTODETECT) == 0) - { - int js = cv_usejoystick2.value -1; - // only gamepadstyle joysticks - load_joystick_data(JOYFILE); - if (joy[js].stick[0].flags & JOYFLAG_DIGITAL) Joystick2.bGamepadStyle=true; - - while (joy[js].flags & JOYFLAG_CALIBRATE) - { - const char *msg = calibrate_joystick_name(js); - CONS_Printf("%s, and press a button\n", msg); - if (I_WaitJoyButton(js)) - calibrate_joystick(js); - else - { - if (joystick2_detected && !joystick_detected) - remove_joystick(); - joystick2_detected=0; - CV_SetValue(&cv_usejoystick2, 0); - return; - } - } - joystick2_detected=1; - save_joystick_data(JOYFILE); - } - else - { - CONS_Printf("\2No Joystick detected.\n"); - } - } - else - { - int i; - event_t event; - event.type=ev_keyup; - event.data2 = 0; - event.data3 = 0; - - lastjoy2buttons = lastjoy2hats = 0; - - // emulate the up of all joystick buttons - for (i=0;i7) - exit(-1); // recursive errors detected - } - shutdowning=true; - - //added:18-02-98: save one time is enough! - if (!errorcount) - { - M_SaveConfig (NULL); //save game config, cvars.. - G_SaveGameData(); // Tails 12-08-2002 - } - - //added:16-02-98: save demo, could be useful for debug - // NOTE: demos are normally not saved here. - I_ShutdownMusic(); - I_ShutdownSound(); - I_ShutdownCD(); - I_ShutdownGraphics(); - I_ShutdownSystem(); - - // put message to stderr - va_start (argptr,error); - fprintf (stderr, "Error: "); - vfprintf (stderr,error,argptr); -#ifdef DEBUGFILE - if (debugfile) - { - fprintf (debugfile,"I_Error :"); - vfprintf (debugfile,error,argptr); - } -#endif - - va_end (argptr); - - fprintf (stderr, "\nPress ENTER"); - fflush( stderr ); - getchar(); - W_Shutdown(); - exit(-1); -} - - -// -// I_Quit : shutdown everything cleanly, in reverse order of Startup. -// -void I_Quit (void) -{ - UINT8 *endoom = NULL; - - //added:16-02-98: when recording a demo, should exit using 'q' key, - // but sometimes we forget and use 'F10'.. so save here too. - M_SaveConfig (NULL); //save game config, cvars.. -#ifndef NONET - D_SaveBan(); // save the ban list -#endif - - // Make sure you lose points for ALT-F4 - if (Playing()) - K_PlayerForfeit(consoleplayer, true); - - G_SaveGameData(); // Tails 12-08-2002 - if (demorecording) - G_CheckDemoStatus(); - D_QuitNetGame (); - I_ShutdownMusic(); - I_ShutdownSound(); - I_ShutdownCD(); - I_ShutdownGraphics(); - I_ShutdownSystem(); - - if (W_CheckNumForName("ENDOOM")!=LUMPERROR) endoom = W_CacheLumpName("ENDOOM",PU_CACHE); - - - //added:03-01-98: maybe it needs that the ticcount continues, - // or something else that will be finished by ShutdownSystem() - // so I do it before. - - if (endoom) - { - puttext(1,1,80,25,endoom); - gotoxy(1,24); - Z_Free(endoom); - } - - if (shutdowning || errorcount) - I_Error("Error detected (%d)",errorcount); - - fflush(stderr); - W_Shutdown(); - exit(0); -} - - -//added:12-02-98: does want to work!!!! rhaaahahha -void I_WaitVBL(INT32 count) -{ - while (count-->0); - { - do { } while (inportb(0x3DA) & 8); - do { } while (!(inportb(0x3DA) & 8)); - } -} - -// Fab: this is probably to activate the 'loading' disc icon -// it should set a flag, that I_FinishUpdate uses to know -// whether it draws a small 'loading' disc icon on the screen or not -// -// also it should explicitly draw the disc because the screen is -// possibly not refreshed while loading -// -void I_BeginRead (void) -{ -} - -// Fab: see above, end the 'loading' disc icon, set the flag false -// -void I_EndRead (void) -{ -} - -#define MOUSE2 -/* Secondary Mouse*/ -#ifdef MOUSE2 -static _go32_dpmi_seginfo oldmouseinfo,newmouseinfo; -static boolean mouse2_started=0; -static UINT16 mouse2port; -static UINT8 mouse2irq; -static volatile int handlermouse2buttons; -static volatile int handlermouse2x,handlermouse2y; -// internal use -static volatile int bytenum; -static volatile UINT8 combytes[8]; - -// -// support a secondary mouse without mouse driver ! -// -// take from the PC-GPE by Mark Feldman -static void I_MicrosoftMouseIntHandler(void) -{ - char dx,dy; - UINT8 inbyte; - - // Get the port byte - inbyte = inportb(mouse2port); - - // Make sure we are properly "synched" - if ((inbyte & 64)== 64 || bytenum>7) - bytenum = 0; - - // Store the byte and adjust bytenum - combytes[bytenum] = inbyte; - bytenum++; - - // Have we received all 3 bytes? - if (bytenum==3) - { - // Yes, so process them - dx = ((combytes[0] & 3) << 6) + combytes[1]; - dy = ((combytes[0] & 12) << 4) + combytes[2]; - handlermouse2x+= dx; - handlermouse2y+= dy; - handlermouse2buttons = (combytes[0] & (32+16)) >>4; - } - else if (bytenum==4) // for logitech 3 buttons - { - if (combytes[3] & 32) - handlermouse2buttons |= 4; - else - handlermouse2buttons &= ~4; - } - - // Acknowledge the interrupt - outportb(0x20,0x20); -} -#ifndef DOXYGEN -static END_OF_FUNCTION(I_MicrosoftMouseIntHandler); -#endif - -// wait ms milliseconde -FUNCINLINE static ATTRINLINE void I_Delay(int ms) -{ - tic_t starttime; - - if (timer_started) - { - starttime=I_GetTime()+(NEWTICRATE*ms)/1000; - while (starttime>=I_GetTime()) - I_Sleep(); - } - else - delay(ms); -} - -// -// Removes the mouse2 handler. -// -static void I_ShutdownMouse2(void) -{ - event_t event; - int i; - - if ( !mouse2_started ) - return; - - outportb(mouse2port+4,0x00); // shutdown mouse (DTR & RTS = 0) - I_Delay(1); - outportb(mouse2port+1,0x00); // disable COM interuption - - asm("cli"); - _go32_dpmi_set_protected_mode_interrupt_vector(mouse2irq, &oldmouseinfo); - _go32_dpmi_free_iret_wrapper(&newmouseinfo); - asm("sti"); - - handlermouse2x=handlermouse2y=handlermouse2buttons=0; - // emulate the up of all mouse buttons - for (i=0;i= 0; i--) - { - joybuttons <<= 1; - if (joy[js].button[i].b) - joybuttons |= 1; - } - - for (i = JOYHATS_MIN -1; i >=0;) - { - if (joy[js].stick[s].flags & JOYFLAG_DIGITAL) - { - if (joy[js].stick[s].axis[1].d1) joyhats |= 1<<(0 + 4*i); - if (joy[js].stick[s].axis[1].d2) joyhats |= 1<<(1 + 4*i); - if (joy[js].stick[s].axis[0].d1) joyhats |= 1<<(2 + 4*i); - if (joy[js].stick[s].axis[0].d2) joyhats |= 1<<(3 + 4*i); - i--; - } - if (s == JOYHATS_MAX) i = -1; - s++; - } - - // post key event for buttons - if (joybuttons!=lastjoybuttons) - { - INT64 j = 1; // only changed bit to 1 - INT64 k = (joybuttons ^ lastjoybuttons); - lastjoybuttons=joybuttons; - - for (i=0;i=0;) - { - event.data1 = i; - event.data2 = event.data3 = 0; - if (joy[js].stick[s].flags & JOYFLAG_DIGITAL) - { - if (joy[js].stick[s].axis[0].d1) - event.data2=-1; - if (joy[js].stick[s].axis[0].d2) - event.data2=1; - if (joy[js].stick[s].axis[1].d1) - event.data3=-1; - if (joy[js].stick[s].axis[1].d2) - event.data3=1; - D_PostEvent(&event); - i++; - } - else if (joy[js].stick[s].flags & JOYFLAG_ANALOGUE) - { - event.data2 = joy[js].stick[s].axis[0].pos*32; - event.data3 = joy[js].stick[s].axis[1].pos*32; - D_PostEvent(&event); - i++; - } - if (s == JOYAXISSET_MAX*2) i = -1; - s++; - } -} - -void I_GetJoystick2Events(void) -{ - event_t event; - INT64 joybuttons= 0; - INT64 joyhats = 0; - int s = 0, i; - int js = cv_usejoystick2.value - 1; - - if (!joystick2_detected) - return; - - // I assume that true is 1 - for (i = JOYBUTTONS_MIN - 1; i >= 0; i--) - { - joybuttons <<= 1; - if (joy[js].button[i].b) - joybuttons |= 1; - } - - for (i = JOYHATS_MIN -1; i >=0;) - { - if (joy[js].stick[s].flags & JOYFLAG_DIGITAL) - { - if (joy[js].stick[s].axis[1].d1) joyhats |= 1<<(0 + 4*i); - if (joy[js].stick[s].axis[1].d2) joyhats |= 1<<(1 + 4*i); - if (joy[js].stick[s].axis[0].d1) joyhats |= 1<<(2 + 4*i); - if (joy[js].stick[s].axis[0].d2) joyhats |= 1<<(3 + 4*i); - i--; - } - if (s == JOYHATS_MAX) i = -1; - s++; - } - - // post key event for buttons - if (joybuttons!=lastjoy2buttons) - { - INT64 j = 1; // only changed bit to 1 - INT64 k = (joybuttons ^ lastjoy2buttons); - lastjoy2buttons=joybuttons; - - for (i=0;i=0;) - { - event.data1 = i; - event.data2 = event.data3 = 0; - if (joy[js].stick[s].flags & JOYFLAG_DIGITAL) - { - if (joy[js].stick[s].axis[0].d1) - event.data2=-1; - if (joy[js].stick[s].axis[0].d2) - event.data2=1; - if (joy[js].stick[s].axis[1].d1) - event.data3=-1; - if (joy[js].stick[s].axis[1].d2) - event.data3=1; - D_PostEvent(&event); - i++; - } - else if (joy[js].stick[s].flags & JOYFLAG_ANALOGUE) - { - event.data2 = joy[js].stick[s].axis[0].pos*32; - event.data3 = joy[js].stick[s].axis[1].pos*32; - D_PostEvent(&event); - i++; - } - if (s == JOYAXISSET_MAX*2) i = -1; - s++; - } -} - -void I_GetMouseEvents(void) -{ - //mouse movement - event_t event; - int xmickeys,ymickeys,buttons,wheels = 0; - static int lastbuttons=0; - __dpmi_regs r; - - if (!mouse_detected) - return; - - r.x.ax=0x0b; // ask the mouvement not the position - __dpmi_int(0x33,&r); - xmickeys=(INT16)r.x.cx; - ymickeys=(INT16)r.x.dx; - r.x.ax=0x03; - __dpmi_int(0x33,&r); - buttons=r.h.bl; - if (wheel_detected) - wheels=(signed char)r.h.bh; - - // post key event for buttons - if (buttons!=lastbuttons) - { - int j=1,k,i; - k=(buttons ^ lastbuttons); // only changed bit to 1 - lastbuttons=buttons; - - for (i=0;i 0) - event.data1 = KEY_MOUSEWHEELUP; - else if (wheels < 0) - event.data1 = KEY_MOUSEWHEELDOWN; - if (event.data1) - D_PostEvent(&event); - - - if ((xmickeys!=0)||(ymickeys!=0)) - { - event.type=ev_mouse; - event.data1=0; - //event.data1=buttons; // not needed - event.data2=xmickeys; - event.data3=-ymickeys; - - D_PostEvent(&event); - } - - //reset wheel like in win32, I don't understand it but works - gamekeydown[KEY_MOUSEWHEELDOWN] = gamekeydown[KEY_MOUSEWHEELUP] = 0; - -} - -void I_GetEvent (void) -{ -#ifdef MOUSE2 - // mouse may be disabled during the game by setting usemouse false - if (mouse2_started) - { - event_t event; - //mouse movement - static UINT8 lastbuttons2=0; - - // post key event for buttons - if (handlermouse2buttons!=lastbuttons2) - { - int j=1,k,i; - k=(handlermouse2buttons ^ lastbuttons2); // only changed bit to 1 - lastbuttons2=handlermouse2buttons; - - for (i=0;i 8 -"More Joystick Names?" -#endif - - if (joyindex == 1) return "Joystick A"; - else if (joyindex == 2) return "Joystick B"; - else if (joyindex == 3) return "Joystick C"; - else if (joyindex == 4) return "Joystick D"; - else if (joyindex == 5) return "Joystick E"; - else if (joyindex == 6) return "Joystick F"; - else if (joyindex == 7) return "Joystick G"; - else if (joyindex == 8) return "Joystick H"; - else return NULL; - -} - -// -// Timer user routine called at ticrate. -// -static void I_TimerISR (void) -{ - // IO_PlayerInput(); // old doom did that - ticcount++; - -} -#ifndef DOXYGEN -static END_OF_FUNCTION(I_TimerISR); -#endif - - -//added:08-01-98: we don't use allegro_exit() so we have to do it ourselves. -static inline void I_ShutdownTimer (void) -{ - if ( !timer_started ) - return; - remove_timer(); -} - - -// -// Installs the timer interrupt handler with timer speed as NEWTICRATE. -// -void I_StartupTimer(void) -{ - ticcount = 0; - - //lock this from being swapped to disk! BEFORE INSTALLING - LOCK_VARIABLE(ticcount); - LOCK_FUNCTION(I_TimerISR); - - if ( install_timer() != 0 ) - I_Error("I_StartupTimer: could not install timer."); - - if ( install_int_ex( I_TimerISR, BPS_TO_TIMER(NEWTICRATE) ) != 0 ) - //should never happen since we use only one. - I_Error("I_StartupTimer: no room for callback routine."); - - //added:08-01-98: remove the timer explicitly because we don't use - // Allegro 's allegro_exit() shutdown code. - I_AddExitFunc(I_ShutdownTimer); - timer_started = true; -} - - -//added:07-02-98: -// -// -static UINT8 ASCIINames[128] = -{ -// 0 1 2 3 -// 4 5 6 7 -// 8 9 A B -// C D E F - 0, 27, '1', '2', - '3', '4', '5', '6', - '7', '8', '9', '0', - KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB, - 'q', 'w', 'e', 'r', - 't', 'y', 'u', 'i', - 'o', 'p', '[', ']', - KEY_ENTER, KEY_LCTRL, 'a', 's', - 'd', 'f', 'g', 'h', - 'j', 'k', 'l', ';', - '\'', '`', KEY_LSHIFT, '\\', - 'z', 'x', 'c', 'v', - 'b', 'n', 'm', ',', - '.', '/', KEY_RSHIFT, '*', - KEY_LALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1, - KEY_F2, KEY_F3, KEY_F4, KEY_F5, - KEY_F6, KEY_F7, KEY_F8, KEY_F9, - KEY_F10,KEY_NUMLOCK,KEY_SCROLLLOCK,KEY_KEYPAD7, -KEY_KEYPAD8,KEY_KEYPAD9, KEY_MINUSPAD,KEY_KEYPAD4, -KEY_KEYPAD5,KEY_KEYPAD6, KEY_PLUSPAD,KEY_KEYPAD1, -KEY_KEYPAD2,KEY_KEYPAD3, KEY_KEYPAD0,KEY_KPADDEL, - 0, 0, 0, KEY_F11, - KEY_F12, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0 -}; - -static volatile int pausepressed=0; -static volatile char nextkeyextended; - -static void I_KeyboardHandler(void) -{ - UINT8 ch; - event_t event; - - ch=inportb(0x60); - - if (pausepressed>0) - pausepressed--; - else if (ch==0xE1) // pause key - { - event.type=ev_keydown; - event.data1=KEY_PAUSE; - D_PostEvent(&event); - pausepressed=5; - } - else if (ch==0xE0) // extended key handled at next call - { - nextkeyextended=1; - } - else - { - if ((ch&0x80)==0) - event.type=ev_keydown; - else - event.type=ev_keyup; - - ch&=0x7f; - - if (nextkeyextended) - { - nextkeyextended=0; - - if (ch==70) // crtl-break - { - asm ("movb $0x79, %%al\ncall ___djgpp_hw_exception" - : : :"%eax","%ebx","%ecx","%edx","%esi","%edi","memory"); - } - - // remap lonely keypad slash - if (ch==53) - event.data1 = KEY_KPADSLASH; - else if (ch>=91 && ch<=93) // remap the bill gates keys... - event.data1 = ch + 0x80; // leftwin, rightwin, menu - else if (ch>=71 && ch<=83) // remap non-keypad extended keys to a value<128, but - event.data1 = 0x80 + ch + 30; // make them different than the KEYPAD keys. - else if (ch==28) - event.data1 = KEY_ENTER; // keypad enter -> return key - else if (ch==29) - event.data1 = KEY_RCTRL; // rctrl -> lctrl - else if (ch==56) - event.data1 = KEY_RALT; // ralt -> lalt - else - ch = 0; - if (ch) - D_PostEvent(&event); - } - else - { - if (ASCIINames[ch]!=0) - event.data1=ASCIINames[ch]; - else - event.data1=ch+0x80; - D_PostEvent(&event); - } - } - - outportb(0x20,0x20); -} -#ifndef DOXYGEN -static END_OF_FUNCTION(I_KeyboardHandler); -#endif - -// Return a key that has been pushed, or 0 -// (replace getchar() at game startup) -// -INT32 I_GetKey (void) -{ - int rc=0; - if ( keyboard_started ) - { - event_t *ev; - - // return the first keypress from the event queue - for ( ; eventtail != eventhead ; eventtail = (eventtail+1)&(MAXEVENTS-1) ) - { - ev = &events[eventtail]; - if (ev->type == ev_keydown || ev->type == ev_console) - { - rc = ev->data1; - continue; - } - } - return rc; - } - - // keyboard not started use the bios call trouth djgpp - if (_conio_kbhit()) - { - rc=getch(); - if (rc==0) rc=getch()+256; - } - else - rc = 0; - - return rc; -} - -/* Keyboard handler stuff */ -static _go32_dpmi_seginfo oldkeyinfo,newkeyinfo; - -// -// Removes the keyboard handler. -// -static inline void I_ShutdownKeyboard(void) -{ - if ( !keyboard_started ) - return; - - asm("cli"); - _go32_dpmi_set_protected_mode_interrupt_vector(9, &oldkeyinfo); - _go32_dpmi_free_iret_wrapper(&newkeyinfo); - asm("sti"); - - keyboard_started=false; -} - -// -// Installs the keyboard handler. -// -void I_StartupKeyboard(void) -{ - if (keyboard_started) - return; - - nextkeyextended=0; - - asm("cli"); - _go32_dpmi_get_protected_mode_interrupt_vector(9, &oldkeyinfo); - newkeyinfo.pm_offset=(int)I_KeyboardHandler; - newkeyinfo.pm_selector=_go32_my_cs(); - _go32_dpmi_allocate_iret_wrapper(&newkeyinfo); - _go32_dpmi_set_protected_mode_interrupt_vector(9, &newkeyinfo); - - LOCK_VARIABLE(nextkeyextended); - LOCK_VARIABLE(pausepressed); - _go32_dpmi_lock_data(ASCIINames,sizeof (ASCIINames)); - LOCK_FUNCTION(I_KeyboardHandler); - - _go32_dpmi_lock_data(events,sizeof (events)); - LOCK_VARIABLE(eventhead); - LOCK_FUNCTION(D_PostEvent); - - asm("sti"); - - //added:08-01-98:register shutdown keyboard code. - I_AddExitFunc(I_ShutdownKeyboard); - keyboard_started = true; -} - - - - -//added:08-01-98: -// -// Clean Startup & Shutdown handling, as does Allegro. -// We need this services for ourselves too, and we don't want to mix -// with Allegro, because someone might not use Allegro. -// (all 'exit' was renamed to 'quit') -// -#define MAX_QUIT_FUNCS 16 -static quitfuncptr quit_funcs[MAX_QUIT_FUNCS] = - { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; - - -//added:08-01-98: -// -// Adds a function to the list that need to be called by I_SystemShutdown(). -// -void I_AddExitFunc(void (*func)()) -{ - int c; - - for (c=0; c=0; c--) - if (quit_funcs[c]) - (*quit_funcs[c])(); -} - -void I_GetDiskFreeSpace(INT64 *freespace) -{ - struct diskfree_t df; - if (_dos_getdiskfree(0,&df)) - *freespace = (unsigned long)df.avail_clusters * - (unsigned long)df.bytes_per_sector * - (unsigned long)df.sectors_per_cluster; - else - *freespace = INT32_MAX; -} - -char *I_GetUserName(void) -{ - static char username[MAXPLAYERNAME]; - char *p; - if ((p=getenv("USER"))==NULL) - if ((p=getenv("user"))==NULL) - if ((p=getenv("USERNAME"))==NULL) - if ((p=getenv("username"))==NULL) - return NULL; - strncpy(username,p,MAXPLAYERNAME); - - if (strcmp(username,"")==0 ) - return NULL; - return username; -} - -INT32 I_mkdir(const char *pdirname, INT32 unixright) -{ - return mkdir(pdirname, unixright); -} - -char * I_GetEnv(const char *name) -{ - return getenv(name); -} - -INT32 I_PutEnv(char *variable) -{ - return putenv(variable); -} - -INT32 I_ClipboardCopy(const char *data, size_t size) -{ - (void)data; - (void)size; - return -1; -} - -char *I_ClipboardPaste(void) -{ - return NULL; -} - -const CPUInfoFlags *I_CPUInfo(void) -{ - static CPUInfoFlags DOS_CPUInfo; - memset(&DOS_CPUInfo,0,sizeof (DOS_CPUInfo)); -#if ALLEGRO_VERSION == 3 - if (!cpu_cpuid) return NULL; - DOS_CPUInfo.CPUID = true; - DOS_CPUInfo.MMX = cpu_mmx; - DOS_CPUInfo.AMD3DNow = cpu_3dnow; -#else - DOS_CPUInfo.CPUID = ((cpu_capabilities&CPU_ID) == CPU_ID); - DOS_CPUInfo.FPU = ((cpu_capabilities&CPU_FPU) == CPU_FPU); -#ifdef CPU_IA64 - DOS_CPUInfo.IA64 = ((cpu_capabilities&CPU_IA64) == CPU_IA64); -#endif -#ifdef CPU_AMD64 - DOS_CPUInfo.AMD64 = ((cpu_capabilities&CPU_AMD64) == CPU_AMD64); -#endif - DOS_CPUInfo.MMX = ((cpu_capabilities&CPU_MMX) == CPU_MMX); - DOS_CPUInfo.MMXExt = ((cpu_capabilities&CPU_MMXPLUS) == CPU_MMXPLUS); - DOS_CPUInfo.SSE = ((cpu_capabilities&CPU_SSE) == CPU_SSE); - DOS_CPUInfo.SSE2 = ((cpu_capabilities&CPU_SSE2) == CPU_SSE2); -#ifdef CPU_SEE3 - DOS_CPUInfo.SSE3 = ((cpu_capabilities&CPU_SSE3) == CPU_SSE3); -#endif - DOS_CPUInfo.AMD3DNow = ((cpu_capabilities&CPU_3DNOW) == CPU_3DNOW); - DOS_CPUInfo.AMD3DNowExt = ((cpu_capabilities&CPU_ENH3DNOW) == CPU_ENH3DNOW); - DOS_CPUInfo.CMOV = ((cpu_capabilities&CPU_CMOV) == CPU_CMOV); -#endif - return &DOS_CPUInfo; -} - -void I_RegisterSysCommands(void) {} diff --git a/src/djgppdos/i_video.c b/src/djgppdos/i_video.c deleted file mode 100644 index 7829acbb9..000000000 --- a/src/djgppdos/i_video.c +++ /dev/null @@ -1,336 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief hardware and software level, screen and video i/o, refresh, -/// setup ... a big mess. Got to clean that up! - -#include -#include -#include -#include -#include -//#include - -#include -//#include -#include - -#include -#include -#include -#include -#include - -#include "../doomdef.h" -#include "../i_system.h" -#include "../v_video.h" -#include "../m_argv.h" -#include "vid_vesa.h" -#include "../i_video.h" - - -//dosstuff -newly added -static unsigned long dascreen; -static int gfx_use_vesa1; - -boolean highcolor; - -#define SCREENDEPTH 1 // bytes per pixel, do NOT change. - -rendermode_t rendermode=render_soft; - -// -// I_OsPolling -// -void I_OsPolling(void) -{ - I_GetEvent(); - //i dont think i have to do anything else here -} - - -// -// I_UpdateNoBlit -// -void I_UpdateNoBlit (void) -{ - // what is this? -} - - -//profile stuff --------------------------------------------------------- -//added:16-01-98:wanted to profile the VID_BlitLinearScreen() asm code. -//#define TIMING //uncomment this to enable profiling -#ifdef TIMING -#include "../p5prof.h" -static INT64 mycount; -static INT64 mytotal = 0; -static unsigned long nombre = NEWTICRATE*10; -//static char runtest[10][80]; -#endif -//profile stuff --------------------------------------------------------- - -// -// I_FinishUpdate -// -static void I_BlitScreenVesa1(void); //see later -void I_FinishUpdate (void) -{ - // draw FPS if enabled - if (cv_ticrate.value) - SCR_DisplayTicRate(); - - if (cv_showping.value && netgame && consoleplayer != serverplayer) - SCR_DisplayLocalPing(); - - //blast it to the screen - // this code sucks - //memcpy(dascreen,screens[0],screenwidth*screenheight); - - //added:03-01-98: I tried to I_WaitVBL(1) here, but it slows down - // the game when the view becomes complicated, it looses ticks - if (cv_vidwait.value) - I_WaitVBL(1); - - -//added:16-01-98:profile screen blit. -#ifdef TIMING - ProfZeroTimer(); -#endif - //added:08-01-98: support vesa1 bank change, without Allegro's BITMAP screen. - if ( gfx_use_vesa1 ) - { - I_Error("Banked screen update not finished for dynamic res\n"); - I_BlitScreenVesa1(); //blast virtual to physical screen. - } - else - { - //added:16-01-98:use quickie asm routine, last 2 args are - // src and dest rowbytes - // (memcpy is as fast as this one...) - VID_BlitLinearScreen(screens[0], vid.direct, - vid.width*vid.bpp, vid.height, - vid.width*vid.bpp, vid.rowbytes ); - } -#ifdef TIMING - RDMSR(0x10,&mycount); - mytotal += mycount; //64bit add - - if (nombre--==0) - I_Error("ScreenBlit CPU Spy reports: 0x%d %d\n", *((int *)&mytotal+1), - (int)mytotal ); -#endif - -} - -// -// I_UpdateNoVsync -// -void I_UpdateNoVsync(void) -{ - int real_vidwait = cv_vidwait.value; - cv_vidwait.value = 0; - I_FinishUpdate(); - cv_vidwait.value = real_vidwait; -} - -// -// I_ReadScreen -// -void I_ReadScreen (UINT8 *scr) -{ - VID_BlitLinearScreen(screens[0], scr, - vid.width*vid.bpp, vid.height, - vid.width*vid.bpp, vid.rowbytes ); -} - - -void I_SetPalette (RGBA_t *palette) -{ - int i; - - outportb(0x3c8,0); - for (i=0;i<256;i++,palette++) - { - outportb(0x3c9,palette->s.red>>2); - outportb(0x3c9,palette->s.green>>2); - outportb(0x3c9,palette->s.blue>>2); - } -} - - -//added 29-12-1997 -/*==========================================================================*/ -// I_BlastScreen : copy the virtual screen buffer to the physical screen mem -// using bank switching if needed. -/*==========================================================================*/ -static void I_BlitScreenVesa1(void) -{ -#define VIDBANKSIZE (1<<16) -#define VIDBANKSIZEMASK (VIDBANKSIZE-1) // defines ahoy! - - __dpmi_regs r; - UINT8 *p_src; - long i; - long virtualsize; - - // virtual screen buffer size - virtualsize = vid.rowbytes * vid.height * SCREENDEPTH; - - p_src = screens[0]; - - for (i=0; virtualsize > 0; i++ ) - { - r.x.ax = 0x4f05; - r.x.bx = 0x0; - r.x.cx = 0x0; - r.x.dx = i; - __dpmi_int(0x10,&r); //set bank - - M_Memcpy((UINT8 *)dascreen,p_src,(virtualsize < VIDBANKSIZE) ? virtualsize : VIDBANKSIZE ); - - p_src += VIDBANKSIZE; - virtualsize -= VIDBANKSIZE; - } - -} - - -//added:08-01-98: now we use Allegro's set_gfx_mode, but we want to -// restore the exact text mode that was before. -static INT16 myOldVideoMode; -static inline void I_SaveOldVideoMode(void) -{ - __dpmi_regs r; - r.x.ax = 0x4f03; // Return current video mode - __dpmi_int(0x10,&r); - if ( r.x.ax != 0x4f ) - myOldVideoMode = -1; - else - myOldVideoMode = r.x.bx; -} - - -// -// Close the screen, restore previous video mode. -// -void I_ShutdownGraphics (void) -{ - __dpmi_regs r; - - rendermode = render_none; - if ( !graphics_started ) - return; - - // free the last video mode screen buffers - if (vid.buffer) - free (vid.buffer); - - /* Restore old video mode */ - if (myOldVideoMode!=-1) - { - /* Restore old video mode */ - r.x.ax = 0x4f02; // Set Super VGA video mode - r.x.bx = myOldVideoMode; - __dpmi_int(0x10,&r); - - // Boris: my s3 don't do a cls because "win95" :< - clrscr(); - } - else // no vesa put the normal video mode - { - r.x.ax = 0x03; - __dpmi_int(0x10,&r); - } - - graphics_started = false; -} - - -//added:08-01-98: -// Set VESA1 video mode, coz Allegro set_gfx_mode a larger screenwidth... -// -#if 0 -int set_vesa1_mode( int width, int height ) -{ - __dpmi_regs r; - - // setup video mode. - r.x.ax = 0x4f02; - if ( ( width==320 )&&( height==200 ) && ( SCREENDEPTH==1 ) ) - r.x.bx = 0x13; // 320x 200x1 (256 colors) - else - if ( ( width==320 )&&( height==240 ) && ( SCREENDEPTH==1 ) ) - r.x.bx = 0x154; // 320x 240x1 (256 colors) - else - if ( ( width==320 )&&( height==400 ) && ( SCREENDEPTH==1 ) ) - r.x.bx = 0x155; // 320x 400x1 (256 colors) - else - if ( ( width==640 )&&( height==400 ) && ( SCREENDEPTH==1 ) ) - r.x.bx = 0x100; // 640x 400x1 (256 colors) - else - if ( ( width==640 )&&( height==480 ) && ( SCREENDEPTH==1 ) ) - r.x.bx = 0x101; // 640x 480x1 (256 colors) - else - if ( ( width==800 )&&( height==600 ) && ( SCREENDEPTH==1 ) ) - r.x.bx = 0x103; // 800x 600x1 (256 colors) - else - if ( ( width==1024)&&( height==768 ) && ( SCREENDEPTH==1 ) ) - r.x.bx = 0x105; //1024x 768x1 (256 colors) - else - I_Error("I_SetVesa1Mode: video mode not supported."); - - // enter graphics mode. - __dpmi_int(0x10,&r); - - if ( r.x.ax != 0x4f ) - I_Error("I_SetVesa1Mode: init video mode failed !"); - - return 0; -} -#endif - - -//added:08-01-98: now uses Allegro to setup Linear Frame Buffer video modes. -// -// Initialize video mode, setup dynamic screen size variables, -// and allocate screens. -// -void I_StartupGraphics(void) -{ - //added:26-01-98: VID_Init() must be done only once, - // use VID_SetMode() to change vid mode while in the game. - if ( graphics_started ) - return; - - // remember the exact screen mode we were... - I_SaveOldVideoMode(); - - CONS_Printf("Vid_Init..."); - - // 0 for 256 color, else use highcolor modes - highcolor = M_CheckParm ("-highcolor"); - - VID_Init(); - - //gfx_use_vesa1 = false; - - //added:03-01-98: register exit code for graphics - I_AddExitFunc(I_ShutdownGraphics); - graphics_started = true; - -} diff --git a/src/djgppdos/internal.h b/src/djgppdos/internal.h deleted file mode 100644 index b34b5ebb7..000000000 --- a/src/djgppdos/internal.h +++ /dev/null @@ -1,773 +0,0 @@ -/* ______ ___ ___ - * /\ _ \ /\_ \ /\_ \ - * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ - * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ - * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ - * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ - * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ - * /\____/ - * \_/__/ - * - * Some definitions for internal use by the library code. - * This should not be included by user programs. - * - * By Shawn Hargreaves. - * - * See readme.txt for copyright information. - */ - - -#ifndef INTERNAL_H -#define INTERNAL_H - -#include "allegro.h" - -/* ______ ___ ___ - * /\ _ \ /\_ \ /\_ \ - * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ - * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ - * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ - * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ - * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ - * /\____/ - * \_/__/ - * - * Some definitions for internal use by the library code. - * This should not be included by user programs. - * - * By Shawn Hargreaves. - * - * See readme.txt for copyright information. - */ - - -#ifndef INTERNDJ_H -#define INTERNDJ_H - -#ifndef DJGPP -#error This file should only be used by the djgpp version of Allegro -#endif - - -#include - - -/* file access macros */ -#define FILE_OPEN(filename, handle) handle = open(filename, O_RDONLY | O_BINARY, S_IRUSR | S_IWUSR) -#define FILE_CREATE(filename, handle) handle = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR) -#define FILE_CLOSE(handle) close(handle) -#define FILE_READ(handle, buf, size, sz) sz = read(handle, buf, size) -#define FILE_WRITE(handle, buf, size, sz) sz = write(handle, buf, size) -#define FILE_SEARCH_STRUCT struct ffblk -#define FILE_FINDFIRST(filename, attrib, dta) findfirst(filename, dta, attrib) -#define FILE_FINDNEXT(dta) findnext(dta) -#define FILE_ATTRIB ff_attrib -#define FILE_SIZE ff_fsize -#define FILE_NAME ff_name -#define FILE_TIME ff_ftime -#define FILE_DATE ff_fdate - - -/* macros to enable and disable interrupts */ -#define DISABLE() asm volatile ("cli") -#define ENABLE() asm volatile ("sti") - - -__INLINE__ void enter_critical(void) -{ - if (windows_version >= 3) { - __dpmi_regs r; - r.x.ax = 0x1681; - __dpmi_int(0x2F, &r); - } - - DISABLE(); -} - - -__INLINE__ void exit_critical(void) -{ - if (windows_version >= 3) { - __dpmi_regs r; - r.x.ax = 0x1682; - __dpmi_int(0x2F, &r); - } - - ENABLE(); -} - - -/* interrupt hander stuff */ -#define _map_irq(irq) (((irq)>7) ? ((irq)+104) : ((irq)+8)) - -int _install_irq(int num, int (*handler)(void)); -void _remove_irq(int num); -void _restore_irq(int irq); -void _enable_irq(int irq); -void _disable_irq(int irq); - -#define _eoi(irq) { outportb(0x20, 0x20); if ((irq)>7) outportb(0xA0, 0x20); } - -typedef struct _IRQ_HANDLER -{ - int (*handler)(void); /* our C handler */ - int number; /* irq number */ - __dpmi_paddr old_vector; /* original protected mode vector */ -} _IRQ_HANDLER; - - -/* DPMI memory mapping routines */ -int _create_physical_mapping(unsigned long *linear, int *segment, unsigned long physaddr, int size); -void _remove_physical_mapping(unsigned long *linear, int *segment); -int _create_linear_mapping(unsigned long *linear, unsigned long physaddr, int size); -void _remove_linear_mapping(unsigned long *linear); -int _create_selector(int *segment, unsigned long linear, int size); -void _remove_selector(int *segment); -void _unlock_dpmi_data(void *addr, int size); - - -/* bank switching routines */ -void _accel_bank_stub(void); -void _accel_bank_stub_end(void); - -void _accel_bank_switch (void); -void _accel_bank_switch_end(void); - -void _vesa_window_1(void); -void _vesa_window_1_end(void); -void _vesa_window_2(void); -void _vesa_window_2_end(void); - -void _vesa_pm_window_1(void); -void _vesa_pm_window_1_end(void); -void _vesa_pm_window_2(void); -void _vesa_pm_window_2_end(void); - -void _vesa_pm_es_window_1(void); -void _vesa_pm_es_window_1_end(void); -void _vesa_pm_es_window_2(void); -void _vesa_pm_es_window_2_end(void); - - -/* stuff for the VESA and VBE/AF drivers */ -extern __dpmi_regs _dpmi_reg; - -extern int _window_2_offset; - -extern void (*_pm_vesa_switcher)(void); -extern void (*_pm_vesa_scroller)(void); -extern void (*_pm_vesa_pallete)(void); - -extern int _mmio_segment; - -extern void *_accel_driver; - -extern int _accel_active; - -extern void *_accel_set_bank; -extern void *_accel_idle; - -void _fill_vbeaf_libc_exports(void *ptr); -void _fill_vbeaf_pmode_exports(void *ptr); - - -/* sound lib stuff */ -extern int _fm_port; -extern int _mpu_port; -extern int _mpu_irq; -extern int _sb_freq; -extern int _sb_port; -extern int _sb_dma; -extern int _sb_irq; - -int _sb_read_dsp_version(void); -int _sb_reset_dsp(int data); -void _sb_voice(int state); -int _sb_set_mixer(int digi_volume, int midi_volume); - -void _mpu_poll(void); - -int _dma_allocate_mem(int bytes, int *sel, unsigned long *phys); -void _dma_start(int channel, unsigned long addr, int size, int auto_init, int input); -void _dma_stop(int channel); -unsigned long _dma_todo(int channel); -void _dma_lock_mem(void); - - -#endif /* ifndef INTERNDJ_H */ - - -/* flag for how many times we have been initialised */ -extern int _allegro_count; - - -/* some Allegro functions need a block of scratch memory */ -extern void *_scratch_mem; -extern int _scratch_mem_size; - -__INLINE__ void _grow_scratch_mem(int size) -{ - if (size > _scratch_mem_size) { - size = (size+1023) & 0xFFFFFC00; - _scratch_mem = realloc(_scratch_mem, size); - _scratch_mem_size = size; - } -} - - -/* list of functions to call at program cleanup */ -void _add_exit_func(void (*func)(void)); -void _remove_exit_func(void (*func)(void)); - - -/* reads a translation file into memory */ -void _load_config_text(void); - - -/* various bits of mouse stuff */ -void _set_mouse_range(void); -extern BITMAP *_mouse_screen; -extern BITMAP *_mouse_sprite, *_mouse_pointer; -extern int _mouse_x_focus, _mouse_y_focus; -extern int _mouse_width, _mouse_height; - - -/* various bits of timer stuff */ -extern int _timer_use_retrace; -extern volatile int _retrace_hpp_value; - - -/* caches and tables for svga bank switching */ -extern int _last_bank_1, _last_bank_2; -extern int *_gfx_bank; - - -/* bank switching routines */ -void _stub_bank_switch (void); -void _stub_bank_switch_end(void); - - -/* stuff for setting up bitmaps */ -void _check_gfx_virginity(void); -BITMAP *_make_bitmap(int w, int h, unsigned long addr, GFX_DRIVER *driver, int color_depth, int bpl); -void _sort_out_virtual_width(int *width, GFX_DRIVER *driver); - -GFX_VTABLE *_get_vtable(int color_depth); - -extern GFX_VTABLE _screen_vtable; - -extern int _sub_bitmap_id_count; - -extern int _textmode; - -#define BYTES_PER_PIXEL(bpp) (((int)(bpp) + 7) / 8) - -int _color_load_depth(int depth); - -extern int _color_conv; - -BITMAP *_fixup_loaded_bitmap(BITMAP *bmp, PALETTE pal, int bpp); - - -/* VGA register access routines */ -void _vga_vsync(void); -void _vga_set_pallete_range(PALLETE p, int from, int to, int vsync); - -extern int _crtc; - - -/* _read_vga_register: - * Reads the contents of a VGA register. - */ -__INLINE__ int _read_vga_register(int port, int index) -{ - if (port==0x3C0) - inportb(_crtc+6); - - outportb(port, index); - return inportb(port+1); -} - - -/* _write_vga_register: - * Writes a byte to a VGA register. - */ -__INLINE__ void _write_vga_register(int port, int index, int v) -{ - if (port==0x3C0) { - inportb(_crtc+6); - outportb(port, index); - outportb(port, v); - } - else { - outportb(port, index); - outportb(port+1, v); - } -} - - -/* _alter_vga_register: - * Alters specific bits of a VGA register. - */ -__INLINE__ void _alter_vga_register(int port, int index, int mask, int v) -{ - int temp; - temp = _read_vga_register(port, index); - temp &= (~mask); - temp |= (v & mask); - _write_vga_register(port, index, temp); -} - - -/* _vsync_out_h: - * Waits until the VGA is not in either a vertical or horizontal retrace. - */ -__INLINE__ void _vsync_out_h(void) -{ - do { - } while (inportb(0x3DA) & 1); -} - - -/* _vsync_out_v: - * Waits until the VGA is not in a vertical retrace. - */ -__INLINE__ void _vsync_out_v(void) -{ - do { - } while (inportb(0x3DA) & 8); -} - - -/* _vsync_in: - * Waits until the VGA is in the vertical retrace period. - */ -__INLINE__ void _vsync_in(void) -{ - if (_timer_use_retrace) { - int t = retrace_count; - - do { - } while (t == retrace_count); - } - else { - do { - } while (!(inportb(0x3DA) & 8)); - } -} - - -/* _write_hpp: - * Writes to the VGA pelpan register. - */ -__INLINE__ void _write_hpp(int value) -{ - if (_timer_use_retrace) { - _retrace_hpp_value = value; - - do { - } while (_retrace_hpp_value == value); - } - else { - do { - } while (!(inportb(0x3DA) & 8)); - - _write_vga_register(0x3C0, 0x33, value); - } -} - - -void _set_vga_virtual_width(int old_width, int new_width); - - -/* current drawing mode */ -extern int _drawing_mode; -extern BITMAP *_drawing_pattern; -extern int _drawing_x_anchor; -extern int _drawing_y_anchor; -extern unsigned int _drawing_x_mask; -extern unsigned int _drawing_y_mask; - - -/* graphics drawing routines */ -void _normal_line(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); -void _normal_rectfill(BITMAP *bmp, int x1, int y1, int x2, int y2, int color); - -int _linear_getpixel8(struct BITMAP *bmp, int x, int y); -void _linear_putpixel8(struct BITMAP *bmp, int x, int y, int color); -void _linear_vline8(struct BITMAP *bmp, int x, int y1, int y2, int color); -void _linear_hline8(struct BITMAP *bmp, int x1, int y, int x2, int color); -void _linear_draw_sprite8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_v_flip8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_h_flip8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_vh_flip8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_trans_sprite8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_lit_sprite8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_draw_rle_sprite8(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_trans_rle_sprite8(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_lit_rle_sprite8(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); -void _linear_draw_character8(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_textout_fixed8(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); -void _linear_blit8(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_blit_backward8(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_masked_blit8(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_clear_to_color8(struct BITMAP *bitmap, int color); - -#ifdef ALLEGRO_COLOR16 - -void _linear_putpixel15(struct BITMAP *bmp, int x, int y, int color); -void _linear_vline15(struct BITMAP *bmp, int x, int y1, int y2, int color); -void _linear_hline15(struct BITMAP *bmp, int x1, int y, int x2, int color); -void _linear_draw_trans_sprite15(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_lit_sprite15(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_draw_rle_sprite15(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_trans_rle_sprite15(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_lit_rle_sprite15(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); - -int _linear_getpixel16(struct BITMAP *bmp, int x, int y); -void _linear_putpixel16(struct BITMAP *bmp, int x, int y, int color); -void _linear_vline16(struct BITMAP *bmp, int x, int y1, int y2, int color); -void _linear_hline16(struct BITMAP *bmp, int x1, int y, int x2, int color); -void _linear_draw_sprite16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_256_sprite16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_v_flip16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_h_flip16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_vh_flip16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_trans_sprite16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_lit_sprite16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_draw_rle_sprite16(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_trans_rle_sprite16(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_lit_rle_sprite16(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); -void _linear_draw_character16(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_textout_fixed16(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); -void _linear_blit16(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_blit_backward16(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_masked_blit16(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_clear_to_color16(struct BITMAP *bitmap, int color); - -#endif - -#ifdef ALLEGRO_COLOR24 - -int _linear_getpixel24(struct BITMAP *bmp, int x, int y); -void _linear_putpixel24(struct BITMAP *bmp, int x, int y, int color); -void _linear_vline24(struct BITMAP *bmp, int x, int y1, int y2, int color); -void _linear_hline24(struct BITMAP *bmp, int x1, int y, int x2, int color); -void _linear_draw_sprite24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_256_sprite24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_v_flip24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_h_flip24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_vh_flip24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_trans_sprite24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_lit_sprite24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_draw_rle_sprite24(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_trans_rle_sprite24(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_lit_rle_sprite24(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); -void _linear_draw_character24(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_textout_fixed24(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); -void _linear_blit24(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_blit_backward24(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_masked_blit24(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_clear_to_color24(struct BITMAP *bitmap, int color); - -#endif - -#ifdef ALLEGRO_COLOR32 - -int _linear_getpixel32(struct BITMAP *bmp, int x, int y); -void _linear_putpixel32(struct BITMAP *bmp, int x, int y, int color); -void _linear_vline32(struct BITMAP *bmp, int x, int y1, int y2, int color); -void _linear_hline32(struct BITMAP *bmp, int x1, int y, int x2, int color); -void _linear_draw_sprite32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_256_sprite32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_v_flip32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_h_flip32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_sprite_vh_flip32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_trans_sprite32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _linear_draw_lit_sprite32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_draw_rle_sprite32(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_trans_rle_sprite32(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _linear_draw_lit_rle_sprite32(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); -void _linear_draw_character32(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _linear_textout_fixed32(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); -void _linear_blit32(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_blit_backward32(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_masked_blit32(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _linear_clear_to_color32(struct BITMAP *bitmap, int color); - -#endif - -int _x_getpixel(struct BITMAP *bmp, int x, int y); -void _x_putpixel(struct BITMAP *bmp, int x, int y, int color); -void _x_vline(struct BITMAP *bmp, int x, int y1, int y2, int color); -void _x_hline(struct BITMAP *bmp, int x1, int y, int x2, int color); -void _x_draw_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _x_draw_sprite_v_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _x_draw_sprite_h_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _x_draw_sprite_vh_flip(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _x_draw_trans_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y); -void _x_draw_lit_sprite(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _x_draw_rle_sprite(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _x_draw_trans_rle_sprite(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y); -void _x_draw_lit_rle_sprite(struct BITMAP *bmp, struct RLE_SPRITE *sprite, int x, int y, int color); -void _x_draw_character(struct BITMAP *bmp, struct BITMAP *sprite, int x, int y, int color); -void _x_textout_fixed(struct BITMAP *bmp, void *f, int h, unsigned char *str, int x, int y, int color); -void _x_blit_from_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _x_blit_to_memory(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _x_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _x_blit_forward(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _x_blit_backward(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _x_masked_blit(struct BITMAP *source, struct BITMAP *dest, int source_x, int source_y, int dest_x, int dest_y, int width, int height); -void _x_clear_to_color(struct BITMAP *bitmap, int color); - - -/* asm helper for stretch_blit() */ -void _do_stretch(BITMAP *source, BITMAP *dest, void *drawer, int sx, fixed sy, fixed syd, int dx, int dy, int dh, int color_depth); - - -/* number of fractional bits used by the polygon rasteriser */ -#define POLYGON_FIX_SHIFT 18 - - -/* bitfield specifying which polygon attributes need interpolating */ -#define INTERP_FLAT 1 -#define INTERP_1COL 2 -#define INTERP_3COL 4 -#define INTERP_FIX_UV 8 -#define INTERP_Z 16 -#define INTERP_FLOAT_UV 32 -#define OPT_FLOAT_UV_TO_FIX 64 -#define COLOR_TO_RGB 128 - - -/* information for polygon scanline fillers */ -typedef struct POLYGON_SEGMENT -{ - fixed u, v, du, dv; /* fixed point u/v coordinates */ - fixed c, dc; /* single color gouraud shade values */ - fixed r, g, b, dr, dg, db; /* RGB gouraud shade values */ - float z, dz; /* polygon depth (1/z) */ - float fu, fv, dfu, dfv; /* floating point u/v coordinates */ - unsigned char *texture; /* the texture map */ - int umask, vmask, vshift; /* texture map size information */ - int seg; /* destination bitmap selector */ -} POLYGON_SEGMENT; - - -/* an active polygon edge */ -typedef struct POLYGON_EDGE -{ - int top; /* top y position */ - int bottom; /* bottom y position */ - fixed x, dx; /* fixed point x position and gradient */ - fixed w; /* width of line segment */ - POLYGON_SEGMENT dat; /* texture/gouraud information */ - struct POLYGON_EDGE *prev; /* doubly linked list */ - struct POLYGON_EDGE *next; -} POLYGON_EDGE; - - -/* prototype for the scanline filler functions */ -typedef void (*SCANLINE_FILLER)(unsigned long addr, int w, POLYGON_SEGMENT *info); - - -/* polygon helper functions */ -extern SCANLINE_FILLER _optim_alternative_drawer; -POLYGON_EDGE *_add_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge, int sort_by_x); -POLYGON_EDGE *_remove_edge(POLYGON_EDGE *list, POLYGON_EDGE *edge); -void _fill_3d_edge_structure(POLYGON_EDGE *edge, V3D *v1, V3D *v2, int flags, BITMAP *bmp); -void _fill_3d_edge_structure_f(POLYGON_EDGE *edge, V3D_f *v1, V3D_f *v2, int flags, BITMAP *bmp); -SCANLINE_FILLER _get_scanline_filler(int type, int *flags, POLYGON_SEGMENT *info, BITMAP *texture, BITMAP *bmp); -void _clip_polygon_segment(POLYGON_SEGMENT *info, int gap, int flags); - - -/* polygon scanline filler functions */ -void _poly_scanline_gcol8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_grgb8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit8(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit8(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb8x(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb15(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask15(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask15(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit15(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit15(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit15(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit15(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb15x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit15x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit15x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit15x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit15x(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_ptex_lit15d(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit15d(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb16(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex16(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex16(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask16(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask16(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit16(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit16(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit16(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit16(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb16x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit16x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit16x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit16x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit16x(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_ptex_lit16d(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit16d(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb24(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex24(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex24(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask24(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask24(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit24(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit24(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit24(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit24(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb24x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit24x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit24x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit24x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit24x(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_ptex_lit24d(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit24d(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb32(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex32(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex32(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask32(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask32(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit32(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit32(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit32(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit32(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_grgb32x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_lit32x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_lit32x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_atex_mask_lit32x(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit32x(unsigned long addr, int w, POLYGON_SEGMENT *info); - -void _poly_scanline_ptex_lit32d(unsigned long addr, int w, POLYGON_SEGMENT *info); -void _poly_scanline_ptex_mask_lit32d(unsigned long addr, int w, POLYGON_SEGMENT *info); - - -/* sound lib stuff */ -extern int _digi_volume; -extern int _midi_volume; -extern int _flip_pan; -extern int _sound_hq; - -extern int (*_midi_init)(void); -extern void (*_midi_exit)(void); - -int _midi_allocate_voice(int min, int max); - -extern volatile long _midi_tick; - -int _digmid_find_patches(char *dir, char *file); - -#define VIRTUAL_VOICES 256 - - -typedef struct /* a virtual (as seen by the user) soundcard voice */ -{ - SAMPLE *sample; /* which sample are we playing? (NULL = free) */ - int num; /* physical voice number (-1 = been killed off) */ - int autokill; /* set to free the voice when the sample finishes */ - long time; /* when we were started (for voice allocation) */ - int priority; /* how important are we? */ -} VOICE; - -extern VOICE _voice[VIRTUAL_VOICES]; - - -typedef struct /* a physical (as used by hardware) soundcard voice */ -{ - int num; /* the virtual voice currently using me (-1 = free) */ - int playmode; /* are we looping? */ - int vol; /* current volume (fixed point .12) */ - int dvol; /* volume delta, for ramping */ - int target_vol; /* target volume, for ramping */ - int pan; /* current pan (fixed point .12) */ - int dpan; /* pan delta, for sweeps */ - int target_pan; /* target pan, for sweeps */ - int freq; /* current frequency (fixed point .12) */ - int dfreq; /* frequency delta, for sweeps */ - int target_freq; /* target frequency, for sweeps */ -} PHYS_VOICE; - -extern PHYS_VOICE _phys_voice[DIGI_VOICES]; - - -#define MIXER_DEF_SFX 8 -#define MIXER_MAX_SFX 64 - -int _mixer_init(int bufsize, int freq, int stereo, int is16bit, int *voices); -void _mixer_exit(void); -void _mix_some_samples(unsigned long buf, unsigned short seg, int issigned); - -void _mixer_init_voice(int voice, SAMPLE *sample); -void _mixer_release_voice(int voice); -void _mixer_start_voice(int voice); -void _mixer_stop_voice(int voice); -void _mixer_loop_voice(int voice, int loopmode); -int _mixer_get_position(int voice); -void _mixer_set_position(int voice, int position); -int _mixer_get_volume(int voice); -void _mixer_set_volume(int voice, int volume); -void _mixer_ramp_volume(int voice, int time, int endvol); -void _mixer_stop_volume_ramp(int voice); -int _mixer_get_frequency(int voice); -void _mixer_set_frequency(int voice, int frequency); -void _mixer_sweep_frequency(int voice, int time, int endfreq); -void _mixer_stop_frequency_sweep(int voice); -int _mixer_get_pan(int voice); -void _mixer_set_pan(int voice, int pan); -void _mixer_sweep_pan(int voice, int time, int endpan); -void _mixer_stop_pan_sweep(int voice); -void _mixer_set_echo(int voice, int strength, int delay); -void _mixer_set_tremolo(int voice, int rate, int depth); -void _mixer_set_vibrato(int voice, int rate, int depth); - -/* dummy functions for the NoSound drivers */ -int _dummy_detect(int input); -int _dummy_init(int input, int voices); -void _dummy_exit(int input); -int _dummy_mixer_volume(int volume); -void _dummy_init_voice(int voice, SAMPLE *sample); -void _dummy_noop1(int p); -void _dummy_noop2(int p1, int p2); -void _dummy_noop3(int p1, int p2, int p3); -int _dummy_get_position(int voice); -int _dummy_get(int voice); -void _dummy_raw_midi(unsigned char data); -int _dummy_load_patches(char *patches, char *drums); -void _dummy_adjust_patches(char *patches, char *drums); -void _dummy_key_on(int inst, int note, int bend, int vol, int pan); - - -/* from djgpp's libc, needed to find which directory we were run from */ -extern int __crt0_argc; -extern char **__crt0_argv; - - -#endif /* ifndef INTERNAL_H */ diff --git a/src/djgppdos/rdb-s.h b/src/djgppdos/rdb-s.h deleted file mode 100644 index 7a6d8be3c..000000000 --- a/src/djgppdos/rdb-s.h +++ /dev/null @@ -1,22 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2005-2018 by Sonic Team Jr. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Set Com port and speed for GDBStubs for DJGGP -/// -/// copy and rename as rdb.h and set the defines below as needed - -#define DEBUG_COM_PORT 2 -#define DEBUG_COM_PORT_SPEED 9600 diff --git a/src/djgppdos/vid_vesa.c b/src/djgppdos/vid_vesa.c deleted file mode 100644 index 01a27dcea..000000000 --- a/src/djgppdos/vid_vesa.c +++ /dev/null @@ -1,900 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief extended vesa VESA2.0 video modes i/o - -#include - -#include "../i_system.h" //I_Error() -#include "vid_vesa.h" -#include "../doomdef.h" //MAXVIDWIDTH, MAXVIDHEIGHT -#include "../screen.h" - -#include -#include -#include -#include -#include -#include - -#include "../console.h" -#include "../command.h" //added:21-03-98: vid_xxx commands -#include "../i_video.h" - - -// PROTOS -static vmode_t *VID_GetModePtr (int modenum); -static int VID_VesaGetModeInfo (int modenum); -static void VID_VesaGetExtraModes (void); -static INT32 VID_VesaInitMode (viddef_t *lvid, vmode_t *pcurrentmode); - -static void VID_Command_NumModes_f (void); -static void VID_Command_ModeInfo_f (void); -static void VID_Command_ModeList_f (void); -static void VID_Command_Mode_f (void); - -consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_stretch = {"stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - -#define VBEVERSION 2 // we need vesa2 or higher - -// ----------------------------------------------------- -#define MASK_LINEAR(addr) (addr & 0x000FFFFF) -#define RM_TO_LINEAR(addr) (((addr & 0xFFFF0000) >> 12) + (addr & 0xFFFF)) -#define RM_OFFSET(addr) (addr & 0xF) -#define RM_SEGMENT(addr) ((addr >> 4) & 0xFFFF) -// ----------------------------------------------------- - -static int totalvidmem; - -static vmode_t vesa_modes[MAX_VESA_MODES] = {{NULL, NULL, 0, 0, 0, 0, 0, 0, NULL, NULL, 0}}; -static vesa_extra_t vesa_extra[MAX_VESA_MODES]; - -//this is the only supported non-vesa mode : standard 320x200x256c. -#define NUMVGAVIDMODES 1 -static INT32 VGA_InitMode (viddef_t *lvid, vmode_t *pcurrentmode); -static char vgamode1[] ="320x200"; -static vmode_t vgavidmodes[NUMVGAVIDMODES] = { - { - NULL, - vgamode1, - 320, 200, //(200.0/320.0)*(320.0/240.0), - 320, 1, // rowbytes, bytes per pixel - 0, 1, - NULL, - VGA_InitMode, 0 - } -}; - -static char names[MAX_VESA_MODES][10]; - -//----------------------------i_video.c------------------------------------ -// these ones should go to i_video.c, but I prefer keep them away from the -// doom sources until the vesa stuff is ok. -static int numvidmodes; //total number of video modes, vga, vesa1, vesa2. -static vmode_t *pvidmodes; //start of videomodes list. -static vmode_t *pcurrentmode; // the current active videomode. -//----------------------------i_video.c------------------------------------ - - - -// table des modes videos. -// seul le mode 320x200x256c standard VGA est support� sans le VESA. -// ce mode est le mode num�ro 0 dans la liste. -typedef struct -{ - int modenum; // vesa vbe2.0 modenum - int mode_attributes; - int winasegment; - int winbsegment; - int bytes_per_scanline; // bytes per logical scanline (+16) - int win; // window number (A=0, B=1) - int win_size; // window size (+6) - int granularity; // how finely i can set the window in vid mem (+4) - int width, height; // displayed width and height (+18, +20) - int bits_per_pixel; // er, better be 8, 15, 16, 24, or 32 (+25) - int bytes_per_pixel; // er, better be 1, 2, or 4 - int memory_model; // and better be 4 or 6, packed or direct color (+27) - int num_pages; // number of complete frame buffer pages (+29) - int red_width; // the # of bits in the red component (+31) - int red_pos; // the bit position of the red component (+32) - int green_width; // etc.. (+33) - int green_pos; // (+34) - int blue_width; // (+35) - int blue_pos; // (+36) - int pptr; - int pagesize; - int numpages; -} modeinfo_t; - -static vbeinfoblock_t vesainfo; -static vesamodeinfo_t vesamodeinfo; - -// ------------------------------------------------------------------------ -// DOS stuff -// ------------------------------------------------------------------------ -static unsigned long conventional_memory = (unsigned long)-1; - -FUNCINLINE static ATTRINLINE void map_in_conventional_memory(void) -{ - if (conventional_memory == (unsigned long)-1) - { - if (__djgpp_nearptr_enable()) - { - conventional_memory = __djgpp_conventional_base; - } - } -} - -// Converts a flat 32 bit ptr to a realmode 0x12345 type ptr (seg<<4 + offs) -#if 0 -unsigned int ptr2real(void *ptr) -{ - map_in_conventional_memory(); - return (int)ptr - conventional_memory; -} -#endif - -// Converts 0x12345 (seg<<4+offs) realmode ptr to a flat 32bit ptr -FUNCINLINE static ATTRINLINE void *real2ptr(unsigned int real) -{ - map_in_conventional_memory(); - return (void *) (real + conventional_memory); -} - -// ------------------------------------------------------------------------ - - -/* ======================================================================== */ -// Add the standard VGA video modes (only one now) to the video modes list. -/* ======================================================================== */ -static inline void VGA_Init(void) -{ - vgavidmodes[NUMVGAVIDMODES-1].pnext = pvidmodes; - pvidmodes = &vgavidmodes[0]; - numvidmodes += NUMVGAVIDMODES; -} - - -//added:30-01-98: return number of video modes in pvidmodes list -INT32 VID_NumModes(void) -{ - return numvidmodes; -} - -//added:21-03-98: return info on video mode -FUNCINLINE static ATTRINLINE const char *VID_ModeInfo (int modenum, char **ppheader) -{ - static const char *badmodestr = "Bad video mode number\n"; - vmode_t *pv; - - pv = VID_GetModePtr (modenum); - - if (!pv) - { - if (ppheader) - *ppheader = NULL; - return badmodestr; - } - else - { - //if (ppheader) - // *ppheader = pv->header; - return pv->name; - } -} - - - -//added:03-02-98: return a video mode number from the dimensions -INT32 VID_GetModeForSize( INT32 w, INT32 h) -{ - vmode_t *pv; - int modenum; - - pv = pvidmodes; - for (modenum=0; pv!=NULL; pv=pv->pnext,modenum++ ) - { - if ( pv->width==(unsigned)w && pv->height==(unsigned)h ) - return modenum; - } - - return 0; -} - - -/* ======================================================================== */ -// -/* ======================================================================== */ -void VID_Init (void) -{ - COM_AddCommand ("vid_nummodes", VID_Command_NumModes_f); - COM_AddCommand ("vid_modeinfo", VID_Command_ModeInfo_f); - COM_AddCommand ("vid_modelist", VID_Command_ModeList_f); - COM_AddCommand ("vid_mode", VID_Command_Mode_f); - CV_RegisterVar (&cv_vidwait); - CV_RegisterVar (&cv_stretch); - - //setup the videmodes list, - // note that mode 0 must always be VGA mode 0x13 - pvidmodes = NULL; - pcurrentmode = NULL; - numvidmodes = 0; - // setup the vesa_modes list - VID_VesaGetExtraModes (); - - // the game boots in 320x200 standard VGA, but - // we need a highcolor mode to run the game in highcolor - if (highcolor && numvidmodes==0) - I_Error ("No 15bit highcolor VESA2 video mode found, cannot run in highcolor.\n"); - - // add the vga modes at the start of the modes list - VGA_Init(); - - -#ifdef DEBUG - CONS_Printf("VID_SetMode(%d)\n",vid.modenum); -#endif - VID_SetMode (0); //vid.modenum); - - -#ifdef DEBUG - CONS_Printf("after VID_SetMode\n"); - CONS_Printf("vid.width %d\n",vid.width); - CONS_Printf("vid.height %d\n",vid.height); - CONS_Printf("vid.buffer %x\n",vid.buffer); - CONS_Printf("vid.rowbytes %d\n",vid.rowbytes); - CONS_Printf("vid.numpages %d\n",vid.numpages); - CONS_Printf("vid.recalc %d\n",vid.recalc); - CONS_Printf("vid.direct %x\n",vid.direct); -#endif - -} - - -// ======================================================================== -// Returns a vmode_t from the video modes list, given a video mode number. -// ======================================================================== -vmode_t *VID_GetModePtr (int modenum) -{ - vmode_t *pv; - - pv = pvidmodes; - if (!pv) - I_Error ("VID_error 1\n"); - - while (modenum--) - { - pv = pv->pnext; - if (!pv) - I_Error ("VID_error 2\n"); - } - - return pv; -} - - -//added:30-01-98:return the name of a video mode -const char *VID_GetModeName (INT32 modenum) -{ - return (VID_GetModePtr(modenum))->name; -} - - -// ======================================================================== -// Sets a video mode -// ======================================================================== -INT32 VID_SetMode (INT32 modenum) //, UINT8 *palette) -{ - int vstat; - vmode_t *pnewmode, *poldmode; - - if ((modenum >= numvidmodes) || (modenum < 0)) - { - if (pcurrentmode == NULL) - { - modenum = 0; // mode hasn't been set yet, so initialize to base - // mode since they gave us an invalid initial mode - } - else - { - //nomodecheck = true; - I_Error ("Unknown video mode: %d\n", modenum); - //nomodecheck = false; - return 0; - } - } - - pnewmode = VID_GetModePtr (modenum); - - if (pnewmode == pcurrentmode) - return 1; // already in the desired mode - - // initialize the new mode - poldmode = pcurrentmode; - pcurrentmode = pnewmode; - - // initialize vidbuffer size for setmode - vid.width = pcurrentmode->width; - vid.height = pcurrentmode->height; - //vid.aspect = pcurrentmode->aspect; - vid.rowbytes = pcurrentmode->rowbytes; - vid.bpp = pcurrentmode->bytesperpixel; - - //debug - //if (vid.rowbytes != vid.width) - // I_Error("vidrowbytes (%d) <> vidwidth(%d)\n",vid.rowbytes,vid.width); - - vstat = (*pcurrentmode->setmode) (&vid, pcurrentmode); - - if (vstat < 1) - { - if (vstat == 0) - { - // harware could not setup mode - //if (!VID_SetMode (vid.modenum)) - // I_Error ("VID_SetMode: couldn't set video mode (hard failure)"); - I_Error("Couldn't set video mode %d\n", modenum); - } - else - if (vstat == -1) - { - CONS_Printf ("Not enough mem for VID_SetMode...\n"); - - // not enough memory; just put things back the way they were - pcurrentmode = poldmode; - vid.width = pcurrentmode->width; - vid.height = pcurrentmode->height; - vid.rowbytes = pcurrentmode->rowbytes; - vid.bpp = pcurrentmode->bytesperpixel; - return 0; - } - } - - vid.modenum = modenum; - - //printf ("%s\n", VID_ModeInfo (vid.modenum, NULL)); - - //added:20-01-98: recalc all tables and realloc buffers based on - // vid values. - vid.recalc = 1; - - if (!cv_stretch.value && (float)vid.width/vid.height != ((float)BASEVIDWIDTH/BASEVIDHEIGHT)) - vid.height = (int)(vid.width * ((float)BASEVIDHEIGHT/BASEVIDWIDTH));// Adjust the height to match - - return 1; -} - - - -// converts a segm:offs 32bit pair to a 32bit flat ptr -#if 0 -void *VID_ExtraFarToLinear (void *ptr) -{ - int temp; - - temp = (int)ptr; - return real2ptr (((temp & 0xFFFF0000) >> 12) + (temp & 0xFFFF)); -} -#endif - - - -// ======================================================================== -// Helper function for VID_VesaGetExtraModes -// In: vesa mode number, from the vesa videomodenumbers list -// Out: false, if no info for given modenum -// ======================================================================== -int VID_VesaGetModeInfo (int modenum) -{ - int bytes_per_pixel; - unsigned int i; - __dpmi_regs regs; - - for (i=0; i 2) || - (vesamodeinfo.XResolution > MAXVIDWIDTH) || - (vesamodeinfo.YResolution > MAXVIDHEIGHT)) - { - return false; - } - - // we only want color graphics modes that are supported by the hardware - if ((vesamodeinfo.ModeAttributes & - (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE) ) != - (MODE_SUPPORTED_IN_HW | COLOR_MODE | GRAPHICS_MODE)) - { - return false; - } - - // we only work with linear frame buffers, except for 320x200, - // which is linear when banked at 0xA000 - if (!(vesamodeinfo.ModeAttributes & LINEAR_FRAME_BUFFER)) - { - if ((vesamodeinfo.XResolution != 320) || - (vesamodeinfo.YResolution != 200)) - { - return false; - } - } - - // pagesize - if ((vesamodeinfo.BytesPerScanLine * vesamodeinfo.YResolution) - > totalvidmem) - { - return false; - } - - vesamodeinfo.NumberOfImagePages = 1; - - -#ifdef DEBUG - CONS_Printf("VID: (VESA) info for mode 0x%x\n", modeinfo.modenum); - CONS_Printf(" mode attrib = 0x%0x\n", modeinfo.mode_attributes); - CONS_Printf(" win a attrib = 0x%0x\n", *(UINT8 *)(infobuf+2)); - CONS_Printf(" win b attrib = 0x%0x\n", *(UINT8 *)(infobuf+3)); - CONS_Printf(" win a seg 0x%0x\n", (int) modeinfo.winasegment); - CONS_Printf(" win b seg 0x%0x\n", (int) modeinfo.winbsegment); - CONS_Printf(" bytes per scanline = %d\n", - modeinfo.bytes_per_scanline); - CONS_Printf(" width = %d, height = %d\n", modeinfo.width, - modeinfo.height); - CONS_Printf(" win = %c\n", 'A' + modeinfo.win); - CONS_Printf(" win granularity = %d\n", modeinfo.granularity); - CONS_Printf(" win size = %d\n", modeinfo.win_size); - CONS_Printf(" bits per pixel = %d\n", modeinfo.bits_per_pixel); - CONS_Printf(" bytes per pixel = %d\n", modeinfo.bytes_per_pixel); - CONS_Printf(" memory model = 0x%x\n", modeinfo.memory_model); - CONS_Printf(" num pages = %d\n", modeinfo.num_pages); - CONS_Printf(" red width = %d\n", modeinfo.red_width); - CONS_Printf(" red pos = %d\n", modeinfo.red_pos); - CONS_Printf(" green width = %d\n", modeinfo.green_width); - CONS_Printf(" green pos = %d\n", modeinfo.green_pos); - CONS_Printf(" blue width = %d\n", modeinfo.blue_width); - CONS_Printf(" blue pos = %d\n", modeinfo.blue_pos); - CONS_Printf(" phys mem = %x\n", modeinfo.pptr); -#endif - } - - return true; -} - - -// ======================================================================== -// Get extended VESA modes information, keep the ones that we support, -// so they'll be available in the game Video menu. -// ======================================================================== -#define MAXVESADESC 100 -static char vesadesc[MAXVESADESC] = ""; - -void VID_VesaGetExtraModes (void) -{ - unsigned int i; - unsigned long addr; - int nummodes; - __dpmi_meminfo phys_mem_info; - unsigned long mode_ptr; - __dpmi_regs regs; - - // make a copy of the video modes list! else trash in __tb - UINT16 vmode[MAX_VESA_MODES+1]; - int numvmodes; - UINT16 vesamode; - - // new ugly stuff... - for (i=0; i>8, - vesainfo.VESAVersion&0xFF); - - // - // vesa description string - // - i = 0; - addr = RM_TO_LINEAR(vesainfo.OemStringPtr); - _farsetsel(_dos_ds); - while (_farnspeekb(addr) != 0) - { - vesadesc[i++] = _farnspeekb(addr++); - if (i == MAXVESADESC-1) - break; - } - vesadesc[i]=0; - CONS_Printf ("%s)\n",vesadesc); - - totalvidmem = vesainfo.TotalMemory << 16; - - // - // find 8 bit modes - // - numvmodes = 0; - mode_ptr = RM_TO_LINEAR(vesainfo.VideoModePtr); - while ((vmode[numvmodes] = _farpeekw(_dos_ds, mode_ptr)) != 0xFFFF) - { - numvmodes++; - if ( numvmodes == MAX_VESA_MODES ) - break; - mode_ptr += 2; - } - vmode[numvmodes] = 0xffff; - - nummodes = 0; // number of video modes accepted for the game - - numvmodes=0; // go again through vmodes table - while ( ((vesamode=vmode[numvmodes++]) != 0xFFFF) && (nummodes < MAX_VESA_MODES) ) - { - //fill the modeinfo struct. - if (VID_VesaGetModeInfo (vesamode)) - { - vesa_modes[nummodes].pnext = &vesa_modes[nummodes+1]; - if (vesamodeinfo.XResolution > 999) - { - if (vesamodeinfo.YResolution > 999) - { - sprintf (&names[nummodes][0], "%4dx%4d", vesamodeinfo.XResolution, - vesamodeinfo.YResolution); - names[nummodes][9] = 0; - } - else - { - sprintf (&names[nummodes][0], "%4dx%3d", vesamodeinfo.XResolution, - vesamodeinfo.YResolution); - names[nummodes][8] = 0; - } - } - else - { - if (vesamodeinfo.YResolution > 999) - { - sprintf (&names[nummodes][0], "%3dx%4d", vesamodeinfo.XResolution, - vesamodeinfo.YResolution); - names[nummodes][8] = 0; - } - else - { - sprintf (&names[nummodes][0], "%3dx%3d", vesamodeinfo.XResolution, - vesamodeinfo.YResolution); - names[nummodes][7] = 0; - } - } - - vesa_modes[nummodes].name = &names[nummodes][0]; - vesa_modes[nummodes].width = vesamodeinfo.XResolution; - vesa_modes[nummodes].height = vesamodeinfo.YResolution; - - //added:20-01-98:aspect ratio to be implemented... - vesa_modes[nummodes].rowbytes = vesamodeinfo.BytesPerScanLine; - vesa_modes[nummodes].windowed = 0; - vesa_modes[nummodes].pextradata = &vesa_extra[nummodes]; - vesa_modes[nummodes].setmode = VID_VesaInitMode; - - if (vesamodeinfo.ModeAttributes & LINEAR_FRAME_BUFFER) - { - // add linear bit to mode for linear modes - vesa_extra[nummodes].vesamode = vesamode | LINEAR_MODE; - vesa_modes[nummodes].numpages = 1; //vesamodeinfo.NumberOfImagePages; - - phys_mem_info.address = (int)vesamodeinfo.PhysBasePtr; - phys_mem_info.size = 0x400000; - - // returns -1 on error - if (__dpmi_physical_address_mapping(&phys_mem_info)) - { - //skip this mode, it doesnt work - continue; - } - - // if physical mapping was ok... convert the selector:offset - vesa_extra[nummodes].plinearmem = - real2ptr (phys_mem_info.address); - - // lock the region - __dpmi_lock_linear_region (&phys_mem_info); - } - else - { - // banked at 0xA0000 - vesa_extra[nummodes].vesamode = vesamode; - //vesa_extra[nummodes].pages[0] = 0; - vesa_extra[nummodes].plinearmem = - real2ptr (vesamodeinfo.WinASegment<<4); - - vesa_modes[nummodes].numpages = 1; //modeinfo.numpages; - } - - vesa_modes[nummodes].bytesperpixel = (vesamodeinfo.BitsPerPixel+1)/8; - - nummodes++; - } - } - -// add the VESA modes at the start of the mode list (if there are any) - if (nummodes) - { - vesa_modes[nummodes-1].pnext = NULL; //pvidmodes; - pvidmodes = &vesa_modes[0]; - numvidmodes += nummodes; - } - -} - - -// ======================================================================== -// Free the video buffer of the last video mode, -// allocate a new buffer for the video mode to set. -// ======================================================================== -static boolean VID_FreeAndAllocVidbuffer (viddef_t *lvid) -{ - int vidbuffersize; - - vidbuffersize = (lvid->width * lvid->height * lvid->bpp * NUMSCREENS); //status bar - - // free allocated buffer for previous video mode - if (lvid->buffer!=NULL) - { - free(lvid->buffer); - } - - // allocate the new screen buffer - if ( (lvid->buffer = (UINT8 *) malloc(vidbuffersize))==NULL ) - return false; - - // initially clear the video buffer - memset (lvid->buffer, 0x00, vidbuffersize); - -#ifdef DEBUG - CONS_Printf("VID_FreeAndAllocVidbuffer done, vidbuffersize: %x\n",vidbuffersize); -#endif - return true; -} - - -// ======================================================================== -// Set video mode routine for STANDARD VGA MODES (NO HIGHCOLOR) -// Out: 1 ok, -// 0 hardware could not set mode, -// -1 no mem -// ======================================================================== -static INT32 VGA_InitMode (viddef_t *lvid, vmode_t *currentmodep) -{ - __dpmi_regs regs; - - if (!VID_FreeAndAllocVidbuffer (lvid)) - return -1; //no mem - - //added:26-01-98: should clear video mem here - - //set mode 0x13 - regs.h.ah = 0; - regs.h.al = 0x13; - __dpmi_int(0x10, ®s); - - // here it is the standard VGA 64k window, not an LFB - // (you could have 320x200x256c with LFB in the vesa modes) - lvid->direct = (UINT8 *) real2ptr (0xa0000); - lvid->u.numpages = 1; - lvid->bpp = currentmodep->bytesperpixel; - - return 1; -} - - -// ======================================================================== -// Set video mode routine for VESA video modes, see VID_SetMode() -// Out: 1 ok, -// 0 hardware could not set mode, -// -1 no mem -// ======================================================================== -INT32 VID_VesaInitMode (viddef_t *lvid, vmode_t *currentmodep) -{ - vesa_extra_t *pextra; - __dpmi_regs regs; - - pextra = currentmodep->pextradata; - -#ifdef DEBUG - CONS_Printf("VID_VesaInitMode...\n"); - CONS_Printf(" currentmodep->name %s\n",currentmodep->name); - CONS_Printf(" width %d\n",currentmodep->width); - CONS_Printf(" height %d\n",currentmodep->height); - CONS_Printf(" rowbytes %d\n",currentmodep->rowbytes); - CONS_Printf(" windowed %d\n",currentmodep->windowed); - CONS_Printf(" numpages %d\n",currentmodep->numpages); - CONS_Printf(" currentmodep->pextradata :\n"); - CONS_Printf(" ->vesamode %x\n",pextra->vesamode); - CONS_Printf(" ->plinearmem %x\n\n",pextra->plinearmem); -#endif - - //added:20-01-98:no page flipping now... TO DO!!! - lvid->u.numpages = 1; - - // clean up any old vid buffer lying around, alloc new if needed - if (!VID_FreeAndAllocVidbuffer (lvid)) - return -1; //no mem - - - //added:20-01-98: should clear video mem here - - - // set the mode - regs.x.ax = 0x4f02; - regs.x.bx = pextra->vesamode; - __dpmi_int (0x10, ®s); - - if (regs.x.ax != 0x4f) - return 0; // could not set mode - -//added:20-01-98: should setup wait_vsync flag, currentpage here... -// plus check for display_enable bit - -//added:20-01-98: here we should set the page if page flipping... - - // points to LFB, or the start of VGA mem. - lvid->direct = pextra->plinearmem; - lvid->bpp = currentmodep->bytesperpixel; - - return 1; -} - -// ======================================================================== -// VIDEO MODE CONSOLE COMMANDS -// ======================================================================== - - -// vid_nummodes -// -//added:21-03-98: -void VID_Command_NumModes_f (void) -{ - int nummodes; - - nummodes = VID_NumModes (); - CONS_Printf ("%d video mode(s) available(s)\n", nummodes); -} - - -// vid_modeinfo -// -void VID_Command_ModeInfo_f (void) -{ - vmode_t *pv; - int modenum; - - if (COM_Argc()!=2) - modenum = vid.modenum; // describe the current mode - else - modenum = atoi (COM_Argv(1)); // .. the given mode number - - if (modenum >= VID_NumModes()) - { - CONS_Printf ("No such video mode\n"); - return; - } - - pv = VID_GetModePtr (modenum); - - CONS_Printf ("%s\n", VID_ModeInfo (modenum, NULL)); - CONS_Printf ("width : %d\n" - "height: %d\n" - "bytes per scanline: %d\n" - "bytes per pixel: %d\n" - "numpages: %d\n", - pv->width, - pv->height, - pv->rowbytes, - pv->bytesperpixel, - pv->numpages ); -} - - -// vid_modelist -// -void VID_Command_ModeList_f (void) -{ - int i, nummodes; - const char *pinfo; - char *pheader; - vmode_t *pv; - boolean na; - - na = false; - - nummodes = VID_NumModes (); - for (i=0 ; ibytesperpixel==1) - CONS_Printf ("%d: %s\n", i, pinfo); - else - CONS_Printf ("%d: %s (hicolor)\n", i, pinfo); - } - -} - - -// vid_mode -// -void VID_Command_Mode_f (void) -{ - int modenum; - - if (COM_Argc()!=2) - { - CONS_Printf ("vid_mode : set video mode\n"); - return; - } - - modenum = atoi(COM_Argv(1)); - - if (modenum >= VID_NumModes()) - CONS_Printf ("No such video mode\n"); - else - // request vid mode change - setmodeneeded = modenum+1; -} diff --git a/src/djgppdos/vid_vesa.h b/src/djgppdos/vid_vesa.h deleted file mode 100644 index b704336e8..000000000 --- a/src/djgppdos/vid_vesa.h +++ /dev/null @@ -1,109 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief VESA extra modes. - -#include "../doomdef.h" -#include "../screen.h" - - - -#define MODE_SUPPORTED_IN_HW 0x0001 -#define COLOR_MODE 0x0008 -#define GRAPHICS_MODE 0x0010 -#define VGA_INCOMPATIBLE 0x0020 -#define LINEAR_FRAME_BUFFER 0x0080 -#define LINEAR_MODE 0x4000 - -#define MAX_VESA_MODES 30 // we'll just take the first 30 if there - - -// VESA information block structure -typedef struct vbeinfoblock_s -{ - UINT8 VESASignature[4]; - UINT16 VESAVersion; - unsigned long OemStringPtr; - UINT8 Capabilities[4]; - unsigned long VideoModePtr; - UINT16 TotalMemory; - UINT8 OemSoftwareRev[2]; - UINT8 OemVendorNamePtr[4]; - UINT8 OemProductNamePtr[4]; - UINT8 OemProductRevPtr[4]; - UINT8 Reserved[222]; - UINT8 OemData[256]; -} ATTRPACK vbeinfoblock_t; - - -// VESA information for a specific mode -typedef struct vesamodeinfo_s -{ - UINT16 ModeAttributes; - UINT8 WinAAttributes; - UINT8 WinBAttributes; - UINT16 WinGranularity; - UINT16 WinSize; - UINT16 WinASegment; - UINT16 WinBSegment; - unsigned long WinFuncPtr; - UINT16 BytesPerScanLine; - UINT16 XResolution; - UINT16 YResolution; - UINT8 XCharSize; - UINT8 YCharSize; - UINT8 NumberOfPlanes; - UINT8 BitsPerPixel; - UINT8 NumberOfBanks; - UINT8 MemoryModel; - UINT8 BankSize; - UINT8 NumberOfImagePages; - UINT8 Reserved_page; - UINT8 RedMaskSize; - UINT8 RedMaskPos; - UINT8 GreenMaskSize; - UINT8 GreenMaskPos; - UINT8 BlueMaskSize; - UINT8 BlueMaskPos; - UINT8 ReservedMaskSize; - UINT8 ReservedMaskPos; - UINT8 DirectColorModeInfo; - - /* VBE 2.0 extensions */ - unsigned long PhysBasePtr; - unsigned long OffScreenMemOffset; - UINT16 OffScreenMemSize; - - /* VBE 3.0 extensions */ - UINT16 LinBytesPerScanLine; - UINT8 BnkNumberOfPages; - UINT8 LinNumberOfPages; - UINT8 LinRedMaskSize; - UINT8 LinRedFieldPos; - UINT8 LinGreenMaskSize; - UINT8 LinGreenFieldPos; - UINT8 LinBlueMaskSize; - UINT8 LinBlueFieldPos; - UINT8 LinRsvdMaskSize; - UINT8 LinRsvdFieldPos; - unsigned long MaxPixelClock; - - UINT8 Reserved[190]; -} ATTRPACK vesamodeinfo_t; - - -// setup standard VGA + VESA modes list, activate the default video mode. -void VID_Init (void); diff --git a/src/doomdata.h b/src/doomdata.h index 767e47383..ed01f42c6 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -23,6 +23,8 @@ // Some global defines, that configure the game. #include "doomdef.h" +#include "m_fixed.h" // See the mapthing_t scale. + // // Map level types. // The following data structures define the persistent format @@ -46,7 +48,7 @@ enum ML_BLOCKMAP, // LUT, motion clipping, walls/grid element }; -// Extra flag for objects +// Extra flag for objects. #define MTF_EXTRA 1 // Reverse gravity flag for objects. @@ -130,14 +132,12 @@ typedef struct #define ML_EFFECT4 512 #define ML_EFFECT5 1024 -// New ones to disable lines for characters -#define ML_NOSONIC 2048 -#define ML_NOTAILS 4096 -#define ML_NOKNUX 8192 -#define ML_NETONLY 14336 // all of the above +#define ML_NETONLY 2048 // Apply effect only in netgames +#define ML_NONET 4096 // Apply effect only in single player games +#define ML_EFFECT6 8192 -// Bounce off walls! -#define ML_BOUNCY 16384 +// Don't bounce off this wall! +#define ML_NOTBOUNCY 16384 #define ML_TFERLINE 32768 @@ -195,24 +195,36 @@ typedef struct #pragma pack() #endif +#define NUMMAPTHINGARGS 6 +#define NUMMAPTHINGSTRINGARGS 2 + // Thing definition, position, orientation and type, // plus visibility flags and attributes. typedef struct { INT16 x, y; - INT16 angle; + INT16 angle, pitch, roll; UINT16 type; UINT16 options; INT16 z; UINT8 extrainfo; + fixed_t scale; + INT16 tag; + INT32 args[NUMMAPTHINGARGS]; + char *stringargs[NUMMAPTHINGSTRINGARGS]; + struct mobj_s *mobj; } mapthing_t; #define ZSHIFT 4 -//extern const char *Color_Names[MAXSKINCOLORS]; -//extern const UINT8 Color_Opposite[MAXSKINCOLORS*2]; - #define NUMMAPS 1035 +/* slope thing types */ +enum +{ + FLOOR_SLOPE_THING = 777, + CEILING_SLOPE_THING = 778, +}; + #endif // __DOOMDATA__ diff --git a/src/doomdef.h b/src/doomdef.h index 3a49cccd4..9c4664135 100644 --- a/src/doomdef.h +++ b/src/doomdef.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,13 +28,10 @@ // Use Mixer interface? #ifdef HAVE_MIXER - //#if !defined(DC) && !defined(_WIN32_WCE) && !defined(_XBOX) && !defined(GP2X) #define SOUND SOUND_MIXER - #define NOHS // No HW3SOUND #ifdef HW3SOUND #undef HW3SOUND #endif - //#endif #endif // Use generic SDL interface. @@ -47,7 +44,6 @@ // Use FMOD? #ifdef HAVE_FMOD #define SOUND SOUND_FMOD - #define NOHS // No HW3SOUND #ifdef HW3SOUND #undef HW3SOUND #endif @@ -64,13 +60,9 @@ #if !defined (HWRENDER) && !defined (NOHW) #define HWRENDER #endif -// judgecutor: 3D sound support -#if !defined(HW3SOUND) && !defined (NOHS) -#define HW3SOUND -#endif #endif -#if defined (_WIN32) || defined (_WIN32_WCE) +#ifdef _WIN32 #define ASMCALL __cdecl #else #define ASMCALL @@ -87,14 +79,8 @@ // warning C4152: nonstandard extension, function/data pointer conversion in expression // warning C4213: nonstandard extension used : cast on l-value -#if defined (_WIN32_WCE) && defined (DEBUG) && defined (ARM) -#if defined (ARMV4) || defined (ARMV4I) -//#pragma warning(disable : 1166) -// warning LNK1166: cannot adjust code at offset= -#endif -#endif - +#include "version.h" #include "doomtype.h" #include @@ -107,23 +93,17 @@ #ifdef GETTEXT #include -#include #endif +#include // locale should not be dependent on GETTEXT -- 11/01/20 Monster Iestyn -#if !defined (_WIN32_WCE) #include #include -#endif #include -#if ((defined (_WIN32) && !defined (_WIN32_WCE)) || defined (__DJGPP__)) && !defined (_XBOX) +#if defined (_WIN32) || defined (__DJGPP__) #include #endif -#ifdef PC_DOS -#include -#endif - //#define NOMD5 // Uncheck this to compile debugging code @@ -146,21 +126,26 @@ extern char logfilename[1024]; //#define DEVELOP // Disable this for release builds to remove excessive cheat commands and enable MD5 checking and stuff, all in one go. :3 #ifdef DEVELOP -#define VERSION 0 // Game version -#define SUBVERSION 0 // more precise version number #define VERSIONSTRING "Development EXE" -#define VERSIONSTRINGW L"Development EXE" // most interface strings are ignored in development mode. // we use comprevision and compbranch instead. +// VERSIONSTRING_RC is for the resource-definition script used by windows builds #else -#define VERSION 2 // Game version -#define SUBVERSION 0 // more precise version number -#define VERSIONSTRING "v2.0" -#define VERSIONSTRINGW L"v2.0" -// Hey! If you change this, add 1 to the MODVERSION below! Otherwise we can't force updates! -// And change CMakeLists.txt, for CMake users! -// AND appveyor.yml, for the build bots! +#ifdef BETAVERSION +#define VERSIONSTRING "v"SRB2VERSION" "BETAVERSION +#define VERSIONSTRING_RC SRB2VERSION " " BETAVERSION "\0" +#else +#define VERSIONSTRING "v"SRB2VERSION +#define VERSIONSTRING_RC SRB2VERSION "\0" #endif +// Hey! If you change this, add 1 to the MODVERSION below! +// Otherwise we can't force updates! +#endif + +#define VERSIONSTRINGW WSTRING (VERSIONSTRING) + +/* A custom URL protocol for server links. */ +#define SERVER_URL_PROTOCOL "srb2kart://" // Does this version require an added patch file? // Comment or uncomment this as necessary. @@ -175,57 +160,27 @@ extern char logfilename[1024]; // the other options the same. // Comment out this line to completely disable update alerts (recommended for testing, but not for release) +#ifndef BETAVERSION #define UPDATE_ALERT +#endif // The string used in the alert that pops up in the event of an update being available. // Please change to apply to your modification (we don't want everyone asking where your mod is on SRB2.org!). #define UPDATE_ALERT_STRING \ "A new update is available for SRB2Kart.\n"\ -"Please visit mb.srb2.org to download it.\n"\ +"Please visit kartkrew.org to download it.\n"\ "\n"\ "You are using version: %s\n"\ "The newest version is: %s\n"\ "\n"\ -"This update is required for online\n"\ -"play using the Master Server.\n"\ -"You will not be able to connect to\n"\ -"the Master Server until you update to\n"\ -"the newest version of the game.\n"\ -"\n"\ "(Press a key)\n" -// The string used in the I_Error alert upon trying to host through command line parameters. -// Generally less filled with newlines, since Windows gives you lots more room to work with. -#define UPDATE_ALERT_STRING_CONSOLE \ -"A new update is available for SRB2Kart.\n"\ -"Please visit mb.srb2.org to download it.\n"\ -"\n"\ -"You are using version: %s\n"\ -"The newest version is: %s\n"\ -"\n"\ -"This update is required for online play using the Master Server.\n"\ -"You will not be able to connect to the Master Server\n"\ -"until you update to the newest version of the game.\n" - // For future use, the codebase is the version of SRB2 that the modification is based on, // and should not be changed unless you have merged changes between versions of SRB2 // (such as 2.0.4 to 2.0.5, etc) into your working copy. // Will always resemble the versionstring, 205 = 2.0.5, 210 = 2.1, etc. -#define CODEBASE 210 +#define CODEBASE 220 -// The Modification ID; must be obtained from Rob ( https://mb.srb2.org/private.php?do=newpm&u=546 ). -// DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. -// "12" is the default mod ID for version 2.1 -// "17" is the 2.1 Kart's mod ID -#define MODID 17 - -// The Modification Version, starting from 1. Do not follow your version string for this, -// it's only for detection of the version the player is using so the MS can alert them of an update. -// Only set it higher, not lower, obviously. -// Note that we use this to help keep internal testing in check; this is why v2.1.0 is not version "1". -#define MODVERSION 6 - -// Filter consvars by version // To version config.cfg, MAJOREXECVERSION is set equal to MODVERSION automatically. // Increment MINOREXECVERSION whenever a config change is needed that does not correspond // to an increment in MODVERSION. This might never happen in practice. @@ -246,17 +201,33 @@ extern char logfilename[1024]; // NOTE: it needs more than this to increase the number of players... #define MAXPLAYERS 16 -#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer -#define MAXSKINS 128 #define PLAYERSMASK (MAXPLAYERS-1) #define MAXPLAYERNAME 21 +#define MAXSPLITSCREENPLAYERS 4 // Max number of players on a single computer + +#define MAXSKINS 128 + +#define COLORRAMPSIZE 16 +#define MAXCOLORNAME 32 +#define NUMCOLORFREESLOTS 1024 // Master Server compatibility ONLY #define MSCOMPAT_MAXPLAYERS (32) +typedef struct skincolor_s +{ + char name[MAXCOLORNAME+1]; // Skincolor name + UINT8 ramp[COLORRAMPSIZE]; // Colormap ramp + UINT16 invcolor; // Signpost color + UINT8 invshade; // Signpost color shade + UINT16 chatcolor; // Chat color + boolean accessible; // Accessible by the color command + setup menu +} skincolor_t; + typedef enum { SKINCOLOR_NONE = 0, + SKINCOLOR_WHITE, SKINCOLOR_SILVER, SKINCOLOR_GREY, @@ -358,76 +329,74 @@ typedef enum SKINCOLOR_BLOSSOM, SKINCOLOR_TAFFY, - // "Careful! MAXSKINCOLORS cannot be greater than 0x40 -- Which it is now." - // (This comment is a dirty liar! This is only limited by the integer type, so 255 for UINT8.) - MAXSKINCOLORS, + FIRSTSUPERCOLOR, // Super special awesome Super flashing colors! - // Super Sonic Yellow - SKINCOLOR_SUPER1 = MAXSKINCOLORS, - SKINCOLOR_SUPER2, - SKINCOLOR_SUPER3, - SKINCOLOR_SUPER4, - SKINCOLOR_SUPER5, + SKINCOLOR_SUPERSILVER1 = FIRSTSUPERCOLOR, + SKINCOLOR_SUPERSILVER2, + SKINCOLOR_SUPERSILVER3, + SKINCOLOR_SUPERSILVER4, + SKINCOLOR_SUPERSILVER5, - // Super Tails Orange - SKINCOLOR_TSUPER1, - SKINCOLOR_TSUPER2, - SKINCOLOR_TSUPER3, - SKINCOLOR_TSUPER4, - SKINCOLOR_TSUPER5, + SKINCOLOR_SUPERRED1, + SKINCOLOR_SUPERRED2, + SKINCOLOR_SUPERRED3, + SKINCOLOR_SUPERRED4, + SKINCOLOR_SUPERRED5, - // Super Knuckles Red - SKINCOLOR_KSUPER1, - SKINCOLOR_KSUPER2, - SKINCOLOR_KSUPER3, - SKINCOLOR_KSUPER4, - SKINCOLOR_KSUPER5, + SKINCOLOR_SUPERORANGE1, + SKINCOLOR_SUPERORANGE2, + SKINCOLOR_SUPERORANGE3, + SKINCOLOR_SUPERORANGE4, + SKINCOLOR_SUPERORANGE5, - // Hyper Sonic Pink - SKINCOLOR_PSUPER1, - SKINCOLOR_PSUPER2, - SKINCOLOR_PSUPER3, - SKINCOLOR_PSUPER4, - SKINCOLOR_PSUPER5, + SKINCOLOR_SUPERGOLD1, + SKINCOLOR_SUPERGOLD2, + SKINCOLOR_SUPERGOLD3, + SKINCOLOR_SUPERGOLD4, + SKINCOLOR_SUPERGOLD5, - // Hyper Sonic Blue - SKINCOLOR_BSUPER1, - SKINCOLOR_BSUPER2, - SKINCOLOR_BSUPER3, - SKINCOLOR_BSUPER4, - SKINCOLOR_BSUPER5, + SKINCOLOR_SUPERPERIDOT1, + SKINCOLOR_SUPERPERIDOT2, + SKINCOLOR_SUPERPERIDOT3, + SKINCOLOR_SUPERPERIDOT4, + SKINCOLOR_SUPERPERIDOT5, - // Aqua Super - SKINCOLOR_ASUPER1, - SKINCOLOR_ASUPER2, - SKINCOLOR_ASUPER3, - SKINCOLOR_ASUPER4, - SKINCOLOR_ASUPER5, + SKINCOLOR_SUPERSKY1, + SKINCOLOR_SUPERSKY2, + SKINCOLOR_SUPERSKY3, + SKINCOLOR_SUPERSKY4, + SKINCOLOR_SUPERSKY5, - // Hyper Sonic Green - SKINCOLOR_GSUPER1, - SKINCOLOR_GSUPER2, - SKINCOLOR_GSUPER3, - SKINCOLOR_GSUPER4, - SKINCOLOR_GSUPER5, + SKINCOLOR_SUPERPURPLE1, + SKINCOLOR_SUPERPURPLE2, + SKINCOLOR_SUPERPURPLE3, + SKINCOLOR_SUPERPURPLE4, + SKINCOLOR_SUPERPURPLE5, - // Hyper Sonic White - SKINCOLOR_WSUPER1, - SKINCOLOR_WSUPER2, - SKINCOLOR_WSUPER3, - SKINCOLOR_WSUPER4, - SKINCOLOR_WSUPER5, + SKINCOLOR_SUPERRUST1, + SKINCOLOR_SUPERRUST2, + SKINCOLOR_SUPERRUST3, + SKINCOLOR_SUPERRUST4, + SKINCOLOR_SUPERRUST5, - // Creamy Super (Shadow?) - SKINCOLOR_CSUPER1, - SKINCOLOR_CSUPER2, - SKINCOLOR_CSUPER3, - SKINCOLOR_CSUPER4, - SKINCOLOR_CSUPER5, + SKINCOLOR_SUPERTAN1, + SKINCOLOR_SUPERTAN2, + SKINCOLOR_SUPERTAN3, + SKINCOLOR_SUPERTAN4, + SKINCOLOR_SUPERTAN5, - MAXTRANSLATIONS -} skincolors_t; + SKINCOLOR_FIRSTFREESLOT, + SKINCOLOR_LASTFREESLOT = SKINCOLOR_FIRSTFREESLOT + NUMCOLORFREESLOTS - 1, + + MAXSKINCOLORS, + + NUMSUPERCOLORS = ((SKINCOLOR_FIRSTFREESLOT - FIRSTSUPERCOLOR)/5) +} skincolornum_t; + +extern UINT16 numskincolors; + +extern skincolor_t skincolors[MAXSKINCOLORS]; // State updates, number of tics / second. // NOTE: used to setup the timer rate, see I_StartupTimer(). @@ -443,21 +412,27 @@ typedef enum // Special linedef executor tag numbers! enum { - LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) - LE_ALLBOSSESDEAD = -3, // All bosses in the map are dead (Egg capsule raise) - LE_BOSSDEAD = -4, // A boss in the map died (Chaos mode boss tally) - LE_BOSS4DROP = -5, // CEZ boss dropped its cage - LE_BRAKVILEATACK = -6 // Brak's doing his LOS attack, oh noes + LE_PINCHPHASE = -2, // A boss entered pinch phase (and, in most cases, is preparing their pinch phase attack!) + LE_ALLBOSSESDEAD = -3, // All bosses in the map are dead (Egg capsule raise) + LE_BOSSDEAD = -4, // A boss in the map died (Chaos mode boss tally) + LE_BOSS4DROP = -5, // CEZ boss dropped its cage (also subtract the number of hitpoints it's lost) + LE_BRAKVILEATACK = -6, // Brak's doing his LOS attack, oh noes + LE_TURRET = 32000, // THZ turret + LE_BRAKPLATFORM = 4200, // v2.0 Black Eggman destroys platform + LE_CAPSULE2 = 682, // Egg Capsule + LE_CAPSULE1 = 681, // Egg Capsule + LE_CAPSULE0 = 680, // Egg Capsule + LE_KOOPA = 650, // Distant cousin to Gay Bowser + LE_AXE = 649, // MKB Axe object + LE_PARAMWIDTH = -100 // If an object that calls LinedefExecute has a nonzero parameter value, this times the parameter will be subtracted. (Mostly for the purpose of coexisting bosses...) }; // Name of local directory for config files and savegames -#if !defined(_arch_dreamcast) && !defined(_WIN32_WCE) && !defined(GP2X) && !defined(_WII) && !defined(_PS3) #if (((defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON)) && !defined (__CYGWIN__)) && !defined (__APPLE__) #define DEFAULTDIR ".srb2kart" #else #define DEFAULTDIR "srb2kart" #endif -#endif #include "g_state.h" @@ -502,19 +477,23 @@ void CONS_Debug(INT32 debugflags, const char *fmt, ...) FUNCDEBUG; // Things that used to be in dstrings.h #define SAVEGAMENAME "srb2sav" extern char savegamename[256]; +extern char liveeventbackup[256]; // m_misc.h #ifdef GETTEXT #define M_GetText(String) gettext(String) -void M_StartupLocale(void); #else // If no translations are to be used, make a stub // M_GetText function that just returns the string. #define M_GetText(x) (x) #endif +void M_StartupLocale(void); extern void *(*M_Memcpy)(void* dest, const void* src, size_t n) FUNCNONNULL; char *va(const char *format, ...) FUNCPRINTF; char *M_GetToken(const char *inputString); +void M_UnGetToken(void); +UINT32 M_GetTokenPos(void); +void M_SetTokenPos(UINT32 newPos); char *sizeu1(size_t num); char *sizeu2(size_t num); char *sizeu3(size_t num); @@ -522,13 +501,15 @@ char *sizeu4(size_t num); char *sizeu5(size_t num); // d_main.c +extern int VERSION; +extern int SUBVERSION; extern boolean devparm; // development mode (-debug) // d_netcmd.c extern INT32 cv_debug; #define DBG_BASIC 0x0001 #define DBG_DETAILED 0x0002 -#define DBG_RANDOMIZER 0x0004 +#define DBG_PLAYER 0x0004 #define DBG_RENDER 0x0008 #define DBG_NIGHTSBASIC 0x0010 #define DBG_NIGHTS 0x0020 @@ -538,20 +519,25 @@ extern INT32 cv_debug; #define DBG_MEMORY 0x0200 #define DBG_SETUP 0x0400 #define DBG_LUA 0x0800 +#define DBG_RANDOMIZER 0x1000 +#define DBG_VIEWMORPH 0x2000 // ======================= // Misc stuff for later... // ======================= +#define ANG2RAD(angle) ((float)((angle)*M_PI)/ANGLE_180) + // Modifier key variables, accessible anywhere extern UINT8 shiftdown, ctrldown, altdown; extern boolean capslock; // WARNING: a should be unsigned but to add with 2048, it isn't! -#define AIMINGTODY(a) (FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160) +#define AIMINGTODY(a) FixedDiv((FINETANGENT((2048+(((INT32)a)>>ANGLETOFINESHIFT)) & FINEMASK)*160), fovtan[viewssnum]) // if we ever make our alloc stuff... #define ZZ_Alloc(x) Z_Malloc(x, PU_STATIC, NULL) +#define ZZ_Calloc(x) Z_Calloc(x, PU_STATIC, NULL) // i_system.c, replace getchar() once the keyboard has been appropriated INT32 I_GetKey(void); @@ -563,6 +549,9 @@ INT32 I_GetKey(void); #define max(x, y) (((x) > (y)) ? (x) : (y)) #endif +// Max gamepad/joysticks that can be detected/used. +#define MAX_JOYSTICKS 4 + #ifndef M_PIl #define M_PIl 3.1415926535897932384626433832795029L #endif @@ -584,13 +573,15 @@ INT32 I_GetKey(void); #endif // The character that separates pathnames. Forward slash on -// most systems, but reverse solidus (\) on Windows and DOS. -#if defined (PC_DOS) || defined (_WIN32) +// most systems, but reverse solidus (\) on Windows. +#if defined (_WIN32) #define PATHSEP "\\" #else #define PATHSEP "/" #endif +#define PUNCTUATION "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" + // Compile date and time and revision. extern const char *compdate, *comptime, *comprevision, *compbranch; @@ -598,19 +589,6 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; // None of these that are disabled in the normal build are guaranteed to work perfectly // Compile them at your own risk! -/// Kalaron/Eternity Engine slope code (SRB2CB ported) -#define ESLOPE - -#ifdef ESLOPE -/// Backwards compatibility with SRB2CB's slope linedef types. -/// \note A simple shim that prints a warning. -#define ESLOPE_TYPESHIM -#endif - -/// Delete file while the game is running. -/// \note EXTREMELY buggy, tends to crash game. -//#define DELFILE - /// Allows the use of devmode in multiplayer. AKA "fishcake" //#define NETGAME_DEVMODE @@ -620,11 +598,8 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Dumps the contents of a network save game upon consistency failure for debugging. //#define DUMPCONSISTENCY -/// Polyobject fake flat code -#define POLYOBJECTS_PLANES - /// See name of player in your crosshair -#define SEENAMES +//#define SEENAMES // Disabled for Kart /// Who put weights on my recycler? ... Inuyasha did. /// \note XMOD port. @@ -635,19 +610,15 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// Most modifications should probably enable this. //#define SAVEGAME_OTHERVERSIONS -#if !defined (_NDS) && !defined (_PSP) +/// Shuffle's incomplete OpenGL sorting code. +#define SHUFFLE // This has nothing to do with sorting, why was it disabled? + /// Allow the use of the SOC RESETINFO command. /// \note Builds that are tight on memory should disable this. /// This stops the game from storing backups of the states, sprites, and mobjinfo tables. /// Though this info is compressed under normal circumstances, it's still a lot of extra /// memory that never gets touched. #define ALLOW_RESETDATA -#endif - -#ifndef NONET -/// Display a connection screen on join attempts. -#define CLIENT_LOADINGSCREEN -#endif /// Experimental tweaks to analog mode. (Needs a lot of work before it's ready for primetime.) //#define REDSANALOG @@ -656,24 +627,59 @@ extern const char *compdate, *comptime, *comprevision, *compbranch; /// \note You should leave this enabled unless you're working with a future SRB2 version. #define MUSICSLOT_COMPATIBILITY -/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink. -/// \note Required for proper collision with moving sloped surfaces that have sector specials on them. -#define SECTORSPECIALSAFTERTHINK - -/// SRB2Kart: Camera always has noclip. -#define NOCLIPCAM - -/// SRB2Kart: MIDI support is shitty and busted and we don't want it, lets throw it behind a define -#define NO_MIDI +/// Experimental attempts at preventing MF_PAPERCOLLISION objects from getting stuck in walls. +//#define PAPER_COLLISIONCORRECTION /// FINALLY some real clipping that doesn't make walls dissappear AND speeds the game up /// (that was the original comment from SRB2CB, sadly it is a lie and actually slows game down) /// on the bright side it fixes some weird issues with translucent walls /// \note SRB2CB port. /// SRB2CB itself ported this from PrBoom+ -//#define NEWCLIP +#define NEWCLIP -/// Hardware renderer: OpenGL +/// OpenGL shaders #define GL_SHADERS + +/// Handle touching sector specials in P_PlayerAfterThink instead of P_PlayerThink. +/// \note Required for proper collision with moving sloped surfaces that have sector specials on them. +#define SECTORSPECIALSAFTERTHINK + +/// Cache patches in Lua in a way that renderer switching will work flawlessly. +//#define LUA_PATCH_SAFETY + +/// Sprite rotation +#define ROTSPRITE +#define ROTANGLES 72 // Needs to be a divisor of 360 (45, 60, 90, 120...) +#define ROTANGDIFF (360 / ROTANGLES) + +/// PNG support +#ifndef HAVE_PNG +#define NO_PNG_LUMPS +#endif + +/// Render flats on walls +#define WALLFLATS + +/// - SRB2Kart options - +/// Camera always has noclip. +#define NOCLIPCAM + +/// Divide volume of music and sounds by this much (loudest sounds on earth) +#define VOLUME_DIVIDER 4 +#define USER_VOLUME_SCALE 2 +#define MAX_VOLUME ( 100 * VOLUME_DIVIDER / USER_VOLUME_SCALE ) + +#if defined (HAVE_CURL) && ! defined (NONET) +#define MASTERSERVER +#else +#undef UPDATE_ALERT +#endif + +#if defined (HAVE_CURL) && ! defined (NONET) +#define MASTERSERVER +#else +#undef UPDATE_ALERT +#endif + #endif // __DOOMDEF__ diff --git a/src/doomstat.h b/src/doomstat.h index e678886a8..629e5cead 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -40,12 +40,29 @@ extern UINT32 mapmusresume; #define MUSIC_FORCERESET 0x4000 // -*-------------- // Use other bits if necessary. -extern INT16 maptol; +extern UINT32 maptol; extern UINT8 globalweather; extern UINT8 curWeather; extern INT32 cursaveslot; -extern INT16 lastmapsaved; -extern boolean gamecomplete; +//extern INT16 lastmapsaved; +extern INT16 lastmaploaded; +extern UINT8 gamecomplete; + +// Extra abilities/settings for skins (combinable stuff) +typedef enum +{ + MA_RUNNING = 1, // In action + MA_INIT = 1<<1, // Initialisation + MA_NOCUTSCENES = 1<<2, // No cutscenes + MA_INGAME = 1<<3 // Timer ignores loads +} marathonmode_t; + +extern marathonmode_t marathonmode; +extern tic_t marathontime; + +#define maxgameovers 13 +extern UINT8 numgameovers; +extern SINT8 startinglivesbalance[maxgameovers+1]; typedef enum { @@ -81,8 +98,8 @@ extern boolean savemoddata; // This mod saves time/emblem data. extern boolean imcontinuing; // Temporary flag while continuing extern boolean metalrecording; -#define ATTACKING_NONE 0 -#define ATTACKING_RECORD 1 +#define ATTACKING_NONE 0 +#define ATTACKING_TIME 1 #define ATTACKING_CAPSULES 2 extern UINT8 modeattacking; @@ -99,6 +116,9 @@ extern boolean multiplayer; extern INT16 gametype; +extern UINT32 gametyperules; +extern INT16 gametypecount; + extern UINT8 splitscreen; extern int r_splitscreen; @@ -110,11 +130,6 @@ extern boolean forceresetplayers, deferencoremode; // Internal parameters for sound rendering. // ======================================== -#ifdef NO_MIDI -#define midi_disabled true -#else -extern boolean midi_disabled; -#endif extern boolean sound_disabled; extern boolean digital_disabled; @@ -157,18 +172,25 @@ extern int splitscreen_party[MAXPLAYERS][MAXSPLITSCREENPLAYERS]; extern boolean splitscreen_partied[MAXPLAYERS]; // Maps of special importance -extern INT16 spstage_start; -extern INT16 sstage_start; -extern INT16 sstage_end; +extern INT16 spstage_start, spmarathon_start; +extern INT16 sstage_start, sstage_end, smpstage_start, smpstage_end; + +extern INT16 titlemap; +extern boolean hidetitlepics; +extern INT16 bootmap; //bootmap for loading a map on startup + +extern INT16 tutorialmap; // map to load for tutorial +extern boolean tutorialmode; // are we in a tutorial right now? +extern INT32 tutorialgcs; // which control scheme is loaded? extern boolean looptitle; -extern boolean useNightsSS; // CTF colors. -extern UINT8 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering; +extern UINT16 skincolor_redteam, skincolor_blueteam, skincolor_redring, skincolor_bluering; extern tic_t countdowntimer; extern boolean countdowntimeup; +extern boolean exitfadestarted; typedef struct { @@ -200,11 +222,65 @@ typedef struct extern cutscene_t *cutscenes[128]; +// Reserve prompt space for tutorials +#define TUTORIAL_PROMPT 201 // one-based +#define TUTORIAL_AREAS 6 +#define TUTORIAL_AREA_PROMPTS 5 +#define MAX_PROMPTS (TUTORIAL_PROMPT+TUTORIAL_AREAS*TUTORIAL_AREA_PROMPTS*3) // 3 control modes +#define MAX_PAGES 128 + +#define PROMPT_PIC_PERSIST 0 +#define PROMPT_PIC_LOOP 1 +#define PROMPT_PIC_DESTROY 2 +#define MAX_PROMPT_PICS 8 +typedef struct +{ + UINT8 numpics; + UINT8 picmode; // sequence mode after displaying last pic, 0 = persist, 1 = loop, 2 = destroy + UINT8 pictoloop; // if picmode == loop, which pic to loop to? + UINT8 pictostart; // initial pic number to show + char picname[MAX_PROMPT_PICS][8]; + UINT8 pichires[MAX_PROMPT_PICS]; + UINT16 xcoord[MAX_PROMPT_PICS]; // gfx + UINT16 ycoord[MAX_PROMPT_PICS]; // gfx + UINT16 picduration[MAX_PROMPT_PICS]; + + char musswitch[7]; + UINT16 musswitchflags; + UINT8 musicloop; + + char tag[33]; // page tag + char name[34]; // narrator name, extra char for color + char iconname[8]; // narrator icon lump + boolean rightside; // narrator side, false = left, true = right + boolean iconflip; // narrator flip icon horizontally + UINT8 hidehud; // hide hud, 0 = show all, 1 = hide depending on prompt position (top/bottom), 2 = hide all + UINT8 lines; // # of lines to show. If name is specified, name takes one of the lines. If 0, defaults to 4. + INT32 backcolor; // see CON_SetupBackColormap: 0-11, INT32_MAX for user-defined (CONS_BACKCOLOR) + UINT8 align; // text alignment, 0 = left, 1 = right, 2 = center + UINT8 verticalalign; // vertical text alignment, 0 = top, 1 = bottom, 2 = middle + UINT8 textspeed; // text speed, delay in tics between characters. + sfxenum_t textsfx; // sfx_ id for printing text + UINT8 nextprompt; // next prompt to jump to, one-based. 0 = current prompt + UINT8 nextpage; // next page to jump to, one-based. 0 = next page within prompt->numpages + char nexttag[33]; // next tag to jump to. If set, this overrides nextprompt and nextpage. + INT32 timetonext; // time in tics to jump to next page automatically. 0 = don't jump automatically + char *text; +} textpage_t; + +typedef struct +{ + textpage_t page[MAX_PAGES]; + INT32 numpages; // Number of pages in this prompt +} textprompt_t; + +extern textprompt_t *textprompts[MAX_PROMPTS]; + // For the Custom Exit linedef. extern INT16 nextmapoverride; -extern boolean skipstats; +extern UINT8 skipstats; -extern UINT32 totalrings; // Total # of rings in a level +extern UINT32 ssspheres; // Total # of spheres in a level // Fun extra stuff extern INT16 lastmap; // Last level you were at (returning from special stages). @@ -252,9 +328,11 @@ typedef struct char lvlttl[22]; ///< Level name without "Zone". (21 character limit instead of 32, 21 characters can display on screen max anyway) char subttl[33]; ///< Subtitle for level char zonttl[22]; ///< "ZONE" replacement name - char actnum[3]; ///< SRB2Kart: Now a 2 character long string. - UINT16 typeoflevel; ///< Combination of typeoflevel flags. + UINT8 actnum; ///< Act number or 0 for none. + UINT32 typeoflevel; ///< Combination of typeoflevel flags. INT16 nextlevel; ///< Map number of next level, or 1100-1102 to end. + INT16 marathonnext; ///< See nextlevel, but for Marathon mode. Necessary to support hub worlds ala SUGOI. + char keywords[33]; ///< Keywords separated by space to search for. 32 characters. char musname[7]; ///< Music track to play. "" for no music. UINT16 mustrack; ///< Subsong to play. Only really relevant for music modules and specific formats supported by GME. 0 to ignore. UINT32 muspos; ///< Music position to jump to. @@ -278,17 +356,31 @@ typedef struct SINT8 unlockrequired; ///< Is an unlockable required to play this level? -1 if no. UINT8 levelselect; ///< Is this map available in the level select? If so, which map list is it available in? SINT8 bonustype; ///< What type of bonus does this level have? (-1 for null.) - SINT8 saveoverride; ///< Set how the game is allowed to save (1 for always, -1 for never, 0 is 2.1 default) + SINT8 maxbonuslives; ///< How many bonus lives to award at Intermission? (-1 for unlimited.) - UINT8 levelflags; ///< LF_flags: merged eight booleans into one UINT8 for space, see below + UINT16 levelflags; ///< LF_flags: merged booleans into one UINT16 for space, see below UINT8 menuflags; ///< LF2_flags: options that affect record attack / nights mode menus + char selectheading[22]; ///< Level select heading. Allows for controllable grouping. + UINT16 startrings; ///< Number of rings players start with. + INT32 sstimer; ///< Timer for special stages. + UINT32 ssspheres; ///< Sphere requirement in special stages. + fixed_t gravity; ///< Map-wide gravity. + + // Title card. + char ltzzpatch[8]; ///< Zig zag patch. + char ltzztext[8]; ///< Zig zag text. + char ltactdiamond[8]; ///< Act diamond. + + // Freed animals stuff. + UINT8 numFlickies; ///< Internal. For freed flicky support. + mobjtype_t *flickies; ///< List of freeable flickies in this level. Allocated dynamically for space reasons. Be careful. + // NiGHTS stuff. UINT8 numGradedMares; ///< Internal. For grade support. nightsgrades_t *grades; ///< NiGHTS grades. Allocated dynamically for space reasons. Be careful. // SRB2kart - //boolean automap; ///< Displays a level's white map outline in modified games fixed_t mobj_scale; ///< Replacement for TOL_ERZ3 fixed_t default_waypoint_radius; ///< 0 is a special value for DEFAULT_WAYPOINT_RADIUS, but scaled with mobjscale @@ -296,6 +388,16 @@ typedef struct UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds char musintername[7]; ///< Intermission screen music. + char muspostbossname[7]; ///< Post-bossdeath music. + UINT16 muspostbosstrack; ///< Post-bossdeath track. + UINT32 muspostbosspos; ///< Post-bossdeath position + UINT32 muspostbossfadein; ///< Post-bossdeath fade-in milliseconds. + + SINT8 musforcereset; ///< Force resetmusic (-1 for default; 0 for force off; 1 for force on) + + // SRB2Kart: Keeps track of if a map lump exists, so we can tell when a map is being replaced. + boolean alreadyExists; + // Lua stuff. // (This is not ifdeffed so the map header structure can stay identical, just in case.) UINT8 numCustomOptions; ///< Internal. For Lua custom value support. @@ -303,25 +405,14 @@ typedef struct } mapheader_t; // level flags -#define LF_SCRIPTISFILE 1 ///< True if the script is a file, not a lump. -#define LF_SPEEDMUSIC 2 ///< Speed up act music for super sneakers -#define LF_NOSSMUSIC 4 ///< Disable Super Sonic music -#define LF_NORELOAD 8 ///< Don't reload level on death -#define LF_NOZONE 16 ///< Don't include "ZONE" on level title -#define LF_SECTIONRACE 32 ///< Section race level +#define LF_SCRIPTISFILE (1<<0) ///< True if the script is a file, not a lump. +#define LF_NOZONE (1<<1) ///< Don't include "ZONE" on level title +#define LF_SECTIONRACE (1<<2) ///< Section race level -#define LF2_HIDEINMENU 1 ///< Hide in the multiplayer menu -#define LF2_HIDEINSTATS 2 ///< Hide in the statistics screen -#define LF2_RECORDATTACK 4 ///< Show this map in Time Attack -#define LF2_NIGHTSATTACK 8 ///< Show this map in NiGHTS mode menu -#define LF2_NOVISITNEEDED 16 ///< Available in time attack/nights mode without visiting the level - -#define LF2_EXISTSHACK 128 ///< Map lump exists; as noted, a single-bit hack that can be freely movable to other variables without concern. - -// Save override -#define SAVE_NEVER -1 -#define SAVE_DEFAULT 0 -#define SAVE_ALWAYS 1 +#define LF2_HIDEINMENU (1<<0) ///< Hide in the multiplayer menu +#define LF2_HIDEINSTATS (1<<1) ///< Hide in the statistics screen +#define LF2_TIMEATTACK (1<<2) ///< Show this map in Time Attack modes +#define LF2_VISITNEEDED (1<<3) ///< Not available in Time Attack modes until you visit the level extern mapheader_t* mapheaderinfo[NUMMAPS]; @@ -346,51 +437,83 @@ typedef struct cupheader_s extern cupheader_t *kartcupheaders; // Start of cup linked list extern UINT16 numkartcupheaders; -enum TypeOfLevel -{ - TOL_SP = 0x01, ///< Single Player - TOL_COOP = 0x02, ///< Cooperative - TOL_COMPETITION = 0x04, ///< Competition - TOL_RACE = 0x08, ///< Race -// Single Player default = 15 - - TOL_MATCH = 0x10, ///< Match - TOL_TAG = 0x20, ///< Tag -// Match/Tag default = 48 - - TOL_CTF = 0x40, ///< Capture the Flag -// CTF default = 64 - - TOL_CUSTOM = 0x80, ///< Custom (Lua-scripted, etc.) - - TOL_2D = 0x0100, ///< 2D - TOL_MARIO = 0x0200, ///< Mario - TOL_NIGHTS = 0x0400, ///< NiGHTS - TOL_TV = 0x0800, ///< Midnight Channel specific: draw TV like overlay on HUD - TOL_XMAS = 0x1000 ///< Christmas NiGHTS - //TOL_KART = 0x4000 ///< Kart 32768 -}; - // Gametypes -enum GameType // SRB2Kart -{ - GT_RACE = 0, // also used in record attack - GT_MATCH, // battle, but renaming would be silly - NUMGAMETYPES, +#define NUMGAMETYPEFREESLOTS 128 - // TODO: This is *horrid*. Remove this hack ASAP. - // the following have been left in on account of just not wanting to deal with removing all the checks for them - GT_COOP, - GT_COMPETITION, - GT_TEAMMATCH, - GT_TAG, - GT_HIDEANDSEEK, - GT_CTF +enum GameType +{ + GT_RACE = 0, + GT_BATTLE, + + GT_FIRSTFREESLOT, + GT_LASTFREESLOT = GT_FIRSTFREESLOT + NUMGAMETYPEFREESLOTS - 1, + NUMGAMETYPES +}; +// If you alter this list, update dehacked.c, MISC_ChangeGameTypeMenu in m_menu.c, and Gametype_Names in g_game.c + +// Gametype rules +enum GameTypeRules +{ + // Race rules + GTR_CIRCUIT = 1, // Enables the finish line, laps, and the waypoint system. + GTR_RINGS = 1<<1, // Rings will be spawned in this mode. (Don't get too cheeky, ring sting is still enabled :]) + GTR_BOTS = 1<<2, // Allows bots in this gametype. Combine with BotTiccmd hooks to make bots support your gametype. + + // Battle gametype rules + GTR_BUMPERS = 1<<3, // Enables the bumper health system + GTR_WANTED = 1<<4, // Enables the wanted anti-camping system + GTR_KARMA = 1<<5, // Enables the Karma system if you're out of bumpers + GTR_ITEMARROWS = 1<<6, // Show item box arrows above players + GTR_CAPSULES = 1<<7, // Enables the wanted anti-camping system + GTR_BATTLESTARTS = 1<<8, // Use Battle Mode start positions. + + GTR_POINTLIMIT = 1<<9, // Reaching point limit ends the round + GTR_TIMELIMIT = 1<<10, // Reaching time limit ends the round + GTR_OVERTIME = 1<<11, // Allow overtime behavior + + // Custom gametype rules + GTR_TEAMS = 1<<12, // Teams are forced on + GTR_NOTEAMS = 1<<13, // Teams are forced off + GTR_TEAMSTARTS = 1<<14, // Use team-based start positions + + // Grand Prix rules + GTR_CAMPAIGN = 1<<15, // Handles cup-based progression + GTR_LIVES = 1<<16, // Lives system, players are forced to spectate during Game Over. + GTR_SPECIALBOTS = 1<<17, // Bot difficulty gets stronger between rounds, and the rival system is enabled. + + // free: to and including 1<<31 }; -// If you alter this list, update dehacked.c, and Gametype_Names in g_game.c // String names for gametypes extern const char *Gametype_Names[NUMGAMETYPES]; +extern const char *Gametype_ConstantNames[NUMGAMETYPES]; + +// Point and time limits for every gametype +extern INT32 pointlimits[NUMGAMETYPES]; +extern INT32 timelimits[NUMGAMETYPES]; + +// TypeOfLevel things +enum TypeOfLevel +{ + // Gametypes + TOL_RACE = 0x0001, ///< Race + TOL_BATTLE = 0x0002, ///< Battle + + // Modifiers + TOL_TV = 0x0100, ///< Midnight Channel specific: draw TV like overlay on HUD +}; + +#define MAXTOL (1<<31) +#define NUMBASETOLNAMES (3) +#define NUMTOLNAMES (NUMBASETOLNAMES + NUMGAMETYPEFREESLOTS) + +typedef struct +{ + const char *name; + UINT32 flag; +} tolinfo_t; +extern tolinfo_t TYPEOFLEVEL[NUMTOLNAMES]; +extern UINT32 lastcustomtol; extern tic_t totalplaytime; extern UINT32 matchesplayed; @@ -408,7 +531,10 @@ extern UINT16 emeralds; #define EMERALD7 64 #define ALL7EMERALDS(v) ((v & (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) == (EMERALD1|EMERALD2|EMERALD3|EMERALD4|EMERALD5|EMERALD6|EMERALD7)) -extern INT32 nummaprings; // keep track of spawned rings/coins +#define NUM_LUABANKS 16 // please only make this number go up between versions, never down. you'll break saves otherwise. also, must fit in UINT8 +extern INT32 luabanks[NUM_LUABANKS]; + +extern INT32 nummaprings; //keep track of spawned rings/coins /** Time attack information, currently a very small structure. */ @@ -444,19 +570,16 @@ typedef struct extern recorddata_t *mainrecords[NUMMAPS]; // mapvisited is now a set of flags that says what we've done in the map. -#define MV_VISITED 1 -#define MV_BEATEN 2 -#define MV_ALLEMERALDS 4 -//#define MV_ULTIMATE 8 -//#define MV_PERFECT 16 -#define MV_MAX 7 // used in gamedata check +#define MV_VISITED (1) +#define MV_BEATEN (1<<1) +#define MV_ENCORE (1<<2) +#define MV_MAX (MV_VISITED|MV_BEATEN|MV_ENCORE) +#define MV_MP ((MV_MAX+1)<<1) extern UINT8 mapvisited[NUMMAPS]; -// Temporary holding place for nights data for the current map -//nightsdata_t ntemprecords; - extern UINT32 token; ///< Number of tokens collected in a level extern UINT32 tokenlist; ///< List of tokens collected +extern boolean gottoken; ///< Did you get a token? Used for end of act extern INT32 tokenbits; ///< Used for setting token bits extern INT32 sstimer; ///< Time allotted in the special stage extern UINT32 bluescore; ///< Blue Team Scores @@ -478,6 +601,7 @@ extern UINT16 tailsflytics; extern UINT16 underwatertics; extern UINT16 spacetimetics; extern UINT16 extralifetics; +extern UINT16 nightslinktics; // SRB2kart extern tic_t introtime; @@ -504,15 +628,19 @@ extern INT32 flameseg; extern UINT8 introtoplay; extern UINT8 creditscutscene; +extern UINT8 useBlackRock; extern UINT8 use1upSound; extern UINT8 maxXtraLife; // Max extra lives from rings +extern UINT8 useContinues; +#define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0)))) extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations // For racing extern tic_t racecountdown, exitcountdown; +#define DEFAULT_GRAVITY (4*FRACUNIT/5) extern fixed_t gravity; extern fixed_t mapobjectscale; @@ -550,11 +678,7 @@ extern INT16 votelevels[5][2]; extern SINT8 votes[MAXPLAYERS]; extern SINT8 pickedvote; -extern tic_t hidetime; - extern UINT32 timesBeaten; // # of times the game has been beaten. -extern UINT32 timesBeatenWithEmeralds; -//extern UINT32 timesBeatenUltimate; // =========================== // Internal parameters, fixed. @@ -571,6 +695,19 @@ extern mapthing_t *playerstarts[MAXPLAYERS]; // Cooperative extern mapthing_t *bluectfstarts[MAXPLAYERS]; // CTF extern mapthing_t *redctfstarts[MAXPLAYERS]; // CTF +#define TUBEWAYPOINTSEQUENCESIZE 256 +#define NUMTUBEWAYPOINTSEQUENCES 256 +extern mobj_t *tubewaypoints[NUMTUBEWAYPOINTSEQUENCES][TUBEWAYPOINTSEQUENCESIZE]; +extern UINT16 numtubewaypoints[NUMTUBEWAYPOINTSEQUENCES]; + +void P_AddTubeWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint); +mobj_t *P_GetFirstTubeWaypoint(UINT8 sequence); +mobj_t *P_GetLastTubeWaypoint(UINT8 sequence); +mobj_t *P_GetPreviousTubeWaypoint(mobj_t *current, boolean wrap); +mobj_t *P_GetNextTubeWaypoint(mobj_t *current, boolean wrap); +mobj_t *P_GetClosestTubeWaypoint(UINT8 sequence, mobj_t *mo); +boolean P_IsDegeneratedTubeWaypointSequence(UINT8 sequence); + // ===================================== // Internal parameters, used for engine. // ===================================== @@ -597,6 +734,8 @@ extern boolean precache; // wipegamestate can be set to -1 // to force a wipe on the next draw extern gamestate_t wipegamestate; +extern INT16 wipetypepre; +extern INT16 wipetypepost; // debug flag to cancel adaptiveness extern boolean singletics; @@ -607,7 +746,7 @@ extern boolean singletics; #include "d_clisrv.h" -extern consvar_t cv_timetic; // display high resolution timer +extern consvar_t cv_showinputjoy; // display joystick in time attack extern consvar_t cv_forceskin; // force clients to use the server's skin extern consvar_t cv_downloading; // allow clients to downloading WADs. extern consvar_t cv_nettimeout; // SRB2Kart: Advanced server options menu diff --git a/src/doomtype.h b/src/doomtype.h index 67491abb3..1e938f10a 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -17,18 +17,20 @@ #ifndef __DOOMTYPE__ #define __DOOMTYPE__ -#if (defined (_WIN32) && !defined (_XBOX)) || (defined (_WIN32_WCE) && !defined (__GNUC__)) +#ifdef _WIN32 //#define WIN32_LEAN_AND_MEAN #define RPC_NO_WINDOWS_H #include #endif -#ifdef _NDS -#include -#endif - /* 7.18.1.1 Exact-width integer types */ #ifdef _MSC_VER +// libopenmpt.h will include stdint.h later; +// include it now so that INT8_MAX etc. don't get redefined +#ifdef HAVE_OPENMPT +#include +#endif + #define UINT8 unsigned __int8 #define SINT8 signed __int8 @@ -52,19 +54,6 @@ typedef long ssize_t; #define PDWORD_PTR PDWORD #endif #endif -#elif defined (_arch_dreamcast) // KOS Dreamcast -#include - -#define UINT8 unsigned char -#define SINT8 signed char - -#define UINT16 uint16 -#define INT16 int16 - -#define INT32 int -#define UINT32 unsigned int -#define INT64 int64 -#define UINT64 uint64 #elif defined (__DJGPP__) #define UINT8 unsigned char #define SINT8 signed char @@ -100,15 +89,13 @@ typedef long ssize_t; /* Strings and some misc platform specific stuff */ -#if defined (_MSC_VER) || defined (__OS2__) - // Microsoft VisualC++ #ifdef _MSC_VER + // Microsoft VisualC++ #if (_MSC_VER <= 1800) // MSVC 2013 and back #define snprintf _snprintf #if (_MSC_VER <= 1200) // MSVC 6.0 and back #define vsnprintf _vsnprintf #endif -#endif #endif #define strncasecmp strnicmp #define strcasecmp stricmp @@ -121,23 +108,15 @@ typedef long ssize_t; #define strncasecmp strnicmp #define strcasecmp strcmpi #endif -#ifdef _PSP - #include -#elif (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) +#if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) #undef stricmp #define stricmp(x,y) strcasecmp(x,y) #undef strnicmp #define strnicmp(x,y,n) strncasecmp(x,y,n) #endif -#ifdef _WIN32_WCE -#ifndef __GNUC__ - #define stricmp(x,y) _stricmp(x,y) - #define strnicmp _strnicmp -#endif - #define strdup _strdup - #define strupr _strupr - #define strlwr _strlwr -#endif + +char *strcasestr(const char *in, const char *what); +#define stristr strcasestr #if defined (macintosh) //|| defined (__APPLE__) //skip all boolean/Boolean crap #define true 1 @@ -157,7 +136,7 @@ typedef long ssize_t; #endif #endif //macintosh -#if defined (PC_DOS) || defined (_WIN32) || defined (_WII) || defined (_PSP) || defined (_arch_dreamcast) || defined (__HAIKU__) || defined(_NDS) || defined(_PS3) +#if defined (PC_DOS) || defined (_WIN32) || defined (__HAIKU__) #define HAVE_DOSSTR_FUNCS #endif @@ -191,21 +170,17 @@ size_t strlcpy(char *dst, const char *src, size_t siz); //faB: clean that up !! #if defined( _MSC_VER) && (_MSC_VER >= 1800) // MSVC 2013 and forward #include "stdbool.h" - #elif (defined (_WIN32) || (defined (_WIN32_WCE) && !defined (__GNUC__))) && !defined (_XBOX) + #elif defined (_WIN32) #define false FALSE // use windows types #define true TRUE #define boolean BOOL - #elif defined(_NDS) - #define boolean bool - #elif defined(_PS3) // defined(__GNUC__)? - #include //_bool_true_false_are_defined? - #define boolean bool #else typedef enum {false, true} boolean; #endif #endif // __BYTEBOOL__ /* 7.18.2.1 Limits of exact-width integer types */ + #ifndef INT8_MIN #define INT8_MIN (-128) #endif @@ -298,12 +273,6 @@ size_t strlcpy(char *dst, const char *src, size_t siz); #endif #define ATTRUNUSED __attribute__((unused)) - - // Xbox-only macros - #ifdef _XBOX - #define FILESTAMP I_OutputMsg("%s:%d\n",__FILE__,__LINE__); - #define XBOXSTATIC static - #endif #elif defined (_MSC_VER) #define ATTRNORETURN __declspec(noreturn) #define ATTRINLINE __forceinline @@ -357,12 +326,6 @@ size_t strlcpy(char *dst, const char *src, size_t siz); #ifndef ATTRNOINLINE #define ATTRNOINLINE #endif -#ifndef XBOXSTATIC -#define XBOXSTATIC -#endif -#ifndef FILESTAMP -#define FILESTAMP -#endif /* Miscellaneous types that don't fit anywhere else (Can this be changed?) */ @@ -405,4 +368,16 @@ typedef UINT32 tic_t; #define UINT2RGBA(a) (UINT32)((a&0xff)<<24)|((a&0xff00)<<8)|((a&0xff0000)>>8)|(((UINT32)a&0xff000000)>>24) #endif +/* preprocessor dumb and needs second macro to expand input */ +#define WSTRING2(s) L ## s +#define WSTRING(s) WSTRING2 (s) + +/* +A hack by Monster Iestyn: Return a pointer to a field of +a struct from a pointer to another field in the struct. +Needed for some lua shenanigans. +*/ +#define FIELDFROM( type, field, have, want ) \ + (void *)((intptr_t)(field) - offsetof (type, have) + offsetof (type, want)) + #endif //__DOOMTYPE__ diff --git a/src/dummy/i_cdmus.c b/src/dummy/i_cdmus.c index fc35eb9cf..94b8fa30e 100644 --- a/src/dummy/i_cdmus.c +++ b/src/dummy/i_cdmus.c @@ -8,8 +8,8 @@ UINT8 cdaudio_started = 0; -consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cd_volume = CVAR_INIT ("cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL); +consvar_t cdUpdate = CVAR_INIT ("cd_update","1",CV_SAVE, NULL, NULL); void I_InitCD(void){} diff --git a/src/dummy/i_system.c b/src/dummy/i_system.c index a3fe3077c..4a657ed19 100644 --- a/src/dummy/i_system.c +++ b/src/dummy/i_system.c @@ -16,6 +16,11 @@ tic_t I_GetTime(void) return 0; } +int I_GetTimeMicros(void) +{ + return 0; +} + void I_Sleep(void){} void I_GetEvent(void){} @@ -150,6 +155,8 @@ void I_GetJoystick2Events(void){} void I_GetMouseEvents(void){} +void I_UpdateMouseGrab(void){} + char *I_GetEnv(const char *name) { (void)name; diff --git a/src/dummy/i_video.c b/src/dummy/i_video.c index 93ba6b751..2b0478220 100644 --- a/src/dummy/i_video.c +++ b/src/dummy/i_video.c @@ -8,12 +8,13 @@ boolean highcolor = false; boolean allow_fullscreen = false; -consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL); void I_StartupGraphics(void){} - void I_ShutdownGraphics(void){} +void VID_StartupOpenGL(void){} + void I_SetPalette(RGBA_t *palette) { (void)palette; @@ -39,6 +40,9 @@ INT32 VID_SetMode(INT32 modenum) return 0; } +void VID_CheckRenderer(void) {} +void VID_CheckGLLoaded(rendermode_t oldrender) {} + const char *VID_GetModeName(INT32 modenum) { (void)modenum; diff --git a/src/endian.h b/src/endian.h index d3c1cb18b..24d8e35cd 100644 --- a/src/endian.h +++ b/src/endian.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2014-2018 by Sonic Team Junior. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/f_finale.c b/src/f_finale.c index 7a8cf0681..4355cf231 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -14,6 +14,7 @@ #include "doomdef.h" #include "doomstat.h" #include "d_main.h" +#include "d_netcmd.h" #include "f_finale.h" #include "g_game.h" #include "hu_stuff.h" @@ -30,41 +31,113 @@ #include "g_input.h" #include "console.h" #include "m_random.h" +#include "m_misc.h" // moviemode functionality #include "y_inter.h" #include "m_cond.h" +#include "p_local.h" +#include "p_setup.h" +#include "st_stuff.h" // hud hiding +#include "fastcmp.h" + +#include "lua_hud.h" // Stage of animation: // 0 = text, 1 = art screen -static INT32 finalecount; -INT32 titlescrollspeed = 5; +INT32 finalecount; +INT32 titlescrollxspeed = 5; +INT32 titlescrollyspeed = 0; +UINT8 titlemapinaction = TITLEMAP_OFF; static INT32 timetonext; // Delay between screen changes -static INT32 continuetime; // Short delay when continuing static tic_t animtimer; // Used for some animation timings static tic_t credbgtimer; // Credits background -static INT32 roidtics; // Asteroid spinning +static INT16 skullAnimCounter; // Prompts: Chevron animation static tic_t stoptimer; static boolean keypressed = false; -// (no longer) De-Demo'd Title Screen +static tic_t xscrolltimer; +static tic_t yscrolltimer; +static INT32 menuanimtimer; // Title screen: background animation timing +mobj_t *titlemapcameraref = NULL; + +// menu presentation state +char curbgname[9]; +SINT8 curfadevalue; +INT32 curbgcolor; +INT32 curbgxspeed; +INT32 curbgyspeed; +boolean curbghide; +boolean hidetitlemap; // WARNING: set to false by M_SetupNextMenu and M_ClearMenus + #if 0 static UINT8 laststaff = 0; #endif +//static UINT8 curDemo = 0; static UINT32 demoDelayLeft; static UINT32 demoIdleLeft; +// customizable title screen graphics + +ttmode_enum ttmode = TTMODE_OLD; +UINT8 ttscale = 1; // FRACUNIT / ttscale +// ttmode user vars +char ttname[9]; +INT16 ttx = 0; +INT16 tty = 0; +INT16 ttloop = -1; +UINT16 tttics = 1; + +boolean curhidepics; +ttmode_enum curttmode; +UINT8 curttscale; +// ttmode user vars +char curttname[9]; +INT16 curttx; +INT16 curtty; +INT16 curttloop; +UINT16 curtttics; + +// ttmode old +/* static patch_t *ttbanner; // SONIC ROBO BLAST 2 static patch_t *ttkart; // *vroom* KART static patch_t *ttcheckers; // *vroom* KART static patch_t *ttkflash; // flash screen +*/ static patch_t *driver[2]; // Driving character on the waiting screen static UINT8 *waitcolormap; // colormap for the spinning character -static void F_SkyScroll(INT32 scrollspeed); +// ttmode user +static patch_t *ttuser[TTMAX_USER]; +static INT32 ttuser_count = 0; + +static boolean goodending; +static patch_t *endbrdr[2]; // border - blue, white, pink - where have i seen those colours before? +static patch_t *endbgsp[3]; // nebula, sun, planet +static patch_t *endegrk[2]; // eggrock - replaced midway through good ending +static patch_t *endfwrk[3]; // firework - replaced with skin when good ending +static patch_t *endspkl[3]; // sparkle +static patch_t *endglow[2]; // glow aura - replaced with black rock's midway through good ending +static patch_t *endxpld[4]; // mini explosion +static patch_t *endescp[5]; // escape pod + flame +static INT32 sparkloffs[3][2]; // eggrock explosions/blackrock sparkles +static INT32 sparklloop; + +// +// PROMPT STATE +// +boolean promptactive = false; +static mobj_t *promptmo; +static INT16 promptpostexectag; +static boolean promptblockcontrols; +static char *promptpagetext = NULL; +static INT32 callpromptnum = INT32_MAX; +static INT32 callpagenum = INT32_MAX; +static INT32 callplayer = INT32_MAX; // // CUTSCENE TEXT WRITING @@ -78,6 +151,9 @@ static INT32 cutscene_textspeed = 0; static UINT8 cutscene_boostspeed = 0; static tic_t cutscene_lasttextwrite = 0; +// STJR Intro +char stjrintro[9] = "STJRI000"; + // // This alters the text string cutscene_disptext. // Use the typical string drawing functions to display it. @@ -155,9 +231,10 @@ static void F_NewCutscene(const char *basetext) } // -// F_SkyScroll +// F_TitleBGScroll // -static void F_SkyScroll(INT32 scrollspeed) +/* +static void F_TitleBGScroll(INT32 scrollspeed) { INT32 x, y, w; patch_t *pat, *pat2; @@ -196,6 +273,7 @@ static void F_SkyScroll(INT32 scrollspeed) W_UnlockCachedPatch(pat); W_UnlockCachedPatch(pat2); } +*/ // ============= // INTRO SCENE @@ -224,6 +302,9 @@ void F_StartIntro(void) F_RunWipe(wipedefs[wipe_intro_toblack], false, "FADEMAP0", false, false); } + S_StopMusic(); + S_StopSounds(); + if (introtoplay) { if (!cutscenes[introtoplay - 1]) @@ -242,8 +323,7 @@ void F_StartIntro(void) F_NewCutscene(introtext[0]); intro_scenenum = 0; - finalecount = animtimer = stoptimer = 0; - roidtics = BASEVIDWIDTH - 64; + finalecount = animtimer = skullAnimCounter = stoptimer = 0; timetonext = introscenetime[intro_scenenum]; S_StopMusic(); } @@ -253,7 +333,7 @@ void F_StartIntro(void) // static void F_IntroDrawScene(void) { - boolean highres = false; + boolean highres = true; INT32 cx = 8, cy = 128; patch_t *background = NULL; INT32 bgxoffs = 0; @@ -305,17 +385,22 @@ void F_IntroDrawer(void) if (rendermode != render_none) { F_WipeStartScreen(); - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + F_WipeColorFill(31); F_WipeEndScreen(); F_RunWipe(99, true, "FADEMAP0", false, false); } // Stay on black for a bit. =) { - tic_t quittime; - quittime = I_GetTime() + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds - while (quittime > I_GetTime()) + tic_t nowtime, quittime, lasttime; + nowtime = lasttime = I_GetTime(); + quittime = nowtime + NEWTICRATE*2; // Shortened the quit time, used to be 2 seconds + while (quittime > nowtime) { + while (!((nowtime = I_GetTime()) - lasttime)) + I_Sleep(); + lasttime = nowtime; + I_OsPolling(); I_UpdateNoBlit(); #ifdef HAVE_THREADS @@ -326,6 +411,9 @@ void F_IntroDrawer(void) I_unlock_mutex(m_menu_mutex); #endif I_FinishUpdate(); // Update the screen with the image Tails 06-19-2001 + + if (moviemode) // make sure we save frames for the white hold too + M_SaveFrame(); } } @@ -359,9 +447,6 @@ void F_IntroTicker(void) // advance animation finalecount++; - if (finalecount % 3 == 0) - roidtics--; - timetonext--; F_WriteText(); @@ -535,9 +620,7 @@ static const char *credits[] = { "SEGA", "Sonic Team", "SRB2 & Sonic Team Jr. (www.srb2.org)", - "\"blazethecat\"", "\"Chaos Zero 64\"", - "\"Rob\"", "", "\1Produced By", "Kart Krew", @@ -546,11 +629,14 @@ static const char *credits[] = { "\"Tyler52\"", "", "", - "\1Thank you", - "\1for playing!", + "\1Thank you ", + "\1for playing! ", NULL }; +#define CREDITS_LEFT 8 +#define CREDITS_RIGHT ((BASEVIDWIDTH) - 8) + static struct { UINT32 x, y; const char *patch; @@ -575,10 +661,15 @@ static struct { // This Tyler52 gag is troublesome // Alignment should be ((spaces+1 * 100) + (headers+1 * 38) + (lines * 15)) // Current max image spacing: (200*17) - {112, (15*100)+(17*38)+(88*15), "TYLER52", SKINCOLOR_NONE}, - {0, 0, NULL, SKINCOLOR_NONE} + {112, (15*100)+(17*38)+(88*15), "TYLER52", SKINCOLOR_NONE} }; +#undef CREDITS_LEFT +#undef CREDITS_RIGHT + +static UINT32 credits_height = 0; +static const UINT8 credits_numpics = sizeof(credits_pics)/sizeof(credits_pics[0]) - 1; + void F_StartCredits(void) { G_SetGamestate(GS_CREDITS); @@ -586,10 +677,6 @@ void F_StartCredits(void) // Just in case they're open ... somehow M_ClearMenus(true); - // Save the second we enter the credits - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot >= 0) - G_SaveGame((UINT32)cursaveslot); - if (creditscutscene) { F_StartCustomCutscene(creditscutscene - 1, false, false); @@ -600,8 +687,9 @@ void F_StartCredits(void) paused = false; CON_ToggleOff(); S_StopMusic(); + S_StopSounds(); - S_ChangeMusicInternal("credit", false); + S_ChangeMusicInternal("_creds", false); S_ShowMusicCredit(); finalecount = 0; @@ -612,7 +700,7 @@ void F_StartCredits(void) void F_CreditDrawer(void) { UINT16 i; - fixed_t y = (80<>1); //V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); @@ -623,7 +711,7 @@ void F_CreditDrawer(void) V_DrawSciencePatch(320<>1; @@ -637,9 +725,6 @@ void F_CreditDrawer(void) V_DrawFixedPatch(credits_pics[i].x<>1))<>FRACBITS > -10) + V_DrawStringAtFixed((BASEVIDWIDTH-V_StringWidth(&credits[i][1], V_ALLOWLOWERCASE|V_YELLOWMAP))<>1, y, V_ALLOWLOWERCASE|V_YELLOWMAP, &credits[i][1]); + y += 12<>FRACBITS > -10) V_DrawStringAtFixed(32<>1); + + // Calculate credits height to display art properly + if (credits_height == 0) + { + for (i = 0; credits[i]; i++) + { + switch(credits[i][0]) + { + case 0: credits_height += 80; break; + case 1: credits_height += 30; break; + default: credits_height += 12; break; + } + } + credits_height = 131*credits_height/80; // account for scroll speeds. This is a guess now, so you may need to update this if you change the credits length. + } // Draw credits text on top for (i = 0; credits[i]; i++) @@ -748,7 +853,7 @@ boolean F_CreditResponder(event_t *event) return false; } - /*if (!(timesBeaten) && !(netgame || multiplayer)) + /*if (!(timesBeaten) && !(netgame || multiplayer) && !cv_debug) return false;*/ if (key != KEY_ESCAPE && key != KEY_ENTER && key != KEY_BACKSPACE) @@ -764,101 +869,151 @@ boolean F_CreditResponder(event_t *event) // ============ // EVALUATION // ============ -#define INTERVAL 50 -#define TRANSLEVEL V_80TRANS -static INT32 eemeralds_start; -static boolean drawemblem = false, drawchaosemblem = false; + +#define SPARKLLOOPTIME 7 // must be odd void F_StartGameEvaluation(void) { - // Credits option in secrets menu - if (cursaveslot == -2) + // Credits option in extras menu + if (cursaveslot == -1) { + S_FadeOutStopMusic(2*MUSICRATE); F_StartGameEnd(); return; } + S_FadeOutStopMusic(5*MUSICRATE); + G_SetGamestate(GS_EVALUATION); // Just in case they're open ... somehow M_ClearMenus(true); - // Save the second we enter the evaluation - // We need to do this again! Remember, it's possible a mod designed skipped - // the credits sequence! - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer) && cursaveslot >= 0) - G_SaveGame((UINT32)cursaveslot); + goodending = (ALL7EMERALDS(emeralds)); gameaction = ga_nothing; paused = false; CON_ToggleOff(); - finalecount = 0; + finalecount = -1; + sparklloop = 0; } void F_GameEvaluationDrawer(void) { INT32 x, y, i; - const fixed_t radius = 48*FRACUNIT; angle_t fa; INT32 eemeralds_cur; char patchname[7] = "CEMGx0"; + const char* endingtext; + + if (marathonmode) + endingtext = "THANKS FOR THE RUN!"; + else if (goodending) + endingtext = "CONGRATULATIONS!"; + else + endingtext = "TRY AGAIN..."; V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); // Draw all the good crap here. - if (ALL7EMERALDS(emeralds)) - V_DrawString(114, 16, 0, "GOT THEM ALL!"); - else - V_DrawString(124, 16, 0, "TRY AGAIN!"); - eemeralds_start++; - eemeralds_cur = eemeralds_start; - - for (i = 0; i < 7; ++i) + if (finalecount > 0 && useBlackRock) { - fa = (FixedAngle(eemeralds_cur*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - x = 160 + FixedInt(FixedMul(FINECOSINE(fa),radius)); - y = 100 + FixedInt(FixedMul(FINESINE(fa),radius)); + INT32 scale = FRACUNIT; + patch_t *rockpat; + UINT8 *colormap[2] = {NULL, NULL}; + patch_t *glow; + INT32 trans = 0; - patchname[4] = 'A'+(char)i; - if (emeralds & (1<= 360) - eemeralds_start -= 360; - - if (finalecount == 5*TICRATE) - { - if ((!modifiedgame || savemoddata) && !(netgame || multiplayer)) + if (finalecount < 5) { - ++timesBeaten; + scale = (finalecount<<(FRACBITS-2)); + x += (30*(FRACUNIT-scale)); + y += (30*(FRACUNIT-scale)); + } - if (ALL7EMERALDS(emeralds)) - ++timesBeatenWithEmeralds; + if (goodending) + { + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - (finalecount % 35)), PU_PATCH); + glow = W_CachePatchName(va("ENDGLOW%.1d", 2+(finalecount & 1)), PU_PATCH); + x -= FRACUNIT; + } + else + { + rockpat = W_CachePatchName("ROID0000", PU_LEVEL); + glow = W_CachePatchName(va("ENDGLOW%.1d", (finalecount & 1)), PU_PATCH); + } - /*if (ultimatemode) - ++timesBeatenUltimate;*/ + if (finalecount >= 5) + trans = (finalecount-5)>>1; + if (trans < 10) + V_DrawFixedPatch(x, y, scale, trans< (finalecount/SPARKLLOOPTIME)) + j = (finalecount/SPARKLLOOPTIME); + while (j) + { + if (j > 1 || sparklloop >= 2) + { + // if j == 0 - alternate between 0 and 1 + // 1 - 1 and 2 + // 2 - 2 and not rendered + V_DrawFixedPatch(x+sparkloffs[j-1][0], y+sparkloffs[j-1][1], FRACUNIT, 0, + W_CachePatchName(va("ENDSPKL%.1d", (j - ((sparklloop & 1) ? 0 : 1))), PU_PATCH), + R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_AQUAMARINE, GTC_CACHE)); + } + j--; + } + } + else + { + patch_t *eggrock = W_CachePatchName("ENDEGRK5", PU_PATCH); + V_DrawFixedPatch(x, y, scale, 0, eggrock, colormap[0]); + if (trans < 10) + V_DrawFixedPatch(x, y, scale, trans<>ANGLETOFINESHIFT) & FINEMASK; + x = (BASEVIDWIDTH<<(FRACBITS-1)) + (60*FINECOSINE(fa)); + y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + (60*FINESINE(fa)); + eemeralds_cur += (360<= 5*TICRATE) { - if (drawemblem) - V_DrawScaledPatch(120, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE)); - - if (drawchaosemblem) - V_DrawScaledPatch(200, 192, 0, W_CachePatchName("NWNGA0", PU_CACHE)); - V_DrawString(8, 16, V_YELLOWMAP, "Unlocked:"); if (!(netgame) && (!modifiedgame || savemoddata)) @@ -877,20 +1032,610 @@ void F_GameEvaluationDrawer(void) } } else if (netgame) - V_DrawString(8, 96, V_YELLOWMAP, "Prizes only\nawarded in\nsingle player!"); + V_DrawString(8, 96, V_YELLOWMAP, "Multiplayer games\ncan't unlock\nextras!"); else - V_DrawString(8, 96, V_YELLOWMAP, "Prizes not\nawarded in\nmodified games!"); + V_DrawString(8, 96, V_YELLOWMAP, "Modified games\ncan't unlock\nextras!"); + } +#endif + + if (marathonmode) + { + const char *rtatext, *cuttext; + rtatext = (marathonmode & MA_INGAME) ? "In-game timer" : "RTA timer"; + cuttext = (marathonmode & MA_NOCUTSCENES) ? "" : " w/ cutscenes"; + endingtext = va("%s, %s%s", skins[players[consoleplayer].skin].realname, rtatext, cuttext); + V_DrawCenteredString(BASEVIDWIDTH/2, 182, V_SNAPTOBOTTOM|(ultimatemode ? V_REDMAP : V_YELLOWMAP), endingtext); } } void F_GameEvaluationTicker(void) { - finalecount++; - - if (finalecount > 10*TICRATE) + if (++finalecount > 10*TICRATE) + { F_StartGameEnd(); + return; + } + + if (!useBlackRock) + ; + else if (!goodending) + { + if (sparklloop) + sparklloop--; + + if (finalecount == (5*TICRATE)/2 + || finalecount == (7*TICRATE)/2 + || finalecount == ((7*TICRATE)/2)+5) + { + S_StartSound(NULL, sfx_s3k5c); + sparklloop = 10; + } + } + else if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again + { + angle_t workingangle = FixedAngle((M_RandomKey(360))<>ANGLETOFINESHIFT; + fixed_t workingradius = M_RandomKey(26); + + sparkloffs[2][0] = sparkloffs[1][0]; + sparkloffs[2][1] = sparkloffs[1][1]; + sparkloffs[1][0] = sparkloffs[0][0]; + sparkloffs[1][1] = sparkloffs[0][1]; + + sparkloffs[0][0] = (30< STOPPINGPOINT) + { + F_StartCredits(); + wipetypepre = INT16_MAX; + return; + } + + if (finalecount == -8) + S_ChangeMusicInternal((goodending ? "_endg" : "_endb"), false); + + if (goodending && finalecount == INFLECTIONPOINT) // time to swap some assets + F_CacheGoodEnding(); + + if (++sparklloop == SPARKLLOOPTIME) // time to roll the randomisation again + { + angle_t workingangle = FixedAngle((M_RandomRange(-170, 80))<>ANGLETOFINESHIFT; + fixed_t workingradius = M_RandomKey(26); + + sparkloffs[0][0] = (30<= INFLECTIONPOINT) // time to swap some assets + F_CacheGoodEnding(); + } + + if (!goodending || finalecount < INFLECTIONPOINT) + rockpat = W_CachePatchName("ROID0000", PU_PATCH); + else + rockpat = W_CachePatchName(va("ROID00%.2d", 34 - ((finalecount - INFLECTIONPOINT) % 35)), PU_PATCH); + + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + + parallaxticker = finalecount - INFLECTIONPOINT; + x = -((parallaxticker*20)< -19) + { + INT32 trans = (-parallaxticker)>>1; + if (trans < 0) + trans = 0; + V_DrawFixedPatch((200< 0) // gunchedrock + { + INT32 scale = FRACUNIT + ((parallaxticker-10)<<7); + INT32 trans = parallaxticker>>2; + UINT8 *colormap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_JET, GTC_CACHE); + + if (parallaxticker < 10) + { + tweakx = parallaxticker< 0) + { + i -= (3+(tweakx<<1)); + j += tweaky<<2; + } + + if (parallaxticker <= 70) // eggrock/blackrock + { + INT32 trans; + fixed_t scale = FRACUNIT; + UINT8 *colormap[2] = {NULL, NULL}; + + x += i; + y += j; + + if (parallaxticker > 66) + { + scale = ((70 - parallaxticker)<<(FRACBITS-2)); + x += (30*(FRACUNIT-scale)); + y += (30*(FRACUNIT-scale)); + } + else if ((parallaxticker > 60) || (goodending && parallaxticker > 0)) + ; + else + { + doexplosions = true; + if (!sparklloop) + { + x += ((sparkloffs[0][0] < 30< INFLECTIONPOINT) + parallaxticker -= 40; + + if ((-parallaxticker/4) < 5) + { + trans = (-parallaxticker/4) + 5; + if (trans < 0) + trans = 0; + V_DrawFixedPatch(x, y, scale, trans< INFLECTIONPOINT) + { + if (finalecount < INFLECTIONPOINT+10) + V_DrawFadeFill(24, 24, BASEVIDWIDTH-48, BASEVIDHEIGHT-48, 0, 0, INFLECTIONPOINT+10-finalecount); + parallaxticker -= 30; + } + + if ((parallaxticker/2) > -15) + colormap[0] = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); + V_DrawFixedPatch(x, y, scale, 0, rockpat, colormap[0]); + if ((parallaxticker/2) > -25) + { + trans = (parallaxticker/2) + 15; + if (trans < 0) + trans = -trans; + if (trans < 10) + V_DrawFixedPatch(x, y, scale, trans< INFLECTIONPOINT) + { + if (finalecount < INFLECTIONPOINT+10) + V_DrawFixedPatch(x, y, scale, (finalecount-INFLECTIONPOINT)<= 3 && doexplosions) + { + INT32 boomtime = parallaxticker - sparklloop; + + x = ((((BASEVIDWIDTH-82)/2)+11)< INFLECTIONPOINT && finalecount < INFLECTIONPOINT+10) + V_DrawScaledPatch(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, (finalecount-INFLECTIONPOINT)<= TICRATE && finalecount < INFLECTIONPOINT) + { + INT32 workingtime = finalecount - TICRATE; + fixed_t radius = ((vid.width/vid.dupx)*(INFLECTIONPOINT - TICRATE - workingtime))/(INFLECTIONPOINT - TICRATE); + angle_t fa; + INT32 eemeralds_cur[4]; + char patchname[7] = "CEMGx0"; + + radius <<= FRACBITS; + + for (i = 0; i < 4; ++i) + { + if (i == 1) + workingtime -= sparklloop; + else if (i) + workingtime -= SPARKLLOOPTIME; + eemeralds_cur[i] = (workingtime % 360)<>ANGLETOFINESHIFT) & FINEMASK; + x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius); + y = (BASEVIDHEIGHT<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius); + eemeralds_cur[j] += (360<>ANGLETOFINESHIFT) & FINEMASK; + x = (BASEVIDWIDTH<<(FRACBITS-1)) + FixedMul(FINECOSINE(fa),radius); + y = ((BASEVIDHEIGHT+16)<<(FRACBITS-1)) + FixedMul(FINESINE(fa),radius); + eemeralds_cur[0] += (360< 20) + + // look, i make an ending for you last-minute, the least you could do is let me have this + if (cv_soundtest.value == 413) + { + INT32 trans = 0; + boolean donttouch = false; + const char *str; + if (goodending) + str = va("[S] %s: Engage.", skins[players[consoleplayer].skin].realname); + else + str = "[S] Eggman: Abscond."; + + if (finalecount < 10) + trans = (10-finalecount)/2; + else if (finalecount > STOPPINGPOINT - 20) + { + trans = 10 + (finalecount - STOPPINGPOINT)/2; + donttouch = true; + } + + if (trans < 10) + { + //colset(linkmap, 164, 165, 169); -- the ideal purple colour to represent a clicked in-game link, but not worth it just for a soundtest-controlled secret + V_DrawCenteredString(BASEVIDWIDTH/2, 8, V_ALLOWLOWERCASE|(trans<'|(trans<= STOPPINGPOINT-TICRATE) ? V_PURPLEMAP : V_BLUEMAP)|(trans<"); + } + + if (finalecount > STOPPINGPOINT-(20+(2*TICRATE))) + { + INT32 trans2 = abs((5*FINECOSINE((FixedAngle((finalecount*5)<>ANGLETOFINESHIFT & FINEMASK)))>>FRACBITS)+2; + if (!donttouch) + { + trans = 10 + (STOPPINGPOINT-(20+(2*TICRATE))) - finalecount; + if (trans > trans2) + trans2 = trans; + } + else + trans2 += 2*trans; + if (trans2 < 10) + V_DrawCharacter(26, BASEVIDHEIGHT-33, '\x1C'|(trans2< 0) - (scrollxspeed < 0), tilex; + INT32 yscrolled, y, yneg = (scrollyspeed > 0) - (scrollyspeed < 0), tiley; + boolean xispos = (scrollxspeed >= 0), yispos = (scrollyspeed >= 0); + INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); + INT16 patwidth, patheight; + INT32 pw, ph; // scaled by dupz + patch_t *pat; + INT32 i, j; + + if (rendermode == render_none) + return; + + if (!patchname || !patchname[0]) + { + V_DrawFill(0, 0, vid.width, vid.height, 31); + return; + } + + if (!scrollxspeed && !scrollyspeed) + { + V_DrawPatchFill(W_CachePatchName(patchname, PU_PATCH)); + return; + } + + pat = W_CachePatchName(patchname, PU_PATCH); + + patwidth = SHORT(pat->width); + patheight = SHORT(pat->height); + pw = patwidth * dupz; + ph = patheight * dupz; + + tilex = max(FixedCeil(FixedDiv(vid.width, pw)) >> FRACBITS, 1)+2; // one tile on both sides of center + tiley = max(FixedCeil(FixedDiv(vid.height, ph)) >> FRACBITS, 1)+2; + + xscrolltimer = ((menuanimtimer*scrollxspeed)/16 + patwidth*xneg) % (patwidth); + yscrolltimer = ((menuanimtimer*scrollyspeed)/16 + patheight*yneg) % (patheight); + + // coordinate offsets + xscrolled = xscrolltimer * dupz; + yscrolled = yscrolltimer * dupz; + + for (x = (xispos) ? -pw*(tilex-1)+pw : 0, i = 0; + i < tilex; + x += pw, i++) + { + for (y = (yispos) ? -ph*(tiley-1)+ph : 0, j = 0; + j < tiley; + y += ph, j++) + { + V_DrawScaledPatch( + (xispos) ? xscrolled - x : x + xscrolled, + (yispos) ? yscrolled - y : y + yscrolled, + V_NOSCALESTART, pat); + } + } + + W_UnlockCachedPatch(pat); +} + +#define LOADTTGFX(arr, name, maxf) \ +lumpnum = W_CheckNumForName(name); \ +if (lumpnum != LUMPERROR) \ +{ \ + arr[0] = W_CachePatchName(name, PU_LEVEL); \ + arr[min(1, maxf-1)] = 0; \ +} \ +else if (strlen(name) <= 6) \ +{ \ + fixed_t cnt = strlen(name); \ + strncpy(lumpname, name, 7); \ + for (i = 0; i < maxf-1; i++) \ + { \ + sprintf(&lumpname[cnt], "%.2hu", (UINT16)(i+1)); \ + lumpname[8] = 0; \ + lumpnum = W_CheckNumForName(lumpname); \ + if (lumpnum != LUMPERROR) \ + arr[i] = W_CachePatchName(lumpname, PU_LEVEL); \ + else \ + break; \ + } \ + arr[min(i, maxf-1)] = 0; \ +} \ +else \ + arr[0] = 0; + +static void F_CacheTitleScreen(void) +{ + switch(curttmode) + { + case TTMODE_OLD: + case TTMODE_NONE: + break; + + case TTMODE_USER: + { + UINT16 i; + lumpnum_t lumpnum; + char lumpname[9]; + + LOADTTGFX(ttuser, curttname, TTMAX_USER) + break; + } + } +} + void F_StartTitleScreen(void) { if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS) + { + ttuser_count = 0; finalecount = 0; + wipetypepost = menupres[MN_MAIN].enterwipe; + } else wipegamestate = GS_TITLESCREEN; + + if (titlemap) + { + mapthing_t *startpos; + + gamestate_t prevwipegamestate = wipegamestate; + titlemapinaction = TITLEMAP_LOADING; + titlemapcameraref = NULL; + gamemap = titlemap; + + if (!mapheaderinfo[gamemap-1]) + P_AllocMapHeader(gamemap-1); + + maptol = mapheaderinfo[gamemap-1]->typeoflevel; + globalweather = mapheaderinfo[gamemap-1]->weather; + + G_DoLoadLevel(true); + if (!titlemap) + return; + + players[displayplayers[0]].playerstate = PST_DEAD; // Don't spawn the player in dummy (I'm still a filthy cheater) + + // Set Default Position + if (playerstarts[0]) + startpos = playerstarts[0]; + else if (deathmatchstarts[0]) + startpos = deathmatchstarts[0]; + else + startpos = NULL; + + if (startpos) + { + camera[0].x = startpos->x << FRACBITS; + camera[0].y = startpos->y << FRACBITS; + camera[0].subsector = R_PointInSubsector(camera[0].x, camera[0].y); + camera[0].z = camera[0].subsector->sector->floorheight + (startpos->z << FRACBITS); + camera[0].angle = (startpos->angle % 360)*ANG1; + camera[0].aiming = 0; + } + else + { + camera[0].x = camera[0].y = camera[0].z = camera[0].angle = camera[0].aiming = 0; + camera[0].subsector = NULL; // toast is filthy too + } + + camera[0].chase = true; + camera[0].height = 0; + + // Run enter linedef exec for MN_MAIN, since this is where we start + if (menupres[MN_MAIN].entertag) + P_LinedefExecute(menupres[MN_MAIN].entertag, players[displayplayers[0]].mo, NULL); + + wipegamestate = prevwipegamestate; + } + else + { + titlemapinaction = TITLEMAP_OFF; + gamemap = 1; // g_game.c + CON_ClearHUD(); + } + G_SetGamestate(GS_TITLESCREEN); - CON_ClearHUD(); // IWAD dependent stuff. - // music is started in the ticker - if (!demo.fromtitle) // SRB2Kart: Don't reset music if the right track is already playing - S_StopMusic(); - demo.fromtitle = false; - - animtimer = 0; + animtimer = skullAnimCounter = 0; demoDelayLeft = demoDelayTime; demoIdleLeft = demoIdleTime; - ttbanner = W_CachePatchName("TTKBANNR", PU_LEVEL); - ttkart = W_CachePatchName("TTKART", PU_LEVEL); - ttcheckers = W_CachePatchName("TTCHECK", PU_LEVEL); - ttkflash = W_CachePatchName("TTKFLASH", PU_LEVEL); + F_CacheTitleScreen(); } // (no longer) De-Demo'd Title Screen void F_TitleScreenDrawer(void) { + boolean hidepics = false; + if (modeattacking) return; // We likely came here from retrying. Don't do a damn thing. + if (needpatchrecache) + F_CacheTitleScreen(); + + // Draw that sky! + if (curbgcolor >= 0) + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, curbgcolor); + else if (!curbghide || !titlemapinaction || gamestate == GS_WAITINGPLAYERS) + F_SkyScroll(curbgxspeed, curbgyspeed, curbgname); + // Don't draw outside of the title screen, or if the patch isn't there. - if (!ttbanner || (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS)) - { - F_SkyScroll(titlescrollspeed); + if (gamestate != GS_TITLESCREEN && gamestate != GS_WAITINGPLAYERS) return; - } - if (finalecount < 50) + // Don't draw if title mode is set to Old/None and the patch isn't there + /* + if (!ttwing && (curttmode == TTMODE_OLD || curttmode == TTMODE_NONE)) + return; + */ + + // rei|miru: use title pics? + hidepics = curhidepics; + if (hidepics) + goto luahook; + + switch(curttmode) { - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + case TTMODE_OLD: + case TTMODE_NONE: +/* + if (finalecount < 50) + { + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - V_DrawSmallScaledPatch(84, 36, 0, ttbanner); + V_DrawSmallScaledPatch(84, 36, 0, ttbanner); - if (finalecount >= 20) - V_DrawSmallScaledPatch(84, 87, 0, ttkart); - else if (finalecount >= 10) - V_DrawSciencePatch((84<= 20) + V_DrawSmallScaledPatch(84, 87, 0, ttkart); + else if (finalecount >= 10) + V_DrawSciencePatch((84<>1; + + V_DrawSciencePatch(0, 0 - FixedMul(40< -1 && ttuser[curttloop]) + ttuser_count = curttloop; + else if (ttuser[max(0, ttuser_count-1)]) + ttuser_count = max(0, ttuser_count-1); + else + break; // draw nothing + } + + V_DrawSciencePatch(curttx<>1; +luahook: + LUAh_TitleHUD(); +} - F_SkyScroll(titlescrollspeed); - - V_DrawSciencePatch(0, 0 - FixedMul(40<type != MT_ALTVIEWMAN) + { + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (!mo2) + continue; + + if (mo2->type != MT_ALTVIEWMAN) + continue; + + cameraref = titlemapcameraref = mo2; + break; + } + } + else + cameraref = titlemapcameraref; + + if (cameraref) + { + camera[0].x = cameraref->x; + camera[0].y = cameraref->y; + camera[0].z = cameraref->z; + camera[0].angle = cameraref->angle; + camera[0].aiming = cameraref->cusval; + camera[0].subsector = cameraref->subsector; + } + else + { + // Default behavior: Do a lil' camera spin if a title map is loaded; + camera[0].angle += titlescrollxspeed*ANG1/64; + } + } + + // no demos to play? or, are they disabled? if (!cv_rollingdemos.value) return; @@ -1092,12 +2137,14 @@ void F_TitleScreenTicker(boolean run) } // Replay intro when done cycling through demos - /*if (curDemo == numDemos) -- uuuh... we have a LOT of maps AND a big devteam... probably not gonna see a repeat unless you're super unlucky :V + /* + if (curDemo == numDemos) -- uuuh... we have a LOT of maps AND a big devteam... probably not gonna see a repeat unless you're super unlucky :V { curDemo = 0; F_StartIntro(); return; - }*/ + } + */ mapname = G_BuildMapName(G_RandMap(TOL_RACE, -2, false, 0, false, NULL)+1); @@ -1153,6 +2200,7 @@ void F_StartWaitingPlayers(void) { INT32 i; INT32 randskin; + spritedef_t *sprdef; spriteframe_t *sprframe; wipegamestate = GS_TITLESCREEN; // technically wiping from title screen @@ -1165,10 +2213,12 @@ void F_StartWaitingPlayers(void) waitcolormap = R_GetTranslationColormap(randskin, skins[randskin].prefcolor, 0); + sprdef = &skins[randskin].sprites[P_GetSkinSprite2(&skins[randskin], SPR2_FSTN, NULL)]; + for (i = 0; i < 2; i++) { - sprframe = &skins[randskin].spritedef.spriteframes[(6+(i*3)) & FF_FRAMEMASK]; - driver[i] = W_CachePatchNum(sprframe->lumppat[1], PU_LEVEL); + sprframe = &sprdef->spriteframes[i]; + driver[i] = W_CachePatchNum(sprframe->lumppat[0], PU_LEVEL); } } @@ -1196,122 +2246,11 @@ void F_WaitingPlayersDrawer(void) V_DrawFixedPatch((160<width / 2, 150< 20) - ncontinues = 20; - - if (imcontinuing) - contsonic = W_CachePatchName("CONT2", PU_CACHE); - else - contsonic = W_CachePatchName("CONT1", PU_CACHE); - - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); - V_DrawCenteredString(BASEVIDWIDTH/2, 100, 0, "CONTINUE?"); - - // Draw a Sonic! - V_DrawScaledPatch((BASEVIDWIDTH - SHORT(contsonic->width))/2, 32, 0, contsonic); - - // Draw the continue markers! Show continues minus one. - x -= ncontinues * 6; - for (i = 0; i < ncontinues; ++i) - V_DrawContinueIcon(x + (i*12), 140, 0, players[consoleplayer].skin, players[consoleplayer].skincolor); - - V_DrawCenteredString(BASEVIDWIDTH/2, 168, 0, va("\x82*\x80" " %02d " "\x82*\x80", timetonext/TICRATE)); -} - -void F_ContinueTicker(void) -{ - if (!imcontinuing) - { - // note the setup to prevent 2x reloading - if (timetonext >= 0) - timetonext--; - if (timetonext == 0) - Command_ExitGame_f(); - } - else - { - // note the setup to prevent 2x reloading - if (continuetime >= 0) - continuetime--; - if (continuetime == 0) - G_Continue(); - } -} - -boolean F_ContinueResponder(event_t *event) -{ - INT32 key = event->data1; - - if (keypressed) - return true; - - if (timetonext >= 21*TICRATE/2) - return false; - if (event->type != ev_keydown) - return false; - - // remap virtual keys (mouse & joystick buttons) - switch (key) - { - case KEY_ENTER: - case KEY_SPACE: - case KEY_MOUSE1: - case KEY_JOY1: - case KEY_JOY1 + 2: - break; - default: - return false; - } - - keypressed = true; - imcontinuing = true; - continuetime = TICRATE; - S_StartSound(0, sfx_itemup); - return true; -} - // ================== // CUSTOM CUTSCENES // ================== static INT32 scenenum, cutnum; -static INT32 picxpos, picypos, picnum, pictime; +static INT32 picxpos, picypos, picnum, pictime, picmode, numpics, pictoloop; static INT32 textxpos, textypos; static boolean dofadenow = false, cutsceneover = false; static boolean runningprecutscene = false, precutresetplayer = false; @@ -1352,6 +2291,7 @@ static void F_AdvanceToNextScene(void) animtimer = pictime = cutscenes[cutnum]->scene[scenenum].picduration[picnum]; } +// See also G_AfterIntermission, the only other place which handles intra-map/ending transitions void F_EndCutScene(void) { cutsceneover = true; // do this first, just in case G_EndGame or something wants to turn it back false later @@ -1380,6 +2320,9 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset G_SetGamestate(GS_CUTSCENE); + if (wipegamestate == GS_CUTSCENE) + wipegamestate = -1; + gameaction = ga_nothing; paused = false; CON_ToggleOff(); @@ -1412,6 +2355,7 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset cutscenes[cutnum]->scene[scenenum].musswitchposition, 0, 0); else S_StopMusic(); + S_StopSounds(); } // @@ -1440,10 +2384,10 @@ void F_CutsceneDrawer(void) { if (cutscenes[cutnum]->scene[scenenum].pichires[picnum]) V_DrawSmallScaledPatch(picxpos, picypos, 0, - W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE)); + W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); else V_DrawScaledPatch(picxpos,picypos, 0, - W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_CACHE)); + W_CachePatchName(cutscenes[cutnum]->scene[scenenum].picname[picnum], PU_PATCH)); } if (dofadenow && rendermode != render_none) @@ -1452,7 +2396,7 @@ void F_CutsceneDrawer(void) F_RunWipe(cutscenes[cutnum]->scene[scenenum].fadeoutid, true, NULL, false, false); } - V_DrawString(textxpos, textypos, 0, cutscene_disptext); + V_DrawString(textxpos, textypos, V_ALLOWLOWERCASE, cutscene_disptext); } void F_CutsceneTicker(void) @@ -1518,3 +2462,614 @@ boolean F_CutsceneResponder(event_t *event) return false; } + +// ================== +// TEXT PROMPTS +// ================== + +static void F_GetPageTextGeometry(UINT8 *pagelines, boolean *rightside, INT32 *boxh, INT32 *texth, INT32 *texty, INT32 *namey, INT32 *chevrony, INT32 *textx, INT32 *textr) +{ + // reuse: + // cutnum -> promptnum + // scenenum -> pagenum + lumpnum_t iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname); + + *pagelines = textprompts[cutnum]->page[scenenum].lines ? textprompts[cutnum]->page[scenenum].lines : 4; + *rightside = (iconlump != LUMPERROR && textprompts[cutnum]->page[scenenum].rightside); + + // Vertical calculations + *boxh = *pagelines*2; + *texth = textprompts[cutnum]->page[scenenum].name[0] ? (*pagelines-1)*2 : *pagelines*2; // name takes up first line if it exists + *texty = BASEVIDHEIGHT - ((*texth * 4) + (*texth/2)*4); + *namey = BASEVIDHEIGHT - ((*boxh * 4) + (*boxh/2)*4); + *chevrony = BASEVIDHEIGHT - (((1*2) * 4) + ((1*2)/2)*4); // force on last line + + // Horizontal calculations + // Shift text to the right if we have a character icon on the left side + // Add 4 margin against icon + *textx = (iconlump != LUMPERROR && !*rightside) ? ((*boxh * 4) + (*boxh/2)*4) + 4 : 4; + *textr = *rightside ? BASEVIDWIDTH - (((*boxh * 4) + (*boxh/2)*4) + 4) : BASEVIDWIDTH-4; +} + +static fixed_t F_GetPromptHideHudBound(void) +{ + UINT8 pagelines; + boolean rightside; + INT32 boxh, texth, texty, namey, chevrony; + INT32 textx, textr; + + if (cutnum == INT32_MAX || scenenum == INT32_MAX || !textprompts[cutnum] || scenenum >= textprompts[cutnum]->numpages || + !textprompts[cutnum]->page[scenenum].hidehud || + (splitscreen && textprompts[cutnum]->page[scenenum].hidehud != 2)) // don't hide on splitscreen, unless hide all is forced + return 0; + else if (textprompts[cutnum]->page[scenenum].hidehud == 2) // hide all + return BASEVIDHEIGHT; + + F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr); + + // calc boxheight (see V_DrawPromptBack) + boxh *= vid.dupy; + boxh = (boxh * 4) + (boxh/2)*5; // 4 lines of space plus gaps between and some leeway + + // return a coordinate to check + // if negative: don't show hud elements below this coordinate (visually) + // if positive: don't show hud elements above this coordinate (visually) + return 0 - boxh; // \todo: if prompt at top of screen (someday), make this return positive +} + +boolean F_GetPromptHideHudAll(void) +{ + if (cutnum == INT32_MAX || scenenum == INT32_MAX || !textprompts[cutnum] || scenenum >= textprompts[cutnum]->numpages || + !textprompts[cutnum]->page[scenenum].hidehud || + (splitscreen && textprompts[cutnum]->page[scenenum].hidehud != 2)) // don't hide on splitscreen, unless hide all is forced + return false; + else if (textprompts[cutnum]->page[scenenum].hidehud == 2) // hide all + return true; + else + return false; +} + +boolean F_GetPromptHideHud(fixed_t y) +{ + INT32 ybound; + boolean fromtop; + fixed_t ytest; + + if (!promptactive) + return false; + + ybound = F_GetPromptHideHudBound(); + fromtop = (ybound >= 0); + ytest = (fromtop ? ybound : BASEVIDHEIGHT + ybound); + + return (fromtop ? y < ytest : y >= ytest); // true means hide +} + +static void F_PreparePageText(char *pagetext) +{ + UINT8 pagelines; + boolean rightside; + INT32 boxh, texth, texty, namey, chevrony; + INT32 textx, textr; + + F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr); + + if (promptpagetext) + Z_Free(promptpagetext); + promptpagetext = (pagetext && pagetext[0]) ? V_WordWrap(textx, textr, 0, pagetext) : Z_StrDup(""); + + F_NewCutscene(promptpagetext); + cutscene_textspeed = textprompts[cutnum]->page[scenenum].textspeed ? textprompts[cutnum]->page[scenenum].textspeed : TICRATE/5; + cutscene_textcount = 0; // no delay in beginning + cutscene_boostspeed = 0; // don't print 8 characters to start + + // \todo update control hot strings on re-config + // and somehow don't reset cutscene text counters +} + +static void F_AdvanceToNextPage(void) +{ + INT32 nextprompt = textprompts[cutnum]->page[scenenum].nextprompt ? textprompts[cutnum]->page[scenenum].nextprompt - 1 : INT32_MAX, + nextpage = textprompts[cutnum]->page[scenenum].nextpage ? textprompts[cutnum]->page[scenenum].nextpage - 1 : INT32_MAX, + oldcutnum = cutnum; + + if (textprompts[cutnum]->page[scenenum].nexttag[0]) + F_GetPromptPageByNamedTag(textprompts[cutnum]->page[scenenum].nexttag, &nextprompt, &nextpage); + + // determine next prompt + if (nextprompt != INT32_MAX) + { + if (nextprompt <= MAX_PROMPTS && textprompts[nextprompt]) + cutnum = nextprompt; + else + cutnum = INT32_MAX; + } + + // determine next page + if (nextpage != INT32_MAX) + { + if (cutnum != INT32_MAX) + { + scenenum = nextpage; + if (scenenum >= MAX_PAGES || scenenum > textprompts[cutnum]->numpages-1) + scenenum = INT32_MAX; + } + } + else + { + if (cutnum != oldcutnum) + scenenum = 0; + else if (scenenum + 1 < MAX_PAGES && scenenum < textprompts[cutnum]->numpages-1) + scenenum++; + else + scenenum = INT32_MAX; + } + + // close the prompt if either num is invalid + if (cutnum == INT32_MAX || scenenum == INT32_MAX) + F_EndTextPrompt(false, false); + else + { + // on page mode, number of tics before allowing boost + // on timer mode, number of tics until page advances + timetonext = textprompts[cutnum]->page[scenenum].timetonext ? textprompts[cutnum]->page[scenenum].timetonext : TICRATE/10; + F_PreparePageText(textprompts[cutnum]->page[scenenum].text); + + // gfx + picnum = textprompts[cutnum]->page[scenenum].pictostart; + numpics = textprompts[cutnum]->page[scenenum].numpics; + picmode = textprompts[cutnum]->page[scenenum].picmode; + pictoloop = textprompts[cutnum]->page[scenenum].pictoloop > 0 ? textprompts[cutnum]->page[scenenum].pictoloop - 1 : 0; + picxpos = textprompts[cutnum]->page[scenenum].xcoord[picnum]; + picypos = textprompts[cutnum]->page[scenenum].ycoord[picnum]; + animtimer = pictime = textprompts[cutnum]->page[scenenum].picduration[picnum]; + + // music change + if (textprompts[cutnum]->page[scenenum].musswitch[0]) + S_ChangeMusic(textprompts[cutnum]->page[scenenum].musswitch, + textprompts[cutnum]->page[scenenum].musswitchflags, + textprompts[cutnum]->page[scenenum].musicloop); + } +} + +void F_EndTextPrompt(boolean forceexec, boolean noexec) +{ + boolean promptwasactive = promptactive; + promptactive = false; + callpromptnum = callpagenum = callplayer = INT32_MAX; + + if (promptwasactive) + { + if (promptmo && promptmo->player && promptblockcontrols) + promptmo->reactiontime = TICRATE/4; // prevent jumping right away // \todo account freeze realtime for this) + // \todo reset frozen realtime? + } + + // \todo net safety, maybe loop all player thinkers? + if ((promptwasactive || forceexec) && !noexec && promptpostexectag) + { + if (tmthing) // edge case where starting an invalid prompt immediately on level load will make P_MapStart fail + P_LinedefExecute(promptpostexectag, promptmo, NULL); + else + { + P_MapStart(); + P_LinedefExecute(promptpostexectag, promptmo, NULL); + P_MapEnd(); + } + } +} + +void F_StartTextPrompt(INT32 promptnum, INT32 pagenum, mobj_t *mo, UINT16 postexectag, boolean blockcontrols, boolean freezerealtime) +{ + INT32 i; + + // if splitscreen and we already have a prompt active, ignore. + // \todo Proper per-player splitscreen support (individual prompts) + if (promptactive && splitscreen && promptnum == callpromptnum && pagenum == callpagenum) + return; + + // \todo proper netgame support + if (netgame) + { + F_EndTextPrompt(true, false); // run the post-effects immediately + return; + } + + // We share vars, so no starting text prompts over cutscenes or title screens! + keypressed = false; + finalecount = 0; + timetonext = 0; + animtimer = 0; + stoptimer = 0; + skullAnimCounter = 0; + + // Set up state + promptmo = mo; + promptpostexectag = postexectag; + promptblockcontrols = blockcontrols; + (void)freezerealtime; // \todo freeze player->realtime, maybe this needs to cycle through player thinkers + + // Initialize current prompt and scene + callpromptnum = promptnum; + callpagenum = pagenum; + cutnum = (promptnum < MAX_PROMPTS && textprompts[promptnum]) ? promptnum : INT32_MAX; + scenenum = (cutnum != INT32_MAX && pagenum < MAX_PAGES && pagenum <= textprompts[cutnum]->numpages-1) ? pagenum : INT32_MAX; + promptactive = (cutnum != INT32_MAX && scenenum != INT32_MAX); + + if (promptactive) + { + // on page mode, number of tics before allowing boost + // on timer mode, number of tics until page advances + timetonext = textprompts[cutnum]->page[scenenum].timetonext ? textprompts[cutnum]->page[scenenum].timetonext : TICRATE/10; + F_PreparePageText(textprompts[cutnum]->page[scenenum].text); + + // gfx + picnum = textprompts[cutnum]->page[scenenum].pictostart; + numpics = textprompts[cutnum]->page[scenenum].numpics; + picmode = textprompts[cutnum]->page[scenenum].picmode; + pictoloop = textprompts[cutnum]->page[scenenum].pictoloop > 0 ? textprompts[cutnum]->page[scenenum].pictoloop - 1 : 0; + picxpos = textprompts[cutnum]->page[scenenum].xcoord[picnum]; + picypos = textprompts[cutnum]->page[scenenum].ycoord[picnum]; + animtimer = pictime = textprompts[cutnum]->page[scenenum].picduration[picnum]; + + // music change + if (textprompts[cutnum]->page[scenenum].musswitch[0]) + S_ChangeMusic(textprompts[cutnum]->page[scenenum].musswitch, + textprompts[cutnum]->page[scenenum].musswitchflags, + textprompts[cutnum]->page[scenenum].musicloop); + + // get the calling player + if (promptblockcontrols && mo && mo->player) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (players[i].mo == mo) + { + callplayer = i; + break; + } + } + } + } + else + F_EndTextPrompt(true, false); // run the post-effects immediately +} + +static boolean F_GetTextPromptTutorialTag(char *tag, INT32 length) +{ + INT32 gcs = gcs_custom; + boolean suffixed = true; + + if (!tag || !tag[0] || !tutorialmode) + return false; + + if (!strncmp(tag, "TAA", 3)) // Accelerate + gcs = G_GetControlScheme(gamecontrol[0], gcl_accelerate, num_gcl_accelerate); + else if (!strncmp(tag, "TAB", 3)) // Brake + gcs = G_GetControlScheme(gamecontrol[0], gcl_brake, num_gcl_brake); + else if (!strncmp(tag, "TAD", 3)) // Drift + gcs = G_GetControlScheme(gamecontrol[0], gcl_drift, num_gcl_drift); + else if (!strncmp(tag, "TAS", 3)) // Spindash + gcs = G_GetControlScheme(gamecontrol[0], gcl_spindash, num_gcl_spindash); + else if (!strncmp(tag, "TAM", 3)) // Movement + gcs = G_GetControlScheme(gamecontrol[0], gcl_movement, num_gcl_movement); + else if (!strncmp(tag, "TAI", 3)) // Item usage + gcs = G_GetControlScheme(gamecontrol[0], gcl_item, num_gcl_item); + else + gcs = G_GetControlScheme(gamecontrol[0], gcl_full, num_gcl_full); + + switch (gcs) + { + case gcs_kart: + // strncat(tag, "KART", length); + suffixed = false; + break; + + default: + strncat(tag, "CUSTOM", length); + break; + } + + return suffixed; +} + +void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum) +{ + INT32 nosuffixpromptnum = INT32_MAX, nosuffixpagenum = INT32_MAX; + INT32 tutorialpromptnum = (tutorialmode) ? TUTORIAL_PROMPT-1 : 0; + boolean suffixed = false, found = false; + char suffixedtag[33]; + + *promptnum = *pagenum = INT32_MAX; + + if (!tag || !tag[0]) + return; + + strncpy(suffixedtag, tag, 33); + suffixedtag[32] = 0; + + if (tutorialmode) + suffixed = F_GetTextPromptTutorialTag(suffixedtag, 33); + + for (*promptnum = 0 + tutorialpromptnum; *promptnum < MAX_PROMPTS; (*promptnum)++) + { + if (!textprompts[*promptnum]) + continue; + + for (*pagenum = 0; *pagenum < textprompts[*promptnum]->numpages && *pagenum < MAX_PAGES; (*pagenum)++) + { + if (suffixed && fastcmp(suffixedtag, textprompts[*promptnum]->page[*pagenum].tag)) + { + // this goes first because fastcmp ends early if first string is shorter + found = true; + break; + } + else if (nosuffixpromptnum == INT32_MAX && nosuffixpagenum == INT32_MAX && fastcmp(tag, textprompts[*promptnum]->page[*pagenum].tag)) + { + if (suffixed) + { + nosuffixpromptnum = *promptnum; + nosuffixpagenum = *pagenum; + // continue searching for the suffixed tag + } + else + { + found = true; + break; + } + } + } + + if (found) + break; + } + + if (suffixed && !found && nosuffixpromptnum != INT32_MAX && nosuffixpagenum != INT32_MAX) + { + found = true; + *promptnum = nosuffixpromptnum; + *pagenum = nosuffixpagenum; + } + + if (!found) + CONS_Debug(DBG_GAMELOGIC, "Text prompt: Can't find a page with named tag %s or suffixed tag %s\n", tag, suffixedtag); +} + +void F_TextPromptDrawer(void) +{ + // reuse: + // cutnum -> promptnum + // scenenum -> pagenum + lumpnum_t iconlump; + UINT8 pagelines; + boolean rightside; + INT32 boxh, texth, texty, namey, chevrony; + INT32 textx, textr; + + // Data + patch_t *patch; + + if (!promptactive) + return; + + iconlump = W_CheckNumForName(textprompts[cutnum]->page[scenenum].iconname); + F_GetPageTextGeometry(&pagelines, &rightside, &boxh, &texth, &texty, &namey, &chevrony, &textx, &textr); + + // Draw gfx first + if (picnum >= 0 && picnum < numpics && textprompts[cutnum]->page[scenenum].picname[picnum][0] != '\0') + { + if (textprompts[cutnum]->page[scenenum].pichires[picnum]) + V_DrawSmallScaledPatch(picxpos, picypos, 0, + W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); + else + V_DrawScaledPatch(picxpos,picypos, 0, + W_CachePatchName(textprompts[cutnum]->page[scenenum].picname[picnum], PU_PATCH)); + } + + // Draw background + V_DrawPromptBack(boxh, textprompts[cutnum]->page[scenenum].backcolor); + + // Draw narrator icon + if (iconlump != LUMPERROR) + { + INT32 iconx, icony, scale, scaledsize; + patch = W_CachePatchName(textprompts[cutnum]->page[scenenum].iconname, PU_PATCH); + + // scale and center + if (patch->width > patch->height) + { + scale = FixedDiv(((boxh * 4) + (boxh/2)*4) - 4, patch->width); + scaledsize = FixedMul(patch->height, scale); + iconx = (rightside ? BASEVIDWIDTH - (((boxh * 4) + (boxh/2)*4)) : 4) << FRACBITS; + icony = ((namey-4) << FRACBITS) + FixedDiv(BASEVIDHEIGHT - namey + 4 - scaledsize, 2); // account for 4 margin + } + else if (patch->height > patch->width) + { + scale = FixedDiv(((boxh * 4) + (boxh/2)*4) - 4, patch->height); + scaledsize = FixedMul(patch->width, scale); + iconx = (rightside ? BASEVIDWIDTH - (((boxh * 4) + (boxh/2)*4)) : 4) << FRACBITS; + icony = namey << FRACBITS; + iconx += FixedDiv(FixedMul(patch->height, scale) - scaledsize, 2); + } + else + { + scale = FixedDiv(((boxh * 4) + (boxh/2)*4) - 4, patch->width); + iconx = (rightside ? BASEVIDWIDTH - (((boxh * 4) + (boxh/2)*4)) : 4) << FRACBITS; + icony = namey << FRACBITS; + } + + if (textprompts[cutnum]->page[scenenum].iconflip) + iconx += FixedMul(patch->width, scale) << FRACBITS; + + V_DrawFixedPatch(iconx, icony, scale, (V_SNAPTOBOTTOM|(textprompts[cutnum]->page[scenenum].iconflip ? V_FLIP : 0)), patch, NULL); + W_UnlockCachedPatch(patch); + } + + // Draw text + V_DrawString(textx, texty, (V_SNAPTOBOTTOM|V_ALLOWLOWERCASE), cutscene_disptext); + + // Draw name + // Don't use V_YELLOWMAP here so that the name color can be changed with control codes + if (textprompts[cutnum]->page[scenenum].name[0]) + V_DrawString(textx, namey, (V_SNAPTOBOTTOM|V_ALLOWLOWERCASE), textprompts[cutnum]->page[scenenum].name); + + // Draw chevron + if (promptblockcontrols && !timetonext) + V_DrawString(textr-8, chevrony + (skullAnimCounter/5), (V_SNAPTOBOTTOM|V_YELLOWMAP), "\x1B"); // down arrow +} + +#define nocontrolallowed(j) {\ + players[j].powers[pw_nocontrol] = 1;\ + if (players[j].mo)\ + {\ + if (players[j].mo->state == states+S_KART_STILL && players[j].mo->tics != -1)\ + players[j].mo->tics++;\ + }\ + } + +void F_TextPromptTicker(void) +{ + INT32 i; + + if (!promptactive || paused || P_AutoPause()) + return; + + // advance animation + finalecount++; + cutscene_boostspeed = 0; + + // for the chevron + if (--skullAnimCounter <= 0) + skullAnimCounter = 8; + + // button handling + if (textprompts[cutnum]->page[scenenum].timetonext) + { + if (promptblockcontrols) // same procedure as below, just without the button handling + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (netgame && i != serverplayer && !IsPlayerAdmin(i)) + continue; + else + { + UINT8 j; + + // Both players' controls are locked, + // But only consoleplayer can advance the prompt. + // \todo Proper per-player splitscreen support (individual prompts) + for (j = 0; j < g_localplayers[j]; j++) + { + if (i == g_localplayers[j]) + nocontrolallowed(i) + } + } + + if (!splitscreen) + break; + } + } + + if (timetonext >= 1) + timetonext--; + + if (!timetonext) + F_AdvanceToNextPage(); + + F_WriteText(); + } + else + { + if (promptblockcontrols) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (netgame && i != serverplayer && !IsPlayerAdmin(i)) + continue; + else + { + UINT8 j; + + players[i].powers[pw_nocontrol] = 1; + + // Both players' controls are locked, + // But only the triggering player can advance the prompt. + for (j = 0; j <= splitscreen; j++) + { + if (callplayer == g_localplayers[j]) + { + if (i != callplayer) + continue; + } + else if (i != consoleplayer) + continue; + } + } + + if (players[i].cmd.buttons & (BT_ACCELERATE|BT_BRAKE|BT_DRIFT)) + { + if (timetonext > 1) + timetonext--; + else if (cutscene_baseptr) // don't set boost if we just reset the string + cutscene_boostspeed = 1; // only after a slight delay + + if (keypressed) + { + if (!splitscreen) + break; + else + continue; + } + + if (!timetonext) // is 0 when finished generating text + { + F_AdvanceToNextPage(); + if (promptactive) + S_StartSound(NULL, sfx_menu1); + } + keypressed = true; // prevent repeat events + } + else if (!(players[i].cmd.buttons & (BT_ACCELERATE|BT_BRAKE|BT_DRIFT))) + keypressed = false; + + if (!splitscreen) + break; + } + } + + // generate letter-by-letter text + if (scenenum >= MAX_PAGES || + !textprompts[cutnum]->page[scenenum].text || + !textprompts[cutnum]->page[scenenum].text[0] || + !F_WriteText()) + timetonext = !promptblockcontrols; // never show the chevron if we can't toggle pages + } + + // gfx + if (picnum >= 0 && picnum < numpics) + { + if (animtimer <= 0) + { + boolean persistanimtimer = false; + + if (picnum < numpics-1 && textprompts[cutnum]->page[scenenum].picname[picnum+1][0] != '\0') + picnum++; + else if (picmode == PROMPT_PIC_LOOP) + picnum = pictoloop; + else if (picmode == PROMPT_PIC_DESTROY) + picnum = -1; + else // if (picmode == PROMPT_PIC_PERSIST) + persistanimtimer = true; + + if (!persistanimtimer && picnum >= 0) + { + picxpos = textprompts[cutnum]->page[scenenum].xcoord[picnum]; + picypos = textprompts[cutnum]->page[scenenum].ycoord[picnum]; + pictime = textprompts[cutnum]->page[scenenum].picduration[picnum]; + animtimer = pictime; + } + } + else + animtimer--; + } +} diff --git a/src/f_finale.h b/src/f_finale.h index d1efa6ce2..cc731f7f3 100644 --- a/src/f_finale.h +++ b/src/f_finale.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -17,6 +17,7 @@ #include "doomtype.h" #include "d_event.h" +#include "p_mobj.h" // // FINALE @@ -33,11 +34,13 @@ void F_IntroTicker(void); void F_TitleScreenTicker(boolean run); void F_CutsceneTicker(void); void F_TitleDemoTicker(void); +void F_TextPromptTicker(void); // Called by main loop. void F_GameEndDrawer(void); void F_IntroDrawer(void); void F_TitleScreenDrawer(void); +void F_SkyScroll(INT32 scrollxspeed, INT32 scrollyspeed, const char *patchname); void F_StartWaitingPlayers(void); void F_WaitingPlayersTicker(void); @@ -47,6 +50,9 @@ void F_GameEvaluationDrawer(void); void F_StartGameEvaluation(void); void F_GameEvaluationTicker(void); +void F_EndingTicker(void); +void F_EndingDrawer(void); + void F_CreditTicker(void); void F_CreditDrawer(void); @@ -54,27 +60,98 @@ void F_StartCustomCutscene(INT32 cutscenenum, boolean precutscene, boolean reset void F_CutsceneDrawer(void); void F_EndCutScene(void); +void F_StartTextPrompt(INT32 promptnum, INT32 pagenum, mobj_t *mo, UINT16 postexectag, boolean blockcontrols, boolean freezerealtime); +void F_GetPromptPageByNamedTag(const char *tag, INT32 *promptnum, INT32 *pagenum); +void F_TextPromptDrawer(void); +void F_EndTextPrompt(boolean forceexec, boolean noexec); +boolean F_GetPromptHideHudAll(void); +boolean F_GetPromptHideHud(fixed_t y); + void F_StartGameEnd(void); void F_StartIntro(void); void F_StartTitleScreen(void); +void F_StartEnding(void); void F_StartCredits(void); -boolean F_ContinueResponder(event_t *event); -void F_StartContinue(void); -void F_ContinueTicker(void); -void F_ContinueDrawer(void); +extern INT32 finalecount; +extern INT32 titlescrollxspeed; +extern INT32 titlescrollyspeed; -extern INT32 titlescrollspeed; +typedef enum +{ + TTMODE_NONE = 0, + TTMODE_OLD, + TTMODE_USER, + //TTMODE_RINGRACERS +} ttmode_enum; + +#define TTMAX_ALACROIX 30 // max frames for SONIC typeface, plus one for NULL terminating entry +#define TTMAX_USER 100 + +extern ttmode_enum ttmode; +extern UINT8 ttscale; +// ttmode user vars +extern char ttname[9]; +extern INT16 ttx; +extern INT16 tty; +extern INT16 ttloop; +extern UINT16 tttics; +extern boolean ttavailable[6]; + + +typedef enum +{ + TITLEMAP_OFF = 0, + TITLEMAP_LOADING, + TITLEMAP_RUNNING +} titlemap_enum; + +// Current menu parameters + +extern mobj_t *titlemapcameraref; +extern char curbgname[9]; +extern SINT8 curfadevalue; +extern INT32 curbgcolor; +extern INT32 curbgxspeed; +extern INT32 curbgyspeed; +extern boolean curbghide; +extern boolean hidetitlemap; + +extern boolean curhidepics; +extern ttmode_enum curttmode; +extern UINT8 curttscale; +// ttmode user vars +extern char curttname[9]; +extern INT16 curttx; +extern INT16 curtty; +extern INT16 curttloop; +extern UINT16 curtttics; + +#define TITLEBACKGROUNDACTIVE (curfadevalue >= 0 || curbgname[0]) + +void F_InitMenuPresValues(void); +void F_MenuPresTicker(boolean run); // // WIPE // + extern boolean WipeInAction; +extern boolean WipeStageTitle; + extern INT32 lastwipetic; +// Don't know where else to place this constant +// But this file seems appropriate +#define PRELEVELTIME 24 // frames in tics + void F_WipeStartScreen(void); void F_WipeEndScreen(void); void F_RunWipe(UINT8 wipetype, boolean drawMenu, const char *colormap, boolean reverse, boolean encorewiggle); +void F_WipeStageTitle(void); +#define F_WipeColorFill(c) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, c) +tic_t F_GetWipeLength(UINT8 wipetype); +boolean F_WipeExists(UINT8 wipetype); enum { @@ -91,6 +168,7 @@ enum wipe_evaluation_toblack, wipe_gameend_toblack, wipe_intro_toblack, + wipe_ending_toblack, wipe_cutscene_toblack, // Specialized wipes @@ -108,10 +186,15 @@ enum wipe_evaluation_final, wipe_gameend_final, wipe_intro_final, + wipe_ending_final, wipe_cutscene_final, + // custom intermissions + wipe_specinter_final, + wipe_multinter_final, + NUMWIPEDEFS, - WIPEFINALSHIFT = wipe_level_final - wipe_level_toblack + WIPEFINALSHIFT = (wipe_level_final-wipe_level_toblack) }; extern UINT8 wipedefs[NUMWIPEDEFS]; diff --git a/src/f_wipe.c b/src/f_wipe.c index 530536377..9399598f5 100644 --- a/src/f_wipe.c +++ b/src/f_wipe.c @@ -31,6 +31,9 @@ #include "m_misc.h" // movie mode #include "d_clisrv.h" // So the network state can be updated during the wipe +#include "g_game.h" +#include "st_stuff.h" + #ifdef HWRENDER #include "hardware/hw_main.h" #endif @@ -59,6 +62,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = { 0, // wipe_evaluation_toblack 0, // wipe_gameend_toblack UINT8_MAX, // wipe_intro_toblack (hardcoded) + 99, // wipe_ending_toblack (hardcoded) 99, // wipe_cutscene_toblack (hardcoded) 72, // wipe_encore_toinvert @@ -74,6 +78,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = { 0, // wipe_evaluation_final 0, // wipe_gameend_final 99, // wipe_intro_final (hardcoded) + 99, // wipe_ending_final (hardcoded) 99 // wipe_cutscene_final (hardcoded) }; @@ -82,6 +87,7 @@ UINT8 wipedefs[NUMWIPEDEFS] = { //-------------------------------------------------------------------------- boolean WipeInAction = false; +boolean WipeStageTitle = false; INT32 lastwipetic = 0; #ifndef NOWIPE @@ -401,6 +407,18 @@ static void F_DoEncoreWiggle(UINT8 time) } } +/** Draw the stage title. + */ +void F_WipeStageTitle(void) +{ + // draw level title + if ((WipeStageTitle) && G_IsTitleCardAvailable()) + { + ST_runTitleCard(); + ST_drawWipeTitleCard(); + } +} + /** After setting up the screens you want to wipe, * calling this will do a 'typical' wipe. */ @@ -505,3 +523,52 @@ void F_RunWipe(UINT8 wipetype, boolean drawMenu, const char *colormap, boolean r } #endif } + +/** Returns tic length of wipe + * One lump equals one tic + */ +tic_t F_GetWipeLength(UINT8 wipetype) +{ +#ifdef NOWIPE + (void)wipetype; + return 0; +#else + static char lumpname[10] = "FADEmmss"; + lumpnum_t lumpnum; + UINT8 wipeframe; + + if (wipetype > 99) + return 0; + + for (wipeframe = 0; wipeframe < 100; wipeframe++) + { + sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)wipetype, (UINT16)wipeframe); + + lumpnum = W_CheckNumForName(lumpname); + if (lumpnum == LUMPERROR) + return --wipeframe; + } + return --wipeframe; +#endif +} + +/** Does the specified wipe exist? + */ +boolean F_WipeExists(UINT8 wipetype) +{ +#ifdef NOWIPE + (void)wipetype; + return false; +#else + static char lumpname[10] = "FADEmm00"; + lumpnum_t lumpnum; + + if (wipetype > 99) + return false; + + sprintf(&lumpname[4], "%.2hu00", (UINT16)wipetype); + + lumpnum = W_CheckNumForName(lumpname); + return !(lumpnum == LUMPERROR); +#endif +} diff --git a/src/filesrch.c b/src/filesrch.c index 1be74f9b9..6dd11c5fc 100644 --- a/src/filesrch.c +++ b/src/filesrch.c @@ -316,18 +316,18 @@ static CV_PossibleValue_t addons_cons_t[] = {{0, "Default"}, #endif {3, "CUSTOM"}, {0, NULL}}; -consvar_t cv_addons_option = {"addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_addons_folder = {"addons_folder", "", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_option = CVAR_INIT ("addons_option", "Default", CV_SAVE|CV_CALL, addons_cons_t, Addons_option_Onchange); +consvar_t cv_addons_folder = CVAR_INIT ("addons_folder", "", CV_SAVE, NULL, NULL); static CV_PossibleValue_t addons_md5_cons_t[] = {{0, "Name"}, {1, "Contents"}, {0, NULL}}; -consvar_t cv_addons_md5 = {"addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_md5 = CVAR_INIT ("addons_md5", "Name", CV_SAVE, addons_md5_cons_t, NULL); -consvar_t cv_addons_showall = {"addons_showall", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_showall = CVAR_INIT ("addons_showall", "No", CV_SAVE, CV_YesNo, NULL); -consvar_t cv_addons_search_case = {"addons_search_case", "No", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_search_case = CVAR_INIT ("addons_search_case", "No", CV_SAVE, CV_YesNo, NULL); static CV_PossibleValue_t addons_search_type_cons_t[] = {{0, "Start"}, {1, "Anywhere"}, {0, NULL}}; -consvar_t cv_addons_search_type = {"addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_addons_search_type = CVAR_INIT ("addons_search_type", "Anywhere", CV_SAVE, addons_search_type_cons_t, NULL); char menupath[1024]; size_t menupathindex[menudepth]; @@ -868,7 +868,7 @@ boolean preparefilemenu(boolean samedepth, boolean replayhut) } else if (ext == EXT_TXT) { - if (!strncmp(dent->d_name, "log-", 4) || !strcmp(dent->d_name, "errorlog.txt")) + if (!strcmp(dent->d_name, "log.txt") || !strcmp(dent->d_name, "errorlog.txt")) ext |= EXT_LOADED; } diff --git a/src/filesrch.h b/src/filesrch.h index 4cb92b238..fb5fc0edd 100644 --- a/src/filesrch.h +++ b/src/filesrch.h @@ -57,7 +57,7 @@ typedef enum #endif EXT_PK3, EXT_SOC, - EXT_LUA, // allowed even if not HAVE_BLUA so that we can yell on load attempt + EXT_LUA, NUM_EXT, NUM_EXT_TABLE = NUM_EXT-EXT_START, EXT_LOADED = 0x80 diff --git a/src/g_demo.c b/src/g_demo.c new file mode 100644 index 000000000..7c2f9f25c --- /dev/null +++ b/src/g_demo.c @@ -0,0 +1,3808 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file g_demo.c +/// \brief Demo recording and playback + +#include "doomdef.h" +#include "console.h" +#include "d_main.h" +#include "d_player.h" +#include "d_clisrv.h" +#include "p_setup.h" +#include "i_system.h" +#include "m_random.h" +#include "p_local.h" +#include "r_draw.h" +#include "r_main.h" +#include "g_game.h" +#include "g_demo.h" +#include "m_misc.h" +#include "m_menu.h" +#include "m_argv.h" +#include "hu_stuff.h" +#include "z_zone.h" +#include "i_video.h" +#include "byteptr.h" +#include "i_joy.h" +#include "r_local.h" +#include "r_skins.h" +#include "y_inter.h" +#include "v_video.h" +#include "lua_hook.h" +#include "md5.h" // demo checksums + +// SRB2Kart +#include "d_netfil.h" // nameonly + +#include "lua_script.h" // LUA_ArchiveDemo and LUA_UnArchiveDemo +#include "lua_libs.h" // gL (Lua state) + +#include "k_kart.h" +#include "k_battle.h" +#include "k_respawn.h" +#include "k_bot.h" + +static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}}; +consvar_t cv_recordmultiplayerdemos = CVAR_INIT ("netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL); + +static CV_PossibleValue_t netdemosyncquality_cons_t[] = {{1, "MIN"}, {35, "MAX"}, {0, NULL}}; +consvar_t cv_netdemosyncquality = CVAR_INIT ("netdemo_syncquality", "1", CV_SAVE, netdemosyncquality_cons_t, NULL); + +boolean nodrawers; // for comparative timing purposes +boolean noblit; // for comparative timing purposes +tic_t demostarttime; // for comparative timing purposes + +static char demoname[128]; +static UINT8 *demobuffer = NULL; +static UINT8 *demotime_p, *demoinfo_p; +UINT8 *demo_p; +static UINT8 *demoend; +static UINT8 demoflags; +boolean demosynced = true; // console warning message + +struct demovars_s demo; + +boolean metalrecording; // recording as metal sonic +mobj_t *metalplayback; +static UINT8 *metalbuffer = NULL; +static UINT8 *metal_p; +static UINT16 metalversion; + +// extra data stuff (events registered this frame while recording) +static struct { + UINT8 flags; // EZT flags + + // EZT_COLOR + UINT8 color, lastcolor; + + // EZT_SCALE + fixed_t scale, lastscale; + + // EZT_KART + INT32 kartitem, kartamount, kartbumpers; + + UINT8 desyncframes; // Don't try to resync unless we've been off for two frames, to monkeypatch a few trouble spots + + // EZT_HIT + UINT16 hits; + mobj_t **hitlist; +} ghostext[MAXPLAYERS]; + +// Your naming conventions are stupid and useless. +// There is no conflict here. +demoghost *ghosts = NULL; + +// +// DEMO RECORDING +// + +#define DEMOVERSION 0x0004 +#define DEMOHEADER "\xF0" "KartReplay" "\x0F" + +#define DF_GHOST 0x01 // This demo contains ghost data too! +#define DF_TIMEATTACK 0x02 // This demo is from Time Attack and contains its final completion time & best lap! +#define DF_BREAKTHECAPSULES 0x04 // This demo is from Break the Capsules and contains its final completion time! +#define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ??? + +#define DF_LUAVARS 0x20 // this demo contains extra lua vars; this is mostly used for backwards compability + +#define DF_ATTACKSHIFT 1 +#define DF_ENCORE 0x40 +#define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode! + +#define DEMO_SPECTATOR 0x40 + +// For demos +#define ZT_FWD 0x01 +#define ZT_SIDE 0x02 +#define ZT_TURNING 0x04 +#define ZT_BUTTONS 0x08 +#define ZT_AIMING 0x10 +#define ZT_LATENCY 0x20 +#define ZT_FLAGS 0x40 +#define DEMOMARKER 0x80 // demoend + +UINT8 demo_extradata[MAXPLAYERS]; +UINT8 demo_writerng; // 0=no, 1=yes, 2=yes but on a timeout +static ticcmd_t oldcmd[MAXPLAYERS]; + +#define METALDEATH 0x44 +#define METALSNICE 0x69 + +#define DW_END 0xFF // End of extradata block +#define DW_RNG 0xFE // Check RNG seed! + +#define DW_EXTRASTUFF 0xFE // Numbers below this are reserved for writing player slot data + +// Below consts are only used for demo extrainfo sections +#define DW_STANDING 0x00 + +// For Metal Sonic and time attack ghosts +#define GZT_XYZ 0x01 +#define GZT_MOMXY 0x02 +#define GZT_MOMZ 0x04 +#define GZT_ANGLE 0x08 +#define GZT_FRAME 0x10 // Animation frame +#define GZT_SPR2 0x20 // Player animations +#define GZT_EXTRA 0x40 +#define GZT_FOLLOW 0x80 // Followmobj + +// GZT_EXTRA flags +#define EZT_COLOR 0x001 // Changed color (Super transformation, Mario fireflowers/invulnerability, etc.) +#define EZT_FLIP 0x002 // Reversed gravity +#define EZT_SCALE 0x004 // Changed size +#define EZT_HIT 0x008 // Damaged a mobj +#define EZT_SPRITE 0x010 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) +#define EZT_KART 0x020 // SRB2Kart: Changed current held item/quantity and bumpers for battle + +// GZT_FOLLOW flags +#define FZT_SPAWNED 0x01 // just been spawned +#define FZT_SKIN 0x02 // has skin +#define FZT_LINKDRAW 0x04 // has linkdraw (combine with spawned only) +#define FZT_COLORIZED 0x08 // colorized (ditto) +#define FZT_SCALE 0x10 // different scale to object +// spare FZT slots 0x20 to 0x80 + +static mobj_t oldmetal, oldghost[MAXPLAYERS]; + +void G_SaveMetal(UINT8 **buffer) +{ + I_Assert(buffer != NULL && *buffer != NULL); + + WRITEUINT32(*buffer, metal_p - metalbuffer); +} + +void G_LoadMetal(UINT8 **buffer) +{ + I_Assert(buffer != NULL && *buffer != NULL); + + G_DoPlayMetal(); + metal_p = metalbuffer + READUINT32(*buffer); +} + +// Finds a skin with the closest stats if the expected skin doesn't exist. +static INT32 GetSkinNumClosestToStats(UINT8 kartspeed, UINT8 kartweight) +{ + INT32 i, closest_skin = 0; + UINT8 closest_stats = UINT8_MAX, stat_diff; + + for (i = 0; i < numskins; i++) + { + stat_diff = abs(skins[i].kartspeed - kartspeed) + abs(skins[i].kartweight - kartweight); + if (stat_diff < closest_stats) + { + closest_stats = stat_diff; + closest_skin = i; + } + } + + return closest_skin; +} + +static void FindClosestSkinForStats(UINT32 p, UINT8 kartspeed, UINT8 kartweight) +{ + INT32 closest_skin = GetSkinNumClosestToStats(kartspeed, kartweight); + + //CONS_Printf("Using %s instead...\n", skins[closest_skin].name); + SetPlayerSkinByNum(p, closest_skin); +} + +void G_ReadDemoExtraData(void) +{ + INT32 p, extradata, i; + char name[17]; + + if (leveltime > starttime) + { + rewind_t *rewind = CL_SaveRewindPoint(demo_p - demobuffer); + if (rewind) + { + memcpy(rewind->oldcmd, oldcmd, sizeof (oldcmd)); + memcpy(rewind->oldghost, oldghost, sizeof (oldghost)); + } + } + + memset(name, '\0', 17); + + p = READUINT8(demo_p); + + while (p < DW_EXTRASTUFF) + { + extradata = READUINT8(demo_p); + + if (extradata & DXD_RESPAWN) + { + if (players[p].mo) + { + // Is this how this should work..? + K_DoIngameRespawn(&players[p]); + } + } + if (extradata & DXD_SKIN) + { + UINT8 kartspeed, kartweight; + + // Skin + M_Memcpy(name, demo_p, 16); + demo_p += 16; + SetPlayerSkin(p, name); + + kartspeed = READUINT8(demo_p); + kartweight = READUINT8(demo_p); + + if (stricmp(skins[players[p].skin].name, name) != 0) + FindClosestSkinForStats(p, kartspeed, kartweight); + + players[p].kartspeed = kartspeed; + players[p].kartweight = kartweight; + } + if (extradata & DXD_COLOR) + { + // Color + M_Memcpy(name, demo_p, 16); + demo_p += 16; + for (i = 0; i < numskincolors; i++) + if (!stricmp(skincolors[i].name, name)) // SRB2kart + { + players[p].skincolor = i; + if (players[p].mo) + players[p].mo->color = i; + break; + } + } + if (extradata & DXD_NAME) + { + // Name + M_Memcpy(player_names[p],demo_p,16); + demo_p += 16; + } + if (extradata & DXD_FOLLOWER) + { + // Set our follower + M_Memcpy(name, demo_p, 16); + demo_p += 16; + SetPlayerFollower(p, name); + + // Follower's color + M_Memcpy(name, demo_p, 16); + demo_p += 16; + for (i = 0; i < numskincolors; i++) + if (!stricmp(skincolors[i].name, name)) // SRB2kart + { + players[p].followercolor = i; + break; + } + } + if (extradata & DXD_PLAYSTATE) + { + extradata = READUINT8(demo_p); + + switch (extradata) { + case DXD_PST_PLAYING: + players[p].pflags |= PF_WANTSTOJOIN; // fuck you + break; + + case DXD_PST_SPECTATING: + players[p].pflags &= ~PF_WANTSTOJOIN; // double-fuck you + if (!playeringame[p]) + { + CL_ClearPlayer(p); + playeringame[p] = true; + G_AddPlayer(p); + players[p].spectator = true; + } + else + { + players[p].spectator = true; + if (players[p].mo) + P_DamageMobj(players[p].mo, NULL, NULL, 1, DMG_INSTAKILL); + else + players[p].playerstate = PST_REBORN; + } + break; + + case DXD_PST_LEFT: + CL_RemovePlayer(p, 0); + break; + } + + G_ResetViews(); + + // maybe these are necessary? + K_CheckBumpers(); + P_CheckRacers(); + } + + + p = READUINT8(demo_p); + } + + while (p != DW_END) + { + UINT32 rng; + + switch (p) + { + case DW_RNG: + rng = READUINT32(demo_p); + if (P_GetRandSeed() != rng) + { + P_SetRandSeed(rng); + + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; + } + } + + p = READUINT8(demo_p); + } + + if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) + { + // end of demo data stream + G_CheckDemoStatus(); + return; + } +} + +void G_WriteDemoExtraData(void) +{ + INT32 i; + char name[16]; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (demo_extradata[i]) + { + WRITEUINT8(demo_p, i); + WRITEUINT8(demo_p, demo_extradata[i]); + + //if (demo_extradata[i] & DXD_RESPAWN) has no extra data + if (demo_extradata[i] & DXD_SKIN) + { + // Skin + memset(name, 0, 16); + strncpy(name, skins[players[i].skin].name, 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + WRITEUINT8(demo_p, skins[players[i].skin].kartspeed); + WRITEUINT8(demo_p, skins[players[i].skin].kartweight); + + } + if (demo_extradata[i] & DXD_COLOR) + { + // Color + memset(name, 0, 16); + strncpy(name, skincolors[players[i].skincolor].name, 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + } + if (demo_extradata[i] & DXD_NAME) + { + // Name + memset(name, 0, 16); + strncpy(name, player_names[i], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + } + if (demo_extradata[i] & DXD_FOLLOWER) + { + // write follower + memset(name, 0, 16); + strncpy(name, followers[players[i].followerskin].skinname, 16); + M_Memcpy(demo_p, name, 16); + demo_p += 16; + + // write follower color + memset(name, 0, 16); + strncpy(name, Followercolor_cons_t[players[i].followercolor].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match" + M_Memcpy(demo_p,name,16); + demo_p += 16; + + } + if (demo_extradata[i] & DXD_PLAYSTATE) + { + demo_writerng = 1; + if (!playeringame[i]) + WRITEUINT8(demo_p, DXD_PST_LEFT); + else if ( + players[i].spectator && + !(players[i].pflags & PF_WANTSTOJOIN) // <= fuck you specifically + ) + WRITEUINT8(demo_p, DXD_PST_SPECTATING); + else + WRITEUINT8(demo_p, DXD_PST_PLAYING); + } + } + + demo_extradata[i] = 0; + } + + // May not be necessary, but might as well play it safe... + if ((leveltime & 255) == 128) + demo_writerng = 1; + + { + static UINT8 timeout = 0; + + if (timeout) timeout--; + + if (demo_writerng == 1 || (demo_writerng == 2 && timeout == 0)) + { + demo_writerng = 0; + timeout = 16; + WRITEUINT8(demo_p, DW_RNG); + WRITEUINT32(demo_p, P_GetRandSeed()); + } + } + + WRITEUINT8(demo_p, DW_END); +} + +void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) +{ + UINT8 ziptic; + + if (!demo_p || !demo.deferstart) + return; + ziptic = READUINT8(demo_p); + + if (ziptic & ZT_FWD) + oldcmd[playernum].forwardmove = READSINT8(demo_p); + if (ziptic & ZT_TURNING) + oldcmd[playernum].turning = READINT16(demo_p); + if (ziptic & ZT_BUTTONS) + oldcmd[playernum].buttons = READUINT16(demo_p); + if (ziptic & ZT_AIMING) + oldcmd[playernum].aiming = READINT16(demo_p); + if (ziptic & ZT_LATENCY) + oldcmd[playernum].latency = READUINT8(demo_p); + if (ziptic & ZT_FLAGS) + oldcmd[playernum].latency = READUINT8(demo_p); + + G_CopyTiccmd(cmd, &oldcmd[playernum], 1); + + if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) + { + // end of demo data stream + G_CheckDemoStatus(); + return; + } +} + +void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) +{ + char ziptic = 0; + UINT8 *ziptic_p; + (void)playernum; + + if (!demo_p) + return; + ziptic_p = demo_p++; // the ziptic, written at the end of this function + + if (cmd->forwardmove != oldcmd[playernum].forwardmove) + { + WRITEUINT8(demo_p,cmd->forwardmove); + oldcmd[playernum].forwardmove = cmd->forwardmove; + ziptic |= ZT_FWD; + } + + if (cmd->turning != oldcmd[playernum].turning) + { + WRITEINT16(demo_p,cmd->turning); + oldcmd[playernum].turning = cmd->turning; + ziptic |= ZT_TURNING; + } + + if (cmd->buttons != oldcmd[playernum].buttons) + { + WRITEUINT16(demo_p,cmd->buttons); + oldcmd[playernum].buttons = cmd->buttons; + ziptic |= ZT_BUTTONS; + } + + if (cmd->aiming != oldcmd[playernum].aiming) + { + WRITEINT16(demo_p,cmd->aiming); + oldcmd[playernum].aiming = cmd->aiming; + ziptic |= ZT_AIMING; + } + + if (cmd->latency != oldcmd[playernum].latency) + { + WRITEUINT8(demo_p,cmd->latency); + oldcmd[playernum].latency = cmd->latency; + ziptic |= ZT_LATENCY; + } + + if (cmd->flags != oldcmd[playernum].flags) + { + WRITEUINT8(demo_p,cmd->flags); + oldcmd[playernum].flags = cmd->flags; + ziptic |= ZT_FLAGS; + } + + *ziptic_p = ziptic; + + // attention here for the ticcmd size! + // latest demos with mouse aiming byte in ticcmd + if (!(demoflags & DF_GHOST) && ziptic_p > demoend - 9) + { + G_CheckDemoStatus(); // no more space + return; + } +} + +void G_GhostAddFlip(INT32 playernum) +{ + if (!metalrecording && (!demo.recording || !(demoflags & DF_GHOST))) + return; + ghostext[playernum].flags |= EZT_FLIP; +} + +void G_GhostAddColor(INT32 playernum, ghostcolor_t color) +{ + if (!demo.recording || !(demoflags & DF_GHOST)) + return; + if (ghostext[playernum].lastcolor == (UINT16)color) + { + ghostext[playernum].flags &= ~EZT_COLOR; + return; + } + ghostext[playernum].flags |= EZT_COLOR; + ghostext[playernum].color = (UINT16)color; +} + +void G_GhostAddScale(INT32 playernum, fixed_t scale) +{ + if (!metalrecording && (!demo.recording || !(demoflags & DF_GHOST))) + return; + if (ghostext[playernum].lastscale == scale) + { + ghostext[playernum].flags &= ~EZT_SCALE; + return; + } + ghostext[playernum].flags |= EZT_SCALE; + ghostext[playernum].scale = scale; +} + +void G_GhostAddHit(INT32 playernum, mobj_t *victim) +{ + if (!demo.recording || !(demoflags & DF_GHOST)) + return; + ghostext[playernum].flags |= EZT_HIT; + ghostext[playernum].hits++; + ghostext[playernum].hitlist = Z_Realloc(ghostext[playernum].hitlist, ghostext[playernum].hits * sizeof(mobj_t *), PU_LEVEL, NULL); + ghostext[playernum].hitlist[ghostext[playernum].hits-1] = victim; +} + +void G_WriteAllGhostTics(void) +{ + INT32 i, counter = leveltime; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (!players[i].mo) + continue; + + counter++; + + if (counter % cv_netdemosyncquality.value != 0) // Only write 1 in this many ghost datas per tic to cut down on multiplayer replay size. + continue; + + WRITEUINT8(demo_p, i); + G_WriteGhostTic(players[i].mo, i); + } + WRITEUINT8(demo_p, 0xFF); +} + +void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) +{ + char ziptic = 0; + UINT8 *ziptic_p; + UINT32 i; + + if (!demo_p) + return; + if (!(demoflags & DF_GHOST)) + return; // No ghost data to write. + + ziptic_p = demo_p++; // the ziptic, written at the end of this function + +#define MAXMOM (0xFFFF<<8) + + // GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic. + if (abs(ghost->x-oldghost[playernum].x) > MAXMOM + || abs(ghost->y-oldghost[playernum].y) > MAXMOM + || abs(ghost->z-oldghost[playernum].z) > MAXMOM + || ((UINT8)(leveltime & 255) > 0 && (UINT8)(leveltime & 255) <= (UINT8)cv_netdemosyncquality.value)) // Hack to enable slightly nicer resyncing + { + oldghost[playernum].x = ghost->x; + oldghost[playernum].y = ghost->y; + oldghost[playernum].z = ghost->z; + ziptic |= GZT_XYZ; + WRITEFIXED(demo_p,oldghost[playernum].x); + WRITEFIXED(demo_p,oldghost[playernum].y); + WRITEFIXED(demo_p,oldghost[playernum].z); + } + else + { + // For moving normally: + fixed_t momx = ghost->x-oldghost[playernum].x; + fixed_t momy = ghost->y-oldghost[playernum].y; + + if (momx != oldghost[playernum].momx + || momy != oldghost[playernum].momy) + { + oldghost[playernum].momx = momx; + oldghost[playernum].momy = momy; + ziptic |= GZT_MOMXY; + WRITEFIXED(demo_p,momx); + WRITEFIXED(demo_p,momy); + } + + momx = ghost->z-oldghost[playernum].z; + if (momx != oldghost[playernum].momz) + { + oldghost[playernum].momz = momx; + ziptic |= GZT_MOMZ; + WRITEFIXED(demo_p,momx); + } + + // This SHOULD set oldghost.x/y/z to match ghost->x/y/z + oldghost[playernum].x += oldghost[playernum].momx; + oldghost[playernum].y += oldghost[playernum].momy; + oldghost[playernum].z +=oldghost[playernum].momz; + } + +#undef MAXMOM + + // Only store the 8 most relevant bits of angle + // because exact values aren't too easy to discern to begin with when only 8 angles have different sprites + // and it does not affect this mode of movement at all anyway. + if (ghost->player && ghost->player->drawangle>>24 != oldghost[playernum].angle) + { + oldghost[playernum].angle = ghost->player->drawangle>>24; + ziptic |= GZT_ANGLE; + WRITEUINT8(demo_p,oldghost[playernum].angle); + } + + // Store the sprite frame. + if ((ghost->frame & FF_FRAMEMASK) != oldghost[playernum].frame) + { + oldghost[playernum].frame = (ghost->frame & FF_FRAMEMASK); + ziptic |= GZT_FRAME; + WRITEUINT8(demo_p,oldghost[playernum].frame); + } + + if (ghost->sprite == SPR_PLAY + && ghost->sprite2 != oldghost[playernum].sprite2) + { + oldghost[playernum].sprite2 = ghost->sprite2; + ziptic |= GZT_SPR2; + WRITEUINT8(demo_p,oldghost[playernum].sprite2); + } + + // Check for sprite set changes + if (ghost->sprite != oldghost[playernum].sprite) + { + oldghost[playernum].sprite = ghost->sprite; + ghostext[playernum].flags |= EZT_SPRITE; + } + + if (ghostext[playernum].flags) + { + ziptic |= GZT_EXTRA; + + if (ghost->player) + { + if ( + ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] || + ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] || + ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper] + ) + { + ghostext[playernum].flags |= EZT_KART; + ghostext[playernum].kartitem = ghost->player->kartstuff[k_itemtype]; + ghostext[playernum].kartamount = ghost->player->kartstuff[k_itemamount]; + ghostext[playernum].kartbumpers = ghost->player->kartstuff[k_bumper]; + + } + } + + if (ghostext[playernum].color == ghostext[playernum].lastcolor) + ghostext[playernum].flags &= ~EZT_COLOR; + if (ghostext[playernum].scale == ghostext[playernum].lastscale) + ghostext[playernum].flags &= ~EZT_SCALE; + + WRITEUINT8(demo_p,ghostext[playernum].flags); + if (ghostext[playernum].flags & EZT_COLOR) + { + WRITEUINT16(demo_p,ghostext[playernum].color); + ghostext[playernum].lastcolor = ghostext[playernum].color; + } + if (ghostext[playernum].flags & EZT_SCALE) + { + WRITEFIXED(demo_p,ghostext[playernum].scale); + ghostext[playernum].lastscale = ghostext[playernum].scale; + } + if (ghostext[playernum].flags & EZT_HIT) + { + WRITEUINT16(demo_p,ghostext[playernum].hits); + for (i = 0; i < ghostext[playernum].hits; i++) + { + mobj_t *mo = ghostext[playernum].hitlist[i]; + //WRITEUINT32(demo_p,UINT32_MAX); // reserved for some method of determining exactly which mobj this is. (mobjnum doesn't work here.) + WRITEUINT32(demo_p,mo->type); + WRITEUINT16(demo_p,(UINT16)mo->health); + WRITEFIXED(demo_p,mo->x); + WRITEFIXED(demo_p,mo->y); + WRITEFIXED(demo_p,mo->z); + WRITEANGLE(demo_p,mo->angle); + } + Z_Free(ghostext[playernum].hitlist); + ghostext[playernum].hits = 0; + ghostext[playernum].hitlist = NULL; + } + if (ghostext[playernum].flags & EZT_SPRITE) + WRITEUINT16(demo_p,oldghost[playernum].sprite); + if (ghostext[playernum].flags & EZT_KART) + { + WRITEINT32(demo_p, ghostext[playernum].kartitem); + WRITEINT32(demo_p, ghostext[playernum].kartamount); + WRITEINT32(demo_p, ghostext[playernum].kartbumpers); + } + + ghostext[playernum].flags = 0; + } + + if (ghost->player && ghost->player->followmobj&& !(ghost->player->followmobj->sprite == SPR_NULL || (ghost->player->followmobj->drawflags & MFD_DONTDRAW) == MFD_DONTDRAW)) // bloats tails runs but what can ya do + { + fixed_t temp; + UINT8 *followtic_p = demo_p++; + UINT8 followtic = 0; + + ziptic |= GZT_FOLLOW; + + if (ghost->player->followmobj->skin) + followtic |= FZT_SKIN; + + if (!(oldghost[playernum].flags2 & MF2_AMBUSH)) + { + followtic |= FZT_SPAWNED; + WRITEINT16(demo_p,ghost->player->followmobj->info->height>>FRACBITS); + if (ghost->player->followmobj->flags2 & MF2_LINKDRAW) + followtic |= FZT_LINKDRAW; + if (ghost->player->followmobj->colorized) + followtic |= FZT_COLORIZED; + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,(UINT8)(((skin_t *)(ghost->player->followmobj->skin))-skins)); + oldghost[playernum].flags2 |= MF2_AMBUSH; + } + + if (ghost->player->followmobj->scale != ghost->scale) + { + followtic |= FZT_SCALE; + WRITEFIXED(demo_p,ghost->player->followmobj->scale); + } + + temp = ghost->player->followmobj->x-ghost->x; + WRITEFIXED(demo_p,temp); + temp = ghost->player->followmobj->y-ghost->y; + WRITEFIXED(demo_p,temp); + temp = ghost->player->followmobj->z-ghost->z; + WRITEFIXED(demo_p,temp); + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,ghost->player->followmobj->sprite2); + WRITEUINT16(demo_p,ghost->player->followmobj->sprite); + WRITEUINT8(demo_p,(ghost->player->followmobj->frame & FF_FRAMEMASK)); + WRITEUINT16(demo_p,ghost->player->followmobj->color); + + *followtic_p = followtic; + } + else + oldghost[playernum].flags2 &= ~MF2_AMBUSH; + + *ziptic_p = ziptic; + + // attention here for the ticcmd size! + // latest demos with mouse aiming byte in ticcmd + if (demo_p >= demoend - (13 + 9 + 9)) + { + G_CheckDemoStatus(); // no more space + return; + } +} + +void G_ConsAllGhostTics(void) +{ + UINT8 p = READUINT8(demo_p); + + while (p != 0xFF) + { + G_ConsGhostTic(p); + p = READUINT8(demo_p); + } + + if (*demo_p == DEMOMARKER) + { + // end of demo data stream + G_CheckDemoStatus(); + return; + } +} + +// Uses ghost data to do consistency checks on your position. +// This fixes desynchronising demos when fighting eggman. +void G_ConsGhostTic(INT32 playernum) +{ + UINT8 ziptic; + INT32 px,py,pz,gx,gy,gz; + mobj_t *testmo; + UINT32 syncleeway; + + if (!demo_p || !demo.deferstart) + return; + if (!(demoflags & DF_GHOST)) + return; // No ghost data to use. + + testmo = players[playernum].mo; + + // Grab ghost data. + ziptic = READUINT8(demo_p); + if (ziptic & GZT_XYZ) + { + oldghost[playernum].x = READFIXED(demo_p); + oldghost[playernum].y = READFIXED(demo_p); + oldghost[playernum].z = READFIXED(demo_p); + syncleeway = 0; + } + else + { + if (ziptic & GZT_MOMXY) + { + oldghost[playernum].momx = READFIXED(demo_p); + oldghost[playernum].momy = READFIXED(demo_p); + } + if (ziptic & GZT_MOMZ) + oldghost[playernum].momz = READFIXED(demo_p); + oldghost[playernum].x += oldghost[playernum].momx; + oldghost[playernum].y += oldghost[playernum].momy; + oldghost[playernum].z += oldghost[playernum].momz; + syncleeway = FRACUNIT; + } + if (ziptic & GZT_ANGLE) + demo_p++; + if (ziptic & GZT_FRAME) + demo_p++; + if (ziptic & GZT_SPR2) + demo_p++; + + if (ziptic & GZT_EXTRA) + { // But wait, there's more! + UINT8 xziptic = READUINT8(demo_p); + if (xziptic & EZT_COLOR) + demo_p += sizeof(UINT16); + if (xziptic & EZT_SCALE) + demo_p += sizeof(fixed_t); + if (xziptic & EZT_HIT) + { // Resync mob damage. + UINT16 i, count = READUINT16(demo_p); + thinker_t *th; + mobj_t *mobj; + + UINT32 type; + UINT16 health; + fixed_t x; + fixed_t y; + fixed_t z; + + for (i = 0; i < count; i++) + { + //demo_p += 4; // reserved. + type = READUINT32(demo_p); + health = READUINT16(demo_p); + x = READFIXED(demo_p); + y = READFIXED(demo_p); + z = READFIXED(demo_p); + demo_p += sizeof(angle_t); // angle, unnecessary for cons. + + mobj = NULL; + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + mobj = (mobj_t *)th; + if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) + break; + } + if (th != &thlist[THINK_MOBJ] && mobj->health != health) // Wasn't damaged?! This is desync! Fix it! + { + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; + P_DamageMobj(mobj, players[0].mo, players[0].mo, 1, DMG_NORMAL); + } + } + } + if (xziptic & EZT_SPRITE) + demo_p += sizeof(UINT16); + if (xziptic & EZT_KART) + { + ghostext[playernum].kartitem = READINT32(demo_p); + ghostext[playernum].kartamount = READINT32(demo_p); + ghostext[playernum].kartbumpers = READINT32(demo_p); + } + } + + if (ziptic & GZT_FOLLOW) + { // Even more... + UINT8 followtic = READUINT8(demo_p); + if (followtic & FZT_SPAWNED) + { + demo_p += sizeof(INT16); + if (followtic & FZT_SKIN) + demo_p++; + } + if (followtic & FZT_SCALE) + demo_p += sizeof(fixed_t); + // momx, momy and momz + demo_p += sizeof(fixed_t) * 3; + if (followtic & FZT_SKIN) + demo_p++; + demo_p += sizeof(UINT16); + demo_p++; + demo_p += sizeof(UINT16); + } + + if (testmo) + { + // Re-synchronise + px = testmo->x; + py = testmo->y; + pz = testmo->z; + gx = oldghost[playernum].x; + gy = oldghost[playernum].y; + gz = oldghost[playernum].z; + + if (abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway) + { + ghostext[playernum].desyncframes++; + + if (ghostext[playernum].desyncframes >= 2) + { + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; + + P_UnsetThingPosition(testmo); + testmo->x = oldghost[playernum].x; + testmo->y = oldghost[playernum].y; + P_SetThingPosition(testmo); + testmo->z = oldghost[playernum].z; + + if (abs(testmo->z - testmo->floorz) < 4*FRACUNIT) + testmo->z = testmo->floorz; // Sync players to the ground when they're likely supposed to be there... + + ghostext[playernum].desyncframes = 2; + } + } + else + ghostext[playernum].desyncframes = 0; + + if (players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem + || players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount + || players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers) + { + if (demosynced) + CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); + demosynced = false; + + players[playernum].kartstuff[k_itemtype] = ghostext[playernum].kartitem; + players[playernum].kartstuff[k_itemamount] = ghostext[playernum].kartamount; + players[playernum].kartstuff[k_bumper] = ghostext[playernum].kartbumpers; + } + } + + if (*demo_p == DEMOMARKER) + { + // end of demo data stream + G_CheckDemoStatus(); + return; + } +} + +void G_GhostTicker(void) +{ + demoghost *g,*p; + for(g = ghosts, p = NULL; g; g = g->next) + { + // Skip normal demo data. + UINT8 ziptic = READUINT8(g->p); + UINT8 xziptic = 0; + + while (ziptic != DW_END) // Get rid of extradata stuff + { + if (ziptic == 0) // Only support player 0 info for now + { + ziptic = READUINT8(g->p); + if (ziptic & DXD_SKIN) + g->p += 18; // We _could_ read this info, but it shouldn't change anything in record attack... + if (ziptic & DXD_COLOR) + g->p += 16; // Same tbh + if (ziptic & DXD_NAME) + g->p += 16; // yea + if (ziptic & DXD_FOLLOWER) + g->p += 32; // ok (32 because there's both the skin and the colour) + if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING) + I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this + } + else if (ziptic == DW_RNG) + g->p += 4; // RNG seed + else + I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this + + ziptic = READUINT8(g->p); + } + + if (ziptic & ZT_FWD) + g->p++; + if (ziptic & ZT_TURNING) + g->p += 2; + if (ziptic & ZT_BUTTONS) + g->p += 2; + if (ziptic & ZT_AIMING) + g->p += 2; + if (ziptic & ZT_LATENCY) + g->p += 1; + if (ziptic & ZT_FLAGS) + g->p += 1; + + // Grab ghost data. + ziptic = READUINT8(g->p); + + if (ziptic == 0xFF) + goto skippedghosttic; // Didn't write ghost info this frame + else if (ziptic != 0) + I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this + ziptic = READUINT8(g->p); + + if (ziptic & GZT_XYZ) + { + g->oldmo.x = READFIXED(g->p); + g->oldmo.y = READFIXED(g->p); + g->oldmo.z = READFIXED(g->p); + } + else + { + if (ziptic & GZT_MOMXY) + { + g->oldmo.momx = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p); + g->oldmo.momy = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p); + } + if (ziptic & GZT_MOMZ) + g->oldmo.momz = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p); + g->oldmo.x += g->oldmo.momx; + g->oldmo.y += g->oldmo.momy; + g->oldmo.z += g->oldmo.momz; + } + if (ziptic & GZT_ANGLE) + g->mo->angle = READUINT8(g->p)<<24; + if (ziptic & GZT_FRAME) + g->oldmo.frame = READUINT8(g->p); + if (ziptic & GZT_SPR2) + g->oldmo.sprite2 = READUINT8(g->p); + + // Update ghost + P_UnsetThingPosition(g->mo); + g->mo->x = g->oldmo.x; + g->mo->y = g->oldmo.y; + g->mo->z = g->oldmo.z; + P_SetThingPosition(g->mo); + g->mo->angle = g->oldmo.angle; + g->mo->frame = g->oldmo.frame | tr_trans30<fadein) + { + g->mo->frame += (((--g->fadein)/6)<fadein is bad, and it's only set once, so... + g->mo->drawflags &= ~MFD_DONTDRAW; + } + g->mo->sprite2 = g->oldmo.sprite2; + + if (ziptic & GZT_EXTRA) + { // But wait, there's more! + xziptic = READUINT8(g->p); + if (xziptic & EZT_COLOR) + { + g->color = READUINT16(g->p); + switch(g->color) + { + default: + case GHC_RETURNSKIN: + g->mo->skin = g->oldmo.skin; + /* FALLTHRU */ + case GHC_NORMAL: // Go back to skin color + g->mo->color = g->oldmo.color; + break; + // Handled below + case GHC_SUPER: + case GHC_INVINCIBLE: + break; + case GHC_FIREFLOWER: // Fireflower + g->mo->color = SKINCOLOR_WHITE; + break; + } + } + if (xziptic & EZT_FLIP) + g->mo->eflags ^= MFE_VERTICALFLIP; + if (xziptic & EZT_SCALE) + { + g->mo->destscale = READFIXED(g->p); + if (g->mo->destscale != g->mo->scale) + P_SetScale(g->mo, g->mo->destscale); + } + if (xziptic & EZT_HIT) + { // Spawn hit poofs for killing things! + UINT16 i, count = READUINT16(g->p), health; + UINT32 type; + fixed_t x,y,z; + angle_t angle; + mobj_t *poof; + for (i = 0; i < count; i++) + { + //g->p += 4; // reserved + type = READUINT32(g->p); + health = READUINT16(g->p); + x = READFIXED(g->p); + y = READFIXED(g->p); + z = READFIXED(g->p); + angle = READANGLE(g->p); + if (!(mobjinfo[type].flags & MF_SHOOTABLE) + || !(mobjinfo[type].flags & (MF_ENEMY|MF_MONITOR)) + || health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad. + continue; + poof = P_SpawnMobj(x, y, z, MT_GHOST); + poof->angle = angle; + poof->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... + poof->health = 0; + P_SetMobjStateNF(poof, S_XPLD1); + } + } + if (xziptic & EZT_SPRITE) + g->mo->sprite = READUINT16(g->p); + if (xziptic & EZT_KART) + g->p += 12; // kartitem, kartamount, kartbumpers + } + + if (READUINT8(g->p) != 0xFF) // Make sure there isn't other ghost data here. + I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this + +skippedghosttic: + // Tick ghost colors (Super and Mario Invincibility flashing) + switch(g->color) + { + case GHC_SUPER: // Super (P_DoSuperStuff) + if (g->mo->skin) + { + skin_t *skin = (skin_t *)g->mo->skin; + g->mo->color = skin->supercolor; + } + else + g->mo->color = SKINCOLOR_SUPERGOLD1; + g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4); + break; + case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer) + g->mo->color = (UINT16)(SKINCOLOR_RUBY + (leveltime % (FIRSTSUPERCOLOR - SKINCOLOR_RUBY))); // Passes through all saturated colours + break; + default: + break; + } + +#define follow g->mo->tracer + if (ziptic & GZT_FOLLOW) + { // Even more... + UINT8 followtic = READUINT8(g->p); + fixed_t temp; + if (followtic & FZT_SPAWNED) + { + if (follow) + P_RemoveMobj(follow); + P_SetTarget(&follow, P_SpawnMobjFromMobj(g->mo, 0, 0, 0, MT_GHOST)); + P_SetTarget(&follow->tracer, g->mo); + follow->tics = -1; + temp = READINT16(g->p)<height = FixedMul(follow->scale, temp); + + if (followtic & FZT_LINKDRAW) + follow->flags2 |= MF2_LINKDRAW; + + if (followtic & FZT_COLORIZED) + follow->colorized = true; + + if (followtic & FZT_SKIN) + follow->skin = &skins[READUINT8(g->p)]; + } + if (follow) + { + if (followtic & FZT_SCALE) + follow->destscale = READFIXED(g->p); + else + follow->destscale = g->mo->destscale; + if (follow->destscale != follow->scale) + P_SetScale(follow, follow->destscale); + + P_UnsetThingPosition(follow); + temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p); + follow->x = g->mo->x + temp; + temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p); + follow->y = g->mo->y + temp; + temp = (g->version < 0x000e) ? READINT16(g->p)<<8 : READFIXED(g->p); + follow->z = g->mo->z + temp; + P_SetThingPosition(follow); + if (followtic & FZT_SKIN) + follow->sprite2 = READUINT8(g->p); + else + follow->sprite2 = 0; + follow->sprite = READUINT16(g->p); + follow->frame = (READUINT8(g->p)) | (g->mo->frame & FF_TRANSMASK); + follow->angle = g->mo->angle; + follow->color = READUINT16(g->p); + + if (!(followtic & FZT_SPAWNED)) + { + if (xziptic & EZT_FLIP) + { + follow->flags2 ^= MF2_OBJECTFLIP; + follow->eflags ^= MFE_VERTICALFLIP; + } + } + } + } + else if (follow) + { + P_RemoveMobj(follow); + P_SetTarget(&follow, NULL); + } + // Demo ends after ghost data. + if (*g->p == DEMOMARKER) + { + g->mo->momx = g->mo->momy = g->mo->momz = 0; +#if 1 // freeze frame (maybe more useful for time attackers) + g->mo->colorized = true; + if (follow) + follow->colorized = true; +#else // dissapearing act + g->mo->fuse = TICRATE; + if (follow) + follow->fuse = TICRATE; +#endif + if (p) + p->next = g->next; + else + ghosts = g->next; + Z_Free(g); + continue; + } + p = g; +#undef follow + } +} + +// Demo rewinding functions +typedef struct rewindinfo_s { + tic_t leveltime; + + struct { + boolean ingame; + player_t player; + mobj_t mobj; + } playerinfo[MAXPLAYERS]; + + struct rewindinfo_s *prev; +} rewindinfo_t; + +static tic_t currentrewindnum; +static rewindinfo_t *rewindhead = NULL; // Reverse chronological order + +void G_InitDemoRewind(void) +{ + CL_ClearRewinds(); + + while (rewindhead) + { + rewindinfo_t *p = rewindhead->prev; + Z_Free(rewindhead); + rewindhead = p; + } + + currentrewindnum = 0; +} + +void G_StoreRewindInfo(void) +{ + static UINT8 timetolog = 8; + rewindinfo_t *info; + size_t i; + + if (timetolog-- > 0) + return; + timetolog = 8; + + info = Z_Calloc(sizeof(rewindinfo_t), PU_STATIC, NULL); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + { + info->playerinfo[i].ingame = false; + continue; + } + + info->playerinfo[i].ingame = true; + memcpy(&info->playerinfo[i].player, &players[i], sizeof(player_t)); + if (players[i].mo) + memcpy(&info->playerinfo[i].mobj, players[i].mo, sizeof(mobj_t)); + } + + info->leveltime = leveltime; + info->prev = rewindhead; + rewindhead = info; +} + +void G_PreviewRewind(tic_t previewtime) +{ + SINT8 i; + size_t j; + fixed_t tweenvalue = 0; + rewindinfo_t *info = rewindhead, *next_info = rewindhead; + + if (!info) + return; + + while (info->leveltime > previewtime && info->prev) + { + next_info = info; + info = info->prev; + } + if (info != next_info) + tweenvalue = FixedDiv(previewtime - info->leveltime, next_info->leveltime - info->leveltime); + + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + { + if (info->playerinfo[i].player.mo) + { + //@TODO spawn temp object to act as a player display + } + + continue; + } + + if (!info->playerinfo[i].ingame || !info->playerinfo[i].player.mo) + { + if (players[i].mo) + players[i].mo->drawflags |= MFD_DONTDRAW; + + continue; + } + + if (!players[i].mo) + continue; //@TODO spawn temp object to act as a player display + + players[i].mo->drawflags &= ~MFD_DONTDRAW; + + P_UnsetThingPosition(players[i].mo); +#define TWEEN(pr) info->playerinfo[i].mobj.pr + FixedMul((INT32) (next_info->playerinfo[i].mobj.pr - info->playerinfo[i].mobj.pr), tweenvalue) + players[i].mo->x = TWEEN(x); + players[i].mo->y = TWEEN(y); + players[i].mo->z = TWEEN(z); + players[i].mo->angle = TWEEN(angle); +#undef TWEEN + P_SetThingPosition(players[i].mo); + + players[i].drawangle = info->playerinfo[i].player.drawangle + FixedMul((INT32) (next_info->playerinfo[i].player.drawangle - info->playerinfo[i].player.drawangle), tweenvalue); + + players[i].mo->sprite = info->playerinfo[i].mobj.sprite; + players[i].mo->frame = info->playerinfo[i].mobj.frame; + + players[i].realtime = info->playerinfo[i].player.realtime; + for (j = 0; j < NUMKARTSTUFF; j++) + players[i].kartstuff[j] = info->playerinfo[i].player.kartstuff[j]; + } + + for (i = splitscreen; i >= 0; i--) + P_ResetCamera(&players[displayplayers[i]], &camera[i]); +} + +void G_ConfirmRewind(tic_t rewindtime) +{ + SINT8 i; + tic_t j; + boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled; + + INT32 olddp1 = displayplayers[0], olddp2 = displayplayers[1], olddp3 = displayplayers[2], olddp4 = displayplayers[3]; + UINT8 oldss = splitscreen; + + menuactive = false; // Prevent loops + + CV_StealthSetValue(&cv_renderview, 0); + + if (rewindtime <= starttime) + { + demo.rewinding = false; + G_DoPlayDemo(NULL); // Restart the current demo + } + else + { + rewind_t *rewind; + sound_disabled = true; // Prevent sound spam + demo.rewinding = true; + + rewind = CL_RewindToTime(rewindtime); + + if (rewind) + { + demo_p = demobuffer + rewind->demopos; + memcpy(oldcmd, rewind->oldcmd, sizeof (oldcmd)); + memcpy(oldghost, rewind->oldghost, sizeof (oldghost)); + paused = false; + } + else + { + demo.rewinding = true; + G_DoPlayDemo(NULL); // Restart the current demo + } + } + + for (j = 0; j < rewindtime && leveltime < rewindtime; j++) + { + G_Ticker((j % NEWTICRATERATIO) == 0); + } + + demo.rewinding = false; + menuactive = oldmenuactive; // Bring the menu back up + sound_disabled = oldsounddisabled; // Re-enable SFX + + wipegamestate = gamestate; // No fading back in! + + COM_BufInsertText("renderview on\n"); + + if (demo.freecam) + return; // don't touch from there + + splitscreen = oldss; + displayplayers[0] = olddp1; + displayplayers[1] = olddp2; + displayplayers[2] = olddp3; + displayplayers[3] = olddp4; + R_ExecuteSetViewSize(); + G_ResetViews(); + + for (i = splitscreen; i >= 0; i--) + P_ResetCamera(&players[displayplayers[i]], &camera[i]); +} + +void G_ReadMetalTic(mobj_t *metal) +{ + UINT8 ziptic; + UINT8 xziptic = 0; + + if (!metal_p) + return; + + if (!metal->health) + { + G_StopMetalDemo(); + return; + } + + switch (*metal_p) + { + case METALSNICE: + break; + case METALDEATH: + if (metal->tracer) + P_RemoveMobj(metal->tracer); + P_KillMobj(metal, NULL, NULL, DMG_NORMAL); + /* FALLTHRU */ + case DEMOMARKER: + default: + // end of demo data stream + G_StopMetalDemo(); + return; + } + metal_p++; + + ziptic = READUINT8(metal_p); + + // Read changes from the tic + if (ziptic & GZT_XYZ) + { + // make sure the values are read in the right order + oldmetal.x = READFIXED(metal_p); + oldmetal.y = READFIXED(metal_p); + oldmetal.z = READFIXED(metal_p); + P_TeleportMove(metal, oldmetal.x, oldmetal.y, oldmetal.z); + oldmetal.x = metal->x; + oldmetal.y = metal->y; + oldmetal.z = metal->z; + } + else + { + if (ziptic & GZT_MOMXY) + { + oldmetal.momx = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p); + oldmetal.momy = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p); + } + if (ziptic & GZT_MOMZ) + oldmetal.momz = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p); + oldmetal.x += oldmetal.momx; + oldmetal.y += oldmetal.momy; + oldmetal.z += oldmetal.momz; + } + if (ziptic & GZT_ANGLE) + metal->angle = READUINT8(metal_p)<<24; + if (ziptic & GZT_FRAME) + oldmetal.frame = READUINT32(metal_p); + if (ziptic & GZT_SPR2) + oldmetal.sprite2 = READUINT8(metal_p); + + // Set movement, position, and angle + // oldmetal contains where you're supposed to be. + metal->momx = oldmetal.momx; + metal->momy = oldmetal.momy; + metal->momz = oldmetal.momz; + P_UnsetThingPosition(metal); + metal->x = oldmetal.x; + metal->y = oldmetal.y; + metal->z = oldmetal.z; + P_SetThingPosition(metal); + metal->frame = oldmetal.frame; + metal->sprite2 = oldmetal.sprite2; + + if (ziptic & GZT_EXTRA) + { // But wait, there's more! + xziptic = READUINT8(metal_p); + if (xziptic & EZT_FLIP) + { + metal->eflags ^= MFE_VERTICALFLIP; + metal->flags2 ^= MF2_OBJECTFLIP; + } + if (xziptic & EZT_SCALE) + { + metal->destscale = READFIXED(metal_p); + if (metal->destscale != metal->scale) + P_SetScale(metal, metal->destscale); + } + if (xziptic & EZT_SPRITE) + metal->sprite = READUINT16(metal_p); + } + +#define follow metal->tracer + if (ziptic & GZT_FOLLOW) + { // Even more... + UINT8 followtic = READUINT8(metal_p); + fixed_t temp; + if (followtic & FZT_SPAWNED) + { + if (follow) + P_RemoveMobj(follow); + P_SetTarget(&follow, P_SpawnMobjFromMobj(metal, 0, 0, 0, MT_GHOST)); + P_SetTarget(&follow->tracer, metal); + follow->tics = -1; + temp = READINT16(metal_p)<height = FixedMul(follow->scale, temp); + + if (followtic & FZT_LINKDRAW) + follow->flags2 |= MF2_LINKDRAW; + + if (followtic & FZT_COLORIZED) + follow->colorized = true; + + if (followtic & FZT_SKIN) + follow->skin = &skins[READUINT8(metal_p)]; + } + if (follow) + { + if (followtic & FZT_SCALE) + follow->destscale = READFIXED(metal_p); + else + follow->destscale = metal->destscale; + if (follow->destscale != follow->scale) + P_SetScale(follow, follow->destscale); + + P_UnsetThingPosition(follow); + temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p); + follow->x = metal->x + temp; + temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p); + follow->y = metal->y + temp; + temp = (metalversion < 0x000e) ? READINT16(metal_p)<<8 : READFIXED(metal_p); + follow->z = metal->z + temp; + P_SetThingPosition(follow); + if (followtic & FZT_SKIN) + follow->sprite2 = READUINT8(metal_p); + else + follow->sprite2 = 0; + follow->sprite = READUINT16(metal_p); + follow->frame = READUINT32(metal_p); // NOT & FF_FRAMEMASK here, so 32 bits + follow->angle = metal->angle; + follow->color = READUINT16(metal_p); + + if (!(followtic & FZT_SPAWNED)) + { + if (xziptic & EZT_FLIP) + { + follow->flags2 ^= MF2_OBJECTFLIP; + follow->eflags ^= MFE_VERTICALFLIP; + } + } + } + } + else if (follow) + { + P_RemoveMobj(follow); + P_SetTarget(&follow, NULL); + } +#undef follow +} + +void G_WriteMetalTic(mobj_t *metal) +{ + UINT8 ziptic = 0; + UINT8 *ziptic_p; + + if (!demo_p) // demo_p will be NULL until the race start linedef executor is activated! + return; + + WRITEUINT8(demo_p, METALSNICE); + ziptic_p = demo_p++; // the ziptic, written at the end of this function + + #define MAXMOM (0xFFFF<<8) + + // GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic. + if (abs(metal->x-oldmetal.x) > MAXMOM + || abs(metal->y-oldmetal.y) > MAXMOM + || abs(metal->z-oldmetal.z) > MAXMOM) + { + oldmetal.x = metal->x; + oldmetal.y = metal->y; + oldmetal.z = metal->z; + ziptic |= GZT_XYZ; + WRITEFIXED(demo_p,oldmetal.x); + WRITEFIXED(demo_p,oldmetal.y); + WRITEFIXED(demo_p,oldmetal.z); + } + else + { + // For moving normally: + // Store movement as a fixed value + fixed_t momx = metal->x-oldmetal.x; + fixed_t momy = metal->y-oldmetal.y; + if (momx != oldmetal.momx + || momy != oldmetal.momy) + { + oldmetal.momx = momx; + oldmetal.momy = momy; + ziptic |= GZT_MOMXY; + WRITEFIXED(demo_p,momx); + WRITEFIXED(demo_p,momy); + } + momx = metal->z-oldmetal.z; + if (momx != oldmetal.momz) + { + oldmetal.momz = momx; + ziptic |= GZT_MOMZ; + WRITEFIXED(demo_p,momx); + } + + // This SHOULD set oldmetal.x/y/z to match metal->x/y/z + oldmetal.x += oldmetal.momx; + oldmetal.y += oldmetal.momy; + oldmetal.z += oldmetal.momz; + } + + #undef MAXMOM + + // Only store the 8 most relevant bits of angle + // because exact values aren't too easy to discern to begin with when only 8 angles have different sprites + // and it does not affect movement at all anyway. + if (metal->player && metal->player->drawangle>>24 != oldmetal.angle) + { + oldmetal.angle = metal->player->drawangle>>24; + ziptic |= GZT_ANGLE; + WRITEUINT8(demo_p,oldmetal.angle); + } + + // Store the sprite frame. + if ((metal->frame & FF_FRAMEMASK) != oldmetal.frame) + { + oldmetal.frame = metal->frame; // NOT & FF_FRAMEMASK here, so 32 bits + ziptic |= GZT_FRAME; + WRITEUINT32(demo_p,oldmetal.frame); + } + + if (metal->sprite == SPR_PLAY + && metal->sprite2 != oldmetal.sprite2) + { + oldmetal.sprite2 = metal->sprite2; + ziptic |= GZT_SPR2; + WRITEUINT8(demo_p,oldmetal.sprite2); + } + + // Check for sprite set changes + if (metal->sprite != oldmetal.sprite) + { + oldmetal.sprite = metal->sprite; + ghostext[0].flags |= EZT_SPRITE; + } + + if (ghostext[0].flags & ~(EZT_COLOR|EZT_HIT)) // these two aren't handled by metal ever + { + ziptic |= GZT_EXTRA; + + if (ghostext[0].scale == ghostext[0].lastscale) + ghostext[0].flags &= ~EZT_SCALE; + + WRITEUINT8(demo_p,ghostext[0].flags); + if (ghostext[0].flags & EZT_SCALE) + { + WRITEFIXED(demo_p,ghostext[0].scale); + ghostext[0].lastscale = ghostext[0].scale; + } + if (ghostext[0].flags & EZT_SPRITE) + WRITEUINT16(demo_p,oldmetal.sprite); + ghostext[0].flags = 0; + } + + if (metal->player && metal->player->followmobj && !(metal->player->followmobj->sprite == SPR_NULL || (metal->player->followmobj->drawflags & MFD_DONTDRAW) == MFD_DONTDRAW)) + { + fixed_t temp; + UINT8 *followtic_p = demo_p++; + UINT8 followtic = 0; + + ziptic |= GZT_FOLLOW; + + if (metal->player->followmobj->skin) + followtic |= FZT_SKIN; + + if (!(oldmetal.flags2 & MF2_AMBUSH)) + { + followtic |= FZT_SPAWNED; + WRITEINT16(demo_p,metal->player->followmobj->info->height>>FRACBITS); + if (metal->player->followmobj->flags2 & MF2_LINKDRAW) + followtic |= FZT_LINKDRAW; + if (metal->player->followmobj->colorized) + followtic |= FZT_COLORIZED; + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,(UINT8)(((skin_t *)(metal->player->followmobj->skin))-skins)); + oldmetal.flags2 |= MF2_AMBUSH; + } + + if (metal->player->followmobj->scale != metal->scale) + { + followtic |= FZT_SCALE; + WRITEFIXED(demo_p,metal->player->followmobj->scale); + } + + temp = metal->player->followmobj->x-metal->x; + WRITEFIXED(demo_p,temp); + temp = metal->player->followmobj->y-metal->y; + WRITEFIXED(demo_p,temp); + temp = metal->player->followmobj->z-metal->z; + WRITEFIXED(demo_p,temp); + if (followtic & FZT_SKIN) + WRITEUINT8(demo_p,metal->player->followmobj->sprite2); + WRITEUINT16(demo_p,metal->player->followmobj->sprite); + WRITEUINT32(demo_p,metal->player->followmobj->frame); // NOT & FF_FRAMEMASK here, so 32 bits + WRITEUINT16(demo_p,metal->player->followmobj->color); + + *followtic_p = followtic; + } + else + oldmetal.flags2 &= ~MF2_AMBUSH; + + *ziptic_p = ziptic; + + // attention here for the ticcmd size! + // latest demos with mouse aiming byte in ticcmd + if (demo_p >= demoend - 32) + { + G_StopMetalRecording(false); // no more space + return; + } +} + +// +// G_RecordDemo +// +void G_RecordDemo(const char *name) +{ + INT32 maxsize; + + strcpy(demoname, name); + strcat(demoname, ".lmp"); + //@TODO make a maxdemosize cvar + maxsize = 1024*1024*2; + if (M_CheckParm("-maxdemo") && M_IsNextParm()) + maxsize = atoi(M_GetNextParm()) * 1024; +// if (demobuffer) +// free(demobuffer); + demo_p = NULL; + demobuffer = malloc(maxsize); + demoend = demobuffer + maxsize; + + demo.recording = true; +} + +void G_RecordMetal(void) +{ + INT32 maxsize; + maxsize = 1024*1024; + if (M_CheckParm("-maxdemo") && M_IsNextParm()) + maxsize = atoi(M_GetNextParm()) * 1024; + demo_p = NULL; + demobuffer = malloc(maxsize); + demoend = demobuffer + maxsize; + metalrecording = true; +} + +void G_BeginRecording(void) +{ + UINT8 i, p; + char name[MAXCOLORNAME+1]; + player_t *player = &players[consoleplayer]; + + char *filename; + UINT8 totalfiles; + UINT8 *m; + + if (demo_p) + return; + memset(name,0,sizeof(name)); + + demo_p = demobuffer; + demoflags = DF_GHOST|(multiplayer ? DF_MULTIPLAYER : (modeattacking<important) + { + nameonly(( filename = va("%s", wadfiles[i]->filename) )); + WRITESTRINGN(demo_p, filename, 64); + WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); + + totalfiles++; + } + + WRITEUINT8(m, totalfiles); + + switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) + { + case ATTACKING_NONE: // 0 + break; + case ATTACKING_TIME: // 1 + demotime_p = demo_p; + WRITEUINT32(demo_p,UINT32_MAX); // time + WRITEUINT32(demo_p,UINT32_MAX); // lap + break; + case ATTACKING_CAPSULES: // 2 + demotime_p = demo_p; + WRITEUINT32(demo_p,UINT32_MAX); // time + break; + default: // 3 + break; + } + + WRITEUINT32(demo_p,P_GetInitSeed()); + + // Reserved for extrainfo location from start of file + demoinfo_p = demo_p; + WRITEUINT32(demo_p, 0); + + // Save netvar data + CV_SaveDemoVars(&demo_p); + + // Now store some info for each in-game player + + // Lat' 12/05/19: Do note that for the first game you load, everything that gets saved here is total garbage; + // The name will always be Player , the skin sonic, the color None and the follower 0. This is only correct on subsequent games. + // In the case of said first game, the skin and the likes are updated with Got_NameAndColor, which are then saved in extradata for the demo with DXD_SKIN in r_things.c for instance. + + + for (p = 0; p < MAXPLAYERS; p++) { + if (playeringame[p]) { + player = &players[p]; + + WRITEUINT8(demo_p, p | (player->spectator ? DEMO_SPECTATOR : 0)); + + // Name + memset(name, 0, 16); + strncpy(name, player_names[p], 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Skin + memset(name, 0, 16); + strncpy(name, skins[player->skin].name, 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Color + memset(name, 0, 16); + strncpy(name, skincolors[player->skincolor].name, 16); + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Save follower's skin name + // PS: We must check for 'follower' to determine if the followerskin is valid. It's going to be 0 if we don't have a follower, but 0 is also absolutely a valid follower! + // Doesn't really matter if the follower mobj is valid so long as it exists in a way or another. + + memset(name, 0, 16); + if (player->follower) + strncpy(name, followers[player->followerskin].skinname, 16); + else + strncpy(name, "None", 16); // Say we don't have one, then. + + M_Memcpy(demo_p,name,16); + demo_p += 16; + + // Save follower's colour + memset(name, 0, 16); + strncpy(name, Followercolor_cons_t[player->followercolor].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match" + M_Memcpy(demo_p, name, 16); + demo_p += 16; + + // Score, since Kart uses this to determine where you start on the map + WRITEUINT32(demo_p, player->score); + + // Power Levels + WRITEUINT16(demo_p, clientpowerlevels[p][gametype == GT_BATTLE ? PWRLV_BATTLE : PWRLV_RACE]); + + // Kart speed and weight + WRITEUINT8(demo_p, skins[player->skin].kartspeed); + WRITEUINT8(demo_p, skins[player->skin].kartweight); + + // And mobjtype_t is best with UINT32 too... + WRITEUINT32(demo_p, player->followitem); + } + } + + WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing + + // player lua vars, always saved even if empty + LUA_Archive(&demo_p); + + WRITEUINT32(demo_p,P_GetInitSeed()); + + memset(&oldcmd,0,sizeof(oldcmd)); + memset(&oldghost,0,sizeof(oldghost)); + memset(&ghostext,0,sizeof(ghostext)); + + for (i = 0; i < MAXPLAYERS; i++) + { + ghostext[i].lastcolor = ghostext[i].color = GHC_NORMAL; + ghostext[i].lastscale = ghostext[i].scale = FRACUNIT; + + if (players[i].mo) + { + oldghost[i].x = players[i].mo->x; + oldghost[i].y = players[i].mo->y; + oldghost[i].z = players[i].mo->z; + oldghost[i].angle = players[i].mo->angle; + + // preticker started us gravity flipped + if (players[i].mo->eflags & MFE_VERTICALFLIP) + ghostext[i].flags |= EZT_FLIP; + } + } +} + +void G_BeginMetal(void) +{ + mobj_t *mo = players[consoleplayer].mo; + +#if 0 + if (demo_p) + return; +#endif + + demo_p = demobuffer; + + // Write header. + M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12; + WRITEUINT8(demo_p,VERSION); + WRITEUINT8(demo_p,SUBVERSION); + WRITEUINT16(demo_p,DEMOVERSION); + + // demo checksum + demo_p += 16; + + M_Memcpy(demo_p, "METL", 4); demo_p += 4; + + memset(&ghostext,0,sizeof(ghostext)); + ghostext[0].lastscale = ghostext[0].scale = FRACUNIT; + + // Set up our memory. + memset(&oldmetal,0,sizeof(oldmetal)); + oldmetal.x = mo->x; + oldmetal.y = mo->y; + oldmetal.z = mo->z; + oldmetal.angle = mo->angle>>24; +} + +void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT16 color, UINT32 val) +{ + char temp[16]; + + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) + { + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + *(UINT32 *)demoinfo_p = demo_p - demobuffer; + } + + WRITEUINT8(demo_p, DW_STANDING); + WRITEUINT8(demo_p, ranking); + + // Name + memset(temp, 0, 16); + strncpy(temp, name, 16); + M_Memcpy(demo_p,temp,16); + demo_p += 16; + + // Skin + memset(temp, 0, 16); + strncpy(temp, skins[skinnum].name, 16); + M_Memcpy(demo_p,temp,16); + demo_p += 16; + + // Color + memset(temp, 0, 16); + strncpy(temp, skincolors[color].name, 16); + M_Memcpy(demo_p,temp,16); + demo_p += 16; + + // Score/time/whatever + WRITEUINT32(demo_p, val); +} + +void G_SetDemoTime(UINT32 ptime, UINT32 plap) +{ + if (!demo.recording || !demotime_p) + return; + if (demoflags & DF_TIMEATTACK) + { + WRITEUINT32(demotime_p, ptime); + WRITEUINT32(demotime_p, plap); + demotime_p = NULL; + } + else if (demoflags & DF_BREAKTHECAPSULES) + { + WRITEUINT32(demotime_p, ptime); + (void)plap; + demotime_p = NULL; + } +} + +static void G_LoadDemoExtraFiles(UINT8 **pp) +{ + UINT8 totalfiles; + char filename[MAX_WADPATH]; + UINT8 md5sum[16]; + filestatus_t ncs; + boolean toomany = false; + boolean alreadyloaded; + UINT8 i, j; + + totalfiles = READUINT8((*pp)); + for (i = 0; i < totalfiles; ++i) + { + if (toomany) + SKIPSTRING((*pp)); + else + { + strlcpy(filename, (char *)(*pp), sizeof filename); + SKIPSTRING((*pp)); + } + READMEM((*pp), md5sum, 16); + + if (!toomany) + { + alreadyloaded = false; + + for (j = 0; j < numwadfiles; ++j) + { + if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) + { + alreadyloaded = true; + break; + } + } + + if (alreadyloaded) + continue; + + if (numwadfiles >= MAX_WADFILES) + toomany = true; + else + ncs = findfile(filename, md5sum, false); + + if (toomany) + { + CONS_Alert(CONS_WARNING, M_GetText("Too many files loaded to add anymore for demo playback\n")); + if (!CON_Ready()) + M_StartMessage(M_GetText("There are too many files loaded to add this demo's addons.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); + } + else if (ncs != FS_FOUND) + { + if (ncs == FS_NOTFOUND) + CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename); + else if (ncs == FS_MD5SUMBAD) + CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename); + else + CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename); + + if (!CON_Ready()) + M_StartMessage(M_GetText("There were errors trying to add this demo's addons. Check the console for more information.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); + } + else + { + P_AddWadFile(filename); + } + } + } +} + +static void G_SkipDemoExtraFiles(UINT8 **pp) +{ + UINT8 totalfiles; + UINT8 i; + + totalfiles = READUINT8((*pp)); + for (i = 0; i < totalfiles; ++i) + { + SKIPSTRING((*pp));// file name + (*pp) += 16;// md5 + } +} + +// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's. +// Enabling quick prevents filesystem checks to see if needed files are available to load. +static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) +{ + UINT8 totalfiles, filesloaded, nmusfilecount; + char filename[MAX_WADPATH]; + UINT8 md5sum[16]; + boolean toomany = false; + boolean alreadyloaded; + UINT8 i, j; + UINT8 error = 0; + + totalfiles = READUINT8((*pp)); + filesloaded = 0; + for (i = 0; i < totalfiles; ++i) + { + if (toomany) + SKIPSTRING((*pp)); + else + { + strlcpy(filename, (char *)(*pp), sizeof filename); + SKIPSTRING((*pp)); + } + READMEM((*pp), md5sum, 16); + + if (!toomany) + { + alreadyloaded = false; + nmusfilecount = 0; + + for (j = 0; j < numwadfiles; ++j) + { + if (wadfiles[j]->important && j > mainwads) + nmusfilecount++; + else + continue; + + if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) + { + alreadyloaded = true; + + if (i != nmusfilecount-1 && error < DFILE_ERROR_OUTOFORDER) + error |= DFILE_ERROR_OUTOFORDER; + + break; + } + } + + if (alreadyloaded) + { + filesloaded++; + continue; + } + + if (numwadfiles >= MAX_WADFILES) + error = DFILE_ERROR_CANNOTLOAD; + else if (!quick && findfile(filename, md5sum, false) != FS_FOUND) + error = DFILE_ERROR_CANNOTLOAD; + else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER) + error |= DFILE_ERROR_NOTLOADED; + } else + error = DFILE_ERROR_CANNOTLOAD; + } + + // Get final file count + nmusfilecount = 0; + + for (j = 0; j < numwadfiles; ++j) + if (wadfiles[j]->important && j > mainwads) + nmusfilecount++; + + if (!error && filesloaded < nmusfilecount) + error = DFILE_ERROR_EXTRAFILES; + + return error; +} + +// Returns bitfield: +// 1 == new demo has lower time +// 2 == new demo has higher score +// 4 == new demo has higher rings +UINT8 G_CmpDemoTime(char *oldname, char *newname) +{ + UINT8 *buffer,*p; + UINT8 flags; + UINT32 oldtime, newtime, oldlap, newlap; + UINT16 oldversion; + size_t bufsize ATTRUNUSED; + UINT8 c; + UINT16 s ATTRUNUSED; + UINT8 aflags = 0; + boolean uselaps = false; + + // load the new file + FIL_DefaultExtension(newname, ".lmp"); + bufsize = FIL_ReadFile(newname, &buffer); + I_Assert(bufsize != 0); + p = buffer; + + // read demo header + I_Assert(!memcmp(p, DEMOHEADER, 12)); + p += 12; // DEMOHEADER + c = READUINT8(p); // VERSION + I_Assert(c == VERSION); + c = READUINT8(p); // SUBVERSION + I_Assert(c == SUBVERSION); + s = READUINT16(p); + I_Assert(s == DEMOVERSION); + p += 64; // full demo title + p += 16; // demo checksum + I_Assert(!memcmp(p, "PLAY", 4)); + p += 4; // PLAY + p += 2; // gamemap + p += 16; // map md5 + flags = READUINT8(p); // demoflags + p++; // gametype + G_SkipDemoExtraFiles(&p); + + aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES); + I_Assert(aflags); + + if (flags & DF_TIMEATTACK) + uselaps = true; // get around uninitalized error + + newtime = READUINT32(p); + if (uselaps) + newlap = READUINT32(p); + else + newlap = UINT32_MAX; + + Z_Free(buffer); + + // load old file + FIL_DefaultExtension(oldname, ".lmp"); + if (!FIL_ReadFile(oldname, &buffer)) + { + CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), oldname); + return UINT8_MAX; + } + p = buffer; + + // read demo header + if (memcmp(p, DEMOHEADER, 12)) + { + CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); + Z_Free(buffer); + return UINT8_MAX; + } p += 12; // DEMOHEADER + p++; // VERSION + p++; // SUBVERSION + oldversion = READUINT16(p); + switch(oldversion) // demoversion + { + case DEMOVERSION: // latest always supported + break; + // too old, cannot support. + default: + CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); + Z_Free(buffer); + return UINT8_MAX; + } + p += 64; // full demo title + p += 16; // demo checksum + if (memcmp(p, "PLAY", 4)) + { + CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); + Z_Free(buffer); + return UINT8_MAX; + } p += 4; // "PLAY" + p += 2; // gamemap + p += 16; // mapmd5 + flags = READUINT8(p); + p++; // gametype + G_SkipDemoExtraFiles(&p); + if (!(flags & aflags)) + { + CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname); + Z_Free(buffer); + return UINT8_MAX; + } + + oldtime = READUINT32(p); + if (uselaps) + oldlap = READUINT32(p); + else + oldlap = 0; + + Z_Free(buffer); + + c = 0; + + if (uselaps) + { + if (newtime < oldtime + || (newtime == oldtime && (newlap < oldlap))) + c |= 1; // Better time + if (newlap < oldlap + || (newlap == oldlap && newtime < oldtime)) + c |= 1<<1; // Better lap time + } + else + { + if (newtime < oldtime) + c |= 1; // Better time + } + + return c; +} + +void G_LoadDemoInfo(menudemo_t *pdemo) +{ + UINT8 *infobuffer, *info_p, *extrainfo_p; + UINT8 version, subversion, pdemoflags; + UINT16 pdemoversion, count; + + if (!FIL_ReadFile(pdemo->filepath, &infobuffer)) + { + CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + + return; + } + + info_p = infobuffer; + + if (memcmp(info_p, DEMOHEADER, 12)) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + Z_Free(infobuffer); + return; + } + + pdemo->type = MD_LOADED; + + info_p += 12; // DEMOHEADER + + version = READUINT8(info_p); + subversion = READUINT8(info_p); + pdemoversion = READUINT16(info_p); + + switch(pdemoversion) + { + case DEMOVERSION: // latest always supported + // demo title + M_Memcpy(pdemo->title, info_p, 64); + info_p += 64; + + break; + // too old, cannot support. + default: + CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + Z_Free(infobuffer); + return; + } + + if (version != VERSION || subversion != SUBVERSION) + pdemo->type = MD_OUTDATED; + + info_p += 16; // demo checksum + if (memcmp(info_p, "PLAY", 4)) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath); + pdemo->type = MD_INVALID; + sprintf(pdemo->title, "INVALID REPLAY"); + Z_Free(infobuffer); + return; + } + info_p += 4; // "PLAY" + pdemo->map = READINT16(info_p); + info_p += 16; // mapmd5 + + pdemoflags = READUINT8(info_p); + + // temp? + if (!(pdemoflags & DF_MULTIPLAYER)) + { + CONS_Alert(CONS_ERROR, M_GetText("%s is not a multiplayer replay and can't be listed on this menu fully yet.\n"), pdemo->filepath); + Z_Free(infobuffer); + return; + } + + pdemo->gametype = READUINT8(info_p); + + pdemo->addonstatus = G_CheckDemoExtraFiles(&info_p, true); + info_p += 4; // RNG seed + + extrainfo_p = infobuffer + READUINT32(info_p); // The extra UINT32 read is for a blank 4 bytes? + + // Pared down version of CV_LoadNetVars to find the kart speed + pdemo->kartspeed = KARTSPEED_NORMAL; // Default to normal speed + count = READUINT16(info_p); + while (count--) + { + UINT16 netid; + char *svalue; + + netid = READUINT16(info_p); + svalue = (char *)info_p; + SKIPSTRING(info_p); + info_p++; // stealth + + if (netid == cv_kartspeed.netid) + { + UINT8 j; + for (j = 0; kartspeed_cons_t[j].strvalue; j++) + if (!stricmp(kartspeed_cons_t[j].strvalue, svalue)) + pdemo->kartspeed = kartspeed_cons_t[j].value; + } + else if (netid == cv_basenumlaps.netid && pdemo->gametype == GT_RACE) + pdemo->numlaps = atoi(svalue); + } + + if (pdemoflags & DF_ENCORE) + pdemo->kartspeed |= DF_ENCORE; + + /*// Temporary info until this is actually present in replays. + (void)extrainfo_p; + sprintf(pdemo->winnername, "transrights420"); + pdemo->winnerskin = 1; + pdemo->winnercolor = SKINCOLOR_MOONSET; + pdemo->winnertime = 6666;*/ + + // Read standings! + count = 0; + + while (READUINT8(extrainfo_p) == DW_STANDING) // Assume standings are always first in the extrainfo + { + INT32 i; + char temp[16]; + + pdemo->standings[count].ranking = READUINT8(extrainfo_p); + + // Name + M_Memcpy(pdemo->standings[count].name, extrainfo_p, 16); + extrainfo_p += 16; + + // Skin + M_Memcpy(temp,extrainfo_p,16); + extrainfo_p += 16; + pdemo->standings[count].skin = UINT8_MAX; + for (i = 0; i < numskins; i++) + if (stricmp(skins[i].name, temp) == 0) + { + pdemo->standings[count].skin = i; + break; + } + + // Color + M_Memcpy(temp,extrainfo_p,16); + extrainfo_p += 16; + for (i = 0; i < numskincolors; i++) + if (!stricmp(skincolors[i].name,temp)) // SRB2kart + { + pdemo->standings[count].color = i; + break; + } + + // Score/time/whatever + pdemo->standings[count].timeorscore = READUINT32(extrainfo_p); + + count++; + + if (count >= MAXPLAYERS) + break; //@TODO still cycle through the rest of these if extra demo data is ever used + } + + // I think that's everything we need? + Z_Free(infobuffer); +} + +// +// G_PlayDemo +// +void G_DeferedPlayDemo(const char *name) +{ + COM_BufAddText("playdemo \""); + COM_BufAddText(name); + COM_BufAddText("\" -addfiles\n"); +} + +// +// Start a demo from a .LMP file or from a wad resource +// + +#define SKIPERRORS + +void G_DoPlayDemo(char *defdemoname) +{ + UINT8 i, p; + lumpnum_t l; + char skin[17],color[MAXCOLORNAME+1],follower[17],*n,*pdemoname; + UINT8 version,subversion; + UINT32 randseed; + char msg[1024]; + + boolean spectator; + UINT8 slots[MAXPLAYERS], kartspeed[MAXPLAYERS], kartweight[MAXPLAYERS], numslots = 0; + +#if defined(SKIPERRORS) && !defined(DEVELOP) + boolean skiperrors = false; +#endif + + G_InitDemoRewind(); + + skin[16] = '\0'; + follower[16] = '\0'; + color[MAXCOLORNAME] = '\0'; + + // No demo name means we're restarting the current demo + if (defdemoname == NULL) + { + demo_p = demobuffer; + pdemoname = ZZ_Alloc(1); // Easier than adding checks for this everywhere it's freed + } + else + { + n = defdemoname+strlen(defdemoname); + while (*n != '/' && *n != '\\' && n != defdemoname) + n--; + if (n != defdemoname) + n++; + pdemoname = ZZ_Alloc(strlen(n)+1); + strcpy(pdemoname,n); + + M_SetPlaybackMenuPointer(); + + // Internal if no extension, external if one exists + if (FIL_CheckExtension(defdemoname)) + { + //FIL_DefaultExtension(defdemoname, ".lmp"); + if (!FIL_ReadFile(defdemoname, &demobuffer)) + { + snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + gameaction = ga_nothing; + M_StartMessage(msg, NULL, MM_NOTHING); + return; + } + demo_p = demobuffer; + } + // load demo resource from WAD + else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) + { + snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + gameaction = ga_nothing; + M_StartMessage(msg, NULL, MM_NOTHING); + return; + } + else // it's an internal demo + { + demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC); +#if defined(SKIPERRORS) && !defined(DEVELOP) + skiperrors = true; // SRB2Kart: Don't print warnings for staff ghosts, since they'll inevitably happen when we make bugfixes/changes... +#endif + } + } + + // read demo header + gameaction = ga_nothing; + demo.playback = true; + if (memcmp(demo_p, DEMOHEADER, 12)) + { + snprintf(msg, 1024, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + demo_p += 12; // DEMOHEADER + + version = READUINT8(demo_p); + subversion = READUINT8(demo_p); + demo.version = READUINT16(demo_p); + switch(demo.version) + { + case 0x000d: + case DEMOVERSION: // latest always supported + break; + // too old, cannot support. + default: + snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + + // demo title + M_Memcpy(demo.titlename, demo_p, 64); + demo_p += 64; + + demo_p += 16; // demo checksum + + if (memcmp(demo_p, "PLAY", 4)) + { + snprintf(msg, 1024, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + demo_p += 4; // "PLAY" + gamemap = READINT16(demo_p); + demo_p += 16; // mapmd5 + + demoflags = READUINT8(demo_p); + gametype = READUINT8(demo_p); + + if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. + G_SkipDemoExtraFiles(&demo_p); + else if (demo.loadfiles) + G_LoadDemoExtraFiles(&demo_p); + else if (demo.ignorefiles) + G_SkipDemoExtraFiles(&demo_p); + else + { + UINT8 error = G_CheckDemoExtraFiles(&demo_p, false); + + if (error) + { + switch (error) + { + case DFILE_ERROR_NOTLOADED: + snprintf(msg, 1024, + M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"), + pdemoname); + break; + + case DFILE_ERROR_OUTOFORDER: + snprintf(msg, 1024, + M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + + case DFILE_ERROR_INCOMPLETEOUTOFORDER: + snprintf(msg, 1024, + M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"), + pdemoname); + break; + + case DFILE_ERROR_CANNOTLOAD: + snprintf(msg, 1024, + M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + + case DFILE_ERROR_EXTRAFILES: + snprintf(msg, 1024, + M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), + pdemoname); + break; + } + + CONS_Alert(CONS_ERROR, "%s", msg); + if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out. + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + } + + modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT; + multiplayer = !!(demoflags & DF_MULTIPLAYER); + CON_ToggleOff(); + + hu_demotime = UINT32_MAX; + hu_demolap = UINT32_MAX; + + switch (modeattacking) + { + case ATTACKING_NONE: // 0 + break; + case ATTACKING_TIME: // 1 + hu_demotime = READUINT32(demo_p); + hu_demolap = READUINT32(demo_p); + break; + case ATTACKING_CAPSULES: // 2 + hu_demotime = READUINT32(demo_p); + break; + default: // 3 + modeattacking = ATTACKING_NONE; + break; + } + + // Random seed + randseed = READUINT32(demo_p); + + demo_p += 4; // Extrainfo location + + // ...*map* not loaded? + if (!gamemap || (gamemap > NUMMAPS) || !mapheaderinfo[gamemap-1] || !(mapheaderinfo[gamemap-1]->alreadyExists == true)) + { + snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + + // net var data + CV_LoadDemoVars(&demo_p); + + // Sigh ... it's an empty demo. + if (*demo_p == DEMOMARKER) + { + snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + + Z_Free(pdemoname); + + memset(&oldcmd,0,sizeof(oldcmd)); + memset(&oldghost,0,sizeof(oldghost)); + memset(&ghostext,0,sizeof(ghostext)); + +#if defined(SKIPERRORS) && !defined(DEVELOP) + if ((VERSION != version || SUBVERSION != subversion) && !skiperrors) +#else + if (VERSION != version || SUBVERSION != subversion) +#endif + CONS_Alert(CONS_WARNING, M_GetText("Demo version does not match game version. Desyncs may occur.\n")); + + // console warning messages +#if defined(SKIPERRORS) && !defined(DEVELOP) + demosynced = (!skiperrors); +#else + demosynced = true; +#endif + + // didn't start recording right away. + demo.deferstart = false; + + displayplayers[0] = consoleplayer = 0; + memset(playeringame,0,sizeof(playeringame)); + + // Load players that were in-game when the map started + p = READUINT8(demo_p); + + for (i = 1; i < MAXSPLITSCREENPLAYERS; i++) + displayplayers[i] = INT32_MAX; + + while (p != 0xFF) + { + spectator = false; + if (p & DEMO_SPECTATOR) + { + spectator = true; + p &= ~DEMO_SPECTATOR; + + if (modeattacking) + { + snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with spectators, and is thus invalid.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + } + slots[numslots] = p; numslots++; + + if (modeattacking && numslots > 1) + { + snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with multiple players, and is thus invalid.\n"), pdemoname); + CONS_Alert(CONS_ERROR, "%s", msg); + M_StartMessage(msg, NULL, MM_NOTHING); + Z_Free(pdemoname); + Z_Free(demobuffer); + demo.playback = false; + demo.title = false; + return; + } + + if (!playeringame[displayplayers[0]] || players[displayplayers[0]].spectator) + displayplayers[0] = consoleplayer = serverplayer = p; + + playeringame[p] = true; + players[p].spectator = spectator; + + // Name + M_Memcpy(player_names[p],demo_p,16); + demo_p += 16; + + // Skin + M_Memcpy(skin,demo_p,16); + demo_p += 16; + SetPlayerSkin(p, skin); + + // Color + M_Memcpy(color,demo_p,16); + demo_p += 16; + for (i = 0; i < numskincolors; i++) + if (!stricmp(skincolors[i].name,color)) // SRB2kart + { + players[p].skincolor = i; + break; + } + + // Follower + M_Memcpy(follower, demo_p, 16); + demo_p += 16; + SetPlayerFollower(p, follower); + + // Follower colour + M_Memcpy(color, demo_p, 16); + demo_p += 16; + for (i = 0; i < numskincolors +2; i++) // +2 because of Match and Opposite + { + if (!stricmp(Followercolor_cons_t[i].strvalue, color)) + { + players[p].followercolor = i; + break; + } + } + + // Score, since Kart uses this to determine where you start on the map + players[p].score = READUINT32(demo_p); + + // Power Levels + clientpowerlevels[p][gametype == GT_BATTLE ? PWRLV_BATTLE : PWRLV_RACE] = READUINT16(demo_p); + + // Kart stats, temporarily + kartspeed[p] = READUINT8(demo_p); + kartweight[p] = READUINT8(demo_p); + + if (stricmp(skins[players[p].skin].name, skin) != 0) + FindClosestSkinForStats(p, kartspeed[p], kartweight[p]); + + // Followitem + players[p].followitem = READUINT32(demo_p); + + // Look for the next player + p = READUINT8(demo_p); + } + + // end of player read (the 0xFF marker) + // so this is where we are to read our lua variables (if possible!) + if (demoflags & DF_LUAVARS) // again, used for compability, lua shit will be saved to replays regardless of if it's even been loaded + { + if (!gL) // No Lua state! ...I guess we'll just start one... + LUA_ClearState(); + + // No modeattacking check, DF_LUAVARS won't be present here. + LUA_UnArchive(&demo_p); + } + + splitscreen = 0; + + if (demo.title) + { + splitscreen = M_RandomKey(6)-1; + splitscreen = min(min(3, numslots-1), splitscreen); // Bias toward 1p and 4p views + + for (p = 0; p <= splitscreen; p++) + G_ResetView(p+1, slots[M_RandomKey(numslots)], false); + } + + R_ExecuteSetViewSize(); + + P_SetRandSeed(randseed); + G_InitNew(demoflags & DF_ENCORE, G_BuildMapName(gamemap), true, true, false); // Doesn't matter whether you reset or not here, given changes to resetplayer. + + for (i = 0; i < MAXPLAYERS; i++) + { + if (players[i].mo) + { + players[i].mo->color = players[i].skincolor; + oldghost[i].x = players[i].mo->x; + oldghost[i].y = players[i].mo->y; + oldghost[i].z = players[i].mo->z; + } + + // Set saved attribute values + // No cheat checking here, because even if they ARE wrong... + // it would only break the replay if we clipped them. + players[i].kartspeed = kartspeed[i]; + players[i].kartweight = kartweight[i]; + } + + demo.deferstart = true; +} + +void G_AddGhost(char *defdemoname) +{ + INT32 i; + lumpnum_t l; + char name[17],skin[17],color[MAXCOLORNAME+1],*n,*pdemoname,md5[16]; + demoghost *gh; + UINT8 flags; + UINT8 *buffer,*p; + mapthing_t *mthing; + UINT16 count, ghostversion; + skin_t *ghskin = &skins[0]; + UINT8 kartspeed = UINT8_MAX, kartweight = UINT8_MAX; + + name[16] = '\0'; + skin[16] = '\0'; + color[16] = '\0'; + + n = defdemoname+strlen(defdemoname); + while (*n != '/' && *n != '\\' && n != defdemoname) + n--; + if (n != defdemoname) + n++; + pdemoname = ZZ_Alloc(strlen(n)+1); + strcpy(pdemoname,n); + + // Internal if no extension, external if one exists + if (FIL_CheckExtension(defdemoname)) + { + //FIL_DefaultExtension(defdemoname, ".lmp"); + if (!FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL)) + { + CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname); + Z_Free(pdemoname); + return; + } + p = buffer; + } + // load demo resource from WAD + else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) + { + CONS_Alert(CONS_ERROR, M_GetText("Failed to read lump '%s'.\n"), defdemoname); + Z_Free(pdemoname); + return; + } + else // it's an internal demo + buffer = p = W_CacheLumpNum(l, PU_LEVEL); + + // read demo header + if (memcmp(p, DEMOHEADER, 12)) + { + CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2 replay.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } p += 12; // DEMOHEADER + + p++; // VERSION + p++; // SUBVERSION + + ghostversion = READUINT16(p); + switch(ghostversion) + { + case 0x000d: + case DEMOVERSION: // latest always supported + break; + // too old, cannot support. + default: + CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + + p += 64; // title + M_Memcpy(md5, p, 16); p += 16; // demo checksum + + for (gh = ghosts; gh; gh = gh->next) + if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum? + { // Don't add another one, then! + CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + + if (memcmp(p, "PLAY", 4)) + { + CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } p += 4; // "PLAY" + + + p += 2; // gamemap + p += 16; // mapmd5 (possibly check for consistency?) + + flags = READUINT8(p); + if (!(flags & DF_GHOST)) + { + CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + + p++; // gametype + G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. + + switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) + { + case ATTACKING_NONE: // 0 + break; + case ATTACKING_TIME: // 1 + p += 8; // demo time, lap + break; + case ATTACKING_CAPSULES: // 2 + p += 4; // demo time + break; + default: // 3 + break; + } + + p += 4; // random seed + p += 4; // Extra data location reference + + // net var data + count = READUINT16(p); + while (count--) + { + SKIPSTRING(p); + SKIPSTRING(p); + p++; + } + + if (*p == DEMOMARKER) + { + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + + if (READUINT8(p) != 0) + { + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + + // Player name (TODO: Display this somehow if it doesn't match cv_playername!) + M_Memcpy(name, p, 16); + p += 16; + + // Skin + M_Memcpy(skin, p, 16); + p += 16; + + // Color + M_Memcpy(color, p, 16); + p += 16; + + // Follower data was here, skip it, we don't care about it for ghosts. + p += 32; // followerskin (16) + followercolor (16) + + p += 4; // score + p += 2; // powerlevel + + kartspeed = READUINT8(p); + kartweight = READUINT8(p); + + if (READUINT8(p) != 0xFF) + { + CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); + Z_Free(pdemoname); + Z_Free(buffer); + return; + } + + for (i = 0; i < numskins; i++) + if (!stricmp(skins[i].name,skin)) + { + ghskin = &skins[i]; + break; + } + + if (i == numskins) + { + if (kartspeed != UINT8_MAX && kartweight != UINT8_MAX) + ghskin = &skins[GetSkinNumClosestToStats(kartspeed, kartweight)]; + + CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Invalid character. Falling back to %s.\n"), pdemoname, ghskin->name); + } + + + gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL); + gh->next = ghosts; + gh->buffer = buffer; + M_Memcpy(gh->checksum, md5, 16); + gh->p = p; + + ghosts = gh; + + gh->version = ghostversion; + mthing = playerstarts[0]; + I_Assert(mthing); + { // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling. + fixed_t z,f,c; + fixed_t offset = mthing->z << FRACBITS; + gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST); + gh->mo->angle = FixedAngle(mthing->angle << FRACBITS); + f = gh->mo->floorz; + c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height; + if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) + { + z = c - offset; + if (z < f) + z = f; + } + else + { + z = f + offset; + if (z > c) + z = c; + } + gh->mo->z = z; + } + + gh->oldmo.x = gh->mo->x; + gh->oldmo.y = gh->mo->y; + gh->oldmo.z = gh->mo->z; + + gh->mo->state = states + S_KART_STILL; + gh->mo->sprite = gh->mo->state->sprite; + gh->mo->sprite2 = (gh->mo->state->frame & FF_FRAMEMASK); + //gh->mo->frame = tr_trans30<mo->drawflags |= MFD_DONTDRAW; + gh->fadein = (9-3)*6; // fade from invisible to trans30 over as close to 35 tics as possible + gh->mo->tics = -1; + + // Set skin + gh->mo->skin = gh->oldmo.skin = ghskin; + + // Set color + gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor; + for (i = 0; i < numskincolors; i++) + if (!stricmp(skincolors[i].name,color)) + { + gh->mo->color = (UINT16)i; + break; + } + gh->oldmo.color = gh->mo->color; + + CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname); + Z_Free(pdemoname); +} + +// Clean up all ghosts +void G_FreeGhosts(void) +{ + while (ghosts) + { + demoghost *next = ghosts->next; + Z_Free(ghosts); + ghosts = next; + } + ghosts = NULL; +} + +// A simplified version of G_AddGhost... +void G_UpdateStaffGhostName(lumpnum_t l) +{ + UINT8 *buffer,*p; + UINT16 ghostversion; + UINT8 flags; + + buffer = p = W_CacheLumpNum(l, PU_CACHE); + + // read demo header + if (memcmp(p, DEMOHEADER, 12)) + { + goto fail; + } + + p += 12; // DEMOHEADER + p++; // VERSION + p++; // SUBVERSION + + ghostversion = READUINT16(p); + switch(ghostversion) + { + case DEMOVERSION: // latest always supported + break; + + // too old, cannot support. + default: + goto fail; + } + + p += 64; // full demo title + p += 16; // demo checksum + + if (memcmp(p, "PLAY", 4)) + { + goto fail; + } + + p += 4; // "PLAY" + p += 2; // gamemap + p += 16; // mapmd5 (possibly check for consistency?) + + flags = READUINT8(p); + if (!(flags & DF_GHOST)) + { + goto fail; // we don't NEED to do it here, but whatever + } + + p++; // Gametype + + G_SkipDemoExtraFiles(&p); + + switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) + { + case ATTACKING_NONE: // 0 + break; + case ATTACKING_TIME: // 1 + p += 8; // demo time, lap + break; + case ATTACKING_CAPSULES: // 2 + p += 4; // demo time + break; + default: // 3 + break; + } + + p += 4; // random seed + p += 4; // Extrainfo location marker + + // Ehhhh don't need ghostversion here (?) so I'll reuse the var here + ghostversion = READUINT16(p); + while (ghostversion--) + { + p += 2; + SKIPSTRING(p); + p++; // stealth + } + + // Assert first player is in and then read name + if (READUINT8(p) != 0) + goto fail; + M_Memcpy(dummystaffname, p,16); + dummystaffname[16] = '\0'; + + // Ok, no longer any reason to care, bye +fail: + Z_Free(buffer); + return; +} + +// +// G_TimeDemo +// NOTE: name is a full filename for external demos +// +static INT32 restorecv_vidwait; + +void G_TimeDemo(const char *name) +{ + nodrawers = M_CheckParm("-nodraw"); + noblit = M_CheckParm("-noblit"); + restorecv_vidwait = cv_vidwait.value; + if (cv_vidwait.value) + CV_Set(&cv_vidwait, "0"); + demo.timing = true; + singletics = true; + framecount = 0; + demostarttime = I_GetTime(); + G_DeferedPlayDemo(name); +} + +void G_DoPlayMetal(void) +{ + lumpnum_t l; + mobj_t *mo = NULL; + thinker_t *th; + + // it's an internal demo + if ((l = W_CheckNumForName(va("%sMS",G_BuildMapName(gamemap)))) == LUMPERROR) + { + CONS_Alert(CONS_WARNING, M_GetText("No bot recording for this map.\n")); + return; + } + else + metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC); + + // find metal sonic + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)th; + if (mo->type != MT_METALSONIC_RACE) + continue; + + break; + } + if (th == &thlist[THINK_MOBJ]) + { + CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n")); + Z_Free(metalbuffer); + return; + } + + // read demo header + metal_p += 12; // DEMOHEADER + metal_p++; // VERSION + metal_p++; // SUBVERSION + metalversion = READUINT16(metal_p); + switch(metalversion) + { + case DEMOVERSION: // latest always supported + break; + // too old, cannot support. + default: + CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n")); + Z_Free(metalbuffer); + return; + } + metal_p += 16; // demo checksum + if (memcmp(metal_p, "METL", 4)) + { + CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, wasn't recorded in Metal format.\n")); + Z_Free(metalbuffer); + return; + } metal_p += 4; // "METL" + + // read initial tic + memset(&oldmetal,0,sizeof(oldmetal)); + oldmetal.x = mo->x; + oldmetal.y = mo->y; + oldmetal.z = mo->z; + metalplayback = mo; +} + +void G_DoneLevelLoad(void) +{ + CONS_Printf(M_GetText("Loaded level in %f sec\n"), (double)(I_GetTime() - demostarttime) / TICRATE); + framecount = 0; + demostarttime = I_GetTime(); +} + +/* +=================== += += G_CheckDemoStatus += += Called after a death or level completion to allow demos to be cleaned up += Returns true if a new demo loop action will take place +=================== +*/ + +// Writes the demo's checksum, or just random garbage if you can't do that for some reason. +static void WriteDemoChecksum(void) +{ + UINT8 *p = demobuffer+16; // checksum position +#ifdef NOMD5 + UINT8 i; + for (i = 0; i < 16; i++, p++) + *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. +#else + md5_buffer((char *)p+16, demo_p - (p+16), p); // make a checksum of everything after the checksum in the file. +#endif +} + +// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist +void G_StopMetalDemo(void) +{ + // Metal Sonic finishing doesn't end the game, dammit. + Z_Free(metalbuffer); + metalbuffer = NULL; + metalplayback = NULL; + metal_p = NULL; +} + +// Stops metal sonic recording. +ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill) +{ + boolean saved = false; + if (demo_p) + { + WRITEUINT8(demo_p, (kill) ? METALDEATH : DEMOMARKER); // add the demo end (or metal death) marker + WriteDemoChecksum(); + saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file. + } + free(demobuffer); + metalrecording = false; + if (saved) + I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap)); + I_Error("Failed to save demo!"); +} + +// Stops timing a demo. +static void G_StopTimingDemo(void) +{ + INT32 demotime; + double f1, f2; + demotime = I_GetTime() - demostarttime; + if (!demotime) + return; + G_StopDemo(); + demo.timing = false; + f1 = (double)demotime; + f2 = (double)framecount*TICRATE; + + CONS_Printf(M_GetText("timed %u gametics in %d realtics - %u frames\n%f seconds, %f avg fps\n"), + leveltime,demotime,(UINT32)framecount,f1/TICRATE,f2/f1); + + // CSV-readable timedemo results, for external parsing + if (timedemo_csv) + { + FILE *f; + const char *csvpath = va("%s"PATHSEP"%s", srb2home, "timedemo.csv"); + const char *header = "id,demoname,seconds,avgfps,leveltime,demotime,framecount,ticrate,rendermode,vidmode,vidwidth,vidheight,procbits\n"; + const char *rowformat = "\"%s\",\"%s\",%f,%f,%u,%d,%u,%u,%u,%u,%u,%u,%u\n"; + boolean headerrow = !FIL_FileExists(csvpath); + UINT8 procbits = 0; + + // Bitness + if (sizeof(void*) == 4) + procbits = 32; + else if (sizeof(void*) == 8) + procbits = 64; + + f = fopen(csvpath, "a+"); + + if (f) + { + if (headerrow) + fputs(header, f); + fprintf(f, rowformat, + timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits); + fclose(f); + CONS_Printf("Timedemo results saved to '%s'\n", csvpath); + } + else + { + // Just print the CSV output to console + CON_LogMessage(header); + CONS_Printf(rowformat, + timedemo_csv_id,timedemo_name,f1/TICRATE,f2/f1,leveltime,demotime,(UINT32)framecount,TICRATE,rendermode,vid.modenum,vid.width,vid.height,procbits); + } + } + + if (restorecv_vidwait != cv_vidwait.value) + CV_SetValue(&cv_vidwait, restorecv_vidwait); + D_AdvanceDemo(); +} + +// reset engine variable set for the demos +// called from stopdemo command, map command, and g_checkdemoStatus. +void G_StopDemo(void) +{ + Z_Free(demobuffer); + demobuffer = NULL; + demo.playback = false; + if (demo.title) + modeattacking = false; + demo.title = false; + demo.timing = false; + singletics = false; + + demo.freecam = false; + // reset democam shit too: + democam.cam = NULL; + democam.soundmobj = NULL; + democam.localangle = 0; + democam.localaiming = 0; + democam.turnheld = false; + democam.keyboardlook = false; + + if (gamestate == GS_INTERMISSION) + Y_EndIntermission(); // cleanup + + if (gamestate == GS_VOTING) + Y_EndVote(); + + G_SetGamestate(GS_NULL); + wipegamestate = GS_NULL; + SV_StopServer(); + SV_ResetServer(); +} + +boolean G_CheckDemoStatus(void) +{ + G_FreeGhosts(); + + // DO NOT end metal sonic demos here + + if (demo.timing) + { + G_StopTimingDemo(); + return true; + } + + if (demo.playback) + { + if (demo.quitafterplaying) + I_Quit(); + + if (multiplayer && !demo.title) + G_ExitLevel(); + else + { + G_StopDemo(); + + if (modeattacking) + M_EndModeAttackRun(); + else + D_AdvanceDemo(); + } + + return true; + } + + if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING)) + { + G_SaveDemo(); + return true; + } + + demo.recording = false; + return false; +} + +void G_SaveDemo(void) +{ + UINT8 *p = demobuffer+16; // after version + UINT32 length; +#ifdef NOMD5 + UINT8 i; +#endif + + // Ensure extrainfo pointer is always available, even if no info is present. + if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) + { + WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker + *(UINT32 *)demoinfo_p = demo_p - demobuffer; + } + WRITEUINT8(demo_p, DW_END); // Mark end of demo extra data. + + M_Memcpy(p, demo.titlename, 64); // Write demo title here + p += 64; + + if (multiplayer) + { + // Change the demo's name to be a slug of the title + char demo_slug[128]; + char *writepoint; + size_t i, strindex = 0; + boolean dash = true; + + for (i = 0; demo.titlename[i] && i < 127; i++) + { + if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') || + (demo.titlename[i] >= '0' && demo.titlename[i] <= '9')) + { + demo_slug[strindex] = demo.titlename[i]; + strindex++; + dash = false; + } + else if (demo.titlename[i] >= 'A' && demo.titlename[i] <= 'Z') + { + demo_slug[strindex] = demo.titlename[i] + 'a' - 'A'; + strindex++; + dash = false; + } + else if (!dash) + { + demo_slug[strindex] = '-'; + strindex++; + dash = true; + } + } + + demo_slug[strindex] = 0; + if (dash) demo_slug[strindex-1] = 0; + + writepoint = strstr(demoname, "-") + 1; + demo_slug[128 - (writepoint - demoname) - 4] = 0; + sprintf(writepoint, "%s.lmp", demo_slug); + } + + length = *(UINT32 *)demoinfo_p; + WRITEUINT32(demoinfo_p, length); + + // Doesn't seem like I can use WriteDemoChecksum here, correct me if I'm wrong -Sal +#ifdef NOMD5 + for (i = 0; i < 16; i++, p++) + *p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. +#else + // Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable. + md5_buffer((char *)p+16, (demobuffer + length) - (p+16), p); +#endif + + if (FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer)) // finally output the file. + demo.savemode = DSM_SAVED; + free(demobuffer); + demo.recording = false; + + if (!modeattacking) + { + if (demo.savemode == DSM_SAVED) + CONS_Printf(M_GetText("Demo %s recorded\n"), demoname); + else + CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname); + } +} + +boolean G_DemoTitleResponder(event_t *ev) +{ + size_t len; + INT32 ch; + + if (ev->type != ev_keydown) + return false; + + ch = (INT32)ev->data1; + + // Only ESC and non-keyboard keys abort connection + if (ch == KEY_ESCAPE) + { + demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING; + return true; + } + + if (ch == KEY_ENTER || ch >= KEY_MOUSE1) + { + demo.savemode = DSM_WILLSAVE; + return true; + } + + if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && fontv[HU_FONT].font[ch-HU_FONTSTART]) + || ch == ' ') // Allow spaces, of course + { + len = strlen(demo.titlename); + if (len < 64) + { + demo.titlename[len+1] = 0; + demo.titlename[len] = CON_ShiftChar(ch); + } + } + else if (ch == KEY_BACKSPACE) + { + if (shiftdown) + memset(demo.titlename, 0, sizeof(demo.titlename)); + else + { + len = strlen(demo.titlename); + + if (len > 0) + demo.titlename[len-1] = 0; + } + } + + return true; +} diff --git a/src/g_demo.h b/src/g_demo.h new file mode 100644 index 000000000..b4039434e --- /dev/null +++ b/src/g_demo.h @@ -0,0 +1,190 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file g_demo.h +/// \brief Demo recording and playback + +#ifndef __G_DEMO__ +#define __G_DEMO__ + +#include "doomdef.h" +#include "doomstat.h" +#include "d_event.h" + +extern UINT8 *demo_p; + +// ====================================== +// DEMO playback/recording related stuff. +// ====================================== + +extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality; + +extern tic_t demostarttime; + +// Publicly-accessible demo vars +struct demovars_s { + char titlename[65]; + boolean recording, playback, timing; + UINT16 version; // Current file format of the demo being played + boolean title; // Title Screen demo can be cancelled by any key + boolean rewinding; // Rewind in progress + + boolean loadfiles, ignorefiles; // Demo file loading options + boolean fromtitle; // SRB2Kart: Don't stop the music + boolean inreplayhut; // Go back to replayhut after demos + boolean quitafterplaying; // quit after playing a demo from cmdline + boolean deferstart; // don't start playing demo right away + + tic_t savebutton; // Used to determine when the local player can choose to save the replay while the race is still going + enum { + DSM_NOTSAVING, + DSM_WILLAUTOSAVE, + DSM_TITLEENTRY, + DSM_WILLSAVE, + DSM_SAVED + } savemode; + + boolean freecam; + +}; + +extern struct demovars_s demo; + +typedef enum { + MD_NOTLOADED, + MD_LOADED, + MD_SUBDIR, + MD_OUTDATED, + MD_INVALID +} menudemotype_e; + +typedef struct menudemo_s { + char filepath[256]; + menudemotype_e type; + + char title[65]; // Null-terminated for string prints + UINT16 map; + UINT8 addonstatus; // What do we need to do addon-wise to play this demo? + UINT8 gametype; + SINT8 kartspeed; // Add OR DF_ENCORE for encore mode, idk + UINT8 numlaps; + + struct { + UINT8 ranking; + char name[17]; + UINT8 skin, color; + UINT32 timeorscore; + } standings[MAXPLAYERS]; +} menudemo_t; + + +extern mobj_t *metalplayback; + +// Only called by startup code. +void G_RecordDemo(const char *name); +void G_RecordMetal(void); +void G_BeginRecording(void); +void G_BeginMetal(void); + +// Only called by shutdown code. +void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT16 color, UINT32 val); +void G_SetDemoTime(UINT32 ptime, UINT32 plap); +UINT8 G_CmpDemoTime(char *oldname, char *newname); + +typedef enum +{ + GHC_NORMAL = 0, + GHC_SUPER, + GHC_FIREFLOWER, + GHC_INVINCIBLE, + GHC_RETURNSKIN // not actually a colour +} ghostcolor_t; + +extern UINT8 demo_extradata[MAXPLAYERS]; +extern UINT8 demo_writerng; + +#define DXD_RESPAWN 0x01 // "respawn" command in console +#define DXD_SKIN 0x02 // skin changed +#define DXD_NAME 0x04 // name changed +#define DXD_COLOR 0x08 // color changed +#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game +#define DXD_FOLLOWER 0x20 // follower was changed + +#define DXD_PST_PLAYING 0x01 +#define DXD_PST_SPECTATING 0x02 +#define DXD_PST_LEFT 0x03 + +// Record/playback tics +void G_ReadDemoExtraData(void); +void G_WriteDemoExtraData(void); +void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum); +void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum); +void G_GhostAddColor(INT32 playernum, ghostcolor_t color); +void G_GhostAddFlip(INT32 playernum); +void G_GhostAddScale(INT32 playernum, fixed_t scale); +void G_GhostAddHit(INT32 playernum, mobj_t *victim); +void G_WriteAllGhostTics(void); +void G_WriteGhostTic(mobj_t *ghost, INT32 playernum); +void G_ConsAllGhostTics(void); +void G_ConsGhostTic(INT32 playernum); +void G_GhostTicker(void); + +void G_InitDemoRewind(void); +void G_StoreRewindInfo(void); +void G_PreviewRewind(tic_t previewtime); +void G_ConfirmRewind(tic_t rewindtime); + +void G_ReadMetalTic(mobj_t *metal); +void G_WriteMetalTic(mobj_t *metal); +void G_SaveMetal(UINT8 **buffer); +void G_LoadMetal(UINT8 **buffer); + +// Your naming conventions are stupid and useless. +// There is no conflict here. +typedef struct demoghost { + UINT8 checksum[16]; + UINT8 *buffer, *p, color; + UINT8 fadein; + UINT16 version; + mobj_t oldmo, *mo; + struct demoghost *next; +} demoghost; +extern demoghost *ghosts; + +// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's. +#define DFILE_ERROR_NOTLOADED 0x01 // Files are not loaded, but can be without a restart. +#define DFILE_ERROR_OUTOFORDER 0x02 // Files are loaded, but out of order. +#define DFILE_ERROR_INCOMPLETEOUTOFORDER 0x03 // Some files are loaded out of order, but others are not. +#define DFILE_ERROR_CANNOTLOAD 0x04 // Files are missing and cannot be loaded. +#define DFILE_ERROR_EXTRAFILES 0x05 // Extra files outside of the replay's file list are loaded. + +void G_DeferedPlayDemo(const char *demo); +void G_DoPlayDemo(char *defdemoname); +void G_TimeDemo(const char *name); +void G_AddGhost(char *defdemoname); +void G_UpdateStaffGhostName(lumpnum_t l); +void G_FreeGhosts(void); +void G_DoneLevelLoad(void); + +void G_DoPlayMetal(void); +void G_StopMetalDemo(void); +ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(boolean kill); + +void G_StopDemo(void); +boolean G_CheckDemoStatus(void); + +void G_LoadDemoInfo(menudemo_t *pdemo); +void G_DeferedPlayDemo(const char *demo); + +void G_SaveDemo(void); + +boolean G_DemoTitleResponder(event_t *ev); + +#endif // __G_DEMO__ diff --git a/src/g_game.c b/src/g_game.c index 207c8ca5f..0151783e9 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -16,6 +16,7 @@ #include "d_main.h" #include "d_clisrv.h" #include "d_player.h" +#include "d_clisrv.h" #include "f_finale.h" #include "filesrch.h" // for refreshdirmenu #include "p_setup.h" @@ -28,6 +29,7 @@ #include "r_main.h" #include "s_sound.h" #include "g_game.h" +#include "g_demo.h" #include "m_cheat.h" #include "m_misc.h" #include "m_menu.h" @@ -39,31 +41,32 @@ #include "byteptr.h" #include "i_joy.h" #include "r_local.h" -#include "r_things.h" +#include "r_skins.h" #include "y_inter.h" #include "v_video.h" -#include "dehacked.h" // get_number (for ghost thok) -#include "lua_script.h" // LUA_ArchiveDemo and LUA_UnArchiveDemo #include "lua_hook.h" -#include "lua_libs.h" // gL (Lua state) #include "k_bot.h" #include "m_cond.h" // condition sets -#include "md5.h" // demo checksums -#include "k_kart.h" // SRB2kart +#include "lua_hud.h" + +// SRB2kart +#include "k_kart.h" #include "k_battle.h" #include "k_pwrlv.h" #include "k_color.h" #include "k_respawn.h" #include "k_grandprix.h" +#include "doomstat.h" + +#ifdef HAVE_DISCORDRPC +#include "discord.h" +#endif gameaction_t gameaction; gamestate_t gamestate = GS_NULL; UINT8 ultimatemode = false; -JoyType_t Joystick; -JoyType_t Joystick2; -JoyType_t Joystick3; -JoyType_t Joystick4; +JoyType_t Joystick[MAXSPLITSCREENPLAYERS]; // 1024 bytes is plenty for a savegame #define SAVEGAMESIZE (1024) @@ -85,9 +88,9 @@ UINT32 mapmusposition; // Position to jump to UINT32 mapmusresume; INT16 gamemap = 1; -INT16 maptol; +UINT32 maptol; -UINT8 globalweather = 0; +UINT8 globalweather = PRECIP_NONE; UINT8 curWeather = PRECIP_NONE; precipprops_t precipprops[MAXPRECIP] = @@ -101,9 +104,16 @@ precipprops_t precipprops[MAXPRECIP] = {MT_RAIN, PRECIPFX_THUNDER} // PRECIP_STORM_NOSTRIKES }; -INT32 cursaveslot = -1; // Auto-save 1p savegame slot -INT16 lastmapsaved = 0; // Last map we auto-saved at -boolean gamecomplete = false; +INT32 cursaveslot = 0; // Auto-save 1p savegame slot +//INT16 lastmapsaved = 0; // Last map we auto-saved at +INT16 lastmaploaded = 0; // Last map the game loaded +UINT8 gamecomplete = 0; + +marathonmode_t marathonmode = 0; +tic_t marathontime = 0; + +UINT8 numgameovers = 0; // for startinglives balance +SINT8 startinglivesbalance[maxgameovers+1] = {3, 5, 7, 9, 12, 15, 20, 25, 30, 40, 50, 75, 99, 0x7F}; UINT16 mainwads = 0; boolean modifiedgame = false; // Set if homebrew PWAD stuff has been added. @@ -113,16 +123,13 @@ UINT8 paused; UINT8 modeattacking = ATTACKING_NONE; boolean imcontinuing = false; boolean runemeraldmanager = false; +UINT16 emeraldspawndelay = 60*TICRATE; // menu demo things -UINT8 numDemos = 0; //3; -- i'm FED UP of losing my skincolour to a broken demo. change this back when we make new ones +UINT8 numDemos = 0; UINT32 demoDelayTime = 15*TICRATE; UINT32 demoIdleTime = 3*TICRATE; -boolean nodrawers; // for comparative timing purposes -boolean noblit; // for comparative timing purposes -static tic_t demostarttime; // for comparative timing purposes - boolean netgame; // only true if packets are broadcast boolean multiplayer; boolean playeringame[MAXPLAYERS]; @@ -135,29 +142,37 @@ INT32 g_localplayers[MAXSPLITSCREENPLAYERS]; tic_t gametic; tic_t levelstarttic; // gametic at level start -UINT32 totalrings; // for intermission +UINT32 ssspheres; // old special stage INT16 lastmap; // last level you were at (returning from special stages) tic_t timeinmap; // Ticker for time spent in level (used for levelcard display) -INT16 spstage_start; -INT16 sstage_start; -INT16 sstage_end; +INT16 spstage_start, spmarathon_start; +INT16 sstage_start, sstage_end, smpstage_start, smpstage_end; + +INT16 titlemap = 0; +boolean hidetitlepics = false; +INT16 bootmap; //bootmap for loading a map on startup + +INT16 tutorialmap = 0; // map to load for tutorial +boolean tutorialmode = false; // are we in a tutorial right now? +INT32 tutorialgcs = gcs_custom; // which control scheme is loaded? boolean looptitle = true; -boolean useNightsSS = false; -UINT8 skincolor_redteam = SKINCOLOR_RED; -UINT8 skincolor_blueteam = SKINCOLOR_BLUE; -UINT8 skincolor_redring = SKINCOLOR_RED; -UINT8 skincolor_bluering = SKINCOLOR_STEEL; +UINT16 skincolor_redteam = SKINCOLOR_RED; +UINT16 skincolor_blueteam = SKINCOLOR_BLUE; +UINT16 skincolor_redring = SKINCOLOR_RASPBERRY; +UINT16 skincolor_bluering = SKINCOLOR_PERIWINKLE; tic_t countdowntimer = 0; boolean countdowntimeup = false; +boolean exitfadestarted = false; cutscene_t *cutscenes[128]; +textprompt_t *textprompts[MAX_PROMPTS]; INT16 nextmapoverride; -boolean skipstats; +UINT8 skipstats; // Pointers to each CTF flag mobj_t *redflag; @@ -177,12 +192,15 @@ UINT16 numkartcupheaders = 0; static boolean exitgame = false; static boolean retrying = false; +static boolean retryingmodeattack = false; UINT8 stagefailed; // Used for GEMS BONUS? Also to see if you beat the stage. UINT16 emeralds; +INT32 luabanks[NUM_LUABANKS]; UINT32 token; // Number of tokens collected in a level UINT32 tokenlist; // List of tokens collected +boolean gottoken; // Did you get a token? Used for end of act INT32 tokenbits; // Used for setting token bits // Old Special Stage @@ -222,6 +240,10 @@ UINT16 tailsflytics = 8*TICRATE; UINT16 underwatertics = 30*TICRATE; UINT16 spacetimetics = 11*TICRATE + (TICRATE/2); UINT16 extralifetics = 4*TICRATE; +UINT16 nightslinktics = 2*TICRATE; + +INT32 gameovertics = 15*TICRATE; +UINT8 ammoremovaltics = 2*TICRATE; // SRB2kart tic_t introtime = 0; @@ -246,13 +268,13 @@ INT32 wantedreduce = 5*TICRATE; INT32 wantedfrequency = 10*TICRATE; INT32 flameseg = TICRATE/4; -INT32 gameovertics = 15*TICRATE; - UINT8 use1upSound = 0; UINT8 maxXtraLife = 2; // Max extra lives from rings +UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes UINT8 introtoplay; UINT8 creditscutscene; +UINT8 useBlackRock = 1; // Emerald locations mobj_t *hunt1; @@ -304,119 +326,28 @@ tic_t curlap; // Current lap time tic_t bestlap; // Best lap time static INT16 randmapbuffer[NUMMAPS+1]; // Buffer for maps RandMap is allowed to roll -tic_t hidetime; - // Grading UINT32 timesBeaten; -UINT32 timesBeatenWithEmeralds; -//UINT32 timesBeatenUltimate; -//@TODO put these all in a struct for namespacing purposes? -static char demoname[128]; -static UINT8 *demobuffer = NULL; -static UINT8 *demotime_p, *demoinfo_p; -UINT8 *demo_p; -static UINT8 *demoend; -static UINT8 demoflags; -static boolean demosynced = true; // console warning message - -struct demovars_s demo; - -boolean metalrecording; // recording as metal sonic -mobj_t *metalplayback; -static UINT8 *metalbuffer = NULL; -static UINT8 *metal_p; -static UINT16 metalversion; - -// extra data stuff (events registered this frame while recording) -static struct { - UINT8 flags; // EZT flags - - // EZT_COLOR - UINT8 color, lastcolor; - - // EZT_SCALE - fixed_t scale, lastscale; - - // EZT_KART - INT32 kartitem, kartamount, kartbumpers; - - UINT8 desyncframes; // Don't try to resync unless we've been off for two frames, to monkeypatch a few trouble spots - - // EZT_HIT - UINT16 hits; - mobj_t **hitlist; -} ghostext[MAXPLAYERS]; - -// Your naming conventions are stupid and useless. -// There is no conflict here. -demoghost *ghosts = NULL; +typedef struct joystickvector2_s +{ + INT32 xaxis; + INT32 yaxis; +} joystickvector2_t; boolean precache = true; // if true, load all graphics at start INT16 prevmap, nextmap; -static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}}; -consvar_t cv_recordmultiplayerdemos = {"netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - -static CV_PossibleValue_t netdemosyncquality_cons_t[] = {{1, "MIN"}, {35, "MAX"}, {0, NULL}}; -consvar_t cv_netdemosyncquality = {"netdemo_syncquality", "1", CV_SAVE, netdemosyncquality_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - static UINT8 *savebuffer; -// Analog Control -static void UserAnalog_OnChange(void); -static void UserAnalog2_OnChange(void); -static void UserAnalog3_OnChange(void); -static void UserAnalog4_OnChange(void); -static void Analog_OnChange(void); -static void Analog2_OnChange(void); -static void Analog3_OnChange(void); -static void Analog4_OnChange(void); void SendWeaponPref(void); void SendWeaponPref2(void); void SendWeaponPref3(void); void SendWeaponPref4(void); -//static CV_PossibleValue_t crosshair_cons_t[] = {{0, "Off"}, {1, "Cross"}, {2, "Angle"}, {3, "Point"}, {0, NULL}}; static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, -#ifdef _WII -{1, "LStick.X"}, {2, "LStick.Y"}, {-1, "LStick.X-"}, {-2, "LStick.Y-"}, -#if JOYAXISSET > 1 -{3, "RStick.X"}, {4, "RStick.Y"}, {-3, "RStick.X-"}, {-4, "RStick.Y-"}, -#endif -#if JOYAXISSET > 2 -{5, "RTrigger"}, {6, "LTrigger"}, {-5, "RTrigger-"}, {-6, "LTrigger-"}, -#endif -#if JOYAXISSET > 3 -{7, "Pitch"}, {8, "Roll"}, {-7, "Pitch-"}, {-8, "Roll-"}, -#endif -#if JOYAXISSET > 4 -{7, "Yaw"}, {8, "Dummy"}, {-7, "Yaw-"}, {-8, "Dummy-"}, -#endif -#if JOYAXISSET > 4 -{9, "LAnalog"}, {10, "RAnalog"}, {-9, "LAnalog-"}, {-10, "RAnalog-"}, -#endif -#elif defined (WMINPUT) -{1, "LStick.X"}, {2, "LStick.Y"}, {-1, "LStick.X-"}, {-2, "LStick.Y-"}, -#if JOYAXISSET > 1 -{3, "RStick.X"}, {4, "RStick.Y"}, {-3, "RStick.X-"}, {-4, "RStick.Y-"}, -#endif -#if JOYAXISSET > 2 -{5, "NStick.X"}, {6, "NStick.Y"}, {-5, "NStick.X-"}, {-6, "NStick.Y-"}, -#endif -#if JOYAXISSET > 3 -{7, "LAnalog"}, {8, "RAnalog"}, {-7, "LAnalog-"}, {-8, "RAnalog-"}, -#endif -#else {1, "X-Axis"}, {2, "Y-Axis"}, {-1, "X-Axis-"}, {-2, "Y-Axis-"}, -#ifdef _arch_dreamcast -{3, "R-Trig"}, {4, "L-Trig"}, {-3, "R-Trig-"}, {-4, "L-Trig-"}, -{5, "Alt X-Axis"}, {6, "Alt Y-Axis"}, {-5, "Alt X-Axis-"}, {-6, "Alt Y-Axis-"}, -{7, "Triggers"}, {-7,"Triggers-"}, -#elif defined (_XBOX) -{3, "Alt X-Axis"}, {4, "Alt Y-Axis"}, {-3, "Alt X-Axis-"}, {-4, "Alt Y-Axis-"}, -#else #if JOYAXISSET > 1 {3, "Z-Axis"}, {4, "X-Rudder"}, {-3, "Z-Axis-"}, {-4, "X-Rudder-"}, #endif @@ -425,166 +356,126 @@ static CV_PossibleValue_t joyaxis_cons_t[] = {{0, "None"}, #endif #if JOYAXISSET > 3 {7, "U-Axis"}, {8, "V-Axis"}, {-7, "U-Axis-"}, {-8, "V-Axis-"}, -#endif -#endif #endif {0, NULL}}; -#ifdef _WII -#if JOYAXISSET > 5 -"More Axis Sets" -#endif -#else #if JOYAXISSET > 4 "More Axis Sets" #endif -#endif - -static CV_PossibleValue_t deadzone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}}; // don't mind me putting these here, I was lazy to figure out where else I could put those without blowing up the compiler. -// it automatically becomes compact with 20+ players, but if you like it, I guess you can turn that on! -// SRB2Kart: irrelevant for us. -//consvar_t cv_compactscoreboard= {"compactscoreboard", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - // chat timer thingy static CV_PossibleValue_t chattime_cons_t[] = {{5, "MIN"}, {999, "MAX"}, {0, NULL}}; -consvar_t cv_chattime = {"chattime", "8", CV_SAVE, chattime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chattime = CVAR_INIT ("chattime", "8", CV_SAVE, chattime_cons_t, NULL); // chatwidth static CV_PossibleValue_t chatwidth_cons_t[] = {{64, "MIN"}, {150, "MAX"}, {0, NULL}}; -consvar_t cv_chatwidth = {"chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chatwidth = CVAR_INIT ("chatwidth", "150", CV_SAVE, chatwidth_cons_t, NULL); // chatheight static CV_PossibleValue_t chatheight_cons_t[] = {{6, "MIN"}, {22, "MAX"}, {0, NULL}}; -consvar_t cv_chatheight = {"chatheight", "8", CV_SAVE, chatheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chatheight = CVAR_INIT ("chatheight", "8", CV_SAVE, chatheight_cons_t, NULL); // chat notifications (do you want to hear beeps? I'd understand if you didn't.) -consvar_t cv_chatnotifications = {"chatnotifications", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chatnotifications = CVAR_INIT ("chatnotifications", "On", CV_SAVE, CV_OnOff, NULL); // chat spam protection (why would you want to disable that???) -consvar_t cv_chatspamprotection = {"chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chatspamprotection = CVAR_INIT ("chatspamprotection", "On", CV_SAVE, CV_OnOff, NULL); // minichat text background -consvar_t cv_chatbacktint = {"chatbacktint", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chatbacktint = CVAR_INIT ("chatbacktint", "On", CV_SAVE, CV_OnOff, NULL); // old shit console chat. (mostly exists for stuff like terminal, not because I cared if anyone liked the old chat.) static CV_PossibleValue_t consolechat_cons_t[] = {{0, "Window"}, {1, "Console"}, {2, "Window (Hidden)"}, {0, NULL}}; -consvar_t cv_consolechat = {"chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_consolechat = CVAR_INIT ("chatmode", "Window", CV_SAVE, consolechat_cons_t, NULL); // Pause game upon window losing focus -consvar_t cv_pauseifunfocused = {"pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_pauseifunfocused = CVAR_INIT ("pauseifunfocused", "Yes", CV_SAVE, CV_YesNo, NULL); // Display song credits -consvar_t cv_songcredits = {"songcredits", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_songcredits = CVAR_INIT ("songcredits", "On", CV_SAVE, CV_OnOff, NULL); -/*consvar_t cv_crosshair = {"crosshair", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_crosshair2 = {"crosshair2", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_crosshair3 = {"crosshair3", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_crosshair4 = {"crosshair4", "Off", CV_SAVE, crosshair_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL};*/ -consvar_t cv_invertmouse = {"invertmouse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_invertmouse2 = {"invertmouse2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -/*consvar_t cv_alwaysfreelook = {"alwaysmlook", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_alwaysfreelook2 = {"alwaysmlook2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chasefreelook = {"chasemlook", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chasefreelook2 = {"chasemlook2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mousemove = {"mousemove", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mousemove2 = {"mousemove2", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};*/ -consvar_t cv_analog = {"analog", "Off", CV_CALL, CV_OnOff, Analog_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_analog2 = {"analog2", "Off", CV_CALL, CV_OnOff, Analog2_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_analog3 = {"analog3", "Off", CV_CALL, CV_OnOff, Analog3_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_analog4 = {"analog4", "Off", CV_CALL, CV_OnOff, Analog4_OnChange, 0, NULL, NULL, 0, 0, NULL}; -#ifdef DC -consvar_t cv_useranalog = {"useranalog", "On", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_useranalog2 = {"useranalog2", "On", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog2_OnChange, 0, NULL, NULL, 0, 0, NULL}; -#else -consvar_t cv_useranalog = {"useranalog", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_useranalog2 = {"useranalog2", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog2_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_useranalog3 = {"useranalog3", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog3_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_useranalog4 = {"useranalog4", "Off", CV_SAVE|CV_CALL, CV_OnOff, UserAnalog4_OnChange, 0, NULL, NULL, 0, 0, NULL}; -#endif +consvar_t cv_invertmouse = CVAR_INIT ("invertmouse", "Off", CV_SAVE, CV_OnOff, NULL); -consvar_t cv_turnaxis = {"joyaxis_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_moveaxis = {"joyaxis_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_brakeaxis = {"joyaxis_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_aimaxis = {"joyaxis_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_lookaxis = {"joyaxis_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_fireaxis = {"joyaxis_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_driftaxis = {"joyaxis_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_deadzone = {"joy_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_invincmusicfade = CVAR_INIT ("invincmusicfade", "300", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_growmusicfade = CVAR_INIT ("growmusicfade", "500", CV_SAVE, CV_Unsigned, NULL); -consvar_t cv_turnaxis2 = {"joyaxis2_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_moveaxis2 = {"joyaxis2_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_brakeaxis2 = {"joyaxis2_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_aimaxis2 = {"joyaxis2_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_lookaxis2 = {"joyaxis2_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_fireaxis2 = {"joyaxis2_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_driftaxis2 = {"joyaxis2_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_deadzone2 = {"joy2_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_resetspecialmusic = CVAR_INIT ("resetspecialmusic", "Yes", CV_SAVE, CV_YesNo, NULL); -consvar_t cv_turnaxis3 = {"joyaxis3_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_moveaxis3 = {"joyaxis3_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_brakeaxis3 = {"joyaxis3_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_aimaxis3 = {"joyaxis3_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_lookaxis3 = {"joyaxis3_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_fireaxis3 = {"joyaxis3_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_driftaxis3 = {"joyaxis3_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_deadzone3 = {"joy3_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_resume = CVAR_INIT ("resume", "Yes", CV_SAVE, CV_YesNo, NULL); -consvar_t cv_turnaxis4 = {"joyaxis4_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_moveaxis4 = {"joyaxis4_move", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_brakeaxis4 = {"joyaxis4_brake", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_aimaxis4 = {"joyaxis4_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_lookaxis4 = {"joyaxis4_look", "None", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_fireaxis4 = {"joyaxis4_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_driftaxis4 = {"joyaxis4_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_deadzone4 = {"joy4_deadzone", "0.5", CV_FLOAT|CV_SAVE, deadzone_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joyaxis_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis3_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis4_turn", "X-Axis", CV_SAVE, joyaxis_cons_t, NULL) +}; -consvar_t cv_invincmusicfade = {"invincmusicfade", "300", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_growmusicfade = {"growmusicfade", "500", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joyaxis_move", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis_move2", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis_move3", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis_move4", "None", CV_SAVE, joyaxis_cons_t, NULL) +}; -consvar_t cv_resetspecialmusic = {"resetspecialmusic", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joyaxis_brake", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_brake", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis3_brake", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis4_brake", "None", CV_SAVE, joyaxis_cons_t, NULL) +}; -consvar_t cv_resume = {"resume", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_aimaxis[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joyaxis_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis3_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis4_aim", "Y-Axis", CV_SAVE, joyaxis_cons_t, NULL) +}; -#if MAXPLAYERS > 16 -#error "please update player_name table using the new value for MAXPLAYERS" -#endif +consvar_t cv_lookaxis[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joyaxis_look", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_look", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis3_look", "None", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis4_look", "None", CV_SAVE, joyaxis_cons_t, NULL) +}; + +consvar_t cv_fireaxis[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joyaxis_fire", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis_fire2", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis_fire3", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis_fire4", "Z-Axis", CV_SAVE, joyaxis_cons_t, NULL) +}; + +consvar_t cv_driftaxis[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joyaxis_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis2_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis3_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL), + CVAR_INIT ("joyaxis4_drift", "Z-Rudder", CV_SAVE, joyaxis_cons_t, NULL) +}; + +static CV_PossibleValue_t zerotoone_cons_t[] = {{0, "MIN"}, {FRACUNIT, "MAX"}, {0, NULL}}; +consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joy_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("joy2_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("joy3_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("joy4_deadzone", "0.125", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) +}; + +consvar_t cv_digitaldeadzone[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("joy_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("joy2_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("joy3_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL), + CVAR_INIT ("joy4_digdeadzone", "0.25", CV_FLOAT|CV_SAVE, zerotoone_cons_t, NULL) +}; #ifdef SEENAMES player_t *seenplayer; // player we're aiming at right now #endif -char player_names[MAXPLAYERS][MAXPLAYERNAME+1] = -{ - "Player 1", - "Player 2", - "Player 3", - "Player 4", - "Player 5", - "Player 6", - "Player 7", - "Player 8", - "Player 9", - "Player 10", - "Player 11", - "Player 12", - "Player 13", - "Player 14", - "Player 15", - "Player 16" -}; // SRB2kart - removed Players 17 through 32 - -INT16 rw_maximums[NUM_WEAPONS] = -{ - 800, // MAX_INFINITY - 400, // MAX_AUTOMATIC - 100, // MAX_BOUNCE - 50, // MAX_SCATTER - 100, // MAX_GRENADE - 50, // MAX_EXPLOSION - 50 // MAX_RAIL -}; +// now automatically allocated in D_RegisterClientCommands +// so that it doesn't have to be updated depending on the value of MAXPLAYERS +char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; +INT32 player_name_changes[MAXPLAYERS]; // Allocation for time and nights data void G_AllocMainRecordData(INT16 i) @@ -594,13 +485,6 @@ void G_AllocMainRecordData(INT16 i) memset(mainrecords[i], 0, sizeof(recorddata_t)); } -/*void G_AllocNightsRecordData(INT16 i) -{ - if (!nightsrecords[i]) - nightsrecords[i] = Z_Malloc(sizeof(nightsdata_t), PU_STATIC, NULL); - memset(nightsrecords[i], 0, sizeof(nightsdata_t)); -}*/ - // MAKE SURE YOU SAVE DATA BEFORE CALLING THIS void G_ClearRecords(void) { @@ -621,14 +505,6 @@ void G_ClearRecords(void) } // For easy retrieval of records -/*UINT32 G_GetBestScore(INT16 map) -{ - if (!mainrecords[map-1]) - return 0; - - return mainrecords[map-1]->score; -}*/ - tic_t G_GetBestTime(INT16 map) { if (!mainrecords[map-1] || mainrecords[map-1]->time <= 0) @@ -638,141 +514,75 @@ tic_t G_GetBestTime(INT16 map) } // Not needed -/*tic_t G_GetBestLap(INT16 map) +/* +tic_t G_GetBestLap(INT16 map) { if (!mainrecords[map-1] || mainrecords[map-1]->lap <= 0) return (tic_t)UINT32_MAX; return mainrecords[map-1]->lap; -}*/ - -/*UINT16 G_GetBestRings(INT16 map) -{ - if (!mainrecords[map-1]) - return 0; - - return mainrecords[map-1]->rings; -}*/ - -// No NiGHTS records for SRB2Kart -/*UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare) -{ - if (!nightsrecords[map-1]) - return 0; - - return nightsrecords[map-1]->score[mare]; } +*/ -tic_t G_GetBestNightsTime(INT16 map, UINT8 mare) +// +// G_UpdateRecordReplays +// +// Update replay files/data, etc. for Record Attack +// +static void G_UpdateRecordReplays(void) { - if (!nightsrecords[map-1] || nightsrecords[map-1]->time[mare] <= 0) - return (tic_t)UINT32_MAX; - - return nightsrecords[map-1]->time[mare]; -} - -UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare) -{ - if (!nightsrecords[map-1]) - return 0; - - return nightsrecords[map-1]->grade[mare]; -} - -// For easy adding of NiGHTS records -void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare) -{ - ntemprecords.score[mare] = pscore; - ntemprecords.grade[mare] = P_GetGrade(pscore, gamemap, mare - 1); - ntemprecords.time[mare] = ptime; - - // Update nummares - // Note that mare "0" is overall, mare "1" is the first real mare - if (ntemprecords.nummares < mare) - ntemprecords.nummares = mare; -} - -void G_SetNightsRecords(void) -{ - INT32 i; - UINT32 totalscore = 0; - tic_t totaltime = 0; - - const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; + const size_t glen = strlen(srb2home)+1+strlen("media")+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; char *gpath; char lastdemo[256], bestdemo[256]; + UINT8 earnedEmblems; - if (!ntemprecords.nummares) - return; + // Record new best time + if (!mainrecords[gamemap-1]) + G_AllocMainRecordData(gamemap-1); - // Set overall + if (players[consoleplayer].pflags & PF_GAMETYPEOVER) { - UINT8 totalrank = 0, realrank = 0; - - for (i = 1; i <= ntemprecords.nummares; ++i) - { - totalscore += ntemprecords.score[i]; - totalrank += ntemprecords.grade[i]; - totaltime += ntemprecords.time[i]; - } - - // Determine overall grade - realrank = (UINT8)((FixedDiv((fixed_t)totalrank << FRACBITS, ntemprecords.nummares << FRACBITS) + (FRACUNIT/2)) >> FRACBITS); - - // You need ALL rainbow As to get a rainbow A overall - if (realrank == GRADE_S && (totalrank / ntemprecords.nummares) != GRADE_S) - realrank = GRADE_A; - - ntemprecords.score[0] = totalscore; - ntemprecords.grade[0] = realrank; - ntemprecords.time[0] = totaltime; + players[consoleplayer].realtime = UINT32_MAX; } - // Now take all temp records and put them in the actual records + if (((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time)) + && (players[consoleplayer].realtime < UINT32_MAX)) // DNF { - nightsdata_t *maprecords; - - if (!nightsrecords[gamemap-1]) - G_AllocNightsRecordData(gamemap-1); - maprecords = nightsrecords[gamemap-1]; - - if (maprecords->nummares != ntemprecords.nummares) - maprecords->nummares = ntemprecords.nummares; - - for (i = 0; i < ntemprecords.nummares + 1; ++i) - { - if (maprecords->score[i] < ntemprecords.score[i]) - maprecords->score[i] = ntemprecords.score[i]; - if (maprecords->grade[i] < ntemprecords.grade[i]) - maprecords->grade[i] = ntemprecords.grade[i]; - if (!maprecords->time[i] || maprecords->time[i] > ntemprecords.time[i]) - maprecords->time[i] = ntemprecords.time[i]; - } + mainrecords[gamemap-1]->time = players[consoleplayer].realtime; } - memset(&ntemprecords, 0, sizeof(nightsdata_t)); + if (modeattacking == ATTACKING_TIME) + { + if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap)) + mainrecords[gamemap-1]->lap = bestlap; + } + else + { + mainrecords[gamemap-1]->lap = 0; + } // Save demo! bestdemo[255] = '\0'; lastdemo[255] = '\0'; - G_SetDemoTime(totaltime, totalscore); + G_SetDemoTime(players[consoleplayer].realtime, bestlap); G_CheckDemoStatus(); - I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); - I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); + gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s", + srb2home, timeattackfolder); + M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755); if ((gpath = malloc(glen)) == NULL) I_Error("Out of memory for replay filepath\n"); - sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-last.lmp", gpath); + sprintf(gpath,"%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); + snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_chooseskin.string); if (FIL_FileExists(lastdemo)) { UINT8 *buf; size_t len = FIL_ReadFile(lastdemo, &buf); - snprintf(bestdemo, 255, "%s-time-best.lmp", gpath); + snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, cv_chooseskin.string); if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) { // Better time, save this demo. if (FIL_FileExists(bestdemo)) @@ -781,13 +591,16 @@ void G_SetNightsRecords(void) CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); } - snprintf(bestdemo, 255, "%s-score-best.lmp", gpath); - if (!FIL_FileExists(bestdemo) || (G_CmpDemoTime(bestdemo, lastdemo) & (1<<1))) - { // Better score, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW HIGH SCORE!"), M_GetText("Saved replay as"), bestdemo); + if (modeattacking == ATTACKING_TIME) + { + snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string); + if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)) + { // Better lap time, save this demo. + if (FIL_FileExists(bestdemo)) + remove(bestdemo); + FIL_WriteFile(bestdemo, buf, len); + CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD LAP!"), M_GetText("Saved replay as"), bestdemo); + } } //CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo); @@ -796,10 +609,16 @@ void G_SetNightsRecords(void) } free(gpath); - // If the mare count changed, this will update the score display - CV_AddValue(&cv_nextmap, 1); - CV_AddValue(&cv_nextmap, -1); -}*/ + // Check emblems when level data is updated + if ((earnedEmblems = M_CheckLevelEmblems())) + CONS_Printf(M_GetText("\x82" "Earned %hu medal%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); + + if (M_UpdateUnlockablesAndExtraEmblems()) + S_StartSound(NULL, sfx_ncitem); + + // SRB2Kart - save here so you NEVER lose your earned times/medals. + G_SaveGameData(); +} // for consistency among messages: this modifies the game and removes savemoddata. void G_SetGameModified(boolean silent, boolean major) @@ -821,6 +640,8 @@ void G_SetGameModified(boolean silent, boolean major) // If in record attack recording, cancel it. if (modeattacking) M_EndModeAttackRun(); + else if (marathonmode) + Command_ExitGame_f(); } /** Builds an original game map name from a map number. @@ -867,9 +688,9 @@ const char *G_BuildMapName(INT32 map) * Used whenever the player view is changed manually. * * \param aiming Pointer to the vertical angle to clip. - * \return Short version of the clipped angle for building a ticcmd. + * \return The clipped angle. */ -INT16 G_ClipAimingPitch(INT32 *aiming) +INT32 G_ClipAimingPitch(INT32 *aiming) { INT32 limitangle; @@ -880,7 +701,7 @@ INT16 G_ClipAimingPitch(INT32 *aiming) else if (*aiming < -limitangle) *aiming = -limitangle; - return (INT16)((*aiming)>>16); + return (*aiming); } INT16 G_SoftwareClipAimingPitch(INT32 *aiming) @@ -898,7 +719,7 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming) return (INT16)((*aiming)>>16); } -static INT32 Joy1Axis(axis_input_e axissel) +INT32 PlayerJoyAxis(UINT8 player, axis_input_e axissel) { INT32 retaxis; INT32 axisval; @@ -908,25 +729,25 @@ static INT32 Joy1Axis(axis_input_e axissel) switch (axissel) { case AXISTURN: - axisval = cv_turnaxis.value; + axisval = cv_turnaxis[player-1].value; break; case AXISMOVE: - axisval = cv_moveaxis.value; + axisval = cv_moveaxis[player-1].value; break; case AXISBRAKE: - axisval = cv_brakeaxis.value; + axisval = cv_brakeaxis[player-1].value; break; case AXISAIM: - axisval = cv_aimaxis.value; + axisval = cv_aimaxis[player-1].value; break; case AXISLOOK: - axisval = cv_lookaxis.value; + axisval = cv_lookaxis[player-1].value; break; case AXISFIRE: - axisval = cv_fireaxis.value; + axisval = cv_fireaxis[player-1].value; break; case AXISDRIFT: - axisval = cv_driftaxis.value; + axisval = cv_driftaxis[player-1].value; break; default: return 0; @@ -937,316 +758,92 @@ static INT32 Joy1Axis(axis_input_e axissel) axisval = -axisval; flp = true; } -#ifdef _arch_dreamcast - if (axisval == 7) // special case - { - retaxis = joyxmove[1] - joyymove[1]; - goto skipDC; - } - else -#endif if (axisval > JOYAXISSET*2 || axisval == 0) //not there in array or None return 0; if (axisval%2) { axisval /= 2; - retaxis = joyxmove[axisval]; + retaxis = joyxmove[player-1][axisval]; } else { axisval--; axisval /= 2; - retaxis = joyymove[axisval]; + retaxis = joyymove[player-1][axisval]; } -#ifdef _arch_dreamcast - skipDC: -#endif - if (retaxis < (-JOYAXISRANGE)) retaxis = -JOYAXISRANGE; if (retaxis > (+JOYAXISRANGE)) retaxis = +JOYAXISRANGE; - if (!Joystick.bGamepadStyle && axissel < AXISDEAD) - { - const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone.value) >> FRACBITS; - if (abs(retaxis) <= jdeadzone) - return 0; - } - if (flp) retaxis = -retaxis; //flip it around - return retaxis; -} -static INT32 Joy2Axis(axis_input_e axissel) -{ - INT32 retaxis; - INT32 axisval; - boolean flp = false; - - //find what axis to get - switch (axissel) + if (!Joystick[player-1].bGamepadStyle && axissel >= AXISDIGITAL) { - case AXISTURN: - axisval = cv_turnaxis2.value; - break; - case AXISMOVE: - axisval = cv_moveaxis2.value; - break; - case AXISBRAKE: - axisval = cv_brakeaxis2.value; - break; - case AXISAIM: - axisval = cv_aimaxis2.value; - break; - case AXISLOOK: - axisval = cv_lookaxis2.value; - break; - case AXISFIRE: - axisval = cv_fireaxis2.value; - break; - case AXISDRIFT: - axisval = cv_driftaxis2.value; - break; - default: - return 0; - } - - - if (axisval < 0) //odd -axises - { - axisval = -axisval; - flp = true; - } -#ifdef _arch_dreamcast - if (axisval == 7) // special case - { - retaxis = joy2xmove[1] - joy2ymove[1]; - goto skipDC; - } - else -#endif - if (axisval > JOYAXISSET*2 || axisval == 0) //not there in array or None - return 0; - - if (axisval%2) - { - axisval /= 2; - retaxis = joy2xmove[axisval]; - } - else - { - axisval--; - axisval /= 2; - retaxis = joy2ymove[axisval]; - } - -#ifdef _arch_dreamcast - skipDC: -#endif - - if (retaxis < (-JOYAXISRANGE)) - retaxis = -JOYAXISRANGE; - if (retaxis > (+JOYAXISRANGE)) - retaxis = +JOYAXISRANGE; - if (!Joystick2.bGamepadStyle && axissel < AXISDEAD) - { - const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone2.value) >> FRACBITS; + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_digitaldeadzone[player-1].value) >> FRACBITS; if (-jdeadzone < retaxis && retaxis < jdeadzone) return 0; } + if (flp) retaxis = -retaxis; //flip it around return retaxis; } -static INT32 Joy3Axis(axis_input_e axissel) +// Take a magnitude of two axes, and adjust it to take out the deadzone +// Will return a value between 0 and JOYAXISRANGE +static INT32 G_BasicDeadZoneCalculation(INT32 magnitude, fixed_t deadZone) { - INT32 retaxis; - INT32 axisval; - boolean flp = false; + const INT32 jdeadzone = (JOYAXISRANGE * deadZone) / FRACUNIT; + INT32 deadzoneAppliedValue = 0; + INT32 adjustedMagnitude = abs(magnitude); - //find what axis to get - switch (axissel) + if (jdeadzone >= JOYAXISRANGE && adjustedMagnitude >= JOYAXISRANGE) // If the deadzone and magnitude are both 100%... + return JOYAXISRANGE; // ...return 100% input directly, to avoid dividing by 0 + else if (adjustedMagnitude > jdeadzone) // Otherwise, calculate how much the magnitude exceeds the deadzone { - case AXISTURN: - axisval = cv_turnaxis3.value; - break; - case AXISMOVE: - axisval = cv_moveaxis3.value; - break; - case AXISBRAKE: - axisval = cv_brakeaxis3.value; - break; - case AXISAIM: - axisval = cv_aimaxis3.value; - break; - case AXISLOOK: - axisval = cv_lookaxis3.value; - break; - case AXISFIRE: - axisval = cv_fireaxis3.value; - break; - case AXISDRIFT: - axisval = cv_driftaxis3.value; - break; - default: - return 0; + adjustedMagnitude = min(adjustedMagnitude, JOYAXISRANGE); + + adjustedMagnitude -= jdeadzone; + + deadzoneAppliedValue = (adjustedMagnitude * JOYAXISRANGE) / (JOYAXISRANGE - jdeadzone); } - - if (axisval < 0) //odd -axises - { - axisval = -axisval; - flp = true; - } -#ifdef _arch_dreamcast - if (axisval == 7) // special case - { - retaxis = joy3xmove[1] - joy3ymove[1]; - goto skipDC; - } - else -#endif - if (axisval > JOYAXISSET*2 || axisval == 0) //not there in array or None - return 0; - - if (axisval%2) - { - axisval /= 2; - retaxis = joy3xmove[axisval]; - } - else - { - axisval--; - axisval /= 2; - retaxis = joy3ymove[axisval]; - } - -#ifdef _arch_dreamcast - skipDC: -#endif - - if (retaxis < (-JOYAXISRANGE)) - retaxis = -JOYAXISRANGE; - if (retaxis > (+JOYAXISRANGE)) - retaxis = +JOYAXISRANGE; - if (!Joystick3.bGamepadStyle && axissel < AXISDEAD) - { - const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone3.value) >> FRACBITS; - if (-jdeadzone < retaxis && retaxis < jdeadzone) - return 0; - } - if (flp) retaxis = -retaxis; //flip it around - return retaxis; + return deadzoneAppliedValue; } -static INT32 Joy4Axis(axis_input_e axissel) +// Get the actual sensible radial value for a joystick axis when accounting for a deadzone +static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvector) { - INT32 retaxis; - INT32 axisval; - boolean flp = false; + INT32 gamepadStyle = Joystick[splitnum].bGamepadStyle; + fixed_t deadZone = cv_deadzone[splitnum].value; - //find what axis to get - switch (axissel) + // When gamepadstyle is "true" the values are just -1, 0, or 1. This is done in the interface code. + if (!gamepadStyle) { - case AXISTURN: - axisval = cv_turnaxis4.value; - break; - case AXISMOVE: - axisval = cv_moveaxis4.value; - break; - case AXISBRAKE: - axisval = cv_brakeaxis4.value; - break; - case AXISAIM: - axisval = cv_aimaxis4.value; - break; - case AXISLOOK: - axisval = cv_lookaxis4.value; - break; - case AXISFIRE: - axisval = cv_fireaxis4.value; - break; - case AXISDRIFT: - axisval = cv_driftaxis4.value; - break; - default: - return 0; - } + // Get the total magnitude of the 2 axes + INT32 magnitude = (joystickvector->xaxis * joystickvector->xaxis) + (joystickvector->yaxis * joystickvector->yaxis); + INT32 normalisedXAxis; + INT32 normalisedYAxis; + INT32 normalisedMagnitude; + double dMagnitude = sqrt((double)magnitude); + magnitude = (INT32)dMagnitude; - if (axisval < 0) //odd -axises - { - axisval = -axisval; - flp = true; - } -#ifdef _arch_dreamcast - if (axisval == 7) // special case - { - retaxis = joy4xmove[1] - joy4ymove[1]; - goto skipDC; - } - else -#endif - if (axisval > JOYAXISSET*2 || axisval == 0) //not there in array or None - return 0; + // Get the normalised xy values from the magnitude + normalisedXAxis = (joystickvector->xaxis * magnitude) / JOYAXISRANGE; + normalisedYAxis = (joystickvector->yaxis * magnitude) / JOYAXISRANGE; - if (axisval%2) - { - axisval /= 2; - retaxis = joy4xmove[axisval]; - } - else - { - axisval--; - axisval /= 2; - retaxis = joy4ymove[axisval]; - } + // Apply the deadzone to the magnitude to give a correct value between 0 and JOYAXISRANGE + normalisedMagnitude = G_BasicDeadZoneCalculation(magnitude, deadZone); -#ifdef _arch_dreamcast - skipDC: -#endif + // Apply the deadzone to the xy axes + joystickvector->xaxis = (normalisedXAxis * normalisedMagnitude) / JOYAXISRANGE; + joystickvector->yaxis = (normalisedYAxis * normalisedMagnitude) / JOYAXISRANGE; - if (retaxis < (-JOYAXISRANGE)) - retaxis = -JOYAXISRANGE; - if (retaxis > (+JOYAXISRANGE)) - retaxis = +JOYAXISRANGE; - if (!Joystick4.bGamepadStyle && axissel < AXISDEAD) - { - const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone4.value) >> FRACBITS; - if (-jdeadzone < retaxis && retaxis < jdeadzone) - return 0; - } - if (flp) retaxis = -retaxis; //flip it around - return retaxis; -} - -boolean InputDown(INT32 gc, UINT8 p) -{ - switch (p) - { - case 2: - return PLAYER2INPUTDOWN(gc); - case 3: - return PLAYER3INPUTDOWN(gc); - case 4: - return PLAYER4INPUTDOWN(gc); - default: - return PLAYER1INPUTDOWN(gc); - } -} - -INT32 JoyAxis(axis_input_e axissel, UINT8 p) -{ - switch (p) - { - case 2: - return Joy2Axis(axissel); - case 3: - return Joy3Axis(axissel); - case 4: - return Joy4Axis(axissel); - default: - return Joy1Axis(axissel); + // Cap the values so they don't go above the correct maximum + joystickvector->xaxis = min(joystickvector->xaxis, JOYAXISRANGE); + joystickvector->xaxis = max(joystickvector->xaxis, -JOYAXISRANGE); + joystickvector->yaxis = min(joystickvector->yaxis, JOYAXISRANGE); + joystickvector->yaxis = max(joystickvector->yaxis, -JOYAXISRANGE); } } @@ -1261,38 +858,38 @@ INT32 JoyAxis(axis_input_e axissel, UINT8 p) INT32 localaiming[MAXSPLITSCREENPLAYERS]; angle_t localangle[MAXSPLITSCREENPLAYERS]; -static fixed_t forwardmove = MAXPLMOVE<>16; -static fixed_t angleturn[3] = {KART_FULLTURN/2, KART_FULLTURN, KART_FULLTURN/4}; // + slow turn +static INT32 angleturn[2] = {KART_FULLTURN, KART_FULLTURN / 4}; // + slow turn void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { - INT32 laim, th, tspeed, forward, axis; //i - const INT32 speed = 1; - // these ones used for multiple conditions - boolean turnleft, turnright, mouseaiming, analogjoystickmove, gamepadjoystickmove; - boolean invertmouse, lookaxis, usejoystick, kbl, rd; - player_t *player; - camera_t *thiscam; - angle_t lang; + const UINT8 forplayer = ssplayer-1; + + const INT32 lookaxis = cv_lookaxis[forplayer].value; + const boolean invertmouse = cv_invertmouse.value; + const boolean analogjoystickmove = cv_usejoystick[forplayer].value && !Joystick[forplayer].bGamepadStyle; + const boolean gamepadjoystickmove = cv_usejoystick[forplayer].value && Joystick[forplayer].bGamepadStyle; + const boolean usejoystick = (analogjoystickmove || gamepadjoystickmove); static INT32 turnheld[MAXSPLITSCREENPLAYERS]; // for accelerative turning static boolean keyboard_look[MAXSPLITSCREENPLAYERS]; // true if lookup/down using keyboard static boolean resetdown[MAXSPLITSCREENPLAYERS]; // don't cam reset every frame + INT32 tspeed, forward, axis; + + joystickvector2_t joystickvector; + + boolean turnleft, turnright; + + player_t *player = &players[g_localplayers[forplayer]]; + camera_t *thiscam = &camera[forplayer]; + INT32 *th = &turnheld[forplayer]; + boolean *kbl = &keyboard_look[forplayer]; + boolean *rd = &resetdown[forplayer]; + const boolean mouseaiming = player->spectator; + if (demo.playback) return; - if (ssplayer == 1) - player = &players[consoleplayer]; - else - player = &players[g_localplayers[ssplayer-1]]; - - thiscam = &camera[ssplayer-1]; - lang = localangle[ssplayer-1]; - laim = localaiming[ssplayer-1]; - th = turnheld[ssplayer-1]; - kbl = keyboard_look[ssplayer-1]; - rd = resetdown[ssplayer-1]; - + // Is there any reason this can't just be I_BaseTiccmd? switch (ssplayer) { case 2: @@ -1315,195 +912,156 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // Kart, don't build a ticcmd if someone is resynching or the server is stopped too so we don't fly off course in bad conditions if (paused || P_AutoPause() || (gamestate == GS_LEVEL && player->playerstate == PST_REBORN) || hu_resynching) { - cmd->angleturn = (INT16)(lang >> 16); - cmd->aiming = G_ClipAimingPitch(&laim); return; } if (K_PlayerUsesBotMovement(player)) { + // Bot ticcmd is generated by K_BuildBotTiccmd return; } - switch (ssplayer) - { - case 2: - mouseaiming = player->spectator; //(PLAYER2INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook2.value; - invertmouse = cv_invertmouse2.value; - lookaxis = cv_lookaxis2.value; - analogjoystickmove = cv_usejoystick2.value && !Joystick2.bGamepadStyle; - gamepadjoystickmove = cv_usejoystick2.value && Joystick2.bGamepadStyle; - break; - case 3: - mouseaiming = false; - invertmouse = false; - lookaxis = cv_lookaxis3.value; - analogjoystickmove = cv_usejoystick3.value && !Joystick3.bGamepadStyle; - gamepadjoystickmove = cv_usejoystick3.value && Joystick3.bGamepadStyle; - break; - case 4: - mouseaiming = false; - invertmouse = false; - lookaxis = cv_lookaxis4.value; - analogjoystickmove = cv_usejoystick4.value && !Joystick4.bGamepadStyle; - gamepadjoystickmove = cv_usejoystick4.value && Joystick4.bGamepadStyle; - break; - case 1: - default: - mouseaiming = player->spectator; //(PLAYER1INPUTDOWN(gc_mouseaiming)) ^ cv_alwaysfreelook.value; - invertmouse = cv_invertmouse.value; - lookaxis = cv_lookaxis.value; - analogjoystickmove = cv_usejoystick.value && !Joystick.bGamepadStyle; - gamepadjoystickmove = cv_usejoystick.value && Joystick.bGamepadStyle; - break; - } + turnright = PlayerInputDown(ssplayer, gc_turnright); + turnleft = PlayerInputDown(ssplayer, gc_turnleft); - usejoystick = (analogjoystickmove || gamepadjoystickmove); - turnright = InputDown(gc_turnright, ssplayer); - turnleft = InputDown(gc_turnleft, ssplayer); - - axis = JoyAxis(AXISTURN, ssplayer); + joystickvector.xaxis = PlayerJoyAxis(ssplayer, AXISTURN); + joystickvector.yaxis = PlayerJoyAxis(ssplayer, AXISAIM); + G_HandleAxisDeadZone(forplayer, &joystickvector); if (encoremode) { turnright ^= turnleft; // swap these using three XORs turnleft ^= turnright; turnright ^= turnleft; - axis = -axis; + joystickvector.xaxis = -joystickvector.xaxis; } - if (gamepadjoystickmove && axis != 0) + if (gamepadjoystickmove && joystickvector.xaxis != 0) { - turnright = turnright || (axis > 0); - turnleft = turnleft || (axis < 0); + turnright = turnright || (joystickvector.xaxis > 0); + turnleft = turnleft || (joystickvector.xaxis < 0); } forward = 0; // use two stage accelerative turning // on the keyboard and joystick if (turnleft || turnright) - th += realtics; + *th += realtics; else - th = 0; + *th = 0; - if (th < SLOWTURNTICS) - tspeed = 2; // slow turn + if (*th < SLOWTURNTICS) + tspeed = 1; // slow turn else - tspeed = speed; + tspeed = 0; - cmd->driftturn = 0; + cmd->turning = 0; // let movement keys cancel each other out if (turnright && !(turnleft)) { - cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed])); - cmd->driftturn = (INT16)(cmd->driftturn - (angleturn[tspeed])); + cmd->turning = (INT16)(cmd->turning - (angleturn[tspeed])); } else if (turnleft && !(turnright)) { - cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed])); - cmd->driftturn = (INT16)(cmd->driftturn + (angleturn[tspeed])); + cmd->turning = (INT16)(cmd->turning + (angleturn[tspeed])); } - if (analogjoystickmove && axis != 0) + if (analogjoystickmove && joystickvector.xaxis != 0) { - // JOYAXISRANGE should be 1023 (divide by 1024) - cmd->angleturn = (INT16)(cmd->angleturn - (((axis * angleturn[1]) >> 10))); // ANALOG! - cmd->driftturn = (INT16)(cmd->driftturn - (((axis * angleturn[1]) >> 10))); + cmd->turning = (INT16)(cmd->turning - (((joystickvector.xaxis * angleturn[0]) >> 10))); } // Specator mouse turning if (player->spectator) { - cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8))); - cmd->driftturn = (INT16)(cmd->driftturn - ((mousex*(encoremode ? -1 : 1)*8))); + cmd->turning = (INT16)(cmd->turning - ((mousex*(encoremode ? -1 : 1)*8))); } if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls { - axis = JoyAxis(AXISMOVE, ssplayer); - if (InputDown(gc_accelerate, ssplayer) || (usejoystick && axis > 0)) + axis = PlayerJoyAxis(ssplayer, AXISMOVE); + if (PlayerInputDown(ssplayer, gc_accelerate) || (usejoystick && axis > 0)) cmd->buttons |= BT_ACCELERATE; - axis = JoyAxis(AXISBRAKE, ssplayer); - if (InputDown(gc_brake, ssplayer) || (usejoystick && axis > 0)) + axis = PlayerJoyAxis(ssplayer, AXISBRAKE); + if (PlayerInputDown(ssplayer, gc_brake) || (usejoystick && axis > 0)) cmd->buttons |= BT_BRAKE; - axis = JoyAxis(AXISAIM, ssplayer); - if (InputDown(gc_aimforward, ssplayer) || (usejoystick && axis < 0)) - forward += forwardmove; - if (InputDown(gc_aimbackward, ssplayer) || (usejoystick && axis > 0)) - forward -= forwardmove; + axis = PlayerJoyAxis(ssplayer, AXISAIM); + if (PlayerInputDown(ssplayer, gc_aimforward) || (usejoystick && axis < 0)) + forward += MAXPLMOVE; + if (PlayerInputDown(ssplayer, gc_aimbackward) || (usejoystick && axis > 0)) + forward -= MAXPLMOVE; } else { // forward with key or button // SRB2kart - we use an accel/brake instead of forward/backward. - axis = JoyAxis(AXISMOVE, ssplayer); - if (InputDown(gc_accelerate, ssplayer) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer]) + axis = PlayerJoyAxis(ssplayer, AXISMOVE); + if (PlayerInputDown(ssplayer, gc_accelerate) || (gamepadjoystickmove && axis > 0) || player->kartstuff[k_sneakertimer]) { cmd->buttons |= BT_ACCELERATE; - forward = forwardmove; // 50 + forward = MAXPLMOVE; // 50 } else if (analogjoystickmove && axis > 0) { cmd->buttons |= BT_ACCELERATE; // JOYAXISRANGE is supposed to be 1023 (divide by 1024) - forward += ((axis * forwardmove) >> 10); + forward += ((axis * MAXPLMOVE) >> 10); } - axis = JoyAxis(AXISBRAKE, ssplayer); - if (InputDown(gc_brake, ssplayer) || (gamepadjoystickmove && axis > 0)) + axis = PlayerJoyAxis(ssplayer, AXISBRAKE); + if (PlayerInputDown(ssplayer, gc_brake) || (gamepadjoystickmove && axis > 0)) { cmd->buttons |= BT_BRAKE; if (cmd->buttons & BT_ACCELERATE || cmd->forwardmove <= 0) - forward -= forwardmove; + forward -= MAXPLMOVE; } else if (analogjoystickmove && axis > 0) { cmd->buttons |= BT_BRAKE; // JOYAXISRANGE is supposed to be 1023 (divide by 1024) if (cmd->buttons & BT_ACCELERATE || cmd->forwardmove <= 0) - forward -= ((axis * forwardmove) >> 10); + forward -= ((axis * MAXPLMOVE) >> 10); } // But forward/backward IS used for aiming. - axis = JoyAxis(AXISAIM, ssplayer); - if (InputDown(gc_aimforward, ssplayer) || (usejoystick && axis < 0)) + if (PlayerInputDown(ssplayer, gc_aimforward) || (joystickvector.yaxis < 0)) cmd->buttons |= BT_FORWARD; - if (InputDown(gc_aimbackward, ssplayer) || (usejoystick && axis > 0)) + if (PlayerInputDown(ssplayer, gc_aimbackward) || (joystickvector.yaxis > 0)) cmd->buttons |= BT_BACKWARD; } // fire with any button/key - axis = JoyAxis(AXISFIRE, ssplayer); - if (InputDown(gc_fire, ssplayer) || (usejoystick && axis > 0)) + axis = PlayerJoyAxis(ssplayer, AXISFIRE); + if (PlayerInputDown(ssplayer, gc_fire) || (usejoystick && axis > 0)) cmd->buttons |= BT_ATTACK; // drift with any button/key - axis = JoyAxis(AXISDRIFT, ssplayer); - if (InputDown(gc_drift, ssplayer) || (usejoystick && axis > 0)) + axis = PlayerJoyAxis(ssplayer, AXISDRIFT); + if (PlayerInputDown(ssplayer, gc_drift) || (usejoystick && axis > 0)) cmd->buttons |= BT_DRIFT; // rear view with any button/key - axis = JoyAxis(AXISLOOKBACK, ssplayer); - if (InputDown(gc_lookback, ssplayer) || (usejoystick && axis > 0)) + axis = PlayerJoyAxis(ssplayer, AXISLOOKBACK); + if (PlayerInputDown(ssplayer, gc_lookback) || (usejoystick && axis > 0)) cmd->buttons |= BT_LOOKBACK; // Lua scriptable buttons - if (InputDown(gc_custom1, ssplayer)) + if (PlayerInputDown(ssplayer, gc_custom1)) cmd->buttons |= BT_CUSTOM1; - if (InputDown(gc_custom2, ssplayer)) + if (PlayerInputDown(ssplayer, gc_custom2)) cmd->buttons |= BT_CUSTOM2; - if (InputDown(gc_custom3, ssplayer)) + if (PlayerInputDown(ssplayer, gc_custom3)) cmd->buttons |= BT_CUSTOM3; // Reset camera - if (InputDown(gc_camreset, ssplayer)) + if (PlayerInputDown(ssplayer, gc_camreset)) { - if (thiscam->chase && !rd) + if (thiscam->chase && *rd == false) P_ResetCamera(player, thiscam); - rd = true; + *rd = true; } else - rd = false; + *rd = false; // spectator aiming shit, ahhhh... { @@ -1516,84 +1074,44 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // mouse look stuff (mouse look is not the same as mouse aim) if (mouseaiming && player->spectator) { - kbl = false; + *kbl = false; // looking up/down - laim += (mlooky<<19)*player_invert*screen_invert; + cmd->aiming += (mlooky<<19)*player_invert*screen_invert; } - axis = JoyAxis(AXISLOOK, ssplayer); + axis = PlayerJoyAxis(ssplayer, AXISLOOK); if (analogjoystickmove && axis != 0 && lookaxis && player->spectator) - laim += (axis<<16) * screen_invert; + cmd->aiming += (axis<<16) * screen_invert; // spring back if not using keyboard neither mouselookin' - if (!kbl && !lookaxis && !mouseaiming) - laim = 0; + if (*kbl == false && !lookaxis && !mouseaiming) + cmd->aiming = 0; if (player->spectator) { - if (InputDown(gc_lookup, ssplayer) || (gamepadjoystickmove && axis < 0)) + if (PlayerInputDown(ssplayer, gc_lookup) || (gamepadjoystickmove && axis < 0)) { - laim += KB_LOOKSPEED * screen_invert; - kbl = true; + cmd->aiming += KB_LOOKSPEED * screen_invert; + *kbl = true; } - else if (InputDown(gc_lookdown, ssplayer) || (gamepadjoystickmove && axis > 0)) + else if (PlayerInputDown(ssplayer, gc_lookdown) || (gamepadjoystickmove && axis > 0)) { - laim -= KB_LOOKSPEED * screen_invert; - kbl = true; + cmd->aiming -= KB_LOOKSPEED * screen_invert; + *kbl = true; } } - if (InputDown(gc_centerview, ssplayer)) // No need to put a spectator limit on this one though :V - laim = 0; - - // accept no mlook for network games - if (!cv_allowmlook.value) - laim = 0; - - cmd->aiming = G_ClipAimingPitch(&laim); + if (PlayerInputDown(ssplayer, gc_centerview)) // No need to put a spectator limit on this one though :V + cmd->aiming = 0; } mousex = mousey = mlooky = 0; cmd->forwardmove += (SINT8)forward; - if (cmd->forwardmove > MAXPLMOVE) - cmd->forwardmove = MAXPLMOVE; - else if (cmd->forwardmove < -MAXPLMOVE) - cmd->forwardmove = -MAXPLMOVE; - - //{ SRB2kart - Drift support - // Not grouped with the rest of turn stuff because it needs to know what buttons you're pressing for rubber-burn turn - // limit turning to angleturn[1] to stop mouselook letting you look too fast - if (cmd->angleturn > (angleturn[1])) - cmd->angleturn = (angleturn[1]); - else if (cmd->angleturn < (-angleturn[1])) - cmd->angleturn = (-angleturn[1]); - - if (cmd->driftturn > (angleturn[1])) - cmd->driftturn = (angleturn[1]); - else if (cmd->driftturn < (-angleturn[1])) - cmd->driftturn = (-angleturn[1]); - - if (player->mo) - cmd->angleturn = K_GetKartTurnValue(player, cmd->angleturn); - - cmd->angleturn *= realtics; - - lang += (cmd->angleturn<<16); - - cmd->angleturn = (INT16)(lang >> 16); cmd->latency = modeattacking ? 0 : (leveltime & 0xFF); // Send leveltime when this tic was generated to the server for control lag calculations - - if (!hu_stopped) - { - localangle[ssplayer-1] = lang; - localaiming[ssplayer-1] = laim; - keyboard_look[ssplayer-1] = kbl; - turnheld[ssplayer-1] = th; - resetdown[ssplayer-1] = rd; - } + cmd->flags = 0; /* Lua: Allow this hook to overwrite ticcmd. We check if we're actually in a level because for some reason this Hook would run in menus and on the titlescreen otherwise. @@ -1605,118 +1123,48 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) -Making some galaxy brain autopilot Lua if you're a masochist -Making a Mario Kart 8 Deluxe tier baby mode that steers you away from walls and whatnot. You know what, do what you want! */ -#ifdef HAVE_BLUA if (gamestate == GS_LEVEL) LUAh_PlayerCmd(player, cmd); -#endif - //Reset away view if a command is given. + if (cmd->forwardmove > MAXPLMOVE) + cmd->forwardmove = MAXPLMOVE; + else if (cmd->forwardmove < -MAXPLMOVE) + cmd->forwardmove = -MAXPLMOVE; + + if (cmd->turning > (angleturn[0])) + cmd->turning = (angleturn[0]); + else if (cmd->turning < (-angleturn[0])) + cmd->turning = (-angleturn[0]); + + // Reset away view if a command is given. if ((cmd->forwardmove || cmd->buttons) && !r_splitscreen && displayplayers[0] != consoleplayer && ssplayer == 1) + { + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(player, &players[consoleplayer], true); displayplayers[0] = consoleplayer; -} - -// User has designated that they want -// analog ON, so tell the game to stop -// fudging with it. -static void UserAnalog_OnChange(void) -{ - /*if (cv_useranalog.value) - CV_SetValue(&cv_analog, 1); - else - CV_SetValue(&cv_analog, 0);*/ -} - -static void UserAnalog2_OnChange(void) -{ - /*if (cv_useranalog2.value) - CV_SetValue(&cv_analog2, 1); - else - CV_SetValue(&cv_analog2, 0);*/ -} - -static void UserAnalog3_OnChange(void) -{ - /*if (cv_useranalog3.value) - CV_SetValue(&cv_analog3, 1); - else - CV_SetValue(&cv_analog3, 0);*/ -} - -static void UserAnalog4_OnChange(void) -{ - /*if (cv_useranalog4.value) - CV_SetValue(&cv_analog4, 1); - else - CV_SetValue(&cv_analog4, 0);*/ -} - -static void Analog_OnChange(void) -{ - if (!cv_cam_dist.string) - return; - - // cameras are not initialized at this point - - /* - if (!cv_chasecam.value && cv_analog.value) { - CV_SetValue(&cv_analog, 0); - return; } - */ - - SendWeaponPref(); } -static void Analog2_OnChange(void) +ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) { - if (!splitscreen || !cv_cam2_dist.string) - return; - - // cameras are not initialized at this point - - /* - if (!cv_chasecam2.value && cv_analog2.value) { - CV_SetValue(&cv_analog2, 0); - return; - } - */ - - SendWeaponPref2(); + return M_Memcpy(dest, src, n*sizeof(*src)); } -static void Analog3_OnChange(void) +ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) { - if (splitscreen < 2 || !cv_cam3_dist.string) - return; - - // cameras are not initialized at this point - - /* - if (!cv_chasecam3.value && cv_analog3.value) { - CV_SetValue(&cv_analog3, 0); - return; + size_t i; + for (i = 0; i < n; i++) + { + dest[i].forwardmove = src[i].forwardmove; + dest[i].turning = (INT16)SHORT(src[i].turning); + dest[i].aiming = (INT16)SHORT(src[i].aiming); + dest[i].buttons = (UINT16)SHORT(src[i].buttons); + dest[i].latency = src[i].latency; + dest[i].flags = src[i].flags; } - */ - - SendWeaponPref3(); -} - -static void Analog4_OnChange(void) -{ - if (splitscreen < 3 || !cv_cam4_dist.string) - return; - - // cameras are not initialized at this point - - /* - if (!cv_chasecam4.value && cv_analog4.value) { - CV_SetValue(&cv_analog4, 0); - return; - } - */ - - SendWeaponPref4(); + return dest; } // @@ -1724,7 +1172,7 @@ static void Analog4_OnChange(void) // void G_DoLoadLevel(boolean resetplayer) { - INT32 i; + INT32 i, j; // Make sure objectplace is OFF when you first start the level! OP_ResetObjectplace(); @@ -1739,7 +1187,23 @@ void G_DoLoadLevel(boolean resetplayer) if (gamestate == GS_VOTING) Y_EndVote(); + // cleanup + if (titlemapinaction == TITLEMAP_LOADING) + { + if (W_CheckNumForName(G_BuildMapName(gamemap)) == LUMPERROR) + { + titlemap = 0; // let's not infinite recursion ok + Command_ExitGame_f(); + return; + } + + titlemapinaction = TITLEMAP_RUNNING; + } + else + titlemapinaction = TITLEMAP_OFF; + G_SetGamestate(GS_LEVEL); + I_UpdateMouseGrab(); for (i = 0; i < MAXPLAYERS; i++) { @@ -1748,16 +1212,13 @@ void G_DoLoadLevel(boolean resetplayer) } // Setup the level. - if (!P_SetupLevel(false)) + if (!P_LoadLevel(false)) // this never returns false? { // fail so reset game stuff Command_ExitGame_f(); return; } - if (!resetplayer) - P_FindEmerald(); - gameaction = ga_nothing; #ifdef PARANOIA Z_CheckHeap(-2); @@ -1773,13 +1234,10 @@ void G_DoLoadLevel(boolean resetplayer) memset(gamekeydown, 0, sizeof (gamekeydown)); for (i = 0;i < JOYAXISSET; i++) { - joyxmove[i] = joyymove[i] = 0; - joy2xmove[i] = joy2ymove[i] = 0; - joy3xmove[i] = joy3ymove[i] = 0; - joy4xmove[i] = joy4ymove[i] = 0; + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + joyxmove[j][i] = joyymove[j][i] = 0; } mousex = mousey = 0; - mouse2x = mouse2y = 0; // clear hud messages remains (usually from game startup) CON_ClearHUD(); @@ -1787,9 +1245,74 @@ void G_DoLoadLevel(boolean resetplayer) server_lagless = cv_lagless.value; } -static INT32 pausedelay = 0; -static INT32 camtoggledelay, camtoggledelay2, camtoggledelay3, camtoggledelay4 = 0; -static INT32 spectatedelay, spectatedelay2, spectatedelay3, spectatedelay4 = 0; +// +// Start the title card. +// +void G_StartTitleCard(void) +{ + // The title card has been disabled for this map. + // Oh well. + if (!G_IsTitleCardAvailable()) + { + WipeStageTitle = false; + return; + } + + // clear the hud + CON_ClearHUD(); + + // prepare status bar + ST_startTitleCard(); + + // start the title card + WipeStageTitle = false; //(!titlemapinaction); -- temporary until titlecards are reworked +} + +// +// Run the title card before fading in to the level. +// +void G_PreLevelTitleCard(void) +{ +#ifndef NOWIPE + tic_t strtime = I_GetTime(); + tic_t endtime = strtime + (PRELEVELTIME*NEWTICRATERATIO); + tic_t nowtime = strtime; + tic_t lasttime = strtime; + while (nowtime < endtime) + { + // draw loop + while (!((nowtime = I_GetTime()) - lasttime)) + I_Sleep(); + lasttime = nowtime; + + ST_runTitleCard(); + ST_preLevelTitleCardDrawer(); + I_FinishUpdate(); // page flip or blit buffer + + if (moviemode) + M_SaveFrame(); + if (takescreenshot) // Only take screenshots after drawing. + M_DoScreenShot(); + } +#endif +} + +// +// Returns true if the current level has a title card. +// +boolean G_IsTitleCardAvailable(void) +{ + // The current level has no name. + if (!mapheaderinfo[gamemap-1]->lvlttl[0]) + return false; + + // The title card is available. + return true; +} + +INT32 pausedelay = 0; +boolean pausebreakkey = false; +static INT32 camtoggledelay[MAXSPLITSCREENPLAYERS]; // // G_Responder @@ -1797,11 +1320,13 @@ static INT32 spectatedelay, spectatedelay2, spectatedelay3, spectatedelay4 = 0; // boolean G_Responder(event_t *ev) { + UINT8 i; + // any other key pops up menu if in demos if (gameaction == ga_nothing && !demo.quitafterplaying && ((demo.playback && !modeattacking && !demo.title && !multiplayer) || gamestate == GS_TITLESCREEN)) { - if (ev->type == ev_keydown && ev->data1 != 301) + if (ev->type == ev_keydown && ev->data1 != 301 && !(gamestate == GS_TITLESCREEN && finalecount < TICRATE)) { M_StartControlPanel(); return true; @@ -1848,35 +1373,37 @@ boolean G_Responder(event_t *ev) return true; } } - - else if (gamestate == GS_CREDITS) + else if (gamestate == GS_CREDITS || gamestate == GS_ENDING) // todo: keep ending here? { if (HU_Responder(ev)) return true; // chat ate the event if (F_CreditResponder(ev)) { - F_StartGameEvaluation(); + // Skip credits for everyone + if (! netgame) + F_StartGameEvaluation(); + else if (server || IsPlayerAdmin(consoleplayer)) + SendNetXCmd(XD_EXITLEVEL, NULL, 0); return true; } } - else if (gamestate == GS_CONTINUING) { - if (F_ContinueResponder(ev)) - return true; + return true; } // Demo End - else if (gamestate == GS_GAMEEND || gamestate == GS_EVALUATION || gamestate == GS_CREDITS) + else if (gamestate == GS_GAMEEND) + { return true; - - else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_WAITINGPLAYERS) + } + else if (gamestate == GS_INTERMISSION || gamestate == GS_VOTING || gamestate == GS_EVALUATION) if (HU_Responder(ev)) return true; // chat ate the event // allow spy mode changes even during the demo if (gamestate == GS_LEVEL && ev->type == ev_keydown - && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[gc_viewpoint][0] || ev->data1 == gamecontrol[gc_viewpoint][1])) + && (ev->data1 == KEY_F12 || ev->data1 == gamecontrol[0][gc_viewpoint][0] || ev->data1 == gamecontrol[0][gc_viewpoint][1])) { if (!demo.playback && (r_splitscreen || !netgame)) g_localplayers[0] = consoleplayer; @@ -1894,29 +1421,26 @@ boolean G_Responder(event_t *ev) if (gamestate == GS_LEVEL && ev->type == ev_keydown && multiplayer && demo.playback && !demo.freecam) { - if (ev->data1 == gamecontrolbis[gc_viewpoint][0] || ev->data1 == gamecontrolbis[gc_viewpoint][1]) + if (ev->data1 == gamecontrol[1][gc_viewpoint][0] || ev->data1 == gamecontrol[1][gc_viewpoint][1]) { G_AdjustView(2, 1, true); - return true; } - else if (ev->data1 == gamecontrol3[gc_viewpoint][0] || ev->data1 == gamecontrol3[gc_viewpoint][1]) + else if (ev->data1 == gamecontrol[2][gc_viewpoint][0] || ev->data1 == gamecontrol[2][gc_viewpoint][1]) { G_AdjustView(3, 1, true); - return true; } - else if (ev->data1 == gamecontrol4[gc_viewpoint][0] || ev->data1 == gamecontrol4[gc_viewpoint][1]) + else if (ev->data1 == gamecontrol[3][gc_viewpoint][0] || ev->data1 == gamecontrol[3][gc_viewpoint][1]) { G_AdjustView(4, 1, true); - return true; } // Allow pausing if ( - ev->data1 == gamecontrol[gc_pause][0] - || ev->data1 == gamecontrol[gc_pause][1] + ev->data1 == gamecontrol[0][gc_pause][0] + || ev->data1 == gamecontrol[0][gc_pause][1] || ev->data1 == KEY_PAUSE ) { @@ -1951,92 +1475,48 @@ boolean G_Responder(event_t *ev) switch (ev->type) { case ev_keydown: - if (ev->data1 == gamecontrol[gc_pause][0] - || ev->data1 == gamecontrol[gc_pause][1] + if (ev->data1 == gamecontrol[0][gc_pause][0] + || ev->data1 == gamecontrol[0][gc_pause][1] || ev->data1 == KEY_PAUSE) { - if (!pausedelay) + if (modeattacking && !demo.playback && (gamestate == GS_LEVEL)) { - // don't let busy scripts prevent pausing - pausedelay = NEWTICRATE/7; + pausebreakkey = (ev->data1 == KEY_PAUSE); + if (menuactive || pausedelay < 0 || leveltime < 2) + return true; - // command will handle all the checks for us - COM_ImmedExecute("pause"); - return true; + if (pausedelay < 1+(NEWTICRATE/2)) + pausedelay = 1+(NEWTICRATE/2); + else if (++pausedelay > 1+(NEWTICRATE/2)+(NEWTICRATE/3)) + { + G_SetModeAttackRetryFlag(); + return true; + } + pausedelay++; // counteract subsequent subtraction this frame } else - pausedelay = NEWTICRATE/7; - } - if (ev->data1 == gamecontrol[gc_camtoggle][0] - || ev->data1 == gamecontrol[gc_camtoggle][1]) - { - if (!camtoggledelay) { - camtoggledelay = NEWTICRATE / 7; - CV_SetValue(&cv_chasecam, cv_chasecam.value ? 0 : 1); + INT32 oldpausedelay = pausedelay; + pausedelay = (NEWTICRATE/7); + if (!oldpausedelay) + { + // command will handle all the checks for us + COM_ImmedExecute("pause"); + return true; + } } } - if (ev->data1 == gamecontrolbis[gc_camtoggle][0] - || ev->data1 == gamecontrolbis[gc_camtoggle][1]) + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (!camtoggledelay2) + if (ev->data1 == gamecontrol[i][gc_camtoggle][0] + || ev->data1 == gamecontrol[i][gc_camtoggle][1]) { - camtoggledelay2 = NEWTICRATE / 7; - CV_SetValue(&cv_chasecam2, cv_chasecam2.value ? 0 : 1); - } - } - if (ev->data1 == gamecontrol3[gc_camtoggle][0] - || ev->data1 == gamecontrol3[gc_camtoggle][1]) - { - if (!camtoggledelay3) - { - camtoggledelay3 = NEWTICRATE / 7; - CV_SetValue(&cv_chasecam3, cv_chasecam3.value ? 0 : 1); - } - } - if (ev->data1 == gamecontrol4[gc_camtoggle][0] - || ev->data1 == gamecontrol4[gc_camtoggle][1]) - { - if (!camtoggledelay4) - { - camtoggledelay4 = NEWTICRATE / 7; - CV_SetValue(&cv_chasecam4, cv_chasecam4.value ? 0 : 1); - } - } - if (ev->data1 == gamecontrol[gc_spectate][0] - || ev->data1 == gamecontrol[gc_spectate][1]) - { - if (!spectatedelay) - { - spectatedelay = NEWTICRATE / 7; - COM_ImmedExecute("changeteam spectator"); - } - } - if (ev->data1 == gamecontrolbis[gc_spectate][0] - || ev->data1 == gamecontrolbis[gc_spectate][1]) - { - if (!spectatedelay2) - { - spectatedelay2 = NEWTICRATE / 7; - COM_ImmedExecute("changeteam2 spectator"); - } - } - if (ev->data1 == gamecontrol3[gc_spectate][0] - || ev->data1 == gamecontrol3[gc_spectate][1]) - { - if (!spectatedelay3) - { - spectatedelay3 = NEWTICRATE / 7; - COM_ImmedExecute("changeteam3 spectator"); - } - } - if (ev->data1 == gamecontrol4[gc_spectate][0] - || ev->data1 == gamecontrol4[gc_spectate][1]) - { - if (!spectatedelay4) - { - spectatedelay4 = NEWTICRATE / 7; - COM_ImmedExecute("changeteam4 spectator"); + if (!camtoggledelay[i]) + { + camtoggledelay[i] = NEWTICRATE / 7; + CV_SetValue(&cv_chasecam[i], cv_chasecam[i].value ? 0 : 1); + } } } @@ -2089,40 +1569,22 @@ boolean G_CouldView(INT32 playernum) // SRB2Kart: Only go through players who are actually playing if (player->exiting) return false; - if (( player->pflags & PF_TIMEOVER )) + if (( player->pflags & PF_GAMETYPEOVER )) return false; // I don't know if we want this actually, but I'll humor the suggestion anyway - if (G_BattleGametype() && !demo.playback) + if ((gametyperules & GTR_BUMPERS) && !demo.playback) { if (player->kartstuff[k_bumper] <= 0) return false; } // SRB2Kart: we have no team-based modes, YET... - /*if (G_GametypeHasTeams()) + if (G_GametypeHasTeams()) { - if (players[consoleplayer].ctfteam - && player->ctfteam != players[consoleplayer].ctfteam) + if (players[consoleplayer].ctfteam && player->ctfteam != players[consoleplayer].ctfteam) return false; } - else if (gametype == GT_HIDEANDSEEK) - { - if (players[consoleplayer].pflags & PF_TAGIT) - return false; - } - // Other Tag-based gametypes? - else if (G_TagGametype()) - { - if (!players[consoleplayer].spectator - && (players[consoleplayer].pflags & PF_TAGIT) != (player->pflags & PF_TAGIT)) - return false; - } - else if (G_GametypeHasSpectators() && G_BattleGametype()) - { - if (!players[consoleplayer].spectator) - return false; - }*/ return true; } @@ -2326,7 +1788,9 @@ void G_Ticker(boolean run) INT32 buf; ticcmd_t *cmd; - // also the -1 is to ensure that the thinker runs in the loop below. + // see also SCR_DisplayMarathonInfo + if ((marathonmode & (MA_INIT|MA_INGAME)) == MA_INGAME && gamestate == GS_LEVEL) + marathontime++; P_MapStart(); // do player reborns if needed @@ -2370,25 +1834,26 @@ void G_Ticker(boolean run) buf = gametic % TICQUEUE; if (!demo.playback) - // read/write demo and check turbo cheat - for (i = 0; i < MAXPLAYERS; i++) { - cmd = &players[i].cmd; - - if (playeringame[i]) + for (i = 0; i < MAXPLAYERS; i++) { - G_CopyTiccmd(cmd, &netcmds[buf][i], 1); + cmd = &players[i].cmd; - // Use the leveltime sent in the player's ticcmd to determine control lag - if (modeattacking || K_PlayerUsesBotMovement(&players[i])) + if (playeringame[i]) { - // Never has lag - cmd->latency = 0; - } - else - { - //@TODO add a cvar to allow setting this max - cmd->latency = min(((leveltime & 0xFF) - cmd->latency) & 0xFF, MAXPREDICTTICS-1); + G_CopyTiccmd(cmd, &netcmds[buf][i], 1); + + // Use the leveltime sent in the player's ticcmd to determine control lag + if (K_PlayerUsesBotMovement(&players[i])) + { + // Never has lag + cmd->latency = 0; + } + else + { + //@TODO add a cvar to allow setting this max + cmd->latency = min(((leveltime & 0xFF) - cmd->latency) & 0xFF, MAXPREDICTTICS-1); + } } } } @@ -2400,7 +1865,8 @@ void G_Ticker(boolean run) if (demo.title) F_TitleDemoTicker(); P_Ticker(run); // tic the game - ST_Ticker(); + ST_Ticker(run); + F_TextPromptTicker(); AM_Ticker(); HU_Ticker(); break; @@ -2418,6 +1884,7 @@ void G_Ticker(boolean run) break; case GS_TIMEATTACK: + F_MenuPresTicker(run); break; case GS_INTRO: @@ -2425,6 +1892,12 @@ void G_Ticker(boolean run) F_IntroTicker(); break; + case GS_ENDING: + if (run) + F_EndingTicker(); + HU_Ticker(); + break; + case GS_CUTSCENE: if (run) F_CutsceneTicker(); @@ -2439,11 +1912,10 @@ void G_Ticker(boolean run) case GS_EVALUATION: if (run) F_GameEvaluationTicker(); + HU_Ticker(); break; case GS_CONTINUING: - if (run) - F_ContinueTicker(); break; case GS_CREDITS: @@ -2453,8 +1925,10 @@ void G_Ticker(boolean run) break; case GS_TITLESCREEN: + if (titlemapinaction) P_Ticker(run); F_TitleScreenTicker(run); break; + case GS_WAITINGPLAYERS: if (netgame) F_WaitingPlayersTicker(); @@ -2471,28 +1945,28 @@ void G_Ticker(boolean run) if (G_GametypeHasSpectators() && (gamestate == GS_LEVEL || gamestate == GS_INTERMISSION || gamestate == GS_VOTING // definitely good || gamestate == GS_WAITINGPLAYERS)) // definitely a problem if we don't do it at all in this gamestate, but might need more protection? + { K_CheckSpectateStatus(); + } - if (pausedelay) - pausedelay--; + if (pausedelay && pausedelay != INT32_MIN) + { + if (pausedelay > 0) + pausedelay--; + else + pausedelay++; + } - if (camtoggledelay) - camtoggledelay--; - if (camtoggledelay2) - camtoggledelay2--; - if (camtoggledelay3) - camtoggledelay3--; - if (camtoggledelay4) - camtoggledelay4--; + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (camtoggledelay[i]) + camtoggledelay[i]--; + } - if (spectatedelay) - spectatedelay--; - if (spectatedelay2) - spectatedelay2--; - if (spectatedelay3) - spectatedelay3--; - if (spectatedelay4) - spectatedelay4--; + if (gametic % NAMECHANGERATE == 0) + { + memset(player_name_changes, 0, sizeof player_name_changes); + } } } @@ -2513,7 +1987,6 @@ static inline void G_PlayerFinishLevel(INT32 player) memset(p->powers, 0, sizeof (p->powers)); memset(p->kartstuff, 0, sizeof (p->kartstuff)); // SRB2kart - p->ringweapons = 0; p->mo->drawflags &= ~(MFD_TRANSMASK|MFD_BRIGHTMASK); // cancel invisibility P_FlashPal(p, 0, 0); // Resets @@ -2527,9 +2000,9 @@ static inline void G_PlayerFinishLevel(INT32 player) if (legitimateexit && !demo.playback && !mapreset) // (yes you're allowed to unlock stuff this way when the game is modified) { matchesplayed++; - if (M_UpdateUnlockablesAndExtraEmblems(true)) + if (M_UpdateUnlockablesAndExtraEmblems()) S_StartSound(NULL, sfx_ncitem); - G_SaveGameData(true); + G_SaveGameData(); } legitimateexit = false; @@ -2540,40 +2013,54 @@ static inline void G_PlayerFinishLevel(INT32 player) // G_PlayerReborn // Called after a player dies. Almost everything is cleared and initialized. // -void G_PlayerReborn(INT32 player) +void G_PlayerReborn(INT32 player, boolean betweenmaps) { player_t *p; INT32 score, marescore; INT32 lives; boolean lostlife; INT32 continues; - // SRB2kart + UINT8 kartspeed; UINT8 kartweight; + boolean followerready; INT32 followerskin; - UINT8 followercolor; - mobj_t *follower; // old follower, will probably be removed by the time we're dead but you never know. - // + UINT16 followercolor; + mobj_t *follower; // old follower, will probably be removed by the time we're dead but you never know. + INT32 charflags; + UINT32 followitem; + INT32 pflags; + INT32 ctfteam; + INT32 starpostnum; INT32 exiting; + tic_t dashmode; INT16 numboxes; INT16 totalring; UINT8 laps; UINT8 mare; - UINT8 skincolor; + UINT16 skincolor; INT32 skin; + UINT32 availabilities; + tic_t jointime; + tic_t quittime; + UINT8 splitscreenindex; boolean spectator; boolean bot; UINT8 botdifficulty; + + INT16 rings; + angle_t playerangleturn; + UINT8 botdiffincrease; boolean botrival; - SINT8 pity; + SINT8 xtralife; // SRB2kart @@ -2586,7 +2073,6 @@ void G_PlayerReborn(INT32 player) INT32 bumper; INT32 comebackpoints; INT32 wanted; - INT32 rings; boolean songcredit = false; score = players[player].score; @@ -2596,51 +2082,64 @@ void G_PlayerReborn(INT32 player) continues = players[player].continues; ctfteam = players[player].ctfteam; exiting = players[player].exiting; + jointime = players[player].jointime; + quittime = players[player].quittime; + splitscreenindex = players[player].splitscreenindex; spectator = players[player].spectator; - pflags = (players[player].pflags & (PF_TIMEOVER|PF_TAGIT|PF_TAGGED|PF_WANTSTOJOIN)); + + pflags = (players[player].pflags & (PF_WANTSTOJOIN|PF_GAMETYPEOVER|PF_FAULT)); + playerangleturn = players[player].angleturn; // As long as we're not in multiplayer, carry over cheatcodes from map to map if (!(netgame || multiplayer)) pflags |= (players[player].pflags & (PF_GODMODE|PF_NOCLIP|PF_INVIS)); + dashmode = players[player].dashmode; + numboxes = players[player].numboxes; laps = players[player].laps; totalring = players[player].totalring; skincolor = players[player].skincolor; skin = players[player].skin; + // SRB2kart kartspeed = players[player].kartspeed; kartweight = players[player].kartweight; + follower = players[player].follower; followerready = players[player].followerready; followercolor = players[player].followercolor; followerskin = players[player].followerskin; - // + + availabilities = players[player].availabilities; + charflags = players[player].charflags; starpostnum = players[player].starpostnum; + followitem = players[player].followitem; mare = players[player].mare; bot = players[player].bot; botdifficulty = players[player].botvars.difficulty; + botdiffincrease = players[player].botvars.diffincrease; botrival = players[player].botvars.rival; - pity = players[player].pity; + xtralife = players[player].xtralife; // SRB2kart - if (leveltime <= starttime) + if (betweenmaps || leveltime < starttime) { itemroulette = 0; roulettetype = 0; itemtype = 0; itemamount = 0; growshrinktimer = 0; - bumper = (G_BattleGametype() ? K_StartingBumperCount() : 0); - rings = (G_BattleGametype() ? 0 : 5); + bumper = ((gametyperules & GTR_BUMPERS) ? K_StartingBumperCount() : 0); + rings = ((gametyperules & GTR_RINGS) ? 5 : 0); comebackpoints = 0; wanted = 0; } @@ -2667,7 +2166,7 @@ void G_PlayerReborn(INT32 player) growshrinktimer = 0; bumper = players[player].kartstuff[k_bumper]; - rings = players[player].kartstuff[k_rings]; + rings = players[player].rings; comebackpoints = players[player].kartstuff[k_comebackpoints]; wanted = players[player].kartstuff[k_wanted]; } @@ -2688,21 +2187,26 @@ void G_PlayerReborn(INT32 player) p->pflags = pflags; p->ctfteam = ctfteam; p->jointime = jointime; + p->quittime = quittime; p->splitscreenindex = splitscreenindex; p->spectator = spectator; + p->angleturn = playerangleturn; // save player config truth reborn p->skincolor = skincolor; p->skin = skin; - // SRB2kart p->kartspeed = kartspeed; p->kartweight = kartweight; // p->charflags = charflags; + p->availabilities = availabilities; + p->followitem = followitem; p->starpostnum = starpostnum; p->exiting = exiting; + p->dashmode = dashmode; + p->numboxes = numboxes; p->laps = laps; p->totalring = totalring; @@ -2710,9 +2214,9 @@ void G_PlayerReborn(INT32 player) p->mare = mare; p->bot = bot; p->botvars.difficulty = botdifficulty; + p->rings = rings; p->botvars.diffincrease = botdiffincrease; p->botvars.rival = botrival; - p->pity = pity; p->xtralife = xtralife; // SRB2kart @@ -2722,7 +2226,6 @@ void G_PlayerReborn(INT32 player) p->kartstuff[k_itemamount] = itemamount; p->kartstuff[k_growshrinktimer] = growshrinktimer; p->kartstuff[k_bumper] = bumper; - p->kartstuff[k_rings] = rings; p->kartstuff[k_comebackpoints] = comebackpoints; p->kartstuff[k_comebacktimer] = comebacktime; p->kartstuff[k_wanted] = wanted; @@ -2742,16 +2245,44 @@ void G_PlayerReborn(INT32 player) // Don't do anything immediately - p->pflags |= PF_USEDOWN; + p->pflags |= PF_SPINDOWN; p->pflags |= PF_ATTACKDOWN; p->pflags |= PF_JUMPDOWN; p->playerstate = PST_LIVE; - p->health = 1; // 0 rings p->panim = PA_IDLE; // standing animation - if ((netgame || multiplayer) && !p->spectator) - p->powers[pw_flashing] = K_GetKartFlashing(p)-1; // Babysitting deterrent + // Check to make sure their color didn't change somehow... + if (G_GametypeHasTeams()) + { + UINT8 i; + + if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) + { + for (i = 0; i <= splitscreen; i++) + { + if (p == &players[g_localplayers[i]]) + { + CV_SetValue(&cv_playercolor[i], skincolor_redteam); + break; + } + } + } + else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) + { + for (i = 0; i <= splitscreen; i++) + { + if (p == &players[g_localplayers[i]]) + { + CV_SetValue(&cv_playercolor[i], skincolor_blueteam); + break; + } + } + } + } + + if (betweenmaps) + return; if (p-players == consoleplayer) { @@ -2764,6 +2295,11 @@ void G_PlayerReborn(INT32 player) mapmusresume = 0; songcredit = true; } + + // This is in S_Start, but this was not here previously. + // if (RESETMUSIC) + // S_StopMusic(); + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); } P_RestoreMusic(p); @@ -2775,47 +2311,6 @@ void G_PlayerReborn(INT32 player) { K_DoIngameRespawn(p); } - - if (gametype == GT_COOP) - P_FindEmerald(); // scan for emeralds to hunt for - - // Reset Nights score and max link to 0 on death - p->maxlink = 0; - - // If NiGHTS, find lowest mare to start with. - p->mare = 0; /*P_FindLowestMare(); - - CONS_Debug(DBG_NIGHTS, M_GetText("Current mare is %d\n"), p->mare); - - if (p->mare == 255) - p->mare = 0;*/ - - // Check to make sure their color didn't change somehow... - /*if (G_GametypeHasTeams()) - { - if (p->ctfteam == 1 && p->skincolor != skincolor_redteam) - { - if (p == &players[consoleplayer]) - CV_SetValue(&cv_playercolor, skincolor_redteam); - else if (p == &players[displayplayers[1]]) - CV_SetValue(&cv_playercolor2, skincolor_redteam); - else if (p == &players[displayplayers[2]]) - CV_SetValue(&cv_playercolor3, skincolor_redteam); - else if (p == &players[displayplayers[3]]) - CV_SetValue(&cv_playercolor4, skincolor_redteam); - } - else if (p->ctfteam == 2 && p->skincolor != skincolor_blueteam) - { - if (p == &players[consoleplayer]) - CV_SetValue(&cv_playercolor, skincolor_blueteam); - else if (p == &players[displayplayers[1]]) - CV_SetValue(&cv_playercolor2, skincolor_blueteam); - else if (p == &players[displayplayers[2]]) - CV_SetValue(&cv_playercolor3, skincolor_blueteam); - else if (p == &players[displayplayers[3]]) - CV_SetValue(&cv_playercolor4, skincolor_blueteam); - } - }*/ } // @@ -2865,96 +2360,32 @@ static boolean G_CheckSpot(INT32 playernum, mapthing_t *mthing) // or a not-so-appropriate spot, if it initially fails // due to a lack of starts open or something. // -void G_SpawnPlayer(INT32 playernum, boolean starpost) +void G_SpawnPlayer(INT32 playernum) { - mapthing_t *spawnpoint; - if (!playeringame[playernum]) return; P_SpawnPlayer(playernum); - - if (starpost) //Don't even bother with looking for a place to spawn. - { - P_MovePlayerToStarpost(playernum); -#ifdef HAVE_BLUA - LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) -#endif - return; - } - - // -- Record Attack -- - if (modeattacking || battlecapsules) - spawnpoint = playerstarts[0]; - - // -- CTF -- - // Order: CTF->DM->Coop - else if (gametype == GT_CTF && players[playernum].ctfteam) - { - if (!(spawnpoint = G_FindCTFStart(playernum)) // find a CTF start - && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start - spawnpoint = G_FindRaceStart(playernum); // fallback - } - - // -- DM/Tag/CTF-spectator/etc -- - // Order: DM->CTF->Coop - else if (gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF - || ((gametype == GT_TAG || gametype == GT_HIDEANDSEEK) && !(players[playernum].pflags & PF_TAGIT))) - { - if (!(spawnpoint = G_FindMatchStart(playernum)) // find a DM start - && !(spawnpoint = G_FindCTFStart(playernum))) // find a CTF start - spawnpoint = G_FindRaceStart(playernum); // fallback - } - - // -- Other game modes -- - // Order: Coop->DM->CTF - else - { - if (!(spawnpoint = G_FindRaceStart(playernum)) // find a Race start - && !(spawnpoint = G_FindMatchStart(playernum))) // find a DM start - spawnpoint = G_FindCTFStart(playernum); // fallback - } - - //No spawns found. ANYWHERE. - if (!spawnpoint) - { - if (nummapthings) - { - if (playernum == consoleplayer - || (splitscreen && playernum == g_localplayers[1]) - || (splitscreen > 1 && playernum == g_localplayers[2]) - || (splitscreen > 2 && playernum == g_localplayers[3])) - CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n")); - spawnpoint = &mapthings[0]; - } - else - { - if (playernum == consoleplayer - || (splitscreen && playernum == g_localplayers[1]) - || (splitscreen > 1 && playernum == g_localplayers[2]) - || (splitscreen > 2 && playernum == g_localplayers[3])) - CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n")); - //P_MovePlayerToSpawn handles this fine if the spawnpoint is NULL. - } - } - P_MovePlayerToSpawn(playernum, spawnpoint); - -#ifdef HAVE_BLUA + G_MovePlayerToSpawnOrStarpost(playernum); LUAh_PlayerSpawn(&players[playernum]); // Lua hook for player spawning :) -#endif - } -mapthing_t *G_FindCTFStart(INT32 playernum) +void G_MovePlayerToSpawnOrStarpost(INT32 playernum) { + if (leveltime > starttime) + P_MovePlayerToStarpost(playernum); + else + P_MovePlayerToSpawn(playernum, G_FindMapStart(playernum)); +} + +mapthing_t *G_FindTeamStart(INT32 playernum) +{ + const boolean doprints = P_IsLocalPlayer(&players[playernum]); INT32 i,j; if (!numredctfstarts && !numbluectfstarts) //why even bother, eh? { - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) + if ((gametyperules & GTR_TEAMSTARTS) && doprints) CONS_Alert(CONS_WARNING, M_GetText("No CTF starts in this map!\n")); return NULL; } @@ -2963,10 +2394,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum) { if (!numredctfstarts) { - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) + if (doprints) CONS_Alert(CONS_WARNING, M_GetText("No Red Team starts in this map!\n")); return NULL; } @@ -2978,10 +2406,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum) return redctfstarts[i]; } - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) + if (doprints) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Red Team starts!\n")); return NULL; } @@ -2989,10 +2414,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum) { if (!numbluectfstarts) { - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) + if (doprints) CONS_Alert(CONS_WARNING, M_GetText("No Blue Team starts in this map!\n")); return NULL; } @@ -3003,10 +2425,7 @@ mapthing_t *G_FindCTFStart(INT32 playernum) if (G_CheckSpot(playernum, bluectfstarts[i])) return bluectfstarts[i]; } - if (playernum == consoleplayer - || (splitscreen && playernum == displayplayers[1]) - || (splitscreen > 1 && playernum == displayplayers[2]) - || (splitscreen > 2 && playernum == displayplayers[3])) + if (doprints) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Blue Team starts!\n")); return NULL; } @@ -3014,8 +2433,9 @@ mapthing_t *G_FindCTFStart(INT32 playernum) return NULL; } -mapthing_t *G_FindMatchStart(INT32 playernum) +mapthing_t *G_FindBattleStart(INT32 playernum) { + const boolean doprints = P_IsLocalPlayer(&players[playernum]); INT32 i, j; if (numdmstarts) @@ -3026,24 +2446,20 @@ mapthing_t *G_FindMatchStart(INT32 playernum) if (G_CheckSpot(playernum, deathmatchstarts[i])) return deathmatchstarts[i]; } - if (playernum == consoleplayer - || (splitscreen && playernum == g_localplayers[1]) - || (splitscreen > 1 && playernum == g_localplayers[2]) - || (splitscreen > 2 && playernum == g_localplayers[3])) + if (doprints) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Deathmatch starts!\n")); return NULL; } - if (playernum == consoleplayer - || (splitscreen && playernum == g_localplayers[1]) - || (splitscreen > 1 && playernum == g_localplayers[2]) - || (splitscreen > 2 && playernum == g_localplayers[3])) + if ((gametyperules & GTR_BATTLESTARTS) && doprints) CONS_Alert(CONS_WARNING, M_GetText("No Deathmatch starts in this map!\n")); return NULL; } mapthing_t *G_FindRaceStart(INT32 playernum) { + const boolean doprints = P_IsLocalPlayer(&players[playernum]); + if (numcoopstarts) { UINT8 i; @@ -3124,22 +2540,99 @@ mapthing_t *G_FindRaceStart(INT32 playernum) // Just spawn there. //return playerstarts[0]; - if (playernum == consoleplayer - || (splitscreen && playernum == g_localplayers[1]) - || (splitscreen > 1 && playernum == g_localplayers[2]) - || (splitscreen > 2 && playernum == g_localplayers[3])) + if (doprints) CONS_Alert(CONS_WARNING, M_GetText("Could not spawn at any Race starts!\n")); return NULL; } - if (playernum == consoleplayer - || (splitscreen && playernum == g_localplayers[1]) - || (splitscreen > 1 && playernum == g_localplayers[2]) - || (splitscreen > 2 && playernum == g_localplayers[3])) + if (doprints) CONS_Alert(CONS_WARNING, M_GetText("No Race starts in this map!\n")); return NULL; } +// Find a Co-op start, or fallback into other types of starts. +static inline mapthing_t *G_FindRaceStartOrFallback(INT32 playernum) +{ + mapthing_t *spawnpoint = NULL; + if (!(spawnpoint = G_FindRaceStart(playernum)) // find a Race start + && !(spawnpoint = G_FindBattleStart(playernum))) // find a DM start + spawnpoint = G_FindTeamStart(playernum); // fallback + return spawnpoint; +} + +// Find a Match start, or fallback into other types of starts. +static inline mapthing_t *G_FindBattleStartOrFallback(INT32 playernum) +{ + mapthing_t *spawnpoint = NULL; + if (!(spawnpoint = G_FindBattleStart(playernum)) // find a DM start + && !(spawnpoint = G_FindTeamStart(playernum))) // find a CTF start + spawnpoint = G_FindRaceStart(playernum); // fallback + return spawnpoint; +} + +static inline mapthing_t *G_FindTeamStartOrFallback(INT32 playernum) +{ + mapthing_t *spawnpoint = NULL; + if (!(spawnpoint = G_FindTeamStart(playernum)) // find a CTF start + && !(spawnpoint = G_FindBattleStart(playernum))) // find a DM start + spawnpoint = G_FindRaceStart(playernum); // fallback + return spawnpoint; +} + +mapthing_t *G_FindMapStart(INT32 playernum) +{ + mapthing_t *spawnpoint; + + if (!playeringame[playernum]) + return NULL; + + // -- Spectators -- + // Order in platform gametypes: Race->DM->CTF + // And, with deathmatch starts: DM->CTF->Race + if (players[playernum].spectator) + { + // In platform gametypes, spawn in Co-op starts first + // Overriden by GTR_BATTLESTARTS. + if (gametyperules & GTR_BATTLESTARTS) + spawnpoint = G_FindBattleStartOrFallback(playernum); + else + spawnpoint = G_FindRaceStartOrFallback(playernum); + } + + // -- CTF -- + // Order: CTF->DM->Race + else if ((gametyperules & GTR_TEAMSTARTS) && players[playernum].ctfteam) + spawnpoint = G_FindTeamStartOrFallback(playernum); + + // -- DM/Tag/CTF-spectator/etc -- + // Order: DM->CTF->Race + else if (gametyperules & GTR_BATTLESTARTS) + spawnpoint = G_FindBattleStartOrFallback(playernum); + + // -- Other game modes -- + // Order: Race->DM->CTF + else + spawnpoint = G_FindRaceStartOrFallback(playernum); + + //No spawns found. ANYWHERE. + if (!spawnpoint) + { + if (nummapthings) + { + if (P_IsLocalPlayer(&players[playernum])) + CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the first mapthing!\n")); + spawnpoint = &mapthings[0]; + } + else + { + if (P_IsLocalPlayer(&players[playernum])) + CONS_Alert(CONS_ERROR, M_GetText("No player spawns found, spawning at the origin!\n")); + } + } + + return spawnpoint; +} + // Go back through all the projectiles and remove all references to the old // player mobj, replacing them with the new one. void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) @@ -3150,9 +2643,9 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) I_Assert((oldmo != NULL) && (newmo != NULL)); // scan all thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -3174,7 +2667,6 @@ void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo) void G_DoReborn(INT32 playernum) { player_t *player = &players[playernum]; - boolean starpost = false; // Make sure objectplace is OFF when you first start the level! OP_ResetObjectplace(); @@ -3183,10 +2675,6 @@ void G_DoReborn(INT32 playernum) // respawn at the start mobj_t *oldmo = NULL; - // Now only respawn at the start if you haven't crossed it at all - if (player->laps) // SRB2kart - starpost = true; - // first dissasociate the corpse if (player->mo) { @@ -3195,7 +2683,7 @@ void G_DoReborn(INT32 playernum) P_RemoveMobj(player->mo); } - G_SpawnPlayer(playernum, starpost); + G_SpawnPlayer(playernum); if (oldmo) G_ChangePlayerReferences(oldmo, players[playernum].mo); } @@ -3204,10 +2692,7 @@ void G_DoReborn(INT32 playernum) void G_AddPlayer(INT32 playernum) { player_t *p = &players[playernum]; - - p->jointime = 0; p->playerstate = PST_REBORN; - demo_extradata[playernum] |= DXD_PLAYSTATE|DXD_COLOR|DXD_NAME|DXD_SKIN|DXD_FOLLOWER; // Set everything } @@ -3267,30 +2752,217 @@ void G_ExitLevel(void) CV_SetValue(&cv_teamscramble, cv_scrambleonchange.value); } - if (netgame || multiplayer) - CON_LogMessage(M_GetText("The round has ended.\n")); + CON_LogMessage(M_GetText("The round has ended.\n")); // Remove CEcho text on round end. HU_ClearCEcho(); // Don't save demos immediately here! Let standings write first } + else if (gamestate == GS_ENDING) + { + F_StartCredits(); + } + else if (gamestate == GS_CREDITS) + { + F_StartGameEvaluation(); + } } // See also the enum GameType in doomstat.h const char *Gametype_Names[NUMGAMETYPES] = { "Race", // GT_RACE - "Battle" // GT_MATCH - - /*"Co-op", // GT_COOP - "Competition", // GT_COMPETITION - "Team Match", // GT_TEAMMATCH - "Tag", // GT_TAG - "Hide and Seek", // GT_HIDEANDSEEK - "CTF" // GT_CTF*/ + "Battle" // GT_BATTLE }; +// For dehacked +const char *Gametype_ConstantNames[NUMGAMETYPES] = +{ + "GT_RACE", // GT_RACE + "GT_BATTLE" // GT_BATTLE +}; + +// Gametype rules +UINT32 gametypedefaultrules[NUMGAMETYPES] = +{ + // Race + GTR_CIRCUIT|GTR_RINGS|GTR_BOTS, + // Battle + GTR_BUMPERS|GTR_WANTED|GTR_KARMA|GTR_ITEMARROWS|GTR_CAPSULES|GTR_BATTLESTARTS|GTR_POINTLIMIT|GTR_TIMELIMIT|GTR_OVERTIME +}; + +// +// G_SetGametype +// +// Set a new gametype, also setting gametype rules accordingly. Yay! +// +void G_SetGametype(INT16 gtype) +{ + gametype = gtype; + gametyperules = gametypedefaultrules[gametype]; +} + +// +// G_AddGametype +// +// Add a gametype. Returns the new gametype number. +// +INT16 G_AddGametype(UINT32 rules) +{ + INT16 newgtype = gametypecount; + gametypecount++; + + // Set gametype rules. + gametypedefaultrules[newgtype] = rules; + Gametype_Names[newgtype] = "???"; + + // Update gametype_cons_t accordingly. + G_UpdateGametypeSelections(); + + return newgtype; +} + +// +// G_AddGametypeConstant +// +// Self-explanatory. Filters out "bad" characters. +// +void G_AddGametypeConstant(INT16 gtype, const char *newgtconst) +{ + size_t r = 0; // read + size_t w = 0; // write + char *gtconst = Z_Calloc(strlen(newgtconst) + 4, PU_STATIC, NULL); + char *tmpconst = Z_Calloc(strlen(newgtconst) + 1, PU_STATIC, NULL); + + // Copy the gametype name. + strcpy(tmpconst, newgtconst); + + // Make uppercase. + strupr(tmpconst); + + // Prepare to write the new constant string now. + strcpy(gtconst, "GT_"); + + // Remove characters that will not be allowed in the constant string. + for (; r < strlen(tmpconst); r++) + { + boolean writechar = true; + char rc = tmpconst[r]; + switch (rc) + { + // Space, at sign and question mark + case ' ': + case '@': + case '?': + // Used for operations + case '+': + case '-': + case '*': + case '/': + case '%': + case '^': + case '&': + case '!': + // Part of Lua's syntax + case '#': + case '=': + case '~': + case '<': + case '>': + case '(': + case ')': + case '{': + case '}': + case '[': + case ']': + case ':': + case ';': + case ',': + case '.': + writechar = false; + break; + } + if (writechar) + { + gtconst[3 + w] = rc; + w++; + } + } + + // Free the temporary string. + Z_Free(tmpconst); + + // Finally, set the constant string. + Gametype_ConstantNames[gtype] = gtconst; +} + +// +// G_UpdateGametypeSelections +// +// Updates gametype_cons_t. +// +void G_UpdateGametypeSelections(void) +{ + INT32 i; + for (i = 0; i < gametypecount; i++) + { + gametype_cons_t[i].value = i; + gametype_cons_t[i].strvalue = Gametype_Names[i]; + } + gametype_cons_t[NUMGAMETYPES].value = 0; + gametype_cons_t[NUMGAMETYPES].strvalue = NULL; +} + +// Gametype rankings +INT16 gametyperankings[NUMGAMETYPES] = +{ + GT_RACE, + GT_BATTLE, +}; + +// Gametype to TOL (Type Of Level) +UINT32 gametypetol[NUMGAMETYPES] = +{ + TOL_RACE, // Race + TOL_BATTLE, // Battle + TOL_TV, // Midnight Channel effect +}; + +tolinfo_t TYPEOFLEVEL[NUMTOLNAMES] = { + {"RACE",TOL_RACE}, + {"BATTLE",TOL_BATTLE}, + {"TV",TOL_TV}, + {NULL, 0} +}; + +UINT32 lastcustomtol = (TOL_TV<<1); + +// +// G_AddTOL +// +// Adds a type of level. +// +void G_AddTOL(UINT32 newtol, const char *tolname) +{ + INT32 i; + for (i = 0; TYPEOFLEVEL[i].name; i++) + ; + + TYPEOFLEVEL[i].name = Z_StrDup(tolname); + TYPEOFLEVEL[i].flag = newtol; +} + +// +// G_AddGametypeTOL +// +// Assigns a type of level to a gametype. +// +void G_AddGametypeTOL(INT16 gtype, UINT32 newtol) +{ + gametypetol[gtype] = newtol; +} + // // G_GetGametypeByName // @@ -3300,7 +2972,7 @@ INT32 G_GetGametypeByName(const char *gametypestr) { INT32 i; - for (i = 0; i < NUMGAMETYPES; i++) + for (i = 0; i < gametypecount; i++) if (!stricmp(gametypestr, Gametype_Names[i])) return i; @@ -3315,12 +2987,18 @@ INT32 G_GetGametypeByName(const char *gametypestr) // boolean G_IsSpecialStage(INT32 mapnum) { -#if 0 - return (gametype == GT_COOP && modeattacking != ATTACKING_RECORD && mapnum >= sstage_start && mapnum <= sstage_end); -#else +#if 1 (void)mapnum; - return false; +#else + if (modeattacking == ATTACKING_TIME) + return false; + if (mapnum >= sstage_start && mapnum <= sstage_end) + return true; + if (mapnum >= smpstage_start && mapnum <= smpstage_end) + return true; #endif + + return false; } // @@ -3333,8 +3011,8 @@ boolean G_GametypeUsesLives(void) { if ((grandprixinfo.gp == true) // In Grand Prix && (gametype == GT_RACE) // NOT in bonus round - && !(modeattacking) // NOT in Record Attack - && !G_IsSpecialStage(gamemap)) // NOT in special stage + && !G_IsSpecialStage(gamemap) // NOT in special stage + && !(modeattacking || metalrecording)) // NOT in Record Attack { return true; } @@ -3350,7 +3028,19 @@ boolean G_GametypeUsesLives(void) // boolean G_GametypeHasTeams(void) { - return (gametype == GT_TEAMMATCH || gametype == GT_CTF); + if (gametyperules & GTR_TEAMS) + { + // Teams forced on by this gametype + return true; + } + else if (gametyperules & GTR_NOTEAMS) + { + // Teams forced off by this gametype + return false; + } + + // Teams are determined by the "teamplay" modifier! + return false; // teamplay } // @@ -3361,22 +3051,7 @@ boolean G_GametypeHasTeams(void) // boolean G_GametypeHasSpectators(void) { - // SRB2Kart: We don't have any exceptions to not being able to spectate yet. Maybe when SP & bots roll around. -#if 0 - return (gametype != GT_COOP && gametype != GT_COMPETITION && gametype != GT_RACE); -#else - return (netgame || (multiplayer && demo.playback)); //true -#endif -} - -// -// G_BattleGametype -// -// Returns true in Battle gamemodes, previously was G_RingSlingerGametype. -// -boolean G_BattleGametype(void) -{ - return (gametype == GT_MATCH); + return (netgame || (multiplayer && demo.playback)); } // @@ -3386,7 +3061,7 @@ boolean G_BattleGametype(void) // INT16 G_SometimesGetDifferentGametype(void) { - boolean encorepossible = ((M_SecretUnlocked(SECRET_ENCORE) || encorescramble == 1) && G_RaceGametype()); + boolean encorepossible = ((M_SecretUnlocked(SECRET_ENCORE) || encorescramble == 1) && (gametyperules & GTR_CIRCUIT)); if (!cv_kartvoterulechanges.value // never && encorescramble != 1) // destroying the code for this one instance @@ -3439,9 +3114,9 @@ INT16 G_SometimesGetDifferentGametype(void) break; } - if (gametype == GT_MATCH) + if (gametype == GT_BATTLE) return GT_RACE; - return GT_MATCH; + return GT_BATTLE; } // @@ -3452,63 +3127,33 @@ INT16 G_SometimesGetDifferentGametype(void) // UINT8 G_GetGametypeColor(INT16 gt) { - if (modeattacking // == ATTACKING_RECORD + if (modeattacking // == ATTACKING_TIME || gamestate == GS_TIMEATTACK) return orangemap[0]; - if (gt == GT_MATCH) + + if (gt == GT_BATTLE) return redmap[0]; + if (gt == GT_RACE) return skymap[0]; + return 255; // FALLBACK } -// -// G_RaceGametype -// -// Returns true in Race gamemodes, previously was G_PlatformGametype. -// -boolean G_RaceGametype(void) -{ - return (gametype == GT_RACE); -} - -// -// G_TagGametype -// -// For Jazz's Tag/HnS modes that have a lot of special cases... -// SRB2Kart: do we actually want to add Kart tag later? :V -// -boolean G_TagGametype(void) -{ - return (gametype == GT_TAG || gametype == GT_HIDEANDSEEK); -} - /** Get the typeoflevel flag needed to indicate support of a gametype. - * In single-player, this always returns TOL_SP. * \param gametype The gametype for which support is desired. * \return The typeoflevel flag to check for that gametype. * \author Graue */ -INT16 G_TOLFlag(INT32 pgametype) +UINT32 G_TOLFlag(INT32 pgametype) { - if (!multiplayer) return TOL_SP; - if (pgametype == GT_COOP) return TOL_RACE; // SRB2kart - if (pgametype == GT_COMPETITION) return TOL_COMPETITION; - if (pgametype == GT_RACE) return TOL_RACE; - if (pgametype == GT_MATCH) return TOL_MATCH; - if (pgametype == GT_TEAMMATCH) return TOL_MATCH; - if (pgametype == GT_TAG) return TOL_TAG; - if (pgametype == GT_HIDEANDSEEK) return TOL_TAG; - if (pgametype == GT_CTF) return TOL_CTF; - - CONS_Alert(CONS_ERROR, M_GetText("Unknown gametype! %d\n"), pgametype); - return INT16_MAX; + return gametypetol[pgametype]; } -static INT32 TOLMaps(INT16 tolflags) +static UINT32 TOLMaps(UINT32 tolflags) { - INT32 num = 0; - INT16 i; + UINT32 num = 0; + UINT32 i; // Find all the maps that are ok and and put them in an array. for (i = 0; i < NUMMAPS; i++) @@ -3533,7 +3178,7 @@ static INT32 TOLMaps(INT16 tolflags) * \author Graue */ static INT16 *okmaps = NULL; -INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer) +INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer) { INT32 numokmaps = 0; INT16 ix, bufx; @@ -3652,7 +3297,7 @@ tryagain: void G_AddMapToBuffer(INT16 map) { - INT16 bufx, refreshnum = max(0, TOLMaps(G_TOLFlag(gametype))-3); + INT16 bufx, refreshnum = max(0, (INT32)TOLMaps(G_TOLFlag(gametype))-3); // Add the map to the buffer. for (bufx = NUMMAPS-1; bufx > 0; bufx--) @@ -3669,28 +3314,92 @@ void G_AddMapToBuffer(INT16 map) } } +// +// G_UpdateVisited +// +static void G_UpdateVisited(void) +{ + boolean spec = G_IsSpecialStage(gamemap); + // Update visitation flags? + if ((!modifiedgame || savemoddata) // Not modified + && !multiplayer && !demo.playback // SP/RA/NiGHTS mode + && !(spec && stagefailed)) // Not failed the special stage + { + UINT8 earnedEmblems; + + // Update visitation flags + mapvisited[gamemap-1] |= MV_BEATEN; + + if (encoremode == true) + { + mapvisited[gamemap-1] |= MV_ENCORE; + } + + if (modeattacking) + G_UpdateRecordReplays(); + + if ((earnedEmblems = M_CompletionEmblems())) + CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); + } +} + +static boolean CanSaveLevel(INT32 mapnum) +{ + // SRB2Kart: No save files yet + (void)mapnum; + return false; +} + +static void G_HandleSaveLevel(void) +{ + // do this before running the intermission or custom cutscene, mostly for the sake of marathon mode but it also massively reduces redundant file save events in f_finale.c + if (nextmap >= 1100-1) + { + if (!gamecomplete) + gamecomplete = 2; // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission + if (cursaveslot > 0) + { + if (marathonmode) + { + // don't keep a backup around when the run is done! + if (FIL_FileExists(liveeventbackup)) + remove(liveeventbackup); + cursaveslot = 0; + } + else if ((!modifiedgame || savemoddata) && !(netgame || multiplayer || ultimatemode || demo.recording || metalrecording || modeattacking)) + G_SaveGame((UINT32)cursaveslot, spstage_start); + } + } + // and doing THIS here means you don't lose your progress if you close the game mid-intermission + else if (!(ultimatemode || netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking) + && (!modifiedgame || savemoddata) && cursaveslot > 0 && CanSaveLevel(lastmap+1)) + G_SaveGame((UINT32)cursaveslot, lastmap+1); // not nextmap+1 to route around special stages +} + // // G_DoCompleted // static void G_DoCompleted(void) { INT32 i, j = 0; + boolean spec = G_IsSpecialStage(gamemap); SINT8 powertype = K_UsingPowerLevels(); - tokenlist = 0; // Reset the list + if (modeattacking && pausedelay) + pausedelay = 0; gameaction = ga_nothing; if (metalplayback) G_StopMetalDemo(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) { // SRB2Kart: exitlevel shouldn't get you the points - if (!players[i].exiting && !(players[i].pflags & PF_TIMEOVER)) + if (!players[i].exiting && !(players[i].pflags & PF_GAMETYPEOVER)) { if (players[i].bot) { @@ -3698,7 +3407,7 @@ static void G_DoCompleted(void) } else { - players[i].pflags |= PF_TIMEOVER; + players[i].pflags |= PF_GAMETYPEOVER; if (P_IsLocalPlayer(&players[i])) { @@ -3711,7 +3420,7 @@ static void G_DoCompleted(void) } // play some generic music if there's no win/cool/lose music going on (for exitlevel commands) - if (G_RaceGametype() && ((multiplayer && demo.playback) || j == r_splitscreen+1) && (cv_inttime.value > 0)) + if ((gametyperules & GTR_CIRCUIT) && ((multiplayer && demo.playback) || j == r_splitscreen+1) && (cv_inttime.value > 0)) S_ChangeMusicInternal("racent", true); if (automapactive) @@ -3729,6 +3438,10 @@ static void G_DoCompleted(void) { nextmap = (INT16)(nextmapoverride-1); } + else if (marathonmode && mapheaderinfo[gamemap-1]->marathonnext) + { + nextmap = (INT16)(mapheaderinfo[gamemap-1]->marathonnext-1); + } else if (grandprixinfo.gp == true) { if (grandprixinfo.roundnum == 0 || grandprixinfo.cup == NULL) // Single session @@ -3752,63 +3465,77 @@ static void G_DoCompleted(void) else { nextmap = (INT16)(mapheaderinfo[gamemap-1]->nextlevel-1); + if (marathonmode && nextmap == spmarathon_start-1) + nextmap = 1100-1; // No infinite loop for you } // Remember last map for when you come out of the special stage. - if (!G_IsSpecialStage(gamemap)) + if (!spec) lastmap = nextmap; // If nextmap is actually going to get used, make sure it points to // a map of the proper gametype -- skip levels that don't support // the current gametype. (Helps avoid playing boss levels in Race, // for instance). - if (!modeattacking && grandprixinfo.gp == false && (nextmap >= 0 && nextmap < NUMMAPS)) + if (!modeattacking && grandprixinfo.gp == false) { - register INT16 cm = nextmap; - INT16 tolflag = G_TOLFlag(gametype); - UINT8 visitedmap[(NUMMAPS+7)/8]; - - memset(visitedmap, 0, sizeof (visitedmap)); - - while (!mapheaderinfo[cm] || !(mapheaderinfo[cm]->typeoflevel & tolflag)) + if (nextmap >= 0 && nextmap < NUMMAPS) { - visitedmap[cm/8] |= (1<<(cm&7)); - if (!mapheaderinfo[cm]) - cm = -1; // guarantee error execution - else - cm = (INT16)(mapheaderinfo[cm]->nextlevel-1); + register INT16 cm = nextmap; + UINT32 tolflag = G_TOLFlag(gametype); + UINT8 visitedmap[(NUMMAPS+7)/8]; - if (cm >= NUMMAPS || cm < 0) // out of range (either 1100-1102 or error) + memset(visitedmap, 0, sizeof (visitedmap)); + + while (!mapheaderinfo[cm] || !(mapheaderinfo[cm]->typeoflevel & tolflag)) { - cm = nextmap; //Start the loop again so that the error checking below is executed. + visitedmap[cm/8] |= (1<<(cm&7)); + if (!mapheaderinfo[cm]) + cm = -1; // guarantee error execution + else if (marathonmode && mapheaderinfo[cm]->marathonnext) + cm = (INT16)(mapheaderinfo[cm]->marathonnext-1); + else + cm = (INT16)(mapheaderinfo[cm]->nextlevel-1); - //Make sure the map actually exists before you try to go to it! - if ((W_CheckNumForName(G_BuildMapName(cm + 1)) == LUMPERROR)) + if (cm >= NUMMAPS || cm < 0) // out of range (either 1100ish or error) { - CONS_Alert(CONS_ERROR, M_GetText("Next map given (MAP %d) doesn't exist! Reverting to MAP01.\n"), cm+1); - cm = 0; + cm = nextmap; //Start the loop again so that the error checking below is executed. + + //Make sure the map actually exists before you try to go to it! + if ((W_CheckNumForName(G_BuildMapName(cm + 1)) == LUMPERROR)) + { + CONS_Alert(CONS_ERROR, M_GetText("Next map given (MAP %d) doesn't exist! Reverting to MAP01.\n"), cm+1); + cm = 0; + break; + } + } + + if (visitedmap[cm/8] & (1<<(cm&7))) // smells familiar + { + // We got stuck in a loop, came back to the map we started on + // without finding one supporting the current gametype. + // Thus, print a warning, and just use this map anyways. + CONS_Alert(CONS_WARNING, M_GetText("Can't find a compatible map after map %d; using map %d anyway\n"), prevmap+1, cm+1); break; } } - - if (visitedmap[cm/8] & (1<<(cm&7))) // smells familiar - { - // We got stuck in a loop, came back to the map we started on - // without finding one supporting the current gametype. - // Thus, print a warning, and just use this map anyways. - CONS_Alert(CONS_WARNING, M_GetText("Can't find a compatible map after map %d; using map %d anyway\n"), prevmap+1, cm+1); - break; - } + nextmap = cm; } - nextmap = cm; - } - if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1102-1) - I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1); + // wrap around in race + if (nextmap >= 1100-1 && nextmap <= 1102-1 && !(gametyperules & GTR_CAMPAIGN)) + nextmap = (INT16)(spstage_start-1); + + if (nextmap < 0 || (nextmap >= NUMMAPS && nextmap < 1100-1) || nextmap > 1103-1) + I_Error("Followed map %d to invalid map %d\n", prevmap + 1, nextmap + 1); + + if (!spec) + lastmap = nextmap; // Remember last map for when you come out of the special stage. + } automapactive = false; - if (gametype != GT_COOP) + if (!(gametyperules & GTR_CAMPAIGN)) { if (cv_advancemap.value == 0) // Stay on same map. { @@ -3831,17 +3558,38 @@ static void G_DoCompleted(void) demointermission: - if (skipstats && !modeattacking) // Don't skip stats if we're in record attack + // If the current gametype has no intermission screen set, then don't start it. + Y_DetermineIntermissionType(); + + if ((skipstats && !modeattacking) || (spec && modeattacking && stagefailed) || (intertype == int_none)) + { + G_UpdateVisited(); + G_HandleSaveLevel(); G_AfterIntermission(); + } else { G_SetGamestate(GS_INTERMISSION); Y_StartIntermission(); + G_UpdateVisited(); + G_HandleSaveLevel(); } } +// See also F_EndCutscene, the only other place which handles intra-map/ending transitions void G_AfterIntermission(void) { + Y_CleanupScreenBuffer(); + + if (modeattacking) + { + M_EndModeAttackRun(); + return; + } + + if (gamecomplete == 2) // special temporary mode to prevent using SP level select in pause menu until the intermission is over without restricting it in every intermission + gamecomplete = 1; + HU_ClearCEcho(); //G_NextLevel(); @@ -3865,7 +3613,7 @@ void G_AfterIntermission(void) return; } - if (mapheaderinfo[gamemap-1]->cutscenenum) // Start a custom cutscene. + if ((gametyperules & GTR_CAMPAIGN) && mapheaderinfo[gamemap-1]->cutscenenum && !modeattacking && skipstats <= 1 && (gamecomplete || !(marathonmode & MA_NOCUTSCENES))) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->cutscenenum-1, false, false); else { @@ -3952,7 +3700,7 @@ static void G_DoStartContinue(void) legitimateexit = false; G_PlayerFinishLevel(consoleplayer); // take away cards and stuff - F_StartContinue(); + //F_StartContinue(); gameaction = ga_nothing; } @@ -3973,7 +3721,8 @@ static void G_DoContinued(void) I_Assert(!netgame && !multiplayer); I_Assert(pl->continues > 0); - pl->continues--; + if (pl->continues) + pl->continues--; // Reset score pl->score = 0; @@ -3982,6 +3731,9 @@ static void G_DoContinued(void) tokenlist = 0; token = 0; + if (!(netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking) && (!modifiedgame || savemoddata) && cursaveslot > 0) + G_SaveGameOver((UINT32)cursaveslot, true); + // Reset # of lives pl->lives = 3; @@ -4007,8 +3759,13 @@ void G_EndGame(void) G_SaveDemo(); // Only do evaluation and credits in coop games. - if (gametype == GT_COOP) + if (gametyperules & GTR_CAMPAIGN) { + if (nextmap == 1103-1) // end game with ending + { + F_StartEnding(); + return; + } if (nextmap == 1102-1) // end game with credits { F_StartCredits(); @@ -4032,10 +3789,12 @@ void G_EndGame(void) void G_LoadGameSettings(void) { // defaults - spstage_start = 1; + spstage_start = spmarathon_start = 1; sstage_start = 50; - sstage_end = 57; // 8 special stages in vanilla SRB2 - useNightsSS = false; //true; + sstage_end = 56; // 7 special stages in vanilla SRB2 + sstage_end++; // plus one weirdo + smpstage_start = 60; + smpstage_end = 66; // 7 multiplayer special stages too // initialize free sfx slots for skin sounds S_InitRuntimeSounds(); @@ -4053,11 +3812,6 @@ void G_LoadGameData(void) //For records tic_t rectime; tic_t reclap; - //UINT32 recscore; - //UINT16 recrings; - - //UINT8 recmares; - //INT32 curmare; // Clear things so previously read gamedata doesn't transfer // to new gamedata @@ -4156,51 +3910,21 @@ void G_LoadGameData(void) } timesBeaten = READUINT32(save_p); - timesBeatenWithEmeralds = READUINT32(save_p); - //timesBeatenUltimate = READUINT32(save_p); // Main records for (i = 0; i < NUMMAPS; ++i) { rectime = (tic_t)READUINT32(save_p); reclap = (tic_t)READUINT32(save_p); - //recscore = READUINT32(save_p); - //recrings = READUINT16(save_p); - - /*if (recrings > 10000 || recscore > MAXSCORE) - goto datacorrupt;*/ if (rectime || reclap) { G_AllocMainRecordData((INT16)i); mainrecords[i]->time = rectime; mainrecords[i]->lap = reclap; - //mainrecords[i]->score = recscore; - //mainrecords[i]->rings = recrings; } } - // Nights records - /*for (i = 0; i < NUMMAPS; ++i) - { - if ((recmares = READUINT8(save_p)) == 0) - continue; - - G_AllocNightsRecordData((INT16)i); - - for (curmare = 0; curmare < (recmares+1); ++curmare) - { - nightsrecords[i]->score[curmare] = READUINT32(save_p); - nightsrecords[i]->grade[curmare] = READUINT8(save_p); - nightsrecords[i]->time[curmare] = (tic_t)READUINT32(save_p); - - if (nightsrecords[i]->grade[curmare] > GRADE_S) - goto datacorrupt; - } - - nightsrecords[i]->nummares = recmares; - }*/ - // done Z_Free(savebuffer); save_p = NULL; @@ -4226,14 +3950,12 @@ void G_LoadGameData(void) // G_SaveGameData // Saves the main data file, which stores information such as emblems found, etc. -void G_SaveGameData(boolean force) +void G_SaveGameData(void) { size_t length; INT32 i, j; UINT8 btemp; - //INT32 curmare; - if (!gamedataloaded) return; // If never loaded (-nodata), don't save @@ -4244,12 +3966,15 @@ void G_SaveGameData(boolean force) return; } - if (majormods && !force) +#if 0 + // SRB2Kart: Let players unlock stuff with addons. + if (modifiedgame && !savemoddata) { free(savebuffer); save_p = savebuffer = NULL; return; } +#endif // Version test WRITEUINT32(save_p, 0xFCAFE211); @@ -4260,12 +3985,11 @@ void G_SaveGameData(boolean force) for (i = 0; i < PWRLV_NUMTYPES; i++) WRITEUINT16(save_p, vspowerlevel[i]); - btemp = (UINT8)(savemoddata); // what used to be here was profoundly dunderheaded - WRITEUINT8(save_p, btemp); + WRITEUINT8(save_p, (UINT8)savemoddata); // TODO put another cipher on these things? meh, I don't care... for (i = 0; i < NUMMAPS; i++) - WRITEUINT8(save_p, mapvisited[i]); + WRITEUINT8(save_p, (mapvisited[i] & MV_MAX)); // To save space, use one bit per collected/achieved/unlocked flag for (i = 0; i < MAXEMBLEMS;) @@ -4302,8 +4026,6 @@ void G_SaveGameData(boolean force) } WRITEUINT32(save_p, timesBeaten); - WRITEUINT32(save_p, timesBeatenWithEmeralds); - //WRITEUINT32(save_p, timesBeatenUltimate); // Main records for (i = 0; i < NUMMAPS; i++) @@ -4312,35 +4034,15 @@ void G_SaveGameData(boolean force) { WRITEUINT32(save_p, mainrecords[i]->time); WRITEUINT32(save_p, mainrecords[i]->lap); - //WRITEUINT32(save_p, mainrecords[i]->score); - //WRITEUINT16(save_p, mainrecords[i]->rings); } else { WRITEUINT32(save_p, 0); WRITEUINT32(save_p, 0); } + WRITEUINT8(save_p, 0); // compat } - // NiGHTS records - /*for (i = 0; i < NUMMAPS; i++) - { - if (!nightsrecords[i] || !nightsrecords[i]->nummares) - { - WRITEUINT8(save_p, 0); - continue; - } - - WRITEUINT8(save_p, nightsrecords[i]->nummares); - - for (curmare = 0; curmare < (nightsrecords[i]->nummares + 1); ++curmare) - { - WRITEUINT32(save_p, nightsrecords[i]->score[curmare]); - WRITEUINT8(save_p, nightsrecords[i]->grade[curmare]); - WRITEUINT32(save_p, nightsrecords[i]->time[curmare]); - } - }*/ - length = save_p - savebuffer; FIL_WriteFile(va(pandf, srb2home, gamedatafilename), savebuffer, length); @@ -4350,61 +4052,6 @@ void G_SaveGameData(boolean force) #define VERSIONSIZE 16 -#ifdef SAVEGAMES_OTHERVERSIONS -static INT16 startonmapnum = 0; - -// -// User wants to load a savegame from a different version? -// -static void M_ForceLoadGameResponse(INT32 ch) -{ - if (ch != 'y' && ch != KEY_ENTER) - { - //refused - Z_Free(savebuffer); - save_p = savebuffer = NULL; - startonmapnum = 0; - M_SetupNextMenu(&SP_LoadDef); - return; - } - - // pick up where we left off. - save_p += VERSIONSIZE; - if (!P_LoadGame(startonmapnum)) - { - M_ClearMenus(true); // so ESC backs out to title - M_StartMessage(M_GetText("Savegame file corrupted\n\nPress ESC\n"), NULL, MM_NOTHING); - Command_ExitGame_f(); - Z_Free(savebuffer); - save_p = savebuffer = NULL; - startonmapnum = 0; - - // no cheating! - memset(&savedata, 0, sizeof(savedata)); - return; - } - - // done - Z_Free(savebuffer); - save_p = savebuffer = NULL; - startonmapnum = 0; - - //set cursaveslot to -1 so nothing gets saved. - cursaveslot = -1; - - displayplayers[0] = consoleplayer; - multiplayer = false; - splitscreen = 0; - SplitScreen_OnChange(); // not needed? - - if (setsizeneeded) - R_ExecuteSetViewSize(); - - M_ClearMenus(true); - CON_ToggleOff(); -} -#endif - // // G_InitFromSavegame // Can be called by the startup code or the menu task. @@ -4423,7 +4070,10 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) startonmapnum = mapoverride; #endif - sprintf(savename, savegamename, slot); + if (marathonmode) + strcpy(savename, liveeventbackup); + else + sprintf(savename, savegamename, slot); length = FIL_ReadFile(savename, &savebuffer); if (!length) @@ -4435,7 +4085,7 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) save_p = savebuffer; memset(vcheck, 0, sizeof (vcheck)); - sprintf(vcheck, "version %d", VERSION); + sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); if (strcmp((const char *)save_p, (const char *)vcheck)) { #ifdef SAVEGAME_OTHERVERSIONS @@ -4475,6 +4125,11 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) memset(&savedata, 0, sizeof(savedata)); return; } + if (marathonmode) + { + marathontime = READUINT32(save_p); + marathonmode |= READUINT8(save_p); + } // done Z_Free(savebuffer); @@ -4499,19 +4154,18 @@ void G_LoadGame(UINT32 slot, INT16 mapoverride) // G_SaveGame // Saves your game. // -void G_SaveGame(UINT32 savegameslot) +void G_SaveGame(UINT32 slot, INT16 mapnum) { boolean saved; char savename[256] = ""; const char *backup; - sprintf(savename, savegamename, savegameslot); + if (marathonmode) + strcpy(savename, liveeventbackup); + else + sprintf(savename, savegamename, slot); backup = va("%s",savename); - // save during evaluation or credits? game's over, folks! - if (gamestate == GS_CREDITS || gamestate == GS_EVALUATION) - gamecomplete = true; - gameaction = ga_nothing; { char name[VERSIONSIZE]; @@ -4525,10 +4179,18 @@ void G_SaveGame(UINT32 savegameslot) } memset(name, 0, sizeof (name)); - sprintf(name, "version %d", VERSION); + sprintf(name, (marathonmode ? "back-up %d" : "version %d"), VERSION); WRITEMEM(save_p, name, VERSIONSIZE); - P_SaveGame(); + P_SaveGame(mapnum); + if (marathonmode) + { + UINT32 writetime = marathontime; + if (!(marathonmode & MA_INGAME)) + writetime += TICRATE*5; // live event backup penalty because we don't know how long it takes to get to the next map + WRITEUINT32(save_p, writetime); + WRITEUINT8(save_p, (marathonmode & ~MA_INIT)); + } length = save_p - savebuffer; saved = FIL_WriteFile(backup, savebuffer, length); @@ -4541,9 +4203,116 @@ void G_SaveGame(UINT32 savegameslot) if (cv_debug && saved) CONS_Printf(M_GetText("Game saved.\n")); else if (!saved) - CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, savegameslot, savegamename); + CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename)); } +#define BADSAVE goto cleanup; +#define CHECKPOS if (save_p >= end_p) BADSAVE +void G_SaveGameOver(UINT32 slot, boolean modifylives) +{ + boolean saved = false; + size_t length; + char vcheck[VERSIONSIZE]; + char savename[255]; + const char *backup; + + if (marathonmode) + strcpy(savename, liveeventbackup); + else + sprintf(savename, savegamename, slot); + backup = va("%s",savename); + + length = FIL_ReadFile(savename, &savebuffer); + if (!length) + { + CONS_Printf(M_GetText("Couldn't read file %s\n"), savename); + return; + } + + { + char temp[sizeof(timeattackfolder)]; + UINT8 *end_p = savebuffer + length; + UINT8 *lives_p; + SINT8 pllives; + + save_p = savebuffer; + // Version check + memset(vcheck, 0, sizeof (vcheck)); + sprintf(vcheck, (marathonmode ? "back-up %d" : "version %d"), VERSION); + if (strcmp((const char *)save_p, (const char *)vcheck)) BADSAVE + save_p += VERSIONSIZE; + + // P_UnArchiveMisc() + (void)READINT16(save_p); + CHECKPOS + (void)READUINT16(save_p); // emeralds + CHECKPOS + READSTRINGN(save_p, temp, sizeof(temp)); // mod it belongs to + if (strcmp(temp, timeattackfolder)) BADSAVE + + // P_UnArchivePlayer() + CHECKPOS + (void)READUINT16(save_p); + CHECKPOS + + WRITEUINT8(save_p, numgameovers); + CHECKPOS + + lives_p = save_p; + pllives = READSINT8(save_p); // lives + CHECKPOS + if (modifylives && pllives < startinglivesbalance[numgameovers]) + { + pllives = startinglivesbalance[numgameovers]; + WRITESINT8(lives_p, pllives); + } + + (void)READINT32(save_p); // Score + CHECKPOS + (void)READINT32(save_p); // continues + + // File end marker check + CHECKPOS + switch (READUINT8(save_p)) + { + case 0xb7: + { + UINT8 i, banksinuse; + CHECKPOS + banksinuse = READUINT8(save_p); + CHECKPOS + if (banksinuse > NUM_LUABANKS) + BADSAVE + for (i = 0; i < banksinuse; i++) + { + (void)READINT32(save_p); + CHECKPOS + } + if (READUINT8(save_p) != 0x1d) + BADSAVE + } + case 0x1d: + break; + default: + BADSAVE + } + + // done + saved = FIL_WriteFile(backup, savebuffer, length); + } + +cleanup: + if (cv_debug && saved) + CONS_Printf(M_GetText("Game saved.\n")); + else if (!saved) + CONS_Alert(CONS_ERROR, M_GetText("Error while writing to %s for save slot %u, base: %s\n"), backup, slot, (marathonmode ? liveeventbackup : savegamename)); + Z_Free(savebuffer); + save_p = savebuffer = NULL; + +} +#undef CHECKPOS +#undef BADSAVE + // // G_DeferedInitNew // Can be called by the startup code or the menu task, @@ -4552,19 +4321,14 @@ void G_SaveGame(UINT32 savegameslot) void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar, UINT8 ssplayers, boolean FLS) { INT32 i; - //UINT8 color = 0; + UINT16 color = SKINCOLOR_NONE; + paused = false; if (demo.playback) COM_BufAddText("stopdemo\n"); - while (ghosts) - { - demoghost *next = ghosts->next; - Z_Free(ghosts); - ghosts = next; - } - ghosts = NULL; + G_FreeGhosts(); // TODO: do we actually need to do this? for (i = 0; i < NUMMAPS+1; i++) randmapbuffer[i] = -1; @@ -4578,27 +4342,32 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar SplitScreen_OnChange(); } - //if (!color) - //color = skins[pickedchar].prefcolor; - SetPlayerSkinByNum(consoleplayer, pickedchar); - CV_StealthSet(&cv_skin, skins[pickedchar].name); + CV_StealthSet(&cv_skin[0], skins[pickedchar].name); - //if (color) - //CV_StealthSetValue(&cv_playercolor, color); + if (color != SKINCOLOR_NONE) + { + CV_StealthSetValue(&cv_playercolor[0], color); + } if (mapname) + { D_MapChange(M_MapNumber(mapname[3], mapname[4]), gametype, pencoremode, true, 1, false, FLS); + } } // // This is the map command interpretation something like Command_Map_f // // called at: map cmd execution, doloadgame, doplaydemo -void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, boolean skipprecutscene) +void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, boolean skipprecutscene, boolean FLS) { INT32 i; + (void)FLS; + + Y_CleanupScreenBuffer(); + if (paused) { paused = false; @@ -4615,8 +4384,8 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool P_SetRandSeed(M_RandomizedSeed()); // Use a more "Random" random seed // Clear a bunch of variables - tokenlist = token = sstimer = redscore = bluescore = lastmap = 0; - racecountdown = exitcountdown = mapreset = 0; + redscore = bluescore = lastmap = 0; + racecountdown = exitcountdown = mapreset = exitfadestarted = 0; for (i = 0; i < MAXPLAYERS; i++) { @@ -4625,7 +4394,7 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool memset(&players[i].respawn, 0, sizeof (players[i].respawn)); // The latter two should clear by themselves, but just in case - players[i].pflags &= ~(PF_TAGIT|PF_TAGGED|PF_FULLSTASIS); + players[i].pflags &= ~(PF_GAMETYPEOVER|PF_FULLSTASIS|PF_FAULT); // Clear cheatcodes too, just in case. players[i].pflags &= ~(PF_GODMODE|PF_NOCLIP|PF_INVIS); @@ -4674,13 +4443,11 @@ void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, bool automapactive = false; imcontinuing = false; - if (!skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking) // Start a custom cutscene. + if ((gametyperules & GTR_CAMPAIGN) && !skipprecutscene && mapheaderinfo[gamemap-1]->precutscenenum && !modeattacking && !(marathonmode & MA_NOCUTSCENES)) // Start a custom cutscene. F_StartCustomCutscene(mapheaderinfo[gamemap-1]->precutscenenum-1, true, resetplayer); else { -#ifdef HAVE_BLUA LUAh_MapChange(gamemap); -#endif G_DoLoadLevel(resetplayer); } @@ -4706,11 +4473,14 @@ char *G_BuildMapTitle(INT32 mapnum) if (mapnum == 0) return Z_StrDup("Random"); + if (!mapheaderinfo[mapnum-1]) + P_AllocMapHeader(mapnum-1); + if (strcmp(mapheaderinfo[mapnum-1]->lvlttl, "")) { size_t len = 1; const char *zonetext = NULL; - const char *actnum = NULL; + const UINT8 actnum = mapheaderinfo[mapnum-1]->actnum; len += strlen(mapheaderinfo[mapnum-1]->lvlttl); if (strlen(mapheaderinfo[mapnum-1]->zonttl) > 0) @@ -4720,3477 +4490,260 @@ char *G_BuildMapTitle(INT32 mapnum) } else if (!(mapheaderinfo[mapnum-1]->levelflags & LF_NOZONE)) { - zonetext = M_GetText("ZONE"); + zonetext = M_GetText("Zone"); len += strlen(zonetext) + 1; // ' ' + zonetext } - if (strlen(mapheaderinfo[mapnum-1]->actnum) > 0) - { - actnum = M_GetText(mapheaderinfo[mapnum-1]->actnum); - len += strlen(actnum) + 1; // ' ' + actnum - } + + if (actnum > 0) + len += 1 + 11; // ' ' + INT32 title = Z_Malloc(len, PU_STATIC, NULL); sprintf(title, "%s", mapheaderinfo[mapnum-1]->lvlttl); if (zonetext) sprintf(title + strlen(title), " %s", zonetext); - if (actnum) sprintf(title + strlen(title), " %s", actnum); + if (actnum > 0) sprintf(title + strlen(title), " %d", actnum); } return title; } -// -// DEMO RECORDING -// - -#define DEMOVERSION 0x0003 -#define DEMOHEADER "\xF0" "KartReplay" "\x0F" - -#define DF_GHOST 0x01 // This demo contains ghost data too! -#define DF_TIMEATTACK 0x02 // This demo is from Time Attack and contains its final completion time & best lap! -#define DF_BREAKTHECAPSULES 0x04 // This demo is from Break the Capsules and contains its final completion time! -#define DF_ATTACKMASK 0x06 // This demo is from ??? attack and contains ??? - -#ifdef HAVE_BLUA -#define DF_LUAVARS 0x20 // this demo contains extra lua vars; this is mostly used for backwards compability -#endif - -#define DF_ATTACKSHIFT 1 -#define DF_ENCORE 0x40 -#define DF_MULTIPLAYER 0x80 // This demo was recorded in multiplayer mode! - -#define DEMO_SPECTATOR 0x40 - -// For demos -#define ZT_FWD 0x01 -#define ZT_ANGLE 0x02 -#define ZT_BUTTONS 0x04 -#define ZT_AIMING 0x08 -#define ZT_DRIFT 0x10 -#define ZT_LATENCY 0x20 -#define DEMOMARKER 0x40 // demoend - -UINT8 demo_extradata[MAXPLAYERS]; -UINT8 demo_writerng; // 0=no, 1=yes, 2=yes but on a timeout -static ticcmd_t oldcmd[MAXPLAYERS]; - -#define DW_END 0xFF // End of extradata block -#define DW_RNG 0xFE // Check RNG seed! - -#define DW_EXTRASTUFF 0xFE // Numbers below this are reserved for writing player slot data - -// Below consts are only used for demo extrainfo sections -#define DW_STANDING 0x00 - -// For Metal Sonic and time attack ghosts -#define GZT_XYZ 0x01 -#define GZT_MOMXY 0x02 -#define GZT_MOMZ 0x04 -#define GZT_ANGLE 0x08 -// Not used for Metal Sonic -#define GZT_SPRITE 0x10 // Animation frame -#define GZT_EXTRA 0x20 - -// GZT_EXTRA flags -#define EZT_THOK 0x01 // Spawned a thok object -#define EZT_SPIN 0x02 // Because one type of thok object apparently wasn't enough -#define EZT_REV 0x03 // And two types wasn't enough either yet -#define EZT_THOKMASK 0x03 -#define EZT_COLOR 0x04 // Changed color (Super transformation, Mario fireflowers/invulnerability, etc.) -#define EZT_FLIP 0x08 // Reversed gravity -#define EZT_SCALE 0x10 // Changed size -#define EZT_HIT 0x20 // Damaged a mobj -#define EZT_SPRITE 0x40 // Changed sprite set completely out of PLAY (NiGHTS, SOCs, whatever) -#define EZT_KART 0x80 // SRB2Kart: Changed current held item/quantity and bumpers for battle - -static mobj_t oldmetal, oldghost[MAXPLAYERS]; - -void G_SaveMetal(UINT8 **buffer) +static void measurekeywords(mapsearchfreq_t *fr, + struct searchdim **dimp, UINT8 *cuntp, + const char *s, const char *q, boolean wanttable) { - I_Assert(buffer != NULL && *buffer != NULL); - - WRITEUINT32(*buffer, metal_p - metalbuffer); -} - -void G_LoadMetal(UINT8 **buffer) -{ - I_Assert(buffer != NULL && *buffer != NULL); - - G_DoPlayMetal(); - metal_p = metalbuffer + READUINT32(*buffer); -} - -ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) -{ - return M_Memcpy(dest, src, n*sizeof(*src)); -} - -ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n) -{ - size_t i; - for (i = 0; i < n; i++) + char *qp; + char *sp; + if (wanttable) + (*dimp) = Z_Realloc((*dimp), 255 * sizeof (struct searchdim), + PU_STATIC, NULL); + for (qp = strtok(va("%s", q), " "); + qp && fr->total < 255; + qp = strtok(0, " ")) { - dest[i].forwardmove = src[i].forwardmove; - dest[i].angleturn = SHORT(src[i].angleturn); - dest[i].aiming = (INT16)SHORT(src[i].aiming); - dest[i].buttons = (UINT16)SHORT(src[i].buttons); - dest[i].driftturn = (INT16)SHORT(src[i].driftturn); - dest[i].latency = (INT16)SHORT(src[i].latency); - } - return dest; -} - -// Finds a skin with the closest stats if the expected skin doesn't exist. -static INT32 GetSkinNumClosestToStats(UINT8 kartspeed, UINT8 kartweight) -{ - INT32 i, closest_skin = 0; - UINT8 closest_stats = UINT8_MAX, stat_diff; - - for (i = 0; i < numskins; i++) - { - stat_diff = abs(skins[i].kartspeed - kartspeed) + abs(skins[i].kartweight - kartweight); - if (stat_diff < closest_stats) + if (( sp = strcasestr(s, qp) )) { - closest_stats = stat_diff; - closest_skin = i; - } - } - - return closest_skin; -} - -static void FindClosestSkinForStats(UINT32 p, UINT8 kartspeed, UINT8 kartweight) -{ - INT32 closest_skin = GetSkinNumClosestToStats(kartspeed, kartweight); - - //CONS_Printf("Using %s instead...\n", skins[closest_skin].name); - SetPlayerSkinByNum(p, closest_skin); -} - -void G_ReadDemoExtraData(void) -{ - INT32 p, extradata, i; - char name[17]; - - if (leveltime > starttime) - { - rewind_t *rewind = CL_SaveRewindPoint(demo_p - demobuffer); - if (rewind) - { - memcpy(rewind->oldcmd, oldcmd, sizeof (oldcmd)); - memcpy(rewind->oldghost, oldghost, sizeof (oldghost)); - } - } - - memset(name, '\0', 17); - - p = READUINT8(demo_p); - - while (p < DW_EXTRASTUFF) - { - extradata = READUINT8(demo_p); - - if (extradata & DXD_RESPAWN) - { - if (players[p].mo) + if (wanttable) { - // Is this how this should work..? - K_DoIngameRespawn(&players[p]); + (*dimp)[(*cuntp)].pos = sp - s; + (*dimp)[(*cuntp)].siz = strlen(qp); } + (*cuntp)++; + fr->total++; } - if (extradata & DXD_SKIN) - { - UINT8 kartspeed, kartweight; - - // Skin - M_Memcpy(name, demo_p, 16); - demo_p += 16; - SetPlayerSkin(p, name); - - kartspeed = READUINT8(demo_p); - kartweight = READUINT8(demo_p); - - if (stricmp(skins[players[p].skin].name, name) != 0) - FindClosestSkinForStats(p, kartspeed, kartweight); - - players[p].kartspeed = kartspeed; - players[p].kartweight = kartweight; - } - if (extradata & DXD_COLOR) - { - // Color - M_Memcpy(name, demo_p, 16); - demo_p += 16; - for (i = 0; i < MAXSKINCOLORS; i++) - if (!stricmp(KartColor_Names[i], name)) // SRB2kart - { - players[p].skincolor = i; - if (players[p].mo) - players[p].mo->color = i; - break; - } - } - if (extradata & DXD_NAME) - { - // Name - M_Memcpy(player_names[p],demo_p,16); - demo_p += 16; - } - if (extradata & DXD_FOLLOWER) - { - // Set our follower - M_Memcpy(name, demo_p, 16); - demo_p += 16; - SetPlayerFollower(p, name); - - // Follower's color - M_Memcpy(name, demo_p, 16); - demo_p += 16; - for (i = 0; i < MAXSKINCOLORS; i++) - if (!stricmp(KartColor_Names[i], name)) // SRB2kart - { - players[p].followercolor = i; - break; - } - - - } - if (extradata & DXD_PLAYSTATE) - { - extradata = READUINT8(demo_p); - - switch (extradata) { - case DXD_PST_PLAYING: - players[p].pflags |= PF_WANTSTOJOIN; // fuck you - break; - - case DXD_PST_SPECTATING: - players[p].pflags &= ~PF_WANTSTOJOIN; // double-fuck you - if (!playeringame[p]) - { - CL_ClearPlayer(p); - playeringame[p] = true; - G_AddPlayer(p); - players[p].spectator = true; - - // There's likely an off-by-one error in timing recording or playback of joins. This hacks around it so I don't have to find out where that is. \o/ - if (oldcmd[p].forwardmove) - P_RandomByte(); - } - else - { - players[p].spectator = true; - if (players[p].mo) - P_DamageMobj(players[p].mo, NULL, NULL, 10000); - else - players[p].playerstate = PST_REBORN; - } - break; - - case DXD_PST_LEFT: - CL_RemovePlayer(p, 0); - break; - } - - G_ResetViews(); - - // maybe these are necessary? - if (G_BattleGametype()) - K_CheckBumpers(); // SRB2Kart - else if (G_RaceGametype()) - P_CheckRacers(); // also SRB2Kart - } - - - p = READUINT8(demo_p); - } - - while (p != DW_END) - { - UINT32 rng; - - switch (p) - { - case DW_RNG: - rng = READUINT32(demo_p); - if (P_GetRandSeed() != rng) - { - P_SetRandSeed(rng); - - if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); - demosynced = false; - } - } - - p = READUINT8(demo_p); - } - - if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) - { - // end of demo data stream - G_CheckDemoStatus(); - return; } + if (wanttable) + (*dimp) = Z_Realloc((*dimp), (*cuntp) * sizeof (struct searchdim), + PU_STATIC, NULL); } -void G_WriteDemoExtraData(void) +static void writesimplefreq(mapsearchfreq_t *fr, INT32 *frc, + INT32 mapnum, UINT8 pos, UINT8 siz) +{ + fr[(*frc)].mapnum = mapnum; + fr[(*frc)].matchd = ZZ_Alloc(sizeof (struct searchdim)); + fr[(*frc)].matchd[0].pos = pos; + fr[(*frc)].matchd[0].siz = siz; + fr[(*frc)].matchc = 1; + fr[(*frc)].total = 1; + (*frc)++; +} + +INT32 G_FindMap(const char *mapname, char **foundmapnamep, + mapsearchfreq_t **freqp, INT32 *freqcp) +{ + INT32 newmapnum = 0; + INT32 mapnum; + INT32 apromapnum = 0; + + size_t mapnamelen; + char *realmapname = NULL; + char *newmapname = NULL; + char *apromapname = NULL; + char *aprop = NULL; + + mapsearchfreq_t *freq; + boolean wanttable; + INT32 freqc; + UINT8 frequ; + + INT32 i; + + mapnamelen = strlen(mapname); + + /* Count available maps; how ugly. */ + for (i = 0, freqc = 0; i < NUMMAPS; ++i) + { + if (mapheaderinfo[i]) + freqc++; + } + + freq = ZZ_Calloc(freqc * sizeof (mapsearchfreq_t)); + + wanttable = !!( freqp ); + + freqc = 0; + for (i = 0, mapnum = 1; i < NUMMAPS; ++i, ++mapnum) + if (mapheaderinfo[i]) + { + if (!( realmapname = G_BuildMapTitle(mapnum) )) + continue; + + aprop = realmapname; + + /* Now that we found a perfect match no need to fucking guess. */ + if (strnicmp(realmapname, mapname, mapnamelen) == 0) + { + if (wanttable) + { + writesimplefreq(freq, &freqc, mapnum, 0, mapnamelen); + } + if (newmapnum == 0) + { + newmapnum = mapnum; + newmapname = realmapname; + realmapname = 0; + Z_Free(apromapname); + if (!wanttable) + break; + } + } + else + if (apromapnum == 0 || wanttable) + { + /* LEVEL 1--match keywords verbatim */ + if (( aprop = strcasestr(realmapname, mapname) )) + { + if (wanttable) + { + writesimplefreq(freq, &freqc, + mapnum, aprop - realmapname, mapnamelen); + } + if (apromapnum == 0) + { + apromapnum = mapnum; + apromapname = realmapname; + realmapname = 0; + } + } + else/* ...match individual keywords */ + { + freq[freqc].mapnum = mapnum; + measurekeywords(&freq[freqc], + &freq[freqc].matchd, &freq[freqc].matchc, + realmapname, mapname, wanttable); + measurekeywords(&freq[freqc], + &freq[freqc].keywhd, &freq[freqc].keywhc, + mapheaderinfo[i]->keywords, mapname, wanttable); + if (freq[freqc].total) + freqc++; + } + } + + Z_Free(realmapname);/* leftover old name */ + } + + if (newmapnum == 0)/* no perfect match--try a substring */ + { + newmapnum = apromapnum; + newmapname = apromapname; + } + + if (newmapnum == 0)/* calculate most queries met! */ + { + frequ = 0; + for (i = 0; i < freqc; ++i) + { + if (freq[i].total > frequ) + { + frequ = freq[i].total; + newmapnum = freq[i].mapnum; + } + } + if (newmapnum) + { + newmapname = G_BuildMapTitle(newmapnum); + } + } + + if (freqp) + (*freqp) = freq; + else + Z_Free(freq); + + if (freqcp) + (*freqcp) = freqc; + + if (foundmapnamep) + (*foundmapnamep) = newmapname; + else + Z_Free(newmapname); + + return newmapnum; +} + +void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc) { INT32 i; - char name[16]; - - for (i = 0; i < MAXPLAYERS; i++) + for (i = 0; i < freqc; ++i) { - if (demo_extradata[i]) - { - WRITEUINT8(demo_p, i); - WRITEUINT8(demo_p, demo_extradata[i]); + Z_Free(freq[i].matchd); + } + Z_Free(freq); +} - //if (demo_extradata[i] & DXD_RESPAWN) has no extra data - if (demo_extradata[i] & DXD_SKIN) +INT32 G_FindMapByNameOrCode(const char *mapname, char **realmapnamep) +{ + boolean usemapcode = false; + + INT32 newmapnum; + + size_t mapnamelen; + + char *p; + + mapnamelen = strlen(mapname); + + if (mapnamelen == 2)/* maybe two digit code */ + { + if (( newmapnum = M_MapNumber(mapname[0], mapname[1]) )) + usemapcode = true; + } + else if (mapnamelen == 5 && strnicmp(mapname, "MAP", 3) == 0) + { + if (( newmapnum = M_MapNumber(mapname[3], mapname[4]) )) + usemapcode = true; + } + + if (!usemapcode) + { + /* Now detect map number in base 10, which no one asked for. */ + newmapnum = strtol(mapname, &p, 10); + if (*p == '\0')/* we got it */ + { + if (newmapnum < 1 || newmapnum > NUMMAPS) { - // Skin - memset(name, 0, 16); - strncpy(name, skins[players[i].skin].name, 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - - WRITEUINT8(demo_p, skins[players[i].skin].kartspeed); - WRITEUINT8(demo_p, skins[players[i].skin].kartweight); - + CONS_Alert(CONS_ERROR, M_GetText("Invalid map number %d.\n"), newmapnum); + return 0; } - if (demo_extradata[i] & DXD_COLOR) - { - // Color - memset(name, 0, 16); - strncpy(name, KartColor_Names[players[i].skincolor], 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - } - if (demo_extradata[i] & DXD_NAME) - { - // Name - memset(name, 0, 16); - strncpy(name, player_names[i], 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - } - if (demo_extradata[i] & DXD_FOLLOWER) - { - // write follower - memset(name, 0, 16); - strncpy(name, followers[players[i].followerskin].skinname, 16); - M_Memcpy(demo_p, name, 16); - demo_p += 16; - - // write follower color - memset(name, 0, 16); - strncpy(name, Followercolor_cons_t[players[i].followercolor].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match" - M_Memcpy(demo_p,name,16); - demo_p += 16; - - } - if (demo_extradata[i] & DXD_PLAYSTATE) - { - demo_writerng = 1; - if (!playeringame[i]) - WRITEUINT8(demo_p, DXD_PST_LEFT); - else if ( - players[i].spectator && - !(players[i].pflags & PF_WANTSTOJOIN) // <= fuck you specifically - ) - WRITEUINT8(demo_p, DXD_PST_SPECTATING); - else - WRITEUINT8(demo_p, DXD_PST_PLAYING); - } - } - - demo_extradata[i] = 0; - } - - // May not be necessary, but might as well play it safe... - if ((leveltime & 255) == 128) - demo_writerng = 1; - - { - static UINT8 timeout = 0; - - if (timeout) timeout--; - - if (demo_writerng == 1 || (demo_writerng == 2 && timeout == 0)) - { - demo_writerng = 0; - timeout = 16; - WRITEUINT8(demo_p, DW_RNG); - WRITEUINT32(demo_p, P_GetRandSeed()); - } - } - - WRITEUINT8(demo_p, DW_END); -} - -void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum) -{ - UINT8 ziptic; - - if (!demo_p || !demo.deferstart) - return; - ziptic = READUINT8(demo_p); - - if (ziptic & ZT_FWD) - oldcmd[playernum].forwardmove = READSINT8(demo_p); - if (ziptic & ZT_ANGLE) - oldcmd[playernum].angleturn = READINT16(demo_p); - if (ziptic & ZT_BUTTONS) - oldcmd[playernum].buttons = READUINT16(demo_p); - if (ziptic & ZT_AIMING) - oldcmd[playernum].aiming = READINT16(demo_p); - if (ziptic & ZT_DRIFT) - oldcmd[playernum].driftturn = READINT16(demo_p); - if (ziptic & ZT_LATENCY) - oldcmd[playernum].latency = READUINT8(demo_p); - - G_CopyTiccmd(cmd, &oldcmd[playernum], 1); - - localangle[0] += (cmd->angleturn<<16); - - if (!(demoflags & DF_GHOST) && *demo_p == DEMOMARKER) - { - // end of demo data stream - G_CheckDemoStatus(); - return; - } -} - -void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum) -{ - char ziptic = 0; - UINT8 *ziptic_p; - - if (!demo_p) - return; - ziptic_p = demo_p++; // the ziptic, written at the end of this function - - if (cmd->forwardmove != oldcmd[playernum].forwardmove) - { - WRITEUINT8(demo_p,cmd->forwardmove); - oldcmd[playernum].forwardmove = cmd->forwardmove; - ziptic |= ZT_FWD; - } - - if (cmd->angleturn != oldcmd[playernum].angleturn) - { - WRITEINT16(demo_p,cmd->angleturn); - oldcmd[playernum].angleturn = cmd->angleturn; - ziptic |= ZT_ANGLE; - } - - if (cmd->buttons != oldcmd[playernum].buttons) - { - WRITEUINT16(demo_p,cmd->buttons); - oldcmd[playernum].buttons = cmd->buttons; - ziptic |= ZT_BUTTONS; - } - - if (cmd->aiming != oldcmd[playernum].aiming) - { - WRITEINT16(demo_p,cmd->aiming); - oldcmd[playernum].aiming = cmd->aiming; - ziptic |= ZT_AIMING; - } - - if (cmd->driftturn != oldcmd[playernum].driftturn) - { - WRITEINT16(demo_p,cmd->driftturn); - oldcmd[playernum].driftturn = cmd->driftturn; - ziptic |= ZT_DRIFT; - } - - if (cmd->latency != oldcmd[playernum].latency) - { - WRITEUINT8(demo_p,cmd->latency); - oldcmd[playernum].latency = cmd->latency; - ziptic |= ZT_LATENCY; - } - - *ziptic_p = ziptic; - - // attention here for the ticcmd size! - // latest demos with mouse aiming byte in ticcmd - if (!(demoflags & DF_GHOST) && ziptic_p > demoend - 9) - { - G_CheckDemoStatus(); // no more space - return; - } -} - -void G_GhostAddThok(INT32 playernum) -{ - if (!demo.recording || !(demoflags & DF_GHOST)) - return; - ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_THOK; -} - -void G_GhostAddSpin(INT32 playernum) -{ - if (!demo.recording || !(demoflags & DF_GHOST)) - return; - ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_SPIN; -} - -void G_GhostAddRev(INT32 playernum) -{ - if (!demo.recording || !(demoflags & DF_GHOST)) - return; - ghostext[playernum].flags = (ghostext[playernum].flags & ~EZT_THOKMASK) | EZT_REV; -} - -void G_GhostAddFlip(INT32 playernum) -{ - if (!demo.recording || !(demoflags & DF_GHOST)) - return; - ghostext[playernum].flags |= EZT_FLIP; -} - -void G_GhostAddColor(INT32 playernum, ghostcolor_t color) -{ - if (!demo.recording || !(demoflags & DF_GHOST)) - return; - if (ghostext[playernum].lastcolor == (UINT8)color) - { - ghostext[playernum].flags &= ~EZT_COLOR; - return; - } - ghostext[playernum].flags |= EZT_COLOR; - ghostext[playernum].color = (UINT8)color; -} - -void G_GhostAddScale(INT32 playernum, fixed_t scale) -{ - if (!demo.recording || !(demoflags & DF_GHOST)) - return; - if (ghostext[playernum].lastscale == scale) - { - ghostext[playernum].flags &= ~EZT_SCALE; - return; - } - ghostext[playernum].flags |= EZT_SCALE; - ghostext[playernum].scale = scale; -} - -void G_GhostAddHit(INT32 playernum, mobj_t *victim) -{ - if (!demo.recording || !(demoflags & DF_GHOST)) - return; - ghostext[playernum].flags |= EZT_HIT; - ghostext[playernum].hits++; - ghostext[playernum].hitlist = Z_Realloc(ghostext[playernum].hitlist, ghostext[playernum].hits * sizeof(mobj_t *), PU_LEVEL, NULL); - ghostext[playernum].hitlist[ghostext[playernum].hits-1] = victim; -} - -void G_WriteAllGhostTics(void) -{ - INT32 i, counter = leveltime; - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - counter++; - - if (counter % cv_netdemosyncquality.value != 0) // Only write 1 in this many ghost datas per tic to cut down on multiplayer replay size. - continue; - - WRITEUINT8(demo_p, i); - G_WriteGhostTic(players[i].mo, i); - } - WRITEUINT8(demo_p, 0xFF); -} - -void G_WriteGhostTic(mobj_t *ghost, INT32 playernum) -{ - char ziptic = 0; - UINT8 *ziptic_p; - UINT32 i; - UINT8 sprite; - UINT8 frame; - - if (!demo_p) - return; - if (!(demoflags & DF_GHOST)) - return; // No ghost data to write. - - ziptic_p = demo_p++; // the ziptic, written at the end of this function - - #define MAXMOM (0x7FFF<<8) - - // GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic. - if (abs(ghost->x-oldghost[playernum].x) > MAXMOM - || abs(ghost->y-oldghost[playernum].y) > MAXMOM - || abs(ghost->z-oldghost[playernum].z) > MAXMOM - || ((UINT8)(leveltime & 255) > 0 && (UINT8)(leveltime & 255) <= (UINT8)cv_netdemosyncquality.value)) // Hack to enable slightly nicer resyncing - { - oldghost[playernum].x = ghost->x; - oldghost[playernum].y = ghost->y; - oldghost[playernum].z = ghost->z; - ziptic |= GZT_XYZ; - WRITEFIXED(demo_p,oldghost[playernum].x); - WRITEFIXED(demo_p,oldghost[playernum].y); - WRITEFIXED(demo_p,oldghost[playernum].z); - } - else - { - // For moving normally: - // Store one full byte of movement, plus one byte of fractional movement. - INT16 momx = (INT16)((ghost->x-oldghost[playernum].x + (1<<4))>>8); - INT16 momy = (INT16)((ghost->y-oldghost[playernum].y + (1<<4))>>8); - if (momx != oldghost[playernum].momx - || momy != oldghost[playernum].momy) - { - oldghost[playernum].momx = momx; - oldghost[playernum].momy = momy; - ziptic |= GZT_MOMXY; - WRITEINT16(demo_p,momx); - WRITEINT16(demo_p,momy); - } - momx = (INT16)((ghost->z-oldghost[playernum].z + (1<<4))>>8); - if (momx != oldghost[playernum].momz) - { - oldghost[playernum].momz = momx; - ziptic |= GZT_MOMZ; - WRITEINT16(demo_p,momx); - } - - // This SHOULD set oldghost.x/y/z to match ghost->x/y/z - // but it keeps the fractional loss of one byte, - // so it will hopefully be made up for in future tics. - oldghost[playernum].x += oldghost[playernum].momx<<8; - oldghost[playernum].y += oldghost[playernum].momy<<8; - oldghost[playernum].z += oldghost[playernum].momz<<8; - } - - #undef MAXMOM - - // Only store the 8 most relevant bits of angle - // because exact values aren't too easy to discern to begin with when only 8 angles have different sprites - // and it does not affect this mode of movement at all anyway. - if (ghost->angle>>24 != oldghost[playernum].angle) - { - oldghost[playernum].angle = ghost->angle>>24; - ziptic |= GZT_ANGLE; - WRITEUINT8(demo_p,oldghost[playernum].angle); - } - - // Store the sprite frame. - frame = ghost->frame & FF_FRAMEMASK; - if (frame != oldghost[playernum].frame) - { - oldghost[playernum].frame = frame; - ziptic |= GZT_SPRITE; - WRITEUINT8(demo_p,oldghost[playernum].frame); - } - - // Check for sprite set changes - sprite = ghost->sprite; - if (sprite != oldghost[playernum].sprite) - { - oldghost[playernum].sprite = sprite; - ghostext[playernum].flags |= EZT_SPRITE; - } - - if (ghost->player) - { - if ( - ghostext[playernum].kartitem != ghost->player->kartstuff[k_itemtype] || - ghostext[playernum].kartamount != ghost->player->kartstuff[k_itemamount] || - ghostext[playernum].kartbumpers != ghost->player->kartstuff[k_bumper] - ) - { - ghostext[playernum].flags |= EZT_KART; - ghostext[playernum].kartitem = ghost->player->kartstuff[k_itemtype]; - ghostext[playernum].kartamount = ghost->player->kartstuff[k_itemamount]; - ghostext[playernum].kartbumpers = ghost->player->kartstuff[k_bumper]; - - } - } - - if (ghostext[playernum].color == ghostext[playernum].lastcolor) - ghostext[playernum].flags &= ~EZT_COLOR; - if (ghostext[playernum].scale == ghostext[playernum].lastscale) - ghostext[playernum].flags &= ~EZT_SCALE; - - if (ghostext[playernum].flags) - { - ziptic |= GZT_EXTRA; - WRITEUINT8(demo_p,ghostext[playernum].flags); - - if (ghostext[playernum].flags & EZT_COLOR) - { - WRITEUINT8(demo_p,ghostext[playernum].color); - ghostext[playernum].lastcolor = ghostext[playernum].color; - } - if (ghostext[playernum].flags & EZT_SCALE) - { - WRITEFIXED(demo_p,ghostext[playernum].scale); - ghostext[playernum].lastscale = ghostext[playernum].scale; - } - if (ghostext[playernum].flags & EZT_HIT) - { - WRITEUINT16(demo_p,ghostext[playernum].hits); - for (i = 0; i < ghostext[playernum].hits; i++) - { - mobj_t *mo = ghostext[playernum].hitlist[i]; - WRITEUINT32(demo_p,UINT32_MAX); // reserved for some method of determining exactly which mobj this is. (mobjnum doesn't work here.) - WRITEUINT32(demo_p,mo->type); - WRITEUINT16(demo_p,(UINT16)mo->health); - WRITEFIXED(demo_p,mo->x); - WRITEFIXED(demo_p,mo->y); - WRITEFIXED(demo_p,mo->z); - WRITEANGLE(demo_p,mo->angle); - } - Z_Free(ghostext[playernum].hitlist); - ghostext[playernum].hits = 0; - ghostext[playernum].hitlist = NULL; - } - if (ghostext[playernum].flags & EZT_SPRITE) - WRITEUINT8(demo_p,sprite); - if (ghostext[playernum].flags & EZT_KART) - { - WRITEINT32(demo_p, ghostext[playernum].kartitem); - WRITEINT32(demo_p, ghostext[playernum].kartamount); - WRITEINT32(demo_p, ghostext[playernum].kartbumpers); - } - ghostext[playernum].flags = 0; - } - - *ziptic_p = ziptic; - - // attention here for the ticcmd size! - // latest demos with mouse aiming byte in ticcmd - if (demo_p >= demoend - (13 + 9)) - { - G_CheckDemoStatus(); // no more space - return; - } -} - -void G_ConsAllGhostTics(void) -{ - UINT8 p = READUINT8(demo_p); - - while (p != 0xFF) - { - G_ConsGhostTic(p); - p = READUINT8(demo_p); - } - - if (*demo_p == DEMOMARKER) - { - // end of demo data stream - G_CheckDemoStatus(); - return; - } -} - -// Uses ghost data to do consistency checks on your position. -// This fixes desynchronising demos when fighting eggman. -void G_ConsGhostTic(INT32 playernum) -{ - UINT8 ziptic; - fixed_t px,py,pz,gx,gy,gz; - mobj_t *testmo; - fixed_t syncleeway; - boolean nightsfail = false; - - if (!demo_p || !demo.deferstart) - return; - if (!(demoflags & DF_GHOST)) - return; // No ghost data to use. - - testmo = players[playernum].mo; - - // Grab ghost data. - ziptic = READUINT8(demo_p); - if (ziptic & GZT_XYZ) - { - oldghost[playernum].x = READFIXED(demo_p); - oldghost[playernum].y = READFIXED(demo_p); - oldghost[playernum].z = READFIXED(demo_p); - syncleeway = 0; - } - else - { - if (ziptic & GZT_MOMXY) - { - oldghost[playernum].momx = READINT16(demo_p)<<8; - oldghost[playernum].momy = READINT16(demo_p)<<8; - } - if (ziptic & GZT_MOMZ) - oldghost[playernum].momz = READINT16(demo_p)<<8; - oldghost[playernum].x += oldghost[playernum].momx; - oldghost[playernum].y += oldghost[playernum].momy; - oldghost[playernum].z += oldghost[playernum].momz; - syncleeway = FRACUNIT; - } - if (ziptic & GZT_ANGLE) - demo_p++; - if (ziptic & GZT_SPRITE) - demo_p++; - - if (ziptic & GZT_EXTRA) - { // But wait, there's more! - ziptic = READUINT8(demo_p); - if (ziptic & EZT_COLOR) - demo_p++; - if (ziptic & EZT_SCALE) - demo_p += sizeof(fixed_t); - if (ziptic & EZT_HIT) - { // Resync mob damage. - UINT16 i, count = READUINT16(demo_p); - thinker_t *th; - mobj_t *mobj; - - UINT32 type; - UINT16 health; - fixed_t x; - fixed_t y; - fixed_t z; - - for (i = 0; i < count; i++) - { - demo_p += 4; // reserved. - type = READUINT32(demo_p); - health = READUINT16(demo_p); - x = READFIXED(demo_p); - y = READFIXED(demo_p); - z = READFIXED(demo_p); - demo_p += sizeof(angle_t); // angle, unnecessary for cons. - - mobj = NULL; - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mobj = (mobj_t *)th; - if (mobj->type == (mobjtype_t)type && mobj->x == x && mobj->y == y && mobj->z == z) - break; - mobj = NULL; // wasn't this one, keep searching. - } - if (mobj && mobj->health != health) // Wasn't damaged?! This is desync! Fix it! - { - if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); - demosynced = false; - P_DamageMobj(mobj, players[0].mo, players[0].mo, 1); - } - } - } - if (ziptic & EZT_SPRITE) - demo_p++; - if (ziptic & EZT_KART) - { - ghostext[playernum].kartitem = READINT32(demo_p); - ghostext[playernum].kartamount = READINT32(demo_p); - ghostext[playernum].kartbumpers = READINT32(demo_p); - } - } - - if (testmo) - { - // Re-synchronise - px = testmo->x; - py = testmo->y; - pz = testmo->z; - gx = oldghost[playernum].x; - gy = oldghost[playernum].y; - gz = oldghost[playernum].z; - - if (nightsfail || abs(px-gx) > syncleeway || abs(py-gy) > syncleeway || abs(pz-gz) > syncleeway) - { - ghostext[playernum].desyncframes++; - - if (ghostext[playernum].desyncframes >= 2) - { - if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); - demosynced = false; - - P_UnsetThingPosition(testmo); - testmo->x = oldghost[playernum].x; - testmo->y = oldghost[playernum].y; - P_SetThingPosition(testmo); - testmo->z = oldghost[playernum].z; - - if (abs(testmo->z - testmo->floorz) < 4*FRACUNIT) - testmo->z = testmo->floorz; // Sync players to the ground when they're likely supposed to be there... - - ghostext[playernum].desyncframes = 2; - } - } - else - ghostext[playernum].desyncframes = 0; - - if (players[playernum].kartstuff[k_itemtype] != ghostext[playernum].kartitem - || players[playernum].kartstuff[k_itemamount] != ghostext[playernum].kartamount - || players[playernum].kartstuff[k_bumper] != ghostext[playernum].kartbumpers) - { - if (demosynced) - CONS_Alert(CONS_WARNING, M_GetText("Demo playback has desynced!\n")); - demosynced = false; - - players[playernum].kartstuff[k_itemtype] = ghostext[playernum].kartitem; - players[playernum].kartstuff[k_itemamount] = ghostext[playernum].kartamount; - players[playernum].kartstuff[k_bumper] = ghostext[playernum].kartbumpers; - } - } - - if (*demo_p == DEMOMARKER) - { - // end of demo data stream - G_CheckDemoStatus(); - return; - } -} - -void G_GhostTicker(void) -{ - demoghost *g,*p; - for(g = ghosts, p = NULL; g; g = g->next) - { - // Skip normal demo data. - UINT8 ziptic = READUINT8(g->p); - - while (ziptic != DW_END) // Get rid of extradata stuff - { - if (ziptic == 0) // Only support player 0 info for now - { - ziptic = READUINT8(g->p); - if (ziptic & DXD_SKIN) - g->p += 18; // We _could_ read this info, but it shouldn't change anything in record attack... - if (ziptic & DXD_COLOR) - g->p += 16; // Same tbh - if (ziptic & DXD_NAME) - g->p += 16; // yea - if (ziptic & DXD_FOLLOWER) - g->p += 32; // ok (32 because there's both the skin and the colour) - if (ziptic & DXD_PLAYSTATE && READUINT8(g->p) != DXD_PST_PLAYING) - I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this - } - else if (ziptic == DW_RNG) - g->p += 4; // RNG seed - else - I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this - - ziptic = READUINT8(g->p); - } - - ziptic = READUINT8(g->p); // Back to actual ziptic stuff - - if (ziptic & ZT_FWD) - g->p++; - if (ziptic & ZT_ANGLE) - g->p += 2; - if (ziptic & ZT_BUTTONS) - g->p += 2; - if (ziptic & ZT_AIMING) - g->p += 2; - if (ziptic & ZT_DRIFT) - g->p += 2; - if (ziptic & ZT_LATENCY) - g->p += 1; - - // Grab ghost data. - ziptic = READUINT8(g->p); - - if (ziptic == 0xFF) - goto skippedghosttic; // Didn't write ghost info this frame - else if (ziptic != 0) - I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this - ziptic = READUINT8(g->p); - - if (ziptic & GZT_XYZ) - { - g->oldmo.x = READFIXED(g->p); - g->oldmo.y = READFIXED(g->p); - g->oldmo.z = READFIXED(g->p); + usemapcode = true; } else { - if (ziptic & GZT_MOMXY) - { - g->oldmo.momx = READINT16(g->p)<<8; - g->oldmo.momy = READINT16(g->p)<<8; - } - if (ziptic & GZT_MOMZ) - g->oldmo.momz = READINT16(g->p)<<8; - g->oldmo.x += g->oldmo.momx; - g->oldmo.y += g->oldmo.momy; - g->oldmo.z += g->oldmo.momz; - } - if (ziptic & GZT_ANGLE) - g->oldmo.angle = READUINT8(g->p)<<24; - if (ziptic & GZT_SPRITE) - g->oldmo.frame = READUINT8(g->p); - - // Update ghost - P_UnsetThingPosition(g->mo); - g->mo->x = g->oldmo.x; - g->mo->y = g->oldmo.y; - g->mo->z = g->oldmo.z; - P_SetThingPosition(g->mo); - g->mo->angle = g->oldmo.angle; - g->mo->frame = g->oldmo.frame | tr_trans30<p); - if (ziptic & EZT_COLOR) - { - g->color = READUINT8(g->p); - switch(g->color) - { - default: - case GHC_NORMAL: // Go back to skin color - g->mo->color = g->oldmo.color; - break; - // Handled below - case GHC_SUPER: - case GHC_INVINCIBLE: - break; - case GHC_FIREFLOWER: // Fireflower - g->mo->color = SKINCOLOR_WHITE; - break; - } - } - if (ziptic & EZT_FLIP) - g->mo->eflags ^= MFE_VERTICALFLIP; - if (ziptic & EZT_SCALE) - { - g->mo->destscale = READFIXED(g->p); - if (g->mo->destscale != g->mo->scale) - P_SetScale(g->mo, g->mo->destscale); - } - if (ziptic & EZT_THOKMASK) - { // Let's only spawn ONE of these per frame, thanks. - mobj_t *mobj; - INT32 type = -1; - if (g->mo->skin) - { - switch (ziptic & EZT_THOKMASK) - { - case EZT_THOK: - type = (UINT32)mobjinfo[MT_PLAYER].painchance; - break; - case EZT_SPIN: - type = (UINT32)mobjinfo[MT_PLAYER].damage; - break; - case EZT_REV: - type = (UINT32)mobjinfo[MT_PLAYER].raisestate; - break; - } - } - if (type == MT_GHOST) - { - mobj = P_SpawnGhostMobj(g->mo); // does a large portion of the work for us - mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|tr_trans60<mo->x, g->mo->y, g->mo->z - FixedDiv(FixedMul(g->mo->info->height, g->mo->scale) - g->mo->height,3*FRACUNIT), MT_THOK); - mobj->sprite = states[mobjinfo[type].spawnstate].sprite; - mobj->frame = (states[mobjinfo[type].spawnstate].frame & FF_FRAMEMASK) | tr_trans60<tics = -1; // nope. - mobj->color = g->mo->color; - if (g->mo->eflags & MFE_VERTICALFLIP) - { - mobj->flags2 |= MF2_OBJECTFLIP; - mobj->eflags |= MFE_VERTICALFLIP; - } - P_SetScale(mobj, g->mo->scale); - mobj->destscale = g->mo->scale; - } - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_UnsetThingPosition(mobj); - mobj->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... - P_SetThingPosition(mobj); - mobj->fuse = 8; - P_SetTarget(&mobj->target, g->mo); - } - if (ziptic & EZT_HIT) - { // Spawn hit poofs for killing things! - UINT16 i, count = READUINT16(g->p), health; - //UINT32 type; - fixed_t x,y,z; - angle_t angle; - mobj_t *poof; - for (i = 0; i < count; i++) - { - g->p += 4; // reserved - g->p += 4; // backwards compat., type used to be here - health = READUINT16(g->p); - x = READFIXED(g->p); - y = READFIXED(g->p); - z = READFIXED(g->p); - angle = READANGLE(g->p); - if (health != 0 || i >= 4) // only spawn for the first 4 hits per frame, to prevent ghosts from splode-spamming too bad. - continue; - poof = P_SpawnMobj(x, y, z, MT_GHOST); - poof->angle = angle; - poof->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; // make an ATTEMPT to curb crazy SOCs fucking stuff up... - poof->health = 0; - P_SetMobjStateNF(poof, S_XPLD1); - } - } - if (ziptic & EZT_SPRITE) - g->mo->sprite = READUINT8(g->p); - if (ziptic & EZT_KART) - g->p += 12; // kartitem, kartamount, kartbumpers - } - - if (READUINT8(g->p) != 0xFF) // Make sure there isn't other ghost data here. - I_Error("Ghost is not a record attack ghost"); //@TODO lmao don't blow up like this - -skippedghosttic: - // Tick ghost colors (Super and Mario Invincibility flashing) - switch(g->color) - { - case GHC_SUPER: // Super Sonic (P_DoSuperStuff) - g->mo->color = SKINCOLOR_SUPER1; - g->mo->color += abs( ( (signed)( (unsigned)leveltime >> 1 ) % 9) - 4); - break; - case GHC_INVINCIBLE: // Mario invincibility (P_CheckInvincibilityTimer) - g->mo->color = (UINT8)(leveltime % MAXSKINCOLORS); - break; - default: - break; - } - - // Demo ends after ghost data. - if (*g->p == DEMOMARKER) - { - g->mo->momx = g->mo->momy = g->mo->momz = 0; - if (p) - p->next = g->next; - else - ghosts = g->next; - Z_Free(g); - continue; - } - p = g; - } -} - -// Demo rewinding functions -typedef struct rewindinfo_s { - tic_t leveltime; - - struct { - boolean ingame; - player_t player; - mobj_t mobj; - } playerinfo[MAXPLAYERS]; - - struct rewindinfo_s *prev; -} rewindinfo_t; - -static tic_t currentrewindnum; -static rewindinfo_t *rewindhead = NULL; // Reverse chronological order - -void G_InitDemoRewind(void) -{ - CL_ClearRewinds(); - - while (rewindhead) - { - rewindinfo_t *p = rewindhead->prev; - Z_Free(rewindhead); - rewindhead = p; - } - - currentrewindnum = 0; -} - -void G_StoreRewindInfo(void) -{ - static UINT8 timetolog = 8; - rewindinfo_t *info; - size_t i; - - if (timetolog-- > 0) - return; - timetolog = 8; - - info = Z_Calloc(sizeof(rewindinfo_t), PU_STATIC, NULL); - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - { - info->playerinfo[i].ingame = false; - continue; - } - - info->playerinfo[i].ingame = true; - memcpy(&info->playerinfo[i].player, &players[i], sizeof(player_t)); - if (players[i].mo) - memcpy(&info->playerinfo[i].mobj, players[i].mo, sizeof(mobj_t)); - } - - info->leveltime = leveltime; - info->prev = rewindhead; - rewindhead = info; -} - -void G_PreviewRewind(tic_t previewtime) -{ - SINT8 i; - size_t j; - fixed_t tweenvalue = 0; - rewindinfo_t *info = rewindhead, *next_info = rewindhead; - - if (!info) - return; - - while (info->leveltime > previewtime && info->prev) - { - next_info = info; - info = info->prev; - } - if (info != next_info) - tweenvalue = FixedDiv(previewtime - info->leveltime, next_info->leveltime - info->leveltime); - - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - { - if (info->playerinfo[i].player.mo) - { - //@TODO spawn temp object to act as a player display - } - - continue; - } - - if (!info->playerinfo[i].ingame || !info->playerinfo[i].player.mo) - { - if (players[i].mo) - players[i].mo->drawflags |= MFD_DONTDRAW; - - continue; - } - - if (!players[i].mo) - continue; //@TODO spawn temp object to act as a player display - - players[i].mo->drawflags &= ~MFD_DONTDRAW; - - P_UnsetThingPosition(players[i].mo); -#define TWEEN(pr) info->playerinfo[i].mobj.pr + FixedMul((INT32) (next_info->playerinfo[i].mobj.pr - info->playerinfo[i].mobj.pr), tweenvalue) - players[i].mo->x = TWEEN(x); - players[i].mo->y = TWEEN(y); - players[i].mo->z = TWEEN(z); - players[i].mo->angle = TWEEN(angle); -#undef TWEEN - P_SetThingPosition(players[i].mo); - - players[i].frameangle = info->playerinfo[i].player.frameangle + FixedMul((INT32) (next_info->playerinfo[i].player.frameangle - info->playerinfo[i].player.frameangle), tweenvalue); - - players[i].mo->sprite = info->playerinfo[i].mobj.sprite; - players[i].mo->frame = info->playerinfo[i].mobj.frame; - - players[i].realtime = info->playerinfo[i].player.realtime; - for (j = 0; j < NUMKARTSTUFF; j++) - players[i].kartstuff[j] = info->playerinfo[i].player.kartstuff[j]; - } - - for (i = splitscreen; i >= 0; i--) - P_ResetCamera(&players[displayplayers[i]], &camera[i]); -} - -void G_ConfirmRewind(tic_t rewindtime) -{ - SINT8 i; - tic_t j; - boolean oldmenuactive = menuactive, oldsounddisabled = sound_disabled; - - INT32 olddp1 = displayplayers[0], olddp2 = displayplayers[1], olddp3 = displayplayers[2], olddp4 = displayplayers[3]; - UINT8 oldss = splitscreen; - - menuactive = false; // Prevent loops - - CV_StealthSetValue(&cv_renderview, 0); - - if (rewindtime <= starttime) - { - demo.rewinding = false; - G_DoPlayDemo(NULL); // Restart the current demo - } - else - { - rewind_t *rewind; - sound_disabled = true; // Prevent sound spam - demo.rewinding = true; - - rewind = CL_RewindToTime(rewindtime); - - if (rewind) - { - demo_p = demobuffer + rewind->demopos; - memcpy(oldcmd, rewind->oldcmd, sizeof (oldcmd)); - memcpy(oldghost, rewind->oldghost, sizeof (oldghost)); - paused = false; - } - else - { - demo.rewinding = true; - G_DoPlayDemo(NULL); // Restart the current demo + newmapnum = G_FindMap(mapname, realmapnamep, NULL, NULL); } } - for (j = 0; j < rewindtime && leveltime < rewindtime; j++) + if (usemapcode) { - G_Ticker((j % NEWTICRATERATIO) == 0); - } - - demo.rewinding = false; - menuactive = oldmenuactive; // Bring the menu back up - sound_disabled = oldsounddisabled; // Re-enable SFX - - wipegamestate = gamestate; // No fading back in! - - COM_BufInsertText("renderview on\n"); - - if (demo.freecam) - return; // don't touch from there - - splitscreen = oldss; - displayplayers[0] = olddp1; - displayplayers[1] = olddp2; - displayplayers[2] = olddp3; - displayplayers[3] = olddp4; - R_ExecuteSetViewSize(); - G_ResetViews(); - - for (i = splitscreen; i >= 0; i--) - P_ResetCamera(&players[displayplayers[i]], &camera[i]); -} - -void G_ReadMetalTic(mobj_t *metal) -{ - UINT8 ziptic; - UINT16 speed; - UINT8 statetype; - - if (!metal_p) - return; - ziptic = READUINT8(metal_p); - - // Read changes from the tic - if (ziptic & GZT_XYZ) - { - P_TeleportMove(metal, READFIXED(metal_p), READFIXED(metal_p), READFIXED(metal_p)); - oldmetal.x = metal->x; - oldmetal.y = metal->y; - oldmetal.z = metal->z; - } - else - { - if (ziptic & GZT_MOMXY) - { - oldmetal.momx = READINT16(metal_p)<<8; - oldmetal.momy = READINT16(metal_p)<<8; - } - if (ziptic & GZT_MOMZ) - oldmetal.momz = READINT16(metal_p)<<8; - oldmetal.x += oldmetal.momx; - oldmetal.y += oldmetal.momy; - oldmetal.z += oldmetal.momz; - } - if (ziptic & GZT_ANGLE) - oldmetal.angle = READUINT8(metal_p)<<24; - if (ziptic & GZT_SPRITE) - metal_p++; // Currently unused. (Metal Sonic figures out what he's doing his own damn self.) - - // Set movement, position, and angle - // oldmetal contains where you're supposed to be. - metal->momx = oldmetal.momx; - metal->momy = oldmetal.momy; - metal->momz = oldmetal.momz; - P_UnsetThingPosition(metal); - metal->x = oldmetal.x; - metal->y = oldmetal.y; - metal->z = oldmetal.z; - P_SetThingPosition(metal); - metal->angle = oldmetal.angle; - - if (ziptic & GZT_EXTRA) - { // But wait, there's more! - ziptic = READUINT8(metal_p); - if (ziptic & EZT_FLIP) - metal->eflags ^= MFE_VERTICALFLIP; - if (ziptic & EZT_SCALE) - { - metal->destscale = READFIXED(metal_p); - if (metal->destscale != metal->scale) - P_SetScale(metal, metal->destscale); - } - } - - // Calculates player's speed based on distance-of-a-line formula - speed = FixedDiv(P_AproxDistance(oldmetal.momx, oldmetal.momy), metal->scale)>>FRACBITS; - - // Use speed to decide an appropriate state - if (speed > 20) // default skin runspeed - statetype = 2; - else if (speed > 1) // stopspeed - statetype = 1; - else - statetype = 0; - - // Set state - if (statetype != metal->threshold) - { - switch (statetype) - { - case 2: // run - P_SetMobjState(metal,metal->info->meleestate); - break; - case 1: // walk - P_SetMobjState(metal,metal->info->seestate); - break; - default: // stand - P_SetMobjState(metal,metal->info->spawnstate); - break; - } - metal->threshold = statetype; - } - - // TODO: Modify state durations based on movement speed, similar to players? - - if (*metal_p == DEMOMARKER) - { - // end of demo data stream - G_StopMetalDemo(); - return; - } -} - -void G_WriteMetalTic(mobj_t *metal) -{ - UINT8 ziptic = 0; - UINT8 *ziptic_p; - - if (!demo_p) // demo_p will be NULL until the race start linedef executor is triggered! - return; - - ziptic_p = demo_p++; // the ziptic, written at the end of this function - - #define MAXMOM (0xFFFF<<8) - - // GZT_XYZ is only useful if you've moved 256 FRACUNITS or more in a single tic. - if (abs(metal->x-oldmetal.x) > MAXMOM - || abs(metal->y-oldmetal.y) > MAXMOM - || abs(metal->z-oldmetal.z) > MAXMOM) - { - oldmetal.x = metal->x; - oldmetal.y = metal->y; - oldmetal.z = metal->z; - WRITEFIXED(demo_p,oldmetal.x); - WRITEFIXED(demo_p,oldmetal.y); - WRITEFIXED(demo_p,oldmetal.z); - ziptic |= GZT_XYZ; - } - else - { - // For moving normally: - // Store one full byte of movement, plus one byte of fractional movement. - INT16 momx = (INT16)((metal->x-oldmetal.x)>>8); - INT16 momy = (INT16)((metal->y-oldmetal.y)>>8); - if (momx != oldmetal.momx - || momy != oldmetal.momy) - { - oldmetal.momx = momx; - oldmetal.momy = momy; - WRITEINT16(demo_p,momx); - WRITEINT16(demo_p,momy); - ziptic |= GZT_MOMXY; - } - momx = (INT16)((metal->z-oldmetal.z)>>8); - if (momx != oldmetal.momz) - { - oldmetal.momz = momx; - WRITEINT16(demo_p,momx); - ziptic |= GZT_MOMZ; - } - - // This SHOULD set oldmetal.x/y/z to match metal->x/y/z - // but it keeps the fractional loss of one byte, - // so it will hopefully be made up for in future tics. - oldmetal.x += oldmetal.momx<<8; - oldmetal.y += oldmetal.momy<<8; - oldmetal.z += oldmetal.momz<<8; - } - - #undef MAXMOM - - // Only store the 8 most relevant bits of angle - // because exact values aren't too easy to discern to begin with when only 8 angles have different sprites - // and it does not affect movement at all anyway. - if (metal->angle>>24 != oldmetal.angle) - { - oldmetal.angle = metal->angle>>24; - WRITEUINT8(demo_p,oldmetal.angle); - ziptic |= GZT_ANGLE; - } - - // Metal Sonic does not need our state changes. - // ... currently. - - { - UINT8 *exttic_p = NULL; - UINT8 exttic = 0; - if ((metal->eflags & MFE_VERTICALFLIP) != (oldmetal.eflags & MFE_VERTICALFLIP)) - { - if (!exttic_p) - exttic_p = demo_p++; - exttic |= EZT_FLIP; - oldmetal.eflags ^= MFE_VERTICALFLIP; - } - if (metal->scale != oldmetal.scale) - { - if (!exttic_p) - exttic_p = demo_p++; - exttic |= EZT_SCALE; - WRITEFIXED(demo_p,metal->scale); - oldmetal.scale = metal->scale; - } - if (exttic_p) - { - *exttic_p = exttic; - ziptic |= GZT_EXTRA; - } - } - - *ziptic_p = ziptic; - - // attention here for the ticcmd size! - // latest demos with mouse aiming byte in ticcmd - if (demo_p >= demoend - 32) - { - G_StopMetalRecording(); // no more space - return; - } -} - -// -// G_RecordDemo -// -void G_RecordDemo(const char *name) -{ - INT32 maxsize; - - CONS_Printf("Recording demo %s.lmp\n", name); - - strcpy(demoname, name); - strcat(demoname, ".lmp"); - //@TODO make a maxdemosize cvar - maxsize = 1024*1024*2; - if (M_CheckParm("-maxdemo") && M_IsNextParm()) - maxsize = atoi(M_GetNextParm()) * 1024; -// if (demobuffer) -// free(demobuffer); - demo_p = NULL; - demobuffer = malloc(maxsize); - demoend = demobuffer + maxsize; - - demo.recording = true; -} - -void G_RecordMetal(void) -{ - INT32 maxsize; - maxsize = 1024*1024; - if (M_CheckParm("-maxdemo") && M_IsNextParm()) - maxsize = atoi(M_GetNextParm()) * 1024; - demo_p = NULL; - demobuffer = malloc(maxsize); - demoend = demobuffer + maxsize; - metalrecording = true; -} - -void G_BeginRecording(void) -{ - UINT8 i, p; - char name[16]; - player_t *player = &players[consoleplayer]; - - char *filename; - UINT8 totalfiles; - UINT8 *m; - - if (demo_p) - return; - memset(name,0,sizeof(name)); - - demo_p = demobuffer; - demoflags = DF_GHOST|(multiplayer ? DF_MULTIPLAYER : (modeattacking<important) - { - nameonly(( filename = va("%s", wadfiles[i]->filename) )); - WRITESTRINGN(demo_p, filename, 64); - WRITEMEM(demo_p, wadfiles[i]->md5sum, 16); - - totalfiles++; - } - - WRITEUINT8(m, totalfiles); - - switch ((demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) - { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - WRITEUINT32(demo_p,UINT32_MAX); // lap - break; - case ATTACKING_CAPSULES: // 2 - demotime_p = demo_p; - WRITEUINT32(demo_p,UINT32_MAX); // time - break; - default: // 3 - break; - } - - WRITEUINT32(demo_p,P_GetInitSeed()); - - // Reserved for extrainfo location from start of file - demoinfo_p = demo_p; - WRITEUINT32(demo_p, 0); - - // Save netvars - CV_SaveNetVars(&demo_p, true); - - // Now store some info for each in-game player - - // Lat' 12/05/19: Do note that for the first game you load, everything that gets saved here is total garbage; - // The name will always be Player , the skin sonic, the color None and the follower 0. This is only correct on subsequent games. - // In the case of said first game, the skin and the likes are updated with Got_NameAndColor, which are then saved in extradata for the demo with DXD_SKIN in r_things.c for instance. - - - for (p = 0; p < MAXPLAYERS; p++) { - if (playeringame[p]) { - player = &players[p]; - - WRITEUINT8(demo_p, p | (player->spectator ? DEMO_SPECTATOR : 0)); - - // Name - memset(name, 0, 16); - strncpy(name, player_names[p], 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Skin - memset(name, 0, 16); - strncpy(name, skins[player->skin].name, 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Color - memset(name, 0, 16); - strncpy(name, KartColor_Names[player->skincolor], 16); - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Save follower's skin name - // PS: We must check for 'follower' to determine if the followerskin is valid. It's going to be 0 if we don't have a follower, but 0 is also absolutely a valid follower! - // Doesn't really matter if the follower mobj is valid so long as it exists in a way or another. - - memset(name, 0, 16); - if (player->follower) - strncpy(name, followers[player->followerskin].skinname, 16); - else - strncpy(name, "None", 16); // Say we don't have one, then. - - M_Memcpy(demo_p,name,16); - demo_p += 16; - - // Save follower's colour - memset(name, 0, 16); - strncpy(name, Followercolor_cons_t[player->followercolor].strvalue, 16); // Not KartColor_Names because followercolor has extra values such as "Match" - M_Memcpy(demo_p, name, 16); - demo_p += 16; - - // Score, since Kart uses this to determine where you start on the map - WRITEUINT32(demo_p, player->score); - - // Power Levels - WRITEUINT16(demo_p, clientpowerlevels[p][G_BattleGametype() ? PWRLV_BATTLE : PWRLV_RACE]); - - // Kart speed and weight - WRITEUINT8(demo_p, skins[player->skin].kartspeed); - WRITEUINT8(demo_p, skins[player->skin].kartweight); - - } - } - - WRITEUINT8(demo_p, 0xFF); // Denote the end of the player listing - -#ifdef HAVE_BLUA - // player lua vars, always saved even if empty... Unless it's record attack. - if (!modeattacking) - LUA_ArchiveDemo(); -#endif - - memset(&oldcmd,0,sizeof(oldcmd)); - memset(&oldghost,0,sizeof(oldghost)); - memset(&ghostext,0,sizeof(ghostext)); - - for (i = 0; i < MAXPLAYERS; i++) - { - ghostext[i].lastcolor = ghostext[i].color = GHC_NORMAL; - ghostext[i].lastscale = ghostext[i].scale = FRACUNIT; - - if (players[i].mo) - { - oldghost[i].x = players[i].mo->x; - oldghost[i].y = players[i].mo->y; - oldghost[i].z = players[i].mo->z; - oldghost[i].angle = players[i].mo->angle; - - // preticker started us gravity flipped - if (players[i].mo->eflags & MFE_VERTICALFLIP) - ghostext[i].flags |= EZT_FLIP; - } - } -} - -void G_BeginMetal(void) -{ - mobj_t *mo = players[consoleplayer].mo; - - if (demo_p) - return; - - demo_p = demobuffer; - - // Write header. - M_Memcpy(demo_p, DEMOHEADER, 12); demo_p += 12; - WRITEUINT8(demo_p,VERSION); - WRITEUINT8(demo_p,SUBVERSION); - WRITEUINT16(demo_p,DEMOVERSION); - - // demo checksum - demo_p += 16; - - M_Memcpy(demo_p, "METL", 4); demo_p += 4; - - // Set up our memory. - memset(&oldmetal,0,sizeof(oldmetal)); - oldmetal.x = mo->x; - oldmetal.y = mo->y; - oldmetal.z = mo->z; - oldmetal.angle = mo->angle; -} - -void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT32 val) -{ - char temp[16]; - - if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) - { - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - *(UINT32 *)demoinfo_p = demo_p - demobuffer; - } - - WRITEUINT8(demo_p, DW_STANDING); - WRITEUINT8(demo_p, ranking); - - // Name - memset(temp, 0, 16); - strncpy(temp, name, 16); - M_Memcpy(demo_p,temp,16); - demo_p += 16; - - // Skin - memset(temp, 0, 16); - strncpy(temp, skins[skinnum].name, 16); - M_Memcpy(demo_p,temp,16); - demo_p += 16; - - // Color - memset(temp, 0, 16); - strncpy(temp, KartColor_Names[color], 16); - M_Memcpy(demo_p,temp,16); - demo_p += 16; - - // Score/time/whatever - WRITEUINT32(demo_p, val); -} - -void G_SetDemoTime(UINT32 ptime, UINT32 plap) -{ - if (!demo.recording || !demotime_p) - return; - if (demoflags & DF_TIMEATTACK) - { - WRITEUINT32(demotime_p, ptime); - WRITEUINT32(demotime_p, plap); - demotime_p = NULL; - } - else if (demoflags & DF_BREAKTHECAPSULES) - { - WRITEUINT32(demotime_p, ptime); - (void)plap; - demotime_p = NULL; - } -} - -static void G_LoadDemoExtraFiles(UINT8 **pp) -{ - UINT8 totalfiles; - char filename[MAX_WADPATH]; - UINT8 md5sum[16]; - filestatus_t ncs; - boolean toomany = false; - boolean alreadyloaded; - UINT8 i, j; - - totalfiles = READUINT8((*pp)); - for (i = 0; i < totalfiles; ++i) - { - if (toomany) - SKIPSTRING((*pp)); - else - { - strlcpy(filename, (char *)(*pp), sizeof filename); - SKIPSTRING((*pp)); - } - READMEM((*pp), md5sum, 16); - - if (!toomany) - { - alreadyloaded = false; - - for (j = 0; j < numwadfiles; ++j) - { - if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) - { - alreadyloaded = true; - break; - } - } - - if (alreadyloaded) - continue; - - if (numwadfiles >= MAX_WADFILES) - toomany = true; - else - ncs = findfile(filename, md5sum, false); - - if (toomany) - { - CONS_Alert(CONS_WARNING, M_GetText("Too many files loaded to add anymore for demo playback\n")); - if (!CON_Ready()) - M_StartMessage(M_GetText("There are too many files loaded to add this demo's addons.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); - } - else if (ncs != FS_FOUND) - { - if (ncs == FS_NOTFOUND) - CONS_Alert(CONS_NOTICE, M_GetText("You do not have a copy of %s\n"), filename); - else if (ncs == FS_MD5SUMBAD) - CONS_Alert(CONS_NOTICE, M_GetText("Checksum mismatch on %s\n"), filename); - else - CONS_Alert(CONS_NOTICE, M_GetText("Unknown error finding file %s\n"), filename); - - if (!CON_Ready()) - M_StartMessage(M_GetText("There were errors trying to add this demo's addons. Check the console for more information.\n\nDemo playback may desync.\n\nPress ESC\n"), NULL, MM_NOTHING); - } - else - { - P_AddWadFile(filename); - } - } - } -} - -static void G_SkipDemoExtraFiles(UINT8 **pp) -{ - UINT8 totalfiles; - UINT8 i; - - totalfiles = READUINT8((*pp)); - for (i = 0; i < totalfiles; ++i) - { - SKIPSTRING((*pp));// file name - (*pp) += 16;// md5 - } -} - -// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's. -// Enabling quick prevents filesystem checks to see if needed files are available to load. -static UINT8 G_CheckDemoExtraFiles(UINT8 **pp, boolean quick) -{ - UINT8 totalfiles, filesloaded, nmusfilecount; - char filename[MAX_WADPATH]; - UINT8 md5sum[16]; - boolean toomany = false; - boolean alreadyloaded; - UINT8 i, j; - UINT8 error = 0; - - totalfiles = READUINT8((*pp)); - filesloaded = 0; - for (i = 0; i < totalfiles; ++i) - { - if (toomany) - SKIPSTRING((*pp)); - else - { - strlcpy(filename, (char *)(*pp), sizeof filename); - SKIPSTRING((*pp)); - } - READMEM((*pp), md5sum, 16); - - if (!toomany) - { - alreadyloaded = false; - nmusfilecount = 0; - - for (j = 0; j < numwadfiles; ++j) - { - if (wadfiles[j]->important && j > mainwads) - nmusfilecount++; - else - continue; - - if (memcmp(md5sum, wadfiles[j]->md5sum, 16) == 0) - { - alreadyloaded = true; - - if (i != nmusfilecount-1 && error < DFILE_ERROR_OUTOFORDER) - error |= DFILE_ERROR_OUTOFORDER; - - break; - } - } - - if (alreadyloaded) - { - filesloaded++; - continue; - } - - if (numwadfiles >= MAX_WADFILES) - error = DFILE_ERROR_CANNOTLOAD; - else if (!quick && findfile(filename, md5sum, false) != FS_FOUND) - error = DFILE_ERROR_CANNOTLOAD; - else if (error < DFILE_ERROR_INCOMPLETEOUTOFORDER) - error |= DFILE_ERROR_NOTLOADED; - } else - error = DFILE_ERROR_CANNOTLOAD; - } - - // Get final file count - nmusfilecount = 0; - - for (j = 0; j < numwadfiles; ++j) - if (wadfiles[j]->important && j > mainwads) - nmusfilecount++; - - if (!error && filesloaded < nmusfilecount) - error = DFILE_ERROR_EXTRAFILES; - - return error; -} - -// Returns bitfield: -// 1 == new demo has lower time -// 2 == new demo has higher score -// 4 == new demo has higher rings -UINT8 G_CmpDemoTime(char *oldname, char *newname) -{ - UINT8 *buffer,*p; - UINT8 flags; - UINT32 oldtime, newtime, oldlap, newlap; - UINT16 oldversion; - size_t bufsize ATTRUNUSED; - UINT8 c; - UINT16 s ATTRUNUSED; - UINT8 aflags = 0; - boolean uselaps = false; - - // load the new file - FIL_DefaultExtension(newname, ".lmp"); - bufsize = FIL_ReadFile(newname, &buffer); - I_Assert(bufsize != 0); - p = buffer; - - // read demo header - I_Assert(!memcmp(p, DEMOHEADER, 12)); - p += 12; // DEMOHEADER - c = READUINT8(p); // VERSION - I_Assert(c == VERSION); - c = READUINT8(p); // SUBVERSION - I_Assert(c == SUBVERSION); - s = READUINT16(p); - I_Assert(s == DEMOVERSION); - p += 64; // full demo title - p += 16; // demo checksum - I_Assert(!memcmp(p, "PLAY", 4)); - p += 4; // PLAY - p += 2; // gamemap - p += 16; // map md5 - flags = READUINT8(p); // demoflags - p++; // gametype - G_SkipDemoExtraFiles(&p); - - aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES); - I_Assert(aflags); - - if (flags & DF_TIMEATTACK) - uselaps = true; // get around uninitalized error - - newtime = READUINT32(p); - if (uselaps) - newlap = READUINT32(p); - else - newlap = UINT32_MAX; - - Z_Free(buffer); - - // load old file - FIL_DefaultExtension(oldname, ".lmp"); - if (!FIL_ReadFile(oldname, &buffer)) - { - CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), oldname); - return UINT8_MAX; - } - p = buffer; - - // read demo header - if (memcmp(p, DEMOHEADER, 12)) - { - CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); - Z_Free(buffer); - return UINT8_MAX; - } p += 12; // DEMOHEADER - p++; // VERSION - p++; // SUBVERSION - oldversion = READUINT16(p); - switch(oldversion) // demoversion - { - case DEMOVERSION: // latest always supported - p += 64; // full demo title - break; - // too old, cannot support. - default: - CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); - Z_Free(buffer); - return UINT8_MAX; - } - p += 16; // demo checksum - if (memcmp(p, "PLAY", 4)) - { - CONS_Alert(CONS_NOTICE, M_GetText("File '%s' invalid format. It will be overwritten.\n"), oldname); - Z_Free(buffer); - return UINT8_MAX; - } p += 4; // "PLAY" - p += 2; // gamemap - p += 16; // mapmd5 - flags = READUINT8(p); - p++; // gametype - G_SkipDemoExtraFiles(&p); - if (!(flags & aflags)) - { - CONS_Alert(CONS_NOTICE, M_GetText("File '%s' not from same game mode. It will be overwritten.\n"), oldname); - Z_Free(buffer); - return UINT8_MAX; - } - - oldtime = READUINT32(p); - if (uselaps) - oldlap = READUINT32(p); - else - oldlap = 0; - - Z_Free(buffer); - - c = 0; - - if (uselaps) - { - if (newtime < oldtime - || (newtime == oldtime && (newlap < oldlap))) - c |= 1; // Better time - if (newlap < oldlap - || (newlap == oldlap && newtime < oldtime)) - c |= 1<<1; // Better lap time - } - else - { - if (newtime < oldtime) - c |= 1; // Better time - } - - return c; -} - -void G_LoadDemoInfo(menudemo_t *pdemo) -{ - UINT8 *infobuffer, *info_p, *extrainfo_p; - UINT8 version, subversion, pdemoflags; - UINT16 pdemoversion, count; - - if (!FIL_ReadFile(pdemo->filepath, &infobuffer)) - { - CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), pdemo->filepath); - pdemo->type = MD_INVALID; - sprintf(pdemo->title, "INVALID REPLAY"); - - return; - } - - info_p = infobuffer; - - if (memcmp(info_p, DEMOHEADER, 12)) - { - CONS_Alert(CONS_ERROR, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemo->filepath); - pdemo->type = MD_INVALID; - sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); - return; - } - - pdemo->type = MD_LOADED; - - info_p += 12; // DEMOHEADER - - version = READUINT8(info_p); - subversion = READUINT8(info_p); - pdemoversion = READUINT16(info_p); - - switch(pdemoversion) - { - case DEMOVERSION: // latest always supported - // demo title - M_Memcpy(pdemo->title, info_p, 64); - info_p += 64; - - break; - // too old, cannot support. - default: - CONS_Alert(CONS_ERROR, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemo->filepath); - pdemo->type = MD_INVALID; - sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); - return; - } - - if (version != VERSION || subversion != SUBVERSION) - pdemo->type = MD_OUTDATED; - - info_p += 16; // demo checksum - if (memcmp(info_p, "PLAY", 4)) - { - CONS_Alert(CONS_ERROR, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemo->filepath); - pdemo->type = MD_INVALID; - sprintf(pdemo->title, "INVALID REPLAY"); - Z_Free(infobuffer); - return; - } - info_p += 4; // "PLAY" - pdemo->map = READINT16(info_p); - info_p += 16; // mapmd5 - - pdemoflags = READUINT8(info_p); - - // temp? - if (!(pdemoflags & DF_MULTIPLAYER)) - { - CONS_Alert(CONS_ERROR, M_GetText("%s is not a multiplayer replay and can't be listed on this menu fully yet.\n"), pdemo->filepath); - Z_Free(infobuffer); - return; - } - - pdemo->gametype = READUINT8(info_p); - - pdemo->addonstatus = G_CheckDemoExtraFiles(&info_p, true); - info_p += 4; // RNG seed - - extrainfo_p = infobuffer + READUINT32(info_p); - - // Pared down version of CV_LoadNetVars to find the kart speed - pdemo->kartspeed = KARTSPEED_NORMAL; // Default to normal speed - count = READUINT16(info_p); - while (count--) - { - UINT16 netid; - char *svalue; - - netid = READUINT16(info_p); - svalue = (char *)info_p; - SKIPSTRING(info_p); - info_p++; // stealth - - if (netid == cv_kartspeed.netid) - { - UINT8 j; - for (j = 0; kartspeed_cons_t[j].strvalue; j++) - if (!stricmp(kartspeed_cons_t[j].strvalue, svalue)) - pdemo->kartspeed = kartspeed_cons_t[j].value; - } - else if (netid == cv_basenumlaps.netid && pdemo->gametype == GT_RACE) - pdemo->numlaps = atoi(svalue); - } - - if (pdemoflags & DF_ENCORE) - pdemo->kartspeed |= DF_ENCORE; - - /*// Temporary info until this is actually present in replays. - (void)extrainfo_p; - sprintf(pdemo->winnername, "transrights420"); - pdemo->winnerskin = 1; - pdemo->winnercolor = SKINCOLOR_MOONSET; - pdemo->winnertime = 6666;*/ - - // Read standings! - count = 0; - - while (READUINT8(extrainfo_p) == DW_STANDING) // Assume standings are always first in the extrainfo - { - INT32 i; - char temp[16]; - - pdemo->standings[count].ranking = READUINT8(extrainfo_p); - - // Name - M_Memcpy(pdemo->standings[count].name, extrainfo_p, 16); - extrainfo_p += 16; - - // Skin - M_Memcpy(temp,extrainfo_p,16); - extrainfo_p += 16; - pdemo->standings[count].skin = UINT8_MAX; - for (i = 0; i < numskins; i++) - if (stricmp(skins[i].name, temp) == 0) - { - pdemo->standings[count].skin = i; - break; - } - - // Color - M_Memcpy(temp,extrainfo_p,16); - extrainfo_p += 16; - for (i = 0; i < MAXSKINCOLORS; i++) - if (!stricmp(KartColor_Names[i],temp)) // SRB2kart - { - pdemo->standings[count].color = i; - break; - } - - // Score/time/whatever - pdemo->standings[count].timeorscore = READUINT32(extrainfo_p); - - count++; - - if (count >= MAXPLAYERS) - break; //@TODO still cycle through the rest of these if extra demo data is ever used - } - - // I think that's everything we need? - Z_Free(infobuffer); -} - -// -// G_PlayDemo -// -void G_DeferedPlayDemo(const char *name) -{ - COM_BufAddText("playdemo \""); - COM_BufAddText(name); - COM_BufAddText("\" -addfiles\n"); -} - -// -// Start a demo from a .LMP file or from a wad resource -// -#define SKIPERRORS -void G_DoPlayDemo(char *defdemoname) -{ - UINT8 i, p; - lumpnum_t l; - char skin[17],color[17],follower[17],*n,*pdemoname; - UINT8 version,subversion; - UINT32 randseed; - char msg[1024]; -#if defined(SKIPERRORS) && !defined(DEVELOP) - boolean skiperrors = false; -#endif - boolean spectator; - UINT8 slots[MAXPLAYERS], kartspeed[MAXPLAYERS], kartweight[MAXPLAYERS], numslots = 0; - - G_InitDemoRewind(); - - skin[16] = '\0'; - color[16] = '\0'; - follower[16] = '\0'; - - // No demo name means we're restarting the current demo - if (defdemoname == NULL) - { - demo_p = demobuffer; - pdemoname = ZZ_Alloc(1); // Easier than adding checks for this everywhere it's freed - } - else - { - n = defdemoname+strlen(defdemoname); - while (*n != '/' && *n != '\\' && n != defdemoname) - n--; - if (n != defdemoname) - n++; - pdemoname = ZZ_Alloc(strlen(n)+1); - strcpy(pdemoname,n); - - M_SetPlaybackMenuPointer(); - - // Internal if no extension, external if one exists - if (FIL_CheckExtension(defdemoname)) - { - //FIL_DefaultExtension(defdemoname, ".lmp"); - if (!FIL_ReadFile(defdemoname, &demobuffer)) - { - snprintf(msg, 1024, M_GetText("Failed to read file '%s'.\n"), defdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - gameaction = ga_nothing; - M_StartMessage(msg, NULL, MM_NOTHING); - return; - } - demo_p = demobuffer; - } - // load demo resource from WAD - else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) - { - snprintf(msg, 1024, M_GetText("Failed to read lump '%s'.\n"), defdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - gameaction = ga_nothing; - M_StartMessage(msg, NULL, MM_NOTHING); - return; - } - else // it's an internal demo - { - demobuffer = demo_p = W_CacheLumpNum(l, PU_STATIC); -#if defined(SKIPERRORS) && !defined(DEVELOP) - skiperrors = true; // SRB2Kart: Don't print warnings for staff ghosts, since they'll inevitably happen when we make bugfixes/changes... -#endif - } - } - - // read demo header - gameaction = ga_nothing; - demo.playback = true; - if (memcmp(demo_p, DEMOHEADER, 12)) - { - snprintf(msg, 1024, M_GetText("%s is not a SRB2Kart replay file.\n"), pdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demo.playback = false; - demo.title = false; - return; - } - demo_p += 12; // DEMOHEADER - - version = READUINT8(demo_p); - subversion = READUINT8(demo_p); - demo.version = READUINT16(demo_p); - switch(demo.version) - { - case DEMOVERSION: // latest always supported - // demo title - M_Memcpy(demo.titlename, demo_p, 64); - demo_p += 64; - - break; - // too old, cannot support. - default: - snprintf(msg, 1024, M_GetText("%s is an incompatible replay format and cannot be played.\n"), pdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demo.playback = false; - demo.title = false; - return; - } - demo_p += 16; // demo checksum - if (memcmp(demo_p, "PLAY", 4)) - { - snprintf(msg, 1024, M_GetText("%s is the wrong type of recording and cannot be played.\n"), pdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demo.playback = false; - demo.title = false; - return; - } - demo_p += 4; // "PLAY" - gamemap = READINT16(demo_p); - demo_p += 16; // mapmd5 - - demoflags = READUINT8(demo_p); - gametype = READUINT8(demo_p); - - if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running. - G_SkipDemoExtraFiles(&demo_p); - else if (demo.loadfiles) - G_LoadDemoExtraFiles(&demo_p); - else if (demo.ignorefiles) - G_SkipDemoExtraFiles(&demo_p); - else - { - UINT8 error = G_CheckDemoExtraFiles(&demo_p, false); - - if (error) - { - switch (error) - { - case DFILE_ERROR_NOTLOADED: - snprintf(msg, 1024, - M_GetText("Required files for this demo are not loaded.\n\nUse\n\"playdemo %s -addfiles\"\nto load them and play the demo.\n"), - pdemoname); - break; - - case DFILE_ERROR_OUTOFORDER: - snprintf(msg, 1024, - M_GetText("Required files for this demo are loaded out of order.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; - - case DFILE_ERROR_INCOMPLETEOUTOFORDER: - snprintf(msg, 1024, - M_GetText("Required files for this demo are not loaded, and some are out of order.\n\nUse\n\"playdemo %s -addfiles\"\nto load needed files and play the demo.\n"), - pdemoname); - break; - - case DFILE_ERROR_CANNOTLOAD: - snprintf(msg, 1024, - M_GetText("Required files for this demo cannot be loaded.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; - - case DFILE_ERROR_EXTRAFILES: - snprintf(msg, 1024, - M_GetText("You have additional files loaded beyond the demo's file list.\n\nUse\n\"playdemo %s -force\"\nto play the demo anyway.\n"), - pdemoname); - break; - } - - CONS_Alert(CONS_ERROR, "%s", msg); - if (!CON_Ready()) // In the console they'll just see the notice there! No point pulling them out. - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demo.playback = false; - demo.title = false; - return; - } - } - - modeattacking = (demoflags & DF_ATTACKMASK)>>DF_ATTACKSHIFT; - multiplayer = !!(demoflags & DF_MULTIPLAYER); - CON_ToggleOff(); - - hu_demotime = UINT32_MAX; - hu_demolap = UINT32_MAX; - - switch (modeattacking) - { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - hu_demotime = READUINT32(demo_p); - hu_demolap = READUINT32(demo_p); - break; - case ATTACKING_CAPSULES: // 2 - hu_demotime = READUINT32(demo_p); - break; - default: // 3 - modeattacking = ATTACKING_NONE; - break; - } - - // Random seed - randseed = READUINT32(demo_p); - demo_p += 4; // Extrainfo location - - // ...*map* not loaded? - if (!gamemap || (gamemap > NUMMAPS) || !mapheaderinfo[gamemap-1] || !(mapheaderinfo[gamemap-1]->menuflags & LF2_EXISTSHACK)) - { - snprintf(msg, 1024, M_GetText("%s features a course that is not currently loaded.\n"), pdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demo.playback = false; - demo.title = false; - return; - } - - // net var data - CV_LoadNetVars(&demo_p); - - // Sigh ... it's an empty demo. - if (*demo_p == DEMOMARKER) - { - snprintf(msg, 1024, M_GetText("%s contains no data to be played.\n"), pdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demo.playback = false; - demo.title = false; - return; - } - - Z_Free(pdemoname); - - memset(&oldcmd,0,sizeof(oldcmd)); - memset(&oldghost,0,sizeof(oldghost)); - memset(&ghostext,0,sizeof(ghostext)); - -#if defined(SKIPERRORS) && !defined(DEVELOP) - if ((VERSION != version || SUBVERSION != subversion) && !skiperrors) -#else - if (VERSION != version || SUBVERSION != subversion) -#endif - CONS_Alert(CONS_WARNING, M_GetText("Demo version does not match game version. Desyncs may occur.\n")); - - // console warning messages -#if defined(SKIPERRORS) && !defined(DEVELOP) - demosynced = (!skiperrors); -#else - demosynced = true; -#endif - - // didn't start recording right away. - demo.deferstart = false; - -/*#ifdef HAVE_BLUA - LUAh_MapChange(gamemap); -#endif*/ - displayplayers[0] = consoleplayer = 0; - memset(playeringame,0,sizeof(playeringame)); - - // Load players that were in-game when the map started - p = READUINT8(demo_p); - - for (i = 1; i < MAXSPLITSCREENPLAYERS; i++) - displayplayers[i] = INT32_MAX; - - while (p != 0xFF) - { - spectator = false; - if (p & DEMO_SPECTATOR) - { - spectator = true; - p &= ~DEMO_SPECTATOR; - - if (modeattacking) - { - snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with spectators, and is thus invalid.\n"), pdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demo.playback = false; - demo.title = false; - return; - } - } - slots[numslots] = p; numslots++; - - if (modeattacking && numslots > 1) - { - snprintf(msg, 1024, M_GetText("%s is a Record Attack replay with multiple players, and is thus invalid.\n"), pdemoname); - CONS_Alert(CONS_ERROR, "%s", msg); - M_StartMessage(msg, NULL, MM_NOTHING); - Z_Free(pdemoname); - Z_Free(demobuffer); - demo.playback = false; - demo.title = false; - return; - } - - if (!playeringame[displayplayers[0]] || players[displayplayers[0]].spectator) - displayplayers[0] = consoleplayer = serverplayer = p; - - playeringame[p] = true; - players[p].spectator = spectator; - - // Name - M_Memcpy(player_names[p],demo_p,16); - demo_p += 16; - - // Skin - M_Memcpy(skin,demo_p,16); - demo_p += 16; - SetPlayerSkin(p, skin); - - // Color - M_Memcpy(color,demo_p,16); - demo_p += 16; - for (i = 0; i < MAXSKINCOLORS; i++) - if (!stricmp(KartColor_Names[i],color)) // SRB2kart - { - players[p].skincolor = i; - break; - } - - // Follower - M_Memcpy(follower, demo_p, 16); - demo_p += 16; - SetPlayerFollower(p, follower); - - // Follower colour - M_Memcpy(color, demo_p, 16); - demo_p += 16; - for (i = 0; i < MAXSKINCOLORS +2; i++) // +2 because of Match and Opposite - { - if (!stricmp(Followercolor_cons_t[i].strvalue, color)) - { - players[p].followercolor = i; - break; - } - } - - // Score, since Kart uses this to determine where you start on the map - players[p].score = READUINT32(demo_p); - - // Power Levels - clientpowerlevels[p][G_BattleGametype() ? PWRLV_BATTLE : PWRLV_RACE] = READUINT16(demo_p); - - // Kart stats, temporarily - kartspeed[p] = READUINT8(demo_p); - kartweight[p] = READUINT8(demo_p); - - if (stricmp(skins[players[p].skin].name, skin) != 0) - FindClosestSkinForStats(p, kartspeed[p], kartweight[p]); - - // Look for the next player - p = READUINT8(demo_p); - } - -// end of player read (the 0xFF marker) -// so this is where we are to read our lua variables (if possible!) -#ifdef HAVE_BLUA - if (demoflags & DF_LUAVARS) // again, used for compability, lua shit will be saved to replays regardless of if it's even been loaded - { - if (!gL) // No Lua state! ...I guess we'll just start one... - LUA_ClearState(); - - // No modeattacking check, DF_LUAVARS won't be present here. - LUA_UnArchiveDemo(); - } -#endif - - splitscreen = 0; - - if (demo.title) - { - splitscreen = M_RandomKey(6)-1; - splitscreen = min(min(3, numslots-1), splitscreen); // Bias toward 1p and 4p views - - for (p = 0; p <= splitscreen; p++) - G_ResetView(p+1, slots[M_RandomKey(numslots)], false); - } - - R_ExecuteSetViewSize(); - - P_SetRandSeed(randseed); - G_InitNew(demoflags & DF_ENCORE, G_BuildMapName(gamemap), true, true); // Doesn't matter whether you reset or not here, given changes to resetplayer. - - for (i = 0; i < MAXPLAYERS; i++) - { - if (players[i].mo) - { - players[i].mo->color = players[i].skincolor; - oldghost[i].x = players[i].mo->x; - oldghost[i].y = players[i].mo->y; - oldghost[i].z = players[i].mo->z; - } - - // Set saved attribute values - // No cheat checking here, because even if they ARE wrong... - // it would only break the replay if we clipped them. - players[i].kartspeed = kartspeed[i]; - players[i].kartweight = kartweight[i]; - } - - demo.deferstart = true; -} -#undef SKIPERRORS - -void G_AddGhost(char *defdemoname) -{ - INT32 i; - lumpnum_t l; - char name[17],skin[17],color[17],*n,*pdemoname,md5[16]; - demoghost *gh; - UINT8 flags; - UINT8 *buffer,*p; - mapthing_t *mthing; - UINT16 count, ghostversion; - skin_t *ghskin = &skins[0]; - UINT8 kartspeed = UINT8_MAX, kartweight = UINT8_MAX; - - name[16] = '\0'; - skin[16] = '\0'; - color[16] = '\0'; - - n = defdemoname+strlen(defdemoname); - while (*n != '/' && *n != '\\' && n != defdemoname) - n--; - if (n != defdemoname) - n++; - pdemoname = ZZ_Alloc(strlen(n)+1); - strcpy(pdemoname,n); - - // Internal if no extension, external if one exists - if (FIL_CheckExtension(defdemoname)) - { - //FIL_DefaultExtension(defdemoname, ".lmp"); - if (!FIL_ReadFileTag(defdemoname, &buffer, PU_LEVEL)) - { - CONS_Alert(CONS_ERROR, M_GetText("Failed to read file '%s'.\n"), defdemoname); - Z_Free(pdemoname); - return; - } - p = buffer; - } - // load demo resource from WAD - else if ((l = W_CheckNumForName(defdemoname)) == LUMPERROR) - { - CONS_Alert(CONS_ERROR, M_GetText("Failed to read lump '%s'.\n"), defdemoname); - Z_Free(pdemoname); - return; - } - else // it's an internal demo - buffer = p = W_CacheLumpNum(l, PU_LEVEL); - - // read demo header - if (memcmp(p, DEMOHEADER, 12)) - { - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Not a SRB2Kart replay.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; - } - - p += 12; // DEMOHEADER - p++; // VERSION - p++; // SUBVERSION - - ghostversion = READUINT16(p); - switch(ghostversion) - { - case DEMOVERSION: // latest always supported - p += 64; // title - break; - // too old, cannot support. - default: - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo version incompatible.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; - } - - M_Memcpy(md5, p, 16); p += 16; // demo checksum - for (gh = ghosts; gh; gh = gh->next) - if (!memcmp(md5, gh->checksum, 16)) // another ghost in the game already has this checksum? - { // Don't add another one, then! - CONS_Debug(DBG_SETUP, "Rejecting duplicate ghost %s (MD5 was matched)\n", pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; - } - - if (memcmp(p, "PLAY", 4)) - { - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Demo format unacceptable.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; - } - - p += 4; // "PLAY" - p += 2; // gamemap - p += 16; // mapmd5 (possibly check for consistency?) - - flags = READUINT8(p); - - if (!(flags & DF_GHOST)) - { - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: No ghost data in this demo.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; - } - - p++; // gametype - G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts. - - switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) - { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - p += 8; // demo time, lap - break; - case ATTACKING_CAPSULES: // 2 - p += 4; // demo time - break; - default: // 3 - break; - } - - p += 4; // random seed - p += 4; // Extra data location reference - - // net var data - count = READUINT16(p); - while (count--) - { - p += 2; - SKIPSTRING(p); - p++; - } - - if (*p == DEMOMARKER) - { - CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Replay is empty.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; - } - - if (READUINT8(p) != 0) - { - CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; - } - - // Player name (TODO: Display this somehow if it doesn't match cv_playername!) - M_Memcpy(name, p, 16); - p += 16; - - // Skin - M_Memcpy(skin, p, 16); - p += 16; - - // Color - M_Memcpy(color, p, 16); - p += 16; - - // Follower data was here, skip it, we don't care about it for ghosts. - p += 32; // followerskin (16) + followercolor (16) - - p += 4; // score - p += 2; // powerlevel - - kartspeed = READUINT8(p); - kartweight = READUINT8(p); - - if (READUINT8(p) != 0xFF) - { - CONS_Alert(CONS_NOTICE, M_GetText("Failed to add ghost %s: Invalid player slot.\n"), pdemoname); - Z_Free(pdemoname); - Z_Free(buffer); - return; - } - - for (i = 0; i < numskins; i++) - if (!stricmp(skins[i].name,skin)) - { - ghskin = &skins[i]; - break; - } - - if (i == numskins) - { - if (kartspeed != UINT8_MAX && kartweight != UINT8_MAX) - ghskin = &skins[GetSkinNumClosestToStats(kartspeed, kartweight)]; - - CONS_Alert(CONS_NOTICE, M_GetText("Ghost %s: Invalid character. Falling back to %s.\n"), pdemoname, ghskin->name); - } - - gh = Z_Calloc(sizeof(demoghost), PU_LEVEL, NULL); - gh->next = ghosts; - gh->buffer = buffer; - M_Memcpy(gh->checksum, md5, 16); - gh->p = p; - - ghosts = gh; - - gh->version = ghostversion; - mthing = playerstarts[0]; - I_Assert(mthing); - { // A bit more complex than P_SpawnPlayer because ghosts aren't solid and won't just push themselves out of the ceiling. - fixed_t z,f,c; - gh->mo = P_SpawnMobj(mthing->x << FRACBITS, mthing->y << FRACBITS, 0, MT_GHOST); - gh->mo->angle = FixedAngle(mthing->angle*FRACUNIT); - f = gh->mo->floorz; - c = gh->mo->ceilingz - mobjinfo[MT_PLAYER].height; - if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) - { - z = c; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); - if (z < f) - z = f; - } - else - { - z = f; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - if (z > c) - z = c; - } - gh->mo->z = z; - } - gh->mo->state = states+S_KART_STILL1; // SRB2kart - was S_PLAY_STND - gh->mo->sprite = gh->mo->state->sprite; - gh->mo->frame = (gh->mo->state->frame & FF_FRAMEMASK) | tr_trans20<mo->tics = -1; - - gh->oldmo.x = gh->mo->x; - gh->oldmo.y = gh->mo->y; - gh->oldmo.z = gh->mo->z; - - // Set skin - gh->mo->skin = gh->oldmo.skin = ghskin; - - // Set color - gh->mo->color = ((skin_t*)gh->mo->skin)->prefcolor; - for (i = 0; i < MAXSKINCOLORS; i++) - if (!stricmp(KartColor_Names[i],color)) // SRB2kart - { - gh->mo->color = (UINT8)i; - break; - } - gh->oldmo.color = gh->mo->color; - - CONS_Printf(M_GetText("Added ghost %s from %s\n"), name, pdemoname); - Z_Free(pdemoname); -} - -// A simplified version of G_AddGhost... -void G_UpdateStaffGhostName(lumpnum_t l) -{ - UINT8 *buffer,*p; - UINT16 ghostversion; - UINT8 flags; - - buffer = p = W_CacheLumpNum(l, PU_CACHE); - - // read demo header - if (memcmp(p, DEMOHEADER, 12)) - { - goto fail; - } - - p += 12; // DEMOHEADER - p++; // VERSION - p++; // SUBVERSION - - ghostversion = READUINT16(p); - switch(ghostversion) - { - case DEMOVERSION: // latest always supported - p += 64; // full demo title - break; - - // too old, cannot support. - default: - goto fail; - } - - p += 16; // demo checksum - - if (memcmp(p, "PLAY", 4)) - { - goto fail; - } - - p += 4; // "PLAY" - p += 2; // gamemap - p += 16; // mapmd5 (possibly check for consistency?) - - flags = READUINT8(p); - if (!(flags & DF_GHOST)) - { - goto fail; // we don't NEED to do it here, but whatever - } - - p++; // Gametype - - G_SkipDemoExtraFiles(&p); - - switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT) - { - case ATTACKING_NONE: // 0 - break; - case ATTACKING_RECORD: // 1 - p += 8; // demo time, lap - break; - case ATTACKING_CAPSULES: // 2 - p += 4; // demo time - break; - default: // 3 - break; - } - - p += 4; // random seed - p += 4; // Extrainfo location marker - - // Ehhhh don't need ghostversion here (?) so I'll reuse the var here - ghostversion = READUINT16(p); - while (ghostversion--) - { - p += 2; - SKIPSTRING(p); - p++; // stealth - } - - // Assert first player is in and then read name - if (READUINT8(p) != 0) - goto fail; - M_Memcpy(dummystaffname, p,16); - dummystaffname[16] = '\0'; - - // Ok, no longer any reason to care, bye -fail: - Z_Free(buffer); - return; -} - -// -// G_TimeDemo -// NOTE: name is a full filename for external demos -// -static INT32 restorecv_vidwait; - -void G_TimeDemo(const char *name) -{ - nodrawers = M_CheckParm("-nodraw"); - noblit = M_CheckParm("-noblit"); - restorecv_vidwait = cv_vidwait.value; - if (cv_vidwait.value) - CV_Set(&cv_vidwait, "0"); - demo.timing = true; - singletics = true; - framecount = 0; - demostarttime = I_GetTime(); - G_DeferedPlayDemo(name); -} - -void G_DoPlayMetal(void) -{ - lumpnum_t l; - mobj_t *mo = NULL; - thinker_t *th; - - // it's an internal demo - if ((l = W_CheckNumForName(va("%sMS",G_BuildMapName(gamemap)))) == LUMPERROR) - { - CONS_Alert(CONS_WARNING, M_GetText("No bot recording for this map.\n")); - return; - } - else - metalbuffer = metal_p = W_CacheLumpNum(l, PU_STATIC); - - // find metal sonic - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo = (mobj_t *)th; - if (mo->type == MT_METALSONIC_RACE) - break; - } - if (!mo) - { - CONS_Alert(CONS_ERROR, M_GetText("Failed to find bot entity.\n")); - Z_Free(metalbuffer); - return; - } - - // read demo header - metal_p += 12; // DEMOHEADER - metal_p++; // VERSION - metal_p++; // SUBVERSION - metalversion = READUINT16(metal_p); - switch(metalversion) - { - case DEMOVERSION: // latest always supported - break; - // too old, cannot support. - default: - CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, format version incompatible.\n")); - Z_Free(metalbuffer); - return; - } - metal_p += 16; // demo checksum - if (memcmp(metal_p, "METL", 4)) - { - CONS_Alert(CONS_WARNING, M_GetText("Failed to load bot recording for this map, wasn't recorded in Metal format.\n")); - Z_Free(metalbuffer); - return; - } metal_p += 4; // "METL" - - // read initial tic - memset(&oldmetal,0,sizeof(oldmetal)); - oldmetal.x = mo->x; - oldmetal.y = mo->y; - oldmetal.z = mo->z; - oldmetal.angle = mo->angle; - metalplayback = mo; -} - -void G_DoneLevelLoad(void) -{ - CONS_Printf(M_GetText("Loaded level in %f sec\n"), (double)(I_GetTime() - demostarttime) / TICRATE); - framecount = 0; - demostarttime = I_GetTime(); -} - -/* -=================== -= -= G_CheckDemoStatus -= -= Called after a death or level completion to allow demos to be cleaned up -= Returns true if a new demo loop action will take place -=================== -*/ - -// Stops metal sonic's demo. Separate from other functions because metal + replays can coexist -void G_StopMetalDemo(void) -{ - - // Metal Sonic finishing doesn't end the game, dammit. - Z_Free(metalbuffer); - metalbuffer = NULL; - metalplayback = NULL; - metal_p = NULL; -} - -// Stops metal sonic recording. -ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void) -{ - boolean saved = false; - if (demo_p) - { - UINT8 *p = demobuffer+16; // checksum position -#ifdef NOMD5 - UINT8 i; - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - for (i = 0; i < 16; i++, p++) - *p = P_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. -#else - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - md5_buffer((char *)p+16, demo_p - (p+16), (void *)p); // make a checksum of everything after the checksum in the file. -#endif - saved = FIL_WriteFile(va("%sMS.LMP", G_BuildMapName(gamemap)), demobuffer, demo_p - demobuffer); // finally output the file. - } - free(demobuffer); - metalrecording = false; - if (saved) - I_Error("Saved to %sMS.LMP", G_BuildMapName(gamemap)); - I_Error("Failed to save demo!"); -} - -// reset engine variable set for the demos -// called from stopdemo command, map command, and g_checkdemoStatus. -void G_StopDemo(void) -{ - Z_Free(demobuffer); - demobuffer = NULL; - demo.playback = false; - if (demo.title) - modeattacking = false; - demo.title = false; - demo.timing = false; - singletics = false; - - demo.freecam = false; - // reset democam shit too: - democam.cam = NULL; - democam.soundmobj = NULL; - democam.localangle = 0; - democam.localaiming = 0; - democam.turnheld = false; - democam.keyboardlook = false; - - CV_SetValue(&cv_playbackspeed, 1); - demo.rewinding = false; - CL_ClearRewinds(); - - if (gamestate == GS_LEVEL && rendermode != render_none) - { - V_SetPaletteLump("PLAYPAL"); // Reset the palette - R_ReInitColormaps(0, LUMPERROR); - } - if (gamestate == GS_INTERMISSION) - Y_EndIntermission(); // cleanup - if (gamestate == GS_VOTING) - Y_EndVote(); - - G_SetGamestate(GS_NULL); - wipegamestate = GS_NULL; - SV_StopServer(); - SV_ResetServer(); -} - -boolean G_CheckDemoStatus(void) -{ - while (ghosts) - { - demoghost *next = ghosts->next; - Z_Free(ghosts); - ghosts = next; - } - ghosts = NULL; - - // DO NOT end metal sonic demos here - - if (demo.timing) - { - INT32 demotime; - double f1, f2; - demotime = I_GetTime() - demostarttime; - if (!demotime) - return true; - G_StopDemo(); - demo.timing = false; - f1 = (double)demotime; - f2 = (double)framecount*TICRATE; - CONS_Printf(M_GetText("timed %u gametics in %d realtics\n%f seconds, %f avg fps\n"), leveltime,demotime,f1/TICRATE,f2/f1); - if (restorecv_vidwait != cv_vidwait.value) - CV_SetValue(&cv_vidwait, restorecv_vidwait); - D_AdvanceDemo(); - return true; - } - - if (demo.playback) - { - if (demo.quitafterplaying) - I_Quit(); - - if (multiplayer && !demo.title) - G_ExitLevel(); - else - { - G_StopDemo(); - - if (modeattacking) - M_EndModeAttackRun(); - else - D_AdvanceDemo(); - } - - return true; - } - - if (demo.recording && (modeattacking || demo.savemode != DSM_NOTSAVING)) - { - G_SaveDemo(); - return true; - } - demo.recording = false; - - return false; -} - -void G_SaveDemo(void) -{ - UINT8 *p = demobuffer+16; // after version - UINT32 length; -#ifdef NOMD5 - UINT8 i; -#endif - - // Ensure extrainfo pointer is always available, even if no info is present. - if (demoinfo_p && *(UINT32 *)demoinfo_p == 0) - { - WRITEUINT8(demo_p, DEMOMARKER); // add the demo end marker - *(UINT32 *)demoinfo_p = demo_p - demobuffer; - } - WRITEUINT8(demo_p, DW_END); // Mark end of demo extra data. - - M_Memcpy(p, demo.titlename, 64); // Write demo title here - p += 64; - - if (multiplayer) - { - // Change the demo's name to be a slug of the title - char demo_slug[128]; - char *writepoint; - size_t i, strindex = 0; - boolean dash = true; - - for (i = 0; demo.titlename[i] && i < 127; i++) - { - if ((demo.titlename[i] >= 'a' && demo.titlename[i] <= 'z') || - (demo.titlename[i] >= '0' && demo.titlename[i] <= '9')) - { - demo_slug[strindex] = demo.titlename[i]; - strindex++; - dash = false; - } - else if (demo.titlename[i] >= 'A' && demo.titlename[i] <= 'Z') - { - demo_slug[strindex] = demo.titlename[i] + 'a' - 'A'; - strindex++; - dash = false; - } - else if (!dash) - { - demo_slug[strindex] = '-'; - strindex++; - dash = true; - } - } - - demo_slug[strindex] = 0; - if (dash) demo_slug[strindex-1] = 0; - - writepoint = strstr(demoname, "-") + 1; - demo_slug[128 - (writepoint - demoname) - 4] = 0; - sprintf(writepoint, "%s.lmp", demo_slug); - } - - length = *(UINT32 *)demoinfo_p; - WRITEUINT32(demoinfo_p, length); -#ifdef NOMD5 - for (i = 0; i < 16; i++, p++) - *p = M_RandomByte(); // This MD5 was chosen by fair dice roll and most likely < 50% correct. -#else - // Make a checksum of everything after the checksum in the file up to the end of the standard data. Extrainfo is freely modifiable. - md5_buffer((char *)p+16, (demobuffer + length) - (p+16), p); -#endif - - - if (FIL_WriteFile(va(pandf, srb2home, demoname), demobuffer, demo_p - demobuffer)) // finally output the file. - demo.savemode = DSM_SAVED; - free(demobuffer); - demo.recording = false; - - if (!modeattacking) - { - if (demo.savemode == DSM_SAVED) - CONS_Printf(M_GetText("Demo %s recorded\n"), demoname); - else - CONS_Alert(CONS_WARNING, M_GetText("Demo %s not saved\n"), demoname); - } -} - -boolean G_DemoTitleResponder(event_t *ev) -{ - size_t len; - INT32 ch; - - if (ev->type != ev_keydown) - return false; - - ch = (INT32)ev->data1; - - // Only ESC and non-keyboard keys abort connection - if (ch == KEY_ESCAPE) - { - demo.savemode = (cv_recordmultiplayerdemos.value == 2) ? DSM_WILLAUTOSAVE : DSM_NOTSAVING; - return true; - } - - if (ch == KEY_ENTER || ch >= KEY_MOUSE1) - { - demo.savemode = DSM_WILLSAVE; - return true; - } - - if ((ch >= HU_FONTSTART && ch <= HU_FONTEND && fontv[HU_FONT].font[ch-HU_FONTSTART]) - || ch == ' ') // Allow spaces, of course - { - len = strlen(demo.titlename); - if (len < 64) - { - demo.titlename[len+1] = 0; - demo.titlename[len] = CON_ShiftChar(ch); - } - } - else if (ch == KEY_BACKSPACE) - { - if (shiftdown) - memset(demo.titlename, 0, sizeof(demo.titlename)); - else - { - len = strlen(demo.titlename); + /* we can't check mapheaderinfo for this hahahaha */ + if (W_CheckNumForName(G_BuildMapName(newmapnum)) == LUMPERROR) + return 0; - if (len > 0) - demo.titlename[len-1] = 0; - } + if (realmapnamep) + (*realmapnamep) = G_BuildMapTitle(newmapnum); } - return true; + return newmapnum; } // @@ -8201,6 +4754,9 @@ boolean G_DemoTitleResponder(event_t *ev) void G_SetGamestate(gamestate_t newstate) { gamestate = newstate; +#ifdef HAVE_DISCORDRPC + DRPC_UpdatePresence(); +#endif } /* These functions handle the exitgame flag. Before, when the user @@ -8242,6 +4798,22 @@ boolean G_GetRetryFlag(void) return retrying; } +void G_SetModeAttackRetryFlag(void) +{ + retryingmodeattack = true; + G_SetRetryFlag(); +} + +void G_ClearModeAttackRetryFlag(void) +{ + retryingmodeattack = false; +} + +boolean G_GetModeAttackRetryFlag(void) +{ + return retryingmodeattack; +} + // Time utility functions INT32 G_TicsToHours(tic_t tics) { diff --git a/src/g_game.h b/src/g_game.h index e0f25aa92..78812a72c 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -17,6 +17,8 @@ #include "doomdef.h" #include "doomstat.h" #include "d_event.h" +#include "g_demo.h" +#include "m_cheat.h" // objectplacing extern char gamedatafilename[64]; extern char timeattackfolder[64]; @@ -26,101 +28,45 @@ extern char customversionstring[32]; #ifdef SEENAMES extern player_t *seenplayer; #endif -extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; +extern char player_names[MAXPLAYERS][MAXPLAYERNAME+1]; +extern INT32 player_name_changes[MAXPLAYERS]; extern player_t players[MAXPLAYERS]; extern boolean playeringame[MAXPLAYERS]; -extern UINT8 *demo_p; - -// ====================================== -// DEMO playback/recording related stuff. -// ====================================== - -// demoplaying back and demo recording -extern consvar_t cv_recordmultiplayerdemos, cv_netdemosyncquality; - -// Publicly-accessible demo vars -struct demovars_s { - char titlename[65]; - boolean recording, playback, timing; - UINT16 version; // Current file format of the demo being played - boolean title; // Title Screen demo can be cancelled by any key - boolean rewinding; // Rewind in progress - - boolean loadfiles, ignorefiles; // Demo file loading options - boolean fromtitle; // SRB2Kart: Don't stop the music - boolean inreplayhut; // Go back to replayhut after demos - boolean quitafterplaying; // quit after playing a demo from cmdline - boolean deferstart; // don't start playing demo right away - - tic_t savebutton; // Used to determine when the local player can choose to save the replay while the race is still going - enum { - DSM_NOTSAVING, - DSM_WILLAUTOSAVE, - DSM_TITLEENTRY, - DSM_WILLSAVE, - DSM_SAVED - } savemode; - - boolean freecam; - -}; - -extern struct demovars_s demo; - -typedef enum { - MD_NOTLOADED, - MD_LOADED, - MD_SUBDIR, - MD_OUTDATED, - MD_INVALID -} menudemotype_e; - -typedef struct menudemo_s { - char filepath[256]; - menudemotype_e type; - - char title[65]; // Null-terminated for string prints - UINT16 map; - UINT8 addonstatus; // What do we need to do addon-wise to play this demo? - UINT8 gametype; - SINT8 kartspeed; // Add OR DF_ENCORE for encore mode, idk - UINT8 numlaps; - - struct { - UINT8 ranking; - char name[17]; - UINT8 skin, color; - UINT32 timeorscore; - } standings[MAXPLAYERS]; -} menudemo_t; - - -extern mobj_t *metalplayback; - // gametic at level start extern tic_t levelstarttic; // for modding? extern INT16 prevmap, nextmap; extern INT32 gameovertics; +extern UINT8 ammoremovaltics; extern tic_t timeinmap; // Ticker for time spent in level (used for levelcard display) -extern INT16 rw_maximums[NUM_WEAPONS]; +extern INT32 pausedelay; +extern boolean pausebreakkey; -// used in game menu -extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection/*, cv_compactscoreboard*/; +extern boolean promptactive; + + +extern consvar_t cv_tutorialprompt; + +extern consvar_t cv_chatwidth, cv_chatnotifications, cv_chatheight, cv_chattime, cv_consolechat, cv_chatbacktint, cv_chatspamprotection; extern consvar_t cv_songcredits; + extern consvar_t cv_pauseifunfocused; -//extern consvar_t cv_crosshair, cv_crosshair2, cv_crosshair3, cv_crosshair4; -extern consvar_t cv_invertmouse/*, cv_alwaysfreelook, cv_chasefreelook, cv_mousemove*/; -extern consvar_t cv_invertmouse2/*, cv_alwaysfreelook2, cv_chasefreelook2, cv_mousemove2*/; -extern consvar_t cv_useranalog, cv_useranalog2, cv_useranalog3, cv_useranalog4; -extern consvar_t cv_analog, cv_analog2, cv_analog3, cv_analog4; -extern consvar_t cv_turnaxis,cv_moveaxis,cv_brakeaxis,cv_aimaxis,cv_lookaxis,cv_fireaxis,cv_driftaxis,cv_deadzone; -extern consvar_t cv_turnaxis2,cv_moveaxis2,cv_brakeaxis2,cv_aimaxis2,cv_lookaxis2,cv_fireaxis2,cv_driftaxis2,cv_deadzone2; -extern consvar_t cv_turnaxis3,cv_moveaxis3,cv_brakeaxis3,cv_aimaxis3,cv_lookaxis3,cv_fireaxis3,cv_driftaxis3,cv_deadzone3; -extern consvar_t cv_turnaxis4,cv_moveaxis4,cv_brakeaxis4,cv_aimaxis4,cv_lookaxis4,cv_fireaxis4,cv_driftaxis4,cv_deadzone4; + +extern consvar_t cv_invertmouse; + +extern consvar_t cv_turnaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_moveaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_brakeaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_aimaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_lookaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_fireaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_driftaxis[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_deadzone[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_digitaldeadzone[MAXSPLITSCREENPLAYERS]; + extern consvar_t cv_ghost_besttime, cv_ghost_bestlap, cv_ghost_last, cv_ghost_guest, cv_ghost_staff; extern consvar_t cv_invincmusicfade; @@ -130,20 +76,6 @@ extern consvar_t cv_resetspecialmusic; extern consvar_t cv_resume; -typedef enum -{ - AXISNONE = 0, - AXISTURN, - AXISMOVE, - AXISBRAKE, - AXISAIM, - AXISLOOK, - AXISDEAD, //Axises that don't want deadzones - AXISFIRE, - AXISDRIFT, - AXISLOOKBACK, -} axis_input_e; - // mouseaiming (looking up/down with the mouse or keyboard) #define KB_LOOKSPEED (1<<25) #define MAXPLMOVE (50) @@ -151,6 +83,7 @@ typedef enum // build an internal map name MAPxx from map number const char *G_BuildMapName(INT32 map); + void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer); // copy ticcmd_t to and fro the normal way @@ -159,11 +92,27 @@ ticcmd_t *G_CopyTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n); ticcmd_t *G_MoveTiccmd(ticcmd_t* dest, const ticcmd_t* src, const size_t n); // clip the console player aiming to the view -INT16 G_ClipAimingPitch(INT32 *aiming); +INT32 G_ClipAimingPitch(INT32 *aiming); INT16 G_SoftwareClipAimingPitch(INT32 *aiming); -boolean InputDown(INT32 gc, UINT8 p); -INT32 JoyAxis(axis_input_e axissel, UINT8 p); +typedef enum +{ + AXISNONE = 0, + + AXISTURN, + AXISMOVE, + AXISBRAKE, + AXISAIM, + AXISLOOK, + + AXISDIGITAL, // axes below this use digital deadzone + + AXISFIRE = AXISDIGITAL, + AXISDRIFT, + AXISLOOKBACK, +} axis_input_e; + +INT32 PlayerJoyAxis(UINT8 player, axis_input_e axissel); extern angle_t localangle[MAXSPLITSCREENPLAYERS]; extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed @@ -173,16 +122,42 @@ extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but sig // void G_ChangePlayerReferences(mobj_t *oldmo, mobj_t *newmo); void G_DoReborn(INT32 playernum); -void G_PlayerReborn(INT32 player); +void G_PlayerReborn(INT32 player, boolean betweenmaps); void G_InitNew(UINT8 pencoremode, const char *mapname, boolean resetplayer, - boolean skipprecutscene); + boolean skipprecutscene, boolean FLS); char *G_BuildMapTitle(INT32 mapnum); +struct searchdim +{ + UINT8 pos; + UINT8 siz; +}; + +typedef struct +{ + INT16 mapnum; + UINT8 matchc; + struct searchdim *matchd;/* offset that a pattern was matched */ + UINT8 keywhc; + struct searchdim *keywhd;/* ...in KEYWORD */ + UINT8 total;/* total hits */ +} +mapsearchfreq_t; + +INT32 G_FindMap(const char *query, char **foundmapnamep, + mapsearchfreq_t **freqp, INT32 *freqc); +void G_FreeMapSearch(mapsearchfreq_t *freq, INT32 freqc); + +/* Match map name by search + 2 digit map code or map number. */ +INT32 G_FindMapByNameOrCode(const char *query, char **foundmapnamep); + // XMOD spawning -mapthing_t *G_FindCTFStart(INT32 playernum); -mapthing_t *G_FindMatchStart(INT32 playernum); +mapthing_t *G_FindTeamStart(INT32 playernum); +mapthing_t *G_FindBattleStart(INT32 playernum); mapthing_t *G_FindRaceStart(INT32 playernum); -void G_SpawnPlayer(INT32 playernum, boolean starpost); +mapthing_t *G_FindMapStart(INT32 playernum); +void G_MovePlayerToSpawnOrStarpost(INT32 playernum); +void G_SpawnPlayer(INT32 playernum); // Can be called by the startup code or M_Responder. // A normal game starts at map 1, but a warp test can start elsewhere @@ -190,117 +165,37 @@ void G_DeferedInitNew(boolean pencoremode, const char *mapname, INT32 pickedchar UINT8 ssplayers, boolean FLS); void G_DoLoadLevel(boolean resetplayer); -void G_LoadDemoInfo(menudemo_t *pdemo); -void G_DeferedPlayDemo(const char *demo); +void G_StartTitleCard(void); +void G_PreLevelTitleCard(void); +boolean G_IsTitleCardAvailable(void); // Can be called by the startup code or M_Responder, calls P_SetupLevel. void G_LoadGame(UINT32 slot, INT16 mapoverride); -void G_SaveGameData(boolean force); +void G_SaveGameData(void); -void G_SaveGame(UINT32 slot); +void G_SaveGame(UINT32 slot, INT16 mapnum); -// Only called by startup code. -void G_RecordDemo(const char *name); -void G_RecordMetal(void); -void G_BeginRecording(void); -void G_BeginMetal(void); +void G_SaveGameOver(UINT32 slot, boolean modifylives); -// Only called by shutdown code. -void G_WriteStanding(UINT8 ranking, char *name, INT32 skinnum, UINT8 color, UINT32 val); -void G_SetDemoTime(UINT32 ptime, UINT32 plap); -UINT8 G_CmpDemoTime(char *oldname, char *newname); - -typedef enum -{ - GHC_NORMAL = 0, - GHC_SUPER, - GHC_FIREFLOWER, - GHC_INVINCIBLE -} ghostcolor_t; - -extern UINT8 demo_extradata[MAXPLAYERS]; -extern UINT8 demo_writerng; -#define DXD_RESPAWN 0x01 // "respawn" command in console -#define DXD_SKIN 0x02 // skin changed -#define DXD_NAME 0x04 // name changed -#define DXD_COLOR 0x08 // color changed -#define DXD_PLAYSTATE 0x10 // state changed between playing, spectating, or not in-game -#define DXD_FOLLOWER 0x20 // follower was changed - -#define DXD_PST_PLAYING 0x01 -#define DXD_PST_SPECTATING 0x02 -#define DXD_PST_LEFT 0x03 - -// Record/playback tics -void G_ReadDemoExtraData(void); -void G_WriteDemoExtraData(void); -void G_ReadDemoTiccmd(ticcmd_t *cmd, INT32 playernum); -void G_WriteDemoTiccmd(ticcmd_t *cmd, INT32 playernum); -void G_GhostAddThok(INT32 playernum); -void G_GhostAddSpin(INT32 playernum); -void G_GhostAddRev(INT32 playernum); -void G_GhostAddColor(INT32 playernum, ghostcolor_t color); -void G_GhostAddFlip(INT32 playernum); -void G_GhostAddScale(INT32 playernum, fixed_t scale); -void G_GhostAddHit(INT32 playernum, mobj_t *victim); -void G_WriteAllGhostTics(void); -void G_WriteGhostTic(mobj_t *ghost, INT32 playernum); -void G_ConsAllGhostTics(void); -void G_ConsGhostTic(INT32 playernum); -void G_GhostTicker(void); - -void G_InitDemoRewind(void); -void G_StoreRewindInfo(void); -void G_PreviewRewind(tic_t previewtime); -void G_ConfirmRewind(tic_t rewindtime); - -void G_ReadMetalTic(mobj_t *metal); -void G_WriteMetalTic(mobj_t *metal); -void G_SaveMetal(UINT8 **buffer); -void G_LoadMetal(UINT8 **buffer); - -// Your naming conventions are stupid and useless. -// There is no conflict here. -typedef struct demoghost { - UINT8 checksum[16]; - UINT8 *buffer, *p, color; - UINT16 version; - mobj_t oldmo, *mo; - struct demoghost *next; -} demoghost; -extern demoghost *ghosts; - -// G_CheckDemoExtraFiles: checks if our loaded WAD list matches the demo's. -#define DFILE_ERROR_NOTLOADED 0x01 // Files are not loaded, but can be without a restart. -#define DFILE_ERROR_OUTOFORDER 0x02 // Files are loaded, but out of order. -#define DFILE_ERROR_INCOMPLETEOUTOFORDER 0x03 // Some files are loaded out of order, but others are not. -#define DFILE_ERROR_CANNOTLOAD 0x04 // Files are missing and cannot be loaded. -#define DFILE_ERROR_EXTRAFILES 0x05 // Extra files outside of the replay's file list are loaded. - -void G_DoPlayDemo(char *defdemoname); -void G_TimeDemo(const char *name); -void G_AddGhost(char *defdemoname); -void G_UpdateStaffGhostName(lumpnum_t l); -void G_DoPlayMetal(void); -void G_DoneLevelLoad(void); -void G_StopMetalDemo(void); -ATTRNORETURN void FUNCNORETURN G_StopMetalRecording(void); -void G_StopDemo(void); -boolean G_CheckDemoStatus(void); -void G_SaveDemo(void); -boolean G_DemoTitleResponder(event_t *ev); +extern UINT32 gametypedefaultrules[NUMGAMETYPES]; +extern UINT32 gametypetol[NUMGAMETYPES]; +extern INT16 gametyperankings[NUMGAMETYPES]; +void G_SetGametype(INT16 gametype); +INT16 G_AddGametype(UINT32 rules); +void G_AddGametypeConstant(INT16 gtype, const char *newgtconst); +void G_UpdateGametypeSelections(void); +void G_AddTOL(UINT32 newtol, const char *tolname); +void G_AddGametypeTOL(INT16 gtype, UINT32 newtol); +//void G_SetGametypeDescription(INT16 gtype, char *descriptiontext, UINT8 leftcolor, UINT8 rightcolor); INT32 G_GetGametypeByName(const char *gametypestr); boolean G_IsSpecialStage(INT32 mapnum); boolean G_GametypeUsesLives(void); boolean G_GametypeHasTeams(void); boolean G_GametypeHasSpectators(void); -boolean G_BattleGametype(void); INT16 G_SometimesGetDifferentGametype(void); UINT8 G_GetGametypeColor(INT16 gt); -boolean G_RaceGametype(void); -boolean G_TagGametype(void); void G_ExitLevel(void); void G_NextLevel(void); void G_Continue(void); @@ -330,10 +225,14 @@ void G_AddPlayer(INT32 playernum); void G_SetExitGameFlag(void); void G_ClearExitGameFlag(void); boolean G_GetExitGameFlag(void); + void G_SetRetryFlag(void); void G_ClearRetryFlag(void); boolean G_GetRetryFlag(void); +void G_SetModeAttackRetryFlag(void); +void G_ClearModeAttackRetryFlag(void); +boolean G_GetModeAttackRetryFlag(void); void G_LoadGameData(void); void G_LoadGameSettings(void); @@ -344,19 +243,9 @@ void G_SetGamestate(gamestate_t newstate); // Gamedata record shit void G_AllocMainRecordData(INT16 i); -//void G_AllocNightsRecordData(INT16 i); void G_ClearRecords(void); -//UINT32 G_GetBestScore(INT16 map); tic_t G_GetBestTime(INT16 map); -//tic_t G_GetBestLap(INT16 map); -//UINT16 G_GetBestRings(INT16 map); -//UINT32 G_GetBestNightsScore(INT16 map, UINT8 mare); -//tic_t G_GetBestNightsTime(INT16 map, UINT8 mare); -//UINT8 G_GetBestNightsGrade(INT16 map, UINT8 mare); - -//void G_AddTempNightsRecords(UINT32 pscore, tic_t ptime, UINT8 mare); -//void G_SetNightsRecords(void); FUNCMATH INT32 G_TicsToHours(tic_t tics); FUNCMATH INT32 G_TicsToMinutes(tic_t tics, boolean full); @@ -365,9 +254,9 @@ FUNCMATH INT32 G_TicsToCentiseconds(tic_t tics); FUNCMATH INT32 G_TicsToMilliseconds(tic_t tics); // Don't split up TOL handling -INT16 G_TOLFlag(INT32 pgametype); +UINT32 G_TOLFlag(INT32 pgametype); -INT16 G_RandMap(INT16 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer); +INT16 G_RandMap(UINT32 tolflags, INT16 pprevmap, boolean ignorebuffer, UINT8 maphell, boolean callagainsoon, INT16 *extbuffer); void G_AddMapToBuffer(INT16 map); #endif diff --git a/src/g_input.c b/src/g_input.c index 08a323c78..0e10ae8a9 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -25,29 +25,49 @@ static CV_PossibleValue_t mousesens_cons_t[] = {{1, "MIN"}, {MAXMOUSESENSITIVITY static CV_PossibleValue_t onecontrolperkey_cons_t[] = {{1, "One"}, {2, "Several"}, {0, NULL}}; // mouse values are used once -consvar_t cv_mousesens = {"mousesens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mousesens2 = {"mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mouseysens = {"mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mouseysens2 = {"mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_controlperkey = {"controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mousesens = CVAR_INIT ("mousesens", "20", CV_SAVE, mousesens_cons_t, NULL); +consvar_t cv_mousesens2 = CVAR_INIT ("mousesens2", "20", CV_SAVE, mousesens_cons_t, NULL); +consvar_t cv_mouseysens = CVAR_INIT ("mouseysens", "20", CV_SAVE, mousesens_cons_t, NULL); +consvar_t cv_mouseysens2 = CVAR_INIT ("mouseysens2", "20", CV_SAVE, mousesens_cons_t, NULL); +consvar_t cv_controlperkey = CVAR_INIT ("controlperkey", "One", CV_SAVE, onecontrolperkey_cons_t, NULL); INT32 mousex, mousey; INT32 mlooky; // like mousey but with a custom sensitivity for mlook -INT32 mouse2x, mouse2y, mlook2y; - // joystick values are repeated -INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET], -joy3xmove[JOYAXISSET], joy3ymove[JOYAXISSET], joy4xmove[JOYAXISSET], joy4ymove[JOYAXISSET]; +INT32 joyxmove[MAXSPLITSCREENPLAYERS][JOYAXISSET], joyymove[MAXSPLITSCREENPLAYERS][JOYAXISSET]; // current state of the keys: true if pushed UINT8 gamekeydown[NUMINPUTS]; // two key codes (or virtual key) per game control -INT32 gamecontrol[num_gamecontrols][2]; -INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player -INT32 gamecontrol3[num_gamecontrols][2]; // tertiary splitscreen player -INT32 gamecontrol4[num_gamecontrols][2]; // quarternary splitscreen player +INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][2]; +INT32 gamecontroldefault[MAXSPLITSCREENPLAYERS][num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention + +// lists of GC codes for selective operation +const INT32 gcl_accelerate[num_gcl_accelerate] = { gc_accelerate }; + +const INT32 gcl_brake[num_gcl_brake] = { gc_brake }; + +const INT32 gcl_drift[num_gcl_drift] = { gc_drift }; + +const INT32 gcl_spindash[num_gcl_spindash] = { + gc_accelerate, gc_drift, gc_brake +}; + +const INT32 gcl_movement[num_gcl_movement] = { + gc_accelerate, gc_drift, gc_brake, gc_turnleft, gc_turnright +}; + +const INT32 gcl_item[num_gcl_item] = { + gc_fire, gc_aimforward, gc_aimbackward +}; + +const INT32 gcl_full[num_gcl_full] = { + gc_accelerate, gc_drift, gc_brake, gc_turnleft, gc_turnright, + gc_fire, gc_aimforward, gc_aimbackward, + gc_lookback +}; typedef struct { @@ -56,11 +76,7 @@ typedef struct UINT8 clicks; } dclick_t; static dclick_t mousedclicks[MOUSEBUTTONS]; -static dclick_t joydclicks[JOYBUTTONS + JOYHATS*4]; -static dclick_t mouse2dclicks[MOUSEBUTTONS]; -static dclick_t joy2dclicks[JOYBUTTONS + JOYHATS*4]; -static dclick_t joy3dclicks[JOYBUTTONS + JOYHATS*4]; -static dclick_t joy4dclicks[JOYBUTTONS + JOYHATS*4]; +static dclick_t joydclicks[MAXSPLITSCREENPLAYERS][JOYBUTTONS + JOYHATS*4]; // protos static UINT8 G_CheckDoubleClick(UINT8 state, dclick_t *dt); @@ -114,40 +130,32 @@ void G_MapEventsToControls(event_t *ev) i = ev->data1; if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on) break; - if (ev->data2 != INT32_MAX) joyxmove[i] = ev->data2; - if (ev->data3 != INT32_MAX) joyymove[i] = ev->data3; + if (ev->data2 != INT32_MAX) joyxmove[0][i] = ev->data2; + if (ev->data3 != INT32_MAX) joyymove[0][i] = ev->data3; break; case ev_joystick2: // buttons are virtual keys i = ev->data1; if (i >= JOYAXISSET || menuactive) break; - if (ev->data2 != INT32_MAX) joy2xmove[i] = ev->data2; - if (ev->data3 != INT32_MAX) joy2ymove[i] = ev->data3; + if (ev->data2 != INT32_MAX) joyxmove[1][i] = ev->data2; + if (ev->data3 != INT32_MAX) joyymove[1][i] = ev->data3; break; case ev_joystick3: i = ev->data1; if (i >= JOYAXISSET) break; - if (ev->data2 != INT32_MAX) joy3xmove[i] = ev->data2; - if (ev->data3 != INT32_MAX) joy3ymove[i] = ev->data3; + if (ev->data2 != INT32_MAX) joyxmove[2][i] = ev->data2; + if (ev->data3 != INT32_MAX) joyymove[2][i] = ev->data3; break; case ev_joystick4: i = ev->data1; if (i >= JOYAXISSET) break; - if (ev->data2 != INT32_MAX) joy4xmove[i] = ev->data2; - if (ev->data3 != INT32_MAX) joy4ymove[i] = ev->data3; - break; - - case ev_mouse2: // buttons are virtual keys - if (menuactive || CON_Ready() || chat_on) - break; - mouse2x = (INT32)(ev->data2*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f)); - mouse2y = (INT32)(ev->data3*((cv_mousesens2.value*cv_mousesens2.value)/110.0f + 0.1f)); - mlook2y = (INT32)(ev->data3*((cv_mouseysens2.value*cv_mousesens2.value)/110.0f + 0.1f)); + if (ev->data2 != INT32_MAX) joyxmove[3][i] = ev->data2; + if (ev->data3 != INT32_MAX) joyymove[3][i] = ev->data3; break; default: @@ -163,31 +171,25 @@ void G_MapEventsToControls(event_t *ev) for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++) { - flag = G_CheckDoubleClick(gamekeydown[KEY_JOY1+i], &joydclicks[i]); + flag = G_CheckDoubleClick(gamekeydown[KEY_JOY1+i], &joydclicks[0][i]); gamekeydown[KEY_DBLJOY1+i] = flag; } - for (i = 0; i < MOUSEBUTTONS; i++) - { - flag = G_CheckDoubleClick(gamekeydown[KEY_2MOUSE1+i], &mouse2dclicks[i]); - gamekeydown[KEY_DBL2MOUSE1+i] = flag; - } - for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++) { - flag = G_CheckDoubleClick(gamekeydown[KEY_2JOY1+i], &joy2dclicks[i]); + flag = G_CheckDoubleClick(gamekeydown[KEY_2JOY1+i], &joydclicks[1][i]); gamekeydown[KEY_DBL2JOY1+i] = flag; } for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++) { - flag = G_CheckDoubleClick(gamekeydown[KEY_3JOY1+i], &joy3dclicks[i]); + flag = G_CheckDoubleClick(gamekeydown[KEY_3JOY1+i], &joydclicks[2][i]); gamekeydown[KEY_DBL3JOY1+i] = flag; } for (i = 0; i < JOYBUTTONS + JOYHATS*4; i++) { - flag = G_CheckDoubleClick(gamekeydown[KEY_4JOY1+i], &joy4dclicks[i]); + flag = G_CheckDoubleClick(gamekeydown[KEY_4JOY1+i], &joydclicks[3][i]); gamekeydown[KEY_DBL4JOY1+i] = flag; } } @@ -241,11 +243,9 @@ static keyname_t keynames[] = {KEY_SCROLLLOCK, "SCROLLLOCK"}, // bill gates keys -#ifndef _arch_dreamcast {KEY_LEFTWIN, "LEFTWIN"}, {KEY_RIGHTWIN, "RIGHTWIN"}, {KEY_MENU, "MENU"}, -#endif {KEY_LSHIFT, "LSHIFT"}, {KEY_RSHIFT, "RSHIFT"}, @@ -307,140 +307,16 @@ static keyname_t keynames[] = {KEY_MOUSE1+0,"MOUSE1"}, {KEY_MOUSE1+1,"MOUSE2"}, {KEY_MOUSE1+2,"MOUSE3"}, -#if !defined (_arch_dreamcast) && !defined (_XBOX) && !defined (_PSP) && !defined (_WII) {KEY_MOUSE1+3,"MOUSE4"}, {KEY_MOUSE1+4,"MOUSE5"}, {KEY_MOUSE1+5,"MOUSE6"}, {KEY_MOUSE1+6,"MOUSE7"}, {KEY_MOUSE1+7,"MOUSE8"}, -#endif - {KEY_2MOUSE1+0,"SEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2 - {KEY_2MOUSE1+1,"SEC_MOUSE1"}, - {KEY_2MOUSE1+2,"SEC_MOUSE3"}, -#if !defined (_arch_dreamcast) && !defined (_XBOX) && !defined (_PSP) && !defined (_WII) - {KEY_2MOUSE1+3,"SEC_MOUSE4"}, - {KEY_2MOUSE1+4,"SEC_MOUSE5"}, - {KEY_2MOUSE1+5,"SEC_MOUSE6"}, - {KEY_2MOUSE1+6,"SEC_MOUSE7"}, - {KEY_2MOUSE1+7,"SEC_MOUSE8"}, -#endif {KEY_MOUSEWHEELUP, "Wheel 1 UP"}, {KEY_MOUSEWHEELDOWN, "Wheel 1 Down"}, {KEY_2MOUSEWHEELUP, "Wheel 2 UP"}, {KEY_2MOUSEWHEELDOWN, "Wheel 2 Down"}, -#ifdef DC - {KEY_JOY1+0, "JOYC"}, - {KEY_JOY1+1, "JOYB"}, - {KEY_JOY1+2, "JOYA"}, - {KEY_JOY1+3, "JOYS"}, - {KEY_JOY1+4, "JOYZ"}, - {KEY_JOY1+5, "JOYY"}, - {KEY_JOY1+6, "JOYX"}, - {KEY_JOY1+7, "JOYD"}, -#elif defined (_XBOX) - {KEY_JOY1+0, "JOYA"}, - {KEY_JOY1+1, "JOYB"}, - {KEY_JOY1+2, "JOYX"}, - {KEY_JOY1+3, "JOYY"}, - {KEY_JOY1+4, "JOYG"}, - {KEY_JOY1+5, "JOYW"}, - {KEY_JOY1+6, "JOYL"}, - {KEY_JOY1+7, "JOYR"}, - {KEY_JOY1+8, "JOYS"}, - {KEY_JOY1+9, "JOYN"}, - {KEY_JOY1+10,"JOYW"}, - {KEY_JOY1+11,"JOYE"}, -#define NOMOREJOYBTN_1S -#elif defined (_PSP) - {KEY_JOY1+0, "TRIANGLE"}, - {KEY_JOY1+1, "CIRCLE" }, - {KEY_JOY1+2, "CROSS" }, - {KEY_JOY1+3, "SQUARE" }, - {KEY_JOY1+4, "LTRIGGER"}, - {KEY_JOY1+5, "RTRIGGER"}, - {KEY_JOY1+6, "SELECT" }, - {KEY_JOY1+7, "START" }, - {KEY_JOY1+8, "HOME" }, - {KEY_JOY1+9, "HOLD" }, -#define NOMOREJOYBTN_1S -#elif defined (GP2X) - {KEY_JOY1+0, "JOYA"}, - {KEY_JOY1+1, "JOYY"}, - {KEY_JOY1+2, "JOYB"}, - {KEY_JOY1+3, "JOYX"}, - {KEY_JOY1+4, "JOYL"}, - {KEY_JOY1+5, "JOYR"}, - {KEY_JOY1+6, "JOYVOLUP"}, - {KEY_JOY1+7, "JOYVOLDOWN"}, - {KEY_JOY1+8, "JOYSELECT"}, -#elif defined (_NDS) - {KEY_JOY1+0, "JOYA"}, - {KEY_JOY1+1, "JOYB"}, - {KEY_JOY1+2, "JOYX"}, - {KEY_JOY1+3, "JOYY"}, - {KEY_JOY1+4, "JOYL"}, - {KEY_JOY1+5, "JOYR"}, - {KEY_JOY1+6, "JOYSTART"}, - {KEY_JOY1+7, "JOYSELECT"}, -#define NOMOREJOYBTN_1S -#elif defined (WMINPUT) - {KEY_JOY1+0, "JOYB"}, - {KEY_JOY1+1, "JOYA"}, - {KEY_JOY1+2, "JOYUP"}, - {KEY_JOY1+3, "JOYDOWN"}, - {KEY_JOY1+4, "JOYLEFT"}, - {KEY_JOY1+5, "JOYRIGHT"}, - {KEY_JOY1+6, "JOYAA"}, - {KEY_JOY1+7, "JOYBB"}, - {KEY_JOY1+8, "JOYCC"}, - {KEY_JOY1+9, "JOYXX"}, - {KEY_JOY1+10, "JOYYY"}, - {KEY_JOY1+11, "JOYZZ"}, - {KEY_JOY1+12, "JOYL"}, - {KEY_JOY1+13, "JOYR"}, - {KEY_JOY1+14, "JOYZL"}, - {KEY_JOY1+15, "JOYZR"}, - {KEY_JOY1+16, "JOYSELECT"}, - {KEY_JOY1+17, "JOYSTART"}, - {KEY_JOY1+18, "JOYHOME"}, - {KEY_JOY1+19, "JOYMINUS"}, - {KEY_JOY1+20, "JOYPLUS"}, - {KEY_JOY1+21, "JOY_1"}, - {KEY_JOY1+22, "JOY_2"}, - {KEY_JOY1+23, "JOY24"}, - {KEY_JOY1+24, "JOY25"}, - {KEY_JOY1+25, "JOY26"}, - {KEY_JOY1+26, "JOY27"}, - {KEY_JOY1+27, "JOY28"}, - {KEY_JOY1+28, "JOY29"}, - {KEY_JOY1+29, "JOY30"}, - {KEY_JOY1+30, "JOY31"}, - {KEY_JOY1+31, "JOY32"}, -#define NOMOREJOYBTN_1S -#elif defined (_WII) - {KEY_JOY1+0, "JOYA"}, - {KEY_JOY1+1, "JOYB"}, - {KEY_JOY1+2, "JOY1"}, - {KEY_JOY1+3, "JOY2"}, - {KEY_JOY1+4, "JOYMINUS"}, - {KEY_JOY1+5, "JOYPLUS"}, - {KEY_JOY1+6, "JOYHOME"}, - {KEY_JOY1+7, "JOYZ"}, - {KEY_JOY1+8, "JOYC"}, - {KEY_JOY1+9, "JOYA_CC"}, - {KEY_JOY1+10, "JOYB_CC"}, - {KEY_JOY1+11, "JOYX"}, - {KEY_JOY1+12, "JOYY"}, - {KEY_JOY1+13, "JOYL"}, - {KEY_JOY1+14, "JOYR"}, - {KEY_JOY1+15, "JOYZL"}, - {KEY_JOY1+16, "JOYZR"}, - {KEY_JOY1+17, "JOYMINUS_CC"}, - {KEY_JOY1+18, "JOYHPLUS_CC"}, - {KEY_JOY1+19, "JOYMHOME_CC"}, -#define NOMOREJOYBTN_1S -#else {KEY_JOY1+0, "JOY1"}, {KEY_JOY1+1, "JOY2"}, {KEY_JOY1+2, "JOY3"}, @@ -450,8 +326,7 @@ static keyname_t keynames[] = {KEY_JOY1+6, "JOY7"}, {KEY_JOY1+7, "JOY8"}, {KEY_JOY1+8, "JOY9"}, -#endif -#if !defined (_arch_dreamcast) && !defined (NOMOREJOYBTN_1S) +#if !defined (NOMOREJOYBTN_1S) // we use up to 32 buttons in DirectInput {KEY_JOY1+9, "JOY10"}, {KEY_JOY1+10, "JOY11"}, @@ -482,12 +357,10 @@ static keyname_t keynames[] = {KEY_HAT1+1, "HATDOWN"}, {KEY_HAT1+2, "HATLEFT"}, {KEY_HAT1+3, "HATRIGHT"}, -#if !defined (_XBOX) && !defined (_PSP) && !defined (_WII) {KEY_HAT1+4, "HATUP2"}, {KEY_HAT1+5, "HATDOWN2"}, {KEY_HAT1+6, "HATLEFT2"}, {KEY_HAT1+7, "HATRIGHT2"}, -#ifndef _arch_dreamcast {KEY_HAT1+8, "HATUP3"}, {KEY_HAT1+9, "HATDOWN3"}, {KEY_HAT1+10, "HATLEFT3"}, @@ -496,142 +369,16 @@ static keyname_t keynames[] = {KEY_HAT1+13, "HATDOWN4"}, {KEY_HAT1+14, "HATLEFT4"}, {KEY_HAT1+15, "HATRIGHT4"}, -#endif -#endif {KEY_DBLMOUSE1+0, "DBLMOUSE1"}, {KEY_DBLMOUSE1+1, "DBLMOUSE2"}, {KEY_DBLMOUSE1+2, "DBLMOUSE3"}, -#if !defined (_arch_dreamcast) && !defined (_XBOX) && !defined (_PSP) && !defined (_WII) {KEY_DBLMOUSE1+3, "DBLMOUSE4"}, {KEY_DBLMOUSE1+4, "DBLMOUSE5"}, {KEY_DBLMOUSE1+5, "DBLMOUSE6"}, {KEY_DBLMOUSE1+6, "DBLMOUSE7"}, {KEY_DBLMOUSE1+7, "DBLMOUSE8"}, -#endif - {KEY_DBL2MOUSE1+0, "DBLSEC_MOUSE2"}, // BP: sorry my mouse handler swap button 1 and 2 - {KEY_DBL2MOUSE1+1, "DBLSEC_MOUSE1"}, - {KEY_DBL2MOUSE1+2, "DBLSEC_MOUSE3"}, -#if !defined (_arch_dreamcast) && !defined (_XBOX) && !defined (_PSP) && !defined (_WII) - {KEY_DBL2MOUSE1+3, "DBLSEC_MOUSE4"}, - {KEY_DBL2MOUSE1+4, "DBLSEC_MOUSE5"}, - {KEY_DBL2MOUSE1+5, "DBLSEC_MOUSE6"}, - {KEY_DBL2MOUSE1+6, "DBLSEC_MOUSE7"}, - {KEY_DBL2MOUSE1+7, "DBLSEC_MOUSE8"}, -#endif -#ifdef DC - {KEY_DBLJOY1+0, "DBLJOYC"}, - {KEY_DBLJOY1+1, "DBLJOYB"}, - {KEY_DBLJOY1+2, "DBLJOYA"}, - {KEY_DBLJOY1+3, "DBLJOYS"}, - {KEY_DBLJOY1+4, "DBLJOYZ"}, - {KEY_DBLJOY1+5, "DBLJOYY"}, - {KEY_DBLJOY1+6, "DBLJOYX"}, - {KEY_DBLJOY1+7, "DBLJOYD"}, -#elif defined (_XBOX) - {KEY_DBLJOY1+0, "DBLJOYA"}, - {KEY_DBLJOY1+1, "DBLJOYB"}, - {KEY_DBLJOY1+2, "DBLJOYX"}, - {KEY_DBLJOY1+3, "DBLJOYY"}, - {KEY_DBLJOY1+4, "DBLJOYG"}, - {KEY_DBLJOY1+5, "DBLJOYW"}, - {KEY_DBLJOY1+6, "DBLJOYL"}, - {KEY_DBLJOY1+7, "DBLJOYR"}, - {KEY_DBLJOY1+8, "DBLJOYS"}, - {KEY_DBLJOY1+9, "DBLJOYN"}, - {KEY_DBLJOY1+10,"DBLJOYW"}, - {KEY_DBLJOY1+11,"DBLJOYE"}, -#define NOMOREJOYBTN_1DBL -#elif defined (_PSP) - {KEY_DBLJOY1+0, "DBLTRIANGLE"}, - {KEY_DBLJOY1+1, "DBLCIRCLE" }, - {KEY_DBLJOY1+2, "DBLCROSS" }, - {KEY_DBLJOY1+3, "DBLSQUARE" }, - {KEY_DBLJOY1+4, "DBLLTRIGGER"}, - {KEY_DBLJOY1+5, "DBLRTRIGGER"}, - {KEY_DBLJOY1+6, "DBLSELECT" }, - {KEY_DBLJOY1+7, "DBLSTART" }, - {KEY_DBLJOY1+8, "DBLHOME" }, - {KEY_DBLJOY1+9, "DBLHOLD" }, -#elif defined (GP2X) - {KEY_DBLJOY1+0, "DBLJOYA"}, - {KEY_DBLJOY1+1, "DBLJOYY"}, - {KEY_DBLJOY1+2, "DBLJOYB"}, - {KEY_DBLJOY1+3, "DBLJOYX"}, - {KEY_DBLJOY1+4, "DBLJOYL"}, - {KEY_DBLJOY1+5, "DBLJOYR"}, - {KEY_DBLJOY1+6, "DBLJOYVOLUP"}, - {KEY_DBLJOY1+7, "DBLJOYVOLDOWN"}, - {KEY_DBLJOY1+8, "DBLJOYSELECT"}, -#define NOMOREJOYBTN_1DBL -#elif defined (_NDS) - {KEY_DBLJOY1+0, "DBLJOYA"}, - {KEY_DBLJOY1+1, "DBLJOYB"}, - {KEY_DBLJOY1+2, "DBLJOYX"}, - {KEY_DBLJOY1+3, "DBLJOYY"}, - {KEY_DBLJOY1+4, "DBLJOYL"}, - {KEY_DBLJOY1+5, "DBLJOYR"}, - {KEY_DBLJOY1+6, "DBLJOYSTART"}, - {KEY_DBLJOY1+7, "DBLJOYSELECT"}, -#define NOMOREJOYBTN_1DBL -#elif defined (WMINPUT) - {KEY_DBLJOY1+0, "DBLJOYB"}, - {KEY_DBLJOY1+1, "DBLJOYA"}, - {KEY_DBLJOY1+2, "DBLJOYUP"}, - {KEY_DBLJOY1+3, "DBLJOYDOWN"}, - {KEY_DBLJOY1+4, "DBLJOYLEFT"}, - {KEY_DBLJOY1+5, "DBLJOYRIGHT"}, - {KEY_DBLJOY1+6, "DBLJOYAA"}, - {KEY_DBLJOY1+7, "DBLJOYBB"}, - {KEY_DBLJOY1+8, "DBLJOYCC"}, - {KEY_DBLJOY1+9, "DBLJOYXX"}, - {KEY_DBLJOY1+10, "DBLJOYYY"}, - {KEY_DBLJOY1+11, "DBLJOYZZ"}, - {KEY_DBLJOY1+12, "DBLJOYL"}, - {KEY_DBLJOY1+13, "DBLJOYR"}, - {KEY_DBLJOY1+14, "DBLJOYZL"}, - {KEY_DBLJOY1+15, "DBLJOYZR"}, - {KEY_DBLJOY1+16, "DBLJOYSELECT"}, - {KEY_DBLJOY1+17, "DBLJOYSTART"}, - {KEY_DBLJOY1+18, "DBLJOYHOME"}, - {KEY_DBLJOY1+19, "DBLJOYMINUS"}, - {KEY_DBLJOY1+20, "DBLJOYPLUS"}, - {KEY_DBLJOY1+21, "DBLJOY_1"}, - {KEY_DBLJOY1+22, "DBLJOY_2"}, - {KEY_DBLJOY1+23, "DBLJOY24"}, - {KEY_DBLJOY1+24, "DBLJOY25"}, - {KEY_DBLJOY1+25, "DBLJOY26"}, - {KEY_DBLJOY1+26, "DBLJOY27"}, - {KEY_DBLJOY1+27, "DBLJOY28"}, - {KEY_DBLJOY1+28, "DBLJOY29"}, - {KEY_DBLJOY1+29, "DBLJOY30"}, - {KEY_DBLJOY1+30, "DBLJOY31"}, - {KEY_DBLJOY1+31, "DBLJOY32"}, -#define NOMOREJOYBTN_1DBL -#elif defined (_WII) - {KEY_DBLJOY1+0, "DBLJOYA"}, - {KEY_DBLJOY1+1, "DBLJOYB"}, - {KEY_DBLJOY1+2, "DBLJOY1"}, - {KEY_DBLJOY1+3, "DBLJOY2"}, - {KEY_DBLJOY1+4, "DBLJOYMINUS"}, - {KEY_DBLJOY1+5, "DBLJOYPLUS"}, - {KEY_DBLJOY1+6, "DBLJOYHOME"}, - {KEY_DBLJOY1+7, "DBLJOYZ"}, - {KEY_DBLJOY1+8, "DBLJOYC"}, - {KEY_DBLJOY1+9, "DBLJOYA_CC"}, - {KEY_DBLJOY1+10, "DBLJOYB_CC"}, - {KEY_DBLJOY1+11, "DBLJOYX"}, - {KEY_DBLJOY1+12, "DBLJOYY"}, - {KEY_DBLJOY1+13, "DBLJOYL"}, - {KEY_DBLJOY1+14, "DBLJOYR"}, - {KEY_DBLJOY1+15, "DBLJOYZL"}, - {KEY_DBLJOY1+16, "DBLJOYZR"}, - {KEY_DBLJOY1+17, "DBLJOYMINUS_CC"}, - {KEY_DBLJOY1+18, "DBLJOYHPLUS_CC"}, - {KEY_DBLJOY1+19, "DBLJOYMHOME_CC"}, -#define NOMOREJOYBTN_1DBL -#else {KEY_DBLJOY1+0, "DBLJOY1"}, {KEY_DBLJOY1+1, "DBLJOY2"}, {KEY_DBLJOY1+2, "DBLJOY3"}, @@ -640,8 +387,7 @@ static keyname_t keynames[] = {KEY_DBLJOY1+5, "DBLJOY6"}, {KEY_DBLJOY1+6, "DBLJOY7"}, {KEY_DBLJOY1+7, "DBLJOY8"}, -#endif -#if !defined (_arch_dreamcast) && !defined (NOMOREJOYBTN_1DBL) +#if !defined (NOMOREJOYBTN_1DBL) {KEY_DBLJOY1+8, "DBLJOY9"}, {KEY_DBLJOY1+9, "DBLJOY10"}, {KEY_DBLJOY1+10, "DBLJOY11"}, @@ -671,12 +417,10 @@ static keyname_t keynames[] = {KEY_DBLHAT1+1, "DBLHATDOWN"}, {KEY_DBLHAT1+2, "DBLHATLEFT"}, {KEY_DBLHAT1+3, "DBLHATRIGHT"}, -#if !defined (_XBOX) && !defined (_PSP) && !defined (_WII) {KEY_DBLHAT1+4, "DBLHATUP2"}, {KEY_DBLHAT1+5, "DBLHATDOWN2"}, {KEY_DBLHAT1+6, "DBLHATLEFT2"}, {KEY_DBLHAT1+7, "DBLHATRIGHT2"}, -#ifndef _arch_dreamcast {KEY_DBLHAT1+8, "DBLHATUP3"}, {KEY_DBLHAT1+9, "DBLHATDOWN3"}, {KEY_DBLHAT1+10, "DBLHATLEFT3"}, @@ -685,101 +429,7 @@ static keyname_t keynames[] = {KEY_DBLHAT1+13, "DBLHATDOWN4"}, {KEY_DBLHAT1+14, "DBLHATLEFT4"}, {KEY_DBLHAT1+15, "DBLHATRIGHT4"}, -#endif -#endif -#ifdef DC - {KEY_2JOY1+0, "SEC_JOYC"}, - {KEY_2JOY1+1, "SEC_JOYB"}, - {KEY_2JOY1+2, "SEC_JOYA"}, - {KEY_2JOY1+3, "SEC_JOYS"}, - {KEY_2JOY1+4, "SEC_JOYZ"}, - {KEY_2JOY1+5, "SEC_JOYY"}, - {KEY_2JOY1+6, "SEC_JOYX"}, - {KEY_2JOY1+7, "SEC_JOYD"}, -#elif defined (_XBOX) - {KEY_2JOY1+0, "SEC_JOYA"}, - {KEY_2JOY1+1, "SEC_JOYB"}, - {KEY_2JOY1+2, "SEC_JOYX"}, - {KEY_2JOY1+3, "SEC_JOYY"}, - {KEY_2JOY1+4, "SEC_JOYG"}, - {KEY_2JOY1+5, "SEC_JOYW"}, - {KEY_2JOY1+6, "SEC_JOYL"}, - {KEY_2JOY1+7, "SEC_JOYR"}, - {KEY_2JOY1+8, "SEC_JOYS"}, - {KEY_2JOY1+9, "SEC_JOYN"}, - {KEY_2JOY1+10,"SEC_JOYW"}, - {KEY_2JOY1+11,"SEC_JOYE"}, -#define NOMOREJOYBTN_2S -#elif defined (_PSP) - {KEY_2JOY1+0, "SEC_TRIANGLE"}, - {KEY_2JOY1+1, "SEC_CIRCLE" }, - {KEY_2JOY1+2, "SEC_CROSS" }, - {KEY_2JOY1+3, "SEC_SQUARE" }, - {KEY_2JOY1+4, "SEC_LTRIGGER"}, - {KEY_2JOY1+5, "SEC_RTRIGGER"}, - {KEY_2JOY1+6, "SEC_SELECT" }, - {KEY_2JOY1+7, "SEC_START" }, - {KEY_2JOY1+8, "SEC_HOME" }, - {KEY_2JOY1+9, "SEC_HOLD" }, -#define NOMOREJOYBTN_2S -#elif defined (WMINPUT) - {KEY_2JOY1+0, "SEC_JOYB"}, - {KEY_2JOY1+1, "SEC_JOYA"}, - {KEY_2JOY1+2, "SEC_JOYUP"}, - {KEY_2JOY1+3, "SEC_JOYDOWN"}, - {KEY_2JOY1+4, "SEC_JOYLEFT"}, - {KEY_2JOY1+5, "SEC_JOYRIGHT"}, - {KEY_2JOY1+6, "SEC_JOYAA"}, - {KEY_2JOY1+7, "SEC_JOYBB"}, - {KEY_2JOY1+8, "SEC_JOYCC"}, - {KEY_2JOY1+9, "SEC_JOYXX"}, - {KEY_2JOY1+10, "SEC_JOYYY"}, - {KEY_2JOY1+11, "SEC_JOYZZ"}, - {KEY_2JOY1+12, "SEC_JOYL"}, - {KEY_2JOY1+13, "SEC_JOYR"}, - {KEY_2JOY1+14, "SEC_JOYZL"}, - {KEY_2JOY1+15, "SEC_JOYZR"}, - {KEY_2JOY1+16, "SEC_JOYSELECT"}, - {KEY_2JOY1+17, "SEC_JOYSTART"}, - {KEY_2JOY1+18, "SEC_JOYHOME"}, - {KEY_2JOY1+19, "SEC_JOYMINUS"}, - {KEY_2JOY1+20, "SEC_JOYPLUS"}, - {KEY_2JOY1+21, "SEC_JOY_1"}, - {KEY_2JOY1+22, "SEC_JOY_2"}, - {KEY_2JOY1+23, "SEC_JOY24"}, - {KEY_2JOY1+24, "SEC_JOY25"}, - {KEY_2JOY1+25, "SEC_JOY26"}, - {KEY_2JOY1+26, "SEC_JOY27"}, - {KEY_2JOY1+27, "SEC_JOY28"}, - {KEY_2JOY1+28, "SEC_JOY29"}, - {KEY_2JOY1+29, "SEC_JOY30"}, - {KEY_2JOY1+30, "SEC_JOY31"}, - {KEY_2JOY1+31, "SEC_JOY32"}, -#define NOMOREJOYBTN_2S -#elif defined (_WII) - {KEY_2JOY1+0, "SEC_JOYA"}, - {KEY_2JOY1+1, "SEC_JOYB"}, - {KEY_2JOY1+2, "SEC_JOY1"}, - {KEY_2JOY1+3, "SEC_JOY2"}, - {KEY_2JOY1+4, "SEC_JOYMINUS"}, - {KEY_2JOY1+5, "SEC_JOYPLUS"}, - {KEY_2JOY1+6, "SEC_JOYHOME"}, - {KEY_2JOY1+7, "SEC_JOYZ"}, - {KEY_2JOY1+8, "SEC_JOYC"}, - {KEY_2JOY1+9, "SEC_JOYA_CC"}, - {KEY_2JOY1+10, "SEC_JOYB_CC"}, - {KEY_2JOY1+11, "SEC_JOYX"}, - {KEY_2JOY1+12, "SEC_JOYY"}, - {KEY_2JOY1+13, "SEC_JOYL"}, - {KEY_2JOY1+14, "SEC_JOYR"}, - {KEY_2JOY1+15, "SEC_JOYZL"}, - {KEY_2JOY1+16, "SEC_JOYZR"}, - {KEY_2JOY1+17, "SEC_JOYMINUS_CC"}, - {KEY_2JOY1+18, "SEC_JOYHPLUS_CC"}, - {KEY_2JOY1+19, "SEC_JOYMHOME_CC"}, -#define NOMOREJOYBTN_2S -#else {KEY_2JOY1+0, "SEC_JOY1"}, {KEY_2JOY1+1, "SEC_JOY2"}, {KEY_2JOY1+2, "SEC_JOY3"}, @@ -788,8 +438,7 @@ static keyname_t keynames[] = {KEY_2JOY1+5, "SEC_JOY6"}, {KEY_2JOY1+6, "SEC_JOY7"}, {KEY_2JOY1+7, "SEC_JOY8"}, -#endif -#if !defined (_arch_dreamcast) && !defined (NOMOREJOYBTN_2S) +#if !defined (NOMOREJOYBTN_2S) // we use up to 32 buttons in DirectInput {KEY_2JOY1+8, "SEC_JOY9"}, {KEY_2JOY1+9, "SEC_JOY10"}, @@ -821,12 +470,10 @@ static keyname_t keynames[] = {KEY_2HAT1+1, "SEC_HATDOWN"}, {KEY_2HAT1+2, "SEC_HATLEFT"}, {KEY_2HAT1+3, "SEC_HATRIGHT"}, -#if !defined (_XBOX) && !defined (_PSP) && !defined (_WII) {KEY_2HAT1+4, "SEC_HATUP2"}, {KEY_2HAT1+5, "SEC_HATDOWN2"}, {KEY_2HAT1+6, "SEC_HATLEFT2"}, {KEY_2HAT1+7, "SEC_HATRIGHT2"}, -#ifndef _arch_dreamcast {KEY_2HAT1+8, "SEC_HATUP3"}, {KEY_2HAT1+9, "SEC_HATDOWN3"}, {KEY_2HAT1+10, "SEC_HATLEFT3"}, @@ -835,101 +482,7 @@ static keyname_t keynames[] = {KEY_2HAT1+13, "SEC_HATDOWN4"}, {KEY_2HAT1+14, "SEC_HATLEFT4"}, {KEY_2HAT1+15, "SEC_HATRIGHT4"}, -#endif -#endif -#ifdef DC - {KEY_DBL2JOY1+0, "DBLSEC_JOYC"}, - {KEY_DBL2JOY1+1, "DBLSEC_JOYB"}, - {KEY_DBL2JOY1+2, "DBLSEC_JOYA"}, - {KEY_DBL2JOY1+3, "DBLSEC_JOYS"}, - {KEY_DBL2JOY1+4, "DBLSEC_JOYZ"}, - {KEY_DBL2JOY1+5, "DBLSEC_JOYY"}, - {KEY_DBL2JOY1+6, "DBLSEC_JOYX"}, - {KEY_DBL2JOY1+7, "DBLSEC_JOYD"}, -#elif defined (_XBOX) - {KEY_DBL2JOY1+0, "DBLSEC_JOYA"}, - {KEY_DBL2JOY1+1, "DBLSEC_JOYB"}, - {KEY_DBL2JOY1+2, "DBLSEC_JOYX"}, - {KEY_DBL2JOY1+3, "DBLSEC_JOYY"}, - {KEY_DBL2JOY1+4, "DBLSEC_JOYG"}, - {KEY_DBL2JOY1+5, "DBLSEC_JOYW"}, - {KEY_DBL2JOY1+6, "DBLSEC_JOYL"}, - {KEY_DBL2JOY1+7, "DBLSEC_JOYR"}, - {KEY_DBL2JOY1+8, "DBLSEC_JOYS"}, - {KEY_DBL2JOY1+9, "DBLSEC_JOYN"}, - {KEY_DBL2JOY1+10,"DBLSEC_JOYW"}, - {KEY_DBL2JOY1+11,"DBLSEC_JOYE"}, -#define NOMOREJOYBTN_2DBL -#elif defined (_PSP) - {KEY_DBL2JOY1+0, "DBLSEC_TRIANGLE"}, - {KEY_DBL2JOY1+1, "DBLSEC_CIRCLE" }, - {KEY_DBL2JOY1+2, "DBLSEC_CROSS" }, - {KEY_DBL2JOY1+3, "DBLSEC_SQUARE" }, - {KEY_DBL2JOY1+4, "DBLSEC_LTRIGGER"}, - {KEY_DBL2JOY1+5, "DBLSEC_RTRIGGER"}, - {KEY_DBL2JOY1+6, "DBLSEC_SELECT" }, - {KEY_DBL2JOY1+7, "DBLSEC_START" }, - {KEY_DBL2JOY1+8, "DBLSEC_HOME" }, - {KEY_DBL2JOY1+9, "DBLSEC_HOLD" }, -#define NOMOREJOYBTN_2DBL -#elif defined (WMINPUT) - {KEY_DBL2JOY1+0, "DBLSEC_JOYB"}, - {KEY_DBL2JOY1+1, "DBLSEC_JOYA"}, - {KEY_DBL2JOY1+2, "DBLSEC_JOYUP"}, - {KEY_DBL2JOY1+3, "DBLSEC_JOYDOWN"}, - {KEY_DBL2JOY1+4, "DBLSEC_JOYLEFT"}, - {KEY_DBL2JOY1+5, "DBLSEC_JOYRIGHT"}, - {KEY_DBL2JOY1+6, "DBLSEC_JOYAA"}, - {KEY_DBL2JOY1+7, "DBLSEC_JOYBB"}, - {KEY_DBL2JOY1+8, "DBLSEC_JOYCC"}, - {KEY_DBL2JOY1+9, "DBLSEC_JOYXX"}, - {KEY_DBL2JOY1+10, "DBLSEC_JOYYY"}, - {KEY_DBL2JOY1+11, "DBLSEC_JOYZZ"}, - {KEY_DBL2JOY1+12, "DBLSEC_JOYL"}, - {KEY_DBL2JOY1+13, "DBLSEC_JOYR"}, - {KEY_DBL2JOY1+14, "DBLSEC_JOYZL"}, - {KEY_DBL2JOY1+15, "DBLSEC_JOYZR"}, - {KEY_DBL2JOY1+16, "DBLSEC_JOYSELECT"}, - {KEY_DBL2JOY1+17, "DBLSEC_JOYSTART"}, - {KEY_DBL2JOY1+18, "DBLSEC_JOYHOME"}, - {KEY_DBL2JOY1+19, "DBLSEC_JOYMINUS"}, - {KEY_DBL2JOY1+20, "DBLSEC_JOYPLUS"}, - {KEY_DBL2JOY1+21, "DBLSEC_JOY_1"}, - {KEY_DBL2JOY1+22, "DBLSEC_JOY_2"}, - {KEY_DBL2JOY1+23, "DBLSEC_JOY24"}, - {KEY_DBL2JOY1+24, "DBLSEC_JOY25"}, - {KEY_DBL2JOY1+25, "DBLSEC_JOY26"}, - {KEY_DBL2JOY1+26, "DBLSEC_JOY27"}, - {KEY_DBL2JOY1+27, "DBLSEC_JOY28"}, - {KEY_DBL2JOY1+28, "DBLSEC_JOY29"}, - {KEY_DBL2JOY1+29, "DBLSEC_JOY30"}, - {KEY_DBL2JOY1+30, "DBLSEC_JOY31"}, - {KEY_DBL2JOY1+31, "DBLSEC_JOY32"}, -#define NOMOREJOYBTN_2SDBL -#elif defined (_WII) - {KEY_DBL2JOY1+0, "DBLSEC_JOYA"}, - {KEY_DBL2JOY1+1, "DBLSEC_JOYB"}, - {KEY_DBL2JOY1+2, "DBLSEC_JOY1"}, - {KEY_DBL2JOY1+3, "DBLSEC_JOY2"}, - {KEY_DBL2JOY1+4, "DBLSEC_JOYMINUS"}, - {KEY_DBL2JOY1+5, "DBLSEC_JOYPLUS"}, - {KEY_DBL2JOY1+6, "DBLSEC_JOYHOME"}, - {KEY_DBL2JOY1+7, "DBLSEC_JOYZ"}, - {KEY_DBL2JOY1+8, "DBLSEC_JOYC"}, - {KEY_DBL2JOY1+9, "DBLSEC_JOYA_CC"}, - {KEY_DBL2JOY1+10, "DBLSEC_JOYB_CC"}, - {KEY_DBL2JOY1+11, "DBLSEC_JOYX"}, - {KEY_DBL2JOY1+12, "DBLSEC_JOYY"}, - {KEY_DBL2JOY1+13, "DBLSEC_JOYL"}, - {KEY_DBL2JOY1+14, "DBLSEC_JOYR"}, - {KEY_DBL2JOY1+15, "DBLSEC_JOYZL"}, - {KEY_DBL2JOY1+16, "DBLSEC_JOYZR"}, - {KEY_DBL2JOY1+17, "DBLSEC_JOYMINUS_CC"}, - {KEY_DBL2JOY1+18, "DBLSEC_JOYHPLUS_CC"}, - {KEY_DBL2JOY1+19, "DBLSEC_JOYMHOME_CC"}, -#define NOMOREJOYBTN_2DBL -#else {KEY_DBL2JOY1+0, "DBLSEC_JOY1"}, {KEY_DBL2JOY1+1, "DBLSEC_JOY2"}, {KEY_DBL2JOY1+2, "DBLSEC_JOY3"}, @@ -938,8 +491,7 @@ static keyname_t keynames[] = {KEY_DBL2JOY1+5, "DBLSEC_JOY6"}, {KEY_DBL2JOY1+6, "DBLSEC_JOY7"}, {KEY_DBL2JOY1+7, "DBLSEC_JOY8"}, -#endif -#if !defined (_arch_dreamcast) && !defined (NOMOREJOYBTN_2DBL) +#if !defined (NOMOREJOYBTN_2DBL) {KEY_DBL2JOY1+8, "DBLSEC_JOY9"}, {KEY_DBL2JOY1+9, "DBLSEC_JOY10"}, {KEY_DBL2JOY1+10, "DBLSEC_JOY11"}, @@ -969,12 +521,10 @@ static keyname_t keynames[] = {KEY_DBL2HAT1+1, "DBLSEC_HATDOWN"}, {KEY_DBL2HAT1+2, "DBLSEC_HATLEFT"}, {KEY_DBL2HAT1+3, "DBLSEC_HATRIGHT"}, -#if !defined (_XBOX) && !defined (_PSP) && !defined (_WII) {KEY_DBL2HAT1+4, "DBLSEC_HATUP2"}, {KEY_DBL2HAT1+5, "DBLSEC_HATDOWN2"}, {KEY_DBL2HAT1+6, "DBLSEC_HATLEFT2"}, {KEY_DBL2HAT1+7, "DBLSEC_HATRIGHT2"}, -#ifndef _arch_dreamcast {KEY_DBL2HAT1+8, "DBLSEC_HATUP3"}, {KEY_DBL2HAT1+9, "DBLSEC_HATDOWN3"}, {KEY_DBL2HAT1+10, "DBLSEC_HATLEFT3"}, @@ -983,8 +533,6 @@ static keyname_t keynames[] = {KEY_DBL2HAT1+13, "DBLSEC_HATDOWN4"}, {KEY_DBL2HAT1+14, "DBLSEC_HATLEFT4"}, {KEY_DBL2HAT1+15, "DBLSEC_HATRIGHT4"}, -#endif -#endif {KEY_3JOY1+0, "TRD_JOY1"}, @@ -1234,13 +782,11 @@ void G_ClearControlKeys(INT32 (*setupcontrols)[2], INT32 control) void G_ClearAllControlKeys(void) { - INT32 i; + INT32 i, j; for (i = 0; i < num_gamecontrols; i++) { - G_ClearControlKeys(gamecontrol, i); - G_ClearControlKeys(gamecontrolbis, i); - G_ClearControlKeys(gamecontrol3, i); - G_ClearControlKeys(gamecontrol4, i); + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + G_ClearControlKeys(gamecontrol[j], i); } } @@ -1280,7 +826,13 @@ INT32 G_KeyStringtoNum(const char *keystr) return keystr[0]; if (!strncmp(keystr, "KEY", 3) && keystr[3] >= '0' && keystr[3] <= '9') - return atoi(&keystr[3]); + { + /* what if we out of range bruh? */ + j = atoi(&keystr[3]); + if (j < NUMINPUTS) + return j; + return 0; + } for (j = 0; j < NUMKEYNAMES; j++) if (!stricmp(keynames[j].name, keystr)) @@ -1289,95 +841,121 @@ INT32 G_KeyStringtoNum(const char *keystr) return 0; } -// SRB2Kart -void G_Controldefault(UINT8 player) +void G_DefineDefaultControls(void) { - if (player == 0 || player == 1) + INT32 i; + + // Keyboard controls + gamecontroldefault[0][gcs_kart][gc_aimforward ][0] = KEY_UPARROW; + gamecontroldefault[0][gcs_kart][gc_aimbackward][0] = KEY_DOWNARROW; + gamecontroldefault[0][gcs_kart][gc_turnleft ][0] = KEY_LEFTARROW; + gamecontroldefault[0][gcs_kart][gc_turnright ][0] = KEY_RIGHTARROW; + gamecontroldefault[0][gcs_kart][gc_accelerate ][0] = 'a'; + gamecontroldefault[0][gcs_kart][gc_drift ][0] = 's'; + gamecontroldefault[0][gcs_kart][gc_brake ][0] = 'd'; + gamecontroldefault[0][gcs_kart][gc_fire ][0] = KEY_SPACE; + gamecontroldefault[0][gcs_kart][gc_lookback ][0] = KEY_LSHIFT; + + gamecontroldefault[0][gcs_kart][gc_pause ][0] = KEY_PAUSE; + gamecontroldefault[0][gcs_kart][gc_console ][0] = KEY_CONSOLE; + gamecontroldefault[0][gcs_kart][gc_screenshot ][0] = KEY_F8; + gamecontroldefault[0][gcs_kart][gc_recordgif ][0] = KEY_F9; + gamecontroldefault[0][gcs_kart][gc_viewpoint ][0] = KEY_F12; + gamecontroldefault[0][gcs_kart][gc_talkkey ][0] = 't'; + //gamecontroldefault[0][gcs_kart][gc_teamkey ][0] = 'y'; + gamecontroldefault[0][gcs_kart][gc_scores ][0] = KEY_TAB; + gamecontroldefault[0][gcs_kart][gc_spectate ][0] = '\''; + gamecontroldefault[0][gcs_kart][gc_lookup ][0] = KEY_PGUP; + gamecontroldefault[0][gcs_kart][gc_lookdown ][0] = KEY_PGDN; + gamecontroldefault[0][gcs_kart][gc_centerview ][0] = KEY_END; + gamecontroldefault[0][gcs_kart][gc_camreset ][0] = KEY_HOME; + gamecontroldefault[0][gcs_kart][gc_camtoggle ][0] = KEY_BACKSPACE; + + for (i = gcs_custom+1; i < num_gamecontrolschemes; i++) // skip gcs_custom { - // Main controls - gamecontrol[gc_aimforward ][0] = KEY_UPARROW; - gamecontrol[gc_aimbackward][0] = KEY_DOWNARROW; - gamecontrol[gc_turnleft ][0] = KEY_LEFTARROW; - gamecontrol[gc_turnright ][0] = KEY_RIGHTARROW; - gamecontrol[gc_accelerate ][0] = 'a'; - gamecontrol[gc_drift ][0] = 's'; - gamecontrol[gc_brake ][0] = 'd'; - gamecontrol[gc_fire ][0] = KEY_SPACE; - gamecontrol[gc_lookback ][0] = KEY_LSHIFT; + // Gamepad controls -- same for all schemes + gamecontroldefault[0][i][gc_accelerate ][1] = KEY_JOY1+0; // A + gamecontroldefault[0][i][gc_lookback ][1] = KEY_JOY1+2; // X + gamecontroldefault[0][i][gc_brake ][1] = KEY_JOY1+1; // B + gamecontroldefault[0][i][gc_fire ][1] = KEY_JOY1+4; // LB + gamecontroldefault[0][i][gc_drift ][1] = KEY_JOY1+5; // RB - gamecontrol[gc_accelerate ][1] = KEY_JOY1+0; // A - gamecontrol[gc_lookback ][1] = KEY_JOY1+2; // X - gamecontrol[gc_brake ][1] = KEY_JOY1+1; // B - gamecontrol[gc_fire ][1] = KEY_JOY1+4; // LB - gamecontrol[gc_drift ][1] = KEY_JOY1+5; // RB + gamecontroldefault[0][i][gc_viewpoint ][1] = KEY_JOY1+3; // Y + gamecontroldefault[0][i][gc_pause ][1] = KEY_JOY1+6; // Back + gamecontroldefault[0][i][gc_systemmenu ][0] = KEY_JOY1+7; // Start + gamecontroldefault[0][i][gc_talkkey ][1] = KEY_HAT1+1; // D-Pad Down + gamecontroldefault[0][i][gc_scores ][1] = KEY_HAT1+0; // D-Pad Up - // Extra controls - gamecontrol[gc_pause ][0] = KEY_PAUSE; - gamecontrol[gc_console ][0] = KEY_CONSOLE; - gamecontrol[gc_screenshot ][0] = KEY_F8; - gamecontrol[gc_recordgif ][0] = KEY_F9; - gamecontrol[gc_viewpoint ][0] = KEY_F12; - gamecontrol[gc_talkkey ][0] = 't'; - //gamecontrol[gc_teamkey ][0] = 'y'; - gamecontrol[gc_scores ][0] = KEY_TAB; - gamecontrol[gc_spectate ][0] = '\''; - gamecontrol[gc_lookup ][0] = KEY_PGUP; - gamecontrol[gc_lookdown ][0] = KEY_PGDN; - gamecontrol[gc_centerview ][0] = KEY_END; - gamecontrol[gc_camreset ][0] = KEY_HOME; - gamecontrol[gc_camtoggle ][0] = KEY_BACKSPACE; + gamecontroldefault[1][i][gc_accelerate ][0] = KEY_2JOY1+0; // A + gamecontroldefault[1][i][gc_lookback ][0] = KEY_2JOY1+2; // X + gamecontroldefault[1][i][gc_brake ][0] = KEY_2JOY1+1; // B + gamecontroldefault[1][i][gc_fire ][0] = KEY_2JOY1+4; // LB + gamecontroldefault[1][i][gc_drift ][0] = KEY_2JOY1+5; // RB - gamecontrol[gc_viewpoint ][1] = KEY_JOY1+3; // Y - gamecontrol[gc_pause ][1] = KEY_JOY1+6; // Back - gamecontrol[gc_systemmenu ][0] = KEY_JOY1+7; // Start - //gamecontrol[gc_camtoggle ][1] = KEY_HAT1+0; // D-Pad Up - //gamecontrol[gc_screenshot ][1] = KEY_HAT1+1; // D-Pad Down // absolutely fucking NOT - gamecontrol[gc_talkkey ][1] = KEY_HAT1+1; // D-Pad Down - gamecontrol[gc_scores ][1] = KEY_HAT1+0; // D-Pad Up - } + gamecontroldefault[2][i][gc_accelerate ][0] = KEY_3JOY1+0; // A + gamecontroldefault[2][i][gc_lookback ][0] = KEY_3JOY1+2; // X + gamecontroldefault[2][i][gc_brake ][0] = KEY_3JOY1+1; // B + gamecontroldefault[2][i][gc_fire ][0] = KEY_3JOY1+4; // LB + gamecontroldefault[2][i][gc_drift ][0] = KEY_3JOY1+5; // RB - if (player == 0 || player == 2) - { - // Player 2 controls - gamecontrolbis[gc_accelerate ][0] = KEY_2JOY1+0; // A - gamecontrolbis[gc_lookback ][0] = KEY_2JOY1+2; // X - gamecontrolbis[gc_brake ][0] = KEY_2JOY1+1; // B - gamecontrolbis[gc_fire ][0] = KEY_2JOY1+4; // LB - gamecontrolbis[gc_drift ][0] = KEY_2JOY1+5; // RB - } - - if (player == 0 || player == 3) - { - // Player 3 controls - gamecontrol3[gc_accelerate ][0] = KEY_3JOY1+0; // A - gamecontrol3[gc_lookback ][0] = KEY_3JOY1+2; // X - gamecontrol3[gc_brake ][0] = KEY_3JOY1+1; // B - gamecontrol3[gc_fire ][0] = KEY_3JOY1+4; // LB - gamecontrol3[gc_drift ][0] = KEY_3JOY1+5; // RB - } - - if (player == 0 || player == 4) - { - // Player 4 controls - gamecontrol4[gc_accelerate ][0] = KEY_4JOY1+0; // A - gamecontrol4[gc_lookback ][0] = KEY_4JOY1+2; // X - gamecontrol4[gc_brake ][0] = KEY_4JOY1+1; // B - gamecontrol4[gc_fire ][0] = KEY_4JOY1+4; // LB - gamecontrol4[gc_drift ][0] = KEY_4JOY1+5; // RB + gamecontroldefault[3][i][gc_accelerate ][0] = KEY_3JOY1+0; // A + gamecontroldefault[3][i][gc_lookback ][0] = KEY_3JOY1+2; // X + gamecontroldefault[3][i][gc_brake ][0] = KEY_3JOY1+1; // B + gamecontroldefault[3][i][gc_fire ][0] = KEY_3JOY1+4; // LB + gamecontroldefault[3][i][gc_drift ][0] = KEY_3JOY1+5; // RB } } -void G_SaveKeySetting(FILE *f) +INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen) +{ + INT32 i, j, gc; + boolean skipscheme; + + for (i = 1; i < num_gamecontrolschemes; i++) // skip gcs_custom (0) + { + skipscheme = false; + for (j = 0; j < (gclist && gclen ? gclen : num_gamecontrols); j++) + { + gc = (gclist && gclen) ? gclist[j] : j; + if (((fromcontrols[gc][0] && gamecontroldefault[0][i][gc][0]) ? fromcontrols[gc][0] != gamecontroldefault[0][i][gc][0] : true) && + ((fromcontrols[gc][0] && gamecontroldefault[0][i][gc][1]) ? fromcontrols[gc][0] != gamecontroldefault[0][i][gc][1] : true) && + ((fromcontrols[gc][1] && gamecontroldefault[0][i][gc][0]) ? fromcontrols[gc][1] != gamecontroldefault[0][i][gc][0] : true) && + ((fromcontrols[gc][1] && gamecontroldefault[0][i][gc][1]) ? fromcontrols[gc][1] != gamecontroldefault[0][i][gc][1] : true)) + { + skipscheme = true; + break; + } + } + if (!skipscheme) + return i; + } + + return gcs_custom; +} + +void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen) +{ + INT32 i, gc; + + for (i = 0; i < (gclist && gclen ? gclen : num_gamecontrols); i++) + { + gc = (gclist && gclen) ? gclist[i] : i; + setupcontrols[gc][0] = fromcontrols[gc][0]; + setupcontrols[gc][1] = fromcontrols[gc][1]; + } +} + +void G_SaveKeySetting(FILE *f, INT32 (*fromcontrolsa)[2], INT32 (*fromcontrolsb)[2], INT32 (*fromcontrolsc)[2], INT32 (*fromcontrolsd)[2]) { INT32 i; for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(gamecontrol[i][0])); + G_KeynumToString(fromcontrolsa[i][0])); - if (gamecontrol[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol[i][1])); + if (fromcontrolsa[i][1]) + fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsa[i][1])); else fprintf(f, "\n"); } @@ -1385,10 +963,10 @@ void G_SaveKeySetting(FILE *f) for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol2 \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(gamecontrolbis[i][0])); + G_KeynumToString(fromcontrolsb[i][0])); - if (gamecontrolbis[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrolbis[i][1])); + if (fromcontrolsb[i][1]) + fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsb[i][1])); else fprintf(f, "\n"); } @@ -1396,10 +974,10 @@ void G_SaveKeySetting(FILE *f) for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol3 \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(gamecontrol3[i][0])); + G_KeynumToString(fromcontrolsc[i][0])); - if (gamecontrol3[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol3[i][1])); + if (fromcontrolsc[i][1]) + fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsc[i][1])); else fprintf(f, "\n"); } @@ -1407,10 +985,10 @@ void G_SaveKeySetting(FILE *f) for (i = 1; i < num_gamecontrols; i++) { fprintf(f, "setcontrol4 \"%s\" \"%s\"", gamecontrolname[i], - G_KeynumToString(gamecontrol4[i][0])); + G_KeynumToString(fromcontrolsd[i][0])); - if (gamecontrol4[i][1]) - fprintf(f, " \"%s\"\n", G_KeynumToString(gamecontrol4[i][1])); + if (fromcontrolsd[i][1]) + fprintf(f, " \"%s\"\n", G_KeynumToString(fromcontrolsd[i][1])); else fprintf(f, "\n"); } @@ -1421,27 +999,19 @@ INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify) INT32 result = gc_null; if (cv_controlperkey.value == 1) { - INT32 i, j; + INT32 i, j, k; for (i = 0; i < num_gamecontrols; i++) { for (j = 0; j < 2; j++) { - if (gamecontrol[i][j] == keynum) { - result = i; - if (modify) gamecontrol[i][j] = KEY_NULL; - } - if (gamecontrolbis[i][j] == keynum) { - result = i; - if (modify) gamecontrolbis[i][j] = KEY_NULL; - } - if (gamecontrol3[i][j] == keynum) { - result = i; - if (modify) gamecontrol3[i][j] = KEY_NULL; - } - if (gamecontrol4[i][j] == keynum) { - result = i; - if (modify) gamecontrol4[i][j] = KEY_NULL; + for (k = 0; k < MAXSPLITSCREENPLAYERS; k++) + { + if (gamecontrol[k][i][j] == keynum) { + result = i; + if (modify) gamecontrol[k][i][j] = KEY_NULL; + } } + if (result && !modify) return result; } @@ -1472,10 +1042,9 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT (void)player; (void)nestedoverride; #else -#if !defined (DC) && !defined (_PSP) && !defined (GP2X) && !defined (_NDS) && !defined(WMINPUT) && !defined(_WII) if (GETMAJOREXECVERSION(cv_execversion.value) < 27 && ( // v2.1.22 numctrl == gc_weaponnext || numctrl == gc_weaponprev || numctrl == gc_tossflag || - numctrl == gc_use || numctrl == gc_camreset || numctrl == gc_jump || + numctrl == gc_spin || numctrl == gc_camreset || numctrl == gc_jump || numctrl == gc_pause || numctrl == gc_systemmenu || numctrl == gc_camtoggle || numctrl == gc_screenshot || numctrl == gc_talkkey || numctrl == gc_scores || numctrl == gc_centerview @@ -1486,13 +1055,10 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT boolean defaultoverride = false; // get the default gamecontrol - if (player == 0 && numctrl == gc_systemmenu) - defaultkey = gamecontrol[numctrl][0]; - else - defaultkey = (player == 1 ? gamecontrolbis[numctrl][0] : gamecontrol[numctrl][1]); + defaultkey = gamecontrol[player][numctrl][0]; // Assign joypad button defaults if there is an open slot. - // At this point, gamecontrol/bis should have the default controls + // At this point, gamecontrol should have the default controls // (unless LOADCONFIG is being run) // // If the player runs SETCONTROL in-game, this block should not be reached @@ -1565,7 +1131,6 @@ static INT32 G_FilterKeyByVersion(INT32 numctrl, INT32 keyidx, INT32 player, INT else return 0; } -#endif #endif // All's good, so pass the keynum as-is @@ -1583,16 +1148,17 @@ static void setcontrol(INT32 (*gc)[2]) INT32 player; boolean nestedoverride = false; - if ((void*)gc == (void*)&gamecontrol4) + if ((void*)gc == (void*)&gamecontrol[3]) player = 3; - else if ((void*)gc == (void*)&gamecontrol3) + else if ((void*)gc == (void*)&gamecontrol[2]) player = 2; - else if ((void*)gc == (void*)&gamecontrolbis) + else if ((void*)gc == (void*)&gamecontrol[1]) player = 1; else player = 0; namectrl = COM_Argv(1); + for (numctrl = 0; numctrl < num_gamecontrols && stricmp(namectrl, gamecontrolname[numctrl]); numctrl++) ; @@ -1650,7 +1216,7 @@ void Command_Setcontrol_f(void) return; } - setcontrol(gamecontrol); + setcontrol(gamecontrol[0]); } void Command_Setcontrol2_f(void) @@ -1665,7 +1231,7 @@ void Command_Setcontrol2_f(void) return; } - setcontrol(gamecontrolbis); + setcontrol(gamecontrol[1]); } void Command_Setcontrol3_f(void) @@ -1680,7 +1246,7 @@ void Command_Setcontrol3_f(void) return; } - setcontrol(gamecontrol3); + setcontrol(gamecontrol[2]); } void Command_Setcontrol4_f(void) @@ -1695,5 +1261,5 @@ void Command_Setcontrol4_f(void) return; } - setcontrol(gamecontrol4); + setcontrol(gamecontrol[3]); } diff --git a/src/g_input.h b/src/g_input.h index 6d0c7e2c8..651f95324 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -22,33 +22,10 @@ // keys (mousebuttons and joybuttons becomes keys) #define NUMKEYS 256 - -#ifdef _arch_dreamcast -#define MOUSEBUTTONS 5 -#define JOYBUTTONS 8 // 8 buttons -#define JOYHATS 2 // 2 hats -#define JOYAXISSET 3 // 3 Sets of 2 axises -#elif defined (_XBOX) -#define MOUSEBUTTONS 5 -#define JOYBUTTONS 12 // 12 buttons -#define JOYHATS 1 // 1 hat -#define JOYAXISSET 2 // 2 Sets of 2 axises -#elif defined (_PSP) -#define MOUSEBUTTONS 3 -#define JOYBUTTONS 14 // 10 buttons -#define JOYHATS 1 // 1 hat -#define JOYAXISSET 1 // 1 Set of 2 axises -#elif defined (_WII) -#define MOUSEBUTTONS 3 -#define JOYBUTTONS 20 // 20 buttons -#define JOYHATS 1 // 1 hat -#define JOYAXISSET 5 // 5 Sets of 2 axises -#else #define MOUSEBUTTONS 8 #define JOYBUTTONS 32 // 32 buttons #define JOYHATS 4 // 4 hats #define JOYAXISSET 4 // 4 Sets of 2 axises -#endif // // mouse and joystick buttons are handled as 'virtual' keys @@ -124,6 +101,13 @@ typedef enum num_gamecontrols } gamecontrols_e; +typedef enum +{ + gcs_custom, + gcs_kart, // Kart doesn't really need this code, like, at all? But I don't feel like removing it. + num_gamecontrolschemes +} gamecontrolschemes_e; + // mouse values are used once extern consvar_t cv_mousesens, cv_mouseysens; extern consvar_t cv_mousesens2, cv_mouseysens2; @@ -131,23 +115,32 @@ extern consvar_t cv_controlperkey; extern INT32 mousex, mousey; extern INT32 mlooky; //mousey with mlookSensitivity -extern INT32 mouse2x, mouse2y, mlook2y; -extern INT32 joyxmove[JOYAXISSET], joyymove[JOYAXISSET], joy2xmove[JOYAXISSET], joy2ymove[JOYAXISSET], - joy3xmove[JOYAXISSET], joy3ymove[JOYAXISSET], joy4xmove[JOYAXISSET], joy4ymove[JOYAXISSET]; +extern INT32 joyxmove[MAXSPLITSCREENPLAYERS][JOYAXISSET], joyymove[MAXSPLITSCREENPLAYERS][JOYAXISSET]; // current state of the keys: true if pushed extern UINT8 gamekeydown[NUMINPUTS]; // two key codes (or virtual key) per game control -extern INT32 gamecontrol[num_gamecontrols][2]; -extern INT32 gamecontrolbis[num_gamecontrols][2]; // secondary splitscreen player -extern INT32 gamecontrol3[num_gamecontrols][2]; -extern INT32 gamecontrol4[num_gamecontrols][2]; -#define PLAYER1INPUTDOWN(gc) (gamekeydown[gamecontrol[gc][0]] || gamekeydown[gamecontrol[gc][1]]) -#define PLAYER2INPUTDOWN(gc) (gamekeydown[gamecontrolbis[gc][0]] || gamekeydown[gamecontrolbis[gc][1]]) -#define PLAYER3INPUTDOWN(gc) (gamekeydown[gamecontrol3[gc][0]] || gamekeydown[gamecontrol3[gc][1]]) -#define PLAYER4INPUTDOWN(gc) (gamekeydown[gamecontrol4[gc][0]] || gamekeydown[gamecontrol4[gc][1]]) +extern INT32 gamecontrol[MAXSPLITSCREENPLAYERS][num_gamecontrols][2]; +extern INT32 gamecontroldefault[MAXSPLITSCREENPLAYERS][num_gamecontrolschemes][num_gamecontrols][2]; // default control storage, use 0 (gcs_custom) for memory retention +#define PlayerInputDown(p, gc) (gamekeydown[gamecontrol[p-1][gc][0]] || gamekeydown[gamecontrol[p-1][gc][1]]) + +#define num_gcl_accelerate 1 +#define num_gcl_brake 1 +#define num_gcl_drift 1 +#define num_gcl_spindash 3 +#define num_gcl_movement 5 +#define num_gcl_item 3 +#define num_gcl_full 9 + +extern const INT32 gcl_accelerate[num_gcl_accelerate]; +extern const INT32 gcl_brake[num_gcl_brake]; +extern const INT32 gcl_drift[num_gcl_drift]; +extern const INT32 gcl_spindash[num_gcl_spindash]; +extern const INT32 gcl_movement[num_gcl_movement]; +extern const INT32 gcl_item[num_gcl_item]; +extern const INT32 gcl_full[num_gcl_full]; // peace to my little coder fingers! // check a gamecontrol being active or not @@ -166,8 +159,10 @@ void Command_Setcontrol_f(void); void Command_Setcontrol2_f(void); void Command_Setcontrol3_f(void); void Command_Setcontrol4_f(void); -void G_Controldefault(UINT8 player); -void G_SaveKeySetting(FILE *f); +void G_DefineDefaultControls(void); +INT32 G_GetControlScheme(INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen); +void G_CopyControls(INT32 (*setupcontrols)[2], INT32 (*fromcontrols)[2], const INT32 *gclist, INT32 gclen); +void G_SaveKeySetting(FILE *f, INT32 (*fromcontrolsa)[2], INT32 (*fromcontrolsb)[2], INT32 (*fromcontrolsc)[2], INT32 (*fromcontrolsd)[2]); INT32 G_CheckDoubleUsage(INT32 keynum, boolean modify); #endif diff --git a/src/g_splitscreen.c b/src/g_splitscreen.c index ffc548147..0354c0d10 100644 --- a/src/g_splitscreen.c +++ b/src/g_splitscreen.c @@ -13,6 +13,7 @@ #include "g_game.h" #include "p_local.h" #include "r_local.h" +#include "doomstat.h" INT32 splitscreen_original_party_size[MAXPLAYERS]; INT32 splitscreen_original_party[MAXPLAYERS][MAXSPLITSCREENPLAYERS]; diff --git a/src/g_state.h b/src/g_state.h index 24904e67c..3aa4a3da7 100644 --- a/src/g_state.h +++ b/src/g_state.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,12 +28,14 @@ typedef enum GS_TITLESCREEN, // title screen GS_TIMEATTACK, // time attack menu + GS_CREDITS, // credit sequence GS_EVALUATION, // Evaluation at the end of a game. - GS_GAMEEND, // game end sequence + GS_GAMEEND, // game end sequence - "did you get all those chaos emeralds?" // Hardcoded fades or other fading methods GS_INTRO, // introduction + GS_ENDING, // currently shared between bad and good endings GS_CUTSCENE, // custom cutscene // Not fadable @@ -52,6 +54,7 @@ typedef enum } gameaction_t; extern gamestate_t gamestate; +extern UINT8 titlemapinaction; extern UINT8 ultimatemode; // was sk_insane extern gameaction_t gameaction; diff --git a/src/hardware/hw3dsdrv.h b/src/hardware/hw3dsdrv.h index 8811d4546..9b8670705 100644 --- a/src/hardware/hw3dsdrv.h +++ b/src/hardware/hw3dsdrv.h @@ -1,20 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// 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. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3dsdrv.h /// \brief 3D sound import/export prototypes for low-level hardware interface #ifndef __HW_3DS_DRV_H__ diff --git a/src/hardware/hw3sound.c b/src/hardware/hw3sound.c index 2594a5df9..cd16c6511 100644 --- a/src/hardware/hw3sound.c +++ b/src/hardware/hw3sound.c @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// 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. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3sound.c /// \brief Hardware 3D sound general code #include "../doomdef.h" @@ -28,7 +21,7 @@ #include "../tables.h" #include "../sounds.h" #include "../r_main.h" -#include "../r_things.h" +#include "../r_skins.h" #include "../m_random.h" #include "../p_local.h" #include "hw3dsdrv.h" @@ -790,18 +783,18 @@ static void HW3S_UpdateListener(mobj_t *listener) if (!listener || !listener->player) return; - if (camera.chase) + if (camera[0].chase) { - data.x = FIXED_TO_FLOAT(camera.x); - data.y = FIXED_TO_FLOAT(camera.y); - data.z = FIXED_TO_FLOAT(camera.z + camera.height - (5 * FRACUNIT)); + data.x = FIXED_TO_FLOAT(camera[0].x); + data.y = FIXED_TO_FLOAT(camera[0].y); + data.z = FIXED_TO_FLOAT(camera[0].z + camera[0].height - (5 * FRACUNIT)); - data.f_angle = ANGLE2DEG(camera.angle); - data.h_angle = ANGLE2DEG(camera.aiming); + data.f_angle = ANGLE2DEG(camera[0].angle); + data.h_angle = ANGLE2DEG(camera[0].aiming); - data.momx = TPS(FIXED_TO_FLOAT(camera.momx)); - data.momy = TPS(FIXED_TO_FLOAT(camera.momy)); - data.momz = TPS(FIXED_TO_FLOAT(camera.momz)); + data.momx = TPS(FIXED_TO_FLOAT(camera[0].momx)); + data.momy = TPS(FIXED_TO_FLOAT(camera[0].momy)); + data.momz = TPS(FIXED_TO_FLOAT(camera[0].momz)); } else { diff --git a/src/hardware/hw3sound.h b/src/hardware/hw3sound.h index a8a475b69..1796dd696 100644 --- a/src/hardware/hw3sound.h +++ b/src/hardware/hw3sound.h @@ -1,20 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 2001 by DooM Legacy Team. // -// 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. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw3sound.h /// \brief High-level functions of hardware 3D sound #ifndef __HW3_SOUND_H__ diff --git a/src/hardware/hw_batching.c b/src/hardware/hw_batching.c new file mode 100644 index 000000000..a63be3a72 --- /dev/null +++ b/src/hardware/hw_batching.c @@ -0,0 +1,454 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.c +/// \brief Draw call batching and related things. + +#ifdef HWRENDER +#include "hw_glob.h" +#include "hw_batching.h" +#include "../i_system.h" + +// The texture for the next polygon given to HWR_ProcessPolygon. +// Set with HWR_SetCurrentTexture. +GLMipmap_t *current_texture = NULL; + +boolean currently_batching = false; + +FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu +UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion +// NOTE have this alloced as 3x finalVertexArray size +int finalVertexArrayAllocSize = 65536; +//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed +//int colorArrayAllocSize = 65536; +// not gonna use this for now, just sort by color and change state when it changes +// later maybe when using vertex attributes if it's needed + +PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed +int polygonArraySize = 0; +UINT32* polygonIndexArray = NULL;// contains sorting pointers for polygonArray +int polygonArrayAllocSize = 65536; + +FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon +int unsortedVertexArraySize = 0; +int unsortedVertexArrayAllocSize = 65536; + +// Enables batching mode. HWR_ProcessPolygon will collect polygons instead of passing them directly to the rendering backend. +// Call HWR_RenderBatches to render all the collected geometry. +void HWR_StartBatching(void) +{ + if (currently_batching) + I_Error("Repeat call to HWR_StartBatching without HWR_RenderBatches"); + + // init arrays if that has not been done yet + if (!finalVertexArray) + { + finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + } + + currently_batching = true; +} + +// This replaces the direct calls to pfnSetTexture in cases where batching is available. +// The texture selection is saved for the next HWR_ProcessPolygon call. +// Doing this was easier than getting a texture pointer to HWR_ProcessPolygon. +void HWR_SetCurrentTexture(GLMipmap_t *texture) +{ + if (currently_batching) + { + current_texture = texture; + } + else + { + HWD.pfnSetTexture(texture); + } +} + +// If batching is enabled, this function collects the polygon data and the chosen texture +// for later use in HWR_RenderBatches. Otherwise the rendering backend is used to +// render the polygon immediately. +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial) +{ + if (currently_batching) + { + if (!pSurf) + I_Error("Got a null FSurfaceInfo in batching");// nulls should not come in the stuff that batching currently applies to + if (polygonArraySize == polygonArrayAllocSize) + { + PolygonArrayEntry* new_array; + // ran out of space, make new array double the size + polygonArrayAllocSize *= 2; + new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); + memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); + free(polygonArray); + polygonArray = new_array; + // also need to redo the index array, dont need to copy it though + free(polygonIndexArray); + polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(UINT32)); + } + + while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) + { + FOutVector* new_array; + // need more space for vertices in unsortedVertexArray + unsortedVertexArrayAllocSize *= 2; + new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); + free(unsortedVertexArray); + unsortedVertexArray = new_array; + } + + // add the polygon data to the arrays + + polygonArray[polygonArraySize].surf = *pSurf; + polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; + polygonArray[polygonArraySize].numVerts = iNumPts; + polygonArray[polygonArraySize].polyFlags = PolyFlags; + polygonArray[polygonArraySize].texture = current_texture; + polygonArray[polygonArraySize].shader = shader; + polygonArray[polygonArraySize].horizonSpecial = horizonSpecial; + polygonArraySize++; + + memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); + unsortedVertexArraySize += iNumPts; + } + else + { + if (shader) + HWD.pfnSetShader(shader); + HWD.pfnDrawPolygon(pSurf, pOutVerts, iNumPts, PolyFlags); + } +} + +static int comparePolygons(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + + int shader1 = poly1->shader; + int shader2 = poly2->shader; + // make skywalls and horizon lines first in order + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + shader1 = -1; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + shader2 = -1; + diff = shader1 - shader2; + if (diff != 0) return diff; + + // skywalls and horizon lines must retain their order for horizon lines to work + if (shader1 == -1 && shader2 == -1) + return index1 - index2; + + diff64 = poly1->texture - poly2->texture; + if (diff64 != 0) return diff64; + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level; + if (diff != 0) return diff; + diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start; + if (diff != 0) return diff; + diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end; + return diff; +} + +static int comparePolygonsNoShaders(const void *p1, const void *p2) +{ + unsigned int index1 = *(const unsigned int*)p1; + unsigned int index2 = *(const unsigned int*)p2; + PolygonArrayEntry* poly1 = &polygonArray[index1]; + PolygonArrayEntry* poly2 = &polygonArray[index2]; + int diff; + INT64 diff64; + + GLMipmap_t *texture1 = poly1->texture; + GLMipmap_t *texture2 = poly2->texture; + if (poly1->polyFlags & PF_NoTexture || poly1->horizonSpecial) + texture1 = NULL; + if (poly2->polyFlags & PF_NoTexture || poly2->horizonSpecial) + texture2 = NULL; + diff64 = texture1 - texture2; + if (diff64 != 0) return diff64; + + // skywalls and horizon lines must retain their order for horizon lines to work + if (texture1 == NULL && texture2 == NULL) + return index1 - index2; + + diff = poly1->polyFlags - poly2->polyFlags; + if (diff != 0) return diff; + + diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; + if (diff64 < 0) return -1; else if (diff64 > 0) return 1; + + return 0; +} + +// This function organizes the geometry collected by HWR_ProcessPolygon calls into batches and uses +// the rendering backend to draw them. +void HWR_RenderBatches(void) +{ + int finalVertexWritePos = 0;// position in finalVertexArray + int finalIndexWritePos = 0;// position in finalVertexIndexArray + + int polygonReadPos = 0;// position in polygonIndexArray + + int currentShader; + int nextShader = 0; + GLMipmap_t *currentTexture; + GLMipmap_t *nextTexture = NULL; + FBITFIELD currentPolyFlags = 0; + FBITFIELD nextPolyFlags = 0; + FSurfaceInfo currentSurfaceInfo; + FSurfaceInfo nextSurfaceInfo; + + int i; + + if (!currently_batching) + I_Error("HWR_RenderBatches called without starting batching"); + + nextSurfaceInfo.LightInfo.fade_end = 0; + nextSurfaceInfo.LightInfo.fade_start = 0; + nextSurfaceInfo.LightInfo.light_level = 0; + + currently_batching = false;// no longer collecting batches + if (!polygonArraySize) + { + ps_hw_numpolys = ps_hw_numcalls = ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 0; + return;// nothing to draw + } + // init stats vars + ps_hw_numpolys = polygonArraySize; + ps_hw_numcalls = ps_hw_numverts = 0; + ps_hw_numshaders = ps_hw_numtextures = ps_hw_numpolyflags = ps_hw_numcolors = 1; + // init polygonIndexArray + for (i = 0; i < polygonArraySize; i++) + { + polygonIndexArray[i] = i; + } + + // sort polygons + ps_hw_batchsorttime = I_GetTimeMicros(); + if (cv_glshaders.value && gl_shadersavailable) + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); + else + qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); + ps_hw_batchsorttime = I_GetTimeMicros() - ps_hw_batchsorttime; + // sort order + // 1. shader + // 2. texture + // 3. polyflags + // 4. colors + light level + // not sure about what order of the last 2 should be, or if it even matters + + ps_hw_batchdrawtime = I_GetTimeMicros(); + + currentShader = polygonArray[polygonIndexArray[0]].shader; + currentTexture = polygonArray[polygonIndexArray[0]].texture; + currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags; + currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf; + // For now, will sort and track the colors. Vertex attributes could be used instead of uniforms + // and a color array could replace the color calls. + + // set state for first batch + + if (cv_glshaders.value && gl_shadersavailable) + { + HWD.pfnSetShader(currentShader); + } + + if (currentPolyFlags & PF_NoTexture) + currentTexture = NULL; + else + HWD.pfnSetTexture(currentTexture); + + while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) + { + int firstIndex; + int lastIndex; + + boolean stopFlag = false; + boolean changeState = false; + boolean changeShader = false; + boolean changeTexture = false; + boolean changePolyFlags = false; + boolean changeSurfaceInfo = false; + + // steps: + // write vertices + // check for changes or end, otherwise go back to writing + // changes will affect the next vars and the change bools + // end could set flag for stopping + // execute draw call + // could check ending flag here + // change states according to next vars and change bools, updating the current vars and reseting the bools + // reset write pos + // repeat loop + + int index = polygonIndexArray[polygonReadPos++]; + int numVerts = polygonArray[index].numVerts; + // before writing, check if there is enough room + // using 'while' instead of 'if' here makes sure that there will *always* be enough room. + // probably never will this loop run more than once though + while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) + { + FOutVector* new_array; + unsigned int* new_index_array; + finalVertexArrayAllocSize *= 2; + new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); + memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); + free(finalVertexArray); + finalVertexArray = new_array; + // also increase size of index array, 3x of vertex array since + // going from fans to triangles increases vertex count to 3x + new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); + memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); + free(finalVertexIndexArray); + finalVertexIndexArray = new_index_array; + } + // write the vertices of the polygon + memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], + numVerts * sizeof(FOutVector)); + // write the indexes, pointing to the fan vertexes but in triangles format + firstIndex = finalVertexWritePos; + lastIndex = finalVertexWritePos + numVerts; + finalVertexWritePos += 2; + while (finalVertexWritePos < lastIndex) + { + finalVertexIndexArray[finalIndexWritePos++] = firstIndex; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; + finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; + } + + if (polygonReadPos >= polygonArraySize) + { + stopFlag = true; + } + else + { + // check if a state change is required, set the change bools and next vars + int nextIndex = polygonIndexArray[polygonReadPos]; + nextShader = polygonArray[nextIndex].shader; + nextTexture = polygonArray[nextIndex].texture; + nextPolyFlags = polygonArray[nextIndex].polyFlags; + nextSurfaceInfo = polygonArray[nextIndex].surf; + if (nextPolyFlags & PF_NoTexture) + nextTexture = 0; + if (currentShader != nextShader && cv_glshaders.value && gl_shadersavailable) + { + changeState = true; + changeShader = true; + } + if (currentTexture != nextTexture) + { + changeState = true; + changeTexture = true; + } + if (currentPolyFlags != nextPolyFlags) + { + changeState = true; + changePolyFlags = true; + } + if (cv_glshaders.value && gl_shadersavailable) + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || + currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || + currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || + currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || + currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || + currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) + { + changeState = true; + changeSurfaceInfo = true; + } + } + else + { + if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) + { + changeState = true; + changeSurfaceInfo = true; + } + } + } + + if (changeState || stopFlag) + { + // execute draw call + HWD.pfnDrawIndexedTriangles(¤tSurfaceInfo, finalVertexArray, finalIndexWritePos, currentPolyFlags, finalVertexIndexArray); + // update stats + ps_hw_numcalls++; + ps_hw_numverts += finalIndexWritePos; + // reset write positions + finalVertexWritePos = 0; + finalIndexWritePos = 0; + } + else continue; + + // if we're here then either its time to stop or time to change state + if (stopFlag) break; + + // change state according to change bools and next vars, update current vars and reset bools + if (changeShader) + { + HWD.pfnSetShader(nextShader); + currentShader = nextShader; + changeShader = false; + + ps_hw_numshaders++; + } + if (changeTexture) + { + // texture should be already ready for use from calls to SetTexture during batch collection + HWD.pfnSetTexture(nextTexture); + currentTexture = nextTexture; + changeTexture = false; + + ps_hw_numtextures++; + } + if (changePolyFlags) + { + currentPolyFlags = nextPolyFlags; + changePolyFlags = false; + + ps_hw_numpolyflags++; + } + if (changeSurfaceInfo) + { + currentSurfaceInfo = nextSurfaceInfo; + changeSurfaceInfo = false; + + ps_hw_numcolors++; + } + // and that should be it? + } + // reset the arrays (set sizes to 0) + polygonArraySize = 0; + unsortedVertexArraySize = 0; + + ps_hw_batchdrawtime = I_GetTimeMicros() - ps_hw_batchdrawtime; +} + + +#endif // HWRENDER diff --git a/src/hardware/hw_batching.h b/src/hardware/hw_batching.h new file mode 100644 index 000000000..7c108a4bd --- /dev/null +++ b/src/hardware/hw_batching.h @@ -0,0 +1,37 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file hw_batching.h +/// \brief Draw call batching and related things. + +#ifndef __HWR_BATCHING_H__ +#define __HWR_BATCHING_H__ + +#include "hw_defs.h" +#include "hw_data.h" +#include "hw_drv.h" + +typedef struct +{ + FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused + unsigned int vertsIndex;// location of verts in unsortedVertexArray + FUINT numVerts; + FBITFIELD polyFlags; + GLMipmap_t *texture; + int shader; + // this tells batching that the plane belongs to a horizon line and must be drawn in correct order with the skywalls + boolean horizonSpecial; +} PolygonArrayEntry; + +void HWR_StartBatching(void); +void HWR_SetCurrentTexture(GLMipmap_t *texture); +void HWR_ProcessPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, int shader, boolean horizonSpecial); +void HWR_RenderBatches(void); + +#endif diff --git a/src/hardware/hw_bsp.c b/src/hardware/hw_bsp.c index da802aaf9..4db69ff8b 100644 --- a/src/hardware/hw_bsp.c +++ b/src/hardware/hw_bsp.c @@ -1,20 +1,17 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_bsp.c /// \brief convert SRB2 map #include "../doomdef.h" #include "../doomstat.h" #ifdef HWRENDER -#include "hw_main.h" #include "hw_glob.h" #include "../r_local.h" #include "../z_zone.h" @@ -56,12 +53,77 @@ static INT32 totalsubsecpolys = 0; // -------------------------------------------------------------------------- // Polygon fast alloc / free // -------------------------------------------------------------------------- +//hurdler: quick fix for those who wants to play with larger wad + +#define ZPLANALLOC +#ifndef ZPLANALLOC +//#define POLYPOOLSIZE 1024000 // may be much over what is needed +/// \todo check out how much is used +static size_t POLYPOOLSIZE = 1024000; + +static UINT8 *gl_polypool = NULL; +static UINT8 *gl_ppcurrent; +static size_t gl_ppfree; +#endif + +// only between levels, clear poly pool +static void HWR_ClearPolys(void) +{ +#ifndef ZPLANALLOC + gl_ppcurrent = gl_polypool; + gl_ppfree = POLYPOOLSIZE; +#endif +} + +// allocate pool for fast alloc of polys +void HWR_InitPolyPool(void) +{ +#ifndef ZPLANALLOC + INT32 pnum; + + //hurdler: quick fix for those who wants to play with larger wad + if ((pnum = M_CheckParm("-polypoolsize"))) + POLYPOOLSIZE = atoi(myargv[pnum+1])*1024; // (in kb) + + CONS_Debug(DBG_RENDER, "HWR_InitPolyPool(): allocating %d bytes\n", POLYPOOLSIZE); + gl_polypool = malloc(POLYPOOLSIZE); + if (!gl_polypool) + I_Error("HWR_InitPolyPool(): couldn't malloc polypool\n"); + HWR_ClearPolys(); +#endif +} + +void HWR_FreePolyPool(void) +{ +#ifndef ZPLANALLOC + if (gl_polypool) + free(gl_polypool); + gl_polypool = NULL; +#endif +} static poly_t *HWR_AllocPoly(INT32 numpts) { poly_t *p; size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * numpts; +#ifdef ZPLANALLOC p = Z_Malloc(size, PU_HWRPLANE, NULL); +#else +#ifdef PARANOIA + if (!gl_polypool) + I_Error("Used gl_polypool without init!\n"); + if (!gl_ppcurrent) + I_Error("gl_ppcurrent == NULL!\n"); +#endif + + if (gl_ppfree < size) + I_Error("HWR_AllocPoly(): no more memory %u bytes left, %u bytes needed\n\n%s\n", + gl_ppfree, size, "You can try the param -polypoolsize 2048 (or higher if needed)"); + + p = (poly_t *)gl_ppcurrent; + gl_ppcurrent += size; + gl_ppfree -= size; +#endif p->numpts = numpts; return p; } @@ -70,7 +132,17 @@ static polyvertex_t *HWR_AllocVertex(void) { polyvertex_t *p; size_t size = sizeof (polyvertex_t); +#ifdef ZPLANALLOC p = Z_Malloc(size, PU_HWRPLANE, NULL); +#else + if (gl_ppfree < size) + I_Error("HWR_AllocVertex(): no more memory %u bytes left, %u bytes needed\n\n%s\n", + gl_ppfree, size, "You can try the param -polypoolsize 2048 (or higher if needed)"); + + p = (polyvertex_t *)gl_ppcurrent; + gl_ppcurrent += size; + gl_ppfree -= size; +#endif return p; } @@ -78,9 +150,16 @@ static polyvertex_t *HWR_AllocVertex(void) /// for now don't free because it doesn't free in reverse order static void HWR_FreePoly(poly_t *poly) { +#ifdef ZPLANALLOC Z_Free(poly); +#else + const size_t size = sizeof (poly_t) + sizeof (polyvertex_t) * poly->numpts; + memset(poly, 0x00, size); + //mempoly -= polysize; +#endif } + // Return interception along bsp line, // with the polygon segment // @@ -363,8 +442,12 @@ static poly_t *CutOutSubsecPoly(seg_t *lseg, INT32 count, poly_t *poly) // for each seg of the subsector for (; count--; lseg++) { - //x,y,dx,dy (like a divline) line_t *line = lseg->linedef; + + if (lseg->glseg) + continue; + + //x,y,dx,dy (like a divline) p1.x = FIXED_TO_FLOAT(lseg->side ? line->v2->x : line->v1->x); p1.y = FIXED_TO_FLOAT(lseg->side ? line->v2->y : line->v1->y); p2.x = FIXED_TO_FLOAT(lseg->side ? line->v1->x : line->v2->x); @@ -491,8 +574,8 @@ static inline void SearchDivline(node_t *bsp, fdivline_t *divline) divline->dy = FIXED_TO_FLOAT(bsp->dy); } -//Hurdler: implement a loading status #ifdef HWR_LOADING_SCREEN +//Hurdler: implement a loading status static size_t ls_count = 0; static UINT8 ls_percent = 0; @@ -746,10 +829,14 @@ static INT32 SolveTProblem(void) INT32 i; size_t l; - if (cv_grsolvetjoin.value == 0) + if (cv_glsolvetjoin.value == 0) return 0; CONS_Debug(DBG_RENDER, "Solving T-joins. This may take a while. Please wait...\n"); +#ifdef HWR_LOADING_SCREEN + CON_Drawer(); //let the user know what we are doing + I_FinishUpdate(); // page flip or blit buffer +#endif numsplitpoly = 0; @@ -793,12 +880,10 @@ static void AdjustSegs(void) float distv1,distv2,tmp; nearv1 = nearv2 = MYMAX; -#ifdef POLYOBJECTS // Don't touch polyobject segs. We'll compensate // for this when we go about drawing them. if (lseg->polyseg) continue; -#endif if (p) { for (j = 0; j < p->numpts; j++) @@ -880,6 +965,8 @@ void HWR_CreatePlanePolygons(INT32 bspnum) I_FinishUpdate(); // page flip or blit buffer #endif + HWR_ClearPolys(); + // find min/max boundaries of map //CONS_Debug(DBG_RENDER, "Looking for boundaries of map...\n"); M_ClearBox(rootbbox); @@ -896,9 +983,9 @@ void HWR_CreatePlanePolygons(INT32 bspnum) I_Error("couldn't malloc extrasubsectors totsubsectors %s\n", sizeu1(totsubsectors)); // allocate table for back to front drawing of subsectors - /*gr_drawsubsectors = (INT16 *)malloc(sizeof (*gr_drawsubsectors) * totsubsectors); - if (!gr_drawsubsectors) - I_Error("couldn't malloc gr_drawsubsectors\n");*/ + /*gl_drawsubsectors = (INT16 *)malloc(sizeof (*gl_drawsubsectors) * totsubsectors); + if (!gl_drawsubsectors) + I_Error("couldn't malloc gl_drawsubsectors\n");*/ // number of the first new subsector that might be added addsubsector = numsubsectors; diff --git a/src/hardware/hw_cache.c b/src/hardware/hw_cache.c index f106be690..73ba81c58 100644 --- a/src/hardware/hw_cache.c +++ b/src/hardware/hw_cache.c @@ -1,14 +1,13 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_cache.c /// \brief load and convert graphics to the hardware format #include "../doomdef.h" @@ -17,65 +16,367 @@ #include "hw_main.h" #include "hw_glob.h" #include "hw_drv.h" +#include "hw_batching.h" #include "../doomstat.h" //gamemode #include "../i_video.h" //rendermode #include "../r_data.h" +#include "../r_textures.h" #include "../w_wad.h" #include "../z_zone.h" #include "../v_video.h" #include "../r_draw.h" +#include "../r_picformats.h" +#include "../p_setup.h" -// Values set after a call to HWR_ResizeBlock() -static INT32 blocksize, blockwidth, blockheight; +INT32 patchformat = GL_TEXFMT_AP_88; // use alpha for holes +INT32 textureformat = GL_TEXFMT_P_8; // use chromakey for hole -INT32 patchformat = GR_TEXFMT_AP_88; // use alpha for holes -INT32 textureformat = GR_TEXFMT_P_8; // use chromakey for hole +static INT32 format2bpp(GLTextureFormat_t format) +{ + if (format == GL_TEXFMT_RGBA) + return 4; + else if (format == GL_TEXFMT_ALPHA_INTENSITY_88 || format == GL_TEXFMT_AP_88) + return 2; + else + return 1; +} -// sprite, use alpha and chroma key for hole +// This code was originally placed directly in HWR_DrawPatchInCache. +// It is now split from it for my sanity! (and the sanity of others) +// -- Monster Iestyn (13/02/19) +static void HWR_DrawColumnInCache(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap, + INT32 pblockheight, INT32 blockmodulo, + fixed_t yfracstep, fixed_t scale_y, + texpatch_t *originPatch, INT32 patchheight, + INT32 bpp) +{ + fixed_t yfrac, position, count; + UINT8 *dest; + const UINT8 *source; + INT32 topdelta, prevdelta = -1; + INT32 originy = 0; + + // for writing a pixel to dest + RGBA_t colortemp; + UINT8 alpha; + UINT8 texel; + UINT16 texelu16; + + (void)patchheight; // This parameter is unused + + if (originPatch) // originPatch can be NULL here, unlike in the software version + originy = originPatch->originy; + + while (patchcol->topdelta != 0xff) + { + topdelta = patchcol->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (const UINT8 *)patchcol + 3; + count = ((patchcol->length * scale_y) + (FRACUNIT/2)) >> FRACBITS; + position = originy + topdelta; + + yfrac = 0; + //yfracstep = (patchcol->length << FRACBITS) / count; + if (position < 0) + { + yfrac = -position<> FRACBITS); + position = 0; + } + + position = ((position * scale_y) + (FRACUNIT/2)) >> FRACBITS; + + if (position < 0) + position = 0; + + if (position + count >= pblockheight) + count = pblockheight - position; + + dest = block + (position*blockmodulo); + while (count > 0) + { + count--; + + texel = source[yfrac>>FRACBITS]; + alpha = 0xFF; + // Make pixel transparent if chroma keyed + if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) + alpha = 0x00; + + //Hurdler: 25/04/2000: now support colormap in hardware mode + if (mipmap->colormap) + texel = mipmap->colormap[texel]; + + // hope compiler will get this switch out of the loops (dreams...) + // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) + // Alam: SRB2 uses Mingw, HUGS + switch (bpp) + { + case 2 : // uhhhhhhhh.......... + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); + memcpy(dest, &texelu16, sizeof(UINT16)); + break; + case 3 : colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); + break; + case 4 : colortemp = V_GetColor(texel); + colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)); + break; + // default is 1 + default: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; + break; + } + + dest += blockmodulo; + yfrac += yfracstep; + } + patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4); + } +} + +static void HWR_DrawFlippedColumnInCache(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap, + INT32 pblockheight, INT32 blockmodulo, + fixed_t yfracstep, fixed_t scale_y, + texpatch_t *originPatch, INT32 patchheight, + INT32 bpp) +{ + fixed_t yfrac, position, count; + UINT8 *dest; + const UINT8 *source; + INT32 topdelta, prevdelta = -1; + INT32 originy = 0; + + // for writing a pixel to dest + RGBA_t colortemp; + UINT8 alpha; + UINT8 texel; + UINT16 texelu16; + + if (originPatch) // originPatch can be NULL here, unlike in the software version + originy = originPatch->originy; + + while (patchcol->topdelta != 0xff) + { + topdelta = patchcol->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + topdelta = patchheight-patchcol->length-topdelta; + source = (const UINT8 *)patchcol + 3; + count = ((patchcol->length * scale_y) + (FRACUNIT/2)) >> FRACBITS; + position = originy + topdelta; + + yfrac = (patchcol->length-1) << FRACBITS; + + if (position < 0) + { + yfrac += position<> FRACBITS); + position = 0; + } + + position = ((position * scale_y) + (FRACUNIT/2)) >> FRACBITS; + + if (position < 0) + position = 0; + + if (position + count >= pblockheight) + count = pblockheight - position; + + dest = block + (position*blockmodulo); + while (count > 0) + { + count--; + + texel = source[yfrac>>FRACBITS]; + alpha = 0xFF; + // Make pixel transparent if chroma keyed + if ((mipmap->flags & TF_CHROMAKEYED) && (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX)) + alpha = 0x00; + + //Hurdler: 25/04/2000: now support colormap in hardware mode + if (mipmap->colormap) + texel = mipmap->colormap[texel]; + + // hope compiler will get this switch out of the loops (dreams...) + // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) + // Alam: SRB2 uses Mingw, HUGS + switch (bpp) + { + case 2 : // uhhhhhhhh.......... + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + texel = ASTBlendPaletteIndexes(*(dest+1), texel, originPatch->style, originPatch->alpha); + texelu16 = (UINT16)((alpha<<8) | texel); + memcpy(dest, &texelu16, sizeof(UINT16)); + break; + case 3 : colortemp = V_GetColor(texel); + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); + break; + case 4 : colortemp = V_GetColor(texel); + colortemp.s.alpha = alpha; + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + { + RGBA_t rgbatexel; + rgbatexel.rgba = *(UINT32 *)dest; + colortemp.rgba = ASTBlendTexturePixel(rgbatexel, colortemp, originPatch->style, originPatch->alpha); + } + memcpy(dest, &colortemp, sizeof(RGBA_t)); + break; + // default is 1 + default: + if ((originPatch != NULL) && (originPatch->style != AST_COPY)) + *dest = ASTBlendPaletteIndexes(*dest, texel, originPatch->style, originPatch->alpha); + else + *dest = texel; + break; + } + + dest += blockmodulo; + yfrac -= yfracstep; + } + patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4); + } +} + + +// Simplified patch caching function +// for use by sprites and other patches that are not part of a wall texture +// no alpha or flipping should be present since we do not want non-texture graphics to have them +// no offsets are used either +// -- Monster Iestyn (13/02/19) static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, - INT32 pblockwidth, INT32 pblockheight, INT32 blockmodulo, - INT32 ptexturewidth, INT32 ptextureheight, - INT32 originx, INT32 originy, // where to draw patch in surface block - const patch_t *realpatch, INT32 bpp) + INT32 pblockwidth, INT32 pblockheight, + INT32 pwidth, INT32 pheight, + const patch_t *realpatch) +{ + INT32 ncols; + fixed_t xfrac, xfracstep; + fixed_t yfracstep, scale_y; + const column_t *patchcol; + UINT8 *block = mipmap->data; + INT32 bpp; + INT32 blockmodulo; + + if (pwidth <= 0 || pheight <= 0) + return; + + ncols = pwidth; + + // source advance + xfrac = 0; + xfracstep = FRACUNIT; + yfracstep = FRACUNIT; + scale_y = FRACUNIT; + + bpp = format2bpp(mipmap->format); + + if (bpp < 1 || bpp > 4) + I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); + + // NOTE: should this actually be pblockwidth*bpp? + blockmodulo = pblockwidth*bpp; + + // Draw each column to the block cache + for (; ncols--; block += bpp, xfrac += xfracstep) + { + patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS])); + + HWR_DrawColumnInCache(patchcol, block, mipmap, + pblockheight, blockmodulo, + yfracstep, scale_y, + NULL, pheight, // not that pheight is going to get used anyway... + bpp); + } +} + +// This function we use for caching patches that belong to textures +static void HWR_DrawTexturePatchInCache(GLMipmap_t *mipmap, + INT32 pblockwidth, INT32 pblockheight, + texture_t *texture, texpatch_t *patch, + const patch_t *realpatch) { INT32 x, x1, x2; INT32 col, ncols; fixed_t xfrac, xfracstep; - fixed_t yfrac, yfracstep, position, count; - fixed_t scale_y; - RGBA_t colortemp; - UINT8 *dest; - const UINT8 *source; + fixed_t yfracstep, scale_y; const column_t *patchcol; - UINT8 alpha; - UINT8 *block = mipmap->grInfo.data; - UINT8 texel; - UINT16 texelu16; + UINT8 *block = mipmap->data; + INT32 bpp; + INT32 blockmodulo; + INT32 width, height; + // Column drawing function pointer. + static void (*ColumnDrawerPointer)(const column_t *patchcol, UINT8 *block, GLMipmap_t *mipmap, + INT32 pblockheight, INT32 blockmodulo, + fixed_t yfracstep, fixed_t scale_y, + texpatch_t *originPatch, INT32 patchheight, + INT32 bpp); - x1 = originx; - x2 = x1 + SHORT(realpatch->width); + if (texture->width <= 0 || texture->height <= 0) + return; + ColumnDrawerPointer = (patch->flip & 2) ? HWR_DrawFlippedColumnInCache : HWR_DrawColumnInCache; + + x1 = patch->originx; + width = SHORT(realpatch->width); + height = SHORT(realpatch->height); + x2 = x1 + width; + + if (x1 > texture->width || x2 < 0) + return; // patch not located within texture's x bounds, ignore + + if (patch->originy > texture->height || (patch->originy + height) < 0) + return; // patch not located within texture's y bounds, ignore + + // patch is actually inside the texture! + // now check if texture is partly off-screen and adjust accordingly + + // left edge if (x1 < 0) x = 0; else x = x1; - if (x2 > ptexturewidth) - x2 = ptexturewidth; + // right edge + if (x2 > texture->width) + x2 = texture->width; - if (!ptexturewidth) - return; - col = x * pblockwidth / ptexturewidth; - ncols = ((x2 - x) * pblockwidth) / ptexturewidth; + col = x * pblockwidth / texture->width; + ncols = ((x2 - x) * pblockwidth) / texture->width; /* - CONS_Debug(DBG_RENDER, "patch %dx%d texture %dx%d block %dx%d\n", SHORT(realpatch->width), - SHORT(realpatch->height), - ptexturewidth, - textureheight, - pblockwidth,pblockheight); + CONS_Debug(DBG_RENDER, "patch %dx%d texture %dx%d block %dx%d\n", + width, height, + texture->width, texture->height, + pblockwidth, pblockheight); CONS_Debug(DBG_RENDER, " col %d ncols %d x %d\n", col, ncols, x); */ @@ -84,218 +385,43 @@ static void HWR_DrawPatchInCache(GLMipmap_t *mipmap, if (x1 < 0) xfrac = -x1<width << FRACBITS) / pblockwidth; + yfracstep = (texture->height<< FRACBITS) / pblockheight; + scale_y = (pblockheight << FRACBITS) / texture->height; + + bpp = format2bpp(mipmap->format); + if (bpp < 1 || bpp > 4) I_Error("HWR_DrawPatchInCache: no drawer defined for this bpp (%d)\n",bpp); + // NOTE: should this actually be pblockwidth*bpp? + blockmodulo = pblockwidth*bpp; + + // Draw each column to the block cache for (block += col*bpp; ncols--; block += bpp, xfrac += xfracstep) { - INT32 topdelta, prevdelta = -1; - patchcol = (const column_t *)((const UINT8 *)realpatch - + LONG(realpatch->columnofs[xfrac>>FRACBITS])); - - scale_y = (pblockheight << FRACBITS) / ptextureheight; - - while (patchcol->topdelta != 0xff) - { - topdelta = patchcol->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (const UINT8 *)patchcol + 3; - count = ((patchcol->length * scale_y) + (FRACUNIT/2)) >> FRACBITS; - position = originy + topdelta; - - yfrac = 0; - //yfracstep = (patchcol->length << FRACBITS) / count; - if (position < 0) - { - yfrac = -position<> FRACBITS); - position = 0; - } - - position = ((position * scale_y) + (FRACUNIT/2)) >> FRACBITS; - - if (position < 0) - position = 0; - - if (position + count >= pblockheight) - count = pblockheight - position; - - dest = block + (position*blockmodulo); - while (count > 0) - { - count--; - - texel = source[yfrac>>FRACBITS]; - alpha = 0xff; - - //Hurdler: not perfect, but better than holes - if (texel == HWR_PATCHES_CHROMAKEY_COLORINDEX && (mipmap->flags & TF_CHROMAKEYED)) - alpha = 0x00; - - //Hurdler: 25/04/2000: now support colormap in hardware mode - if (mipmap->colormap) - texel = mipmap->colormap[texel]; - - // hope compiler will get this switch out of the loops (dreams...) - // gcc do it ! but vcc not ! (why don't use cygwin gcc for win32 ?) - // Alam: SRB2 uses Mingw, HUGS - switch (bpp) - { - case 2 : texelu16 = (UINT16)((alpha<<8) | texel); - memcpy(dest, &texelu16, sizeof(UINT16)); - break; - case 3 : colortemp = V_GetColor(texel); - memcpy(dest, &colortemp, sizeof(RGBA_t)-sizeof(UINT8)); - break; - case 4 : colortemp = V_GetColor(texel); - colortemp.s.alpha = alpha; - memcpy(dest, &colortemp, sizeof(RGBA_t)); - break; - // default is 1 - default: *dest = texel; - break; - } - - dest += blockmodulo; - yfrac += yfracstep; - } - patchcol = (const column_t *)((const UINT8 *)patchcol + patchcol->length + 4); - } - } -} - - -// resize the patch -// set : blocksize = blockwidth * blockheight (no bpp used) -// blockwidth -// blockheight -//note : 8bit (1 byte per pixel) palettized format -static void HWR_ResizeBlock(INT32 originalwidth, INT32 originalheight, - GLTexInfo *grInfo) -{ - // Build the full textures from patches. - static const GLlod_t gr_lods[9] = - { - GR_LOD_LOG2_256, - GR_LOD_LOG2_128, - GR_LOD_LOG2_64, - GR_LOD_LOG2_32, - GR_LOD_LOG2_16, - GR_LOD_LOG2_8, - GR_LOD_LOG2_4, - GR_LOD_LOG2_2, - GR_LOD_LOG2_1 - }; - - typedef struct - { - GLAspectRatio_t aspect; - float max_s; - float max_t; - } booring_aspect_t; - - static const booring_aspect_t gr_aspects[8] = - { - {GR_ASPECT_LOG2_1x1, 255, 255}, - {GR_ASPECT_LOG2_2x1, 255, 127}, - {GR_ASPECT_LOG2_4x1, 255, 63}, - {GR_ASPECT_LOG2_8x1, 255, 31}, - - {GR_ASPECT_LOG2_1x1, 255, 255}, - {GR_ASPECT_LOG2_1x2, 127, 255}, - {GR_ASPECT_LOG2_1x4, 63, 255}, - {GR_ASPECT_LOG2_1x8, 31, 255} - }; - - INT32 j,k; - INT32 max,min; - - // size up to nearest power of 2 - blockwidth = 1; - while (blockwidth < originalwidth) - blockwidth <<= 1; - // scale down the original graphics to fit in 2048 - if (blockwidth > 2048) - blockwidth = 2048; - - // size up to nearest power of 2 - blockheight = 1; - while (blockheight < originalheight) - blockheight <<= 1; - // scale down the original graphics to fit in 2048 - if (blockheight > 2048) - blockheight = 2048; - - // do the boring LOD stuff.. blech! - if (blockwidth >= blockheight) - { - max = blockwidth; - min = blockheight; - } - else - { - max = blockheight; - min = blockwidth; - } - - for (k = 2048, j = 0; k > max; j++) - k>>=1; - grInfo->smallLodLog2 = gr_lods[j]; - grInfo->largeLodLog2 = gr_lods[j]; - - for (k = max, j = 0; k > min && j < 4; j++) - k>>=1; - // aspect ratio too small for 3Dfx (eg: 8x128 is 1x16 : use 1x8) - if (j == 4) - { - j = 3; - //CONS_Debug(DBG_RENDER, "HWR_ResizeBlock : bad aspect ratio %dx%d\n", blockwidth,blockheight); - if (blockwidth < blockheight) - blockwidth = max>>3; + if (patch->flip & 1) + patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[(width-1)-(xfrac>>FRACBITS)])); else - blockheight = max>>3; + patchcol = (const column_t *)((const UINT8 *)realpatch + LONG(realpatch->columnofs[xfrac>>FRACBITS])); + + ColumnDrawerPointer(patchcol, block, mipmap, + pblockheight, blockmodulo, + yfracstep, scale_y, + patch, height, + bpp); } - if (blockwidth < blockheight) - j += 4; - grInfo->aspectRatioLog2 = gr_aspects[j].aspect; - - blocksize = blockwidth * blockheight; - - //CONS_Debug(DBG_RENDER, "Width is %d, Height is %d\n", blockwidth, blockheight); } - -static const INT32 format2bpp[16] = -{ - 0, //0 - 0, //1 - 1, //2 GR_TEXFMT_ALPHA_8 - 1, //3 GR_TEXFMT_INTENSITY_8 - 1, //4 GR_TEXFMT_ALPHA_INTENSITY_44 - 1, //5 GR_TEXFMT_P_8 - 4, //6 GR_RGBA - 0, //7 - 0, //8 - 0, //9 - 2, //10 GR_TEXFMT_RGB_565 - 2, //11 GR_TEXFMT_ARGB_1555 - 2, //12 GR_TEXFMT_ARGB_4444 - 2, //13 GR_TEXFMT_ALPHA_INTENSITY_88 - 2, //14 GR_TEXFMT_AP_88 -}; - static UINT8 *MakeBlock(GLMipmap_t *grMipmap) { UINT8 *block; INT32 bpp, i; UINT16 bu16 = ((0x00 <<8) | HWR_PATCHES_CHROMAKEY_COLORINDEX); + INT32 blocksize = (grMipmap->width * grMipmap->height); - bpp = format2bpp[grMipmap->grInfo.format]; - block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->grInfo.data)); + bpp = format2bpp(grMipmap->format); + block = Z_Malloc(blocksize*bpp, PU_HWRCACHE, &(grMipmap->data)); switch (bpp) { @@ -316,12 +442,14 @@ static UINT8 *MakeBlock(GLMipmap_t *grMipmap) // Create a composite texture from patches, adapt the texture size to a power of 2 // height and width for the hardware texture cache. // -static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) +static void HWR_GenerateTexture(INT32 texnum, GLMapTexture_t *grtex) { UINT8 *block; texture_t *texture; texpatch_t *patch; patch_t *realpatch; + UINT8 *pdata; + INT32 blockwidth, blockheight, blocksize; INT32 i; boolean skyspecial = false; //poor hack for Legacy large skies.. @@ -342,10 +470,9 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) else grtex->mipmap.flags = TF_CHROMAKEYED | TF_WRAPXY; - HWR_ResizeBlock (texture->width, texture->height, &grtex->mipmap.grInfo); - grtex->mipmap.width = (UINT16)blockwidth; - grtex->mipmap.height = (UINT16)blockheight; - grtex->mipmap.grInfo.format = textureformat; + grtex->mipmap.width = (UINT16)texture->width; + grtex->mipmap.height = (UINT16)texture->height; + grtex->mipmap.format = textureformat; grtex->mipmap.colormap = colormaps; @@ -354,6 +481,9 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) grtex->mipmap.colormap += (256*32); #endif + blockwidth = texture->width; + blockheight = texture->height; + blocksize = (blockwidth * blockheight); block = MakeBlock(&grtex->mipmap); if (skyspecial) //Hurdler: not efficient, but better than holes in the sky (and it's done only at level loading) @@ -377,18 +507,33 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // Composite the columns together. for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) { - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); - HWR_DrawPatchInCache(&grtex->mipmap, - blockwidth, blockheight, - blockwidth*format2bpp[grtex->mipmap.grInfo.format], - texture->width, texture->height, - patch->originx, patch->originy, - realpatch, - format2bpp[grtex->mipmap.grInfo.format]); - Z_Unlock(realpatch); + boolean dealloc = true; + size_t lumplength = W_LumpLengthPwad(patch->wad, patch->lump); + pdata = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); + realpatch = (patch_t *)pdata; + +#ifndef NO_PNG_LUMPS + if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = (patch_t *)Picture_PNGConvert(pdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); + else +#endif +#ifdef WALLFLATS + if (texture->type == TEXTURETYPE_FLAT) + realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); + else +#endif + { + (void)lumplength; + dealloc = false; + } + + HWR_DrawTexturePatchInCache(&grtex->mipmap, blockwidth, blockheight, texture, patch, realpatch); + + if (dealloc) + Z_Unlock(realpatch); } //Hurdler: not efficient at all but I don't remember exactly how HWR_DrawPatchInCache works :( - if (format2bpp[grtex->mipmap.grInfo.format]==4) + if (format2bpp(grtex->mipmap.format)==4) { for (i = 3; i < blocksize*4; i += 4) // blocksize*4 because blocksize doesn't include the bpp { @@ -407,7 +552,12 @@ static void HWR_GenerateTexture(INT32 texnum, GLTexture_t *grtex) // patch may be NULL if grMipmap has been initialised already and makebitmap is false void HWR_MakePatch (patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap) { - INT32 newwidth, newheight; +#ifndef NO_PNG_LUMPS + // lump is a png so convert it + size_t len = W_LumpLengthPwad(grPatch->wadnum, grPatch->lumpnum); + if ((patch != NULL) && Picture_IsLumpPNG((const UINT8 *)patch, len)) + patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, NULL, NULL, NULL, NULL, len, NULL, 0); +#endif // don't do it twice (like a cache) if (grMipmap->width == 0) @@ -420,158 +570,181 @@ void HWR_MakePatch (patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, bo grPatch->leftoffset = SHORT(patch->leftoffset); grPatch->topoffset = SHORT(patch->topoffset); - // resize patch - HWR_ResizeBlock(SHORT(patch->width), SHORT(patch->height), &grMipmap->grInfo); - grMipmap->width = (UINT16)blockwidth; - grMipmap->height = (UINT16)blockheight; + grMipmap->width = grMipmap->height = 1; + while (grMipmap->width < grPatch->width) grMipmap->width <<= 1; + while (grMipmap->height < grPatch->height) grMipmap->height <<= 1; // no wrap around, no chroma key grMipmap->flags = 0; // setup the texture info - grMipmap->grInfo.format = patchformat; - } - else - { - blockwidth = grMipmap->width; - blockheight = grMipmap->height; - blocksize = blockwidth * blockheight; + grMipmap->format = patchformat; + + //grPatch->max_s = grPatch->max_t = 1.0f; + grPatch->max_s = (float)grPatch->width / (float)grMipmap->width; + grPatch->max_t = (float)grPatch->height / (float)grMipmap->height; } - Z_Free(grMipmap->grInfo.data); - grMipmap->grInfo.data = NULL; - - newwidth = min(grPatch->width, blockwidth); - newheight = min(grPatch->height, blockheight); + Z_Free(grMipmap->data); + grMipmap->data = NULL; if (makebitmap) { MakeBlock(grMipmap); HWR_DrawPatchInCache(grMipmap, - newwidth, newheight, - blockwidth*format2bpp[grMipmap->grInfo.format], + grMipmap->width, grMipmap->height, grPatch->width, grPatch->height, - 0, 0, - patch, - format2bpp[grMipmap->grInfo.format]); + patch); } - - grPatch->max_s = (float)newwidth / (float)blockwidth; - grPatch->max_t = (float)newheight / (float)blockheight; } // ================================================= // CACHING HANDLING // ================================================= -static size_t gr_numtextures; -static GLTexture_t *gr_textures; // for ALL Doom textures +static size_t gl_numtextures = 0; // Texture count +static GLMapTexture_t *gl_textures; // For all textures +static GLMapTexture_t *gl_flats; // For all (texture) flats, as normal flats don't need to be cached void HWR_InitTextureCache(void) { - gr_numtextures = 0; - gr_textures = NULL; + gl_textures = NULL; + gl_flats = NULL; } - // Callback function for HWR_FreeTextureCache. static void FreeMipmapColormap(INT32 patchnum, void *patch) { - GLPatch_t* const grpatch = patch; + GLPatch_t* const pat = patch; (void)patchnum; //unused - while (grpatch->mipmap->nextcolormap) + + // The patch must be valid, obviously + if (!pat) + return; + + // The mipmap must be valid, obviously + while (pat->mipmap) { - GLMipmap_t *grmip = grpatch->mipmap->nextcolormap; - grpatch->mipmap->nextcolormap = grmip->nextcolormap; - if (grmip->grInfo.data) Z_Free(grmip->grInfo.data); - free(grmip); + // Confusing at first, but pat->mipmap->nextcolormap + // at the beginning of the loop is the first colormap + // from the linked list of colormaps. + GLMipmap_t *next = NULL; + + // No mipmap in this patch, break out of the loop. + if (!pat->mipmap) + break; + + // No colormap mipmap either. + if (!pat->mipmap->nextcolormap) + break; + + // Set the first colormap to the one that comes after it. + next = pat->mipmap->nextcolormap; + pat->mipmap->nextcolormap = next->nextcolormap; + + // Free image data from memory. + if (next->data) + Z_Free(next->data); + next->data = NULL; + + // Free the old colormap mipmap from memory. + free(next); } } -void HWR_FreeTextureCache(void) +void HWR_FreeMipmapCache(void) { INT32 i; + // free references to the textures HWD.pfnClearMipMapCache(); // free all hardware-converted graphics cached in the heap // our gool is only the textures since user of the texture is the texture cache - Z_FreeTags(PU_HWRCACHE, PU_HWRCACHE); - Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRCACHE_UNLOCKED); + Z_FreeTag(PU_HWRCACHE); + Z_FreeTag(PU_HWRCACHE_UNLOCKED); // Alam: free the Z_Blocks before freeing it's users - - // free all skin after each level: must be done after pfnClearMipMapCache! + // free all patch colormaps after each level: must be done after ClearMipMapCache! for (i = 0; i < numwadfiles; i++) M_AATreeIterate(wadfiles[i]->hwrcache, FreeMipmapColormap); +} + +void HWR_FreeTextureCache(void) +{ + // free references to the textures + HWR_FreeMipmapCache(); // now the heap don't have any 'user' pointing to our // texturecache info, we can free it - if (gr_textures) - free(gr_textures); - gr_textures = NULL; - gr_numtextures = 0; + if (gl_textures) + free(gl_textures); + if (gl_flats) + free(gl_flats); + gl_textures = NULL; + gl_flats = NULL; + gl_numtextures = 0; } -void HWR_PrepLevelCache(size_t pnumtextures) +void HWR_LoadTextures(size_t pnumtextures) { - // problem: the mipmap cache management hold a list of mipmaps.. but they are - // reallocated on each level.. - //sub-optimal, but 1) just need re-download stuff in hardware cache VERY fast - // 2) sprite/menu stuff mixed with level textures so can't do anything else - // we must free it since numtextures changed HWR_FreeTextureCache(); - gr_numtextures = pnumtextures; - gr_textures = calloc(pnumtextures, sizeof (*gr_textures)); - if (gr_textures == NULL) - I_Error("HWR_PrepLevelCache: can't alloc gr_textures"); + // Why not Z_Malloc? + gl_numtextures = pnumtextures; + gl_textures = calloc(gl_numtextures, sizeof(*gl_textures)); + gl_flats = calloc(gl_numtextures, sizeof(*gl_flats)); + + // Doesn't tell you which it _is_, but hopefully + // should never ever happen (right?!) + if ((gl_textures == NULL) || (gl_flats == NULL)) + I_Error("HWR_LoadTextures: ran out of memory for OpenGL textures. Sad!"); } void HWR_SetPalette(RGBA_t *palette) { - //Hudler: 16/10/99: added for OpenGL gamma correction - RGBA_t gamma_correction = {0x7F7F7F7F}; - - //Hurdler 16/10/99: added for OpenGL gamma correction - gamma_correction.s.red = (UINT8)cv_grgammared.value; - gamma_correction.s.green = (UINT8)cv_grgammagreen.value; - gamma_correction.s.blue = (UINT8)cv_grgammablue.value; - HWD.pfnSetPalette(palette, &gamma_correction); + HWD.pfnSetPalette(palette); // hardware driver will flush there own cache if cache is non paletized // now flush data texture cache so 32 bit texture are recomputed - if (patchformat == GR_RGBA || textureformat == GR_RGBA) + if (patchformat == GL_TEXFMT_RGBA || textureformat == GL_TEXFMT_RGBA) { - Z_FreeTags(PU_HWRCACHE, PU_HWRCACHE); - Z_FreeTags(PU_HWRCACHE_UNLOCKED, PU_HWRCACHE_UNLOCKED); + Z_FreeTag(PU_HWRCACHE); + Z_FreeTag(PU_HWRCACHE_UNLOCKED); } } // -------------------------------------------------------------------------- // Make sure texture is downloaded and set it as the source // -------------------------------------------------------------------------- -GLTexture_t *HWR_GetTexture(INT32 tex) +GLMapTexture_t *HWR_GetTexture(INT32 tex) { - GLTexture_t *grtex; + GLMapTexture_t *grtex; #ifdef PARANOIA - if ((unsigned)tex >= gr_numtextures) + if ((unsigned)tex >= gl_numtextures) I_Error("HWR_GetTexture: tex >= numtextures\n"); #endif - grtex = &gr_textures[tex]; - if (!grtex->mipmap.grInfo.data && !grtex->mipmap.downloaded) + // Every texture in memory, stored in the + // hardware renderer's bit depth format. Wow! + grtex = &gl_textures[tex]; + + // Generate texture if missing from the cache + if (!grtex->mipmap.data && !grtex->mipmap.downloaded) HWR_GenerateTexture(tex, grtex); - HWD.pfnSetTexture(&grtex->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtex->mipmap.downloaded) + HWD.pfnSetTexture(&grtex->mipmap); + + HWR_SetCurrentTexture(&grtex->mipmap); // The system-memory data can be purged now. - Z_ChangeTag(grtex->mipmap.grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED); return grtex; } - static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) { #ifdef GLENCORE @@ -582,10 +755,7 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) // setup the texture info - grMipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_64; - grMipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; - grMipmap->grInfo.format = GR_TEXFMT_P_8; + grMipmap->format = GL_TEXFMT_P_8; grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; size = W_LumpLength(flatlumpnum); @@ -614,26 +784,48 @@ static void HWR_CacheFlat(GLMipmap_t *grMipmap, lumpnum_t flatlumpnum) pflatsize = 64; break; } + grMipmap->width = (UINT16)pflatsize; grMipmap->height = (UINT16)pflatsize; // the flat raw data needn't be converted with palettized textures W_ReadLump(flatlumpnum, Z_Malloc(W_LumpLength(flatlumpnum), - PU_HWRCACHE, &grMipmap->grInfo.data)); + PU_HWRCACHE, &grMipmap->data)); #ifdef GLENCORE - flat = grMipmap->grInfo.data; + flat = grMipmap->data; for (steppy = 0; steppy < size; steppy++) if (flat[steppy] != HWR_PATCHES_CHROMAKEY_COLORINDEX) flat[steppy] = grMipmap->colormap[flat[steppy]]; #endif } +static void HWR_CacheTextureAsFlat(GLMipmap_t *grMipmap, INT32 texturenum) +{ + UINT8 *flat; + UINT8 *converted; + size_t size; + + // setup the texture info + grMipmap->format = GL_TEXFMT_P_8; + grMipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + + grMipmap->width = (UINT16)textures[texturenum]->width; + grMipmap->height = (UINT16)textures[texturenum]->height; + size = (grMipmap->width * grMipmap->height); + + flat = Z_Malloc(size, PU_HWRCACHE, &grMipmap->data); + converted = (UINT8 *)Picture_TextureToFlat(texturenum); + M_Memcpy(flat, converted, size); + Z_Free(converted); +} // Download a Doom 'flat' to the hardware cache and make it ready for use -void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap) +void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum, boolean noencoremap) { GLMipmap_t *grmip; + if (flatlumpnum == LUMPERROR) + return; grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; @@ -644,21 +836,106 @@ void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap) grmip->colormap += (256*32); #endif - grmip->colormap = colormaps; - -#ifdef GLENCORE - if (!noencoremap && encoremap) - grmip->colormap += (256*32); -#endif - - - if (!grmip->downloaded && !grmip->grInfo.data) + grmip = HWR_GetCachedGLPatch(flatlumpnum)->mipmap; + if (!grmip->downloaded && !grmip->data) HWR_CacheFlat(grmip, flatlumpnum); - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. - Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); +} + +void HWR_GetLevelFlat(levelflat_t *levelflat, boolean noencoremap) +{ + // Who knows? + if (levelflat == NULL) + return; + + if (levelflat->type == LEVELFLAT_FLAT) + HWR_LiterallyGetFlat(levelflat->u.flat.lumpnum, noencoremap); + else if (levelflat->type == LEVELFLAT_TEXTURE) + { + GLMapTexture_t *grtex; + INT32 texturenum = levelflat->u.texture.num; +#ifdef PARANOIA + if ((unsigned)texturenum >= gl_numtextures) + I_Error("HWR_GetLevelFlat: texturenum >= numtextures"); +#endif + + // Who knows? + if (texturenum == 0 || texturenum == -1) + return; + + // Every texture in memory, stored as a 8-bit flat. Wow! + grtex = &gl_flats[texturenum]; + + // Generate flat if missing from the cache + if (!grtex->mipmap.data && !grtex->mipmap.downloaded) + HWR_CacheTextureAsFlat(&grtex->mipmap, texturenum); + + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grtex->mipmap.downloaded) + HWD.pfnSetTexture(&grtex->mipmap); + + HWR_SetCurrentTexture(&grtex->mipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(grtex->mipmap.data, PU_HWRCACHE_UNLOCKED); + } + else if (levelflat->type == LEVELFLAT_PATCH) + { + GLPatch_t *patch = W_CachePatchNum(levelflat->u.flat.lumpnum, PU_CACHE); + levelflat->width = (UINT16)SHORT(patch->width); + levelflat->height = (UINT16)SHORT(patch->height); + HWR_GetPatch(patch); + } +#ifndef NO_PNG_LUMPS + else if (levelflat->type == LEVELFLAT_PNG) + { + INT32 pngwidth = 0, pngheight = 0; + GLMipmap_t *mipmap = levelflat->mipmap; + UINT8 *flat; + size_t size; + + // Cache the picture. + if (!levelflat->picture) + { + levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0); + levelflat->width = (UINT16)pngwidth; + levelflat->height = (UINT16)pngheight; + } + + // Make the mipmap. + if (mipmap == NULL) + { + mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_LEVEL, NULL); + mipmap->format = GL_TEXFMT_P_8; + mipmap->flags = TF_WRAPXY|TF_CHROMAKEYED; + levelflat->mipmap = mipmap; + } + + if (!mipmap->data && !mipmap->downloaded) + { + mipmap->width = levelflat->width; + mipmap->height = levelflat->height; + size = (mipmap->width * mipmap->height); + flat = Z_Malloc(size, PU_LEVEL, &mipmap->data); + if (levelflat->picture == NULL) + I_Error("HWR_GetLevelFlat: levelflat->picture == NULL"); + M_Memcpy(flat, levelflat->picture, size); + } + + // Tell the hardware driver to bind the current texture to the flat's mipmap + HWD.pfnSetTexture(mipmap); + } +#endif + else // set no texture + HWR_SetCurrentTexture(NULL); } // @@ -667,18 +944,27 @@ void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap) // static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) { - if (!grmip->downloaded && !grmip->grInfo.data) + if (!grmip->downloaded && !grmip->data) { - patch_t *patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + patch_t *patch = gpatch->rawpatch; + if (!patch) + patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); HWR_MakePatch(patch, gpatch, grmip, true); - Z_Free(patch); + // You can't free rawpatch for some reason? + // (Obviously I can't, sprite rotation needs that...) + if (!gpatch->rawpatch) + Z_Free(patch); } - HWD.pfnSetTexture(grmip); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!grmip->downloaded) + HWD.pfnSetTexture(grmip); + + HWR_SetCurrentTexture(grmip); // The system-memory data can be purged now. - Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); } // -----------------+ @@ -687,22 +973,29 @@ static void HWR_LoadMappedPatch(GLMipmap_t *grmip, GLPatch_t *gpatch) void HWR_GetPatch(GLPatch_t *gpatch) { // is it in hardware cache - if (!gpatch->mipmap->downloaded && !gpatch->mipmap->grInfo.data) + if (!gpatch->mipmap->downloaded && !gpatch->mipmap->data) { // load the software patch, PU_STATIC or the Z_Malloc for hardware patch will // flush the software patch before the conversion! oh yeah I suffered - patch_t *patch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); - HWR_MakePatch(patch, gpatch, gpatch->mipmap, true); + patch_t *ptr = gpatch->rawpatch; + if (!ptr) + ptr = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + HWR_MakePatch(ptr, gpatch, gpatch->mipmap, true); // this is inefficient.. but the hardware patch in heap is purgeable so it should // not fragment memory, and besides the REAL cache here is the hardware memory - Z_Free(patch); + if (!gpatch->rawpatch) + Z_Free(ptr); } - HWD.pfnSetTexture(gpatch->mipmap); + // If hardware does not have the texture, then call pfnSetTexture to upload it + if (!gpatch->mipmap->downloaded) + HWD.pfnSetTexture(gpatch->mipmap); + + HWR_SetCurrentTexture(gpatch->mipmap); // The system-memory patch data can be purged now. - Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED); } @@ -752,10 +1045,143 @@ void HWR_UnlockCachedPatch(GLPatch_t *gpatch) if (!gpatch) return; - Z_ChangeTag(gpatch->mipmap->grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(gpatch->mipmap->data, PU_HWRCACHE_UNLOCKED); Z_ChangeTag(gpatch, PU_HWRPATCHINFO_UNLOCKED); } +static const INT32 picmode2GR[] = +{ + GL_TEXFMT_P_8, // PALETTE + 0, // INTENSITY (unsupported yet) + GL_TEXFMT_ALPHA_INTENSITY_88, // INTENSITY_ALPHA (corona use this) + 0, // RGB24 (unsupported yet) + GL_TEXFMT_RGBA, // RGBA32 (opengl only) +}; + +static void HWR_DrawPicInCache(UINT8 *block, INT32 pblockwidth, INT32 pblockheight, + INT32 blockmodulo, pic_t *pic, INT32 bpp) +{ + INT32 i,j; + fixed_t posx, posy, stepx, stepy; + UINT8 *dest, *src, texel; + UINT16 texelu16; + INT32 picbpp; + RGBA_t col; + + stepy = ((INT32)SHORT(pic->height)<width)<mode]); + posy = 0; + for (j = 0; j < pblockheight; j++) + { + posx = 0; + dest = &block[j*blockmodulo]; + src = &pic->data[(posy>>FRACBITS)*SHORT(pic->width)*picbpp]; + for (i = 0; i < pblockwidth;i++) + { + switch (pic->mode) + { // source bpp + case PALETTE : + texel = src[(posx+FRACUNIT/2)>>FRACBITS]; + switch (bpp) + { // destination bpp + case 1 : + *dest++ = texel; break; + case 2 : + texelu16 = (UINT16)(texel | 0xff00); + memcpy(dest, &texelu16, sizeof(UINT16)); + dest += sizeof(UINT16); + break; + case 3 : + col = V_GetColor(texel); + memcpy(dest, &col, sizeof(RGBA_t)-sizeof(UINT8)); + dest += sizeof(RGBA_t)-sizeof(UINT8); + break; + case 4 : + memcpy(dest, &V_GetColor(texel), sizeof(RGBA_t)); + dest += sizeof(RGBA_t); + break; + } + break; + case INTENSITY : + *dest++ = src[(posx+FRACUNIT/2)>>FRACBITS]; + break; + case INTENSITY_ALPHA : // assume dest bpp = 2 + memcpy(dest, src + ((posx+FRACUNIT/2)>>FRACBITS)*sizeof(UINT16), sizeof(UINT16)); + dest += sizeof(UINT16); + break; + case RGB24 : + break; // not supported yet + case RGBA32 : // assume dest bpp = 4 + dest += sizeof(UINT32); + memcpy(dest, src + ((posx+FRACUNIT/2)>>FRACBITS)*sizeof(UINT32), sizeof(UINT32)); + break; + } + posx += stepx; + } + posy += stepy; + } +} + +// -----------------+ +// HWR_GetPic : Download a Doom pic (raw row encoded with no 'holes') +// Returns : +// -----------------+ +GLPatch_t *HWR_GetPic(lumpnum_t lumpnum) +{ + GLPatch_t *grpatch = HWR_GetCachedGLPatch(lumpnum); + if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) + { + pic_t *pic; + UINT8 *block; + size_t len; + + pic = W_CacheLumpNum(lumpnum, PU_CACHE); + grpatch->width = SHORT(pic->width); + grpatch->height = SHORT(pic->height); + len = W_LumpLength(lumpnum) - sizeof (pic_t); + + grpatch->leftoffset = 0; + grpatch->topoffset = 0; + + grpatch->mipmap->width = (UINT16)grpatch->width; + grpatch->mipmap->height = (UINT16)grpatch->height; + + if (pic->mode == PALETTE) + grpatch->mipmap->format = textureformat; // can be set by driver + else + grpatch->mipmap->format = picmode2GR[pic->mode]; + + Z_Free(grpatch->mipmap->data); + + // allocate block + block = MakeBlock(grpatch->mipmap); + + if (grpatch->width == SHORT(pic->width) && + grpatch->height == SHORT(pic->height) && + format2bpp(grpatch->mipmap->format) == format2bpp(picmode2GR[pic->mode])) + { + // no conversion needed + M_Memcpy(grpatch->mipmap->data, pic->data,len); + } + else + HWR_DrawPicInCache(block, SHORT(pic->width), SHORT(pic->height), + SHORT(pic->width)*format2bpp(grpatch->mipmap->format), + pic, + format2bpp(grpatch->mipmap->format)); + + Z_Unlock(pic); + Z_ChangeTag(block, PU_HWRCACHE_UNLOCKED); + + grpatch->mipmap->flags = 0; + grpatch->max_s = grpatch->max_t = 1.0f; + } + HWD.pfnSetTexture(grpatch->mipmap); + //CONS_Debug(DBG_RENDER, "picloaded at %x as texture %d\n",grpatch->mipmap.data, grpatch->mipmap.downloaded); + + return grpatch; +} + GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wadnum, UINT16 lumpnum) { aatree_t *hwrcache = wadfiles[wadnum]->hwrcache; @@ -784,7 +1210,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 { INT32 i,j; fixed_t posx, posy, stepx, stepy; - UINT8 *block = mipmap->grInfo.data; // places the data directly into here, it already has the space allocated from HWR_ResizeBlock + UINT8 *block = mipmap->data; // places the data directly into here UINT8 *flat; UINT8 *dest, *src, texel; RGBA_t col; @@ -799,7 +1225,7 @@ static void HWR_DrawFadeMaskInCache(GLMipmap_t *mipmap, INT32 pblockwidth, INT32 for (j = 0; j < pblockheight; j++) { posx = 0; - dest = &block[j*blockwidth]; // 1bpp + dest = &block[j*(mipmap->width)]; // 1bpp src = &flat[(posy>>FRACBITS)*SHORT(fmwidth)]; for (i = 0; i < pblockwidth;i++) { @@ -823,7 +1249,7 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) UINT16 fmheight = 0, fmwidth = 0; // setup the texture info - grMipmap->grInfo.format = GR_TEXFMT_ALPHA_8; // put the correct alpha levels straight in so I don't need to convert it later + grMipmap->format = GL_TEXFMT_ALPHA_8; // put the correct alpha levels straight in so I don't need to convert it later grMipmap->flags = 0; size = W_LumpLength(fademasklumpnum); @@ -853,14 +1279,12 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) } // Thankfully, this will still work for this scenario - HWR_ResizeBlock(fmwidth, fmheight, &grMipmap->grInfo); - - grMipmap->width = blockwidth; - grMipmap->height = blockheight; + grMipmap->width = fmwidth; + grMipmap->height = fmheight; MakeBlock(grMipmap); - HWR_DrawFadeMaskInCache(grMipmap, blockwidth, blockheight, fademasklumpnum, fmwidth, fmheight); + HWR_DrawFadeMaskInCache(grMipmap, fmwidth, fmheight, fademasklumpnum, fmwidth, fmheight); // I DO need to convert this because it isn't power of 2 and we need the alpha } @@ -868,17 +1292,14 @@ static void HWR_CacheFadeMask(GLMipmap_t *grMipmap, lumpnum_t fademasklumpnum) void HWR_GetFadeMask(lumpnum_t fademasklumpnum) { - GLMipmap_t *grmip; - - grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; - - if (!grmip->downloaded && !grmip->grInfo.data) + GLMipmap_t *grmip = HWR_GetCachedGLPatch(fademasklumpnum)->mipmap; + if (!grmip->downloaded && !grmip->data) HWR_CacheFadeMask(grmip, fademasklumpnum); HWD.pfnSetTexture(grmip); // The system-memory data can be purged now. - Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(grmip->data, PU_HWRCACHE_UNLOCKED); } #endif //HWRENDER diff --git a/src/hardware/hw_clip.c b/src/hardware/hw_clip.c index 8ef5636aa..d83b49d7e 100644 --- a/src/hardware/hw_clip.c +++ b/src/hardware/hw_clip.c @@ -73,6 +73,7 @@ #include "hw_main.h" #include "hw_clip.h" #include "hw_glob.h" +#include "../r_main.h" #include "../r_state.h" #include "../tables.h" #include "r_opengl/r_opengl.h" @@ -330,7 +331,7 @@ angle_t gld_FrustumAngle(angle_t tiltangle) // NEWCLIP TODO: SRB2CBTODO: make a global render_fov for this function - float render_fov = FIXED_TO_FLOAT(cv_fov.value); + float render_fov = FIXED_TO_FLOAT(cv_fov[viewssnum].value); float render_fovratio = (float)BASEVIDWIDTH / (float)BASEVIDHEIGHT; // SRB2CBTODO: NEWCLIPTODO: Is this right? float render_multiplier = 64.0f / render_fovratio / RMUL; @@ -462,4 +463,4 @@ boolean gld_SphereInFrustum(float x, float y, float z, float radius) } return true; } -#endif \ No newline at end of file +#endif diff --git a/src/hardware/hw_data.h b/src/hardware/hw_data.h index a96d4c915..30b456350 100644 --- a/src/hardware/hw_data.h +++ b/src/hardware/hw_data.h @@ -1,19 +1,24 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief defines structures and exports for the standard GPU driver +/// \file hw_data.h +/// \brief defines structures and exports for the hardware interface used by Sonic Robo Blast 2 #ifndef _HWR_DATA_ #define _HWR_DATA_ +#if defined (_WIN32) && !defined (__CYGWIN__) +//#define WIN32_LEAN_AND_MEAN +#define RPC_NO_WINDOWS_H +#include +#endif + #include "../doomdef.h" #include "../screen.h" @@ -21,76 +26,49 @@ // TEXTURE INFO // ========================================================================== -// -// hw_glide.h -// - -typedef long GLAspectRatio_t; -#define GR_ASPECT_LOG2_8x1 3 /* 8W x 1H */ -#define GR_ASPECT_LOG2_4x1 2 /* 4W x 1H */ -#define GR_ASPECT_LOG2_2x1 1 /* 2W x 1H */ -#define GR_ASPECT_LOG2_1x1 0 /* 1W x 1H */ -#define GR_ASPECT_LOG2_1x2 -1 /* 1W x 2H */ -#define GR_ASPECT_LOG2_1x4 -2 /* 1W x 4H */ -#define GR_ASPECT_LOG2_1x8 -3 /* 1W x 8H */ - -typedef long GLlod_t; -#define GR_LOD_LOG2_256 0x8 -#define GR_LOD_LOG2_128 0x7 -#define GR_LOD_LOG2_64 0x6 -#define GR_LOD_LOG2_32 0x5 -#define GR_LOD_LOG2_16 0x4 -#define GR_LOD_LOG2_8 0x3 -#define GR_LOD_LOG2_4 0x2 -#define GR_LOD_LOG2_2 0x1 -#define GR_LOD_LOG2_1 0x0 - -typedef long GLTextureFormat_t; -#define GR_TEXFMT_ALPHA_8 0x2 /* (0..0xFF) alpha */ -#define GR_TEXFMT_INTENSITY_8 0x3 /* (0..0xFF) intensity */ -#define GR_TEXFMT_ALPHA_INTENSITY_44 0x4 -#define GR_TEXFMT_P_8 0x5 /* 8-bit palette */ -#define GR_TEXFMT_RGB_565 0xa -#define GR_TEXFMT_ARGB_1555 0xb -#define GR_TEXFMT_ARGB_4444 0xc -#define GR_TEXFMT_ALPHA_INTENSITY_88 0xd -#define GR_TEXFMT_AP_88 0xe /* 8-bit alpha 8-bit palette */ -#define GR_RGBA 0x6 // 32 bit RGBA ! - -typedef struct +typedef enum GLTextureFormat_e { - GLlod_t smallLodLog2; - GLlod_t largeLodLog2; - GLAspectRatio_t aspectRatioLog2; - GLTextureFormat_t format; - void *data; -} GLTexInfo; + GL_TEXFMT_P_8 = 0x01, /* 8-bit palette */ + GL_TEXFMT_AP_88 = 0x02, /* 8-bit alpha, 8-bit palette */ -// grInfo.data holds the address of the graphics data cached in heap memory + GL_TEXFMT_RGBA = 0x10, /* 32 bit RGBA! */ + + GL_TEXFMT_ALPHA_8 = 0x20, /* (0..0xFF) alpha */ + GL_TEXFMT_INTENSITY_8 = 0x21, /* (0..0xFF) intensity */ + GL_TEXFMT_ALPHA_INTENSITY_88 = 0x22, +} GLTextureFormat_t; + +// data holds the address of the graphics data cached in heap memory // NULL if the texture is not in Doom heap cache. struct GLMipmap_s { - GLTexInfo grInfo; - unsigned long flags; - UINT16 width, height; - UINT32 downloaded; // tex_downloaded + //for TexDownloadMipMap + GLTextureFormat_t format; + void *data; - struct GLMipmap_s *nextmipmap; - struct GLMipmap_s *nextcolormap; - const UINT8 *colormap; + UINT32 flags; + UINT16 height; + UINT16 width; + UINT32 downloaded; // the dll driver have it in there cache ? + + struct GLMipmap_s *nextcolormap; + const UINT8 *colormap; + + // opengl + struct GLMipmap_s *nextmipmap; // opengl : liste of all texture in opengl driver }; typedef struct GLMipmap_s GLMipmap_t; // // Doom texture info, as cached for hardware rendering // -struct GLTexture_s +struct GLMapTexture_s { GLMipmap_t mipmap; float scaleX; //used for scaling textures on walls float scaleY; }; -typedef struct GLTexture_s GLTexture_t; +typedef struct GLMapTexture_s GLMapTexture_t; // a cached patch as converted to hardware format, holding the original patch_t // header so that the existing code can retrieve ->width, ->height as usual @@ -107,9 +85,9 @@ struct GLPatch_s float max_s,max_t; UINT16 wadnum; // the software patch lump num for when the hardware patch UINT16 lumpnum; // was flushed, and we need to re-create it - GLMipmap_t *mipmap; - boolean notfound; // if the texture file was not found, mark it here (used in model texture loading) + void *rawpatch; // :^) + GLMipmap_t *mipmap; } ATTRPACK; typedef struct GLPatch_s GLPatch_t; diff --git a/src/hardware/hw_defs.h b/src/hardware/hw_defs.h index 1ee6d45e9..f9e6f0c11 100644 --- a/src/hardware/hw_defs.h +++ b/src/hardware/hw_defs.h @@ -1,19 +1,13 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// 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. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_defs.h /// \brief 3D hardware renderer definitions #ifndef _HWR_DEFS_ @@ -43,6 +37,10 @@ typedef unsigned char FBOOLEAN; // byte value for paletted graphics, which represent the transparent color #define HWR_PATCHES_CHROMAKEY_COLORINDEX 255 +//#define HWR_CHROMAKEY_EQUIVALENTCOLORINDEX 130 + +// the chroma key color shows on border sprites, set it to black +#define HWR_PATCHES_CHROMAKEY_COLORVALUE (0x00000000) //RGBA format as in grSstWinOpen() // RGBA Color components with float type ranging [ 0 ... 1 ] struct FRGBAFloat @@ -87,59 +85,28 @@ typedef struct // a vertex of a Doom 'plane' polygon typedef struct { - float x; - float y; - float z; -} polyvertex_t; + FLOAT x,y,z; +} FVector; -#ifdef _MSC_VER -#pragma warning(disable : 4200) -#endif +// ====================== +// wallVert3D +// ---------------------- +// :crab: IS GONE! :crab: +// ====================== -// a convex 'plane' polygon, clockwise order -typedef struct -{ - INT32 numpts; - polyvertex_t pts[0]; -} poly_t; +// ----------- +// structures +// ----------- -#ifdef _MSC_VER -#pragma warning(default : 4200) -#endif - -// holds extra info for 3D render, for each subsector in subsectors[] -typedef struct -{ - poly_t *planepoly; // the generated convex polygon -} extrasubsector_t; - -// needed for sprite rendering -// equivalent of the software renderer's vissprites -typedef struct gr_vissprite_s -{ - // Doubly linked list - struct gr_vissprite_s *prev; - struct gr_vissprite_s *next; - float x1, x2; - float z1, z2; - float tz, ty; - lumpnum_t patchlumpnum; - boolean flip; - UINT8 translucency; //alpha level 0-255 - mobj_t *mobj; - boolean precip; // Tails 08-25-2002 - boolean vflip; - //Hurdler: 25/04/2000: now support colormap in hardware mode - UINT8 *colormap; - INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing -} gr_vissprite_t; +//Hurdler: Transform (coords + angles) +//BP: transform order : scale(rotation_x(rotation_y(translation(v)))) // Kart features -#define USE_FTRANSFORM_ANGLEZ -#define USE_FTRANSFORM_MIRROR +//#define USE_FTRANSFORM_ANGLEZ +//#define USE_FTRANSFORM_MIRROR // Vanilla features -//#define USE_MODEL_NEXTFRAME +#define USE_MODEL_NEXTFRAME typedef struct { @@ -153,20 +120,98 @@ typedef struct FLOAT fovxangle, fovyangle; UINT8 splitscreen; boolean flip; // screenflip + boolean shearing; // 14042019 + angle_t viewaiming; // 17052019 + boolean roll; + SINT8 rollflip; + FLOAT rollangle; // done to not override USE_FTRANSFORM_ANGLEZ + UINT8 rotaxis; + FLOAT centerx, centery; #ifdef USE_FTRANSFORM_MIRROR boolean mirror; // SRB2Kart: Encore Mode #endif - boolean shearing; // 14042019 - angle_t viewaiming; // 17052019 } FTransform; // Transformed vector, as passed to HWR API typedef struct { FLOAT x,y,z; - FLOAT s,t; + FLOAT s; // s texture ordinate (s over w) + FLOAT t; // t texture ordinate (t over w) } FOutVector; +#ifdef GL_SHADERS +// Predefined shader types +enum +{ + SHADER_DEFAULT = 0, + + SHADER_FLOOR, + SHADER_WALL, + SHADER_SPRITE, + SHADER_MODEL, SHADER_MODEL_LIGHTING, + SHADER_WATER, + SHADER_FOG, + SHADER_SKY, + + NUMBASESHADERS, +}; + +// Maximum amount of shader programs +// Must be higher than NUMBASESHADERS +#define HWR_MAXSHADERS 16 + +// Shader sources (vertex and fragment) +typedef struct +{ + char *vertex; + char *fragment; +} shadersource_t; + +// Custom shader reference table +typedef struct +{ + const char *type; + INT32 id; +} customshaderxlat_t; + +#endif + +typedef struct vbo_vertex_s +{ + float x, y, z; + float u, v; + unsigned char r, g, b, a; +} gl_skyvertex_t; + +typedef enum gl_skyloopmode_e +{ + HWD_SKYLOOP_FAN, + HWD_SKYLOOP_STRIP +} gl_skyloopmode_t; + +typedef struct +{ + gl_skyloopmode_t mode; + int vertexcount; + int vertexindex; + boolean use_texture; +} gl_skyloopdef_t; + +typedef struct +{ + unsigned int vbo; + int rows, columns; + int loopcount; + + int detail, vertex_count; + int texture, width, height; + boolean rebuild; // VBO needs to be rebuilt + + gl_skyloopdef_t *loops; + gl_skyvertex_t *data; +} gl_sky_t; + // ========================================================================== // RENDER MODES // ========================================================================== @@ -194,17 +239,22 @@ enum EPolyFlags PF_Invisible = 0x00000400, // Disable write to color buffer PF_Decal = 0x00000800, // Enable polygon offset PF_Modulated = 0x00001000, // Modulation (multiply output with constant ARGB) - // When set, pass the color constant into the FSurfaceInfo -> FlatColor - PF_NoTexture = 0x00002000, // Disable texture - PF_Ripple = 0x00004000, // Water shader effect - // 0x00008000 + // When set, pass the color constant into the FSurfaceInfo -> PolyColor + PF_NoTexture = 0x00002000, // Use the small white texture + PF_Corona = 0x00004000, // Tell the rendrer we are drawing a corona + PF_Ripple = 0x00008000, // Water shader effect PF_RemoveYWrap = 0x00010000, // Force clamp texture on Y PF_ForceWrapX = 0x00020000, // Force repeat texture on X PF_ForceWrapY = 0x00040000, // Force repeat texture on Y - // 0x20000000 - // 0x40000000 - // 0x80000000 + PF_Clip = 0x40000000, // clip to frustum and nearz plane (glide only, automatic in opengl) + PF_NoZClip = 0x20000000, // in conjonction with PF_Clip + PF_Debug = 0x80000000 // print debug message in driver :) +}; + +enum ESurfFlags +{ + SF_DYNLIGHT = 0x00000001, }; enum ETextureFlags @@ -238,10 +288,14 @@ struct FSurfaceInfo }; typedef struct FSurfaceInfo FSurfaceInfo; +#define GL_DEFAULTMIX 0x00000000 +#define GL_DEFAULTFOG 0xFF000000 + +//Hurdler: added for backward compatibility enum hwdsetspecialstate { + HWD_SET_MODEL_LIGHTING = 1, HWD_SET_SHADERS, - HWD_SET_TEXTUREFILTERMODE, HWD_SET_TEXTUREANISOTROPICMODE, @@ -249,8 +303,14 @@ enum hwdsetspecialstate }; typedef enum hwdsetspecialstate hwdspecialstate_t; -#define GL_DEFAULTMIX 0x00000000 -#define GL_DEFAULTFOG 0xFF000000 +// Lactozilla: Shader info +// Generally set at the start of the frame. +enum hwdshaderinfo +{ + HWD_SHADERINFO_LEVELTIME = 1, +}; + +typedef enum hwdshaderinfo hwdshaderinfo_t; enum hwdfiltermode { diff --git a/src/hardware/hw_dll.h b/src/hardware/hw_dll.h index 14040432d..d22c8c312 100644 --- a/src/hardware/hw_dll.h +++ b/src/hardware/hw_dll.h @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- +// Copyright (C) 2005 by Sonic Team Junior. // -// Copyright (C) 2005 by SRB2 Jr. Team. -// -// 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. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_dll.h /// \brief Win32 DLL and Shared Objects API definitions #ifndef __HWR_DLL_H__ @@ -40,14 +33,14 @@ #define EXPORT #endif #endif - #if defined (_WIN32) && !defined (_XBOX) + #ifdef _WIN32 #define HWRAPI(fn) WINAPI fn #else #define HWRAPI(fn) fn #endif #else // _CREATE_DLL_ #define EXPORT typedef - #if defined (_WIN32) && !defined (_XBOX) + #ifdef _WIN32 #define HWRAPI(fn) (WINAPI *fn) #else #define HWRAPI(fn) (*fn) @@ -62,7 +55,6 @@ #define DEGREE (0.017453292519943295769236907684883l) // 2*PI/360 void GL_DBG_Printf(const char *format, ...) /*FUNCPRINTF*/; -#define DBG_Printf GL_DBG_Printf #ifdef _WINDOWS BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved); diff --git a/src/hardware/hw_draw.c b/src/hardware/hw_draw.c index c86b965a8..0fe237e24 100644 --- a/src/hardware/hw_draw.c +++ b/src/hardware/hw_draw.c @@ -1,14 +1,13 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_draw.c /// \brief miscellaneous drawing (mainly 2d) #ifdef __GNUC__ @@ -29,6 +28,8 @@ #include "../z_zone.h" #include "../v_video.h" #include "../st_stuff.h" +#include "../p_local.h" // stplyr +#include "../g_game.h" // players #include "../k_hud.h" #include @@ -126,7 +127,7 @@ void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option) HWD.pfnDrawPolygon(NULL, v, 4, flags); } -void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, const UINT8 *colormap) +void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap) { FOutVector v[4]; FBITFIELD flags; @@ -138,7 +139,7 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // | /| // |/ | // 0--1 - float dupx, dupy, fscale, fwidth, fheight; + float dupx, dupy, fscalew, fscaleh, fwidth, fheight; if (alphalevel >= 10 && alphalevel < 13) return; @@ -168,7 +169,9 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, } dupx = dupy = (dupx < dupy ? dupx : dupy); - fscale = FIXED_TO_FLOAT(pscale); + fscalew = fscaleh = FIXED_TO_FLOAT(pscale); + if (vscale != pscale) + fscaleh = FIXED_TO_FLOAT(vscale); // See my comments in v_video.c's V_DrawFixedPatch // -- Monster Iestyn 29/10/18 @@ -177,13 +180,13 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, // left offset if (option & V_FLIP) - offsetx = (float)(SHORT(gpatch->width) - SHORT(gpatch->leftoffset)) * fscale; + offsetx = (float)(SHORT(gpatch->width) - SHORT(gpatch->leftoffset)) * fscalew; else - offsetx = (float)SHORT(gpatch->leftoffset) * fscale; + offsetx = (float)SHORT(gpatch->leftoffset) * fscalew; // top offset // TODO: make some kind of vertical version of V_FLIP, maybe by deprecating V_OFFSET in future?!? - offsety = (float)SHORT(gpatch->topoffset) * fscale; + offsety = (float)SHORT(gpatch->topoffset) * fscaleh; if ((option & (V_NOSCALESTART|V_OFFSET)) == (V_NOSCALESTART|V_OFFSET)) // Multiply by dupx/dupy for crosshairs { @@ -211,10 +214,10 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, } } - if (pscale != FRACUNIT) + if (pscale != FRACUNIT || (r_splitscreen && option & V_SPLITSCREEN)) { - fwidth = (float)SHORT(gpatch->width) * fscale * dupx; - fheight = (float)SHORT(gpatch->height) * fscale * dupy; + fwidth = (float)SHORT(gpatch->width) * fscalew * dupx; + fheight = (float)SHORT(gpatch->height) * fscaleh * dupy; } else { @@ -265,9 +268,9 @@ void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, { FSurfaceInfo Surf; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[hudtrans]; - else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[hudtrans]; - else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[hudtrans]; + if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); @@ -317,6 +320,8 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal dupx = dupy = (dupx < dupy ? dupx : dupy); fscale = FIXED_TO_FLOAT(pscale); + // fuck it, no GL support for croppedpatch V_SPLITSCREEN right now. it's not like it's accessible to Lua or anything, and we only use it for menus... + cy -= (float)SHORT(gpatch->topoffset) * fscale; cx -= (float)SHORT(gpatch->leftoffset) * fscale; @@ -327,16 +332,19 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal if (!(option & V_SCALEPATCHMASK)) { - // if it's meant to cover the whole screen, black out the rest + // if it's meant to cover the whole screen, black out the rest (ONLY IF TOP LEFT ISN'T TRANSPARENT) // cx and cy are possibly *slightly* off from float maths // This is done before here compared to software because we directly alter cx and cy to centre if (cx >= -0.1f && cx <= 0.1f && SHORT(gpatch->width) == BASEVIDWIDTH && cy >= -0.1f && cy <= 0.1f && SHORT(gpatch->height) == BASEVIDHEIGHT) { // Need to temporarily cache the real patch to get the colour of the top left pixel - patch_t *realpatch = W_CacheLumpNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); + patch_t *realpatch = W_CacheSoftwarePatchNumPwad(gpatch->wadnum, gpatch->lumpnum, PU_STATIC); const column_t *column = (const column_t *)((const UINT8 *)(realpatch) + LONG((realpatch)->columnofs[0])); - const UINT8 *source = (const UINT8 *)(column) + 3; - HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + if (!column->topdelta) + { + const UINT8 *source = (const UINT8 *)(column) + 3; + HWR_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); + } Z_Free(realpatch); } // centre screen @@ -349,9 +357,7 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal } if (fabsf((float)vid.height - (float)BASEVIDHEIGHT * dupy) > 1.0E-36f) { - if ((option & V_SNAPTOBOTTOM) == V_SNAPTOBOTTOM) - cy += ((float)vid.height/2 - ((float)BASEVIDHEIGHT/2 * dupy)); - else if (option & V_SNAPTOBOTTOM) + if (option & V_SNAPTOBOTTOM) cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy)); else if (!(option & V_SNAPTOTOP)) cy += ((float)vid.height - ((float)BASEVIDHEIGHT * dupy))/2; @@ -362,12 +368,6 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal fwidth = w; fheight = h; - if (fwidth > w - sx) - fwidth = w - sx; - - if (fheight > h - sy) - fheight = h - sy; - if (fwidth > SHORT(gpatch->width)) fwidth = SHORT(gpatch->width); @@ -402,10 +402,17 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].s = v[3].s = ((sx)/(float)SHORT(gpatch->width) )*gpatch->max_s; - v[2].s = v[1].s = ((w )/(float)SHORT(gpatch->width) )*gpatch->max_s; - v[0].t = v[1].t = ((sy)/(float)SHORT(gpatch->height))*gpatch->max_t; - v[2].t = v[3].t = ((h )/(float)SHORT(gpatch->height))*gpatch->max_t; + v[0].s = v[3].s = ((sx )/(float)SHORT(gpatch->width) )*gpatch->max_s; + if (sx + w > SHORT(gpatch->width)) + v[2].s = v[1].s = gpatch->max_s; + else + v[2].s = v[1].s = ((sx+w)/(float)SHORT(gpatch->width) )*gpatch->max_s; + + v[0].t = v[1].t = ((sy )/(float)SHORT(gpatch->height))*gpatch->max_t; + if (sy + h > SHORT(gpatch->height)) + v[2].t = v[3].t = gpatch->max_t; + else + v[2].t = v[3].t = ((sy+h)/(float)SHORT(gpatch->height))*gpatch->max_t; flags = PF_Translucent|PF_NoDepthTest; @@ -419,9 +426,9 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal { FSurfaceInfo Surf; Surf.PolyColor.s.red = Surf.PolyColor.s.green = Surf.PolyColor.s.blue = 0xff; - if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[cv_translucenthud.value]; - else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[cv_translucenthud.value]; - else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[cv_translucenthud.value]; + if (alphalevel == 13) Surf.PolyColor.s.alpha = softwaretranstogl_lo[st_translucency]; + else if (alphalevel == 14) Surf.PolyColor.s.alpha = softwaretranstogl[st_translucency]; + else if (alphalevel == 15) Surf.PolyColor.s.alpha = softwaretranstogl_hi[st_translucency]; else Surf.PolyColor.s.alpha = softwaretranstogl[10-alphalevel]; flags |= PF_Modulated; HWD.pfnDrawPolygon(&Surf, v, 4, flags); @@ -430,6 +437,41 @@ void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscal HWD.pfnDrawPolygon(NULL, v, 4, flags); } +void HWR_DrawPic(INT32 x, INT32 y, lumpnum_t lumpnum) +{ + FOutVector v[4]; + const GLPatch_t *patch; + + // make pic ready in hardware cache + patch = HWR_GetPic(lumpnum); + +// 3--2 +// | /| +// |/ | +// 0--1 + + v[0].x = v[3].x = 2.0f * (float)x/vid.width - 1; + v[2].x = v[1].x = 2.0f * (float)(x + patch->width*FIXED_TO_FLOAT(vid.fdupx))/vid.width - 1; + v[0].y = v[1].y = 1.0f - 2.0f * (float)y/vid.height; + v[2].y = v[3].y = 1.0f - 2.0f * (float)(y + patch->height*FIXED_TO_FLOAT(vid.fdupy))/vid.height; + + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].s = v[3].s = 0; + v[2].s = v[1].s = patch->max_s; + v[0].t = v[1].t = 0; + v[2].t = v[3].t = patch->max_t; + + + //Hurdler: Boris, the same comment as above... but maybe for pics + // it not a problem since they don't have any transparent pixel + // if I'm right !? + // But then, the question is: why not 0 instead of PF_Masked ? + // or maybe PF_Environment ??? (like what I said above) + // BP: PF_Environment don't change anything ! and 0 is undifined + HWD.pfnDrawPolygon(NULL, v, 4, PF_Translucent | PF_NoDepthTest | PF_Clip | PF_NoZClip); +} + // ========================================================================== // V_VIDEO.C STUFF // ========================================================================== @@ -495,7 +537,7 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum v[0].t = v[1].t = (float)((y & flatflag)/dflatsize); v[2].t = v[3].t = (float)(v[0].t + h/dflatsize); - HWR_GetFlat(flatlumpnum, false); // Never Encore map drawflatfill, duh. + HWR_LiterallyGetFlat(flatlumpnum, false); //Hurdler: Boris, the same comment as above... but maybe for pics // it not a problem since they don't have any transparent pixel @@ -516,31 +558,112 @@ void HWR_DrawFlatFill (INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum // 0--1 void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength) { - FOutVector v[4]; - FSurfaceInfo Surf; + FOutVector v[4]; + FSurfaceInfo Surf; - v[0].x = v[3].x = -1.0f; - v[2].x = v[1].x = 1.0f; - v[0].y = v[1].y = -1.0f; - v[2].y = v[3].y = 1.0f; - v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + v[0].x = v[3].x = -1.0f; + v[2].x = v[1].x = 1.0f; + v[0].y = v[1].y = -1.0f; + v[2].y = v[3].y = 1.0f; + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; - v[0].s = v[3].s = 0.0f; - v[2].s = v[1].s = 1.0f; - v[0].t = v[1].t = 1.0f; - v[2].t = v[3].t = 0.0f; + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; - if (color & 0xFF00) // Do COLORMAP fade. - { - Surf.PolyColor.rgba = UINT2RGBA(0x01010160); - Surf.PolyColor.s.alpha = (strength*8); - } - else // Do TRANSMAP** fade. - { - Surf.PolyColor.rgba = pLocalPalette[color].rgba; - Surf.PolyColor.s.alpha = (UINT8)(strength*25.5f); - } - HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); + if (color & 0xFF00) // Do COLORMAP fade. + { + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); + } + else // Do TRANSMAP** fade. + { + Surf.PolyColor.rgba = V_GetColor(color).rgba; + Surf.PolyColor.s.alpha = softwaretranstogl[strength]; + } + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); +} + +// -----------------+ +// HWR_DrawFadeFill : draw flat coloured rectangle, with transparency +// -----------------+ +void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + float fx, fy, fw, fh; + +// 3--2 +// | /| +// |/ | +// 0--1 + + fx = (float)x; + fy = (float)y; + fw = (float)w; + fh = (float)h; + + if (!(color & V_NOSCALESTART)) + { + float dupx = (float)vid.dupx, dupy = (float)vid.dupy; + + fx *= dupx; + fy *= dupy; + fw *= dupx; + fh *= dupy; + + // adjustxy + } + + if (fx >= vid.width || fy >= vid.height) + return; + if (fx < 0) + { + fw += fx; + fx = 0; + } + if (fy < 0) + { + fh += fy; + fy = 0; + } + + if (fw <= 0 || fh <= 0) + return; + if (fx + fw > vid.width) + fw = (float)vid.width - fx; + if (fy + fh > vid.height) + fh = (float)vid.height - fy; + + fx = -1 + fx / (vid.width / 2); + fy = 1 - fy / (vid.height / 2); + fw = fw / (vid.width / 2); + fh = fh / (vid.height / 2); + + v[0].x = v[3].x = fx; + v[2].x = v[1].x = fx + fw; + v[0].y = v[1].y = fy; + v[2].y = v[3].y = fy - fh; + + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 0.0f; + v[2].t = v[3].t = 1.0f; + + if (actualcolor & 0xFF00) // Do COLORMAP fade. + { + Surf.PolyColor.rgba = UINT2RGBA(0x01010160); + Surf.PolyColor.s.alpha = (strength*8); + } + else // Do TRANSMAP** fade. + { + Surf.PolyColor.rgba = V_GetColor(actualcolor).rgba; + Surf.PolyColor.s.alpha = softwaretranstogl[strength]; + } + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } // Draw the console background with translucency support @@ -570,6 +693,36 @@ void HWR_DrawConsoleBack(UINT32 color, INT32 height) HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); } +// Very similar to HWR_DrawConsoleBack, except we draw from the middle(-ish) of the screen to the bottom. +void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight) +{ + FOutVector v[4]; + FSurfaceInfo Surf; + INT32 height; + if (boxheight < 0) + height = -boxheight; + else + height = (boxheight * 4) + (boxheight/2)*5; // 4 lines of space plus gaps between and some leeway + + // setup some neat-o translucency effect + + v[0].x = v[3].x = -1.0f; + v[2].x = v[1].x = 1.0f; + v[0].y = v[1].y = -1.0f; + v[2].y = v[3].y = -1.0f+((height<<1)/(float)vid.height); + v[0].z = v[1].z = v[2].z = v[3].z = 1.0f; + + v[0].s = v[3].s = 0.0f; + v[2].s = v[1].s = 1.0f; + v[0].t = v[1].t = 1.0f; + v[2].t = v[3].t = 0.0f; + + Surf.PolyColor.rgba = UINT2RGBA(color); + Surf.PolyColor.s.alpha = (color == 0 ? 0xC0 : 0x80); // make black darker, like software + + HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); +} + // ========================================================================== // R_DRAW.C STUFF @@ -590,17 +743,17 @@ void HWR_DrawViewBorder(INT32 clearlines) INT32 basewindowx, basewindowy; GLPatch_t *patch; -// if (gr_viewwidth == vid.width) +// if (gl_viewwidth == vid.width) // return; if (!clearlines) clearlines = BASEVIDHEIGHT; // refresh all // calc view size based on original game resolution - baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gr_viewwidth), vid.fdupx)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; - baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gr_viewheight), vid.fdupy)); - top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gr_baseviewwindowy), vid.fdupy)); - side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gr_baseviewwindowx), vid.fdupx)); + baseviewwidth = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwidth), vid.fdupx)); //(cv_viewsize.value * BASEVIDWIDTH/10)&~7; + baseviewheight = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewheight), vid.fdupy)); + top = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_baseviewwindowy), vid.fdupy)); + side = FixedInt(FixedDiv(FLOAT_TO_FIXED(gl_viewwindowx), vid.fdupx)); // top HWR_DrawFlatFill(0, 0, @@ -637,7 +790,7 @@ void HWR_DrawViewBorder(INT32 clearlines) // top edge if (clearlines > basewindowy - 8) { - patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_CACHE); + patch = W_CachePatchNum(viewborderlump[BRDR_T], PU_PATCH); for (x = 0; x < baseviewwidth; x += 8) HWR_DrawPatch(patch, basewindowx + x, basewindowy - 8, 0); @@ -646,7 +799,7 @@ void HWR_DrawViewBorder(INT32 clearlines) // bottom edge if (clearlines > basewindowy + baseviewheight) { - patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_CACHE); + patch = W_CachePatchNum(viewborderlump[BRDR_B], PU_PATCH); for (x = 0; x < baseviewwidth; x += 8) HWR_DrawPatch(patch, basewindowx + x, basewindowy + baseviewheight, 0); @@ -655,7 +808,7 @@ void HWR_DrawViewBorder(INT32 clearlines) // left edge if (clearlines > basewindowy) { - patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_CACHE); + patch = W_CachePatchNum(viewborderlump[BRDR_L], PU_PATCH); for (y = 0; y < baseviewheight && basewindowy + y < clearlines; y += 8) { @@ -667,7 +820,7 @@ void HWR_DrawViewBorder(INT32 clearlines) // right edge if (clearlines > basewindowy) { - patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_CACHE); + patch = W_CachePatchNum(viewborderlump[BRDR_R], PU_PATCH); for (y = 0; y < baseviewheight && basewindowy+y < clearlines; y += 8) { @@ -679,22 +832,22 @@ void HWR_DrawViewBorder(INT32 clearlines) // Draw beveled corners. if (clearlines > basewindowy - 8) HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TL], - PU_CACHE), + PU_PATCH), basewindowx - 8, basewindowy - 8, 0); if (clearlines > basewindowy - 8) HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_TR], - PU_CACHE), + PU_PATCH), basewindowx + baseviewwidth, basewindowy - 8, 0); if (clearlines > basewindowy+baseviewheight) HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BL], - PU_CACHE), + PU_PATCH), basewindowx - 8, basewindowy + baseviewheight, 0); if (clearlines > basewindowy + baseviewheight) HWR_DrawPatch(W_CachePatchNum(viewborderlump[BRDR_BR], - PU_CACHE), + PU_PATCH), basewindowx + baseviewwidth, basewindowy + baseviewheight, 0); } @@ -822,15 +975,12 @@ void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color) // -------------------+ // HWR_DrawConsoleFill : draw flat coloured transparent rectangle because that's cool, and hw sucks less than sw for that. // -------------------+ -void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options) +void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor) { FOutVector v[4]; FSurfaceInfo Surf; float fx, fy, fw, fh; - if (w < 0 || h < 0) - return; // consistency w/ software - // 3--2 // | /| // |/ | @@ -841,23 +991,11 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 fw = (float)w; fh = (float)h; - if (!(options & V_NOSCALESTART)) + if (!(color & V_NOSCALESTART)) { float dupx = (float)vid.dupx, dupy = (float)vid.dupy; INT32 intx, inty; - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) - { - RGBA_t rgbaColour = V_GetColor(color); - FRGBAFloat clearColour; - clearColour.red = (float)rgbaColour.s.red / 255; - clearColour.green = (float)rgbaColour.s.green / 255; - clearColour.blue = (float)rgbaColour.s.blue / 255; - clearColour.alpha = 1; - HWD.pfnClearBuffer(true, false, &clearColour); - return; - } - fx *= dupx; fy *= dupy; fw *= dupx; @@ -865,7 +1003,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 intx = (INT32)fx; inty = (INT32)fy; - K_AdjustXYWithSnap(&intx, &inty, options, dupx, dupy); + K_AdjustXYWithSnap(&intx, &inty, color, dupx, dupy); fx = (float)intx; fy = (float)inty; } @@ -907,7 +1045,7 @@ void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 v[0].t = v[1].t = 0.0f; v[2].t = v[3].t = 1.0f; - Surf.PolyColor.rgba = UINT2RGBA(color); + Surf.PolyColor.rgba = UINT2RGBA(actualcolor); Surf.PolyColor.s.alpha = 0x80; HWD.pfnDrawPolygon(&Surf, v, 4, PF_NoTexture|PF_Modulated|PF_Translucent|PF_NoDepthTest); @@ -922,9 +1060,6 @@ void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color) FSurfaceInfo Surf; float fx, fy, fw, fh; - if (w < 0 || h < 0) - return; // consistency w/ software - // 3--2 // | /| // |/ | diff --git a/src/hardware/hw_drv.h b/src/hardware/hw_drv.h index bf8eb40f3..1480ee839 100644 --- a/src/hardware/hw_drv.h +++ b/src/hardware/hw_drv.h @@ -1,15 +1,14 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief imports/exports for the GPU hardware low-level interface API +/// \file hw_drv.h +/// \brief imports/exports for the 3D hardware low-level interface API #ifndef __HWR_DRV_H__ #define __HWR_DRV_H__ @@ -27,17 +26,22 @@ // ========================================================================== EXPORT boolean HWRAPI(Init) (void); -#if defined (PURESDL) || defined (macintosh) -EXPORT void HWRAPI(SetPalette) (INT32 *, RGBA_t *gamma); -#else -EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal, RGBA_t *pgamma); +#ifndef HAVE_SDL +EXPORT void HWRAPI(Shutdown) (void); #endif +#ifdef _WINDOWS +EXPORT void HWRAPI(GetModeList) (vmode_t **pvidmodes, INT32 *numvidmodes); +#endif +EXPORT void HWRAPI(SetPalette) (RGBA_t *ppal); EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl); EXPORT void HWRAPI(Draw2DLine) (F2DCoord *v1, F2DCoord *v2, RGBA_t Color); EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray); +EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky); EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags); EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); EXPORT void HWRAPI(SetTexture) (FTextureInfo *TexInfo); +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *TexInfo); EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); EXPORT void HWRAPI(ClearMipMapCache) (void); @@ -46,13 +50,11 @@ EXPORT void HWRAPI(ClearMipMapCache) (void); EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value); //Hurdler: added for new development -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface); +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface); EXPORT void HWRAPI(CreateModelVBOs) (model_t *model); EXPORT void HWRAPI(SetTransform) (FTransform *stransform); EXPORT INT32 HWRAPI(GetTextureUsed) (void); -EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform); - EXPORT void HWRAPI(FlushScreenTextures) (void); EXPORT void HWRAPI(StartScreenWipe) (void); EXPORT void HWRAPI(EndScreenWipe) (void); @@ -66,16 +68,13 @@ EXPORT void HWRAPI(DrawScreenFinalTexture) (int width, int height); EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]); // jimita -EXPORT boolean HWRAPI(LoadShaders) (void); -EXPORT void HWRAPI(KillShaders) (void); +EXPORT boolean HWRAPI(CompileShaders) (void); +EXPORT void HWRAPI(CleanShaders) (void); EXPORT void HWRAPI(SetShader) (int shader); EXPORT void HWRAPI(UnSetShader) (void); -EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment); -EXPORT void HWRAPI(InitCustomShaders) (void); - -EXPORT void HWRAPI(StartBatching) (void); -EXPORT void HWRAPI(RenderBatches) (int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors); +EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value); +EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment); // ========================================================================== // HWR DRIVER OBJECT, FOR CLIENT PROGRAM @@ -90,17 +89,26 @@ struct hwdriver_s FinishUpdate pfnFinishUpdate; Draw2DLine pfnDraw2DLine; DrawPolygon pfnDrawPolygon; + DrawIndexedTriangles pfnDrawIndexedTriangles; + RenderSkyDome pfnRenderSkyDome; SetBlend pfnSetBlend; ClearBuffer pfnClearBuffer; SetTexture pfnSetTexture; + UpdateTexture pfnUpdateTexture; ReadRect pfnReadRect; GClipRect pfnGClipRect; ClearMipMapCache pfnClearMipMapCache; - SetSpecialState pfnSetSpecialState; + SetSpecialState pfnSetSpecialState;//Hurdler: added for backward compatibility DrawModel pfnDrawModel; CreateModelVBOs pfnCreateModelVBOs; SetTransform pfnSetTransform; GetTextureUsed pfnGetTextureUsed; +#ifdef _WINDOWS + GetModeList pfnGetModeList; +#endif +#ifndef HAVE_SDL + Shutdown pfnShutdown; +#endif PostImgRedraw pfnPostImgRedraw; FlushScreenTextures pfnFlushScreenTextures; StartScreenWipe pfnStartScreenWipe; @@ -111,18 +119,13 @@ struct hwdriver_s MakeScreenFinalTexture pfnMakeScreenFinalTexture; DrawScreenFinalTexture pfnDrawScreenFinalTexture; - RenderSkyDome pfnRenderSkyDome; + CompileShaders pfnCompileShaders; + CleanShaders pfnCleanShaders; + SetShader pfnSetShader; + UnSetShader pfnUnSetShader; - LoadShaders pfnLoadShaders; - KillShaders pfnKillShaders; - SetShader pfnSetShader; - UnSetShader pfnUnSetShader; - - LoadCustomShader pfnLoadCustomShader; - InitCustomShaders pfnInitCustomShaders; - - StartBatching pfnStartBatching; - RenderBatches pfnRenderBatches; + SetShaderInfo pfnSetShaderInfo; + LoadCustomShader pfnLoadCustomShader; }; extern struct hwdriver_s hwdriver; diff --git a/src/hardware/hw_glob.h b/src/hardware/hw_glob.h index 3d03e7fa1..f62b6ed77 100644 --- a/src/hardware/hw_glob.h +++ b/src/hardware/hw_glob.h @@ -1,47 +1,111 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_glob.h /// \brief globals (shared data & code) for hw_ modules #ifndef _HWR_GLOB_H_ #define _HWR_GLOB_H_ #include "hw_defs.h" +#include "hw_main.h" #include "../m_misc.h" #include "../r_defs.h" +#include "../p_setup.h" + +// the original aspect ratio of Doom graphics isn't square +#define ORIGINAL_ASPECT (320.0f/200.0f) // Uncomment this to enable the OpenGL loading screen //#define HWR_LOADING_SCREEN +// SRB2Kart +#define GLENCORE + +// ----------- +// structures +// ----------- + +// a vertex of a Doom 'plane' polygon +typedef struct +{ + float x; + float y; + float z; +} polyvertex_t; + +#ifdef _MSC_VER +#pragma warning(disable : 4200) +#endif + +// a convex 'plane' polygon, clockwise order +typedef struct +{ + INT32 numpts; + polyvertex_t pts[0]; +} poly_t; + +#ifdef _MSC_VER +#pragma warning(default : 4200) +#endif + +// holds extra info for 3D render, for each subsector in subsectors[] +typedef struct +{ + poly_t *planepoly; // the generated convex polygon +} extrasubsector_t; + +// needed for sprite rendering +// equivalent of the software renderer's vissprites +typedef struct gl_vissprite_s +{ + float x1, x2; + float tz, ty; + float tracertz; // for MF2_LINKDRAW sprites, this contains tracer's tz for use in sorting + //lumpnum_t patchlumpnum; + GLPatch_t *gpatch; + boolean flip; + UINT8 translucency; //alpha level 0-255 + mobj_t *mobj; // NOTE: This is a precipmobj_t if precip is true !!! Watch out. + boolean precip; // Tails 08-25-2002 + boolean vflip; + //Hurdler: 25/04/2000: now support colormap in hardware mode + UINT8 *colormap; + INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing + float z1, z2; +} gl_vissprite_t; + // -------- // hw_bsp.c // -------- extern extrasubsector_t *extrasubsectors; extern size_t addsubsector; +void HWR_InitPolyPool(void); +void HWR_FreePolyPool(void); + // -------- // hw_cache.c // -------- void HWR_InitTextureCache(void); void HWR_FreeTextureCache(void); +void HWR_FreeMipmapCache(void); void HWR_FreeExtraSubsectors(void); -void HWR_GetFlat(lumpnum_t flatlumpnum, boolean noencoremap); -// ^ some flats must NOT be remapped to encore, since we remap them as we cache them for ease, adding a toggle here seems wise. - -GLTexture_t *HWR_GetTexture(INT32 tex); +void HWR_GetLevelFlat(levelflat_t *levelflat, boolean noencoremap); +void HWR_LiterallyGetFlat(lumpnum_t flatlumpnum, boolean noencoremap); +GLMapTexture_t *HWR_GetTexture(INT32 tex); void HWR_GetPatch(GLPatch_t *gpatch); void HWR_GetMappedPatch(GLPatch_t *gpatch, const UINT8 *colormap); void HWR_MakePatch(patch_t *patch, GLPatch_t *grPatch, GLMipmap_t *grMipmap, boolean makebitmap); void HWR_UnlockCachedPatch(GLPatch_t *gpatch); +GLPatch_t *HWR_GetPic(lumpnum_t lumpnum); void HWR_SetPalette(RGBA_t *palette); GLPatch_t *HWR_GetCachedGLPatchPwad(UINT16 wad, UINT16 lump); GLPatch_t *HWR_GetCachedGLPatch(lumpnum_t lumpnum); @@ -50,8 +114,6 @@ void HWR_GetFadeMask(lumpnum_t fademasklumpnum); // -------- // hw_draw.c // -------- -extern consvar_t cv_grrounddown; // on/off - extern INT32 patchformat; extern INT32 textureformat; diff --git a/src/hardware/hw_light.c b/src/hardware/hw_light.c index 079349c37..32c2d550d 100644 --- a/src/hardware/hw_light.c +++ b/src/hardware/hw_light.c @@ -1,14 +1,15 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_light.c +/// \brief Corona/Dynamic/Static lighting add on by Hurdler +/// !!! Under construction !!! #include "../doomdef.h" @@ -24,4 +25,1450 @@ #include "../r_main.h" #include "../p_local.h" +//============================================================================= +// DEFINES +//============================================================================= + +#define DL_SQRRADIUS(x) dynlights->p_lspr[(x)]->dynamic_sqrradius +#define DL_RADIUS(x) dynlights->p_lspr[(x)]->dynamic_radius +#define LIGHT_POS(i) dynlights->position[(i)] + +#define DL_HIGH_QUALITY +//#define STATICLIGHT //Hurdler: TODO! +//#define LIGHTMAPFLAGS (PF_Masked|PF_Clip|PF_NoAlphaTest) // debug see overdraw +#define LIGHTMAPFLAGS (PF_Modulated|PF_Additive|PF_Clip) + +#ifdef ALAM_LIGHTING +static dynlights_t view_dynlights[2]; // 2 players in splitscreen mode +static dynlights_t *dynlights = &view_dynlights[0]; +#endif + +#define UNDEFINED_SPR 0x0 // actually just for testing +#define CORONA_SPR 0x1 // a light source which only emit a corona +#define DYNLIGHT_SPR 0x2 // a light source which is only used for dynamic lighting +#define LIGHT_SPR (DYNLIGHT_SPR|CORONA_SPR) +#define ROCKET_SPR (DYNLIGHT_SPR|CORONA_SPR|0x10) +//#define MONSTER_SPR 4 +//#define AMMO_SPR 8 +//#define BONUS_SPR 16 + +//Hurdler: now we can change those values via FS :) +light_t lspr[NUMLIGHTS] = +{ + // type offset x, y coronas color, c_size,light color,l_radius, sqr radius computed at init + // NOLIGHT: 0 + { UNDEFINED_SPR, 0.0f, 0.0f, 0x00000000, 24.0f, 0x00000000, 0.0f, 0.0f}, + // weapons + // RINGSPARK_L + { LIGHT_SPR, 0.0f, 0.0f, 0x0000e0ff, 16.0f, 0x0000e0ff, 32.0f, 0.0f}, // Tails 09-08-2002 + // SUPERSONIC_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0xff00e0ff, 32.0f, 0xff00e0ff, 128.0f, 0.0f}, // Tails 09-08-2002 + // SUPERSPARK_L + { LIGHT_SPR, 0.0f, 0.0f, 0xe0ffffff, 8.0f, 0xe0ffffff, 64.0f, 0.0f}, + // INVINCIBLE_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x10ffaaaa, 16.0f, 0x10ffaaaa, 128.0f, 0.0f}, + // GREENSHIELD_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x602b7337, 32.0f, 0x602b7337, 128.0f, 0.0f}, + // BLUESHIELD_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x60cb0000, 32.0f, 0x60cb0000, 128.0f, 0.0f}, + + // tall lights + // YELLOWSHIELD_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x601f7baf, 32.0f, 0x601f7baf, 128.0f, 0.0f}, + + // REDSHIELD_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x600000cb, 32.0f, 0x600000cb, 128.0f, 0.0f}, + + // BLACKSHIELD_L // Black light? lol + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x60010101, 32.0f, 0x60ff00ff, 128.0f, 0.0f}, + + // WHITESHIELD_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x60ffffff, 32.0f, 0x60ffffff, 128.0f, 0.0f}, + + // SMALLREDBALL_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x606060f0, 0.0f, 0x302070ff, 32.0f, 0.0f}, + + // small lights + // RINGLIGHT_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x60b0f0f0, 0.0f, 0x30b0f0f0, 100.0f, 0.0f}, + // GREENSMALL_L + { LIGHT_SPR, 0.0f, 14.0f, 0x6070ff70, 60.0f, 0x4070ff70, 100.0f, 0.0f}, + // REDSMALL_L + { LIGHT_SPR, 0.0f, 14.0f, 0x705070ff, 60.0f, 0x405070ff, 100.0f, 0.0f}, + + // type offset x, y coronas color, c_size,light color,l_radius, sqr radius computed at init + // GREENSHINE_L + { LIGHT_SPR, 0.0f, 0.0f, 0xff00ff00, 64.0f, 0xff00ff00, 256.0f, 0.0f}, + // ORANGESHINE_L + { LIGHT_SPR, 0.0f, 0.0f, 0xff0080ff, 64.0f, 0xff0080ff, 256.0f, 0.0f}, + // PINKSHINE_L + { LIGHT_SPR, 0.0f, 0.0f, 0xffe080ff, 64.0f, 0xffe080ff, 256.0f, 0.0f}, + // BLUESHINE_L + { LIGHT_SPR, 0.0f, 0.0f, 0xffff0000, 64.0f, 0xffff0000, 256.0f, 0.0f}, + // REDSHINE_L + { LIGHT_SPR, 0.0f, 0.0f, 0xff0000ff, 64.0f, 0xff0000ff, 256.0f, 0.0f}, + // LBLUESHINE_L + { LIGHT_SPR, 0.0f, 0.0f, 0xffff8080, 64.0f, 0xffff8080, 256.0f, 0.0f}, + // GREYSHINE_L + { LIGHT_SPR, 0.0f, 0.0f, 0xffe0e0e0, 64.0f, 0xffe0e0e0, 256.0f, 0.0f}, + + // monsters + // REDBALL_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x606060ff, 0.0f, 0x606060ff, 100.0f, 0.0f}, + // GREENBALL_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x6060ff60, 120.0f, 0x6060ff60, 100.0f, 0.0f}, + // BLUEBALL_L + { DYNLIGHT_SPR, 0.0f, 0.0f, 0x60ff6060, 120.0f, 0x60ff6060, 100.0f, 0.0f}, + + // NIGHTSLIGHT_L + { LIGHT_SPR, 0.0f, 6.0f, 0x60ffffff, 16.0f, 0x30ffffff, 32.0f, 0.0f}, + + // JETLIGHT_L + { DYNLIGHT_SPR, 0.0f, 6.0f, 0x60ffaaaa, 16.0f, 0x30ffaaaa, 64.0f, 0.0f}, + + // GOOPLIGHT_L + { DYNLIGHT_SPR, 0.0f, 6.0f, 0x60ff00ff, 16.0f, 0x30ff00ff, 32.0f, 0.0f}, + + // STREETLIGHT_L + { LIGHT_SPR, 0.0f, 0.0f, 0xe0ffffff, 64.0f, 0xe0ffffff, 384.0f, 0.0f}, +}; + +light_t *t_lspr[NUMSPRITES] = +{ + &lspr[NOLIGHT], // SPR_NULL + &lspr[NOLIGHT], // SPR_UNKN + + &lspr[NOLIGHT], // SPR_THOK + &lspr[SUPERSONIC_L],// SPR_PLAY + + // Enemies + &lspr[NOLIGHT], // SPR_POSS + &lspr[NOLIGHT], // SPR_SPOS + &lspr[NOLIGHT], // SPR_FISH + &lspr[NOLIGHT], // SPR_BUZZ + &lspr[NOLIGHT], // SPR_RBUZ + &lspr[NOLIGHT], // SPR_JETB + &lspr[NOLIGHT], // SPR_JETG + &lspr[NOLIGHT], // SPR_CCOM + &lspr[NOLIGHT], // SPR_DETN + &lspr[NOLIGHT], // SPR_SKIM + &lspr[NOLIGHT], // SPR_TRET + &lspr[NOLIGHT], // SPR_TURR + &lspr[NOLIGHT], // SPR_SHRP + &lspr[NOLIGHT], // SPR_CRAB + &lspr[NOLIGHT], // SPR_CR2B + &lspr[NOLIGHT], // SPR_CSPR + &lspr[NOLIGHT], // SPR_JJAW + &lspr[NOLIGHT], // SPR_SNLR + &lspr[NOLIGHT], // SPR_VLTR + &lspr[NOLIGHT], // SPR_PNTY + &lspr[NOLIGHT], // SPR_ARCH + &lspr[NOLIGHT], // SPR_CBFS + &lspr[JETLIGHT_L], // SPR_STAB + &lspr[NOLIGHT], // SPR_SPSH + &lspr[NOLIGHT], // SPR_ESHI + &lspr[NOLIGHT], // SPR_GSNP + &lspr[NOLIGHT], // SPR_GSNL + &lspr[NOLIGHT], // SPR_GSNH + &lspr[NOLIGHT], // SPR_MNUS + &lspr[NOLIGHT], // SPR_MNUD + &lspr[NOLIGHT], // SPR_SSHL + &lspr[NOLIGHT], // SPR_UNID + &lspr[NOLIGHT], // SPR_CANA + &lspr[NOLIGHT], // SPR_CANG + &lspr[NOLIGHT], // SPR_PYRE + &lspr[NOLIGHT], // SPR_PTER + &lspr[NOLIGHT], // SPR_DRAB + + // Generic Boos Items + &lspr[JETLIGHT_L], // SPR_JETF // Boss jet fumes + + // Boss 1, (Greenflower) + &lspr[NOLIGHT], // SPR_EGGM + &lspr[NOLIGHT], // SPR_EGLZ + + // Boss 2, (Techno Hill) + &lspr[NOLIGHT], // SPR_EGGN + &lspr[NOLIGHT], // SPR_TANK + &lspr[NOLIGHT], // SPR_GOOP + + // Boss 3 (Deep Sea) + &lspr[NOLIGHT], // SPR_EGGO + &lspr[NOLIGHT], // SPR_SEBH + &lspr[NOLIGHT], // SPR_FAKE + &lspr[LBLUESHINE_L],// SPR_SHCK + + // Boss 4 (Castle Eggman) + &lspr[NOLIGHT], // SPR_EGGP + &lspr[REDBALL_L], // SPR_EFIR + &lspr[NOLIGHT], // SPR_EGR1 + + // Boss 5 (Arid Canyon) + &lspr[NOLIGHT], // SPR_FANG // replaces EGGQ + &lspr[NOLIGHT], // SPR_BRKN + &lspr[NOLIGHT], // SPR_WHAT + &lspr[INVINCIBLE_L], // SPR_VWRE + &lspr[INVINCIBLE_L], // SPR_PROJ + &lspr[NOLIGHT], // SPR_FBOM + &lspr[NOLIGHT], // SPR_FSGN + &lspr[REDBALL_L], // SPR_BARX // bomb explosion (also used by barrel) + &lspr[NOLIGHT], // SPR_BARD // bomb dust (also used by barrel) + + // Boss 6 (Red Volcano) + &lspr[NOLIGHT], // SPR_EEGR + + // Boss 7 (Dark City) + &lspr[NOLIGHT], // SPR_BRAK + &lspr[NOLIGHT], // SPR_BGOO + &lspr[NOLIGHT], // SPR_BMSL + + // Boss 8 (Egg Rock) + &lspr[NOLIGHT], // SPR_EGGT + + &lspr[NOLIGHT], //SPR_RCKT + &lspr[NOLIGHT], //SPR_ELEC + &lspr[NOLIGHT], //SPR_TARG + &lspr[NOLIGHT], //SPR_NPLM + &lspr[NOLIGHT], //SPR_MNPL + + // Metal Sonic + &lspr[NOLIGHT], // SPR_METL + &lspr[NOLIGHT], // SPR_MSCF + &lspr[NOLIGHT], // SPR_MSCB + + // Collectible Items + &lspr[NOLIGHT], // SPR_RING + &lspr[NOLIGHT], // SPR_TRNG + &lspr[NOLIGHT], // SPR_TOKE + &lspr[REDBALL_L], // SPR_RFLG + &lspr[BLUEBALL_L], // SPR_BFLG + &lspr[NOLIGHT], // SPR_SPHR + &lspr[NOLIGHT], // SPR_NCHP + &lspr[NOLIGHT], // SPR_NSTR + &lspr[NOLIGHT], // SPR_EMBM + &lspr[NOLIGHT], // SPR_CEMG + &lspr[NOLIGHT], // SPR_SHRD + + // Interactive Objects + &lspr[NOLIGHT], // SPR_BBLS + &lspr[NOLIGHT], // SPR_SIGN + &lspr[NOLIGHT], // SPR_SPIK + &lspr[NOLIGHT], // SPR_SFLM + &lspr[NOLIGHT], // SPR_USPK + &lspr[NOLIGHT], // SPR_WSPK + &lspr[NOLIGHT], // SPR_WSPB + &lspr[NOLIGHT], // SPR_STPT + &lspr[NOLIGHT], // SPR_BMNE + &lspr[NOLIGHT], // SPR_PUMI + + // Monitor Boxes + &lspr[NOLIGHT], // SPR_MSTV + &lspr[NOLIGHT], // SPR_XLTV + + &lspr[NOLIGHT], // SPR_TRRI + &lspr[NOLIGHT], // SPR_TBRI + + &lspr[NOLIGHT], // SPR_TVRI + &lspr[NOLIGHT], // SPR_TVPI + &lspr[NOLIGHT], // SPR_TVAT + &lspr[NOLIGHT], // SPR_TVFO + &lspr[NOLIGHT], // SPR_TVAR + &lspr[NOLIGHT], // SPR_TVWW + &lspr[NOLIGHT], // SPR_TVEL + &lspr[NOLIGHT], // SPR_TVSS + &lspr[NOLIGHT], // SPR_TVIV + &lspr[NOLIGHT], // SPR_TV1U + &lspr[NOLIGHT], // SPR_TV1P + &lspr[NOLIGHT], // SPR_TVEG + &lspr[NOLIGHT], // SPR_TVMX + &lspr[NOLIGHT], // SPR_TVMY + &lspr[NOLIGHT], // SPR_TVGV + &lspr[NOLIGHT], // SPR_TVRC + &lspr[NOLIGHT], // SPR_TV1K + &lspr[NOLIGHT], // SPR_TVTK + &lspr[NOLIGHT], // SPR_TVFL + &lspr[NOLIGHT], // SPR_TVBB + &lspr[NOLIGHT], // SPR_TVZP + + // Projectiles + &lspr[NOLIGHT], // SPR_MISL + &lspr[SMALLREDBALL_L], // SPR_LASR + &lspr[REDSHINE_L], // SPR_LASF + &lspr[NOLIGHT], // SPR_TORP + &lspr[NOLIGHT], // SPR_ENRG + &lspr[NOLIGHT], // SPR_MINE + &lspr[NOLIGHT], // SPR_JBUL + &lspr[SMALLREDBALL_L], // SPR_TRLS + &lspr[NOLIGHT], // SPR_CBLL + &lspr[NOLIGHT], // SPR_AROW + &lspr[NOLIGHT], // SPR_CFIR + + // Greenflower Scenery + &lspr[NOLIGHT], // SPR_FWR1 + &lspr[NOLIGHT], // SPR_FWR2 + &lspr[NOLIGHT], // SPR_FWR3 + &lspr[NOLIGHT], // SPR_FWR4 + &lspr[NOLIGHT], // SPR_BUS1 + &lspr[NOLIGHT], // SPR_BUS2 + &lspr[NOLIGHT], // SPR_BUS3 + // Trees (both GFZ and misc) + &lspr[NOLIGHT], // SPR_TRE1 + &lspr[NOLIGHT], // SPR_TRE2 + &lspr[NOLIGHT], // SPR_TRE3 + &lspr[NOLIGHT], // SPR_TRE4 + &lspr[NOLIGHT], // SPR_TRE5 + &lspr[NOLIGHT], // SPR_TRE6 + + // Techno Hill Scenery + &lspr[NOLIGHT], // SPR_THZP + &lspr[NOLIGHT], // SPR_FWR5 + &lspr[REDBALL_L], // SPR_ALRM + + // Deep Sea Scenery + &lspr[NOLIGHT], // SPR_GARG + &lspr[NOLIGHT], // SPR_SEWE + &lspr[NOLIGHT], // SPR_DRIP + &lspr[NOLIGHT], // SPR_CRL1 + &lspr[NOLIGHT], // SPR_CRL2 + &lspr[NOLIGHT], // SPR_CRL3 + &lspr[NOLIGHT], // SPR_BCRY + + // Castle Eggman Scenery + &lspr[NOLIGHT], // SPR_CHAN + &lspr[REDBALL_L], // SPR_FLAM + &lspr[NOLIGHT], // SPR_ESTA + &lspr[NOLIGHT], // SPR_SMCH + &lspr[NOLIGHT], // SPR_BMCH + &lspr[NOLIGHT], // SPR_SMCE + &lspr[NOLIGHT], // SPR_BMCE + &lspr[NOLIGHT], // SPR_YSPB + &lspr[NOLIGHT], // SPR_RSPB + &lspr[REDBALL_L], // SPR_SFBR + &lspr[REDBALL_L], // SPR_BFBR + &lspr[NOLIGHT], // SPR_BANR + &lspr[NOLIGHT], // SPR_PINE + &lspr[NOLIGHT], // SPR_CEZB + &lspr[REDBALL_L], // SPR_CNDL + &lspr[NOLIGHT], // SPR_FLMH + &lspr[REDBALL_L], // SPR_CTRC + &lspr[NOLIGHT], // SPR_CFLG + &lspr[NOLIGHT], // SPR_CSTA + &lspr[NOLIGHT], // SPR_CBBS + + // Arid Canyon Scenery + &lspr[NOLIGHT], // SPR_BTBL + &lspr[NOLIGHT], // SPR_STBL + &lspr[NOLIGHT], // SPR_CACT + &lspr[NOLIGHT], // SPR_WWSG + &lspr[NOLIGHT], // SPR_WWS2 + &lspr[NOLIGHT], // SPR_WWS3 + &lspr[NOLIGHT], // SPR_OILL + &lspr[NOLIGHT], // SPR_OILF + &lspr[NOLIGHT], // SPR_BARR + &lspr[NOLIGHT], // SPR_REMT + &lspr[NOLIGHT], // SPR_TAZD + &lspr[NOLIGHT], // SPR_ADST + &lspr[NOLIGHT], // SPR_MCRT + &lspr[NOLIGHT], // SPR_MCSP + &lspr[NOLIGHT], // SPR_SALD + &lspr[NOLIGHT], // SPR_TRAE + &lspr[NOLIGHT], // SPR_TRAI + &lspr[NOLIGHT], // SPR_STEA + + // Red Volcano Scenery + &lspr[REDBALL_L], // SPR_FLME + &lspr[REDBALL_L], // SPR_DFLM + &lspr[NOLIGHT], // SPR_LFAL + &lspr[NOLIGHT], // SPR_JPLA + &lspr[NOLIGHT], // SPR_TFLO + &lspr[NOLIGHT], // SPR_WVIN + + // Dark City Scenery + + // Egg Rock Scenery + + // Christmas Scenery + &lspr[NOLIGHT], // SPR_XMS1 + &lspr[NOLIGHT], // SPR_XMS2 + &lspr[NOLIGHT], // SPR_XMS3 + &lspr[NOLIGHT], // SPR_XMS4 + &lspr[NOLIGHT], // SPR_XMS5 + &lspr[NOLIGHT], // SPR_XMS6 + &lspr[NOLIGHT], // SPR_FHZI + &lspr[NOLIGHT], // SPR_ROSY + + // Halloween Scenery + &lspr[RINGLIGHT_L], // SPR_PUMK + &lspr[NOLIGHT], // SPR_HHPL + &lspr[NOLIGHT], // SPR_SHRM + &lspr[NOLIGHT], // SPR_HHZM + + // Azure Temple Scenery + &lspr[NOLIGHT], // SPR_BGAR + &lspr[NOLIGHT], // SPR_RCRY + &lspr[GREENBALL_L], // SPR_CFLM + + // Botanic Serenity Scenery + &lspr[NOLIGHT], // SPR_BSZ1 + &lspr[NOLIGHT], // SPR_BSZ2 + &lspr[NOLIGHT], // SPR_BSZ3 + //&lspr[NOLIGHT], -- SPR_BSZ4 + &lspr[NOLIGHT], // SPR_BST1 + &lspr[NOLIGHT], // SPR_BST2 + &lspr[NOLIGHT], // SPR_BST3 + &lspr[NOLIGHT], // SPR_BST4 + &lspr[NOLIGHT], // SPR_BST5 + &lspr[NOLIGHT], // SPR_BST6 + &lspr[NOLIGHT], // SPR_BSZ5 + &lspr[NOLIGHT], // SPR_BSZ6 + &lspr[NOLIGHT], // SPR_BSZ7 + &lspr[NOLIGHT], // SPR_BSZ8 + + // Misc Scenery + &lspr[NOLIGHT], // SPR_STLG + &lspr[NOLIGHT], // SPR_DBAL + + // Powerup Indicators + &lspr[NOLIGHT], // SPR_ARMA + &lspr[NOLIGHT], // SPR_ARMF + &lspr[NOLIGHT], // SPR_ARMB + &lspr[NOLIGHT], // SPR_WIND + &lspr[NOLIGHT], // SPR_MAGN + &lspr[NOLIGHT], // SPR_ELEM + &lspr[NOLIGHT], // SPR_FORC + &lspr[NOLIGHT], // SPR_PITY + &lspr[NOLIGHT], // SPR_FIRS + &lspr[NOLIGHT], // SPR_BUBS + &lspr[NOLIGHT], // SPR_ZAPS + &lspr[INVINCIBLE_L], // SPR_IVSP + &lspr[SUPERSPARK_L], // SPR_SSPK + + &lspr[NOLIGHT], // SPR_GOAL + + // Flickies + &lspr[NOLIGHT], // SPR_FBUB + &lspr[NOLIGHT], // SPR_FL01 + &lspr[NOLIGHT], // SPR_FL02 + &lspr[NOLIGHT], // SPR_FL03 + &lspr[NOLIGHT], // SPR_FL04 + &lspr[NOLIGHT], // SPR_FL05 + &lspr[NOLIGHT], // SPR_FL06 + &lspr[NOLIGHT], // SPR_FL07 + &lspr[NOLIGHT], // SPR_FL08 + &lspr[NOLIGHT], // SPR_FL09 + &lspr[NOLIGHT], // SPR_FL10 + &lspr[NOLIGHT], // SPR_FL11 + &lspr[NOLIGHT], // SPR_FL12 + &lspr[NOLIGHT], // SPR_FL13 + &lspr[NOLIGHT], // SPR_FL14 + &lspr[NOLIGHT], // SPR_FL15 + &lspr[NOLIGHT], // SPR_FL16 + &lspr[NOLIGHT], // SPR_FS01 + &lspr[NOLIGHT], // SPR_FS02 + + // Springs + &lspr[NOLIGHT], // SPR_FANS + &lspr[NOLIGHT], // SPR_STEM + &lspr[NOLIGHT], // SPR_BUMP + &lspr[NOLIGHT], // SPR_BLON + &lspr[NOLIGHT], // SPR_SPRY + &lspr[NOLIGHT], // SPR_SPRR + &lspr[NOLIGHT], // SPR_SPRB + &lspr[NOLIGHT], // SPR_YSPR + &lspr[NOLIGHT], // SPR_RSPR + &lspr[NOLIGHT], // SPR_BSPR + &lspr[NOLIGHT], // SPR_SSWY + &lspr[NOLIGHT], // SPR_SSWR + &lspr[NOLIGHT], // SPR_SSWB + &lspr[NOLIGHT], // SPR_BSTY + &lspr[NOLIGHT], // SPR_BSTR + + // Environmental Effects + &lspr[NOLIGHT], // SPR_RAIN + &lspr[NOLIGHT], // SPR_SNO1 + &lspr[NOLIGHT], // SPR_SPLH + &lspr[NOLIGHT], // SPR_LSPL + &lspr[NOLIGHT], // SPR_SPLA + &lspr[NOLIGHT], // SPR_SMOK + &lspr[NOLIGHT], // SPR_BUBL + &lspr[RINGLIGHT_L], // SPR_WZAP + &lspr[NOLIGHT], // SPR_DUST + &lspr[NOLIGHT], // SPR_FPRT + &lspr[SUPERSPARK_L], // SPR_TFOG + &lspr[NIGHTSLIGHT_L], // SPR_SEED + &lspr[NOLIGHT], // SPR_PRTL + + // Game Indicators + &lspr[NOLIGHT], // SPR_SCOR + &lspr[NOLIGHT], // SPR_DRWN + &lspr[NOLIGHT], // SPR_FLII + &lspr[NOLIGHT], // SPR_LCKN + &lspr[NOLIGHT], // SPR_TTAG + &lspr[NOLIGHT], // SPR_GFLG + &lspr[NOLIGHT], // SPR_FNSF + + &lspr[NOLIGHT], // SPR_CORK + &lspr[NOLIGHT], // SPR_LHRT + + // Ring Weapons + &lspr[RINGLIGHT_L], // SPR_RRNG + &lspr[RINGLIGHT_L], // SPR_RNGB + &lspr[RINGLIGHT_L], // SPR_RNGR + &lspr[RINGLIGHT_L], // SPR_RNGI + &lspr[RINGLIGHT_L], // SPR_RNGA + &lspr[RINGLIGHT_L], // SPR_RNGE + &lspr[RINGLIGHT_L], // SPR_RNGS + &lspr[RINGLIGHT_L], // SPR_RNGG + + &lspr[RINGLIGHT_L], // SPR_PIKB + &lspr[RINGLIGHT_L], // SPR_PIKR + &lspr[RINGLIGHT_L], // SPR_PIKA + &lspr[RINGLIGHT_L], // SPR_PIKE + &lspr[RINGLIGHT_L], // SPR_PIKS + &lspr[RINGLIGHT_L], // SPR_PIKG + + &lspr[RINGLIGHT_L], // SPR_TAUT + &lspr[RINGLIGHT_L], // SPR_TGRE + &lspr[RINGLIGHT_L], // SPR_TSCR + + // Mario-specific stuff + &lspr[NOLIGHT], // SPR_COIN + &lspr[NOLIGHT], // SPR_CPRK + &lspr[NOLIGHT], // SPR_GOOM + &lspr[NOLIGHT], // SPR_BGOM + &lspr[REDBALL_L], // SPR_FFWR + &lspr[SMALLREDBALL_L], // SPR_FBLL + &lspr[NOLIGHT], // SPR_SHLL + &lspr[REDBALL_L], // SPR_PUMA + &lspr[NOLIGHT], // SPR_HAMM + &lspr[NOLIGHT], // SPR_KOOP + &lspr[REDBALL_L], // SPR_BFLM + &lspr[NOLIGHT], // SPR_MAXE + &lspr[NOLIGHT], // SPR_MUS1 + &lspr[NOLIGHT], // SPR_MUS2 + &lspr[NOLIGHT], // SPR_TOAD + + // NiGHTS Stuff + &lspr[SUPERSONIC_L], // SPR_NDRN // NiGHTS drone + &lspr[NOLIGHT], // SPR_NSPK + &lspr[NOLIGHT], // SPR_NBMP + &lspr[NOLIGHT], // SPR_HOOP + &lspr[NOLIGHT], // SPR_HSCR + &lspr[NOLIGHT], // SPR_NPRU + &lspr[NOLIGHT], // SPR_CAPS + &lspr[INVINCIBLE_L], // SPR_IDYA + &lspr[NOLIGHT], // SPR_NTPN + &lspr[NOLIGHT], // SPR_SHLP + + // Secret badniks and hazards, shhhh + &lspr[NOLIGHT], // SPR_PENG + &lspr[NOLIGHT], // SPR_POPH, + &lspr[NOLIGHT], // SPR_HIVE + &lspr[NOLIGHT], // SPR_BUMB, + &lspr[NOLIGHT], // SPR_BBUZ + &lspr[NOLIGHT], // SPR_FMCE, + &lspr[NOLIGHT], // SPR_HMCE, + &lspr[NOLIGHT], // SPR_CACO, + &lspr[BLUEBALL_L], // SPR_BAL2, + &lspr[NOLIGHT], // SPR_SBOB, + &lspr[BLUEBALL_L], // SPR_SBFL, + &lspr[BLUEBALL_L], // SPR_SBSK, + &lspr[NOLIGHT], // SPR_BATT, + + // Debris + &lspr[RINGSPARK_L], // SPR_SPRK + &lspr[NOLIGHT], // SPR_BOM1 + &lspr[SUPERSPARK_L], // SPR_BOM2 + &lspr[SUPERSPARK_L], // SPR_BOM3 + &lspr[NOLIGHT], // SPR_BOM4 + &lspr[REDBALL_L], // SPR_BMNB + + // Crumbly rocks + &lspr[NOLIGHT], // SPR_ROIA + &lspr[NOLIGHT], // SPR_ROIB + &lspr[NOLIGHT], // SPR_ROIC + &lspr[NOLIGHT], // SPR_ROID + &lspr[NOLIGHT], // SPR_ROIE + &lspr[NOLIGHT], // SPR_ROIF + &lspr[NOLIGHT], // SPR_ROIG + &lspr[NOLIGHT], // SPR_ROIH + &lspr[NOLIGHT], // SPR_ROII + &lspr[NOLIGHT], // SPR_ROIJ + &lspr[NOLIGHT], // SPR_ROIK + &lspr[NOLIGHT], // SPR_ROIL + &lspr[NOLIGHT], // SPR_ROIM + &lspr[NOLIGHT], // SPR_ROIN + &lspr[NOLIGHT], // SPR_ROIO + &lspr[NOLIGHT], // SPR_ROIP + + // Level debris + &lspr[NOLIGHT], // SPR_GFZD + &lspr[NOLIGHT], // SPR_BRIC + &lspr[NOLIGHT], // SPR_WDDB + &lspr[NOLIGHT], // SPR_BRIR + &lspr[NOLIGHT], // SPR_BRIB + &lspr[NOLIGHT], // SPR_BRIY + + // Gravity Well Objects + &lspr[NOLIGHT], // SPR_GWLG + &lspr[NOLIGHT], // SPR_GWLR + + // Free slots + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], + &lspr[NOLIGHT], +}; + +#ifdef ALAM_LIGHTING + +//============================================================================= +// PROTOS +//============================================================================= + +static void HWR_SetLight(void); + +// -------------------------------------------------------------------------- +// calcul la projection d'un point sur une droite (determin� par deux +// points) et ensuite calcul la distance (au carr� de ce point au point +// project�sur cette droite +// -------------------------------------------------------------------------- +static float HWR_DistP2D(FOutVector *p1, FOutVector *p2, FVector *p3, FVector *inter) +{ + if (p1->z == p2->z) + { + inter->x = p3->x; + inter->z = p1->z; + } + else if (p1->x == p2->x) + { + inter->x = p1->x; + inter->z = p3->z; + } + else + { + register float local, pente; + // Wat een mooie formula! Hurdler's math;-) + pente = (p1->z-p2->z) / (p1->x-p2->x); + local = p1->z - p1->x*pente; + inter->x = (p3->z - local + p3->x/pente) * (pente/(pente*pente+1)); + inter->z = inter->x*pente + local; + } + + return (p3->x-inter->x)*(p3->x-inter->x) + (p3->z-inter->z)*(p3->z-inter->z); +} + +// check if sphere (radius r) centred in p3 touch the bounding box defined by p1, p2 +static boolean SphereTouchBBox3D(FOutVector *p1, FOutVector *p2, FVector *p3, float r) +{ + float minx = p1->x,maxx = p2->x,miny = p2->y,maxy = p1->y,minz = p2->z,maxz = p1->z; + + if (minx > maxx) + { + minx = maxx; + maxx = p1->x; + } + if (miny > maxy) + { + miny = maxy; + maxy = p2->y; + } + if (minz > maxz) + { + minz = maxz; + maxz = p2->z; + } + + if (minx-r > p3->x) return false; + if (maxx+r < p3->x) return false; + if (miny-r > p3->y) return false; + if (maxy+r < p3->y) return false; + if (minz-r > p3->z) return false; + if (maxz+r < p3->z) return false; + return true; +} + +// Hurdler: The old code was removed by me because I don't think it will be used one day. +// (It's still available on the CVS for educational purpose: Revision 1.8) + +// -------------------------------------------------------------------------- +// calcul du dynamic lighting sur les murs +// lVerts contient les coords du mur sans le mlook (up/down) +// -------------------------------------------------------------------------- +void HWR_WallLighting(FOutVector *wlVerts) +{ + int i, j; + + // dynlights->nb == 0 if cv_gldynamiclighting.value is not set + for (j = 0; j < dynlights->nb; j++) + { + FVector inter; + FSurfaceInfo Surf; + float dist_p2d, d[4], s; + + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + + // check bounding box first + if (SphereTouchBBox3D(&wlVerts[2], &wlVerts[0], &LIGHT_POS(j), DL_RADIUS(j))==false) + continue; + d[0] = wlVerts[2].x - wlVerts[0].x; + d[1] = wlVerts[2].z - wlVerts[0].z; + d[2] = LIGHT_POS(j).x - wlVerts[0].x; + d[3] = LIGHT_POS(j).z - wlVerts[0].z; + // backface cull + if (d[2]*d[1] - d[3]*d[0] < 0) + continue; + // check exact distance + dist_p2d = HWR_DistP2D(&wlVerts[2], &wlVerts[0], &LIGHT_POS(j), &inter); + if (dist_p2d >= DL_SQRRADIUS(j)) + continue; + + d[0] = (float)sqrt((wlVerts[0].x-inter.x)*(wlVerts[0].x-inter.x) + + (wlVerts[0].z-inter.z)*(wlVerts[0].z-inter.z)); + d[1] = (float)sqrt((wlVerts[2].x-inter.x)*(wlVerts[2].x-inter.x) + + (wlVerts[2].z-inter.z)*(wlVerts[2].z-inter.z)); + //dAB = sqrtf((wlVerts[0].x-wlVerts[2].x)*(wlVerts[0].x-wlVerts[2].x)+(wlVerts[0].z-wlVerts[2].z)*(wlVerts[0].z-wlVerts[2].z)); + //if ((d[0] < dAB) && (d[1] < dAB)) // test if the intersection is on the wall + //{ + // d[0] = -d[0]; // if yes, the left distcance must be negative for texcoord + //} + // test if the intersection is on the wall + if ((wlVerts[0].x < inter.x && wlVerts[2].x > inter.x) || + (wlVerts[0].x > inter.x && wlVerts[2].x < inter.x) || + (wlVerts[0].z < inter.z && wlVerts[2].z > inter.z) || + (wlVerts[0].z > inter.z && wlVerts[2].z < inter.z)) + { + d[0] = -d[0]; // if yes, the left distcance must be negative for texcoord + } + d[2] = d[1]; d[3] = d[0]; +#ifdef DL_HIGH_QUALITY + s = 0.5f / DL_RADIUS(j); +#else + s = 0.5f / sqrtf(DL_SQRRADIUS(j)-dist_p2d); +#endif + for (i = 0; i < 4; i++) + { + wlVerts[i].s = (float)(0.5f + d[i]*s); + wlVerts[i].t = (float)(0.5f + (wlVerts[i].y-LIGHT_POS(j).y)*s*1.2f); + } + + HWR_SetLight(); + + Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); +#ifdef DL_HIGH_QUALITY + Surf.PolyColor.s.alpha = (UINT8)((1-dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha); +#endif + // next state is null so fade out with alpha + if (dynlights->mo[j]->state->nextstate == S_NULL) + Surf.PolyColor.s.alpha = (UINT8)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha); + + HWD.pfnDrawPolygon (&Surf, wlVerts, 4, LIGHTMAPFLAGS); + + } // end for (j = 0; j < dynlights->nb; j++) +} + +// -------------------------------------------------------------------------- +// calcul du dynamic lighting sur le sol +// clVerts contient les coords du sol avec le mlook (up/down) +// -------------------------------------------------------------------------- +void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts) +{ + int i, j; + FOutVector p1,p2; + + p1.z = FIXED_TO_FLOAT(hwbbox[BOXTOP ]); + p1.x = FIXED_TO_FLOAT(hwbbox[BOXLEFT ]); + p2.z = FIXED_TO_FLOAT(hwbbox[BOXBOTTOM]); + p2.x = FIXED_TO_FLOAT(hwbbox[BOXRIGHT ]); + p2.y = clVerts[0].y; + p1.y = clVerts[0].y; + + for (j = 0; j < dynlights->nb; j++) + { + FSurfaceInfo Surf; + float dist_p2d, s; + + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + + // BP: The kickass Optimization: check if light touch bounding box + if (SphereTouchBBox3D(&p1, &p2, &dynlights->position[j], DL_RADIUS(j))==false) + continue; + // backface cull + //Hurdler: doesn't work with new TANDL code + if ((clVerts[0].y > atransform.z) // true mean it is a ceiling false is a floor + ^ (LIGHT_POS(j).y < clVerts[0].y)) // true mean light is down plane false light is up plane + continue; + dist_p2d = (clVerts[0].y-LIGHT_POS(j).y); + dist_p2d *= dist_p2d; + // done in SphereTouchBBox3D + //if (dist_p2d >= DL_SQRRADIUS(j)) + // continue; + +#ifdef DL_HIGH_QUALITY + s = 0.5f / DL_RADIUS(j); +#else + s = 0.5f / sqrtf(DL_SQRRADIUS(j)-dist_p2d); +#endif + for (i = 0; i < nrClipVerts; i++) + { + clVerts[i].s = 0.5f + (clVerts[i].x-LIGHT_POS(j).x)*s; + clVerts[i].t = 0.5f + (clVerts[i].z-LIGHT_POS(j).z)*s*1.2f; + } + + HWR_SetLight(); + + Surf.PolyColor.rgba = LONG(dynlights->p_lspr[j]->dynamic_color); +#ifdef DL_HIGH_QUALITY + Surf.PolyColor.s.alpha = (unsigned char)((1 - dist_p2d/DL_SQRRADIUS(j))*Surf.PolyColor.s.alpha); +#endif + // next state is null so fade out with alpha + if ((dynlights->mo[j]->state->nextstate == S_NULL)) + Surf.PolyColor.s.alpha = (unsigned char)(((float)dynlights->mo[j]->tics/(float)dynlights->mo[j]->state->tics)*Surf.PolyColor.s.alpha); + + HWD.pfnDrawPolygon (&Surf, clVerts, nrClipVerts, LIGHTMAPFLAGS); + + } // end for (j = 0; j < dynlights->nb; j++) +} + + +static lumpnum_t coronalumpnum = LUMPERROR; +#ifndef NEWCORONAS +// -------------------------------------------------------------------------- +// coronas lighting +// -------------------------------------------------------------------------- +void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr) +{ + light_t *p_lspr; + + if (coronalumpnum == LUMPERROR) + return; + + //CONS_Debug(DBG_RENDER, "sprite (type): %d (%s)\n", spr->type, sprnames[spr->type]); + p_lspr = t_lspr[spr->mobj->sprite]; + if ((spr->mobj->state>=&states[S_EXPLODE1] && spr->mobj->state<=&states[S_EXPLODE3]) + || (spr->mobj->state>=&states[S_FATSHOTX1] && spr->mobj->state<=&states[S_FATSHOTX3])) + { + p_lspr = &lspr[ROCKETEXP_L]; + } + + if (cv_glcoronas.value && (p_lspr->type & CORONA_SPR)) + { // it's an object which emits light + FOutVector light[4]; + FSurfaceInfo Surf; + float cx = 0.0f, cy = 0.0f, cz = 0.0f; // gravity center + float size; + UINT8 i; + + switch (p_lspr->type) + { + case LIGHT_SPR: + size = p_lspr->corona_radius * ((outVerts[0].z+120.0f)/950.0f); // d'ou vienne ces constante ? + break; + case ROCKET_SPR: + p_lspr->corona_color = (((M_RandomByte()>>1)&0xff)<<24)|0x0040ff; + // don't need a break + case CORONA_SPR: + size = p_lspr->corona_radius * ((outVerts[0].z+60.0f)/100.0f); // d'ou vienne ces constante ? + break; + default: + I_Error("HWR_DoCoronasLighting: unknow light type %d",p_lspr->type); + return; + } + if (size > p_lspr->corona_radius) + size = p_lspr->corona_radius; + size *= FIXED_TO_FLOAT(cv_glcoronasize.value<<1); + + // compute position doing average + for (i = 0; i < 4; i++) + { + cx += outVerts[i].x; + cy += outVerts[i].y; + cz += outVerts[i].z; + } + cx /= 4.0f; cy /= 4.0f; cz /= 4.0f; + + // more realistique corona ! + if (cz >= 255*8+250) + return; + Surf.PolyColor.rgba = p_lspr->corona_color; + if (cz > 250.0f) + Surf.PolyColor.s.alpha = 0xff-((int)cz-250)/8; + else + Surf.PolyColor.s.alpha = 0xff; + + // do not be hide by sprite of the light itself ! + cz = cz - 2.0f; + + // Bp; je comprend pas, ou est la rotation haut/bas ? + // tu ajoute un offset a y mais si la tu la reguarde de haut + // sa devrais pas marcher ... comprend pas :( + // (...) bon je croit que j'ai comprit il est tout pourit le code ? + // car comme l'offset est minime sa ce voit pas ! + light[0].x = cx-size; light[0].z = cz; + light[0].y = cy-size*1.33f+p_lspr->light_yoffset; + light[0].s = 0.0f; light[0].t = 0.0f; + + light[1].x = cx+size; light[1].z = cz; + light[1].y = cy-size*1.33f+p_lspr->light_yoffset; + light[1].s = 1.0f; light[1].t = 0.0f; + + light[2].x = cx+size; light[2].z = cz; + light[2].y = cy+size*1.33f+p_lspr->light_yoffset; + light[2].s = 1.0f; light[2].t = 1.0f; + + light[3].x = cx-size; light[3].z = cz; + light[3].y = cy+size*1.33f+p_lspr->light_yoffset; + light[3].s = 0.0f; light[3].t = 1.0f; + + HWR_GetPic(coronalumpnum); /// \todo use different coronas + + HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_Corona | PF_NoDepthTest); + } +} +#endif + +#ifdef NEWCORONAS +// use the lightlist of the frame to draw the coronas at the top of everythink +void HWR_DrawCoronas(void) +{ + int j; + + if (!cv_glcoronas.value || dynlights->nb <= 0 || coronalumpnum == LUMPERROR) + return; + + HWR_GetPic(coronalumpnum); /// \todo use different coronas + for (j = 0;j < dynlights->nb;j++) + { + FOutVector light[4]; + FSurfaceInfo Surf; + float cx = LIGHT_POS(j).x; + float cy = LIGHT_POS(j).y; + float cz = LIGHT_POS(j).z; // gravity center + float size; + light_t *p_lspr = dynlights->p_lspr[j]; + + // it's an object which emits light + if (!(p_lspr->type & CORONA_SPR)) + continue; + + if (!dynlights->mo[j]) + continue; + if (P_MobjWasRemoved(dynlights->mo[j])) + { + P_SetTarget(&dynlights->mo[j], NULL); + continue; + } + + transform(&cx,&cy,&cz); + + // more realistique corona ! + if (cz >= 255*8+250) + continue; + Surf.PolyColor.rgba = p_lspr->corona_color; + if (cz > 250.0f) + Surf.PolyColor.s.alpha = (UINT8)(0xff-(UINT8)(((int)cz-250)/8)); + else + Surf.PolyColor.s.alpha = 0xff; + + switch (p_lspr->type) + { + case LIGHT_SPR: + size = p_lspr->corona_radius * ((cz+120.0f)/950.0f); // d'ou vienne ces constante ? + break; + case ROCKET_SPR: + Surf.PolyColor.s.alpha = (UINT8)((M_RandomByte()>>1)&0xff); + // don't need a break + case CORONA_SPR: + size = p_lspr->corona_radius * ((cz+60.0f)/100.0f); // d'ou vienne ces constante ? + break; + default: + I_Error("HWR_DoCoronasLighting: unknow light type %d",p_lspr->type); + continue; + } + if (size > p_lspr->corona_radius) + size = p_lspr->corona_radius; + size = (float)(FIXED_TO_FLOAT(cv_glcoronasize.value<<1)*size); + + // put light little forward the sprite so there is no + // z-buffer problem (coplanar polygons) + // BP: use PF_Decal do not help :( + cz = cz - 5.0f; + + light[0].x = cx-size; light[0].z = cz; + light[0].y = cy-size*1.33f; + light[0].s = 0.0f; light[0].t = 0.0f; + + light[1].x = cx+size; light[1].z = cz; + light[1].y = cy-size*1.33f; + light[1].s = 1.0f; light[1].t = 0.0f; + + light[2].x = cx+size; light[2].z = cz; + light[2].y = cy+size*1.33f; + light[2].s = 1.0f; light[2].t = 1.0f; + + light[3].x = cx-size; light[3].z = cz; + light[3].y = cy+size*1.33f; + light[3].s = 0.0f; light[3].t = 1.0f; + + HWD.pfnDrawPolygon (&Surf, light, 4, PF_Modulated | PF_Additive | PF_Clip | PF_NoDepthTest | PF_Corona); + } +} +#endif + +// -------------------------------------------------------------------------- +// Remove all the dynamic lights at eatch frame +// -------------------------------------------------------------------------- +void HWR_ResetLights(void) +{ + while (dynlights->nb) + P_SetTarget(&dynlights->mo[--dynlights->nb], NULL); +} + +// -------------------------------------------------------------------------- +// Change view, thus change lights (splitscreen) +// -------------------------------------------------------------------------- +void HWR_SetLights(int viewnumber) +{ + dynlights = &view_dynlights[viewnumber]; +} + +// -------------------------------------------------------------------------- +// Add a light for dynamic lighting +// The light position is already transformed execpt for mlook +// -------------------------------------------------------------------------- +void HWR_DL_AddLight(gl_vissprite_t *spr, GLPatch_t *patch) +{ + light_t *p_lspr; + + //Hurdler: moved here because it's better;-) + (void)patch; + if (!cv_gldynamiclighting.value) + return; + + if (!spr->mobj) +#ifdef PARANOIA + I_Error("vissprite without mobj !!!"); +#else + return; +#endif + + if (dynlights->nb >= DL_MAX_LIGHT) + return; + + // check if sprite contain dynamic light + p_lspr = t_lspr[spr->mobj->sprite]; + if (!(p_lspr->type & DYNLIGHT_SPR)) + return; + if ((p_lspr->type != LIGHT_SPR) || cv_glstaticlighting.value) + return; + + LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(spr->mobj->x); + LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(spr->mobj->z)+FIXED_TO_FLOAT(spr->mobj->height>>1)+p_lspr->light_yoffset; + LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(spr->mobj->y); + + P_SetTarget(&dynlights->mo[dynlights->nb], spr->mobj); + + dynlights->p_lspr[dynlights->nb] = p_lspr; + + dynlights->nb++; +} + +static GLMipmap_t lightmappatchmipmap; +static GLPatch_t lightmappatch = { .mipmap = &lightmappatchmipmap }; + +void HWR_InitLight(void) +{ + size_t i; + + // precalculate sqr radius + for (i = 0;i < NUMLIGHTS;i++) + lspr[i].dynamic_sqrradius = lspr[i].dynamic_radius*lspr[i].dynamic_radius; + + lightmappatch.mipmap->downloaded = false; + coronalumpnum = W_CheckNumForName("CORONA"); +} + +// -----------------+ +// HWR_SetLight : Download a disc shaped alpha map for rendering fake lights +// -----------------+ +static void HWR_SetLight(void) +{ + int i, j; + + if (!lightmappatch.mipmap->downloaded && !lightmappatch.mipmap->data) + { + + UINT16 *Data = Z_Malloc(129*128*sizeof (UINT16), PU_HWRCACHE, &lightmappatch.mipmap->data); + + for (i = 0; i < 128; i++) + { + for (j = 0; j < 128; j++) + { + int pos = ((i-64)*(i-64))+((j-64)*(j-64)); + if (pos <= 63*63) + Data[i*128+j] = (UINT16)(((UINT8)(255-(4*(float)sqrt((float)pos)))) << 8 | 0xff); + else + Data[i*128+j] = 0; + } + } + lightmappatch.mipmap->format = GL_TEXFMT_ALPHA_INTENSITY_88; + + lightmappatch.width = 128; + lightmappatch.height = 128; + lightmappatch.mipmap->width = 128; + lightmappatch.mipmap->height = 128; + lightmappatch.mipmap->flags = 0; //TF_WRAPXY; // DEBUG: view the overdraw ! + } + HWD.pfnSetTexture(lightmappatch.mipmap); + + // The system-memory data can be purged now. + Z_ChangeTag(lightmappatch.mipmap->data, PU_HWRCACHE_UNLOCKED); +} + +//********************************************************** +// Hurdler: new code for faster static lighting and and T&L +//********************************************************** + +#ifdef STATICLIGHT +// is this really necessary? +static sector_t *lgl_backsector; +static seg_t *lgl_curline; +#endif + +// p1 et p2 c'est le deux bou du seg en float +static inline void HWR_BuildWallLightmaps(FVector *p1, FVector *p2, int lighnum, seg_t *line) +{ + lightmap_t *lp; + + // (...) calcul presit de la projection et de la distance + +// if (dist_p2d >= DL_SQRRADIUS(lightnum)) +// return; + + // (...) attention faire le backfase cull histoir de faire mieux que Q3 ! + + (void)lighnum; + (void)p1; + (void)p2; + lp = malloc(sizeof (*lp)); + lp->next = line->lightmaps; + line->lightmaps = lp; + + // (...) encore des b�calcul bien lourd et on stock tout sa dans la lightmap +} + +#ifdef STATICLIGHT +static void HWR_AddLightMapForLine(int lightnum, seg_t *line) +{ + /* + int x1; + int x2; + angle_t angle1; + angle_t angle2; + angle_t span; + angle_t tspan; + */ + FVector p1,p2; + + lgl_curline = line; + lgl_backsector = line->backsector; + + // Reject empty lines used for triggers and special events. + // Identical floor and ceiling on both sides, + // identical light levels on both sides, + // and no middle texture. +/* + if ( lgl_backsector->ceilingpic == gl_frontsector->ceilingpic + && lgl_backsector->floorpic == gl_frontsector->floorpic + && lgl_backsector->lightlevel == gl_frontsector->lightlevel + && lgl_curline->sidedef->midtexture == 0) + { + return; + } +*/ + + p1.y = FIXED_TO_FLOAT(lgl_curline->v1->y); + p1.x = FIXED_TO_FLOAT(lgl_curline->v1->x); + p2.y = FIXED_TO_FLOAT(lgl_curline->v2->y); + p2.x = FIXED_TO_FLOAT(lgl_curline->v2->x); + + // check bbox of the seg +// if (CircleTouchBBox(&p1, &p2, &LIGHT_POS(lightnum), DL_RADIUS(lightnum))==false) +// return; + + HWR_BuildWallLightmaps(&p1, &p2, lightnum, line); +} + +/// \todo see what HWR_AddLine does +static void HWR_CheckSubsector(size_t num, fixed_t *bbox) +{ + int count; + seg_t *line; + subsector_t *sub; + FVector p1,p2; + int lightnum; + + p1.y = FIXED_TO_FLOAT(bbox[BOXTOP ]); + p1.x = FIXED_TO_FLOAT(bbox[BOXLEFT ]); + p2.y = FIXED_TO_FLOAT(bbox[BOXBOTTOM]); + p2.x = FIXED_TO_FLOAT(bbox[BOXRIGHT ]); + + + if (num < numsubsectors) + { + sub = &subsectors[num]; // subsector + for (lightnum = 0; lightnum < dynlights->nb; lightnum++) + { +// if (CircleTouchBBox(&p1, &p2, &LIGHT_POS(lightnum), DL_RADIUS(lightnum))==false) +// continue; + + if (!dynlights->mo[lightnum]) + continue; + if (P_MobjWasRemoved(dynlights->mo[lightnum])) + { + P_SetTarget(&dynlights->mo[lightnum], NULL); + continue; + } + + count = sub->numlines; // how many linedefs + line = &segs[sub->firstline]; // first line seg + while (count--) + { + HWR_AddLightMapForLine (lightnum, line); // compute lightmap + line++; + } + } + } +} + + +// -------------------------------------------------------------------------- +// Hurdler: this adds lights by mobj. +// -------------------------------------------------------------------------- +static void HWR_AddMobjLights(mobj_t *thing) +{ + if (dynlights->nb >= DL_MAX_LIGHT) + return; + if (!(t_lspr[thing->sprite]->type & CORONA_SPR)) + return; + + LIGHT_POS(dynlights->nb).x = FIXED_TO_FLOAT(thing->x); + LIGHT_POS(dynlights->nb).y = FIXED_TO_FLOAT(thing->z) + t_lspr[thing->sprite]->light_yoffset; + LIGHT_POS(dynlights->nb).z = FIXED_TO_FLOAT(thing->y); + + P_SetTarget(&dynlights->mo[dynlights->nb], thing); + + dynlights->p_lspr[dynlights->nb] = t_lspr[thing->sprite]; + + dynlights->nb++; +} + +//Hurdler: The goal of this function is to walk through all the bsp starting +// on the top. +// We need to do that to know all the lights in the map and all the walls +static void HWR_ComputeLightMapsInBSPNode(int bspnum, fixed_t *bbox) +{ + if (bspnum & NF_SUBSECTOR) // Found a subsector? + { + if (bspnum == -1) + HWR_CheckSubsector(0, bbox); // probably unecessary: see boris' comment in hw_bsp + else + HWR_CheckSubsector(bspnum&(~NF_SUBSECTOR), bbox); + return; + } + HWR_ComputeLightMapsInBSPNode(nodes[bspnum].children[0], nodes[bspnum].bbox[0]); + HWR_ComputeLightMapsInBSPNode(nodes[bspnum].children[1], nodes[bspnum].bbox[1]); +} + +static void HWR_SearchLightsInMobjs(void) +{ + thinker_t * th; + //mobj_t * mobj; + + // search in the list of thinkers + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) + HWR_AddMobjLights((mobj_t *)th); +} +#endif + +// +// HWR_CreateStaticLightmaps() +// +void HWR_CreateStaticLightmaps(int bspnum) +{ +#ifdef STATICLIGHT + CONS_Debug(DBG_RENDER, "HWR_CreateStaticLightmaps\n"); + + HWR_ResetLights(); + + // First: Searching for lights + // BP: if i was you, I will make it in create mobj since mobj can be create + // at runtime now with fragle scipt + HWR_SearchLightsInMobjs(); + CONS_Debug(DBG_RENDER, "%d lights found\n", dynlights->nb); + + // Second: Build all lightmap for walls covered by lights + validcount++; // to be sure + HWR_ComputeLightMapsInBSPNode(bspnum, NULL); +#else + (void)bspnum; +#endif +} + +/** + \todo + + - Les coronas ne sont pas g�er avec le nouveau systeme, seul le dynamic lighting l'est + - calculer l'offset des coronas au chargement du level et non faire la moyenne + au moment de l'afficher + BP: euh non en fait il faux encoder la position de la light dans le sprite + car c'est pas focement au mileux de plus il peut en y avoir plusieur (chandelier) + - changer la comparaison pour l'affichage des coronas (+ un epsilon) + BP: non non j'ai trouver mieux :) : lord du AddSprite tu rajoute aussi la coronas + dans la sprite list ! avec un z de epsilon (attention au ZCLIP_PLANE) et donc on + l'affiche en dernier histoir qu'il puisse etre cacher par d'autre sprite :) + Bon fait metre pas mal de code special dans hwr_project sprite mais sa vaux le + coup + - gerer dynamic et static : retenir le nombre de lightstatic et clearer toute les + light > lightstatic (les dynamique) et les lightmap correspondant dans les segs + puit refaire une passe avec le code si dessus mais rien que pour les dynamiques + (tres petite modification) + - finalement virer le hack splitscreen, il n'est plus necessaire ! +*/ +#endif #endif // HWRENDER diff --git a/src/hardware/hw_light.h b/src/hardware/hw_light.h index fbc1d1f26..fed7db47f 100644 --- a/src/hardware/hw_light.h +++ b/src/hardware/hw_light.h @@ -1,14 +1,13 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_light.h /// \brief Dynamic lighting & coronas add on by Hurdler #ifndef _HW_LIGHTS_ @@ -17,4 +16,79 @@ #include "hw_glob.h" #include "hw_defs.h" +#define NUMLIGHTFREESLOTS 32 // Free light slots (for SOCs) + +#ifdef ALAM_LIGHTING +#define NEWCORONAS + +#define DL_MAX_LIGHT 256 // maximum number of lights (extra lights are ignored) + +void HWR_InitLight(void); +void HWR_DL_AddLight(gl_vissprite_t *spr, GLPatch_t *patch); +void HWR_PlaneLighting(FOutVector *clVerts, int nrClipVerts); +void HWR_WallLighting(FOutVector *wlVerts); +void HWR_ResetLights(void); +void HWR_SetLights(int viewnumber); + +#ifdef NEWCORONAS +void HWR_DrawCoronas(void); +#else +void HWR_DoCoronasLighting(FOutVector *outVerts, gl_vissprite_t *spr); +#endif + +typedef struct +{ + int nb; + light_t *p_lspr[DL_MAX_LIGHT]; + FVector position[DL_MAX_LIGHT]; // actually maximum DL_MAX_LIGHT lights + mobj_t *mo[DL_MAX_LIGHT]; +} dynlights_t; + +#endif + +typedef enum +{ + NOLIGHT = 0, + RINGSPARK_L, + SUPERSONIC_L, // Cool. =) + SUPERSPARK_L, + INVINCIBLE_L, + GREENSHIELD_L, + BLUESHIELD_L, + YELLOWSHIELD_L, + REDSHIELD_L, + BLACKSHIELD_L, + WHITESHIELD_L, + SMALLREDBALL_L, + RINGLIGHT_L, + GREENSMALL_L, + REDSMALL_L, + GREENSHINE_L, + ORANGESHINE_L, + PINKSHINE_L, + BLUESHINE_L, + REDSHINE_L, + LBLUESHINE_L, + GREYSHINE_L, + REDBALL_L, + GREENBALL_L, + BLUEBALL_L, + NIGHTSLIGHT_L, + JETLIGHT_L, + GOOPLIGHT_L, + STREETLIGHT_L, + + // free slots for SOCs at run-time -------------------- + FREESLOT0_L, + // + // ... 32 free lights here ... + // + LASTFREESLOT_L = (FREESLOT0_L+NUMLIGHTFREESLOTS-1), + // end of freeslots --------------------------------------------- + + NUMLIGHTS +} lightspritenum_t; + +extern light_t lspr[NUMLIGHTS]; +extern light_t *t_lspr[NUMSPRITES]; #endif diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index 47f1b4e49..bc7a673b7 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -1,14 +1,13 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_main.c /// \brief hardware renderer, using the standard HardWareRender driver DLL for SRB2 #include @@ -16,20 +15,18 @@ #include "../doomstat.h" #ifdef HWRENDER -#include "hw_main.h" #include "hw_glob.h" -#include "hw_drv.h" -#include "hw_md2.h" -#include "hw_clip.h" #include "hw_light.h" +#include "hw_drv.h" +#include "hw_batching.h" #include "../i_video.h" // for rendermode == render_glide #include "../v_video.h" #include "../p_local.h" #include "../p_setup.h" #include "../r_local.h" -#include "../r_bsp.h" // R_NoEncore -#include "../r_main.h" // cv_fov +#include "../r_picformats.h" +#include "../r_bsp.h" #include "../d_clisrv.h" #include "../w_wad.h" #include "../z_zone.h" @@ -38,15 +35,18 @@ #include "../st_stuff.h" #include "../i_system.h" #include "../m_cheat.h" +#include "../f_finale.h" #include "../r_things.h" // R_GetShadowZ - -#ifdef ESLOPE #include "../p_slopes.h" +#include "hw_md2.h" + +#ifdef NEWCLIP +#include "hw_clip.h" #endif -#include // qsort - -#define ABS(x) ((x) < 0 ? -(x) : (x)) +#define R_FAKEFLOORS +#define HWPRECIP +//#define POLYSKY // ========================================================================== // the hardware driver object @@ -54,87 +54,119 @@ struct hwdriver_s hwdriver; // ========================================================================== -// Commands and console variables +// PROTOS // ========================================================================== -static void CV_filtermode_ONChange(void); -static void CV_anisotropic_ONChange(void); -static CV_PossibleValue_t grfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, - {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, - {HWD_SET_TEXTUREFILTER_MIXED1, "Linear_Nearest"}, - {HWD_SET_TEXTUREFILTER_MIXED2, "Nearest_Linear"}, - {HWD_SET_TEXTUREFILTER_MIXED3, "Nearest_Mipmap"}, - {0, NULL}}; -CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}}; +static void HWR_AddSprites(sector_t *sec); +static void HWR_ProjectSprite(mobj_t *thing); +#ifdef HWPRECIP +static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); +#endif -consvar_t cv_grrounddown = {"gr_rounddown", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); +void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, + INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); - -consvar_t cv_grfiltermode = {"gr_filtermode", "Nearest", CV_CALL|CV_SAVE, grfiltermode_cons_t, - CV_filtermode_ONChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_granisotropicmode = {"gr_anisotropicmode", "1", CV_CALL|CV_SAVE, granisotropicmode_cons_t, - CV_anisotropic_ONChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grcorrecttricks = {"gr_correcttricks", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grsolvetjoin = {"gr_solvetjoin", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_grbatching = {"gr_batching", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - -static void CV_filtermode_ONChange(void) -{ - HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_grfiltermode.value); -} - -static void CV_anisotropic_ONChange(void) -{ - HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_granisotropicmode.value); -} +boolean drawsky = true; // ========================================================================== -// Globals +// VIEW GLOBALS // ========================================================================== +// Fineangles in the SCREENWIDTH wide window. +#define FIELDOFVIEW ANGLE_90 +#define ABS(x) ((x) < 0 ? -(x) : (x)) + +static angle_t gl_clipangle; + +// The viewangletox[viewangle + FINEANGLES/4] lookup +// maps the visible view angles to screen X coordinates, +// flattening the arc to a flat projection plane. +// There will be many angles mapped to the same X. +static INT32 gl_viewangletox[FINEANGLES/2]; + +// The xtoviewangleangle[] table maps a screen pixel +// to the lowest viewangle that maps back to x ranges +// from clipangle to -clipangle. +static angle_t gl_xtoviewangle[MAXVIDWIDTH+1]; + +// ========================================================================== +// GLOBALS +// ========================================================================== + +// uncomment to remove the plane rendering +#define DOPLANES +//#define DOWALLS + +// test of drawing sky by polygons like in software with visplane, unfortunately +// this doesn't work since we must have z for pixel and z for texture (not like now with z = oow) +//#define POLYSKY + +// test change fov when looking up/down but bsp projection messup :( +//#define NOCRAPPYMLOOK // base values set at SetViewSize -static float gr_basecentery; -static float gr_basecenterx; +static float gl_basecentery; +static float gl_basecenterx; -float gr_baseviewwindowy, gr_basewindowcentery; -float gr_baseviewwindowx, gr_basewindowcenterx; -float gr_viewwidth, gr_viewheight; // viewport clipping boundaries (screen coords) +float gl_baseviewwindowy, gl_basewindowcentery; +float gl_baseviewwindowx, gl_basewindowcenterx; +float gl_viewwidth, gl_viewheight; // viewport clipping boundaries (screen coords) +float gl_viewwindowx; -static float gr_centerx; -static float gr_viewwindowx; -static float gr_windowcenterx; // center of view window, for projection +static float gl_centerx, gl_centery; +static float gl_viewwindowy; // top left corner of view window +static float gl_windowcenterx; // center of view window, for projection +static float gl_windowcentery; -static float gr_centery; -static float gr_viewwindowy; // top left corner of view window -static float gr_windowcentery; +static float gl_pspritexscale, gl_pspriteyscale; -static float gr_pspritexscale, gr_pspriteyscale; +static seg_t *gl_curline; +static side_t *gl_sidedef; +static line_t *gl_linedef; +static sector_t *gl_frontsector; +static sector_t *gl_backsector; - -static seg_t *gr_curline; -static side_t *gr_sidedef; -static line_t *gr_linedef; -static sector_t *gr_frontsector; -static sector_t *gr_backsector; - -boolean gr_shadersavailable = true; - -// ========================================================================== -// View position -// ========================================================================== +// -------------------------------------------------------------------------- +// STUFF FOR THE PROJECTION CODE +// -------------------------------------------------------------------------- FTransform atransform; +// duplicates of the main code, set after R_SetupFrame() passed them into sharedstruct, +// copied here for local use +static fixed_t dup_viewx, dup_viewy, dup_viewz; +static angle_t dup_viewangle; -// Float variants of viewx, viewy, viewz, etc. -static float gr_viewx, gr_viewy, gr_viewz; -static float gr_viewsin, gr_viewcos; +static float gl_viewx, gl_viewy, gl_viewz; +static float gl_viewsin, gl_viewcos; -static angle_t gr_aimingangle; -static float gr_viewludsin, gr_viewludcos; +// Maybe not necessary with the new T&L code (needs to be checked!) +static float gl_viewludsin, gl_viewludcos; // look up down kik test +static float gl_fovlud; + +static angle_t gl_aimingangle; +static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox); + +// Render stats +int ps_hw_skyboxtime = 0; +int ps_hw_nodesorttime = 0; +int ps_hw_nodedrawtime = 0; +int ps_hw_spritesorttime = 0; +int ps_hw_spritedrawtime = 0; + +// Render stats for batching +int ps_hw_numpolys = 0; +int ps_hw_numverts = 0; +int ps_hw_numcalls = 0; +int ps_hw_numshaders = 0; +int ps_hw_numtextures = 0; +int ps_hw_numpolyflags = 0; +int ps_hw_numcolors = 0; +int ps_hw_batchsorttime = 0; +int ps_hw_batchdrawtime = 0; + +boolean gl_shadersavailable = true; -static INT32 drawcount = 0; // ========================================================================== // Lighting @@ -149,7 +181,7 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col fade_color.rgba = (colormap != NULL) ? (UINT32)colormap->fadergba : GL_DEFAULTFOG; // Crappy backup coloring if you can't do shaders - if (!(cv_grshaders.value && gr_shadersavailable)) + if (!cv_glshaders.value || !gl_shadersavailable) { // be careful, this may get negative for high lightlevel values. float tint_alpha, fade_alpha; @@ -185,6 +217,9 @@ void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *col poly_color.s.blue = (UINT8)blue; } + // Clamp the light level, since it can sometimes go out of the 0-255 range from animations + light_level = min(max(light_level, 0), 255); + Surface->PolyColor.rgba = poly_color.rgba; Surface->TintColor.rgba = tint_color.rgba; Surface->FadeColor.rgba = fade_color.rgba; @@ -200,7 +235,11 @@ UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if realcolor.rgba = (colormap != NULL) ? colormap->rgba : GL_DEFAULTMIX; - if (!(cv_grshaders.value && gr_shadersavailable)) + if (cv_glshaders.value && gl_shadersavailable) + { + surfcolor.s.alpha = (255 - light); + } + else { light = light - (255 - light); @@ -215,47 +254,103 @@ UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if // at 255 brightness, alpha is between 0 and 127, at 0 brightness alpha will always be 255 surfcolor.s.alpha = (alpha*light) / (2*256) + 255-light; } - else - { - surfcolor.s.alpha = (255 - light); - } return surfcolor.s.alpha; } -// Lightnum = current light -// line = the seg to get the light offset from -static FUINT HWR_CalcWallLight(seg_t *line, FUINT lightnum) +static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y) { INT16 finallight = lightnum; - fixed_t extralight = 0; - - if (cv_grfakecontrast.value == 1) // Smooth setting - extralight += line->hwLightOffset; - else - extralight += line->lightOffset * 8; - - if (extralight != 0) + if (cv_glfakecontrast.value != 0) { - finallight += extralight; + const UINT8 contrast = 8; + fixed_t extralight = 0; - if (finallight < 0) - finallight = 0; - if (finallight > 255) - finallight = 255; + if (cv_glfakecontrast.value == 2) // Smooth setting + { + extralight = (-(contrast<> FRACBITS; + } + else + { + if (v1y == v2y) + extralight = -contrast; + else if (v1x == v2x) + extralight = contrast; + } + + if (extralight != 0) + { + finallight += extralight; + + if (finallight < 0) + finallight = 0; + if (finallight > 255) + finallight = 255; + } + } + + return (FUINT)finallight; +} + +static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta) +{ + INT16 finallight = lightnum; + + if (cv_glfakecontrast.value != 0 && cv_glslopecontrast.value != 0) + { + const UINT8 contrast = 8; + fixed_t extralight = 0; + + if (cv_glfakecontrast.value == 2) // Smooth setting + { + fixed_t dirmul = abs(FixedDiv(AngleFixed(dir) - (180<> FRACBITS; + } + else + { + dir = ((dir + ANGLE_45) / ANGLE_90) * ANGLE_90; + + if (dir == ANGLE_180) + extralight = -contrast; + else if (dir == 0) + extralight = contrast; + + if (delta >= FRACUNIT/2) + extralight *= 2; + } + + if (extralight != 0) + { + finallight += extralight; + + if (finallight < 0) + finallight = 0; + if (finallight > 255) + finallight = 255; + } } return (FUINT)finallight; } // ========================================================================== -// Floor and ceiling generation from subsectors +// FLOOR/CEILING GENERATION FROM SUBSECTORS // ========================================================================== -// HWR_RenderPlane -// Render a floor or ceiling convex polygon -void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) +#ifdef DOPLANES + +// -----------------+ +// HWR_RenderPlane : Render a floor or ceiling convex polygon +// -----------------+ +static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) { polyvertex_t * pv; float height; //constant y for all points on the convex flat polygon @@ -263,25 +358,24 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei INT32 nrPlaneVerts; //verts original define of convex flat polygon INT32 i; float flatxref,flatyref; - float fflatsize; - INT32 flatflag; - size_t len; + float fflatwidth = 64.0f, fflatheight = 64.0f; + INT32 flatflag = 63; + boolean texflat = false; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; fixed_t tempxsow, tempytow; -#ifdef ESLOPE pslope_t *slope = NULL; -#endif static FOutVector *planeVerts = NULL; static UINT16 numAllocedPlaneVerts = 0; + int shader; + // no convex poly were generated for this subsector if (!xsub->planepoly) return; -#ifdef ESLOPE // Get the slope pointer to simplify future code if (FOFsector) { @@ -292,16 +386,15 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei } else { - if (gr_frontsector->f_slope && !isceiling) - slope = gr_frontsector->f_slope; - else if (gr_frontsector->c_slope && isceiling) - slope = gr_frontsector->c_slope; + if (gl_frontsector->f_slope && !isceiling) + slope = gl_frontsector->f_slope; + else if (gl_frontsector->c_slope && isceiling) + slope = gl_frontsector->c_slope; } // Set fixedheight to the slope's height from our viewpoint, if we have a slope if (slope) - fixedheight = P_GetZAt(slope, viewx, viewy); -#endif + fixedheight = P_GetSlopeZAt(slope, viewx, viewy); height = FIXED_TO_FLOAT(fixedheight); @@ -311,12 +404,6 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size - { - CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, UINT16_MAX); - return; - } - // Allocate plane-vertex buffer if we need to if (!planeVerts || nrPlaneVerts > numAllocedPlaneVerts) { @@ -325,75 +412,89 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts); } - len = W_LumpLength(lumpnum); - - switch (len) + // set texture for polygon + if (levelflat != NULL) { - case 4194304: // 2048x2048 lump - fflatsize = 2048.0f; - flatflag = 2047; - break; - case 1048576: // 1024x1024 lump - fflatsize = 1024.0f; - flatflag = 1023; - break; - case 262144:// 512x512 lump - fflatsize = 512.0f; - flatflag = 511; - break; - case 65536: // 256x256 lump - fflatsize = 256.0f; - flatflag = 255; - break; - case 16384: // 128x128 lump - fflatsize = 128.0f; - flatflag = 127; - break; - case 1024: // 32x32 lump - fflatsize = 32.0f; - flatflag = 31; - break; - default: // 64x64 lump - fflatsize = 64.0f; - flatflag = 63; - break; + if (levelflat->type == LEVELFLAT_FLAT) + { + size_t len = W_LumpLength(levelflat->u.flat.lumpnum); + switch (len) + { + case 4194304: // 2048x2048 lump + fflatwidth = fflatheight = 2048.0f; + break; + case 1048576: // 1024x1024 lump + fflatwidth = fflatheight = 1024.0f; + break; + case 262144:// 512x512 lump + fflatwidth = fflatheight = 512.0f; + break; + case 65536: // 256x256 lump + fflatwidth = fflatheight = 256.0f; + break; + case 16384: // 128x128 lump + fflatwidth = fflatheight = 128.0f; + break; + case 1024: // 32x32 lump + fflatwidth = fflatheight = 32.0f; + break; + default: // 64x64 lump + fflatwidth = fflatheight = 64.0f; + break; + } + flatflag = ((INT32)fflatwidth)-1; + } + else + { + if (levelflat->type == LEVELFLAT_TEXTURE) + { + fflatwidth = textures[levelflat->u.texture.num]->width; + fflatheight = textures[levelflat->u.texture.num]->height; + } + else if (levelflat->type == LEVELFLAT_PATCH || levelflat->type == LEVELFLAT_PNG) + { + fflatwidth = levelflat->width; + fflatheight = levelflat->height; + } + texflat = true; + } } + else // set no texture + HWR_SetCurrentTexture(NULL); // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatsize); - flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatsize); + flatxref = (float)(((fixed_t)pv->x & (~flatflag)) / fflatwidth); + flatyref = (float)(((fixed_t)pv->y & (~flatflag)) / fflatheight); // transform - v3d = planeVerts; - if (FOFsector != NULL) { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; angle = FOFsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; angle = FOFsector->ceilingpic_angle; } } - else if (gr_frontsector) + else if (gl_frontsector) { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; - angle = gr_frontsector->floorpic_angle; + scrollx = FIXED_TO_FLOAT(gl_frontsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gl_frontsector->floor_yoffs)/fflatheight; + angle = gl_frontsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; - angle = gr_frontsector->ceilingpic_angle; + scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight; + angle = gl_frontsector->ceilingpic_angle; } } @@ -401,7 +502,7 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei if (angle) // Only needs to be done if there's an altered angle { - angle = InvAngle(angle)>>ANGLETOFINESHIFT; + angle = (InvAngle(angle))>>ANGLETOFINESHIFT; // This needs to be done so that it scrolls in a different direction after rotation like software /*tempxsow = FLOAT_TO_FIXED(scrollx); @@ -417,44 +518,48 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); } +#define SETUP3DVERT(vert, vx, vy) {\ + /* Hurdler: add scrolling texture on floor/ceiling */\ + if (texflat)\ + {\ + vert->s = (float)((vx) / fflatwidth) + scrollx;\ + vert->t = -(float)((vy) / fflatheight) + scrolly;\ + }\ + else\ + {\ + vert->s = (float)(((vx) / fflatwidth) - flatxref + scrollx);\ + vert->t = (float)(flatyref - ((vy) / fflatheight) + scrolly);\ + }\ +\ + /* Need to rotate before translate */\ + if (angle) /* Only needs to be done if there's an altered angle */\ + {\ + tempxsow = FLOAT_TO_FIXED(vert->s);\ + tempytow = FLOAT_TO_FIXED(vert->t);\ + vert->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle))));\ + vert->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle))));\ + }\ +\ + vert->x = (vx);\ + vert->y = height;\ + vert->z = (vy);\ +\ + if (slope)\ + {\ + fixedheight = P_GetSlopeZAt(slope, FLOAT_TO_FIXED((vx)), FLOAT_TO_FIXED((vy)));\ + vert->y = FIXED_TO_FLOAT(fixedheight);\ + }\ +} - for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) - { - // Hurdler: add scrolling texture on floor/ceiling - v3d->s = (float)((pv->x / fflatsize) - flatxref + scrollx); - v3d->t = (float)(flatyref - (pv->y / fflatsize) + scrolly); + for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++) + SETUP3DVERT(v3d, pv->x, pv->y); - //v3d->s = (float)(pv->x / fflatsize); - //v3d->t = (float)(pv->y / fflatsize); - - // Need to rotate before translate - if (angle) // Only needs to be done if there's an altered angle - { - tempxsow = FLOAT_TO_FIXED(v3d->s); - tempytow = FLOAT_TO_FIXED(v3d->t); - v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - v3d->t = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); - } - - //v3d->s = (float)(v3d->s - flatxref + scrollx); - //v3d->t = (float)(flatyref - v3d->t + scrolly); - - v3d->x = pv->x; - v3d->y = height; - v3d->z = pv->y; - -#ifdef ESLOPE - if (slope) - { - fixedheight = P_GetZAt(slope, FLOAT_TO_FIXED(pv->x), FLOAT_TO_FIXED(pv->y)); - v3d->y = FIXED_TO_FLOAT(fixedheight); - } -#endif - } + if (slope) + lightlevel = HWR_CalcSlopeLight(lightlevel, R_PointToAngle2(0, 0, slope->normal.x, slope->normal.y), abs(slope->zdelta)); HWR_Lighting(&Surf, lightlevel, planecolormap); - if (PolyFlags & (PF_Translucent|PF_Fog)) + if (PolyFlags & (PF_Translucent|PF_Additive|PF_Substractive|PF_Fog)) { Surf.PolyColor.s.alpha = (UINT8)alpha; PolyFlags |= PF_Modulated; @@ -463,15 +568,147 @@ void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedhei PolyFlags |= PF_Masked|PF_Modulated; if (PolyFlags & PF_Fog) - HWD.pfnSetShader(6); // fog shader + shader = SHADER_FOG; // fog shader else if (PolyFlags & PF_Ripple) - HWD.pfnSetShader(5); // water shader + shader = SHADER_WATER; // water shader else - HWD.pfnSetShader(1); // floor shader + shader = SHADER_FLOOR; // floor shader - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, PolyFlags, shader, false); + + if (subsector) + { + // Horizon lines + FOutVector horizonpts[6]; + float dist, vx, vy; + float x1, y1, xd, yd; + UINT8 numplanes, j; + vertex_t v; // For determining the closest distance from the line to the camera, to split render planes for minimum distortion; + + const float renderdist = 27000.0f; // How far out to properly render the plane + const float farrenderdist = 32768.0f; // From here, raise plane to horizon level to fill in the line with some texture distortion + + seg_t *line = &segs[subsector->firstline]; + + for (i = 0; i < subsector->numlines; i++, line++) + { + if (!line->glseg && line->linedef->special == HORIZONSPECIAL && R_PointOnSegSide(dup_viewx, dup_viewy, line) == 0) + { + P_ClosestPointOnLine(viewx, viewy, line->linedef, &v); + dist = FIXED_TO_FLOAT(R_PointToDist(v.x, v.y)); + + x1 = ((polyvertex_t *)line->pv1)->x; + y1 = ((polyvertex_t *)line->pv1)->y; + xd = ((polyvertex_t *)line->pv2)->x - x1; + yd = ((polyvertex_t *)line->pv2)->y - y1; + + // Based on the seg length and the distance from the line, split horizon into multiple poly sets to reduce distortion + dist = sqrtf((xd*xd) + (yd*yd)) / dist / 16.0f; + if (dist > 100.0f) + numplanes = 100; + else + numplanes = (UINT8)dist + 1; + + for (j = 0; j < numplanes; j++) + { + // Left side + vx = x1 + xd * j / numplanes; + vy = y1 + yd * j / numplanes; + SETUP3DVERT((&horizonpts[1]), vx, vy); + + dist = sqrtf(powf(vx - gl_viewx, 2) + powf(vy - gl_viewy, 2)); + vx = (vx - gl_viewx) * renderdist / dist + gl_viewx; + vy = (vy - gl_viewy) * renderdist / dist + gl_viewy; + SETUP3DVERT((&horizonpts[0]), vx, vy); + + // Right side + vx = x1 + xd * (j+1) / numplanes; + vy = y1 + yd * (j+1) / numplanes; + SETUP3DVERT((&horizonpts[2]), vx, vy); + + dist = sqrtf(powf(vx - gl_viewx, 2) + powf(vy - gl_viewy, 2)); + vx = (vx - gl_viewx) * renderdist / dist + gl_viewx; + vy = (vy - gl_viewy) * renderdist / dist + gl_viewy; + SETUP3DVERT((&horizonpts[3]), vx, vy); + + // Horizon fills + vx = (horizonpts[0].x - gl_viewx) * farrenderdist / renderdist + gl_viewx; + vy = (horizonpts[0].z - gl_viewy) * farrenderdist / renderdist + gl_viewy; + SETUP3DVERT((&horizonpts[5]), vx, vy); + horizonpts[5].y = gl_viewz; + + vx = (horizonpts[3].x - gl_viewx) * farrenderdist / renderdist + gl_viewx; + vy = (horizonpts[3].z - gl_viewy) * farrenderdist / renderdist + gl_viewy; + SETUP3DVERT((&horizonpts[4]), vx, vy); + horizonpts[4].y = gl_viewz; + + // Draw + HWR_ProcessPolygon(&Surf, horizonpts, 6, PolyFlags, shader, true); + } + } + } + } + +#ifdef ALAM_LIGHTING + // add here code for dynamic lighting on planes + HWR_PlaneLighting(planeVerts, nrPlaneVerts); +#endif } +#ifdef POLYSKY +// this don't draw anything it only update the z-buffer so there isn't problem with +// wall/things upper that sky (map12) +static void HWR_RenderSkyPlane(extrasubsector_t *xsub, fixed_t fixedheight) +{ + polyvertex_t *pv; + float height; //constant y for all points on the convex flat polygon + FOutVector *v3d; + INT32 nrPlaneVerts; //verts original define of convex flat polygon + INT32 i; + + // no convex poly were generated for this subsector + if (!xsub->planepoly) + return; + + height = FIXED_TO_FLOAT(fixedheight); + + pv = xsub->planepoly->pts; + nrPlaneVerts = xsub->planepoly->numpts; + + if (nrPlaneVerts < 3) // not even a triangle? + return; + + if (nrPlaneVerts > MAXPLANEVERTICES) // FIXME: exceeds plVerts size + { + CONS_Debug(DBG_RENDER, "polygon size of %d exceeds max value of %d vertices\n", nrPlaneVerts, MAXPLANEVERTICES); + return; + } + + // transform + v3d = planeVerts; + for (i = 0; i < nrPlaneVerts; i++,v3d++,pv++) + { + v3d->s = 0.0f; + v3d->t = 0.0f; + v3d->x = pv->x; + v3d->y = height; + v3d->z = pv->y; + } + + HWD.pfnDrawPolygon(NULL, planeVerts, nrPlaneVerts, + PF_Clip|PF_Invisible|PF_NoTexture|PF_Occlude); +} +#endif //polysky + +#endif //doplanes + +/* + wallVerts order is : + 3--2 + | /| + |/ | + 0--1 +*/ #ifdef WALLSPLATS static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) { @@ -484,13 +721,13 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) M_ClearBox(segbbox); M_AddToBox(segbbox, - FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x), - FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y)); + FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->x), + FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->y)); M_AddToBox(segbbox, - FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x), - FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y)); + FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->x), + FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->y)); - splat = (wallsplat_t *)gr_curline->linedef->splats; + splat = (wallsplat_t *)gl_curline->linedef->splats; for (; splat; splat = splat->next) { //BP: don't draw splat extern to this seg @@ -498,7 +735,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) if (!M_PointInBox(segbbox,splat->v1.x,splat->v1.y) && !M_PointInBox(segbbox,splat->v2.x,splat->v2.y)) continue; - gpatch = W_CachePatchNum(splat->patch, PU_CACHE); + gpatch = W_CachePatchNum(splat->patch, PU_PATCH); HWR_GetPatch(gpatch); wallVerts[0].x = wallVerts[3].x = FIXED_TO_FLOAT(splat->v1.x); @@ -532,7 +769,7 @@ static void HWR_DrawSegsSplats(FSurfaceInfo * pSurf) break; } - HWD.pfnSetShader(2); // wall shader + HWD.pfnSetShader(SHADER_WALL); // wall shader HWD.pfnDrawPolygon(&pSurf, wallVerts, 4, i|PF_Modulated|PF_Decal); } } @@ -542,6 +779,7 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) { switch (transtablenum) { + case 0 : pSurf->PolyColor.s.alpha = 0x00;return PF_Masked; case tr_trans10 : pSurf->PolyColor.s.alpha = 0xe6;return PF_Translucent; case tr_trans20 : pSurf->PolyColor.s.alpha = 0xcc;return PF_Translucent; case tr_trans30 : pSurf->PolyColor.s.alpha = 0xb3;return PF_Translucent; @@ -551,10 +789,14 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) case tr_trans70 : pSurf->PolyColor.s.alpha = 0x4c;return PF_Translucent; case tr_trans80 : pSurf->PolyColor.s.alpha = 0x33;return PF_Translucent; case tr_trans90 : pSurf->PolyColor.s.alpha = 0x19;return PF_Translucent; + case tr_transadd : pSurf->PolyColor.s.alpha = 0xFF;return PF_Additive; + case tr_transsub : pSurf->PolyColor.s.alpha = 0xFF;return PF_Substractive; } return PF_Translucent; } +static void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); + // ========================================================================== // Wall generation from subsector segs // ========================================================================== @@ -562,23 +804,61 @@ FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf) // // HWR_ProjectWall // -void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) +static void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap) { HWR_Lighting(pSurf, lightlevel, wallcolormap); - HWD.pfnSetShader(2); // wall shader - HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude); + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode|PF_Modulated|PF_Occlude, SHADER_WALL, false); // wall shader #ifdef WALLSPLATS - if (gr_curline->linedef->splats && cv_splats.value) + if (gl_curline->linedef->splats && cv_splats.value) HWR_DrawSegsSplats(pSurf); #endif } +// ========================================================================== +// BSP, CULL, ETC.. +// ========================================================================== + +// return the frac from the interception of the clipping line +// (in fact a clipping plane that has a constant, so can clip with simple 2d) +// with the wall segment +// +#ifndef NEWCLIP +static float HWR_ClipViewSegment(INT32 x, polyvertex_t *v1, polyvertex_t *v2) +{ + float num, den; + float v1x, v1y, v1dx, v1dy, v2dx, v2dy; + angle_t pclipangle = gl_xtoviewangle[x]; + + // a segment of a polygon + v1x = v1->x; + v1y = v1->y; + v1dx = (v2->x - v1->x); + v1dy = (v2->y - v1->y); + + // the clipping line + pclipangle = pclipangle + dup_viewangle; //back to normal angle (non-relative) + v2dx = FIXED_TO_FLOAT(FINECOSINE(pclipangle>>ANGLETOFINESHIFT)); + v2dy = FIXED_TO_FLOAT(FINESINE(pclipangle>>ANGLETOFINESHIFT)); + + den = v2dy*v1dx - v2dx*v1dy; + if (den == 0) + return -1; // parallel + + // calc the frac along the polygon segment, + //num = (v2x - v1x)*v2dy + (v1y - v2y)*v2dx; + //num = -v1x * v2dy + v1y * v2dx; + num = (gl_viewx - v1x)*v2dy + (v1y - gl_viewy)*v2dx; + + return num / den; +} +#endif + // // HWR_SplitWall // -void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor) +static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor, FBITFIELD blendmode) { /* SoM: split up and light walls according to the lightlist. This may also include leaving out parts @@ -588,24 +868,23 @@ void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfa float pegt, pegb, pegmul; float height = 0.0f, bheight = 0.0f; -#ifdef ESLOPE float endrealtop, endrealbot, endtop, endbot; float endpegt, endpegb, endpegmul; float endheight = 0.0f, endbheight = 0.0f; + // compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly + // use this as a temp var to store P_GetSlopeZAt's return value each time + fixed_t temp; + fixed_t v1x = FLOAT_TO_FIXED(wallVerts[0].x); fixed_t v1y = FLOAT_TO_FIXED(wallVerts[0].z); // not a typo fixed_t v2x = FLOAT_TO_FIXED(wallVerts[1].x); fixed_t v2y = FLOAT_TO_FIXED(wallVerts[1].z); // not a typo - // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly - // use this as a temp var to store P_GetZAt's return value each time - fixed_t temp; -#endif - INT32 solid, i; + INT32 solid, i; lightlist_t * list = sector->lightlist; const UINT8 alpha = Surf->PolyColor.s.alpha; - FUINT lightnum = HWR_CalcWallLight(gr_curline, sector->lightlevel); + FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y); extracolormap_t *colormap = NULL; realtop = top = wallVerts[3].y; @@ -614,33 +893,28 @@ void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfa pegb = wallVerts[0].t; pegmul = (pegb - pegt) / (top - bot); -#ifdef ESLOPE endrealtop = endtop = wallVerts[2].y; endrealbot = endbot = wallVerts[1].y; endpegt = wallVerts[2].t; endpegb = wallVerts[1].t; endpegmul = (endpegb - endpegt) / (endtop - endbot); -#endif for (i = 0; i < sector->numlights; i++) { -#ifdef ESLOPE - if (endtop < endrealbot) -#endif - if (top < realbot) + if (endtop < endrealbot && top < realbot) return; if (!(list[i].flags & FF_NOSHADE)) { if (pfloor && (pfloor->flags & FF_FOG)) { - lightnum = HWR_CalcWallLight(gr_curline, pfloor->master->frontsector->lightlevel); + lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y); colormap = pfloor->master->frontsector->extra_colormap; } else { - lightnum = HWR_CalcWallLight(gr_curline, *list[i].lightlevel); - colormap = list[i].extra_colormap; + lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y); + colormap = *list[i].extra_colormap; } } @@ -661,80 +935,40 @@ void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfa else solid = false; -#ifdef ESLOPE - if (list[i].slope) - { - temp = P_GetZAt(list[i].slope, v1x, v1y); - height = FIXED_TO_FLOAT(temp); - temp = P_GetZAt(list[i].slope, v2x, v2y); - endheight = FIXED_TO_FLOAT(temp); - } - else - height = endheight = FIXED_TO_FLOAT(list[i].height); + temp = P_GetLightZAt(&list[i], v1x, v1y); + height = FIXED_TO_FLOAT(temp); + temp = P_GetLightZAt(&list[i], v2x, v2y); + endheight = FIXED_TO_FLOAT(temp); if (solid) { - if (*list[i].caster->b_slope) - { - temp = P_GetZAt(*list[i].caster->b_slope, v1x, v1y); - bheight = FIXED_TO_FLOAT(temp); - temp = P_GetZAt(*list[i].caster->b_slope, v2x, v2y); - endbheight = FIXED_TO_FLOAT(temp); - } - else - bheight = endbheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight); + temp = P_GetFFloorBottomZAt(list[i].caster, v1x, v1y); + bheight = FIXED_TO_FLOAT(temp); + temp = P_GetFFloorBottomZAt(list[i].caster, v2x, v2y); + endbheight = FIXED_TO_FLOAT(temp); } -#else - height = FIXED_TO_FLOAT(list[i].height); - if (solid) - bheight = FIXED_TO_FLOAT(*list[i].caster->bottomheight); -#endif -#ifdef ESLOPE - if (endheight >= endtop) -#endif - if (height >= top) + if (endheight >= endtop && height >= top) { if (solid && top > bheight) top = bheight; -#ifdef ESLOPE if (solid && endtop > endbheight) endtop = endbheight; -#endif } -#ifdef ESLOPE if (i + 1 < sector->numlights) { - if (list[i+1].slope) - { - temp = P_GetZAt(list[i+1].slope, v1x, v1y); - bheight = FIXED_TO_FLOAT(temp); - temp = P_GetZAt(list[i+1].slope, v2x, v2y); - endbheight = FIXED_TO_FLOAT(temp); - } - else - bheight = endbheight = FIXED_TO_FLOAT(list[i+1].height); + temp = P_GetLightZAt(&list[i+1], v1x, v1y); + bheight = FIXED_TO_FLOAT(temp); + temp = P_GetLightZAt(&list[i+1], v2x, v2y); + endbheight = FIXED_TO_FLOAT(temp); } else { bheight = realbot; endbheight = endrealbot; } -#else - if (i + 1 < sector->numlights) - { - bheight = FIXED_TO_FLOAT(list[i+1].height); - } - else - { - bheight = realbot; - } -#endif -#ifdef ESLOPE - if (endbheight >= endtop) -#endif - if (bheight >= top) + if (endbheight >= endtop && bheight >= top) continue; //Found a break; @@ -743,15 +977,13 @@ void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfa if (bot < realbot) bot = realbot; -#ifdef ESLOPE endbot = endbheight; if (endbot < endrealbot) endbot = endrealbot; -#endif + Surf->PolyColor.s.alpha = alpha; -#ifdef ESLOPE wallVerts[3].t = pegt + ((realtop - top) * pegmul); wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul); wallVerts[0].t = pegt + ((realtop - bot) * pegmul); @@ -762,39 +994,25 @@ void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfa wallVerts[2].y = endtop; wallVerts[0].y = bot; wallVerts[1].y = endbot; -#else - wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); - wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; -#endif - - if (cutflag & FF_FOG) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap); - else if (cutflag & FF_TRANSLUCENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); + if (blendmode & PF_Fog) + HWR_AddTransparentWall(wallVerts, Surf, texnum, blendmode, true, lightnum, colormap); + else if (blendmode & (PF_Translucent|PF_Additive|PF_Substractive|PF_Environment)) + HWR_AddTransparentWall(wallVerts, Surf, texnum, blendmode, false, lightnum, colormap); else - HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); + HWR_ProjectWall(wallVerts, Surf, blendmode, lightnum, colormap); top = bot; -#ifdef ESLOPE endtop = endbot; -#endif } bot = realbot; -#ifdef ESLOPE endbot = endrealbot; - if (endtop <= endrealbot) -#endif - if (top <= realbot) + if (endtop <= endrealbot && top <= realbot) return; Surf->PolyColor.s.alpha = alpha; -#ifdef ESLOPE wallVerts[3].t = pegt + ((realtop - top) * pegmul); wallVerts[2].t = endpegt + ((endrealtop - endtop) * endpegmul); wallVerts[0].t = pegt + ((realtop - bot) * pegmul); @@ -805,34 +1023,26 @@ void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfa wallVerts[2].y = endtop; wallVerts[0].y = bot; wallVerts[1].y = endbot; -#else - wallVerts[3].t = wallVerts[2].t = pegt + ((realtop - top) * pegmul); - wallVerts[0].t = wallVerts[1].t = pegt + ((realtop - bot) * pegmul); - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; -#endif - - if (cutflag & FF_FOG) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Fog|PF_NoTexture, true, lightnum, colormap); - else if (cutflag & FF_TRANSLUCENT) - HWR_AddTransparentWall(wallVerts, Surf, texnum, PF_Translucent, false, lightnum, colormap); + if (blendmode & PF_Fog) + HWR_AddTransparentWall(wallVerts, Surf, texnum, blendmode, true, lightnum, colormap); + else if (blendmode & (PF_Translucent|PF_Additive|PF_Substractive|PF_Environment)) + HWR_AddTransparentWall(wallVerts, Surf, texnum, blendmode, false, lightnum, colormap); else - HWR_ProjectWall(wallVerts, Surf, PF_Masked, lightnum, colormap); + HWR_ProjectWall(wallVerts, Surf, blendmode, lightnum, colormap); } -// HWR_DrawSkyWalls +// HWR_DrawSkyWall // Draw walls into the depth buffer so that anything behind is culled properly -void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) +static void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) { - HWD.pfnSetTexture(NULL); + HWR_SetCurrentTexture(NULL); // no texture wallVerts[3].t = wallVerts[2].t = 0; wallVerts[0].t = wallVerts[1].t = 0; wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = 0; - + // this no longer sets top/bottom coords, this should be done before caling the function HWR_ProjectWall(wallVerts, Surf, PF_Invisible|PF_NoTexture, 255, NULL); // PF_Invisible so it's not drawn into the colour buffer // PF_NoTexture for no texture @@ -846,60 +1056,46 @@ void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf) // Anything between means the wall segment has been clipped with solidsegs, // reducing wall overdraw to a minimum // -void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom +static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { FOutVector wallVerts[4]; v2d_t vs, ve; // start, end vertices of 2d line (view from above) fixed_t worldtop, worldbottom; fixed_t worldhigh = 0, worldlow = 0; -#ifdef ESLOPE fixed_t worldtopslope, worldbottomslope; fixed_t worldhighslope = 0, worldlowslope = 0; fixed_t v1x, v1y, v2x, v2y; -#endif - GLTexture_t *grTex = NULL; + GLMapTexture_t *grTex = NULL; float cliplow = 0.0f, cliphigh = 0.0f; - INT32 gr_midtexture; + INT32 gl_midtexture; fixed_t h, l; // 3D sides and 2s middle textures -#ifdef ESLOPE fixed_t hS, lS; -#endif FUINT lightnum = 0; // shut up compiler extracolormap_t *colormap; FSurfaceInfo Surf; - gr_sidedef = gr_curline->sidedef; - gr_linedef = gr_curline->linedef; + gl_sidedef = gl_curline->sidedef; + gl_linedef = gl_curline->linedef; - vs.x = ((polyvertex_t *)gr_curline->pv1)->x; - vs.y = ((polyvertex_t *)gr_curline->pv1)->y; - ve.x = ((polyvertex_t *)gr_curline->pv2)->x; - ve.y = ((polyvertex_t *)gr_curline->pv2)->y; + vs.x = ((polyvertex_t *)gl_curline->pv1)->x; + vs.y = ((polyvertex_t *)gl_curline->pv1)->y; + ve.x = ((polyvertex_t *)gl_curline->pv2)->x; + ve.y = ((polyvertex_t *)gl_curline->pv2)->y; -#ifdef ESLOPE v1x = FLOAT_TO_FIXED(vs.x); v1y = FLOAT_TO_FIXED(vs.y); v2x = FLOAT_TO_FIXED(ve.x); v2y = FLOAT_TO_FIXED(ve.y); -#endif -#ifdef ESLOPE #define SLOPEPARAMS(slope, end1, end2, normalheight) \ - if (slope) { \ - end1 = P_GetZAt(slope, v1x, v1y); \ - end2 = P_GetZAt(slope, v2x, v2y); \ - } else \ - end1 = end2 = normalheight; + end1 = P_GetZAt(slope, v1x, v1y, normalheight); \ + end2 = P_GetZAt(slope, v2x, v2y, normalheight); - SLOPEPARAMS(gr_frontsector->c_slope, worldtop, worldtopslope, gr_frontsector->ceilingheight) - SLOPEPARAMS(gr_frontsector->f_slope, worldbottom, worldbottomslope, gr_frontsector->floorheight) -#else - worldtop = gr_frontsector->ceilingheight; - worldbottom = gr_frontsector->floorheight; -#endif + SLOPEPARAMS(gl_frontsector->c_slope, worldtop, worldtopslope, gl_frontsector->ceilingheight) + SLOPEPARAMS(gl_frontsector->f_slope, worldbottom, worldbottomslope, gl_frontsector->floorheight) // remember vertices ordering // 3--2 @@ -915,195 +1111,84 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // x offset the texture { - fixed_t texturehpeg = gr_sidedef->textureoffset + gr_curline->offset; + fixed_t texturehpeg = gl_sidedef->textureoffset + gl_curline->offset; cliplow = (float)texturehpeg; - cliphigh = (float)(texturehpeg + (gr_curline->flength*FRACUNIT)); + cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT)); } - lightnum = HWR_CalcWallLight(gr_curline, gr_frontsector->lightlevel); - colormap = gr_frontsector->extra_colormap; + lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); + colormap = gl_frontsector->extra_colormap; - if (gr_frontsector) + if (gl_frontsector) Surf.PolyColor.s.alpha = 255; - if (gr_backsector) + if (gl_backsector) { - INT32 gr_toptexture, gr_bottomtexture; + INT32 gl_toptexture = 0, gl_bottomtexture = 0; // two sided line + boolean bothceilingssky = false; // turned on if both back and front ceilings are sky + boolean bothfloorssky = false; // likewise, but for floors -#ifdef ESLOPE - SLOPEPARAMS(gr_backsector->c_slope, worldhigh, worldhighslope, gr_backsector->ceilingheight) - SLOPEPARAMS(gr_backsector->f_slope, worldlow, worldlowslope, gr_backsector->floorheight) + SLOPEPARAMS(gl_backsector->c_slope, worldhigh, worldhighslope, gl_backsector->ceilingheight) + SLOPEPARAMS(gl_backsector->f_slope, worldlow, worldlowslope, gl_backsector->floorheight) #undef SLOPEPARAMS -#else - worldhigh = gr_backsector->ceilingheight; - worldlow = gr_backsector->floorheight; -#endif - - // Sky culling - if (!gr_curline->polyseg) // Don't do it for polyobjects - { - // Sky Ceilings - wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX); - - if (gr_frontsector->ceilingpic == skyflatnum) - { - if (gr_backsector->ceilingpic == skyflatnum) - { - // Both front and back sectors are sky, needs skywall from the frontsector's ceiling, but only if the - // backsector is lower - if ((worldhigh <= worldtop && worldhighslope <= worldtopslope)// Assuming ESLOPE is always on with my changes - && (worldhigh != worldtop || worldhighslope != worldtopslope)) - // Removing the second line above will render more rarely visible skywalls. Example: Cave garden ceiling in Dark race - { -#ifdef ESLOPE - wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); - wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); -#else - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh); -#endif - HWR_DrawSkyWall(wallVerts, &Surf); - } - } - else - { - // Only the frontsector is sky, just draw a skywall from the front ceiling -#ifdef ESLOPE - wallVerts[0].y = FIXED_TO_FLOAT(worldtop); - wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); -#else - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); -#endif - HWR_DrawSkyWall(wallVerts, &Surf); - } - } - else if (gr_backsector->ceilingpic == skyflatnum) - { - // Only the backsector is sky, just draw a skywall from the front ceiling -#ifdef ESLOPE - wallVerts[0].y = FIXED_TO_FLOAT(worldtop); - wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); -#else - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); -#endif - HWR_DrawSkyWall(wallVerts, &Surf); - } - - - // Sky Floors - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); - - if (gr_frontsector->floorpic == skyflatnum) - { - if (gr_backsector->floorpic == skyflatnum) - { - // Both front and back sectors are sky, needs skywall from the backsector's floor, but only if the - // it's higher, also needs to check for bottomtexture as the floors don't usually move down - // when both sides are sky floors - if ((worldlow >= worldbottom && worldlowslope >= worldbottomslope) - && (worldlow != worldbottom || worldlowslope != worldbottomslope) - // Removing the second line above will render more rarely visible skywalls. Example: Cave garden ceiling in Dark race - && !(gr_sidedef->bottomtexture)) - { -#ifdef ESLOPE - wallVerts[3].y = FIXED_TO_FLOAT(worldlow); - wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); -#else - wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow); -#endif - - HWR_DrawSkyWall(wallVerts, &Surf); - } - } - else - { - // Only the backsector has sky, just draw a skywall from the back floor -#ifdef ESLOPE - wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); - wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); -#else - wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom); -#endif - - HWR_DrawSkyWall(wallVerts, &Surf); - } - } - else if ((gr_backsector->floorpic == skyflatnum) && !(gr_sidedef->bottomtexture)) - { - // Only the backsector has sky, just draw a skywall from the back floor if there's no bottomtexture -#ifdef ESLOPE - wallVerts[3].y = FIXED_TO_FLOAT(worldlow); - wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); -#else - wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldlow); -#endif - - HWR_DrawSkyWall(wallVerts, &Surf); - } - - } // hack to allow height changes in outdoor areas // This is what gets rid of the upper textures if there should be sky - if (gr_frontsector->ceilingpic == skyflatnum && - gr_backsector->ceilingpic == skyflatnum) + if (gl_frontsector->ceilingpic == skyflatnum + && gl_backsector->ceilingpic == skyflatnum) { - worldtop = worldhigh; -#ifdef ESLOPE - worldtopslope = worldhighslope; -#endif + bothceilingssky = true; } - gr_toptexture = R_GetTextureNum(gr_sidedef->toptexture); - gr_bottomtexture = R_GetTextureNum(gr_sidedef->bottomtexture); + // likewise, but for floors and upper textures + if (gl_frontsector->floorpic == skyflatnum + && gl_backsector->floorpic == skyflatnum) + { + bothfloorssky = true; + } + + if (!bothceilingssky) + gl_toptexture = R_GetTextureNum(gl_sidedef->toptexture); + if (!bothfloorssky) + gl_bottomtexture = R_GetTextureNum(gl_sidedef->bottomtexture); // check TOP TEXTURE - if (( -#ifdef ESLOPE - worldhighslope < worldtopslope || -#endif - worldhigh < worldtop - ) && gr_toptexture) + if ((worldhighslope < worldtopslope || worldhigh < worldtop) && gl_toptexture) { { fixed_t texturevpegtop; // top - grTex = HWR_GetTexture(gr_toptexture); + grTex = HWR_GetTexture(gl_toptexture); // PEGGING - if (gr_linedef->flags & ML_DONTPEGTOP) + if (gl_linedef->flags & ML_DONTPEGTOP) texturevpegtop = 0; -#ifdef ESLOPE - else if (gr_linedef->flags & ML_EFFECT1) - texturevpegtop = worldhigh + textureheight[gr_sidedef->toptexture] - worldtop; + else if (gl_linedef->flags & ML_EFFECT1) + texturevpegtop = worldhigh + textureheight[gl_sidedef->toptexture] - worldtop; else - texturevpegtop = gr_backsector->ceilingheight + textureheight[gr_sidedef->toptexture] - gr_frontsector->ceilingheight; -#else - else - texturevpegtop = worldhigh + textureheight[gr_sidedef->toptexture] - worldtop; -#endif + texturevpegtop = gl_backsector->ceilingheight + textureheight[gl_sidedef->toptexture] - gl_frontsector->ceilingheight; - texturevpegtop += gr_sidedef->rowoffset; + texturevpegtop += gl_sidedef->rowoffset; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpegtop %= SHORT(textures[gr_toptexture]->height)<height)<scaleY; - wallVerts[0].t = wallVerts[1].t = (texturevpegtop + gr_frontsector->ceilingheight - gr_backsector->ceilingheight) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (texturevpegtop + gl_frontsector->ceilingheight - gl_backsector->ceilingheight) * grTex->scaleY; wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; -#ifdef ESLOPE // Adjust t value for sloped walls - if (!(gr_linedef->flags & ML_EFFECT1)) + if (!(gl_linedef->flags & ML_EFFECT1)) { // Unskewed - wallVerts[3].t -= (worldtop - gr_frontsector->ceilingheight) * grTex->scaleY; - wallVerts[2].t -= (worldtopslope - gr_frontsector->ceilingheight) * grTex->scaleY; - wallVerts[0].t -= (worldhigh - gr_backsector->ceilingheight) * grTex->scaleY; - wallVerts[1].t -= (worldhighslope - gr_backsector->ceilingheight) * grTex->scaleY; + wallVerts[3].t -= (worldtop - gl_frontsector->ceilingheight) * grTex->scaleY; + wallVerts[2].t -= (worldtopslope - gl_frontsector->ceilingheight) * grTex->scaleY; + wallVerts[0].t -= (worldhigh - gl_backsector->ceilingheight) * grTex->scaleY; + wallVerts[1].t -= (worldhighslope - gl_backsector->ceilingheight) * grTex->scaleY; } - else if (gr_linedef->flags & ML_DONTPEGTOP) + else if (gl_linedef->flags & ML_DONTPEGTOP) { // Skewed by top wallVerts[0].t = (texturevpegtop + worldtop - worldhigh) * grTex->scaleY; @@ -1116,76 +1201,67 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[3].t = wallVerts[0].t - (worldtop - worldhigh) * grTex->scaleY; wallVerts[2].t = wallVerts[1].t - (worldtopslope - worldhighslope) * grTex->scaleY; } -#endif } // set top/bottom coords -#ifdef ESLOPE wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = FIXED_TO_FLOAT(worldhigh); wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); wallVerts[1].y = FIXED_TO_FLOAT(worldhighslope); -#else - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldhigh); -#endif - if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_toptexture, &Surf, FF_CUTLEVEL, NULL); - else if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, gr_toptexture, PF_Environment, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); + { + FBITFIELD blendmode = PF_Masked; + + if (grTex->mipmap.flags & TF_TRANSPARENT) + blendmode = PF_Environment; + + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, gl_toptexture, &Surf, FF_CUTLEVEL, NULL, blendmode); + else if (grTex->mipmap.flags & TF_TRANSPARENT) + HWR_AddTransparentWall(wallVerts, &Surf, gl_toptexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); + } } // check BOTTOM TEXTURE if (( -#ifdef ESLOPE worldlowslope > worldbottomslope || -#endif - worldlow > worldbottom) && gr_bottomtexture) //only if VISIBLE!!! + worldlow > worldbottom) && gl_bottomtexture) //only if VISIBLE!!! { { fixed_t texturevpegbottom = 0; // bottom - grTex = HWR_GetTexture(gr_bottomtexture); + grTex = HWR_GetTexture(gl_bottomtexture); // PEGGING -#ifdef ESLOPE - if (!(gr_linedef->flags & ML_DONTPEGBOTTOM)) + if (!(gl_linedef->flags & ML_DONTPEGBOTTOM)) texturevpegbottom = 0; - else if (gr_linedef->flags & ML_EFFECT1) + else if (gl_linedef->flags & ML_EFFECT1) texturevpegbottom = worldbottom - worldlow; else - texturevpegbottom = gr_frontsector->floorheight - gr_backsector->floorheight; -#else - if (gr_linedef->flags & ML_DONTPEGBOTTOM) - texturevpegbottom = worldbottom - worldlow; - else - texturevpegbottom = 0; -#endif + texturevpegbottom = gl_frontsector->floorheight - gl_backsector->floorheight; - texturevpegbottom += gr_sidedef->rowoffset; + texturevpegbottom += gl_sidedef->rowoffset; // This is so that it doesn't overflow and screw up the wall, it doesn't need to go higher than the texture's height anyway - texturevpegbottom %= SHORT(textures[gr_bottomtexture]->height)<height)<scaleY; - wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + gr_backsector->floorheight - gr_frontsector->floorheight) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + gl_backsector->floorheight - gl_frontsector->floorheight) * grTex->scaleY; wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; -#ifdef ESLOPE // Adjust t value for sloped walls - if (!(gr_linedef->flags & ML_EFFECT1)) + if (!(gl_linedef->flags & ML_EFFECT1)) { // Unskewed - wallVerts[0].t -= (worldbottom - gr_frontsector->floorheight) * grTex->scaleY; - wallVerts[1].t -= (worldbottomslope - gr_frontsector->floorheight) * grTex->scaleY; - wallVerts[3].t -= (worldlow - gr_backsector->floorheight) * grTex->scaleY; - wallVerts[2].t -= (worldlowslope - gr_backsector->floorheight) * grTex->scaleY; + wallVerts[0].t -= (worldbottom - gl_frontsector->floorheight) * grTex->scaleY; + wallVerts[1].t -= (worldbottomslope - gl_frontsector->floorheight) * grTex->scaleY; + wallVerts[3].t -= (worldlow - gl_backsector->floorheight) * grTex->scaleY; + wallVerts[2].t -= (worldlowslope - gl_backsector->floorheight) * grTex->scaleY; } - else if (gr_linedef->flags & ML_DONTPEGBOTTOM) + else if (gl_linedef->flags & ML_DONTPEGBOTTOM) { // Skewed by bottom wallVerts[0].t = wallVerts[1].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY; @@ -1198,29 +1274,30 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[0].t = (texturevpegbottom + worldlow - worldbottom) * grTex->scaleY; wallVerts[1].t = (texturevpegbottom + worldlowslope - worldbottomslope) * grTex->scaleY; } -#endif } // set top/bottom coords -#ifdef ESLOPE wallVerts[3].y = FIXED_TO_FLOAT(worldlow); wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); wallVerts[2].y = FIXED_TO_FLOAT(worldlowslope); wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); -#else - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldlow); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); -#endif - if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_bottomtexture, &Surf, FF_CUTLEVEL, NULL); - else if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, gr_bottomtexture, PF_Environment, false, lightnum, colormap); - else - HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); + { + FBITFIELD blendmode = PF_Masked; + + if (grTex->mipmap.flags & TF_TRANSPARENT) + blendmode = PF_Environment; + + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, gl_bottomtexture, &Surf, FF_CUTLEVEL, NULL, blendmode); + else if (grTex->mipmap.flags & TF_TRANSPARENT) + HWR_AddTransparentWall(wallVerts, &Surf, gl_bottomtexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); + } } - gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture); - if (gr_midtexture) + gl_midtexture = R_GetTextureNum(gl_sidedef->midtexture); + if (gl_midtexture) { FBITFIELD blendmode; sector_t *front, *back; @@ -1228,19 +1305,19 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom fixed_t texturevpeg = 0; INT32 repeats; - if (gr_linedef->frontsector->heightsec != -1) - front = §ors[gr_linedef->frontsector->heightsec]; + if (gl_linedef->frontsector->heightsec != -1) + front = §ors[gl_linedef->frontsector->heightsec]; else - front = gr_linedef->frontsector; + front = gl_linedef->frontsector; - if (gr_linedef->backsector->heightsec != -1) - back = §ors[gr_linedef->backsector->heightsec]; + if (gl_linedef->backsector->heightsec != -1) + back = §ors[gl_linedef->backsector->heightsec]; else - back = gr_linedef->backsector; + back = gl_linedef->backsector; - if (gr_sidedef->repeatcnt) - repeats = 1 + gr_sidedef->repeatcnt; - else if (gr_linedef->flags & ML_EFFECT5) + if (gl_sidedef->repeatcnt) + repeats = 1 + gl_sidedef->repeatcnt; + else if (gl_linedef->flags & ML_EFFECT5) { fixed_t high, low; @@ -1254,8 +1331,8 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom else low = back->floorheight; - repeats = (high - low)/textureheight[gr_sidedef->midtexture]; - if ((high-low)%textureheight[gr_sidedef->midtexture]) + repeats = (high - low)/textureheight[gl_sidedef->midtexture]; + if ((high-low)%textureheight[gl_sidedef->midtexture]) repeats++; // tile an extra time to fill the gap -- Monster Iestyn } else @@ -1268,64 +1345,51 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // heights of the polygon, and h & l, are the final (clipped) // poly coords. -#ifdef POLYOBJECTS // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, // you must use the linedef's backsector to be correct // From CB - if (gr_curline->polyseg) + if (gl_curline->polyseg) { popentop = back->ceilingheight; popenbottom = back->floorheight; } else -#endif { -#ifdef ESLOPE popentop = min(worldtop, worldhigh); popenbottom = max(worldbottom, worldlow); -#else - popentop = min(front->ceilingheight, back->ceilingheight); - popenbottom = max(front->floorheight, back->floorheight); -#endif } -#ifdef ESLOPE - if (gr_linedef->flags & ML_EFFECT2) + if (gl_linedef->flags & ML_EFFECT2) { - if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) + if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) { - polybottom = max(front->floorheight, back->floorheight) + gr_sidedef->rowoffset; - polytop = polybottom + textureheight[gr_midtexture]*repeats; + polybottom = max(front->floorheight, back->floorheight) + gl_sidedef->rowoffset; + polytop = polybottom + textureheight[gl_midtexture]*repeats; } else { - polytop = min(front->ceilingheight, back->ceilingheight) + gr_sidedef->rowoffset; - polybottom = polytop - textureheight[gr_midtexture]*repeats; + polytop = min(front->ceilingheight, back->ceilingheight) + gl_sidedef->rowoffset; + polybottom = polytop - textureheight[gl_midtexture]*repeats; } } - else if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) -#else - if (gr_linedef->flags & ML_DONTPEGBOTTOM) -#endif + else if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) { - polybottom = popenbottom + gr_sidedef->rowoffset; - polytop = polybottom + textureheight[gr_midtexture]*repeats; + polybottom = popenbottom + gl_sidedef->rowoffset; + polytop = polybottom + textureheight[gl_midtexture]*repeats; } else { - polytop = popentop + gr_sidedef->rowoffset; - polybottom = polytop - textureheight[gr_midtexture]*repeats; + polytop = popentop + gl_sidedef->rowoffset; + polybottom = polytop - textureheight[gl_midtexture]*repeats; } // CB -#ifdef POLYOBJECTS // NOTE: With polyobjects, whenever you need to check the properties of the polyobject sector it belongs to, // you must use the linedef's backsector to be correct - if (gr_curline->polyseg) + if (gl_curline->polyseg) { lowcut = polybottom; highcut = polytop; } -#endif else { // The cut-off values of a linedef can always be constant, since every line has an absoulute front and or back sector @@ -1338,16 +1402,12 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { // PEGGING -#ifdef ESLOPE - if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) -#else - if (gr_linedef->flags & ML_DONTPEGBOTTOM) -#endif - texturevpeg = textureheight[gr_sidedef->midtexture]*repeats - h + polybottom; + if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) + texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; else texturevpeg = polytop - h; - grTex = HWR_GetTexture(gr_midtexture); + grTex = HWR_GetTexture(gl_midtexture); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; wallVerts[0].t = wallVerts[1].t = (h - l + texturevpeg) * grTex->scaleY; @@ -1361,14 +1421,13 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h); wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l); -#ifdef ESLOPE // Correct to account for slopes { fixed_t midtextureslant; - if (gr_linedef->flags & ML_EFFECT2) + if (gl_linedef->flags & ML_EFFECT2) midtextureslant = 0; - else if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) + else if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) midtextureslant = worldlow < worldbottom ? worldbottomslope-worldbottom : worldlowslope-worldlow; @@ -1393,8 +1452,8 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { // PEGGING - if (!!(gr_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gr_linedef->flags & ML_EFFECT3)) - texturevpeg = textureheight[gr_sidedef->midtexture]*repeats - h + polybottom; + if (!!(gl_linedef->flags & ML_DONTPEGBOTTOM) ^ !!(gl_linedef->flags & ML_EFFECT3)) + texturevpeg = textureheight[gl_sidedef->midtexture]*repeats - h + polybottom; else texturevpeg = polytop - h; wallVerts[2].t = texturevpeg * grTex->scaleY; @@ -1404,39 +1463,11 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = FIXED_TO_FLOAT(h); wallVerts[1].y = FIXED_TO_FLOAT(l); } -#endif - // set alpha for transparent walls (new boom and legacy linedef types) + // set alpha for transparent walls // ooops ! this do not work at all because render order we should render it in backtofront order - switch (gr_linedef->special) + switch (gl_linedef->special) { - case 900: - blendmode = HWR_TranstableToAlpha(tr_trans10, &Surf); - break; - case 901: - blendmode = HWR_TranstableToAlpha(tr_trans20, &Surf); - break; - case 902: - blendmode = HWR_TranstableToAlpha(tr_trans30, &Surf); - break; - case 903: - blendmode = HWR_TranstableToAlpha(tr_trans40, &Surf); - break; - case 904: - blendmode = HWR_TranstableToAlpha(tr_trans50, &Surf); - break; - case 905: - blendmode = HWR_TranstableToAlpha(tr_trans60, &Surf); - break; - case 906: - blendmode = HWR_TranstableToAlpha(tr_trans70, &Surf); - break; - case 907: - blendmode = HWR_TranstableToAlpha(tr_trans80, &Surf); - break; - case 908: - blendmode = HWR_TranstableToAlpha(tr_trans90, &Surf); - break; // Translucent case 102: case 121: @@ -1457,149 +1488,146 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom blendmode = PF_Translucent; break; default: - blendmode = PF_Masked; + { + transnum_t transtable = R_GetLinedefTransTable(gl_linedef); + if (transtable != NUMEFFECTMAPS) + blendmode = HWR_TranstableToAlpha(transtable, &Surf); + else + blendmode = PF_Masked; break; + } } -#ifdef POLYOBJECTS - if (gr_curline->polyseg && gr_curline->polyseg->translucency > 0) + if (gl_curline->polyseg && gl_curline->polyseg->translucency > 0) { - if (gr_curline->polyseg->translucency >= NUMTRANSMAPS) // wall not drawn + if (gl_curline->polyseg->translucency >= NUMEFFECTMAPS) // wall not drawn { Surf.PolyColor.s.alpha = 0x00; // This shouldn't draw anything regardless of blendmode blendmode = PF_Masked; } else - blendmode = HWR_TranstableToAlpha(gr_curline->polyseg->translucency, &Surf); + blendmode = HWR_TranstableToAlpha(gl_curline->polyseg->translucency, &Surf); } -#endif - if (gr_frontsector->numlights) + if (gl_frontsector->numlights) { if (!(blendmode & PF_Masked)) - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_TRANSLUCENT, NULL); + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_TRANSLUCENT, NULL, blendmode); else { - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTLEVEL, NULL); + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL, blendmode); } } else if (!(blendmode & PF_Masked)) - HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, blendmode, false, lightnum, colormap); + HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); else HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); } + + // Sky culling + // No longer so much a mess as before! + if (!gl_curline->polyseg) // Don't do it for polyobjects + { + if (gl_frontsector->ceilingpic == skyflatnum) + { + if (gl_backsector->ceilingpic != skyflatnum) // don't cull if back sector is also sky + { + wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space + wallVerts[0].y = FIXED_TO_FLOAT(worldtop); + wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + + if (gl_frontsector->floorpic == skyflatnum) + { + if (gl_backsector->floorpic != skyflatnum) // don't cull if back sector is also sky + { + wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); + wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space + HWR_DrawSkyWall(wallVerts, &Surf); + } + } + } } else { // Single sided line... Deal only with the middletexture (if one exists) - gr_midtexture = R_GetTextureNum(gr_sidedef->midtexture); - if (gr_midtexture - && gr_linedef->special != HORIZONSPECIAL) // Ignore horizon line for OGL + gl_midtexture = R_GetTextureNum(gl_sidedef->midtexture); + if (gl_midtexture && gl_linedef->special != 41) // (Ignore horizon line for OGL) { { fixed_t texturevpeg; // PEGGING -#ifdef ESLOPE - if ((gr_linedef->flags & (ML_DONTPEGBOTTOM|ML_EFFECT2)) == (ML_DONTPEGBOTTOM|ML_EFFECT2)) - texturevpeg = gr_frontsector->floorheight + textureheight[gr_sidedef->midtexture] - gr_frontsector->ceilingheight + gr_sidedef->rowoffset; - else -#endif - if (gr_linedef->flags & ML_DONTPEGBOTTOM) - texturevpeg = worldbottom + textureheight[gr_sidedef->midtexture] - worldtop + gr_sidedef->rowoffset; + if ((gl_linedef->flags & (ML_DONTPEGBOTTOM|ML_EFFECT2)) == (ML_DONTPEGBOTTOM|ML_EFFECT2)) + texturevpeg = gl_frontsector->floorheight + textureheight[gl_sidedef->midtexture] - gl_frontsector->ceilingheight + gl_sidedef->rowoffset; + else if (gl_linedef->flags & ML_DONTPEGBOTTOM) + texturevpeg = worldbottom + textureheight[gl_sidedef->midtexture] - worldtop + gl_sidedef->rowoffset; else // top of texture at top - texturevpeg = gr_sidedef->rowoffset; + texturevpeg = gl_sidedef->rowoffset; - grTex = HWR_GetTexture(gr_midtexture); + grTex = HWR_GetTexture(gl_midtexture); wallVerts[3].t = wallVerts[2].t = texturevpeg * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (texturevpeg + gr_frontsector->ceilingheight - gr_frontsector->floorheight) * grTex->scaleY; + wallVerts[0].t = wallVerts[1].t = (texturevpeg + gl_frontsector->ceilingheight - gl_frontsector->floorheight) * grTex->scaleY; wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; -#ifdef ESLOPE // Texture correction for slopes - if (gr_linedef->flags & ML_EFFECT2) { - wallVerts[3].t += (gr_frontsector->ceilingheight - worldtop) * grTex->scaleY; - wallVerts[2].t += (gr_frontsector->ceilingheight - worldtopslope) * grTex->scaleY; - wallVerts[0].t += (gr_frontsector->floorheight - worldbottom) * grTex->scaleY; - wallVerts[1].t += (gr_frontsector->floorheight - worldbottomslope) * grTex->scaleY; - } else if (gr_linedef->flags & ML_DONTPEGBOTTOM) { + if (gl_linedef->flags & ML_EFFECT2) { + wallVerts[3].t += (gl_frontsector->ceilingheight - worldtop) * grTex->scaleY; + wallVerts[2].t += (gl_frontsector->ceilingheight - worldtopslope) * grTex->scaleY; + wallVerts[0].t += (gl_frontsector->floorheight - worldbottom) * grTex->scaleY; + wallVerts[1].t += (gl_frontsector->floorheight - worldbottomslope) * grTex->scaleY; + } else if (gl_linedef->flags & ML_DONTPEGBOTTOM) { wallVerts[3].t = wallVerts[0].t + (worldbottom-worldtop) * grTex->scaleY; wallVerts[2].t = wallVerts[1].t + (worldbottomslope-worldtopslope) * grTex->scaleY; } else { wallVerts[0].t = wallVerts[3].t - (worldbottom-worldtop) * grTex->scaleY; wallVerts[1].t = wallVerts[2].t - (worldbottomslope-worldtopslope) * grTex->scaleY; } -#endif } -#ifdef ESLOPE + //Set textures properly on single sided walls that are sloped wallVerts[3].y = FIXED_TO_FLOAT(worldtop); wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); -#else - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); -#endif - if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, gr_midtexture, &Surf, FF_CUTLEVEL, NULL); - // I don't think that solid walls can use translucent linedef types... - else { + FBITFIELD blendmode = PF_Masked; if (grTex->mipmap.flags & TF_TRANSPARENT) - HWR_AddTransparentWall(wallVerts, &Surf, gr_midtexture, PF_Environment, false, lightnum, colormap); + blendmode = PF_Environment; + + // I don't think that solid walls can use translucent linedef types... + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, gl_midtexture, &Surf, FF_CUTLEVEL, NULL, blendmode); else - HWR_ProjectWall(wallVerts, &Surf, PF_Masked, lightnum, colormap); + { + if (grTex->mipmap.flags & TF_TRANSPARENT) + HWR_AddTransparentWall(wallVerts, &Surf, gl_midtexture, blendmode, false, lightnum, colormap); + else + HWR_ProjectWall(wallVerts, &Surf, blendmode, lightnum, colormap); + } } } - else + + if (!gl_curline->polyseg) { -#ifdef ESLOPE - //Set textures properly on single sided walls that are sloped - wallVerts[3].y = FIXED_TO_FLOAT(worldtop); - wallVerts[0].y = FIXED_TO_FLOAT(worldbottom); - wallVerts[2].y = FIXED_TO_FLOAT(worldtopslope); - wallVerts[1].y = FIXED_TO_FLOAT(worldbottomslope); -#else - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(worldtop); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldbottom); -#endif - - // When there's no midtexture, draw a skywall to prevent rendering behind it - HWR_DrawSkyWall(wallVerts, &Surf); - } - - - // Single sided lines are simple for skywalls, just need to draw from the top or bottom of the sector if there's - // a sky flat - if (!gr_curline->polyseg) - { - if (gr_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector + if (gl_frontsector->ceilingpic == skyflatnum) // It's a single-sided line with sky for its sector { - wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(INT32_MAX); -#ifdef ESLOPE + wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(INT32_MAX); // draw to top of map space wallVerts[0].y = FIXED_TO_FLOAT(worldtop); wallVerts[1].y = FIXED_TO_FLOAT(worldtopslope); -#else - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(worldtop); -#endif HWR_DrawSkyWall(wallVerts, &Surf); } - if (gr_frontsector->floorpic == skyflatnum) + if (gl_frontsector->floorpic == skyflatnum) { -#ifdef ESLOPE wallVerts[3].y = FIXED_TO_FLOAT(worldbottom); wallVerts[2].y = FIXED_TO_FLOAT(worldbottomslope); -#else - wallVerts[3].y = wallVerts[2].y = FIXED_TO_FLOAT(worldbottom); -#endif - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); - + wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(INT32_MIN); // draw to bottom of map space HWR_DrawSkyWall(wallVerts, &Surf); } } @@ -1607,7 +1635,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom //Hurdler: 3d-floors test - if (gr_frontsector && gr_backsector && gr_frontsector->tag != gr_backsector->tag && (gr_backsector->ffloors || gr_frontsector->ffloors)) + if (gl_frontsector && gl_backsector && gl_frontsector->tag != gl_backsector->tag && (gl_backsector->ffloors || gl_frontsector->ffloors)) { ffloor_t * rover; fixed_t highcut = 0, lowcut = 0; @@ -1617,14 +1645,16 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom ///TODO add slope support (fixing cutoffs, proper wall clipping) - maybe just disable highcut/lowcut if either sector or FOF has a slope /// to allow fun plane intersecting in OGL? But then people would abuse that and make software look bad. :C - highcut = gr_frontsector->ceilingheight < gr_backsector->ceilingheight ? gr_frontsector->ceilingheight : gr_backsector->ceilingheight; - lowcut = gr_frontsector->floorheight > gr_backsector->floorheight ? gr_frontsector->floorheight : gr_backsector->floorheight; + highcut = gl_frontsector->ceilingheight < gl_backsector->ceilingheight ? gl_frontsector->ceilingheight : gl_backsector->ceilingheight; + lowcut = gl_frontsector->floorheight > gl_backsector->floorheight ? gl_frontsector->floorheight : gl_backsector->floorheight; - if (gr_backsector->ffloors) + if (gl_backsector->ffloors) { - for (rover = gr_backsector->ffloors; rover; rover = rover->next) + for (rover = gl_backsector->ffloors; rover; rover = rover->next) { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES) || (rover->flags & FF_INVERTSIDES)) + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES)) + continue; + if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES) continue; if (*rover->topheight < lowcut || *rover->bottomheight > highcut) continue; @@ -1633,19 +1663,18 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gr_curline->linedef-gr_backsector->lines[0]; + size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; newline = rover->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } -#ifdef ESLOPE - h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight; - hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight; - l = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight; - lS = *rover->b_slope ? P_GetZAt(*rover->b_slope, v2x, v2y) : *rover->bottomheight; - if (!(*rover->t_slope) && !gr_frontsector->c_slope && !gr_backsector->c_slope && h > highcut) + h = P_GetFFloorTopZAt (rover, v1x, v1y); + hS = P_GetFFloorTopZAt (rover, v2x, v2y); + l = P_GetFFloorBottomZAt(rover, v1x, v1y); + lS = P_GetFFloorBottomZAt(rover, v2x, v2y); + if (!(*rover->t_slope) && !gl_frontsector->c_slope && !gl_backsector->c_slope && h > highcut) h = hS = highcut; - if (!(*rover->b_slope) && !gr_frontsector->f_slope && !gr_backsector->f_slope && l < lowcut) + if (!(*rover->b_slope) && !gl_frontsector->f_slope && !gl_backsector->f_slope && l < lowcut) l = lS = lowcut; //Hurdler: HW code starts here //FIXME: check if peging is correct @@ -1655,19 +1684,6 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = FIXED_TO_FLOAT(hS); wallVerts[0].y = FIXED_TO_FLOAT(l); wallVerts[1].y = FIXED_TO_FLOAT(lS); -#else - h = *rover->topheight; - l = *rover->bottomheight; - if (h > highcut) - h = highcut; - if (l < lowcut) - l = lowcut; - //Hurdler: HW code starts here - //FIXME: check if peging is correct - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l); -#endif if (rover->flags & FF_FOG) { wallVerts[3].t = wallVerts[2].t = 0; @@ -1679,9 +1695,7 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { fixed_t texturevpeg; boolean attachtobottom = false; -#ifdef ESLOPE boolean slopeskew = false; // skew FOF walls with slopes? -#endif // Wow, how was this missing from OpenGL for so long? // ...Oh well, anyway, Lower Unpegged now changes pegging of FOFs like in software @@ -1690,22 +1704,17 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { texturevpeg = sides[newline->sidenum[0]].rowoffset; attachtobottom = !!(newline->flags & ML_DONTPEGBOTTOM); -#ifdef ESLOPE slopeskew = !!(newline->flags & ML_DONTPEGTOP); -#endif } else { texturevpeg = sides[rover->master->sidenum[0]].rowoffset; - attachtobottom = !!(gr_linedef->flags & ML_DONTPEGBOTTOM); -#ifdef ESLOPE + attachtobottom = !!(gl_linedef->flags & ML_DONTPEGBOTTOM); slopeskew = !!(rover->master->flags & ML_DONTPEGTOP); -#endif } grTex = HWR_GetTexture(texnum); -#ifdef ESLOPE if (!slopeskew) // no skewing { if (attachtobottom) @@ -1730,12 +1739,6 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].t = wallVerts[1].t - (hS - lS) * grTex->scaleY; } } -#else - if (attachtobottom) - texturevpeg -= *rover->topheight - *rover->bottomheight; - wallVerts[3].t = wallVerts[2].t = (*rover->topheight - h + texturevpeg) * grTex->scaleY; - wallVerts[0].t = wallVerts[1].t = (*rover->topheight - l + texturevpeg) * grTex->scaleY; -#endif wallVerts[0].s = wallVerts[3].s = cliplow * grTex->scaleX; wallVerts[2].s = wallVerts[1].s = cliphigh * grTex->scaleX; @@ -1746,13 +1749,13 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom blendmode = PF_Fog|PF_NoTexture; - lightnum = HWR_CalcWallLight(gr_curline, rover->master->frontsector->lightlevel); + lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = rover->master->frontsector->extra_colormap; Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); - if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, 0, &Surf, rover->flags, rover); + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, 0, &Surf, rover->flags, rover, blendmode); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -1760,14 +1763,21 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) + if (rover->flags & FF_TRANSLUCENT) { - blendmode = PF_Translucent; - Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + if (rover->alpha < 256) + { + blendmode = PF_Translucent; + Surf.PolyColor.s.alpha = (UINT8)(rover->alpha-1 > 255 ? 255 : rover->alpha-1); + } + else if (rover->alpha == FFLOOR_ALPHA_SPECIAL_ADDITIVE) + blendmode = PF_Additive; + else if (rover->alpha == FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE) + blendmode = PF_Substractive; } - if (gr_frontsector->numlights) - HWR_SplitWall(gr_frontsector, wallVerts, texnum, &Surf, rover->flags, rover); + if (gl_frontsector->numlights) + HWR_SplitWall(gl_frontsector, wallVerts, texnum, &Surf, rover->flags, rover, blendmode); else { if (blendmode != PF_Masked) @@ -1779,11 +1789,13 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom } } - if (gr_frontsector->ffloors) // Putting this seperate should allow 2 FOF sectors to be connected without too many errors? I think? + if (gl_frontsector->ffloors) // Putting this seperate should allow 2 FOF sectors to be connected without too many errors? I think? { - for (rover = gr_frontsector->ffloors; rover; rover = rover->next) + for (rover = gl_frontsector->ffloors; rover; rover = rover->next) { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_ALLSIDES)) + if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERSIDES)) + continue; + if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) continue; if (*rover->topheight < lowcut || *rover->bottomheight > highcut) continue; @@ -1792,18 +1804,17 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom if (rover->master->flags & ML_TFERLINE) { - size_t linenum = gr_curline->linedef-gr_backsector->lines[0]; + size_t linenum = gl_curline->linedef-gl_backsector->lines[0]; newline = rover->master->frontsector->lines[0] + linenum; texnum = R_GetTextureNum(sides[newline->sidenum[0]].midtexture); } -#ifdef ESLOPE //backsides - h = *rover->t_slope ? P_GetZAt(*rover->t_slope, v1x, v1y) : *rover->topheight; - hS = *rover->t_slope ? P_GetZAt(*rover->t_slope, v2x, v2y) : *rover->topheight; - l = *rover->b_slope ? P_GetZAt(*rover->b_slope, v1x, v1y) : *rover->bottomheight; - lS = *rover->b_slope ? P_GetZAt(*rover->b_slope, v2x, v2y) : *rover->bottomheight; - if (!(*rover->t_slope) && !gr_frontsector->c_slope && !gr_backsector->c_slope && h > highcut) + h = P_GetFFloorTopZAt (rover, v1x, v1y); + hS = P_GetFFloorTopZAt (rover, v2x, v2y); + l = P_GetFFloorBottomZAt(rover, v1x, v1y); + lS = P_GetFFloorBottomZAt(rover, v2x, v2y); + if (!(*rover->t_slope) && !gl_frontsector->c_slope && !gl_backsector->c_slope && h > highcut) h = hS = highcut; - if (!(*rover->b_slope) && !gr_frontsector->f_slope && !gr_backsector->f_slope && l < lowcut) + if (!(*rover->b_slope) && !gl_frontsector->f_slope && !gl_backsector->f_slope && l < lowcut) l = lS = lowcut; //Hurdler: HW code starts here //FIXME: check if peging is correct @@ -1813,19 +1824,6 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom wallVerts[2].y = FIXED_TO_FLOAT(hS); wallVerts[0].y = FIXED_TO_FLOAT(l); wallVerts[1].y = FIXED_TO_FLOAT(lS); -#else - h = *rover->topheight; - l = *rover->bottomheight; - if (h > highcut) - h = highcut; - if (l < lowcut) - l = lowcut; - //Hurdler: HW code starts here - //FIXME: check if peging is correct - // set top/bottom coords - wallVerts[2].y = wallVerts[3].y = FIXED_TO_FLOAT(h); - wallVerts[0].y = wallVerts[1].y = FIXED_TO_FLOAT(l); -#endif if (rover->flags & FF_FOG) { wallVerts[3].t = wallVerts[2].t = 0; @@ -1858,13 +1856,13 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom blendmode = PF_Fog|PF_NoTexture; - lightnum = HWR_CalcWallLight(gr_curline, rover->master->frontsector->lightlevel); + lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y); colormap = rover->master->frontsector->extra_colormap; Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap); - if (gr_backsector->numlights) - HWR_SplitWall(gr_backsector, wallVerts, 0, &Surf, rover->flags, rover); + if (gl_backsector->numlights) + HWR_SplitWall(gl_backsector, wallVerts, 0, &Surf, rover->flags, rover, blendmode); else HWR_AddTransparentWall(wallVerts, &Surf, 0, blendmode, true, lightnum, colormap); } @@ -1872,14 +1870,21 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom { FBITFIELD blendmode = PF_Masked; - if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) + if (rover->flags & FF_TRANSLUCENT) { - blendmode = PF_Translucent; - Surf.PolyColor.s.alpha = (UINT8)rover->alpha-1 > 255 ? 255 : rover->alpha-1; + if (rover->alpha < 256) + { + blendmode = PF_Translucent; + Surf.PolyColor.s.alpha = (UINT8)(rover->alpha-1 > 255 ? 255 : rover->alpha-1); + } + else if (rover->alpha == FFLOOR_ALPHA_SPECIAL_ADDITIVE) + blendmode = PF_Additive; + else if (rover->alpha == FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE) + blendmode = PF_Substractive; } - if (gr_backsector->numlights) - HWR_SplitWall(gr_backsector, wallVerts, texnum, &Surf, rover->flags, rover); + if (gl_backsector->numlights) + HWR_SplitWall(gl_backsector, wallVerts, texnum, &Surf, rover->flags, rover, blendmode); else { if (blendmode != PF_Masked) @@ -1896,148 +1901,538 @@ void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom // From PrBoom: // -// e6y: Check whether the player can look beyond this line, rturns true if we can't +// e6y: Check whether the player can look beyond this line // - +#ifdef NEWCLIP boolean checkforemptylines = true; // Don't modify anything here, just check // Kalaron: Modified for sloped linedefs -static boolean CheckClip(sector_t * afrontsector, sector_t * abacksector) +static boolean CheckClip(seg_t * seg, sector_t * afrontsector, sector_t * abacksector) { fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends + boolean bothceilingssky = false, bothfloorssky = false; + + if (abacksector->ceilingpic == skyflatnum && afrontsector->ceilingpic == skyflatnum) + bothceilingssky = true; + if (abacksector->floorpic == skyflatnum && afrontsector->floorpic == skyflatnum) + bothfloorssky = true; // GZDoom method of sloped line clipping -#ifdef ESLOPE if (afrontsector->f_slope || afrontsector->c_slope || abacksector->f_slope || abacksector->c_slope) { fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t - v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x); - v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y); - v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x); - v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y); + v1x = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->x); + v1y = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->y); + v2x = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->x); + v2y = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->y); #define SLOPEPARAMS(slope, end1, end2, normalheight) \ - if (slope) { \ - end1 = P_GetZAt(slope, v1x, v1y); \ - end2 = P_GetZAt(slope, v2x, v2y); \ - } else \ - end1 = end2 = normalheight; + end1 = P_GetZAt(slope, v1x, v1y, normalheight); \ + end2 = P_GetZAt(slope, v2x, v2y, normalheight); - SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector->floorheight) + SLOPEPARAMS(afrontsector->f_slope, frontf1, frontf2, afrontsector-> floorheight) SLOPEPARAMS(afrontsector->c_slope, frontc1, frontc2, afrontsector->ceilingheight) - SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector->floorheight) - SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight) + SLOPEPARAMS( abacksector->f_slope, backf1, backf2, abacksector-> floorheight) + SLOPEPARAMS( abacksector->c_slope, backc1, backc2, abacksector->ceilingheight) #undef SLOPEPARAMS } else -#endif { - frontf1 = frontf2 = afrontsector->floorheight; + frontf1 = frontf2 = afrontsector-> floorheight; frontc1 = frontc2 = afrontsector->ceilingheight; - backf1 = backf2 = abacksector->floorheight; - backc1 = backc2 = abacksector->ceilingheight; + backf1 = backf2 = abacksector-> floorheight; + backc1 = backc2 = abacksector->ceilingheight; + } + // properly render skies (consider door "open" if both ceilings are sky) + // same for floors + if (!bothceilingssky && !bothfloorssky) + { + // now check for closed sectors! + if ((backc1 <= frontf1 && backc2 <= frontf2) + || (backf1 >= frontc1 && backf2 >= frontc2)) + { + checkforemptylines = false; + return true; + } + + if (backc1 <= backf1 && backc2 <= backf2) + { + // preserve a kind of transparent door/lift special effect: + if (((backc1 >= frontc1 && backc2 >= frontc2) || seg->sidedef->toptexture) + && ((backf1 <= frontf1 && backf2 <= frontf2) || seg->sidedef->bottomtexture)) + { + checkforemptylines = false; + return true; + } + } } - - // now check for closed sectors! - - // here we're talking about a CEILING lower than a floor. ...yeah we don't even need to bother. - if (backc1 <= frontf1 && backc2 <= frontf2) - { - checkforemptylines = false; - return true; - } - - // here we're talking about floors higher than ceilings, don't even bother either. - if (backf1 >= frontc1 && backf2 >= frontc2) - { - checkforemptylines = false; - return true; - } - - // Lat: Ok, here's what we need to do, we want to draw thok barriers. Let's define what a thok barrier is; - // -Must have ceilheight <= floorheight - // -ceilpic must be skyflatnum - // -an adjacant sector needs to have a ceilingheight or a floor height different than the one we have, otherwise, it's just a huge ass wall, we shouldn't render past it. - // -said adjacant sector cannot also be a thok barrier, because that's also dumb and we could render far more than we need to as a result :V - - if (backc1 <= backf1 && backc2 <= backf2) - { - checkforemptylines = false; - - // before we do anything, if both sectors are thok barriers, GET ME OUT OF HERE! - if (frontc1 <= backc1 && frontc2 <= backc2) - return true; // STOP RENDERING. - - // draw floors at the top of thok barriers: - if (backc1 < frontc1 || backc2 < frontc2) + if (!bothceilingssky) { + if (backc1 != frontc1 || backc2 != frontc2) + { + checkforemptylines = false; return false; + } + } - if (backf1 > frontf1 || backf2 > frontf2) + if (!bothfloorssky) { + if (backf1 != frontf1 || backf2 != frontf2) + { + checkforemptylines = false; return false; - - return true; + } } - // Window. - // We know it's a window when the above isn't true and the back and front sectors don't match - if (backc1 != frontc1 || backc2 != frontc2 - || backf1 != frontf1 || backf2 != frontf2) - { - checkforemptylines = false; - return false; - } - - // In this case we just need to check whether there is actually a need to render any lines, so checkforempty lines - // stays true return false; } +#else +//Hurdler: just like in r_bsp.c +#if 1 +#define MAXSEGS MAXVIDWIDTH/2+1 +#else +//Alam_GBC: Or not (may cause overflow) +#define MAXSEGS 128 +#endif -// HWR_AddLine -// Clips the given segment and adds any visible pieces to the line list. -void HWR_AddLine(seg_t *line) +// hw_newend is one past the last valid seg +static cliprange_t * hw_newend; +static cliprange_t gl_solidsegs[MAXSEGS]; + +// needs fix: walls are incorrectly clipped one column less +static consvar_t cv_glclipwalls = CVAR_INIT ("gr_clipwalls", "Off", 0, CV_OnOff, NULL); + +static void printsolidsegs(void) +{ + cliprange_t * start; + if (!hw_newend) + return; + for (start = gl_solidsegs;start != hw_newend;start++) + { + CONS_Debug(DBG_RENDER, "%d-%d|",start->first,start->last); + } + CONS_Debug(DBG_RENDER, "\n\n"); +} + +// +// +// +static void HWR_ClipSolidWallSegment(INT32 first, INT32 last) +{ + cliprange_t *next, *start; + float lowfrac, highfrac; + boolean poorhack = false; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = gl_solidsegs; + while (start->last < first-1) + start++; + + if (first < start->first) + { + if (last < start->first-1) + { + // Post is entirely visible (above start), + // so insert a new clippost. + HWR_StoreWallRange(first, last); + + next = hw_newend; + hw_newend++; + + while (next != start) + { + *next = *(next-1); + next--; + } + + next->first = first; + next->last = last; + printsolidsegs(); + return; + } + + // There is a fragment above *start. + if (!cv_glclipwalls.value) + { + if (!poorhack) HWR_StoreWallRange(first, last); + poorhack = true; + } + else + { + highfrac = HWR_ClipViewSegment(start->first+1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); + HWR_StoreWallRange(0, highfrac); + } + // Now adjust the clip size. + start->first = first; + } + + // Bottom contained in start? + if (last <= start->last) + { + printsolidsegs(); + return; + } + next = start; + while (last >= (next+1)->first-1) + { + // There is a fragment between two posts. + if (!cv_glclipwalls.value) + { + if (!poorhack) HWR_StoreWallRange(first,last); + poorhack = true; + } + else + { + lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); + highfrac = HWR_ClipViewSegment((next+1)->first+1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); + HWR_StoreWallRange(lowfrac, highfrac); + } + next++; + + if (last <= next->last) + { + // Bottom is contained in next. + // Adjust the clip size. + start->last = next->last; + goto crunch; + } + } + + if (first == next->first+1) // 1 line texture + { + if (!cv_glclipwalls.value) + { + if (!poorhack) HWR_StoreWallRange(first,last); + poorhack = true; + } + else + HWR_StoreWallRange(0, 1); + } + else + { + // There is a fragment after *next. + if (!cv_glclipwalls.value) + { + if (!poorhack) HWR_StoreWallRange(first,last); + poorhack = true; + } + else + { + lowfrac = HWR_ClipViewSegment(next->last-1, (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); + HWR_StoreWallRange(lowfrac, 1); + } + } + + // Adjust the clip size. + start->last = last; + + // Remove start+1 to next from the clip list, + // because start now covers their area. +crunch: + if (next == start) + { + printsolidsegs(); + // Post just extended past the bottom of one post. + return; + } + + + while (next++ != hw_newend) + { + // Remove a post. + *++start = *next; + } + + hw_newend = start; + printsolidsegs(); +} + +// +// handle LineDefs with upper and lower texture (windows) +// +static void HWR_ClipPassWallSegment(INT32 first, INT32 last) +{ + cliprange_t *start; + float lowfrac, highfrac; + //to allow noclipwalls but still solidseg reject of non-visible walls + boolean poorhack = false; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = gl_solidsegs; + while (start->last < first - 1) + start++; + + if (first < start->first) + { + if (last < start->first-1) + { + // Post is entirely visible (above start). + HWR_StoreWallRange(0, 1); + return; + } + + // There is a fragment above *start. + if (!cv_glclipwalls.value) + { //20/08/99: Changed by Hurdler (taken from faB's code) + if (!poorhack) HWR_StoreWallRange(0, 1); + poorhack = true; + } + else + { + highfrac = HWR_ClipViewSegment(min(start->first + 1, + start->last), (polyvertex_t *)gl_curline->pv1, + (polyvertex_t *)gl_curline->pv2); + HWR_StoreWallRange(0, highfrac); + } + } + + // Bottom contained in start? + if (last <= start->last) + return; + + while (last >= (start+1)->first-1) + { + // There is a fragment between two posts. + if (!cv_glclipwalls.value) + { + if (!poorhack) HWR_StoreWallRange(0, 1); + poorhack = true; + } + else + { + lowfrac = HWR_ClipViewSegment(max(start->last-1,start->first), (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); + highfrac = HWR_ClipViewSegment(min((start+1)->first+1,(start+1)->last), (polyvertex_t *)gl_curline->pv1, (polyvertex_t *)gl_curline->pv2); + HWR_StoreWallRange(lowfrac, highfrac); + } + start++; + + if (last <= start->last) + return; + } + + if (first == start->first+1) // 1 line texture + { + if (!cv_glclipwalls.value) + { + if (!poorhack) HWR_StoreWallRange(0, 1); + poorhack = true; + } + else + HWR_StoreWallRange(0, 1); + } + else + { + // There is a fragment after *next. + if (!cv_glclipwalls.value) + { + if (!poorhack) HWR_StoreWallRange(0,1); + poorhack = true; + } + else + { + lowfrac = HWR_ClipViewSegment(max(start->last - 1, + start->first), (polyvertex_t *)gl_curline->pv1, + (polyvertex_t *)gl_curline->pv2); + HWR_StoreWallRange(lowfrac, 1); + } + } +} + +// -------------------------------------------------------------------------- +// HWR_ClipToSolidSegs check if it is hide by wall (solidsegs) +// -------------------------------------------------------------------------- +static boolean HWR_ClipToSolidSegs(INT32 first, INT32 last) +{ + cliprange_t * start; + + // Find the first range that touches the range + // (adjacent pixels are touching). + start = gl_solidsegs; + while (start->last < first-1) + start++; + + if (first < start->first) + return true; + + // Bottom contained in start? + if (last <= start->last) + return false; + + return true; +} + +// +// HWR_ClearClipSegs +// +static void HWR_ClearClipSegs(void) +{ + gl_solidsegs[0].first = -0x7fffffff; + gl_solidsegs[0].last = -1; + gl_solidsegs[1].first = vid.width; //viewwidth; + gl_solidsegs[1].last = 0x7fffffff; + hw_newend = gl_solidsegs+2; +} +#endif // NEWCLIP + +// -----------------+ +// HWR_AddLine : Clips the given segment and adds any visible pieces to the line list. +// Notes : gl_cursectorlight is set to the current subsector -> sector -> light value +// : (it may be mixed with the wall's own flat colour in the future ...) +// -----------------+ +static void HWR_AddLine(seg_t * line) { angle_t angle1, angle2; +#ifndef NEWCLIP + INT32 x1, x2; + angle_t span, tspan; + boolean bothceilingssky = false, bothfloorssky = false; +#endif // SoM: Backsector needs to be run through R_FakeFlat static sector_t tempsec; fixed_t v1x, v1y, v2x, v2y; // the seg's vertexes as fixed_t -#ifdef POLYOBJECTS if (line->polyseg && !(line->polyseg->flags & POF_RENDERSIDES)) return; -#endif - gr_curline = line; + gl_curline = line; - v1x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->x); - v1y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv1)->y); - v2x = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->x); - v2y = FLOAT_TO_FIXED(((polyvertex_t *)gr_curline->pv2)->y); + v1x = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->x); + v1y = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv1)->y); + v2x = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->x); + v2y = FLOAT_TO_FIXED(((polyvertex_t *)gl_curline->pv2)->y); // OPTIMIZE: quickly reject orthogonal back sides. - angle1 = R_PointToAngleEx(viewx, viewy, v1x, v1y); - angle2 = R_PointToAngleEx(viewx, viewy, v2x, v2y); + angle1 = R_PointToAngle64(v1x, v1y); + angle2 = R_PointToAngle64(v2x, v2y); +#ifdef NEWCLIP // PrBoom: Back side, i.e. backface culling - read: endAngle >= startAngle! if (angle2 - angle1 < ANGLE_180) return; // PrBoom: use REAL clipping math YAYYYYYYY!!! + if (!gld_clipper_SafeCheckRange(angle2, angle1)) + { return; + } checkforemptylines = true; +#else + // Clip to view edges. + span = angle1 - angle2; - gr_backsector = line->backsector; + // backface culling : span is < ANGLE_180 if ang1 > ang2 : the seg is facing + if (span >= ANGLE_180) + return; - if (!line->backsector) - gld_clipper_SafeAddClipRange(angle2, angle1); - else + // Global angle needed by segcalc. + //rw_angle1 = angle1; + angle1 -= dup_viewangle; + angle2 -= dup_viewangle; + + tspan = angle1 + gl_clipangle; + if (tspan > 2*gl_clipangle) { - gr_backsector = R_FakeFlat(gr_backsector, &tempsec, NULL, NULL, true); - if (CheckClip(gr_frontsector, gr_backsector)) + tspan -= 2*gl_clipangle; + + // Totally off the left edge? + if (tspan >= span) + return; + + angle1 = gl_clipangle; + } + tspan = gl_clipangle - angle2; + if (tspan > 2*gl_clipangle) + { + tspan -= 2*gl_clipangle; + + // Totally off the left edge? + if (tspan >= span) + return; + + angle2 = (angle_t)-(signed)gl_clipangle; + } + +#if 0 + { + float fx1,fx2,fy1,fy2; + //BP: test with a better projection than viewangletox[R_PointToAngle(angle)] + // do not enable this at release 4 mul and 2 div + fx1 = ((polyvertex_t *)(line->pv1))->x-gl_viewx; + fy1 = ((polyvertex_t *)(line->pv1))->y-gl_viewy; + fy2 = (fx1 * gl_viewcos + fy1 * gl_viewsin); + if (fy2 < 0) + // the point is back + fx1 = 0; + else + fx1 = gl_windowcenterx + (fx1 * gl_viewsin - fy1 * gl_viewcos) * gl_centerx / fy2; + + fx2 = ((polyvertex_t *)(line->pv2))->x-gl_viewx; + fy2 = ((polyvertex_t *)(line->pv2))->y-gl_viewy; + fy1 = (fx2 * gl_viewcos + fy2 * gl_viewsin); + if (fy1 < 0) + // the point is back + fx2 = vid.width; + else + fx2 = gl_windowcenterx + (fx2 * gl_viewsin - fy2 * gl_viewcos) * gl_centerx / fy1; + + x1 = fx1+0.5f; + x2 = fx2+0.5f; + } +#else + // The seg is in the view range, + // but not necessarily visible. + angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; + angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; + + x1 = gl_viewangletox[angle1]; + x2 = gl_viewangletox[angle2]; +#endif + // Does not cross a pixel? +// if (x1 == x2) +/* { + // BP: HERE IS THE MAIN PROBLEM ! + //CONS_Debug(DBG_RENDER, "tineline\n"); + return; + } +*/ +#endif + + gl_backsector = line->backsector; + +#ifdef NEWCLIP + if (!line->backsector) + { + gld_clipper_SafeAddClipRange(angle2, angle1); + } + else + { + boolean bothceilingssky = false, bothfloorssky = false; + + gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true); + + if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum) + bothceilingssky = true; + if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum) + bothfloorssky = true; + + if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then + { + if (!line->polyseg && + !line->sidedef->midtexture + && ((!gl_frontsector->ffloors && !gl_backsector->ffloors) + || (gl_frontsector->tag == gl_backsector->tag))) + return; // line is empty, don't even bother + // treat like wide open window instead + HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D + return; + } + + if (CheckClip(line, gl_frontsector, gl_backsector)) { gld_clipper_SafeAddClipRange(angle2, angle1); checkforemptylines = false; @@ -2046,12 +2441,120 @@ void HWR_AddLine(seg_t *line) // Identical floor and ceiling on both sides, // identical light levels on both sides, // and no middle texture. - if (checkforemptylines && R_IsEmptyLine(line, gr_frontsector, gr_backsector)) + if (checkforemptylines && R_IsEmptyLine(line, gl_frontsector, gl_backsector)) return; } HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D return; +#else + // Single sided line? + if (!gl_backsector) + goto clipsolid; + + gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true); + + if (gl_backsector->ceilingpic == skyflatnum && gl_frontsector->ceilingpic == skyflatnum) + bothceilingssky = true; + if (gl_backsector->floorpic == skyflatnum && gl_frontsector->floorpic == skyflatnum) + bothfloorssky = true; + + if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then + { + if (!line->polyseg && + !line->sidedef->midtexture + && ((!gl_frontsector->ffloors && !gl_backsector->ffloors) + || (gl_frontsector->tag == gl_backsector->tag))) + return; // line is empty, don't even bother + + goto clippass; // treat like wide open window instead + } + + if (gl_frontsector->f_slope || gl_frontsector->c_slope || gl_backsector->f_slope || gl_backsector->c_slope) + { + fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends + fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends + +#define SLOPEPARAMS(slope, end1, end2, normalheight) \ + end1 = P_GetZAt(slope, v1x, v1y, normalheight); \ + end2 = P_GetZAt(slope, v2x, v2y, normalheight); + + SLOPEPARAMS(gl_frontsector->f_slope, frontf1, frontf2, gl_frontsector-> floorheight) + SLOPEPARAMS(gl_frontsector->c_slope, frontc1, frontc2, gl_frontsector->ceilingheight) + SLOPEPARAMS( gl_backsector->f_slope, backf1, backf2, gl_backsector-> floorheight) + SLOPEPARAMS( gl_backsector->c_slope, backc1, backc2, gl_backsector->ceilingheight) +#undef SLOPEPARAMS + // if both ceilings are skies, consider it always "open" + // same for floors + if (!bothceilingssky && !bothfloorssky) + { + // Closed door. + if ((backc1 <= frontf1 && backc2 <= frontf2) + || (backf1 >= frontc1 && backf2 >= frontc2)) + { + goto clipsolid; + } + + // Check for automap fix. + if (backc1 <= backf1 && backc2 <= backf2 + && ((backc1 >= frontc1 && backc2 >= frontc2) || gl_curline->sidedef->toptexture) + && ((backf1 <= frontf1 && backf2 >= frontf2) || gl_curline->sidedef->bottomtexture)) + goto clipsolid; + } + + // Window. + if (!bothceilingssky) // ceilings are always the "same" when sky + if (backc1 != frontc1 || backc2 != frontc2) + goto clippass; + if (!bothfloorssky) // floors are always the "same" when sky + if (backf1 != frontf1 || backf2 != frontf2) + goto clippass; + } + else + { + // if both ceilings are skies, consider it always "open" + // same for floors + if (!bothceilingssky && !bothfloorssky) + { + // Closed door. + if (gl_backsector->ceilingheight <= gl_frontsector->floorheight || + gl_backsector->floorheight >= gl_frontsector->ceilingheight) + goto clipsolid; + + // Check for automap fix. + if (gl_backsector->ceilingheight <= gl_backsector->floorheight + && ((gl_backsector->ceilingheight >= gl_frontsector->ceilingheight) || gl_curline->sidedef->toptexture) + && ((gl_backsector->floorheight <= gl_backsector->floorheight) || gl_curline->sidedef->bottomtexture)) + goto clipsolid; + } + + // Window. + if (!bothceilingssky) // ceilings are always the "same" when sky + if (gl_backsector->ceilingheight != gl_frontsector->ceilingheight) + goto clippass; + if (!bothfloorssky) // floors are always the "same" when sky + if (gl_backsector->floorheight != gl_frontsector->floorheight) + goto clippass; + } + + // Reject empty lines used for triggers and special events. + // Identical floor and ceiling on both sides, + // identical light levels on both sides, + // and no middle texture. + if (R_IsEmptyLine(gl_curline, gl_frontsector, gl_backsector)) + return; + +clippass: + if (x1 == x2) + { x2++;x1 -= 2; } + HWR_ClipPassWallSegment(x1, x2-1); + return; + +clipsolid: + if (x1 == x2) + goto clippass; + HWR_ClipSolidWallSegment(x1, x2-1); +#endif } // HWR_CheckBBox @@ -2061,24 +2564,28 @@ void HWR_AddLine(seg_t *line) // // modified to use local variables -boolean HWR_CheckBBox(fixed_t *bspcoord) +static boolean HWR_CheckBBox(fixed_t *bspcoord) { INT32 boxpos; fixed_t px1, py1, px2, py2; angle_t angle1, angle2; +#ifndef NEWCLIP + INT32 sx1, sx2; + angle_t span, tspan; +#endif // Find the corners of the box // that define the edges from current viewpoint. - if (viewx <= bspcoord[BOXLEFT]) + if (dup_viewx <= bspcoord[BOXLEFT]) boxpos = 0; - else if (viewx < bspcoord[BOXRIGHT]) + else if (dup_viewx < bspcoord[BOXRIGHT]) boxpos = 1; else boxpos = 2; - if (viewy >= bspcoord[BOXTOP]) + if (dup_viewy >= bspcoord[BOXTOP]) boxpos |= 0; - else if (viewy > bspcoord[BOXBOTTOM]) + else if (dup_viewy > bspcoord[BOXBOTTOM]) boxpos |= 1<<2; else boxpos |= 2<<2; @@ -2091,12 +2598,60 @@ boolean HWR_CheckBBox(fixed_t *bspcoord) px2 = bspcoord[checkcoord[boxpos][2]]; py2 = bspcoord[checkcoord[boxpos][3]]; - angle1 = R_PointToAngleEx(viewx, viewy, px1, py1); - angle2 = R_PointToAngleEx(viewx, viewy, px2, py2); +#ifdef NEWCLIP + angle1 = R_PointToAngle64(px1, py1); + angle2 = R_PointToAngle64(px2, py2); return gld_clipper_SafeCheckRange(angle2, angle1); -} +#else + // check clip list for an open space + angle1 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px1>>1, py1>>1) - dup_viewangle; + angle2 = R_PointToAngle2(dup_viewx>>1, dup_viewy>>1, px2>>1, py2>>1) - dup_viewangle; -#ifdef POLYOBJECTS + span = angle1 - angle2; + + // Sitting on a line? + if (span >= ANGLE_180) + return true; + + tspan = angle1 + gl_clipangle; + + if (tspan > 2*gl_clipangle) + { + tspan -= 2*gl_clipangle; + + // Totally off the left edge? + if (tspan >= span) + return false; + + angle1 = gl_clipangle; + } + tspan = gl_clipangle - angle2; + if (tspan > 2*gl_clipangle) + { + tspan -= 2*gl_clipangle; + + // Totally off the left edge? + if (tspan >= span) + return false; + + angle2 = (angle_t)-(signed)gl_clipangle; + } + + // Find the first clippost + // that touches the source post + // (adjacent pixels are touching). + angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; + angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; + sx1 = gl_viewangletox[angle1]; + sx2 = gl_viewangletox[angle2]; + + // Does not cross a pixel. + if (sx1 == sx2) + return false; + + return HWR_ClipToSolidSegs(sx1, sx2 - 1); +#endif +} // // HWR_AddPolyObjectSegs @@ -2105,10 +2660,10 @@ boolean HWR_CheckBBox(fixed_t *bspcoord) // Adds all segs in all polyobjects in the given subsector. // Modified for hardware rendering. // -void HWR_AddPolyObjectSegs(void) +static inline void HWR_AddPolyObjectSegs(void) { size_t i, j; - seg_t *gr_fakeline = Z_Calloc(sizeof(seg_t), PU_STATIC, NULL); + seg_t *gl_fakeline = Z_Calloc(sizeof(seg_t), PU_STATIC, NULL); polyvertex_t *pv1 = Z_Calloc(sizeof(polyvertex_t), PU_STATIC, NULL); polyvertex_t *pv2 = Z_Calloc(sizeof(polyvertex_t), PU_STATIC, NULL); @@ -2119,41 +2674,42 @@ void HWR_AddPolyObjectSegs(void) for (j = 0; j < po_ptrs[i]->segCount; ++j) { // Copy the info of a polyobject's seg, then convert it to OpenGL floating point - M_Memcpy(gr_fakeline, po_ptrs[i]->segs[j], sizeof(seg_t)); + M_Memcpy(gl_fakeline, po_ptrs[i]->segs[j], sizeof(seg_t)); // Now convert the line to float and add it to be rendered - pv1->x = FIXED_TO_FLOAT(gr_fakeline->v1->x); - pv1->y = FIXED_TO_FLOAT(gr_fakeline->v1->y); - pv2->x = FIXED_TO_FLOAT(gr_fakeline->v2->x); - pv2->y = FIXED_TO_FLOAT(gr_fakeline->v2->y); + pv1->x = FIXED_TO_FLOAT(gl_fakeline->v1->x); + pv1->y = FIXED_TO_FLOAT(gl_fakeline->v1->y); + pv2->x = FIXED_TO_FLOAT(gl_fakeline->v2->x); + pv2->y = FIXED_TO_FLOAT(gl_fakeline->v2->y); - gr_fakeline->pv1 = pv1; - gr_fakeline->pv2 = pv2; + gl_fakeline->pv1 = pv1; + gl_fakeline->pv2 = pv2; - HWR_AddLine(gr_fakeline); + HWR_AddLine(gl_fakeline); } } // Free temporary data no longer needed Z_Free(pv2); Z_Free(pv1); - Z_Free(gr_fakeline); + Z_Free(gl_fakeline); } -#ifdef POLYOBJECTS_PLANES -void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap) +static void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, + FBITFIELD blendmode, UINT8 lightlevel, levelflat_t *levelflat, sector_t *FOFsector, + UINT8 alpha, extracolormap_t *planecolormap) { float height; //constant y for all points on the convex flat polygon FOutVector *v3d; INT32 i; float flatxref,flatyref; - float fflatsize; - INT32 flatflag; - size_t len; + float fflatwidth = 64.0f, fflatheight = 64.0f; + INT32 flatflag = 63; + boolean texflat = false; float scrollx = 0.0f, scrolly = 0.0f; angle_t angle = 0; FSurfaceInfo Surf; - fixed_t tempxsow, tempytow; + fixed_t tempxs, tempyt; size_t nrPlaneVerts; static FOutVector *planeVerts = NULL; @@ -2166,7 +2722,7 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t if (nrPlaneVerts < 3) //not even a triangle ? return; - if (nrPlaneVerts > INT16_MAX) // FIXME: exceeds plVerts size + if (nrPlaneVerts > (size_t)UINT16_MAX) // FIXME: exceeds plVerts size { CONS_Debug(DBG_RENDER, "polygon size of %s exceeds max value of %d vertices\n", sizeu1(nrPlaneVerts), UINT16_MAX); return; @@ -2180,43 +2736,62 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t Z_Malloc(numAllocedPlaneVerts * sizeof (FOutVector), PU_LEVEL, &planeVerts); } - len = W_LumpLength(lumpnum); - - switch (len) + // set texture for polygon + if (levelflat != NULL) { - case 4194304: // 2048x2048 lump - fflatsize = 2048.0f; - flatflag = 2047; - break; - case 1048576: // 1024x1024 lump - fflatsize = 1024.0f; - flatflag = 1023; - break; - case 262144:// 512x512 lump - fflatsize = 512.0f; - flatflag = 511; - break; - case 65536: // 256x256 lump - fflatsize = 256.0f; - flatflag = 255; - break; - case 16384: // 128x128 lump - fflatsize = 128.0f; - flatflag = 127; - break; - case 1024: // 32x32 lump - fflatsize = 32.0f; - flatflag = 31; - break; - default: // 64x64 lump - fflatsize = 64.0f; - flatflag = 63; - break; + if (levelflat->type == LEVELFLAT_FLAT) + { + size_t len = W_LumpLength(levelflat->u.flat.lumpnum); + switch (len) + { + case 4194304: // 2048x2048 lump + fflatwidth = fflatheight = 2048.0f; + break; + case 1048576: // 1024x1024 lump + fflatwidth = fflatheight = 1024.0f; + break; + case 262144:// 512x512 lump + fflatwidth = fflatheight = 512.0f; + break; + case 65536: // 256x256 lump + fflatwidth = fflatheight = 256.0f; + break; + case 16384: // 128x128 lump + fflatwidth = fflatheight = 128.0f; + break; + case 1024: // 32x32 lump + fflatwidth = fflatheight = 32.0f; + break; + default: // 64x64 lump + fflatwidth = fflatheight = 64.0f; + break; + } + flatflag = ((INT32)fflatwidth)-1; + } + else + { + if (levelflat->type == LEVELFLAT_TEXTURE) + { + fflatwidth = textures[levelflat->u.texture.num]->width; + fflatheight = textures[levelflat->u.texture.num]->height; + } + else if (levelflat->type == LEVELFLAT_PATCH || levelflat->type == LEVELFLAT_PNG) + { + fflatwidth = levelflat->width; + fflatheight = levelflat->height; + } + texflat = true; + } } + else // set no texture + HWR_SetCurrentTexture(NULL); // reference point for flat texture coord for each vertex around the polygon - flatxref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].x) & (~flatflag)) / fflatsize); - flatyref = (float)(((fixed_t)FIXED_TO_FLOAT(polysector->origVerts[0].y) & (~flatflag)) / fflatsize); + flatxref = FIXED_TO_FLOAT(polysector->origVerts[0].x); + flatyref = FIXED_TO_FLOAT(polysector->origVerts[0].y); + + flatxref = (float)(((fixed_t)flatxref & (~flatflag)) / fflatwidth); + flatyref = (float)(((fixed_t)flatyref & (~flatflag)) / fflatheight); // transform v3d = planeVerts; @@ -2225,62 +2800,73 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatsize; - angle = FOFsector->floorpic_angle>>ANGLETOFINESHIFT; + scrollx = FIXED_TO_FLOAT(FOFsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->floor_yoffs)/fflatheight; + angle = FOFsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatsize; - angle = FOFsector->ceilingpic_angle>>ANGLETOFINESHIFT; + scrollx = FIXED_TO_FLOAT(FOFsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(FOFsector->ceiling_yoffs)/fflatheight; + angle = FOFsector->ceilingpic_angle; } } - else if (gr_frontsector) + else if (gl_frontsector) { if (!isceiling) // it's a floor { - scrollx = FIXED_TO_FLOAT(gr_frontsector->floor_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->floor_yoffs)/fflatsize; - angle = gr_frontsector->floorpic_angle>>ANGLETOFINESHIFT; + scrollx = FIXED_TO_FLOAT(gl_frontsector->floor_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gl_frontsector->floor_yoffs)/fflatheight; + angle = gl_frontsector->floorpic_angle; } else // it's a ceiling { - scrollx = FIXED_TO_FLOAT(gr_frontsector->ceiling_xoffs)/fflatsize; - scrolly = FIXED_TO_FLOAT(gr_frontsector->ceiling_yoffs)/fflatsize; - angle = gr_frontsector->ceilingpic_angle>>ANGLETOFINESHIFT; + scrollx = FIXED_TO_FLOAT(gl_frontsector->ceiling_xoffs)/fflatwidth; + scrolly = FIXED_TO_FLOAT(gl_frontsector->ceiling_yoffs)/fflatheight; + angle = gl_frontsector->ceilingpic_angle; } } if (angle) // Only needs to be done if there's an altered angle { + angle = (InvAngle(angle))>>ANGLETOFINESHIFT; + // This needs to be done so that it scrolls in a different direction after rotation like software - tempxsow = FLOAT_TO_FIXED(scrollx); - tempytow = FLOAT_TO_FIXED(scrolly); - scrollx = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - scrolly = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + /*tempxs = FLOAT_TO_FIXED(scrollx); + tempyt = FLOAT_TO_FIXED(scrolly); + scrollx = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + scrolly = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle))));*/ // This needs to be done so everything aligns after rotation // It would be done so that rotation is done, THEN the translation, but I couldn't get it to rotate AND scroll like software does - tempxsow = FLOAT_TO_FIXED(flatxref); - tempytow = FLOAT_TO_FIXED(flatyref); - flatxref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - flatyref = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINESINE(angle)) + FixedMul(tempytow, FINECOSINE(angle)))); + tempxs = FLOAT_TO_FIXED(flatxref); + tempyt = FLOAT_TO_FIXED(flatyref); + flatxref = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + flatyref = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle)))); } for (i = 0; i < (INT32)nrPlaneVerts; i++,v3d++) { - // Hurdler: add scrolling texture on floor/ceiling - v3d->s = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatsize) - flatxref + scrollx); // Go from the polysector's original vertex locations - v3d->t = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatsize) + scrolly); // Means the flat is offset based on the original vertex locations + // Go from the polysector's original vertex locations + // Means the flat is offset based on the original vertex locations + if (texflat) + { + v3d->s = (float)(FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) + scrollx; + v3d->t = -(float)(FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly; + } + else + { + v3d->s = (float)((FIXED_TO_FLOAT(polysector->origVerts[i].x) / fflatwidth) - flatxref + scrollx); + v3d->t = (float)(flatyref - (FIXED_TO_FLOAT(polysector->origVerts[i].y) / fflatheight) + scrolly); + } // Need to rotate before translate if (angle) // Only needs to be done if there's an altered angle { - tempxsow = FLOAT_TO_FIXED(v3d->s); - tempytow = FLOAT_TO_FIXED(v3d->t); - v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxsow, FINECOSINE(angle)) - FixedMul(tempytow, FINESINE(angle)))); - v3d->t = (FIXED_TO_FLOAT(-FixedMul(tempxsow, FINESINE(angle)) - FixedMul(tempytow, FINECOSINE(angle)))); + tempxs = FLOAT_TO_FIXED(v3d->s); + tempyt = FLOAT_TO_FIXED(v3d->t); + v3d->s = (FIXED_TO_FLOAT(FixedMul(tempxs, FINECOSINE(angle)) - FixedMul(tempyt, FINESINE(angle)))); + v3d->t = (FIXED_TO_FLOAT(FixedMul(tempxs, FINESINE(angle)) + FixedMul(tempyt, FINECOSINE(angle)))); } v3d->x = FIXED_TO_FLOAT(polysector->vertices[i]->x); @@ -2288,24 +2874,25 @@ void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t v3d->z = FIXED_TO_FLOAT(polysector->vertices[i]->y); } + HWR_Lighting(&Surf, lightlevel, planecolormap); if (blendmode & PF_Translucent) { Surf.PolyColor.s.alpha = (UINT8)alpha; - blendmode |= PF_Modulated|PF_Occlude; + blendmode |= PF_Modulated|PF_Occlude|PF_Clip; } else - blendmode |= PF_Masked|PF_Modulated; + blendmode |= PF_Masked|PF_Modulated|PF_Clip; - HWD.pfnSetShader(1); // floor shader - HWD.pfnDrawPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode); + HWR_ProcessPolygon(&Surf, planeVerts, nrPlaneVerts, blendmode, SHADER_FLOOR, false); // floor shader } -void HWR_AddPolyObjectPlanes(void) +static void HWR_AddPolyObjectPlanes(void) { size_t i; sector_t *polyobjsector; + INT32 light = 0; // Polyobject Planes need their own function for drawing because they don't have extrasubsectors by themselves // It should be okay because polyobjects should always be convex anyway @@ -2317,61 +2904,64 @@ void HWR_AddPolyObjectPlanes(void) if (!(po_ptrs[i]->flags & POF_RENDERPLANES)) // Only render planes when you should continue; - if (po_ptrs[i]->translucency >= NUMTRANSMAPS) + if (po_ptrs[i]->translucency >= NUMEFFECTMAPS) continue; - if (polyobjsector->floorheight <= gr_frontsector->ceilingheight - && polyobjsector->floorheight >= gr_frontsector->floorheight + if (polyobjsector->floorheight <= gl_frontsector->ceilingheight + && polyobjsector->floorheight >= gl_frontsector->floorheight && (viewz < polyobjsector->floorheight)) { - if (po_ptrs[i]->translucency > 0) - { - FSurfaceInfo Surf; - FBITFIELD blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->floorpic].lumpnum, po_ptrs[i], false, polyobjsector->floorheight, - polyobjsector->lightlevel, Surf.PolyColor.s.alpha, polyobjsector, blendmode, NULL); - } - else - { - HWR_GetFlat(levelflats[polyobjsector->floorpic].lumpnum, R_NoEncore(polyobjsector, false)); - HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, - polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, - polyobjsector, 255, NULL); - } - } - - if (polyobjsector->ceilingheight >= gr_frontsector->floorheight - && polyobjsector->ceilingheight <= gr_frontsector->ceilingheight - && (viewz > polyobjsector->ceilingheight)) - { + light = R_GetPlaneLight(gl_frontsector, polyobjsector->floorheight, true); if (po_ptrs[i]->translucency > 0) { FSurfaceInfo Surf; FBITFIELD blendmode; memset(&Surf, 0x00, sizeof(Surf)); blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); - HWR_AddTransparentPolyobjectFloor(levelflats[polyobjsector->ceilingpic].lumpnum, po_ptrs[i], true, polyobjsector->ceilingheight, - polyobjsector->lightlevel, Surf.PolyColor.s.alpha, polyobjsector, blendmode, NULL); + HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->floorpic], po_ptrs[i], false, polyobjsector->floorheight, + (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap)); } else { - HWR_GetFlat(levelflats[polyobjsector->ceilingpic].lumpnum, R_NoEncore(polyobjsector, true)); + HWR_GetLevelFlat(&levelflats[polyobjsector->floorpic], R_NoEncore(polyobjsector, false)); + HWR_RenderPolyObjectPlane(po_ptrs[i], false, polyobjsector->floorheight, PF_Occlude, + (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->floorpic], + polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap)); + } + } + + if (polyobjsector->ceilingheight >= gl_frontsector->floorheight + && polyobjsector->ceilingheight <= gl_frontsector->ceilingheight + && (viewz > polyobjsector->ceilingheight)) + { + light = R_GetPlaneLight(gl_frontsector, polyobjsector->ceilingheight, true); + if (po_ptrs[i]->translucency > 0) + { + FSurfaceInfo Surf; + FBITFIELD blendmode; + memset(&Surf, 0x00, sizeof(Surf)); + blendmode = HWR_TranstableToAlpha(po_ptrs[i]->translucency, &Surf); + HWR_AddTransparentPolyobjectFloor(&levelflats[polyobjsector->ceilingpic], po_ptrs[i], true, polyobjsector->ceilingheight, + (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), Surf.PolyColor.s.alpha, polyobjsector, blendmode, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap)); + } + else + { + HWR_GetLevelFlat(&levelflats[polyobjsector->ceilingpic], R_NoEncore(polyobjsector, true)); HWR_RenderPolyObjectPlane(po_ptrs[i], true, polyobjsector->ceilingheight, PF_Occlude, - polyobjsector->lightlevel, levelflats[polyobjsector->floorpic].lumpnum, - polyobjsector, 255, NULL); + (light == -1 ? gl_frontsector->lightlevel : *gl_frontsector->lightlist[light].lightlevel), &levelflats[polyobjsector->ceilingpic], + polyobjsector, 255, (light == -1 ? gl_frontsector->extra_colormap : *gl_frontsector->lightlist[light].extra_colormap)); } } } } -#endif -#endif // -----------------+ // HWR_Subsector : Determine floor/ceiling planes. // : Add sprites of things in sector. // : Draw one or more line segments. +// Notes : Sets gl_cursectorlight to the light of the parent sector, to modulate wall textures // -----------------+ -void HWR_Subsector(size_t num) +static void HWR_Subsector(size_t num) { INT16 count; seg_t *line; @@ -2389,6 +2979,11 @@ void HWR_Subsector(size_t num) if (num >= addsubsector) I_Error("HWR_Subsector: ss %s with numss = %s, addss = %s\n", sizeu1(num), sizeu2(numsubsectors), sizeu3(addsubsector)); + + /*if (num >= numsubsectors) + I_Error("HWR_Subsector: ss %i with numss = %i", + num, + numsubsectors);*/ #endif if (num < numsubsectors) @@ -2396,7 +2991,7 @@ void HWR_Subsector(size_t num) // subsector sub = &subsectors[num]; // sector - gr_frontsector = sub->sector; + gl_frontsector = sub->sector; // how many linedefs count = sub->numlines; // first line seg @@ -2406,139 +3001,124 @@ void HWR_Subsector(size_t num) { // there are no segs but only planes sub = &subsectors[0]; - gr_frontsector = sub->sector; + gl_frontsector = sub->sector; count = 0; line = NULL; } //SoM: 4/7/2000: Test to make Boom water work in Hardware mode. - gr_frontsector = R_FakeFlat(gr_frontsector, &tempsec, &floorlightlevel, + gl_frontsector = R_FakeFlat(gl_frontsector, &tempsec, &floorlightlevel, &ceilinglightlevel, false); //FIXME: Use floorlightlevel and ceilinglightlevel insted of lightlevel. - floorcolormap = ceilingcolormap = gr_frontsector->extra_colormap; + floorcolormap = ceilingcolormap = gl_frontsector->extra_colormap; -// ----- for special tricks with HW renderer ----- - if (gr_frontsector->pseudoSector) - { - cullFloorHeight = locFloorHeight = gr_frontsector->virtualFloorheight; - cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight; - } - else if (gr_frontsector->virtualFloor) - { - ///@TODO Is this whole virtualFloor mess even useful? I don't think it even triggers ever. - cullFloorHeight = locFloorHeight = gr_frontsector->virtualFloorheight; - if (gr_frontsector->virtualCeiling) - cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight; - else - cullCeilingHeight = locCeilingHeight = gr_frontsector->ceilingheight; - } - else if (gr_frontsector->virtualCeiling) - { - cullCeilingHeight = locCeilingHeight = gr_frontsector->virtualCeilingheight; - cullFloorHeight = locFloorHeight = gr_frontsector->floorheight; - } - else - { - cullFloorHeight = locFloorHeight = gr_frontsector->floorheight; - cullCeilingHeight = locCeilingHeight = gr_frontsector->ceilingheight; + // ------------------------------------------------------------------------ + // sector lighting, DISABLED because it's done in HWR_StoreWallRange + // ------------------------------------------------------------------------ + /// \todo store a RGBA instead of just intensity, allow coloured sector lighting + //light = (FUBYTE)(sub->sector->lightlevel & 0xFF) / 255.0f; + //gl_cursectorlight.red = light; + //gl_cursectorlight.green = light; + //gl_cursectorlight.blue = light; + //gl_cursectorlight.alpha = light; -#ifdef ESLOPE - if (gr_frontsector->f_slope) - { - cullFloorHeight = P_GetZAt(gr_frontsector->f_slope, viewx, viewy); - locFloorHeight = P_GetZAt(gr_frontsector->f_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); - } - - if (gr_frontsector->c_slope) - { - cullCeilingHeight = P_GetZAt(gr_frontsector->c_slope, viewx, viewy); - locCeilingHeight = P_GetZAt(gr_frontsector->c_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); - } -#endif - } // ----- end special tricks ----- + cullFloorHeight = P_GetSectorFloorZAt (gl_frontsector, viewx, viewy); + cullCeilingHeight = P_GetSectorCeilingZAt(gl_frontsector, viewx, viewy); + locFloorHeight = P_GetSectorFloorZAt (gl_frontsector, gl_frontsector->soundorg.x, gl_frontsector->soundorg.y); + locCeilingHeight = P_GetSectorCeilingZAt(gl_frontsector, gl_frontsector->soundorg.x, gl_frontsector->soundorg.y); - if (gr_frontsector->ffloors) + if (gl_frontsector->ffloors) { - if (gr_frontsector->moved) + if (gl_frontsector->moved) { - gr_frontsector->numlights = sub->sector->numlights = 0; - R_Prep3DFloors(gr_frontsector); - sub->sector->lightlist = gr_frontsector->lightlist; - sub->sector->numlights = gr_frontsector->numlights; - sub->sector->moved = gr_frontsector->moved = false; + gl_frontsector->numlights = sub->sector->numlights = 0; + R_Prep3DFloors(gl_frontsector); + sub->sector->lightlist = gl_frontsector->lightlist; + sub->sector->numlights = gl_frontsector->numlights; + sub->sector->moved = gl_frontsector->moved = false; } - light = R_GetPlaneLight(gr_frontsector, locFloorHeight, false); - if (gr_frontsector->floorlightsec == -1) - floorlightlevel = *gr_frontsector->lightlist[light].lightlevel; - floorcolormap = gr_frontsector->lightlist[light].extra_colormap; + light = R_GetPlaneLight(gl_frontsector, locFloorHeight, false); + if (gl_frontsector->floorlightsec == -1) + floorlightlevel = *gl_frontsector->lightlist[light].lightlevel; + floorcolormap = *gl_frontsector->lightlist[light].extra_colormap; - light = R_GetPlaneLight(gr_frontsector, locCeilingHeight, false); - if (gr_frontsector->ceilinglightsec == -1) - ceilinglightlevel = *gr_frontsector->lightlist[light].lightlevel; - ceilingcolormap = gr_frontsector->lightlist[light].extra_colormap; + light = R_GetPlaneLight(gl_frontsector, locCeilingHeight, false); + if (gl_frontsector->ceilinglightsec == -1) + ceilinglightlevel = *gl_frontsector->lightlist[light].lightlevel; + ceilingcolormap = *gl_frontsector->lightlist[light].extra_colormap; } - sub->sector->extra_colormap = gr_frontsector->extra_colormap; - - //R_PlaneLightOverride(gr_frontsector, false, &floorlightlevel); - //R_PlaneLightOverride(gr_frontsector, true, &ceilinglightlevel); + sub->sector->extra_colormap = gl_frontsector->extra_colormap; // render floor ? +#ifdef DOPLANES // yeah, easy backface cull! :) - if (cullFloorHeight < viewz) + if (cullFloorHeight < dup_viewz) { - if (gr_frontsector->floorpic != skyflatnum) + if (gl_frontsector->floorpic != skyflatnum) { if (sub->validcount != validcount) { - HWR_GetFlat(levelflats[gr_frontsector->floorpic].lumpnum, R_NoEncore(gr_frontsector, false)); - HWR_RenderPlane(&extrasubsectors[num], false, + HWR_GetLevelFlat(&levelflats[gl_frontsector->floorpic], R_NoEncore(gl_frontsector, false)); + HWR_RenderPlane(sub, &extrasubsectors[num], false, // Hack to make things continue to work around slopes. - locFloorHeight == cullFloorHeight ? locFloorHeight : gr_frontsector->floorheight, + locFloorHeight == cullFloorHeight ? locFloorHeight : gl_frontsector->floorheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, floorlightlevel, levelflats[gr_frontsector->floorpic].lumpnum, NULL, 255, floorcolormap); + PF_Occlude, floorlightlevel, &levelflats[gl_frontsector->floorpic], NULL, 255, floorcolormap); } } + else + { +#ifdef POLYSKY + HWR_RenderSkyPlane(&extrasubsectors[num], locFloorHeight); +#endif + } } - if (cullCeilingHeight > viewz) + if (cullCeilingHeight > dup_viewz) { - if (gr_frontsector->ceilingpic != skyflatnum) + if (gl_frontsector->ceilingpic != skyflatnum) { if (sub->validcount != validcount) { - HWR_GetFlat(levelflats[gr_frontsector->ceilingpic].lumpnum, R_NoEncore(gr_frontsector, true)); - HWR_RenderPlane(&extrasubsectors[num], true, + HWR_GetLevelFlat(&levelflats[gl_frontsector->ceilingpic], R_NoEncore(gl_frontsector, true)); + HWR_RenderPlane(sub, &extrasubsectors[num], true, // Hack to make things continue to work around slopes. - locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gr_frontsector->ceilingheight, + locCeilingHeight == cullCeilingHeight ? locCeilingHeight : gl_frontsector->ceilingheight, // We now return you to your regularly scheduled rendering. - PF_Occlude, ceilinglightlevel, levelflats[gr_frontsector->ceilingpic].lumpnum,NULL, 255, ceilingcolormap); + PF_Occlude, ceilinglightlevel, &levelflats[gl_frontsector->ceilingpic], NULL, 255, ceilingcolormap); } } + else + { +#ifdef POLYSKY + HWR_RenderSkyPlane(&extrasubsectors[num], locCeilingHeight); +#endif + } } - if (gr_frontsector->ffloors) +#ifndef POLYSKY + // Moved here because before, when above the ceiling and the floor does not have the sky flat, it doesn't draw the sky + if (gl_frontsector->ceilingpic == skyflatnum || gl_frontsector->floorpic == skyflatnum) + drawsky = true; +#endif + +#ifdef R_FAKEFLOORS + if (gl_frontsector->ffloors) { /// \todo fix light, xoffs, yoffs, extracolormap ? ffloor_t * rover; - for (rover = gr_frontsector->ffloors; + for (rover = gl_frontsector->ffloors; rover; rover = rover->next) { fixed_t cullHeight, centerHeight; // bottom plane -#ifdef ESLOPE - if (*rover->b_slope) - { - cullHeight = P_GetZAt(*rover->b_slope, viewx, viewy); - centerHeight = P_GetZAt(*rover->b_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); - } - else -#endif - cullHeight = centerHeight = *rover->bottomheight; + cullHeight = P_GetFFloorBottomZAt(rover, viewx, viewy); + centerHeight = P_GetFFloorBottomZAt(rover, gl_frontsector->soundorg.x, gl_frontsector->soundorg.y); if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES)) continue; @@ -2547,100 +3127,110 @@ void HWR_Subsector(size_t num) if (centerHeight <= locCeilingHeight && centerHeight >= locFloorHeight && - ((viewz < cullHeight && !(rover->flags & FF_INVERTPLANES)) || - (viewz > cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) + ((dup_viewz < cullHeight && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) || + (dup_viewz > cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { if (rover->flags & FF_FOG) { UINT8 alpha; - light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); - - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); + light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], false, *rover->bottomheight, - *gr_frontsector->lightlist[light].lightlevel, + *gl_frontsector->lightlist[light].lightlevel, alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) // SoM: Flags are more efficient + else if (rover->flags & FF_TRANSLUCENT + && (rover->alpha < 256 + || rover->alpha == FFLOOR_ALPHA_SPECIAL_ADDITIVE || rover->alpha == FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE)) // SoM: Flags are more efficient { - light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); - HWR_AddTransparentFloor(levelflats[*rover->bottompic].lumpnum, + FBITFIELD blendmode = PF_Translucent; + if (rover->alpha == FFLOOR_ALPHA_SPECIAL_ADDITIVE) + blendmode = PF_Additive; + else if (rover->alpha == FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE) + blendmode = PF_Substractive; + + light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + + HWR_AddTransparentFloor(&levelflats[*rover->bottompic], &extrasubsectors[num], false, *rover->bottomheight, - *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, - false, gr_frontsector->lightlist[light].extra_colormap); + *gl_frontsector->lightlist[light].lightlevel, + rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|blendmode, + false, *gl_frontsector->lightlist[light].extra_colormap); } else { - HWR_GetFlat(levelflats[*rover->bottompic].lumpnum, R_NoEncore(gr_frontsector, false)); - light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); - HWR_RenderPlane(&extrasubsectors[num], false, *rover->bottomheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->bottompic].lumpnum, - rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap); + HWR_GetLevelFlat(&levelflats[*rover->bottompic], R_NoEncore(gl_frontsector, false)); + light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + HWR_RenderPlane(sub, &extrasubsectors[num], false, *rover->bottomheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->bottompic], + rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } // top plane -#ifdef ESLOPE - if (*rover->t_slope) - { - cullHeight = P_GetZAt(*rover->t_slope, viewx, viewy); - centerHeight = P_GetZAt(*rover->t_slope, gr_frontsector->soundorg.x, gr_frontsector->soundorg.y); - } - else -#endif - cullHeight = centerHeight = *rover->topheight; + cullHeight = P_GetFFloorTopZAt(rover, viewx, viewy); + centerHeight = P_GetFFloorTopZAt(rover, gl_frontsector->soundorg.x, gl_frontsector->soundorg.y); if (centerHeight >= locFloorHeight && centerHeight <= locCeilingHeight && - ((viewz > cullHeight && !(rover->flags & FF_INVERTPLANES)) || - (viewz < cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) + ((dup_viewz > cullHeight && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) || + (dup_viewz < cullHeight && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { if (rover->flags & FF_FOG) { UINT8 alpha; - light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); - - alpha = HWR_FogBlockAlpha(*gr_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); + light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + alpha = HWR_FogBlockAlpha(*gl_frontsector->lightlist[light].lightlevel, rover->master->frontsector->extra_colormap); HWR_AddTransparentFloor(0, &extrasubsectors[num], true, *rover->topheight, - *gr_frontsector->lightlist[light].lightlevel, + *gl_frontsector->lightlist[light].lightlevel, alpha, rover->master->frontsector, PF_Fog|PF_NoTexture, true, rover->master->frontsector->extra_colormap); } - else if (rover->flags & FF_TRANSLUCENT && rover->alpha < 256) + else if (rover->flags & FF_TRANSLUCENT + && (rover->alpha < 256 + || rover->alpha == FFLOOR_ALPHA_SPECIAL_ADDITIVE || rover->alpha == FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE)) // SoM: Flags are more efficient { - light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); - HWR_AddTransparentFloor(levelflats[*rover->toppic].lumpnum, + FBITFIELD blendmode = PF_Translucent; + if (rover->alpha == FFLOOR_ALPHA_SPECIAL_ADDITIVE) + blendmode = PF_Additive; + else if (rover->alpha == FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE) + blendmode = PF_Substractive; + + light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + + HWR_AddTransparentFloor(&levelflats[*rover->toppic], &extrasubsectors[num], true, *rover->topheight, - *gr_frontsector->lightlist[light].lightlevel, - rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Translucent, - false, gr_frontsector->lightlist[light].extra_colormap); + *gl_frontsector->lightlist[light].lightlevel, + rover->alpha-1 > 255 ? 255 : rover->alpha-1, rover->master->frontsector, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|blendmode, + false, *gl_frontsector->lightlist[light].extra_colormap); } else { - HWR_GetFlat(levelflats[*rover->toppic].lumpnum, R_NoEncore(gr_frontsector, true)); - light = R_GetPlaneLight(gr_frontsector, centerHeight, viewz < cullHeight ? true : false); - HWR_RenderPlane(&extrasubsectors[num], true, *rover->topheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gr_frontsector->lightlist[light].lightlevel, levelflats[*rover->toppic].lumpnum, - rover->master->frontsector, 255, gr_frontsector->lightlist[light].extra_colormap); + HWR_GetLevelFlat(&levelflats[*rover->toppic], R_NoEncore(gl_frontsector, true)); + light = R_GetPlaneLight(gl_frontsector, centerHeight, dup_viewz < cullHeight ? true : false); + HWR_RenderPlane(sub, &extrasubsectors[num], true, *rover->topheight, (rover->flags & FF_RIPPLE ? PF_Ripple : 0)|PF_Occlude, *gl_frontsector->lightlist[light].lightlevel, &levelflats[*rover->toppic], + rover->master->frontsector, 255, *gl_frontsector->lightlist[light].extra_colormap); } } } } +#endif +#endif //doplanes -#ifdef POLYOBJECTS // Draw all the polyobjects in this subsector if (sub->polyList) { @@ -2655,21 +3245,21 @@ void HWR_Subsector(size_t num) po = (polyobj_t *)(po->link.next); } + // for render stats + ps_numpolyobjects += numpolys; + // Sort polyobjects R_SortPolyObjects(sub); // Draw polyobject lines. HWR_AddPolyObjectSegs(); -#ifdef POLYOBJECTS_PLANES if (sub->validcount != validcount) // This validcount situation seems to let us know that the floors have already been drawn. { // Draw polyobject planes HWR_AddPolyObjectPlanes(); } -#endif } -#endif // Hurder ici se passe les choses INT32�essantes! // on vient de tracer le sol et le plafond @@ -2679,11 +3269,11 @@ void HWR_Subsector(size_t num) { // draw sprites first, coz they are clipped to the solidsegs of // subsectors more 'in front' - HWR_AddSprites(gr_frontsector); + HWR_AddSprites(gl_frontsector); //Hurdler: at this point validcount must be the same, but is not because - // gr_frontsector doesn't point anymore to sub->sector due to - // the call gr_frontsector = R_FakeFlat(...) + // gl_frontsector doesn't point anymore to sub->sector due to + // the call gl_frontsector = R_FakeFlat(...) // if it's not done, the sprite is drawn more than once, // what looks really bad with translucency or dynamic light, // without talking about the overdraw of course. @@ -2691,11 +3281,10 @@ void HWR_Subsector(size_t num) while (count--) { -#ifdef POLYOBJECTS - if (!line->polyseg) // ignore segs that belong to polyobjects -#endif + + if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects HWR_AddLine(line); - line++; + line++; } } @@ -2707,41 +3296,203 @@ void HWR_Subsector(size_t num) // traversing subtree recursively. // Just call with BSP root. -void HWR_RenderBSPNode(INT32 bspnum) +#ifdef coolhack +//t;b;l;r +static fixed_t hackbbox[4]; +//BOXTOP, +//BOXBOTTOM, +//BOXLEFT, +//BOXRIGHT +static boolean HWR_CheckHackBBox(fixed_t *bb) { + if (bb[BOXTOP] < hackbbox[BOXBOTTOM]) //y up + return false; + if (bb[BOXBOTTOM] > hackbbox[BOXTOP]) + return false; + if (bb[BOXLEFT] > hackbbox[BOXRIGHT]) + return false; + if (bb[BOXRIGHT] < hackbbox[BOXLEFT]) + return false; + return true; +} +#endif + +// BP: big hack for a test in lighning ref : 1249753487AB +fixed_t *hwbbox; + +static void HWR_RenderBSPNode(INT32 bspnum) +{ + /*//GZDoom code + if(bspnum == -1) + { + HWR_Subsector(subsectors); + return; + } + while(!((size_t)bspnum&(~NF_SUBSECTOR))) // Keep going until found a subsector + { + node_t *bsp = &nodes[bspnum]; + + // Decide which side the view point is on + INT32 side = R_PointOnSide(dup_viewx, dup_viewy, bsp); + + // Recursively divide front space (toward the viewer) + HWR_RenderBSPNode(bsp->children[side]); + + // Possibly divide back space (away from viewer) + side ^= 1; + + if (!HWR_CheckBBox(bsp->bbox[side])) + return; + + bspnum = bsp->children[side]; + } + + HWR_Subsector(bspnum-1); +*/ node_t *bsp = &nodes[bspnum]; // Decide which side the view point is on INT32 side; + ps_numbspcalls++; + // Found a subsector? if (bspnum & NF_SUBSECTOR) { - if (bspnum != -1) + if (bspnum == -1) + { + //*(gl_drawsubsector_p++) = 0; + HWR_Subsector(0); + } + else + { + //*(gl_drawsubsector_p++) = bspnum&(~NF_SUBSECTOR); HWR_Subsector(bspnum&(~NF_SUBSECTOR)); + } return; } // Decide which side the view point is on. - side = R_PointOnSide(viewx, viewy, bsp); + side = R_PointOnSide(dup_viewx, dup_viewy, bsp); + + // BP: big hack for a test in lighning ref : 1249753487AB + hwbbox = bsp->bbox[side]; // Recursively divide front space. HWR_RenderBSPNode(bsp->children[side]); // Possibly divide back space. if (HWR_CheckBBox(bsp->bbox[side^1])) + { + // BP: big hack for a test in lighning ref : 1249753487AB + hwbbox = bsp->bbox[side^1]; HWR_RenderBSPNode(bsp->children[side^1]); + } +} + +/* +// +// Clear 'stack' of subsectors to draw +// +static void HWR_ClearDrawSubsectors(void) +{ + gl_drawsubsector_p = gl_drawsubsectors; +} + +// +// Draw subsectors pushed on the drawsubsectors 'stack', back to front +// +static void HWR_RenderSubsectors(void) +{ + while (gl_drawsubsector_p > gl_drawsubsectors) + { + HWR_RenderBSPNode( + lastsubsec->nextsubsec = bspnum & (~NF_SUBSECTOR); + } +} +*/ + +// ========================================================================== +// FROM R_MAIN.C +// ========================================================================== + +//BP : exactely the same as R_InitTextureMapping +void HWR_InitTextureMapping(void) +{ + angle_t i; + INT32 x; + INT32 t; + fixed_t focallength; + fixed_t grcenterx; + fixed_t grcenterxfrac; + INT32 grviewwidth; + +#define clipanglefov (FIELDOFVIEW>>ANGLETOFINESHIFT) + + grviewwidth = vid.width; + grcenterx = grviewwidth/2; + grcenterxfrac = grcenterx< FRACUNIT*2) + t = -1; + else if (FINETANGENT(i) < -FRACUNIT*2) + t = grviewwidth+1; + else + { + t = FixedMul(FINETANGENT(i), focallength); + t = (grcenterxfrac - t+FRACUNIT-1)>>FRACBITS; + + if (t < -1) + t = -1; + else if (t > grviewwidth+1) + t = grviewwidth+1; + } + gl_viewangletox[i] = t; + } + + // Scan viewangletox[] to generate xtoviewangle[]: + // xtoviewangle will give the smallest view angle + // that maps to x. + for (x = 0; x <= grviewwidth; x++) + { + i = 0; + while (gl_viewangletox[i]>x) + i++; + gl_xtoviewangle[x] = (i<> VISSPRITECHUNKBITS] = {NULL}; +static UINT32 gl_visspritecount; +static gl_vissprite_t *gl_visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL}; // -------------------------------------------------------------------------- // HWR_ClearSprites @@ -2749,31 +3500,79 @@ static gr_vissprite_t *gr_visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = // -------------------------------------------------------------------------- static void HWR_ClearSprites(void) { - gr_visspritecount = 0; + gl_visspritecount = 0; } // -------------------------------------------------------------------------- // HWR_NewVisSprite // -------------------------------------------------------------------------- -static gr_vissprite_t gr_overflowsprite; +static gl_vissprite_t gl_overflowsprite; -static gr_vissprite_t *HWR_GetVisSprite(UINT32 num) +static gl_vissprite_t *HWR_GetVisSprite(UINT32 num) { UINT32 chunk = num >> VISSPRITECHUNKBITS; // Allocate chunk if necessary - if (!gr_visspritechunks[chunk]) - Z_Malloc(sizeof(gr_vissprite_t) * VISSPRITESPERCHUNK, PU_LEVEL, &gr_visspritechunks[chunk]); + if (!gl_visspritechunks[chunk]) + Z_Malloc(sizeof(gl_vissprite_t) * VISSPRITESPERCHUNK, PU_LEVEL, &gl_visspritechunks[chunk]); - return gr_visspritechunks[chunk] + (num & VISSPRITEINDEXMASK); + return gl_visspritechunks[chunk] + (num & VISSPRITEINDEXMASK); } -static gr_vissprite_t *HWR_NewVisSprite(void) +static gl_vissprite_t *HWR_NewVisSprite(void) { - if (gr_visspritecount == MAXVISSPRITES) - return &gr_overflowsprite; + if (gl_visspritecount == MAXVISSPRITES) + return &gl_overflowsprite; - return HWR_GetVisSprite(gr_visspritecount++); + return HWR_GetVisSprite(gl_visspritecount++); +} + +// A hack solution for transparent surfaces appearing on top of linkdraw sprites. +// Keep a list of linkdraw sprites and draw their shapes to the z-buffer after all other +// sprite drawing is done. (effectively the z-buffer drawing of linkdraw sprites is delayed) +// NOTE: This will no longer be necessary once full translucent sorting is implemented, where +// translucent sprites and surfaces are sorted together. + +typedef struct +{ + FOutVector verts[4]; + gl_vissprite_t *spr; +} zbuffersprite_t; + +// this list is used to store data about linkdraw sprites +zbuffersprite_t linkdrawlist[MAXVISSPRITES]; +UINT32 linkdrawcount = 0; + +// add the necessary data to the list for delayed z-buffer drawing +static void HWR_LinkDrawHackAdd(FOutVector *verts, gl_vissprite_t *spr) +{ + if (linkdrawcount < MAXVISSPRITES) + { + memcpy(linkdrawlist[linkdrawcount].verts, verts, sizeof(FOutVector) * 4); + linkdrawlist[linkdrawcount].spr = spr; + linkdrawcount++; + } +} + +// process and clear the list of sprites for delayed z-buffer drawing +static void HWR_LinkDrawHackFinish(void) +{ + UINT32 i; + FSurfaceInfo surf; + surf.PolyColor.rgba = 0xFFFFFFFF; + surf.TintColor.rgba = 0xFFFFFFFF; + surf.FadeColor.rgba = 0xFFFFFFFF; + surf.LightInfo.light_level = 0; + surf.LightInfo.fade_start = 0; + surf.LightInfo.fade_end = 31; + for (i = 0; i < linkdrawcount; i++) + { + // draw sprite shape, only to z-buffer + HWR_GetPatch(linkdrawlist[i].spr->gpatch); + HWR_ProcessPolygon(&surf, linkdrawlist[i].verts, 4, PF_Translucent|PF_Occlude|PF_Invisible|PF_Clip, 0, false); + } + // reset list + linkdrawcount = 0; } // @@ -2826,7 +3625,6 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) FOutVector shadowVerts[4]; FSurfaceInfo sSurf; float fscale; float fx; float fy; float offset; - UINT8 lightlevel = 0; extracolormap_t *colormap = NULL; UINT8 i; SINT8 flip = P_MobjFlip(thing); @@ -2840,24 +3638,15 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) pslope_t *groundslope; groundz = R_GetShadowZ(thing, &groundslope); + floordiff = abs((flip < 0 ? thing->height : 0) + thingzpos - groundz); alpha = floordiff / (4*FRACUNIT) + 75; if (alpha >= 255) return; alpha = 255 - alpha; - if (thing->whiteshadow) - { - gpatch = (GLPatch_t *)W_CachePatchName("LSHADOW", PU_CACHE); - lightlevel = 255; - } - else - { - gpatch = (GLPatch_t *)W_CachePatchName("DSHADOW", PU_CACHE); - lightlevel = 0; - } - - if (!(gpatch && gpatch->mipmap->grInfo.format)) return; + gpatch = (GLPatch_t *)W_CachePatchName(thing->whiteshadow ? "LSHADOW" : "DSHADOW", PU_CACHE); + if (!(gpatch && gpatch->mipmap->format)) return; HWR_GetPatch(gpatch); scalemul = FixedMul(FRACUNIT - floordiff/640, scale); @@ -2886,15 +3675,15 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) { float oldx = shadowVerts[i].x; float oldy = shadowVerts[i].z; - shadowVerts[i].x = fx + ((oldx - fx) * gr_viewcos) - ((oldy - fy) * gr_viewsin); - shadowVerts[i].z = fy + ((oldx - fx) * gr_viewsin) + ((oldy - fy) * gr_viewcos); + shadowVerts[i].x = fx + ((oldx - fx) * gl_viewcos) - ((oldy - fy) * gl_viewsin); + shadowVerts[i].z = fy + ((oldx - fx) * gl_viewsin) + ((oldy - fy) * gl_viewcos); } if (groundslope) { for (i = 0; i < 4; i++) { - slopez = P_GetZAt(groundslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z)); + slopez = P_GetSlopeZAt(groundslope, FLOAT_TO_FIXED(shadowVerts[i].x), FLOAT_TO_FIXED(shadowVerts[i].z)); shadowVerts[i].y = FIXED_TO_FLOAT(slopez) + flip * 0.05f; } } @@ -2914,8 +3703,8 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) { light = R_GetPlaneLight(thing->subsector->sector, groundz, false); // Always use the light at the top instead of whatever I was doing before - if (thing->subsector->sector->lightlist[light].extra_colormap) - colormap = thing->subsector->sector->lightlist[light].extra_colormap; + if (*thing->subsector->sector->lightlist[light].extra_colormap) + colormap = *thing->subsector->sector->lightlist[light].extra_colormap; } else { @@ -2923,21 +3712,22 @@ static void HWR_DrawDropShadow(mobj_t *thing, fixed_t scale) colormap = thing->subsector->sector->extra_colormap; } - HWR_Lighting(&sSurf, lightlevel, colormap); + HWR_Lighting(&sSurf, 0, colormap); sSurf.PolyColor.s.alpha = alpha; - HWD.pfnSetShader(3); // sprite shader - HWD.pfnDrawPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated); + HWR_ProcessPolygon(&sSurf, shadowVerts, 4, PF_Translucent|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader } // This is expecting a pointer to an array containing 4 wallVerts for a sprite -static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts) +static void HWR_RotateSpritePolyToAim(gl_vissprite_t *spr, FOutVector *wallVerts, const boolean precip) { - if (cv_grspritebillboarding.value && spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE) && wallVerts) + if (cv_glspritebillboarding.value + && spr && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE) + && wallVerts) { float basey = FIXED_TO_FLOAT(spr->mobj->z); float lowy = wallVerts[0].y; - if (P_MobjFlip(spr->mobj) == -1) + if (!precip && P_MobjFlip(spr->mobj) == -1) // precip doesn't have eflags so they can't flip { basey = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height); } @@ -2945,24 +3735,24 @@ static void HWR_RotateSpritePolyToAim(gr_vissprite_t *spr, FOutVector *wallVerts // X, Y, AND Z need to be manipulated for the polys to rotate around the // origin, because of how the origin setting works I believe that should // be mobj->z or mobj->z + mobj->height - wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gr_viewludsin + basey; - wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gr_viewludsin + basey; + wallVerts[2].y = wallVerts[3].y = (spr->ty - basey) * gl_viewludsin + basey; + wallVerts[0].y = wallVerts[1].y = (lowy - basey) * gl_viewludsin + basey; // translate back to be around 0 before translating back - wallVerts[3].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos; - wallVerts[2].x += ((spr->ty - basey) * gr_viewludcos) * gr_viewcos; + wallVerts[3].x += ((spr->ty - basey) * gl_viewludcos) * gl_viewcos; + wallVerts[2].x += ((spr->ty - basey) * gl_viewludcos) * gl_viewcos; - wallVerts[0].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos; - wallVerts[1].x += ((lowy - basey) * gr_viewludcos) * gr_viewcos; + wallVerts[0].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos; + wallVerts[1].x += ((lowy - basey) * gl_viewludcos) * gl_viewcos; - wallVerts[3].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin; - wallVerts[2].z += ((spr->ty - basey) * gr_viewludcos) * gr_viewsin; + wallVerts[3].z += ((spr->ty - basey) * gl_viewludcos) * gl_viewsin; + wallVerts[2].z += ((spr->ty - basey) * gl_viewludcos) * gl_viewsin; - wallVerts[0].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin; - wallVerts[1].z += ((lowy - basey) * gr_viewludcos) * gr_viewsin; + wallVerts[0].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin; + wallVerts[1].z += ((lowy - basey) * gl_viewludcos) * gl_viewsin; } } -static void HWR_SplitSprite(gr_vissprite_t *spr) +static void HWR_SplitSprite(gl_vissprite_t *spr) { float this_scale = 1.0f; FOutVector wallVerts[4]; @@ -2971,32 +3761,32 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); extracolormap_t *colormap; - FUINT lightlevel; + FUINT lightlevel = 255; FBITFIELD blend = 0; + FBITFIELD occlusion; + boolean use_linkdraw_hack = false; UINT8 alpha; UINT8 brightmode = 0; INT32 i; float realtop, realbot, top, bot; - float towtop, towbot, towmult; + float ttop, tbot, tmult; float bheight; float realheight, heightmult; const sector_t *sector = spr->mobj->subsector->sector; const lightlist_t *list = sector->lightlist; -#ifdef ESLOPE float endrealtop, endrealbot, endtop, endbot; float endbheight; float endrealheight; fixed_t temp; fixed_t v1x, v1y, v2x, v2y; -#endif this_scale = FIXED_TO_FLOAT(spr->mobj->scale); if (hires) this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)spr->mobj->skin)->highresscale); - gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); // cache the patch in the graphics card memory //12/12/99: Hurdler: same comment as above (for md2) @@ -3042,37 +3832,40 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) baseWallVerts[0].t = baseWallVerts[1].t = gpatch->max_t; } - // Let dispoffset work first since this adjust each vertex - HWR_RotateSpritePolyToAim(spr, baseWallVerts); - - // push it toward the camera to mitigate floor-clipping sprites - { - float sprdist = sqrtf((spr->x1 - gr_viewx)*(spr->x1 - gr_viewx) + (spr->z1 - gr_viewy)*(spr->z1 - gr_viewy) + (spr->ty - gr_viewz)*(spr->ty - gr_viewz)); - float distfact = ((2.0f*spr->dispoffset) + 20.0f) / sprdist; - for (i = 0; i < 4; i++) - { - baseWallVerts[i].x += (gr_viewx - baseWallVerts[i].x)*distfact; - baseWallVerts[i].z += (gr_viewy - baseWallVerts[i].z)*distfact; - baseWallVerts[i].y += (gr_viewz - baseWallVerts[i].y)*distfact; - } + // if it has a dispoffset, push it a little towards the camera + if (spr->dispoffset) { + float co = -gl_viewcos*(0.05f*spr->dispoffset); + float si = -gl_viewsin*(0.05f*spr->dispoffset); + baseWallVerts[0].z = baseWallVerts[3].z = baseWallVerts[0].z+si; + baseWallVerts[1].z = baseWallVerts[2].z = baseWallVerts[1].z+si; + baseWallVerts[0].x = baseWallVerts[3].x = baseWallVerts[0].x+co; + baseWallVerts[1].x = baseWallVerts[2].x = baseWallVerts[1].x+co; } + // Let dispoffset work first since this adjust each vertex + HWR_RotateSpritePolyToAim(spr, baseWallVerts, false); + realtop = top = baseWallVerts[3].y; realbot = bot = baseWallVerts[0].y; - towtop = baseWallVerts[3].t; - towbot = baseWallVerts[0].t; - towmult = (towbot - towtop) / (top - bot); + ttop = baseWallVerts[3].t; + tbot = baseWallVerts[0].t; + tmult = (tbot - ttop) / (top - bot); -#ifdef ESLOPE endrealtop = endtop = baseWallVerts[2].y; endrealbot = endbot = baseWallVerts[1].y; -#endif // copy the contents of baseWallVerts into the drawn wallVerts array // baseWallVerts is used to know the final shape to easily get the vertex // co-ordinates memcpy(wallVerts, baseWallVerts, sizeof(baseWallVerts)); + // if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude) + // this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw. + if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + occlusion = 0; + else + occlusion = PF_Occlude; + if (spr->mobj->drawflags & MFD_TRANSMASK) blend = HWR_TranstableToAlpha((spr->mobj->drawflags & MFD_TRANSMASK)>>MFD_TRANSSHIFT, &Surf); else if (spr->mobj->frame & FF_TRANSMASK) @@ -3084,13 +3877,12 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before Surf.PolyColor.s.alpha = 0xFF; - blend = PF_Translucent|PF_Occlude; + blend = PF_Translucent|occlusion; + if (!occlusion) use_linkdraw_hack = true; } alpha = Surf.PolyColor.s.alpha; - temp = FLOAT_TO_FIXED(realtop); - if (spr->mobj->drawflags & MFD_BRIGHTMASK) { if (spr->mobj->drawflags & MFD_FULLBRIGHT) @@ -3106,51 +3898,32 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) brightmode = 2; } -#ifdef ESLOPE // Start with the lightlevel and colormap from the top of the sprite - lightlevel = 255; - colormap = list[sector->numlights - 1].extra_colormap; + colormap = *list[sector->numlights - 1].extra_colormap; + i = 0; + temp = FLOAT_TO_FIXED(realtop); if (brightmode != 1) - { lightlevel = *list[sector->numlights - 1].lightlevel; - if (brightmode == 2) - lightlevel = 128 + (lightlevel>>1); - } for (i = 1; i < sector->numlights; i++) { - fixed_t h = sector->lightlist[i].slope ? P_GetZAt(sector->lightlist[i].slope, spr->mobj->x, spr->mobj->y) - : sector->lightlist[i].height; + fixed_t h = P_GetLightZAt(§or->lightlist[i], spr->mobj->x, spr->mobj->y); if (h <= temp) { if (brightmode != 1) - { lightlevel = *list[i-1].lightlevel; - if (brightmode == 2) - lightlevel = 128 + (lightlevel>>1); - } - colormap = list[i-1].extra_colormap; + colormap = *list[i-1].extra_colormap; break; } } -#else - i = R_GetPlaneLight(sector, temp, false); - if (brightmode != 1) - { - lightlevel = *list[i].lightlevel; - if (brightmode == 2) - lightlevel = 128 + (lightlevel>>1); - } - colormap = list[i].extra_colormap; -#endif + + if (brightmode == 2) + lightlevel = 128 + (lightlevel>>1); for (i = 0; i < sector->numlights; i++) { -#ifdef ESLOPE - if (endtop < endrealbot) -#endif - if (top < realbot) + if (endtop < endrealbot && top < realbot) return; // even if we aren't changing colormap or lightlevel, we still need to continue drawing down the sprite @@ -3162,42 +3935,23 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (brightmode == 2) lightlevel = 128 + (lightlevel>>1); } - colormap = list[i].extra_colormap; + colormap = *list[i].extra_colormap; } -#ifdef ESLOPE if (i + 1 < sector->numlights) { - if (list[i+1].slope) - { - temp = P_GetZAt(list[i+1].slope, v1x, v1y); - bheight = FIXED_TO_FLOAT(temp); - temp = P_GetZAt(list[i+1].slope, v2x, v2y); - endbheight = FIXED_TO_FLOAT(temp); - } - else - bheight = endbheight = FIXED_TO_FLOAT(list[i+1].height); + temp = P_GetLightZAt(&list[i+1], v1x, v1y); + bheight = FIXED_TO_FLOAT(temp); + temp = P_GetLightZAt(&list[i+1], v2x, v2y); + endbheight = FIXED_TO_FLOAT(temp); } else { bheight = realbot; endbheight = endrealbot; } -#else - if (i + 1 < sector->numlights) - { - bheight = FIXED_TO_FLOAT(list[i+1].height); - } - else - { - bheight = realbot; - } -#endif -#ifdef ESLOPE - if (endbheight >= endtop) -#endif - if (bheight >= top) + if (endbheight >= endtop && bheight >= top) continue; bot = bheight; @@ -3205,18 +3959,15 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) if (bot < realbot) bot = realbot; -#ifdef ESLOPE endbot = endbheight; if (endbot < endrealbot) endbot = endrealbot; -#endif -#ifdef ESLOPE - wallVerts[3].t = towtop + ((realtop - top) * towmult); - wallVerts[2].t = towtop + ((endrealtop - endtop) * towmult); - wallVerts[0].t = towtop + ((realtop - bot) * towmult); - wallVerts[1].t = towtop + ((endrealtop - endbot) * towmult); + wallVerts[3].t = ttop + ((realtop - top) * tmult); + wallVerts[2].t = ttop + ((endrealtop - endtop) * tmult); + wallVerts[0].t = ttop + ((realtop - bot) * tmult); + wallVerts[1].t = ttop + ((endrealtop - endbot) * tmult); wallVerts[3].y = top; wallVerts[2].y = endtop; @@ -3224,7 +3975,8 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[1].y = endbot; // The x and y only need to be adjusted in the case that it's not a papersprite - if (cv_grspritebillboarding.value && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) + if (cv_glspritebillboarding.value + && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) { // Get the x and z of the vertices so billboarding draws correctly realheight = realbot - realtop; @@ -3245,78 +3997,44 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; } -#else - wallVerts[3].t = wallVerts[2].t = towtop + ((realtop - top) * towmult); - wallVerts[0].t = wallVerts[1].t = towtop + ((realtop - bot) * towmult); - - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; - - // The x and y only need to be adjusted in the case that it's not a papersprite - if (cv_grspritebillboarding.value && spr->mobj && !(spr->mobj->frame & FF_PAPERSPRITE)) - { - // Get the x and z of the vertices so billboarding draws correctly - realheight = realbot - realtop; - heightmult = (realtop - top) / realheight; - wallVerts[3].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; - wallVerts[3].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; - wallVerts[2].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; - wallVerts[2].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; - - heightmult = (realtop - bot) / realheight; - wallVerts[0].x = baseWallVerts[3].x + (baseWallVerts[3].x - baseWallVerts[0].x) * heightmult; - wallVerts[0].z = baseWallVerts[3].z + (baseWallVerts[3].z - baseWallVerts[0].z) * heightmult; - wallVerts[1].x = baseWallVerts[2].x + (baseWallVerts[2].x - baseWallVerts[1].x) * heightmult; - wallVerts[1].z = baseWallVerts[2].z + (baseWallVerts[2].z - baseWallVerts[1].z) * heightmult; - } -#endif HWR_Lighting(&Surf, lightlevel, colormap); Surf.PolyColor.s.alpha = alpha; - HWD.pfnSetShader(3); // sprite shader - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader + + if (use_linkdraw_hack) + HWR_LinkDrawHackAdd(wallVerts, spr); top = bot; -#ifdef ESLOPE endtop = endbot; -#endif } bot = realbot; -#ifdef ESLOPE endbot = endrealbot; - if (endtop <= endrealbot) -#endif - if (top <= realbot) + if (endtop <= endrealbot && top <= realbot) return; // If we're ever down here, somehow the above loop hasn't draw all the light levels of sprite -#ifdef ESLOPE - wallVerts[3].t = towtop + ((realtop - top) * towmult); - wallVerts[2].t = towtop + ((endrealtop - endtop) * towmult); - wallVerts[0].t = towtop + ((realtop - bot) * towmult); - wallVerts[1].t = towtop + ((endrealtop - endbot) * towmult); + wallVerts[3].t = ttop + ((realtop - top) * tmult); + wallVerts[2].t = ttop + ((endrealtop - endtop) * tmult); + wallVerts[0].t = ttop + ((realtop - bot) * tmult); + wallVerts[1].t = ttop + ((endrealtop - endbot) * tmult); wallVerts[3].y = top; wallVerts[2].y = endtop; wallVerts[0].y = bot; wallVerts[1].y = endbot; -#else - wallVerts[3].t = wallVerts[2].t = towtop + ((realtop - top) * towmult); - wallVerts[0].t = wallVerts[1].t = towtop + ((realtop - bot) * towmult); - - wallVerts[2].y = wallVerts[3].y = top; - wallVerts[0].y = wallVerts[1].y = bot; -#endif HWR_Lighting(&Surf, lightlevel, colormap); Surf.PolyColor.s.alpha = alpha; - HWD.pfnSetShader(3); // sprite shader - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader + + if (use_linkdraw_hack) + HWR_LinkDrawHackAdd(wallVerts, spr); } // -----------------+ @@ -3324,13 +4042,14 @@ static void HWR_SplitSprite(gr_vissprite_t *spr) // : (monsters, bonuses, weapons, lights, ...) // Returns : // -----------------+ -static void HWR_DrawSprite(gr_vissprite_t *spr) +static void HWR_DrawSprite(gl_vissprite_t *spr) { float this_scale = 1.0f; FOutVector wallVerts[4]; GLPatch_t *gpatch; // sprite patch converted to hardware FSurfaceInfo Surf; const boolean hires = (spr->mobj && spr->mobj->skin && ((skin_t *)spr->mobj->skin)->flags & SF_HIRES); + //const boolean papersprite = (spr->mobj && (spr->mobj->frame & FF_PAPERSPRITE)); if (spr->mobj) this_scale = FIXED_TO_FLOAT(spr->mobj->scale); if (hires) @@ -3354,7 +4073,13 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // sure to do it the right way. So actually, we keep normal sprite // in memory and we add the md2 model if it exists for that sprite - gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + +#ifdef ALAM_LIGHTING + if (!(spr->mobj->flags2 & MF2_DEBRIS) && (spr->mobj->sprite != SPR_PLAY || + (spr->mobj->player && spr->mobj->player->powers[pw_super]))) + HWR_DL_AddLight(spr, gpatch); +#endif // create the sprite billboard // @@ -3403,8 +4128,8 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // if it has a dispoffset, push it a little towards the camera if (spr->dispoffset) { - float co = -gr_viewcos*(0.05f*spr->dispoffset); - float si = -gr_viewsin*(0.05f*spr->dispoffset); + float co = -gl_viewcos*(0.05f*spr->dispoffset); + float si = -gl_viewsin*(0.05f*spr->dispoffset); wallVerts[0].z = wallVerts[3].z = wallVerts[0].z+si; wallVerts[1].z = wallVerts[2].z = wallVerts[1].z+si; wallVerts[0].x = wallVerts[3].x = wallVerts[0].x+co; @@ -3412,21 +4137,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) } // Let dispoffset work first since this adjust each vertex - // ...nah - HWR_RotateSpritePolyToAim(spr, wallVerts); - - // push it toward the camera to mitigate floor-clipping sprites - { - float sprdist = sqrtf((spr->x1 - gr_viewx)*(spr->x1 - gr_viewx) + (spr->z1 - gr_viewy)*(spr->z1 - gr_viewy) + (spr->ty - gr_viewz)*(spr->ty - gr_viewz)); - float distfact = ((2.0f*spr->dispoffset) + 20.0f) / sprdist; - size_t i; - for (i = 0; i < 4; i++) - { - wallVerts[i].x += (gr_viewx - wallVerts[i].x)*distfact; - wallVerts[i].z += (gr_viewy - wallVerts[i].z)*distfact; - wallVerts[i].y += (gr_viewz - wallVerts[i].y)*distfact; - } - } + HWR_RotateSpritePolyToAim(spr, wallVerts, false); // This needs to be AFTER the shadows so that the regular sprites aren't drawn completely black. // sprite lighting by modulating the RGB components @@ -3435,7 +4146,7 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // colormap test { sector_t *sector = spr->mobj->subsector->sector; - UINT8 lightlevel = 255; + FUINT lightlevel = 255; UINT8 brightmode = 0; extracolormap_t *colormap = sector->extra_colormap; @@ -3455,17 +4166,25 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) } if (brightmode != 1) - { lightlevel = sector->lightlevel; - if (brightmode == 2) - lightlevel = 128 + (lightlevel>>1); - } + + if (brightmode == 2) + lightlevel = 128 + (lightlevel>>1); HWR_Lighting(&Surf, lightlevel, colormap); } { FBITFIELD blend = 0; + FBITFIELD occlusion; + boolean use_linkdraw_hack = false; + + // if sprite has linkdraw, then dont write to z-buffer (by not using PF_Occlude) + // this will result in sprites drawn afterwards to be drawn on top like intended when using linkdraw. + if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) + occlusion = 0; + else + occlusion = PF_Occlude; if (spr->mobj->drawflags & MFD_TRANSMASK) blend = HWR_TranstableToAlpha((spr->mobj->drawflags & MFD_TRANSMASK)>>MFD_TRANSSHIFT, &Surf); @@ -3478,16 +4197,20 @@ static void HWR_DrawSprite(gr_vissprite_t *spr) // Hurdler: PF_Environement would be cool, but we need to fix // the issue with the fog before Surf.PolyColor.s.alpha = 0xFF; - blend = PF_Translucent|PF_Occlude; + blend = PF_Translucent|occlusion; + if (!occlusion) use_linkdraw_hack = true; } - HWD.pfnSetShader(3); // sprite shader - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader + + if (use_linkdraw_hack) + HWR_LinkDrawHackAdd(wallVerts, spr); } } +#ifdef HWPRECIP // Sprite drawer for precipitation -static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) +static inline void HWR_DrawPrecipitationSprite(gl_vissprite_t *spr) { FBITFIELD blend = 0; FOutVector wallVerts[4]; @@ -3501,7 +4224,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) return; // cache sprite graphics - gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); // create the sprite billboard // @@ -3520,7 +4243,7 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) wallVerts[1].z = wallVerts[2].z = spr->z2; // Let dispoffset work first since this adjust each vertex - HWR_RotateSpritePolyToAim(spr, wallVerts); + HWR_RotateSpritePolyToAim(spr, wallVerts, true); wallVerts[0].s = wallVerts[3].s = 0; wallVerts[2].s = wallVerts[1].s = gpatch->max_s; @@ -3564,8 +4287,8 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) if (brightmode != 1) lightlevel = *sector->lightlist[light].lightlevel; - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; + if (*sector->lightlist[light].extra_colormap) + colormap = *sector->lightlist[light].extra_colormap; } else { @@ -3596,57 +4319,114 @@ static inline void HWR_DrawPrecipitationSprite(gr_vissprite_t *spr) blend = PF_Translucent|PF_Occlude; } - HWD.pfnSetShader(3); // sprite shader - HWD.pfnDrawPolygon(&Surf, wallVerts, 4, blend|PF_Modulated); + HWR_ProcessPolygon(&Surf, wallVerts, 4, blend|PF_Modulated|PF_Clip, SHADER_SPRITE, false); // sprite shader } +#endif // -------------------------------------------------------------------------- // Sort vissprites by distance // -------------------------------------------------------------------------- +gl_vissprite_t* gl_vsprorder[MAXVISSPRITES]; -gr_vissprite_t* gr_vsprorder[MAXVISSPRITES]; - -// For more correct transparency the transparent sprites would need to be +// Note: For more correct transparency the transparent sprites would need to be // sorted and drawn together with transparent surfaces. static int CompareVisSprites(const void *p1, const void *p2) { - gr_vissprite_t* spr1 = *(gr_vissprite_t*const*)p1; - gr_vissprite_t* spr2 = *(gr_vissprite_t*const*)p2; + gl_vissprite_t* spr1 = *(gl_vissprite_t*const*)p1; + gl_vissprite_t* spr2 = *(gl_vissprite_t*const*)p2; int idiff; float fdiff; + float tz1, tz2; - // make transparent sprites last - // "boolean to int" + // Make transparent sprites last. Comment from the previous sort implementation: + // Sryder: Oh boy, while it's nice having ALL the sprites sorted properly, it fails when we bring MD2's into the + // mix and they want to be translucent. So let's place all the translucent sprites and MD2's AFTER + // everything else, but still ordered of course, the depth buffer can handle the opaque ones plenty fine. + // We just need to move all translucent ones to the end in order + // TODO: Fully sort all sprites and MD2s with walls and floors, this part will be unnecessary after that + int transparency1; + int transparency2; - int transparency1 = (spr1->mobj->drawflags & FF_TRANSMASK) ? - ((spr1->mobj->drawflags & FF_TRANSMASK)>>MFD_TRANSSHIFT) : - ((spr1->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT); + int drawflags1; + int drawflags2; - int transparency2 = (spr2->mobj->drawflags & FF_TRANSMASK) ? - ((spr2->mobj->drawflags & FF_TRANSMASK)>>MFD_TRANSSHIFT) : - ((spr2->mobj->frame & FF_TRANSMASK)>>FF_TRANSSHIFT); + int frame1; + int frame2; + + // check for precip first, because then sprX->mobj is actually a precipmobj_t and does not have flags2 or tracer + int linkdraw1 = !spr1->precip && (spr1->mobj->flags2 & MF2_LINKDRAW) && spr1->mobj->tracer; + int linkdraw2 = !spr2->precip && (spr2->mobj->flags2 & MF2_LINKDRAW) && spr2->mobj->tracer; + + // ^ is the XOR operation + // if comparing a linkdraw and non-linkdraw sprite or 2 linkdraw sprites with different tracers, then use + // the tracer's properties instead of the main sprite's. + if ((linkdraw1 && linkdraw2 && spr1->mobj->tracer != spr2->mobj->tracer) || (linkdraw1 ^ linkdraw2)) + { + if (linkdraw1) + { + tz1 = spr1->tracertz; + drawflags1 = spr1->mobj->tracer->drawflags; + frame1 = spr1->mobj->tracer->frame; + } + else + { + tz1 = spr1->tz; + drawflags1 = (spr1->precip ? 0 : spr1->mobj->drawflags); + frame1 = spr1->mobj->frame; + } + if (linkdraw2) + { + tz2 = spr2->tracertz; + drawflags2 = spr2->mobj->tracer->drawflags; + frame2 = spr2->mobj->tracer->frame; + } + else + { + tz2 = spr2->tz; + drawflags2 = (spr2->precip ? 0 : spr2->mobj->drawflags); + frame2 = spr2->mobj->frame; + } + } + else + { + tz1 = spr1->tz; + drawflags1 = (spr1->precip ? 0 : spr1->mobj->drawflags); + frame1 = spr1->mobj->frame; + tz2 = spr2->tz; + drawflags2 = (spr2->precip ? 0 : spr2->mobj->drawflags); + frame2 = spr2->mobj->frame; + } + + // first compare transparency flags, then compare tz, then compare dispoffset + + transparency1 = (drawflags1 & FF_TRANSMASK) ? + ((drawflags1 & FF_TRANSMASK)>>MFD_TRANSSHIFT) : + ((frame1 & FF_TRANSMASK)>>FF_TRANSSHIFT); + + transparency2 = (drawflags2 & FF_TRANSMASK) ? + ((drawflags2 & FF_TRANSMASK)>>MFD_TRANSSHIFT) : + ((frame2 & FF_TRANSMASK)>>FF_TRANSSHIFT); idiff = transparency1 - transparency2; if (idiff != 0) return idiff; - fdiff = spr2->tz - spr1->tz;// this order seems correct when checking with apitrace. Back to front. + fdiff = tz2 - tz1; // this order seems correct when checking with apitrace. Back to front. if (fabsf(fdiff) < 1.0E-36f) - return spr1->dispoffset - spr2->dispoffset;// smallest dispoffset first if sprites are at (almost) same location. + return spr1->dispoffset - spr2->dispoffset; // smallest dispoffset first if sprites are at (almost) same location. else if (fdiff > 0) return 1; else return -1; } - static void HWR_SortVisSprites(void) { UINT32 i; - for (i = 0; i < gr_visspritecount; i++) + for (i = 0; i < gl_visspritecount; i++) { - gr_vsprorder[i] = HWR_GetVisSprite(i); + gl_vsprorder[i] = HWR_GetVisSprite(i); } - qsort(gr_vsprorder, gr_visspritecount, sizeof(gr_vissprite_t*), CompareVisSprites); + qsort(gl_vsprorder, gl_visspritecount, sizeof(gl_vissprite_t*), CompareVisSprites); } // A drawnode is something that points to a 3D floor, 3D side, or masked @@ -3666,13 +4446,17 @@ typedef struct static wallinfo_t *wallinfo = NULL; static size_t numwalls = 0; // a list of transparent walls to be drawn +void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); + +#define MAX_TRANSPARENTWALL 256 + typedef struct { extrasubsector_t *xsub; boolean isceiling; fixed_t fixedheight; INT32 lightlevel; - lumpnum_t lumpnum; + levelflat_t *levelflat; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -3690,7 +4474,7 @@ typedef struct boolean isceiling; fixed_t fixedheight; INT32 lightlevel; - lumpnum_t lumpnum; + levelflat_t *levelflat; INT32 alpha; sector_t *FOFSector; FBITFIELD blend; @@ -3701,19 +4485,24 @@ typedef struct static size_t numpolyplanes = 0; // a list of transparent poyobject floors to be drawn static polyplaneinfo_t *polyplaneinfo = NULL; -typedef struct gr_drawnode_s +//Hurdler: 3D water sutffs +typedef struct gl_drawnode_s { planeinfo_t *plane; polyplaneinfo_t *polyplane; wallinfo_t *wall; - gr_vissprite_t *sprite; -} gr_drawnode_t; + gl_vissprite_t *sprite; + +// struct gl_drawnode_s *next; +// struct gl_drawnode_s *prev; +} gl_drawnode_t; + +static INT32 drawcount = 0; -#define MAX_TRANSPARENTWALL 256 #define MAX_TRANSPARENTFLOOR 512 // This will likely turn into a copy of HWR_Add3DWater and replace it. -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) +void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap) { static size_t allocedplanes = 0; @@ -3729,8 +4518,8 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean planeinfo[numplanes].isceiling = isceiling; planeinfo[numplanes].fixedheight = fixedheight; - planeinfo[numplanes].lightlevel = lightlevel; - planeinfo[numplanes].lumpnum = lumpnum; + planeinfo[numplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; + planeinfo[numplanes].levelflat = levelflat; planeinfo[numplanes].xsub = xsub; planeinfo[numplanes].alpha = alpha; planeinfo[numplanes].FOFSector = FOFSector; @@ -3744,7 +4533,7 @@ void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean // Adding this for now until I can create extrasubsector info for polyobjects // When that happens it'll just be done through HWR_AddTransparentFloor and HWR_RenderPlane -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) +void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap) { static size_t allocedpolyplanes = 0; @@ -3760,8 +4549,8 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, polyplaneinfo[numpolyplanes].isceiling = isceiling; polyplaneinfo[numpolyplanes].fixedheight = fixedheight; - polyplaneinfo[numpolyplanes].lightlevel = lightlevel; - polyplaneinfo[numpolyplanes].lumpnum = lumpnum; + polyplaneinfo[numpolyplanes].lightlevel = (planecolormap && (planecolormap->flags & CMF_FOG)) ? lightlevel : 255; + polyplaneinfo[numpolyplanes].levelflat = levelflat; polyplaneinfo[numpolyplanes].polysector = polysector; polyplaneinfo[numpolyplanes].alpha = alpha; polyplaneinfo[numpolyplanes].FOFSector = FOFSector; @@ -3772,7 +4561,7 @@ void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, } // putting sortindex and sortnode here so the comparator function can see them -gr_drawnode_t *sortnode; +gl_drawnode_t *sortnode; size_t *sortindex; static int CompareDrawNodes(const void *p1, const void *p2) @@ -3788,7 +4577,7 @@ static int CompareDrawNodes(const void *p1, const void *p2) v1 = sortnode[n1].polyplane->drawcount; else if (sortnode[n1].wall) v1 = sortnode[n1].wall->drawcount; - else I_Error("n1 unknown"); + else I_Error("CompareDrawNodes: n1 unknown"); if (sortnode[n2].plane) v2 = sortnode[n2].plane->drawcount; @@ -3796,10 +4585,10 @@ static int CompareDrawNodes(const void *p1, const void *p2) v2 = sortnode[n2].polyplane->drawcount; else if (sortnode[n2].wall) v2 = sortnode[n2].wall->drawcount; - else I_Error("n2 unknown"); + else I_Error("CompareDrawNodes: n2 unknown"); diff = v2 - v1; - if (diff == 0) I_Error("diff is zero"); + if (diff == 0) I_Error("CompareDrawNodes: diff is zero"); return diff; } @@ -3807,14 +4596,15 @@ static int CompareDrawNodePlanes(const void *p1, const void *p2) { size_t n1 = *(const size_t*)p1; size_t n2 = *(const size_t*)p2; - if (!sortnode[n1].plane) I_Error("Uh.. This isn't a plane! (n1)"); - if (!sortnode[n2].plane) I_Error("Uh.. This isn't a plane! (n2)"); + if (!sortnode[n1].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n1)"); + if (!sortnode[n2].plane) I_Error("CompareDrawNodePlanes: Uh.. This isn't a plane! (n2)"); return ABS(sortnode[n2].plane->fixedheight - viewz) - ABS(sortnode[n1].plane->fixedheight - viewz); } -// HWR_RenderDrawNodes -// Creates, sorts and renders a list of drawnodes for the current frame. -void HWR_RenderDrawNodes(void) +// +// HWR_CreateDrawNodes +// Creates and sorts a list of drawnodes for the scene being rendered. +static void HWR_CreateDrawNodes(void) { UINT32 i = 0, p = 0; size_t run_start = 0; @@ -3823,14 +4613,16 @@ void HWR_RenderDrawNodes(void) // Could this be optimized into _AddTransparentWall/_AddTransparentPlane? // Hell yes! But sort algorithm must be modified to use a linked list. sortnode = Z_Calloc((sizeof(planeinfo_t)*numplanes) - + (sizeof(polyplaneinfo_t)*numpolyplanes) - + (sizeof(wallinfo_t)*numwalls) - ,PU_STATIC, NULL); + + (sizeof(polyplaneinfo_t)*numpolyplanes) + + (sizeof(wallinfo_t)*numwalls) + ,PU_STATIC, NULL); // todo: // However, in reality we shouldn't be re-copying and shifting all this information // that is already lying around. This should all be in some sort of linked list or lists. sortindex = Z_Calloc(sizeof(size_t) * (numplanes + numpolyplanes + numwalls), PU_STATIC, NULL); + ps_hw_nodesorttime = I_GetTimeMicros(); + for (i = 0; i < numplanes; i++, p++) { sortnode[p].plane = &planeinfo[i]; @@ -3849,21 +4641,15 @@ void HWR_RenderDrawNodes(void) sortindex[p] = p; } + ps_numdrawnodes = p; + // p is the number of stuff to sort - // Add the 3D floors, thicksides, and masked textures... - // Instead of going through drawsegs, we need to iterate - // through the lists of masked textures and - // translucent ffloors being drawn. - - // im not sure if this sort on the next line is needed. - // it sorts the list based on the value of the 'drawcount' member of the drawnodes. - // im thinking the list might already be in that order, but i havent bothered to check yet. - // anyway doing this sort does not hurt and does not take much time. - // the while loop after this sort is important however! + // sort the list based on the value of the 'drawcount' member of the drawnodes. qsort(sortindex, p, sizeof(size_t), CompareDrawNodes); - // try solving floor order here. for each consecutive run of floors in the list, sort that run. + // an additional pass is needed to correct the order of consecutive planes in the list. + // for each consecutive run of planes in the list, sort that run based on plane height and view height. while (run_start < p-1)// p-1 because a 1 plane run at the end of the list does not count { // locate run start @@ -3879,7 +4665,6 @@ void HWR_RenderDrawNodes(void) if (run_end > run_start)// if there are multiple consecutive planes, not just one { // consecutive run of planes found, now sort it - // not sure how long these runs can be in reality... qsort(sortindex + run_start, run_end - run_start + 1, sizeof(size_t), CompareDrawNodePlanes); } run_start = run_end + 1;// continue looking for runs coming right after this one @@ -3891,31 +4676,35 @@ void HWR_RenderDrawNodes(void) } } + ps_hw_nodesorttime = I_GetTimeMicros() - ps_hw_nodesorttime; + + ps_hw_nodedrawtime = I_GetTimeMicros(); + // Okay! Let's draw it all! Woo! HWD.pfnSetTransform(&atransform); - HWD.pfnSetShader(0); + HWD.pfnSetShader(SHADER_DEFAULT); for (i = 0; i < p; i++) { if (sortnode[sortindex[i]].plane) { - // We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes. - gr_frontsector = NULL; + // We aren't traversing the BSP tree, so make gl_frontsector null to avoid crashes. + gl_frontsector = NULL; if (!(sortnode[sortindex[i]].plane->blend & PF_NoTexture)) - HWR_GetFlat(sortnode[sortindex[i]].plane->lumpnum, R_NoEncore(sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->isceiling)); - HWR_RenderPlane(sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, - sortnode[sortindex[i]].plane->lumpnum, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, /*sortnode[sortindex[i]].plane->fogplane,*/ sortnode[sortindex[i]].plane->planecolormap); + HWR_GetLevelFlat(sortnode[sortindex[i]].plane->levelflat, R_NoEncore(sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->isceiling)); + HWR_RenderPlane(NULL, sortnode[sortindex[i]].plane->xsub, sortnode[sortindex[i]].plane->isceiling, sortnode[sortindex[i]].plane->fixedheight, sortnode[sortindex[i]].plane->blend, sortnode[sortindex[i]].plane->lightlevel, + sortnode[sortindex[i]].plane->levelflat, sortnode[sortindex[i]].plane->FOFSector, sortnode[sortindex[i]].plane->alpha, sortnode[sortindex[i]].plane->planecolormap); } else if (sortnode[sortindex[i]].polyplane) { - // We aren't traversing the BSP tree, so make gr_frontsector null to avoid crashes. - gr_frontsector = NULL; + // We aren't traversing the BSP tree, so make gl_frontsector null to avoid crashes. + gl_frontsector = NULL; if (!(sortnode[sortindex[i]].polyplane->blend & PF_NoTexture)) - HWR_GetFlat(sortnode[sortindex[i]].polyplane->lumpnum, R_NoEncore(sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->isceiling)); + HWR_GetLevelFlat(sortnode[sortindex[i]].polyplane->levelflat, R_NoEncore(sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->isceiling)); HWR_RenderPolyObjectPlane(sortnode[sortindex[i]].polyplane->polysector, sortnode[sortindex[i]].polyplane->isceiling, sortnode[sortindex[i]].polyplane->fixedheight, sortnode[sortindex[i]].polyplane->blend, sortnode[sortindex[i]].polyplane->lightlevel, - sortnode[sortindex[i]].polyplane->lumpnum, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); + sortnode[sortindex[i]].polyplane->levelflat, sortnode[sortindex[i]].polyplane->FOFSector, sortnode[sortindex[i]].polyplane->alpha, sortnode[sortindex[i]].polyplane->planecolormap); } else if (sortnode[sortindex[i]].wall) { @@ -3926,6 +4715,8 @@ void HWR_RenderDrawNodes(void) } } + ps_hw_nodedrawtime = I_GetTimeMicros() - ps_hw_nodedrawtime; + numwalls = 0; numplanes = 0; numpolyplanes = 0; @@ -3938,66 +4729,101 @@ void HWR_RenderDrawNodes(void) // -------------------------------------------------------------------------- // Draw all vissprites // -------------------------------------------------------------------------- -void HWR_DrawSprites(void) + +// added the stransform so they can be switched as drawing happenes so MD2s and sprites are sorted correctly with each other +static void HWR_DrawSprites(void) { UINT32 i; - for (i = 0; i < gr_visspritecount; i++) - { - gr_vissprite_t *spr = gr_vsprorder[i]; + boolean skipshadow = false; // skip shadow if it was drawn already for a linkdraw sprite encountered earlier in the list +#ifdef BAD_MODEL_OPTIONS + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, cv_glmodellighting.value); +#else + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, false); +#endif + + for (i = 0; i < gl_visspritecount; i++) + { + gl_vissprite_t *spr = gl_vsprorder[i]; +#ifdef HWPRECIP if (spr->precip) - { HWR_DrawPrecipitationSprite(spr); - } else +#endif { - if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value) + if (spr->mobj && spr->mobj->shadowscale && cv_shadow.value && !skipshadow) { HWR_DrawDropShadow(spr->mobj, spr->mobj->shadowscale); } - if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + if ((spr->mobj->flags2 & MF2_LINKDRAW) && spr->mobj->tracer) { - // 8/1/19: Only don't display player models if no default SPR_PLAY is found. - if (!cv_grmdls.value - || ((md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound - || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) - && ((!cv_grfallbackplayermodel.value) - || md2_models[SPR_PLAY].notfound - || md2_models[SPR_PLAY].scale < 0.0f)) - || spr->mobj->state == &states[S_PLAY_SIGN]) + // If this linkdraw sprite is behind a sprite that has a shadow, + // then that shadow has to be drawn first, otherwise the shadow ends up on top of + // the linkdraw sprite because the linkdraw sprite does not modify the z-buffer. + // The !skipshadow check is there in case there are multiple linkdraw sprites connected + // to the same tracer, so the tracer's shadow only gets drawn once. + if (cv_shadow.value && !skipshadow && spr->dispoffset < 0 && spr->mobj->tracer->shadowscale) { - HWR_DrawSprite(spr); - } - else - { - HWR_DrawMD2(spr); + HWR_DrawDropShadow(spr->mobj->tracer, spr->mobj->tracer->shadowscale); + skipshadow = true; + // The next sprite in this loop should be either another linkdraw sprite or the tracer. + // When the tracer is inevitably encountered, skipshadow will cause it's shadow + // to get skipped and skipshadow will get set to false by the 'else' clause below. } } else { - if (!cv_grmdls.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) - { + skipshadow = false; + } + + if (spr->mobj && spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + { + if (!cv_glmodels.value || md2_playermodels[(skin_t*)spr->mobj->skin-skins].notfound || md2_playermodels[(skin_t*)spr->mobj->skin-skins].scale < 0.0f) HWR_DrawSprite(spr); - } else { - HWR_DrawMD2(spr); + if (!HWR_DrawModel(spr)) + HWR_DrawSprite(spr); + } + } + else + { + if (!cv_glmodels.value || md2_models[spr->mobj->sprite].notfound || md2_models[spr->mobj->sprite].scale < 0.0f) + HWR_DrawSprite(spr); + else + { + if (!HWR_DrawModel(spr)) + HWR_DrawSprite(spr); } } } } + HWD.pfnSetSpecialState(HWD_SET_MODEL_LIGHTING, 0); + + // At the end of sprite drawing, draw shapes of linkdraw sprites to z-buffer, so they + // don't get drawn over by transparent surfaces. + HWR_LinkDrawHackFinish(); + // Work around a r_opengl.c bug with PF_Invisible by making this SetBlend call + // where PF_Invisible is off and PF_Masked is on. + // (Other states probably don't matter. Here I left them same as in LinkDrawHackFinish) + // Without this workaround the rest of the draw calls in this frame (including UI, screen texture) + // can get drawn using an incorrect glBlendFunc, resulting in a occasional black screen. + HWD.pfnSetBlend(PF_Translucent|PF_Occlude|PF_Clip|PF_Masked); } // -------------------------------------------------------------------------- // HWR_AddSprites // During BSP traversal, this adds sprites by sector. // -------------------------------------------------------------------------- -void HWR_AddSprites(sector_t *sec) +static UINT8 sectorlight; +static void HWR_AddSprites(sector_t *sec) { mobj_t *thing; +#ifdef HWPRECIP precipmobj_t *precipthing; - fixed_t approx_dist, limit_dist; +#endif + fixed_t limit_dist; // BSP is traversed by subsector. // A sector might have been split into several @@ -4009,63 +4835,29 @@ void HWR_AddSprites(sector_t *sec) // Well, now it will be done. sec->validcount = validcount; + // sprite lighting + sectorlight = sec->lightlevel & 0xff; + // Handle all things in sector. // If a limit exists, handle things a tiny bit different. - if ((limit_dist = (fixed_t)(cv_drawdist.value) * mapobjectscale)) + limit_dist = (fixed_t)(cv_drawdist.value) * mapobjectscale; + for (thing = sec->thinglist; thing; thing = thing->snext) { - for (thing = sec->thinglist; thing; thing = thing->snext) - { - if (thing->sprite == SPR_NULL) - continue; - - if ((viewssnum == 0 && (thing->drawflags & MFD_DONTDRAWP1)) - || (viewssnum == 1 && (thing->drawflags & MFD_DONTDRAWP2)) - || (viewssnum == 2 && (thing->drawflags & MFD_DONTDRAWP3)) - || (viewssnum == 3 && (thing->drawflags & MFD_DONTDRAWP4))) - continue; - - approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); - - if (approx_dist > limit_dist) - continue; - + if (R_ThingVisibleWithinDist(thing, limit_dist)) HWR_ProjectSprite(thing); - } - } - else - { - // Draw everything in sector, no checks - for (thing = sec->thinglist; thing; thing = thing->snext) - { - if (thing->sprite == SPR_NULL) - continue; - - if ((viewssnum == 0 && (thing->drawflags & MFD_DONTDRAWP1)) - || (viewssnum == 1 && (thing->drawflags & MFD_DONTDRAWP2)) - || (viewssnum == 2 && (thing->drawflags & MFD_DONTDRAWP3)) - || (viewssnum == 3 && (thing->drawflags & MFD_DONTDRAWP4))) - continue; - - HWR_ProjectSprite(thing); - } } - // No to infinite precipitation draw distance. - if ((limit_dist = (fixed_t)(cv_drawdist_precip.value) * mapobjectscale)) +#ifdef HWPRECIP + // no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off + if ((limit_dist = (fixed_t)cv_drawdist_precip.value * mapobjectscale)) { for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) { - if (precipthing->precipflags & PCF_INVISIBLE) - continue; - - approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y); - - if (approx_dist > limit_dist) - continue; - - HWR_ProjectPrecipitationSprite(precipthing); + if (R_PrecipThingVisible(precipthing, limit_dist)) + HWR_ProjectPrecipitationSprite(precipthing); } } +#endif } // -------------------------------------------------------------------------- @@ -4073,45 +4865,75 @@ void HWR_AddSprites(sector_t *sec) // Generates a vissprite for a thing if it might be visible. // -------------------------------------------------------------------------- // BP why not use xtoviexangle/viewangletox like in bsp ?.... -void HWR_ProjectSprite(mobj_t *thing) +static void HWR_ProjectSprite(mobj_t *thing) { const fixed_t thingxpos = thing->x + thing->sprxoff; const fixed_t thingypos = thing->y + thing->spryoff; const fixed_t thingzpos = thing->z + thing->sprzoff; - gr_vissprite_t *vis; + gl_vissprite_t *vis; float tr_x, tr_y; float tz; + float tracertz = 0.0f; float x1, x2; - float z1, z2; float rightsin, rightcos; float this_scale; float gz, gzt; spritedef_t *sprdef; spriteframe_t *sprframe; + spriteinfo_t *sprinfo; + md2_t *md2; size_t lumpoff; unsigned rot; - UINT8 flip; + UINT16 flip; boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); + boolean mirrored = thing->mirrored; + boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); + INT32 dispoffset; + angle_t ang; - const boolean papersprite = (thing->frame & FF_PAPERSPRITE); INT32 heightsec, phs; + const boolean papersprite = (thing->frame & FF_PAPERSPRITE); + angle_t mobjangle = (thing->player ? thing->player->drawangle : thing->angle); + float z1, z2; + + fixed_t spr_width, spr_height; + fixed_t spr_offset, spr_topoffset; +#ifdef ROTSPRITE + patch_t *rotsprite = NULL; + INT32 rollangle = 0; +#endif if (!thing) return; - else - this_scale = FIXED_TO_FLOAT(thing->scale); + + dispoffset = thing->info->dispoffset; + + this_scale = FIXED_TO_FLOAT(thing->scale); // transform the origin point - tr_x = FIXED_TO_FLOAT(thingxpos) - gr_viewx; - tr_y = FIXED_TO_FLOAT(thingypos) - gr_viewy; + tr_x = FIXED_TO_FLOAT(thingxpos) - gl_viewx; + tr_y = FIXED_TO_FLOAT(thingypos) - gl_viewy; // rotation around vertical axis - tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin); + tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); // thing is behind view plane? - if (tz < ZCLIP_PLANE && !papersprite && (!cv_grmdls.value || md2_models[thing->sprite].notfound == true)) //Yellow: Only MD2's dont disappear - return; + if (tz < ZCLIP_PLANE && !papersprite) + { + if (cv_glmodels.value) //Yellow: Only MD2's dont disappear + { + if (thing->skin && thing->sprite == SPR_PLAY) + md2 = &md2_playermodels[( (skin_t *)thing->skin - skins )]; + else + md2 = &md2_models[thing->sprite]; + + if (md2->notfound || md2->scale < 0.0f) + return; + } + else + return; + } // The above can stay as it works for cutting sprites that are too close tr_x = FIXED_TO_FLOAT(thingxpos); @@ -4127,9 +4949,15 @@ void HWR_ProjectSprite(mobj_t *thing) //Fab : 02-08-98: 'skin' override spritedef currently used for skin if (thing->skin && thing->sprite == SPR_PLAY) - sprdef = &((skin_t *)thing->skin)->spritedef; + { + sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; + sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; + } else + { sprdef = &sprites[thing->sprite]; + sprinfo = NULL; + } if (rot >= sprdef->numframes) { @@ -4138,6 +4966,7 @@ void HWR_ProjectSprite(mobj_t *thing) thing->sprite = states[S_UNKNOWN].sprite; thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; + sprinfo = NULL; rot = thing->frame&FF_FRAMEMASK; thing->state->sprite = thing->sprite; thing->state->frame = thing->frame; @@ -4150,10 +4979,9 @@ void HWR_ProjectSprite(mobj_t *thing) I_Error("sprframes NULL for sprite %d\n", thing->sprite); #endif - if (thing->player) - ang = R_PointToAngle (thingxpos, thingypos) - thing->player->frameangle; - else - ang = R_PointToAngle (thingxpos, thingypos) - thing->angle; + ang = R_PointToAngle (thingxpos, thingypos) - mobjangle; + if (mirrored) + ang = InvAngle(ang); if (sprframe->rotate == SRF_SINGLE) { @@ -4163,20 +4991,20 @@ void HWR_ProjectSprite(mobj_t *thing) flip = sprframe->flip; // Will only be 0x00 or 0xFF if (papersprite && ang < ANGLE_180) - { - if (flip) - flip = 0; - else - flip = 255; - } + flip ^= 0xFFFF; } else { // choose a different rotation based on player view - if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right + if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right rot = 6; // F7 slot - else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left + else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left rot = 2; // F3 slot + else if (sprframe->rotate & SRF_3DGE) // 16-angle mode + { + rot = (ang+ANGLE_180+ANGLE_11hh)>>28; + rot = ((rot & 1)<<3)|(rot>>1); + } else // Normal behaviour rot = (ang+ANGLE_202h)>>29; @@ -4185,21 +5013,40 @@ void HWR_ProjectSprite(mobj_t *thing) flip = sprframe->flip & (1<skin && ((skin_t *)thing->skin)->flags & SF_HIRES) this_scale = this_scale * FIXED_TO_FLOAT(((skin_t *)thing->skin)->highresscale); + spr_width = spritecachedinfo[lumpoff].width; + spr_height = spritecachedinfo[lumpoff].height; + spr_offset = spritecachedinfo[lumpoff].offset; + spr_topoffset = spritecachedinfo[lumpoff].topoffset; + +#ifdef ROTSPRITE + if (thing->rollangle) + { + rollangle = R_GetRollAngle(thing->rollangle); + if (!(sprframe->rotsprite.cached & (1<sprite, (thing->frame & FF_FRAMEMASK), sprinfo, sprframe, rot, flip); + rotsprite = sprframe->rotsprite.patch[rot][rollangle]; + if (rotsprite != NULL) + { + spr_width = SHORT(rotsprite->width) << FRACBITS; + spr_height = SHORT(rotsprite->height) << FRACBITS; + spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS; + spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS; + // flip -> rotate, not rotate -> flip + flip = 0; + } + } +#endif + if (papersprite) { - rightsin = FIXED_TO_FLOAT(FINESINE((thing->angle)>>ANGLETOFINESHIFT)); - rightcos = FIXED_TO_FLOAT(FINECOSINE((thing->angle)>>ANGLETOFINESHIFT)); + rightsin = FIXED_TO_FLOAT(FINESINE((mobjangle)>>ANGLETOFINESHIFT)); + rightcos = FIXED_TO_FLOAT(FINECOSINE((mobjangle)>>ANGLETOFINESHIFT)); } else { @@ -4207,17 +5054,31 @@ void HWR_ProjectSprite(mobj_t *thing) rightcos = FIXED_TO_FLOAT(FINECOSINE((viewangle + ANGLE_90)>>ANGLETOFINESHIFT)); } + flip = !flip != !hflip; + if (flip) { - x1 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale); - x2 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale); + x1 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); + x2 = (FIXED_TO_FLOAT(spr_offset) * this_scale); } else { - x1 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].offset) * this_scale); - x2 = (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset) * this_scale); + x1 = (FIXED_TO_FLOAT(spr_offset) * this_scale); + x2 = (FIXED_TO_FLOAT(spr_width - spr_offset) * this_scale); } + // test if too close +/* + if (papersprite) + { + z1 = tz - x1 * angle_scalez; + z2 = tz + x2 * angle_scalez; + + if (max(z1, z2) < ZCLIP_PLANE) + return; + } +*/ + z1 = tr_y + x1 * rightsin; z2 = tr_y - x2 * rightsin; x1 = tr_x + x1 * rightcos; @@ -4225,18 +5086,18 @@ void HWR_ProjectSprite(mobj_t *thing) if (vflip) { - gz = FIXED_TO_FLOAT(thingzpos + thing->height) - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale; - gzt = gz + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale; + gz = FIXED_TO_FLOAT(thingzpos+thing->height) - FIXED_TO_FLOAT(spr_topoffset) * this_scale; + gzt = gz + FIXED_TO_FLOAT(spr_height) * this_scale; } else { - gzt = FIXED_TO_FLOAT(thingzpos) + FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale; - gz = gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale; + gzt = FIXED_TO_FLOAT(thingzpos) + FIXED_TO_FLOAT(spr_topoffset) * this_scale; + gz = gzt - FIXED_TO_FLOAT(spr_height) * this_scale; } if (thing->subsector->sector->cullheight) { - if (HWR_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, gr_viewz, gz, gzt)) + if (HWR_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, gl_viewz, gz, gzt)) return; } @@ -4248,33 +5109,65 @@ void HWR_ProjectSprite(mobj_t *thing) if (heightsec != -1 && phs != -1) // only clip things which are in special sectors { - if (gr_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ? + if (gl_viewz < FIXED_TO_FLOAT(sectors[phs].floorheight) ? FIXED_TO_FLOAT(thingzpos) >= FIXED_TO_FLOAT(sectors[heightsec].floorheight) : gzt < FIXED_TO_FLOAT(sectors[heightsec].floorheight)) return; - if (gr_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ? - gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gr_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) : + if (gl_viewz > FIXED_TO_FLOAT(sectors[phs].ceilingheight) ? + gzt < FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) && gl_viewz >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight) : FIXED_TO_FLOAT(thingzpos) >= FIXED_TO_FLOAT(sectors[heightsec].ceilingheight)) return; } + if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) + { + if (! R_ThingVisible(thing->tracer)) + return; + + // calculate tz for tracer, same way it is calculated for this sprite + // transform the origin point + tr_x = FIXED_TO_FLOAT(thing->tracer->x) - gl_viewx; + tr_y = FIXED_TO_FLOAT(thing->tracer->y) - gl_viewy; + + // rotation around vertical axis + tracertz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); + + // Software does not render the linkdraw sprite if the tracer is behind the view plane, + // so do the same check here. + // NOTE: This check has the same flaw as the view plane check at the beginning of HWR_ProjectSprite: + // the view aiming angle is not taken into account, leading to sprites disappearing too early when they + // can still be seen when looking down/up at steep angles. + if (tracertz < ZCLIP_PLANE) + return; + + // if the sprite is behind the tracer, invert dispoffset, putting the sprite behind the tracer + if (tz > tracertz) + dispoffset *= -1; + } + // store information in a vissprite vis = HWR_NewVisSprite(); vis->x1 = x1; vis->x2 = x2; - vis->z1 = z1; - vis->z2 = z2; vis->tz = tz; // Keep tz for the simple sprite sorting that happens - vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST - vis->patchlumpnum = sprframe->lumppat[rot]; + vis->tracertz = tracertz; + vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST + //vis->patchlumpnum = sprframe->lumppat[rot]; +#ifdef ROTSPRITE + if (rotsprite) + vis->gpatch = (GLPatch_t *)rotsprite; + else +#endif + vis->gpatch = (GLPatch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); vis->flip = flip; vis->mobj = thing; - + vis->z1 = z1; + vis->z2 = z2; //Hurdler: 25/04/2000: now support colormap in hardware mode - if ((vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" + if ((vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { - if (vis->mobj->type == MT_CYBRAKDEMON) + if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) vis->colormap = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) vis->colormap = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); @@ -4285,14 +5178,18 @@ void HWR_ProjectSprite(mobj_t *thing) { // New colormap stuff for skins Tails 06-07-2002 if (thing->colorized) + { vis->colormap = R_GetTranslationColormap(TC_RAINBOW, thing->color, GTC_CACHE); + } else if (thing->skin && thing->sprite == SPR_PLAY) // This thing is a player! { size_t skinnum = (skin_t*)thing->skin-skins; vis->colormap = R_GetTranslationColormap((INT32)skinnum, thing->color, GTC_CACHE); } else - vis->colormap = R_GetTranslationColormap(TC_DEFAULT, thing->color, GTC_CACHE); + { + vis->colormap = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color ? vis->mobj->color : SKINCOLOR_GREEN, GTC_CACHE); + } } else { @@ -4314,10 +5211,11 @@ void HWR_ProjectSprite(mobj_t *thing) vis->precip = false; } +#ifdef HWPRECIP // Precipitation projector for hardware mode -void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) +static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) { - gr_vissprite_t *vis; + gl_vissprite_t *vis; float tr_x, tr_y; float tz; float x1, x2; @@ -4330,11 +5228,11 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) UINT8 flip; // transform the origin point - tr_x = FIXED_TO_FLOAT(thing->x) - gr_viewx; - tr_y = FIXED_TO_FLOAT(thing->y) - gr_viewy; + tr_x = FIXED_TO_FLOAT(thing->x) - gl_viewx; + tr_y = FIXED_TO_FLOAT(thing->y) - gl_viewy; // rotation around vertical axis - tz = (tr_x * gr_viewcos) + (tr_y * gr_viewsin); + tz = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); // thing is behind view plane? if (tz < ZCLIP_PLANE) @@ -4386,13 +5284,6 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) x1 = tr_x + x1 * rightcos; x2 = tr_x - x2 * rightcos; - // okay, we can't return now... this is a hack, but weather isn't networked, so it should be ok - if (!(thing->precipflags & PCF_THUNK)) - { - P_PrecipThinker(thing); - thing->precipflags |= PCF_THUNK; - } - // // store information in a vissprite // @@ -4403,7 +5294,8 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->z2 = z2; vis->tz = tz; vis->dispoffset = 0; // Monster Iestyn: 23/11/15: HARDWARE SUPPORT AT LAST - vis->patchlumpnum = sprframe->lumppat[rot]; + //vis->patchlumpnum = sprframe->lumppat[rot]; + vis->gpatch = (GLPatch_t *)W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); vis->flip = flip; vis->mobj = (mobj_t *)thing; @@ -4418,41 +5310,303 @@ void HWR_ProjectPrecipitationSprite(precipmobj_t *thing) vis->ty = FIXED_TO_FLOAT(thing->z + spritecachedinfo[lumpoff].topoffset); vis->precip = true; + + // okay... this is a hack, but weather isn't networked, so it should be ok + if (!(thing->precipflags & PCF_THUNK)) + { + P_PrecipThinker(thing); + thing->precipflags |= PCF_THUNK; + } +} +#endif + +// ========================================================================== +// Sky dome rendering, ported from PrBoom+ +// ========================================================================== + +static gl_sky_t gl_sky; + +static void HWR_SkyDomeVertex(gl_sky_t *sky, gl_skyvertex_t *vbo, int r, int c, signed char yflip, float delta, boolean foglayer) +{ + const float radians = (float)(M_PIl / 180.0f); + const float scale = 10000.0f; + const float maxSideAngle = 60.0f; + + float topAngle = (c / (float)sky->columns * 360.0f); + float sideAngle = (maxSideAngle * (sky->rows - r) / sky->rows); + float height = (float)(sin(sideAngle * radians)); + float realRadius = (float)(scale * cos(sideAngle * radians)); + float x = (float)(realRadius * cos(topAngle * radians)); + float y = (!yflip) ? scale * height : -scale * height; + float z = (float)(realRadius * sin(topAngle * radians)); + float timesRepeat = (4 * (256.0f / sky->width)); + if (fpclassify(timesRepeat) == FP_ZERO) + timesRepeat = 1.0f; + + if (!foglayer) + { + vbo->r = 255; + vbo->g = 255; + vbo->b = 255; + vbo->a = (r == 0 ? 0 : 255); + + // And the texture coordinates. + vbo->u = (-timesRepeat * c / (float)sky->columns); + if (!yflip) // Flipped Y is for the lower hemisphere. + vbo->v = (r / (float)sky->rows) + 0.5f; + else + vbo->v = 1.0f + ((sky->rows - r) / (float)sky->rows) + 0.5f; + } + + if (r != 4) + y += 300.0f; + + // And finally the vertex. + vbo->x = x; + vbo->y = y + delta; + vbo->z = z; } -static boolean drewsky = false; - -void HWR_DrawSkyBackground(float fpov) +// Clears the sky dome. +void HWR_ClearSkyDome(void) { - FTransform dometransform; + gl_sky_t *sky = &gl_sky; - if (drewsky) - return; + if (sky->loops) + free(sky->loops); + if (sky->data) + free(sky->data); - memset(&dometransform, 0x00, sizeof(FTransform)); + sky->loops = NULL; + sky->data = NULL; - //04/01/2000: Hurdler: added for T&L - // It should replace all other gr_viewxxx when finished - if (!atransform.shearing) - dometransform.anglex = (float)(aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + sky->vbo = 0; + sky->rows = sky->columns = 0; + sky->loopcount = 0; - dometransform.flip = atransform.flip; - dometransform.mirror = atransform.mirror; - dometransform.shearing = atransform.shearing; - dometransform.viewaiming = atransform.viewaiming; + sky->detail = 0; + sky->texture = -1; + sky->width = sky->height = 0; - dometransform.scalex = 1; - dometransform.scaley = (float)vid.width/vid.height; - dometransform.scalez = 1; - dometransform.fovxangle = fpov; // Tails - dometransform.fovyangle = fpov; // Tails - dometransform.splitscreen = splitscreen; + sky->rebuild = true; +} - HWR_GetTexture(texturetranslation[skytexture]); - HWD.pfnSetShader(7); // sky shader - HWD.pfnRenderSkyDome(skytexture, textures[skytexture]->width, textures[skytexture]->height, dometransform); - HWD.pfnSetShader(0); +void HWR_BuildSkyDome(void) +{ + int c, r; + signed char yflip; + int row_count = 4; + int col_count = 4; + float delta; + + gl_sky_t *sky = &gl_sky; + gl_skyvertex_t *vertex_p; + texture_t *texture = textures[texturetranslation[skytexture]]; + + sky->detail = 16; + col_count *= sky->detail; + + if ((sky->columns != col_count) || (sky->rows != row_count)) + HWR_ClearSkyDome(); + + sky->columns = col_count; + sky->rows = row_count; + sky->vertex_count = 2 * sky->rows * (sky->columns * 2 + 2) + sky->columns * 2; + + if (!sky->loops) + sky->loops = malloc((sky->rows * 2 + 2) * sizeof(sky->loops[0])); + + // create vertex array + if (!sky->data) + sky->data = malloc(sky->vertex_count * sizeof(sky->data[0])); + + sky->texture = texturetranslation[skytexture]; + sky->width = texture->width; + sky->height = texture->height; + + vertex_p = &sky->data[0]; + sky->loopcount = 0; + + for (yflip = 0; yflip < 2; yflip++) + { + sky->loops[sky->loopcount].mode = HWD_SKYLOOP_FAN; + sky->loops[sky->loopcount].vertexindex = vertex_p - &sky->data[0]; + sky->loops[sky->loopcount].vertexcount = col_count; + sky->loops[sky->loopcount].use_texture = false; + sky->loopcount++; + + delta = 0.0f; + + for (c = 0; c < col_count; c++) + { + HWR_SkyDomeVertex(sky, vertex_p, 1, c, yflip, 0.0f, true); + vertex_p->r = 255; + vertex_p->g = 255; + vertex_p->b = 255; + vertex_p->a = 255; + vertex_p++; + } + + delta = (yflip ? 5.0f : -5.0f) / 128.0f; + + for (r = 0; r < row_count; r++) + { + sky->loops[sky->loopcount].mode = HWD_SKYLOOP_STRIP; + sky->loops[sky->loopcount].vertexindex = vertex_p - &sky->data[0]; + sky->loops[sky->loopcount].vertexcount = 2 * col_count + 2; + sky->loops[sky->loopcount].use_texture = true; + sky->loopcount++; + + for (c = 0; c <= col_count; c++) + { + HWR_SkyDomeVertex(sky, vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0), yflip, delta, false); + HWR_SkyDomeVertex(sky, vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0), yflip, delta, false); + } + } + } +} + +static void HWR_DrawSkyBackground(player_t *player) +{ + HWD.pfnSetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated); + + if (cv_glskydome.value) + { + FTransform dometransform; + const float fpov = FIXED_TO_FLOAT(cv_fov[viewssnum].value+player->fovadd); + postimg_t *type = &postimgtype[0]; + SINT8 i; + + for (i = r_splitscreen; i >= 0; i--) + { + if (player == &players[displayplayers[i]]) + { + type = &postimgtype[i]; + break; + } + } + + memset(&dometransform, 0x00, sizeof(FTransform)); + + //04/01/2000: Hurdler: added for T&L + // It should replace all other gl_viewxxx when finished + HWR_SetTransformAiming(&dometransform, player, false); + dometransform.angley = (float)((viewangle-ANGLE_270)>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + + if (*type == postimg_flip) + dometransform.flip = true; + else + dometransform.flip = false; + + dometransform.scalex = 1; + dometransform.scaley = (float)vid.width/vid.height; + dometransform.scalez = 1; + dometransform.fovxangle = fpov; // Tails + dometransform.fovyangle = fpov; // Tails + if (player->viewrollangle != 0) + { + fixed_t rol = AngleFixed(player->viewrollangle); + dometransform.rollangle = FIXED_TO_FLOAT(rol); + dometransform.roll = true; + } + dometransform.splitscreen = r_splitscreen; + + HWR_GetTexture(texturetranslation[skytexture]); + + if (gl_sky.texture != texturetranslation[skytexture]) + { + HWR_ClearSkyDome(); + HWR_BuildSkyDome(); + } + + HWD.pfnSetShader(SHADER_SKY); // sky shader + HWD.pfnSetTransform(&dometransform); + HWD.pfnRenderSkyDome(&gl_sky); + } + else + { + FOutVector v[4]; + angle_t angle; + float dimensionmultiply; + float aspectratio; + float angleturn; + + HWR_GetTexture(texturetranslation[skytexture]); + aspectratio = (float)vid.width/(float)vid.height; + + //Hurdler: the sky is the only texture who need 4.0f instead of 1.0 + // because it's called just after clearing the screen + // and thus, the near clipping plane is set to 3.99 + // Sryder: Just use the near clipping plane value then + + // 3--2 + // | /| + // |/ | + // 0--1 + v[0].x = v[3].x = -ZCLIP_PLANE-1; + v[1].x = v[2].x = ZCLIP_PLANE+1; + v[0].y = v[1].y = -ZCLIP_PLANE-1; + v[2].y = v[3].y = ZCLIP_PLANE+1; + + v[0].z = v[1].z = v[2].z = v[3].z = ZCLIP_PLANE+1; + + // X + + // NOTE: This doesn't work right with texture widths greater than 1024 + // software doesn't draw any further than 1024 for skies anyway, but this doesn't overlap properly + // The only time this will probably be an issue is when a sky wider than 1024 is used as a sky AND a regular wall texture + + angle = (dup_viewangle + gl_xtoviewangle[0]); + + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->width/256.0f); + + v[0].s = v[3].s = (-1.0f * angle) / ((ANGLE_90-1)*dimensionmultiply); // left + v[2].s = v[1].s = v[0].s + (1.0f/dimensionmultiply); // right (or left + 1.0f) + // use +angle and -1.0f above instead if you wanted old backwards behavior + + // Y + angle = aimingangle; + dimensionmultiply = ((float)textures[texturetranslation[skytexture]]->height/(128.0f*aspectratio)); + + if (r_splitscreen == 1) + { + dimensionmultiply *= 2; + angle *= 2; + } + + // Middle of the sky should always be at angle 0 + // need to keep correct aspect ratio with X + if (atransform.flip) + { + // During vertical flip the sky should be flipped and it's y movement should also be flipped obviously + v[3].t = v[2].t = -(0.5f-(0.5f/dimensionmultiply)); // top + v[0].t = v[1].t = v[3].t - (1.0f/dimensionmultiply); // bottom (or top - 1.0f) + } + else + { + v[0].t = v[1].t = -(0.5f-(0.5f/dimensionmultiply)); // bottom + v[3].t = v[2].t = v[0].t - (1.0f/dimensionmultiply); // top (or bottom - 1.0f) + } + + angleturn = (((float)ANGLE_45-1.0f)*aspectratio)*dimensionmultiply; + + if (angle > ANGLE_180) // Do this because we don't want the sky to suddenly teleport when crossing over 0 to 360 and vice versa + { + angle = InvAngle(angle); + v[3].t = v[2].t += ((float) angle / angleturn); + v[0].t = v[1].t += ((float) angle / angleturn); + } + else + { + v[3].t = v[2].t -= ((float) angle / angleturn); + v[0].t = v[1].t -= ((float) angle / angleturn); + } + + HWD.pfnUnSetShader(); + HWD.pfnDrawPolygon(NULL, v, 4, 0); + } + + HWD.pfnSetShader(SHADER_DEFAULT); } @@ -4461,12 +5615,23 @@ void HWR_DrawSkyBackground(float fpov) // -----------------+ static inline void HWR_ClearView(void) { - HWD.pfnGClipRect((INT32)gr_viewwindowx, - (INT32)gr_viewwindowy, - (INT32)(gr_viewwindowx + gr_viewwidth), - (INT32)(gr_viewwindowy + gr_viewheight), + // 3--2 + // | /| + // |/ | + // 0--1 + + /// \bug faB - enable depth mask, disable color mask + + HWD.pfnGClipRect((INT32)gl_viewwindowx, + (INT32)gl_viewwindowy, + (INT32)(gl_viewwindowx + gl_viewwidth), + (INT32)(gl_viewwindowy + gl_viewheight), ZCLIP_PLANE); HWD.pfnClearBuffer(false, true, 0); + + //disable clip window - set to full size + // rem by Hurdler + // HWD.pfnGClipRect(0, 0, vid.width, vid.height); } @@ -4476,174 +5641,252 @@ static inline void HWR_ClearView(void) void HWR_SetViewSize(void) { // setup view size - gr_viewwidth = (float)vid.width; - gr_viewheight = (float)vid.height; + gl_viewwidth = (float)vid.width; + gl_viewheight = (float)vid.height; - if (r_splitscreen) - gr_viewheight /= 2; + if (r_splitscreen > 0) + { + gl_viewheight /= 2; - if (r_splitscreen > 1) - gr_viewwidth /= 2; + if (r_splitscreen > 1) + { + gl_viewwidth /= 2; + } + } - gr_basecenterx = gr_viewwidth / 2; - gr_basecentery = gr_viewheight / 2; + gl_basecenterx = gl_viewwidth / 2; + gl_basecentery = gl_viewheight / 2; - gr_baseviewwindowy = 0; - gr_basewindowcentery = (float)(gr_viewheight / 2); + gl_baseviewwindowx = 0; + gl_basewindowcenterx = gl_viewwidth / 2; - gr_baseviewwindowx = 0; - gr_basewindowcenterx = (float)(gr_viewwidth / 2); + gl_baseviewwindowy = 0; + gl_basewindowcentery = gl_viewheight / 2; - gr_pspritexscale = ((vid.width*gr_pspriteyscale*BASEVIDHEIGHT)/BASEVIDWIDTH)/vid.height; - gr_pspriteyscale = ((vid.height*gr_pspritexscale*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width; + gl_pspritexscale = gl_viewwidth / BASEVIDWIDTH; + gl_pspriteyscale = ((vid.height*gl_pspritexscale*BASEVIDWIDTH)/BASEVIDHEIGHT)/vid.width; HWD.pfnFlushScreenTextures(); } +// -------------------+ +// HWR_ShiftViewPort : offset viewport according to current split +// -------------------+ +static void HWR_ShiftViewPort(void) +{ + gl_centerx = gl_basecenterx; + gl_viewwindowx = gl_baseviewwindowx; + gl_windowcenterx = gl_basewindowcenterx; + + gl_centery = gl_basecentery; + gl_viewwindowy = gl_baseviewwindowy; + gl_windowcentery = gl_basewindowcentery; + + if (viewssnum > ( r_splitscreen > 1 )) + { + gl_viewwindowy += gl_viewheight; + gl_windowcentery += gl_viewheight; + } + + if (r_splitscreen > 1 && viewssnum & 1) + { + gl_viewwindowx += gl_viewwidth; + gl_windowcenterx += gl_viewwidth; + } +} + +// Set view aiming, for the sky dome, the skybox, +// and the normal view, all with a single function. +static void HWR_SetTransformAiming(FTransform *trans, player_t *player, boolean skybox) +{ + // 1 = always on + // 2 = chasecam only + if (cv_glshearing.value == 1 || (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox))) + { + fixed_t fixedaiming = AIMINGTODY(aimingangle); + trans->viewaiming = FIXED_TO_FLOAT(fixedaiming); + trans->shearing = true; + gl_aimingangle = 0; + } + else + { + trans->shearing = false; + gl_aimingangle = aimingangle; + } + + trans->anglex = (float)(gl_aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); +} // ========================================================================== -// Render the current frame. +// Same as rendering the player view, but from the skybox object // ========================================================================== -void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox) +void HWR_RenderSkyboxView(player_t *player) { - angle_t a1; - const float fpov = FIXED_TO_FLOAT(cv_fov.value+player->fovadd); - postimg_t *postprocessor = &postimgtype[0]; - INT32 i; + const float fpov = FIXED_TO_FLOAT(cv_fov[viewssnum].value+player->fovadd); + postimg_t *type = &postimgtype[viewssnum]; + + { + // do we really need to save player (is it not the same)? + player_t *saved_player = stplyr; + stplyr = player; + ST_doPaletteStuff(); + stplyr = saved_player; +#ifdef ALAM_LIGHTING + HWR_SetLights(viewssnum); +#endif + } + + // note: sets viewangle, viewx, viewy, viewz + R_SkyboxFrame(player); + + // copy view cam position for local use + dup_viewx = viewx; + dup_viewy = viewy; + dup_viewz = viewz; + dup_viewangle = viewangle; // set window position - gr_centerx = gr_basecenterx; - gr_viewwindowx = gr_baseviewwindowx; - gr_windowcenterx = gr_basewindowcenterx; - gr_centery = gr_basecentery; - gr_viewwindowy = gr_baseviewwindowy; - gr_windowcentery = gr_basewindowcentery; - - if ((r_splitscreen == 1 && viewnumber == 1) || (r_splitscreen > 1 && viewnumber > 1)) - { - gr_viewwindowy += gr_viewheight; - gr_windowcentery += gr_viewheight; - } - - if (r_splitscreen > 1 && viewnumber & 1) - { - gr_viewwindowx += gr_viewwidth; - gr_windowcenterx += gr_viewwidth; - } + HWR_ShiftViewPort(); // check for new console commands. NetUpdate(); - gr_viewx = FIXED_TO_FLOAT(viewx); - gr_viewy = FIXED_TO_FLOAT(viewy); - gr_viewz = FIXED_TO_FLOAT(viewz); - gr_viewsin = FIXED_TO_FLOAT(viewsin); - gr_viewcos = FIXED_TO_FLOAT(viewcos); + gl_viewx = FIXED_TO_FLOAT(dup_viewx); + gl_viewy = FIXED_TO_FLOAT(dup_viewy); + gl_viewz = FIXED_TO_FLOAT(dup_viewz); + gl_viewsin = FIXED_TO_FLOAT(viewsin); + gl_viewcos = FIXED_TO_FLOAT(viewcos); - // Set T&L transform - atransform.x = gr_viewx; - atransform.y = gr_viewy; - atransform.z = gr_viewz; + //04/01/2000: Hurdler: added for T&L + // It should replace all other gl_viewxxx when finished + memset(&atransform, 0x00, sizeof(FTransform)); + HWR_SetTransformAiming(&atransform, player, true); + atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + + gl_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gl_aimingangle>>ANGLETOFINESHIFT)); + gl_viewludcos = FIXED_TO_FLOAT(-FINESINE(gl_aimingangle>>ANGLETOFINESHIFT)); + + if (*type == postimg_flip) + atransform.flip = true; + else + atransform.flip = false; + + atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) + atransform.y = gl_viewy; // FIXED_TO_FLOAT(viewy) + atransform.z = gl_viewz; // FIXED_TO_FLOAT(viewz) atransform.scalex = 1; atransform.scaley = (float)vid.width/vid.height; atransform.scalez = 1; - // 14042019 - gr_aimingangle = aimingangle; - atransform.shearing = false; - atransform.viewaiming = aimingangle; - - if (cv_grshearing.value) - { - gr_aimingangle = 0; - atransform.shearing = true; - } - - gr_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gr_aimingangle>>ANGLETOFINESHIFT)); - gr_viewludcos = FIXED_TO_FLOAT(-FINESINE(gr_aimingangle>>ANGLETOFINESHIFT)); - - atransform.anglex = (float)(gr_aimingangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); - atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails + if (player->viewrollangle != 0) + { + fixed_t rol = AngleFixed(player->viewrollangle); + atransform.rollangle = FIXED_TO_FLOAT(rol); + atransform.roll = true; + } atransform.splitscreen = r_splitscreen; - for (i = 0; i <= splitscreen; i++) - { - if (player == &players[displayplayers[i]]) - postprocessor = &postimgtype[i]; - } + gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); - atransform.flip = false; - if (*postprocessor == postimg_flip) - atransform.flip = true; - - atransform.mirror = false; - if (*postprocessor == postimg_mirror) - atransform.mirror = true; - - // Clear view, set viewport (glViewport), set perspective... + //------------------------------------------------------------------------ HWR_ClearView(); + + if (drawsky) + HWR_DrawSkyBackground(player); + + //Hurdler: it doesn't work in splitscreen mode + drawsky = r_splitscreen; + HWR_ClearSprites(); - ST_doPaletteStuff(); + drawcount = 0; - // Draw the sky background. - HWR_DrawSkyBackground(fpov); - if (skybox) - drewsky = true; - - a1 = gld_FrustumAngle(gr_aimingangle); - gld_clipper_Clear(); - gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); +#ifdef NEWCLIP + { + angle_t a1 = gld_FrustumAngle(gl_aimingangle); + gld_clipper_Clear(); + gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); #ifdef HAVE_SPHEREFRUSTRUM - gld_FrustrumSetup(); + gld_FrustrumSetup(); +#endif + } +#else + HWR_ClearClipSegs(); #endif - // Set transform. + //04/01/2000: Hurdler: added for T&L + // Actually it only works on Walls and Planes HWD.pfnSetTransform(&atransform); // Reset the shader state. - HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_grshaders.value); - HWD.pfnSetShader(0); + HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_glshaders.value); + HWD.pfnSetShader(SHADER_DEFAULT); - if (cv_grbatching.value) - HWD.pfnStartBatching(); - - drawcount = 0; validcount++; - // Recursively "render" the BSP tree. + if (cv_glbatching.value) + HWR_StartBatching(); + HWR_RenderBSPNode((INT32)numnodes-1); - if (cv_grbatching.value) +#ifndef NEWCLIP + // Make a viewangle int so we can render things based on mouselook + viewangle = localaiming[viewssnum]; + + // Handle stuff when you are looking farther up or down. + if ((gl_aimingangle || fpov > 90.0f)) { - int dummy = 0;// the vars in RenderBatches are meant for render stats. But we don't have that stuff in this branch - // so that stuff could be removed... - HWD.pfnRenderBatches(&dummy, &dummy, &dummy, &dummy, &dummy, &dummy, &dummy); + dup_viewangle += ANGLE_90; + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //left + + dup_viewangle += ANGLE_90; + if (((INT32)gl_aimingangle > ANGLE_45 || (INT32)gl_aimingangle<-ANGLE_45)) + { + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //back + } + + dup_viewangle += ANGLE_90; + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //right + + dup_viewangle += ANGLE_90; } +#endif + + if (cv_glbatching.value) + HWR_RenderBatches(); // Check for new console commands. - // this was removed since it caused crashes on leaving record attack with models on since it was removing mobjs that were about to be rendered - //NetUpdate(); + NetUpdate(); + +#ifdef ALAM_LIGHTING + //14/11/99: Hurdler: moved here because it doesn't work with + // subsector, see other comments; + HWR_ResetLights(); +#endif // Draw MD2 and sprites HWR_SortVisSprites(); HWR_DrawSprites(); - if (numplanes || numpolyplanes || numwalls) // Render FOFs and translucent walls after everything - HWR_RenderDrawNodes(); +#ifdef NEWCORONAS + //Hurdler: they must be drawn before translucent planes, what about gl fog? + HWR_DrawCoronas(); +#endif + + if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything + { + HWR_CreateDrawNodes(); + } - // Unset transform and shader HWD.pfnSetTransform(NULL); HWD.pfnUnSetShader(); - // Run post processor effects - if (!skybox) - HWR_DoPostProcessor(player); - // Check for new console commands. NetUpdate(); @@ -4653,61 +5896,329 @@ void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox) } // ========================================================================== -// Render the player view. +// // ========================================================================== -void HWR_RenderPlayerView(INT32 viewnumber, player_t *player) +void HWR_RenderPlayerView(void) { + player_t * player = &players[displayplayers[viewssnum]]; + + const float fpov = FIXED_TO_FLOAT(cv_fov[viewssnum].value+player->fovadd); + postimg_t *type = &postimgtype[viewssnum]; + const boolean skybox = (skyboxmo[0] && cv_skybox.value); // True if there's a skybox object and skyboxes are on - // Clear the color buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. - if (viewnumber == 0) // Only do it if it's the first screen being rendered + FRGBAFloat ClearColor; + + ClearColor.red = 0.0f; + ClearColor.green = 0.0f; + ClearColor.blue = 0.0f; + ClearColor.alpha = 1.0f; + + if (cv_glshaders.value) + HWD.pfnSetShaderInfo(HWD_SHADERINFO_LEVELTIME, (INT32)leveltime); // The water surface shader needs the leveltime. + + if (viewssnum == 0) // Only do it if it's the first screen being rendered + HWD.pfnClearBuffer(true, false, &ClearColor); // Clear the Color Buffer, stops HOMs. Also seems to fix the skybox issue on Intel GPUs. + + ps_hw_skyboxtime = I_GetTimeMicros(); + if (skybox && drawsky) // If there's a skybox and we should be drawing the sky, draw the skybox + HWR_RenderSkyboxView(player); // This is drawn before everything else so it is placed behind + ps_hw_skyboxtime = I_GetTimeMicros() - ps_hw_skyboxtime; + { - FRGBAFloat ClearColor; - - ClearColor.red = 0.0f; - ClearColor.green = 0.0f; - ClearColor.blue = 0.0f; - ClearColor.alpha = 1.0f; - - HWD.pfnClearBuffer(true, false, &ClearColor); + // do we really need to save player (is it not the same)? + player_t *saved_player = stplyr; + stplyr = player; + ST_doPaletteStuff(); + stplyr = saved_player; +#ifdef ALAM_LIGHTING + HWR_SetLights(viewssnum); +#endif } - if (viewnumber > 3) - return; + // note: sets viewangle, viewx, viewy, viewz + R_SetupFrame(player); + framecount++; // timedemo - // Render the skybox if there is one. - drewsky = false; - if (skybox) + // copy view cam position for local use + dup_viewx = viewx; + dup_viewy = viewy; + dup_viewz = viewz; + dup_viewangle = viewangle; + + // set window position + HWR_ShiftViewPort(); + + // check for new console commands. + NetUpdate(); + + gl_viewx = FIXED_TO_FLOAT(dup_viewx); + gl_viewy = FIXED_TO_FLOAT(dup_viewy); + gl_viewz = FIXED_TO_FLOAT(dup_viewz); + gl_viewsin = FIXED_TO_FLOAT(viewsin); + gl_viewcos = FIXED_TO_FLOAT(viewcos); + + //04/01/2000: Hurdler: added for T&L + // It should replace all other gl_viewxxx when finished + memset(&atransform, 0x00, sizeof(FTransform)); + + HWR_SetTransformAiming(&atransform, player, false); + atransform.angley = (float)(viewangle>>ANGLETOFINESHIFT)*(360.0f/(float)FINEANGLES); + + gl_viewludsin = FIXED_TO_FLOAT(FINECOSINE(gl_aimingangle>>ANGLETOFINESHIFT)); + gl_viewludcos = FIXED_TO_FLOAT(-FINESINE(gl_aimingangle>>ANGLETOFINESHIFT)); + + if (*type == postimg_flip) + atransform.flip = true; + else + atransform.flip = false; + + atransform.x = gl_viewx; // FIXED_TO_FLOAT(viewx) + atransform.y = gl_viewy; // FIXED_TO_FLOAT(viewy) + atransform.z = gl_viewz; // FIXED_TO_FLOAT(viewz) + atransform.scalex = 1; + atransform.scaley = (float)vid.width/vid.height; + atransform.scalez = 1; + + atransform.fovxangle = fpov; // Tails + atransform.fovyangle = fpov; // Tails + if (player->viewrollangle != 0) { - R_SkyboxFrame(player); - HWR_RenderFrame(viewnumber, player, true); + fixed_t rol = AngleFixed(player->viewrollangle); + atransform.rollangle = FIXED_TO_FLOAT(rol); + atransform.roll = true; + } + atransform.splitscreen = r_splitscreen; + + gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); + + //------------------------------------------------------------------------ + HWR_ClearView(); // Clears the depth buffer and resets the view I believe + + if (!skybox && drawsky) // Don't draw the regular sky if there's a skybox + HWR_DrawSkyBackground(player); + + //Hurdler: it doesn't work in splitscreen mode + drawsky = r_splitscreen; + + HWR_ClearSprites(); + + drawcount = 0; + +#ifdef NEWCLIP + { + angle_t a1 = gld_FrustumAngle(gl_aimingangle); + gld_clipper_Clear(); + gld_clipper_SafeAddClipRange(viewangle + a1, viewangle - a1); +#ifdef HAVE_SPHEREFRUSTRUM + gld_FrustrumSetup(); +#endif + } +#else + HWR_ClearClipSegs(); +#endif + + //04/01/2000: Hurdler: added for T&L + // Actually it only works on Walls and Planes + HWD.pfnSetTransform(&atransform); + + // Reset the shader state. + HWD.pfnSetSpecialState(HWD_SET_SHADERS, cv_glshaders.value); + HWD.pfnSetShader(SHADER_DEFAULT); + + ps_numbspcalls = 0; + ps_numpolyobjects = 0; + ps_bsptime = I_GetTimeMicros(); + + validcount++; + + if (cv_glbatching.value) + HWR_StartBatching(); + + HWR_RenderBSPNode((INT32)numnodes-1); + +#ifndef NEWCLIP + // Make a viewangle int so we can render things based on mouselook + viewangle = localaiming[viewssnum]; + + // Handle stuff when you are looking farther up or down. + if ((gl_aimingangle || fpov > 90.0f)) + { + dup_viewangle += ANGLE_90; + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //left + + dup_viewangle += ANGLE_90; + if (((INT32)gl_aimingangle > ANGLE_45 || (INT32)gl_aimingangle<-ANGLE_45)) + { + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //back + } + + dup_viewangle += ANGLE_90; + HWR_ClearClipSegs(); + HWR_RenderBSPNode((INT32)numnodes-1); //right + + dup_viewangle += ANGLE_90; + } +#endif + + ps_bsptime = I_GetTimeMicros() - ps_bsptime; + + if (cv_glbatching.value) + HWR_RenderBatches(); + + // Check for new console commands. + NetUpdate(); + +#ifdef ALAM_LIGHTING + //14/11/99: Hurdler: moved here because it doesn't work with + // subsector, see other comments; + HWR_ResetLights(); +#endif + + // Draw MD2 and sprites + ps_numsprites = gl_visspritecount; + ps_hw_spritesorttime = I_GetTimeMicros(); + HWR_SortVisSprites(); + ps_hw_spritesorttime = I_GetTimeMicros() - ps_hw_spritesorttime; + ps_hw_spritedrawtime = I_GetTimeMicros(); + HWR_DrawSprites(); + ps_hw_spritedrawtime = I_GetTimeMicros() - ps_hw_spritedrawtime; + +#ifdef NEWCORONAS + //Hurdler: they must be drawn before translucent planes, what about gl fog? + HWR_DrawCoronas(); +#endif + + ps_numdrawnodes = 0; + ps_hw_nodesorttime = 0; + ps_hw_nodedrawtime = 0; + if (numplanes || numpolyplanes || numwalls) //Hurdler: render 3D water and transparent walls after everything + { + HWR_CreateDrawNodes(); } - R_SetupFrame(player, false); // This can stay false because it is only used to set viewsky in r_main.c, which isn't used here - HWR_RenderFrame(viewnumber, player, false); + HWD.pfnSetTransform(NULL); + HWD.pfnUnSetShader(); + + HWR_DoPostProcessor(player); + + // Check for new console commands. + NetUpdate(); + + // added by Hurdler for correct splitscreen + // moved here by hurdler so it works with the new near clipping plane + HWD.pfnGClipRect(0, 0, vid.width, vid.height, NZCLIP_PLANE); } // ========================================================================== // 3D ENGINE COMMANDS // ========================================================================== -// ************************************************************************** -// 3D ENGINE SETUP -// ************************************************************************** +#ifdef BAD_MODEL_OPTIONS +static CV_PossibleValue_t grmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}}; +#endif +static CV_PossibleValue_t grfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}}; +static CV_PossibleValue_t grshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}}; + +static void CV_glfiltermode_OnChange(void); +static void CV_glanisotropic_OnChange(void); + +static CV_PossibleValue_t glfiltermode_cons_t[]= {{HWD_SET_TEXTUREFILTER_POINTSAMPLED, "Nearest"}, + {HWD_SET_TEXTUREFILTER_BILINEAR, "Bilinear"}, {HWD_SET_TEXTUREFILTER_TRILINEAR, "Trilinear"}, + {HWD_SET_TEXTUREFILTER_MIXED1, "Linear_Nearest"}, + {HWD_SET_TEXTUREFILTER_MIXED2, "Nearest_Linear"}, + {HWD_SET_TEXTUREFILTER_MIXED3, "Nearest_Mipmap"}, + {0, NULL}}; +CV_PossibleValue_t granisotropicmode_cons_t[] = {{1, "MIN"}, {16, "MAX"}, {0, NULL}}; + +consvar_t cv_glshaders = CVAR_INIT ("gr_shaders", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_fovchange = CVAR_INIT ("gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL); + +#ifdef ALAM_LIGHTING +consvar_t cv_gldynamiclighting = CVAR_INIT ("gr_dynamiclighting", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_glstaticlighting = CVAR_INIT ("gr_staticlighting", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_glcoronas = CVAR_INIT ("gr_coronas", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_glcoronasize = CVAR_INIT ("gr_coronasize", "1", CV_SAVE|CV_FLOAT, 0, NULL); +#endif + +consvar_t cv_glmodels = CVAR_INIT ("gr_models", "Off", CV_SAVE, CV_OnOff, NULL); + +#ifdef BAD_MODEL_OPTIONS +consvar_t cv_glmodelinterpolation = CVAR_INIT ("gr_modelinterpolation", "Sometimes", CV_SAVE, grmodelinterpolation_cons_t, NULL); +consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV_OnOff, NULL); +#endif + +consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, grshearing_cons_t, NULL); +consvar_t cv_glspritebillboarding = CVAR_INIT ("gr_spritebillboarding", "Off", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_glskydome = CVAR_INIT ("gr_skydome", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_glfakecontrast = CVAR_INIT ("gr_fakecontrast", "Smooth", CV_SAVE, grfakecontrast_cons_t, NULL); +consvar_t cv_glslopecontrast = CVAR_INIT ("gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NULL); + +consvar_t cv_glfiltermode = CVAR_INIT ("gr_filtermode", "Nearest", CV_SAVE|CV_CALL, glfiltermode_cons_t, CV_glfiltermode_OnChange); +consvar_t cv_glanisotropicmode = CVAR_INIT ("gr_anisotropicmode", "1", CV_CALL, granisotropicmode_cons_t, CV_glanisotropic_OnChange); + +consvar_t cv_glsolvetjoin = CVAR_INIT ("gr_solvetjoin", "On", 0, CV_OnOff, NULL); + +consvar_t cv_glbatching = CVAR_INIT ("gr_batching", "On", 0, CV_OnOff, NULL); + +static void CV_glfiltermode_OnChange(void) +{ + if (rendermode == render_opengl) + HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); +} + +static void CV_glanisotropic_OnChange(void) +{ + if (rendermode == render_opengl) + HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value); +} -// -------------------------------------------------------------------------- -// Add hardware engine commands & consvars -// -------------------------------------------------------------------------- //added by Hurdler: console varibale that are saved void HWR_AddCommands(void) { - CV_RegisterVar(&cv_grrounddown); - CV_RegisterVar(&cv_grfiltermode); - CV_RegisterVar(&cv_granisotropicmode); - CV_RegisterVar(&cv_grcorrecttricks); - CV_RegisterVar(&cv_grsolvetjoin); + CV_RegisterVar(&cv_fovchange); - CV_RegisterVar(&cv_grbatching); +#ifdef ALAM_LIGHTING + CV_RegisterVar(&cv_glstaticlighting); + CV_RegisterVar(&cv_gldynamiclighting); + CV_RegisterVar(&cv_glcoronasize); + CV_RegisterVar(&cv_glcoronas); +#endif + +#ifdef BAD_MODEL_OPTIONS + CV_RegisterVar(&cv_glmodellighting); + CV_RegisterVar(&cv_glmodelinterpolation); +#endif + + CV_RegisterVar(&cv_glmodels); + + CV_RegisterVar(&cv_glskydome); + CV_RegisterVar(&cv_glspritebillboarding); + CV_RegisterVar(&cv_glfakecontrast); + CV_RegisterVar(&cv_glshearing); + CV_RegisterVar(&cv_glshaders); + + CV_RegisterVar(&cv_glfiltermode); + CV_RegisterVar(&cv_glsolvetjoin); + + CV_RegisterVar(&cv_glbatching); + +#ifndef NEWCLIP + CV_RegisterVar(&cv_glclipwalls); +#endif +} + +void HWR_AddSessionCommands(void) +{ + static boolean alreadycalled = false; + if (alreadycalled) + return; + + CV_RegisterVar(&cv_glanisotropicmode); + + alreadycalled = true; } // -------------------------------------------------------------------------- @@ -4721,26 +6232,35 @@ void HWR_Startup(void) if (!startupdone) { CONS_Printf("HWR_Startup()...\n"); + + HWR_InitPolyPool(); + HWR_AddSessionCommands(); HWR_InitTextureCache(); - HWR_InitMD2(); + HWR_InitModels(); +#ifdef ALAM_LIGHTING + HWR_InitLight(); +#endif + + HWR_LoadAllCustomShaders(); + if (!HWR_CompileShaders()) + gl_shadersavailable = false; } if (rendermode == render_opengl) - textureformat = patchformat = -#ifdef _NDS - GR_TEXFMT_P_8; -#else - GR_RGBA; -#endif + textureformat = patchformat = GL_TEXFMT_RGBA; startupdone = true; - - // jimita - HWD.pfnKillShaders(); - if (!HWD.pfnLoadShaders()) - gr_shadersavailable = false; } +// -------------------------------------------------------------------------- +// Called after switching to the hardware renderer +// -------------------------------------------------------------------------- +void HWR_Switch(void) +{ + // Set special states from CVARs + HWD.pfnSetSpecialState(HWD_SET_TEXTUREFILTERMODE, cv_glfiltermode.value); + HWD.pfnSetSpecialState(HWD_SET_TEXTUREANISOTROPICMODE, cv_glanisotropicmode.value); +} // -------------------------------------------------------------------------- // Free resources allocated by the hardware renderer @@ -4749,10 +6269,34 @@ void HWR_Shutdown(void) { CONS_Printf("HWR_Shutdown()\n"); HWR_FreeExtraSubsectors(); + HWR_FreePolyPool(); HWR_FreeTextureCache(); HWD.pfnFlushScreenTextures(); } +void transform(float *cx, float *cy, float *cz) +{ + float tr_x,tr_y; + // translation + tr_x = *cx - gl_viewx; + tr_y = *cz - gl_viewy; +// *cy = *cy; + + // rotation around vertical y axis + *cx = (tr_x * gl_viewsin) - (tr_y * gl_viewcos); + tr_x = (tr_x * gl_viewcos) + (tr_y * gl_viewsin); + + //look up/down ----TOTAL SUCKS!!!--- do the 2 in one!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + tr_y = *cy - gl_viewz; + + *cy = (tr_x * gl_viewludcos) + (tr_y * gl_viewludsin); + *cz = (tr_x * gl_viewludsin) - (tr_y * gl_viewludcos); + + //scale y before frustum so that frustum can be scaled to screen height + *cy *= ORIGINAL_ASPECT * gl_fovlud; + *cx *= gl_fovlud; +} + void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap) { static size_t allocedwalls = 0; @@ -4783,12 +6327,14 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, FBITFIELD blendmode = blend; UINT8 alpha = pSurf->PolyColor.s.alpha; // retain the alpha + int shader; + // Lighting is done here instead so that fog isn't drawn incorrectly on transparent walls after sorting HWR_Lighting(pSurf, lightlevel, wallcolormap); pSurf->PolyColor.s.alpha = alpha; // put the alpha back after lighting - HWD.pfnSetShader(2); // wall shader + shader = SHADER_WALL; // wall shader if (blend & PF_Environment) blendmode |= PF_Occlude; // PF_Occlude must be used for solid objects @@ -4796,27 +6342,32 @@ void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, if (fogwall) { blendmode |= PF_Fog; - HWD.pfnSetShader(6); // fog shader + shader = SHADER_FOG; // fog shader } blendmode |= PF_Modulated; // No PF_Occlude means overlapping (incorrect) transparency - HWD.pfnDrawPolygon(pSurf, wallVerts, 4, blendmode); + HWR_ProcessPolygon(pSurf, wallVerts, 4, blendmode, shader, false); #ifdef WALLSPLATS - if (gr_curline->linedef->splats && cv_splats.value) + if (gl_curline->linedef->splats && cv_splats.value) HWR_DrawSegsSplats(pSurf); #endif } +INT32 HWR_GetTextureUsed(void) +{ + return HWD.pfnGetTextureUsed(); +} + void HWR_DoPostProcessor(player_t *player) { postimg_t *type = &postimgtype[0]; - UINT8 i; + SINT8 i; HWD.pfnUnSetShader(); - for (i = r_splitscreen; i > 0; i--) + for (i = r_splitscreen; i >= 0; i--) { if (player == &players[displayplayers[i]]) { @@ -4847,7 +6398,7 @@ void HWR_DoPostProcessor(player_t *player) Surf.PolyColor.s.alpha = 0xc0; // match software mode - HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Translucent|PF_NoTexture|PF_NoDepthTest); + HWD.pfnDrawPolygon(&Surf, v, 4, PF_Modulated|PF_Additive|PF_NoTexture|PF_NoDepthTest|PF_Clip|PF_NoZClip); } // Capture the screen for intermission and screen waving @@ -4862,7 +6413,7 @@ void HWR_DoPostProcessor(player_t *player) { // 10 by 10 grid. 2 coordinates (xy) float v[SCREENVERTS][SCREENVERTS][2]; - double disStart = leveltime; + static double disStart = 0; UINT8 x, y; INT32 WAVELENGTH; INT32 AMPLITUDE; @@ -4892,6 +6443,8 @@ void HWR_DoPostProcessor(player_t *player) } } HWD.pfnPostImgRedraw(v); + if (!(paused || P_AutoPause())) + disStart += 1; // Capture the screen again for screen waving on the intermission if(gamestate != GS_INTERMISSION) @@ -4902,11 +6455,13 @@ void HWR_DoPostProcessor(player_t *player) void HWR_StartScreenWipe(void) { + //CONS_Debug(DBG_RENDER, "In HWR_StartScreenWipe()\n"); HWD.pfnStartScreenWipe(); } void HWR_EndScreenWipe(void) { + //CONS_Debug(DBG_RENDER, "In HWR_EndScreenWipe()\n"); HWD.pfnEndScreenWipe(); } @@ -4915,34 +6470,57 @@ void HWR_DrawIntermissionBG(void) HWD.pfnDrawIntermissionBG(); } -void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) +// +// hwr mode wipes +// +static lumpnum_t wipelumpnum; + +// puts wipe lumpname in wipename[9] +static boolean HWR_WipeCheck(UINT8 wipenum, UINT8 scrnnum) { static char lumpname[9] = "FADEmmss"; - lumpnum_t lumpnum; size_t lsize; - if (wipenum > 99 || scrnnum > 99) // not a valid wipe number - return; // shouldn't end up here really, the loop should've stopped running beforehand + // not a valid wipe number + if (wipenum > 99 || scrnnum > 99) + return false; // shouldn't end up here really, the loop should've stopped running beforehand - // puts the numbers into the lumpname - sprintf(&lumpname[4], "%.2hu%.2hu", (UINT16)wipenum, (UINT16)scrnnum); - lumpnum = W_CheckNumForName(lumpname); + // puts the numbers into the wipename + lumpname[4] = '0'+(wipenum/10); + lumpname[5] = '0'+(wipenum%10); + lumpname[6] = '0'+(scrnnum/10); + lumpname[7] = '0'+(scrnnum%10); + wipelumpnum = W_CheckNumForName(lumpname); - if (lumpnum == LUMPERROR) // again, shouldn't be here really - return; - - lsize = W_LumpLength(lumpnum); + // again, shouldn't be here really + if (wipelumpnum == LUMPERROR) + return false; + lsize = W_LumpLength(wipelumpnum); if (!(lsize == 256000 || lsize == 64000 || lsize == 16000 || lsize == 4000)) { CONS_Alert(CONS_WARNING, "Fade mask lump %s of incorrect size, ignored\n", lumpname); - return; // again, shouldn't get here if it is a bad size + return false; // again, shouldn't get here if it is a bad size } - HWR_GetFadeMask(lumpnum); + return true; +} + +void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum) +{ + if (!HWR_WipeCheck(wipenum, scrnnum)) + return; + + HWR_GetFadeMask(wipelumpnum); HWD.pfnDoScreenWipe(); } +void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum) +{ + // It does the same thing + HWR_DoWipe(wipenum, scrnnum); +} + void HWR_MakeScreenFinalTexture(void) { HWD.pfnMakeScreenFinalTexture(); @@ -4954,13 +6532,7 @@ void HWR_DrawScreenFinalTexture(int width, int height) } // jimita 18032019 -typedef struct -{ - char type[16]; - INT32 id; -} shaderxlat_t; - -static inline UINT16 HWR_CheckShader(UINT16 wadnum) +static inline UINT16 HWR_FindShaderDefs(UINT16 wadnum) { UINT16 i; lumpinfo_t *lump_p; @@ -4973,7 +6545,34 @@ static inline UINT16 HWR_CheckShader(UINT16 wadnum) return INT16_MAX; } -void HWR_LoadShaders(UINT16 wadnum, boolean PK3) +boolean HWR_CompileShaders(void) +{ + return HWD.pfnCompileShaders(); +} + +customshaderxlat_t shaderxlat[] = +{ + {"Flat", SHADER_FLOOR}, + {"WallTexture", SHADER_WALL}, + {"Sprite", SHADER_SPRITE}, + {"Model", SHADER_MODEL}, + {"ModelLighting", SHADER_MODEL_LIGHTING}, + {"WaterRipple", SHADER_WATER}, + {"Fog", SHADER_FOG}, + {"Sky", SHADER_SKY}, + {NULL, 0}, +}; + +void HWR_LoadAllCustomShaders(void) +{ + INT32 i; + + // read every custom shader + for (i = 0; i < numwadfiles; i++) + HWR_LoadCustomShadersFromFile(i, (wadfiles[i]->type == RET_PK3)); +} + +void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3) { UINT16 lump; char *shaderdef, *line; @@ -4984,19 +6583,7 @@ void HWR_LoadShaders(UINT16 wadnum, boolean PK3) int shadertype = 0; int i; - #define SHADER_TYPES 7 - shaderxlat_t shaderxlat[SHADER_TYPES] = - { - {"Flat", 1}, - {"WallTexture", 2}, - {"Sprite", 3}, - {"Model", 4}, - {"WaterRipple", 5}, - {"Fog", 6}, - {"Sky", 7}, - }; - - lump = HWR_CheckShader(wadnum); + lump = HWR_FindShaderDefs(wadnum); if (lump == INT16_MAX) return; @@ -5004,9 +6591,6 @@ void HWR_LoadShaders(UINT16 wadnum, boolean PK3) size = W_LumpLengthPwad(wadnum, lump); line = Z_Malloc(size+1, PU_STATIC, NULL); - if (!line) - I_Error("HWR_LoadShaders: No more free memory\n"); - M_Memcpy(line, shaderdef, size); line[size] = '\0'; @@ -5025,7 +6609,7 @@ void HWR_LoadShaders(UINT16 wadnum, boolean PK3) value = strtok(NULL, "\r\n "); if (!value) { - CONS_Alert(CONS_WARNING, "HWR_LoadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); stoken = strtok(NULL, "\r\n"); // skip end of line goto skip_lump; } @@ -5044,19 +6628,19 @@ skip_lump: value = strtok(NULL, "\r\n= "); if (!value) { - CONS_Alert(CONS_WARNING, "HWR_LoadShaders: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + CONS_Alert(CONS_WARNING, "HWR_LoadCustomShadersFromFile: Missing shader target (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); stoken = strtok(NULL, "\r\n"); // skip end of line goto skip_field; } if (!shadertype) { - CONS_Alert(CONS_ERROR, "HWR_LoadShaders: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader type (file %s, line %d)\n", wadfiles[wadnum]->filename, linenum); Z_Free(line); return; } - for (i = 0; i < SHADER_TYPES; i++) + for (i = 0; shaderxlat[i].type; i++) { if (!stricmp(shaderxlat[i].type, stoken)) { @@ -5082,7 +6666,7 @@ skip_lump: if (shader_lumpnum == INT16_MAX) { - CONS_Alert(CONS_ERROR, "HWR_LoadShaders: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); + CONS_Alert(CONS_ERROR, "HWR_LoadCustomShadersFromFile: Missing shader source %s (file %s, line %d)\n", shader_lumpname, wadfiles[wadnum]->filename, linenum); Z_Free(shader_lumpname); continue; } @@ -5104,10 +6688,26 @@ skip_field: } } - HWD.pfnInitCustomShaders(); - Z_Free(line); return; } +const char *HWR_GetShaderName(INT32 shader) +{ + INT32 i; + + if (shader) + { + for (i = 0; shaderxlat[i].type; i++) + { + if (shaderxlat[i].id == shader) + return shaderxlat[i].type; + } + + return "Unknown"; + } + + return "Default"; +} + #endif // HWRENDER diff --git a/src/hardware/hw_main.h b/src/hardware/hw_main.h index bc4a74e5f..3efeca45b 100644 --- a/src/hardware/hw_main.h +++ b/src/hardware/hw_main.h @@ -1,28 +1,18 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. // -// 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. -// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hw_main.h /// \brief 3D render mode functions -#define GLENCORE - #ifndef __HWR_MAIN_H__ #define __HWR_MAIN_H__ -#include "hw_glob.h" #include "hw_data.h" #include "hw_defs.h" @@ -30,125 +20,125 @@ #include "../d_player.h" #include "../r_defs.h" -#define GLENCORE - // Startup & Shutdown the hardware mode renderer void HWR_Startup(void); +void HWR_Switch(void); void HWR_Shutdown(void); -extern float gr_viewwidth, gr_viewheight, gr_baseviewwindowx, gr_baseviewwindowy; - -extern float gr_basewindowcenterx, gr_basewindowcentery; - -extern FTransform atransform; - -// hw_draw.c -void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); -void HWR_DrawFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, const UINT8 *colormap); -void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); -void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); -void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, UINT32 color, INT32 options); // Lat: separate flags from color since color needs to be an uint to work right. -void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color); void HWR_drawAMline(const fline_t *fl, INT32 color); void HWR_FadeScreenMenuBack(UINT16 color, UINT8 strength); void HWR_DrawConsoleBack(UINT32 color, INT32 height); +void HWR_DrawTutorialBack(UINT32 color, INT32 boxheight); +void HWR_RenderSkyboxView(player_t *player); +void HWR_RenderPlayerView(void); +void HWR_ClearSkyDome(void); +void HWR_BuildSkyDome(void); void HWR_DrawViewBorder(INT32 clearlines); void HWR_DrawFlatFill(INT32 x, INT32 y, INT32 w, INT32 h, lumpnum_t flatlumpnum); +void HWR_InitTextureMapping(void); +void HWR_SetViewSize(void); +void HWR_DrawPatch(GLPatch_t *gpatch, INT32 x, INT32 y, INT32 option); +void HWR_DrawStretchyFixedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 option, const UINT8 *colormap); +void HWR_DrawCroppedPatch(GLPatch_t *gpatch, fixed_t x, fixed_t y, fixed_t scale, INT32 option, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h); +void HWR_CreatePlanePolygons(INT32 bspnum); +void HWR_CreateStaticLightmaps(INT32 bspnum); +void HWR_LoadTextures(size_t pnumtextures); +void HWR_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color); +void HWR_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT16 actualcolor, UINT8 strength); +void HWR_DrawConsoleFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 color, UINT32 actualcolor); // Lat: separate flags from color since color needs to be an uint to work right. +void HWR_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 color); +void HWR_DrawPic(INT32 x,INT32 y,lumpnum_t lumpnum); UINT8 *HWR_GetScreenshot(void); -boolean HWR_Screenshot(const char *lbmname); +boolean HWR_Screenshot(const char *pathname); -// hw_main.c -void HWR_RenderFrame(INT32 viewnumber, player_t *player, boolean skybox); -void HWR_RenderPlayerView(INT32 viewnumber, player_t *player); -void HWR_LoadShaders(UINT16 wadnum, boolean PK3); -void HWR_SetViewSize(void); void HWR_AddCommands(void); - -// My original intention was to split hw_main.c -// into files like hw_bsp.c, hw_sprites.c... - -// hw_main.c: Lighting and fog -void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); -UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work - +void HWR_AddSessionCommands(void); +void transform(float *cx, float *cy, float *cz); FBITFIELD HWR_TranstableToAlpha(INT32 transtablenum, FSurfaceInfo *pSurf); - -// hw_main.c: Post-rendering +INT32 HWR_GetTextureUsed(void); void HWR_DoPostProcessor(player_t *player); void HWR_StartScreenWipe(void); void HWR_EndScreenWipe(void); void HWR_DrawIntermissionBG(void); void HWR_DoWipe(UINT8 wipenum, UINT8 scrnnum); +void HWR_DoTintedWipe(UINT8 wipenum, UINT8 scrnnum); void HWR_MakeScreenFinalTexture(void); void HWR_DrawScreenFinalTexture(int width, int height); -// hw_main.c: Planes -void HWR_RenderPlane(extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, FBITFIELD PolyFlags, INT32 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap); -void HWR_AddTransparentFloor(lumpnum_t lumpnum, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); +// This stuff is put here so MD2's can use them +void HWR_Lighting(FSurfaceInfo *Surface, INT32 light_level, extracolormap_t *colormap); +UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap); // Let's see if this can work -#ifdef POLYOBJECTS -#ifdef POLYOBJECTS_PLANES -void HWR_RenderPolyObjectPlane(polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, FBITFIELD blendmode, UINT8 lightlevel, lumpnum_t lumpnum, sector_t *FOFsector, UINT8 alpha, extracolormap_t *planecolormap); -void HWR_AddPolyObjectPlanes(void); -void HWR_AddTransparentPolyobjectFloor(lumpnum_t lumpnum, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, extracolormap_t *planecolormap); -#endif -#endif +boolean HWR_CompileShaders(void); -// hw_main.c: Segs -void HWR_ProcessSeg(void); // Sort of like GLWall::Process in GZDoom -void HWR_RenderWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); -void HWR_ProjectWall(FOutVector *wallVerts, FSurfaceInfo *pSurf, FBITFIELD blendmode, INT32 lightlevel, extracolormap_t *wallcolormap); -void HWR_AddTransparentWall(FOutVector *wallVerts, FSurfaceInfo * pSurf, INT32 texnum, FBITFIELD blend, boolean fogwall, INT32 lightlevel, extracolormap_t *wallcolormap); -void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum, FSurfaceInfo* Surf, INT32 cutflag, ffloor_t *pfloor); -void HWR_DrawSkyWall(FOutVector *wallVerts, FSurfaceInfo *Surf); -void HWR_DrawSkyBackground(float fpov); +void HWR_LoadAllCustomShaders(void); +void HWR_LoadCustomShadersFromFile(UINT16 wadnum, boolean PK3); +const char *HWR_GetShaderName(INT32 shader); -#ifdef POLYOBJECTS -void HWR_AddPolyObjectSegs(void); -#endif - -// hw_main.c: BSP -void HWR_RenderBSPNode(INT32 bspnum); -void HWR_Subsector(size_t num); -void HWR_AddLine(seg_t *line); -boolean HWR_CheckBBox(fixed_t *bspcoord); -void HWR_RenderDrawNodes(void); - -// hw_main.c: Sprites -void HWR_AddSprites(sector_t *sec); -void HWR_ProjectSprite(mobj_t *thing); -void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); -void HWR_DrawSprites(void); - -// hw_bsp.c -void HWR_CreatePlanePolygons(INT32 bspnum); - -// hw_cache.c -void HWR_PrepLevelCache(size_t pnumtextures); - -// hw_trick.c -void HWR_CorrectSWTricks(void); - -// Console variables -extern consvar_t cv_grshaders; -extern consvar_t cv_grshearing; -extern consvar_t cv_grfov; -extern consvar_t cv_grmdls; -extern consvar_t cv_grfog; -extern consvar_t cv_grfogdensity; -extern consvar_t cv_grgammared; -extern consvar_t cv_grgammagreen; -extern consvar_t cv_grgammablue; -extern consvar_t cv_grfiltermode; -extern consvar_t cv_granisotropicmode; -extern consvar_t cv_grcorrecttricks; -extern consvar_t cv_grfovchange; -extern consvar_t cv_grsolvetjoin; -extern consvar_t cv_grspritebillboarding; -extern consvar_t cv_grfakecontrast; -extern consvar_t cv_grfallbackplayermodel; +extern customshaderxlat_t shaderxlat[]; extern CV_PossibleValue_t granisotropicmode_cons_t[]; +#ifdef ALAM_LIGHTING +extern consvar_t cv_gldynamiclighting; +extern consvar_t cv_glstaticlighting; +extern consvar_t cv_glcoronas; +extern consvar_t cv_glcoronasize; +#endif + +extern consvar_t cv_glshaders; +extern consvar_t cv_glmodels; + +// SRB2Kart: We don't like these options. +// Interpolation should be up to who animated the model. +// Lighting makes the modeler's intended texturing look funky. +//#define BAD_MODEL_OPTIONS + +#ifdef BAD_MODEL_OPTIONS +extern consvar_t cv_glmodelinterpolation; +extern consvar_t cv_glmodellighting; +#endif + +extern consvar_t cv_glfiltermode; +extern consvar_t cv_glanisotropicmode; +extern consvar_t cv_fovchange; +extern consvar_t cv_glsolvetjoin; +extern consvar_t cv_glshearing; +extern consvar_t cv_glspritebillboarding; +extern consvar_t cv_glskydome; +extern consvar_t cv_glfakecontrast; +extern consvar_t cv_glslopecontrast; + +extern consvar_t cv_glbatching; + +extern float gl_viewwidth, gl_viewheight, gl_baseviewwindowy; + +extern float gl_viewwindowx, gl_basewindowcentery; + +// BP: big hack for a test in lighting ref : 1249753487AB +extern fixed_t *hwbbox; +extern FTransform atransform; + + +// Render stats +extern int ps_hw_skyboxtime; +extern int ps_hw_nodesorttime; +extern int ps_hw_nodedrawtime; +extern int ps_hw_spritesorttime; +extern int ps_hw_spritedrawtime; + +// Render stats for batching +extern int ps_hw_numpolys; +extern int ps_hw_numverts; +extern int ps_hw_numcalls; +extern int ps_hw_numshaders; +extern int ps_hw_numtextures; +extern int ps_hw_numpolyflags; +extern int ps_hw_numcolors; +extern int ps_hw_batchsorttime; +extern int ps_hw_batchdrawtime; + +extern boolean gl_shadersavailable; + #endif diff --git a/src/hardware/hw_md2.c b/src/hardware/hw_md2.c index cb4fab7b3..9896eb458 100644 --- a/src/hardware/hw_md2.c +++ b/src/hardware/hw_md2.c @@ -1,18 +1,16 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief MD2 Handling +/// \file hw_md2.c +/// \brief 3D Model Handling /// Inspired from md2.c by Mete Ciragan (mete@swissquake.ch) - #ifdef __GNUC__ #include #endif @@ -21,8 +19,10 @@ #include #include +#include "../d_main.h" #include "../doomdef.h" #include "../doomstat.h" +#include "../fastcmp.h" #ifdef HWRENDER #include "hw_drv.h" @@ -37,11 +37,15 @@ #include "../r_things.h" #include "../r_draw.h" #include "../p_tick.h" -#include "../k_color.h" // colortranslations + #include "hw_model.h" #include "hw_main.h" #include "../v_video.h" + +// SRB2Kart +#include "../k_color.h" + #ifdef HAVE_PNG #ifndef _MSC_VER @@ -94,8 +98,10 @@ static model_t *md2_readModel(const char *filename) //Filename checking fixed ~Monster Iestyn and Golden if (FIL_FileExists(va("%s"PATHSEP"%s", srb2home, filename))) return LoadModel(va("%s"PATHSEP"%s", srb2home, filename), PU_STATIC); - else if (FIL_FileExists(va("%s"PATHSEP"%s", srb2path, filename))) + + if (FIL_FileExists(va("%s"PATHSEP"%s", srb2path, filename))) return LoadModel(va("%s"PATHSEP"%s", srb2path, filename), PU_STATIC); + return NULL; } @@ -158,13 +164,13 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ #endif volatile png_FILE_p png_FILE; //Filename checking fixed ~Monster Iestyn and Golden - char *pngfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2home, filename); + char *pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pngfilename, ".png"); png_FILE = fopen(pngfilename, "rb"); if (!png_FILE) { - pngfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2path, filename); + pngfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2path, filename); FIL_ForceExtension(pngfilename, ".png"); png_FILE = fopen(pngfilename, "rb"); //CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename); @@ -199,7 +205,7 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ //CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename); png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); fclose(png_FILE); - Z_Free(grpatch->mipmap->grInfo.data); + Z_Free(grpatch->mipmap->data); return 0; } #ifdef USE_FAR_KEYWORD @@ -240,7 +246,7 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ { png_uint_32 i, pitch = png_get_rowbytes(png_ptr, png_info_ptr); - png_bytep PNG_image = Z_Malloc(pitch*height, PU_HWRCACHE, &grpatch->mipmap->grInfo.data); + png_bytep PNG_image = Z_Malloc(pitch*height, PU_HWRMODELTEXTURE, &grpatch->mipmap->data); png_bytepp row_pointers = png_malloc(png_ptr, height * sizeof (png_bytep)); for (i = 0; i < height; i++) row_pointers[i] = PNG_image + i*pitch; @@ -253,7 +259,7 @@ static GLTextureFormat_t PNG_Load(const char *filename, int *w, int *h, GLPatch_ fclose(png_FILE); *w = (int)width; *h = (int)height; - return GR_RGBA; + return GL_TEXFMT_RGBA; } #endif @@ -291,13 +297,13 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h, INT32 ch, rep; FILE *file; //Filename checking fixed ~Monster Iestyn and Golden - char *pcxfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2home, filename); + char *pcxfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2home, filename); FIL_ForceExtension(pcxfilename, ".pcx"); file = fopen(pcxfilename, "rb"); if (!file) { - pcxfilename = va("%s"PATHSEP"mdls"PATHSEP"%s", srb2path, filename); + pcxfilename = va("%s"PATHSEP"models"PATHSEP"%s", srb2path, filename); FIL_ForceExtension(pcxfilename, ".pcx"); file = fopen(pcxfilename, "rb"); if (!file) @@ -320,7 +326,7 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h, pw = *w = header.xmax - header.xmin + 1; ph = *h = header.ymax - header.ymin + 1; - image = Z_Malloc(pw*ph*4, PU_HWRCACHE, &grpatch->mipmap->grInfo.data); + image = Z_Malloc(pw*ph*4, PU_HWRMODELTEXTURE, &grpatch->mipmap->data); if (fread(palette, sizeof (UINT8), PALSIZE, file) != PALSIZE) { @@ -354,11 +360,11 @@ static GLTextureFormat_t PCX_Load(const char *filename, int *w, int *h, } } fclose(file); - return GR_RGBA; + return GL_TEXFMT_RGBA; } // -----------------+ -// md2_loadTexture : Download a pcx or png texture for MD2 models +// md2_loadTexture : Download a pcx or png texture for models // -----------------+ static void md2_loadTexture(md2_t *model) { @@ -368,7 +374,7 @@ static void md2_loadTexture(md2_t *model) if (model->grpatch) { grpatch = model->grpatch; - Z_Free(grpatch->mipmap->grInfo.data); + Z_Free(grpatch->mipmap->data); } else { @@ -377,17 +383,20 @@ static void md2_loadTexture(md2_t *model) grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL); } - if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data) + if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) { int w = 0, h = 0; + UINT32 size; + RGBA_t *image; + #ifdef HAVE_PNG - grpatch->mipmap->grInfo.format = PNG_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap->grInfo.format == 0) + grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch); + if (grpatch->mipmap->format == 0) #endif - grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap->grInfo.format == 0) + grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch); + if (grpatch->mipmap->format == 0) { - grpatch->notfound = true;// mark it so its not searched for again repeatedly + model->notexturefile = true; // mark it so its not searched for again repeatedly return; } @@ -399,13 +408,17 @@ static void md2_loadTexture(md2_t *model) grpatch->mipmap->width = (UINT16)w; grpatch->mipmap->height = (UINT16)h; - // not correct! - grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; + // Lactozilla: Apply colour cube + image = grpatch->mipmap->data; + size = w*h; + while (size--) + { + V_CubeApply(&image->s.red, &image->s.green, &image->s.blue); + image++; + } } + HWD.pfnSetTexture(grpatch->mipmap); - HWR_UnlockCachedPatch(grpatch); } // -----------------+ @@ -422,7 +435,7 @@ static void md2_loadBlendTexture(md2_t *model) if (model->blendgrpatch) { grpatch = model->blendgrpatch; - Z_Free(grpatch->mipmap->grInfo.data); + Z_Free(grpatch->mipmap->data); } else { @@ -431,17 +444,17 @@ static void md2_loadBlendTexture(md2_t *model) grpatch->mipmap = Z_Calloc(sizeof (GLMipmap_t), PU_HWRPATCHINFO, NULL); } - if (!grpatch->mipmap->downloaded && !grpatch->mipmap->grInfo.data) + if (!grpatch->mipmap->downloaded && !grpatch->mipmap->data) { int w = 0, h = 0; #ifdef HAVE_PNG - grpatch->mipmap->grInfo.format = PNG_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap->grInfo.format == 0) + grpatch->mipmap->format = PNG_Load(filename, &w, &h, grpatch); + if (grpatch->mipmap->format == 0) #endif - grpatch->mipmap->grInfo.format = PCX_Load(filename, &w, &h, grpatch); - if (grpatch->mipmap->grInfo.format == 0) + grpatch->mipmap->format = PCX_Load(filename, &w, &h, grpatch); + if (grpatch->mipmap->format == 0) { - grpatch->notfound = true;// mark it so its not searched for again repeatedly + model->noblendfile = true; // mark it so its not searched for again repeatedly Z_Free(filename); return; } @@ -453,14 +466,9 @@ static void md2_loadBlendTexture(md2_t *model) grpatch->height = (INT16)h; grpatch->mipmap->width = (UINT16)w; grpatch->mipmap->height = (UINT16)h; - - // not correct! - grpatch->mipmap->grInfo.smallLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.largeLodLog2 = GR_LOD_LOG2_256; - grpatch->mipmap->grInfo.aspectRatioLog2 = GR_ASPECT_LOG2_1x1; } + HWD.pfnSetTexture(grpatch->mipmap); // We do need to do this so that it can be cleared and knows to recreate it when necessary - HWR_UnlockCachedPatch(grpatch); Z_Free(filename); } @@ -468,20 +476,23 @@ static void md2_loadBlendTexture(md2_t *model) // Don't spam the console, or the OS with fopen requests! static boolean nomd2s = false; -void HWR_InitMD2(void) +void HWR_InitModels(void) { size_t i; INT32 s; FILE *f; - char name[18], filename[32]; + char name[24], filename[32]; float scale, offset; + size_t prefixlen; - CONS_Printf("InitMD2()...\n"); + CONS_Printf("HWR_InitModels()...\n"); for (s = 0; s < MAXSKINS; s++) { md2_playermodels[s].scale = -1.0f; md2_playermodels[s].model = NULL; md2_playermodels[s].grpatch = NULL; + md2_playermodels[s].notexturefile = false; + md2_playermodels[s].noblendfile = false; md2_playermodels[s].skin = -1; md2_playermodels[s].notfound = true; md2_playermodels[s].error = false; @@ -491,125 +502,147 @@ void HWR_InitMD2(void) md2_models[i].scale = -1.0f; md2_models[i].model = NULL; md2_models[i].grpatch = NULL; + md2_models[i].notexturefile = false; + md2_models[i].noblendfile = false; md2_models[i].skin = -1; md2_models[i].notfound = true; md2_models[i].error = false; } - // read the mdls.dat file + // read the models.dat file //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); if (!f) { - f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt"); if (!f) { - CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno)); + CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); nomd2s = true; return; } } - while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) + + // length of the player model prefix + prefixlen = strlen(PLAYERMODELPREFIX); + + while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4) { - /*if (stricmp(name, "PLAY") == 0) - { - CONS_Printf("MD2 for sprite PLAY detected in mdls.dat, use a player skin instead!\n"); - continue; - }*/ - // 8/1/19: Allow PLAY to load for default MD2. + char *skinname = name; + size_t len = strlen(name); - for (i = 0; i < NUMSPRITES; i++) + // check for the player model prefix. + if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen)) { - if (stricmp(name, sprnames[i]) == 0) + skinname += prefixlen; + goto addskinmodel; + } + + // add sprite model + if (len == 4) // must be 4 characters long exactly. otherwise it's not a sprite name. + { + for (i = 0; i < NUMSPRITES; i++) { - //if (stricmp(name, "PLAY") == 0) - //continue; - - //CONS_Debug(DBG_RENDER, " Found: %s %s %f %f\n", name, filename, scale, offset); - md2_models[i].scale = scale; - md2_models[i].offset = offset; - md2_models[i].notfound = false; - strcpy(md2_models[i].filename, filename); - goto md2found; + if (stricmp(name, sprnames[i]) == 0) + { + md2_models[i].scale = scale; + md2_models[i].offset = offset; + md2_models[i].notfound = false; + strcpy(md2_models[i].filename, filename); + goto modelfound; + } } } +addskinmodel: + // add player model for (s = 0; s < MAXSKINS; s++) { - if (stricmp(name, skins[s].name) == 0) + if (stricmp(skinname, skins[s].name) == 0) { - //CONS_Printf(" Found: %s %s %f %f\n", name, filename, scale, offset); md2_playermodels[s].skin = s; md2_playermodels[s].scale = scale; md2_playermodels[s].offset = offset; md2_playermodels[s].notfound = false; strcpy(md2_playermodels[s].filename, filename); - goto md2found; + goto modelfound; } } + // no sprite/player skin name found?!?D - CONS_Printf("Unknown sprite/player skin %s detected in mdls.dat\n", name); -md2found: + CONS_Printf("Unknown sprite/player skin %s detected in models.dat\n", name); + +modelfound: // move on to next line... continue; } fclose(f); } -void HWR_AddPlayerMD2(int skin) // For MD2's that were added after startup +void HWR_AddPlayerModel(int skin) // For skins that were added after startup { FILE *f; - char name[18], filename[32]; + char name[24], filename[32]; float scale, offset; + size_t prefixlen; if (nomd2s) return; - CONS_Printf("AddPlayerMD2()...\n"); + //CONS_Printf("HWR_AddPlayerModel()...\n"); - // read the mdls.dat file + // read the models.dat file //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); if (!f) { - f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt"); if (!f) { - CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno)); + CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); nomd2s = true; return; } } - // Check for any MD2s that match the names of sprite names! - while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) + // length of the player model prefix + prefixlen = strlen(PLAYERMODELPREFIX); + + // Check for any models that match the names of player skins! + while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4) { - if (stricmp(name, skins[skin].name) == 0) + char *skinname = name; + size_t len = strlen(name); + + // ignore the player model prefix. + if (!strnicmp(name, PLAYERMODELPREFIX, prefixlen) && (len > prefixlen)) + skinname += prefixlen; + + if (stricmp(skinname, skins[skin].name) == 0) { md2_playermodels[skin].skin = skin; md2_playermodels[skin].scale = scale; md2_playermodels[skin].offset = offset; md2_playermodels[skin].notfound = false; strcpy(md2_playermodels[skin].filename, filename); - goto playermd2found; + goto playermodelfound; } } - //CONS_Printf("MD2 for player skin %s not found\n", skins[skin].name); md2_playermodels[skin].notfound = true; -playermd2found: +playermodelfound: fclose(f); } - -void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startup +void HWR_AddSpriteModel(size_t spritenum) // For sprites that were added after startup { FILE *f; - // name[18] is used to check for names in the mdls.dat file that match with sprites or player skins + // name[24] is used to check for names in the models.dat file that match with sprites or player skins // sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long - char name[18], filename[32]; + // PLAYERMODELPREFIX is 6 characters long + char name[24], filename[32]; float scale, offset; if (nomd2s) @@ -618,41 +651,49 @@ void HWR_AddSpriteMD2(size_t spritenum) // For MD2s that were added after startu if (spritenum == SPR_PLAY) // Handled already NEWMD2: Per sprite, per-skin check return; - // Read the md2.dat file + // Read the models.dat file //Filename checking fixed ~Monster Iestyn and Golden - f = fopen(va("%s"PATHSEP"%s", srb2home, "mdls.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2home, "models.dat"), "rt"); if (!f) { - f = fopen(va("%s"PATHSEP"%s", srb2path, "mdls.dat"), "rt"); + f = fopen(va("%s"PATHSEP"%s", srb2path, "models.dat"), "rt"); if (!f) { - CONS_Printf("%s %s\n", M_GetText("Error while loading mdls.dat:"), strerror(errno)); + CONS_Printf("%s %s\n", M_GetText("Error while loading models.dat:"), strerror(errno)); nomd2s = true; return; } } - // Check for any MD2s that match the names of sprite names! - while (fscanf(f, "%19s %31s %f %f", name, filename, &scale, &offset) == 4) + // Check for any models that match the names of sprite names! + while (fscanf(f, "%25s %31s %f %f", name, filename, &scale, &offset) == 4) { + // length of the sprite name + size_t len = strlen(name); + if (len != 4) // must be 4 characters long exactly. otherwise it's not a sprite name. + continue; + + // check for the player model prefix. + if (!strnicmp(name, PLAYERMODELPREFIX, strlen(PLAYERMODELPREFIX))) + continue; // that's not a sprite... + if (stricmp(name, sprnames[spritenum]) == 0) { md2_models[spritenum].scale = scale; md2_models[spritenum].offset = offset; md2_models[spritenum].notfound = false; strcpy(md2_models[spritenum].filename, filename); - goto spritemd2found; + goto spritemodelfound; } } - //CONS_Printf("MD2 for sprite %s not found\n", sprnames[spritenum]); md2_models[spritenum].notfound = true; -spritemd2found: +spritemodelfound: fclose(f); } -static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolors_t color) +static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, GLMipmap_t *grmip, INT32 skinnum, skincolornum_t color) { UINT16 w = gpatch->width, h = gpatch->height; UINT32 size = w*h; @@ -676,36 +717,36 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, // no wrap around, no chroma key grmip->flags = 0; // setup the texture info - grmip->grInfo.format = GR_RGBA; + grmip->format = GL_TEXFMT_RGBA; } - if (grmip->grInfo.data) + if (grmip->data) { - Z_Free(grmip->grInfo.data); - grmip->grInfo.data = NULL; + Z_Free(grmip->data); + grmip->data = NULL; } - cur = Z_Malloc(size*4, PU_HWRCACHE, &grmip->grInfo.data); + cur = Z_Malloc(size*4, PU_HWRMODELTEXTURE, &grmip->data); memset(cur, 0x00, size*4); - image = gpatch->mipmap->grInfo.data; - blendimage = blendgpatch->mipmap->grInfo.data; + image = gpatch->mipmap->data; + blendimage = blendgpatch->mipmap->data; // TC_METALSONIC includes an actual skincolor translation, on top of its flashing. if (skinnum == TC_METALSONIC) - color = SKINCOLOR_BLUEBERRY; + color = SKINCOLOR_MIDNIGHT; - if (color != SKINCOLOR_NONE) + if (color != SKINCOLOR_NONE && color < numskincolors) { UINT8 numdupes = 1; UINT8 prevdupes = numdupes; - translation[translen] = colortranslations[color][0]; + translation[translen] = skincolors[color].ramp[0]; cutoff[translen] = 255; for (i = 1; i < 16; i++) { - if (translation[translen] == colortranslations[color][i]) + if (translation[translen] == skincolors[color].ramp[i]) { numdupes++; continue; @@ -725,7 +766,7 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, numdupes = 1; translen++; - translation[translen] = (UINT8)colortranslations[color][i]; + translation[translen] = (UINT8)skincolors[color].ramp[i]; } translen++; @@ -790,9 +831,6 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, } else { - // All settings that use skincolors! - UINT16 brightness; - // Everything below requires a blend image if (blendimage == NULL) { @@ -800,200 +838,240 @@ static void HWR_CreateBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, goto skippixel; } - if (translen <= 0) - { - cur->rgba = image->rgba; - goto skippixel; - } - - // Don't bother with blending the pixel if the alpha of the blend pixel is 0 - if (skinnum == TC_RAINBOW) + // Metal Sonic dash mode + if (skinnum == TC_DASHMODE) { if (image->s.alpha == 0 && blendimage->s.alpha == 0) + { + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 + cur->rgba = image->rgba; + } + else + { + UINT8 ialpha = 255 - blendimage->s.alpha, balpha = blendimage->s.alpha; + RGBA_t icolor = *image, bcolor; + + memset(&bcolor, 0x00, sizeof(RGBA_t)); + + if (blendimage->s.alpha) + { + bcolor.s.blue = 0; + bcolor.s.red = 255; + bcolor.s.green = (blendimage->s.red + blendimage->s.green + blendimage->s.blue) / 3; + } + + if (image->s.alpha && image->s.red > image->s.green << 1) // this is pretty arbitrary, but it works well for Metal Sonic + { + icolor.s.red = image->s.blue; + icolor.s.blue = image->s.red; + } + + cur->s.red = (ialpha * icolor.s.red + balpha * bcolor.s.red)/255; + cur->s.green = (ialpha * icolor.s.green + balpha * bcolor.s.green)/255; + cur->s.blue = (ialpha * icolor.s.blue + balpha * bcolor.s.blue)/255; + cur->s.alpha = image->s.alpha; + } + } + else + { + // All settings that use skincolors! + UINT16 brightness; + + if (translen <= 0) { cur->rgba = image->rgba; goto skippixel; } - else - { - UINT16 imagebright, blendbright; - imagebright = K_ColorRelativeLuminance(image->s.red, image->s.green, image->s.blue); - blendbright = K_ColorRelativeLuminance(blendimage->s.red, blendimage->s.green, blendimage->s.blue); - - // slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway - brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; - } - } - else - { - if (blendimage->s.alpha == 0) - { - cur->rgba = image->rgba; - goto skippixel; // for metal sonic blend - } - else - { - brightness = K_ColorRelativeLuminance(blendimage->s.red, blendimage->s.green, blendimage->s.blue); - } - } - - // Calculate a sort of "gradient" for the skincolor - // (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...) - { - RGBA_t nextcolor; - UINT8 firsti, secondi, mul, mulmax; - INT32 r, g, b; - - // Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors. - // Ensue horrible mess. + // Don't bother with blending the pixel if the alpha of the blend pixel is 0 if (skinnum == TC_RAINBOW) { - //UINT16 brightdif = 256; - INT32 /*compare,*/ m, d; - - // Ignore pure white & pitch black - if (brightness > 253 || brightness < 2) + if (image->s.alpha == 0 && blendimage->s.alpha == 0) { cur->rgba = image->rgba; - cur++; image++; blendimage++; - continue; + goto skippixel; } - - firsti = 0; - mul = 0; - mulmax = 1; - - /*for (i = 0; i < translen; i++) - { - if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is) - continue; - - compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness)); - - if (compare < brightdif) - { - brightdif = (UINT16)compare; - firsti = i; // best matching color that's equal brightness or darker - } - }*/ - firsti = color_match_lookup[brightness]; - - secondi = firsti+1; // next color in line - - m = (INT16)brightness - (INT16)colorbrightnesses[secondi]; - d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi]; - - if (m >= d) - m = d-1; - - mulmax = 16; - - // calculate the "gradient" multiplier based on how close this color is to the one next in line - if (m <= 0 || d <= 0) - mul = 0; else - mul = (mulmax-1) - ((m * mulmax) / d); + { + UINT16 imagebright, blendbright; + + imagebright = K_ColorRelativeLuminance(image->s.red, image->s.green, image->s.blue); + blendbright = K_ColorRelativeLuminance(blendimage->s.red, blendimage->s.green, blendimage->s.blue); + + // slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway + brightness = (imagebright*(255-blendimage->s.alpha))/255 + (blendbright*blendimage->s.alpha)/255; + } } else { - // Just convert brightness to a skincolor value, use distance to next position to find the gradient multipler - firsti = 0; - - for (i = 1; i < translen; i++) + if (blendimage->s.alpha == 0) { - if (brightness >= cutoff[i]) - break; - firsti = i; + cur->rgba = image->rgba; + goto skippixel; // for metal sonic blend + } + else + { + brightness = K_ColorRelativeLuminance(blendimage->s.red, blendimage->s.green, blendimage->s.blue); + } + } + + // Calculate a sort of "gradient" for the skincolor + // (Me splitting this into a function didn't work, so I had to ruin this entire function's groove...) + { + RGBA_t nextcolor; + UINT8 firsti, secondi, mul, mulmax; + INT32 r, g, b; + + // Rainbow needs to find the closest match to the textures themselves, instead of matching brightnesses to other colors. + // Ensue horrible mess. + if (skinnum == TC_RAINBOW) + { + //UINT16 brightdif = 256; + INT32 /*compare,*/ m, d; + + // Ignore pure white & pitch black + if (brightness > 253 || brightness < 2) + { + cur->rgba = image->rgba; + cur++; image++; blendimage++; + continue; + } + + firsti = 0; + mul = 0; + mulmax = 1; + + /*for (i = 0; i < translen; i++) + { + if (brightness > colorbrightnesses[i]) // don't allow greater matches (because calculating a makeshift gradient for this is already a huge mess as is) + continue; + + compare = abs((INT16)(colorbrightnesses[i]) - (INT16)(brightness)); + + if (compare < brightdif) + { + brightdif = (UINT16)compare; + firsti = i; // best matching color that's equal brightness or darker + } + }*/ + firsti = color_match_lookup[brightness]; + + secondi = firsti+1; // next color in line + + m = (INT16)brightness - (INT16)colorbrightnesses[secondi]; + d = (INT16)colorbrightnesses[firsti] - (INT16)colorbrightnesses[secondi]; + + if (m >= d) + m = d-1; + + mulmax = 16; + + // calculate the "gradient" multiplier based on how close this color is to the one next in line + if (m <= 0 || d <= 0) + mul = 0; + else + mul = (mulmax-1) - ((m * mulmax) / d); + } + else + { + // Just convert brightness to a skincolor value, use distance to next position to find the gradient multipler + firsti = 0; + + for (i = 1; i < translen; i++) + { + if (brightness >= cutoff[i]) + break; + firsti = i; + } + + secondi = firsti+1; + + mulmax = cutoff[firsti] - cutoff[secondi]; + mul = cutoff[firsti] - brightness; } - secondi = firsti+1; + blendcolor = V_GetColor(translation[firsti]); - mulmax = cutoff[firsti] - cutoff[secondi]; - mul = cutoff[firsti] - brightness; + if (mul > 0) // If it's 0, then we only need the first color. + { + nextcolor = V_GetColor(translation[secondi]); + + // Find difference between points + r = (INT32)(nextcolor.s.red - blendcolor.s.red); + g = (INT32)(nextcolor.s.green - blendcolor.s.green); + b = (INT32)(nextcolor.s.blue - blendcolor.s.blue); + + // Find the gradient of the two points + r = ((mul * r) / mulmax); + g = ((mul * g) / mulmax); + b = ((mul * b) / mulmax); + + // Add gradient value to color + blendcolor.s.red += r; + blendcolor.s.green += g; + blendcolor.s.blue += b; + } } - blendcolor = V_GetColor(translation[firsti]); - - if (mul > 0) // If it's 0, then we only need the first color. + if (skinnum == TC_RAINBOW) { - nextcolor = V_GetColor(translation[secondi]); + UINT32 tempcolor; + UINT16 colorbright; - // Find difference between points - r = (INT32)(nextcolor.s.red - blendcolor.s.red); - g = (INT32)(nextcolor.s.green - blendcolor.s.green); - b = (INT32)(nextcolor.s.blue - blendcolor.s.blue); + colorbright = K_ColorRelativeLuminance(blendcolor.s.red, blendcolor.s.green, blendcolor.s.blue); - // Find the gradient of the two points - r = ((mul * r) / mulmax); - g = ((mul * g) / mulmax); - b = ((mul * b) / mulmax); + if (colorbright == 0) + { + colorbright = 1; // no dividing by 0 please + } - // Add gradient value to color - blendcolor.s.red += r; - blendcolor.s.green += g; - blendcolor.s.blue += b; + tempcolor = (brightness * blendcolor.s.red) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.red = (UINT8)tempcolor; + + tempcolor = (brightness * blendcolor.s.green) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.green = (UINT8)tempcolor; + + tempcolor = (brightness * blendcolor.s.blue) / colorbright; + tempcolor = min(255, tempcolor); + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; } - } - - if (skinnum == TC_RAINBOW) - { - UINT32 tempcolor; - UINT16 colorbright; - - colorbright = K_ColorRelativeLuminance(blendcolor.s.red, blendcolor.s.green, blendcolor.s.blue); - - if (colorbright == 0) + else { - colorbright = 1; // no dividing by 0 please + // Color strength depends on image alpha + INT32 tempcolor; + + tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.red = (UINT8)tempcolor; + + tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.green = (UINT8)tempcolor; + + tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255); + tempcolor = min(255, tempcolor); + cur->s.blue = (UINT8)tempcolor; + cur->s.alpha = image->s.alpha; } - tempcolor = (brightness * blendcolor.s.red) / colorbright; - tempcolor = min(255, tempcolor); - cur->s.red = (UINT8)tempcolor; - - tempcolor = (brightness * blendcolor.s.green) / colorbright; - tempcolor = min(255, tempcolor); - cur->s.green = (UINT8)tempcolor; - - tempcolor = (brightness * blendcolor.s.blue) / colorbright; - tempcolor = min(255, tempcolor); - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; - } - else - { - // Color strength depends on image alpha - INT32 tempcolor; - - tempcolor = ((image->s.red * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.red * blendimage->s.alpha) / 255); - tempcolor = min(255, tempcolor); - cur->s.red = (UINT8)tempcolor; - - tempcolor = ((image->s.green * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.green * blendimage->s.alpha) / 255); - tempcolor = min(255, tempcolor); - cur->s.green = (UINT8)tempcolor; - - tempcolor = ((image->s.blue * (255-blendimage->s.alpha)) / 255) + ((blendcolor.s.blue * blendimage->s.alpha) / 255); - tempcolor = min(255, tempcolor); - cur->s.blue = (UINT8)tempcolor; - cur->s.alpha = image->s.alpha; - } - skippixel: - // *Now* we can do Metal Sonic's flashing - if (skinnum == TC_METALSONIC) - { - // Blend dark blue into white - if (cur->s.alpha > 0 && cur->s.red == 0 && cur->s.green == 0 && cur->s.blue < 255 && cur->s.blue > 31) + // *Now* we can do Metal Sonic's flashing + if (skinnum == TC_METALSONIC) { - // Sal: Invert non-blue - cur->s.red = cur->s.green = (255 - cur->s.blue); - cur->s.blue = 255; - } + // Blend dark blue into white + if (cur->s.alpha > 0 && cur->s.red == 0 && cur->s.green == 0 && cur->s.blue < 255 && cur->s.blue > 31) + { + // Sal: Invert non-blue + cur->s.red = cur->s.green = (255 - cur->s.blue); + cur->s.blue = 255; + } - cur->s.alpha = image->s.alpha; + cur->s.alpha = image->s.alpha; + } } } @@ -1006,7 +1084,7 @@ skippixel: return; } -static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolors_t color) +static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT32 skinnum, const UINT8 *colormap, skincolornum_t color) { // mostly copied from HWR_GetMappedPatch, hence the similarities and comment GLMipmap_t *grmip, *newmip; @@ -1018,17 +1096,25 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT return; } - // search for the mimmap + if ((blendgpatch && blendgpatch->mipmap->format) + && (gpatch->width != blendgpatch->width || gpatch->height != blendgpatch->height)) + { + // Blend image exists, but it's bad. + HWD.pfnSetTexture(gpatch->mipmap); + return; + } + + // search for the mipmap // skip the first (no colormap translated) for (grmip = gpatch->mipmap; grmip->nextcolormap; ) { grmip = grmip->nextcolormap; if (grmip->colormap == colormap) { - if (grmip->downloaded && grmip->grInfo.data) + if (grmip->downloaded && grmip->data) { HWD.pfnSetTexture(grmip); // found the colormap, set it to the correct texture - Z_ChangeTag(grmip->grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(grmip->data, PU_HWRMODELTEXTURE_UNLOCKED); return; } } @@ -1043,47 +1129,170 @@ static void HWR_GetBlendedTexture(GLPatch_t *gpatch, GLPatch_t *blendgpatch, INT // (...) unfortunately z_malloc fragment alot the memory :(so malloc is better newmip = calloc(1, sizeof (*newmip)); if (newmip == NULL) - I_Error("%s: Out of memory", "HWR_GetMappedPatch"); + I_Error("%s: Out of memory", "HWR_GetBlendedTexture"); grmip->nextcolormap = newmip; newmip->colormap = colormap; HWR_CreateBlendedTexture(gpatch, blendgpatch, newmip, skinnum, color); HWD.pfnSetTexture(newmip); - Z_ChangeTag(newmip->grInfo.data, PU_HWRCACHE_UNLOCKED); + Z_ChangeTag(newmip->data, PU_HWRMODELTEXTURE_UNLOCKED); } +static boolean HWR_AllowModel(mobj_t *mobj) +{ + // Signpost overlay. Not needed. + if (mobj->state-states == S_KART_SIGN) + return false; -// -----------------+ -// HWR_DrawMD2 : Draw MD2 -// : -// Returns : -// -----------------+ + // Otherwise, render the model. + return true; +} -void HWR_DrawMD2(gr_vissprite_t *spr) +static boolean HWR_CanInterpolateModel(mobj_t *mobj, model_t *model) +{ + // SRB2Kart: Interpoleration should ALWAYS be up to the modeler. +#ifdef BAD_MODEL_OPTIONS + if (cv_glmodelinterpolation.value == 2) // Always interpolate + return true; +#endif + return model->interpolate[(mobj->frame & FF_FRAMEMASK)]; +} + +static boolean HWR_CanInterpolateSprite2(modelspr2frames_t *spr2frame) +{ +#ifdef BAD_MODEL_OPTIONS + if (cv_glmodelinterpolation.value == 2) // Always interpolate + return true; +#endif + return spr2frame->interpolate; +} + +// +// HWR_GetModelSprite2 (see P_GetSkinSprite2) +// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. +// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. +// + +static UINT8 HWR_GetModelSprite2(md2_t *md2, skin_t *skin, UINT8 spr2, player_t *player) +{ + UINT8 super = 0, i = 0; + + (void)player; + + if (!md2 || !md2->model || !md2->model->spr2frames || !skin) + return 0; + + if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) + return 0; + + while (!md2->model->spr2frames[spr2].numframes + && spr2 != SPR2_STIL + && ++i != 32) // recursion limiter + { + if (spr2 & FF_SPR2SUPER) + { + super = FF_SPR2SUPER; + spr2 &= ~FF_SPR2SUPER; + continue; + } + + switch(spr2) + { + // Normal special cases. + // (none in kart) + + // Use the handy list, that's what it's there for! + default: + spr2 = spr2defaults[spr2]; + break; + } + + spr2 |= super; + } + + if (i >= 32) // probably an infinite loop... + return 0; + + return spr2; +} + +// Adjust texture coords of model to fit into a patch's max_s and max_t +static void adjustTextureCoords(model_t *model, GLPatch_t *gpatch) +{ + int i; + for (i = 0; i < model->numMeshes; i++) + { + int j; + mesh_t *mesh = &model->meshes[i]; + int numVertices; + float *uvReadPtr = mesh->originaluvs; + float *uvWritePtr; + + // i dont know if this is actually possible, just logical conclusion of structure in CreateModelVBOs + if (!mesh->frames && !mesh->tinyframes) continue; + + if (mesh->frames) // again CreateModelVBO and CreateModelVBOTiny iterate like this so I'm gonna do that too + numVertices = mesh->numTriangles * 3; + else + numVertices = mesh->numVertices; + + // if originaluvs points to uvs, we need to allocate new memory for adjusted uvs + // the old uvs are kept around for use in possible readjustments + if (mesh->uvs == mesh->originaluvs) + mesh->uvs = Z_Malloc(numVertices * 2 * sizeof(float), PU_STATIC, NULL); + + uvWritePtr = mesh->uvs; + + // fix uvs (texture coordinates) to take into account that the actual texture + // has empty space added until the next power of two + for (j = 0; j < numVertices; j++) + { + *uvWritePtr++ = *uvReadPtr++ * gpatch->max_s; + *uvWritePtr++ = *uvReadPtr++ * gpatch->max_t; + } + } + // Save the values we adjusted the uvs for + model->max_s = gpatch->max_s; + model->max_t = gpatch->max_t; +} + +// +// HWR_DrawModel +// + +boolean HWR_DrawModel(gl_vissprite_t *spr) { md2_t *md2; char filename[64]; INT32 frame = 0; INT32 nextFrame = -1; + UINT8 spr2 = 0; FTransform p; FSurfaceInfo Surf; - if (!cv_grmdls.value) - return; + if (!cv_glmodels.value) + return false; if (spr->precip) - return; + return false; + + // Lactozilla: Disallow certain models from rendering + if (!HWR_AllowModel(spr->mobj)) + return false; + + memset(&p, 0x00, sizeof(FTransform)); // MD2 colormap fix // colormap test if (spr->mobj->subsector) { sector_t *sector = spr->mobj->subsector->sector; - extracolormap_t *colormap = sector->extra_colormap; UINT8 lightlevel = 255; + extracolormap_t *colormap = NULL; UINT8 brightmode = 0; + if (spr->mobj->drawflags & MFD_BRIGHTMASK) { @@ -1109,8 +1318,8 @@ void HWR_DrawMD2(gr_vissprite_t *spr) if (brightmode != 1) lightlevel = *sector->lightlist[light].lightlevel; - if (sector->lightlist[light].extra_colormap) - colormap = sector->lightlist[light].extra_colormap; + if (*sector->lightlist[light].extra_colormap) + colormap = *sector->lightlist[light].extra_colormap; } else { @@ -1127,9 +1336,7 @@ void HWR_DrawMD2(gr_vissprite_t *spr) HWR_Lighting(&Surf, lightlevel, colormap); } else - { Surf.PolyColor.rgba = 0xFFFFFFFF; - } // Look at HWR_ProjectSprite for more { @@ -1141,9 +1348,14 @@ void HWR_DrawMD2(gr_vissprite_t *spr) INT32 durs = spr->mobj->state->tics; INT32 tics = spr->mobj->tics; //mdlframe_t *next = NULL; - const UINT8 flip = (UINT8)((spr->mobj->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP); + const boolean papersprite = (spr->mobj->frame & FF_PAPERSPRITE); + const UINT8 flip = (UINT8)(!(spr->mobj->eflags & MFE_VERTICALFLIP) != !(spr->mobj->frame & FF_VERTICALFLIP)); + const UINT8 hflip = (UINT8)(!(spr->mobj->mirrored) != !(spr->mobj->frame & FF_HORIZONTALFLIP)); spritedef_t *sprdef; spriteframe_t *sprframe; + spriteinfo_t *sprinfo; + angle_t ang; + INT32 mod; float finalscale; // Apparently people don't like jump frames like that, so back it goes @@ -1166,84 +1378,97 @@ void HWR_DrawMD2(gr_vissprite_t *spr) { md2 = &md2_playermodels[(skin_t*)spr->mobj->skin-skins]; md2->skin = (skin_t*)spr->mobj->skin-skins; + sprinfo = &((skin_t *)spr->mobj->skin)->sprinfo[spr->mobj->sprite2]; } - else // if we can't find the player md2, use SPR_PLAY's MD2. + else + { md2 = &md2_models[spr->mobj->sprite]; + sprinfo = &spriteinfo[spr->mobj->sprite]; + } + + // texture loading before model init, so it knows if sprite graphics are used, which + // means that texture coordinates have to be adjusted + gpatch = md2->grpatch; + if (!gpatch || ((!gpatch->mipmap->format || !gpatch->mipmap->downloaded) && !md2->notexturefile)) + md2_loadTexture(md2); + gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture... + + if ((gpatch && gpatch->mipmap->format) // don't load the blend texture if the base texture isn't available + && (!md2->blendgrpatch + || ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded) + && !md2->noblendfile))) + md2_loadBlendTexture(md2); if (md2->error) - return; // we already failed loading this before :( + return false; // we already failed loading this before :( if (!md2->model) { - CONS_Debug(DBG_RENDER, "Loading model... (%s, %s)", sprnames[spr->mobj->sprite], md2->filename); - sprintf(filename, "mdls/%s", md2->filename); + //CONS_Debug(DBG_RENDER, "Loading model... (%s)", sprnames[spr->mobj->sprite]); + sprintf(filename, "models/%s", md2->filename); md2->model = md2_readModel(filename); if (md2->model) { md2_printModelInfo(md2->model); + // If model uses sprite patch as texture, then + // adjust texture coordinates to take power of two textures into account + if (!gpatch || !gpatch->mipmap->format) + adjustTextureCoords(md2->model, spr->gpatch); + // note down the max_s and max_t that end up in the VBO + md2->model->vbo_max_s = md2->model->max_s; + md2->model->vbo_max_t = md2->model->max_t; HWD.pfnCreateModelVBOs(md2->model); } else { //CONS_Debug(DBG_RENDER, " FAILED\n"); md2->error = true; // prevent endless fail - return; + return false; } } + + //HWD.pfnSetBlend(blend); // This seems to actually break translucency? finalscale = md2->scale; //Hurdler: arf, I don't like that implementation at all... too much crappy - gpatch = md2->grpatch; - if (!gpatch || ((!gpatch->mipmap->grInfo.format || !gpatch->mipmap->downloaded) && !gpatch->notfound)) - md2_loadTexture(md2); - gpatch = md2->grpatch; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture... - if ((gpatch && gpatch->mipmap->grInfo.format) // don't load the blend texture if the base texture isn't available - && (!md2->blendgrpatch - || ((!((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format || !((GLPatch_t *)md2->blendgrpatch)->mipmap->downloaded) - && !((GLPatch_t *)md2->blendgrpatch)->notfound))) - md2_loadBlendTexture(md2); - - if (gpatch && gpatch->mipmap->grInfo.format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture + if (gpatch && gpatch->mipmap->format) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture { - if ((skincolors_t)spr->mobj->color != SKINCOLOR_NONE && - md2->blendgrpatch && ((GLPatch_t *)md2->blendgrpatch)->mipmap->grInfo.format - && gpatch->width == ((GLPatch_t *)md2->blendgrpatch)->width && gpatch->height == ((GLPatch_t *)md2->blendgrpatch)->height) + INT32 skinnum = TC_DEFAULT; + + if ((spr->mobj->flags & (MF_ENEMY|MF_BOSS)) && (spr->mobj->flags2 & MF2_FRET) && !(spr->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { - INT32 skinnum = TC_DEFAULT; - if ((spr->mobj->flags & MF_BOSS) && (spr->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" - { - if (spr->mobj->type == MT_CYBRAKDEMON) - skinnum = TC_ALLWHITE; - else if (spr->mobj->type == MT_METALSONIC_BATTLE) - skinnum = TC_METALSONIC; - else - skinnum = TC_BOSS; - } - else if (spr->mobj->color) - { - if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - { - if (spr->mobj->colorized) - skinnum = TC_RAINBOW; - else - { - skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); - } - } - else skinnum = TC_DEFAULT; - } - HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolors_t)spr->mobj->color); + if (spr->mobj->type == MT_CYBRAKDEMON || spr->mobj->colorized) + skinnum = TC_ALLWHITE; + else if (spr->mobj->type == MT_METALSONIC_BATTLE) + skinnum = TC_METALSONIC; + else + skinnum = TC_BOSS; } - else + else if ((skincolornum_t)spr->mobj->color != SKINCOLOR_NONE) { - // This is safe, since we know the texture has been downloaded - HWD.pfnSetTexture(gpatch->mipmap); + if (spr->mobj->colorized) + skinnum = TC_RAINBOW; + else if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) + skinnum = (INT32)((skin_t*)spr->mobj->skin-skins); + else + skinnum = TC_DEFAULT; } + + // Translation or skin number found + HWR_GetBlendedTexture(gpatch, (GLPatch_t *)md2->blendgrpatch, skinnum, spr->colormap, (skincolornum_t)spr->mobj->color); } else { // Sprite - gpatch = W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + gpatch = spr->gpatch; //W_CachePatchNum(spr->patchlumpnum, PU_CACHE); + // Check if sprite dimensions are different from previously used sprite. + // If so, uvs need to be readjusted. + // Comparing floats with the != operator here should be okay because they + // are just copies of glpatches' max_s and max_t values. + // Instead of the != operator, memcmp is used to avoid a compiler warning. + if (memcmp(&(gpatch->max_s), &(md2->model->max_s), sizeof(md2->model->max_s)) != 0 || + memcmp(&(gpatch->max_t), &(md2->model->max_t), sizeof(md2->model->max_t)) != 0) + adjustTextureCoords(md2->model, gpatch); HWR_GetMappedPatch(gpatch, spr->colormap); } @@ -1254,56 +1479,96 @@ void HWR_DrawMD2(gr_vissprite_t *spr) tics = spr->mobj->anim_duration; } - //FIXME: this is not yet correct - frame = (spr->mobj->frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames; + frame = (spr->mobj->frame & FF_FRAMEMASK); + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) + { + spr2 = HWR_GetModelSprite2(md2, spr->mobj->skin, spr->mobj->sprite2, spr->mobj->player); + mod = md2->model->spr2frames[spr2].numframes; +#ifndef DONTHIDEDIFFANIMLENGTH // by default, different anim length is masked by the mod + if (mod > (INT32)((skin_t *)spr->mobj->skin)->sprites[spr2].numframes) + mod = ((skin_t *)spr->mobj->skin)->sprites[spr2].numframes; +#endif + if (!mod) + mod = 1; + frame = md2->model->spr2frames[spr2].frames[frame%mod]; + } + else + { + mod = md2->model->meshes[0].numFrames; + if (!mod) + mod = 1; + } #ifdef USE_MODEL_NEXTFRAME - if (cv_grmdls.value == 1 && tics <= durs) +#define INTERPOLERATION_LIMIT TICRATE/4 + if ( +#ifdef BAD_MODEL_OPTIONS + cv_glmodelinterpolation.value && +#endif + tics <= durs && tics <= INTERPOLERATION_LIMIT) { - // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation - if (spr->mobj->frame & FF_ANIMATE) + if (durs > INTERPOLERATION_LIMIT) + durs = INTERPOLERATION_LIMIT; + + if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY && md2->model->spr2frames) { - nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; - if (nextFrame >= spr->mobj->state->var1) - nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK); - nextFrame %= md2->model->meshes[0].numFrames; - //next = &md2->model->meshes[0].frames[nextFrame]; - } - else - { - if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL - && !(spr->mobj->player && (spr->mobj->state->nextstate == S_PLAY_TAP1 || spr->mobj->state->nextstate == S_PLAY_TAP2) && spr->mobj->state == &states[S_PLAY_STND])) + if (HWR_CanInterpolateSprite2(&md2->model->spr2frames[spr2]) + && (spr->mobj->frame & FF_ANIMATE + || (spr->mobj->state->nextstate != S_NULL + && states[spr->mobj->state->nextstate].sprite == SPR_PLAY + && ((P_GetSkinSprite2(spr->mobj->skin, (((spr->mobj->player && spr->mobj->player->powers[pw_super]) ? FF_SPR2SUPER : 0)|states[spr->mobj->state->nextstate].frame) & FF_FRAMEMASK, spr->mobj->player) == spr->mobj->sprite2))))) { - nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % md2->model->meshes[0].numFrames; - //next = &md2->model->meshes[0].frames[nextFrame]; + nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; + if (nextFrame >= mod) + nextFrame = 0; + if (frame || !(spr->mobj->state->frame & FF_SPR2ENDSTATE)) + nextFrame = md2->model->spr2frames[spr2].frames[nextFrame]; + else + nextFrame = -1; + } + } + else if (HWR_CanInterpolateModel(spr->mobj, md2->model)) + { + // frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation + if (spr->mobj->frame & FF_ANIMATE) + { + nextFrame = (spr->mobj->frame & FF_FRAMEMASK) + 1; + if (nextFrame >= (INT32)(spr->mobj->state->var1 + (spr->mobj->state->frame & FF_FRAMEMASK))) + nextFrame = (spr->mobj->state->frame & FF_FRAMEMASK) % mod; + } + else + { + if (spr->mobj->state->nextstate != S_NULL && states[spr->mobj->state->nextstate].sprite != SPR_NULL) + nextFrame = (states[spr->mobj->state->nextstate].frame & FF_FRAMEMASK) % mod; } } } +#undef INTERPOLERATION_LIMIT #endif //Hurdler: it seems there is still a small problem with mobj angle p.x = FIXED_TO_FLOAT(thingxpos); p.y = FIXED_TO_FLOAT(thingypos) + md2->offset; - if (spr->mobj->eflags & MFE_VERTICALFLIP) - p.z = FIXED_TO_FLOAT(thingzpos + spr->mobj->height); + if (flip) + p.z = FIXED_TO_FLOAT(spr->mobj->z + spr->mobj->height); else p.z = FIXED_TO_FLOAT(thingzpos); if (spr->mobj->skin && spr->mobj->sprite == SPR_PLAY) - sprdef = &((skin_t *)spr->mobj->skin)->spritedef; + sprdef = &((skin_t *)spr->mobj->skin)->sprites[spr->mobj->sprite2]; else sprdef = &sprites[spr->mobj->sprite]; sprframe = &sprdef->spriteframes[spr->mobj->frame & FF_FRAMEMASK]; - if (sprframe->rotate) + if (sprframe->rotate || papersprite) { - fixed_t anglef; + fixed_t anglef = AngleFixed(spr->mobj->angle); + if (spr->mobj->player) - anglef = AngleFixed(spr->mobj->player->frameangle); - else - anglef = AngleFixed(spr->mobj->angle); + anglef = AngleFixed(spr->mobj->player->drawangle); + p.angley = FIXED_TO_FLOAT(anglef); } else @@ -1311,15 +1576,45 @@ void HWR_DrawMD2(gr_vissprite_t *spr) const fixed_t anglef = AngleFixed((R_PointToAngle(thingxpos, thingypos))-ANGLE_180); p.angley = FIXED_TO_FLOAT(anglef); } + + p.rollangle = 0.0f; + p.rollflip = 1; + p.rotaxis = 0; + if (spr->mobj->rollangle) + { + fixed_t anglef = AngleFixed(spr->mobj->rollangle); + p.rollangle = FIXED_TO_FLOAT(anglef); + p.roll = true; + + // rotation pivot + p.centerx = FIXED_TO_FLOAT(spr->mobj->radius/2); + p.centery = FIXED_TO_FLOAT(spr->mobj->height/(flip ? -2 : 2)); + + // rotation axis + if (sprinfo->available) + p.rotaxis = (UINT8)(sprinfo->pivot[(spr->mobj->frame & FF_FRAMEMASK)].rotaxis); + + // for NiGHTS specifically but should work everywhere else + ang = R_PointToAngle (spr->mobj->x, spr->mobj->y) - (spr->mobj->player ? spr->mobj->player->drawangle : spr->mobj->angle); + if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right + p.rollflip = 1; + else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left + p.rollflip = -1; + + if (flip) + p.rollflip *= -1; + } + p.anglex = 0.0f; + #ifdef USE_FTRANSFORM_ANGLEZ // Slope rotation from Kart p.anglez = 0.0f; - if (spr->mobj->modeltilt) + if (spr->mobj->standingslope) { - fixed_t tempz = spr->mobj->modeltilt->normal.z; - fixed_t tempy = spr->mobj->modeltilt->normal.y; - fixed_t tempx = spr->mobj->modeltilt->normal.x; + fixed_t tempz = spr->mobj->standingslope->normal.z; + fixed_t tempy = spr->mobj->standingslope->normal.y; + fixed_t tempx = spr->mobj->standingslope->normal.x; fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx)); p.anglez = FIXED_TO_FLOAT(tempangle); tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy)); @@ -1335,9 +1630,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr) p.mirror = atransform.mirror; // from Kart #endif - HWD.pfnSetShader(4); // model shader - HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, &Surf); + HWD.pfnSetShader(SHADER_MODEL); // model shader + HWD.pfnDrawModel(md2->model, frame, durs, tics, nextFrame, &p, finalscale, flip, hflip, &Surf); } + + return true; } #endif //HWRENDER diff --git a/src/hardware/hw_md2.h b/src/hardware/hw_md2.h index fab8e6ad9..0f4d2c7bc 100644 --- a/src/hardware/hw_md2.h +++ b/src/hardware/hw_md2.h @@ -1,15 +1,14 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file -/// \brief MD2 Handling +/// \file hw_md2.h +/// \brief 3D Model Handling /// Inspired from md2.h by Mete Ciragan (mete@swissquake.ch) #ifndef _HW_MD2_H_ @@ -29,7 +28,9 @@ typedef struct float offset; model_t *model; void *grpatch; + boolean notexturefile; // true if texture file was not found void *blendgrpatch; + boolean noblendfile; // true if blend texture file was not found boolean notfound; INT32 skin; boolean error; @@ -38,9 +39,11 @@ typedef struct extern md2_t md2_models[NUMSPRITES]; extern md2_t md2_playermodels[MAXSKINS]; -void HWR_InitMD2(void); -void HWR_DrawMD2(gr_vissprite_t *spr); -void HWR_AddPlayerMD2(INT32 skin); -void HWR_AddSpriteMD2(size_t spritenum); +void HWR_InitModels(void); +void HWR_AddPlayerModel(INT32 skin); +void HWR_AddSpriteModel(size_t spritenum); +boolean HWR_DrawModel(gl_vissprite_t *spr); + +#define PLAYERMODELPREFIX "PLAYER" #endif // _HW_MD2_H_ diff --git a/src/hardware/hw_md2load.c b/src/hardware/hw_md2load.c index 3805deffb..fed81e411 100644 --- a/src/hardware/hw_md2load.c +++ b/src/hardware/hw_md2load.c @@ -252,6 +252,8 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) md2triangle_t *tris; md2texcoord_t *texcoords; md2frame_t *frames; + char *fname = NULL; + int foffset = 0; int t; @@ -326,6 +328,16 @@ model_t *MD2_LoadModel(const char *fileName, int ztag, boolean useFloat) texcoords = (md2texcoord_t*)&buffer[header->offsetST]; frames = (md2frame_t*)&buffer[header->offsetFrames]; + retModel->framenames = (char*)Z_Calloc(header->numFrames*16, ztag, 0); + fname = retModel->framenames; + for (i = 0; i < header->numFrames; i++) + { + md2frame_t *fr = (md2frame_t*)&buffer[header->offsetFrames + foffset]; + memcpy(fname, fr->name, 16); + foffset += sizeof(md2frame_t) + (sizeof(md2vertex_t) * header->numXYZ); + fname += 16; + } + // Read in textures retModel->numMaterials = header->numSkins; diff --git a/src/hardware/hw_md3load.c b/src/hardware/hw_md3load.c index 53f6034c0..87931d27b 100644 --- a/src/hardware/hw_md3load.c +++ b/src/hardware/hw_md3load.c @@ -148,6 +148,8 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) { const float WUNITS = 1.0f; model_t *retModel = NULL; + md3Frame *frames = NULL; + char *fname = NULL; md3modelHeader *mdh; long fileLen; long fileReadLen; @@ -227,6 +229,16 @@ model_t *MD3_LoadModel(const char *fileName, int ztag, boolean useFloat) retModel->meshes = (mesh_t*)Z_Calloc(sizeof(mesh_t)*retModel->numMeshes, ztag, 0); + frames = (md3Frame*)&buffer[mdh->offsetFrames]; + retModel->framenames = (char*)Z_Calloc(mdh->numFrames*16, ztag, 0); + fname = retModel->framenames; + for (i = 0; i < mdh->numFrames; i++) + { + memcpy(fname, frames->name, 16); + fname += 16; + frames++; + } + matCount = 0; for (i = 0, surfEnd = 0; i < mdh->numSurfaces; i++) { diff --git a/src/hardware/hw_model.c b/src/hardware/hw_model.c index 2c36f9744..4ed03744b 100644 --- a/src/hardware/hw_model.c +++ b/src/hardware/hw_model.c @@ -7,11 +7,14 @@ the licensing is for Sonic Robo Blast 2. */ -#include "../z_zone.h" #include "../doomdef.h" +#include "../doomtype.h" +#include "../info.h" +#include "../z_zone.h" #include "hw_model.h" #include "hw_md2load.h" #include "hw_md3load.h" +#include "hw_md2.h" #include "u_list.h" #include @@ -195,6 +198,9 @@ model_t *LoadModel(const char *filename, int ztag) Optimize(model); GeneratePolygonNormals(model, ztag); + LoadModelSprite2(model); + if (!model->spr2frames) + LoadModelInterpolationSettings(model); // Default material properties for (i = 0 ; i < model->numMaterials; i++) @@ -215,9 +221,156 @@ model_t *LoadModel(const char *filename, int ztag) material->shininess = 25.0f; } + // Set originaluvs to point to uvs + for (i = 0; i < model->numMeshes; i++) + model->meshes[i].originaluvs = model->meshes[i].uvs; + + model->max_s = 1.0; + model->max_t = 1.0; + model->vbo_max_s = 1.0; + model->vbo_max_t = 1.0; + return model; } +void HWR_ReloadModels(void) +{ + size_t i; + INT32 s; + + for (s = 0; s < MAXSKINS; s++) + { + if (md2_playermodels[s].model) + LoadModelSprite2(md2_playermodels[s].model); + } + + for (i = 0; i < NUMSPRITES; i++) + { + if (md2_models[i].model) + LoadModelInterpolationSettings(md2_models[i].model); + } +} + +void LoadModelInterpolationSettings(model_t *model) +{ + INT32 i; + INT32 numframes = model->meshes[0].numFrames; + char *framename = model->framenames; + + if (!framename) + return; + + #define GET_OFFSET \ + memcpy(&interpolation_flag, framename + offset, 2); \ + model->interpolate[i] = (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2)); + + for (i = 0; i < numframes; i++) + { + int offset = (strlen(framename) - 4); + char interpolation_flag[3]; + memset(&interpolation_flag, 0x00, 3); + + // find the +i on the frame name + // ANIM+i00 + // so the offset is (frame name length - 4) + GET_OFFSET; + + // maybe the frame had three digits? + // ANIM+i000 + // so the offset is (frame name length - 5) + if (!model->interpolate[i]) + { + offset--; + GET_OFFSET; + } + + framename += 16; + } + + #undef GET_OFFSET +} + +void LoadModelSprite2(model_t *model) +{ + INT32 i; + modelspr2frames_t *spr2frames = NULL; + INT32 numframes = model->meshes[0].numFrames; + char *framename = model->framenames; + + if (!framename) + return; + + for (i = 0; i < numframes; i++) + { + char prefix[6]; + char name[5]; + char interpolation_flag[3]; + char framechars[4]; + UINT8 frame = 0; + UINT8 spr2idx; + boolean interpolate = false; + + memset(&prefix, 0x00, 6); + memset(&name, 0x00, 5); + memset(&interpolation_flag, 0x00, 3); + memset(&framechars, 0x00, 4); + + if (strlen(framename) >= 9) + { + boolean super; + char *modelframename = framename; + memcpy(&prefix, modelframename, 5); + modelframename += 5; + memcpy(&name, modelframename, 4); + modelframename += 4; + // Oh look + memcpy(&interpolation_flag, modelframename, 2); + if (!memcmp(interpolation_flag, MODEL_INTERPOLATION_FLAG, 2)) + { + interpolate = true; + modelframename += 2; + } + memcpy(&framechars, modelframename, 3); + + if ((super = (!memcmp(prefix, "SUPER", 5))) || (!memcmp(prefix, "SPR2_", 5))) + { + spr2idx = 0; + while (spr2idx < free_spr2) + { + if (!memcmp(spr2names[spr2idx], name, 4)) + { + if (!spr2frames) + spr2frames = (modelspr2frames_t*)Z_Calloc(sizeof(modelspr2frames_t)*NUMPLAYERSPRITES*2, PU_STATIC, NULL); + if (super) + spr2idx |= FF_SPR2SUPER; + if (framechars[0]) + { + frame = atoi(framechars); + if (spr2frames[spr2idx].numframes < frame+1) + spr2frames[spr2idx].numframes = frame+1; + } + else + { + frame = spr2frames[spr2idx].numframes; + spr2frames[spr2idx].numframes++; + } + spr2frames[spr2idx].frames[frame] = i; + spr2frames[spr2idx].interpolate = interpolate; + break; + } + spr2idx++; + } + } + } + + framename += 16; + } + + if (model->spr2frames) + Z_Free(model->spr2frames); + model->spr2frames = spr2frames; +} + // // GenerateVertexNormals // diff --git a/src/hardware/hw_model.h b/src/hardware/hw_model.h index 1803f4c5c..6b39eb24d 100644 --- a/src/hardware/hw_model.h +++ b/src/hardware/hw_model.h @@ -59,6 +59,11 @@ typedef struct mesh_s int numTriangles; float *uvs; + // if uv adjustment is needed, uvs is changed to point to adjusted ones and + // this one retains the originals + // note: this member has been added with the assumption that models are never freed. + // (UnloadModel is called by nobody at the time of writing.) + float *originaluvs; float *lightuvs; int numFrames; @@ -73,6 +78,15 @@ typedef struct tag_s // matrix_t transform; } tag_t; +#define MODEL_INTERPOLATION_FLAG "+i" + +typedef struct +{ + INT32 frames[256]; + UINT8 numframes; + boolean interpolate; +} modelspr2frames_t; + typedef struct model_s { int maxNumFrames; @@ -86,15 +100,32 @@ typedef struct model_s char *mdlFilename; boolean unloaded; + + char *framenames; + boolean interpolate[256]; + modelspr2frames_t *spr2frames; + + // the max_s and max_t values that the uvs are currently adjusted to + // (if a sprite is used as a texture) + float max_s; + float max_t; + // These are the values that the uvs in the VBO have been adjusted to. + // If they are not same as max_s and max_t, then the VBO won't be used. + float vbo_max_s; + float vbo_max_t; } model_t; extern int numModels; extern model_t *modelHead; +void HWR_ReloadModels(void); + tag_t *GetTagByName(model_t *model, char *name, int frame); model_t *LoadModel(const char *filename, int ztag); void UnloadModel(model_t *model); void Optimize(model_t *model); +void LoadModelInterpolationSettings(model_t *model); +void LoadModelSprite2(model_t *model); void GenerateVertexNormals(model_t *model); void GeneratePolygonNormals(model_t *model, int ztag); void CreateVBOTiny(mesh_t *mesh, tinyframe_t *frame); diff --git a/src/hardware/hw_trick.c b/src/hardware/hw_trick.c deleted file mode 100644 index de4a76c59..000000000 --- a/src/hardware/hw_trick.c +++ /dev/null @@ -1,919 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2001 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief special trick routines to make some SW tricks look OK with -/// HW rendering. This includes: -/// - deepwatereffect (e.g. tnt/map02) -/// - invisible staircase (e.g. eternal/map02) -/// - floating ceilings (e.g. eternal/map03) -/// -/// It is not guaranteed that it looks identical to the SW mode, -/// but it looks in most of the cases far better than having -/// holes in the architecture, HOM, etc. -/// -/// It fixes as well missing textures, which are replaced by either -/// a default texture or the midtexture. -/// -/// words of notice: -/// pseudosectors, as mentioned in this file, are sectors where both -/// sidedefs point to the same sector. This expression is also used -/// for sectors which are enclosed by another sector but have no -/// correct sidedefs at all -/// -/// if a vertex is inside a poly is determined by the angles between -/// this vertex and all angles on the linedefs (imagine walking along -/// a circle always facing a certain point inside/outside the circle; -/// if inside, angle have taken all values [0..pi), otherwise the -/// range was < pi/2 - -#include -#include "../doomdef.h" -#include "../doomstat.h" - -#ifdef HWRENDER -#include "hw_main.h" -#include "hw_glob.h" -#include "hw_dll.h" -#include "../r_local.h" -#include "../i_system.h" - -// -// add a line to a sectors list of lines -// -static void addLineToChain(sector_t *sector, line_t *line) -{ - linechain_t *thisElem = NULL, *nextElem; - - if (!sector) - return; - - nextElem = sector->sectorLines; - - while (nextElem) // walk through chain - { - thisElem = nextElem; - nextElem = thisElem->next; - } - - // add a new element into the chain - if (thisElem) - { - thisElem->next = malloc(sizeof (linechain_t)); - if (thisElem->next) - { - thisElem->next->line = line; - thisElem->next->next = NULL; - } - else - { - I_Error("Out of memory in addLineToChain(.)\n"); - } - } - else // first element in chain - { - sector->sectorLines = malloc(sizeof (linechain_t)); - if (sector->sectorLines) - { - sector->sectorLines->line = line; - sector->sectorLines->next = NULL; - } - else - { - I_Error("Out of memory in addLineToChain(.)\n"); - } - } -} - -// -// We dont want a memory hole, do we?;-) -// -static void releaseLineChains(void) -{ - linechain_t *thisElem, *nextElem; - sector_t *sector; - size_t i; - - for (i = 0; i < numsectors; i++) - { - sector = §ors[i]; - nextElem = sector->sectorLines; - - while (nextElem) - { - thisElem = nextElem; - nextElem = thisElem->next; - free(thisElem); - } - - sector->sectorLines = NULL; - } -} - -// -// check if a pseudo sector is valid by checking all its linedefs -// -static boolean isPSectorValid(sector_t *sector) -{ - linechain_t *thisElem, *nextElem; - - if (!sector->pseudoSector) // check only pseudosectors, others dont care - { -#ifdef PARANOIA - CONS_Debug(DBG_RENDER, "Alert! non-pseudosector fed to isPSectorClosed()\n"); -#endif - return false; - } - - nextElem = sector->sectorLines; - - while (nextElem) - { - thisElem = nextElem; - nextElem = thisElem->next; - if (thisElem->line->frontsector != thisElem->line->backsector) - return false; - } - return true; -} - -// -// angles are always phiMax-phiMin [0...2\pi) -// -FUNCMATH static double phiDiff(double phiMin, double phiMax) -{ - double result; - - result = phiMax-phiMin; - - if (result < 0.0l) - result += 2.0l*M_PIl; - - return result; -} - -// -// sort phi's so that enclosed angle < \pi -// -static void sortPhi(double phi1, double phi2, double *phiMin, double *phiMax) -{ - if (phiDiff(phi1, phi2) < M_PIl) - { - *phiMin = phi1; - *phiMax = phi2; - } - else - { - *phiMin = phi2; - *phiMax = phi1; - } -} - -// -// return if angle(phi1, phi2) is bigger than \pi -// if so, the vertex lies inside the poly -// -FUNCMATH static boolean biggerThanPi(double phi1, double phi2) -{ - if (phiDiff(phi1, phi2) > M_PIl) - return true; - - return false; -} - -#define DELTAPHI (M_PIl/100.0l) // some small phi << \pi - -// -// calculate bounds for minimum angle -// -static void phiBounds(double phi1, double phi2, double *phiMin, double *phiMax) -{ - double phi1Tmp, phi2Tmp; - double psi1, psi2, psi3, psi4, psi5, psi6, psi7; // for optimization - - sortPhi(phi1, phi2, &phi1Tmp, &phi2Tmp); - phi1 = phi1Tmp; - phi2 = phi2Tmp; - - // check start condition - if (*phiMin > M_PIl || *phiMax > M_PIl) - { - *phiMin = phi1; - *phiMax = phi2; - return; - } - - // 6 cases: - // new angles inbetween phiMin, phiMax -> forget it - // new angles enclose phiMin -> set phiMin - // new angles enclose phiMax -> set phiMax - // new angles completely outside phiMin, phiMax -> leave largest area free - // new angles close the range completely! - // new angles enlarges range on both sides - - psi1 = phiDiff(*phiMin, phi1); - psi2 = phiDiff(*phiMin, phi2); - psi3 = phiDiff(*phiMax, phi1); - psi4 = phiDiff(*phiMax, phi2); - psi5 = phiDiff(*phiMin, *phiMax); - psi6 = (double)(2.0l*M_PIl - psi5); // phiDiff(*phiMax, *phiMin); - psi7 = (double)(2.0l*M_PIl - psi2); // phiDiff(phi2, *phiMin); - - // case 1 & 5! - if ((psi1 <= psi5) && (psi2 <= psi5)) - { - if (psi1 <= psi2) // case 1 - { - return; - } - else // case 5 - { - // create some artificial interval here not to get into numerical trouble - // in fact we know now the sector is completely enclosed -> base for computational optimization - *phiMax = 0.0l; - *phiMin = DELTAPHI; - return; - } - } - - // case 2 - if ((psi1 >= psi5) && (psi2 <= psi5)) - { - *phiMin = phi1; - return; - } - - // case 3 - if ((psi3 >= psi6) && (psi4 <= psi6)) - { - *phiMax = phi2; - return; - } - - // case 4 & 6 -#ifdef PARANOIA - if ((psi3 <= psi6) && (psi4 <= psi6)) // FIXME: isn't this case implicitly true anyway?? -#endif - { - if (psi3 <= psi4) //case 4 - { - if (psi3 >= psi7) - { - *phiMin = phi1; - return; - } - else - { - *phiMax = phi2; - return; - } - } - else // case 6 - { - *phiMin = phi1; - *phiMax = phi2; - return; - } - } - -#ifdef PARANOIA - CONS_Debug(DBG_RENDER, "phiMin = %f, phiMax = %f, phi1 = %f, phi2 = %f\n", *phiMin, *phiMax, phi1, phi2); - I_Error("phiBounds() out of range!\n"); -#endif -} - -// -// Check if a vertex lies inside a sector -// This works for "well-behaved" convex polygons -// If we need it mathematically correct, we need to sort the -// linedefs first so we have them in a row, then walk along the linedefs, -// but this is a bit overdone -// -static inline boolean isVertexInside(vertex_t *vertex, sector_t *sector) -{ - double xa, ya, xe, ye; - linechain_t *chain; - double phiMin, phiMax; - double phi1, phi2; - - chain = sector->sectorLines; - phiMin = phiMax = 10.0l*M_PIl; // some value > \pi - - while (chain) - { - // start and end vertex - xa = (double)chain->line->v1->x - (double)vertex->x; - ya = (double)chain->line->v1->y - (double)vertex->y; - xe = (double)chain->line->v2->x - (double)vertex->x; - ye = (double)chain->line->v2->y - (double)vertex->y; - - // angle phi of connection between the vertices and the x-axis - phi1 = atan2(ya, xa); - phi2 = atan2(ye, xe); - - // if we have just started, we can have to create start bounds for phi - - phiBounds(phi1, phi2, &phiMin, &phiMax); - chain = chain->next; - } - - return biggerThanPi(phiMin, phiMax); -} - - -#define MAXSTACK 256 // Not more than 256 polys in each other? -// -// generate a list of sectors which enclose the given sector -// -static void generateStacklist(sector_t *thisSector) -{ - size_t i, stackCnt = 0; - sector_t *locStacklist[MAXSTACK]; - sector_t *checkSector; - - for (i = 0; i < numsectors; i++) - { - checkSector = §ors[i]; - - if (checkSector == thisSector) // dont check self - continue; - - // buggy sector? - if (!thisSector->sectorLines) - continue; - - // check if an arbitrary vertex of thisSector lies inside the checkSector - if (isVertexInside(thisSector->sectorLines->line->v1, checkSector)) - { - // if so, the thisSector lies inside the checkSector - locStacklist[stackCnt] = checkSector; - stackCnt++; - - if (MAXSTACK-1 == stackCnt) // beware of the SIGSEGV! and consider terminating NULL! - break; - } - } - - thisSector->stackList = malloc(sizeof (sector_t *) * (stackCnt+1)); - if (NULL == thisSector->stackList) - { - I_Error("Out of memory error in generateStacklist()"); - } - - locStacklist[stackCnt] = NULL; // terminating NULL - - memcpy(thisSector->stackList, locStacklist, sizeof (sector_t *) * (stackCnt+1)); -} - -// -// Bubble sort the stacklist with rising lineoutlengths -// -static void sortStacklist(sector_t *sector) -{ - sector_t **list; - sector_t *sec1, *sec2; - boolean finished; - size_t i; - - list = sector->stackList; - finished = false; - - if (!*list) - return; // nothing to sort - - while (!finished) - { - i = 0; - finished = true; - - while (*(list+i+1)) - { - sec1 = *(list+i); - sec2 = *(list+i+1); - - if (sec1->lineoutLength > sec2->lineoutLength) - { - *(list+i) = sec2; - *(list+i+1) = sec1; - finished = false; - } - i++; - } - } -} - -// -// length of a line in euclidian sense -// -static double lineLength(line_t *line) -{ - double dx, dy, length; - - dx = (double) line->v1->x - (double) line->v2->x; - dy = (double) line->v1->y - (double) line->v2->y; - - length = hypot(dx, dy); - - return length; -} - - -// -// length of the sector lineout -// -static double calcLineoutLength(sector_t *sector) -{ - linechain_t *chain; - double length = 0.0L; - chain = sector->sectorLines; - - while (chain) // sum up lengths of all lines - { - length += lineLength(chain->line); - chain = chain->next; - } - return length; -} - -// -// Calculate length of the sectors lineout -// -static void calcLineouts(sector_t *sector) -{ - size_t secCount = 0; - sector_t *encSector = *(sector->stackList); - - while (encSector) - { - if (encSector->lineoutLength < 0.0L) // if length has not yet been calculated - { - encSector->lineoutLength = calcLineoutLength(encSector); - } - - secCount++; - encSector = *((sector->stackList) + secCount); - } -} - -// -// Free Stacklists of all sectors -// -static void freeStacklists(void) -{ - size_t i; - - for (i = 0; i < numsectors; i++) - { - if (sectors[i].stackList) - { - free(sectors[i].stackList); - sectors[i].stackList = NULL; - } - } -} - -// -// if more than half of the toptextures are missing -// -static boolean areToptexturesMissing(sector_t *thisSector) -{ - linechain_t *thisElem, *nextElem = thisSector->sectorLines; - sector_t *frontSector, *backSector; - size_t nomiss = 0; - side_t *sidel, *sider; - - while (nextElem) // walk through chain - { - thisElem = nextElem; - nextElem = thisElem->next; - - frontSector = thisElem->line->frontsector; - backSector = thisElem->line->backsector; - - if (frontSector == backSector) // skip damn renderer tricks here - continue; - - if (!frontSector || !backSector) - continue; - - sider = &sides[thisElem->line->sidenum[0]]; - sidel = &sides[thisElem->line->sidenum[1]]; - - if (backSector->ceilingheight < frontSector->ceilingheight) - { - if (sider->toptexture != 0) - { - nomiss++; - break; // we can stop here if decision criterium is ==0 - } - } - else if (backSector->ceilingheight > frontSector->ceilingheight) - { - if (sidel->toptexture != 0) - { - nomiss++; - break; // we can stop here if decision criterium is ==0 - } - } - } - - return nomiss == 0; -} - -// -// are more textures missing than present? -// -static boolean areBottomtexturesMissing(sector_t *thisSector) -{ - linechain_t *thisElem, *nextElem = thisSector->sectorLines; - sector_t *frontSector, *backSector; - size_t nomiss = 0; - side_t *sidel, *sider; - - while (nextElem) // walk through chain - { - thisElem = nextElem; - nextElem = thisElem->next; - - frontSector = thisElem->line->frontsector; - backSector = thisElem->line->backsector; - - if (frontSector == backSector) // skip damn renderer tricks here - continue; - - if (!frontSector || !backSector) - continue; - - sider = &sides[thisElem->line->sidenum[0]]; - sidel = &sides[thisElem->line->sidenum[1]]; - - if (backSector->floorheight > frontSector->floorheight) - { - if (sider->bottomtexture != 0) - { - nomiss++; - break; // we can stop here if decision criterium is ==0 - } - } - - else if (backSector->floorheight < frontSector->floorheight) - { - if (sidel->bottomtexture != 0) - { - nomiss++; - break; // we can stop here if decision criterium is ==0 - } - } - } - - // return missing >= nomiss; - return nomiss == 0; -} - -// -// check if no adjacent sector has same ceiling height -// -static boolean isCeilingFloating(sector_t *thisSector) -{ - sector_t *adjSector, *refSector = NULL, *frontSector, *backSector; - linechain_t *thisElem, *nextElem; - - if (!thisSector) - return false; - - nextElem = thisSector->sectorLines; - - while (nextElem) // walk through chain - { - thisElem = nextElem; - nextElem = thisElem->next; - - frontSector = thisElem->line->frontsector; - backSector = thisElem->line->backsector; - - if (frontSector == thisSector) - adjSector = backSector; - else - adjSector = frontSector; - - if (!adjSector) // assume floating sectors have surrounding sectors - return false; - -#ifdef ESLOPE - if (adjSector->c_slope) // Don't bother with slopes - return false; -#endif - - if (!refSector) - { - refSector = adjSector; - continue; - } - - // if adjacent sector has same height or more than one adjacent sector exists -> stop - if (thisSector->ceilingheight == adjSector->ceilingheight || refSector != adjSector) - return false; - } - - // now check for walltextures - if (!areToptexturesMissing(thisSector)) - return false; - - return true; -} - -// -// check if no adjacent sector has same ceiling height -// FIXME: throw that together with isCeilingFloating?? -// -static boolean isFloorFloating(sector_t *thisSector) -{ - sector_t *adjSector, *refSector = NULL, *frontSector, *backSector; - linechain_t *thisElem, *nextElem; - - if (!thisSector) - return false; - - nextElem = thisSector->sectorLines; - - while (nextElem) // walk through chain - { - thisElem = nextElem; - nextElem = thisElem->next; - - frontSector = thisElem->line->frontsector; - backSector = thisElem->line->backsector; - - if (frontSector == thisSector) - adjSector = backSector; - else - adjSector = frontSector; - - if (!adjSector) // assume floating sectors have surrounding sectors - return false; - -#ifdef ESLOPE - if (adjSector->f_slope) // Don't bother with slopes - return false; -#endif - - if (!refSector) - { - refSector = adjSector; - continue; - } - - // if adjacent sector has same height or more than one adjacent sector exists -> stop - if (thisSector->floorheight == adjSector->floorheight || refSector != adjSector) - return false; - } - - // now check for walltextures - if (!areBottomtexturesMissing(thisSector)) - return false; - - return true; -} - -// -// estimate ceilingheight according to height of adjacent sector -// -static fixed_t estimateCeilHeight(sector_t *thisSector) -{ - sector_t *adjSector; - - if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line) - return 0; - - adjSector = thisSector->sectorLines->line->frontsector; - if (adjSector == thisSector) - adjSector = thisSector->sectorLines->line->backsector; - - if (!adjSector) - return 0; - - return adjSector->ceilingheight; -} - -// -// estimate ceilingheight according to height of adjacent sector -// -static fixed_t estimateFloorHeight(sector_t *thisSector) -{ - sector_t *adjSector; - - if (!thisSector || !thisSector->sectorLines || !thisSector->sectorLines->line) - return 0; - - adjSector = thisSector->sectorLines->line->frontsector; - if (adjSector == thisSector) - adjSector = thisSector->sectorLines->line->backsector; - - if (!adjSector) - return 0; - - return adjSector->floorheight; -} - -#define CORRECT_FLOAT_EXPERIMENTAL - -// -------------------------------------------------------------------------- -// Some levels have missing sidedefs, which produces HOM, so lets try to compensate for that -// and some levels have deep water trick, invisible staircases etc. -// -------------------------------------------------------------------------- -// FIXME: put some nice default texture in legacy.dat and use it -void HWR_CorrectSWTricks(void) -{ - size_t i; - size_t k; - line_t *ld; - side_t *sidel = NULL, *sider; - sector_t *secl, *secr; - sector_t **sectorList; - sector_t *outSector; - - if ((0 == cv_grcorrecttricks.value)) - return; - - // determine lines for sectors - for (i = 0; i < numlines; i++) - { - ld = &lines[i]; - secr = ld->frontsector; - secl = ld->backsector; - - if (secr == secl) - { - secr->pseudoSector = true; // special renderer trick? - addLineToChain(secr, ld); - } - else - { - addLineToChain(secr, ld); - addLineToChain(secl, ld); - } - } - - // preprocessing - for (i = 0; i < numsectors; i++) - { - sector_t *checkSector; - - checkSector = §ors[i]; - - // identify real pseudosectors first - if (checkSector->pseudoSector) - { - if (!isPSectorValid(checkSector)) // drop invalid pseudo sectors - { - checkSector->pseudoSector = false; - } - } - - // determine enclosing sectors for pseudosectors ... used later - if (checkSector->pseudoSector) - { - generateStacklist(checkSector); - calcLineouts(checkSector); - sortStacklist(checkSector); - } - } - - // set virtual floor heights for pseudo sectors - // required for deep water effect e.g. - for (i = 0; i < numsectors; i++) - { - if (sectors[i].pseudoSector) - { - sectorList = sectors[i].stackList; - k = 0; - while (*(sectorList+k)) - { - outSector = *(sectorList+k); - if (!outSector->pseudoSector) - { - sectors[i].virtualFloorheight = outSector->floorheight; - sectors[i].virtualCeilingheight = outSector->ceilingheight; - break; - } - k++; - } - if (*(sectorList+k) == NULL) // sorry, did not work :( - { - sectors[i].virtualFloorheight = sectors[i].floorheight; - sectors[i].virtualCeilingheight = sectors[i].ceilingheight; - } - } - } -#ifdef CORRECT_FLOAT_EXPERIMENTAL - // correct ceiling/floor heights of totally floating sectors - for (i = 0; i < numsectors; i++) - { - sector_t *floatSector; - - floatSector = §ors[i]; - - // correct height of floating sectors - if (isCeilingFloating(floatSector)) - { - floatSector->virtualCeilingheight = estimateCeilHeight(floatSector); - floatSector->virtualCeiling = true; - } - if (isFloorFloating(floatSector)) - { - floatSector->virtualFloorheight = estimateFloorHeight(floatSector); - floatSector->virtualFloor = true; - } - } -#endif - - // now for the missing textures - for (i = 0; i < numlines; i++) - { - ld = &lines[i]; - sider = &sides[ld->sidenum[0]]; - if (ld->sidenum[1] != 0xffff) - sidel = &sides[ld->sidenum[1]]; - - secr = ld->frontsector; - secl = ld->backsector; - - if (secr == secl) // special renderer trick - continue; // we cant correct missing textures here - - if (secl) // only if there is a backsector - { - if (secr->pseudoSector || secl->pseudoSector) - continue; - if (!secr->virtualFloor && !secl->virtualFloor) - { - if (secl->floorheight > secr->floorheight) - { - // now check if r-sidedef is correct - if (sider->bottomtexture == 0) - { - if (sider->midtexture == 0) - sider->bottomtexture = 0; // Tails // More redwall sky shenanigans - else - sider->bottomtexture = sider->midtexture; - } - } - else if (secl->floorheight < secr->floorheight) - { - // now check if l-sidedef is correct - if (sidel->bottomtexture == 0) - { - if (sidel->midtexture == 0) - sidel->bottomtexture = 0; // Tails // More redwall sky shenanigans - else - sidel->bottomtexture = sidel->midtexture; - } - } - } - - if (!secr->virtualCeiling && !secl->virtualCeiling) - { - if (secl->ceilingheight < secr->ceilingheight) - { - // now check if r-sidedef is correct - if (sider->toptexture == 0) - { - if (sider->midtexture == 0) - sider->toptexture = 0; // Tails // When this was REDWALL it was causing issues in the sky sometimes - else - sider->toptexture = sider->midtexture; - } - } - else if (secl->ceilingheight > secr->ceilingheight) - { - // now check if l-sidedef is correct - if (sidel->toptexture == 0) - { - if (sidel->midtexture == 0) - sidel->toptexture = 0; // Tails // When this was REDWALL it was causing issues in the sky sometimes - else - sidel->toptexture = sidel->midtexture; - } - } - } - } // if (NULL != secl) - } // for (i = 0; i < numlines; i++) - - // release all linechains - releaseLineChains(); - freeStacklists(); -} - -#endif // HWRENDER diff --git a/src/hardware/hws_data.h b/src/hardware/hws_data.h index 9e2d0547e..a8607ac67 100644 --- a/src/hardware/hws_data.h +++ b/src/hardware/hws_data.h @@ -1,19 +1,12 @@ -// Emacs style mode select -*- C++ -*- +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- +// Copyright (C) 2005 by Sonic Team Junior. // -// Copyright (C) 2005 by SRB2 Jr. Team. -// -// 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. +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file hws_data.h /// \brief 3D sound definitions #ifndef __HWS_DATA_H__ @@ -114,7 +107,7 @@ typedef struct snddev_s size_t numsfxs; // Windows specific data -#if defined (_WIN32) && !defined (_XBOX) +#ifdef _WIN32 UINT32 cooplevel; HWND hWnd; #endif diff --git a/src/hardware/r_minigl/r_minigl.dev b/src/hardware/r_minigl/r_minigl.dev deleted file mode 100644 index edf725ac5..000000000 --- a/src/hardware/r_minigl/r_minigl.dev +++ /dev/null @@ -1,89 +0,0 @@ -[Project] -FileName=r_minigl.dev -Name=r_minigl -Ver=1 -IsCpp=1 -Type=3 -Compiler=-D_M_IX86=500_@@_-Wall_@@_-D_WINDOWS_@@_-DUSE_WGL_SWAP_@@_-Os_@@_-fomit-frame-pointer_@@_ -CppCompiler= -Includes= -Linker=--def ../r_mingw.def_@@_-lgdi32_@@_ -Libs= -UnitCount=4 -Folders= -ObjFiles= -PrivateResource= -ResourceIncludes= -MakeIncludes= -Icon= -ExeOutput=C:\srb2demo2 -ObjectOutput=..\..\..\objs\Mingw\r_minigl -OverrideOutput=1 -OverrideOutputName=r_minigl.dll -HostApplication= -CommandLine= -IncludeVersionInfo=0 -SupportXPThemes=0 -CompilerSet=0 -CompilerSettings=00000000000000000111d0 -UseCustomMakefile=0 -CustomMakefile= - -[Unit1] -FileName=..\r_opengl\ogl_win.c -Folder= -Compile=0 -CompileCpp=0 -Link=0 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd=$(CC) -c ogl_win.c -o ../../../objs/Mingw/r_minigl/ogl_win.o $(CFLAGS) - -[Unit2] -FileName=..\r_opengl\r_opengl.c -Folder= -Compile=0 -CompileCpp=0 -Link=0 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd=$(CC) -c r_opengl.c -o ../../../objs/Mingw/r_minigl/r_opengl.o $(CFLAGS) - -[Unit3] -FileName=..\r_opengl\r_opengl.h -Folder= -Compile=1 -CompileCpp=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd= - -[VersionInfo] -Major=0 -Minor=1 -Release=1 -Build=1 -LanguageID=1033 -CharsetID=1252 -CompanyName= -FileVersion=0.1 -FileDescription=Developed using the Dev-C++ IDE -InternalName= -LegalCopyright= -LegalTrademarks= -OriginalFilename=r_opengl.exe -ProductName=r_opengl -ProductVersion=0.1 -AutoIncBuildNr=0 - -[Unit4] -FileName=r_minigl.c -CompileCpp=0 -Folder=r_minigl -Compile=1 -Link=1 -Priority=1000 -OverrideBuildCmd=0 -BuildCmd=$(CC) -c r_minigl.c -o ../../../objs/Mingw/r_minigl/r_minigl.o $(CFLAGS) - diff --git a/src/hardware/r_minigl/r_minigl.dsp b/src/hardware/r_minigl/r_minigl.dsp deleted file mode 100644 index 686ca35a3..000000000 --- a/src/hardware/r_minigl/r_minigl.dsp +++ /dev/null @@ -1,103 +0,0 @@ -# Microsoft Developer Studio Project File - Name="r_minigl" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=r_minigl - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "r_minigl.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "r_minigl.mak" CFG="r_minigl - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "r_minigl - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "r_minigl - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "r_minigl - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "..\..\..\objs\Release" -# PROP BASE Intermediate_Dir "..\..\..\objs\Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "..\..\..\bin\VC\Release\r_minigl" -# PROP Intermediate_Dir "..\..\..\objs\VC\Release\r_minigl" -# PROP Ignore_Export_Lib 1 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "R_MINIGL_EXPORTS" /YX /FD /c -# ADD CPP /nologo /G5 /MT /W3 /GX /Zi /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__" /FR /FD /c -# SUBTRACT CPP /YX -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x80c /d "NDEBUG" -# ADD RSC /l 0x40c /d "NDEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 -# ADD LINK32 user32.lib gdi32.lib /nologo /dll /pdb:"..\..\..\bin\VC\Release\r_minigl.pdb" /machine:I386 /out:"..\..\..\bin\VC\Release\r_minigl.dll" -# SUBTRACT LINK32 /pdb:none /debug - -!ELSEIF "$(CFG)" == "r_minigl - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "..\..\..\objs\Debug" -# PROP BASE Intermediate_Dir "..\..\..\objs\Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "..\..\..\bin\VC\Debug\r_minigl" -# PROP Intermediate_Dir "..\..\..\objs\VC\Debug\r_minigl" -# PROP Ignore_Export_Lib 1 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "R_MINIGL_EXPORTS" /YX /FD /GZ /c -# ADD CPP /nologo /MTd /W4 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "__WIN32__" /D "__MSC__" /D "_MBCS" /D "_USRDLL" /D "R_MINIGL_EXPORTS" /FR /FD /GZ /c -# SUBTRACT CPP /YX -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x80c /d "_DEBUG" -# ADD RSC /l 0x40c /d "_DEBUG" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept -# ADD LINK32 ouser32.lib gdi32.lib /nologo /dll /pdb:"..\..\..\bin\VC\Debug\r_minigl.pdb" /debug /machine:I386 /out:"..\..\..\bin\VC\Debug\r_minigl.dll" /pdbtype:sept -# SUBTRACT LINK32 /pdb:none - -!ENDIF - -# Begin Target - -# Name "r_minigl - Win32 Release" -# Name "r_minigl - Win32 Debug" -# Begin Source File - -SOURCE=.\r_minigl.c -# End Source File -# Begin Source File - -SOURCE=..\r_opengl\r_opengl.h -# End Source File -# End Target -# End Project diff --git a/src/hardware/r_opengl/ogl_win.c b/src/hardware/r_opengl/ogl_win.c index 562afe998..c9bf60144 100644 --- a/src/hardware/r_opengl/ogl_win.c +++ b/src/hardware/r_opengl/ogl_win.c @@ -206,7 +206,7 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth if (iLastPFD) { - DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n"); + GL_DBG_Printf("WARNING : SetPixelFormat() called twise not supported by all drivers !\n"); } // set the pixel format only if different than the current @@ -215,17 +215,17 @@ int SetupPixelFormat(INT32 WantColorBits, INT32 WantStencilBits, INT32 WantDepth else iLastPFD = iPFD; - DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n", + GL_DBG_Printf("SetupPixelFormat() - %d ColorBits - %d StencilBits - %d DepthBits\n", WantColorBits, WantStencilBits, WantDepthBits); nPixelFormat = ChoosePixelFormat(hDC, &pfd); if (nPixelFormat == 0) - DBG_Printf("ChoosePixelFormat() FAILED\n"); + GL_DBG_Printf("ChoosePixelFormat() FAILED\n"); if (SetPixelFormat(hDC, nPixelFormat, &pfd) == 0) { - DBG_Printf("SetPixelFormat() FAILED\n"); + GL_DBG_Printf("SetPixelFormat() FAILED\n"); return 0; } @@ -243,7 +243,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) BOOL WantFullScreen = !(lvid->u.windowed); //(lvid->u.windowed ? 0 : CDS_FULLSCREEN); UNREFERENCED_PARAMETER(pcurrentmode); - DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n", + GL_DBG_Printf ("SetMode(): %dx%d %d bits (%s)\n", lvid->width, lvid->height, lvid->bpp*8, WantFullScreen ? "fullscreen" : "windowed"); @@ -301,7 +301,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) hDC = GetDC(hWnd); if (!hDC) { - DBG_Printf("GetDC() FAILED\n"); + GL_DBG_Printf("GetDC() FAILED\n"); return 0; } @@ -321,12 +321,12 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) hGLRC = pwglCreateContext(hDC); if (!hGLRC) { - DBG_Printf("pwglCreateContext() FAILED\n"); + GL_DBG_Printf("pwglCreateContext() FAILED\n"); return 0; } if (!pwglMakeCurrent(hDC, hGLRC)) { - DBG_Printf("wglMakeCurrent() FAILED\n"); + GL_DBG_Printf("wglMakeCurrent() FAILED\n"); return 0; } } @@ -337,15 +337,15 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) //BP: why don't we make it earlier ? //Hurdler: we cannot do that before intialising gl context renderer = (LPCSTR)pglGetString(GL_RENDERER); - DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR)); - DBG_Printf("Renderer : %s\n", renderer); - DBG_Printf("Version : %s\n", pglGetString(GL_VERSION)); - DBG_Printf("Extensions : %s\n", gl_extensions); + GL_DBG_Printf("Vendor : %s\n", pglGetString(GL_VENDOR)); + GL_DBG_Printf("Renderer : %s\n", renderer); + GL_DBG_Printf("Version : %s\n", pglGetString(GL_VERSION)); + GL_DBG_Printf("Extensions : %s\n", gl_extensions); // BP: disable advenced feature that don't work on somes hardware // Hurdler: Now works on G400 with bios 1.6 and certified drivers 6.04 if (strstr(renderer, "810")) oglflags |= GLF_NOZBUFREAD; - DBG_Printf("oglflags : 0x%X\n", oglflags); + GL_DBG_Printf("oglflags : 0x%X\n", oglflags); #ifdef USE_WGL_SWAP if (isExtAvailable("WGL_EXT_swap_control",gl_extensions)) @@ -386,7 +386,7 @@ static INT32 WINAPI SetRes(viddef_t *lvid, vmode_t *pcurrentmode) // -----------------+ static void UnSetRes(void) { - DBG_Printf("UnSetRes()\n"); + GL_DBG_Printf("UnSetRes()\n"); pwglMakeCurrent(hDC, NULL); pwglDeleteContext(hGLRC); @@ -437,7 +437,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) video_modes[iMode].misc = 0; video_modes[iMode].name = malloc(12 * sizeof (CHAR)); sprintf(video_modes[iMode].name, "%dx%d", (INT32)Tmp.dmPelsWidth, (INT32)Tmp.dmPelsHeight); - DBG_Printf ("Mode: %s\n", video_modes[iMode].name); + GL_DBG_Printf ("Mode: %s\n", video_modes[iMode].name); video_modes[iMode].width = Tmp.dmPelsWidth; video_modes[iMode].height = Tmp.dmPelsHeight; video_modes[iMode].bytesperpixel = Tmp.dmBitsPerPel/8; @@ -474,7 +474,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) HDC bpphdc; INT32 iBitsPerPel; - DBG_Printf ("HWRAPI GetModeList()\n"); + GL_DBG_Printf ("HWRAPI GetModeList()\n"); bpphdc = GetDC(NULL); // on obtient le bpp actuel iBitsPerPel = GetDeviceCaps(bpphdc, BITSPIXEL); @@ -490,7 +490,7 @@ EXPORT void HWRAPI(GetModeList) (vmode_t** pvidmodes, INT32 *numvidmodes) video_modes[i].misc = 0; video_modes[i].name = malloc(12 * sizeof (CHAR)); sprintf(video_modes[i].name, "%dx%d", res[i][0], res[i][1]); - DBG_Printf ("Mode: %s\n", video_modes[i].name); + GL_DBG_Printf ("Mode: %s\n", video_modes[i].name); video_modes[i].width = res[i][0]; video_modes[i].height = res[i][1]; video_modes[i].bytesperpixel = iBitsPerPel/8; @@ -511,9 +511,9 @@ EXPORT void HWRAPI(Shutdown) (void) #ifdef DEBUG_TO_FILE long nb_centiemes; - DBG_Printf ("HWRAPI Shutdown()\n"); + GL_DBG_Printf ("HWRAPI Shutdown()\n"); nb_centiemes = ((clock()-my_clock)*100)/CLOCKS_PER_SEC; - DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n", + GL_DBG_Printf("Nb frames: %li; Nb sec: %2.2f -> %2.1f fps\n", nb_frames, nb_centiemes/100.0f, (100*nb_frames)/(double)nb_centiemes); #endif @@ -530,7 +530,7 @@ EXPORT void HWRAPI(Shutdown) (void) } FreeLibrary(GLU32); FreeLibrary(OGL32); - DBG_Printf ("HWRAPI Shutdown(DONE)\n"); + GL_DBG_Printf ("HWRAPI Shutdown(DONE)\n"); } // -----------------+ @@ -543,7 +543,7 @@ EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl) #else UNREFERENCED_PARAMETER(waitvbl); #endif - // DBG_Printf ("FinishUpdate()\n"); + // GL_DBG_Printf ("FinishUpdate()\n"); #ifdef DEBUG_TO_FILE if ((++nb_frames)==2) // on ne commence pas � la premi�re frame my_clock = clock(); @@ -564,20 +564,15 @@ EXPORT void HWRAPI(FinishUpdate) (INT32 waitvbl) // : in OpenGL, we store values for conversion of paletted graphics when // : they are downloaded to the 3D card. // -----------------+ -EXPORT void HWRAPI(SetPalette) (RGBA_t *pal, RGBA_t *gamma) +EXPORT void HWRAPI(SetPalette) (RGBA_t *pal) { - INT32 i; - - for (i = 0; i < 256; i++) - { - myPaletteData[i].s.red = (UINT8)MIN((pal[i].s.red*gamma->s.red)/127, 255); - myPaletteData[i].s.green = (UINT8)MIN((pal[i].s.green*gamma->s.green)/127, 255); - myPaletteData[i].s.blue = (UINT8)MIN((pal[i].s.blue*gamma->s.blue)/127, 255); - myPaletteData[i].s.alpha = pal[i].s.alpha; - } - + size_t palsize = (sizeof(RGBA_t) * 256); // on a palette change, you have to reload all of the textures - Flush(); + if (memcmp(&myPaletteData, pal, palsize)) + { + memcpy(&myPaletteData, pal, palsize); + Flush(); + } } #endif diff --git a/src/hardware/r_opengl/r_opengl.c b/src/hardware/r_opengl/r_opengl.c index eef723e51..942d3d3de 100644 --- a/src/hardware/r_opengl/r_opengl.c +++ b/src/hardware/r_opengl/r_opengl.c @@ -1,14 +1,12 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2019 by Sonic Team Junior. +// Copyright (C) 1998-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- -/// \file +/// \file r_opengl.c /// \brief OpenGL API for Sonic Robo Blast 2 #if defined (_WIN32) @@ -26,8 +24,6 @@ #include "r_opengl.h" #include "r_vbo.h" -#include "../../p_tick.h" // for leveltime (NOTE: THIS IS BAD, FIGURE OUT HOW TO PROPERLY IMPLEMENT gl_leveltime) - #if defined (HWRENDER) && !defined (NOROPENGL) struct GLRGBAFloat @@ -45,7 +41,7 @@ static const GLubyte white[4] = { 255, 255, 255, 255 }; // ========================================================================== // With OpenGL 1.1+, the first texture should be 1 -#define NOTEXTURE_NUM 0 +static GLuint NOTEXTURE_NUM = 0; #define N_PI_DEMI (M_PIl/2.0f) //(1.5707963268f) @@ -62,8 +58,8 @@ static GLuint tex_downloaded = 0; static GLfloat fov = 90.0f; static FBITFIELD CurrentPolyFlags; -static FTextureInfo* gr_cachetail = NULL; -static FTextureInfo* gr_cachehead = NULL; +static FTextureInfo *gl_cachetail = NULL; +static FTextureInfo *gl_cachehead = NULL; RGBA_t myPaletteData[256]; GLint screen_width = 0; // used by Draw2DLine() @@ -75,7 +71,7 @@ static GLboolean MipMap = GL_FALSE; static GLint min_filter = GL_LINEAR; static GLint mag_filter = GL_LINEAR; static GLint anisotropic_filter = 0; -static FTransform md2_transform; +static boolean model_lighting = false; const GLubyte *gl_version = NULL; const GLubyte *gl_renderer = NULL; @@ -84,22 +80,24 @@ const GLubyte *gl_extensions = NULL; //Hurdler: 04/10/2000: added for the kick ass coronas as Boris wanted;-) static GLfloat modelMatrix[16]; static GLfloat projMatrix[16]; -static GLint viewport[4]; - -#ifdef USE_PALETTED_TEXTURE - PFNGLCOLORTABLEEXTPROC glColorTableEXT = NULL; - GLubyte palette_tex[256*3]; -#endif +static GLint viewport[4]; // Sryder: NextTexAvail is broken for these because palette changes or changes to the texture filter or antialiasing // flush all of the stored textures, leaving them unavailable at times such as between levels -// These need to start at 0 and be set to their number, and be reset to 0 when deleted so that Intel GPUs +// These need to start at 0 and be set to their number, and be reset to 0 when deleted so that intel GPUs // can know when the textures aren't there, as textures are always considered resident in their virtual memory static GLuint screentexture = 0; static GLuint startScreenWipe = 0; static GLuint endScreenWipe = 0; static GLuint finalScreenTexture = 0; +// Lactozilla: Shader functions +static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade); +static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum); + +static GLRGBAFloat shader_defaultcolor = {1.0f, 1.0f, 1.0f, 1.0f}; + // shortcut for ((float)1/i) static const GLfloat byte2float[256] = { 0.000000f, 0.003922f, 0.007843f, 0.011765f, 0.015686f, 0.019608f, 0.023529f, 0.027451f, @@ -165,6 +163,56 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) #endif } +// -----------------+ +// GL_MSG_Warning : Raises a warning. +// : +// Returns : +// -----------------+ + +static void GL_MSG_Warning(const char *format, ...) +{ + char str[4096] = ""; + va_list arglist; + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + +#ifdef HAVE_SDL + CONS_Alert(CONS_WARNING, "%s", str); +#endif +#ifdef DEBUG_TO_FILE + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + fwrite(str, strlen(str), 1, gllogstream); +#endif +} + +// -----------------+ +// GL_MSG_Error : Raises an error. +// : +// Returns : +// -----------------+ + +static void GL_MSG_Error(const char *format, ...) +{ + char str[4096] = ""; + va_list arglist; + + va_start(arglist, format); + vsnprintf(str, 4096, format, arglist); + va_end(arglist); + +#ifdef HAVE_SDL + CONS_Alert(CONS_ERROR, "%s", str); +#endif +#ifdef DEBUG_TO_FILE + if (!gllogstream) + gllogstream = fopen("ogllog.txt", "w"); + fwrite(str, strlen(str), 1, gllogstream); +#endif +} + #ifdef STATIC_OPENGL /* 1.0 functions */ /* Miscellaneous */ @@ -179,6 +227,9 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) #define pglEnable glEnable #define pglDisable glDisable #define pglGetFloatv glGetFloatv +//glGetIntegerv +//glGetString +#define pglHint glHint /* Depth Buffer */ #define pglClearDepth glClearDepth @@ -192,7 +243,7 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) #define pglPushMatrix glPushMatrix #define pglPopMatrix glPopMatrix #define pglLoadIdentity glLoadIdentity -#define pglMultMatrixd glMultMatrixd +#define pglMultMatrixf glMultMatrixf #define pglRotatef glRotatef #define pglScalef glScalef #define pglTranslatef glTranslatef @@ -202,15 +253,11 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) #define pglVertexPointer glVertexPointer #define pglNormalPointer glNormalPointer #define pglTexCoordPointer glTexCoordPointer +#define pglColorPointer glColorPointer #define pglDrawArrays glDrawArrays #define pglDrawElements glDrawElements #define pglEnableClientState glEnableClientState #define pglDisableClientState glDisableClientState -#define pglClientActiveTexture glClientActiveTexture -#define pglGenBuffers glGenBuffers -#define pglBindBuffer glBindBuffer -#define pglBufferData glBufferData -#define pglDeleteBuffers glDeleteBuffers /* Lighting */ #define pglShadeModel glShadeModel @@ -227,10 +274,7 @@ FUNCPRINTF void GL_DBG_Printf(const char *format, ...) #define pglTexEnvi glTexEnvi #define pglTexParameteri glTexParameteri #define pglTexImage2D glTexImage2D - -/* Fog */ -#define pglFogf glFogf -#define pglFogfv glFogfv +#define pglTexSubImage2D glTexSubImage2D /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -305,6 +349,8 @@ typedef void (APIENTRY * PFNglNormalPointer) (GLenum type, GLsizei stride, const static PFNglNormalPointer pglNormalPointer; typedef void (APIENTRY * PFNglTexCoordPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); static PFNglTexCoordPointer pglTexCoordPointer; +typedef void (APIENTRY * PFNglColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); +static PFNglColorPointer pglColorPointer; typedef void (APIENTRY * PFNglDrawArrays) (GLenum mode, GLint first, GLsizei count); static PFNglDrawArrays pglDrawArrays; typedef void (APIENTRY * PFNglDrawElements) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices); @@ -313,14 +359,6 @@ typedef void (APIENTRY * PFNglEnableClientState) (GLenum cap); static PFNglEnableClientState pglEnableClientState; typedef void (APIENTRY * PFNglDisableClientState) (GLenum cap); static PFNglDisableClientState pglDisableClientState; -typedef void (APIENTRY * PFNglGenBuffers) (GLsizei n, GLuint *buffers); -static PFNglGenBuffers pglGenBuffers; -typedef void (APIENTRY * PFNglBindBuffer) (GLenum target, GLuint buffer); -static PFNglBindBuffer pglBindBuffer; -typedef void (APIENTRY * PFNglBufferData) (GLenum target, GLsizei size, const GLvoid *data, GLenum usage); -static PFNglBufferData pglBufferData; -typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); -static PFNglDeleteBuffers pglDeleteBuffers; /* Lighting */ typedef void (APIENTRY * PFNglShadeModel) (GLenum mode); @@ -347,12 +385,8 @@ typedef void (APIENTRY * PFNglTexParameteri) (GLenum target, GLenum pname, GLint static PFNglTexParameteri pglTexParameteri; typedef void (APIENTRY * PFNglTexImage2D) (GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); static PFNglTexImage2D pglTexImage2D; - -/* Fog */ -typedef void (APIENTRY * PFNglFogf) (GLenum pname, GLfloat param); -static PFNglFogf pglFogf; -typedef void (APIENTRY * PFNglFogfv) (GLenum pname, const GLfloat *params); -static PFNglFogfv pglFogfv; +typedef void (APIENTRY * PFNglTexSubImage2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels); +static PFNglTexSubImage2D pglTexSubImage2D; /* 1.1 functions */ /* texture objects */ //GL_EXT_texture_object @@ -382,9 +416,16 @@ static PFNglMultiTexCoord2fv pglMultiTexCoord2fv; typedef void (APIENTRY *PFNglClientActiveTexture) (GLenum); static PFNglClientActiveTexture pglClientActiveTexture; -// sky dome needs this -typedef void (APIENTRY *PFNglColorPointer) (GLint, GLenum, GLsizei, const GLvoid*); -static PFNglColorPointer pglColorPointer; +/* 1.5 functions for buffers */ +typedef void (APIENTRY * PFNglGenBuffers) (GLsizei n, GLuint *buffers); +static PFNglGenBuffers pglGenBuffers; +typedef void (APIENTRY * PFNglBindBuffer) (GLenum target, GLuint buffer); +static PFNglBindBuffer pglBindBuffer; +typedef void (APIENTRY * PFNglBufferData) (GLenum target, GLsizei size, const GLvoid *data, GLenum usage); +static PFNglBufferData pglBufferData; +typedef void (APIENTRY * PFNglDeleteBuffers) (GLsizei n, const GLuint *buffers); +static PFNglDeleteBuffers pglDeleteBuffers; + /* 1.2 Parms */ /* GL_CLAMP_TO_EDGE_EXT */ @@ -406,6 +447,14 @@ static PFNglColorPointer pglColorPointer; #define GL_TEXTURE1 0x84C1 #endif +/* 1.5 Parms */ +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#endif +#ifndef GL_STATIC_DRAW +#define GL_STATIC_DRAW 0x88E4 +#endif + boolean SetupGLfunc(void) { #ifndef STATIC_OPENGL @@ -413,7 +462,7 @@ boolean SetupGLfunc(void) func = GetGLFunc(#proc); \ if (!func) \ { \ - GL_DBG_Printf("failed to get OpenGL function: %s\n", #proc); \ + GL_MSG_Warning("failed to get OpenGL function: %s", #proc); \ } \ GETOPENGLFUNC(pglClearColor, glClearColor) @@ -451,6 +500,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglVertexPointer, glVertexPointer) GETOPENGLFUNC(pglNormalPointer, glNormalPointer) GETOPENGLFUNC(pglTexCoordPointer, glTexCoordPointer) + GETOPENGLFUNC(pglColorPointer, glColorPointer) GETOPENGLFUNC(pglDrawArrays, glDrawArrays) GETOPENGLFUNC(pglDrawElements, glDrawElements) GETOPENGLFUNC(pglEnableClientState, glEnableClientState) @@ -468,9 +518,7 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglTexEnvi, glTexEnvi) GETOPENGLFUNC(pglTexParameteri, glTexParameteri) GETOPENGLFUNC(pglTexImage2D, glTexImage2D) - - GETOPENGLFUNC(pglFogf, glFogf) - GETOPENGLFUNC(pglFogfv, glFogfv) + GETOPENGLFUNC(pglTexSubImage2D, glTexSubImage2D) GETOPENGLFUNC(pglGenTextures, glGenTextures) GETOPENGLFUNC(pglDeleteTextures, glDeleteTextures) @@ -480,10 +528,14 @@ boolean SetupGLfunc(void) GETOPENGLFUNC(pglCopyTexSubImage2D, glCopyTexSubImage2D) #undef GETOPENGLFUNC + #endif return true; } +static boolean gl_allowshaders = false; +static boolean gl_shadersenabled = false; + #ifdef GL_SHADERS typedef GLuint (APIENTRY *PFNglCreateShader) (GLenum); typedef void (APIENTRY *PFNglShaderSource) (GLuint, GLsizei, const GLchar**, GLint*); @@ -527,19 +579,11 @@ static PFNglUniform2fv pglUniform2fv; static PFNglUniform3fv pglUniform3fv; static PFNglGetUniformLocation pglGetUniformLocation; -#define MAXSHADERS 16 -#define MAXSHADERPROGRAMS 16 - // 18032019 -static char *gl_customvertexshaders[MAXSHADERS]; -static char *gl_customfragmentshaders[MAXSHADERS]; - -static boolean gl_allowshaders = false; -static boolean gl_shadersenabled = false; static GLuint gl_currentshaderprogram = 0; static boolean gl_shaderprogramchanged = true; -static boolean gl_batching = false;// are we currently collecting batches? +static shadersource_t gl_customshaders[HWR_MAXSHADERS]; // 13062019 typedef enum @@ -564,14 +608,59 @@ typedef struct gl_shaderprogram_s boolean custom; GLint uniforms[gluniform_max+1]; } gl_shaderprogram_t; -static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; +static gl_shaderprogram_t gl_shaderprograms[HWR_MAXSHADERS]; -// ======================== -// Fragment shader macros -// ======================== +// Shader info +static INT32 shader_leveltime = 0; + +// ================ +// Vertex shaders +// ================ // -// GLSL Software fragment shader +// Generic vertex shader +// + +#define GLSL_DEFAULT_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = gl_Color;\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// replicates the way fixed function lighting is used by the model lighting option, +// stores the lighting result to gl_Color +// (ambient lighting of 0.75 and diffuse lighting from above) +#define GLSL_MODEL_LIGHTING_VERTEX_SHADER \ + "void main()\n" \ + "{\n" \ + "float nDotVP = dot(gl_Normal, vec3(0, 1, 0));\n" \ + "float light = 0.75 + max(nDotVP, 0.0);\n" \ + "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ + "gl_FrontColor = vec4(light, light, light, 1.0);\n" \ + "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ + "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ + "}\0" + +// ================== +// Fragment shaders +// ================== + +// +// Generic fragment shader +// + +#define GLSL_DEFAULT_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "void main(void) {\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "}\0" + +// +// Software fragment shader // #define GLSL_DOOM_COLORMAP \ @@ -631,6 +720,29 @@ static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; "gl_FragColor = final_color;\n" \ "}\0" +// same as above but multiplies results with the lighting value from the +// accompanying vertex shader (stored in gl_Color) +#define GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER \ + "uniform sampler2D tex;\n" \ + "uniform vec4 poly_color;\n" \ + "uniform vec4 tint_color;\n" \ + "uniform vec4 fade_color;\n" \ + "uniform float lighting;\n" \ + "uniform float fade_start;\n" \ + "uniform float fade_end;\n" \ + GLSL_DOOM_COLORMAP \ + GLSL_DOOM_LIGHT_EQUATION \ + "void main(void) {\n" \ + "vec4 texel = texture2D(tex, gl_TexCoord[0].st);\n" \ + "vec4 base_color = texel * poly_color;\n" \ + "vec4 final_color = base_color;\n" \ + GLSL_SOFTWARE_TINT_EQUATION \ + GLSL_SOFTWARE_FADE_EQUATION \ + "final_color *= gl_Color;\n" \ + "final_color.a = texel.a * poly_color.a;\n" \ + "gl_FragColor = final_color;\n" \ + "}\0" + // // Water surface shader // @@ -690,90 +802,52 @@ static gl_shaderprogram_t gl_shaderprograms[MAXSHADERPROGRAMS]; "}\0" // -// GLSL generic fragment shader +// Sky fragment shader +// Modulates poly_color with gl_Color // - -#define GLSL_DEFAULT_FRAGMENT_SHADER \ +#define GLSL_SKY_FRAGMENT_SHADER \ "uniform sampler2D tex;\n" \ "uniform vec4 poly_color;\n" \ "void main(void) {\n" \ - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * poly_color;\n" \ + "gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color * poly_color;\n" \ "}\0" -static const char *fragment_shaders[] = { - // Default fragment shader - GLSL_DEFAULT_FRAGMENT_SHADER, +// ================ +// Shader sources +// ================ - // Floor fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, +static struct { + const char *vertex; + const char *fragment; +} const gl_shadersources[] = { + // Default shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_DEFAULT_FRAGMENT_SHADER}, - // Wall fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + // Floor shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - // Sprite fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + // Wall shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - // Model fragment shader - GLSL_SOFTWARE_FRAGMENT_SHADER, + // Sprite shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - // Water fragment shader - GLSL_WATER_FRAGMENT_SHADER, + // Model shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SOFTWARE_FRAGMENT_SHADER}, - // Fog fragment shader - GLSL_FOG_FRAGMENT_SHADER, + // Model shader + diffuse lighting from above + {GLSL_MODEL_LIGHTING_VERTEX_SHADER, GLSL_SOFTWARE_MODEL_LIGHTING_FRAGMENT_SHADER}, - // Sky fragment shader - "uniform sampler2D tex;\n" - "void main(void) {\n" - "gl_FragColor = texture2D(tex, gl_TexCoord[0].st);\n" - "}\0", + // Water shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_WATER_FRAGMENT_SHADER}, - NULL, -}; + // Fog shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_FOG_FRAGMENT_SHADER}, -// ====================== -// Vertex shader macros -// ====================== + // Sky shader + {GLSL_DEFAULT_VERTEX_SHADER, GLSL_SKY_FRAGMENT_SHADER}, -// -// GLSL generic vertex shader -// - -#define GLSL_DEFAULT_VERTEX_SHADER \ - "void main()\n" \ - "{\n" \ - "gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;\n" \ - "gl_FrontColor = gl_Color;\n" \ - "gl_TexCoord[0].xy = gl_MultiTexCoord0.xy;\n" \ - "gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;\n" \ - "}\0" - -static const char *vertex_shaders[] = { - // Default vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Floor vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Wall vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Sprite vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Model vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Water vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Fog vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - // Sky vertex shader - GLSL_DEFAULT_VERTEX_SHADER, - - NULL, + {NULL, NULL}, }; #endif // GL_SHADERS @@ -784,11 +858,12 @@ void SetupGLFunc4(void) pglMultiTexCoord2f = GetGLFunc("glMultiTexCoord2f"); pglClientActiveTexture = GetGLFunc("glClientActiveTexture"); pglMultiTexCoord2fv = GetGLFunc("glMultiTexCoord2fv"); + + /* 1.5 funcs */ pglGenBuffers = GetGLFunc("glGenBuffers"); pglBindBuffer = GetGLFunc("glBindBuffer"); pglBufferData = GetGLFunc("glBufferData"); pglDeleteBuffers = GetGLFunc("glDeleteBuffers"); - pglColorPointer = GetGLFunc("glColorPointer"); #ifdef GL_SHADERS pglCreateShader = GetGLFunc("glCreateShader"); @@ -818,7 +893,7 @@ void SetupGLFunc4(void) } // jimita -EXPORT boolean HWRAPI(LoadShaders) (void) +EXPORT boolean HWRAPI(CompileShaders) (void) { #ifdef GL_SHADERS GLuint gl_vertShader, gl_fragShader; @@ -826,33 +901,38 @@ EXPORT boolean HWRAPI(LoadShaders) (void) if (!pglUseProgram) return false; - gl_customvertexshaders[0] = NULL; - gl_customfragmentshaders[0] = NULL; + gl_customshaders[0].vertex = NULL; + gl_customshaders[0].fragment = NULL; - for (i = 0; vertex_shaders[i] && fragment_shaders[i]; i++) + for (i = 0; gl_shadersources[i].vertex && gl_shadersources[i].fragment; i++) { gl_shaderprogram_t *shader; - const GLchar* vert_shader = vertex_shaders[i]; - const GLchar* frag_shader = fragment_shaders[i]; - boolean custom = ((gl_customvertexshaders[i] || gl_customfragmentshaders[i]) && (i > 0)); + const GLchar *vert_shader = gl_shadersources[i].vertex; + const GLchar *frag_shader = gl_shadersources[i].fragment; + boolean custom = ((gl_customshaders[i].vertex || gl_customshaders[i].fragment) && (i > 0)); // 18032019 - if (gl_customvertexshaders[i]) - vert_shader = gl_customvertexshaders[i]; - if (gl_customfragmentshaders[i]) - frag_shader = gl_customfragmentshaders[i]; + if (gl_customshaders[i].vertex) + vert_shader = gl_customshaders[i].vertex; + if (gl_customshaders[i].fragment) + frag_shader = gl_customshaders[i].fragment; - if (i >= MAXSHADERS) - break; - if (i >= MAXSHADERPROGRAMS) + if (i >= HWR_MAXSHADERS) break; + shader = &gl_shaderprograms[i]; + shader->program = 0; + shader->custom = custom; + // // Load and compile vertex shader // gl_vertShader = pglCreateShader(GL_VERTEX_SHADER); if (!gl_vertShader) - I_Error("Hardware driver: Error creating vertex shader %d", i); + { + GL_MSG_Error("CompileShaders: Error creating vertex shader %s\n", HWR_GetShaderName(i)); + continue; + } pglShaderSource(gl_vertShader, 1, &vert_shader, NULL); pglCompileShader(gl_vertShader); @@ -861,15 +941,8 @@ EXPORT boolean HWRAPI(LoadShaders) (void) pglGetShaderiv(gl_vertShader, GL_COMPILE_STATUS, &result); if (result == GL_FALSE) { - GLchar* infoLog; - GLint logLength; - - pglGetShaderiv(gl_vertShader, GL_INFO_LOG_LENGTH, &logLength); - - infoLog = malloc(logLength); - pglGetShaderInfoLog(gl_vertShader, logLength, NULL, infoLog); - - I_Error("Hardware driver: Error compiling vertex shader %d\n%s", i, infoLog); + Shader_CompileError("Error compiling vertex shader", gl_vertShader, i); + continue; } // @@ -877,7 +950,10 @@ EXPORT boolean HWRAPI(LoadShaders) (void) // gl_fragShader = pglCreateShader(GL_FRAGMENT_SHADER); if (!gl_fragShader) - I_Error("Hardware driver: Error creating fragment shader %d", i); + { + GL_MSG_Error("CompileShaders: Error creating fragment shader %s\n", HWR_GetShaderName(i)); + continue; + } pglShaderSource(gl_fragShader, 1, &frag_shader, NULL); pglCompileShader(gl_fragShader); @@ -886,33 +962,31 @@ EXPORT boolean HWRAPI(LoadShaders) (void) pglGetShaderiv(gl_fragShader, GL_COMPILE_STATUS, &result); if (result == GL_FALSE) { - GLchar* infoLog; - GLint logLength; - - pglGetShaderiv(gl_fragShader, GL_INFO_LOG_LENGTH, &logLength); - - infoLog = malloc(logLength); - pglGetShaderInfoLog(gl_fragShader, logLength, NULL, infoLog); - - I_Error("Hardware driver: Error compiling fragment shader %d\n%s", i, infoLog); + Shader_CompileError("Error compiling fragment shader", gl_fragShader, i); + continue; } - shader = &gl_shaderprograms[i]; shader->program = pglCreateProgram(); - shader->custom = custom; pglAttachShader(shader->program, gl_vertShader); pglAttachShader(shader->program, gl_fragShader); pglLinkProgram(shader->program); // check link status pglGetProgramiv(shader->program, GL_LINK_STATUS, &result); - if (result != GL_TRUE) - I_Error("Hardware driver: Error linking shader program %d", i); // delete the shader objects pglDeleteShader(gl_vertShader); pglDeleteShader(gl_fragShader); + // couldn't link? + if (result != GL_TRUE) + { + shader->program = 0; + shader->custom = false; + GL_MSG_Error("CompileShaders: Error linking shader program %s\n", HWR_GetShaderName(i)); + continue; + } + // 13062019 #define GETUNI(uniform) pglGetUniformLocation(shader->program, uniform); @@ -929,40 +1003,70 @@ EXPORT boolean HWRAPI(LoadShaders) (void) #undef GETUNI } -#endif return true; +#else + return false; +#endif +} + +// +// Shader info +// Those are given to the uniforms. +// + +EXPORT void HWRAPI(SetShaderInfo) (hwdshaderinfo_t info, INT32 value) +{ +#ifdef GL_SHADERS + switch (info) + { + case HWD_SHADERINFO_LEVELTIME: + shader_leveltime = value; + break; + default: + break; + } +#else + (void)info; + (void)value; +#endif } // // Custom shader loading // -EXPORT void HWRAPI(LoadCustomShader) (int number, char *shader, size_t size, boolean fragment) +EXPORT void HWRAPI(LoadCustomShader) (int number, char *code, size_t size, boolean isfragment) { #ifdef GL_SHADERS - if (!pglUseProgram) return; - if (number < 1 || number > MAXSHADERS) - I_Error("LoadCustomShader(): cannot load shader %d (max %d)", number, MAXSHADERS); + shadersource_t *shader; - if (fragment) - { - gl_customfragmentshaders[number] = malloc(size+1); - strncpy(gl_customfragmentshaders[number], shader, size); - gl_customfragmentshaders[number][size] = 0; + if (!pglUseProgram) + return; + + if (number < 1 || number > HWR_MAXSHADERS) + I_Error("LoadCustomShader: cannot load shader %d (min 1, max %d)", number, HWR_MAXSHADERS); + else if (code == NULL) + I_Error("LoadCustomShader: empty shader"); + + shader = &gl_customshaders[number]; + +#define COPYSHADER(source) { \ + if (shader->source) \ + free(shader->source); \ + shader->source = malloc(size+1); \ + strncpy(shader->source, code, size); \ + shader->source[size] = 0; \ } + + if (isfragment) + COPYSHADER(fragment) else - { - gl_customvertexshaders[number] = malloc(size+1); - strncpy(gl_customvertexshaders[number], shader, size); - gl_customvertexshaders[number][size] = 0; - } -#endif -} + COPYSHADER(vertex) -EXPORT void HWRAPI(InitCustomShaders) (void) -{ -#ifdef GL_SHADERS - KillShaders(); - LoadShaders(); +#else + (void)number; + (void)shader; + (void)size; + (void)fragment; #endif } @@ -971,16 +1075,23 @@ EXPORT void HWRAPI(SetShader) (int shader) #ifdef GL_SHADERS if (gl_allowshaders) { - gl_shadersenabled = true; + // If using model lighting, set the appropriate shader. + // However don't override a custom shader. + if (shader == SHADER_MODEL && model_lighting + && !(gl_shaderprograms[SHADER_MODEL].custom && !gl_shaderprograms[SHADER_MODEL_LIGHTING].custom)) + shader = SHADER_MODEL_LIGHTING; if ((GLuint)shader != gl_currentshaderprogram) { gl_currentshaderprogram = shader; gl_shaderprogramchanged = true; } + gl_shadersenabled = true; + return; } - else +#else + (void)shader; #endif - gl_shadersenabled = false; + gl_shadersenabled = false; } EXPORT void HWRAPI(UnSetShader) (void) @@ -988,15 +1099,28 @@ EXPORT void HWRAPI(UnSetShader) (void) #ifdef GL_SHADERS gl_shadersenabled = false; gl_currentshaderprogram = 0; - gl_shaderprogramchanged = true;// not sure if this is needed if (!pglUseProgram) return; pglUseProgram(0); #endif } -EXPORT void HWRAPI(KillShaders) (void) +EXPORT void HWRAPI(CleanShaders) (void) { - // unused......................... + INT32 i; + + for (i = 1; i < HWR_MAXSHADERS; i++) + { + shadersource_t *shader = &gl_customshaders[i]; + + if (shader->vertex) + free(shader->vertex); + + if (shader->fragment) + free(shader->fragment); + + shader->vertex = NULL; + shader->fragment = NULL; + } } // -----------------+ @@ -1005,8 +1129,10 @@ EXPORT void HWRAPI(KillShaders) (void) static void SetNoTexture(void) { // Disable texture. - if (tex_downloaded != NOTEXTURE_NUM && !gl_batching) + if (tex_downloaded != NOTEXTURE_NUM) { + if (NOTEXTURE_NUM == 0) + pglGenTextures(1, &NOTEXTURE_NUM); pglBindTexture(GL_TEXTURE_2D, NOTEXTURE_NUM); tex_downloaded = NOTEXTURE_NUM; } @@ -1038,15 +1164,56 @@ static void GLPerspective(GLfloat fovy, GLfloat aspect) m[1][1] = cotangent; m[2][2] = -(zFar + zNear) / deltaZ; m[3][2] = -2.0f * zNear * zFar / deltaZ; + pglMultMatrixf(&m[0][0]); } +static void GLProject(GLfloat objX, GLfloat objY, GLfloat objZ, + GLfloat* winX, GLfloat* winY, GLfloat* winZ) +{ + GLfloat in[4], out[4]; + int i; + + for (i=0; i<4; i++) + { + out[i] = + objX * modelMatrix[0*4+i] + + objY * modelMatrix[1*4+i] + + objZ * modelMatrix[2*4+i] + + modelMatrix[3*4+i]; + } + for (i=0; i<4; i++) + { + in[i] = + out[0] * projMatrix[0*4+i] + + out[1] * projMatrix[1*4+i] + + out[2] * projMatrix[2*4+i] + + out[3] * projMatrix[3*4+i]; + } + if (fpclassify(in[3]) == FP_ZERO) return; + in[0] /= in[3]; + in[1] /= in[3]; + in[2] /= in[3]; + /* Map x, y and z to range 0-1 */ + in[0] = in[0] * 0.5f + 0.5f; + in[1] = in[1] * 0.5f + 0.5f; + in[2] = in[2] * 0.5f + 0.5f; + + /* Map x,y to viewport */ + in[0] = in[0] * viewport[2] + viewport[0]; + in[1] = in[1] * viewport[3] + viewport[1]; + + *winX=in[0]; + *winY=in[1]; + *winZ=in[2]; +} + // -----------------+ // SetModelView : // -----------------+ void SetModelView(GLint w, GLint h) { - //GL_DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); +// GL_DBG_Printf("SetModelView(): %dx%d\n", (int)w, (int)h); // The screen textures need to be flushed if the width or height change so that they be remade for the correct size if (screen_width != w || screen_height != h) @@ -1056,9 +1223,6 @@ void SetModelView(GLint w, GLint h) screen_height = h; pglViewport(0, 0, w, h); -#ifdef GL_ACCUM_BUFFER_BIT - pglClear(GL_ACCUM_BUFFER_BIT); -#endif pglMatrixMode(GL_PROJECTION); pglLoadIdentity(); @@ -1067,25 +1231,42 @@ void SetModelView(GLint w, GLint h) pglLoadIdentity(); GLPerspective(fov, ASPECT_RATIO); + //pglScalef(1.0f, 320.0f/200.0f, 1.0f); // gl_scalefrustum (ORIGINAL_ASPECT) // added for new coronas' code (without depth buffer) pglGetIntegerv(GL_VIEWPORT, viewport); pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); } + // -----------------+ // SetStates : Set permanent states // -----------------+ void SetStates(void) { +#ifdef GL_LIGHT_MODEL_AMBIENT + GLfloat LightDiffuse[] = {1.0f, 1.0f, 1.0f, 1.0f}; +#endif + +// GL_DBG_Printf("SetStates()\n"); + + // Hurdler: not necessary, is it? + pglShadeModel(GL_SMOOTH); // iterate vertice colors + //pglShadeModel(GL_FLAT); + pglEnable(GL_TEXTURE_2D); // two-dimensional texturing + pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); pglAlphaFunc(GL_NOTEQUAL, 0.0f); + + //pglBlendFunc(GL_ONE, GL_ZERO); // copy pixel to frame buffer (opaque) pglEnable(GL_BLEND); // enable color blending pglColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + //pglDisable(GL_DITHER); // faB: ??? (undocumented in OpenGL 1.1) + // Hurdler: yes, it is! pglEnable(GL_DEPTH_TEST); // check the depth buffer pglDepthMask(GL_TRUE); // enable writing to depth buffer pglClearDepth(1.0f); @@ -1096,35 +1277,45 @@ void SetStates(void) CurrentPolyFlags = 0xffffffff; SetBlend(0); - //tex_downloaded = (GLuint)-1; + tex_downloaded = 0; SetNoTexture(); pglPolygonOffset(-1.0f, -1.0f); + //pglEnable(GL_CULL_FACE); + //pglCullFace(GL_FRONT); + + pglDisable(GL_FOG); + + // Lighting for models +#ifdef GL_LIGHT_MODEL_AMBIENT + pglLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightDiffuse); + pglEnable(GL_LIGHT0); +#endif + // bp : when no t&l :) pglLoadIdentity(); pglScalef(1.0f, 1.0f, -1.0f); pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) } + // -----------------+ // Flush : flush OpenGL textures // : Clear list of downloaded mipmaps // -----------------+ void Flush(void) { - //GL_DBG_Printf("HWR_Flush()\n"); + //GL_DBG_Printf ("HWR_Flush()\n"); - while (gr_cachehead) + while (gl_cachehead) { - // ceci n'est pas du tout necessaire vu que tu les a charger normalement et - // donc il sont dans ta liste ! - if (gr_cachehead->downloaded) - pglDeleteTextures(1, (GLuint *)&gr_cachehead->downloaded); - gr_cachehead->downloaded = 0; - gr_cachehead = gr_cachehead->nextmipmap; + if (gl_cachehead->downloaded) + pglDeleteTextures(1, (GLuint *)&gl_cachehead->downloaded); + gl_cachehead->downloaded = 0; + gl_cachehead = gl_cachehead->nextmipmap; } - gr_cachetail = gr_cachehead = NULL; //Hurdler: well, gr_cachehead is already NULL + gl_cachetail = gl_cachehead = NULL; //Hurdler: well, gl_cachehead is already NULL tex_downloaded = 0; } @@ -1173,6 +1364,7 @@ EXPORT boolean HWRAPI(Init) (void) // -----------------+ EXPORT void HWRAPI(ClearMipMapCache) (void) { + // GL_DBG_Printf ("HWR_Flush(exe)\n"); Flush(); } @@ -1186,7 +1378,7 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 * dst_data) { INT32 i; - //GL_DBG_Printf("ReadRect()\n"); + // GL_DBG_Printf ("ReadRect()\n"); if (dst_stride == width*3) { GLubyte*top = (GLvoid*)dst_data, *bottom = top + dst_stride * (height - 1); @@ -1234,7 +1426,7 @@ EXPORT void HWRAPI(ReadRect) (INT32 x, INT32 y, INT32 width, INT32 height, // -----------------+ EXPORT void HWRAPI(GClipRect) (INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip) { - //GL_DBG_Printf("GClipRect(%d, %d, %d, %d)\n", minx, miny, maxx, maxy); + // GL_DBG_Printf ("GClipRect(%d, %d, %d, %d)\n", minx, miny, maxx, maxy); pglViewport(minx, screen_height-maxy, maxx-minx, maxy-miny); NEAR_CLIPPING_PLANE = nearclip; @@ -1258,7 +1450,7 @@ EXPORT void HWRAPI(ClearBuffer) (FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat * ClearColor) { - //GL_DBG_Printf("ClearBuffer(%d)\n", alpha); + // GL_DBG_Printf ("ClearBuffer(%d)\n", alpha); GLbitfield ClearMask = 0; if (ColorMask) @@ -1293,7 +1485,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, F2DCoord * v2, RGBA_t Color) { - //GL_DBG_Printf("DrawLine(): %f %f, %f %f\n", v1->x, v1->y, v2->x, v2->y); + // GL_DBG_Printf ("DrawLine() (%f %f %f) %d\n", v1->x, -v1->y, -v1->z, v1->argb); GLfloat p[12]; GLfloat dx, dy; GLfloat angle; @@ -1328,9 +1520,7 @@ EXPORT void HWRAPI(Draw2DLine) (F2DCoord * v1, static void Clamp2D(GLenum pname) { pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP); // fallback clamp -#ifdef GL_CLAMP_TO_EDGE pglTexParameteri(GL_TEXTURE_2D, pname, GL_CLAMP_TO_EDGE); -#endif } @@ -1376,7 +1566,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) // Sryder: Fog // multiplies input colour by input alpha, and destination colour by input colour, then adds them pglBlendFunc(GL_SRC_ALPHA, GL_SRC_COLOR); - pglAlphaFunc(GL_NOTEQUAL, 0.0f); + pglAlphaFunc(GL_ALWAYS, 0.0f); // Don't discard zero alpha fragments break; default : // must be 0, otherwise it's an error // No blending @@ -1400,6 +1590,7 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) else pglDisable(GL_POLYGON_OFFSET_FILL); } + if (Xor&PF_NoDepthTest) { if (PolyFlags & PF_NoDepthTest) @@ -1436,19 +1627,22 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) } else #endif - - // mix texture colour with Surface->PolyColor if (PolyFlags & PF_Modulated) + { // mix texture colour with Surface->PolyColor pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - // colour from texture is unchanged before blending + } else + { // colour from texture is unchanged before blending pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + } } if (Xor & PF_Occlude) // depth test but (no) depth write { if (PolyFlags&PF_Occlude) + { pglDepthMask(1); + } else pglDepthMask(0); } @@ -1466,11 +1660,214 @@ EXPORT void HWRAPI(SetBlend) (FBITFIELD PolyFlags) } } if (PolyFlags & PF_NoTexture) + { SetNoTexture(); + } } CurrentPolyFlags = PolyFlags; } +// -----------------+ +// UpdateTexture : Updates the texture data. +// -----------------+ +EXPORT void HWRAPI(UpdateTexture) (FTextureInfo *pTexInfo) +{ + // Download a mipmap + boolean updatemipmap = true; + static RGBA_t tex[2048*2048]; + const GLvoid *ptex = tex; + INT32 w, h; + GLuint texnum = 0; + + if (!pTexInfo->downloaded) + { + pglGenTextures(1, &texnum); + pTexInfo->downloaded = texnum; + updatemipmap = false; + } + else + texnum = pTexInfo->downloaded; + + //GL_DBG_Printf ("DownloadMipmap %d %x\n",(INT32)texnum,pTexInfo->data); + + w = pTexInfo->width; + h = pTexInfo->height; + + if ((pTexInfo->format == GL_TEXFMT_P_8) || + (pTexInfo->format == GL_TEXFMT_AP_88)) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && + (pTexInfo->flags & TF_CHROMAKEYED)) + { + tex[w*j+i].s.red = 0; + tex[w*j+i].s.green = 0; + tex[w*j+i].s.blue = 0; + tex[w*j+i].s.alpha = 0; + pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it + } + else + { + tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; + tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; + tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; + tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; + } + + pImgData++; + + if (pTexInfo->format == GL_TEXFMT_AP_88) + { + if (!(pTexInfo->flags & TF_CHROMAKEYED)) + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + + } + } + } + else if (pTexInfo->format == GL_TEXFMT_RGBA) + { + // corona test : passed as ARGB 8888, which is not in glide formats + // Hurdler: not used for coronas anymore, just for dynamic lighting + ptex = pTexInfo->data; + } + else if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88) + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = *pImgData; + tex[w*j+i].s.green = *pImgData; + tex[w*j+i].s.blue = *pImgData; + pImgData++; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } + else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) // Used for fade masks + { + const GLubyte *pImgData = (const GLubyte *)pTexInfo->data; + INT32 i, j; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't + tex[w*j+i].s.green = 255; + tex[w*j+i].s.blue = 255; + tex[w*j+i].s.alpha = *pImgData; + pImgData++; + } + } + } + else + GL_MSG_Warning ("SetTexture(bad format) %ld\n", pTexInfo->format); + + // the texture number was already generated by pglGenTextures + pglBindTexture(GL_TEXTURE_2D, texnum); + tex_downloaded = texnum; + + // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues + if (pTexInfo->flags & TF_TRANSPARENT) + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + } + else + { + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); + } + + if (pTexInfo->format == GL_TEXFMT_ALPHA_INTENSITY_88) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + else if (pTexInfo->format == GL_TEXFMT_ALPHA_8) + { + //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); + //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + else + { + if (MipMap) + { + pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + // Control the mipmap level of detail + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail + if (pTexInfo->flags & TF_TRANSPARENT) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff + else + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); + } + else + { + if (updatemipmap) + pglTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + else + pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); + } + } + + if (pTexInfo->flags & TF_WRAPX) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_S); + + if (pTexInfo->flags & TF_WRAPY) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + else + Clamp2D(GL_TEXTURE_WRAP_T); + + if (maximumAnisotropy) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); +} // -----------------+ // SetTexture : The mipmap becomes the current texture source @@ -1486,232 +1883,25 @@ EXPORT void HWRAPI(SetTexture) (FTextureInfo *pTexInfo) { if (pTexInfo->downloaded != tex_downloaded) { - if (!gl_batching) - pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); + pglBindTexture(GL_TEXTURE_2D, pTexInfo->downloaded); tex_downloaded = pTexInfo->downloaded; } } else { - // Download a mipmap - static RGBA_t tex[2048*2048]; - const GLvoid *ptex = tex; - INT32 w, h; - GLuint texnum = 0; - - pglGenTextures(1, &texnum); - //GL_DBG_Printf("DownloadMipmap %d\n", (INT32)texnum, pTexInfo->grInfo.data); - - w = pTexInfo->width; - h = pTexInfo->height; - -#ifdef USE_PALETTED_TEXTURE - if (glColorTableEXT && - (pTexInfo->grInfo.format == GR_TEXFMT_P_8) && - !(pTexInfo->flags & TF_CHROMAKEYED)) - { - // do nothing here. - // Not a problem with MiniGL since we don't use paletted texture - } - else -#endif - - if ((pTexInfo->grInfo.format == GR_TEXFMT_P_8) || - (pTexInfo->grInfo.format == GR_TEXFMT_AP_88)) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - if ((*pImgData == HWR_PATCHES_CHROMAKEY_COLORINDEX) && - (pTexInfo->flags & TF_CHROMAKEYED)) - { - tex[w*j+i].s.red = 0; - tex[w*j+i].s.green = 0; - tex[w*j+i].s.blue = 0; - tex[w*j+i].s.alpha = 0; - pTexInfo->flags |= TF_TRANSPARENT; // there is a hole in it - } - else - { - tex[w*j+i].s.red = myPaletteData[*pImgData].s.red; - tex[w*j+i].s.green = myPaletteData[*pImgData].s.green; - tex[w*j+i].s.blue = myPaletteData[*pImgData].s.blue; - tex[w*j+i].s.alpha = myPaletteData[*pImgData].s.alpha; - } - - pImgData++; - - if (pTexInfo->grInfo.format == GR_TEXFMT_AP_88) - { - if (!(pTexInfo->flags & TF_CHROMAKEYED)) - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - - } - } - } - else if (pTexInfo->grInfo.format == GR_RGBA) - { - // corona test : passed as ARGB 8888, which is not in glide formats - // Hurdler: not used for coronas anymore, just for dynamic lighting - ptex = pTexInfo->grInfo.data; - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = *pImgData; - tex[w*j+i].s.green = *pImgData; - tex[w*j+i].s.blue = *pImgData; - pImgData++; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - } - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) // Used for fade masks - { - const GLubyte *pImgData = (const GLubyte *)pTexInfo->grInfo.data; - INT32 i, j; - - for (j = 0; j < h; j++) - { - for (i = 0; i < w; i++) - { - tex[w*j+i].s.red = 255; // 255 because the fade mask is modulated with the screen texture, so alpha affects it while the colours don't - tex[w*j+i].s.green = 255; - tex[w*j+i].s.blue = 255; - tex[w*j+i].s.alpha = *pImgData; - pImgData++; - } - } - } - else - GL_DBG_Printf("SetTexture(bad format) %ld\n", pTexInfo->grInfo.format); - - // the texture number was already generated by pglGenTextures - pglBindTexture(GL_TEXTURE_2D, texnum); - pTexInfo->downloaded = texnum; - tex_downloaded = texnum; - - // disable texture filtering on any texture that has holes so there's no dumb borders or blending issues - if (pTexInfo->flags & TF_TRANSPARENT) - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - } - else - { - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter); - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter); - } - -#ifdef USE_PALETTED_TEXTURE - //Hurdler: not really supported and not tested recently - if (glColorTableEXT && - (pTexInfo->grInfo.format == GR_TEXFMT_P_8) && - !(pTexInfo->flags & TF_CHROMAKEYED)) - { - glColorTableEXT(GL_TEXTURE_2D, GL_RGB8, 256, GL_RGB, GL_UNSIGNED_BYTE, palette_tex); - pglTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, w, h, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, pTexInfo->grInfo.data); - } - else -#endif - if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_INTENSITY_88) - { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); -#ifdef GL_TEXTURE_MIN_LOD - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); -#endif -#ifdef GL_TEXTURE_MAX_LOD - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); -#endif - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - else if (pTexInfo->grInfo.format == GR_TEXFMT_ALPHA_8) - { - //pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, GL_ALPHA, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); -#ifdef GL_TEXTURE_MIN_LOD - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); -#endif -#ifdef GL_TEXTURE_MAX_LOD - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 4); -#endif - //pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_LINEAR_MIPMAP_LINEAR); - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - else - { - if (MipMap) - { - pgluBuild2DMipmaps(GL_TEXTURE_2D, textureformatGL, w, h, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - // Control the mipmap level of detail -#ifdef GL_TEXTURE_MIN_LOD - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0); // the lower the number, the higer the detail -#endif -#ifdef GL_TEXTURE_MAX_LOD - if (pTexInfo->flags & TF_TRANSPARENT) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0); // No mippmaps on transparent stuff - else - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 5); -#endif - } - else - pglTexImage2D(GL_TEXTURE_2D, 0, textureformatGL, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, ptex); - } - - if (pTexInfo->flags & TF_WRAPX) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_S); - - if (pTexInfo->flags & TF_WRAPY) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - else - Clamp2D(GL_TEXTURE_WRAP_T); - - if (maximumAnisotropy) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropic_filter); - + UpdateTexture(pTexInfo); pTexInfo->nextmipmap = NULL; - if (gr_cachetail) - { // insertion en fin de liste - gr_cachetail->nextmipmap = pTexInfo; - gr_cachetail = pTexInfo; + if (gl_cachetail) + { // insertion at the tail + gl_cachetail->nextmipmap = pTexInfo; + gl_cachetail = pTexInfo; } - else // initialisation de la liste - gr_cachetail = gr_cachehead = pTexInfo; + else // initialization of the linked list + gl_cachetail = gl_cachehead = pTexInfo; } } -static void load_shaders(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) +static void *Shader_Load(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) { #ifdef GL_SHADERS if (gl_shadersenabled && pglUseProgram) @@ -1719,522 +1909,208 @@ static void load_shaders(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat * gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; if (shader->program) { - boolean custom = (gl_shaderprograms[gl_currentshaderprogram].custom); - // 13062019 - // Check for fog - //if (changed) + if (gl_shaderprogramchanged) { - if (!custom) - { - if (gl_shaderprogramchanged) - { - pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); - gl_shaderprogramchanged = false; - } - } - else // always load custom shaders - { - if (gl_shaderprogramchanged) - { - pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); - gl_shaderprogramchanged = false; - } - } - } - - // set uniforms - { - #define UNIFORM_1(uniform, a, function) \ - if (uniform != -1) \ - function (uniform, a); - - #define UNIFORM_2(uniform, a, b, function) \ - if (uniform != -1) \ - function (uniform, a, b); - - #define UNIFORM_3(uniform, a, b, c, function) \ - if (uniform != -1) \ - function (uniform, a, b, c); - - #define UNIFORM_4(uniform, a, b, c, d, function) \ - if (uniform != -1) \ - function (uniform, a, b, c, d); - - // polygon - UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); - UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); - UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); - UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); - UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); - UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); - UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)leveltime) / TICRATE, pglUniform1f); - - #undef UNIFORM_1 - #undef UNIFORM_2 - #undef UNIFORM_3 - #undef UNIFORM_4 + pglUseProgram(gl_shaderprograms[gl_currentshaderprogram].program); + gl_shaderprogramchanged = false; } + Shader_SetUniforms(Surface, poly, tint, fade); + return shader; } else pglUseProgram(0); } +#else + (void)Surface; + (void)poly; + (void)tint; + (void)fade; +#endif + return NULL; +} + +static void Shader_SetUniforms(FSurfaceInfo *Surface, GLRGBAFloat *poly, GLRGBAFloat *tint, GLRGBAFloat *fade) +{ +#ifdef GL_SHADERS + if (gl_shadersenabled) + { + gl_shaderprogram_t *shader = &gl_shaderprograms[gl_currentshaderprogram]; + if (!shader->program) + return; + + // Color uniforms can be left NULL and will be set to white (1.0f, 1.0f, 1.0f, 1.0f) + if (poly == NULL) + poly = &shader_defaultcolor; + if (tint == NULL) + tint = &shader_defaultcolor; + if (fade == NULL) + fade = &shader_defaultcolor; + + #define UNIFORM_1(uniform, a, function) \ + if (uniform != -1) \ + function (uniform, a); + + #define UNIFORM_2(uniform, a, b, function) \ + if (uniform != -1) \ + function (uniform, a, b); + + #define UNIFORM_3(uniform, a, b, c, function) \ + if (uniform != -1) \ + function (uniform, a, b, c); + + #define UNIFORM_4(uniform, a, b, c, d, function) \ + if (uniform != -1) \ + function (uniform, a, b, c, d); + + // polygon + UNIFORM_4(shader->uniforms[gluniform_poly_color], poly->red, poly->green, poly->blue, poly->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[gluniform_tint_color], tint->red, tint->green, tint->blue, tint->alpha, pglUniform4f); + UNIFORM_4(shader->uniforms[gluniform_fade_color], fade->red, fade->green, fade->blue, fade->alpha, pglUniform4f); + if (Surface != NULL) + { + UNIFORM_1(shader->uniforms[gluniform_lighting], Surface->LightInfo.light_level, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_start], Surface->LightInfo.fade_start, pglUniform1f); + UNIFORM_1(shader->uniforms[gluniform_fade_end], Surface->LightInfo.fade_end, pglUniform1f); + } + UNIFORM_1(shader->uniforms[gluniform_leveltime], ((float)shader_leveltime) / TICRATE, pglUniform1f); + + #undef UNIFORM_1 + #undef UNIFORM_2 + #undef UNIFORM_3 + #undef UNIFORM_4 + } +#else + (void)Surface; + (void)poly; + (void)tint; + (void)fade; #endif } -// unfinished draw call batching - -// Note: could use realloc in the array reallocation code - -typedef struct +static void Shader_CompileError(const char *message, GLuint program, INT32 shadernum) { - FSurfaceInfo surf;// surf also has its own polyflags for some reason, but it seems unused - unsigned int vertsIndex;// location of verts in unsortedVertexArray - FUINT numVerts; - FBITFIELD polyFlags; - GLuint texNum; - GLuint shader; -} PolygonArrayEntry; + GLchar *infoLog = NULL; + GLint logLength; -FOutVector* finalVertexArray = NULL;// contains subset of sorted vertices and texture coordinates to be sent to gpu -UINT32* finalVertexIndexArray = NULL;// contains indexes for glDrawElements, taking into account fan->triangles conversion -// NOTE have this alloced as 3x finalVertexArray size -int finalVertexArrayAllocSize = 65536; -//GLubyte* colorArray = NULL;// contains color data to be sent to gpu, if needed -//int colorArrayAllocSize = 65536; -// not gonna use this for now, just sort by color and change state when it changes -// later maybe when using vertex attributes if it's needed + pglGetShaderiv(program, GL_INFO_LOG_LENGTH, &logLength); -PolygonArrayEntry* polygonArray = NULL;// contains the polygon data from DrawPolygon, waiting to be processed -int polygonArraySize = 0; -unsigned int* polygonIndexArray = NULL;// contains sorting pointers for polygonArray -int polygonArrayAllocSize = 65536; - -FOutVector* unsortedVertexArray = NULL;// contains unsorted vertices and texture coordinates from DrawPolygon -int unsortedVertexArraySize = 0; -int unsortedVertexArrayAllocSize = 65536; - -EXPORT void HWRAPI(StartBatching) (void) -{ - //CONS_Printf("StartBatching begin\n"); - // init arrays if that has not been done yet - if (!finalVertexArray) + if (logLength) { - finalVertexArray = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - finalVertexIndexArray = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - polygonArray = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(unsigned int)); - unsortedVertexArray = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); + infoLog = malloc(logLength); + pglGetShaderInfoLog(program, logLength, NULL, infoLog); } - // drawing functions will now collect the drawing data instead of passing it to opengl - gl_batching = true; - //CONS_Printf("StartBatching end\n"); + + GL_MSG_Error("CompileShaders: %s (%s)\n%s", message, HWR_GetShaderName(shadernum), (infoLog ? infoLog : "")); + + if (infoLog) + free(infoLog); } -static int comparePolygons(const void *p1, const void *p2) +// code that is common between DrawPolygon and DrawIndexedTriangles +// the corona thing is there too, i have no idea if that stuff works with DrawIndexedTriangles and batching +static void PreparePolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FBITFIELD PolyFlags) { - PolygonArrayEntry* poly1 = &polygonArray[*(const unsigned int*)p1]; - PolygonArrayEntry* poly2 = &polygonArray[*(const unsigned int*)p2]; - int diff; - INT64 diff64; + static GLRGBAFloat poly = {0,0,0,0}; + static GLRGBAFloat tint = {0,0,0,0}; + static GLRGBAFloat fade = {0,0,0,0}; - int shader1 = poly1->shader; - int shader2 = poly2->shader; - // make skywalls first in order - if (poly1->polyFlags & PF_NoTexture) - shader1 = -1; - if (poly2->polyFlags & PF_NoTexture) - shader2 = -1; - diff = shader1 - shader2; - if (diff != 0) return diff; + if ((PolyFlags & PF_Corona) && (oglflags & GLF_NOZBUFREAD)) + PolyFlags &= ~(PF_NoDepthTest|PF_Corona); - diff = poly1->texNum - poly2->texNum; - if (diff != 0) return diff; + SetBlend(PolyFlags); //TODO: inline (#pragma..) - diff = poly1->polyFlags - poly2->polyFlags; - if (diff != 0) return diff; - - diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - diff64 = poly1->surf.TintColor.rgba - poly2->surf.TintColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - diff64 = poly1->surf.FadeColor.rgba - poly2->surf.FadeColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - - diff = poly1->surf.LightInfo.light_level - poly2->surf.LightInfo.light_level; - if (diff != 0) return diff; - diff = poly1->surf.LightInfo.fade_start - poly2->surf.LightInfo.fade_start; - if (diff != 0) return diff; - diff = poly1->surf.LightInfo.fade_end - poly2->surf.LightInfo.fade_end; - return diff; -} - -static int comparePolygonsNoShaders(const void *p1, const void *p2) -{ - PolygonArrayEntry* poly1 = &polygonArray[*(const unsigned int*)p1]; - PolygonArrayEntry* poly2 = &polygonArray[*(const unsigned int*)p2]; - int diff; - INT64 diff64; - - GLuint texNum1 = poly1->texNum; - GLuint texNum2 = poly2->texNum; - if (poly1->polyFlags & PF_NoTexture) - texNum1 = 0; - if (poly2->polyFlags & PF_NoTexture) - texNum2 = 0; - diff = texNum1 - texNum2; - if (diff != 0) return diff; - - diff = poly1->polyFlags - poly2->polyFlags; - if (diff != 0) return diff; - - diff64 = poly1->surf.PolyColor.rgba - poly2->surf.PolyColor.rgba; - if (diff64 < 0) return -1; else if (diff64 > 0) return 1; - - return 0; -} - -// the parameters for this functions (numPolys etc.) are used to return rendering stats -EXPORT void HWRAPI(RenderBatches) (int *sNumPolys, int *sNumVerts, int *sNumCalls, int *sNumShaders, int *sNumTextures, int *sNumPolyFlags, int *sNumColors) -{ - int finalVertexWritePos = 0;// position in finalVertexArray - int finalIndexWritePos = 0;// position in finalVertexIndexArray - - int polygonReadPos = 0;// position in polygonIndexArray - - GLuint currentShader; - GLuint currentTexture; - FBITFIELD currentPolyFlags; - FSurfaceInfo currentSurfaceInfo; - - GLRGBAFloat firstPoly = {0,0,0,0}; // may be misleading but this means first PolyColor - GLRGBAFloat firstTint = {0,0,0,0}; - GLRGBAFloat firstFade = {0,0,0,0}; - - boolean needRebind = false; - - int i; - - //CONS_Printf("RenderBatches\n"); - gl_batching = false;// no longer collecting batches - if (!polygonArraySize) + // PolyColor + if (pSurf) { - *sNumPolys = *sNumCalls = *sNumShaders = *sNumTextures = *sNumPolyFlags = *sNumColors = 0; - return;// nothing to draw - } - // init stats vars - *sNumPolys = polygonArraySize; - *sNumCalls = *sNumVerts = 0; - *sNumShaders = *sNumTextures = *sNumPolyFlags = *sNumColors = 1; - // init polygonIndexArray - for (i = 0; i < polygonArraySize; i++) - { - polygonIndexArray[i] = i; + // If Modulated, mix the surface colour to the texture + if (CurrentPolyFlags & PF_Modulated) + { + // Poly color + poly.red = byte2float[pSurf->PolyColor.s.red]; + poly.green = byte2float[pSurf->PolyColor.s.green]; + poly.blue = byte2float[pSurf->PolyColor.s.blue]; + poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; + + pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); + } + + // Tint color + tint.red = byte2float[pSurf->TintColor.s.red]; + tint.green = byte2float[pSurf->TintColor.s.green]; + tint.blue = byte2float[pSurf->TintColor.s.blue]; + tint.alpha = byte2float[pSurf->TintColor.s.alpha]; + + // Fade color + fade.red = byte2float[pSurf->FadeColor.s.red]; + fade.green = byte2float[pSurf->FadeColor.s.green]; + fade.blue = byte2float[pSurf->FadeColor.s.blue]; + fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; } - // sort polygons - //CONS_Printf("qsort polys\n"); - //*sSortTime = I_GetTimeMicros(); - if (gl_allowshaders) - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygons); - else - qsort(polygonIndexArray, polygonArraySize, sizeof(unsigned int), comparePolygonsNoShaders); - //*sSortTime = I_GetTimeMicros() - *sSortTime; - //CONS_Printf("sort done\n"); - // sort order - // 1. shader - // 2. texture - // 3. polyflags - // 4. colors + light level - // not sure about order of last 2, or if it even matters - - //*sDrawTime = I_GetTimeMicros(); - - currentShader = polygonArray[polygonIndexArray[0]].shader; - currentTexture = polygonArray[polygonIndexArray[0]].texNum; - currentPolyFlags = polygonArray[polygonIndexArray[0]].polyFlags; - currentSurfaceInfo = polygonArray[polygonIndexArray[0]].surf; - // For now, will sort and track the colors. Vertex attributes could be used instead of uniforms - // and a color array could replace the color calls. - - // set state for first batch - //CONS_Printf("set first state\n"); - gl_currentshaderprogram = currentShader; - gl_shaderprogramchanged = true; - if (currentPolyFlags & PF_Modulated) + // this test is added for new coronas' code (without depth buffer) + // I think I should do a separate function for drawing coronas, so it will be a little faster + if (PolyFlags & PF_Corona) // check to see if we need to draw the corona { - // Poly color - firstPoly.red = byte2float[currentSurfaceInfo.PolyColor.s.red]; - firstPoly.green = byte2float[currentSurfaceInfo.PolyColor.s.green]; - firstPoly.blue = byte2float[currentSurfaceInfo.PolyColor.s.blue]; - firstPoly.alpha = byte2float[currentSurfaceInfo.PolyColor.s.alpha]; - pglColor4ubv((GLubyte*)¤tSurfaceInfo.PolyColor.s); + FUINT i; + FUINT j; + + //rem: all 8 (or 8.0f) values are hard coded: it can be changed to a higher value + GLfloat buf[8][8]; + GLfloat cx, cy, cz; + GLfloat px = 0.0f, py = 0.0f, pz = -1.0f; + GLfloat scalef = 0.0f; + + GLubyte c[4]; + + float alpha; + + cx = (pOutVerts[0].x + pOutVerts[2].x) / 2.0f; // we should change the coronas' ... + cy = (pOutVerts[0].y + pOutVerts[2].y) / 2.0f; // ... code so its only done once. + cz = pOutVerts[0].z; + + // I dont know if this is slow or not + GLProject(cx, cy, cz, &px, &py, &pz); + //GL_DBG_Printf("Projection: (%f, %f, %f)\n", px, py, pz); + + if ((pz < 0.0l) || + (px < -8.0l) || + (py < viewport[1]-8.0l) || + (px > viewport[2]+8.0l) || + (py > viewport[1]+viewport[3]+8.0l)) + return; + + // the damned slow glReadPixels functions :( + pglReadPixels((INT32)px-4, (INT32)py, 8, 8, GL_DEPTH_COMPONENT, GL_FLOAT, buf); + //GL_DBG_Printf("DepthBuffer: %f %f\n", buf[0][0], buf[3][3]); + + for (i = 0; i < 8; i++) + for (j = 0; j < 8; j++) + scalef += (pz > buf[i][j]+0.00005f) ? 0 : 1; + + // quick test for screen border (not 100% correct, but looks ok) + if (px < 4) scalef -= (GLfloat)(8*(4-px)); + if (py < viewport[1]+4) scalef -= (GLfloat)(8*(viewport[1]+4-py)); + if (px > viewport[2]-4) scalef -= (GLfloat)(8*(4-(viewport[2]-px))); + if (py > viewport[1]+viewport[3]-4) scalef -= (GLfloat)(8*(4-(viewport[1]+viewport[3]-py))); + + scalef /= 64; + //GL_DBG_Printf("Scale factor: %f\n", scalef); + + if (scalef < 0.05f) + return; + + // GLubyte c[4]; + c[0] = pSurf->PolyColor.s.red; + c[1] = pSurf->PolyColor.s.green; + c[2] = pSurf->PolyColor.s.blue; + + alpha = byte2float[pSurf->PolyColor.s.alpha]; + alpha *= scalef; // change the alpha value (it seems better than changing the size of the corona) + c[3] = (unsigned char)(alpha * 255); + pglColor4ubv(c); } - // Tint color - firstTint.red = byte2float[currentSurfaceInfo.TintColor.s.red]; - firstTint.green = byte2float[currentSurfaceInfo.TintColor.s.green]; - firstTint.blue = byte2float[currentSurfaceInfo.TintColor.s.blue]; - firstTint.alpha = byte2float[currentSurfaceInfo.TintColor.s.alpha]; - // Fade color - firstFade.red = byte2float[currentSurfaceInfo.FadeColor.s.red]; - firstFade.green = byte2float[currentSurfaceInfo.FadeColor.s.green]; - firstFade.blue = byte2float[currentSurfaceInfo.FadeColor.s.blue]; - firstFade.alpha = byte2float[currentSurfaceInfo.FadeColor.s.alpha]; - if (gl_allowshaders) - load_shaders(¤tSurfaceInfo, &firstPoly, &firstTint, &firstFade); - - if (currentPolyFlags & PF_NoTexture) - currentTexture = 0; - pglBindTexture(GL_TEXTURE_2D, currentTexture); - tex_downloaded = currentTexture; - - SetBlend(currentPolyFlags); - - //CONS_Printf("first pointers to ogl\n"); - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].s); - - while (1)// note: remember handling notexture polyflag as having texture number 0 (also in comparePolygons) - { - int firstIndex; - int lastIndex; - - boolean stopFlag = false; - boolean changeState = false; - boolean changeShader = false; - GLuint nextShader = 0U; - boolean changeTexture = false; - GLuint nextTexture = 0U; - boolean changePolyFlags = false; - FBITFIELD nextPolyFlags = 0U; - boolean changeSurfaceInfo = false; - FSurfaceInfo nextSurfaceInfo; - - //CONS_Printf("loop iter start\n"); - // new try: - // write vertices - // check for changes or end, otherwise go back to writing - // changes will affect the next vars and the change bools - // end could set flag for stopping - // execute draw call - // could check ending flag here - // change states according to next vars and change bools, updating the current vars and reseting the bools - // reset write pos - // repeat loop - - int index = polygonIndexArray[polygonReadPos++]; - int numVerts = polygonArray[index].numVerts; - // before writing, check if there is enough room - // using 'while' instead of 'if' here makes sure that there will *always* be enough room. - // probably never will this loop run more than once though - while (finalVertexWritePos + numVerts > finalVertexArrayAllocSize) - { - FOutVector* new_array; - unsigned int* new_index_array; - //CONS_Printf("final vert realloc\n"); - finalVertexArrayAllocSize *= 2; - new_array = malloc(finalVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, finalVertexArray, finalVertexWritePos * sizeof(FOutVector)); - free(finalVertexArray); - finalVertexArray = new_array; - // also increase size of index array, 3x of vertex array since - // going from fans to triangles increases vertex count to 3x - new_index_array = malloc(finalVertexArrayAllocSize * 3 * sizeof(UINT32)); - memcpy(new_index_array, finalVertexIndexArray, finalIndexWritePos * sizeof(UINT32)); - free(finalVertexIndexArray); - finalVertexIndexArray = new_index_array; - // if vertex buffers are reallocated then opengl needs to know too - needRebind = true; - } - //CONS_Printf("write verts to final\n"); - // write the vertices of the polygon - memcpy(&finalVertexArray[finalVertexWritePos], &unsortedVertexArray[polygonArray[index].vertsIndex], - numVerts * sizeof(FOutVector)); - // write the indexes, pointing to the fan vertexes but in triangles format - firstIndex = finalVertexWritePos; - lastIndex = finalVertexWritePos + numVerts; - finalVertexWritePos += 2; - //CONS_Printf("write final vert indices\n"); - while (finalVertexWritePos < lastIndex) - { - finalVertexIndexArray[finalIndexWritePos++] = firstIndex; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos - 1; - finalVertexIndexArray[finalIndexWritePos++] = finalVertexWritePos++; - } - - if (polygonReadPos >= polygonArraySize) - { - stopFlag = true; - } - else - { - //CONS_Printf("state change check\n"); - // check if a state change is required, set the change bools and next vars - int nextIndex = polygonIndexArray[polygonReadPos]; - nextShader = polygonArray[nextIndex].shader; - nextTexture = polygonArray[nextIndex].texNum; - nextPolyFlags = polygonArray[nextIndex].polyFlags; - nextSurfaceInfo = polygonArray[nextIndex].surf; - if (nextPolyFlags & PF_NoTexture) - nextTexture = 0; - if (currentShader != nextShader) - { - changeState = true; - changeShader = true; - } - if (currentTexture != nextTexture) - { - changeState = true; - changeTexture = true; - } - if (currentPolyFlags != nextPolyFlags) - { - changeState = true; - changePolyFlags = true; - } - if (gl_allowshaders) - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba || - currentSurfaceInfo.TintColor.rgba != nextSurfaceInfo.TintColor.rgba || - currentSurfaceInfo.FadeColor.rgba != nextSurfaceInfo.FadeColor.rgba || - currentSurfaceInfo.LightInfo.light_level != nextSurfaceInfo.LightInfo.light_level || - currentSurfaceInfo.LightInfo.fade_start != nextSurfaceInfo.LightInfo.fade_start || - currentSurfaceInfo.LightInfo.fade_end != nextSurfaceInfo.LightInfo.fade_end) - { - changeState = true; - changeSurfaceInfo = true; - } - } - else - { - if (currentSurfaceInfo.PolyColor.rgba != nextSurfaceInfo.PolyColor.rgba) - { - changeState = true; - changeSurfaceInfo = true; - } - } - } - - if (changeState || stopFlag) - { - if (needRebind) - { - //CONS_Printf("rebind\n"); - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &finalVertexArray[0].s); - needRebind = false; - } - //CONS_Printf("exec draw call\n"); - // execute draw call - pglDrawElements(GL_TRIANGLES, finalIndexWritePos, GL_UNSIGNED_INT, finalVertexIndexArray); - //CONS_Printf("draw call done\n"); - // update stats - (*sNumCalls)++; - *sNumVerts += finalIndexWritePos; - // reset write positions - finalVertexWritePos = 0; - finalIndexWritePos = 0; - } - else continue; - - // if we're here then either its time to stop or time to change state - if (stopFlag) break; - - //CONS_Printf("state change\n"); - - // change state according to change bools and next vars, update current vars and reset bools - if (changeShader) - { - GLRGBAFloat poly = {0,0,0,0}; - GLRGBAFloat tint = {0,0,0,0}; - GLRGBAFloat fade = {0,0,0,0}; - gl_currentshaderprogram = nextShader; - gl_shaderprogramchanged = true; - if (nextPolyFlags & PF_Modulated) - { - // Poly color - poly.red = byte2float[nextSurfaceInfo.PolyColor.s.red]; - poly.green = byte2float[nextSurfaceInfo.PolyColor.s.green]; - poly.blue = byte2float[nextSurfaceInfo.PolyColor.s.blue]; - poly.alpha = byte2float[nextSurfaceInfo.PolyColor.s.alpha]; - } - // Tint color - tint.red = byte2float[nextSurfaceInfo.TintColor.s.red]; - tint.green = byte2float[nextSurfaceInfo.TintColor.s.green]; - tint.blue = byte2float[nextSurfaceInfo.TintColor.s.blue]; - tint.alpha = byte2float[nextSurfaceInfo.TintColor.s.alpha]; - // Fade color - fade.red = byte2float[nextSurfaceInfo.FadeColor.s.red]; - fade.green = byte2float[nextSurfaceInfo.FadeColor.s.green]; - fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue]; - fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; - - load_shaders(&nextSurfaceInfo, &poly, &tint, &fade); - currentShader = nextShader; - changeShader = false; - - (*sNumShaders)++; - } - if (changeTexture) - { - // texture should be already ready for use from calls to SetTexture during batch collection - pglBindTexture(GL_TEXTURE_2D, nextTexture); - tex_downloaded = nextTexture; - currentTexture = nextTexture; - changeTexture = false; - - (*sNumTextures)++; - } - if (changePolyFlags) - { - SetBlend(nextPolyFlags); - currentPolyFlags = nextPolyFlags; - changePolyFlags = false; - - (*sNumPolyFlags)++; - } - if (changeSurfaceInfo) - { - GLRGBAFloat poly = {0,0,0,0}; - GLRGBAFloat tint = {0,0,0,0}; - GLRGBAFloat fade = {0,0,0,0}; - gl_shaderprogramchanged = false; - if (nextPolyFlags & PF_Modulated) - { - // Poly color - poly.red = byte2float[nextSurfaceInfo.PolyColor.s.red]; - poly.green = byte2float[nextSurfaceInfo.PolyColor.s.green]; - poly.blue = byte2float[nextSurfaceInfo.PolyColor.s.blue]; - poly.alpha = byte2float[nextSurfaceInfo.PolyColor.s.alpha]; - pglColor4ubv((GLubyte*)&nextSurfaceInfo.PolyColor.s); - } - if (gl_allowshaders) - { - // Tint color - tint.red = byte2float[nextSurfaceInfo.TintColor.s.red]; - tint.green = byte2float[nextSurfaceInfo.TintColor.s.green]; - tint.blue = byte2float[nextSurfaceInfo.TintColor.s.blue]; - tint.alpha = byte2float[nextSurfaceInfo.TintColor.s.alpha]; - // Fade color - fade.red = byte2float[nextSurfaceInfo.FadeColor.s.red]; - fade.green = byte2float[nextSurfaceInfo.FadeColor.s.green]; - fade.blue = byte2float[nextSurfaceInfo.FadeColor.s.blue]; - fade.alpha = byte2float[nextSurfaceInfo.FadeColor.s.alpha]; - - load_shaders(&nextSurfaceInfo, &poly, &tint, &fade); - } - currentSurfaceInfo = nextSurfaceInfo; - changeSurfaceInfo = false; - - (*sNumColors)++; - } - // and that should be it? - } - // reset the arrays (set sizes to 0) - polygonArraySize = 0; - unsortedVertexArraySize = 0; - - //*sDrawTime = I_GetTimeMicros() - *sDrawTime; + Shader_Load(pSurf, &poly, &tint, &fade); } // -----------------+ @@ -2242,332 +2118,110 @@ EXPORT void HWRAPI(RenderBatches) (int *sNumPolys, int *sNumVerts, int *sNumCall // -----------------+ EXPORT void HWRAPI(DrawPolygon) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags) { - if (gl_batching) - { - //CONS_Printf("Batched DrawPolygon\n"); - if (!pSurf) - I_Error("Got a null FSurfaceInfo in batching");// nulls should only come in sky background pic drawing - if (polygonArraySize == polygonArrayAllocSize) - { - PolygonArrayEntry* new_array; - // ran out of space, make new array double the size - polygonArrayAllocSize *= 2; - new_array = malloc(polygonArrayAllocSize * sizeof(PolygonArrayEntry)); - memcpy(new_array, polygonArray, polygonArraySize * sizeof(PolygonArrayEntry)); - free(polygonArray); - polygonArray = new_array; - // also need to redo the index array, dont need to copy it though - free(polygonIndexArray); - polygonIndexArray = malloc(polygonArrayAllocSize * sizeof(unsigned int)); - } + PreparePolygon(pSurf, pOutVerts, PolyFlags); - while (unsortedVertexArraySize + (int)iNumPts > unsortedVertexArrayAllocSize) - { - FOutVector* new_array; - // need more space for vertices in unsortedVertexArray - unsortedVertexArrayAllocSize *= 2; - new_array = malloc(unsortedVertexArrayAllocSize * sizeof(FOutVector)); - memcpy(new_array, unsortedVertexArray, unsortedVertexArraySize * sizeof(FOutVector)); - free(unsortedVertexArray); - unsortedVertexArray = new_array; - } + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); + pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); - // add the polygon data to the arrays + if (PolyFlags & PF_RemoveYWrap) + pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - polygonArray[polygonArraySize].surf = *pSurf; - polygonArray[polygonArraySize].vertsIndex = unsortedVertexArraySize; - polygonArray[polygonArraySize].numVerts = iNumPts; - polygonArray[polygonArraySize].polyFlags = PolyFlags; - polygonArray[polygonArraySize].texNum = tex_downloaded; - polygonArray[polygonArraySize].shader = gl_currentshaderprogram; - polygonArraySize++; + if (PolyFlags & PF_ForceWrapX) + Clamp2D(GL_TEXTURE_WRAP_S); - memcpy(&unsortedVertexArray[unsortedVertexArraySize], pOutVerts, iNumPts * sizeof(FOutVector)); - unsortedVertexArraySize += iNumPts; - } - else - { - static GLRGBAFloat poly = {0,0,0,0}; - static GLRGBAFloat tint = {0,0,0,0}; - static GLRGBAFloat fade = {0,0,0,0}; - - SetBlend(PolyFlags); //TODO: inline (#pragma..) - - // PolyColor - if (pSurf) - { - // If Modulated, mix the surface colour to the texture - if (CurrentPolyFlags & PF_Modulated) - { - // Poly color - poly.red = byte2float[pSurf->PolyColor.s.red]; - poly.green = byte2float[pSurf->PolyColor.s.green]; - poly.blue = byte2float[pSurf->PolyColor.s.blue]; - poly.alpha = byte2float[pSurf->PolyColor.s.alpha]; - - pglColor4ubv((GLubyte*)&pSurf->PolyColor.s); - } - - // Tint color - tint.red = byte2float[pSurf->TintColor.s.red]; - tint.green = byte2float[pSurf->TintColor.s.green]; - tint.blue = byte2float[pSurf->TintColor.s.blue]; - tint.alpha = byte2float[pSurf->TintColor.s.alpha]; - - // Fade color - fade.red = byte2float[pSurf->FadeColor.s.red]; - fade.green = byte2float[pSurf->FadeColor.s.green]; - fade.blue = byte2float[pSurf->FadeColor.s.blue]; - fade.alpha = byte2float[pSurf->FadeColor.s.alpha]; - } - - load_shaders(pSurf, &poly, &tint, &fade); - - pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); - pglDrawArrays(GL_TRIANGLE_FAN, 0, iNumPts); - - if (PolyFlags & PF_RemoveYWrap) - pglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - - if (PolyFlags & PF_ForceWrapX) - Clamp2D(GL_TEXTURE_WRAP_S); - - if (PolyFlags & PF_ForceWrapY) - Clamp2D(GL_TEXTURE_WRAP_T); - } + if (PolyFlags & PF_ForceWrapY) + Clamp2D(GL_TEXTURE_WRAP_T); } -// Sky dome code, taken/backported from SRB2 - -typedef struct vbo_vertex_s +EXPORT void HWRAPI(DrawIndexedTriangles) (FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags, UINT32 *IndexArray) { - float x, y, z; - float u, v; - unsigned char r, g, b, a; -} vbo_vertex_t; + PreparePolygon(pSurf, pOutVerts, PolyFlags); -typedef struct -{ - int mode; - int vertexcount; - int vertexindex; - int use_texture; -} GLSkyLoopDef; + pglVertexPointer(3, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(FOutVector), &pOutVerts[0].s); + pglDrawElements(GL_TRIANGLES, iNumPts, GL_UNSIGNED_INT, IndexArray); -typedef struct -{ - unsigned int id; - int rows, columns; - int loopcount; - GLSkyLoopDef *loops; - vbo_vertex_t *data; -} GLSkyVBO; + // the DrawPolygon variant of this has some code about polyflags and wrapping here but havent noticed any problems from omitting it? +} static const boolean gl_ext_arb_vertex_buffer_object = true; -#define NULL_VBO_VERTEX ((vbo_vertex_t*)NULL) -#define sky_vbo_x (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->x : &vbo->data[0].x) -#define sky_vbo_u (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->u : &vbo->data[0].u) -#define sky_vbo_r (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->r : &vbo->data[0].r) +#define NULL_VBO_VERTEX ((gl_skyvertex_t*)NULL) +#define sky_vbo_x (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->x : &sky->data[0].x) +#define sky_vbo_u (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->u : &sky->data[0].u) +#define sky_vbo_r (gl_ext_arb_vertex_buffer_object ? &NULL_VBO_VERTEX->r : &sky->data[0].r) -// The texture offset to be applied to the texture coordinates in SkyVertex(). -static int rows, columns; -static signed char yflip; -static int texw, texh; -static boolean foglayer; -static float delta = 0.0f; - -static int gl_sky_detail = 16; - -static INT32 lasttex = -1; - -#define MAP_COEFF 128.0f - -static void SkyVertex(vbo_vertex_t *vbo, int r, int c) -{ - const float radians = (float)(M_PIl / 180.0f); - const float scale = 10000.0f; - const float maxSideAngle = 60.0f; - - float topAngle = (c / (float)columns * 360.0f); - float sideAngle = (maxSideAngle * (rows - r) / rows); - float height = (float)(sin(sideAngle * radians)); - float realRadius = (float)(scale * cos(sideAngle * radians)); - float x = (float)(realRadius * cos(topAngle * radians)); - float y = (!yflip) ? scale * height : -scale * height; - float z = (float)(realRadius * sin(topAngle * radians)); - float timesRepeat = (4 * (256.0f / texw)); - if (fpclassify(timesRepeat) == FP_ZERO) - timesRepeat = 1.0f; - - if (!foglayer) - { - vbo->r = 255; - vbo->g = 255; - vbo->b = 255; - vbo->a = (r == 0 ? 0 : 255); - - // And the texture coordinates. - //vbo->u = (-timesRepeat * c / (float)columns); - vbo->u = (timesRepeat * c / (float)columns);// TEST - if (!yflip) // Flipped Y is for the lower hemisphere. - vbo->v = (r / (float)rows) + 0.5f; - else - vbo->v = 1.0f + ((rows - r) / (float)rows) + 0.5f; - } - - if (r != 4) - { - y += 300.0f; - } - - // And finally the vertex. - vbo->x = x; - vbo->y = y + delta; - vbo->z = z; -} - -static GLSkyVBO sky_vbo; - -static void gld_BuildSky(int row_count, int col_count) -{ - int c, r; - vbo_vertex_t *vertex_p; - int vertex_count = 2 * row_count * (col_count * 2 + 2) + col_count * 2; - - GLSkyVBO *vbo = &sky_vbo; - - if ((vbo->columns != col_count) || (vbo->rows != row_count)) - { - free(vbo->loops); - free(vbo->data); - memset(vbo, 0, sizeof(&vbo)); - } - - if (!vbo->data) - { - memset(vbo, 0, sizeof(&vbo)); - vbo->loops = malloc((row_count * 2 + 2) * sizeof(vbo->loops[0])); - // create vertex array - vbo->data = malloc(vertex_count * sizeof(vbo->data[0])); - } - - vbo->columns = col_count; - vbo->rows = row_count; - - vertex_p = &vbo->data[0]; - vbo->loopcount = 0; - - for (yflip = 0; yflip < 2; yflip++) - { - vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_FAN; - vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; - vbo->loops[vbo->loopcount].vertexcount = col_count; - vbo->loops[vbo->loopcount].use_texture = false; - vbo->loopcount++; - - delta = 0.0f; - foglayer = true; - for (c = 0; c < col_count; c++) - { - SkyVertex(vertex_p, 1, c); - vertex_p->r = 255; - vertex_p->g = 255; - vertex_p->b = 255; - vertex_p->a = 255; - vertex_p++; - } - foglayer = false; - - delta = (yflip ? 5.0f : -5.0f) / MAP_COEFF; - - for (r = 0; r < row_count; r++) - { - vbo->loops[vbo->loopcount].mode = GL_TRIANGLE_STRIP; - vbo->loops[vbo->loopcount].vertexindex = vertex_p - &vbo->data[0]; - vbo->loops[vbo->loopcount].vertexcount = 2 * col_count + 2; - vbo->loops[vbo->loopcount].use_texture = true; - vbo->loopcount++; - - for (c = 0; c <= col_count; c++) - { - SkyVertex(vertex_p++, r + (yflip ? 1 : 0), (c ? c : 0)); - SkyVertex(vertex_p++, r + (yflip ? 0 : 1), (c ? c : 0)); - } - } - } -} - -//----------------------------------------------------------------------------- -// -// -// -//----------------------------------------------------------------------------- - -static void RenderDome(INT32 skytexture) +EXPORT void HWRAPI(RenderSkyDome) (gl_sky_t *sky) { int i, j; - int vbosize; - GLSkyVBO *vbo = &sky_vbo; - rows = 4; - columns = 4 * gl_sky_detail; - - vbosize = 2 * rows * (columns * 2 + 2) + columns * 2; + Shader_Load(NULL, NULL, NULL, NULL); // Build the sky dome! Yes! - if (lasttex != skytexture) + if (sky->rebuild) { // delete VBO when already exists if (gl_ext_arb_vertex_buffer_object) { - if (vbo->id) - pglDeleteBuffers(1, &vbo->id); + if (sky->vbo) + pglDeleteBuffers(1, &sky->vbo); } - lasttex = skytexture; - gld_BuildSky(rows, columns); - if (gl_ext_arb_vertex_buffer_object) { // generate a new VBO and get the associated ID - pglGenBuffers(1, &vbo->id); + pglGenBuffers(1, &sky->vbo); // bind VBO in order to use - pglBindBuffer(GL_ARRAY_BUFFER, vbo->id); + pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo); // upload data to VBO - pglBufferData(GL_ARRAY_BUFFER, vbosize * sizeof(vbo->data[0]), vbo->data, GL_STATIC_DRAW); + pglBufferData(GL_ARRAY_BUFFER, sky->vertex_count * sizeof(sky->data[0]), sky->data, GL_STATIC_DRAW); } + + sky->rebuild = false; } // bind VBO in order to use if (gl_ext_arb_vertex_buffer_object) - pglBindBuffer(GL_ARRAY_BUFFER, vbo->id); + pglBindBuffer(GL_ARRAY_BUFFER, sky->vbo); // activate and specify pointers to arrays - pglVertexPointer(3, GL_FLOAT, sizeof(vbo->data[0]), sky_vbo_x); - pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo->data[0]), sky_vbo_u); - pglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(vbo->data[0]), sky_vbo_r); + pglVertexPointer(3, GL_FLOAT, sizeof(sky->data[0]), sky_vbo_x); + pglTexCoordPointer(2, GL_FLOAT, sizeof(sky->data[0]), sky_vbo_u); + pglColorPointer(4, GL_UNSIGNED_BYTE, sizeof(sky->data[0]), sky_vbo_r); // activate color arrays pglEnableClientState(GL_COLOR_ARRAY); // set transforms - pglScalef(1.0f, (float)texh / 230.0f, 1.0f); + pglScalef(1.0f, (float)sky->height / 200.0f, 1.0f); pglRotatef(270.0f, 0.0f, 1.0f, 0.0f); for (j = 0; j < 2; j++) { - for (i = 0; i < vbo->loopcount; i++) + for (i = 0; i < sky->loopcount; i++) { - GLSkyLoopDef *loop = &vbo->loops[i]; + gl_skyloopdef_t *loop = &sky->loops[i]; + unsigned int mode = 0; if (j == 0 ? loop->use_texture : !loop->use_texture) continue; - pglDrawArrays(loop->mode, loop->vertexindex, loop->vertexcount); + switch (loop->mode) + { + case HWD_SKYLOOP_FAN: + mode = GL_TRIANGLE_FAN; + break; + case HWD_SKYLOOP_STRIP: + mode = GL_TRIANGLE_STRIP; + break; + default: + continue; + } + + pglDrawArrays(mode, loop->vertexindex, loop->vertexcount); } } @@ -2582,16 +2236,6 @@ static void RenderDome(INT32 skytexture) pglDisableClientState(GL_COLOR_ARRAY); } -EXPORT void HWRAPI(RenderSkyDome) (INT32 tex, INT32 texture_width, INT32 texture_height, FTransform transform) -{ - SetBlend(PF_Translucent|PF_NoDepthTest|PF_Modulated); - SetTransform(&transform); - texw = texture_width; - texh = texture_height; - RenderDome(tex); - SetBlend(0); -} - // ========================================================================== // // ========================================================================== @@ -2599,6 +2243,10 @@ EXPORT void HWRAPI(SetSpecialState) (hwdspecialstate_t IdState, INT32 Value) { switch (IdState) { + case HWD_SET_MODEL_LIGHTING: + model_lighting = Value; + break; + case HWD_SET_SHADERS: switch (Value) { @@ -2863,9 +2511,9 @@ EXPORT void HWRAPI(CreateModelVBOs) (model_t *model) } } -#define BUFFER_OFFSET(i) ((char*)(i)) +#define BUFFER_OFFSET(i) ((void*)(i)) -static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) +static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { static GLRGBAFloat poly = {0,0,0,0}; static GLRGBAFloat tint = {0,0,0,0}; @@ -2876,8 +2524,17 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 boolean useTinyFrames; + boolean useVBO = true; + int i; + // Because otherwise, scaling the screen negatively vertically breaks the lighting + GLfloat LightPos[] = {0.0f, 1.0f, 0.0f, 0.0f}; +#ifdef GL_LIGHT_MODEL_AMBIENT + GLfloat ambient[4]; + GLfloat diffuse[4]; +#endif + // Affect input model scaling scale *= 0.5f; scalex = scale; @@ -2902,35 +2559,65 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 poly.blue = byte2float[Surface->PolyColor.s.blue]; poly.alpha = byte2float[Surface->PolyColor.s.alpha]; - if (poly.alpha < 1) - SetBlend(PF_Translucent|PF_Modulated); +#ifdef GL_LIGHT_MODEL_AMBIENT + if (model_lighting) + { + if (!gl_shadersenabled) + { + ambient[0] = poly.red; + ambient[1] = poly.green; + ambient[2] = poly.blue; + ambient[3] = poly.alpha; + + diffuse[0] = poly.red; + diffuse[1] = poly.green; + diffuse[2] = poly.blue; + diffuse[3] = poly.alpha; + + if (ambient[0] > 0.75f) + ambient[0] = 0.75f; + if (ambient[1] > 0.75f) + ambient[1] = 0.75f; + if (ambient[2] > 0.75f) + ambient[2] = 0.75f; + + pglLightfv(GL_LIGHT0, GL_POSITION, LightPos); + + pglEnable(GL_LIGHTING); + pglMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, ambient); + pglMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, diffuse); + } + pglShadeModel(GL_SMOOTH); + } +#endif else - SetBlend(PF_Masked|PF_Modulated|PF_Occlude); + pglColor4ubv((GLubyte*)&Surface->PolyColor.s); - pglColor4ubv((GLubyte*)&Surface->PolyColor.s); + SetBlend((poly.alpha < 1 ? PF_Translucent : (PF_Masked|PF_Occlude))|PF_Modulated); - tint.red = byte2float[Surface->TintColor.s.red]; - tint.green = byte2float[Surface->TintColor.s.green]; - tint.blue = byte2float[Surface->TintColor.s.blue]; - tint.alpha = byte2float[Surface->TintColor.s.alpha]; + tint.red = byte2float[Surface->TintColor.s.red]; + tint.green = byte2float[Surface->TintColor.s.green]; + tint.blue = byte2float[Surface->TintColor.s.blue]; + tint.alpha = byte2float[Surface->TintColor.s.alpha]; fade.red = byte2float[Surface->FadeColor.s.red]; fade.green = byte2float[Surface->FadeColor.s.green]; fade.blue = byte2float[Surface->FadeColor.s.blue]; fade.alpha = byte2float[Surface->FadeColor.s.alpha]; - load_shaders(Surface, &poly, &tint, &fade); + Shader_Load(Surface, &poly, &tint, &fade); pglEnable(GL_CULL_FACE); pglEnable(GL_NORMALIZE); #ifdef USE_FTRANSFORM_MIRROR - // flipped is if the object is flipped + // flipped is if the object is vertically flipped + // hflipped is if the object is horizontally flipped // pos->flip is if the screen is flipped vertically // pos->mirror is if the screen is flipped horizontally // XOR all the flips together to figure out what culling to use! { - boolean reversecull = (flipped ^ pos->flip ^ pos->mirror); + boolean reversecull = (flipped ^ hflipped ^ pos->flip ^ pos->mirror); if (reversecull) pglCullFace(GL_FRONT); else @@ -2938,21 +2625,42 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 } #else // pos->flip is if the screen is flipped too - if (flipped != pos->flip) // If either are active, but not both, invert the model's culling + if (flipped ^ hflipped ^ pos->flip) // If one or three of these are active, but not two, invert the model's culling + { pglCullFace(GL_FRONT); + } else + { pglCullFace(GL_BACK); + } #endif pglPushMatrix(); // should be the same as glLoadIdentity + //Hurdler: now it seems to work pglTranslatef(pos->x, pos->z, pos->y); if (flipped) scaley = -scaley; + if (hflipped) + scalez = -scalez; + #ifdef USE_FTRANSFORM_ANGLEZ pglRotatef(pos->anglez, 0.0f, 0.0f, -1.0f); // rotate by slope from Kart #endif - pglRotatef(pos->anglex, -1.0f, 0.0f, 0.0f); pglRotatef(pos->angley, 0.0f, -1.0f, 0.0f); + pglRotatef(pos->anglex, 1.0f, 0.0f, 0.0f); + + if (pos->roll) + { + float roll = (1.0f * pos->rollflip); + pglTranslatef(pos->centerx, pos->centery, 0); + if (pos->rotaxis == 2) // Z + pglRotatef(pos->rollangle, 0.0f, 0.0f, roll); + else if (pos->rotaxis == 1) // Y + pglRotatef(pos->rollangle, 0.0f, roll, 0.0f); + else // X + pglRotatef(pos->rollangle, roll, 0.0f, 0.0f); + pglTranslatef(-pos->centerx, -pos->centery, 0); + } pglScalef(scalex, scaley, scalez); @@ -2961,6 +2669,15 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (useTinyFrames) pglScalef(1 / 64.0f, 1 / 64.0f, 1 / 64.0f); + // Don't use the VBO if it does not have the correct texture coordinates. + // (Can happen when model uses a sprite as a texture and the sprite changes) + // Comparing floats with the != operator here should be okay because they + // are just copies of glpatches' max_s and max_t values. + // Instead of the != operator, memcmp is used to avoid a compiler warning. + if (memcmp(&(model->vbo_max_s), &(model->max_s), sizeof(model->max_s)) != 0 || + memcmp(&(model->vbo_max_t), &(model->max_t), sizeof(model->max_t)) != 0) + useVBO = false; + pglEnableClientState(GL_NORMAL_ARRAY); for (i = 0; i < model->numMeshes; i++) @@ -2977,12 +2694,23 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (!nextframe || fpclassify(pol) == FP_ZERO) { - pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); - pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0)); - pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3)); - pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6)); - pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); - pglBindBuffer(GL_ARRAY_BUFFER, 0); + if (useVBO) + { + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglVertexPointer(3, GL_SHORT, sizeof(vbotiny_t), BUFFER_OFFSET(0)); + pglNormalPointer(GL_BYTE, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short)*3)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbotiny_t), BUFFER_OFFSET(sizeof(short) * 3 + sizeof(char) * 6)); + + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + pglVertexPointer(3, GL_SHORT, 0, frame->vertices); + pglNormalPointer(GL_BYTE, 0, frame->normals); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + } } else { @@ -3018,14 +2746,25 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 if (!nextframe || fpclassify(pol) == FP_ZERO) { - // Zoom! Take advantage of just shoving the entire arrays to the GPU. - pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); - pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0)); - pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3)); - pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6)); + if (useVBO) + { + pglBindBuffer(GL_ARRAY_BUFFER, frame->vboID); + pglVertexPointer(3, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(0)); + pglNormalPointer(GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 3)); + pglTexCoordPointer(2, GL_FLOAT, sizeof(vbo64_t), BUFFER_OFFSET(sizeof(float) * 6)); - pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); - pglBindBuffer(GL_ARRAY_BUFFER, 0); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + // No tinyframes, no mesh indices + //pglDrawElements(GL_TRIANGLES, mesh->numTriangles * 3, GL_UNSIGNED_SHORT, mesh->indices); + pglBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + pglVertexPointer(3, GL_FLOAT, 0, frame->vertices); + pglNormalPointer(GL_FLOAT, 0, frame->normals); + pglTexCoordPointer(2, GL_FLOAT, 0, mesh->uvs); + pglDrawArrays(GL_TRIANGLES, 0, mesh->numTriangles * 3); + } } else { @@ -3037,6 +2776,7 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 AllocLerpBuffer(mesh->numVertices * sizeof(float) * 3); vertPtr = vertBuffer; normPtr = normBuffer; + //int j = 0; for (j = 0; j < mesh->numVertices * 3; j++) { @@ -3058,14 +2798,23 @@ static void DrawModelEx(model_t *model, INT32 frameIndex, INT32 duration, INT32 pglPopMatrix(); // should be the same as glLoadIdentity pglDisable(GL_CULL_FACE); pglDisable(GL_NORMALIZE); + +#ifdef GL_LIGHT_MODEL_AMBIENT + if (model_lighting) + { + if (!gl_shadersenabled) + pglDisable(GL_LIGHTING); + pglShadeModel(GL_FLAT); + } +#endif } // -----------------+ // HWRAPI DrawModel : Draw a model // -----------------+ -EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, FSurfaceInfo *Surface) +EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, INT32 tics, INT32 nextFrameIndex, FTransform *pos, float scale, UINT8 flipped, UINT8 hflipped, FSurfaceInfo *Surface) { - DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, Surface); + DrawModelEx(model, frameIndex, duration, tics, nextFrameIndex, pos, scale, flipped, hflipped, Surface); } // -----------------+ @@ -3074,16 +2823,14 @@ EXPORT void HWRAPI(DrawModel) (model_t *model, INT32 frameIndex, INT32 duration, EXPORT void HWRAPI(SetTransform) (FTransform *stransform) { static boolean special_splitscreen; - GLdouble used_fov; boolean shearing = false; + float used_fov; + pglLoadIdentity(); + if (stransform) { used_fov = stransform->fovxangle; - shearing = stransform->shearing; - // keep a trace of the transformation for md2 - memcpy(&md2_transform, stransform, sizeof (md2_transform)); - #ifdef USE_FTRANSFORM_MIRROR // mirroring from Kart if (stransform->mirror) @@ -3095,16 +2842,17 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) else pglScalef(stransform->scalex, stransform->scaley, -stransform->scalez); - pglMatrixMode(GL_MODELVIEW); - pglRotatef(stransform->anglex, 1.0f, 0.0f, 0.0f); + if (stransform->roll) + pglRotatef(stransform->rollangle, 0.0f, 0.0f, 1.0f); + pglRotatef(stransform->anglex , 1.0f, 0.0f, 0.0f); pglRotatef(stransform->angley+270.0f, 0.0f, 1.0f, 0.0f); pglTranslatef(-stransform->x, -stransform->z, -stransform->y); special_splitscreen = (stransform->splitscreen == 1); + shearing = stransform->shearing; } else { - //Hurdler: is "fov" correct? used_fov = fov; pglScalef(1.0f, 1.0f, -1.0f); } @@ -3117,33 +2865,49 @@ EXPORT void HWRAPI(SetTransform) (FTransform *stransform) // https://zdoom.org/wiki/Y-shearing if (shearing) { - float dy = FIXED_TO_FLOAT(AIMINGTODY(stransform->viewaiming)) * 2; //screen_width/BASEVIDWIDTH; - pglTranslatef(0.0f, -dy/BASEVIDHEIGHT, 0.0f); + float fdy = stransform->viewaiming * 2; + if (stransform->flip) + fdy *= -1.0f; + pglTranslatef(0.0f, -fdy/BASEVIDHEIGHT, 0.0f); } if (special_splitscreen) { - used_fov = atan(tan(used_fov*M_PIl/360)*0.8)*360/M_PIl; - GLPerspective((GLfloat)used_fov, 2*ASPECT_RATIO); + used_fov = atan(tan(used_fov*M_PI/360)*0.8)*360/M_PI; + GLPerspective(used_fov, 2*ASPECT_RATIO); } else - GLPerspective((GLfloat)used_fov, ASPECT_RATIO); + GLPerspective(used_fov, ASPECT_RATIO); + pglGetFloatv(GL_PROJECTION_MATRIX, projMatrix); // added for new coronas' code (without depth buffer) pglMatrixMode(GL_MODELVIEW); pglGetFloatv(GL_MODELVIEW_MATRIX, modelMatrix); // added for new coronas' code (without depth buffer) + } EXPORT INT32 HWRAPI(GetTextureUsed) (void) { - FTextureInfo* tmp = gr_cachehead; - INT32 res = 0; + FTextureInfo *tmp = gl_cachehead; + INT32 res = 0; while (tmp) { - res += tmp->height*tmp->width*(screen_depth/8); + // Figure out the correct bytes-per-pixel for this texture + // I don't know which one the game actually _uses_ but this + // follows format2bpp in hw_cache.c + int bpp = 1; + int format = tmp->format; + if (format == GL_TEXFMT_RGBA) + bpp = 4; + else if (format == GL_TEXFMT_ALPHA_INTENSITY_88 || format == GL_TEXFMT_AP_88) + bpp = 2; + + // Add it up! + res += tmp->height*tmp->width*bpp; tmp = tmp->nextmipmap; } + return res; } @@ -3162,7 +2926,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) 16.0f, -16.0f, 6.0f }; - // Use a power of two texture + // Use a power of two texture, dammit if(screen_width <= 1024) texsize = 1024; if(screen_width <= 512) @@ -3175,6 +2939,8 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) pglDisable(GL_DEPTH_TEST); pglDisable(GL_BLEND); + // const float blackBack[16] + // Draw a black square behind the screen texture, // so nothing shows through the edges pglColor4ubv(white); @@ -3198,6 +2964,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) float_nextx = (float)(x+1)/(xfix); float_nexty = (float)(y+1)/(yfix); + // float stCoords[8]; stCoords[0] = float_x; stCoords[1] = float_y; stCoords[2] = float_x; @@ -3209,6 +2976,7 @@ EXPORT void HWRAPI(PostImgRedraw) (float points[SCREENVERTS][SCREENVERTS][2]) pglTexCoordPointer(2, GL_FLOAT, 0, stCoords); + // float vertCoords[12]; vertCoords[0] = points[x][y][0]; vertCoords[1] = points[x][y][1]; vertCoords[2] = 4.4f; @@ -3240,7 +3008,6 @@ EXPORT void HWRAPI(FlushScreenTextures) (void) pglDeleteTextures(1, &startScreenWipe); pglDeleteTextures(1, &endScreenWipe); pglDeleteTextures(1, &finalScreenTexture); - screentexture = 0; startScreenWipe = 0; endScreenWipe = 0; @@ -3309,6 +3076,7 @@ EXPORT void HWRAPI(EndScreenWipe)(void) tex_downloaded = endScreenWipe; } + // Draw the last scene under the intermission EXPORT void HWRAPI(DrawIntermissionBG)(void) { @@ -3333,6 +3101,9 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); + // const float screenVerts[12] + + // float fix[8]; fix[0] = 0.0f; fix[1] = 0.0f; fix[2] = 0.0f; @@ -3343,8 +3114,10 @@ EXPORT void HWRAPI(DrawIntermissionBG)(void) fix[7] = 0.0f; pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + pglBindTexture(GL_TEXTURE_2D, screentexture); pglColor4ubv(white); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); @@ -3387,6 +3160,9 @@ EXPORT void HWRAPI(DoScreenWipe)(void) xfix = 1/((float)(texsize)/((float)((screen_width)))); yfix = 1/((float)(texsize)/((float)((screen_height)))); + // const float screenVerts[12] + + // float fix[8]; fix[0] = 0.0f; fix[1] = 0.0f; fix[2] = 0.0f; @@ -3398,7 +3174,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void) pglClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - SetBlend(PF_Modulated|PF_NoDepthTest); + SetBlend(PF_Modulated|PF_NoDepthTest|PF_Clip|PF_NoZClip); pglEnable(GL_TEXTURE_2D); // Draw the original screen @@ -3408,7 +3184,7 @@ EXPORT void HWRAPI(DoScreenWipe)(void) pglVertexPointer(3, GL_FLOAT, 0, screenVerts); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest); + SetBlend(PF_Modulated|PF_Translucent|PF_NoDepthTest|PF_Clip|PF_NoZClip); // Draw the end screen that fades in pglActiveTexture(GL_TEXTURE0); @@ -3422,6 +3198,8 @@ EXPORT void HWRAPI(DoScreenWipe)(void) pglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + // const float defaultST[8] + pglClientActiveTexture(GL_TEXTURE0); pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, screenVerts); @@ -3531,6 +3309,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) yoff = newaspect / origaspect; } + // float off[12]; off[0] = -xoff; off[1] = -yoff; off[2] = 1.0f; @@ -3544,7 +3323,7 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) off[10] = -yoff; off[11] = 1.0f; - + // float fix[8]; fix[0] = 0.0f; fix[1] = 0.0f; fix[2] = 0.0f; @@ -3562,11 +3341,11 @@ EXPORT void HWRAPI(DrawScreenFinalTexture)(int width, int height) pglBindTexture(GL_TEXTURE_2D, finalScreenTexture); pglColor4ubv(white); + pglTexCoordPointer(2, GL_FLOAT, 0, fix); pglVertexPointer(3, GL_FLOAT, 0, off); pglDrawArrays(GL_TRIANGLE_FAN, 0, 4); - tex_downloaded = finalScreenTexture; } diff --git a/src/hardware/r_opengl/r_opengl.h b/src/hardware/r_opengl/r_opengl.h index 6d11bf4e3..f44e0818b 100644 --- a/src/hardware/r_opengl/r_opengl.h +++ b/src/hardware/r_opengl/r_opengl.h @@ -57,6 +57,15 @@ #undef DEBUG_TO_FILE // maybe defined in previous *.h #define DEBUG_TO_FILE // output debugging msgs to ogllog.txt +// todo: find some way of getting SDL to log to ogllog.txt, without +// interfering with r_opengl.dll +#ifdef HAVE_SDL +#undef DEBUG_TO_FILE +#endif +//#if defined(HAVE_SDL) && !defined(_DEBUG) +//#undef DEBUG_TO_FILE +//#endif + #ifdef DEBUG_TO_FILE extern FILE *gllogstream; #endif @@ -73,10 +82,6 @@ void Flush(void); INT32 isExtAvailable(const char *extension, const GLubyte *start); void SetModelView(GLint w, GLint h); void SetStates(void); -#ifdef USE_PALETTED_TEXTURE -extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; -extern GLubyte palette_tex[256*3]; -#endif #ifndef GL_EXT_texture_filter_anisotropic #define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE diff --git a/src/http-mserv.c b/src/http-mserv.c index 9d05b80e5..68851483a 100644 --- a/src/http-mserv.c +++ b/src/http-mserv.c @@ -1,4 +1,4 @@ -// SONIC ROBO BLAST 2 KART +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2020 by James R. // @@ -11,10 +11,12 @@ /* Documentation available here. - + */ +#ifdef HAVE_CURL #include +#endif #include "doomdef.h" #include "d_clisrv.h" @@ -34,20 +36,25 @@ Documentation available here. static void MasterServer_Debug_OnChange (void); -consvar_t cv_masterserver_timeout = { - "masterserver_timeout", "5", CV_SAVE, CV_Unsigned, - NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */ -}; +consvar_t cv_masterserver_timeout = CVAR_INIT +( + "masterserver_timeout", "5", CV_SAVE, CV_Unsigned, + NULL +); -consvar_t cv_masterserver_debug = { +consvar_t cv_masterserver_debug = CVAR_INIT +( "masterserver_debug", "Off", CV_SAVE|CV_CALL, CV_OnOff, - MasterServer_Debug_OnChange, 0, NULL, NULL, 0, 0, NULL/* C90 moment */ -}; + MasterServer_Debug_OnChange +); -consvar_t cv_masterserver_token = { - "masterserver_token", "", CV_SAVE, NULL, - NULL, 0, NULL, NULL, 0, 0, NULL/* C90 moment */ -}; +consvar_t cv_masterserver_token = CVAR_INIT +( + "masterserver_token", "", CV_SAVE, NULL, + NULL +); + +#ifdef MASTERSERVER static int hms_started; @@ -137,7 +144,7 @@ HMS_connect (const char *format, ...) if (cv_masterserver_token.string[0]) { quack_token = curl_easy_escape(curl, cv_masterserver_token.string, 0); - token_length = ( sizeof "?token="-1 )+ strlen(quack_token); + token_length = ( sizeof "&token="-1 )+ strlen(quack_token); } else { @@ -152,7 +159,9 @@ HMS_connect (const char *format, ...) seek = strlen(hms_api) + 1;/* + '/' */ va_start (ap, format); - url = malloc(seek + vsnprintf(0, 0, format, ap) + token_length + 1); + url = malloc(seek + vsnprintf(0, 0, format, ap) + + sizeof "?v=2" - 1 + + token_length + 1); va_end (ap); sprintf(url, "%s/", hms_api); @@ -165,8 +174,11 @@ HMS_connect (const char *format, ...) seek += vsprintf(&url[seek], format, ap); va_end (ap); + strcpy(&url[seek], "?v=2"); + seek += sizeof "?v=2" - 1; + if (quack_token) - sprintf(&url[seek], "?token=%s", quack_token); + sprintf(&url[seek], "&token=%s", quack_token); CONS_Printf("HMS: connecting '%s'...\n", url); @@ -254,117 +266,6 @@ HMS_end (struct HMS_buffer *buffer) free(buffer); } -int -HMS_fetch_rooms (int joining, int query_id) -{ - struct HMS_buffer *hms; - int ok; - - int doing_shit; - - char *id; - char *title; - char *room_motd; - - int id_no; - - char *p; - char *end; - - int i; - - (void)query_id; - - hms = HMS_connect("rooms"); - - if (! hms) - return 0; - - if (HMS_do(hms)) - { - doing_shit = 1; - - p = hms->buffer; - - for (i = 0; i < NUM_LIST_ROOMS && ( end = strstr(p, "\n\n\n") );) - { - *end = '\0'; - - id = strtok(p, "\n"); - title = strtok(0, "\n"); - room_motd = strtok(0, ""); - - if (id && title && room_motd) - { - id_no = atoi(id); - - /* - Don't show the 'All' room if hosting. And it's a hack like this - because I'm way too lazy to add another feature to the MS. - */ - if (joining || id_no != 0) - { -#ifdef HAVE_THREADS - I_lock_mutex(&ms_QueryId_mutex); - { - if (query_id != ms_QueryId) - doing_shit = 0; - } - I_unlock_mutex(ms_QueryId_mutex); - - if (! doing_shit) - break; -#endif - - room_list[i].header.buffer[0] = 1; - - room_list[i].id = id_no; - strlcpy(room_list[i].name, title, sizeof room_list[i].name); - strlcpy(room_list[i].motd, room_motd, sizeof room_list[i].motd); - - i++; - } - - p = ( end + 3 );/* skip the three linefeeds */ - } - else - break; - } - - if (doing_shit) - room_list[i].header.buffer[0] = 0; - - ok = 1; - - if (doing_shit) - { -#ifdef HAVE_THREADS - I_lock_mutex(&m_menu_mutex); -#endif - { - for (i = 0; room_list[i].header.buffer[0]; i++) - { - if(*room_list[i].name != '\0') - { - MP_RoomMenu[i+1].text = room_list[i].name; - roomIds[i] = room_list[i].id; - MP_RoomMenu[i+1].status = IT_STRING|IT_CALL; - } - } - } -#ifdef HAVE_THREADS - I_unlock_mutex(m_menu_mutex); -#endif - } - } - else - ok = 0; - - HMS_end(hms); - - return ok; -} - int HMS_register (void) { @@ -373,29 +274,26 @@ HMS_register (void) char post[256]; - char *title; + char *contact; - hms = HMS_connect("rooms/%d/register", ms_RoomId); + hms = HMS_connect( + "games/%s/%d/servers/register", SRB2APPLICATION, MODVERSION); if (! hms) return 0; - title = curl_easy_escape(hms->curl, cv_servername.string, 0); + contact = curl_easy_escape(hms->curl, cv_server_contact.string, 0); snprintf(post, sizeof post, "port=%d&" - "title=%s&" - "version=%d.%d", + "contact=%s", current_port, - title, - - VERSION, - SUBVERSION + contact ); - curl_free(title); + curl_free(contact); curl_easy_setopt(hms->curl, CURLOPT_POSTFIELDS, post); @@ -469,6 +367,7 @@ HMS_list_servers (void) { struct HMS_buffer *hms; + char *list; char *p; hms = HMS_connect("servers"); @@ -478,46 +377,41 @@ HMS_list_servers (void) if (HMS_do(hms)) { - p = &hms->buffer[strlen(hms->buffer)]; - while (*--p == '\n') - ; + list = curl_easy_unescape(hms->curl, hms->buffer, 0, NULL); - CONS_Printf("%s\n", hms->buffer); + p = strtok(list, "\n"); + + while (p != NULL) + { + CONS_Printf("\x80%s\n", p); + p = strtok(NULL, "\n"); + } + + curl_free(list); } HMS_end(hms); } msg_server_t * -HMS_fetch_servers (msg_server_t *list, int room_number, int query_id) +HMS_fetch_servers (msg_server_t *list, int query_id) { struct HMS_buffer *hms; int doing_shit; - char local_version[9]; - - char *room; - char *address; char *port; - char *title; - char *version; + char *contact; char *end; - char *section_end; char *p; int i; (void)query_id; - if (room_number > 0) - { - hms = HMS_connect("rooms/%d/servers", room_number); - } - else - hms = HMS_connect("servers"); + hms = HMS_connect("games/%s/%d/servers", SRB2APPLICATION, MODVERSION); if (! hms) return NULL; @@ -526,81 +420,51 @@ HMS_fetch_servers (msg_server_t *list, int room_number, int query_id) { doing_shit = 1; - snprintf(local_version, sizeof local_version, - "%d.%d", - VERSION, - SUBVERSION - ); - p = hms->buffer; i = 0; - do + while (i < MAXSERVERLIST && ( end = strchr(p, '\n') )) { - section_end = strstr(p, "\n\n"); + *end = '\0'; - room = strtok(p, "\n"); + address = strtok(p, " "); + port = strtok(0, " "); + contact = strtok(0, ""); - p = strtok(0, ""); - - if (! p) - break; - - while (i < MAXSERVERLIST && ( end = strchr(p, '\n') )) + if (address && port) { - *end = '\0'; - - address = strtok(p, " "); - port = strtok(0, " "); - title = strtok(0, " "); - version = strtok(0, ""); - - if (address && port && title && version) - { #ifdef HAVE_THREADS - I_lock_mutex(&ms_QueryId_mutex); - { - if (query_id != ms_QueryId) - doing_shit = 0; - } - I_unlock_mutex(ms_QueryId_mutex); + I_lock_mutex(&ms_QueryId_mutex); + { + if (query_id != ms_QueryId) + doing_shit = 0; + } + I_unlock_mutex(ms_QueryId_mutex); - if (! doing_shit) - break; + if (! doing_shit) + break; #endif - if (strcmp(version, local_version) == 0) - { - strlcpy(list[i].ip, address, sizeof list[i].ip); - strlcpy(list[i].port, port, sizeof list[i].port); - strlcpy(list[i].name, title, sizeof list[i].name); - strlcpy(list[i].version, version, sizeof list[i].version); + strlcpy(list[i].ip, address, sizeof list[i].ip); + strlcpy(list[i].port, port, sizeof list[i].port); - list[i].room = atoi(room); - - list[i].header.buffer[0] = 1; - - i++; - } - - if (end == section_end)/* end of list for this room */ - break; - else - p = ( end + 1 );/* skip server delimiter */ - } - else + if (contact) { - section_end = 0;/* malformed so quit the parsing */ - break; + strlcpy(list[i].contact, contact, sizeof list[i].contact); } + + list[i].header.buffer[0] = 1; + + i++; + + p = ( end + 1 );/* skip server delimiter */ } - - if (! doing_shit) + else + { + /* malformed so quit the parsing */ break; - - p = ( section_end + 2 ); + } } - while (section_end) ; if (doing_shit) list[i].header.buffer[0] = 0; @@ -622,7 +486,7 @@ HMS_compare_mod_version (char *buffer, size_t buffer_size) char *version; char *version_name; - hms = HMS_connect("versions/%d", MODID); + hms = HMS_connect("games/%s/version", SRB2APPLICATION); if (! hms) return 0; @@ -651,6 +515,19 @@ HMS_compare_mod_version (char *buffer, size_t buffer_size) return ok; } +static char * +Strip_trailing_slashes (char *api) +{ + char * p = &api[strlen(api)]; + + while (*--p == '/') + ; + + p[1] = '\0'; + + return api; +} + void HMS_set_api (char *api) { @@ -659,17 +536,21 @@ HMS_set_api (char *api) #endif { free(hms_api); - hms_api = api; + hms_api = Strip_trailing_slashes(api); } #ifdef HAVE_THREADS I_unlock_mutex(hms_api_mutex); #endif } +#endif/*MASTERSERVER*/ + static void MasterServer_Debug_OnChange (void) { +#ifdef MASTERSERVER /* TODO: change to 'latest-log.txt' for log files revision. */ if (cv_masterserver_debug.value) CONS_Printf("Master server debug messages will appear in log.txt\n"); +#endif } diff --git a/src/hu_stuff.c b/src/hu_stuff.c index 19a049b12..35f977bd6 100644 --- a/src/hu_stuff.c +++ b/src/hu_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,6 +18,7 @@ #include "m_menu.h" // gametype_cons_t #include "m_cond.h" // emblems +#include "m_misc.h" // word jumping #include "d_clisrv.h" @@ -47,14 +48,14 @@ #include "hardware/hw_main.h" #endif -#ifdef HAVE_BLUA #include "lua_hud.h" #include "lua_hook.h" -#endif +// SRB2Kart #include "s_sound.h" // song credits #include "k_kart.h" #include "k_color.h" +#include "k_hud.h" // coords are scaled #define HU_INPUTX 0 @@ -89,22 +90,18 @@ patch_t *rmatcico; patch_t *bmatcico; patch_t *tagico; patch_t *tallminus; +patch_t *tallinfin; //------------------------------------------- // coop hud //------------------------------------------- -patch_t *emeraldpics[7]; -patch_t *tinyemeraldpics[7]; static patch_t *emblemicon; -static patch_t *tokenicon; //------------------------------------------- // misc vars //------------------------------------------- -// crosshair 0 = off, 1 = cross, 2 = angle, 3 = point, see m_menu.c -static patch_t *crosshair[HU_CROSSHAIRS]; // 3 precached crosshair graphics // song credits static patch_t *songcreditbg; @@ -190,31 +187,7 @@ void HU_LoadGraphics(void) // minus for negative tallnums tallminus = HU_CachePatch("STTMINUS"); - // cache the crosshairs, don't bother to know which one is being used, - // just cache all 3, they're so small anyway. - for (i = 0; i < HU_CROSSHAIRS; i++) - { - crosshair[i] = HU_CachePatch("CROSHAI%c", '1'+i); - } - emblemicon = HU_CachePatch("EMBLICON"); - tokenicon = HU_CachePatch("TOKNICON"); - - emeraldpics[0] = HU_CachePatch("CHAOS1"); - emeraldpics[1] = HU_CachePatch("CHAOS2"); - emeraldpics[2] = HU_CachePatch("CHAOS3"); - emeraldpics[3] = HU_CachePatch("CHAOS4"); - emeraldpics[4] = HU_CachePatch("CHAOS5"); - emeraldpics[5] = HU_CachePatch("CHAOS6"); - emeraldpics[6] = HU_CachePatch("CHAOS7"); - tinyemeraldpics[0] = HU_CachePatch("TEMER1"); - tinyemeraldpics[1] = HU_CachePatch("TEMER2"); - tinyemeraldpics[2] = HU_CachePatch("TEMER3"); - tinyemeraldpics[3] = HU_CachePatch("TEMER4"); - tinyemeraldpics[4] = HU_CachePatch("TEMER5"); - tinyemeraldpics[5] = HU_CachePatch("TEMER6"); - tinyemeraldpics[6] = HU_CachePatch("TEMER7"); - songcreditbg = HU_CachePatch("K_SONGCR"); // cache ping gfx: @@ -445,7 +418,7 @@ void HU_AddChatText(const char *text, boolean playsound) static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) { - XBOXSTATIC char buf[254]; + char buf[254]; size_t numwords, ix; char *msg = &buf[2]; const size_t msgspace = sizeof buf - 2; @@ -481,39 +454,35 @@ static void DoSayCommand(SINT8 target, size_t usedargs, UINT8 flags) if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { - // what we're gonna do now is check if the node exists + // what we're gonna do now is check if the player exists // with that logic, characters 4 and 5 are our numbers: const char *newmsg; - INT32 spc = 1; // used if nodenum[1] is a space. - char *nodenum = (char*) malloc(3); - strncpy(nodenum, msg+3, 3); + char playernum[3]; + INT32 spc = 1; // used if playernum[1] is a space. + + strncpy(playernum, msg+3, 3); + // check for undesirable characters in our "number" - if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) + if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9'))) { - // check if nodenum[1] is a space - if (nodenum[1] == ' ') + // check if playernum[1] is a space + if (playernum[1] == ' ') spc = 0; - // let it slide + // let it slide else { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); - free(nodenum); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); return; } } // I'm very bad at C, I swear I am, additional checks eww! - if (spc != 0) - { - if (msg[5] != ' ') - { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); - free(nodenum); - return; - } - } + if (spc != 0 && msg[5] != ' ') + { + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); + return; + } - target = atoi((const char*) nodenum); // turn that into a number - free(nodenum); + target = atoi(playernum); // turn that into a number //CONS_Printf("%d\n", target); // check for target player, if it doesn't exist then we can't send the message! @@ -644,13 +613,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) M_GetText("Illegal say command received from %s while muted\n") : M_GetText("Illegal csay command received from non-admin %s\n"), player_names[playernum]); if (server) - { - XBOXSTATIC UINT8 buf[2]; - - buf[0] = (UINT8)playernum; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - } + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } @@ -664,13 +627,7 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) { CONS_Alert(CONS_WARNING, M_GetText("Illegal say command received from %s containing invalid characters\n"), player_names[playernum]); if (server) - { - XBOXSTATIC char buf[2]; - - buf[0] = (char)playernum; - buf[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &buf, 2); - } + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); return; } } @@ -690,10 +647,8 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) // run the lua hook even if we were supposed to eat the msg, netgame consistency goes first. -#ifdef HAVE_BLUA if (LUAh_PlayerMsg(playernum, target, flags, msg, spam_eatmsg)) return; -#endif if (spam_eatmsg) return; // don't proceed if we were supposed to eat the message. @@ -761,10 +716,19 @@ static void Got_Saycmd(UINT8 **p, INT32 playernum) } else { - sprintf(color_prefix, "%c", '\x80' + (K_SkincolorToTextColor(players[playernum].skincolor) >> V_CHARCOLORSHIFT)); + UINT16 chatcolor = skincolors[players[playernum].skincolor].chatcolor; + + if (chatcolor > V_TANMAP) + { + sprintf(color_prefix, "%c", '\x80'); + } + else + { + sprintf(color_prefix, "%c", '\x80' + (chatcolor >> V_CHARCOLORSHIFT)); + } + cstart = color_prefix; } - prefix = cstart; // Give admins and remote admins their symbols. @@ -911,7 +875,7 @@ void HU_Ticker(void) hu_tick++; hu_tick &= 7; // currently only to blink chat input cursor - if (PLAYER1INPUTDOWN(gc_scores)) + if (PlayerInputDown(1, gc_scores)) hu_showscores = !chat_on; else hu_showscores = false; @@ -920,9 +884,6 @@ void HU_Ticker(void) #ifndef NONET static boolean teamtalk = false; -/*static char chatchars[QUEUESIZE]; -static INT32 head = 0, tail = 0;*/ -// WHY DO YOU OVERCOMPLICATE EVERYTHING????????? // Clear spaces so we don't end up with messages only made out of emptiness static boolean HU_clearChatSpaces(void) @@ -986,11 +947,11 @@ static void HU_queueChatChar(INT32 c) if (strlen(msg) > 4 && strnicmp(msg, "/pm", 3) == 0) // used /pm { - INT32 spc = 1; // used if nodenum[1] is a space. - char *nodenum = (char*) malloc(3); + INT32 spc = 1; // used if playernum[1] is a space. + char playernum[3]; const char *newmsg; - // what we're gonna do now is check if the node exists + // what we're gonna do now is check if the player exists // with that logic, characters 4 and 5 are our numbers: // teamtalk can't send PMs, just don't send it, else everyone would be able to see it, and no one wants to see your sex RP sicko. @@ -1000,19 +961,18 @@ static void HU_queueChatChar(INT32 c) return; } - strncpy(nodenum, msg+3, 3); + strncpy(playernum, msg+3, 3); // check for undesirable characters in our "number" - if (((nodenum[0] < '0') || (nodenum[0] > '9')) || ((nodenum[1] < '0') || (nodenum[1] > '9'))) + if (((playernum[0] < '0') || (playernum[0] > '9')) || ((playernum[1] < '0') || (playernum[1] > '9'))) { - // check if nodenum[1] is a space - if (nodenum[1] == ' ') + // check if playernum[1] is a space + if (playernum[1] == ' ') spc = 0; // let it slide else { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); - free(nodenum); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); return; } } @@ -1021,14 +981,12 @@ static void HU_queueChatChar(INT32 c) { if (msg[5] != ' ') { - HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); - free(nodenum); + HU_AddChatText("\x82NOTICE: \x80Invalid command format. Correct format is \'/pm \'.", false); return; } } - target = atoi((const char*) nodenum); // turn that into a number - free(nodenum); + target = atoi(playernum); // turn that into a number //CONS_Printf("%d\n", target); // check for target player, if it doesn't exist then we can't send the message! @@ -1040,7 +998,7 @@ static void HU_queueChatChar(INT32 c) return; } - // we need to get rid of the /pm + // we need to get rid of the /pm newmsg = msg+5+spc; strlcpy(msg, newmsg, 255); } @@ -1066,6 +1024,8 @@ void HU_clearChatChars(void) w_chat[i] = 0; // reset this. chat_on = false; c_input = 0; + + I_UpdateMouseGrab(); } #ifndef NONET @@ -1097,7 +1057,7 @@ boolean HU_Responder(event_t *ev) INT32 i; for (i = 0; i < num_gamecontrols; i++) { - if (gamecontrol[i][0] == ev->data1 || gamecontrol[i][1] == ev->data1) + if (gamecontrol[0][i][0] == ev->data1 || gamecontrol[0][i][1] == ev->data1) break; } @@ -1109,7 +1069,7 @@ boolean HU_Responder(event_t *ev) if (!chat_on) { // enter chat mode - if ((ev->data1 == gamecontrol[gc_talkkey][0] || ev->data1 == gamecontrol[gc_talkkey][1]) + if ((ev->data1 == gamecontrol[0][gc_talkkey][0] || ev->data1 == gamecontrol[0][gc_talkkey][1]) && netgame && !OLD_MUTE) // check for old chat mute, still let the players open the chat incase they want to scroll otherwise. { chat_on = true; @@ -1119,7 +1079,7 @@ boolean HU_Responder(event_t *ev) typelines = 1; return true; } - if ((ev->data1 == gamecontrol[gc_teamkey][0] || ev->data1 == gamecontrol[gc_teamkey][1]) + if ((ev->data1 == gamecontrol[0][gc_teamkey][0] || ev->data1 == gamecontrol[0][gc_teamkey][1]) && netgame && !OLD_MUTE) { chat_on = true; @@ -1144,8 +1104,8 @@ boolean HU_Responder(event_t *ev) // Ignore non-keyboard keys, except when the talk key is bound if (ev->data1 >= KEY_MOUSE1 - && (ev->data1 != gamecontrol[gc_talkkey][0] - && ev->data1 != gamecontrol[gc_talkkey][1])) + && (ev->data1 != gamecontrol[0][gc_talkkey][0] + && ev->data1 != gamecontrol[0][gc_talkkey][1])) return false; c = CON_ShiftChar(c); @@ -1204,14 +1164,16 @@ boolean HU_Responder(event_t *ev) chat_on = false; c_input = 0; // reset input cursor chat_scrollmedown = true; // you hit enter, so you might wanna autoscroll to see what you just sent. :) + I_UpdateMouseGrab(); } else if (c == KEY_ESCAPE - || ((c == gamecontrol[gc_talkkey][0] || c == gamecontrol[gc_talkkey][1] - || c == gamecontrol[gc_teamkey][0] || c == gamecontrol[gc_teamkey][1]) + || ((c == gamecontrol[0][gc_talkkey][0] || c == gamecontrol[0][gc_talkkey][1] + || c == gamecontrol[0][gc_teamkey][0] || c == gamecontrol[0][gc_teamkey][1]) && c >= KEY_MOUSE1)) // If it's not a keyboard key, then the chat button is used as a toggle. { chat_on = false; c_input = 0; // reset input cursor + I_UpdateMouseGrab(); } else if ((c == KEY_UPARROW || c == KEY_MOUSEWHEELUP) && chat_scroll > 0 && !OLDCHAT) // CHAT SCROLLING YAYS! { @@ -1226,9 +1188,19 @@ boolean HU_Responder(event_t *ev) chat_scrolltime = 4; } else if (c == KEY_LEFTARROW && c_input != 0 && !OLDCHAT) // i said go back - c_input--; + { + if (ctrldown) + c_input = M_JumpWordReverse(w_chat, c_input); + else + c_input--; + } else if (c == KEY_RIGHTARROW && c_input < strlen(w_chat) && !OLDCHAT) // don't need to check for admin or w/e here since the chat won't ever contain anything if it's muted. - c_input++; + { + if (ctrldown) + c_input += M_JumpWord(&w_chat[c_input]); + else + c_input++; + } return true; } #endif @@ -1299,7 +1271,7 @@ static char *CHAT_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) // 30/7/18: chaty is now the distance at which the lowest point of the chat will be drawn if that makes any sense. -INT16 chatx = 13, chaty = 169; // let's use this as our coordinates, shh +INT16 chatx = 13, chaty = 169; // let's use this as our coordinates // chat stuff by VincyTM LOL XD! @@ -1368,6 +1340,7 @@ static void HU_drawMiniChat(void) dy = 0; dx = 0; msglines += linescount+1; + if (msg) Z_Free(msg); } @@ -1383,7 +1356,9 @@ static void HU_drawMiniChat(void) } else #endif + { y -= (cv_kartspeedometer.value ? 16 : 0); + } dx = 0; dy = 0; @@ -1442,6 +1417,7 @@ static void HU_drawMiniChat(void) } dy += charheight; dx = 0; + if (msg) Z_Free(msg); } @@ -1482,13 +1458,15 @@ static void HU_drawChatLog(INT32 offset) if (r_splitscreen) { y -= BASEVIDHEIGHT/2; + if (r_splitscreen > 1) y += 16; } else #endif + { y -= (cv_kartspeedometer.value ? 16 : 0); - + } chat_topy = y + chat_scroll*charheight; chat_bottomy = chat_topy + boxh*charheight; @@ -1539,6 +1517,7 @@ static void HU_drawChatLog(INT32 offset) } dy += charheight; dx = 0; + if (msg) Z_Free(msg); } @@ -1550,18 +1529,16 @@ static void HU_drawChatLog(INT32 offset) } chat_scrollmedown = false; - // getmaxscroll through a lazy hack. We do all these loops, so let's not do more loops that are gonna lag the game more. :P - chat_maxscroll = (dy/charheight); // welcome to C, we don't know what min() and max() are. - if (chat_maxscroll <= (UINT32)boxh) - chat_maxscroll = 0; - else - chat_maxscroll -= boxh; + // getmaxscroll through a lazy hack. We do all these loops, + // so let's not do more loops that are gonna lag the game more. :P + chat_maxscroll = max(dy / charheight - cv_chatheight.value, 0); // if we're not bound by the time, autoscroll for next frame: if (atbottom) chat_scroll = chat_maxscroll; // draw arrows to indicate that we can (or not) scroll. + // account for Y = -1 offset in tinyfont if (chat_scroll > 0) V_DrawCharacter(chatx-9, ((justscrolledup) ? (chat_topy-1) : (chat_topy)), V_SNAPTOBOTTOM | V_SNAPTOLEFT | highlight | '\x1A', false); // up arrow if (chat_scroll < chat_maxscroll) @@ -1600,7 +1577,9 @@ static void HU_DrawChat(void) } else #endif + { y -= (cv_kartspeedometer.value ? 16 : 0); + } if (teamtalk) { @@ -1694,26 +1673,24 @@ static void HU_DrawChat(void) } else #endif + { p_dispy -= (cv_kartspeedometer.value ? 16 : 0); + } i = 0; for(i=0; (i '9'))) || ((w_chat[4] != 0) && (((w_chat[4] < '0') || (w_chat[4] > '9'))))) && (w_chat[4] != ' ')) break; - - nodenum = (char*) malloc(3); - strncpy(nodenum, w_chat+3, 3); - n = atoi((const char*) nodenum); // turn that into a number - free(nodenum); + strncpy(playernum, w_chat+3, 3); + n = atoi(playernum); // turn that into a number // special cases: if ((n == 0) && !(w_chat[4] == '0')) @@ -1833,175 +1810,19 @@ static void HU_DrawChat_Old(void) y += charheight; } } + + if (hu_tick < 4) + V_DrawCharacter(HU_INPUTX + c, y, '_' | cv_constextsize.value |V_NOSCALESTART|t, true); } #endif -// draw the Crosshair, at the exact center of the view. -// -// Crosshairs are pre-cached at HU_Init - -/*static inline void HU_DrawCrosshair(void) -{ - INT32 i, x, y; - - i = cv_crosshair.value & 3; - if (!i) - return; - - if ((netgame || multiplayer) && players[displayplayers[0]].spectator) - return; - -#ifdef HWRENDER - if (rendermode != render_soft) - { - x = (INT32)gr_basewindowcenterx; - y = (INT32)gr_basewindowcentery; - } - else -#endif - { - x = viewwindowx + (viewwidth>>1); - y = viewwindowy + (viewheight>>1); - } - - V_DrawScaledPatch(x, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); -} - -static inline void HU_DrawCrosshair2(void) -{ - INT32 i, x, y; - - i = cv_crosshair2.value & 3; - if (!i) - return; - - if ((netgame || multiplayer) && players[displayplayers[1]].spectator) - return; - -#ifdef HWRENDER - if (rendermode != render_soft) - { - x = (INT32)gr_basewindowcenterx; - y = (INT32)gr_basewindowcentery; - } - else -#endif - { - x = viewwindowx + (viewwidth>>1); - y = viewwindowy + (viewheight>>1); - } - - if (splitscreen) - { - if (splitscreen > 1) -#ifdef HWRENDER - if (rendermode != render_soft) - x += (INT32)gr_viewwidth; - else -#endif - x += viewwidth; - else - { -#ifdef HWRENDER - if (rendermode != render_soft) - y += (INT32)gr_viewheight; - else -#endif - y += viewheight; - } - - V_DrawScaledPatch(x, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); - } -} - -static inline void HU_DrawCrosshair3(void) -{ - INT32 i, x, y; - - i = cv_crosshair3.value & 3; - if (!i) - return; - - if ((netgame || multiplayer) && players[displayplayers[2]].spectator) - return; - -#ifdef HWRENDER - if (rendermode != render_soft) - { - x = (INT32)gr_basewindowcenterx; - y = (INT32)gr_basewindowcentery; - } - else -#endif - { - x = viewwindowx + (viewwidth>>1); - y = viewwindowy + (viewheight>>1); - } - - if (splitscreen > 1) - { -#ifdef HWRENDER - if (rendermode != render_soft) - y += (INT32)gr_viewheight; - else -#endif - y += viewheight; - - V_DrawScaledPatch(x, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); - } -} - -static inline void HU_DrawCrosshair4(void) -{ - INT32 i, x, y; - - i = cv_crosshair4.value & 3; - if (!i) - return; - - if ((netgame || multiplayer) && players[displayplayers[3]].spectator) - return; - -#ifdef HWRENDER - if (rendermode != render_soft) - { - x = (INT32)gr_basewindowcenterx; - y = (INT32)gr_basewindowcentery; - } - else -#endif - { - x = viewwindowx + (viewwidth>>1); - y = viewwindowy + (viewheight>>1); - } - - if (splitscreen > 2) - { -#ifdef HWRENDER - if (rendermode != render_soft) - { - x += (INT32)gr_viewwidth; - y += (INT32)gr_viewheight; - } - else -#endif - { - x += viewwidth; - y += viewheight; - } - - V_DrawScaledPatch(x, y, V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, crosshair[i - 1]); - } -}*/ - static void HU_DrawCEcho(void) { INT32 i = 0; INT32 y = (BASEVIDHEIGHT/2)-4; INT32 pnumlines = 0; - UINT32 realflags = cechoflags; - INT32 realalpha = (INT32)((cechoflags & V_ALPHAMASK) >> V_ALPHASHIFT); + UINT32 realflags = cechoflags|V_SPLITSCREEN; // requested as part of splitscreen's stuff char *line; char *echoptr; @@ -2021,15 +1842,6 @@ static void HU_DrawCEcho(void) return; } - // Automatic fadeout - if (realflags & V_AUTOFADEOUT) - { - UINT32 tempalpha = (UINT32)max((INT32)(10 - cechotimer), realalpha); - - realflags &= ~V_ALPHASHIFT; - realflags |= (tempalpha << V_ALPHASHIFT); - } - strcpy(temp, cechotext); echoptr = &temp[0]; @@ -2142,6 +1954,9 @@ void HU_DrawSongCredits(void) // void HU_Drawer(void) { + if (needpatchrecache) + R_ReloadHUDGraphics(); + if (cv_vhseffect.value && (paused || (demo.playback && cv_playbackspeed.value > 1))) V_DrawVhsEffect(demo.rewinding); @@ -2155,7 +1970,7 @@ void HU_Drawer(void) if (!OLDCHAT) HU_DrawChat(); else - HU_DrawChat_Old(); // why the fuck......................... + HU_DrawChat_Old(); } else { @@ -2193,7 +2008,7 @@ void HU_Drawer(void) if (!( Playing() || demo.playback ) || gamestate == GS_INTERMISSION || gamestate == GS_CUTSCENE || gamestate == GS_CREDITS || gamestate == GS_EVALUATION - || gamestate == GS_GAMEEND + || gamestate == GS_ENDING || gamestate == GS_GAMEEND || gamestate == GS_VOTING || gamestate == GS_WAITINGPLAYERS) // SRB2kart return; @@ -2202,14 +2017,11 @@ void HU_Drawer(void) { if (netgame || multiplayer) { -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_rankings)) -#endif HU_DrawRankings(); -#ifdef HAVE_BLUA - LUAh_ScoresHUD(); -#endif + LUAh_ScoresHUD(); } + if (demo.playback) { HU_DrawDemoInfo(); @@ -2219,22 +2031,6 @@ void HU_Drawer(void) if (gamestate != GS_LEVEL) return; - // draw the crosshair, not when viewing demos nor with chasecam - /*if (!automapactive && !demo.playback) - { - if (cv_crosshair.value && !camera[0].chase && !players[displayplayers[0]].spectator) - HU_DrawCrosshair(); - - if (cv_crosshair2.value && !camera[1].chase && !players[displayplayers[1]].spectator) - HU_DrawCrosshair2(); - - if (cv_crosshair3.value && !camera[2].chase && !players[displayplayers[2]].spectator) - HU_DrawCrosshair3(); - - if (cv_crosshair4.value && !camera[3].chase && !players[displayplayers[3]].spectator) - HU_DrawCrosshair4(); - }*/ - // draw song credits if (cv_songcredits.value && !( hu_showscores && (netgame || multiplayer) )) HU_DrawSongCredits(); @@ -2254,6 +2050,21 @@ void HU_Drawer(void) V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_YELLOWMAP | V_ALLOWLOWERCASE, resynch_text); } + + if (modeattacking && pausedelay > 0 && !pausebreakkey) + { + INT32 strength = ((pausedelay - 1 - NEWTICRATE/2)*10)/(NEWTICRATE/3); + INT32 y = hudinfo[HUD_LIVES].y - 13; + + V_DrawThinString(hudinfo[HUD_LIVES].x-2, y, + hudinfo[HUD_LIVES].f|((leveltime & 4) ? V_SKYMAP : V_BLUEMAP), + "HOLD TO RETRY..."); + + if (strength > 9) + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 0); + else if (strength > 0) + V_DrawFadeScreen(0, strength); + } } //====================================================================== @@ -2381,360 +2192,6 @@ HU_drawMiniPing (INT32 x, INT32 y, UINT32 ping, INT32 flags) V_DrawScaledPatch(x, y, flags, patch); } -// -// HU_DrawTabRankings -- moved to k_kart.c -// - -// -// HU_DrawTeamTabRankings -// -/*void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer) -{ - INT32 i,x,y; - INT32 redplayers = 0, blueplayers = 0; - boolean smol = false; - const UINT8 *colormap; - char name[MAXPLAYERNAME+1]; - - // before we draw, we must count how many players are in each team. It makes an additional loop, but we need to know if we have to draw a big or a small ranking. - for (i = 0; i < MAXPLAYERS; i++) - { - if (players[tab[i].num].spectator) - continue; //ignore them. - - if (tab[i].color == skincolor_redteam) //red - { - if (redplayers++ > 8) - { - smol = true; - break; // don't make more loops than we need to. - } - } - else if (tab[i].color == skincolor_blueteam) //blue - { - if (blueplayers++ > 8) - { - smol = true; - break; - } - } - else //er? not on red or blue, so ignore them - continue; - - } - - // I'll be blunt with you, this may add more lines, but I'm not adding weird cases for this, so we're executing a separate function. - if (smol == true || cv_compactscoreboard.value) - { - HU_Draw32TeamTabRankings(tab, whiteplayer); - return; - } - - V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two teams. - V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. - V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. - - i=0, redplayers=0, blueplayers=0; - - for (i = 0; i < MAXPLAYERS; i++) - { - if (players[tab[i].num].spectator) - continue; //ignore them. - - if (tab[i].color == skincolor_redteam) //red - { - if (redplayers++ > 8) - continue; - x = 32 + (BASEVIDWIDTH/2); - y = (redplayers * 16) + 16; - } - else if (tab[i].color == skincolor_blueteam) //blue - { - if (blueplayers++ > 8) - continue; - x = 32; - y = (blueplayers * 16) + 16; - } - else //er? not on red or blue, so ignore them - continue; - - strlcpy(name, tab[i].name, 7); - V_DrawString(x + 20, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) - | V_ALLOWLOWERCASE, name); - - if (gametype == GT_CTF) - { - if (players[tab[i].num].gotflag & GF_REDFLAG) // Red - V_DrawSmallScaledPatch(x-28, y-4, 0, rflagico); - else if (players[tab[i].num].gotflag & GF_BLUEFLAG) // Blue - V_DrawSmallScaledPatch(x-28, y-4, 0, bflagico); - } - - // Draw emeralds - if (!players[tab[i].num].powers[pw_super] - || ((leveltime/7) & 1)) - { - HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); - } - - if (players[tab[i].num].powers[pw_super]) - { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - V_DrawSmallMappedPatch (x, y-4, 0, facewantprefix[players[tab[i].num].skin], colormap); - } - else - { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if (players[tab[i].num].health <= 0) - V_DrawSmallTranslucentMappedPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap); - else - V_DrawSmallMappedPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap); - } - V_DrawRightAlignedThinString(x+120, y-1, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); - if (!splitscreen) - { - if (!(tab[i].num == serverplayer)) - HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); - } - V_DrawRightAlignedThinString(x+100, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); - if (!splitscreen) - { - if (!(tab[i].num == serverplayer)) - HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); - //else - // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); - } - } -} - -// -// HU_DrawDualTabRankings -// -void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer) -{ - INT32 i; - const UINT8 *colormap; - char name[MAXPLAYERNAME+1]; - - V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two sides. - V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. - V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. - - for (i = 0; i < scorelines; i++) - { - if (players[tab[i].num].spectator) - continue; //ignore them. - - strlcpy(name, tab[i].name, 7); - if (!(tab[i].num == serverplayer)) - HU_drawPing(x+ 113, y+2, playerpingtable[tab[i].num], false); - //else - // V_DrawSmallString(x+ 94, y+4, V_YELLOWMAP, "SERVER"); - - V_DrawString(x + 20, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) - | V_ALLOWLOWERCASE, name); - - if (G_GametypeUsesLives()) //show lives - V_DrawRightAlignedString(x, y+4, V_ALLOWLOWERCASE, va("%dx", players[tab[i].num].lives)); - else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) - V_DrawSmallScaledPatch(x-28, y-4, 0, tagico); - - // Draw emeralds - if (!players[tab[i].num].powers[pw_super] - || ((leveltime/7) & 1)) - { - HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); - } - - //V_DrawSmallScaledPatch (x, y-4, 0, livesback); - if (tab[i].color == 0) - { - colormap = colormaps; - if (players[tab[i].num].powers[pw_super]) - V_DrawSmallScaledPatch (x, y-4, 0, facewantprefix[players[tab[i].num].skin]); - else - { - if (players[tab[i].num].health <= 0) - V_DrawSmallTranslucentPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin]); - else - V_DrawSmallScaledPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin]); - } - } - else - { - if (players[tab[i].num].powers[pw_super]) - { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - V_DrawSmallMappedPatch (x, y-4, 0, facewantprefix[players[tab[i].num].skin], colormap); - } - else - { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if (players[tab[i].num].health <= 0) - V_DrawSmallTranslucentMappedPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap); - else - V_DrawSmallMappedPatch (x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap); - } - } - - // All data drawn with thin string for space. - if (G_RaceGametype()) - { - if (circuitmap) - { - if (players[tab[i].num].exiting) - V_DrawRightAlignedThinString(x+146, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); - else - V_DrawRightAlignedThinString(x+146, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); - } - else - V_DrawRightAlignedThinString(x+146, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); - } - else - V_DrawRightAlignedThinString(x+100, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); - - y += 16; - if (y > 160) - { - y = 32; - x += BASEVIDWIDTH/2; - } - } -} - -// -// HU_Draw32TabRankings -// -static void HU_Draw32TabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer) -{ - INT32 i; - const UINT8 *colormap; - char name[MAXPLAYERNAME+1]; - - V_DrawFill(160, 26, 1, 154, 0); //Draw a vertical line to separate the two sides. - V_DrawFill(1, 26, 318, 1, 0); //And a horizontal line to make a T. - V_DrawFill(1, 180, 318, 1, 0); //And a horizontal line near the bottom. - - for (i = 0; i < scorelines; i++) - { - if (players[tab[i].num].spectator) - continue; //ignore them. - - strlcpy(name, tab[i].name, 7); - if (!splitscreen) // don't draw it on splitscreen, - { - if (!(tab[i].num == serverplayer)) - HU_drawPing(x+ 135, y+3, playerpingtable[tab[i].num], true); - //else - // V_DrawSmallString(x+ 129, y+4, V_YELLOWMAP, "HOST"); - } - - V_DrawString(x + 10, y, - ((tab[i].num == whiteplayer) ? V_YELLOWMAP : 0) - | ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT) - | V_ALLOWLOWERCASE, name); - - if (G_GametypeUsesLives()) //show lives - V_DrawRightAlignedThinString(x-1, y, V_ALLOWLOWERCASE, va("%d", players[tab[i].num].lives)); - else if (G_TagGametype() && players[tab[i].num].pflags & PF_TAGIT) - V_DrawFixedPatch((x-10)*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, tagico, 0); - - // Draw emeralds - if (!players[tab[i].num].powers[pw_super] - || ((leveltime/7) & 1)) - { - HU_Draw32Emeralds(x+60, y+2, tab[i].emeralds); - //HU_DrawEmeralds(x-12,y+2,tab[i].emeralds); - } - - //V_DrawSmallScaledPatch (x, y-4, 0, livesback); - if (tab[i].color == 0) - { - colormap = colormaps; - if (players[tab[i].num].powers[pw_super]) - V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], 0); - else - { - if (players[tab[i].num].health <= 0) - V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, V_HUDTRANSHALF, faceprefix[players[tab[i].num].skin], 0); - else - V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, faceprefix[players[tab[i].num].skin], 0); - } - } - else - { - if (players[tab[i].num].powers[pw_super]) - { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT/4, 0, superprefix[players[tab[i].num].skin], colormap); - } - else - { - colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo ? players[tab[i].num].mo->color : tab[i].color, GTC_CACHE); - if (players[tab[i].num].health <= 0) - V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, V_HUDTRANSHALF, faceprefix[players[tab[i].num].skin], colormap); - else - V_DrawFixedPatch(x*FRACUNIT, (y)*FRACUNIT, FRACUNIT/4, 0, faceprefix[players[tab[i].num].skin], colormap); - } - } - - // All data drawn with thin string for space. - if (gametype == GT_RACE) - { - if (circuitmap) - { - if (players[tab[i].num].exiting) - V_DrawRightAlignedThinString(x+128, y, 0, va("%i:%02i.%02i", G_TicsToMinutes(players[tab[i].num].realtime,true), G_TicsToSeconds(players[tab[i].num].realtime), G_TicsToCentiseconds(players[tab[i].num].realtime))); - else - V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); - } - else - V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%i:%02i.%02i", G_TicsToMinutes(tab[i].count,true), G_TicsToSeconds(tab[i].count), G_TicsToCentiseconds(tab[i].count))); - } - else - V_DrawRightAlignedThinString(x+128, y, ((players[tab[i].num].health > 0) ? 0 : V_TRANSLUCENT), va("%u", tab[i].count)); - - y += 9; - if (i == 16) - { - y = 32; - x += BASEVIDWIDTH/2; - } - } -} - -// -// HU_DrawEmeralds -// -void HU_DrawEmeralds(INT32 x, INT32 y, INT32 pemeralds) -{ - //Draw the emeralds, in the CORRECT order, using tiny emerald sprites. - if (pemeralds & EMERALD1) - V_DrawSmallScaledPatch(x , y-6, 0, tinyemeraldpics[0]); - - if (pemeralds & EMERALD2) - V_DrawSmallScaledPatch(x+4, y-3, 0, tinyemeraldpics[1]); - - if (pemeralds & EMERALD3) - V_DrawSmallScaledPatch(x+4, y+3, 0, tinyemeraldpics[2]); - - if (pemeralds & EMERALD4) - V_DrawSmallScaledPatch(x , y+6, 0, tinyemeraldpics[3]); - - if (pemeralds & EMERALD5) - V_DrawSmallScaledPatch(x-4, y+3, 0, tinyemeraldpics[4]); - - if (pemeralds & EMERALD6) - V_DrawSmallScaledPatch(x-4, y-3, 0, tinyemeraldpics[5]); - - if (pemeralds & EMERALD7) - V_DrawSmallScaledPatch(x, y, 0, tinyemeraldpics[6]); -}*/ - // // HU_DrawSpectatorTicker // @@ -2804,7 +2261,6 @@ static inline void HU_DrawSpectatorTicker(void) // static void HU_DrawRankings(void) { - patch_t *p; playersort_t tab[MAXPLAYERS]; INT32 i, j, scorelines, hilicol, numplayersingame = 0; boolean completed[MAXPLAYERS]; @@ -2825,28 +2281,9 @@ static void HU_DrawRankings(void) else V_DrawString(4, 188, hilicol|V_SNAPTOBOTTOM|V_SNAPTOLEFT, gametype_cons_t[gametype].strvalue); - if (G_GametypeHasTeams()) + if (gametyperules & (GTR_TIMELIMIT|GTR_POINTLIMIT)) { - if (gametype == GT_CTF) - p = bflagico; - else - p = bmatcico; - - V_DrawSmallScaledPatch(128 - SHORT(p->width)/4, 4, 0, p); - V_DrawCenteredString(128, 16, 0, va("%u", bluescore)); - - if (gametype == GT_CTF) - p = rflagico; - else - p = rmatcico; - - V_DrawSmallScaledPatch(192 - SHORT(p->width)/4, 4, 0, p); - V_DrawCenteredString(192, 16, 0, va("%u", redscore)); - } - - if (!G_RaceGametype()) - { - if (cv_timelimit.value && timelimitintics > 0) + if ((gametyperules & GTR_TIMELIMIT) && cv_timelimit.value && timelimitintics > 0) { UINT32 timeval = (timelimitintics + starttime + 1 - leveltime); if (timeval > timelimitintics+1) @@ -2867,24 +2304,12 @@ static void HU_DrawRankings(void) } } - if (cv_pointlimit.value > 0) + if ((gametyperules & GTR_POINTLIMIT) && cv_pointlimit.value > 0) { V_DrawCenteredString(256, 8, 0, "POINT LIMIT"); V_DrawCenteredString(256, 16, hilicol, va("%d", cv_pointlimit.value)); } } - /*else if (gametype == GT_COOP) - { - INT32 totalscore = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - totalscore += players[i].score; - } - - V_DrawCenteredString(256, 8, 0, "TOTAL SCORE"); - V_DrawCenteredString(256, 16, 0, va("%u", totalscore)); - }*/ else { if (circuitmap) @@ -2939,7 +2364,7 @@ static void HU_DrawRankings(void) tab[scorelines].name = player_names[i]; - if (G_RaceGametype()) + if ((gametyperules & GTR_CIRCUIT)) { if (circuitmap) tab[scorelines].count = players[i].laps; @@ -2957,12 +2382,7 @@ static void HU_DrawRankings(void) #endif } - /*if (G_GametypeHasTeams()) - HU_DrawTeamTabRankings(tab, whiteplayer); //separate function for Spazzo's silly request -- gotta fix this up later - else if (scorelines > 10)*/ - HU_DrawTabRankings(((scorelines > 8) ? 32 : 40), 33, tab, scorelines, whiteplayer, hilicol); - /*else - HU_DrawDualTabRankings(32, 32, tab, scorelines, whiteplayer);*/ + K_DrawTabRankings(((scorelines > 8) ? 32 : 40), 33, tab, scorelines, whiteplayer, hilicol); // draw spectators in a ticker across the bottom if (netgame && G_GametypeHasSpectators()) diff --git a/src/hu_stuff.h b/src/hu_stuff.h index 4ad473357..afbbe7b73 100644 --- a/src/hu_stuff.h +++ b/src/hu_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -36,7 +36,7 @@ // Level title font #define LT_FONTSTART '!' // the first font characters -#define LT_FONTEND 'Z' // the last font characters +#define LT_FONTEND 'z' // the last font characters #define LT_FONTSIZE (LT_FONTEND - LT_FONTSTART + 1) #define CRED_FONTSTART '!' // the first font character @@ -60,8 +60,6 @@ enum }; #undef X -#define HU_CROSSHAIRS 3 // maximum of 9 - see HU_Init(); - extern char *shiftxform; // english translation shift table extern char english_shiftxform[]; @@ -80,15 +78,15 @@ typedef struct // chat stuff //------------------------------------ #define HU_MAXMSGLEN 224 -#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand. +#define CHAT_BUFSIZE 64 // that's enough messages, right? We'll delete the older ones when that gets out of hand. #define NETSPLITSCREEN // why the hell WOULDN'T we want this? #ifdef NETSPLITSCREEN #define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640) #else #define OLDCHAT (cv_consolechat.value == 1 || dedicated || vid.width < 640) #endif -#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot. -#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted. +#define CHAT_MUTE (cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this still allows to open the chat but not to type. That's used for scrolling and whatnot. +#define OLD_MUTE (OLDCHAT && cv_mute.value && !(server || IsPlayerAdmin(consoleplayer))) // this is used to prevent oldchat from opening when muted. // some functions void HU_AddChatText(const char *text, boolean playsound); @@ -99,14 +97,14 @@ extern boolean chat_on; extern patch_t *pinggfx[5]; extern patch_t *framecounter; extern patch_t *frameslash; -extern patch_t *emeraldpics[7]; -extern patch_t *tinyemeraldpics[7]; + extern patch_t *rflagico; extern patch_t *bflagico; extern patch_t *rmatcico; extern patch_t *bmatcico; extern patch_t *tagico; extern patch_t *tallminus; +extern patch_t *tallinfin; // set true whenever the tab rankings are being shown for any reason extern boolean hu_showscores; @@ -129,12 +127,8 @@ void HU_Drawer(void); char HU_dequeueChatChar(void); void HU_Erase(void); void HU_clearChatChars(void); -void HU_drawPing(INT32 x, INT32 y, UINT32 ping, INT32 flags); // Lat': Ping drawer for scoreboard. +void HU_drawPing(INT32 x, INT32 y, UINT32 ping, INT32 flags); // Lat': Ping drawer for scoreboard. void HU_drawMiniPing(INT32 x, INT32 y, UINT32 ping, INT32 flags); -//void HU_DrawTeamTabRankings(playersort_t *tab, INT32 whiteplayer); -//void HU_DrawDualTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer); -void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol); -void HU_DrawEmeralds(INT32 x, INT32 y, INT32 pemeralds); INT32 HU_CreateTeamScoresTbl(playersort_t *tab, UINT32 dmtotals[]); diff --git a/src/i_addrinfo.c b/src/i_addrinfo.c index 42d4b8924..e77774549 100644 --- a/src/i_addrinfo.c +++ b/src/i_addrinfo.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2018 by Sonic Team Junior. +// Copyright (C) 2011-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -20,17 +20,11 @@ #else #include #endif -#elif !defined (__DJGPP__) && !defined(_WII) +#elif !defined (__DJGPP__) #include -#ifndef _NDS #include -#endif -#ifdef _PS3 -#include -#elif ! defined (_arch_dreamcast) #include #endif -#endif #include "i_addrinfo.h" @@ -262,9 +256,6 @@ int I_getaddrinfo(const char *node, const char *service, for (i = 0, j = 0; i < ailen; i++, j++) { ai = *res+i; -#ifdef _PS3 - addr[i].sin_len = famsize; -#endif addr[i].sin_port = htons((UINT16)sockport); if (nodename) { diff --git a/src/i_addrinfo.h b/src/i_addrinfo.h index 1b8ce9153..7ae006719 100644 --- a/src/i_addrinfo.h +++ b/src/i_addrinfo.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2011-2018 by Sonic Team Junior. +// Copyright (C) 2011-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -39,17 +39,7 @@ #define EAI_NONAME -2 #endif -#ifdef _PS3 // PSL1GHT v2 -struct my_addrinfo { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - size_t ai_addrlen; - struct sockaddr *ai_addr; - struct my_addrinfo *ai_next; -}; -#elif defined (_WIN32) // already use the stub for Win32 +#ifdef _WIN32 // already use the stub for Win32 // w32api, ws2tcpip.h, r1.12 struct my_addrinfo { int ai_flags; diff --git a/src/i_joy.h b/src/i_joy.h index f780d8018..b10f4c55d 100644 --- a/src/i_joy.h +++ b/src/i_joy.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -53,6 +53,6 @@ typedef struct JoyType_s JoyType_t; for palyer[sic] 1-4's joystick/gamepad */ -extern JoyType_t Joystick, Joystick2, Joystick3, Joystick4; +extern JoyType_t Joystick[MAXSPLITSCREENPLAYERS]; #endif // __I_JOY_H__ diff --git a/src/i_net.h b/src/i_net.h index 0e17077bb..5d93f191e 100644 --- a/src/i_net.h +++ b/src/i_net.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_sound.h b/src/i_sound.h index 93e3f6dd0..981f769b9 100644 --- a/src/i_sound.h +++ b/src/i_sound.h @@ -2,14 +2,14 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file i_sound.h -/// \brief System interface, sound, music and CD +/// \brief System interface, sound, music #ifndef __I_SOUND__ #define __I_SOUND__ @@ -30,7 +30,9 @@ typedef enum { MU_MP3_MAD_UNUSED, // use MU_MP3 instead MU_FLAC, MU_MODPLUG_UNUSED, // use MU_MOD instead - MU_GME + MU_GME, + MU_MOD_EX, // libopenmpt + MU_MID_EX // Non-native MIDI } musictype_t; /** \brief Sound subsystem runing and waiting @@ -118,7 +120,7 @@ void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch); \return void */ -void I_SetSfxVolume(UINT8 volume); +void I_SetSfxVolume(int volume); /// ------------------------ // MUSIC SYSTEM @@ -227,7 +229,7 @@ void I_ResumeSong(void); \return void */ -void I_SetMusicVolume(UINT8 volume); +void I_SetMusicVolume(int volume); boolean I_SetSongTrack(INT32 track); @@ -242,53 +244,4 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)); boolean I_FadeOutStopSong(UINT32 ms); boolean I_FadeInPlaySong(UINT32 ms, boolean looping); -/// ------------------------ -// CD MUSIC I/O -/// ------------------------ - -/** \brief cd music interface -*/ -extern UINT8 cdaudio_started; - -/** \brief Startup the CD system -*/ -void I_InitCD(void); - -/** \brief Stop the CD playback -*/ -void I_StopCD(void); - -/** \brief Pause the CD playback -*/ -void I_PauseCD(void); - -/** \brief Resume the CD playback -*/ -void I_ResumeCD(void); - -/** \brief Shutdown the CD system -*/ -void I_ShutdownCD(void); - -/** \brief Update the CD info -*/ -void I_UpdateCD(void); - -/** \brief The I_PlayCD function - - \param track CD track number - \param looping if true, loop the track - - \return void -*/ -void I_PlayCD(UINT8 track, UINT8 looping); - -/** \brief The I_SetVolumeCD function - - \param volume volume level to set at - - \return return 0 on failure -*/ -boolean I_SetVolumeCD(INT32 volume); - #endif diff --git a/src/i_system.h b/src/i_system.h index 3e589c69a..daa76f3ab 100644 --- a/src/i_system.h +++ b/src/i_system.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -46,6 +46,8 @@ UINT32 I_GetFreeMem(UINT32 *total); */ tic_t I_GetTime(void); +int I_GetTimeMicros(void);// provides microsecond counter for render stats + /** \brief The I_Sleep function \return void @@ -182,9 +184,13 @@ void I_JoyScale4(void); // Called by D_SRB2Main. +/** \brief to startup a joystick +*/ +void I_InitJoystick(UINT8 index); + /** \brief to startup the first joystick */ -void I_InitJoystick(void); +void I_InitJoystick1(void); /** \brief to startup the second joystick */ @@ -218,14 +224,10 @@ const char *I_GetJoyName(INT32 joyindex); void I_UpdateMumble(const mobj_t *mobj, const listener_t listener); #endif -/** \brief Startup the first mouse +/** \brief Startup the mouse */ void I_StartupMouse(void); -/** \brief Startup the second mouse -*/ -void I_StartupMouse2(void); - /** \brief setup timer irq and user timer routine. */ void I_StartupTimer(void); @@ -320,23 +322,11 @@ const char *I_LocateWad(void); /** \brief First Joystick's events */ -void I_GetJoystickEvents(void); +void I_GetJoystickEvents(UINT8 index); -/** \brief Second Joystick's events +/** \brief Checks if the mouse needs to be grabbed */ -void I_GetJoystick2Events(void); - -/** \brief Third Joystick's events -*/ -void I_GetJoystick3Events(void); - -/** \brief Fourth Joystick's events -*/ -void I_GetJoystick4Events(void); - -/** \brief Mouses events -*/ -void I_GetMouseEvents(void); +void I_UpdateMouseGrab(void); char *I_GetEnv(const char *name); diff --git a/src/i_tcp.c b/src/i_tcp.c index 1f1cf4f22..5180869a5 100644 --- a/src/i_tcp.c +++ b/src/i_tcp.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,20 +18,12 @@ #ifdef __GNUC__ #include #endif -#ifdef __OS2__ -#include -#include -#endif // __OS2__ - -#ifdef _PS3 -#define NO_IPV6 // PSL1GHT v2 do not have IPv6 support -#endif #ifndef NO_IPV6 #define HAVE_IPV6 #endif -#if defined (_WIN32) || defined (_WIN32_WCE) +#ifdef _WIN32 #define USE_WINSOCK #if defined (_WIN64) || defined (HAVE_IPV6) #define USE_WINSOCK2 @@ -40,12 +32,6 @@ #endif #endif //WIN32 OS -#ifdef _XBOX // XBox have on WinSock API? -#undef USE_WINSOCK -#undef USE_WINSOCK1 -#undef USE_WINSOCK2 -#endif - #ifdef USE_WINSOCK2 #include #endif @@ -61,17 +47,12 @@ #else #ifdef USE_WINSOCK1 #include -#elif !defined (SCOUW2) && !defined (SCOUW7) && !defined (__OS2__) -#ifdef HAVE_LWIP -#include -#elif !defined (USE_WINSOCK) +#elif !defined (SCOUW2) && !defined (SCOUW7) +#ifndef USE_WINSOCK #include #endif //normal BSD API -#ifdef HAVE_LWIP -#include -#define ioctl lwip_ioctl -#elif !defined (USE_WINSOCK) //!HAVE_LWIP +#ifndef USE_WINSOCK #ifdef __APPLE_CC__ #ifndef _BSD_SOCKLEN_T_ #define _BSD_SOCKLEN_T_ @@ -81,14 +62,7 @@ #include #endif //normal BSD API -#if defined(_arch_dreamcast) && !defined(HAVE_LWIP) -#include -#elif defined(HAVE_LWIP) -#include -#elif defined (_PS3) -#include -#include -#elif !defined(USE_WINSOCK) //!HAVE_LWIP +#ifndef USE_WINSOCK #include #include #endif //normal BSD API @@ -96,10 +70,6 @@ #include #include -#ifdef _arch_dreamcast -#include "sdl12/SRB2DC/dchelp.h" -#endif - #if (defined (__unix__) && !defined (MSDOS)) || defined(__APPLE__) || defined (UNIXCOMMON) #include #endif // UNIXCOMMON @@ -190,11 +160,6 @@ static UINT8 UPNP_support = TRUE; // winsock stuff (in winsock a socket is not a file) #define ioctl ioctlsocket #define close closesocket - - #ifdef _WIN32_WCE - #include "sdl12/SRB2CE/cehelp.h" - #endif - #endif #include "i_addrinfo.h" @@ -205,9 +170,7 @@ static UINT8 UPNP_support = TRUE; #define SELECTTEST #endif -#elif defined(HAVE_LWIP) -#define SELECTTEST -#elif !defined( _arch_dreamcast) +#else #define SELECTTEST #endif @@ -217,7 +180,7 @@ static UINT8 UPNP_support = TRUE; typedef SOCKET SOCKET_TYPE; #define ERRSOCKET (SOCKET_ERROR) #else -#if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__) || defined(_PS3) +#if (defined (__unix__) && !defined (MSDOS)) || defined (__APPLE__) || defined (__HAIKU__) typedef int SOCKET_TYPE; #else typedef unsigned long SOCKET_TYPE; @@ -524,7 +487,7 @@ static void cleanupnodes(void) // Why can't I start at zero? for (j = 1; j < MAXNETNODES; j++) - if (!(nodeingame[j] || SV_SendingFile(j))) + if (!(nodeingame[j] || SendingFile(j))) nodeconnected[j] = false; } @@ -1181,12 +1144,6 @@ boolean I_InitTcpDriver(void) CONS_Debug(DBG_NETPLAY, "WinSock description: %s\n",WSAData.szDescription); CONS_Debug(DBG_NETPLAY, "WinSock System Status: %s\n",WSAData.szSystemStatus); #endif -#ifdef HAVE_LWIP - lwip_kos_init(); -#elif defined(_arch_dreamcast) - //return; - net_init(); -#endif #ifdef __DJGPP__ #ifdef WATTCP // Alam_GBC: survive bootp, dhcp, rarp and wattcp/pktdrv from failing to load survive_eth = 1; // would be needed to not exit if pkt_eth_init() fails @@ -1239,9 +1196,6 @@ boolean I_InitTcpDriver(void) CONS_Debug(DBG_NETPLAY, "No TCP/IP driver detected\n"); #endif // libsocket #endif // __DJGPP__ -#ifdef _PS3 - netInitialize(); -#endif #ifndef __DJGPP__ init_tcp_driver = true; #endif @@ -1289,11 +1243,6 @@ void I_ShutdownTcpDriver(void) WS_addrinfocleanup(); WSACleanup(); #endif -#ifdef HAVE_LWIP - lwip_kos_shutdown(); -#elif defined(_arch_dreamcast) - net_shutdown(); -#endif #ifdef __DJGPP__ #ifdef WATTCP // wattcp //_outch = NULL; @@ -1302,9 +1251,6 @@ void I_ShutdownTcpDriver(void) __lsck_uninit(); #endif // libsocket #endif // __DJGPP__ -#ifdef _PS3 - netDeinitialize(); -#endif CONS_Printf("shut down\n"); init_tcp_driver = false; #endif @@ -1477,6 +1423,7 @@ static void SOCK_ClearBans(void) boolean I_InitTcpNetwork(void) { char serverhostname[255]; + const char *urlparam = NULL; boolean ret = false; // initilize the OS's TCP/IP stack if (!I_InitTcpDriver()) @@ -1530,10 +1477,12 @@ boolean I_InitTcpNetwork(void) ret = true; } - else if (M_CheckParm("-connect")) + else if ((urlparam = M_GetUrlProtocolArg()) != NULL || M_CheckParm("-connect")) { - if (M_IsNextParm()) - strcpy(serverhostname, M_GetNextParm()); + if (urlparam != NULL) + strlcpy(serverhostname, urlparam, sizeof(serverhostname)); + else if (M_IsNextParm()) + strlcpy(serverhostname, M_GetNextParm(), sizeof(serverhostname)); else serverhostname[0] = 0; // assuming server in the LAN, use broadcast to detect it diff --git a/src/i_tcp.h b/src/i_tcp.h index 06680cd9b..738b8b4d1 100644 --- a/src/i_tcp.h +++ b/src/i_tcp.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/i_threads.h b/src/i_threads.h index 45a3dcc3e..ecb9fce67 100644 --- a/src/i_threads.h +++ b/src/i_threads.h @@ -1,4 +1,4 @@ -// SONIC ROBO BLAST 2 KART +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2020 by James R. // diff --git a/src/i_video.h b/src/i_video.h index 4bb2c5829..98ed7f38a 100644 --- a/src/i_video.h +++ b/src/i_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -32,10 +32,14 @@ typedef enum render_none = 3 // for dedicated server } rendermode_t; -/** \brief currect render mode +/** \brief current render mode */ extern rendermode_t rendermode; +/** \brief OpenGL state + 0 = never loaded, 1 = loaded successfully, -1 = failed loading +*/ +extern INT32 vid_opengl_state; /** \brief use highcolor modes if true */ @@ -45,7 +49,7 @@ extern boolean highcolor; */ void I_StartupGraphics(void); -/** \brief restore old video mode +/** \brief shutdown video mode */ void I_ShutdownGraphics(void); @@ -81,10 +85,22 @@ INT32 VID_GetModeForSize(INT32 w, INT32 h); \param modenum video mode to set to - \return currect video mode + \return current video mode */ INT32 VID_SetMode(INT32 modenum); +/** \brief Checks the render state +*/ +void VID_CheckRenderer(void); + +/** \brief Load OpenGL mode +*/ +void VID_StartupOpenGL(void); + +/** \brief Checks if OpenGL loaded +*/ +void VID_CheckGLLoaded(rendermode_t oldrender); + /** \brief The VID_GetModeName function \param modenum video mode number diff --git a/src/info.c b/src/info.c index e67a7be69..5677e4270 100644 --- a/src/info.c +++ b/src/info.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -16,71 +16,769 @@ #include "doomstat.h" #include "sounds.h" #include "p_mobj.h" +#include "p_local.h" // DMG_ constants #include "m_misc.h" #include "z_zone.h" #include "d_player.h" +#include "v_video.h" // V_*MAP constants #include "lzf.h" // Hey, moron! If you change this table, don't forget about the sprite enum in info.h and the sprite lights in hw_light.c! +// For the sake of constant merge conflicts, let's spread this out char sprnames[NUMSPRITES + 1][5] = { - "NULL","UNKN","THOK","PLAY","POSS","SPOS","FISH","BUZZ","RBUZ","JETB", - "JETW","JETG","CCOM","DETN","SKIM","TRET","TURR","SHRP","JJAW","SNLR", - "VLTR","PNTY","ARCH","CBFS","SPSH","ESHI","GSNP","MNUS","SSHL","UNID", - "BBUZ","JETF","EGGM","EGGN","TNKA","TNKB","SPNK","GOOP","EGGO","PRPL", - "FAKE","EGGP","EFIR","EGGQ","EGGR","BRAK","BGOO","BMSL","EGGT","RCKT", - "ELEC","TARG","NPLM","MNPL","METL","MSCF","MSCB","RING","TRNG","EMMY", - "TOKE","RFLG","BFLG","NWNG","EMBM","CEMG","EMER","FANS","BUBL","SIGN", - "STEM","SPIK","SFLM","USPK","STPT","BMNE","SRBX","RRBX","BRBX","SHTV", - "PINV","YLTV","BLTV","BKTV","WHTV","GRTV","ELTV","EGGB","MIXU","RECY", - "QUES","GBTV","PRUP","PTTV","MTEX","MISL","TORP","ENRG","MINE","JBUL", - "TRLS","CBLL","AROW","CFIR","FWR1","FWR2","FWR3","FWR4","BUS1","BUS2", - "THZP","ALRM","GARG","SEWE","DRIP","CRL1","CRL2","CRL3","BCRY","CHAN", - "FLAM","ESTA","SMCH","BMCH","SMCE","BMCE","BTBL","STBL","CACT","FLME", - "DFLM","XMS1","XMS2","XMS3","BSZ1","BSZ2","BSZ3","BSZ4","BSZ5","BSZ6", - "BSZ7","BSZ8","STLG","DBAL","RCRY","ARMA","ARMF","ARMB","WIND","MAGN", - "ELEM","FORC","PITY","IVSP","SSPK","GOAL","BIRD","BUNY","MOUS","CHIC", - "COWZ","RBRD","SPVY","SPVR","SPVB","SPVG","SPDY","SPDR","SPDB","SPDG", - "SPHY","SPHR","SPHB","SPHG","RAIN","SNO1","SNO2","SPLH","SPLA","SMOK", - "BUBP","BUBO","BUBN","BUBM","POPP","TFOG","SEED","PRTL","SCOR","DRWN", - "TTAG","GFLG","RRNG","RNGB","RNGR","RNGI","RNGA","RNGE","RNGS","RNGG", - "PIKB","PIKR","PIKA","PIKE","PIKS","PIKG","TAUT","TGRE","TSCR","COIN", - "CPRK","GOOM","BGOM","FFWR","FBLL","SHLL","PUMA","HAMM","KOOP","BFLM", - "MAXE","MUS1","MUS2","TOAD","NDRN","SUPE","SUPZ","NDRL","NSPK","NBMP", - "HOOP","NSCR","NPRU","CAPS","SUPT","SPRK","BOM1","BOM2","BOM3","BOM4", - "ROIA","ROIB","ROIC","ROID","ROIE","ROIF","ROIG","ROIH","ROII","ROIJ", - "ROIK","ROIL","ROIM","ROIN","ROIO","ROIP","BBAL","GWLG","GWLR","SRBA", - "SRBB","SRBC","SRBD","SRBE","SRBF","SRBG","SRBH","SRBI","SRBJ","SRBK", - "SRBL","SRBM","SRBN","SRBO", - //SRB2kart Sprites + "NULL", // invisible object + "UNKN", - "RNDM","RPOP","SGNS","FAST","DSHR","BOST","BOSM","KFRE","KINV","KINF", - "WIPD","DRIF","BDRF","DUST","DRWS","RSHE","FITM","BANA","ORBN","JAWZ","SSMN", - "KRBM","BHOG","BHBM","SPBM","THNS","BUBS","BWVE", - "FLMS","FLMD","FLMP","FLML","FLMF", - "SINK","SITR", - "KBLN","DEZL","POKE","AUDI","DECO","DOOD","SNES","GBAS","SPRS","BUZB", - "CHOM","SACO","CRAB","BRNG","BUMP","FLEN","CLAS","PSHW","ISTA", - "ISTB","ARRO","ITEM","ITMO","ITMI","ITMN","WANT","PBOM","HIT1","HIT2", - "HIT3","RETI","AIDU","KSPK","LZI1","LZI2","KLIT","FZSM","FZBM","FPRT", - "SBUS","MARB","FUFO","RUST","BLON","VAPE","HTZA","HTZB","SGVA","SGVB", - "SGVC","PGTR","PGF1","PGF2","PGF3","PGBH","DPLR","SPTL","ENM1","GARU", - "MARR","REAP","JITB","CDMO","CDBU","PINE","PPLR","DPPT","AATR","COCO", - "BDST","FROG","CBRA","HOLE","BBRA","EGFG","SMKP","MTYM","THWP","SNOB", - "ICEB","CNDL","DOCH","DUCK","GTRE","CHES","CHIM","DRGN","LZMN","PGSS", - "ZTCH","MKMA","MKMP","RTCH","BOWL","BOWH","BRRL","BRRR","HRSE","TOAH", - "BFRT","OFRT","RFRT","PFRT","ASPK","HBST","HBSO","HBSF","WBLZ","WBLN", + "THOK", // Thok! mobj + "PLAY", - "FWRK","MXCL","RGSP","DRAF","GRES","OTFG","DBOS","EGOO","WTRL","XMS4", - "XMS5","FBUB","GCHA","CHEZ","VIEW","DBCL","DBNC","DBST", + // Enemies + "POSS", // Crawla (Blue) + "SPOS", // Crawla (Red) + "FISH", // SDURF + "BUZZ", // Buzz (Gold) + "RBUZ", // Buzz (Red) + "JETB", // Jetty-Syn Bomber + "JETG", // Jetty-Syn Gunner + "CCOM", // Crawla Commander + "DETN", // Deton + "SKIM", // Skim mine dropper + "TRET", // Industrial Turret + "TURR", // Pop-Up Turret + "SHRP", // Sharp + //"CRAB", // Crushstacean + "CR2B", // Banpyura + "CSPR", // Banpyura spring + "JJAW", // Jet Jaw + "SNLR", // Snailer + "VLTR", // BASH + "PNTY", // Pointy + "ARCH", // Robo-Hood + "CBFS", // Castlebot Facestabber + "STAB", // Castlebot Facestabber spear aura + "SPSH", // Egg Guard + "ESHI", // Egg Guard's shield + "GSNP", // Green Snapper + "GSNL", // Green Snapper leg + "GSNH", // Green Snapper head + "MNUS", // Minus + "MNUD", // Minus dirt + "SSHL", // Spring Shell + "UNID", // Unidus + "CANA", // Canarivore + "CANG", // Canarivore gas + "PYRE", // Pyre Fly + "PTER", // Pterabyte + "DRAB", // Dragonbomber + + // Generic Boss Items + "JETF", // Boss jet fumes + + // Boss 1 (Greenflower) + "EGGM", // Boss 1 + "EGLZ", // Boss 1 Junk + + // Boss 2 (Techno Hill) + "EGGN", // Boss 2 + "TANK", // Boss 2 Junk + "GOOP", // Boss 2 Goop + + // Boss 3 (Deep Sea) + "EGGO", // Boss 3 + "SEBH", // Boss 3 Junk + "FAKE", // Boss 3 Fakemobile + "SHCK", // Boss 3 Shockwave + + // Boss 4 (Castle Eggman) + "EGGP", + "EFIR", // Boss 4 jet flame + "EGR1", // Boss 4 Spectator Eggrobo + + // Boss 5 (Arid Canyon) + "FANG", // replaces EGGQ + "BRKN", + "WHAT", + "VWRE", + "PROJ", // projector light + "FBOM", + "FSGN", + "BARX", // bomb explosion (also used by barrel) + "BARD", // bomb dust (also used by barrel) + + // Boss 6 (Red Volcano) + "EGGR", + + // Boss 7 (Dark City) + "BRAK", + "BGOO", // Goop + "BMSL", + + // Boss 8 (Egg Rock) + "EGGT", + + // Cy-Brak-Demon; uses "BRAK as well", but has some extras + "RCKT", // Rockets! + "ELEC", // Electricity! + "TARG", // Targeting reticules! + "NPLM", // Big napalm bombs! + "MNPL", // Mini napalm bombs! + + // Metal Sonic + "METL", + "MSCF", + "MSCB", + + // Collectible Items + "RING", + "TRNG", // Team Rings + "TOKE", // Special Stage Token + "RFLG", // Red CTF Flag + "BFLG", // Blue CTF Flag + //"SPHR", // Sphere + "NCHP", // NiGHTS chip + "NSTR", // NiGHTS star + "EMBM", // Emblem + "CEMG", // Chaos Emeralds + "SHRD", // Emerald Hunt + + // Interactive Objects + "BBLS", // water bubble source + "SIGN", // Level end sign + "SPIK", // Spike Ball + "SFLM", // Spin fire + "USPK", // Floor spike + "WSPK", // Wall spike + "WSPB", // Wall spike base + "STPT", // Starpost + "BMNE", // Big floating mine + "PUMI", // Rollout Rock + + // Monitor Boxes + "MSTV", // MiSc TV sprites + "XLTV", // eXtra Large TV sprites + + "TRRI", // Red team: 10 RIngs + "TBRI", // Blue team: 10 RIngs + + "TVRI", // 10 RIng + "TVPI", // PIty shield + "TVAT", // ATtraction shield + "TVFO", // FOrce shield + "TVAR", // ARmageddon shield + "TVWW", // WhirlWind shield + "TVEL", // ELemental shield + "TVSS", // Super Sneakers + "TVIV", // InVincibility + "TV1U", // 1Up + "TV1P", // 1uP (textless) + "TVEG", // EGgman + "TVMX", // MiXup + "TVMY", // MYstery + "TVGV", // GraVity boots + "TVRC", // ReCycler + "TV1K", // 1",000 points (1 K) + "TVTK", // 10",000 points (Ten K) + "TVFL", // FLame shield + "TVBB", // BuBble shield + "TVZP", // Thunder shield (ZaP) + + // Projectiles + "MISL", + "LASR", // GFZ3 laser + "LASF", // GFZ3 laser flames + "TORP", // Torpedo + "ENRG", // Energy ball + "MINE", // Skim mine + "JBUL", // Jetty-Syn Bullet + "TRLS", + "CBLL", // Cannonball + "AROW", // Arrow + "CFIR", // Colored fire of various sorts + + // The letter + "LETR", + + // Greenflower Scenery + "FWR1", + "FWR2", // GFZ Sunflower + "FWR3", // GFZ budding flower + "FWR4", + "BUS1", // GFZ Bush w/ berries + "BUS2", // GFZ Bush w/o berries + "BUS3", // GFZ Bush w/ BLUE berries + // Trees (both GFZ and misc) + "TRE1", // GFZ + "TRE2", // Checker + "TRE3", // Frozen Hillside + "TRE4", // Polygon + "TRE5", // Bush tree + "TRE6", // Spring tree + + // Techno Hill Scenery + "THZP", // THZ1 Steam Flower + "FWR5", // THZ1 Spin flower (red) + "FWR6", // THZ1 Spin flower (yellow) + "THZT", // Steam Whistle tree/bush + "ALRM", // THZ2 Alarm + + // Deep Sea Scenery + "GARG", // Deep Sea Gargoyle + "SEWE", // Deep Sea Seaweed + "DRIP", // Dripping water + "CORL", // Coral + "BCRY", // Blue Crystal + "KELP", // Kelp + "ALGA", // Animated algae top + "ALGB", // Animated algae segment + "DSTG", // DSZ Stalagmites + "LIBE", // DSZ Light beam + + // Castle Eggman Scenery + "CHAN", // CEZ Chain + "FLAM", // Flame + "ESTA", // Eggman esta una estatua! + "SMCH", // Small Mace Chain + "BMCH", // Big Mace Chain + "SMCE", // Small Mace + "BMCE", // Big Mace + "YSPB", // Yellow spring on a ball + "RSPB", // Red spring on a ball + "SFBR", // Small Firebar + "BFBR", // Big Firebar + "BANR", // Banner/pole + "PINE", // Pine Tree + "CEZB", // Bush + "CNDL", // Candle/pricket + "FLMH", // Flame holder + "CTRC", // Fire torch + "CFLG", // Waving flag/segment + "CSTA", // Crawla statue + "CBBS", // Facestabber statue + "CABR", // Brambles + + // Arid Canyon Scenery + "BTBL", // Big tumbleweed + "STBL", // Small tumbleweed + "CACT", // Cacti + "WWSG", // Caution Sign + "WWS2", // Cacti Sign + "WWS3", // Sharp Turn Sign + "OILL", // Oil lamp + "OILF", // Oil lamp flare + "BARR", // TNT barrel + "REMT", // TNT proximity shell + "TAZD", // Dust devil + "ADST", // Arid dust + "MCRT", // Minecart + "MCSP", // Minecart spark + "SALD", // Saloon door + "TRAE", // Train cameo locomotive + "TRAI", // Train cameo wagon + "STEA", // Train steam + + // Red Volcano Scenery + "FLME", // Flame jet + "DFLM", // Blade's flame + "LFAL", // Lavafall + "JPLA", // Jungle palm + "TFLO", // Torch flower + "WVIN", // Wall vines + + // Dark City Scenery + + // Egg Rock Scenery + + // Christmas Scenery + "XMS1", // Christmas Pole + "XMS2", // Candy Cane + "XMS3", // Snowman + "XMS4", // Lamppost + "XMS5", // Hanging Star + "XMS6", // Mistletoe + "FHZI", // FHZ Ice + "ROSY", + + // Halloween Scenery + "PUMK", // Pumpkins + "HHPL", // Dr Seuss Trees + "SHRM", // Mushroom + "HHZM", // Misc + + // Azure Temple Scenery + "BGAR", // ATZ Gargoyles + "RCRY", // ATZ Red Crystal (Target) + "CFLM", // Green torch flame + + // Botanic Serenity Scenery + "BSZ1", // Tall flowers + "BSZ2", // Medium flowers + "BSZ3", // Small flowers + //"BSZ4", -- Tulips + "BST1", // Red tulip + "BST2", // Purple tulip + "BST3", // Blue tulip + "BST4", // Cyan tulip + "BST5", // Yellow tulip + "BST6", // Orange tulip + "BSZ5", // Cluster of Tulips + "BSZ6", // Bush + "BSZ7", // Vine + "BSZ8", // Misc things + + // Misc Scenery + "STLG", // Stalagmites + "DBAL", // Disco + + // Powerup Indicators + "ARMA", // Armageddon Shield Orb + "ARMF", // Armageddon Shield Ring", Front + "ARMB", // Armageddon Shield Ring", Back + "WIND", // Whirlwind Shield Orb + "MAGN", // Attract Shield Orb + "ELEM", // Elemental Shield Orb + "FORC", // Force Shield Orb + "PITY", // Pity Shield Orb + "FIRS", // Flame Shield Orb + //"BUBS", // Bubble Shield Orb + "ZAPS", // Thunder Shield Orb + "IVSP", // invincibility sparkles + "SSPK", // Super Sonic Spark + + "GOAL", // Special Stage goal (here because lol NiGHTS) + + // Flickies + "FBUB", // Flicky-sized bubble + "FL01", // Bluebird + "FL02", // Rabbit + "FL03", // Chicken + "FL04", // Seal + "FL05", // Pig + "FL06", // Chipmunk + "FL07", // Penguin + "FL08", // Fish + "FL09", // Ram + "FL10", // Puffin + "FL11", // Cow + "FL12", // Rat + "FL13", // Bear + "FL14", // Dove + "FL15", // Cat + "FL16", // Canary + "FS01", // Spider + "FS02", // Bat + + // Springs + "FANS", // Fan + "STEM", // Steam riser + "BMPR", // Bumpers + "BLON", // Balloons + "SPVY", // Yellow Vertical Spring + "SPVR", // Red Vertical Spring + "SPVB", // Blue Vertical Spring + "SPVG", // Grey Vertical Spring + "SPDY", // Yellow Diagonal Spring + "SPDR", // Red Diagonal Spring + "SPDB", // Blue Diagonal Spring + "SPDG", // Grey Diagonal Spring + "SPHY", // Yellow Horizontal Spring + "SPHR", // Red Horizontal Spring + "SPHB", // Blue Horizontal Spring + "SPHG", // Grey Horizontal Spring + "BSTY", // Yellow Booster + "BSTR", // Red Booster + + // Environmental Effects + "RAIN", // Rain + "SNO1", // Snowflake + "SNO2", // Blizzard Snowball + "SPLH", // Water Splish + "LSPL", // Lava Splish + "SPLA", // Water Splash + "SMOK", + "BUBL", // Bubble + "WZAP", + "DUST", // Spindash dust + "FPRT", // Spindash dust (flame) + "TFOG", // Teleport Fog + "SEED", // Sonic CD flower seed + "PRTL", // Particle (for fans", etc.) + + // Game Indicators + "SCOR", // Score logo + "DRWN", // Drowning Timer + "FLII", // AI flight indicator + "LCKN", // Target + "TTAG", // Tag Sign + "GFLG", // Got Flag sign + "FNSF", // Finish flag + + "CORK", + "LHRT", + + // Ring Weapons + "RRNG", // Red Ring + "RNGB", // Bounce Ring + "RNGR", // Rail Ring + "RNGI", // Infinity Ring + "RNGA", // Automatic Ring + "RNGE", // Explosion Ring + "RNGS", // Scatter Ring + "RNGG", // Grenade Ring + + "PIKB", // Bounce Ring Pickup + "PIKR", // Rail Ring Pickup + "PIKA", // Automatic Ring Pickup + "PIKE", // Explosion Ring Pickup + "PIKS", // Scatter Ring Pickup + "PIKG", // Grenade Ring Pickup + + "TAUT", // Thrown Automatic Ring + "TGRE", // Thrown Grenade Ring + "TSCR", // Thrown Scatter Ring + + // Mario-specific stuff + "COIN", + "CPRK", + "GOOM", + "BGOM", + "FFWR", + "FBLL", + "SHLL", + "PUMA", + "HAMM", + "KOOP", + "BFLM", + "MAXE", + "MUS1", + "MUS2", + "TOAD", + + // NiGHTS Stuff + "NDRN", // NiGHTS drone + "NSPK", // NiGHTS sparkle + "NBMP", // NiGHTS Bumper + "HOOP", // NiGHTS hoop sprite + "NSCR", // NiGHTS score sprite + "NPRU", // Nights Powerups + "CAPS", // Capsule thingy for NiGHTS + "IDYA", // Ideya + "NTPN", // Nightopian + "SHLP", // Shleep + + // Secret badniks and hazards", shhhh + "PENG", + "POPH", + "HIVE", + "BUMB", + "BBUZ", + "FMCE", + "HMCE", + "CACO", + "BAL2", + "SBOB", + "SBFL", + "SBSK", + "HBAT", + + // Debris + "SPRK", // Sparkle + "BOM1", // Robot Explosion + "BOM2", // Boss Explosion 1 + "BOM3", // Boss Explosion 2 + "BOM4", // Underwater Explosion + "BMNB", // Mine Explosion + + // Crumbly rocks + "ROIA", + "ROIB", + "ROIC", + "ROID", + "ROIE", + "ROIF", + "ROIG", + "ROIH", + "ROII", + "ROIJ", + "ROIK", + "ROIL", + "ROIM", + "ROIN", + "ROIO", + "ROIP", + + // Level debris + "GFZD", // GFZ debris + "BRIC", // Bricks + "WDDB", // Wood Debris + "BRIR", // CEZ3 colored bricks + "BRIB", + "BRIY", + + // Gravity Well Objects + "GWLG", + "GWLR", + + //SRB2kart Sprites (sort later) + "RNDM", // Random Item Box + "RPOP", // Random Item Box Pop + "SGNS", // Signpost sparkle + "FAST", // Speed boost trail + "DSHR", // Speed boost dust release + "BOST", // Sneaker booster flame + "BOSM", // Sneaker booster smoke + "KFRE", // Sneaker fire trail + "KINV", // Invincibility sparkle trail + "KINF", // Invincibility flash + "WIPD", // Wipeout dust trail + "DRIF", // Drift Sparks + "BDRF", // Brake drift sparks + "DRWS", // Drift dust sparks + + // Kart Items + "RSHE", // Rocket sneaker + "FITM", // Eggman Monitor + "BANA", // Banana Peel + "ORBN", // Orbinaut + "JAWZ", // Jawz + "SSMN", // SS Mine + "KRBM", // SS Mine BOOM + "BHOG", // Ballhog + "BHBM", // Ballhog BOOM + "SPBM", // Self-Propelled Bomb + "THNS", // Thunder Shield + "BUBS", // Bubble Shield (not Bubs) + "BWVE", // Bubble Shield waves + "FLMS", // Flame Shield + "FLMD", // Flame Shield dash + "FLMP", // Flame Shield paper sprites + "FLML", // Flame Shield speed lines + "FLMF", // Flame Shield flash + "SINK", // Kitchen Sink + "SITR", // Kitchen Sink Trail + "KBLN", // Battle Mode Bumper + + "DEZL", // DEZ Laser respawn + + // Additional Kart Objects + "POKE", // Pokey + "AUDI", // Audience members + "DECO", // Old 1.0 Kart Decoratives + New misc ones + "DOOD", // All the old D00Dkart objects + "SNES", // Sprites for SNES remake maps + "GBAS", // Sprites for GBA remake maps + "SPRS", // Sapphire Coast Spring Shell + "BUZB", // Sapphire Coast Buzz Mk3 + "CHOM", // Sapphire Coast Chomper + "SACO", // Sapphire Coast Fauna + "CRAB", // Crystal Abyss mobs + "BRNG", // Chaotix Big Ring + + "BUMP", // Player/shell bump + "FLEN", // Shell hit graphics stuff + "CLAS", // items clash + "PSHW", // thrown indicator + "ISTA", // instashield layer A + "ISTB", // instashield layer B + + "ARRO", // player arrows + "ITEM", + "ITMO", + "ITMI", + "ITMN", + "WANT", + + "PBOM", // player bomb + + "HIT1", // battle points + "HIT2", // battle points + "HIT3", // battle points + + "RETI", // player reticule + + "AIDU", + + "KSPK", // Spark radius for the lightning shield + "LZI1", // Lightning that falls on the player for lightning shield + "LZI2", // ditto + "KLIT", // You have a twisted mind. But this actually is for the diagonal lightning. + + "FZSM", // F-Zero NO CONTEST explosion + "FZBM", + + // Various plants + "SBUS", + + "MARB", // Marble Zone sprites + "FUFO", // CD Special Stage UFO (don't ask me why it begins with an F) + + "RUST", // Rusty Rig sprites + + "VAPE", // Volcanic Valley + + // Hill Top Zone + "HTZA", + "HTZB", + + // Ports of gardens + "SGVA", + "SGVB", + "SGVC", + "PGTR", + "PGF1", + "PGF2", + "PGF3", + "PGBH", + "DPLR", + + // Midnight Channel stuff: + "SPTL", // Spotlight + "ENM1", // Shadows (Roaming and static) + "GARU", // Wind attack roaming shadows use. + "MARR", // Mayonaka Arrow + + //Mementos stuff: + "REAP", + + "JITB", // Jack In The Box + + // Color Drive stuff: + "CDMO", + "CDBU", + + // Daytona Speedway + "DPIN", + + // Egg Zeppelin + "PPLR", + + // Desert Palace + "DPPT", + + // Aurora Atoll + "AATR", + "COCO", + + // Barren Badlands + "BDST", + "FROG", + "CBRA", + "HOLE", + "BBRA", + + // Eerie Grove + "EGFG", + + // SMK ports + "SMKP", + "MTYM", + "THWP", + "SNOB", + "ICEB", + + // Ezo's maps - many single-use sprites! + "ECND", + "DOCH", + "DUCK", + "GTRE", + "CHES", + "CHIM", + "DRGN", + "LZMN", + "PGSS", + "ZTCH", + "MKMA", + "MKMP", + "RTCH", + "BOWL", + "BOWH", + "BRRL", + "BRRR", + "HRSE", + "TOAH", + "BFRT", + "OFRT", + "RFRT", + "PFRT", + "ASPK", + "HBST", + "HBSO", + "HBSF", + "WBLZ", + "WBLN", + + "FWRK", + "MXCL", + "RGSP", + "DRAF", + "GRES", + + "OTFG", + + "DBOS", // Drift boost flame + + "EGOO", + + "WTRL", // Water Trail + + "GCHA", // follower: generic chao + "CHEZ", // follower: cheese + + // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later + "VIEW", + + "DBCL", // Drift boost clip + "DBNC", // Drift boost clip's sparks + "DBST", // Drift boost plume +}; + +char spr2names[NUMPLAYERSPRITES][5] = +{ + "STIN", "STIL", "STIR", // Still + "SLWN", "SLWL", "SLWR", // Slow driving + "FSTN", "FSTL", "FSTR", // Fast driving + "DRLN", "DRLO", "DRLI", // Drifting left + "DRRN", "DRRO", "DRRI", // Drifting right + "SPIN", // Spinout + "SQSH", // Squish + "SIGN", // Finish signpost + "XTRA", // Three Faces of Darkness +}; +playersprite_t free_spr2 = SPR2_FIRSTFREESLOT; + +playersprite_t spr2defaults[NUMPLAYERSPRITES] = { + 0, // SPR2_STIN + SPR2_STIN, // SPR2_STIL + SPR2_STIN, // SPR2_STIR + + 0, // SPR2_SLWN + SPR2_SLWN, // SPR2_SLWL + SPR2_SLWN, // SPR2_SLWR + + 0, // SPR2_FSTN + SPR2_FSTN, // SPR2_FSTL + SPR2_FSTN, // SPR2_FSTR + + 0, // SPR2_DRLN + SPR2_DRLN, // SPR2_DRLO + SPR2_DRLN, // SPR2_DRLI + + 0, // SPR2_DRRN + SPR2_DRRN, // SPR2_DRRO + SPR2_DRRN, // SPR2_DRRI + + 0, // SPR2_SPIN + SPR2_SPIN, // SPR2_SQSH + + 0, // SPR2_SIGN }; // Doesn't work with g++, needs actionf_p1 (don't modify this comment) state_t states[NUMSTATES] = { // frame is masked through FF_FRAMEMASK - // FF_ANIMATE (0x4000) makes simple state animations (var1 #frames, var2 tic delay) - // FF_FULLBRIGHT (0x8000) activates the fullbright colormap + // FF_ANIMATE makes simple state animations (var1 #frames, var2 tic delay) + // FF_FULLBRIGHT activates the fullbright colormap // use FF_TRANS10 - FF_TRANS90 for easy translucency // (or tr_trans10< 0) + skincolorsbackup = Z_Realloc(skincolorsbackup, skincolorsbackupsize, PU_STATIC, NULL); + else + M_Memcpy(skincolorsbackup, skincolors, sizeof(skincolors)); #endif } @@ -21183,5 +28977,13 @@ void P_ResetData(INT32 flags) else M_Memcpy(mobjinfo, mobjinfobackup, sizeof(mobjinfobackup)); } + + if (flags & 8) + { + if (skincolorsbackupsize > 0) + lzf_decompress(skincolorsbackup, skincolorsbackupsize, skincolors, sizeof(skincolors)); + else + M_Memcpy(skincolors, skincolorsbackup, sizeof(skincolorsbackup)); + } #endif } diff --git a/src/info.h b/src/info.h index e34e7bd53..e7d53cb5b 100644 --- a/src/info.h +++ b/src/info.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,18 +27,18 @@ void A_Explode(); void A_Pain(); void A_Fall(); -void A_MonitorPop(); void A_Look(); void A_Chase(); void A_FaceStabChase(); +void A_FaceStabRev(); +void A_FaceStabHurl(); +void A_FaceStabMiss(); +void A_StatueBurst(); void A_FaceTarget(); void A_FaceTracer(); void A_Scream(); void A_BossDeath(); void A_CustomPower(); // Use this for a custom power -void A_GiveWeapon(); // Gives the player weapon(s) -void A_JumpShield(); // Obtained Jump Shield -void A_RingShield(); // Obtained Ring Shield void A_RingBox(); // Obtained Ring Box Tails void A_Invincibility(); // Obtained Invincibility Box void A_SuperSneakers(); // Obtained Super Sneakers Box @@ -48,18 +48,12 @@ void A_FanBubbleSpawn(); void A_BubbleRise(); // Bubbles float to surface void A_BubbleCheck(); // Don't draw if not underwater void A_AwardScore(); -void A_ExtraLife(); // Extra Life -void A_BombShield(); // Obtained Bomb Shield -void A_WaterShield(); // Obtained Water Shield -void A_ForceShield(); // Obtained Force Shield -void A_PityShield(); // Obtained Pity Shield. We're... sorry. +void A_GiveShield(); // Obtained Shield void A_GravityBox(); void A_ScoreRise(); // Rise the score logo -void A_ParticleSpawn(); void A_AttractChase(); // Ring Chase void A_DropMine(); // Drop Mine from Skim or Jetty-Syn Bomber void A_FishJump(); // Fish Jump -void A_ThrownRing(); // Sparkle trail for red ring void A_GrenadeRing(); // SRB2kart void A_SetSolidSteam(); void A_UnsetSolidSteam(); @@ -78,7 +72,6 @@ void A_DetonChase(); // Deton Chaser void A_CapeChase(); // Fake little Super Sonic cape void A_RotateSpikeBall(); // Spike ball rotation void A_SlingAppear(); -void A_MaceRotate(); void A_UnidusBall(); void A_RockSpawn(); void A_SetFuse(); @@ -87,7 +80,6 @@ void A_SmokeTrailer(); void A_RingExplode(); void A_OldRingExplode(); void A_MixUp(); -void A_RecyclePowers(); void A_BossScream(); void A_Boss2TakeDamage(); void A_GoopSplat(); @@ -101,13 +93,23 @@ void A_JetJawRoam(); void A_JetJawChomp(); void A_PointyThink(); void A_CheckBuddy(); +void A_HoodFire(); void A_HoodThink(); -void A_ArrowCheck(); +void A_HoodFall(); +void A_ArrowBonks(); void A_SnailerThink(); void A_SharpChase(); void A_SharpSpin(); +void A_SharpDecel(); +void A_CrushstaceanWalk(); +void A_CrushstaceanPunch(); +void A_CrushclawAim(); +void A_CrushclawLaunch(); void A_VultureVtol(); void A_VultureCheck(); +void A_VultureHover(); +void A_VultureBlast(); +void A_VultureFly(); void A_SkimChase(); void A_SkullAttack(); void A_LobShot(); @@ -128,11 +130,11 @@ void A_SetReactionTime(); void A_Boss1Spikeballs(); void A_Boss3TakeDamage(); void A_Boss3Path(); +void A_Boss3ShockThink(); void A_LinedefExecute(); void A_PlaySeeSound(); void A_PlayAttackSound(); void A_PlayActiveSound(); -void A_1upThinker(); void A_BossZoom(); //Unused void A_Boss1Chase(); void A_Boss2Chase(); @@ -143,6 +145,9 @@ void A_SpawnObjectAbsolute(); void A_SpawnObjectRelative(); void A_ChangeAngleRelative(); void A_ChangeAngleAbsolute(); +void A_RollAngle(); +void A_ChangeRollAngleRelative(); +void A_ChangeRollAngleAbsolute(); void A_PlaySound(); void A_FindTarget(); void A_FindTracer(); @@ -150,6 +155,7 @@ void A_SetTics(); void A_SetRandomTics(); void A_ChangeColorRelative(); void A_ChangeColorAbsolute(); +void A_Dye(); void A_MoveRelative(); void A_MoveAbsolute(); void A_Thrust(); @@ -166,7 +172,7 @@ void A_ItemPop(); // SRB2kart void A_JawzChase(); // SRB2kart void A_JawzExplode(); // SRB2kart void A_SPBChase(); // SRB2kart -void A_MineExplode(); // SRB2kart +void A_SSMineExplode(); // SRB2kart void A_BallhogExplode(); // SRB2kart void A_LightningFollowPlayer(); // SRB2kart: Lightning shield effect player chasing void A_FZBoomFlash(); // SRB2kart @@ -176,7 +182,6 @@ void A_RoamingShadowThinker(); // SRB2kart: Roaming Shadow moving + attacking pl void A_MayonakaArrow(); //SRB2kart: midnight channel arrow sign void A_ReaperThinker(); //SRB2kart: mementos reaper void A_MementosTPParticles(); //SRB2kart: mementos teleporter particles. Man that's a lot of actions for my shite. -void A_FlameParticle(); // SRB2kart void A_FlameShieldPaper(); void A_OrbitNights(); void A_GhostMe(); @@ -224,6 +229,66 @@ void A_BrakFireShot(); void A_BrakLobShot(); void A_NapalmScatter(); void A_SpawnFreshCopy(); +void A_FlickySpawn(); +void A_FlickyCenter(); +void A_FlickyAim(); +void A_FlickyFly(); +void A_FlickySoar(); +void A_FlickyCoast(); +void A_FlickyHop(); +void A_FlickyFlounder(); +void A_FlickyCheck(); +void A_FlickyHeightCheck(); +void A_FlickyFlutter(); +void A_FlameParticle(); +void A_FadeOverlay(); +void A_Boss5Jump(); +void A_LightBeamReset(); +void A_MineExplode(); +void A_MineRange(); +void A_ConnectToGround(); +void A_SpawnParticleRelative(); +void A_MultiShotDist(); +void A_WhoCaresIfYourSonIsABee(); +void A_ParentTriesToSleep(); +void A_CryingToMomma(); +void A_CheckFlags2(); +void A_Boss5FindWaypoint(); +void A_DoNPCSkid(); +void A_DoNPCPain(); +void A_PrepareRepeat(); +void A_Boss5ExtraRepeat(); +void A_Boss5Calm(); +void A_Boss5CheckOnGround(); +void A_Boss5CheckFalling(); +void A_Boss5PinchShot(); +void A_Boss5MakeItRain(); +void A_Boss5MakeJunk(); +void A_LookForBetter(); +void A_Boss5BombExplode(); +void A_TNTExplode(); +void A_DebrisRandom(); +void A_TrainCameo(); +void A_TrainCameo2(); +void A_CanarivoreGas(); +void A_KillSegments(); +void A_SnapperSpawn(); +void A_SnapperThinker(); +void A_SaloonDoorSpawn(); +void A_MinecartSparkThink(); +void A_ModuloToState(); +void A_LavafallRocks(); +void A_LavafallLava(); +void A_FallingLavaCheck(); +void A_FireShrink(); +void A_SpawnPterabytes(); +void A_PterabyteHover(); +void A_RolloutSpawn(); +void A_RolloutRock(); +void A_DragonbomberSpawn(); +void A_DragonWing(); +void A_DragonSegment(); +void A_ChangeHeight(); // ratio of states to sprites to mobj types is roughly 6 : 1 : 1 #define NUMMOBJFREESLOTS 512 @@ -240,58 +305,77 @@ typedef enum sprite SPR_PLAY, // Enemies - SPR_POSS, - SPR_SPOS, - SPR_FISH, // Greenflower Fish + SPR_POSS, // Crawla (Blue) + SPR_SPOS, // Crawla (Red) + SPR_FISH, // SDURF SPR_BUZZ, // Buzz (Gold) SPR_RBUZ, // Buzz (Red) SPR_JETB, // Jetty-Syn Bomber - SPR_JETW, // Jetty-Syn Water Bomber SPR_JETG, // Jetty-Syn Gunner SPR_CCOM, // Crawla Commander SPR_DETN, // Deton SPR_SKIM, // Skim mine dropper - SPR_TRET, + SPR_TRET, // Industrial Turret SPR_TURR, // Pop-Up Turret SPR_SHRP, // Sharp + //SPR_CRAB, // Crushstacean + SPR_CR2B, // Banpyura + SPR_CSPR, // Banpyura spring SPR_JJAW, // Jet Jaw SPR_SNLR, // Snailer - SPR_VLTR, // Vulture + SPR_VLTR, // BASH SPR_PNTY, // Pointy SPR_ARCH, // Robo-Hood - SPR_CBFS, // CastleBot FaceStabber (Egg Knight?) + SPR_CBFS, // Castlebot Facestabber + SPR_STAB, // Castlebot Facestabber spear aura SPR_SPSH, // Egg Guard - SPR_ESHI, // Egg Shield for Egg Guard + SPR_ESHI, // Egg Guard's shield SPR_GSNP, // Green Snapper + SPR_GSNL, // Green Snapper leg + SPR_GSNH, // Green Snapper head SPR_MNUS, // Minus + SPR_MNUD, // Minus dirt SPR_SSHL, // Spring Shell SPR_UNID, // Unidus - SPR_BBUZ, // AquaBuzz, for Azure Temple + SPR_CANA, // Canarivore + SPR_CANG, // Canarivore gas + SPR_PYRE, // Pyre Fly + SPR_PTER, // Pterabyte + SPR_DRAB, // Dragonbomber // Generic Boss Items SPR_JETF, // Boss jet fumes // Boss 1 (Greenflower) - SPR_EGGM, + SPR_EGGM, // Boss 1 + SPR_EGLZ, // Boss 1 Junk // Boss 2 (Techno Hill) SPR_EGGN, // Boss 2 - SPR_TNKA, // Boss 2 Tank 1 - SPR_TNKB, // Boss 2 Tank 2 - SPR_SPNK, // Boss 2 Spigot + SPR_TANK, // Boss 2 Junk SPR_GOOP, // Boss 2 Goop // Boss 3 (Deep Sea) SPR_EGGO, // Boss 3 - SPR_PRPL, // Boss 3 Propeller + SPR_SEBH, // Boss 3 Junk SPR_FAKE, // Boss 3 Fakemobile + SPR_SHCK, // Boss 3 Shockwave // Boss 4 (Castle Eggman) SPR_EGGP, SPR_EFIR, // Boss 4 jet flame + SPR_EGR1, // Boss 4 Spectator Eggrobo // Boss 5 (Arid Canyon) - SPR_EGGQ, + SPR_FANG, // replaces EGGQ + SPR_BRKN, + SPR_WHAT, + SPR_VWRE, + SPR_PROJ, // projector light + SPR_FBOM, + SPR_FSGN, + SPR_BARX, // bomb explosion (also used by barrel) + SPR_BARD, // bomb dust (also used by barrel) // Boss 6 (Red Volcano) SPR_EGGR, @@ -319,51 +403,61 @@ typedef enum sprite // Collectible Items SPR_RING, SPR_TRNG, // Team Rings - SPR_EMMY, // emerald test SPR_TOKE, // Special Stage Token SPR_RFLG, // Red CTF Flag SPR_BFLG, // Blue CTF Flag - SPR_NWNG, // NiGHTS Wing collectable item. + //SPR_SPHR, // Sphere + SPR_NCHP, // NiGHTS chip + SPR_NSTR, // NiGHTS star SPR_EMBM, // Emblem SPR_CEMG, // Chaos Emeralds - SPR_EMER, // Emerald Hunt + SPR_SHRD, // Emerald Hunt // Interactive Objects - SPR_FANS, - SPR_BUBL, // water bubble source + SPR_BBLS, // water bubble source SPR_SIGN, // Level end sign - SPR_STEM, // Steam riser SPR_SPIK, // Spike Ball SPR_SFLM, // Spin fire SPR_USPK, // Floor spike + SPR_WSPK, // Wall spike + SPR_WSPB, // Wall spike base SPR_STPT, // Starpost SPR_BMNE, // Big floating mine + SPR_PUMI, // Rollout Rock // Monitor Boxes - SPR_SRBX, - SPR_RRBX, - SPR_BRBX, - SPR_SHTV, - SPR_PINV, - SPR_YLTV, - SPR_BLTV, // Force shield - SPR_BKTV, // Bomb shield TV - SPR_WHTV, // Jump shield TV - SPR_GRTV, // Pity shield TV - SPR_ELTV, // Elemental shield TV - SPR_EGGB, // Eggman box - SPR_MIXU, // Player mixing monitor - SPR_RECY, // Recycler (power mixing) monitor - SPR_QUES, // Random monitor - SPR_GBTV, // Gravity boots TV - SPR_PRUP, // 1up - SPR_PTTV, // Score TVs + SPR_MSTV, // MiSc TV sprites + SPR_XLTV, // eXtra Large TV sprites - // Monitor Miscellany - SPR_MTEX, // Exploding monitor + SPR_TRRI, // Red team: 10 RIngs + SPR_TBRI, // Blue team: 10 RIngs + + SPR_TVRI, // 10 RIng + SPR_TVPI, // PIty shield + SPR_TVAT, // ATtraction shield + SPR_TVFO, // FOrce shield + SPR_TVAR, // ARmageddon shield + SPR_TVWW, // WhirlWind shield + SPR_TVEL, // ELemental shield + SPR_TVSS, // Super Sneakers + SPR_TVIV, // InVincibility + SPR_TV1U, // 1Up + SPR_TV1P, // 1uP (textless) + SPR_TVEG, // EGgman + SPR_TVMX, // MiXup + SPR_TVMY, // MYstery + SPR_TVGV, // GraVity boots + SPR_TVRC, // ReCycler + SPR_TV1K, // 1,000 points (1 K) + SPR_TVTK, // 10,000 points (Ten K) + SPR_TVFL, // FLame shield + SPR_TVBB, // BuBble shield + SPR_TVZP, // Thunder shield (ZaP) // Projectiles SPR_MISL, + SPR_LASR, // GFZ3 laser + SPR_LASF, // GFZ3 laser flames SPR_TORP, // Torpedo SPR_ENRG, // Energy ball SPR_MINE, // Skim mine @@ -373,6 +467,9 @@ typedef enum sprite SPR_AROW, // Arrow SPR_CFIR, // Colored fire of various sorts + // The letter + SPR_LETR, + // Greenflower Scenery SPR_FWR1, SPR_FWR2, // GFZ Sunflower @@ -380,19 +477,33 @@ typedef enum sprite SPR_FWR4, SPR_BUS1, // GFZ Bush w/ berries SPR_BUS2, // GFZ Bush w/o berries + SPR_BUS3, // GFZ Bush w/ BLUE berries + // Trees (both GFZ and misc) + SPR_TRE1, // GFZ + SPR_TRE2, // Checker + SPR_TRE3, // Frozen Hillside + SPR_TRE4, // Polygon + SPR_TRE5, // Bush tree + SPR_TRE6, // Spring tree // Techno Hill Scenery - SPR_THZP, // Techno Hill Zone Plant + SPR_THZP, // THZ1 Steam Flower + SPR_FWR5, // THZ1 Spin flower (red) + SPR_FWR6, // THZ1 Spin flower (yellow) + SPR_THZT, // Steam Whistle tree/bush SPR_ALRM, // THZ2 Alarm // Deep Sea Scenery SPR_GARG, // Deep Sea Gargoyle SPR_SEWE, // Deep Sea Seaweed SPR_DRIP, // Dripping water - SPR_CRL1, // Coral 1 - SPR_CRL2, // Coral 2 - SPR_CRL3, // Coral 3 + SPR_CORL, // Coral SPR_BCRY, // Blue Crystal + SPR_KELP, // Kelp + SPR_ALGA, // Animated algae top + SPR_ALGB, // Animated algae segment + SPR_DSTG, // DSZ Stalagmites + SPR_LIBE, // DSZ Light beam // Castle Eggman Scenery SPR_CHAN, // CEZ Chain @@ -402,30 +513,85 @@ typedef enum sprite SPR_BMCH, // Big Mace Chain SPR_SMCE, // Small Mace SPR_BMCE, // Big Mace + SPR_YSPB, // Yellow spring on a ball + SPR_RSPB, // Red spring on a ball + SPR_SFBR, // Small Firebar + SPR_BFBR, // Big Firebar + SPR_BANR, // Banner/pole + SPR_PINE, // Pine Tree + SPR_CEZB, // Bush + SPR_CNDL, // Candle/pricket + SPR_FLMH, // Flame holder + SPR_CTRC, // Fire torch + SPR_CFLG, // Waving flag/segment + SPR_CSTA, // Crawla statue + SPR_CBBS, // Facestabber statue + SPR_CABR, // Brambles // Arid Canyon Scenery SPR_BTBL, // Big tumbleweed SPR_STBL, // Small tumbleweed - SPR_CACT, // Cacti sprites + SPR_CACT, // Cacti + SPR_WWSG, // Caution Sign + SPR_WWS2, // Cacti Sign + SPR_WWS3, // Sharp Turn Sign + SPR_OILL, // Oil lamp + SPR_OILF, // Oil lamp flare + SPR_BARR, // TNT barrel + SPR_REMT, // TNT proximity shell + SPR_TAZD, // Dust devil + SPR_ADST, // Arid dust + SPR_MCRT, // Minecart + SPR_MCSP, // Minecart spark + SPR_SALD, // Saloon door + SPR_TRAE, // Train cameo locomotive + SPR_TRAI, // Train cameo wagon + SPR_STEA, // Train steam // Red Volcano Scenery SPR_FLME, // Flame jet SPR_DFLM, // Blade's flame + SPR_LFAL, // Lavafall + SPR_JPLA, // Jungle palm + SPR_TFLO, // Torch flower + SPR_WVIN, // Wall vines // Dark City Scenery // Egg Rock Scenery // Christmas Scenery - SPR_XMS1, - SPR_XMS2, - SPR_XMS3, + SPR_XMS1, // Christmas Pole + SPR_XMS2, // Candy Cane + SPR_XMS3, // Snowman + SPR_XMS4, // Lamppost + SPR_XMS5, // Hanging Star + SPR_XMS6, // Mistletoe + SPR_FHZI, // FHZ Ice + SPR_ROSY, + + // Halloween Scenery + SPR_PUMK, // Pumpkins + SPR_HHPL, // Dr Seuss Trees + SPR_SHRM, // Mushroom + SPR_HHZM, // Misc + + // Azure Temple Scenery + SPR_BGAR, // ATZ Gargoyles + SPR_RCRY, // ATZ Red Crystal (Target) + SPR_CFLM, // Green torch flame // Botanic Serenity Scenery SPR_BSZ1, // Tall flowers SPR_BSZ2, // Medium flowers SPR_BSZ3, // Small flowers - SPR_BSZ4, // Tulip + //SPR_BSZ4, -- Tulips + SPR_BST1, // Red tulip + SPR_BST2, // Purple tulip + SPR_BST3, // Blue tulip + SPR_BST4, // Cyan tulip + SPR_BST5, // Yellow tulip + SPR_BST6, // Orange tulip SPR_BSZ5, // Cluster of Tulips SPR_BSZ6, // Bush SPR_BSZ7, // Vine @@ -434,7 +600,6 @@ typedef enum sprite // Misc Scenery SPR_STLG, // Stalagmites SPR_DBAL, // Disco - SPR_RCRY, // ATZ Red Crystal (Target) // Powerup Indicators SPR_ARMA, // Armageddon Shield Orb @@ -442,23 +607,43 @@ typedef enum sprite SPR_ARMB, // Armageddon Shield Ring, Back SPR_WIND, // Whirlwind Shield Orb SPR_MAGN, // Attract Shield Orb - SPR_ELEM, // Elemental Shield Orb and Fire + SPR_ELEM, // Elemental Shield Orb SPR_FORC, // Force Shield Orb SPR_PITY, // Pity Shield Orb + SPR_FIRS, // Flame Shield Orb + //SPR_BUBS, // Bubble Shield Orb + SPR_ZAPS, // Thunder Shield Orb SPR_IVSP, // invincibility sparkles SPR_SSPK, // Super Sonic Spark SPR_GOAL, // Special Stage goal (here because lol NiGHTS) - // Freed Animals - SPR_BIRD, // Birdie freed! - SPR_BUNY, // Bunny freed! - SPR_MOUS, // Mouse - SPR_CHIC, // Chicken - SPR_COWZ, // Cow - SPR_RBRD, // Red Birdie in Bubble + // Flickies + SPR_FBUB, // Flicky-sized bubble + SPR_FL01, // Bluebird + SPR_FL02, // Rabbit + SPR_FL03, // Chicken + SPR_FL04, // Seal + SPR_FL05, // Pig + SPR_FL06, // Chipmunk + SPR_FL07, // Penguin + SPR_FL08, // Fish + SPR_FL09, // Ram + SPR_FL10, // Puffin + SPR_FL11, // Cow + SPR_FL12, // Rat + SPR_FL13, // Bear + SPR_FL14, // Dove + SPR_FL15, // Cat + SPR_FL16, // Canary + SPR_FS01, // Spider + SPR_FS02, // Bat // Springs + SPR_FANS, // Fan + SPR_STEM, // Steam riser + SPR_BMPR, // Bumpers + SPR_BLON, // Balloons SPR_SPVY, // Yellow Vertical Spring SPR_SPVR, // Red Vertical Spring SPR_SPVB, // Blue Vertical Spring @@ -471,19 +656,21 @@ typedef enum sprite SPR_SPHR, // Red Horizontal Spring SPR_SPHB, // Blue Horizontal Spring SPR_SPHG, // Grey Horizontal Spring + SPR_BSTY, // Yellow Booster + SPR_BSTR, // Red Booster // Environmental Effects SPR_RAIN, // Rain SPR_SNO1, // Snowflake SPR_SNO2, // Blizzard Snowball SPR_SPLH, // Water Splish + SPR_LSPL, // Lava Splish SPR_SPLA, // Water Splash SPR_SMOK, - SPR_BUBP, // Small bubble - SPR_BUBO, // Medium bubble - SPR_BUBN, // Large bubble - SPR_BUBM, // Extra Large (would you like fries with that?) bubble - SPR_POPP, // Extra Large bubble goes POP! + SPR_BUBL, // Bubble + SPR_WZAP, + SPR_DUST, // Spindash dust + SPR_FPRT, // Spindash dust (flame) SPR_TFOG, // Teleport Fog SPR_SEED, // Sonic CD flower seed SPR_PRTL, // Particle (for fans, etc.) @@ -491,8 +678,14 @@ typedef enum sprite // Game Indicators SPR_SCOR, // Score logo SPR_DRWN, // Drowning Timer + SPR_FLII, // AI flight indicator + SPR_LCKN, // Target SPR_TTAG, // Tag Sign SPR_GFLG, // Got Flag sign + SPR_FNSF, // Finish flag + + SPR_CORK, + SPR_LHRT, // Ring Weapons SPR_RRNG, // Red Ring @@ -534,23 +727,38 @@ typedef enum sprite // NiGHTS Stuff SPR_NDRN, // NiGHTS drone - SPR_SUPE, // NiGHTS character flying - SPR_SUPZ, // NiGHTS hurt - SPR_NDRL, // NiGHTS character drilling SPR_NSPK, // NiGHTS sparkle SPR_NBMP, // NiGHTS Bumper SPR_HOOP, // NiGHTS hoop sprite SPR_NSCR, // NiGHTS score sprite SPR_NPRU, // Nights Powerups SPR_CAPS, // Capsule thingy for NiGHTS - SPR_SUPT, // Super Sonic Transformation (NiGHTS) + SPR_IDYA, // Ideya + SPR_NTPN, // Nightopian + SPR_SHLP, // Shleep + + // Secret badniks and hazards, shhhh + SPR_PENG, + SPR_POPH, + SPR_HIVE, + SPR_BUMB, + SPR_BBUZ, + SPR_FMCE, + SPR_HMCE, + SPR_CACO, + SPR_BAL2, + SPR_SBOB, + SPR_SBFL, + SPR_SBSK, + SPR_HBAT, // Debris - SPR_SPRK, // spark + SPR_SPRK, // Sparkle SPR_BOM1, // Robot Explosion SPR_BOM2, // Boss Explosion 1 SPR_BOM3, // Boss Explosion 2 SPR_BOM4, // Underwater Explosion + SPR_BMNB, // Mine Explosion // Crumbly rocks SPR_ROIA, @@ -570,31 +778,19 @@ typedef enum sprite SPR_ROIO, SPR_ROIP, - // Blue Spheres - SPR_BBAL, + // Level debris + SPR_GFZD, // GFZ debris + SPR_BRIC, // Bricks + SPR_WDDB, // Wood Debris + SPR_BRIR, // CEZ3 colored bricks + SPR_BRIB, + SPR_BRIY, // Gravity Well Objects SPR_GWLG, SPR_GWLR, - // SRB1 Sprites - SPR_SRBA, - SPR_SRBB, - SPR_SRBC, - SPR_SRBD, - SPR_SRBE, - SPR_SRBF, - SPR_SRBG, - SPR_SRBH, - SPR_SRBI, - SPR_SRBJ, - SPR_SRBK, - SPR_SRBL, - SPR_SRBM, - SPR_SRBN, - SPR_SRBO, - - // Springs + // SRB2Kart SPR_RNDM, // Random Item Box SPR_RPOP, // Random Item Box Pop SPR_SGNS, // Signpost sparkle @@ -608,7 +804,6 @@ typedef enum sprite SPR_WIPD, // Wipeout dust trail SPR_DRIF, // Drift Sparks SPR_BDRF, // Brake drift sparks - SPR_DUST, // Drift Dust SPR_DRWS, // Drift dust sparks // Kart Items @@ -681,7 +876,6 @@ typedef enum sprite SPR_FZSM, // F-Zero NO CONTEST explosion SPR_FZBM, - SPR_FPRT, // Various plants SPR_SBUS, @@ -691,8 +885,6 @@ typedef enum sprite SPR_RUST, // Rusty Rig sprites - SPR_BLON, // D2 Balloon Panic - SPR_VAPE, // Volcanic Valley // Hill Top Zone @@ -726,7 +918,7 @@ typedef enum sprite SPR_CDBU, // Daytona Speedway - SPR_PINE, + SPR_DPIN, // Egg Zeppelin SPR_PPLR, @@ -756,7 +948,7 @@ typedef enum sprite SPR_ICEB, // Ezo's maps - many single-use sprites! - SPR_CNDL, + SPR_ECND, SPR_DOCH, SPR_DUCK, SPR_GTRE, @@ -800,13 +992,8 @@ typedef enum sprite SPR_WTRL, // Water Trail - // Xmas-specific sprites that don't fit aboxe - SPR_XMS4, - SPR_XMS5, - - SPR_FBUB, // follower bubble - SPR_GCHA, // follower: generic chao - SPR_CHEZ, // follower: cheese + SPR_GCHA, // follower: generic chao + SPR_CHEZ, // follower: cheese // First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later SPR_VIEW, @@ -820,6 +1007,25 @@ typedef enum sprite NUMSPRITES } spritenum_t; +// Make sure to be conscious of FF_FRAMEMASK and the fact sprite2 is stored as a UINT8 whenever you change this table. +// Currently, FF_FRAMEMASK is 0xff, or 255 - but the second half is used by FF_SPR2SUPER, so the limitation is 0x7f. +// Since this is zero-based, there can be at most 128 different SPR2_'s without changing that. +typedef enum playersprite +{ + SPR2_STIN = 0, SPR2_STIL, SPR2_STIR, + SPR2_SLWN, SPR2_SLWL, SPR2_SLWR, + SPR2_FSTN, SPR2_FSTL, SPR2_FSTR, + SPR2_DRLN, SPR2_DRLO, SPR2_DRLI, + SPR2_DRRN, SPR2_DRRO, SPR2_DRRI, + SPR2_SPIN, + SPR2_SQSH, + SPR2_SIGN, + SPR2_XTRA, + SPR2_FIRSTFREESLOT, + SPR2_LASTFREESLOT = 0x7f, + NUMPLAYERSPRITES +} playersprite_t; + typedef enum state { S_NULL, @@ -837,67 +1043,28 @@ typedef enum state // Thok S_THOK, - // SRB2kart Frames - S_KART_STILL1, - S_KART_STILL2, - S_KART_STILL1_L, - S_KART_STILL2_L, - S_KART_STILL1_R, - S_KART_STILL2_R, - - S_KART_SLOW1, - S_KART_SLOW2, - S_KART_SLOW1_L, - S_KART_SLOW2_L, - S_KART_SLOW1_R, - S_KART_SLOW2_R, - - S_KART_FAST1, - S_KART_FAST2, - S_KART_FAST1_L, - S_KART_FAST2_L, - S_KART_FAST1_R, - S_KART_FAST2_R, - - S_KART_DRIFT1_L, - S_KART_DRIFT2_L, - - S_KART_DRIFT1_L_OUT, - S_KART_DRIFT2_L_OUT, - - S_KART_DRIFT1_L_IN, - S_KART_DRIFT2_L_IN, - S_KART_DRIFT3_L_IN, - S_KART_DRIFT4_L_IN, - - S_KART_DRIFT1_R, - S_KART_DRIFT2_R, - - S_KART_DRIFT1_R_OUT, - S_KART_DRIFT2_R_OUT, - - S_KART_DRIFT1_R_IN, - S_KART_DRIFT2_R_IN, - S_KART_DRIFT3_R_IN, - S_KART_DRIFT4_R_IN, - - S_KART_SPIN, - S_KART_PAIN, + S_KART_STILL, + S_KART_STILL_L, + S_KART_STILL_R, + S_KART_SLOW, + S_KART_SLOW_L, + S_KART_SLOW_R, + S_KART_FAST, + S_KART_FAST_L, + S_KART_FAST_R, + S_KART_DRIFT_L, + S_KART_DRIFT_L_OUT, + S_KART_DRIFT_L_IN, + S_KART_DRIFT_R, + S_KART_DRIFT_R_OUT, + S_KART_DRIFT_R_IN, + S_KART_SPINOUT, S_KART_SQUISH, + S_KART_SIGN, // technically the player goes here but it's an infinite tic state S_OBJPLACE_DUMMY, - // 1-Up Box Sprites overlay (uses player sprite) - S_PLAY_BOX1, - S_PLAY_BOX2, - S_PLAY_ICON1, - S_PLAY_ICON2, - S_PLAY_ICON3, - - // Level end sign overlay (uses player sprite) - S_PLAY_SIGN, - // Blue Crawla S_POSS_STND, S_POSS_RUN1, @@ -934,10 +1101,6 @@ typedef enum state S_RBUZZFLY1, S_RBUZZFLY2, - // AquaBuzz - S_BBUZZFLY1, - S_BBUZZFLY2, - // Jetty-Syn Bomber S_JETBLOOK1, S_JETBLOOK2, @@ -974,7 +1137,6 @@ typedef enum state S_DETON13, S_DETON14, S_DETON15, - S_DETON16, // Skim Mine Dropper S_SKIM1, @@ -1016,14 +1178,55 @@ typedef enum state S_TURRETPOPDOWN7, S_TURRETPOPDOWN8, - // Sharp - S_SHARP_ROAM1, - S_SHARP_ROAM2, - S_SHARP_AIM1, - S_SHARP_AIM2, - S_SHARP_AIM3, - S_SHARP_AIM4, - S_SHARP_SPIN, + // Spincushion + S_SPINCUSHION_LOOK, + S_SPINCUSHION_CHASE1, + S_SPINCUSHION_CHASE2, + S_SPINCUSHION_CHASE3, + S_SPINCUSHION_CHASE4, + S_SPINCUSHION_AIM1, + S_SPINCUSHION_AIM2, + S_SPINCUSHION_AIM3, + S_SPINCUSHION_AIM4, + S_SPINCUSHION_AIM5, + S_SPINCUSHION_SPIN1, + S_SPINCUSHION_SPIN2, + S_SPINCUSHION_SPIN3, + S_SPINCUSHION_SPIN4, + S_SPINCUSHION_STOP1, + S_SPINCUSHION_STOP2, + S_SPINCUSHION_STOP3, + S_SPINCUSHION_STOP4, + + // Crushstacean + S_CRUSHSTACEAN_ROAM1, + S_CRUSHSTACEAN_ROAM2, + S_CRUSHSTACEAN_ROAM3, + S_CRUSHSTACEAN_ROAM4, + S_CRUSHSTACEAN_ROAMPAUSE, + S_CRUSHSTACEAN_PUNCH1, + S_CRUSHSTACEAN_PUNCH2, + S_CRUSHCLAW_AIM, + S_CRUSHCLAW_OUT, + S_CRUSHCLAW_STAY, + S_CRUSHCLAW_IN, + S_CRUSHCLAW_WAIT, + S_CRUSHCHAIN, + + // Banpyura + S_BANPYURA_ROAM1, + S_BANPYURA_ROAM2, + S_BANPYURA_ROAM3, + S_BANPYURA_ROAM4, + S_BANPYURA_ROAMPAUSE, + S_CDIAG1, + S_CDIAG2, + S_CDIAG3, + S_CDIAG4, + S_CDIAG5, + S_CDIAG6, + S_CDIAG7, + S_CDIAG8, // Jet Jaw S_JETJAW_ROAM1, @@ -1050,21 +1253,18 @@ typedef enum state S_JETJAW_CHOMP14, S_JETJAW_CHOMP15, S_JETJAW_CHOMP16, + S_JETJAW_SOUND, // Snailer S_SNAILER1, + S_SNAILER_FLICKY, // Vulture S_VULTURE_STND, - S_VULTURE_VTOL1, - S_VULTURE_VTOL2, - S_VULTURE_VTOL3, - S_VULTURE_VTOL4, + S_VULTURE_DRIFT, S_VULTURE_ZOOM1, S_VULTURE_ZOOM2, - S_VULTURE_ZOOM3, - S_VULTURE_ZOOM4, - S_VULTURE_ZOOM5, + S_VULTURE_STUNNED, // Pointy S_POINTY1, @@ -1072,13 +1272,14 @@ typedef enum state // Robo-Hood S_ROBOHOOD_LOOK, - S_ROBOHOOD_STND, - S_ROBOHOOD_SHOOT, - S_ROBOHOOD_JUMP, + S_ROBOHOOD_STAND, + S_ROBOHOOD_FIRE1, + S_ROBOHOOD_FIRE2, + S_ROBOHOOD_JUMP1, S_ROBOHOOD_JUMP2, - S_ROBOHOOD_FALL, + S_ROBOHOOD_JUMP3, - // CastleBot FaceStabber + // Castlebot Facestabber S_FACESTABBER_STND1, S_FACESTABBER_STND2, S_FACESTABBER_STND3, @@ -1089,6 +1290,11 @@ typedef enum state S_FACESTABBER_CHARGE2, S_FACESTABBER_CHARGE3, S_FACESTABBER_CHARGE4, + S_FACESTABBER_PAIN, + S_FACESTABBER_DIE1, + S_FACESTABBER_DIE2, + S_FACESTABBER_DIE3, + S_FACESTABBERSPEAR, // Egg Guard S_EGGGUARD_STND, @@ -1106,34 +1312,48 @@ typedef enum state // Egg Shield for Egg Guard S_EGGSHIELD, + S_EGGSHIELDBREAK, // Green Snapper + S_SNAPPER_SPAWN, + S_SNAPPER_SPAWN2, S_GSNAPPER_STND, S_GSNAPPER1, S_GSNAPPER2, S_GSNAPPER3, S_GSNAPPER4, + S_SNAPPER_XPLD, + S_SNAPPER_LEG, + S_SNAPPER_LEGRAISE, + S_SNAPPER_HEAD, // Minus + S_MINUS_INIT, S_MINUS_STND, - S_MINUS_DIGGING, + S_MINUS_DIGGING1, + S_MINUS_DIGGING2, + S_MINUS_DIGGING3, + S_MINUS_DIGGING4, + S_MINUS_BURST0, + S_MINUS_BURST1, + S_MINUS_BURST2, + S_MINUS_BURST3, + S_MINUS_BURST4, + S_MINUS_BURST5, S_MINUS_POPUP, - S_MINUS_UPWARD1, - S_MINUS_UPWARD2, - S_MINUS_UPWARD3, - S_MINUS_UPWARD4, - S_MINUS_UPWARD5, - S_MINUS_UPWARD6, - S_MINUS_UPWARD7, - S_MINUS_UPWARD8, - S_MINUS_DOWNWARD1, - S_MINUS_DOWNWARD2, - S_MINUS_DOWNWARD3, - S_MINUS_DOWNWARD4, - S_MINUS_DOWNWARD5, - S_MINUS_DOWNWARD6, - S_MINUS_DOWNWARD7, - S_MINUS_DOWNWARD8, + S_MINUS_AERIAL1, + S_MINUS_AERIAL2, + S_MINUS_AERIAL3, + S_MINUS_AERIAL4, + + // Minus dirt + S_MINUSDIRT1, + S_MINUSDIRT2, + S_MINUSDIRT3, + S_MINUSDIRT4, + S_MINUSDIRT5, + S_MINUSDIRT6, + S_MINUSDIRT7, // Spring Shell S_SSHELL_STND, @@ -1162,14 +1382,66 @@ typedef enum state S_UNIDUS_RUN, S_UNIDUS_BALL, + // Canarivore + S_CANARIVORE_LOOK, + S_CANARIVORE_AWAKEN1, + S_CANARIVORE_AWAKEN2, + S_CANARIVORE_AWAKEN3, + S_CANARIVORE_GAS1, + S_CANARIVORE_GAS2, + S_CANARIVORE_GAS3, + S_CANARIVORE_GAS4, + S_CANARIVORE_GAS5, + S_CANARIVORE_GASREPEAT, + S_CANARIVORE_CLOSE1, + S_CANARIVORE_CLOSE2, + S_CANARIVOREGAS_1, + S_CANARIVOREGAS_2, + S_CANARIVOREGAS_3, + S_CANARIVOREGAS_4, + S_CANARIVOREGAS_5, + S_CANARIVOREGAS_6, + S_CANARIVOREGAS_7, + S_CANARIVOREGAS_8, + + // Pyre Fly + S_PYREFLY_FLY, + S_PYREFLY_BURN, + S_PYREFIRE1, + S_PYREFIRE2, + + // Pterabyte + S_PTERABYTESPAWNER, + S_PTERABYTEWAYPOINT, + S_PTERABYTE_FLY1, + S_PTERABYTE_FLY2, + S_PTERABYTE_FLY3, + S_PTERABYTE_FLY4, + S_PTERABYTE_SWOOPDOWN, + S_PTERABYTE_SWOOPUP, + + // Dragonbomber + S_DRAGONBOMBER, + S_DRAGONWING1, + S_DRAGONWING2, + S_DRAGONWING3, + S_DRAGONWING4, + S_DRAGONTAIL_LOADED, + S_DRAGONTAIL_EMPTY, + S_DRAGONTAIL_EMPTYLOOP, + S_DRAGONTAIL_RELOAD, + S_DRAGONMINE, + S_DRAGONMINE_LAND1, + S_DRAGONMINE_LAND2, + S_DRAGONMINE_SLOWFLASH1, + S_DRAGONMINE_SLOWFLASH2, + S_DRAGONMINE_SLOWLOOP, + S_DRAGONMINE_FASTFLASH1, + S_DRAGONMINE_FASTFLASH2, + S_DRAGONMINE_FASTLOOP, + // Boss Explosion - S_BPLD1, - S_BPLD2, - S_BPLD3, - S_BPLD4, - S_BPLD5, - S_BPLD6, - S_BPLD7, + S_BOSSEXPLODE, // S3&K Boss Explosion S_SONIC3KBOSSEXPLOSION1, @@ -1180,10 +1452,10 @@ typedef enum state S_SONIC3KBOSSEXPLOSION6, S_JETFUME1, - S_JETFUME2, // Boss 1 S_EGGMOBILE_STND, + S_EGGMOBILE_ROFL, S_EGGMOBILE_LATK1, S_EGGMOBILE_LATK2, S_EGGMOBILE_LATK3, @@ -1193,7 +1465,6 @@ typedef enum state S_EGGMOBILE_LATK7, S_EGGMOBILE_LATK8, S_EGGMOBILE_LATK9, - S_EGGMOBILE_LATK10, S_EGGMOBILE_RATK1, S_EGGMOBILE_RATK2, S_EGGMOBILE_RATK3, @@ -1203,7 +1474,6 @@ typedef enum state S_EGGMOBILE_RATK7, S_EGGMOBILE_RATK8, S_EGGMOBILE_RATK9, - S_EGGMOBILE_RATK10, S_EGGMOBILE_PANIC1, S_EGGMOBILE_PANIC2, S_EGGMOBILE_PANIC3, @@ -1214,27 +1484,25 @@ typedef enum state S_EGGMOBILE_PANIC8, S_EGGMOBILE_PANIC9, S_EGGMOBILE_PANIC10, + S_EGGMOBILE_PANIC11, + S_EGGMOBILE_PANIC12, + S_EGGMOBILE_PANIC13, + S_EGGMOBILE_PANIC14, + S_EGGMOBILE_PANIC15, S_EGGMOBILE_PAIN, S_EGGMOBILE_PAIN2, S_EGGMOBILE_DIE1, S_EGGMOBILE_DIE2, S_EGGMOBILE_DIE3, S_EGGMOBILE_DIE4, - S_EGGMOBILE_DIE5, - S_EGGMOBILE_DIE6, - S_EGGMOBILE_DIE7, - S_EGGMOBILE_DIE8, - S_EGGMOBILE_DIE9, - S_EGGMOBILE_DIE10, - S_EGGMOBILE_DIE11, - S_EGGMOBILE_DIE12, - S_EGGMOBILE_DIE13, - S_EGGMOBILE_DIE14, S_EGGMOBILE_FLEE1, S_EGGMOBILE_FLEE2, S_EGGMOBILE_BALL, S_EGGMOBILE_TARGET, + S_BOSSEGLZ1, + S_BOSSEGLZ2, + // Boss 2 S_EGGMOBILE2_STND, S_EGGMOBILE2_POGO1, @@ -1250,16 +1518,6 @@ typedef enum state S_EGGMOBILE2_DIE2, S_EGGMOBILE2_DIE3, S_EGGMOBILE2_DIE4, - S_EGGMOBILE2_DIE5, - S_EGGMOBILE2_DIE6, - S_EGGMOBILE2_DIE7, - S_EGGMOBILE2_DIE8, - S_EGGMOBILE2_DIE9, - S_EGGMOBILE2_DIE10, - S_EGGMOBILE2_DIE11, - S_EGGMOBILE2_DIE12, - S_EGGMOBILE2_DIE13, - S_EGGMOBILE2_DIE14, S_EGGMOBILE2_FLEE1, S_EGGMOBILE2_FLEE2, @@ -1271,9 +1529,11 @@ typedef enum state S_GOOP1, S_GOOP2, S_GOOP3, + S_GOOPTRAIL, // Boss 3 S_EGGMOBILE3_STND, + S_EGGMOBILE3_SHOCK, S_EGGMOBILE3_ATK1, S_EGGMOBILE3_ATK2, S_EGGMOBILE3_ATK3A, @@ -1282,54 +1542,16 @@ typedef enum state S_EGGMOBILE3_ATK3D, S_EGGMOBILE3_ATK4, S_EGGMOBILE3_ATK5, - S_EGGMOBILE3_LAUGH1, - S_EGGMOBILE3_LAUGH2, - S_EGGMOBILE3_LAUGH3, - S_EGGMOBILE3_LAUGH4, - S_EGGMOBILE3_LAUGH5, - S_EGGMOBILE3_LAUGH6, - S_EGGMOBILE3_LAUGH7, - S_EGGMOBILE3_LAUGH8, - S_EGGMOBILE3_LAUGH9, - S_EGGMOBILE3_LAUGH10, - S_EGGMOBILE3_LAUGH11, - S_EGGMOBILE3_LAUGH12, - S_EGGMOBILE3_LAUGH13, - S_EGGMOBILE3_LAUGH14, - S_EGGMOBILE3_LAUGH15, - S_EGGMOBILE3_LAUGH16, - S_EGGMOBILE3_LAUGH17, - S_EGGMOBILE3_LAUGH18, - S_EGGMOBILE3_LAUGH19, - S_EGGMOBILE3_LAUGH20, + S_EGGMOBILE3_ROFL, S_EGGMOBILE3_PAIN, S_EGGMOBILE3_PAIN2, S_EGGMOBILE3_DIE1, S_EGGMOBILE3_DIE2, S_EGGMOBILE3_DIE3, S_EGGMOBILE3_DIE4, - S_EGGMOBILE3_DIE5, - S_EGGMOBILE3_DIE6, - S_EGGMOBILE3_DIE7, - S_EGGMOBILE3_DIE8, - S_EGGMOBILE3_DIE9, - S_EGGMOBILE3_DIE10, - S_EGGMOBILE3_DIE11, - S_EGGMOBILE3_DIE12, - S_EGGMOBILE3_DIE13, - S_EGGMOBILE3_DIE14, S_EGGMOBILE3_FLEE1, S_EGGMOBILE3_FLEE2, - // Boss 3 Propeller - S_PROPELLER1, - S_PROPELLER2, - S_PROPELLER3, - S_PROPELLER4, - S_PROPELLER5, - S_PROPELLER6, - S_PROPELLER7, - // Boss 3 Pinch S_FAKEMOBILE_INIT, S_FAKEMOBILE, @@ -1339,8 +1561,15 @@ typedef enum state S_FAKEMOBILE_ATK3B, S_FAKEMOBILE_ATK3C, S_FAKEMOBILE_ATK3D, - S_FAKEMOBILE_ATK4, - S_FAKEMOBILE_ATK5, + S_FAKEMOBILE_DIE1, + S_FAKEMOBILE_DIE2, + + S_BOSSSEBH1, + S_BOSSSEBH2, + + // Boss 3 Shockwave + S_SHOCKWAVE1, + S_SHOCKWAVE2, // Boss 4 S_EGGMOBILE4_STND, @@ -1358,36 +1587,164 @@ typedef enum state S_EGGMOBILE4_RATK6, S_EGGMOBILE4_RAISE1, S_EGGMOBILE4_RAISE2, - S_EGGMOBILE4_RAISE3, - S_EGGMOBILE4_RAISE4, - S_EGGMOBILE4_RAISE5, - S_EGGMOBILE4_RAISE6, - S_EGGMOBILE4_RAISE7, - S_EGGMOBILE4_RAISE8, - S_EGGMOBILE4_RAISE9, - S_EGGMOBILE4_RAISE10, - S_EGGMOBILE4_PAIN, + S_EGGMOBILE4_PAIN1, + S_EGGMOBILE4_PAIN2, S_EGGMOBILE4_DIE1, S_EGGMOBILE4_DIE2, S_EGGMOBILE4_DIE3, S_EGGMOBILE4_DIE4, - S_EGGMOBILE4_DIE5, - S_EGGMOBILE4_DIE6, - S_EGGMOBILE4_DIE7, - S_EGGMOBILE4_DIE8, - S_EGGMOBILE4_DIE9, - S_EGGMOBILE4_DIE10, - S_EGGMOBILE4_DIE11, - S_EGGMOBILE4_DIE12, - S_EGGMOBILE4_DIE13, - S_EGGMOBILE4_DIE14, S_EGGMOBILE4_FLEE1, S_EGGMOBILE4_FLEE2, S_EGGMOBILE4_MACE, + S_EGGMOBILE4_MACE_DIE1, + S_EGGMOBILE4_MACE_DIE2, + S_EGGMOBILE4_MACE_DIE3, // Boss 4 jet flame - S_JETFLAME1, - S_JETFLAME2, + S_JETFLAME, + + // Boss 4 Spectator Eggrobo + S_EGGROBO1_STND, + S_EGGROBO1_BSLAP1, + S_EGGROBO1_BSLAP2, + S_EGGROBO1_PISSED, + + // Boss 4 Spectator Eggrobo jet flame + S_EGGROBOJET, + + // Boss 5 + S_FANG_SETUP, + S_FANG_INTRO0, + S_FANG_INTRO1, + S_FANG_INTRO2, + S_FANG_INTRO3, + S_FANG_INTRO4, + S_FANG_INTRO5, + S_FANG_INTRO6, + S_FANG_INTRO7, + S_FANG_INTRO8, + S_FANG_INTRO9, + S_FANG_INTRO10, + S_FANG_INTRO11, + S_FANG_INTRO12, + S_FANG_CLONE1, + S_FANG_CLONE2, + S_FANG_CLONE3, + S_FANG_CLONE4, + S_FANG_IDLE0, + S_FANG_IDLE1, + S_FANG_IDLE2, + S_FANG_IDLE3, + S_FANG_IDLE4, + S_FANG_IDLE5, + S_FANG_IDLE6, + S_FANG_IDLE7, + S_FANG_IDLE8, + S_FANG_PAIN1, + S_FANG_PAIN2, + S_FANG_PATHINGSTART1, + S_FANG_PATHINGSTART2, + S_FANG_PATHING, + S_FANG_BOUNCE1, + S_FANG_BOUNCE2, + S_FANG_BOUNCE3, + S_FANG_BOUNCE4, + S_FANG_FALL1, + S_FANG_FALL2, + S_FANG_CHECKPATH1, + S_FANG_CHECKPATH2, + S_FANG_PATHINGCONT1, + S_FANG_PATHINGCONT2, + S_FANG_PATHINGCONT3, + S_FANG_SKID1, + S_FANG_SKID2, + S_FANG_SKID3, + S_FANG_CHOOSEATTACK, + S_FANG_FIRESTART1, + S_FANG_FIRESTART2, + S_FANG_FIRE1, + S_FANG_FIRE2, + S_FANG_FIRE3, + S_FANG_FIRE4, + S_FANG_FIREREPEAT, + S_FANG_LOBSHOT0, + S_FANG_LOBSHOT1, + S_FANG_LOBSHOT2, + S_FANG_WAIT1, + S_FANG_WAIT2, + S_FANG_WALLHIT, + S_FANG_PINCHPATHINGSTART1, + S_FANG_PINCHPATHINGSTART2, + S_FANG_PINCHPATHING, + S_FANG_PINCHBOUNCE0, + S_FANG_PINCHBOUNCE1, + S_FANG_PINCHBOUNCE2, + S_FANG_PINCHBOUNCE3, + S_FANG_PINCHBOUNCE4, + S_FANG_PINCHFALL0, + S_FANG_PINCHFALL1, + S_FANG_PINCHFALL2, + S_FANG_PINCHSKID1, + S_FANG_PINCHSKID2, + S_FANG_PINCHLOBSHOT0, + S_FANG_PINCHLOBSHOT1, + S_FANG_PINCHLOBSHOT2, + S_FANG_PINCHLOBSHOT3, + S_FANG_PINCHLOBSHOT4, + S_FANG_DIE1, + S_FANG_DIE2, + S_FANG_DIE3, + S_FANG_DIE4, + S_FANG_DIE5, + S_FANG_DIE6, + S_FANG_DIE7, + S_FANG_DIE8, + S_FANG_FLEEPATHING1, + S_FANG_FLEEPATHING2, + S_FANG_FLEEBOUNCE1, + S_FANG_FLEEBOUNCE2, + S_FANG_KO, + + S_BROKENROBOTRANDOM, + S_BROKENROBOTA, + S_BROKENROBOTB, + S_BROKENROBOTC, + S_BROKENROBOTD, + S_BROKENROBOTE, + S_BROKENROBOTF, + + S_ALART1, + S_ALART2, + + S_VWREF, + S_VWREB, + + S_PROJECTORLIGHT1, + S_PROJECTORLIGHT2, + S_PROJECTORLIGHT3, + S_PROJECTORLIGHT4, + S_PROJECTORLIGHT5, + + S_FBOMB1, + S_FBOMB2, + S_FBOMB_EXPL1, + S_FBOMB_EXPL2, + S_FBOMB_EXPL3, + S_FBOMB_EXPL4, + S_FBOMB_EXPL5, + S_FBOMB_EXPL6, + S_TNTDUST_1, + S_TNTDUST_2, + S_TNTDUST_3, + S_TNTDUST_4, + S_TNTDUST_5, + S_TNTDUST_6, + S_TNTDUST_7, + S_TNTDUST_8, + S_FSGNA, + S_FSGNB, + S_FSGNC, + S_FSGND, // Black Eggman (Boss 7) S_BLACKEGG_STND, @@ -1620,54 +1977,27 @@ typedef enum state S_CYBRAKDEMONVILEEXPLOSION3, // Metal Sonic (Race) - // S_PLAY_STND - S_METALSONIC_STAND, - // S_PLAY_TAP1 - S_METALSONIC_WAIT1, - S_METALSONIC_WAIT2, - // S_PLAY_RUN1 - S_METALSONIC_WALK1, - S_METALSONIC_WALK2, - S_METALSONIC_WALK3, - S_METALSONIC_WALK4, - S_METALSONIC_WALK5, - S_METALSONIC_WALK6, - S_METALSONIC_WALK7, - S_METALSONIC_WALK8, - // S_PLAY_SPD1 - S_METALSONIC_RUN1, - S_METALSONIC_RUN2, - S_METALSONIC_RUN3, - S_METALSONIC_RUN4, + S_METALSONIC_RACE, // Metal Sonic (Battle) S_METALSONIC_FLOAT, S_METALSONIC_VECTOR, S_METALSONIC_STUN, - S_METALSONIC_BLOCK, S_METALSONIC_RAISE, S_METALSONIC_GATHER, S_METALSONIC_DASH, S_METALSONIC_BOUNCE, + S_METALSONIC_BADBOUNCE, S_METALSONIC_SHOOT, S_METALSONIC_PAIN, - S_METALSONIC_DEATH, + S_METALSONIC_DEATH1, + S_METALSONIC_DEATH2, + S_METALSONIC_DEATH3, + S_METALSONIC_DEATH4, S_METALSONIC_FLEE1, S_METALSONIC_FLEE2, - S_METALSONIC_FLEE3, - S_METALSONIC_FLEE4, S_MSSHIELD_F1, S_MSSHIELD_F2, - S_MSSHIELD_F3, - S_MSSHIELD_F4, - S_MSSHIELD_F5, - S_MSSHIELD_F6, - S_MSSHIELD_F7, - S_MSSHIELD_F8, - S_MSSHIELD_F9, - S_MSSHIELD_F10, - S_MSSHIELD_F11, - S_MSSHIELD_F12, // Ring S_RING, @@ -1685,27 +2015,33 @@ typedef enum state S_FASTRING12, // Blue Sphere for special stages - S_BLUEBALL, - S_BLUEBALLSPARK, + S_BLUESPHERE, + S_BLUESPHEREBONUS, + S_BLUESPHERESPARK, + + // Bomb Sphere + S_BOMBSPHERE1, + S_BOMBSPHERE2, + S_BOMBSPHERE3, + S_BOMBSPHERE4, + + // NiGHTS Chip + S_NIGHTSCHIP, + S_NIGHTSCHIPBONUS, + + // NiGHTS Star + S_NIGHTSSTAR, + S_NIGHTSSTARXMAS, // Gravity Wells for special stages S_GRAVWELLGREEN, - S_GRAVWELLGREEN2, - S_GRAVWELLGREEN3, - S_GRAVWELLRED, - S_GRAVWELLRED2, - S_GRAVWELLRED3, // Individual Team Rings S_TEAMRING, - // Special Stage Token - S_EMMY, - // Special Stage Token S_TOKEN, - S_MOVINGTOKEN, // CTF Flags S_REDFLAG, @@ -1748,34 +2084,23 @@ typedef enum state S_CEMG6, S_CEMG7, - // Emeralds (for hunt) - S_EMER1, - - S_FAN, - S_FAN2, - S_FAN3, - S_FAN4, - S_FAN5, + // Emerald hunt shards + S_SHRD1, + S_SHRD2, + S_SHRD3, // Bubble Source S_BUBBLES1, S_BUBBLES2, + S_BUBBLES3, + S_BUBBLES4, // Level End Sign S_SIGN_POLE, S_SIGN_BACK, S_SIGN_SIDE, S_SIGN_FACE, - - // Steam Riser - S_STEAM1, - S_STEAM2, - S_STEAM3, - S_STEAM4, - S_STEAM5, - S_STEAM6, - S_STEAM7, - S_STEAM8, + S_SIGN_ERROR, // Spike Ball S_SPIKEBALL1, @@ -1787,7 +2112,7 @@ typedef enum state S_SPIKEBALL7, S_SPIKEBALL8, - // Fire Shield's Spawn + // Elemental Shield's Spawn S_SPINFIRE1, S_SPINFIRE2, S_SPINFIRE3, @@ -1805,194 +2130,181 @@ typedef enum state S_SPIKED1, S_SPIKED2, + // Wall spikes + S_WALLSPIKE1, + S_WALLSPIKE2, + S_WALLSPIKE3, + S_WALLSPIKE4, + S_WALLSPIKE5, + S_WALLSPIKE6, + S_WALLSPIKEBASE, + S_WALLSPIKED1, + S_WALLSPIKED2, + // Starpost S_STARPOST_IDLE, S_STARPOST_FLASH, + S_STARPOST_STARTSPIN, S_STARPOST_SPIN, + S_STARPOST_ENDSPIN, // Big floating mine - S_BIGMINE1, - S_BIGMINE2, - S_BIGMINE3, - S_BIGMINE4, - S_BIGMINE5, - S_BIGMINE6, - S_BIGMINE7, - S_BIGMINE8, + S_BIGMINE_IDLE, + S_BIGMINE_ALERT1, + S_BIGMINE_ALERT2, + S_BIGMINE_ALERT3, + S_BIGMINE_SET1, + S_BIGMINE_SET2, + S_BIGMINE_SET3, + S_BIGMINE_BLAST1, + S_BIGMINE_BLAST2, + S_BIGMINE_BLAST3, + S_BIGMINE_BLAST4, + S_BIGMINE_BLAST5, // Cannon Launcher S_CANNONLAUNCHER1, S_CANNONLAUNCHER2, S_CANNONLAUNCHER3, - // Super Ring Box - S_SUPERRINGBOX, - S_SUPERRINGBOX1, - S_SUPERRINGBOX2, - S_SUPERRINGBOX3, - S_SUPERRINGBOX4, - S_SUPERRINGBOX5, - S_SUPERRINGBOX6, + // Monitor Miscellany + S_BOXSPARKLE1, + S_BOXSPARKLE2, + S_BOXSPARKLE3, + S_BOXSPARKLE4, - // Red Team Ring Box - S_REDRINGBOX, - S_REDRINGBOX1, + S_BOX_FLICKER, + S_BOX_POP1, + S_BOX_POP2, - // Blue Team Ring Box - S_BLUERINGBOX, - S_BLUERINGBOX1, + S_GOLDBOX_FLICKER, + S_GOLDBOX_OFF1, + S_GOLDBOX_OFF2, + S_GOLDBOX_OFF3, + S_GOLDBOX_OFF4, + S_GOLDBOX_OFF5, + S_GOLDBOX_OFF6, + S_GOLDBOX_OFF7, - // Super Sneakers Box - S_SHTV, - S_SHTV1, - S_SHTV2, - S_SHTV3, - S_SHTV4, - S_SHTV5, - S_SHTV6, + // Monitor States (one per box) + S_MYSTERY_BOX, + S_RING_BOX, + S_PITY_BOX, + S_ATTRACT_BOX, + S_FORCE_BOX, + S_ARMAGEDDON_BOX, + S_WHIRLWIND_BOX, + S_ELEMENTAL_BOX, + S_SNEAKERS_BOX, + S_INVULN_BOX, + S_1UP_BOX, + S_EGGMAN_BOX, + S_MIXUP_BOX, + S_GRAVITY_BOX, + S_RECYCLER_BOX, + S_SCORE1K_BOX, + S_SCORE10K_BOX, + S_FLAMEAURA_BOX, + S_BUBBLEWRAP_BOX, + S_THUNDERCOIN_BOX, - // Invincibility Box - S_PINV, - S_PINV1, - S_PINV2, - S_PINV3, - S_PINV4, - S_PINV5, - S_PINV6, + // Gold Repeat Monitor States (one per box) + S_PITY_GOLDBOX, + S_ATTRACT_GOLDBOX, + S_FORCE_GOLDBOX, + S_ARMAGEDDON_GOLDBOX, + S_WHIRLWIND_GOLDBOX, + S_ELEMENTAL_GOLDBOX, + S_SNEAKERS_GOLDBOX, + S_INVULN_GOLDBOX, + S_EGGMAN_GOLDBOX, + S_GRAVITY_GOLDBOX, + S_FLAMEAURA_GOLDBOX, + S_BUBBLEWRAP_GOLDBOX, + S_THUNDERCOIN_GOLDBOX, - // 1up Box - S_PRUP, - S_PRUP1, - S_PRUP2, - S_PRUP3, - S_PRUP4, - S_PRUP5, - S_PRUP6, + // Team Ring Boxes (these are special) + S_RING_REDBOX1, + S_RING_REDBOX2, + S_REDBOX_POP1, + S_REDBOX_POP2, - // Ring Shield Box - S_YLTV, - S_YLTV1, - S_YLTV2, - S_YLTV3, - S_YLTV4, - S_YLTV5, - S_YLTV6, + S_RING_BLUEBOX1, + S_RING_BLUEBOX2, + S_BLUEBOX_POP1, + S_BLUEBOX_POP2, - // Force Shield Box - S_BLTV1, - S_BLTV2, - S_BLTV3, - S_BLTV4, - S_BLTV5, - S_BLTV6, - S_BLTV7, + // Box Icons -- 2 states each, animation and action + S_RING_ICON1, + S_RING_ICON2, - // Bomb Shield Box - S_BKTV1, - S_BKTV2, - S_BKTV3, - S_BKTV4, - S_BKTV5, - S_BKTV6, - S_BKTV7, + S_PITY_ICON1, + S_PITY_ICON2, - // Jump Shield Box - S_WHTV1, - S_WHTV2, - S_WHTV3, - S_WHTV4, - S_WHTV5, - S_WHTV6, - S_WHTV7, + S_ATTRACT_ICON1, + S_ATTRACT_ICON2, - // Water Shield Box - S_GRTV, - S_GRTV1, - S_GRTV2, - S_GRTV3, - S_GRTV4, - S_GRTV5, - S_GRTV6, + S_FORCE_ICON1, + S_FORCE_ICON2, - // Pity Shield Box - S_PITV1, - S_PITV2, - S_PITV3, - S_PITV4, - S_PITV5, - S_PITV6, - S_PITV7, + S_ARMAGEDDON_ICON1, + S_ARMAGEDDON_ICON2, - // Eggman Box - S_EGGTV1, - S_EGGTV2, - S_EGGTV3, - S_EGGTV4, - S_EGGTV5, - S_EGGTV6, - S_EGGTV7, + S_WHIRLWIND_ICON1, + S_WHIRLWIND_ICON2, - // Teleport Box - S_MIXUPBOX1, - S_MIXUPBOX2, - S_MIXUPBOX3, - S_MIXUPBOX4, - S_MIXUPBOX5, - S_MIXUPBOX6, - S_MIXUPBOX7, + S_ELEMENTAL_ICON1, + S_ELEMENTAL_ICON2, - // Recycler Box - S_RECYCLETV1, - S_RECYCLETV2, - S_RECYCLETV3, - S_RECYCLETV4, - S_RECYCLETV5, - S_RECYCLETV6, - S_RECYCLETV7, + S_SNEAKERS_ICON1, + S_SNEAKERS_ICON2, - // Question Box - S_RANDOMBOX1, - S_RANDOMBOX2, - S_RANDOMBOX3, + S_INVULN_ICON1, + S_INVULN_ICON2, - // Gravity Boots Box - S_GBTV1, - S_GBTV2, - S_GBTV3, - S_GBTV4, - S_GBTV5, - S_GBTV6, - S_GBTV7, + S_1UP_ICON1, + S_1UP_ICON2, - // Score boxes - S_SCORETVA1, - S_SCORETVA2, - S_SCORETVA3, - S_SCORETVA4, - S_SCORETVA5, - S_SCORETVA6, - S_SCORETVA7, - S_SCORETVB1, - S_SCORETVB2, - S_SCORETVB3, - S_SCORETVB4, - S_SCORETVB5, - S_SCORETVB6, - S_SCORETVB7, + S_EGGMAN_ICON1, + S_EGGMAN_ICON2, - // Monitor Explosion - S_MONITOREXPLOSION1, - S_MONITOREXPLOSION2, + S_MIXUP_ICON1, + S_MIXUP_ICON2, - S_REDMONITOREXPLOSION1, - S_REDMONITOREXPLOSION2, + S_GRAVITY_ICON1, + S_GRAVITY_ICON2, - S_BLUEMONITOREXPLOSION1, - S_BLUEMONITOREXPLOSION2, + S_RECYCLER_ICON1, + S_RECYCLER_ICON2, + + S_SCORE1K_ICON1, + S_SCORE1K_ICON2, + + S_SCORE10K_ICON1, + S_SCORE10K_ICON2, + + S_FLAMEAURA_ICON1, + S_FLAMEAURA_ICON2, + + S_BUBBLEWRAP_ICON1, + S_BUBBLEWRAP_ICON2, + + S_THUNDERCOIN_ICON1, + S_THUNDERCOIN_ICON2, + + // --- S_ROCKET, S_LASER, + S_LASER2, + S_LASERFLASH, + + S_LASERFLAME1, + S_LASERFLAME2, + S_LASERFLAME3, + S_LASERFLAME4, + S_LASERFLAME5, S_TORPEDO, @@ -2019,39 +2331,63 @@ typedef enum state // Arrow S_ARROW, - S_ARROWUP, - S_ARROWDOWN, + S_ARROWBONK, - // Trapgoyle Demon fire - S_DEMONFIRE1, - S_DEMONFIRE2, - S_DEMONFIRE3, - S_DEMONFIRE4, - S_DEMONFIRE5, - S_DEMONFIRE6, + // Glaregoyle Demon fire + S_DEMONFIRE, + // The letter + S_LETTER, + + // GFZ flowers S_GFZFLOWERA, - S_GFZFLOWERA2, - - S_GFZFLOWERB1, - S_GFZFLOWERB2, - - S_GFZFLOWERC1, + S_GFZFLOWERB, + S_GFZFLOWERC, + S_BLUEBERRYBUSH, S_BERRYBUSH, S_BUSH, - // THZ Plant - S_THZPLANT1, - S_THZPLANT2, - S_THZPLANT3, - S_THZPLANT4, + // Trees (both GFZ and misc) + S_GFZTREE, + S_GFZBERRYTREE, + S_GFZCHERRYTREE, + S_CHECKERTREE, + S_CHECKERSUNSETTREE, + S_FHZTREE, // Frozen Hillside + S_FHZPINKTREE, + S_POLYGONTREE, + S_BUSHTREE, + S_BUSHREDTREE, + S_SPRINGTREE, + + // THZ flowers + S_THZFLOWERA, // THZ1 Steam flower + S_THZFLOWERB, // THZ1 Spin flower (red) + S_THZFLOWERC, // THZ1 Spin flower (yellow) + + // THZ Steam Whistle tree/bush + S_THZTREE, + S_THZTREEBRANCH1, + S_THZTREEBRANCH2, + S_THZTREEBRANCH3, + S_THZTREEBRANCH4, + S_THZTREEBRANCH5, + S_THZTREEBRANCH6, + S_THZTREEBRANCH7, + S_THZTREEBRANCH8, + S_THZTREEBRANCH9, + S_THZTREEBRANCH10, + S_THZTREEBRANCH11, + S_THZTREEBRANCH12, + S_THZTREEBRANCH13, // THZ Alarm S_ALARM1, // Deep Sea Gargoyle S_GARGOYLE, + S_BIGGARGOYLE, // DSZ Seaweed S_SEAWEED1, @@ -2070,26 +2406,49 @@ typedef enum state S_DRIPC1, S_DRIPC2, - // Coral 1 + // Coral S_CORAL1, - - // Coral 2 S_CORAL2, - - // Coral 3 S_CORAL3, + S_CORAL4, + S_CORAL5, // Blue Crystal S_BLUECRYSTAL1, + // Kelp, + S_KELP, + + // Animated algae + S_ANIMALGAETOP1, + S_ANIMALGAETOP2, + S_ANIMALGAESEG, + + // DSZ Stalagmites + S_DSZSTALAGMITE, + S_DSZ2STALAGMITE, + + // DSZ Light beam + S_LIGHTBEAM1, + S_LIGHTBEAM2, + S_LIGHTBEAM3, + S_LIGHTBEAM4, + S_LIGHTBEAM5, + S_LIGHTBEAM6, + S_LIGHTBEAM7, + S_LIGHTBEAM8, + S_LIGHTBEAM9, + S_LIGHTBEAM10, + S_LIGHTBEAM11, + S_LIGHTBEAM12, + // CEZ Chain S_CEZCHAIN, // Flame - S_FLAME1, - S_FLAME2, - S_FLAME3, - S_FLAME4, + S_FLAME, + S_FLAMEPARTICLE, + S_FLAMEREST, // Eggman Statue S_EGGSTATUE1, @@ -2098,19 +2457,84 @@ typedef enum state S_SLING1, S_SLING2, - // CEZ Small Mace Chain + // CEZ maces and chains S_SMALLMACECHAIN, - - // CEZ Big Mace Chain S_BIGMACECHAIN, - - // CEZ Small Mace S_SMALLMACE, - - // CEZ Big Mace S_BIGMACE, + S_SMALLGRABCHAIN, + S_BIGGRABCHAIN, - S_CEZFLOWER1, + // Yellow spring on a ball + S_YELLOWSPRINGBALL, + S_YELLOWSPRINGBALL2, + S_YELLOWSPRINGBALL3, + S_YELLOWSPRINGBALL4, + S_YELLOWSPRINGBALL5, + + // Red spring on a ball + S_REDSPRINGBALL, + S_REDSPRINGBALL2, + S_REDSPRINGBALL3, + S_REDSPRINGBALL4, + S_REDSPRINGBALL5, + + // Small Firebar + S_SMALLFIREBAR1, + S_SMALLFIREBAR2, + S_SMALLFIREBAR3, + S_SMALLFIREBAR4, + S_SMALLFIREBAR5, + S_SMALLFIREBAR6, + S_SMALLFIREBAR7, + S_SMALLFIREBAR8, + S_SMALLFIREBAR9, + S_SMALLFIREBAR10, + S_SMALLFIREBAR11, + S_SMALLFIREBAR12, + S_SMALLFIREBAR13, + S_SMALLFIREBAR14, + S_SMALLFIREBAR15, + S_SMALLFIREBAR16, + + // Big Firebar + S_BIGFIREBAR1, + S_BIGFIREBAR2, + S_BIGFIREBAR3, + S_BIGFIREBAR4, + S_BIGFIREBAR5, + S_BIGFIREBAR6, + S_BIGFIREBAR7, + S_BIGFIREBAR8, + S_BIGFIREBAR9, + S_BIGFIREBAR10, + S_BIGFIREBAR11, + S_BIGFIREBAR12, + S_BIGFIREBAR13, + S_BIGFIREBAR14, + S_BIGFIREBAR15, + S_BIGFIREBAR16, + + S_CEZFLOWER, + S_CEZPOLE, + S_CEZBANNER1, + S_CEZBANNER2, + S_PINETREE, + S_CEZBUSH1, + S_CEZBUSH2, + S_CANDLE, + S_CANDLEPRICKET, + S_FLAMEHOLDER, + S_FIRETORCH, + S_WAVINGFLAG, + S_WAVINGFLAGSEG1, + S_WAVINGFLAGSEG2, + S_CRAWLASTATUE, + S_FACESTABBERSTATUE, + S_SUSPICIOUSFACESTABBERSTATUE_WAIT, + S_SUSPICIOUSFACESTABBERSTATUE_BURST1, + S_SUSPICIOUSFACESTABBERSTATUE_BURST2, + S_BRAMBLES, // Big Tumbleweed S_BIGTUMBLEWEED, @@ -2134,11 +2558,105 @@ typedef enum state S_LITTLETUMBLEWEED_ROLL7, S_LITTLETUMBLEWEED_ROLL8, - // Cacti Sprites + // Cacti S_CACTI1, S_CACTI2, S_CACTI3, S_CACTI4, + S_CACTI5, + S_CACTI6, + S_CACTI7, + S_CACTI8, + S_CACTI9, + S_CACTI10, + S_CACTI11, + S_CACTITINYSEG, + S_CACTISMALLSEG, + + // Warning signs + S_ARIDSIGN_CAUTION, + S_ARIDSIGN_CACTI, + S_ARIDSIGN_SHARPTURN, + + // Oil lamp + S_OILLAMP, + S_OILLAMPFLARE, + + // TNT barrel + S_TNTBARREL_STND1, + S_TNTBARREL_EXPL1, + S_TNTBARREL_EXPL2, + S_TNTBARREL_EXPL3, + S_TNTBARREL_EXPL4, + S_TNTBARREL_EXPL5, + S_TNTBARREL_EXPL6, + S_TNTBARREL_EXPL7, + S_TNTBARREL_FLYING, + + // TNT proximity shell + S_PROXIMITY_TNT, + S_PROXIMITY_TNT_TRIGGER1, + S_PROXIMITY_TNT_TRIGGER2, + S_PROXIMITY_TNT_TRIGGER3, + S_PROXIMITY_TNT_TRIGGER4, + S_PROXIMITY_TNT_TRIGGER5, + S_PROXIMITY_TNT_TRIGGER6, + S_PROXIMITY_TNT_TRIGGER7, + S_PROXIMITY_TNT_TRIGGER8, + S_PROXIMITY_TNT_TRIGGER9, + S_PROXIMITY_TNT_TRIGGER10, + S_PROXIMITY_TNT_TRIGGER11, + S_PROXIMITY_TNT_TRIGGER12, + S_PROXIMITY_TNT_TRIGGER13, + S_PROXIMITY_TNT_TRIGGER14, + S_PROXIMITY_TNT_TRIGGER15, + S_PROXIMITY_TNT_TRIGGER16, + S_PROXIMITY_TNT_TRIGGER17, + S_PROXIMITY_TNT_TRIGGER18, + S_PROXIMITY_TNT_TRIGGER19, + S_PROXIMITY_TNT_TRIGGER20, + S_PROXIMITY_TNT_TRIGGER21, + S_PROXIMITY_TNT_TRIGGER22, + S_PROXIMITY_TNT_TRIGGER23, + + // Dust devil + S_DUSTDEVIL, + S_DUSTLAYER1, + S_DUSTLAYER2, + S_DUSTLAYER3, + S_DUSTLAYER4, + S_DUSTLAYER5, + S_ARIDDUST1, + S_ARIDDUST2, + S_ARIDDUST3, + + // Minecart + S_MINECART_IDLE, + S_MINECART_DTH1, + S_MINECARTEND, + S_MINECARTSEG_FRONT, + S_MINECARTSEG_BACK, + S_MINECARTSEG_LEFT, + S_MINECARTSEG_RIGHT, + S_MINECARTSIDEMARK1, + S_MINECARTSIDEMARK2, + S_MINECARTSPARK, + + // Saloon door + S_SALOONDOOR, + S_SALOONDOORCENTER, + + // Train cameo + S_TRAINCAMEOSPAWNER_1, + S_TRAINCAMEOSPAWNER_2, + S_TRAINCAMEOSPAWNER_3, + S_TRAINCAMEOSPAWNER_4, + S_TRAINCAMEOSPAWNER_5, + S_TRAINPUFFMAKER, + + // Train + S_TRAINDUST, + S_TRAINSTEAM, // Flame jet S_FLAMEJETSTND, @@ -2147,64 +2665,75 @@ typedef enum state S_FLAMEJETFLAME1, S_FLAMEJETFLAME2, S_FLAMEJETFLAME3, + S_FLAMEJETFLAME4, + S_FLAMEJETFLAME5, + S_FLAMEJETFLAME6, + S_FLAMEJETFLAME7, + S_FLAMEJETFLAME8, + S_FLAMEJETFLAME9, // Spinning flame jets S_FJSPINAXISA1, // Counter-clockwise S_FJSPINAXISA2, - S_FJSPINAXISA3, - S_FJSPINAXISA4, - S_FJSPINAXISA5, - S_FJSPINAXISA6, - S_FJSPINAXISA7, - S_FJSPINAXISA8, - S_FJSPINAXISA9, - S_FJSPINHELPERA1, - S_FJSPINHELPERA2, - S_FJSPINHELPERA3, S_FJSPINAXISB1, // Clockwise S_FJSPINAXISB2, - S_FJSPINAXISB3, - S_FJSPINAXISB4, - S_FJSPINAXISB5, - S_FJSPINAXISB6, - S_FJSPINAXISB7, - S_FJSPINAXISB8, - S_FJSPINAXISB9, - S_FJSPINHELPERB1, - S_FJSPINHELPERB2, - S_FJSPINHELPERB3, // Blade's flame S_FLAMEJETFLAMEB1, S_FLAMEJETFLAMEB2, S_FLAMEJETFLAMEB3, - S_FLAMEJETFLAMEB4, - S_FLAMEJETFLAMEB5, - S_FLAMEJETFLAMEB6, - // Trapgoyles - S_TRAPGOYLE, - S_TRAPGOYLE_CHECK, - S_TRAPGOYLE_FIRE1, - S_TRAPGOYLE_FIRE2, - S_TRAPGOYLE_FIRE3, - S_TRAPGOYLEUP, - S_TRAPGOYLEUP_CHECK, - S_TRAPGOYLEUP_FIRE1, - S_TRAPGOYLEUP_FIRE2, - S_TRAPGOYLEUP_FIRE3, - S_TRAPGOYLEDOWN, - S_TRAPGOYLEDOWN_CHECK, - S_TRAPGOYLEDOWN_FIRE1, - S_TRAPGOYLEDOWN_FIRE2, - S_TRAPGOYLEDOWN_FIRE3, - S_TRAPGOYLELONG, - S_TRAPGOYLELONG_CHECK, - S_TRAPGOYLELONG_FIRE1, - S_TRAPGOYLELONG_FIRE2, - S_TRAPGOYLELONG_FIRE3, - S_TRAPGOYLELONG_FIRE4, - S_TRAPGOYLELONG_FIRE5, + // Lavafall + S_LAVAFALL_DORMANT, + S_LAVAFALL_TELL, + S_LAVAFALL_SHOOT, + S_LAVAFALL_LAVA1, + S_LAVAFALL_LAVA2, + S_LAVAFALL_LAVA3, + S_LAVAFALLROCK, + + // Rollout Rock + S_ROLLOUTSPAWN, + S_ROLLOUTROCK, + + // RVZ scenery + S_BIGFERNLEAF, + S_BIGFERN1, + S_BIGFERN2, + S_JUNGLEPALM, + S_TORCHFLOWER, + S_WALLVINE_LONG, + S_WALLVINE_SHORT, + + // Glaregoyles + S_GLAREGOYLE, + S_GLAREGOYLE_CHARGE, + S_GLAREGOYLE_BLINK, + S_GLAREGOYLE_HOLD, + S_GLAREGOYLE_FIRE, + S_GLAREGOYLE_LOOP, + S_GLAREGOYLE_COOLDOWN, + S_GLAREGOYLEUP, + S_GLAREGOYLEUP_CHARGE, + S_GLAREGOYLEUP_BLINK, + S_GLAREGOYLEUP_HOLD, + S_GLAREGOYLEUP_FIRE, + S_GLAREGOYLEUP_LOOP, + S_GLAREGOYLEUP_COOLDOWN, + S_GLAREGOYLEDOWN, + S_GLAREGOYLEDOWN_CHARGE, + S_GLAREGOYLEDOWN_BLINK, + S_GLAREGOYLEDOWN_HOLD, + S_GLAREGOYLEDOWN_FIRE, + S_GLAREGOYLEDOWN_LOOP, + S_GLAREGOYLEDOWN_COOLDOWN, + S_GLAREGOYLELONG, + S_GLAREGOYLELONG_CHARGE, + S_GLAREGOYLELONG_BLINK, + S_GLAREGOYLELONG_HOLD, + S_GLAREGOYLELONG_FIRE, + S_GLAREGOYLELONG_LOOP, + S_GLAREGOYLELONG_COOLDOWN, // ATZ's Red Crystal/Target S_TARGET_IDLE, @@ -2213,6 +2742,12 @@ typedef enum state S_TARGET_RESPAWN, S_TARGET_ALLDONE, + // ATZ's green flame + S_GREENFLAME, + + // ATZ Blue Gargoyle + S_BLUEGARGOYLE, + // Stalagmites S_STG0, S_STG1, @@ -2228,11 +2763,74 @@ typedef enum state // Xmas-specific stuff S_XMASPOLE, S_CANDYCANE, - S_SNOWMAN, - S_SNOWMANHAT, - S_LAMPPOST1, - S_LAMPPOST2, + S_SNOWMAN, // normal + S_SNOWMANHAT, // with hat + scarf + S_LAMPPOST1, // normal + S_LAMPPOST2, // with snow S_HANGSTAR, + S_MISTLETOE, + // Xmas GFZ bushes + S_XMASBLUEBERRYBUSH, + S_XMASBERRYBUSH, + S_XMASBUSH, + // FHZ + S_FHZICE1, + S_FHZICE2, + S_ROSY_IDLE1, + S_ROSY_IDLE2, + S_ROSY_IDLE3, + S_ROSY_IDLE4, + S_ROSY_JUMP, + S_ROSY_WALK, + S_ROSY_HUG, + S_ROSY_PAIN, + S_ROSY_STND, + S_ROSY_UNHAPPY, + + // Halloween Scenery + // Pumpkins + S_JACKO1, + S_JACKO1OVERLAY_1, + S_JACKO1OVERLAY_2, + S_JACKO1OVERLAY_3, + S_JACKO1OVERLAY_4, + S_JACKO2, + S_JACKO2OVERLAY_1, + S_JACKO2OVERLAY_2, + S_JACKO2OVERLAY_3, + S_JACKO2OVERLAY_4, + S_JACKO3, + S_JACKO3OVERLAY_1, + S_JACKO3OVERLAY_2, + S_JACKO3OVERLAY_3, + S_JACKO3OVERLAY_4, + // Dr Seuss Trees + S_HHZTREE_TOP, + S_HHZTREE_TRUNK, + S_HHZTREE_LEAF, + // Mushroom + S_HHZSHROOM_1, + S_HHZSHROOM_2, + S_HHZSHROOM_3, + S_HHZSHROOM_4, + S_HHZSHROOM_5, + S_HHZSHROOM_6, + S_HHZSHROOM_7, + S_HHZSHROOM_8, + S_HHZSHROOM_9, + S_HHZSHROOM_10, + S_HHZSHROOM_11, + S_HHZSHROOM_12, + S_HHZSHROOM_13, + S_HHZSHROOM_14, + S_HHZSHROOM_15, + S_HHZSHROOM_16, + // Misc + S_HHZGRASS, + S_HHZTENT1, + S_HHZTENT2, + S_HHZSTALAGMITE_TALL, + S_HHZSTALAGMITE_SHORT, // Botanic Serenity's loads of scenery states S_BSZTALLFLOWER_RED, @@ -2279,8 +2877,10 @@ typedef enum state S_BSZVINE_ORANGE, S_BSZSHRUB, S_BSZCLOVER, - S_BSZFISH, - S_BSZSUNFLOWER, + S_BIG_PALMTREE_TRUNK, + S_BIG_PALMTREE_TOP, + S_PALMTREE_TRUNK, + S_PALMTREE_TOP, S_DBALL1, S_DBALL2, @@ -2324,6 +2924,22 @@ typedef enum state S_ARMF14, S_ARMF15, S_ARMF16, + S_ARMF17, + S_ARMF18, + S_ARMF19, + S_ARMF20, + S_ARMF21, + S_ARMF22, + S_ARMF23, + S_ARMF24, + S_ARMF25, + S_ARMF26, + S_ARMF27, + S_ARMF28, + S_ARMF29, + S_ARMF30, + S_ARMF31, + S_ARMF32, S_ARMB1, S_ARMB2, @@ -2341,6 +2957,22 @@ typedef enum state S_ARMB14, S_ARMB15, S_ARMB16, + S_ARMB17, + S_ARMB18, + S_ARMB19, + S_ARMB20, + S_ARMB21, + S_ARMB22, + S_ARMB23, + S_ARMB24, + S_ARMB25, + S_ARMB26, + S_ARMB27, + S_ARMB28, + S_ARMB29, + S_ARMB30, + S_ARMB31, + S_ARMB32, S_WIND1, S_WIND2, @@ -2363,6 +2995,7 @@ typedef enum state S_MAGN10, S_MAGN11, S_MAGN12, + S_MAGN13, S_FORC1, S_FORC2, @@ -2386,6 +3019,8 @@ typedef enum state S_FORC19, S_FORC20, + S_FORC21, + S_ELEM1, S_ELEM2, S_ELEM3, @@ -2399,6 +3034,9 @@ typedef enum state S_ELEM11, S_ELEM12, + S_ELEM13, + S_ELEM14, + S_ELEMF1, S_ELEMF2, S_ELEMF3, @@ -2407,6 +3045,8 @@ typedef enum state S_ELEMF6, S_ELEMF7, S_ELEMF8, + S_ELEMF9, + S_ELEMF10, S_PITY1, S_PITY2, @@ -2418,6 +3058,86 @@ typedef enum state S_PITY8, S_PITY9, S_PITY10, + S_PITY11, + S_PITY12, + + S_FIRS1, + S_FIRS2, + S_FIRS3, + S_FIRS4, + S_FIRS5, + S_FIRS6, + S_FIRS7, + S_FIRS8, + S_FIRS9, + + S_FIRS10, + S_FIRS11, + + S_FIRSB1, + S_FIRSB2, + S_FIRSB3, + S_FIRSB4, + S_FIRSB5, + S_FIRSB6, + S_FIRSB7, + S_FIRSB8, + S_FIRSB9, + + S_FIRSB10, + + S_BUBS1, + S_BUBS2, + S_BUBS3, + S_BUBS4, + S_BUBS5, + S_BUBS6, + S_BUBS7, + S_BUBS8, + S_BUBS9, + + S_BUBS10, + S_BUBS11, + + S_BUBSB1, + S_BUBSB2, + S_BUBSB3, + S_BUBSB4, + + S_BUBSB5, + S_BUBSB6, + + S_ZAPS1, + S_ZAPS2, + S_ZAPS3, + S_ZAPS4, + S_ZAPS5, + S_ZAPS6, + S_ZAPS7, + S_ZAPS8, + S_ZAPS9, + S_ZAPS10, + S_ZAPS11, + S_ZAPS12, + S_ZAPS13, // blank frame + S_ZAPS14, + S_ZAPS15, + S_ZAPS16, + + S_ZAPSB1, // blank frame + S_ZAPSB2, + S_ZAPSB3, + S_ZAPSB4, + S_ZAPSB5, + S_ZAPSB6, + S_ZAPSB7, + S_ZAPSB8, + S_ZAPSB9, + S_ZAPSB10, + S_ZAPSB11, // blank frame + + //Thunder spark + S_THUNDERCOIN_SPARK, // Invincibility Sparkles S_IVSP, @@ -2429,43 +3149,212 @@ typedef enum state S_SSPK4, S_SSPK5, - // Freed Birdie - S_BIRD1, - S_BIRD2, - S_BIRD3, + // Flicky-sized bubble + S_FLICKY_BUBBLE, - // Freed Bunny - S_BUNNY1, - S_BUNNY2, - S_BUNNY3, - S_BUNNY4, - S_BUNNY5, - S_BUNNY6, - S_BUNNY7, - S_BUNNY8, - S_BUNNY9, - S_BUNNY10, + // Bluebird + S_FLICKY_01_OUT, + S_FLICKY_01_FLAP1, + S_FLICKY_01_FLAP2, + S_FLICKY_01_FLAP3, + S_FLICKY_01_STAND, + S_FLICKY_01_CENTER, - // Freed Mouse - S_MOUSE1, - S_MOUSE2, + // Rabbit + S_FLICKY_02_OUT, + S_FLICKY_02_AIM, + S_FLICKY_02_HOP, + S_FLICKY_02_UP, + S_FLICKY_02_DOWN, + S_FLICKY_02_STAND, + S_FLICKY_02_CENTER, - // Freed Chicken - S_CHICKEN1, - S_CHICKENHOP, - S_CHICKENFLY1, - S_CHICKENFLY2, + // Chicken + S_FLICKY_03_OUT, + S_FLICKY_03_AIM, + S_FLICKY_03_HOP, + S_FLICKY_03_UP, + S_FLICKY_03_FLAP1, + S_FLICKY_03_FLAP2, + S_FLICKY_03_STAND, + S_FLICKY_03_CENTER, - // Freed Cow - S_COW1, - S_COW2, - S_COW3, - S_COW4, + // Seal + S_FLICKY_04_OUT, + S_FLICKY_04_AIM, + S_FLICKY_04_HOP, + S_FLICKY_04_UP, + S_FLICKY_04_DOWN, + S_FLICKY_04_SWIM1, + S_FLICKY_04_SWIM2, + S_FLICKY_04_SWIM3, + S_FLICKY_04_SWIM4, + S_FLICKY_04_STAND, + S_FLICKY_04_CENTER, - // Red Birdie in Bubble - S_RBIRD1, - S_RBIRD2, - S_RBIRD3, + // Pig + S_FLICKY_05_OUT, + S_FLICKY_05_AIM, + S_FLICKY_05_HOP, + S_FLICKY_05_UP, + S_FLICKY_05_DOWN, + S_FLICKY_05_STAND, + S_FLICKY_05_CENTER, + + // Chipmunk + S_FLICKY_06_OUT, + S_FLICKY_06_AIM, + S_FLICKY_06_HOP, + S_FLICKY_06_UP, + S_FLICKY_06_DOWN, + S_FLICKY_06_STAND, + S_FLICKY_06_CENTER, + + // Penguin + S_FLICKY_07_OUT, + S_FLICKY_07_AIML, + S_FLICKY_07_HOPL, + S_FLICKY_07_UPL, + S_FLICKY_07_DOWNL, + S_FLICKY_07_AIMR, + S_FLICKY_07_HOPR, + S_FLICKY_07_UPR, + S_FLICKY_07_DOWNR, + S_FLICKY_07_SWIM1, + S_FLICKY_07_SWIM2, + S_FLICKY_07_SWIM3, + S_FLICKY_07_STAND, + S_FLICKY_07_CENTER, + + // Fish + S_FLICKY_08_OUT, + S_FLICKY_08_AIM, + S_FLICKY_08_HOP, + S_FLICKY_08_FLAP1, + S_FLICKY_08_FLAP2, + S_FLICKY_08_FLAP3, + S_FLICKY_08_FLAP4, + S_FLICKY_08_SWIM1, + S_FLICKY_08_SWIM2, + S_FLICKY_08_SWIM3, + S_FLICKY_08_SWIM4, + S_FLICKY_08_STAND, + S_FLICKY_08_CENTER, + + // Ram + S_FLICKY_09_OUT, + S_FLICKY_09_AIM, + S_FLICKY_09_HOP, + S_FLICKY_09_UP, + S_FLICKY_09_DOWN, + S_FLICKY_09_STAND, + S_FLICKY_09_CENTER, + + // Puffin + S_FLICKY_10_OUT, + S_FLICKY_10_FLAP1, + S_FLICKY_10_FLAP2, + S_FLICKY_10_STAND, + S_FLICKY_10_CENTER, + + // Cow + S_FLICKY_11_OUT, + S_FLICKY_11_AIM, + S_FLICKY_11_RUN1, + S_FLICKY_11_RUN2, + S_FLICKY_11_RUN3, + S_FLICKY_11_STAND, + S_FLICKY_11_CENTER, + + // Rat + S_FLICKY_12_OUT, + S_FLICKY_12_AIM, + S_FLICKY_12_RUN1, + S_FLICKY_12_RUN2, + S_FLICKY_12_RUN3, + S_FLICKY_12_STAND, + S_FLICKY_12_CENTER, + + // Bear + S_FLICKY_13_OUT, + S_FLICKY_13_AIM, + S_FLICKY_13_HOP, + S_FLICKY_13_UP, + S_FLICKY_13_DOWN, + S_FLICKY_13_STAND, + S_FLICKY_13_CENTER, + + // Dove + S_FLICKY_14_OUT, + S_FLICKY_14_FLAP1, + S_FLICKY_14_FLAP2, + S_FLICKY_14_FLAP3, + S_FLICKY_14_STAND, + S_FLICKY_14_CENTER, + + // Cat + S_FLICKY_15_OUT, + S_FLICKY_15_AIM, + S_FLICKY_15_HOP, + S_FLICKY_15_UP, + S_FLICKY_15_DOWN, + S_FLICKY_15_STAND, + S_FLICKY_15_CENTER, + + // Canary + S_FLICKY_16_OUT, + S_FLICKY_16_FLAP1, + S_FLICKY_16_FLAP2, + S_FLICKY_16_FLAP3, + S_FLICKY_16_STAND, + S_FLICKY_16_CENTER, + + // Spider + S_SECRETFLICKY_01_OUT, + S_SECRETFLICKY_01_AIM, + S_SECRETFLICKY_01_HOP, + S_SECRETFLICKY_01_UP, + S_SECRETFLICKY_01_DOWN, + S_SECRETFLICKY_01_STAND, + S_SECRETFLICKY_01_CENTER, + + // Bat + S_SECRETFLICKY_02_OUT, + S_SECRETFLICKY_02_FLAP1, + S_SECRETFLICKY_02_FLAP2, + S_SECRETFLICKY_02_FLAP3, + S_SECRETFLICKY_02_STAND, + S_SECRETFLICKY_02_CENTER, + + // Fan + S_FAN, + S_FAN2, + S_FAN3, + S_FAN4, + S_FAN5, + + // Steam Riser + S_STEAM1, + S_STEAM2, + S_STEAM3, + S_STEAM4, + S_STEAM5, + S_STEAM6, + S_STEAM7, + S_STEAM8, + + // Bumpers + S_BUMPER, + S_BUMPERHIT, + + // Balloons + S_BALLOON, + S_BALLOONPOP1, + S_BALLOONPOP2, + S_BALLOONPOP3, + S_BALLOONPOP4, + S_BALLOONPOP5, + S_BALLOONPOP6, // Yellow Spring S_YELLOWSPRING1, @@ -2539,6 +3428,17 @@ typedef enum state S_GHORIZ3, S_GHORIZ4, + // Booster + S_BOOSTERSOUND, + S_YELLOWBOOSTERROLLER, + S_YELLOWBOOSTERSEG_LEFT, + S_YELLOWBOOSTERSEG_RIGHT, + S_YELLOWBOOSTERSEG_FACE, + S_REDBOOSTERROLLER, + S_REDBOOSTERSEG_LEFT, + S_REDBOOSTERSEG_RIGHT, + S_REDBOOSTERSEG_FACE, + // Rain S_RAIN1, S_RAINRETURN, @@ -2564,6 +3464,9 @@ typedef enum state S_SPLISH8, S_SPLISH9, + // Lava Splish + S_LAVASPLISH, + // added water splash S_SPLASH1, S_SPLASH2, @@ -2578,14 +3481,29 @@ typedef enum state // Bubbles S_SMALLBUBBLE, - S_SMALLBUBBLE1, S_MEDIUMBUBBLE, - S_MEDIUMBUBBLE1, - S_LARGEBUBBLE, + S_LARGEBUBBLE1, + S_LARGEBUBBLE2, S_EXTRALARGEBUBBLE, // breathable S_POP1, // Extra Large bubble goes POP! + S_WATERZAP, + + // Spindash dust + S_SPINDUST1, + S_SPINDUST2, + S_SPINDUST3, + S_SPINDUST4, + S_SPINDUST_BUBBLE1, + S_SPINDUST_BUBBLE2, + S_SPINDUST_BUBBLE3, + S_SPINDUST_BUBBLE4, + S_SPINDUST_FIRE1, + S_SPINDUST_FIRE2, + S_SPINDUST_FIRE3, + S_SPINDUST_FIRE4, + S_FOG1, S_FOG2, S_FOG3, @@ -2604,7 +3522,6 @@ typedef enum state S_SEED, S_PARTICLE, - S_PARTICLEGEN, // Score Logos S_SCRA, // 100 @@ -2618,6 +3535,7 @@ typedef enum state S_SCRI, // 4000 (mario) S_SCRJ, // 8000 (mario) S_SCRK, // 1UP (mario) + S_SCRL, // 10 // Drowning Timer Numbers S_ZERO1, @@ -2627,14 +3545,35 @@ typedef enum state S_FOUR1, S_FIVE1, + S_ZERO2, + S_ONE2, + S_TWO2, + S_THREE2, + S_FOUR2, + S_FIVE2, + + S_FLIGHTINDICATOR, + + S_LOCKON1, + S_LOCKON2, + S_LOCKON3, + S_LOCKON4, + S_LOCKONINF1, + S_LOCKONINF2, + S_LOCKONINF3, + S_LOCKONINF4, + // Tag Sign - S_TTAG1, + S_TTAG, // Got Flag Sign - S_GOTFLAG1, - S_GOTFLAG2, - S_GOTFLAG3, - S_GOTFLAG4, + S_GOTFLAG, + + // Finish flag + S_FINISHFLAG, + + S_CORK, + S_LHRT, // Red Ring S_RRNG1, @@ -2801,28 +3740,23 @@ typedef enum state S_FIREFLOWER2, S_FIREFLOWER3, S_FIREFLOWER4, - S_FIREBALL1, - S_FIREBALL2, - S_FIREBALL3, - S_FIREBALL4, - S_FIREBALLEXP1, - S_FIREBALLEXP2, - S_FIREBALLEXP3, + S_FIREBALL, + S_FIREBALLTRAIL1, + S_FIREBALLTRAIL2, S_SHELL, - S_SHELL1, - S_SHELL2, - S_SHELL3, - S_SHELL4, - S_PUMA1, - S_PUMA2, - S_PUMA3, - S_PUMA4, - S_PUMA5, - S_PUMA6, - S_HAMMER1, - S_HAMMER2, - S_HAMMER3, - S_HAMMER4, + S_PUMA_START1, + S_PUMA_START2, + S_PUMA_UP1, + S_PUMA_UP2, + S_PUMA_UP3, + S_PUMA_DOWN1, + S_PUMA_DOWN2, + S_PUMA_DOWN3, + S_PUMATRAIL1, + S_PUMATRAIL2, + S_PUMATRAIL3, + S_PUMATRAIL4, + S_HAMMER, S_KOOPA1, S_KOOPA2, S_KOOPAFLAME1, @@ -2836,8 +3770,8 @@ typedef enum state S_TOAD, // Nights-specific stuff - S_NIGHTSDRONE1, - S_NIGHTSDRONE2, + S_NIGHTSDRONE_MAN1, + S_NIGHTSDRONE_MAN2, S_NIGHTSDRONE_SPARKLING1, S_NIGHTSDRONE_SPARKLING2, S_NIGHTSDRONE_SPARKLING3, @@ -2854,97 +3788,10 @@ typedef enum state S_NIGHTSDRONE_SPARKLING14, S_NIGHTSDRONE_SPARKLING15, S_NIGHTSDRONE_SPARKLING16, - S_NIGHTSGOAL1, - S_NIGHTSGOAL2, - S_NIGHTSGOAL3, - S_NIGHTSGOAL4, - - S_NIGHTSFLY1A, - S_NIGHTSFLY1B, - S_NIGHTSDRILL1A, - S_NIGHTSDRILL1B, - S_NIGHTSDRILL1C, - S_NIGHTSDRILL1D, - S_NIGHTSFLY2A, - S_NIGHTSFLY2B, - S_NIGHTSDRILL2A, - S_NIGHTSDRILL2B, - S_NIGHTSDRILL2C, - S_NIGHTSDRILL2D, - S_NIGHTSFLY3A, - S_NIGHTSFLY3B, - S_NIGHTSDRILL3A, - S_NIGHTSDRILL3B, - S_NIGHTSDRILL3C, - S_NIGHTSDRILL3D, - S_NIGHTSFLY4A, - S_NIGHTSFLY4B, - S_NIGHTSDRILL4A, - S_NIGHTSDRILL4B, - S_NIGHTSDRILL4C, - S_NIGHTSDRILL4D, - S_NIGHTSFLY5A, - S_NIGHTSFLY5B, - S_NIGHTSDRILL5A, - S_NIGHTSDRILL5B, - S_NIGHTSDRILL5C, - S_NIGHTSDRILL5D, - S_NIGHTSFLY6A, - S_NIGHTSFLY6B, - S_NIGHTSDRILL6A, - S_NIGHTSDRILL6B, - S_NIGHTSDRILL6C, - S_NIGHTSDRILL6D, - S_NIGHTSFLY7A, - S_NIGHTSFLY7B, - S_NIGHTSDRILL7A, - S_NIGHTSDRILL7B, - S_NIGHTSDRILL7C, - S_NIGHTSDRILL7D, - S_NIGHTSFLY8A, - S_NIGHTSFLY8B, - S_NIGHTSDRILL8A, - S_NIGHTSDRILL8B, - S_NIGHTSDRILL8C, - S_NIGHTSDRILL8D, - S_NIGHTSFLY9A, - S_NIGHTSFLY9B, - S_NIGHTSDRILL9A, - S_NIGHTSDRILL9B, - S_NIGHTSDRILL9C, - S_NIGHTSDRILL9D, - S_NIGHTSHURT1, - S_NIGHTSHURT2, - S_NIGHTSHURT3, - S_NIGHTSHURT4, - S_NIGHTSHURT5, - S_NIGHTSHURT6, - S_NIGHTSHURT7, - S_NIGHTSHURT8, - S_NIGHTSHURT9, - S_NIGHTSHURT10, - S_NIGHTSHURT11, - S_NIGHTSHURT12, - S_NIGHTSHURT13, - S_NIGHTSHURT14, - S_NIGHTSHURT15, - S_NIGHTSHURT16, - S_NIGHTSHURT17, - S_NIGHTSHURT18, - S_NIGHTSHURT19, - S_NIGHTSHURT20, - S_NIGHTSHURT21, - S_NIGHTSHURT22, - S_NIGHTSHURT23, - S_NIGHTSHURT24, - S_NIGHTSHURT25, - S_NIGHTSHURT26, - S_NIGHTSHURT27, - S_NIGHTSHURT28, - S_NIGHTSHURT29, - S_NIGHTSHURT30, - S_NIGHTSHURT31, - S_NIGHTSHURT32, + S_NIGHTSDRONE_GOAL1, + S_NIGHTSDRONE_GOAL2, + S_NIGHTSDRONE_GOAL3, + S_NIGHTSDRONE_GOAL4, S_NIGHTSPARKLE1, S_NIGHTSPARKLE2, @@ -2995,20 +3842,12 @@ typedef enum state S_NIGHTSCORE90_2, S_NIGHTSCORE100_2, - S_NIGHTSWING, - S_NIGHTSWING_XMAS, - // NiGHTS Paraloop Powerups - S_NIGHTSPOWERUP1, - S_NIGHTSPOWERUP2, - S_NIGHTSPOWERUP3, - S_NIGHTSPOWERUP4, - S_NIGHTSPOWERUP5, - S_NIGHTSPOWERUP6, - S_NIGHTSPOWERUP7, - S_NIGHTSPOWERUP8, - S_NIGHTSPOWERUP9, - S_NIGHTSPOWERUP10, + S_NIGHTSSUPERLOOP, + S_NIGHTSDRILLREFILL, + S_NIGHTSHELPER, + S_NIGHTSEXTRATIME, + S_NIGHTSLINKFREEZE, S_EGGCAPSULE, // Orbiting Chaos Emeralds @@ -3020,14 +3859,11 @@ typedef enum state S_ORBITEM6, S_ORBITEM7, S_ORBITEM8, - S_ORBITEM9, - S_ORBITEM10, - S_ORBITEM11, - S_ORBITEM12, - S_ORBITEM13, - S_ORBITEM14, - S_ORBITEM15, - S_ORBITEM16, + S_ORBIDYA1, + S_ORBIDYA2, + S_ORBIDYA3, + S_ORBIDYA4, + S_ORBIDYA5, // "Flicky" helper S_NIGHTOPIANHELPER1, @@ -3038,43 +3874,163 @@ typedef enum state S_NIGHTOPIANHELPER6, S_NIGHTOPIANHELPER7, S_NIGHTOPIANHELPER8, + S_NIGHTOPIANHELPER9, + + // Nightopian + S_PIAN0, + S_PIAN1, + S_PIAN2, + S_PIAN3, + S_PIAN4, + S_PIAN5, + S_PIAN6, + S_PIANSING, + + // Shleep + S_SHLEEP1, + S_SHLEEP2, + S_SHLEEP3, + S_SHLEEP4, + S_SHLEEPBOUNCE1, + S_SHLEEPBOUNCE2, + S_SHLEEPBOUNCE3, + + // Secret badniks and hazards, shhhh + S_PENGUINATOR_LOOK, + S_PENGUINATOR_WADDLE1, + S_PENGUINATOR_WADDLE2, + S_PENGUINATOR_WADDLE3, + S_PENGUINATOR_WADDLE4, + S_PENGUINATOR_SLIDE1, + S_PENGUINATOR_SLIDE2, + S_PENGUINATOR_SLIDE3, + S_PENGUINATOR_SLIDE4, + S_PENGUINATOR_SLIDE5, + + S_POPHAT_LOOK, + S_POPHAT_SHOOT1, + S_POPHAT_SHOOT2, + S_POPHAT_SHOOT3, + S_POPHAT_SHOOT4, + S_POPSHOT, + S_POPSHOT_TRAIL, + + S_HIVEELEMENTAL_LOOK, + S_HIVEELEMENTAL_PREPARE1, + S_HIVEELEMENTAL_PREPARE2, + S_HIVEELEMENTAL_SHOOT1, + S_HIVEELEMENTAL_SHOOT2, + S_HIVEELEMENTAL_DORMANT, + S_HIVEELEMENTAL_PAIN, + S_HIVEELEMENTAL_DIE1, + S_HIVEELEMENTAL_DIE2, + S_HIVEELEMENTAL_DIE3, + + S_BUMBLEBORE_SPAWN, + S_BUMBLEBORE_LOOK1, + S_BUMBLEBORE_LOOK2, + S_BUMBLEBORE_FLY1, + S_BUMBLEBORE_FLY2, + S_BUMBLEBORE_RAISE, + S_BUMBLEBORE_FALL1, + S_BUMBLEBORE_FALL2, + S_BUMBLEBORE_STUCK1, + S_BUMBLEBORE_STUCK2, + S_BUMBLEBORE_DIE, + + S_BUGGLEIDLE, + S_BUGGLEFLY, + + S_SMASHSPIKE_FLOAT, + S_SMASHSPIKE_EASE1, + S_SMASHSPIKE_EASE2, + S_SMASHSPIKE_FALL, + S_SMASHSPIKE_STOMP1, + S_SMASHSPIKE_STOMP2, + S_SMASHSPIKE_RISE1, + S_SMASHSPIKE_RISE2, + + S_CACO_LOOK, + S_CACO_WAKE1, + S_CACO_WAKE2, + S_CACO_WAKE3, + S_CACO_WAKE4, + S_CACO_ROAR, + S_CACO_CHASE, + S_CACO_CHASE_REPEAT, + S_CACO_RANDOM, + S_CACO_PREPARE_SOUND, + S_CACO_PREPARE1, + S_CACO_PREPARE2, + S_CACO_PREPARE3, + S_CACO_SHOOT_SOUND, + S_CACO_SHOOT1, + S_CACO_SHOOT2, + S_CACO_CLOSE, + S_CACO_DIE_FLAGS, + S_CACO_DIE_GIB1, + S_CACO_DIE_GIB2, + S_CACO_DIE_SCREAM, + S_CACO_DIE_SHATTER, + S_CACO_DIE_FALL, + S_CACOSHARD_RANDOMIZE, + S_CACOSHARD1_1, + S_CACOSHARD1_2, + S_CACOSHARD2_1, + S_CACOSHARD2_2, + S_CACOFIRE1, + S_CACOFIRE2, + S_CACOFIRE3, + S_CACOFIRE_EXPLODE1, + S_CACOFIRE_EXPLODE2, + S_CACOFIRE_EXPLODE3, + S_CACOFIRE_EXPLODE4, + + S_SPINBOBERT_MOVE_FLIPUP, + S_SPINBOBERT_MOVE_UP, + S_SPINBOBERT_MOVE_FLIPDOWN, + S_SPINBOBERT_MOVE_DOWN, + S_SPINBOBERT_FIRE_MOVE, + S_SPINBOBERT_FIRE_GHOST, + S_SPINBOBERT_FIRE_TRAIL1, + S_SPINBOBERT_FIRE_TRAIL2, + S_SPINBOBERT_FIRE_TRAIL3, + + S_HANGSTER_LOOK, + S_HANGSTER_SWOOP1, + S_HANGSTER_SWOOP2, + S_HANGSTER_ARC1, + S_HANGSTER_ARC2, + S_HANGSTER_ARC3, + S_HANGSTER_FLY1, + S_HANGSTER_FLY2, + S_HANGSTER_FLY3, + S_HANGSTER_FLY4, + S_HANGSTER_FLYREPEAT, + S_HANGSTER_ARCUP1, + S_HANGSTER_ARCUP2, + S_HANGSTER_ARCUP3, + S_HANGSTER_RETURN1, + S_HANGSTER_RETURN2, + S_HANGSTER_RETURN3, S_CRUMBLE1, S_CRUMBLE2, - S_SUPERTRANS1, - S_SUPERTRANS2, - S_SUPERTRANS3, - S_SUPERTRANS4, - S_SUPERTRANS5, - S_SUPERTRANS6, - S_SUPERTRANS7, - S_SUPERTRANS8, - S_SUPERTRANS9, - // Spark S_SPRK1, S_SPRK2, S_SPRK3, - S_SPRK4, - S_SPRK5, - S_SPRK6, - S_SPRK7, - S_SPRK8, - S_SPRK9, - S_SPRK10, - S_SPRK11, - S_SPRK12, - S_SPRK13, - S_SPRK14, - S_SPRK15, - S_SPRK16, // Robot Explosion + S_XPLD_FLICKY, S_XPLD1, S_XPLD2, S_XPLD3, S_XPLD4, + S_XPLD5, + S_XPLD6, + S_XPLD_EGGTRAP, // Underwater Explosion S_WPLD1, @@ -3084,6 +4040,11 @@ typedef enum state S_WPLD5, S_WPLD6, + S_DUST1, + S_DUST2, + S_DUST3, + S_DUST4, + S_ROCKSPAWN, S_ROCKCRUMBLEA, @@ -3103,69 +4064,13 @@ typedef enum state S_ROCKCRUMBLEO, S_ROCKCRUMBLEP, - S_SRB1_CRAWLA1, - S_SRB1_CRAWLA2, - S_SRB1_CRAWLA3, - S_SRB1_CRAWLA4, - - S_SRB1_BAT1, - S_SRB1_BAT2, - S_SRB1_BAT3, - S_SRB1_BAT4, - - S_SRB1_ROBOFISH1, - S_SRB1_ROBOFISH2, - S_SRB1_ROBOFISH3, - - S_SRB1_VOLCANOGUY1, - S_SRB1_VOLCANOGUY2, - - S_SRB1_HOPPY1, - S_SRB1_HOPPY2, - - S_SRB1_HOPPYWATER1, - S_SRB1_HOPPYWATER2, - - S_SRB1_HOPPYSKYLAB1, - - S_SRB1_MMZFLYING1, - S_SRB1_MMZFLYING2, - S_SRB1_MMZFLYING3, - S_SRB1_MMZFLYING4, - S_SRB1_MMZFLYING5, - - S_SRB1_UFO1, - S_SRB1_UFO2, - - S_SRB1_GRAYBOT1, - S_SRB1_GRAYBOT2, - S_SRB1_GRAYBOT3, - S_SRB1_GRAYBOT4, - S_SRB1_GRAYBOT5, - S_SRB1_GRAYBOT6, - - S_SRB1_ROBOTOPOLIS1, - S_SRB1_ROBOTOPOLIS2, - - S_SRB1_RBZBUZZ1, - S_SRB1_RBZBUZZ2, - - S_SRB1_RBZSPIKES1, - S_SRB1_RBZSPIKES2, - - S_SRB1_METALSONIC1, - S_SRB1_METALSONIC2, - S_SRB1_METALSONIC3, - - S_SRB1_GOLDBOT1, - S_SRB1_GOLDBOT2, - S_SRB1_GOLDBOT3, - S_SRB1_GOLDBOT4, - S_SRB1_GOLDBOT5, - S_SRB1_GOLDBOT6, - - S_SRB1_GENREX1, - S_SRB1_GENREX2, + // Level debris + S_GFZDEBRIS, + S_BRICKDEBRIS, + S_WOODDEBRIS, + S_REDBRICKDEBRIS, // for CEZ3 + S_BLUEBRICKDEBRIS, // for CEZ3 + S_YELLOWBRICKDEBRIS, // for CEZ3 //{ Random Item Box S_RANDOMITEM1, @@ -3951,7 +4856,7 @@ typedef enum state S_SONICBUSH, // Marble Zone - S_FLAMEPARTICLE, + S_MARBLEFLAMEPARTICLE, S_MARBLETORCH, S_MARBLELIGHT, S_MARBLEBURNER, @@ -3964,12 +4869,6 @@ typedef enum state S_RUSTYLAMP_ORANGE, S_RUSTYCHAIN, - // D2 Balloon Panic - S_BALLOON, - S_BALLOONPOP1, - S_BALLOONPOP2, - S_BALLOONPOP3, - // Smokin' & Vapin' (Don't try this at home, kids!) S_PETSMOKE0, S_PETSMOKE1, @@ -4033,8 +4932,8 @@ typedef enum state S_CDTREEBSP, // Daytona Speedway - S_PINETREE, - S_PINETREE_SIDE, + S_DAYTONAPINETREE, + S_DAYTONAPINETREE_SIDE, // Egg Zeppelin S_EZZPROPELLER, @@ -4300,7 +5199,10 @@ typedef struct extern state_t states[NUMSTATES]; extern char sprnames[NUMSPRITES + 1][5]; +extern char spr2names[NUMPLAYERSPRITES][5]; +extern playersprite_t spr2defaults[NUMPLAYERSPRITES]; extern state_t *astate; +extern playersprite_t free_spr2; typedef enum mobj_type { @@ -4311,35 +5213,54 @@ typedef enum mobj_type MT_PLAYER, // Enemies - MT_BLUECRAWLA, - MT_REDCRAWLA, - MT_GFZFISH, // Greenflower Fish - MT_GOLDBUZZ, - MT_REDBUZZ, - MT_AQUABUZZ, // AquaBuzz for ATZ + MT_BLUECRAWLA, // Crawla (Blue) + MT_REDCRAWLA, // Crawla (Red) + MT_GFZFISH, // SDURF + MT_GOLDBUZZ, // Buzz (Gold) + MT_REDBUZZ, // Buzz (Red) MT_JETTBOMBER, // Jetty-Syn Bomber MT_JETTGUNNER, // Jetty-Syn Gunner MT_CRAWLACOMMANDER, // Crawla Commander MT_DETON, // Deton MT_SKIM, // Skim mine dropper - MT_TURRET, - MT_POPUPTURRET, - MT_SHARP, // Sharp + MT_TURRET, // Industrial Turret + MT_POPUPTURRET, // Pop-Up Turret + MT_SPINCUSHION, // Spincushion + MT_CRUSHSTACEAN, // Crushstacean + MT_CRUSHCLAW, // Big meaty claw + MT_CRUSHCHAIN, // Chain + MT_BANPYURA, // Banpyura + MT_BANPSPRING, // Banpyura spring MT_JETJAW, // Jet Jaw MT_SNAILER, // Snailer - MT_VULTURE, // Vulture + MT_VULTURE, // BASH MT_POINTY, // Pointy MT_POINTYBALL, // Pointy Ball MT_ROBOHOOD, // Robo-Hood - MT_FACESTABBER, // CastleBot FaceStabber + MT_FACESTABBER, // Castlebot Facestabber + MT_FACESTABBERSPEAR, // Castlebot Facestabber spear aura MT_EGGGUARD, // Egg Guard - MT_EGGSHIELD, // Egg Shield for Egg Guard + MT_EGGSHIELD, // Egg Guard's shield MT_GSNAPPER, // Green Snapper + MT_SNAPPER_LEG, // Green Snapper leg + MT_SNAPPER_HEAD, // Green Snapper head MT_MINUS, // Minus + MT_MINUSDIRT, // Minus dirt MT_SPRINGSHELL, // Spring Shell MT_YELLOWSHELL, // Spring Shell (yellow) MT_UNIDUS, // Unidus MT_UNIBALL, // Unidus Ball + MT_CANARIVORE, // Canarivore + MT_CANARIVORE_GAS, // Canarivore gas + MT_PYREFLY, // Pyre Fly + MT_PYREFLY_FIRE, // Pyre Fly fire + MT_PTERABYTESPAWNER, // Pterabyte spawner + MT_PTERABYTEWAYPOINT, // Pterabyte waypoint + MT_PTERABYTE, // Pterabyte + MT_DRAGONBOMBER, // Dragonbomber + MT_DRAGONWING, // Dragonbomber wing + MT_DRAGONTAIL, // Dragonbomber tail segment + MT_DRAGONMINE, // Dragonbomber mine // Generic Boss Items MT_BOSSEXPLODE, @@ -4348,6 +5269,7 @@ typedef enum mobj_type MT_EGGTRAP, MT_BOSS3WAYPOINT, MT_BOSS9GATHERPOINT, + MT_BOSSJUNK, // Boss 1 MT_EGGMOBILE, @@ -4359,20 +5281,32 @@ typedef enum mobj_type // Boss 2 MT_EGGMOBILE2, MT_EGGMOBILE2_POGO, - MT_BOSSTANK1, - MT_BOSSTANK2, - MT_BOSSSPIGOT, MT_GOOP, + MT_GOOPTRAIL, // Boss 3 MT_EGGMOBILE3, - MT_PROPELLER, MT_FAKEMOBILE, + MT_SHOCKWAVE, // Boss 4 MT_EGGMOBILE4, MT_EGGMOBILE4_MACE, MT_JETFLAME, + MT_EGGROBO1, + MT_EGGROBO1JET, + + // Boss 5 + MT_FANG, + MT_BROKENROBOT, + MT_VWREF, + MT_VWREB, + MT_PROJECTORLIGHT, + MT_FBOMB, + MT_TNTDUST, // also used by barrel + MT_FSGNA, + MT_FSGNB, + MT_FANGWAYPOINT, // Black Eggman (Boss 7) MT_BLACKEGGMAN, @@ -4402,11 +5336,12 @@ typedef enum mobj_type // Collectible Items MT_RING, MT_FLINGRING, // Lost ring - MT_BLUEBALL, // Blue sphere replacement for special stages + MT_BLUESPHERE, // Blue sphere for special stages + MT_FLINGBLUESPHERE, // Lost blue sphere + MT_BOMBSPHERE, MT_REDTEAMRING, //Rings collectable by red team. MT_BLUETEAMRING, //Rings collectable by blue team. - MT_EMMY, // emerald token for special stage - MT_TOKEN, // Special Stage Token (uncollectible part) + MT_TOKEN, // Special Stage token for special stage MT_REDFLAG, // Red CTF Flag MT_BLUEFLAG, // Blue CTF Flag MT_EMBLEM, @@ -4423,7 +5358,10 @@ typedef enum mobj_type // Springs and others MT_FAN, - MT_STEAM, // Steam riser + MT_STEAM, + MT_BUMPER, + MT_BALLOON, + MT_YELLOWSPRING, MT_REDSPRING, MT_BLUESPRING, @@ -4437,60 +5375,89 @@ typedef enum mobj_type MT_BLUEHORIZ, // Blue Horizontal Spring MT_GREYHORIZ, // Grey Horizontal Spring + MT_BOOSTERSEG, + MT_BOOSTERROLLER, + MT_YELLOWBOOSTER, + MT_REDBOOSTER, + // Interactive Objects MT_BUBBLES, // Bubble source MT_SIGN, // Level end sign MT_SIGN_PIECE, MT_SPIKEBALL, // Spike Ball - MT_SPECIALSPIKEBALL, MT_SPINFIRE, MT_SPIKE, + MT_WALLSPIKE, + MT_WALLSPIKEBASE, MT_STARPOST, MT_BIGMINE, - MT_BIGAIRMINE, + MT_BLASTEXECUTOR, MT_CANNONLAUNCHER, - // Monitor Boxes - MT_SUPERRINGBOX, - MT_REDRINGBOX, - MT_BLUERINGBOX, - MT_SNEAKERTV, - MT_INV, - MT_PRUP, // 1up Box - MT_YELLOWTV, - MT_BLUETV, - MT_BLACKTV, // Bomb shield TV - MT_WHITETV, // Jump shield TV - MT_GREENTV, - MT_PITYTV, // Pity Shield TV - MT_EGGMANBOX, - MT_MIXUPBOX, - MT_RECYCLETV, - MT_RECYCLEICO, - MT_QUESTIONBOX, - MT_GRAVITYBOX, - MT_SCORETVSMALL, - MT_SCORETVLARGE, - // Monitor miscellany - MT_MONITOREXPLOSION, - MT_REDMONITOREXPLOSION, - MT_BLUEMONITOREXPLOSION, - MT_RINGICO, - MT_SHOESICO, - MT_INVCICO, - MT_1UPICO, - MT_YSHIELDICO, - MT_BSHIELDICO, - MT_KSHIELDICO, - MT_WSHIELDICO, - MT_GSHIELDICO, - MT_PITYSHIELDICO, - MT_EGGMANICO, - MT_MIXUPICO, - MT_GRAVITYICO, - MT_SCOREICOSMALL, - MT_SCOREICOLARGE, + MT_BOXSPARKLE, + + // Monitor boxes -- regular + MT_RING_BOX, + MT_PITY_BOX, + MT_ATTRACT_BOX, + MT_FORCE_BOX, + MT_ARMAGEDDON_BOX, + MT_WHIRLWIND_BOX, + MT_ELEMENTAL_BOX, + MT_SNEAKERS_BOX, + MT_INVULN_BOX, + MT_1UP_BOX, + MT_EGGMAN_BOX, + MT_MIXUP_BOX, + MT_MYSTERY_BOX, + MT_GRAVITY_BOX, + MT_RECYCLER_BOX, + MT_SCORE1K_BOX, + MT_SCORE10K_BOX, + MT_FLAMEAURA_BOX, + MT_BUBBLEWRAP_BOX, + MT_THUNDERCOIN_BOX, + + // Monitor boxes -- repeating (big) boxes + MT_PITY_GOLDBOX, + MT_ATTRACT_GOLDBOX, + MT_FORCE_GOLDBOX, + MT_ARMAGEDDON_GOLDBOX, + MT_WHIRLWIND_GOLDBOX, + MT_ELEMENTAL_GOLDBOX, + MT_SNEAKERS_GOLDBOX, + MT_INVULN_GOLDBOX, + MT_EGGMAN_GOLDBOX, + MT_GRAVITY_GOLDBOX, + MT_FLAMEAURA_GOLDBOX, + MT_BUBBLEWRAP_GOLDBOX, + MT_THUNDERCOIN_GOLDBOX, + + // Monitor boxes -- special + MT_RING_REDBOX, + MT_RING_BLUEBOX, + + // Monitor icons + MT_RING_ICON, + MT_PITY_ICON, + MT_ATTRACT_ICON, + MT_FORCE_ICON, + MT_ARMAGEDDON_ICON, + MT_WHIRLWIND_ICON, + MT_ELEMENTAL_ICON, + MT_SNEAKERS_ICON, + MT_INVULN_ICON, + MT_1UP_ICON, + MT_EGGMAN_ICON, + MT_MIXUP_ICON, + MT_GRAVITY_ICON, + MT_RECYCLER_ICON, + MT_SCORE1K_ICON, + MT_SCORE10K_ICON, + MT_FLAMEAURA_ICON, + MT_BUBBLEWRAP_ICON, + MT_THUNDERCOIN_ICON, // Projectiles MT_ROCKET, @@ -4504,51 +5471,142 @@ typedef enum mobj_type MT_CANNONBALL, // Cannonball MT_CANNONBALLDECOR, // Decorative/still cannonball MT_ARROW, // Arrow - MT_DEMONFIRE, // Trapgoyle fire + MT_DEMONFIRE, // Glaregoyle fire + + // The letter + MT_LETTER, // Greenflower Scenery MT_GFZFLOWER1, MT_GFZFLOWER2, MT_GFZFLOWER3, + + MT_BLUEBERRYBUSH, MT_BERRYBUSH, MT_BUSH, + // Trees (both GFZ and misc) + MT_GFZTREE, + MT_GFZBERRYTREE, + MT_GFZCHERRYTREE, + MT_CHECKERTREE, + MT_CHECKERSUNSETTREE, + MT_FHZTREE, // Frozen Hillside + MT_FHZPINKTREE, + MT_POLYGONTREE, + MT_BUSHTREE, + MT_BUSHREDTREE, + MT_SPRINGTREE, + // Techno Hill Scenery - MT_THZPLANT, // THZ Plant + MT_THZFLOWER1, + MT_THZFLOWER2, + MT_THZFLOWER3, + MT_THZTREE, // Steam whistle tree/bush + MT_THZTREEBRANCH, // branch of said tree MT_ALARM, // Deep Sea Scenery MT_GARGOYLE, // Deep Sea Gargoyle + MT_BIGGARGOYLE, // Deep Sea Gargoyle (Big) MT_SEAWEED, // DSZ Seaweed MT_WATERDRIP, // Dripping Water source MT_WATERDROP, // Water drop from dripping water - MT_CORAL1, // Coral 1 - MT_CORAL2, // Coral 2 - MT_CORAL3, // Coral 3 + MT_CORAL1, // Coral + MT_CORAL2, + MT_CORAL3, + MT_CORAL4, + MT_CORAL5, MT_BLUECRYSTAL, // Blue Crystal + MT_KELP, // Kelp + MT_ANIMALGAETOP, // Animated algae top + MT_ANIMALGAESEG, // Animated algae segment + MT_DSZSTALAGMITE, // Deep Sea 1 Stalagmite + MT_DSZ2STALAGMITE, // Deep Sea 2 Stalagmite + MT_LIGHTBEAM, // DSZ Light beam // Castle Eggman Scenery MT_CHAIN, // CEZ Chain - MT_FLAME, // Flame + MT_FLAME, // Flame (has corona) + MT_FLAMEPARTICLE, MT_EGGSTATUE, // Eggman Statue MT_MACEPOINT, // Mace rotation point - MT_SWINGMACEPOINT, // Mace swinging point - MT_HANGMACEPOINT, // Hangable mace chain - MT_SPINMACEPOINT, // Spin/Controllable mace chain + MT_CHAINMACEPOINT, // Combination of chains and maces point + MT_SPRINGBALLPOINT, // Spring ball point + MT_CHAINPOINT, // Mace chain MT_HIDDEN_SLING, // Spin mace chain (activatable) + MT_FIREBARPOINT, // Firebar + MT_CUSTOMMACEPOINT, // Custom mace MT_SMALLMACECHAIN, // Small Mace Chain MT_BIGMACECHAIN, // Big Mace Chain MT_SMALLMACE, // Small Mace MT_BIGMACE, // Big Mace - MT_CEZFLOWER, + MT_SMALLGRABCHAIN, // Small Grab Chain + MT_BIGGRABCHAIN, // Big Grab Chain + MT_YELLOWSPRINGBALL, // Yellow spring on a ball + MT_REDSPRINGBALL, // Red spring on a ball + MT_SMALLFIREBAR, // Small Firebar + MT_BIGFIREBAR, // Big Firebar + MT_CEZFLOWER, // Flower + MT_CEZPOLE1, // Pole (with red banner) + MT_CEZPOLE2, // Pole (with blue banner) + MT_CEZBANNER1, // Banner (red) + MT_CEZBANNER2, // Banner (blue) + MT_PINETREE, // Pine Tree + MT_CEZBUSH1, // Bush 1 + MT_CEZBUSH2, // Bush 2 + MT_CANDLE, // Candle + MT_CANDLEPRICKET, // Candle pricket + MT_FLAMEHOLDER, // Flame holder + MT_FIRETORCH, // Fire torch + MT_WAVINGFLAG1, // Waving flag (red) + MT_WAVINGFLAG2, // Waving flag (blue) + MT_WAVINGFLAGSEG1, // Waving flag segment (red) + MT_WAVINGFLAGSEG2, // Waving flag segment (blue) + MT_CRAWLASTATUE, // Crawla statue + MT_FACESTABBERSTATUE, // Facestabber statue + MT_SUSPICIOUSFACESTABBERSTATUE, // :eggthinking: + MT_BRAMBLES, // Brambles // Arid Canyon Scenery MT_BIGTUMBLEWEED, MT_LITTLETUMBLEWEED, - MT_CACTI1, - MT_CACTI2, - MT_CACTI3, - MT_CACTI4, + MT_CACTI1, // Tiny Red Flower Cactus + MT_CACTI2, // Small Red Flower Cactus + MT_CACTI3, // Tiny Blue Flower Cactus + MT_CACTI4, // Small Blue Flower Cactus + MT_CACTI5, // Prickly Pear + MT_CACTI6, // Barrel Cactus + MT_CACTI7, // Tall Barrel Cactus + MT_CACTI8, // Armed Cactus + MT_CACTI9, // Ball Cactus + MT_CACTI10, // Tiny Cactus + MT_CACTI11, // Small Cactus + MT_CACTITINYSEG, // Tiny Cactus Segment + MT_CACTISMALLSEG, // Small Cactus Segment + MT_ARIDSIGN_CAUTION, // Caution Sign + MT_ARIDSIGN_CACTI, // Cacti Sign + MT_ARIDSIGN_SHARPTURN, // Sharp Turn Sign + MT_OILLAMP, + MT_TNTBARREL, + MT_PROXIMITYTNT, + MT_DUSTDEVIL, + MT_DUSTLAYER, + MT_ARIDDUST, + MT_MINECART, + MT_MINECARTSEG, + MT_MINECARTSPAWNER, + MT_MINECARTEND, + MT_MINECARTENDSOLID, + MT_MINECARTSIDEMARK, + MT_MINECARTSPARK, + MT_SALOONDOOR, + MT_SALOONDOORCENTER, + MT_TRAINCAMEOSPAWNER, + MT_TRAINSEG, + MT_TRAINDUSTSPAWNER, + MT_TRAINSTEAMSPAWNER, + MT_MINECARTSWITCHPOINT, // Red Volcano Scenery MT_FLAMEJET, @@ -4556,22 +5614,36 @@ typedef enum mobj_type MT_FLAMEJETFLAME, MT_FJSPINAXISA, // Counter-clockwise - MT_FJSPINHELPERA, MT_FJSPINAXISB, // Clockwise - MT_FJSPINHELPERB, MT_FLAMEJETFLAMEB, // Blade's flame + MT_LAVAFALL, + MT_LAVAFALL_LAVA, + MT_LAVAFALLROCK, + + MT_ROLLOUTSPAWN, + MT_ROLLOUTROCK, + + MT_BIGFERNLEAF, + MT_BIGFERN, + MT_JUNGLEPALM, + MT_TORCHFLOWER, + MT_WALLVINE_LONG, + MT_WALLVINE_SHORT, + // Dark City Scenery // Egg Rock Scenery // Azure Temple Scenery - MT_TRAPGOYLE, - MT_TRAPGOYLEUP, - MT_TRAPGOYLEDOWN, - MT_TRAPGOYLELONG, + MT_GLAREGOYLE, + MT_GLAREGOYLEUP, + MT_GLAREGOYLEDOWN, + MT_GLAREGOYLELONG, MT_TARGET, // AKA Red Crystal + MT_GREENFLAME, + MT_BLUEGARGOYLE, // Stalagmites MT_STALAGMITE0, @@ -4588,11 +5660,37 @@ typedef enum mobj_type // Christmas Scenery MT_XMASPOLE, MT_CANDYCANE, - MT_SNOWMAN, - MT_SNOWMANHAT, - MT_LAMPPOST1, - MT_LAMPPOST2, + MT_SNOWMAN, // normal + MT_SNOWMANHAT, // with hat + scarf + MT_LAMPPOST1, // normal + MT_LAMPPOST2, // with snow MT_HANGSTAR, + MT_MISTLETOE, + // Xmas GFZ bushes + MT_XMASBLUEBERRYBUSH, + MT_XMASBERRYBUSH, + MT_XMASBUSH, + // FHZ + MT_FHZICE1, + MT_FHZICE2, + MT_ROSY, + MT_CDLHRT, + + // Halloween Scenery + // Pumpkins + MT_JACKO1, + MT_JACKO2, + MT_JACKO3, + // Dr Seuss Trees + MT_HHZTREE_TOP, + MT_HHZTREE_PART, + // Misc + MT_HHZSHROOM, + MT_HHZGRASS, + MT_HHZTENTACLE1, + MT_HHZTENTACLE2, + MT_HHZSTALAGMITE_TALL, + MT_HHZSTALAGMITE_SHORT, // Botanic Serenity scenery MT_BSZTALLFLOWER_RED, @@ -4639,42 +5737,81 @@ typedef enum mobj_type MT_BSZVINE_ORANGE, MT_BSZSHRUB, MT_BSZCLOVER, - MT_BSZFISH, - MT_BSZSUNFLOWER, + MT_BIG_PALMTREE_TRUNK, + MT_BIG_PALMTREE_TOP, + MT_PALMTREE_TRUNK, + MT_PALMTREE_TOP, // Misc scenery MT_DBALL, MT_EGGSTATUE2, // Powerup Indicators - MT_GREENORB, // Elemental shield mobj - MT_YELLOWORB, // Attract shield mobj - MT_BLUEORB, // Force shield mobj - MT_BLACKORB, // Armageddon shield mobj - MT_WHITEORB, // Whirlwind shield mobj - MT_PITYORB, // Pity shield mobj - MT_IVSP, // invincibility sparkles + MT_ELEMENTAL_ORB, // Elemental shield mobj + MT_ATTRACT_ORB, // Attract shield mobj + MT_FORCE_ORB, // Force shield mobj + MT_ARMAGEDDON_ORB, // Armageddon shield mobj + MT_WHIRLWIND_ORB, // Whirlwind shield mobj + MT_PITY_ORB, // Pity shield mobj + MT_FLAMEAURA_ORB, // Flame shield mobj + MT_BUBBLEWRAP_ORB, // Bubble shield mobj + MT_THUNDERCOIN_ORB, // Thunder shield mobj + MT_THUNDERCOIN_SPARK, // Thunder spark + MT_IVSP, // Invincibility sparkles MT_SUPERSPARK, // Super Sonic Spark - // Freed Animals - MT_BIRD, // Birdie freed! - MT_BUNNY, // Bunny freed! - MT_MOUSE, // Mouse - MT_CHICKEN, // Chicken - MT_COW, // Cow - MT_REDBIRD, // Red Birdie in Bubble + // Flickies + MT_FLICKY_01, // Bluebird + MT_FLICKY_01_CENTER, + MT_FLICKY_02, // Rabbit + MT_FLICKY_02_CENTER, + MT_FLICKY_03, // Chicken + MT_FLICKY_03_CENTER, + MT_FLICKY_04, // Seal + MT_FLICKY_04_CENTER, + MT_FLICKY_05, // Pig + MT_FLICKY_05_CENTER, + MT_FLICKY_06, // Chipmunk + MT_FLICKY_06_CENTER, + MT_FLICKY_07, // Penguin + MT_FLICKY_07_CENTER, + MT_FLICKY_08, // Fish + MT_FLICKY_08_CENTER, + MT_FLICKY_09, // Ram + MT_FLICKY_09_CENTER, + MT_FLICKY_10, // Puffin + MT_FLICKY_10_CENTER, + MT_FLICKY_11, // Cow + MT_FLICKY_11_CENTER, + MT_FLICKY_12, // Rat + MT_FLICKY_12_CENTER, + MT_FLICKY_13, // Bear + MT_FLICKY_13_CENTER, + MT_FLICKY_14, // Dove + MT_FLICKY_14_CENTER, + MT_FLICKY_15, // Cat + MT_FLICKY_15_CENTER, + MT_FLICKY_16, // Canary + MT_FLICKY_16_CENTER, + MT_SECRETFLICKY_01, // Spider + MT_SECRETFLICKY_01_CENTER, + MT_SECRETFLICKY_02, // Bat + MT_SECRETFLICKY_02_CENTER, + MT_SEED, // Environmental Effects MT_RAIN, // Rain MT_SNOWFLAKE, // Snowflake MT_BLIZZARDSNOW, // Blizzard Snowball MT_SPLISH, // Water splish! + MT_LAVASPLISH, // Lava splish! MT_SMOKE, MT_SMALLBUBBLE, // small bubble MT_MEDIUMBUBBLE, // medium bubble MT_EXTRALARGEBUBBLE, // extra large bubble + MT_WATERZAP, + MT_SPINDUST, // Spindash dust MT_TFOG, - MT_SEED, MT_PARTICLE, MT_PARTICLEGEN, // For fans, etc. @@ -4682,9 +5819,11 @@ typedef enum mobj_type MT_SCORE, // score logo MT_DROWNNUMBERS, // Drowning Timer MT_GOTEMERALD, // Chaos Emerald (intangible) + MT_LOCKON, // Target + MT_LOCKONINF, // In-level Target MT_TAG, // Tag Sign MT_GOTFLAG, // Got Flag sign - MT_GOTFLAG2, // Got Flag sign + MT_FINISHFLAG, // Finish flag // Ambient Sounds MT_AWATERA, // Ambient Water Sound 1 @@ -4697,6 +5836,10 @@ typedef enum mobj_type MT_AWATERH, // Ambient Water Sound 8 MT_RANDOMAMBIENT, MT_RANDOMAMBIENT2, + MT_MACHINEAMBIENCE, + + MT_CORK, + MT_LHRT, // Ring Weapons MT_REDRING, @@ -4729,8 +5872,10 @@ typedef enum mobj_type MT_BLUEGOOMBA, MT_FIREFLOWER, MT_FIREBALL, + MT_FIREBALLTRAIL, MT_SHELL, MT_PUMA, + MT_PUMATRAIL, MT_HAMMER, MT_KOOPA, MT_KOOPAFLAME, @@ -4744,8 +5889,9 @@ typedef enum mobj_type MT_AXISTRANSFER, MT_AXISTRANSFERLINE, MT_NIGHTSDRONE, - MT_NIGHTSGOAL, - MT_NIGHTSCHAR, + MT_NIGHTSDRONE_MAN, + MT_NIGHTSDRONE_SPARKLING, + MT_NIGHTSDRONE_GOAL, MT_NIGHTSPARKLE, MT_NIGHTSLOOPHELPER, MT_NIGHTSBUMPER, // NiGHTS Bumper @@ -4753,14 +5899,40 @@ typedef enum mobj_type MT_HOOPCOLLIDE, // Collision detection for NiGHTS hoops MT_HOOPCENTER, // Center of a hoop MT_NIGHTSCORE, - MT_NIGHTSWING, + MT_NIGHTSCHIP, // NiGHTS Chip + MT_FLINGNIGHTSCHIP, // Lost NiGHTS Chip + MT_NIGHTSSTAR, // NiGHTS Star + MT_FLINGNIGHTSSTAR, // Lost NiGHTS Star MT_NIGHTSSUPERLOOP, MT_NIGHTSDRILLREFILL, MT_NIGHTSHELPER, MT_NIGHTSEXTRATIME, MT_NIGHTSLINKFREEZE, MT_EGGCAPSULE, + MT_IDEYAANCHOR, MT_NIGHTOPIANHELPER, // the actual helper object that orbits you + MT_PIAN, // decorative singing friend + MT_SHLEEP, // almost-decorative sleeping enemy + + // Secret badniks and hazards, shhhh + MT_PENGUINATOR, + MT_POPHAT, + MT_POPSHOT, + MT_POPSHOT_TRAIL, + + MT_HIVEELEMENTAL, + MT_BUMBLEBORE, + + MT_BUGGLE, + + MT_SMASHINGSPIKEBALL, + MT_CACOLANTERN, + MT_CACOSHARD, + MT_CACOFIRE, + MT_SPINBOBERT, + MT_SPINBOBERT_FIRE1, + MT_SPINBOBERT_FIRE2, + MT_HANGSTER, // Utility Objects MT_TELEPORTMAN, @@ -4771,9 +5943,9 @@ typedef enum mobj_type MT_PULL, MT_GHOST, MT_OVERLAY, + MT_ANGLEMAN, MT_POLYANCHOR, MT_POLYSPAWN, - MT_POLYSPAWNCRUSH, // Skybox objects MT_SKYBOX, @@ -4782,6 +5954,7 @@ typedef enum mobj_type MT_SPARK, //spark MT_EXPLODE, // Robot Explosion MT_UWEXPLODE, // Underwater Explosion + MT_DUST, MT_ROCKSPAWNER, MT_FALLINGROCK, MT_ROCKCRUMBLE1, @@ -4801,22 +5974,13 @@ typedef enum mobj_type MT_ROCKCRUMBLE15, MT_ROCKCRUMBLE16, - MT_SRB1_CRAWLA, - MT_SRB1_BAT, - MT_SRB1_ROBOFISH, - MT_SRB1_VOLCANOGUY, - MT_SRB1_HOPPY, - MT_SRB1_HOPPYWATER, - MT_SRB1_HOPPYSKYLAB, - MT_SRB1_MMZFLYING, - MT_SRB1_UFO, - MT_SRB1_GRAYBOT, - MT_SRB1_ROBOTOPOLIS, - MT_SRB1_RBZBUZZ, - MT_SRB1_RBZSPIKES, - MT_SRB1_METALSONIC, - MT_SRB1_GOLDBOT, - MT_SRB1_GENREX, + // Level debris + MT_GFZDEBRIS, + MT_BRICKDEBRIS, + MT_WOODDEBRIS, + MT_REDBRICKDEBRIS, // for CEZ3 + MT_BLUEBRICKDEBRIS, // for CEZ3 + MT_YELLOWBRICKDEBRIS, // for CEZ3 // SRB2kart MT_RANDOMITEM, @@ -4965,7 +6129,7 @@ typedef enum mobj_type MT_SONICBUSH, // Marble Zone - MT_FLAMEPARTICLE, + MT_MARBLEFLAMEPARTICLE, MT_MARBLETORCH, MT_MARBLELIGHT, MT_MARBLEBURNER, @@ -4977,9 +6141,6 @@ typedef enum mobj_type MT_RUSTYLAMP_ORANGE, MT_RUSTYCHAIN, - // D2 Balloon Panic - MT_BALLOON, - // Smokin' & Vapin' (Don't try this at home, kids!) MT_PETSMOKER, MT_PETSMOKE, @@ -5021,8 +6182,8 @@ typedef enum mobj_type MT_CDTREEB, // Daytona Speedway - MT_PINETREE, - MT_PINETREE_SIDE, + MT_DAYTONAPINETREE, + MT_DAYTONAPINETREE_SIDE, // Egg Zeppelin MT_EZZPROPELLER, diff --git a/src/k_battle.c b/src/k_battle.c index aac0dc8e5..98cc10a3b 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -42,8 +42,10 @@ INT32 K_StartingBumperCount(void) boolean K_IsPlayerWanted(player_t *player) { UINT8 i; - if (!(G_BattleGametype())) + + if (!(gametyperules & GTR_WANTED)) return false; + for (i = 0; i < 4; i++) { if (battlewanted[i] == -1) @@ -63,7 +65,7 @@ void K_CalculateBattleWanted(void) boolean setbumper = false; UINT8 i, j; - if (!G_BattleGametype()) + if (!(gametyperules & GTR_WANTED)) { for (i = 0; i < 4; i++) battlewanted[i] = -1; @@ -211,7 +213,7 @@ void K_CheckBumpers(void) INT32 winnerscoreadd = 0; boolean nobumpers = false; - if (!G_BattleGametype()) + if (!(gametyperules & GTR_BUMPERS)) return; if (gameaction == ga_completed) @@ -253,7 +255,7 @@ void K_CheckBumpers(void) { for (i = 0; i < MAXPLAYERS; i++) { - players[i].pflags |= PF_TIMEOVER; + players[i].pflags |= PF_GAMETYPEOVER; P_DoPlayerExit(&players[i]); } } @@ -284,7 +286,7 @@ static void K_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjty boolean flip[MAXPLANESPERSECTOR]; UINT8 numflats = 0; mobj_t *mo; - subsector_t *ss = R_IsPointInSubsector(x, y); + subsector_t *ss = R_PointInSubsectorOrNull(x, y); sector_t *sec; if (!ss) @@ -298,20 +300,12 @@ static void K_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjty if (sec->floorpic != skyflatnum) { -#ifdef ESLOPE - flatz[numflats] = (sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight); -#else - flatz[numflats] = (sec->floorheight); -#endif + flatz[numflats] = P_GetZAt(sec->f_slope, x, y, sec->floorheight); numflats++; } if (sec->ceilingpic != skyflatnum && ceiling) { -#ifdef ESLOPE - flatz[numflats] = (sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale); -#else - flatz[numflats] = (sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale); -#endif + flatz[numflats] = P_GetZAt(sec->c_slope, x, y, sec->ceilingheight) - FixedMul(mobjinfo[type].height, scale); flip[numflats] = true; numflats++; } @@ -325,20 +319,12 @@ static void K_SpawnOvertimeParticles(fixed_t x, fixed_t y, fixed_t scale, mobjty continue; if (*rover->toppic != skyflatnum) { -#ifdef ESLOPE - flatz[numflats] = (*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight); -#else - flatz[numflats] = (*rover->topheight); -#endif + flatz[numflats] = P_GetZAt(*rover->t_slope, x, y, *rover->topheight); numflats++; } if (*rover->bottompic != skyflatnum && ceiling) { -#ifdef ESLOPE - flatz[numflats] = (*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : *rover->bottomheight) - FixedMul(mobjinfo[type].height, scale); -#else - flatz[numflats] = (*rover->bottomheight) - FixedMul(mobjinfo[type].height, scale); -#endif + flatz[numflats] = P_GetZAt(*rover->b_slope, x, y, *rover->bottomheight); flip[numflats] = true; numflats++; } @@ -486,20 +472,23 @@ void K_RunBattleOvertime(void) } } -static void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj) +void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj) { - UINT8 sequence = mt->extrainfo-1; - fixed_t speed = (FRACUNIT >> 3) * mt->angle; + UINT8 sequence = mt->args[0] - 1; + fixed_t speed = (FRACUNIT >> 3) * mt->args[1]; boolean backandforth = (mt->options & MTF_AMBUSH); boolean reverse = (mt->options & MTF_OBJECTSPECIAL); mobj_t *mo2; mobj_t *target = NULL; thinker_t *th; + // TODO: This and the movement stuff in the thinker should both be using + // 2.2's new optimized functions for doing things with tube waypoints + // Find the inital target - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -559,7 +548,7 @@ void K_SpawnBattleCapsules(void) if (battlecapsules) return; - if (!G_BattleGametype()) + if (!(gametyperules & GTR_CAPSULES)) return; if (modeattacking != ATTACKING_CAPSULES) @@ -584,179 +573,7 @@ void K_SpawnBattleCapsules(void) for (i = 0; i < nummapthings; i++, mt++) { if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum) - { - sector_t *mtsector, *sec; - fixed_t x, y, z; - fixed_t floorheights[MAXFFLOORS+1]; - UINT8 numfloors = 1; - mobj_t *mobj = NULL; - boolean fly = true; - UINT8 j; - - mt->mobj = NULL; - - mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector; - mt->z = (INT16)( -#ifdef ESLOPE - mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : -#endif - mtsector->floorheight)>>FRACBITS; - - x = mt->x << FRACBITS; - y = mt->y << FRACBITS; - - sec = R_PointInSubsector(x, y)->sector; - - if (mt->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[MT_BATTLECAPSULE].height; - - floorheights[0] = z; - - if (mt->options >> ZSHIFT) - z -= ((mt->options >> ZSHIFT) << FRACBITS); - } - else - { - z = -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - - floorheights[0] = z; - - if (mt->options >> ZSHIFT) - z += ((mt->options >> ZSHIFT) << FRACBITS); - } - - - if (sec->ffloors) - { - ffloor_t *rover; - for (rover = sec->ffloors; rover; rover = rover->next) - { - if ((rover->flags & FF_EXISTS) && (rover->flags & FF_BLOCKOTHERS)) - { - if (mt->options & MTF_OBJECTFLIP) - { - floorheights[numfloors] = ( -#ifdef ESLOPE - *rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : -#endif - *rover->bottomheight) - mobjinfo[MT_BATTLECAPSULE].height; - } - else - { - floorheights[numfloors] = ( -#ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : -#endif - *rover->topheight); - } - - numfloors++; - } - } - } - - mt->z = (INT16)(z>>FRACBITS); - - mobj = P_SpawnMobj(x, y, z, MT_BATTLECAPSULE); - mobj->spawnpoint = mt; - - if (mt->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - for (j = 0; j < numfloors; j++) - { - if (z == floorheights[j]) - { - fly = false; - break; - } - } - - // Flying capsules - if (fly) - { - mobj->flags |= MF_NOGRAVITY; - mobj->extravalue1 = 1; // Set extravalue1 for later reference - } - - // Moving capsules! - if (mt->extrainfo && mt->angle) - K_SetupMovingCapsule(mt, mobj); - - // Moved from P_SpawnMobj due to order of operations mumbo jumbo - { - mobj_t *cur, *prev = mobj; - - // Init hnext list - // Spherical top - cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); - P_SetMobjState(cur, S_BATTLECAPSULE_TOP); - - P_SetTarget(&cur->target, mobj); - P_SetTarget(&cur->hprev, prev); - P_SetTarget(&prev->hnext, cur); - prev = cur; - - // Tippity-top decorational button - cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); - P_SetMobjState(cur, S_BATTLECAPSULE_BUTTON); - - P_SetTarget(&cur->target, mobj); - P_SetTarget(&cur->hprev, prev); - P_SetTarget(&prev->hnext, cur); - prev = cur; - - // Supports on the bottom - for (j = 0; j < 4; j++) - { - cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); - cur->extravalue1 = j; - - if (mobj->extravalue1) // Flying capsule, moving or not - P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORTFLY); - else if (mobj->target && !P_MobjWasRemoved(mobj->target)) // Grounded, moving capsule - P_SetMobjState(cur, S_KARMAWHEEL); - else - P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORT); // Grounded, stationary capsule - - P_SetTarget(&cur->target, mobj); - P_SetTarget(&cur->hprev, prev); - P_SetTarget(&prev->hnext, cur); - prev = cur; - } - - // Side paneling - for (j = 0; j < 8; j++) - { - cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); - cur->extravalue1 = j; - - if (j & 1) - P_SetMobjState(cur, S_BATTLECAPSULE_SIDE2); - else - P_SetMobjState(cur, S_BATTLECAPSULE_SIDE1); - - P_SetTarget(&cur->target, mobj); - P_SetTarget(&cur->hprev, prev); - P_SetTarget(&prev->hnext, cur); - prev = cur; - } - } - - mt->mobj = mobj; - } + P_SpawnMapThing(mt); } battlecapsules = true; diff --git a/src/k_battle.h b/src/k_battle.h index b69938d39..45a6b76c8 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -21,6 +21,7 @@ void K_CalculateBattleWanted(void); void K_SpawnBattlePoints(player_t *source, player_t *victim, UINT8 amount); void K_CheckBumpers(void); void K_RunBattleOvertime(void); +void K_SetupMovingCapsule(mapthing_t *mt, mobj_t *mobj); void K_SpawnBattleCapsules(void); #endif diff --git a/src/k_bot.c b/src/k_bot.c index 1cfef7fb9..a32a554e1 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -259,7 +259,7 @@ void K_UpdateMatchRaceBots(void) --------------------------------------------------*/ boolean K_PlayerUsesBotMovement(player_t *player) { - if (player->bot || player->exiting) + if (player->bot || player->exiting || player->quittime) return true; return false; @@ -682,9 +682,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // Remove any existing controls memset(cmd, 0, sizeof(ticcmd_t)); - cmd->angleturn = (player->mo->angle >> 16); - if (gamestate != GS_LEVEL) + if (gamestate != GS_LEVEL + || player->mo->scale <= 1) // funny post-finish death { // No need to do anything else. return; @@ -696,11 +696,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) return; } -#ifdef HAVE_BLUA // Complete override of all ticcmd functionality if (LUAh_BotTiccmd(player, cmd)) return; -#endif // Start boost handler if (leveltime <= starttime) @@ -865,8 +863,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) if (abs(player->botvars.turnconfirm) >= BOTTURNCONFIRM) { // You're commiting to your turn, you're allowed! - cmd->driftturn = turnamt; - cmd->angleturn += K_GetKartTurnValue(player, turnamt); + cmd->turning = turnamt; } } diff --git a/src/k_botitem.c b/src/k_botitem.c index 94f0b8e10..ce56b9b6e 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -917,7 +917,7 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd) saferingsval -= 5; } - if (player->kartstuff[k_rings] > saferingsval) + if (player->rings > saferingsval) { cmd->buttons |= BT_ATTACK; } @@ -944,7 +944,7 @@ static void K_BotItemRouletteMash(player_t *player, ticcmd_t *cmd) return; } - if (player->kartstuff[k_rings] < 0 && cv_superring.value) + if (player->rings < 0 && cv_superring.value) { // Uh oh, we need a loan! // It'll be better in the long run for bots to lose an item set for 10 free rings. diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 4dd55cc42..d5a08d2ad 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -183,12 +183,12 @@ static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, if (flip == true) { specialflag = SF_FLIPSPECIAL_CEILING; - highestfloor = (sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : sec->ceilingheight); + highestfloor = P_GetZAt(sec->c_slope, x, y, sec->ceilingheight); } else { specialflag = SF_FLIPSPECIAL_FLOOR; - highestfloor = (sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : sec->floorheight); + highestfloor = P_GetZAt(sec->f_slope, x, y, sec->floorheight); } if (sec->flags & specialflag) @@ -206,8 +206,8 @@ static boolean K_BotHatesThisSector(player_t *player, sector_t *sec, fixed_t x, continue; } - top = (*rover->t_slope ? P_GetZAt(*rover->t_slope, x, y) : *rover->topheight); - bottom = (*rover->b_slope ? P_GetZAt(*rover->b_slope, x, y) : *rover->bottomheight); + top = P_GetZAt(*rover->t_slope, x, y, *rover->topheight); + bottom = P_GetZAt(*rover->b_slope, x, y, *rover->bottomheight); if (!(rover->flags & FF_BLOCKPLAYER)) { @@ -694,8 +694,8 @@ static boolean K_BotSteerObjects(mobj_t *thing) ) // Ring Sting else PlayerAttackSteer( - thing->player->kartstuff[k_rings] <= 0, - globalsmuggle.botmo->player->kartstuff[k_rings] <= 0 + thing->player->rings <= 0, + globalsmuggle.botmo->player->rings <= 0 ) else { @@ -739,7 +739,7 @@ static boolean K_BotSteerObjects(mobj_t *thing) } break; default: - if (thing->flags & (MF_SOLID|MF_ENEMY|MF_BOSS|MF_PAIN|MF_MISSILE|MF_FIRE)) + if (thing->flags & (MF_SOLID|MF_ENEMY|MF_BOSS|MF_PAIN|MF_MISSILE)) { K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, false, 2 * (KART_FULLTURN + dodge)); } diff --git a/src/k_collide.c b/src/k_collide.c index 1921e3d38..56747a47f 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -45,7 +45,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) else { // Player Damage - P_DamageMobj(t2, t1, t1->target, 1); + P_DamageMobj(t2, t1, t1->target, 1, DMG_WIPEOUT); K_KartBouncing(t2, t1, false, false); S_StartSound(t2, sfx_s3k7b); } @@ -64,7 +64,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) t2->z += t2->height; S_StartSound(t2, t2->info->deathsound); - P_KillMobj(t2, t1, t1); + P_KillMobj(t2, t1, t1, DMG_NORMAL); P_SetObjectMomZ(t2, 8*FRACUNIT, false); P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT); @@ -77,7 +77,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) { damageitem = true; // Bomb death - P_KillMobj(t2, t1, t1); + P_KillMobj(t2, t1, t1, DMG_NORMAL); } else if (t2->flags & MF_SPRING && (t1->type != MT_ORBINAUT_SHIELD && t1->type != MT_JAWZ_SHIELD)) { @@ -87,7 +87,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) else if (t2->flags & MF_SHOOTABLE) { // Shootable damage - P_DamageMobj(t2, t2, t1->target, 1); + P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); damageitem = true; } @@ -100,7 +100,7 @@ boolean K_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2) t1->z += t1->height; S_StartSound(t1, t1->info->deathsound); - P_KillMobj(t1, t2, t2); + P_KillMobj(t1, t2, t2, DMG_NORMAL); P_SetObjectMomZ(t1, 8*FRACUNIT, false); P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y)+ANGLE_90, 16*FRACUNIT); @@ -148,7 +148,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) else { // Player Damage - K_SpinPlayer(t2->player, t1->target, 0, t1, (t1->type == MT_BANANA || t1->type == MT_BANANA_SHIELD)); + P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); } damageitem = true; @@ -165,7 +165,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) t2->z += t2->height; S_StartSound(t2, t2->info->deathsound); - P_KillMobj(t2, t1, t1); + P_KillMobj(t2, t1, t1, DMG_NORMAL); P_SetObjectMomZ(t2, 8*FRACUNIT, false); P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT); @@ -177,7 +177,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) else if (t2->flags & MF_SHOOTABLE) { // Shootable damage - P_DamageMobj(t2, t2, t1->target, 1); + P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); damageitem = true; } @@ -190,7 +190,7 @@ boolean K_BananaBallhogCollide(mobj_t *t1, mobj_t *t2) t1->z += t1->height; S_StartSound(t1, t1->info->deathsound); - P_KillMobj(t1, t2, t2); + P_KillMobj(t1, t2, t2, DMG_NORMAL); P_SetObjectMomZ(t1, 8*FRACUNIT, false); P_InstaThrust(t1, R_PointToAngle2(t2->x, t2->y, t1->x, t1->y)+ANGLE_90, 16*FRACUNIT); @@ -219,7 +219,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) if (!P_CanPickupItem(t2->player, 2)) return true; - if (G_BattleGametype() && t2->player->kartstuff[k_bumper] <= 0) + if ((gametyperules & GTR_BUMPERS) && t2->player->kartstuff[k_bumper] <= 0) { if (t2->player->kartstuff[k_comebackmode] || t2->player->kartstuff[k_comebacktimer]) return true; @@ -237,7 +237,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) { // Melt item S_StartSound(t2, sfx_s3k43); - P_KillMobj(t1, t2, t2); + P_KillMobj(t1, t2, t2, DMG_NORMAL); return true; } else @@ -253,7 +253,7 @@ boolean K_EggItemCollide(mobj_t *t1, mobj_t *t2) if (t1->target && t1->target->player) { - if (G_RaceGametype() || t1->target->player->kartstuff[k_bumper] > 0) + if ((gametyperules & GTR_CIRCUIT) || t1->target->player->kartstuff[k_bumper] > 0) t2->player->kartstuff[k_eggmanblame] = t1->target->player-players; else t2->player->kartstuff[k_eggmanblame] = t2->player-players; @@ -289,7 +289,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2) // Bomb punting if ((t1->state >= &states[S_SSMINE1] && t1->state <= &states[S_SSMINE4]) || (t1->state >= &states[S_SSMINE_DEPLOY8] && t1->state <= &states[S_SSMINE_DEPLOY13])) - P_KillMobj(t1, t2, t2); + P_KillMobj(t1, t2, t2, DMG_NORMAL); else K_PuntMine(t1, t2); } @@ -297,7 +297,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2) || t2->type == MT_ORBINAUT_SHIELD || t2->type == MT_JAWZ_SHIELD) { // Bomb death - P_KillMobj(t1, t2, t2); + P_KillMobj(t1, t2, t2, DMG_NORMAL); // Other Item Damage if (t2->eflags & MFE_VERTICALFLIP) @@ -306,7 +306,7 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2) t2->z += t2->height; S_StartSound(t2, t2->info->deathsound); - P_KillMobj(t2, t1, t1); + P_KillMobj(t2, t1, t1, DMG_NORMAL); P_SetObjectMomZ(t2, 8*FRACUNIT, false); P_InstaThrust(t2, R_PointToAngle2(t1->x, t1->y, t2->x, t2->y)+ANGLE_90, 16*FRACUNIT); @@ -314,9 +314,9 @@ boolean K_MineCollide(mobj_t *t1, mobj_t *t2) else if (t2->flags & MF_SHOOTABLE) { // Bomb death - P_KillMobj(t1, t2, t2); + P_KillMobj(t1, t2, t2, DMG_NORMAL); // Shootable damage - P_DamageMobj(t2, t2, t1->target, 1); + P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); } return true; @@ -329,15 +329,12 @@ boolean K_MineExplosionCollide(mobj_t *t1, mobj_t *t2) if (t2->player->powers[pw_flashing]) return true; - if (t1->state == &states[S_MINEEXPLOSION1]) - K_ExplodePlayer(t2->player, t1->target, t1); - else - K_SpinPlayer(t2->player, t1->target, 0, t1, false); + P_DamageMobj(t2, t1, t1->target, 1, (t1->state == &states[S_MINEEXPLOSION1]) ? DMG_EXPLODE : DMG_NORMAL); } else if (t2->flags & MF_SHOOTABLE) { // Shootable damage - P_DamageMobj(t2, t2, t1->target, 1); + P_DamageMobj(t2, t1, t1->target, 1, DMG_NORMAL); } return true; @@ -358,15 +355,15 @@ boolean K_KitchenSinkCollide(mobj_t *t1, mobj_t *t2) HU_SetCEchoDuration(5); HU_DoCEcho(va("%s\\was hit by a kitchen sink.\\\\\\\\", player_names[t2->player-players])); I_OutputMsg("%s was hit by a kitchen sink.\n", player_names[t2->player-players]); - P_DamageMobj(t2, t1, t1->target, 10000); - P_KillMobj(t1, t2, t2); + P_DamageMobj(t2, t1, t1->target, 1, DMG_INSTAKILL); + P_KillMobj(t1, t2, t2, DMG_NORMAL); } else if (t2->flags & MF_SHOOTABLE) { // Shootable damage - P_KillMobj(t2, t2, t1->target); + P_KillMobj(t2, t2, t1->target, DMG_NORMAL); // This item damage - P_KillMobj(t1, t2, t2); + P_KillMobj(t1, t2, t2, DMG_NORMAL); } return true; @@ -381,7 +378,7 @@ boolean K_FallingRockCollide(mobj_t *t1, mobj_t *t2) boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2) { - if (!(t2->flags & MF_SOLID || t2->flags & MF_SHOOTABLE || t2->flags & MF_BOUNCE)) + if (!(t2->flags & MF_SOLID || t2->flags & MF_SHOOTABLE)) return true; if (!(t2->health)) @@ -394,7 +391,7 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2) return false; if (t1->health) - P_KillMobj(t1, t2, t2); + P_KillMobj(t1, t2, t2, DMG_NORMAL); /*if (t2->player && (t2->player->kartstuff[k_invincibilitytimer] > 0 || t2->player->kartstuff[k_growshrinktimer] > 0)) diff --git a/src/k_color.c b/src/k_color.c index ee3fbc626..6cfe4d5a8 100644 --- a/src/k_color.c +++ b/src/k_color.c @@ -17,518 +17,6 @@ #include "r_things.h" #include "v_video.h" -// These should be within 14 characters to fit on the character select screen -const char *KartColor_Names[MAXSKINCOLORS] = -{ - "None", // SKINCOLOR_NONE - "White", // SKINCOLOR_WHITE - "Silver", // SKINCOLOR_SILVER - "Grey", // SKINCOLOR_GREY - "Nickel", // SKINCOLOR_NICKEL - "Black", // SKINCOLOR_BLACK - "Skunk", // SKINCOLOR_SKUNK - "Fairy", // SKINCOLOR_FAIRY - "Popcorn", // SKINCOLOR_POPCORN - "Artichoke", // SKINCOLOR_ARTICHOKE - "Pigeon", // SKINCOLOR_PIGEON - "Sepia", // SKINCOLOR_SEPIA - "Beige", // SKINCOLOR_BEIGE - "Caramel", // SKINCOLOR_CARAMEL - "Peach", // SKINCOLOR_PEACH - "Brown", // SKINCOLOR_BROWN - "Leather", // SKINCOLOR_LEATHER - "Pink", // SKINCOLOR_PINK - "Rose", // SKINCOLOR_ROSE - "Cinnamon", // SKINCOLOR_CINNAMON - "Ruby", // SKINCOLOR_RUBY - "Raspberry", // SKINCOLOR_RASPBERRY - "Red", // SKINCOLOR_RED - "Crimson", // SKINCOLOR_CRIMSON - "Maroon", // SKINCOLOR_MAROON - "Lemonade", // SKINCOLOR_LEMONADE - "Scarlet", // SKINCOLOR_SCARLET - "Ketchup", // SKINCOLOR_KETCHUP - "Dawn", // SKINCOLOR_DAWN - "Sunslam", // SKINCOLOR_SUNSLAM - "Creamsicle", // SKINCOLOR_CREAMSICLE - "Orange", // SKINCOLOR_ORANGE - "Rosewood", // SKINCOLOR_ROSEWOOD - "Tangerine", // SKINCOLOR_TANGERINE - "Tan", // SKINCOLOR_TAN - "Cream", // SKINCOLOR_CREAM - "Gold", // SKINCOLOR_GOLD - "Royal", // SKINCOLOR_ROYAL - "Bronze", // SKINCOLOR_BRONZE - "Copper", // SKINCOLOR_COPPER - "Yellow", // SKINCOLOR_YELLOW - "Mustard", // SKINCOLOR_MUSTARD - "Banana", // SKINCOLOR_BANANA - "Olive", // SKINCOLOR_OLIVE - "Crocodile", // SKINCOLOR_CROCODILE - "Peridot", // SKINCOLOR_PERIDOT - "Vomit", // SKINCOLOR_VOMIT - "Garden", // SKINCOLOR_GARDEN - "Lime", // SKINCOLOR_LIME - "Handheld", // SKINCOLOR_HANDHELD - "Tea", // SKINCOLOR_TEA - "Pistachio", // SKINCOLOR_PISTACHIO - "Moss", // SKINCOLOR_MOSS - "Camouflage", // SKINCOLOR_CAMOUFLAGE - "Mint", // SKINCOLOR_MINT - "Green", // SKINCOLOR_GREEN - "Pinetree", // SKINCOLOR_PINETREE - "Turtle", // SKINCOLOR_TURTLE - "Swamp", // SKINCOLOR_SWAMP - "Dream", // SKINCOLOR_DREAM - "Plague", // SKINCOLOR_PLAGUE - "Emerald", // SKINCOLOR_EMERALD - "Algae", // SKINCOLOR_ALGAE - "Aquamarine", // SKINCOLOR_AQUAMARINE - "Turquoise", // SKINCOLOR_TURQUOISE - "Teal", // SKINCOLOR_TEAL - "Robin", // SKINCOLOR_ROBIN - "Cyan", // SKINCOLOR_CYAN - "Jawz", // SKINCOLOR_JAWZ - "Cerulean", // SKINCOLOR_CERULEAN - "Navy", // SKINCOLOR_NAVY - "Platinum", // SKINCOLOR_PLATINUM - "Slate", // SKINCOLOR_SLATE - "Steel", // SKINCOLOR_STEEL - "Thunder", // SKINCOLOR_THUNDER - "Nova", // SKINCOLOR_NOVA - "Rust", // SKINCOLOR_RUST - "Wristwatch", // SKINCOLOR_WRISTWATCH - "Jet", // SKINCOLOR_JET - "Sapphire", // SKINCOLOR_SAPPHIRE - "Ultramarine", // SKINCOLOR_ULTRAMARINE - "Periwinkle", // SKINCOLOR_PERIWINKLE - "Blue", // SKINCOLOR_BLUE - "Midnight", // SKINCOLOR_MIDNIGHT - "Blueberry", // SKINCOLOR_BLUEBERRY - "Thistle", // SKINCOLOR_THISTLE - "Purple", // SKINCOLOR_PURPLE - "Pastel", // SKINCOLOR_PASTEL - "Moonset", // SKINCOLOR_MOONSET - "Dusk", // SKINCOLOR_DUSK - "Violet", // SKINCOLOR_VIOLET - "Magenta", // SKINCOLOR_MAGENTA - "Fuchsia", // SKINCOLOR_FUCHSIA - "Toxic", // SKINCOLOR_TOXIC - "Mauve", // SKINCOLOR_MAUVE - "Lavender", // SKINCOLOR_LAVENDER - "Byzantium", // SKINCOLOR_BYZANTIUM - "Pomegranate", // SKINCOLOR_POMEGRANATE - "Lilac", // SKINCOLOR_LILAC - "Blossom", // SKINCOLOR_BLOSSOM - "Taffy" // SKINCOLOR_TAFFY -}; - -// Color_Opposite replacement; frame setting has not been changed from 8 for most, should be done later -const UINT8 KartColor_Opposite[MAXSKINCOLORS*2] = -{ - SKINCOLOR_NONE,8, // SKINCOLOR_NONE - SKINCOLOR_BLACK,8, // SKINCOLOR_WHITE - SKINCOLOR_NICKEL,8, // SKINCOLOR_SILVER - SKINCOLOR_GREY,8, // SKINCOLOR_GREY - SKINCOLOR_SILVER,8, // SKINCOLOR_NICKEL - SKINCOLOR_WHITE,8, // SKINCOLOR_BLACK - SKINCOLOR_VOMIT,8, // SKINCOLOR_SKUNK - SKINCOLOR_ARTICHOKE,12, // SKINCOLOR_FAIRY - SKINCOLOR_PIGEON,12, // SKINCOLOR_POPCORN - SKINCOLOR_FAIRY,12, // SKINCOLOR_ARTICHOKE - SKINCOLOR_POPCORN,12, // SKINCOLOR_PIGEON - SKINCOLOR_LEATHER,6, // SKINCOLOR_SEPIA - SKINCOLOR_BROWN,2, // SKINCOLOR_BEIGE - SKINCOLOR_CERULEAN,8, // SKINCOLOR_CARAMEL - SKINCOLOR_CYAN,8, // SKINCOLOR_PEACH - SKINCOLOR_BEIGE,8, // SKINCOLOR_BROWN - SKINCOLOR_SEPIA,8, // SKINCOLOR_LEATHER - SKINCOLOR_PISTACHIO,8, // SKINCOLOR_PINK - SKINCOLOR_MOSS,8, // SKINCOLOR_ROSE - SKINCOLOR_WRISTWATCH,6, // SKINCOLOR_CINNAMON - SKINCOLOR_SAPPHIRE,8, // SKINCOLOR_RUBY - SKINCOLOR_MINT,8, // SKINCOLOR_RASPBERRY - SKINCOLOR_GREEN,6, // SKINCOLOR_RED - SKINCOLOR_PINETREE,6, // SKINCOLOR_CRIMSON - SKINCOLOR_TOXIC,8, // SKINCOLOR_MAROON - SKINCOLOR_THUNDER,8, // SKINCOLOR_LEMONADE - SKINCOLOR_ALGAE,10, // SKINCOLOR_SCARLET - SKINCOLOR_MUSTARD,10, // SKINCOLOR_KETCHUP - SKINCOLOR_DUSK,8, // SKINCOLOR_DAWN - SKINCOLOR_MOONSET,8, // SKINCOLOR_SUNSLAM - SKINCOLOR_PERIWINKLE,8, // SKINCOLOR_CREAMSICLE - SKINCOLOR_BLUE,8, // SKINCOLOR_ORANGE - SKINCOLOR_BLUEBERRY,6, // SKINCOLOR_ROSEWOOD - SKINCOLOR_LIME,8, // SKINCOLOR_TANGERINE - SKINCOLOR_RUST,8, // SKINCOLOR_TAN - SKINCOLOR_COPPER,10, // SKINCOLOR_CREAM - SKINCOLOR_SLATE,8, // SKINCOLOR_GOLD - SKINCOLOR_PLATINUM,6, // SKINCOLOR_ROYAL - SKINCOLOR_STEEL,8, // SKINCOLOR_BRONZE - SKINCOLOR_CREAM,6, // SKINCOLOR_COPPER - SKINCOLOR_AQUAMARINE,8, // SKINCOLOR_YELLOW - SKINCOLOR_KETCHUP,8, // SKINCOLOR_MUSTARD - SKINCOLOR_EMERALD,8, // SKINCOLOR_BANANA - SKINCOLOR_TEAL,8, // SKINCOLOR_OLIVE - SKINCOLOR_VIOLET,8, // SKINCOLOR_CROCODILE - SKINCOLOR_NAVY,6, // SKINCOLOR_PERIDOT - SKINCOLOR_SKUNK,8, // SKINCOLOR_VOMIT - SKINCOLOR_LAVENDER,6, // SKINCOLOR_GARDEN - SKINCOLOR_TANGERINE,8, // SKINCOLOR_LIME - SKINCOLOR_ULTRAMARINE,8, // SKINCOLOR_HANDHELD - SKINCOLOR_BLOSSOM,8, // SKINCOLOR_TEA - SKINCOLOR_PINK,6, // SKINCOLOR_PISTACHIO - SKINCOLOR_ROSE,8, // SKINCOLOR_MOSS - SKINCOLOR_CAMOUFLAGE,8, // SKINCOLOR_CAMOUFLAGE - SKINCOLOR_RASPBERRY,8, // SKINCOLOR_MINT - SKINCOLOR_RED,8, // SKINCOLOR_GREEN - SKINCOLOR_CRIMSON,8, // SKINCOLOR_PINETREE - SKINCOLOR_MAGENTA,8, // SKINCOLOR_TURTLE - SKINCOLOR_BYZANTIUM,8, // SKINCOLOR_SWAMP - SKINCOLOR_POMEGRANATE,8, // SKINCOLOR_DREAM - SKINCOLOR_NOVA,8, // SKINCOLOR_PLAGUE - SKINCOLOR_BANANA,8, // SKINCOLOR_EMERALD - SKINCOLOR_SCARLET,10, // SKINCOLOR_ALGAE - SKINCOLOR_YELLOW,8, // SKINCOLOR_AQUAMARINE - SKINCOLOR_MAUVE,10, // SKINCOLOR_TURQUOISE - SKINCOLOR_OLIVE,8, // SKINCOLOR_TEAL - SKINCOLOR_THISTLE,8, // SKINCOLOR_ROBIN - SKINCOLOR_PEACH,8, // SKINCOLOR_CYAN - SKINCOLOR_LILAC,10, // SKINCOLOR_JAWZ - SKINCOLOR_CARAMEL,8, // SKINCOLOR_CERULEAN - SKINCOLOR_PERIDOT,8, // SKINCOLOR_NAVY - SKINCOLOR_ROYAL,8, // SKINCOLOR_PLATINUM - SKINCOLOR_GOLD,10, // SKINCOLOR_SLATE - SKINCOLOR_BRONZE,10, // SKINCOLOR_STEEL - SKINCOLOR_LEMONADE,8, // SKINCOLOR_THUNDER - SKINCOLOR_PLAGUE,10, // SKINCOLOR_NOVA - SKINCOLOR_TAN,8, // SKINCOLOR_RUST - SKINCOLOR_CINNAMON,8, // SKINCOLOR_WRISTWATCH - SKINCOLOR_TAFFY,8, // SKINCOLOR_JET - SKINCOLOR_RUBY,6, // SKINCOLOR_SAPPHIRE - SKINCOLOR_HANDHELD,10, // SKINCOLOR_ULTRAMARINE - SKINCOLOR_CREAMSICLE,8, // SKINCOLOR_PERIWINKLE - SKINCOLOR_ORANGE,8, // SKINCOLOR_BLUE - SKINCOLOR_ROSEWOOD,8, // SKINCOLOR_MIDNIGHT - SKINCOLOR_PURPLE,8, // SKINCOLOR_BLUEBERRY - SKINCOLOR_ROBIN,8, // SKINCOLOR_THISTLE - SKINCOLOR_MIDNIGHT,10, // SKINCOLOR_PURPLE - SKINCOLOR_FUCHSIA,11, // SKINCOLOR_PASTEL - SKINCOLOR_SUNSLAM,10, // SKINCOLOR_MOONSET - SKINCOLOR_DAWN,6, // SKINCOLOR_DUSK - SKINCOLOR_CROCODILE,8, // SKINCOLOR_VIOLET - SKINCOLOR_TURTLE,8, // SKINCOLOR_MAGENTA - SKINCOLOR_PASTEL,11, // SKINCOLOR_FUCHSIA - SKINCOLOR_MAROON,8, // SKINCOLOR_TOXIC - SKINCOLOR_TURQUOISE,8, // SKINCOLOR_MAUVE - SKINCOLOR_GARDEN,6, // SKINCOLOR_LAVENDER - SKINCOLOR_SWAMP,8, // SKINCOLOR_BYZANTIUM - SKINCOLOR_DREAM,8, // SKINCOLOR_POMEGRANATE - SKINCOLOR_JAWZ,6, // SKINCOLOR_LILAC - SKINCOLOR_TEA,8, // SKINCOLOR_BLOSSOM - SKINCOLOR_JET,8 // SKINCOLOR_TAFFY -}; - -UINT8 colortranslations[MAXTRANSLATIONS][16] = { - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // SKINCOLOR_NONE - { 0, 0, 0, 0, 1, 2, 5, 8, 9, 11, 14, 17, 20, 22, 25, 28}, // SKINCOLOR_WHITE - { 0, 1, 2, 3, 5, 7, 9, 12, 13, 15, 18, 20, 23, 25, 27, 30}, // SKINCOLOR_SILVER - { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_GREY - { 3, 5, 8, 11, 15, 17, 19, 21, 23, 24, 25, 26, 27, 29, 30, 31}, // SKINCOLOR_NICKEL - { 4, 7, 11, 15, 20, 22, 24, 27, 28, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_BLACK - { 0, 1, 2, 3, 4, 10, 16, 21, 23, 24, 25, 26, 27, 28, 29, 31}, // SKINCOLOR_SKUNK - { 0, 0, 252, 252, 200, 201, 211, 14, 16, 18, 20, 22, 24, 26, 28, 31}, // SKINCOLOR_FAIRY - { 0, 80, 80, 81, 82, 218, 240, 11, 13, 16, 18, 21, 23, 26, 28, 31}, // SKINCOLOR_POPCORN - { 80, 88, 89, 98, 99, 91, 12, 14, 16, 18, 20, 22, 24, 26, 28, 31}, // SKINCOLOR_ARTICHOKE - { 0, 128, 129, 130, 146, 170, 14, 15, 17, 19, 21, 23, 25, 27, 29, 31}, // SKINCOLOR_PIGEON - { 0, 1, 3, 5, 7, 9, 241, 242, 243, 245, 247, 249, 236, 237, 238, 239}, // SKINCOLOR_SEPIA - { 0, 208, 216, 217, 240, 241, 242, 243, 245, 247, 249, 250, 251, 237, 238, 239}, // SKINCOLOR_BEIGE - {208, 48, 216, 217, 218, 220, 221, 223, 224, 226, 228, 230, 232, 234, 236, 239}, // SKINCOLOR_CARAMEL - { 0, 208, 48, 216, 218, 221, 212, 213, 214, 215, 206, 207, 197, 198, 199, 254}, // SKINCOLOR_PEACH - {216, 217, 219, 221, 224, 225, 227, 229, 230, 232, 234, 235, 237, 239, 29, 30}, // SKINCOLOR_BROWN - {218, 221, 224, 227, 229, 231, 233, 235, 237, 239, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_LEATHER - { 0, 208, 208, 209, 209, 210, 211, 211, 212, 213, 214, 215, 41, 43, 45, 46}, // SKINCOLOR_PINK - {209, 210, 211, 211, 212, 213, 214, 215, 41, 42, 43, 44, 45, 71, 46, 47}, // SKINCOLOR_ROSE - {216, 221, 224, 226, 228, 60, 61, 43, 44, 45, 71, 46, 47, 29, 30, 31}, // SKINCOLOR_CINNAMON - { 0, 208, 209, 210, 211, 213, 39, 40, 41, 43, 186, 186, 169, 169, 253, 254}, // SKINCOLOR_RUBY - { 0, 208, 209, 210, 32, 33, 34, 35, 37, 39, 41, 43, 44, 45, 46, 47}, // SKINCOLOR_RASPBERRY - {209, 210, 32, 34, 36, 38, 39, 40, 41, 42, 43, 44 , 45, 71, 46, 47}, // SKINCOLOR_RED - {210, 33, 35, 38, 40, 42, 43, 45, 71, 71, 46, 46, 47, 47, 30, 31}, // SKINCOLOR_CRIMSON - { 32, 33, 35, 37, 39, 41, 43, 237, 26, 26, 27, 27, 28, 29, 30, 31}, // SKINCOLOR_MAROON - { 0, 80, 81, 82, 83, 216, 210, 211, 212, 213, 214, 215, 43, 44, 71, 47}, // SKINCOLOR_LEMONADE - { 48, 49, 50, 51, 53, 34, 36, 38, 184, 185, 168, 168, 169, 169, 254, 31}, // SKINCOLOR_SCARLET - { 72, 73, 64, 51, 52, 54, 34, 36, 38, 40, 42, 43, 44, 71, 46, 47}, // SKINCOLOR_KETCHUP - { 0, 208, 216, 209, 210, 211, 212, 57, 58, 59, 60, 61, 63, 71, 47, 31}, // SKINCOLOR_DAWN - { 82, 72, 73, 64, 51, 53, 55, 213, 214, 195, 195, 173, 174, 175, 253, 254}, // SKINCOLOR_SUNSLAM - { 0, 0, 208, 208, 48, 49, 50, 52, 53, 54, 56, 57, 58, 60, 61, 63}, // SKINCOLOR_CREAMSICLE - {208, 48, 49, 50, 51, 52, 53, 54, 55, 57, 59, 60, 62, 44, 71, 47}, // SKINCOLOR_ORANGE - { 50, 52, 55, 56, 58, 59, 60, 61, 62, 63, 44, 45, 71, 46, 47, 30}, // SKINCOLOR_ROSEWOOD - { 80, 81, 82, 83, 64, 51, 52, 54, 55, 57, 58, 60, 61, 63, 71, 47}, // SKINCOLOR_TANGERINE - { 0, 80, 81, 82, 83, 84, 85, 86, 87, 245, 246, 248, 249, 251, 237, 239}, // SKINCOLOR_TAN - { 0, 80, 80, 81, 81, 49, 51, 222, 224, 227, 230, 233, 236, 239, 29, 31}, // SKINCOLOR_CREAM - { 0, 80, 81, 83, 64, 65, 66, 67, 68, 215, 69, 70, 44, 71, 46, 47}, // SKINCOLOR_GOLD - { 80, 81, 83, 64, 65, 223, 229, 196, 196, 197, 197, 198, 199, 29, 30, 31}, // SKINCOLOR_ROYAL - { 83, 64, 65, 66, 67, 215, 69, 70, 44, 44, 45, 71, 46, 47, 29, 31}, // SKINCOLOR_BRONZE - { 0, 82, 64, 65, 67, 68, 70, 237, 239, 28, 28, 29, 29, 30, 30, 31}, // SKINCOLOR_COPPER - { 0, 80, 81, 82, 83, 73, 84, 74, 64, 65, 66, 67, 68, 69, 70, 71}, // SKINCOLOR_YELLOW - { 80, 81, 82, 83, 64, 65, 65, 76, 76, 77, 77, 78, 79, 237, 239, 29}, // SKINCOLOR_MUSTARD - { 80, 81, 83, 72, 73, 74, 75, 76, 77, 78, 79, 236, 237, 238, 239, 30}, // SKINCOLOR_BANANA - { 80, 82, 73, 74, 75, 76, 77, 78, 79, 236, 237, 238, 239, 28, 29, 31}, // SKINCOLOR_OLIVE - { 0, 80, 81, 88, 88, 188, 189, 76, 76, 77, 78, 79, 236, 237, 238, 239}, // SKINCOLOR_CROCODILE - { 0, 80, 81, 88, 188, 189, 190, 191, 94, 94, 95, 95, 109, 110, 111, 31}, // SKINCOLOR_PERIDOT - { 0, 208, 216, 209, 218, 51, 65, 76, 191, 191, 126, 143, 138, 175, 169, 254}, // SKINCOLOR_VOMIT - { 81, 82, 83, 73, 64, 65, 66, 92, 92, 93, 93, 94, 95, 109, 110, 111}, // SKINCOLOR_GARDEN - { 0, 80, 81, 88, 188, 189, 114, 114, 115, 115, 116, 116, 117, 118, 119, 111}, // SKINCOLOR_LIME - { 83, 72, 73, 74, 75, 76, 102, 104, 105, 106, 107, 108, 109, 110, 111, 31}, // SKINCOLOR_HANDHELD - { 0, 80, 80, 81, 88, 89, 90, 91, 92, 93, 94, 95, 109, 110, 111, 31}, // SKINCOLOR_TEA - { 0, 80, 88, 88, 89, 90, 91, 102, 103, 104, 105, 106, 107, 108, 109, 110}, // SKINCOLOR_PISTACHIO - { 88, 89, 90, 91, 91, 92, 93, 94, 107, 107, 108, 108, 109, 109, 110, 111}, // SKINCOLOR_MOSS - {208, 84, 85, 240, 241, 243, 245, 94, 107, 108, 108, 109, 109, 110, 110, 111}, // SKINCOLOR_CAMOUFLAGE - { 0, 88, 88, 89, 89, 100, 101, 102, 125, 126, 143, 143, 138, 175, 169, 254}, // SKINCOLOR_MINT - { 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111}, // SKINCOLOR_GREEN - { 97, 99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 30, 30, 31}, // SKINCOLOR_PINETREE - { 96, 112, 112, 113, 113, 114, 114, 115, 115, 116, 116, 117, 117, 118, 119, 111}, // SKINCOLOR_TURTLE - { 96, 112, 113, 114, 115, 116, 117, 118, 119, 119, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_SWAMP - { 0, 0, 208, 208, 48, 89, 98, 100, 148, 148, 172, 172, 173, 173, 174, 175}, // SKINCOLOR_DREAM - { 80, 88, 96, 112, 113, 124, 142, 149, 149, 173, 174, 175, 169, 253, 254, 31}, // SKINCOLOR_PLAGUE - { 0, 120, 121, 112, 113, 114, 115, 125, 125, 126, 126, 127, 138, 175, 253, 254}, // SKINCOLOR_EMERALD - {128, 129, 130, 131, 132, 133, 134, 115, 115, 116, 116, 117, 118, 119, 110, 111}, // SKINCOLOR_ALGAE - { 0, 128, 120, 121, 122, 123, 124, 125, 126, 126, 127, 127, 118, 118, 119, 111}, // SKINCOLOR_AQUAMARINE - {128, 120, 121, 122, 123, 141, 141, 142, 142, 143, 143, 138, 138, 139, 139, 31}, // SKINCOLOR_TURQUOISE - { 0, 120, 120, 121, 140, 141, 142, 143, 143, 138, 138, 139, 139, 254, 254, 31}, // SKINCOLOR_TEAL - { 0, 80, 81, 82, 83, 88, 121, 140, 133, 133, 134, 135, 136, 137, 138, 139}, // SKINCOLOR_ROBIN - { 0, 0, 128, 128, 255, 131, 132, 134, 142, 142, 143, 127, 118, 119, 110, 111}, // SKINCOLOR_CYAN - { 0, 0, 128, 128, 129, 146, 133, 134, 135, 149, 149, 173, 173, 174, 175, 31}, // SKINCOLOR_JAWZ - { 0, 128, 129, 130, 131, 132, 133, 135, 136, 136, 137, 137, 138, 138, 139, 31}, // SKINCOLOR_CERULEAN - {128, 129, 130, 132, 134, 135, 136, 137, 137, 138, 138, 139, 139, 29, 30, 31}, // SKINCOLOR_NAVY - { 0, 0, 0, 144, 144, 145, 9, 11, 14, 142, 136, 137, 138, 138, 139, 31}, // SKINCOLOR_PLATINUM - { 0, 0, 144, 144, 144, 145, 145, 145, 170, 170, 171, 171, 172, 173, 174, 175}, // SKINCOLOR_SLATE - { 0, 144, 144, 145, 145, 170, 170, 171, 171, 172, 172, 173, 173, 174, 175, 31}, // SKINCOLOR_STEEL - { 80, 81, 82, 83, 64, 65, 11, 171, 172, 173, 173, 157, 158, 159, 254, 31}, // SKINCOLOR_THUNDER - { 0, 83, 49, 50, 51, 32, 192, 148, 148, 172, 173, 174, 175, 29, 30, 31}, // SKINCOLOR_NOVA - {208, 48, 216, 217, 240, 241, 242, 171, 172, 173, 24, 25, 26, 28, 29, 31}, // SKINCOLOR_RUST - { 48, 218, 221, 224, 227, 231, 196, 173, 173, 174, 159, 159, 253, 253, 254, 31}, // SKINCOLOR_WRISTWATCH - {145, 146, 147, 148, 149, 173, 173, 174, 175, 175, 28, 28, 29, 29, 30, 31}, // SKINCOLOR_JET - { 0, 128, 129, 131, 133, 135, 149, 150, 152, 154, 156, 158, 159, 253, 254, 31}, // SKINCOLOR_SAPPHIRE - { 0, 0, 120, 120, 121, 133, 135, 149, 149, 166, 166, 167, 168, 169, 254, 31}, // SKINCOLOR_ULTRAMARINE - { 0, 0, 144, 144, 145, 146, 147, 149, 150, 152, 154, 155, 157, 159, 253, 254}, // SKINCOLOR_PERIWINKLE - {144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 155, 156, 158, 253, 254, 31}, // SKINCOLOR_BLUE - {146, 148, 149, 150, 152, 153, 155, 157, 159, 253, 253, 254, 254, 31, 31, 31}, // SKINCOLOR_MIDNIGHT - { 0, 144, 145, 146, 147, 171, 172, 166, 166, 167, 167, 168, 168, 175, 169, 253}, // SKINCOLOR_BLUEBERRY - { 0, 0, 0, 252, 252, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 254}, // SKINCOLOR_THISTLE - { 0, 252, 160, 161, 162, 163, 164, 165, 166, 167, 168, 168, 169, 169, 253, 254}, // SKINCOLOR_PURPLE - { 0, 128, 128, 129, 129, 146, 170, 162, 163, 164, 165, 166, 167, 168, 169, 254}, // SKINCOLOR_PASTEL - { 0, 144, 145, 146, 170, 162, 163, 184, 184, 207, 207, 44, 45, 46, 47, 31}, // SKINCOLOR_MOONSET - {252, 200, 201, 192, 193, 194, 172, 172, 173, 173, 174, 174, 175, 169, 253, 254}, // SKINCOLOR_DUSK - {176, 177, 178, 179, 180, 181, 182, 183, 184, 165, 165, 166, 167, 168, 169, 254}, // SKINCOLOR_VIOLET - {252, 200, 177, 177, 178, 179, 180, 181, 182, 183, 183, 184, 185, 186, 187, 31}, // SKINCOLOR_MAGENTA - {208, 209, 209, 32, 33, 182, 183, 184, 185, 185, 186, 186, 187, 253, 254, 31}, // SKINCOLOR_FUCHSIA - { 0, 0, 88, 88, 89, 6, 8, 10, 193, 194, 195, 184, 185, 186, 187, 31}, // SKINCOLOR_TOXIC - { 80, 81, 82, 83, 64, 50, 201, 192, 193, 194, 195, 173, 174, 175, 253, 254}, // SKINCOLOR_MAUVE - {252, 177, 179, 192, 193, 194, 195, 196, 196, 197, 197, 198, 198, 199, 30, 31}, // SKINCOLOR_LAVENDER - {145, 192, 193, 194, 195, 196, 197, 198, 199, 199, 29, 29, 30, 30, 31, 31}, // SKINCOLOR_BYZANTIUM - {208, 209, 210, 211, 212, 213, 214, 195, 195, 196, 196, 197, 198, 199, 29, 30}, // SKINCOLOR_POMEGRANATE - { 0, 0, 0, 252, 252, 176, 200, 201, 179, 192, 193, 194, 195, 196, 197, 198}, // SKINCOLOR_LILAC - { 0, 252, 252, 176, 200, 177, 201, 202, 202, 34, 36, 38, 40, 42, 45, 46}, // SKINCOLOR_BLOSSOM - { 0, 252, 252, 200, 200, 201, 202, 203, 204, 204, 205, 206, 207, 43, 45, 47}, // SKINCOLOR_TAFFY - - // THESE STILL NEED CONVERTED!!! - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 100, 104, 113, 116, 119}, // SKINCOLOR_SUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 96, 98, 101, 104, 113, 115, 117, 119}, // SKINCOLOR_SUPER2 - { 0, 0, 0, 0, 0, 0, 96, 98, 100, 102, 104, 113, 114, 116, 117, 119}, // SKINCOLOR_SUPER3 - { 0, 0, 0, 0, 96, 97, 99, 100, 102, 104, 113, 114, 115, 116, 117, 119}, // SKINCOLOR_SUPER4 - { 0, 0, 96, 0, 0, 0, 0, 0, 104, 113, 114, 115, 116, 117, 118, 119}, // SKINCOLOR_SUPER5 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 80, 82, 85, 115, 117, 119}, // SKINCOLOR_TSUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 80, 81, 83, 85, 115, 116, 117, 119}, // SKINCOLOR_TSUPER2 - { 0, 0, 0, 0, 0, 0, 80, 81, 82, 83, 85, 115, 116, 117, 118, 119}, // SKINCOLOR_TSUPER3 - { 0, 0, 0, 0, 80, 81, 82, 83, 84, 85, 115, 115, 116, 117, 118, 119}, // SKINCOLOR_TSUPER4 - { 0, 0, 80, 80, 81, 82, 83, 84, 85, 115, 115, 116, 117, 117, 118, 119}, // SKINCOLOR_TSUPER5 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 121, 123, 125, 127, 129, 132}, // SKINCOLOR_KSUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 121, 122, 124, 125, 127, 128, 130, 132}, // SKINCOLOR_KSUPER2 - { 0, 0, 0, 0, 0, 0, 121, 122, 123, 124, 125, 127, 128, 129, 130, 132}, // SKINCOLOR_KSUPER3 - { 0, 0, 0, 0, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132}, // SKINCOLOR_KSUPER4 - { 0, 0, 121, 121, 122, 123, 124, 125, 126, 126, 127, 128, 129, 130, 131, 132}, // SKINCOLOR_KSUPER5 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 122, 124, 248, 251, 255}, // SKINCOLOR_PSUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 1, 121, 122, 124, 248, 250, 252, 255}, // SKINCOLOR_PSUPER2 - { 0, 0, 0, 0, 0, 0, 1, 121, 122, 123, 124, 248, 249, 251, 253, 255}, // SKINCOLOR_PSUPER3 - { 0, 0, 0, 0, 1, 121, 122, 123, 124, 248, 249, 250, 251, 252, 253, 255}, // SKINCOLOR_PSUPER4 - { 0, 0, 1, 121, 122, 123, 124, 248, 248, 249, 250, 251, 252, 253, 254, 255}, // SKINCOLOR_PSUPER5 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 224, 225, 227, 228, 230, 232}, // SKINCOLOR_BSUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 224, 225, 226, 227, 228, 229, 230, 232}, // SKINCOLOR_BSUPER2 - { 0, 0, 0, 0, 0, 0, 224, 224, 225, 226, 227, 228, 229, 230, 231, 232}, // SKINCOLOR_BSUPER3 - { 0, 0, 0, 0, 224, 224, 225, 226, 226, 227, 228, 229, 229, 230, 231, 232}, // SKINCOLOR_BSUPER4 - { 0, 0, 224, 224, 225, 225, 226, 227, 227, 228, 228, 229, 230, 230, 231, 232}, // SKINCOLOR_BSUPER5 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 208, 210, 212, 215, 220, 222}, // SKINCOLOR_ASUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 208, 209, 211, 213, 215, 220, 221, 223}, // SKINCOLOR_ASUPER2 - { 0, 0, 0, 0, 0, 0, 208, 209, 210, 211, 212, 213, 215, 220, 221, 223}, // SKINCOLOR_ASUPER3 - { 0, 0, 0, 0, 208, 209, 210, 211, 212, 213, 214, 215, 220, 221, 222, 223}, // SKINCOLOR_ASUPER4 - { 0, 0, 208, 208, 209, 210, 211, 211, 212, 213, 214, 215, 220, 221, 222, 223}, // SKINCOLOR_ASUPER5 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 176, 160, 163, 167, 171, 175}, // SKINCOLOR_GSUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 176, 176, 160, 163, 166, 169, 172, 175}, // SKINCOLOR_GSUPER2 - { 0, 0, 0, 0, 0, 0, 176, 176, 160, 162, 164, 166, 168, 170, 172, 175}, // SKINCOLOR_GSUPER3 - { 0, 0, 0, 0, 176, 176, 176, 160, 161, 163, 165, 167, 169, 171, 173, 175}, // SKINCOLOR_GSUPER4 - { 0, 0, 176, 176, 176, 160, 161, 163, 164, 166, 167, 169, 170, 172, 173, 175}, // SKINCOLOR_GSUPER5 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // SKINCOLOR_WSUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 9}, // SKINCOLOR_WSUPER2 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 6, 8, 11}, // SKINCOLOR_WSUPER3 - { 0, 0, 0, 0, 0, 0, 0, 1, 1, 3, 4, 6, 8, 9, 11, 13}, // SKINCOLOR_WSUPER4 - { 0, 0, 0, 0, 1, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 15}, // SKINCOLOR_WSUPER5 - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 98, 99, 81, 73, 79}, // SKINCOLOR_CSUPER1 - { 0, 0, 0, 0, 0, 0, 0, 0, 96, 97, 98, 81, 81, 71, 75, 79}, // SKINCOLOR_CSUPER2 - { 0, 0, 0, 0, 0, 0, 96, 97, 98, 99, 81, 81, 70, 73, 76, 79}, // SKINCOLOR_CSUPER3 - { 0, 0, 0, 0, 96, 96, 97, 98, 99, 81, 81, 70, 72, 74, 76, 79}, // SKINCOLOR_CSUPER4 - { 0, 0, 96, 96, 97, 98, 98, 99, 81, 81, 69, 71, 73, 75, 77, 79}, // SKINCOLOR_CSUPER5 -}; - -/*-------------------------------------------------- - INT32 K_SkincolorToTextColor(UINT8 skincolor) - - See header file for description. ---------------------------------------------------*/ -INT32 K_SkincolorToTextColor(UINT8 skincolor) -{ - INT32 textcolor = 0; - - switch (skincolor) - { - default: // default to white? - case SKINCOLOR_WHITE: - case SKINCOLOR_SILVER: - case SKINCOLOR_SLATE: - textcolor = 0; // No color is white - break; - case SKINCOLOR_GREY: - case SKINCOLOR_NICKEL: - case SKINCOLOR_BLACK: - case SKINCOLOR_SKUNK: - case SKINCOLOR_PLATINUM: - case SKINCOLOR_JET: - textcolor = V_GRAYMAP; - break; - case SKINCOLOR_SEPIA: - case SKINCOLOR_BEIGE: - case SKINCOLOR_CARAMEL: - case SKINCOLOR_PEACH: - case SKINCOLOR_BROWN: - case SKINCOLOR_LEATHER: - case SKINCOLOR_RUST: - case SKINCOLOR_WRISTWATCH: - textcolor = V_BROWNMAP; - break; - case SKINCOLOR_FAIRY: - case SKINCOLOR_PINK: - case SKINCOLOR_ROSE: - case SKINCOLOR_LEMONADE: - case SKINCOLOR_LILAC: - case SKINCOLOR_BLOSSOM: - case SKINCOLOR_TAFFY: - textcolor = V_PINKMAP; - break; - case SKINCOLOR_CINNAMON: - case SKINCOLOR_RUBY: - case SKINCOLOR_RASPBERRY: - case SKINCOLOR_RED: - case SKINCOLOR_CRIMSON: - case SKINCOLOR_MAROON: - case SKINCOLOR_SCARLET: - case SKINCOLOR_KETCHUP: - textcolor = V_REDMAP; - break; - case SKINCOLOR_DAWN: - case SKINCOLOR_SUNSLAM: - case SKINCOLOR_CREAMSICLE: - case SKINCOLOR_ORANGE: - case SKINCOLOR_ROSEWOOD: - case SKINCOLOR_TANGERINE: - textcolor = V_ORANGEMAP; - break; - case SKINCOLOR_TAN: - case SKINCOLOR_CREAM: - textcolor = V_TANMAP; - break; - case SKINCOLOR_GOLD: - case SKINCOLOR_ROYAL: - case SKINCOLOR_BRONZE: - case SKINCOLOR_COPPER: - case SKINCOLOR_THUNDER: - textcolor = V_GOLDMAP; - break; - case SKINCOLOR_POPCORN: - case SKINCOLOR_YELLOW: - case SKINCOLOR_MUSTARD: - case SKINCOLOR_BANANA: - case SKINCOLOR_OLIVE: - case SKINCOLOR_CROCODILE: - textcolor = V_YELLOWMAP; - break; - case SKINCOLOR_ARTICHOKE: - case SKINCOLOR_PERIDOT: - case SKINCOLOR_VOMIT: - case SKINCOLOR_GARDEN: - case SKINCOLOR_LIME: - case SKINCOLOR_HANDHELD: - case SKINCOLOR_TEA: - case SKINCOLOR_PISTACHIO: - case SKINCOLOR_MOSS: - case SKINCOLOR_CAMOUFLAGE: - case SKINCOLOR_MINT: - case SKINCOLOR_GREEN: - case SKINCOLOR_PINETREE: - case SKINCOLOR_TURTLE: - case SKINCOLOR_SWAMP: - case SKINCOLOR_DREAM: - case SKINCOLOR_PLAGUE: - case SKINCOLOR_EMERALD: - case SKINCOLOR_ALGAE: - textcolor = V_GREENMAP; - break; - case SKINCOLOR_AQUAMARINE: - case SKINCOLOR_TURQUOISE: - case SKINCOLOR_TEAL: - textcolor = V_AQUAMAP; - break; - case SKINCOLOR_PIGEON: - case SKINCOLOR_ROBIN: - case SKINCOLOR_CYAN: - case SKINCOLOR_JAWZ: - case SKINCOLOR_CERULEAN: - case SKINCOLOR_NAVY: - case SKINCOLOR_SAPPHIRE: - textcolor = V_SKYMAP; - break; - case SKINCOLOR_STEEL: - case SKINCOLOR_ULTRAMARINE: - case SKINCOLOR_PERIWINKLE: - case SKINCOLOR_BLUE: - case SKINCOLOR_MIDNIGHT: - case SKINCOLOR_BLUEBERRY: - case SKINCOLOR_NOVA: - textcolor = V_BLUEMAP; - break; - case SKINCOLOR_THISTLE: - case SKINCOLOR_PURPLE: - case SKINCOLOR_PASTEL: - textcolor = V_PURPLEMAP; - break; - case SKINCOLOR_MAGENTA: - case SKINCOLOR_FUCHSIA: - case SKINCOLOR_MOONSET: - case SKINCOLOR_VIOLET: - textcolor = V_MAGENTAMAP; - break; - case SKINCOLOR_DUSK: - case SKINCOLOR_TOXIC: - case SKINCOLOR_MAUVE: - case SKINCOLOR_LAVENDER: - case SKINCOLOR_BYZANTIUM: - case SKINCOLOR_POMEGRANATE: - textcolor = V_LAVENDERMAP; - break; - } - - return textcolor; -} - /*-------------------------------------------------- UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b) @@ -543,6 +31,17 @@ UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b) return min(brightness, UINT8_MAX); } +/*-------------------------------------------------- + UINT16 K_RainbowColor(tic_t time) + + See header file for description. +--------------------------------------------------*/ + +UINT16 K_RainbowColor(tic_t time) +{ + return (UINT16)(SKINCOLOR_PINK + (time % (SKINCOLOR_TAFFY - SKINCOLOR_PINK))); +} + /*-------------------------------------------------- void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) @@ -561,7 +60,7 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) // first generate the brightness of all the colours of that skincolour for (i = 0; i < 16; i++) { - color = V_GetColor(colortranslations[skincolor][i]); + color = V_GetColor(skincolors[skincolor].ramp[i]); colorbrightnesses[i] = K_ColorRelativeLuminance(color.s.red, color.s.green, color.s.blue); } @@ -585,7 +84,7 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor) if (temp < brightdif) { brightdif = (UINT16)temp; - dest_colormap[i] = colortranslations[skincolor][j]; + dest_colormap[i] = skincolors[skincolor].ramp[j]; } } } @@ -613,7 +112,7 @@ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color) if (skinnum == TC_ALLWHITE) dest_colormap[i] = 0; else if (skinnum == TC_BLINK) - dest_colormap[i] = colortranslations[color][3]; + dest_colormap[i] = skincolors[color].ramp[3]; else dest_colormap[i] = (UINT8)i; } @@ -645,24 +144,8 @@ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color) for (i = 0; i < SKIN_RAMP_LENGTH; i++) { // Sryder 2017-10-26: What was here before was most definitely not particularly readable, check above for new color translation table - dest_colormap[starttranscolor + i] = colortranslations[color][i]; + dest_colormap[starttranscolor + i] = skincolors[color].ramp[i]; } } -/*-------------------------------------------------- - UINT8 K_GetKartColorByName(const char *name) - - See header file for description. ---------------------------------------------------*/ -UINT8 K_GetKartColorByName(const char *name) -{ - UINT8 color = (UINT8)atoi(name); - if (color > 0 && color < MAXSKINCOLORS) - return color; - for (color = 1; color < MAXSKINCOLORS; color++) - if (!stricmp(KartColor_Names[color], name)) - return color; - return 0; -} - //} diff --git a/src/k_color.h b/src/k_color.h index 85164623d..e90ab0fc4 100644 --- a/src/k_color.h +++ b/src/k_color.h @@ -19,25 +19,6 @@ #define DEFAULT_STARTTRANSCOLOR 96 #define NUM_PALETTE_ENTRIES 256 -extern UINT8 colortranslations[MAXTRANSLATIONS][16]; -extern const char *KartColor_Names[MAXSKINCOLORS]; -extern const UINT8 KartColor_Opposite[MAXSKINCOLORS*2]; - -/*-------------------------------------------------- - INT32 K_SkincolorToTextColor(UINT8 skincolor); - - Gives you the "text" color (V_ constants) from a skincolor (SKINCOLOR_ constants). - Used primarily by the chat system. - - Input Arguments:- - skincolor - SKINCOLOR_ constant - - Return:- - V_ constant for font coloring ---------------------------------------------------*/ -INT32 K_SkincolorToTextColor(UINT8 skincolor); - - /*-------------------------------------------------- UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b); @@ -55,6 +36,20 @@ INT32 K_SkincolorToTextColor(UINT8 skincolor); UINT8 K_ColorRelativeLuminance(UINT8 r, UINT8 g, UINT8 b); +/*-------------------------------------------------- + UINT16 K_RainbowColor(tic_t time) + + Gives you a color to use for rainbow effects (like invincibility). + + Input Arguments:- + time - Time offset, usually is leveltime. + + Return:- + Skincolor value. +--------------------------------------------------*/ + +UINT16 K_RainbowColor(tic_t time); + /*-------------------------------------------------- void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor); @@ -86,17 +81,4 @@ void K_RainbowColormap(UINT8 *dest_colormap, UINT8 skincolor); --------------------------------------------------*/ void K_GenerateKartColormap(UINT8 *dest_colormap, INT32 skinnum, UINT8 color); -/*-------------------------------------------------- - UINT8 K_GetKartColorByName(const char *name); - - Finds the corresponding SKINCOLOR_ constant to the string provided. - - Input Arguments:- - name - The name of the color desired. - - Return:- - SKINCOLOR_ constant, SKINCOLOR_NONE if invalid ---------------------------------------------------*/ -UINT8 K_GetKartColorByName(const char *name); - #endif diff --git a/src/k_grandprix.c b/src/k_grandprix.c index a4882147a..57e31a885 100644 --- a/src/k_grandprix.c +++ b/src/k_grandprix.c @@ -533,7 +533,7 @@ void K_FakeBotResults(player_t *bot) if (besttime == UINT32_MAX // No one finished, so you don't finish either. || bot->distancetofinish >= worstdist) // Last place, you aren't going to finish. { - bot->pflags |= PF_TIMEOVER; + bot->pflags |= PF_GAMETYPEOVER; return; } diff --git a/src/k_hud.c b/src/k_hud.c index 4ceb24dd9..42c7fd7c2 100644 --- a/src/k_hud.c +++ b/src/k_hud.c @@ -870,11 +870,6 @@ static void K_initKartHUD(void) } } } - - if (timeinmap > 105) - hudtrans = cv_translucenthud.value; - else - hudtrans = 0; } static void K_drawKartItem(void) @@ -893,7 +888,7 @@ static void K_drawKartItem(void) INT32 itembar = 0; INT32 maxl = 0; // itembar's normal highest value const INT32 barlength = (r_splitscreen > 1 ? 12 : 26); - UINT8 localcolor = SKINCOLOR_NONE; + UINT16 localcolor = SKINCOLOR_NONE; SINT8 colormode = TC_RAINBOW; UINT8 *colmap = NULL; boolean flipamount = false; // Used for 3P/4P splitscreen to flip item amount stuff @@ -1106,7 +1101,7 @@ static void K_drawKartItem(void) switch (stplyr->karthud[khud_itemblinkmode]) { case 2: - localcolor = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); + localcolor = K_RainbowColor(leveltime); break; case 1: localcolor = SKINCOLOR_RED; @@ -1167,7 +1162,7 @@ static void K_drawKartItem(void) V_DrawFixedPatch(fx<collected) { - emblempic[curemb] = W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE); + emblempic[curemb] = W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE); emblemcol[curemb] = R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_CACHE); if (++curemb == 3) break; @@ -1538,10 +1533,8 @@ static boolean K_drawKartPositionFaces(void) if (numplayersingame <= 1) return true; -#ifdef HAVE_BLUA if (!LUA_HudEnabled(hud_minirankings)) return false; // Don't proceed but still return true for free play above if HUD is disabled. -#endif for (j = 0; j < numplayersingame; j++) { @@ -1576,7 +1569,7 @@ static boolean K_drawKartPositionFaces(void) else Y -= (9*5); - if (G_BattleGametype() || strank <= 2) // too close to the top, or playing battle, or a spectator? would have had (strank == -1) called out, but already caught by (strank <= 2) + if (gametype == GT_BATTLE || strank <= 2) // too close to the top, or playing battle, or a spectator? would have had (strank == -1) called out, but already caught by (strank <= 2) { i = 0; if (ranklines > 5) // could be both... @@ -1610,13 +1603,11 @@ static boolean K_drawKartPositionFaces(void) else colormap = R_GetTranslationColormap(players[rankplayer[i]].skin, players[rankplayer[i]].mo->color, GTC_CACHE); - V_DrawMappedPatch(FACE_X, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, facerankprefix[players[rankplayer[i]].skin], colormap); + V_DrawMappedPatch(FACE_X, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin][FACE_RANK], colormap); -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_battlebumpers)) { -#endif - if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_bumper] > 0) + if (gametype == GT_BATTLE && players[rankplayer[i]].kartstuff[k_bumper] > 0) { V_DrawMappedPatch(bumperx-2, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_tinybumper[0], colormap); for (j = 1; j < players[rankplayer[i]].kartstuff[k_bumper]; j++) @@ -1625,15 +1616,13 @@ static boolean K_drawKartPositionFaces(void) V_DrawMappedPatch(bumperx, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_tinybumper[1], colormap); } } -#ifdef HAVE_BLUA } // A new level of stupidity: checking if lua is enabled to close a bracket. :Fascinating: -#endif } if (i == strank) V_DrawScaledPatch(FACE_X, Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_facehighlight[(leveltime / 4) % 8]); - if (G_BattleGametype() && players[rankplayer[i]].kartstuff[k_bumper] <= 0) + if (gametype == GT_BATTLE && players[rankplayer[i]].kartstuff[k_bumper] <= 0) V_DrawScaledPatch(FACE_X-4, Y-3, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_ranknobumpers); else { @@ -1653,7 +1642,7 @@ static boolean K_drawKartPositionFaces(void) // // HU_DrawTabRankings -- moved here to take advantage of kart stuff! // -void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol) +void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol) { static tic_t alagles_timer = 9; INT32 i, rightoffset = 240; @@ -1730,8 +1719,8 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I else colormap = R_GetTranslationColormap(players[tab[i].num].skin, players[tab[i].num].mo->color, GTC_CACHE); - V_DrawMappedPatch(x, y-4, 0, facerankprefix[players[tab[i].num].skin], colormap); - /*if (G_BattleGametype() && players[tab[i].num].kartstuff[k_bumper] > 0) -- not enough space for this + V_DrawMappedPatch(x, y-4, 0, faceprefix[players[tab[i].num].skin][FACE_RANK], colormap); + /*if (gametype == GT_BATTLE && players[tab[i].num].kartstuff[k_bumper] > 0) -- not enough space for this { INT32 bumperx = x+19; V_DrawMappedPatch(bumperx-2, y-4, 0, kp_tinybumper[0], colormap); @@ -1746,7 +1735,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I if (tab[i].num == whiteplayer) V_DrawScaledPatch(x, y-4, 0, kp_facehighlight[(leveltime / 4) % 8]); - if (G_BattleGametype() && players[tab[i].num].kartstuff[k_bumper] <= 0) + if (gametype == GT_BATTLE && players[tab[i].num].kartstuff[k_bumper] <= 0) V_DrawScaledPatch(x-4, y-7, 0, kp_ranknobumpers); else { @@ -1757,14 +1746,14 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I V_DrawScaledPatch(x-5, y+6, 0, kp_facenum[pos]); } - if (G_RaceGametype()) + if (gametype == GT_RACE) { #define timestring(time) va("%i'%02i\"%02i", G_TicsToMinutes(time, true), G_TicsToSeconds(time), G_TicsToCentiseconds(time)) if (scorelines > 8) { if (players[tab[i].num].exiting) V_DrawRightAlignedThinString(x+rightoffset, y-1, hilicol|V_6WIDTHSPACE, timestring(players[tab[i].num].realtime)); - else if (players[tab[i].num].pflags & PF_TIMEOVER) + else if (players[tab[i].num].pflags & PF_GAMETYPEOVER) V_DrawRightAlignedThinString(x+rightoffset, y-1, V_6WIDTHSPACE, "NO CONTEST."); else if (circuitmap) V_DrawRightAlignedThinString(x+rightoffset, y-1, V_6WIDTHSPACE, va("Lap %d", tab[i].count)); @@ -1773,7 +1762,7 @@ void HU_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, I { if (players[tab[i].num].exiting) V_DrawRightAlignedString(x+rightoffset, y, hilicol, timestring(players[tab[i].num].realtime)); - else if (players[tab[i].num].pflags & PF_TIMEOVER) + else if (players[tab[i].num].pflags & PF_GAMETYPEOVER) V_DrawRightAlignedThinString(x+rightoffset, y-1, 0, "NO CONTEST."); else if (circuitmap) V_DrawRightAlignedString(x+rightoffset, y, 0, va("Lap %d", tab[i].count)); @@ -1805,15 +1794,15 @@ static void K_drawKartLapsAndRings(void) boolean colorring = false; INT32 ringx = 0; - rn[0] = ((abs(stplyr->kartstuff[k_rings]) / 10) % 10); - rn[1] = (abs(stplyr->kartstuff[k_rings]) % 10); + rn[0] = ((abs(stplyr->rings) / 10) % 10); + rn[1] = (abs(stplyr->rings) % 10); - if (stplyr->kartstuff[k_rings] <= 0 && (leveltime/5 & 1)) // In debt + if (stplyr->rings <= 0 && (leveltime/5 & 1)) // In debt { ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_CRIMSON, GTC_CACHE); colorring = true; } - else if (stplyr->kartstuff[k_rings] >= 20) // Maxed out + else if (stplyr->rings >= 20) // Maxed out ringmap = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_YELLOW, GTC_CACHE); if (stplyr->karthud[khud_ringframe] > RINGANIM_FLIPFRAME) @@ -1892,7 +1881,7 @@ static void K_drawKartLapsAndRings(void) V_DrawMappedPatch(fr+ringx, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags|ringflip, kp_smallring[ringanim_realframe], (colorring ? ringmap : NULL)); - if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt + if (stplyr->rings < 0) // Draw the minus for ring debt V_DrawMappedPatch(fr+7, fy-10, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringdebtminussmall, ringmap); V_DrawMappedPatch(fr+11, fy-10, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[rn[0]], ringmap); @@ -1906,7 +1895,7 @@ static void K_drawKartLapsAndRings(void) if (uselives) { UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); - V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags, facemmapprefix[stplyr->skin], colormap); + V_DrawMappedPatch(fr+21, fy-13, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_MINIMAP], colormap); V_DrawScaledPatch(fr+34, fy-10, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[(stplyr->lives % 10)]); // make sure this doesn't overflow } } @@ -1928,7 +1917,7 @@ static void K_drawKartLapsAndRings(void) V_DrawMappedPatch(LAPS_X+ringx+7, LAPS_Y-16, V_HUDTRANS|V_SLIDEIN|splitflags|ringflip, kp_ring[ringanim_realframe], (colorring ? ringmap : NULL)); - if (stplyr->kartstuff[k_rings] < 0) // Draw the minus for ring debt + if (stplyr->rings < 0) // Draw the minus for ring debt { V_DrawMappedPatch(LAPS_X+23, LAPS_Y-11, V_HUDTRANS|V_SLIDEIN|splitflags, kp_ringdebtminus, ringmap); V_DrawMappedPatch(LAPS_X+29, LAPS_Y-11, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[rn[0]], ringmap); @@ -1948,7 +1937,7 @@ static void K_drawKartLapsAndRings(void) if (uselives) { UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); - V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|V_SLIDEIN|splitflags, facerankprefix[stplyr->skin], colormap); + V_DrawMappedPatch(LAPS_X+46, LAPS_Y-16, V_HUDTRANS|V_SLIDEIN|splitflags, faceprefix[stplyr->skin][FACE_RANK], colormap); V_DrawScaledPatch(LAPS_X+63, LAPS_Y-11, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->lives % 10)]); // make sure this doesn't overflow } } @@ -1996,7 +1985,7 @@ static void K_drawKartSpeedometer(void) numbers[1] = ((convSpeed / 10) % 10); numbers[2] = (convSpeed % 10); - if (G_BattleGametype()) + if (gametype == GT_BATTLE) battleoffset = 8; V_DrawScaledPatch(LAPS_X, LAPS_Y-25 + battleoffset, V_HUDTRANS|V_SLIDEIN|splitflags, kp_speedometersticker); @@ -2200,14 +2189,14 @@ static void K_drawKartWanted(void) if (players[battlewanted[i]].skincolor) { colormap = R_GetTranslationColormap(TC_RAINBOW, p->skincolor, GTC_CACHE); - V_DrawFixedPatch(x<skin] : facerankprefix[p->skin]), colormap); + V_DrawFixedPatch(x<skin][FACE_WANTED] : faceprefix[p->skin][FACE_RANK]), colormap); /*if (basey2) // again with 4p stuff - V_DrawFixedPatch(x<skin] : facerankprefix[p->skin]), colormap);*/ + V_DrawFixedPatch(x<skin][FACE_WANTED] : faceprefix[p->skin][FACE_RANK]), colormap);*/ } } } -static void K_ObjectTracking(fixed_t *hud_x, fixed_t *hud_y, vertex_t *campos, angle_t camang, angle_t camaim, vertex_t *point) +static void K_ObjectTracking(fixed_t *hud_x, fixed_t *hud_y, vector3_t *campos, angle_t camang, angle_t camaim, vector3_t *point, UINT8 cnum) { const INT32 swhalf = (BASEVIDWIDTH / 2); const fixed_t swhalffixed = swhalf * FRACUNIT; @@ -2223,7 +2212,7 @@ static void K_ObjectTracking(fixed_t *hud_x, fixed_t *hud_y, vertex_t *campos, a fixed_t distance = R_PointToDist2(campos->x, campos->y, point->x, point->y); fixed_t factor = INT32_MAX; - const fixed_t fov = cv_fov.value; + const fixed_t fov = cv_fov[cnum].value; fixed_t intendedfov = 90*FRACUNIT; fixed_t fovmul = FRACUNIT; @@ -2309,7 +2298,7 @@ static void K_drawKartPlayerCheck(void) { const fixed_t maxdistance = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed)); camera_t *thiscam; - vertex_t c; + vector3_t c; UINT8 cnum = 0; UINT8 i; INT32 splitflags = V_SNAPTOBOTTOM|V_SPLITSCREEN; @@ -2354,7 +2343,7 @@ static void K_drawKartPlayerCheck(void) UINT8 *colormap = NULL; UINT8 pnum = 0; fixed_t x = 0; - vertex_t v; + vector3_t v; if (!playeringame[i] || checkplayer->spectator) { @@ -2400,7 +2389,7 @@ static void K_drawKartPlayerCheck(void) pnum += 2; } - K_ObjectTracking(&x, NULL, &c, thiscam->angle + ANGLE_180, 0, &v); + K_ObjectTracking(&x, NULL, &c, thiscam->angle + ANGLE_180, 0, &v, cnum); colormap = R_GetTranslationColormap(TC_DEFAULT, checkplayer->mo->color, GTC_CACHE); V_DrawFixedPatch(x, CHEK_Y * FRACUNIT, FRACUNIT, V_HUDTRANS|V_SPLITSCREEN|splitflags, kp_check[pnum], colormap); @@ -2419,7 +2408,7 @@ static boolean K_ShowPlayerNametag(player_t *p) return false; } - if (G_RaceGametype()) + if (gametype == GT_RACE) { if ((p->kartstuff[k_position] < stplyr->kartstuff[k_position]-2) || (p->kartstuff[k_position] > stplyr->kartstuff[k_position]+2)) @@ -2446,8 +2435,9 @@ static void K_DrawRivalTagForPlayer(fixed_t x, fixed_t y) static void K_DrawNameTagForPlayer(fixed_t x, fixed_t y, player_t *p, UINT8 cnum) { - INT32 namelen = V_ThinStringWidth(player_names[p - players], V_6WIDTHSPACE|V_ALLOWLOWERCASE); - INT32 clr = K_SkincolorToTextColor(p->skincolor); + const INT32 clr = skincolors[p->skincolor].chatcolor; + const INT32 namelen = V_ThinStringWidth(player_names[p - players], V_6WIDTHSPACE|V_ALLOWLOWERCASE); + UINT8 *colormap = V_GetStringColormap(clr); INT32 barx = 0, bary = 0, barw = 0; @@ -2499,7 +2489,7 @@ static void K_drawKartNameTags(void) { const fixed_t maxdistance = 8192*mapobjectscale; camera_t *thiscam; - vertex_t c; + vector3_t c; UINT8 cnum = 0; UINT8 tobesorted[MAXPLAYERS]; fixed_t sortdist[MAXPLAYERS]; @@ -2538,7 +2528,7 @@ static void K_drawKartNameTags(void) { player_t *ntplayer = &players[i]; fixed_t distance = maxdistance+1; - vertex_t v; + vector3_t v; if (!playeringame[i] || ntplayer->spectator) { @@ -2613,7 +2603,7 @@ static void K_drawKartNameTags(void) fixed_t y = -BASEVIDWIDTH * FRACUNIT; SINT8 localindicator = -1; - vertex_t v; + vector3_t v; v.x = ntplayer->mo->x; v.y = ntplayer->mo->y; @@ -2624,7 +2614,7 @@ static void K_drawKartNameTags(void) v.z += ntplayer->mo->height; } - K_ObjectTracking(&x, &y, &c, thiscam->angle, thiscam->aiming, &v); + K_ObjectTracking(&x, &y, &c, thiscam->angle, thiscam->aiming, &v, cnum); /* if ((x < 0 || x > BASEVIDWIDTH * FRACUNIT) @@ -2814,14 +2804,14 @@ static void K_drawKartMinimap(void) y -= SHORT(AutomapPic->topoffset); // Draw the super item in Battle - if (G_BattleGametype() && battleovertime.enabled) + if (gametype == GT_BATTLE && battleovertime.enabled) { if (battleovertime.enabled >= 10*TICRATE || (battleovertime.enabled & 1)) { const INT32 prevsplitflags = splitflags; splitflags &= ~V_HUDTRANSHALF; splitflags |= V_HUDTRANS; - colormap = R_GetTranslationColormap(TC_RAINBOW, (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))), GTC_CACHE); + colormap = R_GetTranslationColormap(TC_RAINBOW, K_RainbowColor(leveltime), GTC_CACHE); K_drawKartMinimapIcon(battleovertime.x, battleovertime.y, x, y, splitflags, kp_itemminimap, colormap, AutomapPic); splitflags = prevsplitflags; } @@ -2831,7 +2821,7 @@ static void K_drawKartMinimap(void) for (i = 0; i < 4; i++) localplayers[i] = -1; - if (G_RaceGametype()) + if (gametype == GT_RACE) hyu *= 2; // double in race // Player's tiny icons on the Automap. (drawn opposite direction so player 1 is drawn last in splitscreen) @@ -2853,7 +2843,7 @@ static void K_drawKartMinimap(void) } else colormap = NULL; - K_drawKartMinimapIcon(g->mo->x, g->mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic); + K_drawKartMinimapIcon(g->mo->x, g->mo->y, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); g = g->next; } @@ -2874,7 +2864,7 @@ static void K_drawKartMinimap(void) if (i != displayplayers[0] || r_splitscreen) { - if (G_BattleGametype() && players[i].kartstuff[k_bumper] <= 0) + if (gametype == GT_BATTLE && players[i].kartstuff[k_bumper] <= 0) continue; if (players[i].kartstuff[k_hyudorotimer] > 0) @@ -2909,10 +2899,10 @@ static void K_drawKartMinimap(void) else colormap = NULL; - K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic); + K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); // Target reticule - if ((G_RaceGametype() && players[i].kartstuff[k_position] == spbplace) - || (G_BattleGametype() && K_IsPlayerWanted(&players[i]))) + if ((gametype == GT_RACE && players[i].kartstuff[k_position] == spbplace) + || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[i]))) K_drawKartMinimapIcon(players[i].mo->x, players[i].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); } } @@ -2961,11 +2951,11 @@ static void K_drawKartMinimap(void) else colormap = NULL; - K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, facemmapprefix[skin], colormap, AutomapPic); + K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, faceprefix[skin][FACE_MINIMAP], colormap, AutomapPic); // Target reticule - if ((G_RaceGametype() && players[localplayers[i]].kartstuff[k_position] == spbplace) - || (G_BattleGametype() && K_IsPlayerWanted(&players[localplayers[i]]))) + if ((gametype == GT_RACE && players[localplayers[i]].kartstuff[k_position] == spbplace) + || (gametype == GT_BATTLE && K_IsPlayerWanted(&players[localplayers[i]]))) K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic); } } @@ -3095,6 +3085,9 @@ static void K_drawKartStartBulbs(void) x = 28*FRACUNIT; } + if (timeinmap < 16) + return; // temporary for current map start behaviour + for (i = 0; i < 10; i++) { UINT8 patchnum = letters_order[i]; @@ -3249,10 +3242,9 @@ static void K_drawBattleFullscreen(void) INT32 splitflags = V_SNAPTOTOP; // I don't feel like properly supporting non-green resolutions, so you can have a misuse of SNAPTO instead fixed_t scale = FRACUNIT; boolean drawcomebacktimer = true; // lazy hack because it's cleaner in the long run. -#ifdef HAVE_BLUA + if (!LUA_HudEnabled(hud_battlecomebacktimer)) drawcomebacktimer = false; -#endif if (r_splitscreen) { @@ -3361,9 +3353,7 @@ static void K_drawBattleFullscreen(void) return; } -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_freeplay)) -#endif K_drawKartFreePlay(leveltime); } } @@ -3407,13 +3397,13 @@ static void K_drawKartFirstPerson(void) splitflags |= (stplyr->mo->frame & FF_TRANSMASK); } - if (cmd->driftturn > 400) // strong left turn + if (cmd->turning > 400) // strong left turn target = 2; - else if (cmd->driftturn < -400) // strong right turn + else if (cmd->turning < -400) // strong right turn target = -2; - else if (cmd->driftturn > 0) // weak left turn + else if (cmd->turning > 0) // weak left turn target = 1; - else if (cmd->driftturn < 0) // weak right turn + else if (cmd->turning < 0) // weak right turn target = -1; else // forward target = 0; @@ -3436,8 +3426,8 @@ static void K_drawKartFirstPerson(void) x <<= FRACBITS; y <<= FRACBITS; - if (tn != cmd->driftturn/50) - tn -= (tn - (cmd->driftturn/50))/8; + if (tn != cmd->turning/50) + tn -= (tn - (cmd->turning/50))/8; if (dr != stplyr->kartstuff[k_drift]*16) dr -= (dr - (stplyr->kartstuff[k_drift]*16))/8; @@ -3455,7 +3445,7 @@ static void K_drawKartFirstPerson(void) if (stplyr->mo) { UINT8 driftcolor = K_DriftSparkColor(stplyr, stplyr->kartstuff[k_driftcharge]); - const angle_t ang = R_PointToAngle2(0, 0, stplyr->rmomx, stplyr->rmomy) - stplyr->frameangle; + const angle_t ang = R_PointToAngle2(0, 0, stplyr->rmomx, stplyr->rmomy) - stplyr->drawangle; // yes, the following is correct. no, you do not need to swap the x and y. fixed_t xoffs = -P_ReturnThrustY(stplyr->mo, ang, (BASEVIDWIDTH<<(FRACBITS-2))/2); fixed_t yoffs = -(P_ReturnThrustX(stplyr->mo, ang, 4*FRACUNIT) - 4*FRACUNIT); @@ -3466,7 +3456,7 @@ static void K_drawKartFirstPerson(void) xoffs -= (tn)*scale; xoffs -= (dr)*scale; - if (stplyr->frameangle == stplyr->mo->angle) + if (stplyr->drawangle == stplyr->mo->angle) { const fixed_t mag = FixedDiv(stplyr->speed, 10*stplyr->mo->scale); @@ -3513,8 +3503,8 @@ static void K_drawInput(void) static INT32 pn = 0; INT32 target = 0, splitflags = (V_SNAPTOBOTTOM|V_SNAPTORIGHT); INT32 x = BASEVIDWIDTH - 32, y = BASEVIDHEIGHT-24, offs, col; - const INT32 accent1 = splitflags|colortranslations[stplyr->skincolor][5]; - const INT32 accent2 = splitflags|colortranslations[stplyr->skincolor][9]; + const INT32 accent1 = splitflags | skincolors[stplyr->skincolor].ramp[5]; + const INT32 accent2 = splitflags | skincolors[stplyr->skincolor].ramp[9]; ticcmd_t *cmd = &stplyr->cmd; if (timeinmap <= 105) @@ -3559,14 +3549,14 @@ static void K_drawInput(void) y -= 1; - if (!cmd->driftturn) // no turn + if (!cmd->turning) // no turn target = 0; else // turning of multiple strengths! { - target = ((abs(cmd->driftturn) - 1)/125)+1; + target = ((abs(cmd->turning) - 1)/125)+1; if (target > 4) target = 4; - if (cmd->driftturn < 0) + if (cmd->turning < 0) target = -target; } @@ -3889,7 +3879,7 @@ void K_drawKartHUD(void) return; } - battlefullscreen = ((G_BattleGametype()) + battlefullscreen = ((gametype == GT_BATTLE) && (stplyr->exiting || (stplyr->kartstuff[k_bumper] <= 0 && stplyr->kartstuff[k_comebacktimer] @@ -3899,66 +3889,50 @@ void K_drawKartHUD(void) if (!demo.title && (!battlefullscreen || r_splitscreen)) { // Draw the CHECK indicator before the other items, so it's overlapped by everything else -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_check)) // delete lua when? -#endif if (cv_kartcheck.value && !splitscreen && !players[displayplayers[0]].exiting && !freecam) K_drawKartPlayerCheck(); // nametags -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_names)) -#endif K_drawKartNameTags(); // Draw WANTED status - if (G_BattleGametype()) + if (gametype == GT_BATTLE) { -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_wanted)) -#endif K_drawKartWanted(); } if (cv_kartminimap.value) { -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_minimap)) -#endif K_drawKartMinimap(); } } if (battlefullscreen && !freecam) { -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_battlefullscreen)) -#endif K_drawBattleFullscreen(); return; } // Draw the item window -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_item) && !freecam) -#endif K_drawKartItem(); // If not splitscreen, draw... if (!r_splitscreen && !demo.title) { // Draw the timestamp -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_time)) -#endif K_drawKartTimestamp(stplyr->realtime, TIME_X, TIME_Y, gamemap, 0); if (!modeattacking) { // The top-four faces on the left - /*#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_minirankings)) - #endif*/ + //if (LUA_HudEnabled(hud_minirankings)) isfreeplay = K_drawKartPositionFaces(); } } @@ -3968,9 +3942,7 @@ void K_drawKartHUD(void) // Draw the speedometer if (cv_kartspeedometer.value && !r_splitscreen) { -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_speedometer)) -#endif K_drawKartSpeedometer(); } @@ -3996,12 +3968,10 @@ void K_drawKartHUD(void) V_DrawTinyScaledPatch(x-54, y, 0, W_CachePatchName("TTKBANNR", PU_CACHE)); V_DrawTinyScaledPatch(x-54, y+25, 0, W_CachePatchName("TTKART", PU_CACHE)); } - else if (G_RaceGametype()) // Race-only elements + else if (gametype == GT_RACE) // Race-only elements { // Draw the lap counter -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_gametypeinfo)) -#endif K_drawKartLapsAndRings(); if (isfreeplay) @@ -4009,26 +3979,20 @@ void K_drawKartHUD(void) else if (!modeattacking) { // Draw the numerical position -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_position)) -#endif K_DrawKartPositionNum(stplyr->kartstuff[k_position]); } else //if (!(demo.playback && hu_showscores)) { // Draw the input UI -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_position)) -#endif K_drawInput(); } } - else if (G_BattleGametype()) // Battle-only + else if (gametype == GT_BATTLE) // Battle-only { // Draw the hits left! -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_gametypeinfo)) -#endif K_drawKartBumpersOrKarma(); } } @@ -4053,7 +4017,7 @@ void K_drawKartHUD(void) } // Race overlays - if (G_RaceGametype() && !freecam) + if (gametype == GT_RACE && !freecam) { if (stplyr->exiting) K_drawKartFinish(); @@ -4064,15 +4028,13 @@ void K_drawKartHUD(void) if (modeattacking || freecam) // everything after here is MP and debug only return; - if (G_BattleGametype() && !r_splitscreen && (stplyr->karthud[khud_yougotem] % 2)) // * YOU GOT EM * + if (gametype == GT_BATTLE && !r_splitscreen && (stplyr->karthud[khud_yougotem] % 2)) // * YOU GOT EM * V_DrawScaledPatch(BASEVIDWIDTH/2 - (SHORT(kp_yougotem->width)/2), 32, V_HUDTRANS, kp_yougotem); // Draw FREE PLAY. if (isfreeplay && !stplyr->spectator && timeinmap > 113) { -#ifdef HAVE_BLUA if (LUA_HudEnabled(hud_freeplay)) -#endif K_drawKartFreePlay(leveltime); } @@ -4102,18 +4064,21 @@ void K_drawKartHUD(void) if (cv_kartdebugcolorize.value && stplyr->mo && stplyr->mo->skin) { INT32 x = 0, y = 0; - UINT8 c; + UINT16 c; - for (c = 1; c < MAXSKINCOLORS; c++) + for (c = 0; c < numskincolors; c++) { - UINT8 *cm = R_GetTranslationColormap(TC_RAINBOW, c, GTC_CACHE); - V_DrawFixedPatch(x<>1, 0, facewantprefix[stplyr->skin], cm); - - x += 16; - if (x > BASEVIDWIDTH-16) + if (skincolors[c].accessible) { - x = 0; - y += 16; + UINT8 *cm = R_GetTranslationColormap(TC_RAINBOW, c, GTC_CACHE); + V_DrawFixedPatch(x<>1, 0, faceprefix[stplyr->skin][FACE_WANTED], cm); + + x += 16; + if (x > BASEVIDWIDTH-16) + { + x = 0; + y += 16; + } } } } diff --git a/src/k_hud.h b/src/k_hud.h index 27f21bd23..ac623d05c 100644 --- a/src/k_hud.h +++ b/src/k_hud.h @@ -11,6 +11,7 @@ #include "doomtype.h" #include "doomstat.h" +#include "hu_stuff.h" #ifndef __K_HUD__ #define __K_HUD__ @@ -24,5 +25,6 @@ void K_LoadKartHUDGraphics(void); void K_drawKartHUD(void); void K_drawKartFreePlay(UINT32 flashtime); void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT16 emblemmap, UINT8 mode); +void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol); #endif diff --git a/src/k_kart.c b/src/k_kart.c index 589e986b0..9f6a803da 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -28,6 +28,7 @@ #include "lua_hud.h" // For Lua hud checks #include "lua_hook.h" // For MobjDamage and ShouldDamage #include "m_cheat.h" // objectplacing +#include "p_spec.h" #include "k_waypoint.h" #include "k_bot.h" @@ -305,35 +306,35 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] = /*Jawz x2*/ { 0, 0, 1, 2, 0, 0, 0, 0 } // Jawz x2 }; -static INT32 K_KartItemOddsBattle[NUMKARTRESULTS-1][6] = +static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][2] = { - //P-Odds 0 1 2 3 4 5 - /*Sneaker*/ { 3, 2, 2, 2, 0, 2 }, // Sneaker - /*Rocket Sneaker*/ { 0, 0, 0, 0, 0, 0 }, // Rocket Sneaker - /*Invincibility*/ { 0, 1, 2, 3, 4, 2 }, // Invincibility - /*Banana*/ { 2, 1, 0, 0, 0, 0 }, // Banana - /*Eggman Monitor*/ { 1, 1, 0, 0, 0, 0 }, // Eggman Monitor - /*Orbinaut*/ { 6, 2, 1, 0, 0, 0 }, // Orbinaut - /*Jawz*/ { 3, 3, 3, 2, 0, 2 }, // Jawz - /*Mine*/ { 2, 3, 3, 1, 0, 2 }, // Mine - /*Ballhog*/ { 0, 1, 2, 1, 0, 2 }, // Ballhog - /*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 0 }, // Self-Propelled Bomb - /*Grow*/ { 0, 0, 1, 2, 4, 2 }, // Grow - /*Shrink*/ { 0, 0, 0, 0, 0, 0 }, // Shrink - /*Thunder Shield*/ { 0, 0, 0, 0, 0, 0 }, // Thunder Shield - /*Bubble Shield*/ { 0, 0, 0, 0, 0, 0 }, // Bubble Shield - /*Flame Shield*/ { 0, 0, 0, 0, 0, 0 }, // Flame Shield - /*Hyudoro*/ { 1, 1, 0, 0, 0, 0 }, // Hyudoro - /*Pogo Spring*/ { 1, 1, 0, 0, 0, 0 }, // Pogo Spring - /*Super Ring*/ { 0, 0, 0, 0, 0, 0 }, // Super Ring - /*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0 }, // Kitchen Sink - /*Sneaker x2*/ { 0, 0, 0, 0, 0, 0 }, // Sneaker x2 - /*Sneaker x3*/ { 0, 0, 0, 2, 4, 2 }, // Sneaker x3 - /*Banana x3*/ { 1, 2, 1, 0, 0, 0 }, // Banana x3 - /*Banana x10*/ { 0, 0, 1, 1, 0, 2 }, // Banana x10 - /*Orbinaut x3*/ { 0, 1, 2, 1, 0, 0 }, // Orbinaut x3 - /*Orbinaut x4*/ { 0, 0, 1, 3, 4, 2 }, // Orbinaut x4 - /*Jawz x2*/ { 0, 0, 1, 2, 4, 2 } // Jawz x2 + //P-Odds 0 1 + /*Sneaker*/ { 2, 1 }, // Sneaker + /*Rocket Sneaker*/ { 0, 0 }, // Rocket Sneaker + /*Invincibility*/ { 2, 1 }, // Invincibility + /*Banana*/ { 1, 0 }, // Banana + /*Eggman Monitor*/ { 1, 0 }, // Eggman Monitor + /*Orbinaut*/ { 8, 0 }, // Orbinaut + /*Jawz*/ { 8, 1 }, // Jawz + /*Mine*/ { 4, 1 }, // Mine + /*Ballhog*/ { 2, 1 }, // Ballhog + /*Self-Propelled Bomb*/ { 0, 0 }, // Self-Propelled Bomb + /*Grow*/ { 2, 1 }, // Grow + /*Shrink*/ { 0, 0 }, // Shrink + /*Thunder Shield*/ { 0, 0 }, // Thunder Shield + /*Bubble Shield*/ { 0, 0 }, // Bubble Shield + /*Flame Shield*/ { 0, 0 }, // Flame Shield + /*Hyudoro*/ { 2, 0 }, // Hyudoro + /*Pogo Spring*/ { 2, 0 }, // Pogo Spring + /*Super Ring*/ { 0, 0 }, // Super Ring + /*Kitchen Sink*/ { 0, 0 }, // Kitchen Sink + /*Sneaker x2*/ { 0, 0 }, // Sneaker x2 + /*Sneaker x3*/ { 0, 1 }, // Sneaker x3 + /*Banana x3*/ { 1, 0 }, // Banana x3 + /*Banana x10*/ { 0, 1 }, // Banana x10 + /*Orbinaut x3*/ { 2, 0 }, // Orbinaut x3 + /*Orbinaut x4*/ { 1, 1 }, // Orbinaut x4 + /*Jawz x2*/ { 2, 1 } // Jawz x2 }; #define DISTVAR (2048) // Magic number distance for use with item roulette tiers @@ -434,7 +435,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, if (!KartItemCVars[item-1]->value && !modeattacking) return 0; - if (G_BattleGametype()) + if (gametype == GT_BATTLE) { I_Assert(pos < 6); // DO NOT allow positions past the bounds of the table newodds = K_KartItemOddsBattle[item-1][pos]; @@ -455,7 +456,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, if (!playeringame[i] || players[i].spectator) continue; - if (!G_BattleGametype() || players[i].kartstuff[k_bumper]) + if (!(gametyperules & GTR_BUMPERS) || players[i].kartstuff[k_bumper]) pingame++; if (players[i].exiting) @@ -467,7 +468,7 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, return 0; } - if (players[i].mo && G_RaceGametype()) + if (players[i].mo && gametype == GT_RACE) { if (players[i].kartstuff[k_position] == 1 && first == -1) first = i; @@ -619,19 +620,20 @@ INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, fixed_t mashed, boolean spbrush, UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush) { UINT8 i; - UINT8 n = 0; UINT8 useodds = 0; UINT8 disttable[14]; - UINT8 totallen = 0; UINT8 distlen = 0; boolean oddsvalid[8]; + // Unused now, oops :V + (void)bestbumper; + for (i = 0; i < 8; i++) { UINT8 j; boolean available = false; - if (G_BattleGametype() && i > 5) + if (gametype == GT_BATTLE && i > 1) { oddsvalid[i] = false; break; @@ -652,30 +654,24 @@ UINT8 K_FindUseodds(player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbum #define SETUPDISTTABLE(odds, num) \ if (oddsvalid[odds]) \ for (i = num; i; --i) \ - disttable[distlen++] = odds; \ - totallen += num; + disttable[distlen++] = odds; - if (G_BattleGametype()) // Battle Mode + if (gametype == GT_BATTLE) // Battle Mode { - SETUPDISTTABLE(0,1); - SETUPDISTTABLE(1,1); - SETUPDISTTABLE(2,1); - SETUPDISTTABLE(3,1); - SETUPDISTTABLE(4,1); - - if (player->kartstuff[k_roulettetype] == 1 && oddsvalid[5]) // 5 is the extreme odds of player-controlled "Karma" items - useodds = 5; + if (player->kartstuff[k_roulettetype] == 1 && oddsvalid[1] == true) + { + // 1 is the extreme odds of player-controlled "Karma" items + useodds = 1; + } else { - SINT8 wantedpos = (bestbumper-player->kartstuff[k_bumper]); // 0 is the best player's bumper count, 1 is a bumper below best, 2 is two bumpers below, etc - if (K_IsPlayerWanted(player)) - wantedpos++; - if (wantedpos > 4) // Don't run off into karma items - wantedpos = 4; - if (wantedpos < 0) // Don't go below somehow - wantedpos = 0; - n = (wantedpos * distlen) / totallen; - useodds = disttable[n]; + useodds = 0; + + if (oddsvalid[0] == false && oddsvalid[1] == true) + { + // try to use karma odds as a fallback + useodds = 1; + } } } else @@ -852,7 +848,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) // Record Attack / alone mashing behavior if (modeattacking || pingame == 1) { - if (G_RaceGametype()) + if (gametype == GT_RACE) { if (mashed && (modeattacking || cv_superring.value)) // ANY mashed value? You get rings. { @@ -872,7 +868,7 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) S_StartSound(NULL, sfx_itrolf); } } - else if (G_BattleGametype()) + else if (gametype == GT_BATTLE) { if (mashed && (modeattacking || cv_banana.value)) // ANY mashed value? You get a banana. { @@ -899,43 +895,40 @@ static void K_KartItemRoulette(player_t *player, ticcmd_t *cmd) return; } - if (G_RaceGametype()) + // SPECIAL CASE No. 4: + // Being in ring debt occasionally forces Super Ring on you if you mashed + if ((gametyperules & GTR_RINGS) && mashed && player->rings < 0 && cv_superring.value) { - // SPECIAL CASE No. 4: - // Being in ring debt occasionally forces Super Ring on you if you mashed - if (mashed && player->kartstuff[k_rings] < 0 && cv_superring.value) + INT32 debtamount = min(20, abs(player->rings)); + if (P_RandomChance((debtamount*FRACUNIT)/20)) { - INT32 debtamount = min(20, abs(player->kartstuff[k_rings])); - if (P_RandomChance((debtamount*FRACUNIT)/20)) - { - K_KartGetItemResult(player, KITEM_SUPERRING); - player->karthud[khud_itemblink] = TICRATE; - player->karthud[khud_itemblinkmode] = 1; - player->kartstuff[k_itemroulette] = 0; - player->kartstuff[k_roulettetype] = 0; - if (P_IsDisplayPlayer(player)) - S_StartSound(NULL, sfx_itrolm); - return; - } - } - - // SPECIAL CASE No. 5: - // Force SPB onto 2nd if they get too far behind - if (player->kartstuff[k_position] == 2 && pdis > (DISTVAR*8) - && spbplace == -1 && !indirectitemcooldown && !dontforcespb - && cv_selfpropelledbomb.value) - { - K_KartGetItemResult(player, KITEM_SPB); + K_KartGetItemResult(player, KITEM_SUPERRING); player->karthud[khud_itemblink] = TICRATE; - player->karthud[khud_itemblinkmode] = (mashed ? 1 : 0); + player->karthud[khud_itemblinkmode] = 1; player->kartstuff[k_itemroulette] = 0; player->kartstuff[k_roulettetype] = 0; if (P_IsDisplayPlayer(player)) - S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf)); + S_StartSound(NULL, sfx_itrolm); return; } } + // SPECIAL CASE No. 5: + // Force SPB onto 2nd if they get too far behind + if ((gametyperules & GTR_CIRCUIT) && player->kartstuff[k_position] == 2 && pdis > (DISTVAR*8) + && spbplace == -1 && !indirectitemcooldown && !dontforcespb + && cv_selfpropelledbomb.value) + { + K_KartGetItemResult(player, KITEM_SPB); + player->karthud[khud_itemblink] = TICRATE; + player->karthud[khud_itemblinkmode] = (mashed ? 1 : 0); + player->kartstuff[k_itemroulette] = 0; + player->kartstuff[k_roulettetype] = 0; + if (P_IsDisplayPlayer(player)) + S_StartSound(NULL, (mashed ? sfx_itrolm : sfx_itrolf)); + return; + } + // NOW that we're done with all of those specialized cases, we can move onto the REAL item roulette tables. // Initializes existing spawnchance values for (i = 0; i < NUMKARTRESULTS; i++) @@ -1043,34 +1036,6 @@ fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against) return FixedMul(weight, mobj->scale); } -// This kind of wipeout happens with no rings -- doesn't remove a bumper, has no invulnerability, and is much shorter. -static void K_DebtStingPlayer(player_t *player, INT32 length) -{ - if (player->health <= 0) - return; - - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0 - || player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 - || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) - return; - - player->kartstuff[k_ringboost] = 0; - player->kartstuff[k_driftboost] = 0; - player->kartstuff[k_drift] = 0; - player->kartstuff[k_driftcharge] = 0; - player->trickpanel = 0; - - player->kartstuff[k_spinouttype] = 2; - player->kartstuff[k_spinouttimer] = length; - player->kartstuff[k_wipeoutslow] = min(length-1, wipeoutslowtime+1); - - if (player->mo->state != &states[S_KART_SPIN]) - P_SetPlayerMobjState(player->mo, S_KART_SPIN); - - K_DropHnextList(player, false); - return; -} - void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { mobj_t *fx; @@ -1232,16 +1197,14 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { mobj1->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; mobj1->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj1->player->kartstuff[k_spinouttimer]); - //mobj1->player->kartstuff[k_spinouttype] = 1; // Enforce type + //mobj1->player->kartstuff[k_spinouttype] = KSPIN_WIPEOUT; // Enforce type } else if (mobj2->player // Player VS player bumping only && (K_GetShieldFromItem(mobj1->player->kartstuff[k_itemtype]) == KSHIELD_NONE)) // Ignore for shields { - if (mobj1->player->kartstuff[k_rings] <= 0) + if (mobj1->player->rings <= 0) { - K_DebtStingPlayer(mobj1->player, TICRATE + (4 * (mobj2->player->kartweight - mobj1->player->kartweight))); - K_KartPainEnergyFling(mobj1->player); - P_PlayRinglossSound(mobj1); + P_DamageMobj(mobj1, mobj2, mobj2, 1, DMG_STING); } P_PlayerRingBurst(mobj1->player, 1); } @@ -1258,23 +1221,21 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) { mobj2->player->kartstuff[k_wipeoutslow] = wipeoutslowtime+1; mobj2->player->kartstuff[k_spinouttimer] = max(wipeoutslowtime+1, mobj2->player->kartstuff[k_spinouttimer]); - //mobj2->player->kartstuff[k_spinouttype] = 1; // Enforce type + //mobj2->player->kartstuff[k_spinouttype] = KSPIN_WIPEOUT; // Enforce type } else if (mobj1->player // Player VS player bumping only && (K_GetShieldFromItem(mobj2->player->kartstuff[k_itemtype]) == KSHIELD_NONE)) // Ignore for shields { - if (mobj2->player->kartstuff[k_rings] <= 0) + if (mobj2->player->rings <= 0) { - K_DebtStingPlayer(mobj2->player, TICRATE + (4 * (mobj1->player->kartweight - mobj2->player->kartweight))); - K_KartPainEnergyFling(mobj2->player); - P_PlayRinglossSound(mobj2); + P_DamageMobj(mobj2, mobj1, mobj1, 1, DMG_STING); } P_PlayerRingBurst(mobj2->player, 1); } } } -/** \brief Checks that the player is on an offroad subsector for realsies +/** \brief Checks that the player is on an offroad subsector for realsies. Also accounts for line riding to prevent cheese. \param mo player mobj object @@ -1282,18 +1243,64 @@ void K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2, boolean bounce, boolean solid) */ static UINT8 K_CheckOffroadCollide(mobj_t *mo) { - UINT8 i; + // Check for sectors in touching_sectorlist + UINT8 i; // special type iter + msecnode_t *node; // touching_sectorlist iter + sector_t *s; // main sector shortcut + sector_t *s2; // FOF sector shortcut + ffloor_t *rover; // FOF + + fixed_t flr; + fixed_t cel; // floor & ceiling for height checks to make sure we're touching the offroad sector. I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); - for (i = 2; i < 5; i++) + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) { - if (P_MobjTouchingSectorSpecial(mo, 1, i, true)) - return i-1; - } + if (!node->m_sector) + break; // shouldn't happen. - return 0; + s = node->m_sector; + // 1: Check for the main sector, make sure we're on the floor of that sector and see if we can apply offroad. + // Make arbitrary Z checks because we want to check for 1 sector in particular, we don't want to affect the player if the offroad sector is way below them and they're lineriding a normal sector above. + + flr = P_MobjFloorZ(mo, s, s, mo->x, mo->y, NULL, false, true); + cel = P_MobjCeilingZ(mo, s, s, mo->x, mo->y, NULL, true, true); // get Z coords of both floors and ceilings for this sector (this accounts for slopes properly.) + // NOTE: we don't use P_GetZAt with our x/y directly because the mobj won't have the same height because of its hitbox on the slope. Complex garbage but tldr it doesn't work. + + if ( ((s->flags & SF_FLIPSPECIAL_FLOOR) && mo->z == flr) // floor check + || ((mo->eflags & MFE_VERTICALFLIP && (s->flags & SF_FLIPSPECIAL_CEILING) && (mo->z + mo->height) == cel)) ) // ceiling check. + + for (i = 2; i < 5; i++) // check for sector special + + if (GETSECSPECIAL(s->special, 1) == i) + return i-1; // return offroad type + + // 2: If we're here, we haven't found anything. So let's try looking for FOFs in the sectors using the same logic. + for (rover = s->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) // This FOF doesn't exist anymore. + continue; + + s2 = §ors[rover->secnum]; // makes things easier for us + + flr = P_GetFOFBottomZ(mo, s, rover, mo->x, mo->y, NULL); + cel = P_GetFOFTopZ(mo, s, rover, mo->x, mo->y, NULL); // Z coords for fof top/bottom. + + // we will do essentially the same checks as above instead of bothering with top/bottom height of the FOF. + // Reminder that an FOF's floor is its bottom, silly! + if ( ((s2->flags & SF_FLIPSPECIAL_FLOOR) && mo->z == cel) // "floor" check + || ((s2->flags & SF_FLIPSPECIAL_CEILING) && (mo->z + mo->height) == flr) ) // "ceiling" check. + + for (i = 2; i < 5; i++) // check for sector special + + if (GETSECSPECIAL(s2->special, 1) == i) + return i-1; // return offroad type + + } + } + return 0; // couldn't find any offroad } /** \brief Updates the Player's offroad value once per frame @@ -1746,53 +1753,55 @@ void K_KartMoveAnimation(player_t *player) ticcmd_t *cmd = &player->cmd; const boolean spinningwheels = ((cmd->buttons & BT_ACCELERATE) || (onground && player->speed > 0)); - if (cmd->driftturn < -minturn) + if (cmd->turning < -minturn) { turndir = -1; } - else if (cmd->driftturn > minturn) + else if (cmd->turning > minturn) { turndir = 1; } +#define SetState(sn) \ + if (player->mo->state != &states[sn]) \ + P_SetPlayerMobjState(player->mo, sn) + if (!onground) { // Only use certain frames in the air, to make it look like your tires are spinning fruitlessly! if (player->kartstuff[k_drift] > 0) { - if (!spinningwheels || !(player->mo->state >= &states[S_KART_DRIFT1_L] && player->mo->state <= &states[S_KART_DRIFT2_L])) - { - // Neutral drift - P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_L); - } + // Neutral drift + SetState(S_KART_DRIFT_L); } else if (player->kartstuff[k_drift] > 0) { - if (!spinningwheels || !(player->mo->state >= &states[S_KART_DRIFT1_R] && player->mo->state <= &states[S_KART_DRIFT2_R])) - { - // Neutral drift - P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_R); - } + // Neutral drift + SetState(S_KART_DRIFT_R); } else { - if ((turndir == -1) - && (!spinningwheels || !(player->mo->state >= &states[S_KART_FAST1_R] && player->mo->state <= &states[S_KART_FAST2_R]))) + if (turndir == -1) { - P_SetPlayerMobjState(player->mo, S_KART_FAST2_R); + SetState(S_KART_FAST_R); } - else if ((turndir == 1) - && (!spinningwheels || !(player->mo->state >= &states[S_KART_FAST1_L] && player->mo->state <= &states[S_KART_FAST2_L]))) + else if (turndir == 1) { - P_SetPlayerMobjState(player->mo, S_KART_FAST2_L); + SetState(S_KART_FAST_L); } - else if ((turndir == 0) - && (!spinningwheels || !(player->mo->state >= &states[S_KART_FAST1] && player->mo->state <= &states[S_KART_FAST2]))) + else if (turndir == 0) { - P_SetPlayerMobjState(player->mo, S_KART_FAST2); + SetState(S_KART_FAST); } } + + if (!spinningwheels) + { + // TODO: These should prooobably be different SPR2s + // Just a quick hack to prevent needing to do that :V + player->mo->frame = (player->mo->frame & ~FF_FRAMEMASK); + } } else { @@ -1800,46 +1809,40 @@ void K_KartMoveAnimation(player_t *player) { // Drifting LEFT! - if ((turndir == -1) - && !(player->mo->state >= &states[S_KART_DRIFT1_L_OUT] && player->mo->state <= &states[S_KART_DRIFT2_L_OUT])) + if (turndir == -1) { // Right -- outwards drift - P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_L_OUT); + SetState(S_KART_DRIFT_L_OUT); } - else if ((turndir == 1) - && !(player->mo->state >= &states[S_KART_DRIFT1_L_IN] && player->mo->state <= &states[S_KART_DRIFT4_L_IN])) + else if (turndir == 1) { // Left -- inwards drift - P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_L_IN); + SetState(S_KART_DRIFT_L_IN); } - else if ((turndir == 0) - && !(player->mo->state >= &states[S_KART_DRIFT1_L] && player->mo->state <= &states[S_KART_DRIFT2_L])) + else { // Neutral drift - P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_L); + SetState(S_KART_DRIFT_L); } } else if (player->kartstuff[k_drift] < 0) { // Drifting RIGHT! - if ((turndir == -1) - && !(player->mo->state >= &states[S_KART_DRIFT1_R_IN] && player->mo->state <= &states[S_KART_DRIFT4_R_IN])) + if (turndir == -1) { // Right -- inwards drift - P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_R_IN); + SetState(S_KART_DRIFT_R_IN); } - else if ((turndir == 1) - && !(player->mo->state >= &states[S_KART_DRIFT1_R_OUT] && player->mo->state <= &states[S_KART_DRIFT2_R_OUT])) + else if (turndir == 1) { // Left -- outwards drift - P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_R_OUT); + SetState(S_KART_DRIFT_R_OUT); } - else if ((turndir == 0) - && !(player->mo->state >= &states[S_KART_DRIFT1_R] && player->mo->state <= &states[S_KART_DRIFT2_R])) + else { // Neutral drift - P_SetPlayerMobjState(player->mo, S_KART_DRIFT1_R); + SetState(S_KART_DRIFT_R); } } else @@ -1848,20 +1851,17 @@ void K_KartMoveAnimation(player_t *player) { // Going REAL fast! - if ((turndir == -1) - && !(player->mo->state >= &states[S_KART_FAST1_R] && player->mo->state <= &states[S_KART_FAST2_R])) + if (turndir == -1) { - P_SetPlayerMobjState(player->mo, S_KART_FAST1_R); + SetState(S_KART_FAST_R); } - else if ((turndir == 1) - && !(player->mo->state >= &states[S_KART_FAST1_L] && player->mo->state <= &states[S_KART_FAST2_L])) + else if (turndir == 1) { - P_SetPlayerMobjState(player->mo, S_KART_FAST1_L); + SetState(S_KART_FAST_L); } - else if ((turndir == 0) - && !(player->mo->state >= &states[S_KART_FAST1] && player->mo->state <= &states[S_KART_FAST2])) + else { - P_SetPlayerMobjState(player->mo, S_KART_FAST1); + SetState(S_KART_FAST); } } else @@ -1870,46 +1870,42 @@ void K_KartMoveAnimation(player_t *player) { // Drivin' slow. - if ((turndir == -1) - && !(player->mo->state >= &states[S_KART_SLOW1_R] && player->mo->state <= &states[S_KART_SLOW2_R])) + if (turndir == -1) { - P_SetPlayerMobjState(player->mo, S_KART_SLOW1_R); + SetState(S_KART_SLOW_R); } - else if ((turndir == 1) - && !(player->mo->state >= &states[S_KART_SLOW1_L] && player->mo->state <= &states[S_KART_SLOW2_L])) + else if (turndir == 1) { - P_SetPlayerMobjState(player->mo, S_KART_SLOW1_L); + SetState(S_KART_SLOW_L); } - else if ((turndir == 0) - && !(player->mo->state >= &states[S_KART_SLOW1] && player->mo->state <= &states[S_KART_SLOW2])) + else { - P_SetPlayerMobjState(player->mo, S_KART_SLOW1); + SetState(S_KART_SLOW); } } else { // Completely still. - if ((turndir == -1) - && !(player->mo->state >= &states[S_KART_STILL1_R] && player->mo->state <= &states[S_KART_STILL2_R])) + if (turndir == -1) { - P_SetPlayerMobjState(player->mo, S_KART_STILL1_R); + SetState(S_KART_STILL_R); } - else if ((turndir == 1) - && !(player->mo->state >= &states[S_KART_STILL1_L] && player->mo->state <= &states[S_KART_STILL2_L])) + else if (turndir == 1) { - P_SetPlayerMobjState(player->mo, S_KART_STILL1_L); + SetState(S_KART_STILL_L); } - else if ((turndir == 0) - && !(player->mo->state >= &states[S_KART_STILL1] && player->mo->state <= &states[S_KART_STILL2])) + else { - P_SetPlayerMobjState(player->mo, S_KART_STILL1); + SetState(S_KART_STILL); } } } } } +#undef SetState + // Update lastspeed value -- we use to display slow driving frames instead of fast driving when slowing down. player->lastspeed = player->speed; } @@ -1966,7 +1962,7 @@ void K_PlayOvertakeSound(mobj_t *source) { boolean tasteful = (!source->player || !source->player->karthud[khud_voices]); - if (!G_RaceGametype()) // Only in race + if (!gametype == GT_RACE) // Only in race return; // 4 seconds from before race begins, 10 seconds afterwards @@ -2220,7 +2216,7 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower) fixed_t finalspeed; UINT8 kartspeed = player->kartspeed; - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + if ((gametyperules & (GTR_BUMPERS|GTR_KARMA)) == (GTR_BUMPERS|GTR_KARMA) && player->kartstuff[k_bumper] <= 0) kartspeed = 1; finalspeed = K_GetKartSpeedFromStat(kartspeed); @@ -2259,7 +2255,7 @@ fixed_t K_GetKartAccel(player_t *player) fixed_t k_accel = 32; // 36; UINT8 kartspeed = player->kartspeed; - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + if ((gametyperules & (GTR_BUMPERS|GTR_KARMA)) == (GTR_BUMPERS|GTR_KARMA) && player->kartstuff[k_bumper] <= 0) kartspeed = 1; //k_accel += 3 * (9 - kartspeed); // 36 - 60 @@ -2285,7 +2281,7 @@ UINT16 K_GetKartFlashing(player_t *player) tics += (tics/8) * (player->kartspeed); - if (G_BattleGametype()) + if (gametype == GT_BATTLE) tics *= 2; return tics; @@ -2313,7 +2309,7 @@ SINT8 K_GetForwardMove(player_t *player) return forwardmove; } -fixed_t K_3dKartMovement(player_t *player, boolean onground) +fixed_t K_3dKartMovement(player_t *player) { const fixed_t accelmax = 4000; const fixed_t p_speed = K_GetKartSpeed(player, true); @@ -2323,8 +2319,6 @@ fixed_t K_3dKartMovement(player_t *player, boolean onground) fixed_t orig = ORIG_FRICTION; SINT8 forwardmove = K_GetForwardMove(player); - if (!onground) return 0; // If the player isn't on the ground, there is no change in speed - if (K_PlayerUsesBotMovement(player)) { orig = K_BotFrictionRubberband(player, ORIG_FRICTION); @@ -2374,108 +2368,98 @@ void K_DoInstashield(player_t *player) P_SetTarget(&layerb->target, player->mo); } -void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflictor, boolean trapitem) +void K_BattleHitPlayer(player_t *player, player_t *victim, UINT8 points, boolean reducewanted) { - UINT8 scoremultiply = 1; - // PS: Inflictor is unused for all purposes here and is actually only ever relevant to Lua. It may be nil too. -#ifdef HAVE_BLUA - boolean force = false; // Used to check if Lua ShouldSpin should get us damaged reguardless of flashtics or heck knows what. - UINT8 shouldForce = LUAh_ShouldSpin(player, inflictor, source); - if (P_MobjWasRemoved(player->mo)) - return; // mobj was removed (in theory that shouldn't happen) - if (shouldForce == 1) - force = true; - else if (shouldForce == 2) - return; -#else - static const boolean force = false; - (void)inflictor; // in case some weirdo doesn't want Lua. -#endif + if (reducewanted == false) + points = 1; // Force to 1 - if (!trapitem && G_BattleGametype()) + if (gametyperules & GTR_POINTLIMIT) + { + P_AddPlayerScore(player, points); + K_SpawnBattlePoints(player, victim, points); + } + + if ((gametyperules & GTR_WANTED) && (reducewanted == true)) + { + // Seems a little backwards, but the WANTED system is meant to prevent camping. + // If you don't want people to go after you, then be proactive! + player->kartstuff[k_wanted] -= wantedreduce; + victim->kartstuff[k_wanted] -= (wantedreduce/2); + } +} + +void K_RemoveBumper(player_t *player, mobj_t *inflictor, mobj_t *source) +{ + UINT8 score = 1; + boolean trapitem = false; + + if (!(gametyperules & GTR_BUMPERS)) + return; + + if (player->powers[pw_flashing] || P_PlayerInPain(player)) + return; + + if (inflictor && !P_MobjWasRemoved(inflictor)) + { + if (inflictor->type == MT_BANANA && inflictor->health <= 1) + { + trapitem = true; + } + } + + if (gametyperules & GTR_POINTLIMIT) { if (K_IsPlayerWanted(player)) - scoremultiply = 3; - else if (player->kartstuff[k_bumper] == 1) - scoremultiply = 2; + score = 3; + else if ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] == 1) + score = 2; } - if (player->health <= 0) - return; - - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2) - || player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 - || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) + if (source && source->player && player != source->player) { - if (!force) // if shoulddamage force, we go THROUGH that. - { - K_DoInstashield(player); - return; - } + K_BattleHitPlayer(source->player, player, score, trapitem); } -#ifdef HAVE_BLUA - if (LUAh_PlayerSpin(player, inflictor, source)) // Let Lua do its thing or overwrite if it wants to. Make sure to let any possible instashield happen because we didn't get "damaged" in this case. - return; -#endif - - if (source && source != player->mo && source->player) - K_PlayHitEmSound(source); - - player->kartstuff[k_sneakertimer] = 0; - player->kartstuff[k_numsneakers] = 0; - player->kartstuff[k_driftboost] = 0; - player->kartstuff[k_ringboost] = 0; - - player->kartstuff[k_drift] = 0; - player->kartstuff[k_driftcharge] = 0; - player->trickpanel = 0; - - if (G_BattleGametype()) + if (player->kartstuff[k_bumper] > 0) { - if (source && source->player && player != source->player) + if (player->kartstuff[k_bumper] == 1) { - P_AddPlayerScore(source->player, scoremultiply); - K_SpawnBattlePoints(source->player, player, scoremultiply); - if (!trapitem) - { - source->player->kartstuff[k_wanted] -= wantedreduce; - player->kartstuff[k_wanted] -= (wantedreduce/2); - } + mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! + P_SetTarget(&karmahitbox->target, player->mo); + karmahitbox->destscale = player->mo->scale; + P_SetScale(karmahitbox, player->mo->scale); + CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); } - if (player->kartstuff[k_bumper] > 0) - { - if (player->kartstuff[k_bumper] == 1) - { - mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! - P_SetTarget(&karmahitbox->target, player->mo); - karmahitbox->destscale = player->mo->scale; - P_SetScale(karmahitbox, player->mo->scale); - CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); - } - player->kartstuff[k_bumper]--; - if (K_IsPlayerWanted(player)) - K_CalculateBattleWanted(); - } + player->kartstuff[k_bumper]--; - if (!player->kartstuff[k_bumper]) - { - player->kartstuff[k_comebacktimer] = comebacktime; - if (player->kartstuff[k_comebackmode] == 2) - { - mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE); - S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound); - player->kartstuff[k_comebackmode] = 0; - } - } - - K_CheckBumpers(); + if (K_IsPlayerWanted(player)) + K_CalculateBattleWanted(); } + if (player->kartstuff[k_bumper] == 0) + { + player->kartstuff[k_comebacktimer] = comebacktime; + + if (player->kartstuff[k_comebackmode] == 2) + { + mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE); + S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound); + player->kartstuff[k_comebackmode] = 0; + } + } + + K_CheckBumpers(); +} + +void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type) +{ + (void)inflictor; + (void)source; + player->kartstuff[k_spinouttype] = type; - if (player->kartstuff[k_spinouttype] <= 0) // type 0 is spinout, type 1 is wipeout, type 2 is no-invuln wipeout + if (( player->kartstuff[k_spinouttype] & KSPIN_THRUST )) { // At spinout, player speed is increased to 1/4 their regular speed, moving them forward if (player->speed < K_GetKartSpeed(player, true)/4) @@ -2484,21 +2468,7 @@ void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflicto } player->kartstuff[k_spinouttimer] = (3*TICRATE/2)+2; - player->powers[pw_flashing] = K_GetKartFlashing(player); - - P_PlayRinglossSound(player->mo); - P_PlayerRingBurst(player, 5); - K_PlayPainSound(player->mo); - - if (player->mo->state != &states[S_KART_SPIN]) - P_SetPlayerMobjState(player->mo, S_KART_SPIN); - - player->kartstuff[k_instashield] = 15; - if (cv_kartdebughuddrop.value && !modeattacking) - K_DropItems(player); - else - K_DropHnextList(player, false); - return; + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); } static void K_RemoveGrowShrink(player_t *player) @@ -2524,98 +2494,10 @@ static void K_RemoveGrowShrink(player_t *player) P_RestoreMusic(player); } -void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor) +void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source) { - UINT8 scoremultiply = 1; - // PS: Inflictor is unused for all purposes here and is actually only ever relevant to Lua. It may be nil too. -#ifdef HAVE_BLUA - boolean force = false; // Used to check if Lua ShouldSquish should get us damaged reguardless of flashtics or heck knows what. - UINT8 shouldForce = LUAh_ShouldSquish(player, inflictor, source); - if (P_MobjWasRemoved(player->mo)) - return; // mobj was removed (in theory that shouldn't happen) - if (shouldForce == 1) - force = true; - else if (shouldForce == 2) - return; -#else - static const boolean force = false; - (void)inflictor; // Please stop forgetting to put inflictor in yer functions thank -Lat' -#endif - - if (G_BattleGametype()) - { - if (K_IsPlayerWanted(player)) - scoremultiply = 3; - else if (player->kartstuff[k_bumper] == 1) - scoremultiply = 2; - } - - if (player->health <= 0) - return; - - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_invincibilitytimer] > 0 - || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 - || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) - { - if (!force) // You know the drill by now. - { - K_DoInstashield(player); - return; - } - } - -#ifdef HAVE_BLUA - if (LUAh_PlayerSquish(player, inflictor, source)) // Let Lua do its thing or overwrite if it wants to. Make sure to let any possible instashield happen because we didn't get "damaged" in this case. - return; -#endif - - player->kartstuff[k_sneakertimer] = 0; - player->kartstuff[k_numsneakers] = 0; - player->kartstuff[k_driftboost] = 0; - player->kartstuff[k_ringboost] = 0; - - player->kartstuff[k_drift] = 0; - player->kartstuff[k_driftcharge] = 0; - player->trickpanel = 0; - - if (G_BattleGametype()) - { - if (source && source->player && player != source->player) - { - P_AddPlayerScore(source->player, scoremultiply); - K_SpawnBattlePoints(source->player, player, scoremultiply); - source->player->kartstuff[k_wanted] -= wantedreduce; - player->kartstuff[k_wanted] -= (wantedreduce/2); - } - - if (player->kartstuff[k_bumper] > 0) - { - if (player->kartstuff[k_bumper] == 1) - { - mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! - P_SetTarget(&karmahitbox->target, player->mo); - karmahitbox->destscale = player->mo->scale; - P_SetScale(karmahitbox, player->mo->scale); - CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); - } - player->kartstuff[k_bumper]--; - if (K_IsPlayerWanted(player)) - K_CalculateBattleWanted(); - } - - if (!player->kartstuff[k_bumper]) - { - player->kartstuff[k_comebacktimer] = comebacktime; - if (player->kartstuff[k_comebackmode] == 2) - { - mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE); - S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound); - player->kartstuff[k_comebackmode] = 0; - } - } - - K_CheckBumpers(); - } + (void)inflictor; + (void)source; player->kartstuff[k_squishedtimer] = TICRATE; @@ -2627,183 +2509,69 @@ void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor) K_RemoveGrowShrink(player); } - player->powers[pw_flashing] = K_GetKartFlashing(player); - player->mo->flags |= MF_NOCLIP; if (player->mo->state != &states[S_KART_SQUISH]) // Squash P_SetPlayerMobjState(player->mo, S_KART_SQUISH); - - P_PlayRinglossSound(player->mo); - P_PlayerRingBurst(player, 5); - K_PlayPainSound(player->mo); - - player->kartstuff[k_instashield] = 15; - if (cv_kartdebughuddrop.value && !modeattacking) - K_DropItems(player); - else - K_DropHnextList(player, false); - return; } -void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor) // A bit of a hack, we just throw the player up higher here and extend their spinout timer +void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source) // A bit of a hack, we just throw the player up higher here and extend their spinout timer { - UINT8 scoremultiply = 1; -#ifdef HAVE_BLUA - boolean force = false; // Used to check if Lua ShouldExplode should get us damaged reguardless of flashtics or heck knows what. - UINT8 shouldForce = LUAh_ShouldExplode(player, inflictor, source); + (void)source; - if (P_MobjWasRemoved(player->mo)) - return; // mobj was removed (in theory that shouldn't happen) - if (shouldForce == 1) - force = true; - else if (shouldForce == 2) - return; - -#else - static const boolean force = false; -#endif - - if (G_BattleGametype()) - { - if (K_IsPlayerWanted(player)) - scoremultiply = 3; - else if (player->kartstuff[k_bumper] == 1) - scoremultiply = 2; - } - - if (player->health <= 0) - return; - - if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0 // Do not check spinout, because SPB and Eggman should combo - || (G_BattleGametype() && ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1))) - { - if (!force) // ShouldDamage can bypass that, again. - { - K_DoInstashield(player); - return; - } - } - -#ifdef HAVE_BLUA - if (LUAh_PlayerExplode(player, inflictor, source)) // Same thing. Also make sure to let Instashield happen blah blah - return; -#endif - - if (source && source != player->mo && source->player) - K_PlayHitEmSound(source); - - player->mo->momz = 18*mapobjectscale*P_MobjFlip(player->mo); // please stop forgetting mobjflip checks!!!! + player->mo->momz = 18*mapobjectscale*P_MobjFlip(player->mo); // please stop forgetting mobjflip checks!!!! player->mo->momx = player->mo->momy = 0; - player->kartstuff[k_sneakertimer] = 0; - player->kartstuff[k_numsneakers] = 0; - player->kartstuff[k_driftboost] = 0; - player->kartstuff[k_ringboost] = 0; - - player->kartstuff[k_drift] = 0; - player->kartstuff[k_driftcharge] = 0; - player->trickpanel = 0; - - // This is the only part that SHOULDN'T combo :VVVVV - if (G_BattleGametype() && !(player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2))) - { - if (source && source->player && player != source->player) - { - P_AddPlayerScore(source->player, scoremultiply); - K_SpawnBattlePoints(source->player, player, scoremultiply); - source->player->kartstuff[k_wanted] -= wantedreduce; - player->kartstuff[k_wanted] -= (wantedreduce/2); - } - - if (player->kartstuff[k_bumper] > 0) - { - if (player->kartstuff[k_bumper] == 1) - { - mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! - P_SetTarget(&karmahitbox->target, player->mo); - karmahitbox->destscale = player->mo->scale; - P_SetScale(karmahitbox, player->mo->scale); - CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); - } - player->kartstuff[k_bumper]--; - if (K_IsPlayerWanted(player)) - K_CalculateBattleWanted(); - } - - if (!player->kartstuff[k_bumper]) - { - player->kartstuff[k_comebacktimer] = comebacktime; - if (player->kartstuff[k_comebackmode] == 2) - { - mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE); - S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound); - player->kartstuff[k_comebackmode] = 0; - } - } - - K_CheckBumpers(); - } - - player->kartstuff[k_spinouttype] = 1; + player->kartstuff[k_spinouttype] = KSPIN_EXPLOSION; player->kartstuff[k_spinouttimer] = (3*TICRATE/2)+2; - player->powers[pw_flashing] = K_GetKartFlashing(player); - - if (inflictor && inflictor->type == MT_SPBEXPLOSION && inflictor->extravalue1) + if (inflictor && !P_MobjWasRemoved(inflictor)) { - player->kartstuff[k_spinouttimer] = ((5*player->kartstuff[k_spinouttimer])/2)+1; - player->mo->momz *= 2; + if (inflictor->type == MT_SPBEXPLOSION && inflictor->extravalue1) + { + player->kartstuff[k_spinouttimer] = ((5*player->kartstuff[k_spinouttimer])/2)+1; + player->mo->momz *= 2; + } } if (player->mo->eflags & MFE_UNDERWATER) player->mo->momz = (117 * player->mo->momz) / 200; - if (player->mo->state != &states[S_KART_SPIN]) - P_SetPlayerMobjState(player->mo, S_KART_SPIN); - - P_PlayRinglossSound(player->mo); - P_PlayerRingBurst(player, 5); - K_PlayPainSound(player->mo); + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); if (P_IsDisplayPlayer(player)) P_StartQuake(64<kartstuff[k_instashield] = 15; K_DropItems(player); - - return; } -void K_StealBumper(player_t *player, player_t *victim, boolean force) +// This kind of wipeout happens with no rings -- doesn't remove a bumper, has no invulnerability, and is much shorter. +void K_DebtStingPlayer(player_t *player, mobj_t *source) +{ + INT32 length = TICRATE; + + if (source->player) + { + length += (4 * (source->player->kartweight - player->kartweight)); + } + + player->kartstuff[k_spinouttype] = KSPIN_STUNG; + player->kartstuff[k_spinouttimer] = length; + player->kartstuff[k_wipeoutslow] = min(length-1, wipeoutslowtime+1); + + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); +} + +void K_StealBumper(player_t *player, player_t *victim) { INT32 newbumper; angle_t newangle, diff; fixed_t newx, newy; mobj_t *newmo; - if (!G_BattleGametype()) + if (!(gametyperules & GTR_BUMPERS)) return; - if (player->health <= 0 || victim->health <= 0) - return; - - if (!force) - { - if (victim->kartstuff[k_bumper] <= 0) // || player->kartstuff[k_bumper] >= K_StartingBumperCount()+2 - return; - - if (player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0) - return; - - if (victim->powers[pw_flashing] > 0 || victim->kartstuff[k_squishedtimer] > 0 || (victim->kartstuff[k_spinouttimer] > 0 && victim->kartstuff[k_spinouttype] != 2) - || victim->kartstuff[k_invincibilitytimer] > 0 || victim->kartstuff[k_growshrinktimer] > 0 || victim->kartstuff[k_hyudorotimer] > 0) - { - K_DoInstashield(victim); - return; - } - } - if (netgame && player->kartstuff[k_bumper] <= 0) CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]); @@ -3147,10 +2915,10 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I return NULL; } -UINT8 K_DriftSparkColor(player_t *player, INT32 charge) +UINT16 K_DriftSparkColor(player_t *player, INT32 charge) { INT32 ds = K_GetKartDriftSparkValue(player); - UINT8 color = SKINCOLOR_NONE; + UINT16 color = SKINCOLOR_NONE; if (charge < 0) { @@ -3167,7 +2935,7 @@ UINT8 K_DriftSparkColor(player_t *player, INT32 charge) } else { - color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); + color = K_RainbowColor(leveltime); } } else if (charge >= ds*2) @@ -3288,8 +3056,8 @@ static void K_SpawnDriftSparks(player_t *player) } } - if ((player->kartstuff[k_drift] > 0 && player->cmd.driftturn > 0) // Inward drifts - || (player->kartstuff[k_drift] < 0 && player->cmd.driftturn < 0)) + if ((player->kartstuff[k_drift] > 0 && player->cmd.turning > 0) // Inward drifts + || (player->kartstuff[k_drift] < 0 && player->cmd.turning < 0)) { if ((player->kartstuff[k_drift] < 0 && (i & 1)) || (player->kartstuff[k_drift] > 0 && !(i & 1))) @@ -3302,8 +3070,8 @@ static void K_SpawnDriftSparks(player_t *player) size--; } } - else if ((player->kartstuff[k_drift] > 0 && player->cmd.driftturn < 0) // Outward drifts - || (player->kartstuff[k_drift] < 0 && player->cmd.driftturn > 0)) + else if ((player->kartstuff[k_drift] > 0 && player->cmd.turning < 0) // Outward drifts + || (player->kartstuff[k_drift] < 0 && player->cmd.turning > 0)) { if ((player->kartstuff[k_drift] < 0 && (i & 1)) || (player->kartstuff[k_drift] > 0 && !(i & 1))) @@ -3372,8 +3140,7 @@ static void K_SpawnAIZDust(player_t *player) void K_SpawnBoostTrail(player_t *player) { - fixed_t newx; - fixed_t newy; + fixed_t newx, newy, newz; fixed_t ground; mobj_t *flame; angle_t travelangle; @@ -3385,11 +3152,11 @@ void K_SpawnBoostTrail(player_t *player) if (!P_IsObjectOnGround(player->mo) || player->kartstuff[k_hyudorotimer] != 0 - || (G_BattleGametype() && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer])) + || ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer])) return; if (player->mo->eflags & MFE_VERTICALFLIP) - ground = player->mo->ceilingz - FixedMul(mobjinfo[MT_SNEAKERTRAIL].height, player->mo->scale); + ground = player->mo->ceilingz; else ground = player->mo->floorz; @@ -3402,14 +3169,13 @@ void K_SpawnBoostTrail(player_t *player) { newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale)); newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale)); -#ifdef ESLOPE - if (player->mo->standingslope) + newz = P_GetZAt(player->mo->standingslope, newx, newy, ground); + + if (player->mo->eflags & MFE_VERTICALFLIP) { - ground = P_GetZAt(player->mo->standingslope, newx, newy); - if (player->mo->eflags & MFE_VERTICALFLIP) - ground -= FixedMul(mobjinfo[MT_SNEAKERTRAIL].height, player->mo->scale); + newz -= FixedMul(mobjinfo[MT_SNEAKERTRAIL].height, player->mo->scale); } -#endif + flame = P_SpawnMobj(newx, newy, ground, MT_SNEAKERTRAIL); P_SetTarget(&flame->target, player->mo); @@ -3475,7 +3241,7 @@ void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent) I_Assert(!P_MobjWasRemoved(mo)); if (mo->player) - aoff = (mo->player->frameangle + ANGLE_180); + aoff = (mo->player->drawangle + ANGLE_180); else aoff = (mo->angle + ANGLE_180); @@ -3524,7 +3290,7 @@ void K_SpawnDraftDust(mobj_t *mo) { UINT8 leniency = (3*TICRATE)/4 + ((mo->player->kartweight-1) * (TICRATE/4)); - ang = mo->player->frameangle; + ang = mo->player->drawangle; if (mo->player->kartstuff[k_drift] != 0) { @@ -3598,9 +3364,9 @@ void K_DriftDustHandling(mobj_t *spawner) if (spawner->player) { - if (spawner->player->pflags & PF_SKIDDOWN) + if (spawner->player->pflags & PF_FAULT) { - anglediff = abs((signed)(spawner->angle - spawner->player->frameangle)); + anglediff = abs((signed)(spawner->angle - spawner->player->drawangle)); if (leveltime % 6 == 0) S_StartSound(spawner, sfx_screec); // repeated here because it doesn't always happen to be within the range when this is the case } @@ -3941,13 +3707,13 @@ void K_PuntMine(mobj_t *thismine, mobj_t *punter) mine->flags2 = thismine->flags2; mine->floorz = thismine->floorz; mine->ceilingz = thismine->ceilingz; - + //Since we aren't using P_KillMobj, we need to clean up the hnext reference { P_SetTarget(&thismine->target->hnext, NULL); //target is the player who owns the mine thismine->target->player->kartstuff[k_bananadrag] = 0; thismine->target->player->kartstuff[k_itemheld] = 0; - + if (--thismine->target->player->kartstuff[k_itemamount] <= 0) thismine->target->player->kartstuff[k_itemtype] = KITEM_NONE; } @@ -4060,7 +3826,7 @@ static void K_DoHyudoroSteal(player_t *player) boolean sink = P_RandomChance(FRACUNIT/64); INT32 hyu = hyudorotime; - if (G_RaceGametype()) + if (gametype == GT_RACE) hyu *= 2; // double in race for (i = 0; i < MAXPLAYERS; i++) @@ -4069,8 +3835,8 @@ static void K_DoHyudoroSteal(player_t *player) && player != &players[i] && !players[i].exiting && !players[i].spectator // Player in-game // Can steal from this player - && (G_RaceGametype() //&& players[i].kartstuff[k_position] < player->kartstuff[k_position]) - || (G_BattleGametype() && players[i].kartstuff[k_bumper] > 0)) + && (gametype == GT_RACE //&& players[i].kartstuff[k_position] < player->kartstuff[k_position]) + || ((gametyperules & GTR_BUMPERS) && players[i].kartstuff[k_bumper] > 0)) // Has an item && (players[i].kartstuff[k_itemtype] @@ -4096,7 +3862,7 @@ static void K_DoHyudoroSteal(player_t *player) player->kartstuff[k_itemheld] = 0; return; } - else if ((G_RaceGametype() && player->kartstuff[k_position] == 1) || numplayers == 0) // No-one can be stolen from? Oh well... + else if ((gametype == GT_RACE && player->kartstuff[k_position] == 1) || numplayers == 0) // No-one can be stolen from? Oh well... { player->kartstuff[k_hyudorotimer] = hyu; player->kartstuff[k_stealingtimer] = stealtime; @@ -4278,9 +4044,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound) if (mo->eflags & MFE_SPRUNG) return; -#ifdef ESLOPE mo->standingslope = NULL; -#endif mo->eflags |= MFE_SPRUNG; @@ -4334,7 +4098,7 @@ killnext: banana->z += banana->height; S_StartSound(banana, banana->info->deathsound); - P_KillMobj(banana, inflictor, source); + P_KillMobj(banana, inflictor, source, DMG_NORMAL); P_SetObjectMomZ(banana, 8*FRACUNIT, false); if (inflictor) @@ -4595,7 +4359,7 @@ void K_DropRocketSneaker(player_t *player) flingangle = -(ANG60); else flingangle = ANG60; - + S_StartSound(shoe, shoe->info->deathsound); P_SetObjectMomZ(shoe, 8*FRACUNIT, false); P_InstaThrust(shoe, R_PointToAngle2(shoe->target->x, shoe->target->y, shoe->x, shoe->y)+flingangle, 16*FRACUNIT); @@ -4618,7 +4382,7 @@ void K_DropKitchenSink(player_t *player) if (player->mo->hnext->type != MT_SINK_SHIELD) return; //so we can just call this function regardless of what is being held - P_KillMobj(player->mo->hnext, NULL, NULL); + P_KillMobj(player->mo->hnext, NULL, NULL, DMG_NORMAL); P_SetTarget(&player->mo->hnext, NULL); } @@ -4665,65 +4429,57 @@ void K_RepairOrbitChain(mobj_t *orbit) } // Simplified version of a code bit in P_MobjFloorZ -static fixed_t K_BananaSlopeZ(pslope_t *slope, fixed_t x, fixed_t y, fixed_t radius, boolean ceiling) +static fixed_t K_BananaSlopeZ(pslope_t *slope, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, boolean ceiling) { fixed_t testx, testy; - if (slope->d.x < 0) - testx = radius; - else - testx = -radius; - - if (slope->d.y < 0) - testy = radius; - else - testy = -radius; - - if ((slope->zdelta > 0) ^ !!(ceiling)) + if (slope == NULL) { - testx = -testx; - testy = -testy; + testx = x; + testy = y; + } + else + { + if (slope->d.x < 0) + testx = radius; + else + testx = -radius; + + if (slope->d.y < 0) + testy = radius; + else + testy = -radius; + + if ((slope->zdelta > 0) ^ !!(ceiling)) + { + testx = -testx; + testy = -testy; + } + + testx += x; + testy += y; } - testx += x; - testy += y; - - return P_GetZAt(slope, testx, testy); + return P_GetZAt(slope, testx, testy, z); } static void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t height, boolean flip, boolean player) { fixed_t newz; sector_t *sec; -#ifdef ESLOPE pslope_t *slope = NULL; -#endif sec = R_PointInSubsector(x, y)->sector; if (flip) { -#ifdef ESLOPE - if (sec->c_slope) - { - slope = sec->c_slope; - newz = K_BananaSlopeZ(slope, x, y, radius, true); - } - else -#endif - newz = sec->ceilingheight; + slope = sec->c_slope; + newz = K_BananaSlopeZ(slope, x, y, sec->ceilingheight, radius, true); } else { -#ifdef ESLOPE - if (sec->f_slope) - { - slope = sec->f_slope; - newz = K_BananaSlopeZ(slope, x, y, radius, false); - } - else -#endif - newz = sec->floorheight; + slope = sec->f_slope; + newz = K_BananaSlopeZ(slope, x, y, sec->floorheight, radius, true); } // Check FOFs for a better suited slope @@ -4745,19 +4501,8 @@ static void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z || (rover->flags & FF_SWIMMABLE))) continue; -#ifdef ESLOPE - if (*rover->t_slope) - top = K_BananaSlopeZ(*rover->t_slope, x, y, radius, false); - else -#endif - top = *rover->topheight; - -#ifdef ESLOPE - if (*rover->b_slope) - bottom = K_BananaSlopeZ(*rover->b_slope, x, y, radius, true); - else -#endif - bottom = *rover->bottomheight; + top = K_BananaSlopeZ(*rover->t_slope, x, y, *rover->topheight, radius, false); + bottom = K_BananaSlopeZ(*rover->b_slope, x, y, *rover->bottomheight, radius, true); if (flip) { @@ -4780,10 +4525,7 @@ static void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z if (bottom < newz && abs(d1) < abs(d2)) { newz = bottom; -#ifdef ESLOPE - if (*rover->b_slope) - slope = *rover->b_slope; -#endif + slope = *rover->b_slope; } } else @@ -4807,18 +4549,13 @@ static void K_CalculateBananaSlope(mobj_t *mobj, fixed_t x, fixed_t y, fixed_t z if (top > newz && abs(d1) < abs(d2)) { newz = top; -#ifdef ESLOPE - if (*rover->t_slope) - slope = *rover->t_slope; -#endif + slope = *rover->t_slope; } } } } -#if 0 - mobj->standingslope = slope; -#endif + //mobj->standingslope = slope; #ifdef HWRENDER mobj->modeltilt = slope; @@ -4909,8 +4646,10 @@ static void K_MoveHeldObjects(player_t *player) cur->momx = FixedMul(FINECOSINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1); cur->momy = FixedMul(FINESINE(cur->angle>>ANGLETOFINESHIFT), cur->extravalue1); cur->flags &= ~MF_NOCLIPTHING; + if (!P_TryMove(cur, player->mo->x + cur->momx, player->mo->y + cur->momy, true)) - P_SlideMove(cur, true); + P_SlideMove(cur); + if (P_IsObjectOnGround(player->mo)) { if (P_MobjFlip(cur) > 0) @@ -5018,13 +4757,11 @@ static void K_MoveHeldObjects(player_t *player) if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT) P_TeleportMove(cur, targx, targy, cur->z); -#ifdef ESLOPE if (P_IsObjectOnGround(cur)) { K_CalculateBananaSlope(cur, cur->x, cur->y, cur->z, cur->radius, cur->height, (cur->eflags & MFE_VERTICALFLIP), false); } -#endif cur = cur->hnext; } @@ -5071,7 +4808,7 @@ static void K_MoveHeldObjects(player_t *player) #if 1 { - angle_t input = player->frameangle - cur->angle; + angle_t input = player->drawangle - cur->angle; boolean invert = (input > ANGLE_180); if (invert) input = InvAngle(input); @@ -5083,7 +4820,7 @@ static void K_MoveHeldObjects(player_t *player) cur->angle = cur->angle + input; } #else - cur->angle = player->frameangle; + cur->angle = player->drawangle; #endif angoffset = ANGLE_90 + (ANGLE_180 * num); @@ -5171,7 +4908,7 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) thisang = InvAngle(thisang); // Jawz only go after the person directly ahead of you in race... sort of literally now! - if (G_RaceGametype()) + if (gametype == GT_RACE) { // Don't go for people who are behind you if (thisang > ANGLE_67h) @@ -5226,14 +4963,22 @@ player_t *K_FindJawzTarget(mobj_t *actor, player_t *source) static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) { const INT32 numsnds = 13; + + const fixed_t closedist = 160*FRACUNIT; + const fixed_t fardist = 1536*FRACUNIT; + + const UINT8 dampenval = 48; // 255 * 48 = close enough to FRACUNIT/6 + INT32 class, s, w; // engine class number + UINT8 volume = 255; - fixed_t volumedampen = 0; + fixed_t volumedampen = FRACUNIT; + INT32 targetsnd = 0; INT32 i; - s = (player->kartspeed-1)/3; - w = (player->kartweight-1)/3; + s = (player->kartspeed - 1) / 3; + w = (player->kartweight - 1) / 3; #define LOCKSTAT(stat) \ if (stat < 0) { stat = 0; } \ @@ -5242,83 +4987,119 @@ static void K_UpdateEngineSounds(player_t *player, ticcmd_t *cmd) LOCKSTAT(w); #undef LOCKSTAT - class = s+(3*w); + class = s + (3*w); - // Silence the engines if (leveltime < 8 || player->spectator) { - player->karthud[khud_enginesnd] = 0; // Reset sound number + // Silence the engines, and reset sound number while we're at it. + player->karthud[khud_enginesnd] = 0; return; } #if 0 if ((leveltime % 8) != ((player-players) % 8)) // Per-player offset, to make engines sound distinct! #else - if (leveltime % 8) // .25 seconds of wait time between engine sounds + if (leveltime % 8) #endif + { + // .25 seconds of wait time between each engine sound playback return; + } if (player->respawn.state == RESPAWNST_DROP) // Dropdashing + { + // Dropdashing targetsnd = ((cmd->buttons & BT_ACCELERATE) ? 12 : 0); - else if (K_PlayerEBrake(player) == true) // Spindashing + } + else if (K_PlayerEBrake(player) == true) + { + // Spindashing targetsnd = ((cmd->buttons & BT_DRIFT) ? 12 : 0); + } else - targetsnd = (((6*K_GetForwardMove(player))/25) + ((player->speed / mapobjectscale)/5))/2; + { + // Average out the value of forwardmove and the speed that you're moving at. + targetsnd = (((6 * cmd->forwardmove) / 25) + ((player->speed / mapobjectscale) / 5)) / 2; + } - if (targetsnd < 0) - targetsnd = 0; - if (targetsnd > 12) - targetsnd = 12; + if (targetsnd < 0) { targetsnd = 0; } + if (targetsnd > 12) { targetsnd = 12; } - if (player->karthud[khud_enginesnd] < targetsnd) - player->karthud[khud_enginesnd]++; - if (player->karthud[khud_enginesnd] > targetsnd) - player->karthud[khud_enginesnd]--; + if (player->karthud[khud_enginesnd] < targetsnd) { player->karthud[khud_enginesnd]++; } + if (player->karthud[khud_enginesnd] > targetsnd) { player->karthud[khud_enginesnd]--; } - if (player->karthud[khud_enginesnd] < 0) - player->karthud[khud_enginesnd] = 0; - if (player->karthud[khud_enginesnd] > 12) - player->karthud[khud_enginesnd] = 12; + if (player->karthud[khud_enginesnd] < 0) { player->karthud[khud_enginesnd] = 0; } + if (player->karthud[khud_enginesnd] > 12) { player->karthud[khud_enginesnd] = 12; } + + // This code calculates how many players (and thus, how many engine sounds) are within ear shot, + // and rebalances the volume of your engine sound based on how far away they are. + + // This results in multiple things: + // - When on your own, you will hear your own engine sound extremely clearly. + // - When you were alone but someone is gaining on you, yours will go quiet, and you can hear theirs more clearly. + // - When around tons of people, engine sounds will try to rebalance to not be as obnoxious. for (i = 0; i < MAXPLAYERS; i++) { UINT8 thisvol = 0; fixed_t dist; - if (!playeringame[i] || !players[i].mo || players[i].spectator || players[i].exiting) - continue; - - if (P_IsDisplayPlayer(&players[i])) + if (!playeringame[i] || !players[i].mo) { - volumedampen += FRACUNIT; // We already know what this is gonna be, let's not waste our time. + // This player doesn't exist. continue; } - dist = P_AproxDistance(P_AproxDistance(player->mo->x-players[i].mo->x, - player->mo->y-players[i].mo->y), player->mo->z-players[i].mo->z) / 2; + if (players[i].spectator) + { + // This player isn't playing an engine sound. + continue; + } + + if (P_IsDisplayPlayer(&players[i])) + { + // Don't dampen yourself! + continue; + } + + dist = P_AproxDistance( + P_AproxDistance( + player->mo->x - players[i].mo->x, + player->mo->y - players[i].mo->y), + player->mo->z - players[i].mo->z) / 2; dist = FixedDiv(dist, mapobjectscale); - if (dist > 1536< fardist) + { + // ENEMY OUT OF RANGE ! continue; - else if (dist < 160<>FRACBITS)) / (((1536<>(FRACBITS+4)); + { + thisvol = (15 * ((closedist - dist) / FRACUNIT)) / ((fardist - closedist) >> (FRACBITS+4)); + } - if (thisvol == 0) - continue; - - volumedampen += (thisvol * 257); // 255 * 257 = FRACUNIT + volumedampen += (thisvol * dampenval); } if (volumedampen > FRACUNIT) - volume = FixedDiv(volume<>FRACBITS; + { + volume = FixedDiv(volume * FRACUNIT, volumedampen) / FRACUNIT; + } - if (volume <= 0) // Might as well + if (volume <= 0) + { + // Don't need to play the sound at all. return; + } - S_StartSoundAtVolume(player->mo, (sfx_krta00 + player->karthud[khud_enginesnd]) + (class*numsnds), volume); + S_StartSoundAtVolume(player->mo, (sfx_krta00 + player->karthud[khud_enginesnd]) + (class * numsnds), volume); } static void K_UpdateInvincibilitySounds(player_t *player) @@ -5370,12 +5151,12 @@ void K_KartPlayerHUDUpdate(player_t *player) if (player->karthud[khud_tauntvoices]) player->karthud[khud_tauntvoices]--; - if (!(player->pflags & PF_SKIDDOWN)) + if (!(player->pflags & PF_FAULT)) player->karthud[khud_fault] = 0; else if (player->karthud[khud_fault] > 0 && player->karthud[khud_fault] < 2*TICRATE) player->karthud[khud_fault]++; - if (G_RaceGametype()) + if (gametype == GT_RACE) { // 0 is the fast spin animation, set at 30 tics of ring boost or higher! if (player->kartstuff[k_ringboost] >= 30) @@ -5409,7 +5190,7 @@ void K_KartPlayerHUDUpdate(player_t *player) if (player->karthud[khud_ringspblock] >= 14) // debt animation { - if ((player->kartstuff[k_rings] > 0) // Get out of 0 ring animation + if ((player->rings > 0) // Get out of 0 ring animation && (normalanim == 3 || normalanim == 10)) // on these transition frames. player->karthud[khud_ringspblock] = normalanim; else @@ -5417,7 +5198,7 @@ void K_KartPlayerHUDUpdate(player_t *player) } else // normal animation { - if ((player->kartstuff[k_rings] <= 0) // Go into 0 ring animation + if ((player->rings <= 0) // Go into 0 ring animation && (player->karthud[khud_ringspblock] == 1 || player->karthud[khud_ringspblock] == 8)) // on these transition frames. player->karthud[khud_ringspblock] = debtanim; else @@ -5428,7 +5209,7 @@ void K_KartPlayerHUDUpdate(player_t *player) player->karthud[khud_ringspblock] = (leveltime % 14); // reset to normal anim next time } - if (G_BattleGametype() && (player->exiting || player->kartstuff[k_comebacktimer])) + if ((gametyperules & GTR_BUMPERS) && (player->exiting || player->kartstuff[k_comebacktimer])) { if (player->exiting) { @@ -5452,7 +5233,7 @@ void K_KartPlayerHUDUpdate(player_t *player) if (player->karthud[khud_cardanimation] < 0) player->karthud[khud_cardanimation] = 0; } - else if (G_RaceGametype() && player->exiting) + else if (gametype == GT_RACE && player->exiting) { if (player->karthud[khud_cardanimation] < 2*TICRATE) player->karthud[khud_cardanimation]++; @@ -5623,7 +5404,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } - if (G_RaceGametype() && player->kartstuff[k_rings] <= 0) // spawn ring debt indicator + if (gametype == GT_RACE && player->rings <= 0) // spawn ring debt indicator { mobj_t *debtflag = P_SpawnMobj(player->mo->x + player->mo->momx, player->mo->y + player->mo->momy, player->mo->z + player->mo->momz + player->mo->height + (24*player->mo->scale), MT_THOK); @@ -5761,7 +5542,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->karthud[khud_timeovercam] = 0; // Specific hack because it insists on setting flashing tics during this anyway... - if (player->kartstuff[k_spinouttype] == 2) + if (( player->kartstuff[k_spinouttype] & KSPIN_IFRAMES ) == 0) { player->powers[pw_flashing] = 0; } @@ -5772,23 +5553,16 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) { player->powers[pw_flashing] = K_GetKartFlashing(player); } - else if (player->powers[pw_flashing] >= K_GetKartFlashing(player)) - { - player->powers[pw_flashing]--; - } if (player->kartstuff[k_spinouttimer]) { if ((P_IsObjectOnGround(player->mo) - || (player->kartstuff[k_spinouttype] != 0)) + || ( player->kartstuff[k_spinouttype] & KSPIN_AIRTIMER )) && (!player->kartstuff[k_sneakertimer])) { player->kartstuff[k_spinouttimer]--; if (player->kartstuff[k_wipeoutslow] > 1) player->kartstuff[k_wipeoutslow]--; - // Actually, this caused more problems than it solved. Just make sure you set type before you spinout. Which K_SpinPlayer always does. - /*if (player->kartstuff[k_spinouttimer] == 0) - player->kartstuff[k_spinouttype] = 0;*/ // Reset type } } else @@ -5806,15 +5580,15 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) } } - if (player->kartstuff[k_rings] > 20) - player->kartstuff[k_rings] = 20; - else if (player->kartstuff[k_rings] < -20) - player->kartstuff[k_rings] = -20; + if (player->rings > 20) + player->rings = 20; + else if (player->rings < -20) + player->rings = -20; if (player->kartstuff[k_ringdelay]) player->kartstuff[k_ringdelay]--; - if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_squishedtimer]) + if (P_PlayerInPain(player)) player->kartstuff[k_ringboost] = 0; else if (player->kartstuff[k_ringboost]) player->kartstuff[k_ringboost]--; @@ -5925,9 +5699,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) K_KartPlayerHUDUpdate(player); - if (G_BattleGametype() && player->kartstuff[k_bumper] > 0 - && !player->kartstuff[k_spinouttimer] && !player->kartstuff[k_squishedtimer] - && (player->respawn.state == RESPAWNST_DROP) && !player->powers[pw_flashing]) + if ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] > 0 && !P_PlayerInPain(player) && !player->powers[pw_flashing]) { player->kartstuff[k_wanted]++; if (battleovertime.enabled >= 10*TICRATE) @@ -5937,7 +5709,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) player->kartstuff[k_killfield]++; if (player->kartstuff[k_killfield] > 4*TICRATE) { - K_SpinPlayer(player, NULL, 0, NULL, false); + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL); //player->kartstuff[k_killfield] = 1; } } @@ -5956,7 +5728,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd) if (player->kartstuff[k_eggmanexplode]) { - if (player->spectator || (G_BattleGametype() && !player->kartstuff[k_bumper])) + if (player->spectator || (gametype == GT_BATTLE && !player->kartstuff[k_bumper])) player->kartstuff[k_eggmanexplode] = 0; else { @@ -6507,8 +6279,9 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) fixed_t p_speed; fixed_t weightadjust; fixed_t turnfixed = turnvalue * FRACUNIT; + fixed_t currentSpeed = 0; - if ((player->mo == NULL || P_MobjWasRemoved(player->mo))) + if (player->mo == NULL || P_MobjWasRemoved(player->mo)) { return 0; } @@ -6528,8 +6301,9 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) return 0; } - // SRB2kart - no additional angle if not moving - if ((player->speed <= 0) // Not moving + currentSpeed = R_PointToDist2(0, 0, player->mo->momx, player->mo->momy); + + if ((currentSpeed <= 0) // Not moving && ((player->cmd.buttons & BT_EBRAKEMASK) != BT_EBRAKEMASK) // not e-braking && (player->respawn.state == RESPAWNST_NONE)) // Not respawning { @@ -6537,7 +6311,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) } p_maxspeed = K_GetKartSpeed(player, false); - p_speed = min(player->speed, (p_maxspeed * 2)); + p_speed = min(FixedHypot(player->mo->momx, player->mo->momy), (p_maxspeed * 2)); weightadjust = FixedDiv((p_maxspeed * 3) - p_speed, (p_maxspeed * 3) + (player->kartweight * FRACUNIT)); if (K_PlayerUsesBotMovement(player)) @@ -6578,7 +6352,7 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue) INT32 K_GetKartDriftSparkValue(player_t *player) { - UINT8 kartspeed = (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + UINT8 kartspeed = (gametype == GT_BATTLE && player->kartstuff[k_bumper] <= 0) ? 1 : player->kartspeed; return (26*4 + kartspeed*2 + (9 - player->kartweight))*8; @@ -6692,14 +6466,14 @@ static void K_KartDrift(player_t *player, boolean onground) } // Drifting: left or right? - if ((player->cmd.driftturn > 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1 + if ((player->cmd.turning > 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1 && (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != 1) { // Starting left drift player->kartstuff[k_drift] = 1; player->kartstuff[k_driftend] = player->kartstuff[k_driftcharge] = 0; } - else if ((player->cmd.driftturn < 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1 + else if ((player->cmd.turning < 0) && player->speed > minspeed && player->kartstuff[k_jmp] == 1 && (player->kartstuff[k_drift] == 0 || player->kartstuff[k_driftend] == 1)) // && player->kartstuff[k_drift] != -1) { // Starting right drift @@ -6723,7 +6497,7 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_driftend] = 0; } - if (player->kartstuff[k_spinouttimer] > 0 || player->speed == 0) + if (P_PlayerInPain(player) || player->speed <= 0) { // Stop drifting player->kartstuff[k_drift] = player->kartstuff[k_driftcharge] = 0; @@ -6744,10 +6518,10 @@ static void K_KartDrift(player_t *player, boolean onground) if (player->kartstuff[k_drift] > 5) player->kartstuff[k_drift] = 5; - if (player->cmd.driftturn > 0) // Inward - driftadditive += abs(player->cmd.driftturn)/100; - if (player->cmd.driftturn < 0) // Outward - driftadditive -= abs(player->cmd.driftturn)/75; + if (player->cmd.turning > 0) // Inward + driftadditive += abs(player->cmd.turning)/100; + if (player->cmd.turning < 0) // Outward + driftadditive -= abs(player->cmd.turning)/75; } else if (player->kartstuff[k_drift] <= -1) // Drifting to the right { @@ -6755,10 +6529,10 @@ static void K_KartDrift(player_t *player, boolean onground) if (player->kartstuff[k_drift] < -5) player->kartstuff[k_drift] = -5; - if (player->cmd.driftturn < 0) // Inward - driftadditive += abs(player->cmd.driftturn)/100; - if (player->cmd.driftturn > 0) // Outward - driftadditive -= abs(player->cmd.driftturn)/75; + if (player->cmd.turning < 0) // Inward + driftadditive += abs(player->cmd.turning)/100; + if (player->cmd.turning > 0) // Outward + driftadditive -= abs(player->cmd.turning)/75; } // Disable drift-sparks until you're going fast enough @@ -6822,9 +6596,9 @@ static void K_KartDrift(player_t *player, boolean onground) } if ((player->kartstuff[k_handleboost] == 0) - || (!player->cmd.driftturn) + || (!player->cmd.turning) || (!player->kartstuff[k_aizdriftstrat]) - || (player->cmd.driftturn > 0) != (player->kartstuff[k_aizdriftstrat] > 0)) + || (player->cmd.turning > 0) != (player->kartstuff[k_aizdriftstrat] > 0)) { if (!player->kartstuff[k_drift]) player->kartstuff[k_aizdriftstrat] = 0; @@ -6868,7 +6642,7 @@ void K_KartUpdatePosition(player_t *player) if (!playeringame[i] || players[i].spectator || !players[i].mo) continue; - if (G_RaceGametype()) + if (gametype == GT_RACE) { if (player->exiting) // End of match standings { @@ -6887,7 +6661,7 @@ void K_KartUpdatePosition(player_t *player) } } } - else if (G_BattleGametype()) + else if (gametype == GT_BATTLE) { if (player->exiting) // End of match standings { @@ -7038,7 +6812,7 @@ static void K_KartSpindash(player_t *player) if (player->speed < 6*mapobjectscale && player->powers[pw_flashing] == 0) { - if (cmd->driftturn != 0 && leveltime % 8 == 0) + if (cmd->turning != 0 && leveltime % 8 == 0) S_StartSound(player->mo, sfx_ruburn); if ((cmd->buttons & (BT_DRIFT|BT_BRAKE)) == (BT_DRIFT|BT_BRAKE)) @@ -7056,7 +6830,7 @@ static void K_KartSpindash(player_t *player) } } else if (chargetime < -TICRATE) - K_SpinPlayer(player, NULL, 0, NULL, false); + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL); else { if (player->kartstuff[k_spindash] % 4 == 0) @@ -7074,6 +6848,81 @@ static void K_KartSpindash(player_t *player) } } +// +// K_AdjustPlayerFriction +// +void K_AdjustPlayerFriction(player_t *player) +{ + fixed_t prevfriction = player->mo->friction; + + if (P_IsObjectOnGround(player->mo) == false) + { + return; + } + + // Reduce friction after hitting a horizontal spring + if (player->kartstuff[k_tiregrease]) + { + player->mo->friction += ((FRACUNIT - prevfriction) / greasetics) * player->kartstuff[k_tiregrease]; + } + + /* + if (K_PlayerEBrake(player) == true) + { + player->mo->friction -= 1024; + } + else if (player->speed > 0 && cmd->forwardmove < 0) + { + player->mo->friction -= 512; + } + */ + + // Karma ice physics + if (gametype == GT_BATTLE && player->kartstuff[k_bumper] <= 0) + { + player->mo->friction += 1228; + } + + // Water gets ice physics too + if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) + { + player->mo->friction += 614; + } + + // Wipeout slowdown + if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow]) + { + if (player->kartstuff[k_offroad]) + player->mo->friction -= 4912; + if (player->kartstuff[k_wipeoutslow] == 1) + player->mo->friction -= 9824; + } + + // Cap between intended values + if (player->mo->friction > FRACUNIT) + player->mo->friction = FRACUNIT; + if (player->mo->friction < 0) + player->mo->friction = 0; + + // Friction was changed, so we must recalculate movefactor + if (player->mo->friction != prevfriction) + { + player->mo->movefactor = FixedDiv(ORIG_FRICTION, player->mo->friction); + + if (player->mo->movefactor < FRACUNIT) + player->mo->movefactor = 19*player->mo->movefactor - 18*FRACUNIT; + else + player->mo->movefactor = FRACUNIT; + } + + // Don't go too far above your top speed when rubberbanding + // Down here, because we do NOT want to modify movefactor + if (K_PlayerUsesBotMovement(player)) + { + player->mo->friction = K_BotFrictionRubberband(player, player->mo->friction); + } +} + // // K_MoveKartPlayer // @@ -7122,12 +6971,11 @@ void K_MoveKartPlayer(player_t *player, boolean onground) else if (cmd->buttons & BT_ATTACK) player->pflags |= PF_ATTACKDOWN; - if (player && player->mo && player->mo->health > 0 && !player->spectator && !mapreset && leveltime > introtime - && player->kartstuff[k_spinouttimer] == 0 && player->kartstuff[k_squishedtimer] == 0 && (player->respawn.state == RESPAWNST_NONE)) + if (player && player->mo && player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime) { // First, the really specific, finicky items that function without the item being directly in your item slot. // Karma item dropping - if (player->kartstuff[k_comebackmode] && !player->kartstuff[k_comebacktimer]) + if (player->kartstuff[k_comebackmode]) { if (ATTACK_IS_DOWN) { @@ -7163,7 +7011,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) // Ring boosting if (player->kartstuff[k_userings]) { - if ((player->pflags & PF_ATTACKDOWN) && !player->kartstuff[k_ringdelay] && player->kartstuff[k_rings] > 0) + if ((player->pflags & PF_ATTACKDOWN) && !player->kartstuff[k_ringdelay] && player->rings > 0) { mobj_t *ring = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_RING); P_SetMobjState(ring, S_FASTRING1); @@ -7171,7 +7019,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) ring->extravalue2 = 1; // Ring use animation flag ring->shadowscale = 0; P_SetTarget(&ring->target, player->mo); // user - player->kartstuff[k_rings]--; + player->rings--; player->kartstuff[k_ringdelay] = 3; } } @@ -7721,7 +7569,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { INT32 hyu = hyudorotime; - if (G_RaceGametype()) + if (gametype == GT_RACE) hyu *= 2; // double in race if (leveltime & 1) @@ -7743,14 +7591,14 @@ void K_MoveKartPlayer(player_t *player, boolean onground) player->mo->drawflags &= ~MFD_DONTDRAW; } - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) // dead in match? you da bomb + if (gametype == GT_BATTLE && player->kartstuff[k_bumper] <= 0) // dead in match? you da bomb { K_DropItems(player); //K_StripItems(player); K_StripOther(player); player->mo->drawflags |= MFD_SHADOW; player->powers[pw_flashing] = player->kartstuff[k_comebacktimer]; } - else if (G_RaceGametype() || player->kartstuff[k_bumper] > 0) + else if (gametype == GT_RACE || player->kartstuff[k_bumper] > 0) { player->mo->drawflags &= ~(MFD_TRANSMASK|MFD_BRIGHTMASK); } @@ -7760,12 +7608,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground) const angle_t lr = ANGLE_45; fixed_t speed = P_AproxDistance(player->mo->momx, player->mo->momy); - if (cmd->driftturn > 0) + if (cmd->turning > 0) { P_InstaThrust(player->mo, player->mo->angle + lr, speed*2); player->trickpanel = 2; } - else if (cmd->driftturn < 0) + else if (cmd->turning < 0) { P_InstaThrust(player->mo, player->mo->angle - lr, speed*2); player->trickpanel = 3; @@ -7802,7 +7650,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) { player->trickdelay--; - if ((player->kartstuff[k_throwdir] != 0 || cmd->driftturn != 0) && player->trickdelay <= 0) + if ((player->kartstuff[k_throwdir] != 0 || cmd->turning != 0) && player->trickdelay <= 0) { // Don't allow a trick until you go back to neutral player->trickdelay = 1; @@ -7811,66 +7659,6 @@ void K_MoveKartPlayer(player_t *player, boolean onground) } K_KartDrift(player, P_IsObjectOnGround(player->mo)); // Not using onground, since we don't want this affected by spring pads - - if (onground) - { - fixed_t prevfriction = player->mo->friction; - - // Reduce friction after hitting a horizontal spring - if (player->kartstuff[k_tiregrease]) - player->mo->friction += ((FRACUNIT - prevfriction) / greasetics) * player->kartstuff[k_tiregrease]; - - /* - if (K_PlayerEBrake(player) == true) - player->mo->friction -= 1024; - else if (player->speed > 0 && cmd->forwardmove < 0) - player->mo->friction -= 512; - */ - - // Karma ice physics - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) - player->mo->friction += 1228; - - if (player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) - player->mo->friction += 614; - - // Wipeout slowdown - if (player->kartstuff[k_spinouttimer] && player->kartstuff[k_wipeoutslow]) - { - if (player->kartstuff[k_offroad]) - player->mo->friction -= 4912; - if (player->kartstuff[k_wipeoutslow] == 1) - player->mo->friction -= 9824; - } - - // Cap between intended values - if (player->mo->friction > FRACUNIT) - player->mo->friction = FRACUNIT; - if (player->mo->friction < 0) - player->mo->friction = 0; - - // Friction was changed, so we must recalculate movefactor - if (player->mo->friction != prevfriction) - { - player->mo->movefactor = FixedDiv(ORIG_FRICTION, player->mo->friction); - - if (player->mo->movefactor < FRACUNIT) - player->mo->movefactor = 19*player->mo->movefactor - 18*FRACUNIT; - else - player->mo->movefactor = FRACUNIT; - - if (player->mo->movefactor < 32) - player->mo->movefactor = 32; - } - - // Don't go too far above your top speed when rubberbanding - // Down here, because we do NOT want to modify movefactor - if (K_PlayerUsesBotMovement(player)) - { - player->mo->friction = K_BotFrictionRubberband(player, player->mo->friction); - } - } - K_KartSpindash(player); // Squishing @@ -7935,7 +7723,7 @@ void K_CheckSpectateStatus(void) continue; if (leveltime > (starttime + 20*TICRATE)) // DON'T allow if the match is 20 seconds in return; - if (G_RaceGametype() && players[i].laps >= 2) // DON'T allow if the race is at 2 laps + if (gametype == GT_RACE && players[i].laps >= 2) // DON'T allow if the race is at 2 laps return; continue; } diff --git a/src/k_kart.h b/src/k_kart.h index c5710affc..2c1236368 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -40,13 +40,16 @@ void K_KartPlayerHUDUpdate(player_t *player); void K_KartPlayerThink(player_t *player, ticcmd_t *cmd); void K_KartPlayerAfterThink(player_t *player); void K_DoInstashield(player_t *player); -void K_SpinPlayer(player_t *player, mobj_t *source, INT32 type, mobj_t *inflictor, boolean trapitem); -void K_SquishPlayer(player_t *player, mobj_t *source, mobj_t *inflictor); -void K_ExplodePlayer(player_t *player, mobj_t *source, mobj_t *inflictor); -void K_StealBumper(player_t *player, player_t *victim, boolean force); +void K_BattleHitPlayer(player_t *player, player_t *victim, UINT8 points, boolean reducewanted); +void K_RemoveBumper(player_t *player, mobj_t *inflictor, mobj_t *source); +void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type); +void K_SquishPlayer(player_t *player, mobj_t *inflictor, mobj_t *source); +void K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source); +void K_DebtStingPlayer(player_t *player, mobj_t *source); +void K_StealBumper(player_t *player, player_t *victim); void K_SpawnKartExplosion(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle, boolean spawncenter, boolean ghostit, mobj_t *source); void K_SpawnMineExplosion(mobj_t *source, UINT8 color); -UINT8 K_DriftSparkColor(player_t *player, INT32 charge); +UINT16 K_DriftSparkColor(player_t *player, INT32 charge); void K_SpawnBoostTrail(player_t *player); void K_SpawnSparkleTrail(mobj_t *mo); void K_SpawnWipeoutTrail(mobj_t *mo, boolean translucent); @@ -81,8 +84,9 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower); fixed_t K_GetKartAccel(player_t *player); UINT16 K_GetKartFlashing(player_t *player); SINT8 K_GetForwardMove(player_t *player); -fixed_t K_3dKartMovement(player_t *player, boolean onground); +fixed_t K_3dKartMovement(player_t *player); boolean K_PlayerEBrake(player_t *player); +void K_AdjustPlayerFriction(player_t *player); void K_MoveKartPlayer(player_t *player, boolean onground); void K_CheckSpectateStatus(void); diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index eac664408..ac2d009bc 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -35,11 +35,11 @@ SINT8 K_UsingPowerLevels(void) return PWRLV_DISABLED; } - if (G_RaceGametype()) + if (gametype == GT_RACE) { pt = PWRLV_RACE; } - else if (G_BattleGametype()) + else if (gametype == GT_BATTLE) { pt = PWRLV_BATTLE; } @@ -110,9 +110,9 @@ INT16 K_CalculatePowerLevelAvg(void) return 0; // No average. } - if (G_RaceGametype()) + if ((gametyperules & GTR_CIRCUIT)) t = PWRLV_RACE; - else if (G_BattleGametype()) + else if ((gametyperules & GTR_BUMPERS)) t = PWRLV_BATTLE; if (t == PWRLV_DISABLED) @@ -304,9 +304,9 @@ void K_PlayerForfeit(UINT8 playernum, boolean pointloss) if (p < 2) // no players return; - if (G_RaceGametype()) + if ((gametyperules & GTR_CIRCUIT)) powertype = PWRLV_RACE; - else if (G_BattleGametype()) + else if ((gametyperules & GTR_BUMPERS)) powertype = PWRLV_BATTLE; if (powertype == PWRLV_DISABLED) // No power type?! @@ -349,8 +349,8 @@ void K_PlayerForfeit(UINT8 playernum, boolean pointloss) if (playernum == consoleplayer) { vspowerlevel[powertype] = clientpowerlevels[playernum][powertype]; - if (M_UpdateUnlockablesAndExtraEmblems(true)) + if (M_UpdateUnlockablesAndExtraEmblems()) S_StartSound(NULL, sfx_ncitem); - G_SaveGameData(true); // save your punishment! + G_SaveGameData(); // save your punishment! } } diff --git a/src/k_respawn.c b/src/k_respawn.c index d1d47638e..875e05055 100644 --- a/src/k_respawn.c +++ b/src/k_respawn.c @@ -81,7 +81,7 @@ static void K_RespawnAtWaypoint(player_t *player, waypoint_t *waypoint) player->respawn.pointx = waypoint->mobj->x; player->respawn.pointy = waypoint->mobj->y; player->respawn.pointz = waypoint->mobj->z; - player->respawn.flip = (waypoint->mobj->flags2 & MF2_OBJECTFLIP) ? true : false; // K_RespawnOffset wants a boolean! + player->respawn.flip = (waypoint->mobj->flags2 & MF2_OBJECTFLIP) ? true : false; // K_RespawnOffset wants a boolean! player->respawn.pointz += K_RespawnOffset(player, player->respawn.flip); } @@ -97,7 +97,8 @@ void K_DoIngameRespawn(player_t *player) return; } - if (player->respawn.state != RESPAWNST_NONE) + if (player->respawn.state != RESPAWNST_NONE && + ( player->pflags & PF_FAULT ) == 0) { return; } @@ -110,16 +111,15 @@ void K_DoIngameRespawn(player_t *player) if (leveltime < starttime) // FAULT { player->powers[pw_nocontrol] = (starttime - leveltime) + 50; - player->pflags |= PF_SKIDDOWN; // cheeky pflag reuse + player->pflags |= PF_FAULT; S_StartSound(player->mo, sfx_s3k83); player->karthud[khud_fault] = 1; } player->kartstuff[k_ringboost] = 0; player->kartstuff[k_driftboost] = 0; - player->kartstuff[k_drift] = 0; - player->kartstuff[k_driftcharge] = 0; - player->trickpanel = 0; + + P_ResetPlayer(player); // Set up respawn position if invalid if (player->respawn.wp != NULL && leveltime >= starttime) @@ -134,11 +134,11 @@ void K_DoIngameRespawn(player_t *player) mapthing_t *beststart = NULL; UINT8 numstarts = 0; - if (G_RaceGametype()) + if (gametype == GT_RACE) { numstarts = numcoopstarts; } - else if (G_BattleGametype()) + else if (gametype == GT_BATTLE) { numstarts = numdmstarts; } @@ -152,11 +152,11 @@ void K_DoIngameRespawn(player_t *player) UINT32 dist = UINT32_MAX; mapthing_t *checkstart = NULL; - if (G_RaceGametype()) + if (gametype == GT_RACE) { checkstart = playerstarts[i]; } - else if (G_BattleGametype()) + else if (gametype == GT_BATTLE) { checkstart = deathmatchstarts[i]; } @@ -187,11 +187,13 @@ void K_DoIngameRespawn(player_t *player) else { sector_t *s; - fixed_t z = (beststart->options >> ZSHIFT) * FRACUNIT; + fixed_t z = beststart->z * FRACUNIT; player->respawn.pointx = beststart->x << FRACBITS; player->respawn.pointy = beststart->y << FRACBITS; + player->mo->angle = ( beststart->angle * ANG1 ); + s = R_PointInSubsector(beststart->x << FRACBITS, beststart->y << FRACBITS)->sector; player->respawn.flip = (beststart->options & MTF_OBJECTFLIP); @@ -233,17 +235,11 @@ void K_DoIngameRespawn(player_t *player) } /*-------------------------------------------------- - static size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint) + size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint) - Returns the index for the next respawn waypoint. - - Input Arguments:- - waypoint - Waypoint to look after. - - Return:- - An table index for waypoint_t -> nextwaypoints. + See header file for description. --------------------------------------------------*/ -static size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint) +size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint) { size_t i = 0U; size_t newwaypoint = SIZE_MAX; @@ -281,7 +277,7 @@ static void K_MovePlayerToRespawnPoint(player_t *player) const fixed_t realstepamt = (64 * mapobjectscale); fixed_t stepamt = realstepamt; - vertex_t dest, step, laser; + vector3_t dest, step, laser; angle_t stepha, stepva; fixed_t dist, fulldist; @@ -334,7 +330,7 @@ static void K_MovePlayerToRespawnPoint(player_t *player) } // Set angle, regardless of if we're done or not - player->frameangle = R_PointToAngle2( + player->drawangle = R_PointToAngle2( player->mo->x, player->mo->y, dest.x, dest.y ); @@ -383,7 +379,7 @@ static void K_MovePlayerToRespawnPoint(player_t *player) ); // Move toward the respawn point - player->frameangle = stepha; + player->drawangle = stepha; step.x = FixedMul(FixedMul(FINECOSINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT)); step.y = FixedMul(FixedMul(FINESINE(stepha >> ANGLETOFINESHIFT), stepamt), FINECOSINE(stepva >> ANGLETOFINESHIFT)); @@ -563,7 +559,7 @@ static void K_DropDashWait(player_t *player) for (i = 0; i < ns; i++) { const angle_t newangle = sidediff * i; - vertex_t spawn; + vector3_t spawn; mobj_t *laser; spawn.x = player->mo->x + P_ReturnThrustX(player->mo, newangle, 31 * player->mo->scale); @@ -674,37 +670,6 @@ static void K_HandleDropDash(player_t *player) //P_PlayRinglossSound(player->mo); P_PlayerRingBurst(player, 3); - if (G_BattleGametype()) - { - if (player->kartstuff[k_bumper] > 0) - { - if (player->kartstuff[k_bumper] == 1) - { - mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! - P_SetTarget(&karmahitbox->target, player->mo); - karmahitbox->destscale = player->mo->scale; - P_SetScale(karmahitbox, player->mo->scale); - CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); - } - player->kartstuff[k_bumper]--; - if (K_IsPlayerWanted(player)) - K_CalculateBattleWanted(); - } - - if (!player->kartstuff[k_bumper]) - { - player->kartstuff[k_comebacktimer] = comebacktime; - if (player->kartstuff[k_comebackmode] == 2) - { - mobj_t *poof = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_EXPLODE); - S_StartSound(poof, mobjinfo[MT_KARMAHITBOX].seesound); - player->kartstuff[k_comebackmode] = 0; - } - } - - K_CheckBumpers(); - } - player->respawn.state = RESPAWNST_NONE; } } diff --git a/src/k_respawn.h b/src/k_respawn.h index 81b5cea8d..d5a946560 100644 --- a/src/k_respawn.h +++ b/src/k_respawn.h @@ -54,6 +54,21 @@ fixed_t K_RespawnOffset(player_t *player, boolean flip); void K_DoIngameRespawn(player_t *player); +/*-------------------------------------------------- + size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint); + + Returns the index for the next respawn waypoint. + + Input Arguments:- + waypoint - Waypoint to look past. + + Return:- + An table index for waypoint_t -> nextwaypoints. +--------------------------------------------------*/ + +size_t K_NextRespawnWaypointIndex(waypoint_t *waypoint); + + /*-------------------------------------------------- void K_RespawnChecker(player_t *player); diff --git a/src/k_waypoint.c b/src/k_waypoint.c index 7d119498a..b9581e871 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -19,6 +19,7 @@ #include "r_local.h" #include "z_zone.h" #include "g_game.h" +#include "p_slopes.h" // The number of sparkles per waypoint connection in the waypoint visualisation static const UINT32 SPARKLES_PER_CONNECTION = 16U; @@ -425,10 +426,10 @@ static void K_DebugWaypointsSpawnLine(waypoint_t *const waypoint1, waypoint_t *c fixed_t x, y, z; UINT32 waypointdist; INT32 n; - skincolors_t linkcolour = SKINCOLOR_GREEN; + UINT16 linkcolour = SKINCOLOR_GREEN; // This array is used to choose which colour should be on this connection - const skincolors_t linkcolours[] = { + const UINT16 linkcolours[] = { SKINCOLOR_RED, SKINCOLOR_BLUE, SKINCOLOR_ORANGE, @@ -437,7 +438,7 @@ static void K_DebugWaypointsSpawnLine(waypoint_t *const waypoint1, waypoint_t *c SKINCOLOR_CYAN, SKINCOLOR_WHITE, }; - const size_t linkcolourssize = sizeof(linkcolours) / sizeof(skincolors_t); + const size_t linkcolourssize = sizeof(linkcolours) / sizeof(UINT16); // Error conditions I_Assert(waypoint1 != NULL); @@ -1908,14 +1909,14 @@ static boolean K_RaiseWaypoint( ){ if (descending) { - z = P_GetFOFBottomZAt(rover, x, y); + z = P_GetZAt(*rover->b_slope, x, y, *rover->bottomheight); if (z > riser->z && z < sort) sort = z; } else { - z = P_GetFOFTopZAt(rover, x, y); + z = P_GetZAt(*rover->t_slope, x, y, *rover->topheight); if (z < riser->z && z > sort) sort = z; @@ -1999,23 +2000,23 @@ void K_AdjustWaypointsParameters (void) } for ( - th = thinkercap.next; - th != &thinkercap; - th = th->next + th = thlist[THINK_MOBJ].next; + th != &thlist[THINK_MOBJ]; + th = th->next ){ - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - anchor = (const mobj_t *)th; + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; - if (anchor->type == MT_WAYPOINT_ANCHOR) - { - for ( - waypointmobj = waypointcap; - waypointmobj; - waypointmobj = waypointmobj->tracer - ){ - K_AnchorWaypointRadius(waypointmobj, anchor); - } + anchor = (const mobj_t *)th; + + if (anchor->type == MT_WAYPOINT_ANCHOR) + { + for ( + waypointmobj = waypointcap; + waypointmobj; + waypointmobj = waypointmobj->tracer + ){ + K_AnchorWaypointRadius(waypointmobj, anchor); } } } diff --git a/src/keys.h b/src/keys.h index cf3a0d060..6cdd7956c 100644 --- a/src/keys.h +++ b/src/keys.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/locale/en.po b/src/locale/en.po index ce4510802..30ebe4368 100644 --- a/src/locale/en.po +++ b/src/locale/en.po @@ -1377,11 +1377,6 @@ msgstr "" msgid "modifiedgame is false, you can unlock secrets\n" msgstr "" -#: d_netcmd.c:4599 -#, c-format -msgid "Valid skin numbers are 0 to %d (-1 disables)\n" -msgstr "" - #: d_netcmd.c:4617 d_netcmd.c:4629 msgid "You may not change your name when chat is muted.\n" msgstr "" @@ -2073,7 +2068,7 @@ msgstr "" #: m_cheat.c:292 #, c-format -msgid "Sissy Mode %s\n" +msgid "Cheese Mode %s\n" msgstr "" #: m_cheat.c:315 m_cheat.c:349 m_cheat.c:514 m_cheat.c:538 m_cheat.c:557 @@ -3830,7 +3825,7 @@ msgid "Music lump is not MID music format\n" msgstr "" #: win32/win_snd.c:2128 -msgid "I_RegisterSong: StreamBufferSetup FAILED" +msgid "I_LoadSong: StreamBufferSetup FAILED" msgstr "" #: win32/win_sys.c:892 diff --git a/src/locale/srb2.pot b/src/locale/srb2.pot index c61cbcc97..960c36dbe 100644 --- a/src/locale/srb2.pot +++ b/src/locale/srb2.pot @@ -1362,11 +1362,6 @@ msgstr "" msgid "No CHEAT-marked variables are changed -- Cheats are disabled.\n" msgstr "" -#: d_netcmd.c:4439 -#, c-format -msgid "Valid skin numbers are 0 to %d (-1 disables)\n" -msgstr "" - #: d_netcmd.c:4457 d_netcmd.c:4469 msgid "You may not change your name when chat is muted.\n" msgstr "" @@ -2150,7 +2145,7 @@ msgstr "" #: m_cheat.c:294 #, c-format -msgid "Sissy Mode %s\n" +msgid "Cheese Mode %s\n" msgstr "" #: m_cheat.c:314 @@ -4026,7 +4021,7 @@ msgid "Music lump is not MID music format\n" msgstr "" #: win32/win_snd.c:2126 -msgid "I_RegisterSong: StreamBufferSetup FAILED" +msgid "I_LoadSong: StreamBufferSetup FAILED" msgstr "" #: win32/win_sys.c:894 diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 9916ceab8..0ee1a7a02 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,18 +11,19 @@ /// \brief basic functions for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA +#include "fastcmp.h" #include "p_local.h" #include "p_setup.h" // So we can have P_SetupLevelSky -#ifdef ESLOPE -#include "p_slopes.h" // P_GetZAt -#endif +#include "p_slopes.h" // P_GetSlopeZAt #include "z_zone.h" #include "r_main.h" -#include "r_things.h" +#include "r_draw.h" +#include "r_things.h" // R_Frame2Char etc #include "m_random.h" #include "s_sound.h" #include "g_game.h" +#include "m_menu.h" +#include "y_inter.h" #include "hu_stuff.h" // HU_AddChatText #include "console.h" #include "k_kart.h" // SRB2Kart @@ -30,14 +31,20 @@ #include "k_color.h" #include "k_hud.h" #include "d_netcmd.h" // IsPlayerAdmin +#include "m_menu.h" // Player Setup menu color stuff + +// SRB2Kart +#include "p_spec.h" // P_StartQuake #include "lua_script.h" #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#include "lua_hook.h" // hook_cmd_running +#include "lua_hook.h" // hook_cmd_running errors -#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); else if (hook_cmd_running) return luaL_error(L, "CMD Building code should not call this function!"); -// Yes technically cmd hook isn't a hud but whatever, this avoids having 2 defines for virtually the same thing. +#define NOHUD if (hud_running)\ +return luaL_error(L, "HUD rendering code should not call this function!");\ +else if (hook_cmd_running)\ +return luaL_error(L, "CMD building code should not call this function!"); boolean luaL_checkboolean(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TBOOLEAN); @@ -141,12 +148,109 @@ static int lib_chatprintf(lua_State *L) return 0; } -static int lib_evalMath(lua_State *L) +static const struct { + const char *meta; + const char *utype; +} meta2utype[] = { + {META_STATE, "state_t"}, + {META_MOBJINFO, "mobjinfo_t"}, + {META_SFXINFO, "sfxinfo_t"}, + {META_SKINCOLOR, "skincolor_t"}, + {META_COLORRAMP, "skincolor_t.ramp"}, + {META_SPRITEINFO, "spriteinfo_t"}, + {META_PIVOTLIST, "spriteframepivot_t[]"}, + {META_FRAMEPIVOT, "spriteframepivot_t"}, + + {META_MOBJ, "mobj_t"}, + {META_MAPTHING, "mapthing_t"}, + + {META_PLAYER, "player_t"}, + {META_TICCMD, "ticcmd_t"}, + {META_SKIN, "skin_t"}, + {META_POWERS, "player_t.powers"}, + {META_SOUNDSID, "skin_t.soundsid"}, + + {META_VERTEX, "vertex_t"}, + {META_LINE, "line_t"}, + {META_SIDE, "side_t"}, + {META_SUBSECTOR, "subsector_t"}, + {META_SECTOR, "sector_t"}, + {META_FFLOOR, "ffloor_t"}, +#ifdef HAVE_LUA_SEGS + {META_SEG, "seg_t"}, + {META_NODE, "node_t"}, +#endif + {META_SLOPE, "slope_t"}, + {META_VECTOR2, "vector2_t"}, + {META_VECTOR3, "vector3_t"}, + {META_MAPHEADER, "mapheader_t"}, + + {META_POLYOBJ, "polyobj_t"}, + + {META_CVAR, "consvar_t"}, + + {META_SECTORLINES, "sector_t.lines"}, + {META_SIDENUM, "line_t.sidenum"}, + {META_LINEARGS, "line_t.args"}, + {META_LINESTRINGARGS, "line_t.stringargs"}, + + {META_THINGARGS, "mapthing.args"}, + {META_THINGSTRINGARGS, "mapthing.stringargs"}, +#ifdef HAVE_LUA_SEGS + {META_NODEBBOX, "node_t.bbox"}, + {META_NODECHILDREN, "node_t.children"}, +#endif + + {META_BBOX, "bbox"}, + + {META_HUDINFO, "hudinfo_t"}, + {META_PATCH, "patch_t"}, + {META_COLORMAP, "colormap"}, + {META_CAMERA, "camera_t"}, + + {META_ACTION, "action"}, + + {META_LUABANKS, "luabanks[]"}, + {NULL, NULL} +}; + +// goes through the above list and returns the utype string for the userdata type +// returns "unknown" instead if we couldn't find the right userdata type +static const char *GetUserdataUType(lua_State *L) { - const char *word = luaL_checkstring(L, 1); - LUA_Deprecated(L, "EvalMath(string)", "_G[string]"); - lua_pushinteger(L, LUA_EvalMath(word)); - return 1; + UINT8 i; + lua_getmetatable(L, -1); + + for (i = 0; meta2utype[i].meta; i++) + { + luaL_getmetatable(L, meta2utype[i].meta); + if (lua_rawequal(L, -1, -2)) + { + lua_pop(L, 2); + return meta2utype[i].utype; + } + lua_pop(L, 1); + } + + lua_pop(L, 1); + return "unknown"; +} + +// Return a string representing the type of userdata the given var is +// e.g. players[0] -> "player_t" +// or players[0].powers -> "player_t.powers" +static int lib_userdataType(lua_State *L) +{ + int type; + lua_settop(L, 1); // pop everything except arg 1 (in case somebody decided to add more) + type = lua_type(L, 1); + if (type == LUA_TLIGHTUSERDATA || type == LUA_TUSERDATA) + { + lua_pushstring(L, GetUserdataUType(L)); + return 1; + } + else + return luaL_typerror(L, 1, "userdata"); } static int lib_isPlayerAdmin(lua_State *L) @@ -159,6 +263,55 @@ static int lib_isPlayerAdmin(lua_State *L) return 1; } +static int lib_reserveLuabanks(lua_State *L) +{ + static boolean reserved = false; + if (!lua_lumploading) + return luaL_error(L, "luabanks[] cannot be reserved from within a hook or coroutine!"); + if (reserved) + return luaL_error(L, "luabanks[] has already been reserved! Only one savedata-enabled mod at a time may use this feature."); + reserved = true; + LUA_PushUserdata(L, &luabanks, META_LUABANKS); + return 1; +} + +// M_MENU +////////////// + +static int lib_pMoveColorBefore(lua_State *L) +{ + UINT16 color = (UINT16)luaL_checkinteger(L, 1); + UINT16 targ = (UINT16)luaL_checkinteger(L, 2); + + NOHUD + M_MoveColorBefore(color, targ); + return 0; +} + +static int lib_pMoveColorAfter(lua_State *L) +{ + UINT16 color = (UINT16)luaL_checkinteger(L, 1); + UINT16 targ = (UINT16)luaL_checkinteger(L, 2); + + NOHUD + M_MoveColorAfter(color, targ); + return 0; +} + +static int lib_pGetColorBefore(lua_State *L) +{ + UINT16 color = (UINT16)luaL_checkinteger(L, 1); + lua_pushinteger(L, M_GetColorBefore(color)); + return 1; +} + +static int lib_pGetColorAfter(lua_State *L) +{ + UINT16 color = (UINT16)luaL_checkinteger(L, 1); + lua_pushinteger(L, M_GetColorAfter(color)); + return 1; +} + // M_RANDOM ////////////// @@ -208,16 +361,7 @@ static int lib_pRandomRange(lua_State *L) return 1; } -// Deprecated, macros, etc. -static int lib_pRandom(lua_State *L) -{ - NOHUD - LUA_Deprecated(L, "P_Random", "P_RandomByte"); - lua_pushinteger(L, P_RandomByte()); - demo_writerng = 2; - return 1; -} - +// Macros. static int lib_pSignedRandom(lua_State *L) { NOHUD @@ -286,6 +430,41 @@ static int lib_pClosestPointOnLine(lua_State *L) return 2; } +static int lib_pPointOnLineSide(lua_State *L) +{ + int n = lua_gettop(L); + fixed_t x = luaL_checkfixed(L, 1); + fixed_t y = luaL_checkfixed(L, 2); + //HUDSAFE + if (lua_isuserdata(L, 3)) // use a real linedef to get our points + { + line_t *line = *((line_t **)luaL_checkudata(L, 3, META_LINE)); + if (!line) + return LUA_ErrInvalid(L, "line_t"); + lua_pushinteger(L, P_PointOnLineSide(x, y, line)); + } + else // use custom coordinates of our own! + { + vertex_t v1, v2; // fake vertexes + line_t junk; // fake linedef + + if (n < 6) + return luaL_error(L, "arguments 3 to 6 not all given (expected 4 fixed-point integers)"); + + v1.x = luaL_checkfixed(L, 3); + v1.y = luaL_checkfixed(L, 4); + v2.x = luaL_checkfixed(L, 5); + v2.y = luaL_checkfixed(L, 6); + + junk.v1 = &v1; + junk.v2 = &v2; + junk.dx = v2.x - v1.x; + junk.dy = v2.y - v1.y; + lua_pushinteger(L, P_PointOnLineSide(x, y, &junk)); + } + return 1; +} + // P_ENEMY ///////////// @@ -293,6 +472,7 @@ static int lib_pCheckMeleeRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckMeleeRange(actor)); @@ -303,6 +483,7 @@ static int lib_pJetbCheckMeleeRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_JetbCheckMeleeRange(actor)); @@ -313,6 +494,7 @@ static int lib_pFaceStabCheckMeleeRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_FaceStabCheckMeleeRange(actor)); @@ -323,6 +505,7 @@ static int lib_pSkimCheckMeleeRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SkimCheckMeleeRange(actor)); @@ -333,6 +516,7 @@ static int lib_pCheckMissileRange(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckMissileRange(actor)); @@ -343,6 +527,7 @@ static int lib_pNewChaseDir(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); P_NewChaseDir(actor); @@ -356,6 +541,7 @@ static int lib_pLookForPlayers(lua_State *L) boolean allaround = lua_optboolean(L, 3); boolean tracer = lua_optboolean(L, 4); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_LookForPlayers(actor, allaround, tracer, dist)); @@ -372,16 +558,35 @@ static int lib_pSpawnMobj(lua_State *L) fixed_t z = luaL_checkfixed(L, 3); mobjtype_t type = luaL_checkinteger(L, 4); NOHUD + INLEVEL if (type >= NUMMOBJTYPES) return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); LUA_PushUserdata(L, P_SpawnMobj(x, y, z, type), META_MOBJ); return 1; } +static int lib_pSpawnMobjFromMobj(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + fixed_t x = luaL_checkfixed(L, 2); + fixed_t y = luaL_checkfixed(L, 3); + fixed_t z = luaL_checkfixed(L, 4); + mobjtype_t type = luaL_checkinteger(L, 5); + NOHUD + INLEVEL + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + if (type >= NUMMOBJTYPES) + return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); + LUA_PushUserdata(L, P_SpawnMobjFromMobj(actor, x, y, z, type), META_MOBJ); + return 1; +} + static int lib_pRemoveMobj(lua_State *L) { mobj_t *th = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!th) return LUA_ErrInvalid(L, "mobj_t"); if (th->player) @@ -390,12 +595,52 @@ static int lib_pRemoveMobj(lua_State *L) return 0; } +// P_IsValidSprite2 technically doesn't exist, and probably never should... but too much would need to be exposed to allow this to be checked by other methods. + +static int lib_pIsValidSprite2(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + UINT8 spr2 = (UINT8)luaL_checkinteger(L, 2); + //HUDSAFE + INLEVEL + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, (mobj->skin && (((skin_t *)mobj->skin)->sprites[spr2].numframes))); + return 1; +} + +// P_SpawnLockOn doesn't exist either, but we want to expose making a local mobj without encouraging hacks. + +static int lib_pSpawnLockOn(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *lockon = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + statenum_t state = luaL_checkinteger(L, 3); + NOHUD + INLEVEL + if (!lockon) + return LUA_ErrInvalid(L, "mobj_t"); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (state >= NUMSTATES) + return luaL_error(L, "state %d out of range (0 - %d)", state, NUMSTATES-1); + if (P_IsLocalPlayer(player)) // Only display it on your own view. + { + mobj_t *visual = P_SpawnMobj(lockon->x, lockon->y, lockon->z, MT_LOCKON); // positioning, flip handled in P_SceneryThinker + P_SetTarget(&visual->target, lockon); + visual->drawflags |= MFD_DONTDRAW; + P_SetMobjStateNF(visual, state); + } + return 0; +} + static int lib_pSpawnMissile(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *dest = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); mobjtype_t type = luaL_checkinteger(L, 3); NOHUD + INLEVEL if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -413,6 +658,7 @@ static int lib_pSpawnXYZMissile(lua_State *L) fixed_t y = luaL_checkfixed(L, 5); fixed_t z = luaL_checkfixed(L, 6); NOHUD + INLEVEL if (!source || !dest) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -432,6 +678,7 @@ static int lib_pSpawnPointMissile(lua_State *L) fixed_t y = luaL_checkfixed(L, 7); fixed_t z = luaL_checkfixed(L, 8); NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -449,6 +696,7 @@ static int lib_pSpawnAlteredDirectionMissile(lua_State *L) fixed_t z = luaL_checkfixed(L, 5); INT32 shiftingAngle = (INT32)luaL_checkinteger(L, 5); NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -462,6 +710,7 @@ static int lib_pColorTeamMissile(lua_State *L) mobj_t *missile = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); player_t *source = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); NOHUD + INLEVEL if (!missile) return LUA_ErrInvalid(L, "mobj_t"); if (!source) @@ -478,6 +727,7 @@ static int lib_pSPMAngle(lua_State *L) UINT8 allowaim = (UINT8)luaL_optinteger(L, 4, 0); UINT32 flags2 = (UINT32)luaL_optinteger(L, 5, 0); NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -492,6 +742,7 @@ static int lib_pSpawnPlayerMissile(lua_State *L) mobjtype_t type = luaL_checkinteger(L, 2); UINT32 flags2 = (UINT32)luaL_optinteger(L, 3, 0); NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (type >= NUMMOBJTYPES) @@ -504,6 +755,7 @@ static int lib_pMobjFlip(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); lua_pushinteger(L, P_MobjFlip(mobj)); @@ -514,28 +766,20 @@ static int lib_pGetMobjGravity(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); lua_pushfixed(L, P_GetMobjGravity(mobj)); return 1; } -static int lib_pWeaponOrPanel(lua_State *L) -{ - mobjtype_t type = luaL_checkinteger(L, 1); - //HUDSAFE - if (type >= NUMMOBJTYPES) - return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); - lua_pushboolean(L, P_WeaponOrPanel(type)); - return 1; -} - static int lib_pFlashPal(lua_State *L) { player_t *pl = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); UINT16 type = (UINT16)luaL_checkinteger(L, 2); UINT16 duration = (UINT16)luaL_checkinteger(L, 3); NOHUD + INLEVEL if (!pl) return LUA_ErrInvalid(L, "player_t"); P_FlashPal(pl, type, duration); @@ -546,6 +790,7 @@ static int lib_pGetClosestAxis(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); LUA_PushUserdata(L, P_GetClosestAxis(source), META_MOBJ); @@ -564,6 +809,7 @@ static int lib_pSpawnParaloop(lua_State *L) statenum_t nstate = luaL_optinteger(L, 8, S_NULL); boolean spawncenter = lua_optboolean(L, 9); NOHUD + INLEVEL if (type >= NUMMOBJTYPES) return luaL_error(L, "mobj type %d out of range (0 - %d)", type, NUMMOBJTYPES-1); if (nstate >= NUMSTATES) @@ -577,6 +823,7 @@ static int lib_pBossTargetPlayer(lua_State *L) mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); boolean closest = lua_optboolean(L, 2); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_BossTargetPlayer(actor, closest)); @@ -587,6 +834,7 @@ static int lib_pSupermanLook4Players(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_SupermanLook4Players(actor)); @@ -598,6 +846,7 @@ static int lib_pSetScale(lua_State *L) mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t newscale = luaL_checkfixed(L, 2); NOHUD + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); if (newscale < FRACUNIT/100) @@ -611,6 +860,7 @@ static int lib_pInsideANonSolidFFloor(lua_State *L) mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); //HUDSAFE + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); if (!rover) @@ -623,6 +873,7 @@ static int lib_pCheckDeathPitCollide(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckDeathPitCollide(mo)); @@ -631,45 +882,137 @@ static int lib_pCheckDeathPitCollide(lua_State *L) static int lib_pCheckSolidLava(lua_State *L) { - mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); //HUDSAFE - if (!mo) - return LUA_ErrInvalid(L, "mobj_t"); + INLEVEL if (!rover) return LUA_ErrInvalid(L, "ffloor_t"); - lua_pushboolean(L, P_CheckSolidLava(mo, rover)); + lua_pushboolean(L, P_CheckSolidLava(rover)); return 1; } +static int lib_pMaceRotate(lua_State *L) +{ + mobj_t *center = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + INT32 baserot = luaL_checkinteger(L, 2); + INT32 baseprevrot = luaL_checkinteger(L, 3); + NOHUD + INLEVEL + if (!center) + return LUA_ErrInvalid(L, "mobj_t"); + P_MaceRotate(center, baserot, baseprevrot); + return 0; +} + +static int lib_pRailThinker(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; + NOHUD + INLEVEL + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, P_RailThinker(mobj)); + P_SetTarget(&tmthing, ptmthing); + return 1; +} + +static int lib_pXYMovement(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; + NOHUD + INLEVEL + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + P_XYMovement(actor); + P_SetTarget(&tmthing, ptmthing); + return 0; +} + +static int lib_pRingXYMovement(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; + NOHUD + INLEVEL + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + P_RingXYMovement(actor); + P_SetTarget(&tmthing, ptmthing); + return 0; +} + +static int lib_pSceneryXYMovement(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *ptmthing = tmthing; + NOHUD + INLEVEL + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + P_SceneryXYMovement(actor); + P_SetTarget(&tmthing, ptmthing); + return 0; +} + +static int lib_pZMovement(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, P_ZMovement(actor)); + P_CheckPosition(actor, actor->x, actor->y); + return 1; +} + +static int lib_pRingZMovement(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + P_RingZMovement(actor); + P_CheckPosition(actor, actor->x, actor->y); + return 0; +} + +static int lib_pSceneryZMovement(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, P_SceneryZMovement(actor)); + P_CheckPosition(actor, actor->x, actor->y); + return 1; +} + +static int lib_pPlayerZMovement(lua_State *L) +{ + mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + NOHUD + INLEVEL + if (!actor) + return LUA_ErrInvalid(L, "mobj_t"); + P_PlayerZMovement(actor); + P_CheckPosition(actor, actor->x, actor->y); + return 0; +} + // P_USER //////////// -static int lib_pGetPlayerHeight(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - //HUDSAFE - if (!player) - return LUA_ErrInvalid(L, "player_t"); - lua_pushfixed(L, P_GetPlayerHeight(player)); - return 1; -} - -static int lib_pGetPlayerSpinHeight(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - //HUDSAFE - if (!player) - return LUA_ErrInvalid(L, "player_t"); - lua_pushfixed(L, P_GetPlayerSpinHeight(player)); - return 1; -} - static int lib_pAddPlayerScore(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); UINT32 amount = (UINT32)luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_AddPlayerScore(player, amount); @@ -680,41 +1023,40 @@ static int lib_pPlayerInPain(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushboolean(L, P_PlayerInPain(player)); return 1; } -static int lib_pDoPlayerPain(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - mobj_t *source = NULL, *inflictor = NULL; - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) - source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) - inflictor = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); - P_DoPlayerPain(player, source, inflictor); - return 0; -} - static int lib_pResetPlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_ResetPlayer(player); return 0; } +static int lib_pPlayerFullbright(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + lua_pushboolean(L, P_PlayerFullbright(player)); + return 1; +} + + static int lib_pIsObjectInGoop(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_IsObjectInGoop(mo)); @@ -725,26 +1067,18 @@ static int lib_pIsObjectOnGround(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_IsObjectOnGround(mo)); return 1; } -static int lib_pInSpaceSector(lua_State *L) -{ - mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - //HUDSAFE - if (!mo) - return LUA_ErrInvalid(L, "mobj_t"); - lua_pushboolean(L, P_InSpaceSector(mo)); - return 1; -} - static int lib_pInQuicksand(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_InQuicksand(mo)); @@ -757,17 +1091,70 @@ static int lib_pSetObjectMomZ(lua_State *L) fixed_t value = luaL_checkfixed(L, 2); boolean relative = lua_optboolean(L, 3); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_SetObjectMomZ(mo, value, relative); return 0; } +static int lib_pPlayJingle(lua_State *L) +{ + player_t *player = NULL; + jingletype_t jingletype = luaL_checkinteger(L, 2); + //NOHUD + //INLEVEL + if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) + { + player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (jingletype >= NUMJINGLES) + return luaL_error(L, "jingletype %d out of range (0 - %d)", jingletype, NUMJINGLES-1); + P_PlayJingle(player, jingletype); + return 0; +} + +static int lib_pPlayJingleMusic(lua_State *L) +{ + player_t *player = NULL; + const char *musnamearg = luaL_checkstring(L, 2); + char musname[7], *p = musname; + UINT16 musflags = luaL_optinteger(L, 3, 0); + boolean looping = lua_opttrueboolean(L, 4); + jingletype_t jingletype = luaL_optinteger(L, 5, JT_OTHER); + //NOHUD + //INLEVEL + if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) + { + player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (jingletype >= NUMJINGLES) + return luaL_error(L, "jingletype %d out of range (0 - %d)", jingletype, NUMJINGLES-1); + + musname[6] = '\0'; + strncpy(musname, musnamearg, 6); + + while (*p) { + *p = tolower(*p); + ++p; + } + + P_PlayJingleMusic(player, musname, musflags, looping, jingletype); + return 0; +} + static int lib_pRestoreMusic(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - if (!player || P_IsLocalPlayer(player)) + //NOHUD + //INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (P_IsLocalPlayer(player)) { P_RestoreMusic(player); lua_pushboolean(L, true); @@ -781,6 +1168,7 @@ static int lib_pSpawnShieldOrb(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_SpawnShieldOrb(player); @@ -791,6 +1179,7 @@ static int lib_pSpawnGhostMobj(lua_State *L) { mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); LUA_PushUserdata(L, P_SpawnGhostMobj(mobj), META_MOBJ); @@ -802,6 +1191,7 @@ static int lib_pGivePlayerRings(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); INT32 num_rings = (INT32)luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_GivePlayerRings(player, num_rings); @@ -813,6 +1203,7 @@ static int lib_pGivePlayerLives(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); INT32 numlives = (INT32)luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_GivePlayerLives(player, numlives); @@ -823,39 +1214,21 @@ static int lib_pResetScore(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_ResetScore(player); return 0; } -static int lib_pDoJumpShield(lua_State *L) +static int lib_pMovePlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); - P_DoJumpShield(player); - return 0; -} - -static int lib_pBlackOw(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_BlackOw(player); - return 0; -} - -static int lib_pElementalFireTrail(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_ElementalFireTrail(player); + P_MovePlayer(player); return 0; } @@ -863,6 +1236,7 @@ static int lib_pDoPlayerExit(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_DoPlayerExit(player); @@ -875,6 +1249,7 @@ static int lib_pInstaThrust(lua_State *L) angle_t angle = luaL_checkangle(L, 2); fixed_t move = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_InstaThrust(mo, angle, move); @@ -907,58 +1282,28 @@ static int lib_pReturnThrustY(lua_State *L) return 1; } -static int lib_pLookForEnemies(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - lua_pushboolean(L, P_LookForEnemies(player)); - return 1; -} - static int lib_pNukeEnemies(lua_State *L) { mobj_t *inflictor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); fixed_t radius = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!inflictor || !source) return LUA_ErrInvalid(L, "mobj_t"); P_NukeEnemies(inflictor, source, radius); return 0; } -static int lib_pHomingAttack(lua_State *L) -{ - mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - mobj_t *enemy = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - NOHUD - if (!source || !enemy) - return LUA_ErrInvalid(L, "mobj_t"); - P_HomingAttack(source, enemy); - return 0; -} - -/*static int lib_pSuperReady(lua_State *L) +static int lib_pSwitchShield(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - //HUDSAFE - if (!player) - return LUA_ErrInvalid(L, "player_t"); - lua_pushboolean(L, P_SuperReady(player)); - return 1; -}*/ - -static int lib_pTelekinesis(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - fixed_t thrust = luaL_checkfixed(L, 2); - fixed_t range = luaL_checkfixed(L, 3); + UINT16 shield = luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); - P_Telekinesis(player, thrust, range); + P_SwitchShield(player, shield); return 0; } @@ -972,6 +1317,7 @@ static int lib_pCheckPosition(lua_State *L) fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckPosition(thing, x, y)); @@ -988,6 +1334,7 @@ static int lib_pTryMove(lua_State *L) fixed_t y = luaL_checkfixed(L, 3); boolean allowdropoff = lua_optboolean(L, 4); NOHUD + INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_TryMove(thing, x, y, allowdropoff)); @@ -1002,6 +1349,7 @@ static int lib_pMove(lua_State *L) mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); fixed_t speed = luaL_checkfixed(L, 2); NOHUD + INLEVEL if (!actor) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_Move(actor, speed)); @@ -1018,6 +1366,7 @@ static int lib_pTeleportMove(lua_State *L) fixed_t y = luaL_checkfixed(L, 3); fixed_t z = luaL_checkfixed(L, 4); NOHUD + INLEVEL if (!thing) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_TeleportMove(thing, x, y, z)); @@ -1029,11 +1378,11 @@ static int lib_pTeleportMove(lua_State *L) static int lib_pSlideMove(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - boolean forceslide = luaL_checkboolean(L, 2); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); - P_SlideMove(mo, forceslide); + P_SlideMove(mo); return 0; } @@ -1041,6 +1390,7 @@ static int lib_pBounceMove(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_BounceMove(mo); @@ -1052,6 +1402,7 @@ static int lib_pCheckSight(lua_State *L) mobj_t *t1 = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *t2 = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); //HUDSAFE? + INLEVEL if (!t1 || !t2) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_CheckSight(t1, t2)); @@ -1066,6 +1417,7 @@ static int lib_pCheckHoopPosition(lua_State *L) fixed_t z = luaL_checkfixed(L, 4); fixed_t radius = luaL_checkfixed(L, 5); NOHUD + INLEVEL if (!hoopthing) return LUA_ErrInvalid(L, "mobj_t"); P_CheckHoopPosition(hoopthing, x, y, z, radius); @@ -1077,10 +1429,13 @@ static int lib_pRadiusAttack(lua_State *L) mobj_t *spot = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); fixed_t damagedist = luaL_checkfixed(L, 3); + UINT8 damagetype = luaL_optinteger(L, 4, 0); + boolean sightcheck = lua_opttrueboolean(L, 5); NOHUD + INLEVEL if (!spot || !source) return LUA_ErrInvalid(L, "mobj_t"); - P_RadiusAttack(spot, source, damagedist); + P_RadiusAttack(spot, source, damagedist, damagetype, sightcheck); return 0; } @@ -1091,15 +1446,29 @@ static int lib_pFloorzAtPos(lua_State *L) fixed_t z = luaL_checkfixed(L, 3); fixed_t height = luaL_checkfixed(L, 4); //HUDSAFE + INLEVEL lua_pushfixed(L, P_FloorzAtPos(x, y, z, height)); return 1; } +static int lib_pCeilingzAtPos(lua_State *L) +{ + fixed_t x = luaL_checkfixed(L, 1); + fixed_t y = luaL_checkfixed(L, 2); + fixed_t z = luaL_checkfixed(L, 3); + fixed_t height = luaL_checkfixed(L, 4); + //HUDSAFE + INLEVEL + lua_pushfixed(L, P_CeilingzAtPos(x, y, z, height)); + return 1; +} + static int lib_pDoSpring(lua_State *L) { mobj_t *spring = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); mobj_t *object = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); NOHUD + INLEVEL if (!spring || !object) return LUA_ErrInvalid(L, "mobj_t"); lua_pushboolean(L, P_DoSpring(spring, object)); @@ -1113,6 +1482,7 @@ static int lib_pRemoveShield(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); P_RemoveShield(player); @@ -1123,7 +1493,9 @@ static int lib_pDamageMobj(lua_State *L) { mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; INT32 damage; + UINT8 damagetype; NOHUD + INLEVEL if (!target) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1131,21 +1503,25 @@ static int lib_pDamageMobj(lua_State *L) if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); damage = (INT32)luaL_optinteger(L, 4, 1); - lua_pushboolean(L, P_DamageMobj(target, inflictor, source, damage)); + damagetype = (UINT8)luaL_optinteger(L, 5, 0); + lua_pushboolean(L, P_DamageMobj(target, inflictor, source, damage, damagetype)); return 1; } static int lib_pKillMobj(lua_State *L) { mobj_t *target = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)), *inflictor = NULL, *source = NULL; + UINT8 damagetype; NOHUD + INLEVEL if (!target) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); - P_KillMobj(target, inflictor, source); + damagetype = (UINT8)luaL_optinteger(L, 4, 0); + P_KillMobj(target, inflictor, source, damagetype); return 0; } @@ -1154,30 +1530,21 @@ static int lib_pPlayerRingBurst(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); INT32 num_rings = (INT32)luaL_optinteger(L, 2, -1); NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); if (num_rings == -1) - num_rings = player->health - 1; + num_rings = player->rings; P_PlayerRingBurst(player, num_rings); return 0; } -static int lib_pPlayerFlagBurst(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - boolean toss = lua_optboolean(L, 2); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_PlayerFlagBurst(player, toss); - return 0; -} - static int lib_pPlayRinglossSound(lua_State *L) { mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); player_t *player = NULL; NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1196,6 +1563,7 @@ static int lib_pPlayDeathSound(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); player_t *player = NULL; NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1214,6 +1582,7 @@ static int lib_pPlayVictorySound(lua_State *L) mobj_t *source = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); player_t *player = NULL; NOHUD + INLEVEL if (!source) return LUA_ErrInvalid(L, "mobj_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) @@ -1229,10 +1598,15 @@ static int lib_pPlayVictorySound(lua_State *L) static int lib_pPlayLivesJingle(lua_State *L) { - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); + player_t *player = NULL; + //NOHUD + //INLEVEL + if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) + { + player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } P_PlayLivesJingle(player); return 0; } @@ -1242,22 +1616,13 @@ static int lib_pCanPickupItem(lua_State *L) player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); UINT8 weapon = (UINT8)luaL_optinteger(L, 2, 0); //HUDSAFE + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); lua_pushboolean(L, P_CanPickupItem(player, weapon)); return 1; } -static int lib_pDoNightsScore(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_DoNightsScore(player); - return 0; -} - // P_SPEC //////////// @@ -1267,6 +1632,7 @@ static int lib_pThrust(lua_State *L) angle_t angle = luaL_checkangle(L, 2); fixed_t move = luaL_checkfixed(L, 3); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_Thrust(mo, angle, move); @@ -1278,6 +1644,7 @@ static int lib_pSetMobjStateNF(lua_State *L) mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); statenum_t state = luaL_checkinteger(L, 2); NOHUD + INLEVEL if (!mobj) return LUA_ErrInvalid(L, "mobj_t"); if (state >= NUMSTATES) @@ -1288,21 +1655,11 @@ static int lib_pSetMobjStateNF(lua_State *L) return 1; } -static int lib_pDoSuperTransformation(lua_State *L) -{ - player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - boolean giverings = lua_optboolean(L, 2); - NOHUD - if (!player) - return LUA_ErrInvalid(L, "player_t"); - P_DoSuperTransformation(player, giverings); - return 0; -} - static int lib_pExplodeMissile(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); P_ExplodeMissile(mo); @@ -1316,18 +1673,92 @@ static int lib_pMobjTouchingSectorSpecial(lua_State *L) INT32 number = (INT32)luaL_checkinteger(L, 3); boolean touchground = lua_optboolean(L, 4); //HUDSAFE + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); LUA_PushUserdata(L, P_MobjTouchingSectorSpecial(mo, section, number, touchground), META_SECTOR); return 1; } +static int lib_pFindLowestFloorSurrounding(lua_State *L) +{ + sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + //HUDSAFE + INLEVEL + if (!sector) + return LUA_ErrInvalid(L, "sector_t"); + lua_pushfixed(L, P_FindLowestFloorSurrounding(sector)); + return 1; +} + +static int lib_pFindHighestFloorSurrounding(lua_State *L) +{ + sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + //HUDSAFE + INLEVEL + if (!sector) + return LUA_ErrInvalid(L, "sector_t"); + lua_pushfixed(L, P_FindHighestFloorSurrounding(sector)); + return 1; +} + +static int lib_pFindNextHighestFloor(lua_State *L) +{ + sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + fixed_t currentheight; + //HUDSAFE + INLEVEL + if (!sector) + return LUA_ErrInvalid(L, "sector_t"); + // defaults to floorheight of sector arg + currentheight = (fixed_t)luaL_optinteger(L, 2, sector->floorheight); + lua_pushfixed(L, P_FindNextHighestFloor(sector, currentheight)); + return 1; +} + +static int lib_pFindNextLowestFloor(lua_State *L) +{ + sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + fixed_t currentheight; + //HUDSAFE + INLEVEL + if (!sector) + return LUA_ErrInvalid(L, "sector_t"); + // defaults to floorheight of sector arg + currentheight = (fixed_t)luaL_optinteger(L, 2, sector->floorheight); + lua_pushfixed(L, P_FindNextLowestFloor(sector, currentheight)); + return 1; +} + +static int lib_pFindLowestCeilingSurrounding(lua_State *L) +{ + sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + //HUDSAFE + INLEVEL + if (!sector) + return LUA_ErrInvalid(L, "sector_t"); + lua_pushfixed(L, P_FindLowestCeilingSurrounding(sector)); + return 1; +} + +static int lib_pFindHighestCeilingSurrounding(lua_State *L) +{ + sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + //HUDSAFE + INLEVEL + if (!sector) + return LUA_ErrInvalid(L, "sector_t"); + lua_pushfixed(L, P_FindHighestCeilingSurrounding(sector)); + return 1; +} + static int lib_pFindSpecialLineFromTag(lua_State *L) { INT16 special = (INT16)luaL_checkinteger(L, 1); INT16 line = (INT16)luaL_checkinteger(L, 2); INT32 start = (INT32)luaL_optinteger(L, 3, -1); NOHUD + INLEVEL lua_pushinteger(L, P_FindSpecialLineFromTag(special, line, start)); return 1; } @@ -1337,6 +1768,7 @@ static int lib_pSwitchWeather(lua_State *L) INT32 weathernum = (INT32)luaL_checkinteger(L, 1); player_t *user = NULL; NOHUD + INLEVEL if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup weather for only the player, otherwise setup weather for all players user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); if (!user) // global @@ -1352,6 +1784,7 @@ static int lib_pLinedefExecute(lua_State *L) mobj_t *actor = NULL; sector_t *caller = NULL; NOHUD + INLEVEL if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) actor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) @@ -1364,6 +1797,7 @@ static int lib_pSpawnLightningFlash(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); NOHUD + INLEVEL if (!sector) return LUA_ErrInvalid(L, "sector_t"); P_SpawnLightningFlash(sector); @@ -1375,8 +1809,11 @@ static int lib_pFadeLight(lua_State *L) INT16 tag = (INT16)luaL_checkinteger(L, 1); INT32 destvalue = (INT32)luaL_checkinteger(L, 2); INT32 speed = (INT32)luaL_checkinteger(L, 3); + boolean ticbased = lua_optboolean(L, 4); + boolean force = lua_optboolean(L, 5); NOHUD - P_FadeLight(tag, destvalue, speed); + INLEVEL + P_FadeLight(tag, destvalue, speed, ticbased, force); return 0; } @@ -1384,6 +1821,7 @@ static int lib_pThingOnSpecial3DFloor(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); NOHUD + INLEVEL if (!mo) return LUA_ErrInvalid(L, "mobj_t"); LUA_PushUserdata(L, P_ThingOnSpecial3DFloor(mo), META_SECTOR); @@ -1394,6 +1832,7 @@ static int lib_pIsFlagAtBase(lua_State *L) { mobjtype_t flag = luaL_checkinteger(L, 1); NOHUD + INLEVEL if (flag >= NUMMOBJTYPES) return luaL_error(L, "mobj type %d out of range (0 - %d)", flag, NUMMOBJTYPES-1); lua_pushboolean(L, P_IsFlagAtBase(flag)); @@ -1405,6 +1844,7 @@ static int lib_pSetupLevelSky(lua_State *L) const char *skytexname = luaL_checkstring(L, 1); player_t *user = NULL; NOHUD + INLEVEL if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) // if a player, setup sky for only the player, otherwise setup sky for all players user = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); if (!user) // global @@ -1423,6 +1863,7 @@ static int lib_pSetSkyboxMobj(lua_State *L) int w = 0; NOHUD + INLEVEL if (!lua_isnil(L,1)) // nil leaves mo as NULL to remove the skybox rendering. { mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); // otherwise it is a skybox mobj. @@ -1469,6 +1910,7 @@ static int lib_pStartQuake(lua_State *L) static mappoint_t q_epicenter = {0,0,0}; NOHUD + INLEVEL // While technically we don't support epicenter and radius, // we get their values anyway if they exist. @@ -1526,34 +1968,76 @@ static int lib_pStartQuake(lua_State *L) static int lib_evCrumbleChain(lua_State *L) { - sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); - ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); + sector_t *sec = NULL; + ffloor_t *rover = NULL; NOHUD - if (!sec) - return LUA_ErrInvalid(L, "sector_t"); + INLEVEL + if (!lua_isnone(L, 2)) + { + if (!lua_isnil(L, 1)) + { + sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + if (!sec) + return LUA_ErrInvalid(L, "sector_t"); + } + rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); + } + else + rover = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); if (!rover) return LUA_ErrInvalid(L, "ffloor_t"); EV_CrumbleChain(sec, rover); return 0; } -#ifdef ESLOPE +static int lib_evStartCrumble(lua_State *L) +{ + sector_t *sec = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + ffloor_t *rover = *((ffloor_t **)luaL_checkudata(L, 2, META_FFLOOR)); + boolean floating = lua_optboolean(L, 3); + player_t *player = NULL; + fixed_t origalpha; + boolean crumblereturn = lua_optboolean(L, 6); + NOHUD + if (!sec) + return LUA_ErrInvalid(L, "sector_t"); + if (!rover) + return LUA_ErrInvalid(L, "ffloor_t"); + if (!lua_isnone(L, 4) && lua_isuserdata(L, 4)) + { + player = *((player_t **)luaL_checkudata(L, 4, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!lua_isnone(L,5)) + origalpha = luaL_checkfixed(L, 5); + else + origalpha = rover->alpha; + lua_pushboolean(L, EV_StartCrumble(sec, rover, floating, player, origalpha, crumblereturn) != 0); + return 0; +} + // P_SLOPES //////////// static int lib_pGetZAt(lua_State *L) { - pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); fixed_t x = luaL_checkfixed(L, 2); fixed_t y = luaL_checkfixed(L, 3); //HUDSAFE - if (!slope) - return LUA_ErrInvalid(L, "pslope_t"); + if (lua_isnil(L, 1)) + { + fixed_t z = luaL_checkfixed(L, 4); + lua_pushfixed(L, P_GetZAt(NULL, x, y, z)); + } + else + { + pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); + lua_pushfixed(L, P_GetSlopeZAt(slope, x, y)); + } - lua_pushfixed(L, P_GetZAt(slope, x, y)); return 1; } -#endif // R_DEFS //////////// @@ -1603,10 +2087,25 @@ static int lib_rPointInSubsector(lua_State *L) fixed_t x = luaL_checkfixed(L, 1); fixed_t y = luaL_checkfixed(L, 2); //HUDSAFE + INLEVEL LUA_PushUserdata(L, R_PointInSubsector(x, y), META_SUBSECTOR); return 1; } +static int lib_rPointInSubsectorOrNil(lua_State *L) +{ + fixed_t x = luaL_checkfixed(L, 1); + fixed_t y = luaL_checkfixed(L, 2); + subsector_t *sub = R_PointInSubsectorOrNull(x, y); + //HUDSAFE + INLEVEL + if (sub) + LUA_PushUserdata(L, sub, META_SUBSECTOR); + else + lua_pushnil(L); + return 1; +} + // R_THINGS //////////// @@ -1636,26 +2135,64 @@ static int lib_rFrame2Char(lua_State *L) static int lib_rSetPlayerSkin(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INT32 i = -1, j = -1; NOHUD + INLEVEL if (!player) return LUA_ErrInvalid(L, "player_t"); + + j = (player-players); + if (lua_isnoneornil(L, 2)) return luaL_error(L, "argument #2 not given (expected number or string)"); else if (lua_type(L, 2) == LUA_TNUMBER) // skin number { - INT32 i = luaL_checkinteger(L, 2); - if (i < 0 || i >= MAXSKINS) - return luaL_error(L, "skin number (argument #2) %d out of range (0 - %d)", i, MAXSKINS-1); - SetPlayerSkinByNum(player-players, i); + i = luaL_checkinteger(L, 2); + if (i < 0 || i >= numskins) + return luaL_error(L, "skin %d (argument #2) out of range (0 - %d)", i, numskins-1); } else // skin name { const char *skinname = luaL_checkstring(L, 2); - SetPlayerSkin(player-players, skinname); + i = R_SkinAvailable(skinname); + if (i == -1) + return luaL_error(L, "skin %s (argument 2) is not loaded", skinname); } + + if (!R_SkinUsable(j, i)) + return luaL_error(L, "skin %d (argument 2) not usable - check with R_SkinUsable(player_t, skin) first.", i); + SetPlayerSkinByNum(j, i); return 0; } +static int lib_rSkinUsable(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INT32 i = -1, j = -1; + if (player) + j = (player-players); + else if (netgame || multiplayer) + return luaL_error(L, "player_t (argument #1) must be provided in multiplayer games"); + if (lua_isnoneornil(L, 2)) + return luaL_error(L, "argument #2 not given (expected number or string)"); + else if (lua_type(L, 2) == LUA_TNUMBER) // skin number + { + i = luaL_checkinteger(L, 2); + if (i < 0 || i >= numskins) + return luaL_error(L, "skin %d (argument #2) out of range (0 - %d)", i, numskins-1); + } + else // skin name + { + const char *skinname = luaL_checkstring(L, 2); + i = R_SkinAvailable(skinname); + if (i == -1) + return luaL_error(L, "skin %s (argument 2) is not loaded", skinname); + } + + lua_pushboolean(L, R_SkinUsable(j, i)); + return 1; +} + // R_DATA //////////// @@ -1675,33 +2212,87 @@ static int lib_rTextureNumForName(lua_State *L) return 1; } +// R_DRAW +//////////// +static int lib_rGetColorByName(lua_State *L) +{ + const char* colorname = luaL_checkstring(L, 1); + //HUDSAFE + lua_pushinteger(L, R_GetColorByName(colorname)); + return 1; +} + +static int lib_rGetSuperColorByName(lua_State *L) +{ + const char* colorname = luaL_checkstring(L, 1); + //HUDSAFE + lua_pushinteger(L, R_GetSuperColorByName(colorname)); + return 1; +} + +// Lua exclusive function, returns the name of a color from the SKINCOLOR_ constant. +// SKINCOLOR_GREEN > "Green" for example +static int lib_rGetNameByColor(lua_State *L) +{ + UINT16 colornum = (UINT16)luaL_checkinteger(L, 1); + if (!colornum || colornum >= numskincolors) + return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1); + lua_pushstring(L, skincolors[colornum].name); + return 1; +} + // S_SOUND //////////// +static int GetValidSoundOrigin(lua_State *L, void **origin) +{ + const char *type; + + lua_settop(L, 1); + type = GetUserdataUType(L); + + if (fasticmp(type, "mobj_t")) + { + *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + if (!(*origin)) + return LUA_ErrInvalid(L, "mobj_t"); + return 1; + } + else if (fasticmp(type, "sector_t")) + { + *origin = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); + if (!(*origin)) + return LUA_ErrInvalid(L, "sector_t"); + + *origin = &((sector_t *)(*origin))->soundorg; + return 1; + } + + return LUA_ErrInvalid(L, "mobj_t/sector_t"); +} static int lib_sStartSound(lua_State *L) { - const void *origin = NULL; + void *origin = NULL; sfxenum_t sound_id = luaL_checkinteger(L, 2); player_t *player = NULL; - //NOHUD // kys @whoever did this. + //NOHUD + if (sound_id >= NUMSFX) return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1); - if (!lua_isnil(L, 1)) - { - origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - if (!origin) - return LUA_ErrInvalid(L, "mobj_t"); - } + if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) { player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); if (!player) return LUA_ErrInvalid(L, "player_t"); } + if (!lua_isnil(L, 1)) + if (!GetValidSoundOrigin(L, &origin)) + return 0; if (!player || P_IsLocalPlayer(player)) { - if (hud_running) - origin = NULL; // HUD rendering startsound shouldn't have an origin, just remove it instead of having a retarded error. + if (hud_running || hook_cmd_running) + origin = NULL; // HUD rendering and CMD building startsound shouldn't have an origin, just remove it instead of having a retarded error. S_StartSound(origin, sound_id); } @@ -1710,18 +2301,12 @@ static int lib_sStartSound(lua_State *L) static int lib_sStartSoundAtVolume(lua_State *L) { - const void *origin = NULL; + void *origin = NULL; sfxenum_t sound_id = luaL_checkinteger(L, 2); INT32 volume = (INT32)luaL_checkinteger(L, 3); player_t *player = NULL; - NOHUD + //NOHUD - if (!lua_isnil(L, 1)) - { - origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - if (!origin) - return LUA_ErrInvalid(L, "mobj_t"); - } if (sound_id >= NUMSFX) return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1); if (!lua_isnone(L, 4) && lua_isuserdata(L, 4)) @@ -1730,44 +2315,39 @@ static int lib_sStartSoundAtVolume(lua_State *L) if (!player) return LUA_ErrInvalid(L, "player_t"); } + if (!lua_isnil(L, 1)) + if (!GetValidSoundOrigin(L, &origin)) + return LUA_ErrInvalid(L, "mobj_t/sector_t"); + if (!player || P_IsLocalPlayer(player)) - S_StartSoundAtVolume(origin, sound_id, volume); + S_StartSoundAtVolume(origin, sound_id, volume); return 0; } static int lib_sStopSound(lua_State *L) { - void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - NOHUD - if (!origin) - return LUA_ErrInvalid(L, "mobj_t"); + void *origin = NULL; + //NOHUD + if (!GetValidSoundOrigin(L, &origin)) + return LUA_ErrInvalid(L, "mobj_t/sector_t"); + S_StopSound(origin); return 0; } static int lib_sStopSoundByID(lua_State *L) { - void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + void *origin = NULL; sfxenum_t sound_id = luaL_checkinteger(L, 2); - NOHUD - if (!origin) - return LUA_ErrInvalid(L, "mobj_t"); - S_StopSoundByID(origin, sound_id); - return 0; -} + //NOHUD -static int lib_sShowMusicCredit(lua_State *L) -{ - player_t *player = NULL; - //HUDSAFE - if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) - { - player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - if (!player) - return LUA_ErrInvalid(L, "player_t"); - } - if (!player || P_IsLocalPlayer(player)) - S_ShowMusicCredit(); + if (sound_id >= NUMSFX) + return luaL_error(L, "sfx %d out of range (0 - %d)", sound_id, NUMSFX-1); + if (!lua_isnil(L, 1)) + if (!GetValidSoundOrigin(L, &origin)) + return LUA_ErrInvalid(L, "mobj_t/sector_t"); + + S_StopSoundByID(origin, sound_id); return 0; } @@ -1781,7 +2361,7 @@ static int lib_sChangeMusic(lua_State *L) boolean looping; player_t *player = NULL; UINT16 music_flags = 0; - NOHUD + //NOHUD if (lua_isnumber(L, 1)) { @@ -1810,7 +2390,7 @@ static int lib_sChangeMusic(lua_State *L) boolean looping = (boolean)lua_opttrueboolean(L, 2); player_t *player = NULL; UINT16 music_flags = 0; - NOHUD + //NOHUD #endif if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) @@ -1846,7 +2426,7 @@ static int lib_sSpeedMusic(lua_State *L) fixed_t fixedspeed = luaL_checkfixed(L, 1); float speed = FIXED_TO_FLOAT(fixedspeed); player_t *player = NULL; - NOHUD + //NOHUD if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) { player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); @@ -1863,7 +2443,7 @@ static int lib_sSpeedMusic(lua_State *L) static int lib_sMusicType(lua_State *L) { player_t *player = NULL; - NOHUD + //NOHUD if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) { player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1880,8 +2460,8 @@ static int lib_sMusicType(lua_State *L) static int lib_sMusicPlaying(lua_State *L) { player_t *player = NULL; - NOHUD - if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) + //NOHUD + if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) { player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!player) @@ -1897,7 +2477,7 @@ static int lib_sMusicPlaying(lua_State *L) static int lib_sMusicPaused(lua_State *L) { player_t *player = NULL; - NOHUD + //NOHUD if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) { player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1914,8 +2494,8 @@ static int lib_sMusicPaused(lua_State *L) static int lib_sMusicName(lua_State *L) { player_t *player = NULL; - NOHUD - if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) + //NOHUD + if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) { player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!player) @@ -1928,39 +2508,8 @@ static int lib_sMusicName(lua_State *L) return 1; } -static int lib_sMusicInfo(lua_State *L) -{ - player_t *player = NULL; - NOHUD - if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) - { - player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - if (!player) - return LUA_ErrInvalid(L, "player_t"); - } - if (!player || P_IsLocalPlayer(player)) - { - char mname[7]; - UINT16 mflags; - boolean looping; - if (S_MusicInfo(mname, &mflags, &looping)) - { - lua_pushstring(L, mname); - lua_pushinteger(L, mflags); - lua_pushboolean(L, looping); - } - else - lua_pushboolean(L, false); - } - else - lua_pushnil(L); - return 1; -} - static int lib_sMusicExists(lua_State *L) { - boolean checkMIDI = lua_opttrueboolean(L, 2); - boolean checkDigi = lua_opttrueboolean(L, 3); #ifdef MUSICSLOT_COMPATIBILITY const char *music_name; UINT32 music_num; @@ -1989,24 +2538,7 @@ static int lib_sMusicExists(lua_State *L) const char *music_name = luaL_checkstring(L, 1); #endif NOHUD - lua_pushboolean(L, S_MusicExists(music_name, checkMIDI, checkDigi)); - return 1; -} - -static int lib_sGetMusicLength(lua_State *L) -{ - player_t *player = NULL; - NOHUD - if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) - { - player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - if (!player) - return LUA_ErrInvalid(L, "player_t"); - } - if (!player || P_IsLocalPlayer(player)) - lua_pushinteger(L, (int)S_GetMusicLength()); - else - lua_pushnil(L); + lua_pushboolean(L, S_MusicExists(music_name)); return 1; } @@ -2014,7 +2546,7 @@ static int lib_sSetMusicLoopPoint(lua_State *L) { UINT32 looppoint = (UINT32)luaL_checkinteger(L, 1); player_t *player = NULL; - NOHUD + //NOHUD if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) { player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); @@ -2030,36 +2562,13 @@ static int lib_sSetMusicLoopPoint(lua_State *L) static int lib_sGetMusicLoopPoint(lua_State *L) { - player_t *player = NULL; - NOHUD - if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) - { - player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - if (!player) - return LUA_ErrInvalid(L, "player_t"); - } - if (!player || P_IsLocalPlayer(player)) - lua_pushinteger(L, (int)S_GetMusicLoopPoint()); - else - lua_pushnil(L); + lua_pushinteger(L, S_GetMusicLoopPoint()); return 1; } -static int lib_sSetMusicPosition(lua_State *L) +static int lib_sGetMusicLength(lua_State *L) { - UINT32 position = (UINT32)luaL_checkinteger(L, 1); - player_t *player = NULL; - NOHUD - if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) - { - player = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); - if (!player) - return LUA_ErrInvalid(L, "player_t"); - } - if (!player || P_IsLocalPlayer(player)) - lua_pushboolean(L, S_SetMusicPosition(position)); - else - lua_pushnil(L); + lua_pushinteger(L, S_GetMusicLength()); return 1; } @@ -2080,6 +2589,13 @@ static int lib_sGetMusicPosition(lua_State *L) return 1; } +static int lib_sSetMusicPosition(lua_State *L) +{ + UINT32 pos = (UINT32)luaL_checkinteger(L, 1); + lua_pushboolean(L, S_SetMusicPosition(pos)); + return 1; +} + static int lib_sStopMusic(lua_State *L) { player_t *player = NULL; @@ -2246,10 +2762,11 @@ static int lib_sFadeOutStopMusic(lua_State *L) static int lib_sOriginPlaying(lua_State *L) { - void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); - NOHUD - if (!origin) - return LUA_ErrInvalid(L, "mobj_t"); + void *origin = NULL; + //NOHUD + INLEVEL + if (!GetValidSoundOrigin(L, &origin)) + return LUA_ErrInvalid(L, "mobj_t/sector_t"); lua_pushboolean(L, S_OriginPlaying(origin)); return 1; } @@ -2257,7 +2774,7 @@ static int lib_sOriginPlaying(lua_State *L) static int lib_sIdPlaying(lua_State *L) { sfxenum_t id = luaL_checkinteger(L, 1); - NOHUD + //NOHUD if (id >= NUMSFX) return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1); lua_pushboolean(L, S_IdPlaying(id)); @@ -2266,32 +2783,336 @@ static int lib_sIdPlaying(lua_State *L) static int lib_sSoundPlaying(lua_State *L) { - void *origin = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + void *origin = NULL; sfxenum_t id = luaL_checkinteger(L, 2); - NOHUD - if (!origin) - return LUA_ErrInvalid(L, "mobj_t"); + //NOHUD + INLEVEL if (id >= NUMSFX) return luaL_error(L, "sfx %d out of range (0 - %d)", id, NUMSFX-1); + if (!GetValidSoundOrigin(L, &origin)) + return LUA_ErrInvalid(L, "mobj_t/sector_t"); lua_pushboolean(L, S_SoundPlaying(origin, id)); return 1; } +// This doesn't really exist, but we're providing it as a handy netgame-safe wrapper for stuff that should be locally handled. + +static int lib_sStartMusicCaption(lua_State *L) +{ + player_t *player = NULL; + const char *caption = luaL_checkstring(L, 1); + UINT16 lifespan = (UINT16)luaL_checkinteger(L, 2); + //HUDSAFE + //INLEVEL + + if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) + { + player = *((player_t **)luaL_checkudata(L, 3, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + + if (lifespan && (!player || P_IsLocalPlayer(player))) + { + strlcpy(S_sfx[sfx_None].caption, caption, sizeof(S_sfx[sfx_None].caption)); + S_StartCaption(sfx_None, -1, lifespan); + } + return 0; +} + +static int lib_sShowMusicCredit(lua_State *L) +{ + player_t *player = NULL; + //HUDSAFE + if (!lua_isnone(L, 1) && lua_isuserdata(L, 1)) + { + player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + if (!player) + return LUA_ErrInvalid(L, "player_t"); + } + if (!player || P_IsLocalPlayer(player)) + S_ShowMusicCredit(); + return 0; +} + // G_GAME //////////// +// Copypasted from lib_cvRegisterVar :] +static int lib_gAddGametype(lua_State *L) +{ + const char *k; + lua_Integer i; + + const char *gtname = NULL; + const char *gtconst = NULL; + INT16 newgtidx = 0; + UINT32 newgtrules = 0; + UINT32 newgttol = 0; + INT32 newgtpointlimit = 0; + INT32 newgttimelimit = 0; + INT16 newgtrankingstype = -1; + int newgtinttype = 0; + + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. + + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + + // Ran out of gametype slots + if (gametypecount == NUMGAMETYPEFREESLOTS) + return luaL_error(L, "Ran out of free gametype slots!"); + +#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("G_AddGametype") " (%s)", e); +#define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) + + lua_pushnil(L); + while (lua_next(L, 1)) { + // stack: gametype table, key/index, value + // 1 2 3 + i = 0; + k = NULL; + if (lua_isnumber(L, 2)) + i = lua_tointeger(L, 2); + else if (lua_isstring(L, 2)) + k = lua_tostring(L, 2); + + // Sorry, no gametype rules as key names. + if (i == 1 || (k && fasticmp(k, "name"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("name", LUA_TSTRING) + gtname = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 2 || (k && fasticmp(k, "identifier"))) { + if (!lua_isstring(L, 3)) + TYPEERROR("identifier", LUA_TSTRING) + gtconst = Z_StrDup(lua_tostring(L, 3)); + } else if (i == 3 || (k && fasticmp(k, "rules"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("rules", LUA_TNUMBER) + newgtrules = (UINT32)lua_tointeger(L, 3); + } else if (i == 4 || (k && fasticmp(k, "typeoflevel"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("typeoflevel", LUA_TNUMBER) + newgttol = (UINT32)lua_tointeger(L, 3); + } else if (i == 5 || (k && fasticmp(k, "rankingtype"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("rankingtype", LUA_TNUMBER) + newgtrankingstype = (INT16)lua_tointeger(L, 3); + } else if (i == 6 || (k && fasticmp(k, "intermissiontype"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("intermissiontype", LUA_TNUMBER) + newgtinttype = (int)lua_tointeger(L, 3); + } else if (i == 7 || (k && fasticmp(k, "defaultpointlimit"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("defaultpointlimit", LUA_TNUMBER) + newgtpointlimit = (INT32)lua_tointeger(L, 3); + } else if (i == 8 || (k && fasticmp(k, "defaulttimelimit"))) { + if (!lua_isnumber(L, 3)) + TYPEERROR("defaulttimelimit", LUA_TNUMBER) + newgttimelimit = (INT32)lua_tointeger(L, 3); + } + lua_pop(L, 1); + } + +#undef FIELDERROR +#undef TYPEERROR + + // pop gametype table + lua_pop(L, 1); + + // Set defaults + if (gtname == NULL) + gtname = Z_StrDup("Unnamed gametype"); + + // Add the new gametype + newgtidx = G_AddGametype(newgtrules); + G_AddGametypeTOL(newgtidx, newgttol); + + // Not covered by G_AddGametype alone. + if (newgtrankingstype == -1) + newgtrankingstype = newgtidx; + gametyperankings[newgtidx] = newgtrankingstype; + intermissiontypes[newgtidx] = newgtinttype; + pointlimits[newgtidx] = newgtpointlimit; + timelimits[newgtidx] = newgttimelimit; + + // Write the new gametype name. + Gametype_Names[newgtidx] = gtname; + + // Write the constant name. + if (gtconst == NULL) + gtconst = gtname; + G_AddGametypeConstant(newgtidx, gtconst); + + // Update gametype_cons_t accordingly. + G_UpdateGametypeSelections(); + + // done + CONS_Printf("Added gametype %s\n", Gametype_Names[newgtidx]); + return 0; +} + +static int Lcheckmapnumber (lua_State *L, int idx, const char *fun) +{ + if (ISINLEVEL) + return luaL_optinteger(L, idx, gamemap); + else + { + if (lua_isnoneornil(L, idx)) + { + return luaL_error(L, + "%s can only be used without a parameter while in a level.", + fun + ); + } + else + return luaL_checkinteger(L, idx); + } +} + static int lib_gBuildMapName(lua_State *L) { - INT32 map = luaL_optinteger(L, 1, gamemap); + INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapName"); //HUDSAFE lua_pushstring(L, G_BuildMapName(map)); return 1; } +static int lib_gBuildMapTitle(lua_State *L) +{ + INT32 map = Lcheckmapnumber(L, 1, "G_BuildMapTitle"); + char *name; + if (map < 1 || map > NUMMAPS) + { + return luaL_error(L, + "map number %d out of range (1 - %d)", + map, + NUMMAPS + ); + } + name = G_BuildMapTitle(map); + lua_pushstring(L, name); + Z_Free(name); + return 1; +} + +static void +Lpushdim (lua_State *L, int c, struct searchdim *v) +{ + int i; + lua_createtable(L, c, 0);/* I guess narr is numeric indices??? */ + for (i = 0; i < c; ++i) + { + lua_createtable(L, 0, 2);/* and hashed indices (field)... */ + lua_pushnumber(L, v[i].pos); + lua_setfield(L, -2, "pos"); + + lua_pushnumber(L, v[i].siz); + lua_setfield(L, -2, "siz"); + lua_rawseti(L, -2, 1 + i); + } +} + +/* +I decided to make this return a table because userdata +is scary and tables let the user set their own fields. +*/ +/* +Returns: + +[1] => map number +[2] => map title +[3] => search frequency table + +The frequency table is unsorted. It has the following format: + +{ + ['mapnum'], + + ['matchd'] => matches in map title string + ['keywhd'] => matches in map keywords + + The above two tables have the following format: + + { + ['pos'] => offset from start of string + ['siz'] => length of match + }... + + ['total'] => the total matches +}... +*/ +static int lib_gFindMap(lua_State *L) +{ + const char *query = luaL_checkstring(L, 1); + + INT32 map; + char *realname; + INT32 frc; + mapsearchfreq_t *frv; + + INT32 i; + + map = G_FindMap(query, &realname, &frv, &frc); + + lua_settop(L, 0); + + lua_pushnumber(L, map); + lua_pushstring(L, realname); + + lua_createtable(L, frc, 0); + for (i = 0; i < frc; ++i) + { + lua_createtable(L, 0, 4); + lua_pushnumber(L, frv[i].mapnum); + lua_setfield(L, -2, "mapnum"); + + Lpushdim(L, frv[i].matchc, frv[i].matchd); + lua_setfield(L, -2, "matchd"); + + Lpushdim(L, frv[i].keywhc, frv[i].keywhd); + lua_setfield(L, -2, "keywhd"); + + lua_pushnumber(L, frv[i].total); + lua_setfield(L, -2, "total"); + lua_rawseti(L, -2, 1 + i); + } + + G_FreeMapSearch(frv, frc); + Z_Free(realname); + + return 3; +} + +/* +Returns: + +[1] => map number +[2] => map title +*/ +static int lib_gFindMapByNameOrCode(lua_State *L) +{ + const char *query = luaL_checkstring(L, 1); + INT32 map; + char *realname; + map = G_FindMapByNameOrCode(query, &realname); + lua_pushnumber(L, map); + if (map) + { + lua_pushstring(L, realname); + Z_Free(realname); + return 2; + } + else + return 1; +} + static int lib_gDoReborn(lua_State *L) { INT32 playernum = luaL_checkinteger(L, 1); NOHUD + INLEVEL if (playernum >= MAXPLAYERS) return luaL_error(L, "playernum %d out of range (0 - %d)", playernum, MAXPLAYERS-1); G_DoReborn(playernum); @@ -2304,28 +3125,23 @@ static int lib_gSetCustomExitVars(lua_State *L) { int n = lua_gettop(L); // Num arguments NOHUD + INLEVEL // LUA EXTENSION: Custom exit like support // Supported: // G_SetCustomExitVars(); [reset to defaults] // G_SetCustomExitVars(int) [nextmap override only] - // G_SetCustomExitVars(bool) [skipstats only] - // G_SetCustomExitVars(int, bool) [both of the above] + // G_SetCustomExitVars(nil, int) [skipstats only] + // G_SetCustomExitVars(int, int) [both of the above] + + nextmapoverride = 0; + skipstats = 0; + if (n >= 1) { - if (lua_isnumber(L, 1) || n >= 2) - { - nextmapoverride = (INT16)luaL_checknumber(L, 1); - lua_remove(L, 1); // remove nextmapoverride; skipstats now 1 if available - } - skipstats = lua_optboolean(L, 1); + nextmapoverride = (INT16)luaL_optinteger(L, 1, 0); + skipstats = (INT16)luaL_optinteger(L, 2, 0); } - else - { - nextmapoverride = 0; - skipstats = false; - } - // --- return 0; } @@ -2345,6 +3161,7 @@ static int lib_gIsSpecialStage(lua_State *L) { INT32 mapnum = luaL_optinteger(L, 1, gamemap); //HUDSAFE + INLEVEL lua_pushboolean(L, G_IsSpecialStage(mapnum)); return 1; } @@ -2352,6 +3169,7 @@ static int lib_gIsSpecialStage(lua_State *L) static int lib_gGametypeUsesLives(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_GametypeUsesLives()); return 1; } @@ -2359,6 +3177,7 @@ static int lib_gGametypeUsesLives(lua_State *L) static int lib_gGametypeHasTeams(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_GametypeHasTeams()); return 1; } @@ -2366,31 +3185,11 @@ static int lib_gGametypeHasTeams(lua_State *L) static int lib_gGametypeHasSpectators(lua_State *L) { //HUDSAFE + INLEVEL lua_pushboolean(L, G_GametypeHasSpectators()); return 1; } -static int lib_gBattleGametype(lua_State *L) -{ - //HUDSAFE - lua_pushboolean(L, G_BattleGametype()); - return 1; -} - -static int lib_gRaceGametype(lua_State *L) -{ - //HUDSAFE - lua_pushboolean(L, G_RaceGametype()); - return 1; -} - -static int lib_gTagGametype(lua_State *L) -{ - //HUDSAFE - lua_pushboolean(L, G_TagGametype()); - return 1; -} - static int lib_gTicsToHours(lua_State *L) { tic_t rtic = luaL_checkinteger(L, 1); @@ -2511,14 +3310,6 @@ static int lib_kLossSound(lua_State *L) // Note: Pain, Death and Victory are already exposed. -static int lib_kGetKartColorByName(lua_State *L) -{ - const char *name = luaL_checkstring(L, 1); - //HUDSAFE - lua_pushinteger(L, K_GetKartColorByName(name)); - return 1; -} - static int lib_kIsPlayerLosing(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -2594,34 +3385,33 @@ static int lib_kSpawnBattlePoints(lua_State *L) static int lib_kSpinPlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *inflictor = NULL; mobj_t *source = NULL; INT32 type = (INT32)luaL_optinteger(L, 3, 0); - mobj_t *inflictor = NULL; - boolean trapitem = lua_optboolean(L, 5); NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) - source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - if (!lua_isnone(L, 4) && lua_isuserdata(L, 4)) - inflictor = *((mobj_t **)luaL_checkudata(L, 4, META_MOBJ)); - K_SpinPlayer(player, source, type, inflictor, trapitem); + inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) + source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + K_SpinPlayer(player, inflictor, source, type); return 0; } static int lib_kSquishPlayer(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - mobj_t *source = NULL; mobj_t *inflictor = NULL; + mobj_t *source = NULL; NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); - if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) - source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); - K_SquishPlayer(player, source, inflictor); + if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) + source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + K_SquishPlayer(player, inflictor, source); return 0; } @@ -2634,10 +3424,10 @@ static int lib_kExplodePlayer(lua_State *L) if (!player) return LUA_ErrInvalid(L, "player_t"); if (!lua_isnone(L, 2) && lua_isuserdata(L, 2)) - source = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + inflictor = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); if (!lua_isnone(L, 3) && lua_isuserdata(L, 3)) - inflictor = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); - K_ExplodePlayer(player, source, inflictor); + source = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + K_ExplodePlayer(player, inflictor, source); return 0; } @@ -2645,13 +3435,12 @@ static int lib_kStealBumper(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); player_t *victim = *((player_t **)luaL_checkudata(L, 2, META_PLAYER)); - boolean force = lua_optboolean(L, 3); NOHUD if (!player) return LUA_ErrInvalid(L, "player_t"); if (!victim) return LUA_ErrInvalid(L, "player_t"); - K_StealBumper(player, victim, force); + K_StealBumper(player, victim); return 0; } @@ -2888,60 +3677,32 @@ static int lib_kGetItemPatch(lua_State *L) return 1; } -// sets the remaining time before players blow up -static int lib_kSetRaceCountdown(lua_State *L) -{ - tic_t c = (tic_t)luaL_checkinteger(L, 1); - racecountdown = c; - return 0; -} - -// sets the remaining time before the race ends after everyone finishes -static int lib_kSetExitCountdown(lua_State *L) -{ - tic_t c = (tic_t)luaL_checkinteger(L, 1); - NOHUD - exitcountdown = c; - return 0; -} - -// Sets the item cooldown before another shrink / SPB can be rolled -static int lib_kSetIndirectItemCountdown(lua_State *L) -{ - tic_t c = (tic_t)luaL_checkinteger(L, 1); - NOHUD - indirectitemcooldown = c; - return 0; -} - -// Sets the item cooldown before another shrink / SPB can be rolled -static int lib_kSetHyuCountdown(lua_State *L) -{ - tic_t c = (tic_t)luaL_checkinteger(L, 1); - NOHUD - hyubgone = c; - return 0; -} - static luaL_Reg lib[] = { {"print", lib_print}, {"chatprint", lib_chatprint}, {"chatprintf", lib_chatprintf}, - {"EvalMath", lib_evalMath}, + {"userdataType", lib_userdataType}, {"IsPlayerAdmin", lib_isPlayerAdmin}, + {"reserveLuabanks", lib_reserveLuabanks}, + + // m_menu + {"M_MoveColorAfter",lib_pMoveColorAfter}, + {"M_MoveColorBefore",lib_pMoveColorBefore}, + {"M_GetColorAfter",lib_pGetColorAfter}, + {"M_GetColorBefore",lib_pGetColorBefore}, // m_random {"P_RandomFixed",lib_pRandomFixed}, {"P_RandomByte",lib_pRandomByte}, {"P_RandomKey",lib_pRandomKey}, {"P_RandomRange",lib_pRandomRange}, - {"P_Random",lib_pRandom}, // DEPRECATED {"P_SignedRandom",lib_pSignedRandom}, // MACRO {"P_RandomChance",lib_pRandomChance}, // MACRO // p_maputil {"P_AproxDistance",lib_pAproxDistance}, {"P_ClosestPointOnLine",lib_pClosestPointOnLine}, + {"P_PointOnLineSide",lib_pPointOnLineSide}, // p_enemy {"P_CheckMeleeRange", lib_pCheckMeleeRange}, @@ -2955,7 +3716,10 @@ static luaL_Reg lib[] = { // p_mobj // don't add P_SetMobjState or P_SetPlayerMobjState, use "mobj.state = S_NEWSTATE" instead. {"P_SpawnMobj",lib_pSpawnMobj}, + {"P_SpawnMobjFromMobj",lib_pSpawnMobjFromMobj}, {"P_RemoveMobj",lib_pRemoveMobj}, + {"P_IsValidSprite2", lib_pIsValidSprite2}, + {"P_SpawnLockOn", lib_pSpawnLockOn}, {"P_SpawnMissile",lib_pSpawnMissile}, {"P_SpawnXYZMissile",lib_pSpawnXYZMissile}, {"P_SpawnPointMissile",lib_pSpawnPointMissile}, @@ -2965,7 +3729,6 @@ static luaL_Reg lib[] = { {"P_SpawnPlayerMissile",lib_pSpawnPlayerMissile}, {"P_MobjFlip",lib_pMobjFlip}, {"P_GetMobjGravity",lib_pGetMobjGravity}, - {"P_WeaponOrPanel",lib_pWeaponOrPanel}, {"P_FlashPal",lib_pFlashPal}, {"P_GetClosestAxis",lib_pGetClosestAxis}, {"P_SpawnParaloop",lib_pSpawnParaloop}, @@ -2975,37 +3738,40 @@ static luaL_Reg lib[] = { {"P_InsideANonSolidFFloor",lib_pInsideANonSolidFFloor}, {"P_CheckDeathPitCollide",lib_pCheckDeathPitCollide}, {"P_CheckSolidLava",lib_pCheckSolidLava}, + {"P_MaceRotate",lib_pMaceRotate}, + {"P_RailThinker",lib_pRailThinker}, + {"P_XYMovement",lib_pXYMovement}, + {"P_RingXYMovement",lib_pRingXYMovement}, + {"P_SceneryXYMovement",lib_pSceneryXYMovement}, + {"P_ZMovement",lib_pZMovement}, + {"P_RingZMovement",lib_pRingZMovement}, + {"P_SceneryZMovement",lib_pSceneryZMovement}, + {"P_PlayerZMovement",lib_pPlayerZMovement}, // p_user - {"P_GetPlayerHeight",lib_pGetPlayerHeight}, - {"P_GetPlayerSpinHeight",lib_pGetPlayerSpinHeight}, {"P_AddPlayerScore",lib_pAddPlayerScore}, {"P_PlayerInPain",lib_pPlayerInPain}, - {"P_DoPlayerPain",lib_pDoPlayerPain}, {"P_ResetPlayer",lib_pResetPlayer}, + {"P_PlayerFullbright",lib_pPlayerFullbright}, {"P_IsObjectInGoop",lib_pIsObjectInGoop}, {"P_IsObjectOnGround",lib_pIsObjectOnGround}, - {"P_InSpaceSector",lib_pInSpaceSector}, {"P_InQuicksand",lib_pInQuicksand}, {"P_SetObjectMomZ",lib_pSetObjectMomZ}, + {"P_PlayJingle",lib_pPlayJingle}, + {"P_PlayJingleMusic",lib_pPlayJingleMusic}, {"P_RestoreMusic",lib_pRestoreMusic}, {"P_SpawnShieldOrb",lib_pSpawnShieldOrb}, {"P_SpawnGhostMobj",lib_pSpawnGhostMobj}, {"P_GivePlayerRings",lib_pGivePlayerRings}, {"P_GivePlayerLives",lib_pGivePlayerLives}, {"P_ResetScore",lib_pResetScore}, - {"P_DoJumpShield",lib_pDoJumpShield}, - {"P_BlackOw",lib_pBlackOw}, - {"P_ElementalFireTrail",lib_pElementalFireTrail}, + {"P_MovePlayer",lib_pMovePlayer}, {"P_DoPlayerExit",lib_pDoPlayerExit}, {"P_InstaThrust",lib_pInstaThrust}, {"P_ReturnThrustX",lib_pReturnThrustX}, {"P_ReturnThrustY",lib_pReturnThrustY}, - {"P_LookForEnemies",lib_pLookForEnemies}, {"P_NukeEnemies",lib_pNukeEnemies}, - {"P_HomingAttack",lib_pHomingAttack}, - //{"P_SuperReady",lib_pSuperReady}, - {"P_Telekinesis",lib_pTelekinesis}, + {"P_SwitchShield",lib_pSwitchShield}, // p_map {"P_CheckPosition",lib_pCheckPosition}, @@ -3018,6 +3784,7 @@ static luaL_Reg lib[] = { {"P_CheckHoopPosition",lib_pCheckHoopPosition}, {"P_RadiusAttack",lib_pRadiusAttack}, {"P_FloorzAtPos",lib_pFloorzAtPos}, + {"P_CeilingzAtPos",lib_pCeilingzAtPos}, {"P_DoSpring",lib_pDoSpring}, // p_inter @@ -3025,20 +3792,23 @@ static luaL_Reg lib[] = { {"P_DamageMobj",lib_pDamageMobj}, {"P_KillMobj",lib_pKillMobj}, {"P_PlayerRingBurst",lib_pPlayerRingBurst}, - {"P_PlayerFlagBurst",lib_pPlayerFlagBurst}, {"P_PlayRinglossSound",lib_pPlayRinglossSound}, {"P_PlayDeathSound",lib_pPlayDeathSound}, {"P_PlayVictorySound",lib_pPlayVictorySound}, {"P_PlayLivesJingle",lib_pPlayLivesJingle}, {"P_CanPickupItem",lib_pCanPickupItem}, - {"P_DoNightsScore",lib_pDoNightsScore}, // p_spec {"P_Thrust",lib_pThrust}, {"P_SetMobjStateNF",lib_pSetMobjStateNF}, - {"P_DoSuperTransformation",lib_pDoSuperTransformation}, {"P_ExplodeMissile",lib_pExplodeMissile}, {"P_MobjTouchingSectorSpecial",lib_pMobjTouchingSectorSpecial}, + {"P_FindLowestFloorSurrounding",lib_pFindLowestFloorSurrounding}, + {"P_FindHighestFloorSurrounding",lib_pFindHighestFloorSurrounding}, + {"P_FindNextHighestFloor",lib_pFindNextHighestFloor}, + {"P_FindNextLowestFloor",lib_pFindNextLowestFloor}, + {"P_FindLowestCeilingSurrounding",lib_pFindLowestCeilingSurrounding}, + {"P_FindHighestCeilingSurrounding",lib_pFindHighestCeilingSurrounding}, {"P_FindSpecialLineFromTag",lib_pFindSpecialLineFromTag}, {"P_SwitchWeather",lib_pSwitchWeather}, {"P_LinedefExecute",lib_pLinedefExecute}, @@ -3050,11 +3820,10 @@ static luaL_Reg lib[] = { {"P_SetSkyboxMobj",lib_pSetSkyboxMobj}, {"P_StartQuake",lib_pStartQuake}, {"EV_CrumbleChain",lib_evCrumbleChain}, + {"EV_StartCrumble",lib_evStartCrumble}, -#ifdef ESLOPE // p_slopes {"P_GetZAt",lib_pGetZAt}, -#endif // r_defs {"R_PointToAngle",lib_rPointToAngle}, @@ -3062,29 +3831,34 @@ static luaL_Reg lib[] = { {"R_PointToDist",lib_rPointToDist}, {"R_PointToDist2",lib_rPointToDist2}, {"R_PointInSubsector",lib_rPointInSubsector}, + {"R_PointInSubsectorOrNil",lib_rPointInSubsectorOrNil}, // r_things (sprite) {"R_Char2Frame",lib_rChar2Frame}, {"R_Frame2Char",lib_rFrame2Char}, {"R_SetPlayerSkin",lib_rSetPlayerSkin}, + {"R_SkinUsable",lib_rSkinUsable}, // r_data {"R_CheckTextureNumForName",lib_rCheckTextureNumForName}, {"R_TextureNumForName",lib_rTextureNumForName}, + // r_draw + {"R_GetColorByName", lib_rGetColorByName}, + {"R_GetSuperColorByName", lib_rGetSuperColorByName}, + {"R_GetNameByColor", lib_rGetNameByColor}, + // s_sound {"S_StartSound",lib_sStartSound}, {"S_StartSoundAtVolume",lib_sStartSoundAtVolume}, {"S_StopSound",lib_sStopSound}, {"S_StopSoundByID",lib_sStopSoundByID}, - {"S_ShowMusicCredit",lib_sShowMusicCredit}, {"S_ChangeMusic",lib_sChangeMusic}, {"S_SpeedMusic",lib_sSpeedMusic}, {"S_MusicType",lib_sMusicType}, {"S_MusicPlaying",lib_sMusicPlaying}, {"S_MusicPaused",lib_sMusicPaused}, {"S_MusicName",lib_sMusicName}, - {"S_MusicInfo",lib_sMusicInfo}, {"S_MusicExists",lib_sMusicExists}, {"S_GetMusicLength",lib_sGetMusicLength}, {"S_SetMusicLoopPoint",lib_sSetMusicLoopPoint}, @@ -3098,12 +3872,21 @@ static luaL_Reg lib[] = { {"S_StopFadingMusic",lib_sStopFadingMusic}, {"S_FadeMusic",lib_sFadeMusic}, {"S_FadeOutStopMusic",lib_sFadeOutStopMusic}, + {"S_GetMusicLength",lib_sGetMusicLength}, + {"S_GetMusicPosition",lib_sGetMusicPosition}, + {"S_SetMusicPosition",lib_sSetMusicPosition}, {"S_OriginPlaying",lib_sOriginPlaying}, {"S_IdPlaying",lib_sIdPlaying}, {"S_SoundPlaying",lib_sSoundPlaying}, + {"S_StartMusicCaption", lib_sStartMusicCaption}, + {"S_ShowMusicCredit",lib_sShowMusicCredit}, // g_game + {"G_AddGametype", lib_gAddGametype}, {"G_BuildMapName",lib_gBuildMapName}, + {"G_BuildMapTitle",lib_gBuildMapTitle}, + {"G_FindMap",lib_gFindMap}, + {"G_FindMapByNameOrCode",lib_gFindMapByNameOrCode}, {"G_DoReborn",lib_gDoReborn}, {"G_SetCustomExitVars",lib_gSetCustomExitVars}, {"G_ExitLevel",lib_gExitLevel}, @@ -3111,9 +3894,6 @@ static luaL_Reg lib[] = { {"G_GametypeUsesLives",lib_gGametypeUsesLives}, {"G_GametypeHasTeams",lib_gGametypeHasTeams}, {"G_GametypeHasSpectators",lib_gGametypeHasSpectators}, - {"G_BattleGametype",lib_gBattleGametype}, - {"G_RaceGametype",lib_gRaceGametype}, - {"G_TagGametype",lib_gTagGametype}, {"G_TicsToHours",lib_gTicsToHours}, {"G_TicsToMinutes",lib_gTicsToMinutes}, {"G_TicsToSeconds",lib_gTicsToSeconds}, @@ -3128,7 +3908,6 @@ static luaL_Reg lib[] = { {"K_PlayLossSound", lib_kLossSound}, {"K_PlayPainSound", lib_kPainSound}, {"K_PlayHitEmSound", lib_kHitEmSound}, - {"K_GetKartColorByName",lib_kGetKartColorByName}, {"K_IsPlayerLosing",lib_kIsPlayerLosing}, {"K_IsPlayerWanted",lib_kIsPlayerWanted}, {"K_KartBouncing",lib_kKartBouncing}, @@ -3160,10 +3939,6 @@ static luaL_Reg lib[] = { {"K_GetKartAccel",lib_kGetKartAccel}, {"K_GetKartFlashing",lib_kGetKartFlashing}, {"K_GetItemPatch",lib_kGetItemPatch}, - {"K_SetRaceCountdown",lib_kSetRaceCountdown}, - {"K_SetExitCountdown",lib_kSetExitCountdown}, - {"K_SetIndirectItemCooldown",lib_kSetIndirectItemCountdown}, - {"K_SetHyudoroCooldown",lib_kSetHyuCountdown}, {NULL, NULL} }; @@ -3185,5 +3960,3 @@ int LUA_BaseLib(lua_State *L) luaL_register(L, NULL, lib); return 0; } - -#endif diff --git a/src/lua_blockmaplib.c b/src/lua_blockmaplib.c index dabbdd9f6..1949d56bb 100644 --- a/src/lua_blockmaplib.c +++ b/src/lua_blockmaplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2016 by Iestyn "Monster Iestyn" Jealous. -// Copyright (C) 2016 by Sonic Team Junior. +// Copyright (C) 2016-2020 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2016-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,9 +11,9 @@ /// \brief blockmap library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA #include "p_local.h" #include "r_main.h" // validcount +#include "p_polyobj.h" #include "lua_script.h" #include "lua_libs.h" //#include "lua_hud.h" // hud_running errors @@ -21,6 +21,7 @@ static const char *const search_opt[] = { "objects", "lines", + "polyobjs", NULL}; // a quickly-made function pointer typedef used by lib_searchBlockmap... @@ -54,10 +55,12 @@ static UINT8 lib_searchBlockmap_Objects(lua_State *L, INT32 x, INT32 y, mobj_t * CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); blockfuncerror = true; + P_SetTarget(&bnext, NULL); return 0; // *shrugs* } if (!lua_isnil(gL, -1)) { // if nil, continue + P_SetTarget(&bnext, NULL); if (lua_toboolean(gL, -1)) return 2; // stop whole search else @@ -79,9 +82,7 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th { INT32 offset; const INT32 *list; // Big blockmap -#ifdef POLYOBJECTS polymaplink_t *plink; // haleyjd 02/22/06 -#endif line_t *ld; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) @@ -89,7 +90,6 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th offset = y*bmapwidth + x; -#ifdef POLYOBJECTS // haleyjd 02/22/06: consider polyobject lines plink = polyblocklinks[offset]; @@ -132,7 +132,6 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th } plink = (polymaplink_t *)(plink->link.next); } -#endif offset = *(blockmap + offset); // offset = blockmap[y*bmapwidth+x]; @@ -170,6 +169,55 @@ static UINT8 lib_searchBlockmap_Lines(lua_State *L, INT32 x, INT32 y, mobj_t *th return 0; // Everything was checked. } +// Helper function for "polyobjs" search +static UINT8 lib_searchBlockmap_PolyObjs(lua_State *L, INT32 x, INT32 y, mobj_t *thing) +{ + INT32 offset; + polymaplink_t *plink; // haleyjd 02/22/06 + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + return 0; + + offset = y*bmapwidth + x; + + // haleyjd 02/22/06: consider polyobject lines + plink = polyblocklinks[offset]; + + while (plink) + { + polyobj_t *po = plink->po; + + if (po->validcount != validcount) // if polyobj hasn't been checked + { + po->validcount = validcount; + + lua_pushvalue(L, 1); + LUA_PushUserdata(L, thing, META_MOBJ); + LUA_PushUserdata(L, po, META_POLYOBJ); + if (lua_pcall(gL, 2, 1, 0)) { + if (!blockfuncerror || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + blockfuncerror = true; + return 0; // *shrugs* + } + if (!lua_isnil(gL, -1)) + { // if nil, continue + if (lua_toboolean(gL, -1)) + return 2; // stop whole search + else + return 1; // stop block search + } + lua_pop(gL, 1); + if (P_MobjWasRemoved(thing)) + return 2; + } + plink = (polymaplink_t *)(plink->link.next); + } + + return 0; // Everything was checked. +} + // The searchBlockmap function // arguments: searchBlockmap(searchtype, function, mobj, [x1, x2, y1, y2]) // return value: @@ -198,6 +246,9 @@ static int lib_searchBlockmap(lua_State *L) case 1: // "lines" searchFunc = lib_searchBlockmap_Lines; break; + case 2: // "polyobjs" + searchFunc = lib_searchBlockmap_PolyObjs; + break; } // the mobj we are searching around, the "calling" mobj we could say @@ -262,5 +313,3 @@ int LUA_BlockmapLib(lua_State *L) lua_register(L, "searchBlockmap", lib_searchBlockmap); return 0; } - -#endif diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index b0a174d9f..2ef17841f 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,7 +11,6 @@ /// \brief console modifying/etc library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA #include "fastcmp.h" #include "p_local.h" #include "g_game.h" @@ -22,7 +21,12 @@ #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#define NOHUD if (hud_running) return luaL_error(L, "HUD rendering code should not call this function!"); +// for functions not allowed in hud.add hooks +#define NOHUD if (hud_running)\ +return luaL_error(L, "HUD rendering code should not call this function!"); +// for functions not allowed in hooks or coroutines (supercedes above) +#define NOHOOK if (!lua_lumploading)\ + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); static const char *cvname = NULL; @@ -82,21 +86,17 @@ deny: CONS_Alert(CONS_WARNING, M_GetText("Illegal lua command received from %s\n"), player_names[playernum]); if (server) - { - XBOXSTATIC UINT8 bufn[2]; - - bufn[0] = (UINT8)playernum; - bufn[1] = KICK_MSG_CON_FAIL; - SendNetXCmd(XD_KICK, &bufn, 2); - } + SendKick(playernum, KICK_MSG_CON_FAIL | KICK_MSG_KEEP_BODY); } // Wrapper for COM_AddCommand commands void COM_Lua_f(void) { char *buf, *p; - UINT8 i, flags; + UINT8 i; UINT16 len; + UINT16 flags; + UINT8 lpn = 0; INT32 playernum = consoleplayer; I_Assert(gL != NULL); @@ -113,27 +113,30 @@ void COM_Lua_f(void) lua_rawgeti(gL, -1, 2); // push flags from command info table if (lua_isboolean(gL, -1)) - flags = (lua_toboolean(gL, -1) ? 1 : 0); + flags = (lua_toboolean(gL, -1) ? COM_ADMIN : 0); else - flags = (UINT8)lua_tointeger(gL, -1); + flags = (UINT16)lua_tointeger(gL, -1); lua_pop(gL, 1); // pop flags - if (flags & 2) // flag 2: splitscreen player command. TODO: support 4P + if (flags & COM_SPLITSCREEN) // splitscreen player command. { - if (!splitscreen) + lpn = (flags & COM_SPLITSCREEN) >> COM_SSSHIFT; + + if (splitscreen < lpn) { lua_pop(gL, 1); // pop command info table - return; // can't execute splitscreen command without player 2! + return; // can't execute splitscreen command without the player being in-game! } - playernum = g_localplayers[1]; + + playernum = g_localplayers[lpn]; } - if (netgame) + if (netgame && !( flags & COM_LOCAL ))/* don't send local commands */ { // Send the command through the network UINT8 argc; lua_pop(gL, 1); // pop command info table - if (flags & 1 && !server && !IsPlayerAdmin(playernum)) // flag 1: only server/admin can use this command. + if ((flags & COM_ADMIN) && !server && !IsPlayerAdmin(playernum)) // only server/admin can use this command. { CONS_Printf(M_GetText("Only the server or a remote admin can use this.\n")); return; @@ -153,10 +156,8 @@ void COM_Lua_f(void) WRITEUINT8(p, argc); for (i = 0; i < argc; i++) WRITESTRINGN(p, COM_Argv(i), 255); - if (flags & 2) - SendNetXCmd2(XD_LUACMD, buf, p-buf); - else - SendNetXCmd(XD_LUACMD, buf, p-buf); + + SendNetXCmdForPlayer(lpn, XD_LUACMD, buf, p-buf); free(buf); return; } @@ -183,11 +184,19 @@ static int lib_comAddCommand(lua_State *L) strlwr(name); luaL_checktype(L, 2, LUA_TFUNCTION); - NOHUD + NOHOOK if (lua_gettop(L) >= 3) { // For the third argument, only take a boolean or a number. lua_settop(L, 3); - if (lua_type(L, 3) != LUA_TBOOLEAN) + if (lua_type(L, 3) == LUA_TBOOLEAN) + { + CONS_Alert(CONS_WARNING, + "Using a boolean for admin commands is " + "deprecated and will be removed.\n" + "Use \"COM_ADMIN\" instead.\n" + ); + } + else luaL_checktype(L, 3, LUA_TNUMBER); } else @@ -230,34 +239,32 @@ static int lib_comAddCommand(lua_State *L) static int lib_comBufAddText(lua_State *L) { int n = lua_gettop(L); /* number of arguments */ - player_t *plr; + player_t *plr = NULL; if (n < 2) return luaL_error(L, "COM_BufAddText requires two arguments: player and text."); NOHUD lua_settop(L, 2); - plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - if (!plr) - return LUA_ErrInvalid(L, "player_t"); - if (plr != &players[consoleplayer]) + if (!lua_isnoneornil(L, 1)) + plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + if (plr && plr != &players[consoleplayer]) return 0; - COM_BufAddText(va("%s\n", luaL_checkstring(L, 2))); + COM_BufAddTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE); return 0; } static int lib_comBufInsertText(lua_State *L) { int n = lua_gettop(L); /* number of arguments */ - player_t *plr; + player_t *plr = NULL; if (n < 2) return luaL_error(L, "COM_BufInsertText requires two arguments: player and text."); NOHUD lua_settop(L, 2); - plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); - if (!plr) - return LUA_ErrInvalid(L, "player_t"); - if (plr != &players[consoleplayer]) + if (!lua_isnoneornil(L, 1)) + plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + if (plr && plr != &players[consoleplayer]) return 0; - COM_BufInsertText(va("%s\n", luaL_checkstring(L, 2))); + COM_BufInsertTextEx(va("%s\n", luaL_checkstring(L, 2)), COM_SAFE); return 0; } @@ -295,7 +302,7 @@ static int lib_cvRegisterVar(lua_State *L) consvar_t *cvar; luaL_checktype(L, 1, LUA_TTABLE); lua_settop(L, 1); // Clear out all other possible arguments, leaving only the first one. - NOHUD + NOHOOK cvar = lua_newuserdata(L, sizeof(consvar_t)); luaL_getmetatable(L, META_CVAR); lua_setmetatable(L, -2); @@ -303,6 +310,8 @@ static int lib_cvRegisterVar(lua_State *L) #define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to " LUA_QL("CV_RegisterVar") " (%s)", e); #define TYPEERROR(f, t) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t), luaL_typename(L, -1))) + memset(cvar, 0x00, sizeof(consvar_t)); // zero everything by default + lua_pushnil(L); while (lua_next(L, 1)) { // stack: cvar table, cvar userdata, key/index, value @@ -390,6 +399,13 @@ static int lib_cvRegisterVar(lua_State *L) #undef FIELDERROR #undef TYPEERROR + if (!cvar->name) + return luaL_error(L, M_GetText("Variable has no name!\n")); + if ((cvar->flags & CV_NOINIT) && !(cvar->flags & CV_CALL)) + return luaL_error(L, M_GetText("Variable %s has CV_NOINIT without CV_CALL\n"), cvar->name); + if ((cvar->flags & CV_CALL) && !cvar->func) + return luaL_error(L, M_GetText("Variable %s has CV_CALL without a function\n"), cvar->name); + // stack: cvar table, cvar userdata lua_getfield(L, LUA_REGISTRYINDEX, "CV_Vars"); I_Assert(lua_istable(L, 3)); @@ -436,6 +452,45 @@ static int lib_cvFindVar(lua_State *L) return 0; } +static int CVarSetFunction +( + lua_State *L, + void (*Set)(consvar_t *, const char *), + void (*SetValue)(consvar_t *, INT32) +){ + consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + + switch (lua_type(L, 2)) + { + case LUA_TSTRING: + (*Set)(cvar, lua_tostring(L, 2)); + break; + case LUA_TNUMBER: + (*SetValue)(cvar, (INT32)lua_tonumber(L, 2)); + break; + default: + return luaL_typerror(L, 1, "string or number"); + } + + return 0; +} + +static int lib_cvSet(lua_State *L) +{ + return CVarSetFunction(L, CV_Set, CV_SetValue); +} + +static int lib_cvStealthSet(lua_State *L) +{ + return CVarSetFunction(L, CV_StealthSet, CV_StealthSetValue); +} + +static int lib_cvAddValue(lua_State *L) +{ + consvar_t *cvar = (consvar_t *)luaL_checkudata(L, 1, META_CVAR); + CV_AddValue(cvar, (INT32)luaL_checknumber(L, 2)); + return 0; +} // CONS_Printf for a single player // Use 'print' in baselib for a global message. @@ -447,6 +502,7 @@ static int lib_consPrintf(lua_State *L) if (n < 2) return luaL_error(L, "CONS_Printf requires at least two arguments: player and text."); //HUDSAFE + plr = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); if (!plr) return LUA_ErrInvalid(L, "player_t"); @@ -475,6 +531,10 @@ static luaL_Reg lib[] = { {"COM_BufAddText", lib_comBufAddText}, {"COM_BufInsertText", lib_comBufInsertText}, {"CV_RegisterVar", lib_cvRegisterVar}, + {"CV_FindVar", lib_cvFindVar}, + {"CV_Set", lib_cvSet}, + {"CV_StealthSet", lib_cvStealthSet}, + {"CV_AddValue", lib_cvAddValue}, {"CONS_Printf", lib_consPrintf}, {"CV_FindVar", lib_cvFindVar}, {NULL, NULL} @@ -538,5 +598,3 @@ int LUA_ConsoleLib(lua_State *L) luaL_register(L, NULL, lib); return 0; } - -#endif diff --git a/src/lua_hook.h b/src/lua_hook.h index 6af3941f1..d99d70327 100644 --- a/src/lua_hook.h +++ b/src/lua_hook.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -10,8 +10,6 @@ /// \file lua_hook.h /// \brief hooks for Lua scripting -#ifdef HAVE_BLUA - #include "r_defs.h" #include "d_player.h" @@ -20,9 +18,12 @@ enum hook { hook_MapChange, hook_MapLoad, hook_PlayerJoin, + hook_PreThinkFrame, hook_ThinkFrame, + hook_PostThinkFrame, hook_MobjSpawn, hook_MobjCollide, + hook_MobjLineCollide, hook_MobjMoveCollide, hook_TouchSpecial, hook_MobjFuse, @@ -39,72 +40,92 @@ enum hook { hook_JumpSpinSpecial, hook_BotTiccmd, hook_BotAI, + hook_BotRespawn, hook_LinedefExecute, hook_PlayerMsg, hook_HurtMsg, hook_PlayerSpawn, + hook_ShieldSpawn, + hook_ShieldSpecial, + hook_MobjMoveBlocked, + hook_MapThingSpawn, + hook_FollowMobj, + hook_PlayerCanDamage, hook_PlayerQuit, hook_MusicChange, - hook_ShouldSpin, //SRB2KART - hook_ShouldExplode, //SRB2KART - hook_ShouldSquish, //SRB2KART - hook_PlayerSpin, //SRB2KART - hook_PlayerExplode, //SRB2KART - hook_PlayerSquish, //SRB2KART - hook_PlayerCmd, //SRB2KART - hook_IntermissionThinker, //SRB2KART - hook_VoteThinker, //SRB2KART + hook_TeamSwitch, + hook_ViewpointSwitch, + hook_SeenPlayer, + hook_PlayerThink, + hook_ShouldJingleContinue, + hook_GameQuit, + hook_PlayerCmd, + + // SRB2Kart + hook_IntermissionThinker, + hook_VoteThinker, hook_MAX // last hook }; extern const char *const hookNames[]; -extern boolean hook_cmd_running; // This is used by PlayerCmd and lua_playerlib to prevent anything from being wirtten to player while we run PlayerCmd. +extern boolean hook_cmd_running; void LUAh_MapChange(INT16 mapnumber); // Hook for map change (before load) void LUAh_MapLoad(void); // Hook for map load void LUAh_PlayerJoin(int playernum); // Hook for Got_AddPlayer +void LUAh_PreThinkFrame(void); // Hook for frame (before mobj and player thinkers) void LUAh_ThinkFrame(void); // Hook for frame (after mobj and player thinkers) +void LUAh_PostThinkFrame(void); // Hook for frame (at end of tick, ie after overlays, precipitation, specials) boolean LUAh_MobjHook(mobj_t *mo, enum hook which); boolean LUAh_PlayerHook(player_t *plr, enum hook which); #define LUAh_MobjSpawn(mo) LUAh_MobjHook(mo, hook_MobjSpawn) // Hook for P_SpawnMobj by mobj type UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which); +UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which); #define LUAh_MobjCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjCollide) // Hook for PIT_CheckThing by (thing) mobj type +#define LUAh_MobjLineCollide(thing, line) LUAh_MobjLineCollideHook(thing, line, hook_MobjLineCollide) // Hook for PIT_CheckThing by (thing) mobj type #define LUAh_MobjMoveCollide(thing1, thing2) LUAh_MobjCollideHook(thing1, thing2, hook_MobjMoveCollide) // Hook for PIT_CheckThing by (tmthing) mobj type boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher); // Hook for P_TouchSpecialThing by mobj type #define LUAh_MobjFuse(mo) LUAh_MobjHook(mo, hook_MobjFuse) // Hook for mobj->fuse == 0 by mobj type boolean LUAh_MobjThinker(mobj_t *mo); // Hook for P_MobjThinker or P_SceneryThinker by mobj type #define LUAh_BossThinker(mo) LUAh_MobjHook(mo, hook_BossThinker) // Hook for P_GenericBossThinker by mobj type -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); // Hook for P_DamageMobj by mobj type (Should mobj take damage?) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source); // Hook for P_KillMobj by mobj type +UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Should mobj take damage?) +boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); // Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) +boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for P_KillMobj by mobj type #define LUAh_BossDeath(mo) LUAh_MobjHook(mo, hook_BossDeath) // Hook for A_BossDeath by mobj type #define LUAh_MobjRemoved(mo) LUAh_MobjHook(mo, hook_MobjRemoved) // Hook for P_RemoveMobj by mobj type #define LUAh_JumpSpecial(player) LUAh_PlayerHook(player, hook_JumpSpecial) // Hook for P_DoJumpStuff (Any-jumping) #define LUAh_AbilitySpecial(player) LUAh_PlayerHook(player, hook_AbilitySpecial) // Hook for P_DoJumpStuff (Double-jumping) -#define LUAh_SpinSpecial(player) LUAh_PlayerHook(player, hook_SpinSpecial) // Hook for P_DoSpinDash (Spin button effect) +#define LUAh_SpinSpecial(player) LUAh_PlayerHook(player, hook_SpinSpecial) // Hook for P_DoSpinAbility (Spin button effect) #define LUAh_JumpSpinSpecial(player) LUAh_PlayerHook(player, hook_JumpSpinSpecial) // Hook for P_DoJumpStuff (Spin button effect (mid-air)) boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd); // Hook for B_BuildTiccmd boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd); // Hook for B_BuildTailsTiccmd by skin name +boolean LUAh_BotRespawn(mobj_t *sonic, mobj_t *tails); // Hook for B_CheckRespawn boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector); // Hook for linedef executors boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute); // Hook for chat messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source); // Hook for hurt messages +boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); // Hook for hurt messages #define LUAh_PlayerSpawn(player) LUAh_PlayerHook(player, hook_PlayerSpawn) // Hook for G_SpawnPlayer -void LUAh_PlayerQuit(player_t *plr, int reason); // Hook for player quitting +void LUAh_PlayerQuit(player_t *plr, kickreason_t reason); // Hook for player quitting boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms); // Hook for music changes -UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be spun out? -UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be exploded? -UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Should player be squished? - -boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SpinPlayer. Allows Lua to execute code and/or overwrite its behavior. -boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_ExplodePlayer. Allows Lua to execute code and/or overwrite its behavior. -boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source); // SRB2KART: Hook for K_SquishPlayer. Allows Lua to execute code and/or overwrite its behavior. - boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Allows to write to player cmd before the game does anything with them. void LUAh_IntermissionThinker(void); // Hook for Y_Ticker void LUAh_VoteThinker(void); // Hook for Y_VoteTicker +#define LUAh_ShieldSpawn(player) LUAh_PlayerHook(player, hook_ShieldSpawn) // Hook for P_SpawnShieldOrb +#define LUAh_ShieldSpecial(player) LUAh_PlayerHook(player, hook_ShieldSpecial) // Hook for shield abilities +#define LUAh_MobjMoveBlocked(mo) LUAh_MobjHook(mo, hook_MobjMoveBlocked) // Hook for P_XYMovement (when movement is blocked) +boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing); // Hook for P_SpawnMapThing by mobj type +boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj); // Hook for P_PlayerAfterThink Smiles mobj-following +UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj); // Hook for P_PlayerCanDamage +boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble); // Hook for team switching in... uh.... +UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced); // Hook for spy mode +#ifdef SEENAMES +boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend); // Hook for MT_NAMECHECK #endif +#define LUAh_PlayerThink(player) LUAh_PlayerHook(player, hook_PlayerThink) // Hook for P_PlayerThink +boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname); // Hook for whether a jingle of the given music should continue playing +void LUAh_GameQuit(void); // Hook for game quitting +boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd); // Hook for building player's ticcmd struct (Ported from SRB2Kart) diff --git a/src/lua_hooklib.c b/src/lua_hooklib.c index 1e7299461..b1f07d4a4 100644 --- a/src/lua_hooklib.c +++ b/src/lua_hooklib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,11 +11,10 @@ /// \brief hooks for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA #include "doomstat.h" #include "p_mobj.h" #include "g_game.h" -#include "r_things.h" +#include "r_skins.h" #include "k_bot.h" #include "z_zone.h" @@ -24,6 +23,10 @@ #include "lua_hook.h" #include "lua_hud.h" // hud_running errors +#include "m_perfstats.h" +#include "d_netcmd.h" // for cv_perfstats +#include "i_system.h" // I_GetTimeMicros + static UINT8 hooksAvailable[(hook_MAX/8)+1]; const char *const hookNames[hook_MAX+1] = { @@ -31,9 +34,12 @@ const char *const hookNames[hook_MAX+1] = { "MapChange", "MapLoad", "PlayerJoin", + "PreThinkFrame", "ThinkFrame", + "PostThinkFrame", "MobjSpawn", "MobjCollide", + "MobjLineCollide", "MobjMoveCollide", "TouchSpecial", "MobjFuse", @@ -50,21 +56,31 @@ const char *const hookNames[hook_MAX+1] = { "JumpSpinSpecial", "BotTiccmd", "BotAI", + "BotRespawn", "LinedefExecute", "PlayerMsg", "HurtMsg", "PlayerSpawn", + "ShieldSpawn", + "ShieldSpecial", + "MobjMoveBlocked", + "MapThingSpawn", + "FollowMobj", + "PlayerCanDamage", "PlayerQuit", "MusicChange", - "ShouldSpin", - "ShouldExplode", - "ShouldSquish", - "PlayerSpin", - "PlayerExplode", - "PlayerSquish", + "TeamSwitch", + "ViewpointSwitch", + "SeenPlayer", + "PlayerThink", + "ShouldJingleContinue", + "GameQuit", "PlayerCmd", + + // SRB2Kart "IntermissionThinker", "VoteThinker", + NULL }; @@ -76,8 +92,7 @@ struct hook_s UINT16 id; union { mobjtype_t mt; - char *skinname; - char *funcname; + char *str; } s; boolean error; }; @@ -104,6 +119,12 @@ static hook_p linedefexecutorhooks; // For other hooks, a unique linked list hook_p roothook; +static void PushHook(lua_State *L, hook_p hookp) +{ + lua_pushfstring(L, FMT_HOOKID, hookp->id); + lua_gettable(L, LUA_REGISTRYINDEX); +} + // Takes hook, function, and additional arguments (mobj type to act on, etc.) static int lib_addHook(lua_State *L) { @@ -116,14 +137,15 @@ static int lib_addHook(lua_State *L) luaL_checktype(L, 1, LUA_TFUNCTION); - if (hud_running) - return luaL_error(L, "HUD rendering code should not call this function!"); + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); switch(hook.type) { // Take a mobjtype enum which this hook is specifically for. case hook_MobjSpawn: case hook_MobjCollide: + case hook_MobjLineCollide: case hook_MobjMoveCollide: case hook_TouchSpecial: case hook_MobjFuse: @@ -135,41 +157,27 @@ static int lib_addHook(lua_State *L) case hook_BossDeath: case hook_MobjRemoved: case hook_HurtMsg: + case hook_MobjMoveBlocked: + case hook_MapThingSpawn: + case hook_FollowMobj: hook.s.mt = MT_NULL; if (lua_isnumber(L, 2)) hook.s.mt = lua_tonumber(L, 2); luaL_argcheck(L, hook.s.mt < NUMMOBJTYPES, 2, "invalid mobjtype_t"); break; case hook_BotAI: - hook.s.skinname = NULL; + case hook_ShouldJingleContinue: + hook.s.str = NULL; if (lua_isstring(L, 2)) { // lowercase copy - const char *s = lua_tostring(L, 2); - char *p = hook.s.skinname = ZZ_Alloc(strlen(s)+1); - do { - *p = tolower(*s); - ++p; - } while(*(++s)); - *p = 0; + hook.s.str = Z_StrDup(lua_tostring(L, 2)); + strlwr(hook.s.str); } break; case hook_LinedefExecute: // Linedef executor functions - { // uppercase copy - const char *s = luaL_checkstring(L, 2); - char *p = hook.s.funcname = ZZ_Alloc(strlen(s)+1); - do { - *p = toupper(*s); - ++p; - } while(*(++s)); - *p = 0; - } + hook.s.str = Z_StrDup(luaL_checkstring(L, 2)); + strupr(hook.s.str); break; - case hook_ShouldSpin: - case hook_ShouldExplode: - case hook_ShouldSquish: - case hook_PlayerSpin: - case hook_PlayerExplode: - case hook_PlayerSquish: default: break; } @@ -187,6 +195,7 @@ static int lib_addHook(lua_State *L) lastp = &mobjthinkerhooks[hook.s.mt]; break; case hook_MobjCollide: + case hook_MobjLineCollide: case hook_MobjMoveCollide: lastp = &mobjcollidehooks[hook.s.mt]; break; @@ -199,6 +208,9 @@ static int lib_addHook(lua_State *L) case hook_MobjDeath: case hook_BossDeath: case hook_MobjRemoved: + case hook_MobjMoveBlocked: + case hook_MapThingSpawn: + case hook_FollowMobj: lastp = &mobjhooks[hook.s.mt]; break; case hook_JumpSpecial: @@ -206,17 +218,18 @@ static int lib_addHook(lua_State *L) case hook_SpinSpecial: case hook_JumpSpinSpecial: case hook_PlayerSpawn: + case hook_PlayerCanDamage: + case hook_TeamSwitch: + case hook_ViewpointSwitch: + case hook_SeenPlayer: + case hook_ShieldSpawn: + case hook_ShieldSpecial: + case hook_PlayerThink: lastp = &playerhooks; break; case hook_LinedefExecute: lastp = &linedefexecutorhooks; break; - case hook_ShouldSpin: - case hook_ShouldExplode: - case hook_ShouldSquish: - case hook_PlayerSpin: - case hook_PlayerExplode: - case hook_PlayerSquish: default: lastp = &roothook; break; @@ -256,48 +269,56 @@ boolean LUAh_MobjHook(mobj_t *mo, enum hook which) I_Assert(mo->type < NUMMOBJTYPES); + if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type])) + return false; + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); // Look for all generic mobj hooks for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == which) - { - if (lua_gettop(gL) == 0) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; + { + if (hookp->type != which) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + LUA_PushUserdata(gL, mo, META_MOBJ); + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); + hookp->error = true; + continue; } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) - if (hookp->type == which) - { - if (lua_gettop(gL) == 0) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; + { + if (hookp->type != which) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + LUA_PushUserdata(gL, mo, META_MOBJ); + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); + hookp->error = true; + continue; } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -311,26 +332,29 @@ boolean LUAh_PlayerHook(player_t *plr, enum hook which) return false; lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); for (hookp = playerhooks; hookp; hookp = hookp->next) - if (hookp->type == which) - { - if (lua_gettop(gL) == 0) - LUA_PushUserdata(gL, plr, META_PLAYER); - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; + { + if (hookp->type != which) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + LUA_PushUserdata(gL, plr, META_PLAYER); + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); + hookp->error = true; + continue; } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } lua_settop(gL, 0); return hooked; @@ -344,16 +368,21 @@ void LUAh_MapChange(INT16 mapnumber) return; lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushinteger(gL, mapnumber); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MapChange) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - LUA_Call(gL, 1); + { + if (hookp->type != hook_MapChange) + continue; + + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 0, 1)) { + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); } + } lua_settop(gL, 0); } @@ -366,16 +395,21 @@ void LUAh_MapLoad(void) return; lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushinteger(gL, gamemap); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MapLoad) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - LUA_Call(gL, 1); + { + if (hookp->type != hook_MapLoad) + continue; + + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 0, 1)) { + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); } + } lua_settop(gL, 0); } @@ -388,39 +422,1230 @@ void LUAh_PlayerJoin(int playernum) return; lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); lua_pushinteger(gL, playernum); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerJoin) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - LUA_Call(gL, 1); + { + if (hookp->type != hook_PlayerJoin) + continue; + + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 0, 1)) { + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); } + } lua_settop(gL, 0); } +// Hook for frame (before mobj and player thinkers) +void LUAh_PreThinkFrame(void) +{ + hook_p hookp; + if (!gL || !(hooksAvailable[hook_PreThinkFrame/8] & (1<<(hook_PreThinkFrame%8)))) + return; + + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PreThinkFrame) + continue; + + PushHook(gL, hookp); + if (lua_pcall(gL, 0, 0, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + } + } + + lua_pop(gL, 1); // Pop error handler +} + // Hook for frame (after mobj and player thinkers) void LUAh_ThinkFrame(void) { hook_p hookp; + // variables used by perf stats + int hook_index = 0; + int time_taken = 0; if (!gL || !(hooksAvailable[hook_ThinkFrame/8] & (1<<(hook_ThinkFrame%8)))) return; + lua_pushcfunction(gL, LUA_GetErrorMessage); + for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_ThinkFrame) + { + if (hookp->type != hook_ThinkFrame) + continue; + + if (cv_perfstats.value == 3) + time_taken = I_GetTimeMicros(); + PushHook(gL, hookp); + if (lua_pcall(gL, 0, 0, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + } + if (cv_perfstats.value == 3) { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - if (lua_pcall(gL, 0, 0, 0)) { + lua_Debug ar; + time_taken = I_GetTimeMicros() - time_taken; + // we need the function, let's just retrieve it again + PushHook(gL, hookp); + lua_getinfo(gL, ">S", &ar); + PS_SetThinkFrameHookInfo(hook_index, time_taken, ar.short_src); + hook_index++; + } + } + + lua_pop(gL, 1); // Pop error handler +} + +// Hook for frame (at end of tick, ie after overlays, precipitation, specials) +void LUAh_PostThinkFrame(void) +{ + hook_p hookp; + if (!gL || !(hooksAvailable[hook_PostThinkFrame/8] & (1<<(hook_PostThinkFrame%8)))) + return; + + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PostThinkFrame) + continue; + + PushHook(gL, hookp); + if (lua_pcall(gL, 0, 0, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + } + } + + lua_pop(gL, 1); // Pop error handler +} + +// Hook for mobj collisions +UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) +{ + hook_p hookp; + UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) + return 0; + + I_Assert(thing1->type < NUMMOBJTYPES); + + if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing1->type])) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic mobj collision hooks + for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != which) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, thing1, META_MOBJ); + LUA_PushUserdata(gL, thing2, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + for (hookp = mobjcollidehooks[thing1->type]; hookp; hookp = hookp->next) + { + if (hookp->type != which) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, thing1, META_MOBJ); + LUA_PushUserdata(gL, thing2, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return shouldCollide; +} + +UINT8 LUAh_MobjLineCollideHook(mobj_t *thing, line_t *line, enum hook which) +{ + hook_p hookp; + UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) + return 0; + + I_Assert(thing->type < NUMMOBJTYPES); + + if (!(mobjcollidehooks[MT_NULL] || mobjcollidehooks[thing->type])) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic mobj collision hooks + for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != which) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, thing, META_MOBJ); + LUA_PushUserdata(gL, line, META_LINE); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + for (hookp = mobjcollidehooks[thing->type]; hookp; hookp = hookp->next) + { + if (hookp->type != which) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, thing, META_MOBJ); + LUA_PushUserdata(gL, line, META_LINE); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return shouldCollide; +} + +// Hook for mobj thinkers +boolean LUAh_MobjThinker(mobj_t *mo) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8)))) + return false; + + I_Assert(mo->type < NUMMOBJTYPES); + + if (!(mobjthinkerhooks[MT_NULL] || mobjthinkerhooks[mo->type])) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic mobj thinker hooks + for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next) + { + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + LUA_PushUserdata(gL, mo, META_MOBJ); + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + for (hookp = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next) + { + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + LUA_PushUserdata(gL, mo, META_MOBJ); + PushHook(gL, hookp); + lua_pushvalue(gL, -2); + if (lua_pcall(gL, 1, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for P_TouchSpecialThing by mobj type +boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8)))) + return false; + + I_Assert(special->type < NUMMOBJTYPES); + + if (!(mobjhooks[MT_NULL] || mobjhooks[special->type])) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic touch special hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_TouchSpecial) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, special, META_MOBJ); + LUA_PushUserdata(gL, toucher, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + for (hookp = mobjhooks[special->type]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_TouchSpecial) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, special, META_MOBJ); + LUA_PushUserdata(gL, toucher, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for P_DamageMobj by mobj type (Should mobj take damage?) +UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +{ + hook_p hookp; + UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8)))) + return 0; + + I_Assert(target->type < NUMMOBJTYPES); + + if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic should damage hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_ShouldDamage) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { + if (lua_toboolean(gL, -1)) + shouldDamage = 1; // Force yes + else + shouldDamage = 2; // Force no + } + lua_pop(gL, 1); + } + + for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_ShouldDamage) + continue; + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { + if (lua_toboolean(gL, -1)) + shouldDamage = 1; // Force yes + else + shouldDamage = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return shouldDamage; +} + +// Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) +boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8)))) + return false; + + I_Assert(target->type < NUMMOBJTYPES); + + if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic mobj damage hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_MobjDamage) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_MobjDamage) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damage); + lua_pushinteger(gL, damagetype); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for P_KillMobj by mobj type +boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8)))) + return false; + + I_Assert(target->type < NUMMOBJTYPES); + + if (!(mobjhooks[MT_NULL] || mobjhooks[target->type])) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic mobj death hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_MobjDeath) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_MobjDeath) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, target, META_MOBJ); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for B_BuildTiccmd +boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8)))) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_BotTiccmd) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, bot, META_PLAYER); + LUA_PushUserdata(gL, cmd, META_TICCMD); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for B_BuildTailsTiccmd by skin name +boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) +{ +#if 1 + (void)sonic; + (void)tails; + (void)cmd; + return false; +#else + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8)))) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_BotAI + || (hookp->s.str && strcmp(hookp->s.str, ((skin_t*)tails->skin)->name))) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, sonic, META_MOBJ); + LUA_PushUserdata(gL, tails, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 8, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + + // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. + if (lua_istable(gL, 2+1)) { + boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false; +#define CHECKFIELD(field) \ + lua_getfield(gL, 2+1, #field);\ + if (lua_toboolean(gL, -1))\ + field = true;\ + lua_pop(gL, 1); + + CHECKFIELD(forward) + CHECKFIELD(backward) + CHECKFIELD(left) + CHECKFIELD(right) + CHECKFIELD(strafeleft) + CHECKFIELD(straferight) + CHECKFIELD(jump) + CHECKFIELD(spin) +#undef CHECKFIELD + B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin); + } else + B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8)); + + lua_pop(gL, 8); + hooked = true; + } + + lua_settop(gL, 0); + return hooked; +#endif +} + +// Hook for B_CheckRespawn +boolean LUAh_BotRespawn(mobj_t *sonic, mobj_t *tails) +{ + hook_p hookp; + UINT8 shouldRespawn = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[hook_BotRespawn/8] & (1<<(hook_BotRespawn%8)))) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_BotRespawn) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, sonic, META_MOBJ); + LUA_PushUserdata(gL, tails, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { + if (lua_toboolean(gL, -1)) + shouldRespawn = 1; // Force yes + else + shouldRespawn = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return shouldRespawn; +} + +// Hook for linedef executors +boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8)))) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next) + { + if (strcmp(hookp->s.str, line->stringargs[0])) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, line, META_LINE); + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, sector, META_SECTOR); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + if (lua_pcall(gL, 3, 0, 1)) { + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + } + hooked = true; + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for player chat +// Added the "mute" field. It's set to true if the message was supposed to be eaten by spam protection. +// But for netgame consistency purposes, this hook is ran first reguardless, so this boolean allows for modders to adapt if they so desire. +boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8)))) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PlayerMsg) + continue; + + if (lua_gettop(gL) == 1) + { + if (lua_gettop(gL) == 0) + { + LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player + if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c + lua_pushinteger(gL, 3); // type + lua_pushnil(gL); // target + } else if (target == -1) { // sayteam + lua_pushinteger(gL, 1); // type + lua_pushnil(gL); // target + } else if (target == 0) { // say + lua_pushinteger(gL, 0); // type + lua_pushnil(gL); // target + } else { // sayto + lua_pushinteger(gL, 2); // type + LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target + } + lua_pushstring(gL, msg); // msg + if (mute) + lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc. + else + lua_pushboolean(gL, false); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 4, 1, 1)) { if (!hookp->error || cv_debug & DBG_LUA) CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); lua_pop(gL, 1); hookp->error = true; + continue; } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); } + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for hurt messages +boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_HurtMsg/8] & (1<<(hook_HurtMsg%8)))) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_HurtMsg + || (hookp->s.mt && !(inflictor && hookp->s.mt == inflictor->type))) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, inflictor, META_MOBJ); + LUA_PushUserdata(gL, source, META_MOBJ); + lua_pushinteger(gL, damagetype); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + lua_pushvalue(gL, -5); + if (lua_pcall(gL, 4, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + +void LUAh_NetArchiveHook(lua_CFunction archFunc) +{ + hook_p hookp; + int errorhandlerindex; + if (!gL || !(hooksAvailable[hook_NetVars/8] & (1<<(hook_NetVars%8)))) + return; + + // stack: tables + I_Assert(lua_gettop(gL) > 0); + I_Assert(lua_istable(gL, -1)); + + lua_pushcfunction(gL, LUA_GetErrorMessage); + errorhandlerindex = lua_gettop(gL); + + // tables becomes an upvalue of archFunc + lua_pushvalue(gL, -2); + lua_pushcclosure(gL, archFunc, 1); + // stack: tables, archFunc + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_NetVars) + continue; + + PushHook(gL, hookp); + lua_pushvalue(gL, -2); // archFunc + if (lua_pcall(gL, 1, 0, errorhandlerindex)) { + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + } + } + + lua_pop(gL, 2); // Pop archFunc and error handler + // stack: tables +} + +boolean LUAh_MapThingSpawn(mobj_t *mo, mapthing_t *mthing) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_MapThingSpawn/8] & (1<<(hook_MapThingSpawn%8)))) + return false; + + if (!(mobjhooks[MT_NULL] || mobjhooks[mo->type])) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic mobj map thing spawn hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_MapThingSpawn) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, mthing, META_MAPTHING); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + for (hookp = mobjhooks[mo->type]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_MapThingSpawn) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, mo, META_MOBJ); + LUA_PushUserdata(gL, mthing, META_MAPTHING); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for P_PlayerAfterThink Smiles mobj-following +boolean LUAh_FollowMobj(player_t *player, mobj_t *mobj) +{ + hook_p hookp; + boolean hooked = false; + if (!gL || !(hooksAvailable[hook_FollowMobj/8] & (1<<(hook_FollowMobj%8)))) + return 0; + + if (!(mobjhooks[MT_NULL] || mobjhooks[mobj->type])) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + // Look for all generic mobj follow item hooks + for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_FollowMobj) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + for (hookp = mobjhooks[mobj->type]; hookp; hookp = hookp->next) + { + if (hookp->type != hook_FollowMobj) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (lua_toboolean(gL, -1)) + hooked = true; + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return hooked; +} + +// Hook for P_PlayerCanDamage +UINT8 LUAh_PlayerCanDamage(player_t *player, mobj_t *mobj) +{ + hook_p hookp; + UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[hook_PlayerCanDamage/8] & (1<<(hook_PlayerCanDamage%8)))) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PlayerCanDamage) + continue; + + ps_lua_mobjhooks++; + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, mobj, META_MOBJ); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave shouldCollide = 0. + if (lua_toboolean(gL, -1)) + shouldCollide = 1; // Force yes + else + shouldCollide = 2; // Force no + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return shouldCollide; +} + +void LUAh_PlayerQuit(player_t *plr, kickreason_t reason) +{ + hook_p hookp; + if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) + return; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_PlayerQuit) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit + lua_pushinteger(gL, reason); // Reason for quitting + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 0, 1)) { + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + } + } + + lua_settop(gL, 0); } // Hook for Y_Ticker @@ -430,18 +1655,273 @@ void LUAh_IntermissionThinker(void) if (!gL || !(hooksAvailable[hook_IntermissionThinker/8] & (1<<(hook_IntermissionThinker%8)))) return; + lua_pushcfunction(gL, LUA_GetErrorMessage); + for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_IntermissionThinker) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - if (lua_pcall(gL, 0, 0, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - } + { + if (hookp->type != hook_IntermissionThinker) + continue; + + PushHook(gL, hookp); + if (lua_pcall(gL, 0, 0, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; } + } + + lua_pop(gL, 1); // Pop error handler +} + +// Hook for team switching +// It's just an edit of LUAh_ViewpointSwitch. +boolean LUAh_TeamSwitch(player_t *player, int newteam, boolean fromspectators, boolean tryingautobalance, boolean tryingscramble) +{ + hook_p hookp; + boolean canSwitchTeam = true; + if (!gL || !(hooksAvailable[hook_TeamSwitch/8] & (1<<(hook_TeamSwitch%8)))) + return true; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_TeamSwitch) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushinteger(gL, newteam); + lua_pushboolean(gL, fromspectators); + lua_pushboolean(gL, tryingautobalance); + lua_pushboolean(gL, tryingscramble); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + lua_pushvalue(gL, -6); + if (lua_pcall(gL, 5, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + canSwitchTeam = false; // Can't switch team + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + return canSwitchTeam; +} + +// Hook for spy mode +UINT8 LUAh_ViewpointSwitch(player_t *player, player_t *newdisplayplayer, boolean forced) +{ + hook_p hookp; + UINT8 canSwitchView = 0; // 0 = default, 1 = force yes, 2 = force no. + if (!gL || !(hooksAvailable[hook_ViewpointSwitch/8] & (1<<(hook_ViewpointSwitch%8)))) + return 0; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + hud_running = true; // local hook + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_ViewpointSwitch) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, newdisplayplayer, META_PLAYER); + lua_pushboolean(gL, forced); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + lua_pushvalue(gL, -4); + if (lua_pcall(gL, 3, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1)) + { // if nil, leave canSwitchView = 0. + if (lua_toboolean(gL, -1)) + canSwitchView = 1; // Force viewpoint switch + else + canSwitchView = 2; // Skip viewpoint switch + } + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + + hud_running = false; + + return canSwitchView; +} + +// Hook for MT_NAMECHECK +#ifdef SEENAMES +boolean LUAh_SeenPlayer(player_t *player, player_t *seenfriend) +{ + hook_p hookp; + boolean hasSeenPlayer = true; + if (!gL || !(hooksAvailable[hook_SeenPlayer/8] & (1<<(hook_SeenPlayer%8)))) + return true; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + hud_running = true; // local hook + + for (hookp = playerhooks; hookp; hookp = hookp->next) + { + if (hookp->type != hook_SeenPlayer) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, player, META_PLAYER); + LUA_PushUserdata(gL, seenfriend, META_PLAYER); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1) && !lua_toboolean(gL, -1)) + hasSeenPlayer = false; // Hasn't seen player + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + + hud_running = false; + + return hasSeenPlayer; +} +#endif // SEENAMES + +boolean LUAh_ShouldJingleContinue(player_t *player, const char *musname) +{ + hook_p hookp; + boolean keepplaying = false; + if (!gL || !(hooksAvailable[hook_ShouldJingleContinue/8] & (1<<(hook_ShouldJingleContinue%8)))) + return true; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + hud_running = true; // local hook + + for (hookp = roothook; hookp; hookp = hookp->next) + { + if (hookp->type != hook_ShouldJingleContinue + || (hookp->s.str && strcmp(hookp->s.str, musname))) + continue; + + if (lua_gettop(gL) == 1) + { + LUA_PushUserdata(gL, player, META_PLAYER); + lua_pushstring(gL, musname); + } + PushHook(gL, hookp); + lua_pushvalue(gL, -3); + lua_pushvalue(gL, -3); + if (lua_pcall(gL, 2, 1, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + continue; + } + if (!lua_isnil(gL, -1) && lua_toboolean(gL, -1)) + keepplaying = true; // Keep playing this boolean + lua_pop(gL, 1); + } + + lua_settop(gL, 0); + + hud_running = false; + + return keepplaying; +} + +// Hook for music changes +boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, + UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms) +{ + hook_p hookp; + boolean hooked = false; + + if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8)))) + return false; + + lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); + + for (hookp = roothook; hookp; hookp = hookp->next) + if (hookp->type == hook_MusicChange) + { + PushHook(gL, hookp); + lua_pushstring(gL, oldname); + lua_pushstring(gL, newname); + lua_pushinteger(gL, *mflags); + lua_pushboolean(gL, *looping); + lua_pushinteger(gL, *position); + lua_pushinteger(gL, *prefadems); + lua_pushinteger(gL, *fadeinms); + if (lua_pcall(gL, 7, 6, 1)) { + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1)); + lua_pop(gL, 1); + continue; + } + + // output 1: true, false, or string musicname override + if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6)) + hooked = true; + else if (lua_isstring(gL, -6)) + strncpy(newname, lua_tostring(gL, -6), 7); + // output 2: mflags override + if (lua_isnumber(gL, -5)) + *mflags = lua_tonumber(gL, -5); + // output 3: looping override + if (lua_isboolean(gL, -4)) + *looping = lua_toboolean(gL, -4); + // output 4: position override + if (lua_isboolean(gL, -3)) + *position = lua_tonumber(gL, -3); + // output 5: prefadems override + if (lua_isboolean(gL, -2)) + *prefadems = lua_tonumber(gL, -2); + // output 6: fadeinms override + if (lua_isboolean(gL, -1)) + *fadeinms = lua_tonumber(gL, -1); + + lua_pop(gL, 7); // Pop returned values and error handler + } + + lua_settop(gL, 0); + newname[6] = 0; + return hooked; } // Hook for Y_VoteTicker @@ -465,463 +1945,30 @@ void LUAh_VoteThinker(void) } } - -// Hook for mobj collisions -UINT8 LUAh_MobjCollideHook(mobj_t *thing1, mobj_t *thing2, enum hook which) +// Hook for game quitting +void LUAh_GameQuit(void) { hook_p hookp; - UINT8 shouldCollide = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[which/8] & (1<<(which%8)))) - return 0; + if (!gL || !(hooksAvailable[hook_GameQuit/8] & (1<<(hook_GameQuit%8)))) + return; - I_Assert(thing1->type < NUMMOBJTYPES); - - lua_settop(gL, 0); - - // Look for all generic mobj collision hooks - for (hookp = mobjcollidehooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == which) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjcollidehooks[thing1->type]; hookp; hookp = hookp->next) - if (hookp->type == which) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, thing1, META_MOBJ); - LUA_PushUserdata(gL, thing2, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { // if nil, leave shouldCollide = 0. - if (lua_toboolean(gL, -1)) - shouldCollide = 1; // Force yes - else - shouldCollide = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldCollide; -} - -// Hook for mobj thinkers -boolean LUAh_MobjThinker(mobj_t *mo) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjThinker/8] & (1<<(hook_MobjThinker%8)))) - return false; - - I_Assert(mo->type < NUMMOBJTYPES); - - lua_settop(gL, 0); - - // Look for all generic mobj thinker hooks - for (hookp = mobjthinkerhooks[MT_NULL]; hookp; hookp = hookp->next) - { - if (lua_gettop(gL) == 0) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjthinkerhooks[mo->type]; hookp; hookp = hookp->next) - { - if (lua_gettop(gL) == 0) - LUA_PushUserdata(gL, mo, META_MOBJ); - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); - if (lua_pcall(gL, 1, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_TouchSpecialThing by mobj type -boolean LUAh_TouchSpecial(mobj_t *special, mobj_t *toucher) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_TouchSpecial/8] & (1<<(hook_TouchSpecial%8)))) - return 0; - - I_Assert(special->type < NUMMOBJTYPES); - - lua_settop(gL, 0); - - // Look for all generic touch special hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_TouchSpecial) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[special->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_TouchSpecial) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, special, META_MOBJ); - LUA_PushUserdata(gL, toucher, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_DamageMobj by mobj type (Should mobj take damage?) -UINT8 LUAh_ShouldDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) -{ - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_ShouldDamage/8] & (1<<(hook_ShouldDamage%8)))) - return 0; - - I_Assert(target->type < NUMMOBJTYPES); - - lua_settop(gL, 0); - - // Look for all generic should damage hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_ShouldDamage) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_ShouldDamage) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; -} - -// Hook for P_DamageMobj by mobj type (Mobj actually takes damage!) -boolean LUAh_MobjDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjDamage/8] & (1<<(hook_MobjDamage%8)))) - return 0; - - I_Assert(target->type < NUMMOBJTYPES); - - lua_settop(gL, 0); - - // Look for all generic mobj damage hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDamage) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDamage) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - lua_pushinteger(gL, damage); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - lua_pushvalue(gL, -5); - if (lua_pcall(gL, 4, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for P_KillMobj by mobj type -boolean LUAh_MobjDeath(mobj_t *target, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_MobjDeath/8] & (1<<(hook_MobjDeath%8)))) - return 0; - - I_Assert(target->type < NUMMOBJTYPES); - - lua_settop(gL, 0); - - // Look for all generic mobj death hooks - for (hookp = mobjhooks[MT_NULL]; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDeath) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - for (hookp = mobjhooks[target->type]; hookp; hookp = hookp->next) - if (hookp->type == hook_MobjDeath) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, target, META_MOBJ); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for B_BuildTiccmd -boolean LUAh_BotTiccmd(player_t *bot, ticcmd_t *cmd) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_BotTiccmd/8] & (1<<(hook_BotTiccmd%8)))) - return false; - - lua_settop(gL, 0); + lua_pushcfunction(gL, LUA_GetErrorMessage); for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_BotTiccmd) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, bot, META_PLAYER); - LUA_PushUserdata(gL, cmd, META_TICCMD); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } + { + if (hookp->type != hook_GameQuit) + continue; - lua_settop(gL, 0); - return hooked; + PushHook(gL, hookp); + if (lua_pcall(gL, 0, 0, 1)) { + if (!hookp->error || cv_debug & DBG_LUA) + CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); + lua_pop(gL, 1); + hookp->error = true; + } + } + + lua_pop(gL, 1); // Pop error handler } // Hook for G_BuildTicCmd @@ -964,584 +2011,3 @@ boolean LUAh_PlayerCmd(player_t *player, ticcmd_t *cmd) lua_settop(gL, 0); return hooked; } - -// Hook for B_BuildTailsTiccmd by skin name -boolean LUAh_BotAI(mobj_t *sonic, mobj_t *tails, ticcmd_t *cmd) -{ -#if 1 - (void)sonic; - (void)tails; - (void)cmd; - return false; -#else - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_BotAI/8] & (1<<(hook_BotAI%8)))) - return false; - - lua_settop(gL, 0); - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_BotAI - && (hookp->s.skinname == NULL || !strcmp(hookp->s.skinname, ((skin_t*)tails->skin)->name))) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, sonic, META_MOBJ); - LUA_PushUserdata(gL, tails, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - if (lua_pcall(gL, 2, 8, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - - // This turns forward, backward, left, right, jump, and spin into a proper ticcmd for tails. - if (lua_istable(gL, 2+1)) { - boolean forward=false, backward=false, left=false, right=false, strafeleft=false, straferight=false, jump=false, spin=false; -#define CHECKFIELD(field) \ - lua_getfield(gL, 2+1, #field);\ - if (lua_toboolean(gL, -1))\ - field = true;\ - lua_pop(gL, 1); - - CHECKFIELD(forward) - CHECKFIELD(backward) - CHECKFIELD(left) - CHECKFIELD(right) - CHECKFIELD(strafeleft) - CHECKFIELD(straferight) - CHECKFIELD(jump) - CHECKFIELD(spin) -#undef CHECKFIELD - B_KeysToTiccmd(tails, cmd, forward, backward, left, right, strafeleft, straferight, jump, spin); - } else - B_KeysToTiccmd(tails, cmd, lua_toboolean(gL, 2+1), lua_toboolean(gL, 2+2), lua_toboolean(gL, 2+3), lua_toboolean(gL, 2+4), lua_toboolean(gL, 2+5), lua_toboolean(gL, 2+6), lua_toboolean(gL, 2+7), lua_toboolean(gL, 2+8)); - - lua_pop(gL, 8); - hooked = true; - } - - lua_settop(gL, 0); - return hooked; -#endif -} - -// Hook for linedef executors -boolean LUAh_LinedefExecute(line_t *line, mobj_t *mo, sector_t *sector) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_LinedefExecute/8] & (1<<(hook_LinedefExecute%8)))) - return 0; - - lua_settop(gL, 0); - - for (hookp = linedefexecutorhooks; hookp; hookp = hookp->next) - if (!strcmp(hookp->s.funcname, line->text)) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, line, META_LINE); - LUA_PushUserdata(gL, mo, META_MOBJ); - LUA_PushUserdata(gL, sector, META_SECTOR); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - LUA_Call(gL, 3); - hooked = true; - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for player chat -// Added the "mute" field. It's set to true if the message was supposed to be eaten by spam protection. -// But for netgame consistency purposes, this hook is ran first reguardless, so this boolean allows for modders to adapt if they so desire. -boolean LUAh_PlayerMsg(int source, int target, int flags, char *msg, int mute) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_PlayerMsg/8] & (1<<(hook_PlayerMsg%8)))) - return false; - - lua_settop(gL, 0); - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerMsg) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, &players[source], META_PLAYER); // Source player - if (flags & 2 /*HU_CSAY*/) { // csay TODO: make HU_CSAY accessible outside hu_stuff.c - lua_pushinteger(gL, 3); // type - lua_pushnil(gL); // target - } else if (target == -1) { // sayteam - lua_pushinteger(gL, 1); // type - lua_pushnil(gL); // target - } else if (target == 0) { // say - lua_pushinteger(gL, 0); // type - lua_pushnil(gL); // target - } else { // sayto - lua_pushinteger(gL, 2); // type - LUA_PushUserdata(gL, &players[target-1], META_PLAYER); // target - } - lua_pushstring(gL, msg); // msg - if (mute) - lua_pushboolean(gL, true); // the message was supposed to be eaten by spamprotecc. - else - lua_pushboolean(gL, false); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - lua_pushvalue(gL, -6); - if (lua_pcall(gL, 5, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -// Hook for hurt messages -boolean LUAh_HurtMsg(player_t *player, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_HurtMsg/8] & (1<<(hook_HurtMsg%8)))) - return false; - - lua_settop(gL, 0); - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_HurtMsg - && (hookp->s.mt == MT_NULL || (inflictor && hookp->s.mt == inflictor->type))) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return hooked; -} - -void LUAh_NetArchiveHook(lua_CFunction archFunc) -{ - hook_p hookp; - - if (!gL || !(hooksAvailable[hook_NetVars/8] & (1<<(hook_NetVars%8)))) - return; - - // stack: tables - I_Assert(lua_gettop(gL) > 0); - I_Assert(lua_istable(gL, -1)); - - // tables becomes an upvalue of archFunc - lua_pushvalue(gL, -1); - lua_pushcclosure(gL, archFunc, 1); - // stack: tables, archFunc - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_NetVars) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -2); // archFunc - LUA_Call(gL, 1); - } - - lua_pop(gL, 1); // pop archFunc - // stack: tables -} - -void LUAh_PlayerQuit(player_t *plr, int reason) -{ - hook_p hookp; - if (!gL || !(hooksAvailable[hook_PlayerQuit/8] & (1<<(hook_PlayerQuit%8)))) - return; - - lua_settop(gL, 0); - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerQuit) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, plr, META_PLAYER); // Player that quit - lua_pushinteger(gL, reason); // Reason for quitting - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -3); - lua_pushvalue(gL, -3); - LUA_Call(gL, 2); - } - - lua_settop(gL, 0); -} - -// Hook for music changes -boolean LUAh_MusicChange(const char *oldname, char *newname, UINT16 *mflags, boolean *looping, - UINT32 *position, UINT32 *prefadems, UINT32 *fadeinms) -{ - hook_p hookp; - boolean hooked = false; - - if (!gL || !(hooksAvailable[hook_MusicChange/8] & (1<<(hook_MusicChange%8)))) - return false; - - lua_settop(gL, 0); - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_MusicChange) - { - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushstring(gL, oldname); - lua_pushstring(gL, newname); - lua_pushinteger(gL, *mflags); - lua_pushboolean(gL, *looping); - lua_pushinteger(gL, *position); - lua_pushinteger(gL, *prefadems); - lua_pushinteger(gL, *fadeinms); - if (lua_pcall(gL, 7, 6, 0)) { - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1)); - lua_pop(gL, 1); - continue; - } - - // output 1: true, false, or string musicname override - if (lua_isboolean(gL, -6) && lua_toboolean(gL, -6)) - hooked = true; - else if (lua_isstring(gL, -6)) - strncpy(newname, lua_tostring(gL, -6), 7); - // output 2: mflags override - if (lua_isnumber(gL, -5)) - *mflags = lua_tonumber(gL, -5); - // output 3: looping override - if (lua_isboolean(gL, -4)) - *looping = lua_toboolean(gL, -4); - // output 4: position override - if (lua_isboolean(gL, -3)) - *position = lua_tonumber(gL, -3); - // output 5: prefadems override - if (lua_isboolean(gL, -2)) - *prefadems = lua_tonumber(gL, -2); - // output 6: fadeinms override - if (lua_isboolean(gL, -1)) - *fadeinms = lua_tonumber(gL, -1); - - lua_pop(gL, 6); - } - - lua_settop(gL, 0); - newname[6] = 0; - return hooked; -} - -// Hook for K_SpinPlayer. Determines if yes or no we should get damaged reguardless of circumstances. -UINT8 LUAh_ShouldSpin(player_t *player, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_ShouldSpin/8] & (1<<(hook_ShouldSpin%8)))) - return 0; - - lua_settop(gL, 0); - - // We can afford not to check for mobj type because it will always be MT_PLAYER in this case. - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_ShouldSpin) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; -} - -// Hook for K_ExplodePlayer. Determines if yes or no we should get damaged reguardless of circumstances. -UINT8 LUAh_ShouldExplode(player_t *player, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_ShouldExplode/8] & (1<<(hook_ShouldExplode%8)))) - return 0; - - lua_settop(gL, 0); - - // We can afford not to check for mobj type because it will always be MT_PLAYER in this case. - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_ShouldExplode) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; -} - -// Hook for K_SquishPlayer. Determines if yes or no we should get damaged reguardless of circumstances. -UINT8 LUAh_ShouldSquish(player_t *player, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - UINT8 shouldDamage = 0; // 0 = default, 1 = force yes, 2 = force no. - if (!gL || !(hooksAvailable[hook_ShouldSquish/8] & (1<<(hook_ShouldSquish%8)))) - return 0; - - lua_settop(gL, 0); - - // We can afford not to check for mobj type because it will always be MT_PLAYER in this case. - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_ShouldSquish) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (!lua_isnil(gL, -1)) - { - if (lua_toboolean(gL, -1)) - shouldDamage = 1; // Force yes - else - shouldDamage = 2; // Force no - } - lua_pop(gL, 1); - } - - lua_settop(gL, 0); - return shouldDamage; -} - -// Hook for K_SpinPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. -boolean LUAh_PlayerSpin(player_t *player, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_PlayerSpin/8] & (1<<(hook_PlayerSpin%8)))) - return 0; - - lua_settop(gL, 0); - - // We can afford not to look for target->type because it will always be MT_PLAYER. - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerSpin) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - lua_settop(gL, 0); - return hooked; -} - -// Hook for K_SquishPlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. -boolean LUAh_PlayerSquish(player_t *player, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_PlayerSquish/8] & (1<<(hook_PlayerSquish%8)))) - return 0; - - lua_settop(gL, 0); - - // We can afford not to look for target->type because it will always be MT_PLAYER. - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerSquish) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - lua_settop(gL, 0); - return hooked; -} - -// Hook for K_ExplodePlayer. This is used when the player has actually been spun out, but before anything has actually been done. This allows Lua to overwrite the behavior or to just perform actions. -boolean LUAh_PlayerExplode(player_t *player, mobj_t *inflictor, mobj_t *source) -{ - hook_p hookp; - boolean hooked = false; - if (!gL || !(hooksAvailable[hook_PlayerExplode/8] & (1<<(hook_PlayerExplode%8)))) - return 0; - - lua_settop(gL, 0); - - // We can afford not to look for target->type because it will always be MT_PLAYER. - - for (hookp = roothook; hookp; hookp = hookp->next) - if (hookp->type == hook_PlayerExplode) - { - if (lua_gettop(gL) == 0) - { - LUA_PushUserdata(gL, player, META_PLAYER); - LUA_PushUserdata(gL, inflictor, META_MOBJ); - LUA_PushUserdata(gL, source, META_MOBJ); - } - lua_pushfstring(gL, FMT_HOOKID, hookp->id); - lua_gettable(gL, LUA_REGISTRYINDEX); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - lua_pushvalue(gL, -4); - if (lua_pcall(gL, 3, 1, 0)) { - if (!hookp->error || cv_debug & DBG_LUA) - CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL, -1)); - lua_pop(gL, 1); - hookp->error = true; - continue; - } - if (lua_toboolean(gL, -1)) - hooked = true; - lua_pop(gL, 1); - } - lua_settop(gL, 0); - return hooked; -} - -#endif diff --git a/src/lua_hud.h b/src/lua_hud.h index 286700544..63fd36d30 100644 --- a/src/lua_hud.h +++ b/src/lua_hud.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2018 by Sonic Team Junior. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -30,6 +30,9 @@ enum hud { hud_freeplay, hud_rankings, // Tab rankings + // Intermission + hud_intermissiontally, + hud_intermissionmessages, hud_MAX }; @@ -39,3 +42,6 @@ boolean LUA_HudEnabled(enum hud option); void LUAh_GameHUD(player_t *stplyr); void LUAh_ScoresHUD(void); +void LUAh_TitleHUD(void); +void LUAh_TitleCardHUD(player_t *stplayr); +void LUAh_IntermissionHUD(void); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 8410cd55f..2180012b0 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2018 by Sonic Team Junior. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,7 +11,7 @@ /// \brief custom HUD rendering library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA +#include "fastcmp.h" #include "r_defs.h" #include "r_local.h" #include "st_stuff.h" // hudinfo[] @@ -19,6 +19,7 @@ #include "i_video.h" // rendermode #include "p_local.h" // camera_t #include "screen.h" // screen width/height +#include "m_random.h" // m_random #include "v_video.h" #include "w_wad.h" #include "z_zone.h" @@ -37,6 +38,11 @@ static UINT8 hudAvailable; // hud hooks field static UINT8 camnum = 1; +#ifdef LUA_PATCH_SAFETY +static patchinfo_t *patchinfo, *patchinfohead; +static int numluapatches; +#endif + // must match enum hud in lua_hud.h static const char *const hud_disable_options[] = { "stagetitle", @@ -56,16 +62,21 @@ static const char *const hud_disable_options[] = { "speedometer", "freeplay", "rankings", + + "intermissiontally", + "intermissionmessages", NULL}; enum hudinfo { hudinfo_x = 0, - hudinfo_y + hudinfo_y, + hudinfo_f }; static const char *const hudinfo_opt[] = { "x", "y", + "f", NULL}; enum patch { @@ -85,11 +96,17 @@ static const char *const patch_opt[] = { enum hudhook { hudhook_game = 0, - hudhook_scores + hudhook_scores, + hudhook_intermission, + hudhook_title, + hudhook_titlecard }; static const char *const hudhook_opt[] = { "game", "scores", + "intermission", + "title", + "titlecard", NULL}; // alignment types for v.drawString @@ -97,20 +114,22 @@ enum align { align_left = 0, align_center, align_right, - align_fixed, align_small, + align_smallcenter, align_smallright, align_thin, + align_thincenter, align_thinright }; static const char *const align_opt[] = { "left", "center", "right", - "fixed", "small", + "small-center", "small-right", "thin", + "thin-center", "thin-right", NULL}; @@ -199,6 +218,9 @@ static int hudinfo_get(lua_State *L) case hudinfo_y: lua_pushinteger(L, info->y); break; + case hudinfo_f: + lua_pushinteger(L, info->f); + break; } return 1; } @@ -217,6 +239,9 @@ static int hudinfo_set(lua_State *L) case hudinfo_y: info->y = (INT32)luaL_checkinteger(L, 3); break; + case hudinfo_f: + info->f = (INT32)luaL_checkinteger(L, 3); + break; } return 0; } @@ -230,17 +255,31 @@ static int hudinfo_num(lua_State *L) static int colormap_get(lua_State *L) { - return luaL_error(L, "colormap is not a struct."); + const UINT8 *colormap = *((UINT8 **)luaL_checkudata(L, 1, META_COLORMAP)); + UINT32 i = luaL_checkinteger(L, 2); + if (i >= 256) + return luaL_error(L, "colormap index %d out of range (0 - %d)", i, 255); + lua_pushinteger(L, colormap[i]); + return 1; } static int patch_get(lua_State *L) { +#ifdef LUA_PATCH_SAFETY patch_t *patch = *((patch_t **)luaL_checkudata(L, 1, META_PATCH)); +#else + patchinfo_t *patch = *((patchinfo_t **)luaL_checkudata(L, 1, META_PATCH)); +#endif enum patch field = luaL_checkoption(L, 2, NULL, patch_opt); - // patches are CURRENTLY always valid, expected to be cached with PU_STATIC - // this may change in the future, so patch.valid still exists - I_Assert(patch != NULL); + // patches are invalidated when switching renderers + if (!patch) { + if (field == patch_valid) { + lua_pushboolean(L, 0); + return 1; + } + return LUA_ErrInvalid(L, "patch_t"); + } switch (field) { @@ -346,21 +385,270 @@ static int libd_patchExists(lua_State *L) static int libd_cachePatch(lua_State *L) { +#ifdef LUA_PATCH_SAFETY + int i; + lumpnum_t lumpnum; + patchinfo_t *luapat; + patch_t *realpatch; + HUDONLY - LUA_PushUserdata(L, W_CachePatchName(luaL_checkstring(L, 1), PU_STATIC), META_PATCH); + + luapat = patchinfohead; + lumpnum = W_CheckNumForLongName(luaL_checkstring(L, 1)); + if (lumpnum == LUMPERROR) + lumpnum = W_GetNumForLongName("MISSING"); + + for (i = 0; i < numluapatches; i++) + { + // check if already cached + if (luapat->wadnum == WADFILENUM(lumpnum) && luapat->lumpnum == LUMPNUM(lumpnum)) + { + LUA_PushUserdata(L, luapat, META_PATCH); + return 1; + } + luapat = luapat->next; + if (!luapat) + break; + } + + if (numluapatches > 0) + { + patchinfo->next = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); + patchinfo = patchinfo->next; + } + else + { + patchinfo = Z_Malloc(sizeof(patchinfo_t), PU_STATIC, NULL); + patchinfohead = patchinfo; + } + + realpatch = W_CachePatchNum(lumpnum, PU_PATCH); + + patchinfo->width = realpatch->width; + patchinfo->height = realpatch->height; + patchinfo->leftoffset = realpatch->leftoffset; + patchinfo->topoffset = realpatch->topoffset; + + patchinfo->wadnum = WADFILENUM(lumpnum); + patchinfo->lumpnum = LUMPNUM(lumpnum); + + LUA_PushUserdata(L, patchinfo, META_PATCH); + numluapatches++; +#else + HUDONLY + LUA_PushUserdata(L, W_CachePatchLongName(luaL_checkstring(L, 1), PU_PATCH), META_PATCH); +#endif return 1; } +// v.getSpritePatch(sprite, [frame, [angle, [rollangle]]]) +static int libd_getSpritePatch(lua_State *L) +{ + UINT32 i; // sprite prefix + UINT32 frame = 0; // 'A' + UINT8 angle = 0; + spritedef_t *sprdef; + spriteframe_t *sprframe; + HUDONLY + + if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR_THOK + { + i = lua_tonumber(L, 1); + if (i >= NUMSPRITES) + return 0; + } + else if (lua_isstring(L, 1)) // sprite prefix name given, e.g. "THOK" + { + const char *name = lua_tostring(L, 1); + for (i = 0; i < NUMSPRITES; i++) + if (fastcmp(name, sprnames[i])) + break; + if (i >= NUMSPRITES) + return 0; + } + else + return 0; + + if (i == SPR_PLAY) // Use getSprite2Patch instead! + return 0; + + sprdef = &sprites[i]; + + // set frame number + frame = luaL_optinteger(L, 2, 0); + frame &= FF_FRAMEMASK; // ignore any bits that are not the actual frame, just in case + if (frame >= sprdef->numframes) + return 0; + // set angle number + sprframe = &sprdef->spriteframes[frame]; + angle = luaL_optinteger(L, 3, 1); + + // convert WAD editor angle numbers (1-8) to internal angle numbers (0-7) + // keep 0 the same since we'll make it default to angle 1 (which is internally 0) + // in case somebody didn't know that angle 0 really just maps all 8/16 angles to the same patch + if (angle != 0) + angle--; + + if (angle >= ((sprframe->rotate & SRF_3DGE) ? 16 : 8)) // out of range? + return 0; + +#ifdef ROTSPRITE + if (lua_isnumber(L, 4)) + { + // rotsprite????? + angle_t rollangle = luaL_checkangle(L, 4); + INT32 rot = R_GetRollAngle(rollangle); + + if (rot) { + if (!(sprframe->rotsprite.cached & (1<flip & (1<rotsprite.patch[angle][rot], META_PATCH); + lua_pushboolean(L, false); + lua_pushboolean(L, true); + return 3; + } + } +#endif + + // push both the patch and it's "flip" value + LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); + lua_pushboolean(L, (sprframe->flip & (1<= MAXSKINS) + return luaL_error(L, "skin number %d out of range (0 - %d)", i, MAXSKINS-1); + if (i >= numskins) + return 0; + } + else // find skin by name + { + const char *name = luaL_checkstring(L, 1); + for (i = 0; i < numskins; i++) + if (fastcmp(skins[i].name, name)) + break; + if (i >= numskins) + return 0; + } + + lua_remove(L, 1); // remove skin now + + if (lua_isnumber(L, 1)) // sprite number given, e.g. SPR2_STIL + { + j = lua_tonumber(L, 1); + if (j & FF_SPR2SUPER) // e.g. SPR2_STIL|FF_SPR2SUPER + { + super = true; + j &= ~FF_SPR2SUPER; // remove flag so the next check doesn't fail + } + if (j >= free_spr2) + return 0; + } + else if (lua_isstring(L, 1)) // sprite prefix name given, e.g. "STND" + { + const char *name = lua_tostring(L, 1); + for (j = 0; j < free_spr2; j++) + if (fastcmp(name, spr2names[j])) + break; + // if you want super flags you'll have to use the optional boolean following this + if (j >= free_spr2) + return 0; + } + else + return 0; + + if (lua_isboolean(L, 2)) // optional boolean for superness + { + super = lua_toboolean(L, 2); // note: this can override FF_SPR2SUPER from sprite number + lua_remove(L, 2); // remove + } + // if it's not boolean then just assume it's the frame number + + if (super) + j |= FF_SPR2SUPER; + + j = P_GetSkinSprite2(&skins[i], j, NULL); // feed skin and current sprite2 through to change sprite2 used if necessary + + sprdef = &skins[i].sprites[j]; + + // set frame number + frame = luaL_optinteger(L, 2, 0); + frame &= FF_FRAMEMASK; // ignore any bits that are not the actual frame, just in case + if (frame >= sprdef->numframes) + return 0; + // set angle number + sprframe = &sprdef->spriteframes[frame]; + angle = luaL_optinteger(L, 3, 1); + + // convert WAD editor angle numbers (1-8) to internal angle numbers (0-7) + // keep 0 the same since we'll make it default to angle 1 (which is internally 0) + // in case somebody didn't know that angle 0 really just maps all 8/16 angles to the same patch + if (angle != 0) + angle--; + + if (angle >= ((sprframe->rotate & SRF_3DGE) ? 16 : 8)) // out of range? + return 0; + +#ifdef ROTSPRITE + if (lua_isnumber(L, 4)) + { + // rotsprite????? + angle_t rollangle = luaL_checkangle(L, 4); + INT32 rot = R_GetRollAngle(rollangle); + + if (rot) { + if (!(sprframe->rotsprite.cached & (1<flip & (1<rotsprite.patch[angle][rot], META_PATCH); + lua_pushboolean(L, false); + lua_pushboolean(L, true); + return 3; + } + } +#endif + + // push both the patch and it's "flip" value + LUA_PushUserdata(L, W_CachePatchNum(sprframe->lumppat[angle], PU_PATCH), META_PATCH); + lua_pushboolean(L, (sprframe->flip & (1<wadnum<<16)+luapat->lumpnum, PU_PATCH); +#else patch = *((patch_t **)luaL_checkudata(L, 3, META_PATCH)); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); +#endif flags = luaL_optinteger(L, 4, 0); if (!lua_isnoneornil(L, 5)) colormap = *((UINT8 **)luaL_checkudata(L, 5, META_COLORMAP)); @@ -376,6 +664,9 @@ static int libd_drawScaled(lua_State *L) fixed_t x, y, scale; INT32 flags; patch_t *patch; +#ifdef LUA_PATCH_SAFETY + patchinfo_t *luapat; +#endif const UINT8 *colormap = NULL; HUDONLY @@ -384,7 +675,14 @@ static int libd_drawScaled(lua_State *L) scale = luaL_checkinteger(L, 3); if (scale < 0) return luaL_error(L, "negative scale"); +#ifdef LUA_PATCH_SAFETY + luapat = *((patchinfo_t **)luaL_checkudata(L, 4, META_PATCH)); + patch = W_CachePatchNum((luapat->wadnum<<16)+luapat->lumpnum, PU_PATCH); +#else patch = *((patch_t **)luaL_checkudata(L, 4, META_PATCH)); + if (!patch) + return LUA_ErrInvalid(L, "patch_t"); +#endif flags = luaL_optinteger(L, 5, 0); if (!lua_isnoneornil(L, 6)) colormap = *((UINT8 **)luaL_checkudata(L, 6, META_COLORMAP)); @@ -395,6 +693,33 @@ static int libd_drawScaled(lua_State *L) return 0; } +static int libd_drawStretched(lua_State *L) +{ + fixed_t x, y, hscale, vscale; + INT32 flags; + patch_t *patch; + const UINT8 *colormap = NULL; + + HUDONLY + x = luaL_checkinteger(L, 1); + y = luaL_checkinteger(L, 2); + hscale = luaL_checkinteger(L, 3); + if (hscale < 0) + return luaL_error(L, "negative horizontal scale"); + vscale = luaL_checkinteger(L, 4); + if (vscale < 0) + return luaL_error(L, "negative vertical scale"); + patch = *((patch_t **)luaL_checkudata(L, 5, META_PATCH)); + flags = luaL_optinteger(L, 6, 0); + if (!lua_isnoneornil(L, 7)) + colormap = *((UINT8 **)luaL_checkudata(L, 7, META_COLORMAP)); + + flags &= ~V_PARAMMASK; // Don't let crashes happen. + + V_DrawStretchyFixedPatch(x, y, hscale, vscale, flags, patch, colormap); + return 0; +} + // KART: draw patch on minimap from x, y coordinates on the map static int libd_drawOnMinimap(lua_State *L) { @@ -597,7 +922,6 @@ static int libd_drawPaddedNum(lua_State *L) return 0; } - static int libd_drawPingNum(lua_State *L) { INT32 x, y, flags, num; @@ -675,13 +999,13 @@ static int libd_drawString(lua_State *L) case align_right: V_DrawRightAlignedString(x, y, flags, str); break; - case align_fixed: - V_DrawStringAtFixed(x, y, flags, str); - break; // hu_font, 0.5x scale case align_small: V_DrawSmallString(x, y, flags, str); break; + case align_smallcenter: + V_DrawCenteredSmallString(x, y, flags, str); + break; case align_smallright: V_DrawRightAlignedSmallString(x, y, flags, str); break; @@ -689,6 +1013,9 @@ static int libd_drawString(lua_State *L) case align_thin: V_DrawThinString(x, y, flags, str); break; + case align_thincenter: + V_DrawCenteredThinString(x, y, flags, str); + break; case align_thinright: V_DrawRightAlignedThinString(x, y, flags, str); break; @@ -735,7 +1062,7 @@ static int libd_stringWidth(lua_State *L) static int libd_getColormap(lua_State *L) { INT32 skinnum = TC_DEFAULT; - skincolors_t color = luaL_optinteger(L, 2, 0); + skincolornum_t color = luaL_optinteger(L, 2, 0); UINT8* colormap = NULL; HUDONLY if (lua_isnoneornil(L, 1)) @@ -761,6 +1088,19 @@ static int libd_getColormap(lua_State *L) return 1; } +static int libd_getStringColormap(lua_State *L) +{ + INT32 flags = luaL_checkinteger(L, 1); + UINT8* colormap = NULL; + HUDONLY + colormap = V_GetStringColormap(flags & V_CHARCOLORMASK); + if (colormap) { + LUA_PushUserdata(L, colormap, META_COLORMAP); // push as META_COLORMAP userdata, specifically for patches to use! + return 1; + } + return 0; +} + static int libd_width(lua_State *L) { HUDONLY @@ -802,9 +1142,78 @@ static int libd_renderer(lua_State *L) return 1; } -// 30/10/18 Lat': Get cv_translucenthud's value for HUD rendering as a normal V_xxTRANS int +// M_RANDOM +////////////// + +static int libd_RandomFixed(lua_State *L) +{ + HUDONLY + lua_pushfixed(L, M_RandomFixed()); + return 1; +} + +static int libd_RandomByte(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, M_RandomByte()); + return 1; +} + +static int libd_RandomKey(lua_State *L) +{ + INT32 a = (INT32)luaL_checkinteger(L, 1); + + HUDONLY + if (a > 65536) + LUA_UsageWarning(L, "v.RandomKey: range > 65536 is undefined behavior"); + lua_pushinteger(L, M_RandomKey(a)); + return 1; +} + +static int libd_RandomRange(lua_State *L) +{ + INT32 a = (INT32)luaL_checkinteger(L, 1); + INT32 b = (INT32)luaL_checkinteger(L, 2); + + HUDONLY + if (b < a) { + INT32 c = a; + a = b; + b = c; + } + if ((b-a+1) > 65536) + LUA_UsageWarning(L, "v.RandomRange: range > 65536 is undefined behavior"); + lua_pushinteger(L, M_RandomRange(a, b)); + return 1; +} + +// Macros. +static int libd_SignedRandom(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, M_SignedRandom()); + return 1; +} + +static int libd_RandomChance(lua_State *L) +{ + fixed_t p = luaL_checkfixed(L, 1); + HUDONLY + lua_pushboolean(L, M_RandomChance(p)); + return 1; +} + +// 30/10/18 Lat': Get st_translucency's value for HUD rendering as a normal V_xxTRANS int // Could as well be thrown in global vars for ease of access but I guess it makes sense for it to be a HUD fn static int libd_getlocaltransflag(lua_State *L) +{ + HUDONLY + lua_pushinteger(L, (10-st_translucency)*V_10TRANS); + return 1; +} + +// Get cv_translucenthud's value for HUD rendering as a normal V_xxTRANS int +static int libd_getusertransflag(lua_State *L) { HUDONLY lua_pushinteger(L, (10-cv_translucenthud.value)*V_10TRANS); // A bit weird that it's called "translucenthud" yet 10 is fully opaque :V @@ -812,10 +1221,17 @@ static int libd_getlocaltransflag(lua_State *L) } static luaL_Reg lib_draw[] = { + // cache {"patchExists", libd_patchExists}, {"cachePatch", libd_cachePatch}, + {"getSpritePatch", libd_getSpritePatch}, + {"getSprite2Patch", libd_getSprite2Patch}, + {"getColormap", libd_getColormap}, + {"getStringColormap", libd_getStringColormap}, + // drawing {"draw", libd_draw}, {"drawScaled", libd_drawScaled}, + {"drawStretched", libd_drawStretched}, {"drawNum", libd_drawNum}, {"drawPaddedNum", libd_drawPaddedNum}, {"drawPingNum", libd_drawPingNum}, @@ -823,8 +1239,16 @@ static luaL_Reg lib_draw[] = { {"fadeScreen", libd_fadeScreen}, {"drawString", libd_drawString}, {"drawKartString", libd_drawKartString}, + // misc {"stringWidth", libd_stringWidth}, - {"getColormap", libd_getColormap}, + // m_random + {"RandomFixed",libd_RandomFixed}, + {"RandomByte",libd_RandomByte}, + {"RandomKey",libd_RandomKey}, + {"RandomRange",libd_RandomRange}, + {"SignedRandom",libd_SignedRandom}, // MACRO + {"RandomChance",libd_RandomChance}, // MACRO + // properties {"width", libd_width}, {"height", libd_height}, {"dupx", libd_dupx}, @@ -832,6 +1256,7 @@ static luaL_Reg lib_draw[] = { {"renderer", libd_renderer}, {"localTransFlag", libd_getlocaltransflag}, {"drawOnMinimap", libd_drawOnMinimap}, + {"userTransFlag", libd_getusertransflag}, {NULL, NULL} }; @@ -875,6 +1300,9 @@ static int lib_hudadd(lua_State *L) luaL_checktype(L, 1, LUA_TFUNCTION); field = luaL_checkoption(L, 2, "game", hudhook_opt); + if (!lua_lumploading) + return luaL_error(L, "This function cannot be called from within a hook or coroutine!"); + lua_getfield(L, LUA_REGISTRYINDEX, "HUD"); I_Assert(lua_istable(L, -1)); lua_rawgeti(L, -1, field+2); // HUD[2+] @@ -904,6 +1332,10 @@ int LUA_HudLib(lua_State *L) { memset(hud_enabled, 0xff, (hud_MAX/8)+1); +#ifdef LUA_PATCH_SAFETY + numluapatches = 0; +#endif + lua_newtable(L); // HUD registry table lua_newtable(L); luaL_register(L, NULL, lib_draw); @@ -913,7 +1345,16 @@ int LUA_HudLib(lua_State *L) lua_rawseti(L, -2, 2); // HUD[2] = game rendering functions array lua_newtable(L); - lua_rawseti(L, -2, 3); // HUD[2] = scores rendering functions array + lua_rawseti(L, -2, 3); // HUD[3] = scores rendering functions array + + lua_newtable(L); + lua_rawseti(L, -2, 4); // HUD[4] = intermission rendering functions array + + lua_newtable(L); + lua_rawseti(L, -2, 5); // HUD[5] = title rendering functions array + + lua_newtable(L); + lua_rawseti(L, -2, 6); // HUD[6] = title card rendering functions array lua_setfield(L, LUA_REGISTRYINDEX, "HUD"); luaL_newmetatable(L, META_HUDINFO); @@ -977,7 +1418,7 @@ void LUAh_GameHUD(player_t *stplayr) lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); I_Assert(lua_istable(gL, -1)); - lua_rawgeti(gL, -1, 2); // HUD[2] = rendering funcs + lua_rawgeti(gL, -1, 2+hudhook_game); // HUD[2] = rendering funcs I_Assert(lua_istable(gL, -1)); lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw @@ -1027,7 +1468,7 @@ void LUAh_ScoresHUD(void) lua_getfield(gL, LUA_REGISTRYINDEX, "HUD"); I_Assert(lua_istable(gL, -1)); - lua_rawgeti(gL, -1, 3); // HUD[3] = rendering funcs + lua_rawgeti(gL, -1, 2+hudhook_scores); // HUD[3] = rendering funcs I_Assert(lua_istable(gL, -1)); lua_rawgeti(gL, -2, 1); // HUD[1] = lib_draw @@ -1042,4 +1483,86 @@ void LUAh_ScoresHUD(void) hud_running = false; } -#endif +void LUAh_TitleHUD(void) +{ + if (!gL || !(hudAvailable & (1<= free_spr2) + return 0; + lua_pushlstring(L, spr2names[i], 4); + return 1; + } + else if (lua_isstring(L, 1)) + { + const char *name = lua_tostring(L, 1); + for (i = 0; i < free_spr2; i++) + if (fastcmp(name, spr2names[i])) + { + lua_pushinteger(L, i); + return 1; + } + } + return 0; +} + +static int lib_getSpr2default(lua_State *L) +{ + playersprite_t i; + + lua_remove(L, 1); // don't care about spr2defaults[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else if (lua_isstring(L, 1)) + { + const char *name = lua_tostring(L, 1); + for (i = 0; i < free_spr2; i++) + if (fastcmp(name, spr2names[i])) + break; + } + else + return luaL_error(L, "spr2defaults[] invalid index"); + + if (i >= free_spr2) + return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, 0, free_spr2-1); + + lua_pushinteger(L, spr2defaults[i]); + return 1; +} + +static int lib_setSpr2default(lua_State *L) +{ + playersprite_t i; + UINT8 j = 0; + + if (hud_running) + return luaL_error(L, "Do not alter spr2defaults[] in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter spr2defaults[] in CMD building code!"); + +// todo: maybe allow setting below first freeslot..? step 1 is toggling this, step 2 is testing to see whether it's net-safe +#ifdef SETALLSPR2DEFAULTS +#define FIRSTMODIFY 0 +#else +#define FIRSTMODIFY SPR2_FIRSTFREESLOT + if (free_spr2 == SPR2_FIRSTFREESLOT) + return luaL_error(L, "You can only modify the spr2defaults[] entries of sprite2 freeslots, and none are currently added."); +#endif + + lua_remove(L, 1); // don't care about spr2defaults[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else if (lua_isstring(L, 1)) + { + const char *name = lua_tostring(L, 1); + for (i = 0; i < free_spr2; i++) + { + if (fastcmp(name, spr2names[i])) + break; + } + if (i == free_spr2) + return luaL_error(L, "spr2defaults[] invalid index"); + } + else + return luaL_error(L, "spr2defaults[] invalid index"); + + if (i < FIRSTMODIFY || i >= free_spr2) + return luaL_error(L, "spr2defaults[] index %d out of range (%d - %d)", i, FIRSTMODIFY, free_spr2-1); +#undef FIRSTMODIFY + + if (lua_isnumber(L, 2)) + j = lua_tonumber(L, 2); + else if (lua_isstring(L, 2)) + { + const char *name = lua_tostring(L, 2); + for (j = 0; j < free_spr2; j++) + { + if (fastcmp(name, spr2names[j])) + break; + } + if (j == free_spr2) + return luaL_error(L, "spr2defaults[] invalid set"); + } + else + return luaL_error(L, "spr2defaults[] invalid set"); + + if (j >= free_spr2) + return luaL_error(L, "spr2defaults[] set %d out of range (%d - %d)", j, 0, free_spr2-1); + + spr2defaults[i] = j; + return 0; +} + +static int lib_spr2namelen(lua_State *L) +{ + lua_pushinteger(L, free_spr2); + return 1; +} + +///////////////// +// SPRITE INFO // +///////////////// + +// spriteinfo[] +static int lib_getSpriteInfo(lua_State *L) +{ + UINT32 i = NUMSPRITES; + lua_remove(L, 1); + + if (lua_isstring(L, 1)) + { + const char *name = lua_tostring(L, 1); + INT32 spr; + for (spr = 0; spr < NUMSPRITES; spr++) + { + if (fastcmp(name, sprnames[spr])) + { + i = spr; + break; + } + } + if (i == NUMSPRITES) + { + char *check; + i = strtol(name, &check, 10); + if (check == name || *check != '\0') + return luaL_error(L, "unknown sprite name %s", name); + } + } + else + i = luaL_checkinteger(L, 1); + + if (i == 0 || i >= NUMSPRITES) + return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1); + + LUA_PushUserdata(L, &spriteinfo[i], META_SPRITEINFO); + return 1; +} + +#define FIELDERROR(f, e) luaL_error(L, "bad value for " LUA_QL(f) " in table passed to spriteinfo[] (%s)", e); +#define TYPEERROR(f, t1, t2) FIELDERROR(f, va("%s expected, got %s", lua_typename(L, t1), lua_typename(L, t2))) + +static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, int idx) +{ + int okcool = 0; + switch (lua_type(L, stk)) + { + case LUA_TTABLE: + lua_pushnil(L); + while (lua_next(L, stk)) + { + const char *key = NULL; + lua_Integer ikey = -1; + lua_Integer value = 0; + // x or y? + switch (lua_type(L, stk+1)) + { + case LUA_TSTRING: + key = lua_tostring(L, stk+1); + break; + case LUA_TNUMBER: + ikey = lua_tointeger(L, stk+1); + break; + default: + FIELDERROR("pivot key", va("string or number expected, got %s", luaL_typename(L, stk+1))) + } + // then get value + switch (lua_type(L, stk+2)) + { + case LUA_TNUMBER: + value = lua_tonumber(L, stk+2); + break; + case LUA_TBOOLEAN: + value = (UINT8)lua_toboolean(L, stk+2); + break; + default: + TYPEERROR("pivot value", LUA_TNUMBER, lua_type(L, stk+2)) + } + // finally set omg!!!!!!!!!!!!!!!!!! + if (ikey == 1 || (key && fastcmp(key, "x"))) + pivot[idx].x = (INT32)value; + else if (ikey == 2 || (key && fastcmp(key, "y"))) + pivot[idx].y = (INT32)value; + else if (ikey == 3 || (key && fastcmp(key, "rotaxis"))) + pivot[idx].rotaxis = (UINT8)value; + else if (ikey == -1 && (key != NULL)) + FIELDERROR("pivot key", va("invalid option %s", key)); + okcool = 1; + lua_pop(L, 1); + } + break; + default: + TYPEERROR("sprite pivot", LUA_TTABLE, lua_type(L, stk)) + } + return okcool; +} + +static int PopPivotTable(spriteinfo_t *info, lua_State *L, int stk) +{ + // Just in case? + if (!lua_istable(L, stk)) + TYPEERROR("pivot table", LUA_TTABLE, lua_type(L, stk)); + + lua_pushnil(L); + // stk = 0 has the pivot table + // stk = 1 has the frame key + // stk = 2 has the frame table + // stk = 3 has either a string or a number as key + // stk = 4 has the value for the key mentioned above + while (lua_next(L, stk)) + { + int idx = 0; + const char *framestr = NULL; + switch (lua_type(L, stk+1)) + { + case LUA_TSTRING: + framestr = lua_tostring(L, stk+1); + idx = R_Char2Frame(framestr[0]); + break; + case LUA_TNUMBER: + idx = lua_tonumber(L, stk+1); + break; + default: + TYPEERROR("pivot frame", LUA_TNUMBER, lua_type(L, stk+1)); + } + if ((idx < 0) || (idx >= 64)) + return luaL_error(L, "pivot frame %d out of range (0 - %d)", idx, 63); + // the values in pivot[] are also tables + if (PopPivotSubTable(info->pivot, L, stk+2, idx)) + info->available = true; + lua_pop(L, 1); + } + + return 0; +} + +static int lib_setSpriteInfo(lua_State *L) +{ + spriteinfo_t *info; + + if (!lua_lumploading) + return luaL_error(L, "Do not alter spriteinfo_t from within a hook or coroutine!"); + if (hud_running) + return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!"); + + lua_remove(L, 1); + { + UINT32 i = luaL_checkinteger(L, 1); + if (i == 0 || i >= NUMSPRITES) + return luaL_error(L, "spriteinfo[] index %d out of range (1 - %d)", i, NUMSPRITES-1); +#ifdef ROTSPRITE + if (sprites != NULL) + R_FreeSingleRotSprite(&sprites[i]); +#endif + info = &spriteinfo[i]; // get the spriteinfo to assign to. + } + luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. + lua_remove(L, 1); // pop sprite num, don't need it any more. + lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the spriteinfo. + + lua_pushnil(L); + while (lua_next(L, 1)) { + lua_Integer i = 0; + const char *str = NULL; + if (lua_isnumber(L, 2)) + i = lua_tointeger(L, 2); + else + str = luaL_checkstring(L, 2); + + if (i == 1 || (str && fastcmp(str, "pivot"))) + { + // pivot[] is a table + if (lua_istable(L, 3)) + return PopPivotTable(info, L, 3); + else + FIELDERROR("pivot", va("%s expected, got %s", lua_typename(L, LUA_TTABLE), luaL_typename(L, -1))) + } + + lua_pop(L, 1); + } + + return 0; +} + +#undef FIELDERROR +#undef TYPEERROR + +static int lib_spriteinfolen(lua_State *L) +{ + lua_pushinteger(L, NUMSPRITES); + return 1; +} + +// spriteinfo_t +static int spriteinfo_get(lua_State *L) +{ + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFO)); + const char *field = luaL_checkstring(L, 2); + + I_Assert(sprinfo != NULL); + + // push spriteframepivot_t userdata + if (fastcmp(field, "pivot")) + { + // bypass LUA_PushUserdata + void **userdata = lua_newuserdata(L, sizeof(void *)); + *userdata = &sprinfo->pivot; + luaL_getmetatable(L, META_PIVOTLIST); + lua_setmetatable(L, -2); + + // stack is left with the userdata on top, as if getting it had originally succeeded. + return 1; + } + else + return luaL_error(L, LUA_QL("spriteinfo_t") " has no field named " LUA_QS, field); + + return 0; +} + +static int spriteinfo_set(lua_State *L) +{ + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFO)); + const char *field = luaL_checkstring(L, 2); + + if (!lua_lumploading) + return luaL_error(L, "Do not alter spriteinfo_t from within a hook or coroutine!"); + if (hud_running) + return luaL_error(L, "Do not alter spriteinfo_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter spriteinfo_t in CMD building code!"); + + I_Assert(sprinfo != NULL); + + lua_remove(L, 1); // remove spriteinfo + lua_remove(L, 1); // remove field + lua_settop(L, 1); // leave only one value + +#ifdef ROTSPRITE + if (sprites != NULL) + R_FreeSingleRotSprite(&sprites[sprinfo-spriteinfo]); +#endif + + if (fastcmp(field, "pivot")) + { + // pivot[] is a table + if (lua_istable(L, 1)) + return PopPivotTable(sprinfo, L, 1); + // pivot[] is userdata + else if (lua_isuserdata(L, 1)) + { + spriteframepivot_t *pivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); + memcpy(&sprinfo->pivot, pivot, sizeof(spriteframepivot_t)); + sprinfo->available = true; // Just in case? + } + } + else + return luaL_error(L, va("Field %s does not exist in spriteinfo_t", field)); + + return 0; +} + +static int spriteinfo_num(lua_State *L) +{ + spriteinfo_t *sprinfo = *((spriteinfo_t **)luaL_checkudata(L, 1, META_SPRITEINFO)); + + I_Assert(sprinfo != NULL); + I_Assert(sprinfo >= spriteinfo); + + lua_pushinteger(L, (UINT32)(sprinfo-spriteinfo)); + return 1; +} + +// framepivot_t +static int pivotlist_get(lua_State *L) +{ + void **userdata; + spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_PIVOTLIST)); + const char *field = luaL_checkstring(L, 2); + UINT8 frame; + + I_Assert(framepivot != NULL); + + frame = R_Char2Frame(field[0]); + if (frame == 255) + luaL_error(L, "invalid frame %s", field); + + // bypass LUA_PushUserdata + userdata = lua_newuserdata(L, sizeof(void *)); + *userdata = &framepivot[frame]; + luaL_getmetatable(L, META_FRAMEPIVOT); + lua_setmetatable(L, -2); + + // stack is left with the userdata on top, as if getting it had originally succeeded. + return 1; +} + +static int pivotlist_set(lua_State *L) +{ + // Because I already know it's a spriteframepivot_t anyway + spriteframepivot_t *pivotlist = *((spriteframepivot_t **)lua_touserdata(L, 1)); + //spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + const char *field = luaL_checkstring(L, 2); + UINT8 frame; + + if (!lua_lumploading) + return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!"); + if (hud_running) + return luaL_error(L, "Do not alter spriteframepivot_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!"); + + I_Assert(pivotlist != NULL); + + frame = R_Char2Frame(field[0]); + if (frame == 255) + luaL_error(L, "invalid frame %s", field); + + // pivot[] is a table + if (lua_istable(L, 3)) + return PopPivotSubTable(pivotlist, L, 3, frame); + // pivot[] is userdata + else if (lua_isuserdata(L, 3)) + { + spriteframepivot_t *copypivot = *((spriteframepivot_t **)luaL_checkudata(L, 3, META_FRAMEPIVOT)); + memcpy(&pivotlist[frame], copypivot, sizeof(spriteframepivot_t)); + } + + return 0; +} + +static int pivotlist_num(lua_State *L) +{ + lua_pushinteger(L, 64); + return 1; +} + +static int framepivot_get(lua_State *L) +{ + spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + const char *field = luaL_checkstring(L, 2); + + I_Assert(framepivot != NULL); + + if (fastcmp("x", field)) + lua_pushinteger(L, framepivot->x); + else if (fastcmp("y", field)) + lua_pushinteger(L, framepivot->y); + else if (fastcmp("rotaxis", field)) + lua_pushinteger(L, (UINT8)framepivot->rotaxis); + else + return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); + + return 1; +} + +static int framepivot_set(lua_State *L) +{ + spriteframepivot_t *framepivot = *((spriteframepivot_t **)luaL_checkudata(L, 1, META_FRAMEPIVOT)); + const char *field = luaL_checkstring(L, 2); + + if (!lua_lumploading) + return luaL_error(L, "Do not alter spriteframepivot_t from within a hook or coroutine!"); + if (hud_running) + return luaL_error(L, "Do not alter spriteframepivot_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter spriteframepivot_t in CMD building code!"); + + I_Assert(framepivot != NULL); + + if (fastcmp("x", field)) + framepivot->x = luaL_checkinteger(L, 3); + else if (fastcmp("y", field)) + framepivot->y = luaL_checkinteger(L, 3); + else if (fastcmp("rotaxis", field)) + framepivot->rotaxis = luaL_checkinteger(L, 3); + else + return luaL_error(L, va("Field %s does not exist in spriteframepivot_t", field)); + + return 0; +} + +static int framepivot_num(lua_State *L) +{ + lua_pushinteger(L, 2); + return 1; +} + //////////////// // STATE INFO // //////////////// @@ -171,7 +698,7 @@ static int lib_setState(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter states in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter states in BuildCMD code!"); + return luaL_error(L, "Do not alter states in CMD building code!"); // clear the state to start with, in case of missing table elements memset(state,0,sizeof(state_t)); @@ -205,6 +732,18 @@ static int lib_setState(lua_State *L) case LUA_TSTRING: // It's a string, expect the name of a built-in action LUA_SetActionByName(state, lua_tostring(L, 3)); break; + case LUA_TUSERDATA: // It's a userdata, expect META_ACTION of a built-in action + { + actionf_t *action = *((actionf_t **)luaL_checkudata(L, 3, META_ACTION)); + + if (!action) + return luaL_error(L, "not a valid action?"); + + state->action = *action; + state->action.acv = action->acv; + state->action.acp1 = action->acp1; + break; + } case LUA_TFUNCTION: // It's a function (a Lua function or a C function? either way!) lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION); I_Assert(lua_istable(L, -1)); @@ -354,9 +893,8 @@ static int state_get(lua_State *L) return 0; // Just what is this?? // get the function from the global // because the metatable will trigger. - lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a new C closure if not. - lua_pushstring(L, name); // push the name we found. - return 2; // return both the function and its name, in case somebody wanted to do a comparison by name or something? + lua_getglobal(L, name); // actually gets from LREG_ACTIONS if applicable, and pushes a META_ACTION userdata if not. + return 1; // return just the function } else if (fastcmp(field,"var1")) number = st->var1; else if (fastcmp(field,"var2")) @@ -382,7 +920,7 @@ static int state_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter states in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter states in BuildCMD code!"); + return luaL_error(L, "Do not alter states in CMD building code!"); if (fastcmp(field,"sprite")) { value = luaL_checknumber(L, 3); @@ -402,6 +940,18 @@ static int state_set(lua_State *L) case LUA_TSTRING: // It's a string, expect the name of a built-in action LUA_SetActionByName(st, lua_tostring(L, 3)); break; + case LUA_TUSERDATA: // It's a userdata, expect META_ACTION of a built-in action + { + actionf_t *action = *((actionf_t **)luaL_checkudata(L, 3, META_ACTION)); + + if (!action) + return luaL_error(L, "not a valid action?"); + + st->action = *action; + st->action.acv = action->acv; + st->action.acp1 = action->acp1; + break; + } case LUA_TFUNCTION: // It's a function (a Lua function or a C function? either way!) lua_getfield(L, LUA_REGISTRYINDEX, LREG_STATEACTION); I_Assert(lua_istable(L, -1)); @@ -472,7 +1022,7 @@ static int lib_setMobjInfo(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter mobjinfo in BuildCMD code!"); + return luaL_error(L, "Do not alter mobjinfo in CMD building code!"); // clear the mobjinfo to start with, in case of missing table elements memset(info,0,sizeof(mobjinfo_t)); @@ -641,7 +1191,7 @@ static int mobjinfo_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter mobjinfo in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter mobjinfo in BuildCMD code!"); + return luaL_error(L, "Do not alter mobjinfo in CMD building code!"); I_Assert(info != NULL); I_Assert(info >= mobjinfo); @@ -740,8 +1290,8 @@ static int lib_getSfxInfo(lua_State *L) lua_remove(L, 1); i = luaL_checkinteger(L, 1); - if (i >= NUMSFX) - return luaL_error(L, "sfxinfo[] index %d out of range (0 - %d)", i, NUMSFX-1); + if (i == 0 || i >= NUMSFX) + return luaL_error(L, "sfxinfo[] index %d out of range (1 - %d)", i, NUMSFX-1); LUA_PushUserdata(L, &S_sfx[i], META_SFXINFO); return 1; } @@ -754,18 +1304,18 @@ static int lib_setSfxInfo(lua_State *L) lua_remove(L, 1); { UINT32 i = luaL_checkinteger(L, 1); - if (i >= NUMSFX) - return luaL_error(L, "sfxinfo[] index %d out of range (0 - %d)", i, NUMSFX-1); - info = &S_sfx[i]; // get the mobjinfo to assign to. + if (i == 0 || i >= NUMSFX) + return luaL_error(L, "sfxinfo[] index %d out of range (1 - %d)", i, NUMSFX-1); + info = &S_sfx[i]; // get the sfxinfo to assign to. } luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. - lua_remove(L, 1); // pop mobjtype num, don't need it any more. - lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the mobjinfo. + lua_remove(L, 1); // pop sfx num, don't need it any more. + lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the sfx. if (hud_running) return luaL_error(L, "Do not alter sfxinfo in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter sfxinfo in BuildCMD code!"); + return luaL_error(L, "Do not alter sfxinfo in CMD building code!"); lua_pushnil(L); while (lua_next(L, 1)) { @@ -787,6 +1337,9 @@ static int lib_setSfxInfo(lua_State *L) case sfxinfow_flags: info->pitch = (INT32)luaL_checkinteger(L, 3); break; + case sfxinfow_caption: + strlcpy(info->caption, luaL_checkstring(L, 3), sizeof(info->caption)); + break; default: break; } @@ -824,11 +1377,14 @@ static int sfxinfo_get(lua_State *L) case sfxinfor_flags: lua_pushinteger(L, sfx->pitch); return 1; + case sfxinfor_caption: + lua_pushstring(L, sfx->caption); + return 1; case sfxinfor_skinsound: lua_pushinteger(L, sfx->skinsound); return 1; default: - return luaL_error(L, "impossible error"); + return luaL_error(L, "Field does not exist in sfxinfo_t"); } return 0; } @@ -842,7 +1398,7 @@ static int sfxinfo_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter S_sfx in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter S_sfx in BuildCMD code!"); + return luaL_error(L, "Do not alter S_sfx in CMD building code!"); I_Assert(sfx != NULL); @@ -861,8 +1417,11 @@ static int sfxinfo_set(lua_State *L) case sfxinfow_flags: sfx->pitch = luaL_checkinteger(L, 1); break; + case sfxinfow_caption: + strlcpy(sfx->caption, luaL_checkstring(L, 1), sizeof(sfx->caption)); + break; default: - return luaL_error(L, "impossible error"); + return luaL_error(L, "Field does not exist in sfxinfo_t"); } return 0; } @@ -878,6 +1437,321 @@ static int sfxinfo_num(lua_State *L) return 1; } +////////////// +// LUABANKS // +////////////// + +static int lib_getluabanks(lua_State *L) +{ + UINT8 i; + + lua_remove(L, 1); // don't care about luabanks[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else + return luaL_error(L, "luabanks[] invalid index"); + + if (i >= NUM_LUABANKS) + luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1); + + lua_pushinteger(L, luabanks[i]); + return 1; +} + +static int lib_setluabanks(lua_State *L) +{ + UINT8 i; + INT32 j = 0; + + if (hud_running) + return luaL_error(L, "Do not alter luabanks[] in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter luabanks[] in CMD building code!"); + + lua_remove(L, 1); // don't care about luabanks[] dummy userdata. + + if (lua_isnumber(L, 1)) + i = lua_tonumber(L, 1); + else + return luaL_error(L, "luabanks[] invalid index"); + + if (i >= NUM_LUABANKS) + luaL_error(L, "luabanks[] index %d out of range (%d - %d)", i, 0, NUM_LUABANKS-1); + + if (lua_isnumber(L, 2)) + j = lua_tonumber(L, 2); + else + return luaL_error(L, "luabanks[] invalid set"); + + luabanks[i] = j; + return 0; +} + +static int lib_luabankslen(lua_State *L) +{ + lua_pushinteger(L, NUM_LUABANKS); + return 1; +} + +//////////////////// +// SKINCOLOR INFO // +//////////////////// + +// Arbitrary skincolors[] table index -> skincolor_t * +static int lib_getSkinColor(lua_State *L) +{ + UINT32 i; + lua_remove(L, 1); + + i = luaL_checkinteger(L, 1); + if (!i || i >= numskincolors) + return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", i, numskincolors-1); + LUA_PushUserdata(L, &skincolors[i], META_SKINCOLOR); + return 1; +} + +//Set the entire c->ramp array +static void setRamp(lua_State *L, skincolor_t* c) { + UINT32 i; + lua_pushnil(L); + for (i=0; iramp[i] = lua_isnumber(L,-1) ? (UINT8)luaL_checkinteger(L,-1) : 120; + lua_pop(L, 1); + } else + c->ramp[i] = 120; + } + lua_pop(L,1); +} + +// Lua table full of data -> skincolors[] +static int lib_setSkinColor(lua_State *L) +{ + UINT32 j; + skincolor_t *info; + UINT16 cnum; //skincolor num + lua_remove(L, 1); // don't care about skincolors[] userdata. + { + cnum = (UINT16)luaL_checkinteger(L, 1); + if (!cnum || cnum >= numskincolors) + return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", cnum, numskincolors-1); + info = &skincolors[cnum]; // get the skincolor to assign to. + } + luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table. + lua_remove(L, 1); // pop skincolor num, don't need it any more. + lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the skincolor. + + if (hud_running) + return luaL_error(L, "Do not alter skincolors in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter skincolors in CMD building code!"); + + // clear the skincolor to start with, in case of missing table elements + memset(info,0,sizeof(skincolor_t)); + + Color_cons_t[cnum].value = cnum; + lua_pushnil(L); + while (lua_next(L, 1)) { + lua_Integer i = 0; + const char *str = NULL; + if (lua_isnumber(L, 2)) + i = lua_tointeger(L, 2); + else + str = luaL_checkstring(L, 2); + + if (i == 1 || (str && fastcmp(str,"name"))) { + const char* n = luaL_checkstring(L, 3); + strlcpy(info->name, n, MAXCOLORNAME+1); + if (strlen(n) > MAXCOLORNAME) + CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name); +#if 0 + if (strchr(info->name, ' ') != NULL) + CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", info->name); +#endif + + if (info->name[0] != '\0') // don't check empty string for dupe + { + UINT16 dupecheck = R_GetColorByName(info->name); + if (!stricmp(info->name, skincolors[SKINCOLOR_NONE].name) || (dupecheck && (dupecheck != info-skincolors))) + CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') is a duplicate of another skincolor's name.\n", info->name); + } + } else if (i == 2 || (str && fastcmp(str,"ramp"))) { + if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL) + return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array."); + else if (lua_istable(L, 3)) + setRamp(L, info); + else + for (j=0; jramp[j] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[j]; + skincolor_modified[cnum] = true; + } else if (i == 3 || (str && fastcmp(str,"invcolor"))) { + UINT16 v = (UINT16)luaL_checkinteger(L, 3); + if (v >= numskincolors) + return luaL_error(L, "skincolor_t field 'invcolor' out of range (1 - %d)", numskincolors-1); + info->invcolor = v; + } else if (i == 4 || (str && fastcmp(str,"invshade"))) + info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE; + else if (i == 5 || (str && fastcmp(str,"chatcolor"))) + info->chatcolor = (UINT16)luaL_checkinteger(L, 3); + else if (i == 6 || (str && fastcmp(str,"accessible"))) { + boolean v = lua_toboolean(L, 3); + if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible) + return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum); + else + info->accessible = v; + } + lua_pop(L, 1); + } + return 0; +} + +// #skincolors -> numskincolors +static int lib_skincolorslen(lua_State *L) +{ + lua_pushinteger(L, numskincolors); + return 1; +} + +// skincolor_t *, field -> number +static int skincolor_get(lua_State *L) +{ + skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR)); + const char *field = luaL_checkstring(L, 2); + + I_Assert(info != NULL); + I_Assert(info >= skincolors); + + if (fastcmp(field,"name")) + lua_pushstring(L, info->name); + else if (fastcmp(field,"ramp")) + LUA_PushUserdata(L, info->ramp, META_COLORRAMP); + else if (fastcmp(field,"invcolor")) + lua_pushinteger(L, info->invcolor); + else if (fastcmp(field,"invshade")) + lua_pushinteger(L, info->invshade); + else if (fastcmp(field,"chatcolor")) + lua_pushinteger(L, info->chatcolor); + else if (fastcmp(field,"accessible")) + lua_pushboolean(L, info->accessible); + else + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field); + return 1; +} + +// skincolor_t *, field, number -> skincolors[] +static int skincolor_set(lua_State *L) +{ + UINT32 i; + skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR)); + const char *field = luaL_checkstring(L, 2); + UINT16 cnum = (UINT16)(info-skincolors); + + I_Assert(info != NULL); + I_Assert(info >= skincolors); + + if (!cnum || cnum >= numskincolors) + return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", cnum, numskincolors-1); + + if (fastcmp(field,"name")) { + const char* n = luaL_checkstring(L, 3); + strlcpy(info->name, n, MAXCOLORNAME+1); + if (strlen(n) > MAXCOLORNAME) + CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') longer than %d chars; clipped to %s.\n", n, MAXCOLORNAME, info->name); +#if 0 + if (strchr(info->name, ' ') != NULL) + CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') contains spaces.\n", info->name); +#endif + + if (info->name[0] != '\0') // don't check empty string for dupe + { + UINT16 dupecheck = R_GetColorByName(info->name); + if (!stricmp(info->name, skincolors[SKINCOLOR_NONE].name) || (dupecheck && (dupecheck != cnum))) + CONS_Alert(CONS_WARNING, "skincolor_t field 'name' ('%s') is a duplicate of another skincolor's name.\n", info->name); + } + } else if (fastcmp(field,"ramp")) { + if (!lua_istable(L, 3) && luaL_checkudata(L, 3, META_COLORRAMP) == NULL) + return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' must be a table or array."); + else if (lua_istable(L, 3)) + setRamp(L, info); + else + for (i=0; iramp[i] = (*((UINT8 **)luaL_checkudata(L, 3, META_COLORRAMP)))[i]; + skincolor_modified[cnum] = true; + } else if (fastcmp(field,"invcolor")) { + UINT16 v = (UINT16)luaL_checkinteger(L, 3); + if (v >= numskincolors) + return luaL_error(L, "skincolor_t field 'invcolor' out of range (1 - %d)", numskincolors-1); + info->invcolor = v; + } else if (fastcmp(field,"invshade")) + info->invshade = (UINT8)luaL_checkinteger(L, 3)%COLORRAMPSIZE; + else if (fastcmp(field,"chatcolor")) + info->chatcolor = (UINT16)luaL_checkinteger(L, 3); + else if (fastcmp(field,"accessible")) { + boolean v = lua_toboolean(L, 3); + if (cnum < FIRSTSUPERCOLOR && v != skincolors[cnum].accessible) + return luaL_error(L, "skincolors[] index %d is a standard color; accessibility changes are prohibited.", cnum); + else + info->accessible = v; + } else + CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "skincolor_t", field); + return 1; +} + +// skincolor_t * -> SKINCOLOR_* +static int skincolor_num(lua_State *L) +{ + skincolor_t *info = *((skincolor_t **)luaL_checkudata(L, 1, META_SKINCOLOR)); + + I_Assert(info != NULL); + I_Assert(info >= skincolors); + + lua_pushinteger(L, info-skincolors); + return 1; +} + +// ramp, n -> ramp[n] +static int colorramp_get(lua_State *L) +{ + UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP)); + UINT32 n = luaL_checkinteger(L, 2); + if (n >= COLORRAMPSIZE) + return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1); + lua_pushinteger(L, colorramp[n]); + return 1; +} + +// ramp, n, value -> ramp[n] = value +static int colorramp_set(lua_State *L) +{ + UINT8 *colorramp = *((UINT8 **)luaL_checkudata(L, 1, META_COLORRAMP)); + UINT16 cnum = (UINT16)(((UINT8*)colorramp - (UINT8*)(skincolors[0].ramp))/sizeof(skincolor_t)); + UINT32 n = luaL_checkinteger(L, 2); + UINT8 i = (UINT8)luaL_checkinteger(L, 3); + if (!cnum || cnum >= numskincolors) + return luaL_error(L, "skincolors[] index %d out of range (1 - %d)", cnum, numskincolors-1); + if (n >= COLORRAMPSIZE) + return luaL_error(L, LUA_QL("skincolor_t") " field 'ramp' index %d out of range (0 - %d)", n, COLORRAMPSIZE-1); + if (hud_running) + return luaL_error(L, "Do not alter skincolor_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter skincolor_t in CMD building code!"); + colorramp[n] = i; + skincolor_modified[cnum] = true; + return 0; +} + +// #ramp -> COLORRAMPSIZE +static int colorramp_len(lua_State *L) +{ + lua_pushinteger(L, COLORRAMPSIZE); + return 1; +} + ////////////////////////////// // // Now push all these functions into the Lua state! @@ -915,6 +1789,28 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + luaL_newmetatable(L, META_SKINCOLOR); + lua_pushcfunction(L, skincolor_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, skincolor_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, skincolor_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_COLORRAMP); + lua_pushcfunction(L, colorramp_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, colorramp_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, colorramp_len); + lua_setfield(L, -2, "__len"); + lua_pop(L,1); + luaL_newmetatable(L, META_SFXINFO); lua_pushcfunction(L, sfxinfo_get); lua_setfield(L, -2, "__index"); @@ -926,6 +1822,39 @@ int LUA_InfoLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + luaL_newmetatable(L, META_SPRITEINFO); + lua_pushcfunction(L, spriteinfo_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, spriteinfo_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, spriteinfo_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_PIVOTLIST); + lua_pushcfunction(L, pivotlist_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, pivotlist_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, pivotlist_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_FRAMEPIVOT); + lua_pushcfunction(L, framepivot_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, framepivot_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, framepivot_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getSprname); @@ -936,6 +1865,29 @@ int LUA_InfoLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "sprnames"); + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getSpr2name); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_spr2namelen); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "spr2names"); + + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getSpr2default); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setSpr2default); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_spr2namelen); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "spr2defaults"); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getState); @@ -962,6 +1914,19 @@ int LUA_InfoLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "mobjinfo"); + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getSkinColor); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setSkinColor); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_skincolorslen); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "skincolors"); + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getSfxInfo); @@ -976,7 +1941,30 @@ int LUA_InfoLib(lua_State *L) lua_pushvalue(L, -1); lua_setglobal(L, "S_sfx"); lua_setglobal(L, "sfxinfo"); + + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getSpriteInfo); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setSpriteInfo); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_spriteinfolen); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "spriteinfo"); + + luaL_newmetatable(L, META_LUABANKS); + lua_pushcfunction(L, lib_getluabanks); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_setluabanks); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, lib_luabankslen); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + return 0; } - -#endif diff --git a/src/lua_libs.h b/src/lua_libs.h index cb1cb49c7..756459a55 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -10,8 +10,6 @@ /// \file lua_libs.h /// \brief libraries for Lua scripting -#ifdef HAVE_BLUA - extern lua_State *gL; #define LREG_VALID "VALID_USERDATA" @@ -22,6 +20,11 @@ extern lua_State *gL; #define META_STATE "STATE_T*" #define META_MOBJINFO "MOBJINFO_T*" #define META_SFXINFO "SFXINFO_T*" +#define META_SKINCOLOR "SKINCOLOR_T*" +#define META_COLORRAMP "SKINCOLOR_T*RAMP" +#define META_SPRITEINFO "SPRITEINFO_T*" +#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]" +#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*" #define META_MOBJ "MOBJ_T*" #define META_MAPTHING "MAPTHING_T*" @@ -40,23 +43,43 @@ extern lua_State *gL; #define META_SUBSECTOR "SUBSECTOR_T*" #define META_SECTOR "SECTOR_T*" #define META_FFLOOR "FFLOOR_T*" -#ifdef ESLOPE +#ifdef HAVE_LUA_SEGS +#define META_SEG "SEG_T*" +#define META_NODE "NODE_T*" +#endif #define META_SLOPE "PSLOPE_T*" #define META_VECTOR2 "VECTOR2_T" #define META_VECTOR3 "VECTOR3_T" -#endif #define META_MAPHEADER "MAPHEADER_T*" +#define META_POLYOBJ "POLYOBJ_T*" + #define META_CVAR "CONSVAR_T*" #define META_SECTORLINES "SECTOR_T*LINES" #define META_SIDENUM "LINE_T*SIDENUM" +#define META_LINEARGS "LINE_T*ARGS" +#define META_LINESTRINGARGS "LINE_T*STRINGARGS" +#define META_THINGARGS "MAPTHING_T*ARGS" +#define META_THINGSTRINGARGS "MAPTHING_T*STRINGARGS" +#define META_POLYOBJVERTICES "POLYOBJ_T*VERTICES" +#define META_POLYOBJLINES "POLYOBJ_T*LINES" +#ifdef HAVE_LUA_SEGS +#define META_NODEBBOX "NODE_T*BBOX" +#define META_NODECHILDREN "NODE_T*CHILDREN" +#endif + +#define META_BBOX "BOUNDING_BOX" #define META_HUDINFO "HUDINFO_T*" #define META_PATCH "PATCH_T*" #define META_COLORMAP "COLORMAP" #define META_CAMERA "CAMERA_T*" +#define META_ACTION "ACTIONF_T*" + +#define META_LUABANKS "LUABANKS[]*" + boolean luaL_checkboolean(lua_State *L, int narg); int LUA_EnumLib(lua_State *L); @@ -71,7 +94,6 @@ int LUA_PlayerLib(lua_State *L); int LUA_SkinLib(lua_State *L); int LUA_ThinkerLib(lua_State *L); int LUA_MapLib(lua_State *L); +int LUA_PolyObjLib(lua_State *L); int LUA_BlockmapLib(lua_State *L); int LUA_HudLib(lua_State *L); - -#endif diff --git a/src/lua_maplib.c b/src/lua_maplib.c index 0522cb737..bcba5fb01 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,20 +11,18 @@ /// \brief game map library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA #include "r_state.h" #include "p_local.h" #include "p_setup.h" #include "z_zone.h" -#ifdef ESLOPE #include "p_slopes.h" -#endif +#include "p_polyobj.h" #include "r_main.h" #include "lua_script.h" #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#include "lua_hook.h" // cmd errors +#include "lua_hook.h" // hook_cmd_running errors #include "dehacked.h" #include "fastcmp.h" @@ -43,13 +41,9 @@ enum sector_e { sector_heightsec, sector_camsec, sector_lines, -#ifdef ESLOPE sector_ffloors, sector_fslope, sector_cslope -#else - sector_ffloors -#endif }; static const char *const sector_opt[] = { @@ -66,10 +60,8 @@ static const char *const sector_opt[] = { "camsec", "lines", "ffloors", -#ifdef ESLOPE "f_slope", "c_slope", -#endif NULL}; enum subsector_e { @@ -77,6 +69,7 @@ enum subsector_e { subsector_sector, subsector_numlines, subsector_firstline, + subsector_polyList }; static const char *const subsector_opt[] = { @@ -84,6 +77,7 @@ static const char *const subsector_opt[] = { "sector", "numlines", "firstline", + "polyList", NULL}; enum line_e { @@ -95,14 +89,19 @@ enum line_e { line_flags, line_special, line_tag, + line_args, + line_stringargs, line_sidenum, line_frontside, line_backside, + line_alpha, + line_executordelay, line_slopetype, line_frontsector, line_backsector, line_firsttag, line_nexttag, + line_polyobj, line_text, line_callcount }; @@ -116,14 +115,19 @@ static const char *const line_opt[] = { "flags", "special", "tag", + "args", + "stringargs", "sidenum", "frontside", "backside", + "alpha", + "executordelay", "slopetype", "frontsector", "backsector", "firsttag", "nexttag", + "polyobj", "text", "callcount", NULL}; @@ -135,6 +139,7 @@ enum side_e { side_toptexture, side_bottomtexture, side_midtexture, + side_line, side_sector, side_special, side_repeatcnt, @@ -148,6 +153,7 @@ static const char *const side_opt[] = { "toptexture", "bottomtexture", "midtexture", + "line", "sector", "special", "repeatcnt", @@ -158,14 +164,20 @@ enum vertex_e { vertex_valid = 0, vertex_x, vertex_y, - vertex_z + vertex_floorz, + vertex_floorzset, + vertex_ceilingz, + vertex_ceilingzset }; static const char *const vertex_opt[] = { "valid", "x", "y", - "z", + "floorz", + "floorzset", + "ceilingz", + "ceilingzset", NULL}; enum ffloor_e { @@ -175,10 +187,8 @@ enum ffloor_e { ffloor_toplightlevel, ffloor_bottomheight, ffloor_bottompic, -#ifdef ESLOPE ffloor_tslope, ffloor_bslope, -#endif ffloor_sector, ffloor_flags, ffloor_master, @@ -195,10 +205,8 @@ static const char *const ffloor_opt[] = { "toplightlevel", "bottomheight", "bottompic", -#ifdef ESLOPE "t_slope", "b_slope", -#endif "sector", // secnum pushed as control sector userdata "flags", "master", // control linedef @@ -208,7 +216,84 @@ static const char *const ffloor_opt[] = { "alpha", NULL}; -#ifdef ESLOPE +#ifdef HAVE_LUA_SEGS +enum seg_e { + seg_valid = 0, + seg_v1, + seg_v2, + seg_side, + seg_offset, + seg_angle, + seg_sidedef, + seg_linedef, + seg_frontsector, + seg_backsector, + seg_polyseg +}; + +static const char *const seg_opt[] = { + "valid", + "v1", + "v2", + "side", + "offset", + "angle", + "sidedef", + "linedef", + "frontsector", + "backsector", + "polyseg", + NULL}; + +enum node_e { + node_valid = 0, + node_x, + node_y, + node_dx, + node_dy, + node_bbox, + node_children, +}; + +static const char *const node_opt[] = { + "valid", + "x", + "y", + "dx", + "dy", + "bbox", + "children", + NULL}; + +enum nodechild_e { + nodechild_valid = 0, + nodechild_right, + nodechild_left, +}; + +static const char *const nodechild_opt[] = { + "valid", + "right", + "left", + NULL}; +#endif + +enum bbox_e { + bbox_valid = 0, + bbox_top, + bbox_bottom, + bbox_left, + bbox_right, +}; + +static const char *const bbox_opt[] = { + "valid", + "top", + "bottom", + "left", + "right", + NULL}; + enum slope_e { slope_valid = 0, slope_o, @@ -217,8 +302,6 @@ enum slope_e { slope_normal, slope_zangle, slope_xydirection, - slope_sourceline, - slope_refpos, slope_flags }; @@ -230,8 +313,6 @@ static const char *const slope_opt[] = { "normal", "zangle", "xydirection", - "sourceline", - "refpos", "flags", NULL}; @@ -247,17 +328,22 @@ static const char *const vector_opt[] = { "y", "z", NULL}; -#endif static const char *const array_opt[] ={"iterate",NULL}; static const char *const valid_opt[] ={"valid",NULL}; +///////////////////////////////////////////// +// sector/subsector list iterate functions // +///////////////////////////////////////////// + // iterates through a sector's thinglist! static int lib_iterateSectorThinglist(lua_State *L) { mobj_t *state = NULL; mobj_t *thing = NULL; + INLEVEL + if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sector.thinglist() directly, use it as 'for rover in sector.thinglist do end'."); @@ -291,6 +377,8 @@ static int lib_iterateSectorFFloors(lua_State *L) ffloor_t *state = NULL; ffloor_t *ffloor = NULL; + INLEVEL + if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sector.ffloors() directly, use it as 'for rover in sector.ffloors do end'."); @@ -318,6 +406,41 @@ static int lib_iterateSectorFFloors(lua_State *L) return 0; } +// iterates through a subsector's polyList! (for polyobj_t) +static int lib_iterateSubSectorPolylist(lua_State *L) +{ + polyobj_t *state = NULL; + polyobj_t *po = NULL; + + INLEVEL + + if (lua_gettop(L) < 2) + return luaL_error(L, "Don't call subsector.polyList() directly, use it as 'for polyobj in subsector.polyList do end'."); + + if (!lua_isnil(L, 1)) + state = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + else + return 0; // no polylist to iterate through sorry! + + lua_settop(L, 2); + lua_remove(L, 1); // remove state now. + + if (!lua_isnil(L, 1)) + { + po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + po = (polyobj_t *)(po->link.next); + } + else + po = state; // state is used as the "start" of the polylist + + if (po) + { + LUA_PushUserdata(L, po, META_POLYOBJ); + return 1; + } + return 0; +} + static int sector_iterate(lua_State *L) { lua_pushvalue(L, lua_upvalueindex(1)); // iterator function, or the "generator" @@ -326,39 +449,59 @@ static int sector_iterate(lua_State *L) return 3; } +//////////////////// +// sector.lines[] // +//////////////////// + // sector.lines, i -> sector.lines[i] // sector.lines.valid, for validity checking +// +// 25/9/19 Monster Iestyn +// Modified this and _num to use triple pointers, to allow for a new hack of mine involving offsetof +// this way we don't need to check frontsector or backsector of line #0 in the array +// static int sectorlines_get(lua_State *L) { - line_t **seclines = *((line_t ***)luaL_checkudata(L, 1, META_SECTORLINES)); + line_t ***seclines = *((line_t ****)luaL_checkudata(L, 1, META_SECTORLINES)); size_t i; size_t numoflines = 0; lua_settop(L, 2); if (!lua_isnumber(L, 2)) { int field = luaL_checkoption(L, 2, NULL, valid_opt); - if (!seclines) + if (!seclines || !(*seclines)) { if (field == 0) { lua_pushboolean(L, 0); return 1; } - return luaL_error(L, "accessed sector_t doesn't exist anymore."); + return luaL_error(L, "accessed sector_t.lines doesn't exist anymore."); } else if (field == 0) { lua_pushboolean(L, 1); return 1; } } +/* a snip from sector_t struct in r_defs.h, for reference + size_t linecount; + struct line_s **lines; // [linecount] size +*/ + // get the "linecount" by shifting our retrieved memory address of "lines" to where "linecount" is in the sector_t, then dereferencing the result + // we need this to determine the array's actual size, and therefore also the maximum value allowed as an index + // this only works if seclines is actually a pointer to a sector's lines member in memory, oh boy + numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount); + +/* OLD HACK // check first linedef to figure which of its sectors owns this sector->lines pointer // then check that sector's linecount to get a maximum index - //if (!seclines[0]) + //if (!(*seclines)[0]) //return luaL_error(L, "no lines found!"); // no first linedef????? - if (seclines[0]->frontsector->lines == seclines) - numoflines = seclines[0]->frontsector->linecount; - else if (seclines[0]->backsector && seclines[0]->backsector->lines == seclines) // check backsector exists first - numoflines = seclines[0]->backsector->linecount; + if ((*seclines)[0]->frontsector->lines == *seclines) + numoflines = (*seclines)[0]->frontsector->linecount; + else if ((*seclines)[0]->backsector && *seclines[0]->backsector->lines == *seclines) // check backsector exists first + numoflines = (*seclines)[0]->backsector->linecount; //if neither sector has it then ??? +*/ if (!numoflines) return luaL_error(L, "no lines found!"); @@ -366,27 +509,29 @@ static int sectorlines_get(lua_State *L) i = (size_t)lua_tointeger(L, 2); if (i >= numoflines) return 0; - LUA_PushUserdata(L, seclines[i], META_LINE); + LUA_PushUserdata(L, (*seclines)[i], META_LINE); return 1; } +// #(sector.lines) -> sector.linecount static int sectorlines_num(lua_State *L) { - line_t **seclines = *((line_t ***)luaL_checkudata(L, 1, META_SECTORLINES)); + line_t ***seclines = *((line_t ****)luaL_checkudata(L, 1, META_SECTORLINES)); size_t numoflines = 0; - // check first linedef to figure which of its sectors owns this sector->lines pointer - // then check that sector's linecount to get a maximum index - //if (!seclines[0]) - //return luaL_error(L, "no lines found!"); // no first linedef????? - if (seclines[0]->frontsector->lines == seclines) - numoflines = seclines[0]->frontsector->linecount; - else if (seclines[0]->backsector && seclines[0]->backsector->lines == seclines) // check backsector exists first - numoflines = seclines[0]->backsector->linecount; - //if neither sector has it then ??? + + if (!seclines || !(*seclines)) + return luaL_error(L, "accessed sector_t.lines doesn't exist anymore."); + + // see comments in the _get function above + numoflines = *(size_t *)FIELDFROM (sector_t, seclines, lines,/* -> */linecount); lua_pushinteger(L, numoflines); return 1; } +////////////// +// sector_t // +////////////// + static int sector_get(lua_State *L) { sector_t *sector = *((sector_t **)luaL_checkudata(L, 1, META_SECTOR)); @@ -456,21 +601,19 @@ static int sector_get(lua_State *L) LUA_PushUserdata(L, §ors[sector->camsec], META_SECTOR); return 1; case sector_lines: // lines - LUA_PushUserdata(L, sector->lines, META_SECTORLINES); + LUA_PushUserdata(L, §or->lines, META_SECTORLINES); // push the address of the "lines" member in the struct, to allow our hacks in sectorlines_get/_num to work return 1; case sector_ffloors: // ffloors lua_pushcfunction(L, lib_iterateSectorFFloors); LUA_PushUserdata(L, sector->ffloors, META_FFLOOR); lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateFFloors and sector->ffloors as upvalues for the function return 1; -#ifdef ESLOPE case sector_fslope: // f_slope LUA_PushUserdata(L, sector->f_slope, META_SLOPE); return 1; case sector_cslope: // c_slope LUA_PushUserdata(L, sector->c_slope, META_SLOPE); return 1; -#endif } return 0; } @@ -486,7 +629,7 @@ static int sector_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter sector_t in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter sector_t in BuildCMD code!"); + return luaL_error(L, "Do not alter sector_t in CMD building code!"); switch(field) { @@ -494,11 +637,10 @@ static int sector_set(lua_State *L) case sector_thinglist: // thinglist case sector_heightsec: // heightsec case sector_camsec: // camsec + case sector_lines: // lines case sector_ffloors: // ffloors -#ifdef ESLOPE case sector_fslope: // f_slope case sector_cslope: // c_slope -#endif default: return luaL_error(L, "sector_t field " LUA_QS " cannot be set.", sector_opt[field]); case sector_floorheight: { // floorheight @@ -555,6 +697,10 @@ static int sector_num(lua_State *L) return 1; } +///////////////// +// subsector_t // +///////////////// + static int subsector_get(lua_State *L) { subsector_t *subsector = *((subsector_t **)luaL_checkudata(L, 1, META_SUBSECTOR)); @@ -583,6 +729,11 @@ static int subsector_get(lua_State *L) case subsector_firstline: lua_pushinteger(L, subsector->firstline); return 1; + case subsector_polyList: // polyList + lua_pushcfunction(L, lib_iterateSubSectorPolylist); + LUA_PushUserdata(L, subsector->polyList, META_POLYOBJ); + lua_pushcclosure(L, sector_iterate, 2); // push lib_iterateSubSectorPolylist and subsector->polyList as upvalues for the function + return 1; } return 0; } @@ -594,6 +745,46 @@ static int subsector_num(lua_State *L) return 1; } +//////////// +// line_t // +//////////// + +// args, i -> args[i] +static int lineargs_get(lua_State *L) +{ + INT32 *args = *((INT32**)luaL_checkudata(L, 1, META_LINEARGS)); + int i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMLINEARGS) + return luaL_error(L, LUA_QL("line_t.args") " index cannot be %d", i); + lua_pushinteger(L, args[i]); + return 1; +} + +// #args -> NUMLINEARGS +static int lineargs_len(lua_State* L) +{ + lua_pushinteger(L, NUMLINEARGS); + return 1; +} + +// stringargs, i -> stringargs[i] +static int linestringargs_get(lua_State *L) +{ + char **stringargs = *((char***)luaL_checkudata(L, 1, META_LINESTRINGARGS)); + int i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMLINESTRINGARGS) + return luaL_error(L, LUA_QL("line_t.stringargs") " index cannot be %d", i); + lua_pushstring(L, stringargs[i]); + return 1; +} + +// #stringargs -> NUMLINESTRINGARGS +static int linestringargs_len(lua_State *L) +{ + lua_pushinteger(L, NUMLINESTRINGARGS); + return 1; +} + static int line_get(lua_State *L) { line_t *line = *((line_t **)luaL_checkudata(L, 1, META_LINE)); @@ -634,6 +825,12 @@ static int line_get(lua_State *L) case line_tag: lua_pushinteger(L, line->tag); return 1; + case line_args: + LUA_PushUserdata(L, line->args, META_LINEARGS); + return 1; + case line_stringargs: + LUA_PushUserdata(L, line->stringargs, META_LINESTRINGARGS); + return 1; case line_sidenum: LUA_PushUserdata(L, line->sidenum, META_SIDENUM); return 1; @@ -645,6 +842,12 @@ static int line_get(lua_State *L) return 0; LUA_PushUserdata(L, &sides[line->sidenum[1]], META_SIDE); return 1; + case line_alpha: + lua_pushfixed(L, line->alpha); + return 1; + case line_executordelay: + lua_pushinteger(L, line->executordelay); + return 1; case line_slopetype: switch(line->slopetype) { @@ -674,6 +877,9 @@ static int line_get(lua_State *L) case line_nexttag: lua_pushinteger(L, line->nexttag); return 1; + case line_polyobj: + LUA_PushUserdata(L, line->polyobj, META_POLYOBJ); + return 1; case line_text: lua_pushstring(L, line->text); return 1; @@ -691,6 +897,10 @@ static int line_num(lua_State *L) return 1; } +//////////////////// +// line.sidenum[] // +//////////////////// + static int sidenum_get(lua_State *L) { UINT16 *sidenum = *((UINT16 **)luaL_checkudata(L, 1, META_SIDENUM)); @@ -719,6 +929,10 @@ static int sidenum_get(lua_State *L) return 1; } +//////////// +// side_t // +//////////// + static int side_get(lua_State *L) { side_t *side = *((side_t **)luaL_checkudata(L, 1, META_SIDE)); @@ -753,6 +967,9 @@ static int side_get(lua_State *L) case side_midtexture: lua_pushinteger(L, side->midtexture); return 1; + case side_line: + LUA_PushUserdata(L, side->line, META_LINE); + return 1; case side_sector: LUA_PushUserdata(L, side->sector, META_SECTOR); return 1; @@ -786,6 +1003,7 @@ static int side_set(lua_State *L) switch(field) { case side_valid: // valid + case side_line: case side_sector: case side_special: case side_text: @@ -820,6 +1038,10 @@ static int side_num(lua_State *L) return 1; } +////////////// +// vertex_t // +////////////// + static int vertex_get(lua_State *L) { vertex_t *vertex = *((vertex_t **)luaL_checkudata(L, 1, META_VERTEX)); @@ -845,8 +1067,17 @@ static int vertex_get(lua_State *L) case vertex_y: lua_pushfixed(L, vertex->y); return 1; - case vertex_z: - lua_pushfixed(L, vertex->z); + case vertex_floorzset: + lua_pushboolean(L, vertex->floorzset); + return 1; + case vertex_ceilingzset: + lua_pushboolean(L, vertex->ceilingzset); + return 1; + case vertex_floorz: + lua_pushfixed(L, vertex->floorz); + return 1; + case vertex_ceilingz: + lua_pushfixed(L, vertex->ceilingz); return 1; } return 0; @@ -859,9 +1090,295 @@ static int vertex_num(lua_State *L) return 1; } +#ifdef HAVE_LUA_SEGS + +/////////// +// seg_t // +/////////// + +static int seg_get(lua_State *L) +{ + seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); + enum seg_e field = luaL_checkoption(L, 2, seg_opt[0], seg_opt); + + if (!seg) + { + if (field == seg_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed seg_t doesn't exist anymore."); + } + + switch(field) + { + case seg_valid: // valid + lua_pushboolean(L, 1); + return 1; + case seg_v1: + LUA_PushUserdata(L, seg->v1, META_VERTEX); + return 1; + case seg_v2: + LUA_PushUserdata(L, seg->v2, META_VERTEX); + return 1; + case seg_side: + lua_pushinteger(L, seg->side); + return 1; + case seg_offset: + lua_pushfixed(L, seg->offset); + return 1; + case seg_angle: + lua_pushangle(L, seg->angle); + return 1; + case seg_sidedef: + LUA_PushUserdata(L, seg->sidedef, META_SIDE); + return 1; + case seg_linedef: + LUA_PushUserdata(L, seg->linedef, META_LINE); + return 1; + case seg_frontsector: + LUA_PushUserdata(L, seg->frontsector, META_SECTOR); + return 1; + case seg_backsector: + LUA_PushUserdata(L, seg->backsector, META_SECTOR); + return 1; + case seg_polyseg: + LUA_PushUserdata(L, seg->polyseg, META_POLYOBJ); + return 1; + } + return 0; +} + +static int seg_num(lua_State *L) +{ + seg_t *seg = *((seg_t **)luaL_checkudata(L, 1, META_SEG)); + lua_pushinteger(L, seg-segs); + return 1; +} + +//////////// +// node_t // +//////////// + +static int node_get(lua_State *L) +{ + node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); + enum node_e field = luaL_checkoption(L, 2, node_opt[0], node_opt); + + if (!node) + { + if (field == node_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } + + switch(field) + { + case node_valid: // valid + lua_pushboolean(L, 1); + return 1; + case node_x: + lua_pushfixed(L, node->x); + return 1; + case node_y: + lua_pushfixed(L, node->y); + return 1; + case node_dx: + lua_pushfixed(L, node->x); + return 1; + case node_dy: + lua_pushfixed(L, node->x); + return 1; + case node_bbox: + LUA_PushUserdata(L, node->bbox, META_NODEBBOX); + return 1; + case node_children: + LUA_PushUserdata(L, node->children, META_NODECHILDREN); + return 1; + } + return 0; +} + +static int node_num(lua_State *L) +{ + node_t *node = *((node_t **)luaL_checkudata(L, 1, META_NODE)); + lua_pushinteger(L, node-nodes); + return 1; +} + +/////////////// +// node.bbox // +/////////////// + +/* +// node.bbox[i][j]: i = 0 or 1, j = 0 1 2 or 3 +// NOTE: 2D arrays are NOT double pointers, +// the second bbox will be directly after the first in memory (hence the way the bbox is pushed here) +// this function handles the [i] part, bbox_get handles the [j] part +static int nodebbox_get(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!bbox) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + LUA_PushUserdata(L, bbox + i*4*sizeof(fixed_t), META_BBOX); + return 1; +} +*/ +static int nodebbox_call(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_NODEBBOX)); + int i, j; + int n = lua_gettop(L); + + if (!bbox) + return luaL_error(L, "accessed node bbox doesn't exist anymore."); + if (n < 3) + return luaL_error(L, "arguments 2 and/or 3 not given (expected node.bbox(child, coord))"); + // get child + if (!lua_isnumber(L, 2)) { + enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt); + switch (field) { + case nodechild_right: i = 0; break; + case nodechild_left: i = 1; break; + default: + return luaL_error(L, "invalid node child \"%s\".", lua_tostring(L, 2)); + } + } + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + } + // get bbox coord + if (!lua_isnumber(L, 3)) { + enum bbox_e field = luaL_checkoption(L, 3, bbox_opt[0], bbox_opt); + switch (field) { + case bbox_top: j = BOXTOP; break; + case bbox_bottom: j = BOXBOTTOM; break; + case bbox_left: j = BOXLEFT; break; + case bbox_right: j = BOXRIGHT; break; + default: + return luaL_error(L, "invalid bbox coordinate \"%s\".", lua_tostring(L, 3)); + } + } + else { + j = lua_tointeger(L, 3); + if (j < 0 || j > 3) + return 0; + } + lua_pushinteger(L, bbox[i*4 + j]); + return 1; +} + +///////////////////// +// node.children[] // +///////////////////// + +// node.children[i]: i = 0 or 1 +static int nodechildren_get(lua_State *L) +{ + UINT16 *children = *((UINT16 **)luaL_checkudata(L, 1, META_NODECHILDREN)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + enum nodechild_e field = luaL_checkoption(L, 2, nodechild_opt[0], nodechild_opt); + if (!children) + { + if (field == nodechild_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed node_t doesn't exist anymore."); + } else if (field == nodechild_valid) { + lua_pushboolean(L, 1); + return 1; + } else switch (field) { + case nodechild_right: i = 0; break; + case nodechild_left: i = 1; break; + default: return 0; + } + } + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 1) + return 0; + } + lua_pushinteger(L, children[i]); + return 1; +} +#endif + +////////// +// bbox // +////////// + +// bounding box (aka fixed_t array with four elements) +// NOTE: may be useful for polyobjects or other things later +static int bbox_get(lua_State *L) +{ + fixed_t *bbox = *((fixed_t **)luaL_checkudata(L, 1, META_BBOX)); + int i; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + enum bbox_e field = luaL_checkoption(L, 2, bbox_opt[0], bbox_opt); + if (!bbox) + { + if (field == bbox_valid) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed bbox doesn't exist anymore."); + } else if (field == bbox_valid) { + lua_pushboolean(L, 1); + return 1; + } else switch (field) { + case bbox_top: i = BOXTOP; break; + case bbox_bottom: i = BOXBOTTOM; break; + case bbox_left: i = BOXLEFT; break; + case bbox_right: i = BOXRIGHT; break; + default: return 0; + } + } + else { + i = lua_tointeger(L, 2); + if (i < 0 || i > 3) + return 0; + } + lua_pushinteger(L, bbox[i]); + return 1; +} + +/////////////// +// sectors[] // +/////////////// + static int lib_iterateSectors(lua_State *L) { size_t i = 0; + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sectors.iterate() directly, use it as 'for sector in sectors.iterate do end'."); lua_settop(L, 2); @@ -879,6 +1396,7 @@ static int lib_iterateSectors(lua_State *L) static int lib_getSector(lua_State *L) { int field; + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -905,9 +1423,14 @@ static int lib_numsectors(lua_State *L) return 1; } +////////////////// +// subsectors[] // +////////////////// + static int lib_iterateSubsectors(lua_State *L) { size_t i = 0; + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call subsectors.iterate() directly, use it as 'for subsector in subsectors.iterate do end'."); lua_settop(L, 2); @@ -925,6 +1448,7 @@ static int lib_iterateSubsectors(lua_State *L) static int lib_getSubsector(lua_State *L) { int field; + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -951,9 +1475,14 @@ static int lib_numsubsectors(lua_State *L) return 1; } +///////////// +// lines[] // +///////////// + static int lib_iterateLines(lua_State *L) { size_t i = 0; + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call lines.iterate() directly, use it as 'for line in lines.iterate do end'."); lua_settop(L, 2); @@ -971,6 +1500,7 @@ static int lib_iterateLines(lua_State *L) static int lib_getLine(lua_State *L) { int field; + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -997,9 +1527,14 @@ static int lib_numlines(lua_State *L) return 1; } +///////////// +// sides[] // +///////////// + static int lib_iterateSides(lua_State *L) { size_t i = 0; + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call sides.iterate() directly, use it as 'for side in sides.iterate do end'."); lua_settop(L, 2); @@ -1017,6 +1552,7 @@ static int lib_iterateSides(lua_State *L) static int lib_getSide(lua_State *L) { int field; + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1043,9 +1579,14 @@ static int lib_numsides(lua_State *L) return 1; } +//////////////// +// vertexes[] // +//////////////// + static int lib_iterateVertexes(lua_State *L) { size_t i = 0; + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call vertexes.iterate() directly, use it as 'for vertex in vertexes.iterate do end'."); lua_settop(L, 2); @@ -1063,6 +1604,7 @@ static int lib_iterateVertexes(lua_State *L) static int lib_getVertex(lua_State *L) { int field; + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -1089,6 +1631,117 @@ static int lib_numvertexes(lua_State *L) return 1; } +#ifdef HAVE_LUA_SEGS + +//////////// +// segs[] // +//////////// + +static int lib_iterateSegs(lua_State *L) +{ + size_t i = 0; + INLEVEL + if (lua_gettop(L) < 2) + return luaL_error(L, "Don't call segs.iterate() directly, use it as 'for seg in segs.iterate do end'."); + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + i = (size_t)(*((seg_t **)luaL_checkudata(L, 1, META_SEG)) - segs)+1; + if (i < numsegs) + { + LUA_PushUserdata(L, &segs[i], META_SEG); + return 1; + } + return 0; +} + +static int lib_getSeg(lua_State *L) +{ + int field; + INLEVEL + lua_settop(L, 2); + lua_remove(L, 1); // dummy userdata table is unused. + if (lua_isnumber(L, 1)) + { + size_t i = lua_tointeger(L, 1); + if (i >= numsegs) + return 0; + LUA_PushUserdata(L, &segs[i], META_SEG); + return 1; + } + field = luaL_checkoption(L, 1, NULL, array_opt); + switch(field) + { + case 0: // iterate + lua_pushcfunction(L, lib_iterateSegs); + return 1; + } + return 0; +} + +static int lib_numsegs(lua_State *L) +{ + lua_pushinteger(L, numsegs); + return 1; +} + +///////////// +// nodes[] // +///////////// + +static int lib_iterateNodes(lua_State *L) +{ + size_t i = 0; + INLEVEL + if (lua_gettop(L) < 2) + return luaL_error(L, "Don't call nodes.iterate() directly, use it as 'for node in nodes.iterate do end'."); + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + i = (size_t)(*((node_t **)luaL_checkudata(L, 1, META_NODE)) - nodes)+1; + if (i < numsegs) + { + LUA_PushUserdata(L, &nodes[i], META_NODE); + return 1; + } + return 0; +} + +static int lib_getNode(lua_State *L) +{ + int field; + INLEVEL + lua_settop(L, 2); + lua_remove(L, 1); // dummy userdata table is unused. + if (lua_isnumber(L, 1)) + { + size_t i = lua_tointeger(L, 1); + if (i >= numnodes) + return 0; + LUA_PushUserdata(L, &nodes[i], META_NODE); + return 1; + } + field = luaL_checkoption(L, 1, NULL, array_opt); + switch(field) + { + case 0: // iterate + lua_pushcfunction(L, lib_iterateNodes); + return 1; + } + return 0; +} + +static int lib_numnodes(lua_State *L) +{ + lua_pushinteger(L, numnodes); + return 1; +} +#endif + +////////////// +// ffloor_t // +////////////// + static int ffloor_get(lua_State *L) { ffloor_t *ffloor = *((ffloor_t **)luaL_checkudata(L, 1, META_FFLOOR)); @@ -1134,14 +1787,12 @@ static int ffloor_get(lua_State *L) lua_pushlstring(L, levelflat->name, i); return 1; } -#ifdef ESLOPE case ffloor_tslope: LUA_PushUserdata(L, *ffloor->t_slope, META_SLOPE); return 1; case ffloor_bslope: LUA_PushUserdata(L, *ffloor->b_slope, META_SLOPE); return 1; -#endif case ffloor_sector: LUA_PushUserdata(L, §ors[ffloor->secnum], META_SECTOR); return 1; @@ -1178,15 +1829,13 @@ static int ffloor_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter ffloor_t in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter ffloor_t in BuildCMD code!"); + return luaL_error(L, "Do not alter ffloor_t in CMD building code!"); switch(field) { case ffloor_valid: // valid -#ifdef ESLOPE case ffloor_tslope: // t_slope case ffloor_bslope: // b_slope -#endif case ffloor_sector: // sector case ffloor_master: // master case ffloor_target: // target @@ -1247,7 +1896,10 @@ static int ffloor_set(lua_State *L) return 0; } -#ifdef ESLOPE +////////////// +// pslope_t // +////////////// + static int slope_get(lua_State *L) { pslope_t *slope = *((pslope_t **)luaL_checkudata(L, 1, META_SLOPE)); @@ -1285,12 +1937,6 @@ static int slope_get(lua_State *L) case slope_xydirection: // xydirection lua_pushangle(L, slope->xydirection); return 1; - case slope_sourceline: // source linedef - LUA_PushUserdata(L, slope->sourceline, META_LINE); - return 1; - case slope_refpos: // refpos - lua_pushinteger(L, slope->refpos); - return 1; case slope_flags: // flags lua_pushinteger(L, slope->flags); return 1; @@ -1309,16 +1955,14 @@ static int slope_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter pslope_t in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter pslope_t in BuildCMD code!"); + return luaL_error(L, "Do not alter pslope_t in CMD building code!"); switch(field) // todo: reorganize this shit { case slope_valid: // valid - case slope_sourceline: // sourceline case slope_d: // d case slope_flags: // flags case slope_normal: // normal - case slope_refpos: // refpos default: return luaL_error(L, "pslope_t field " LUA_QS " cannot be set.", slope_opt[field]); case slope_o: { // o @@ -1386,6 +2030,10 @@ static int slope_set(lua_State *L) return 0; } +/////////////// +// vector*_t // +/////////////// + static int vector2_get(lua_State *L) { vector2_t *vec = *((vector2_t **)luaL_checkudata(L, 1, META_VECTOR2)); @@ -1422,7 +2070,10 @@ static int vector3_get(lua_State *L) return 0; } -#endif + +///////////////////// +// mapheaderinfo[] // +///////////////////// static int lib_getMapheaderinfo(lua_State *L) { @@ -1456,6 +2107,10 @@ static int lib_nummapheaders(lua_State *L) return 1; } +///////////////// +// mapheader_t // +///////////////// + static int mapheaderinfo_get(lua_State *L) { mapheader_t *header = *((mapheader_t **)luaL_checkudata(L, 1, META_MAPHEADER)); @@ -1468,11 +2123,15 @@ static int mapheaderinfo_get(lua_State *L) else if (fastcmp(field,"zonttl")) lua_pushstring(L, header->zonttl); else if (fastcmp(field,"actnum")) - lua_pushstring(L, header->actnum); + lua_pushinteger(L, header->actnum); else if (fastcmp(field,"typeoflevel")) lua_pushinteger(L, header->typeoflevel); else if (fastcmp(field,"nextlevel")) lua_pushinteger(L, header->nextlevel); + else if (fastcmp(field,"marathonnext")) + lua_pushinteger(L, header->marathonnext); + else if (fastcmp(field,"keywords")) + lua_pushstring(L, header->keywords); else if (fastcmp(field,"musname")) lua_pushstring(L, header->musname); else if (fastcmp(field,"mustrack")) @@ -1483,6 +2142,16 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->musinterfadeout); else if (fastcmp(field,"musintername")) lua_pushstring(L, header->musintername); + else if (fastcmp(field,"muspostbossname")) + lua_pushstring(L, header->muspostbossname); + else if (fastcmp(field,"muspostbosstrack")) + lua_pushinteger(L, header->muspostbosstrack); + else if (fastcmp(field,"muspostbosspos")) + lua_pushinteger(L, header->muspostbosspos); + else if (fastcmp(field,"muspostbossfadein")) + lua_pushinteger(L, header->muspostbossfadein); + else if (fastcmp(field,"musforcereset")) + lua_pushinteger(L, header->musforcereset); else if (fastcmp(field,"forcecharacter")) lua_pushstring(L, header->forcecharacter); else if (fastcmp(field,"weather")) @@ -1520,16 +2189,28 @@ static int mapheaderinfo_get(lua_State *L) lua_pushinteger(L, header->levelselect); else if (fastcmp(field,"bonustype")) lua_pushinteger(L, header->bonustype); - else if (fastcmp(field,"saveoverride")) - lua_pushinteger(L, header->saveoverride); + else if (fastcmp(field,"ltzzpatch")) + lua_pushstring(L, header->ltzzpatch); + else if (fastcmp(field,"ltzztext")) + lua_pushstring(L, header->ltzztext); + else if (fastcmp(field,"ltactdiamond")) + lua_pushstring(L, header->ltactdiamond); + else if (fastcmp(field,"maxbonuslives")) + lua_pushinteger(L, header->maxbonuslives); else if (fastcmp(field,"levelflags")) lua_pushinteger(L, header->levelflags); else if (fastcmp(field,"menuflags")) lua_pushinteger(L, header->menuflags); - /*else if (fastcmp(field,"automap")) - lua_pushboolean(L, header->automap);*/ else if (fastcmp(field,"mobj_scale")) lua_pushfixed(L, header->mobj_scale); + else if (fastcmp(field,"startrings")) + lua_pushinteger(L, header->startrings); + else if (fastcmp(field, "sstimer")) + lua_pushinteger(L, header->sstimer); + else if (fastcmp(field, "ssspheres")) + lua_pushinteger(L, header->ssspheres); + else if (fastcmp(field, "gravity")) + lua_pushfixed(L, header->gravity); // TODO add support for reading numGradedMares and grades else { // Read custom vars now @@ -1582,6 +2263,22 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__len"); lua_pop(L, 1); + luaL_newmetatable(L, META_LINEARGS); + lua_pushcfunction(L, lineargs_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lineargs_len); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_LINESTRINGARGS); + lua_pushcfunction(L, linestringargs_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, linestringargs_len); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + luaL_newmetatable(L, META_SIDENUM); lua_pushcfunction(L, sidenum_get); lua_setfield(L, -2, "__index"); @@ -1614,7 +2311,41 @@ int LUA_MapLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L, 1); -#ifdef ESLOPE +#ifdef HAVE_LUA_SEGS + luaL_newmetatable(L, META_SEG); + lua_pushcfunction(L, seg_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, seg_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_NODE); + lua_pushcfunction(L, node_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, node_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_NODEBBOX); + //lua_pushcfunction(L, nodebbox_get); + //lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, nodebbox_call); + lua_setfield(L, -2, "__call"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_NODECHILDREN); + lua_pushcfunction(L, nodechildren_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); +#endif + + luaL_newmetatable(L, META_BBOX); + lua_pushcfunction(L, bbox_get); + lua_setfield(L, -2, "__index"); + lua_pop(L, 1); + luaL_newmetatable(L, META_SLOPE); lua_pushcfunction(L, slope_get); lua_setfield(L, -2, "__index"); @@ -1632,7 +2363,6 @@ int LUA_MapLib(lua_State *L) lua_pushcfunction(L, vector3_get); lua_setfield(L, -2, "__index"); lua_pop(L, 1); -#endif luaL_newmetatable(L, META_MAPHEADER); lua_pushcfunction(L, mapheaderinfo_get); @@ -1692,6 +2422,28 @@ int LUA_MapLib(lua_State *L) lua_setmetatable(L, -2); lua_setglobal(L, "vertexes"); +#ifdef HAVE_LUA_SEGS + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getSeg); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numsegs); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "segs"); + + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getNode); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numnodes); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "nodes"); +#endif + lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_pushcfunction(L, lib_getMapheaderinfo); @@ -1703,5 +2455,3 @@ int LUA_MapLib(lua_State *L) lua_setglobal(L, "mapheaderinfo"); return 0; } - -#endif diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index b86a03c3b..c6c07fc7e 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,12 +11,10 @@ /// \brief basic math library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA //#include "fastcmp.h" #include "tables.h" #include "p_local.h" #include "doomstat.h" // for ALL7EMERALDS -#include "k_color.h" // KartColor_Opposite #include "lua_script.h" #include "lua_libs.h" @@ -82,20 +80,9 @@ static int lib_finecosine(lua_State *L) static int lib_finetangent(lua_State *L) { - // 2.1.15 ONLY HACK: optional boolean argument, only add ANGLE_90 if true - boolean newtan = lua_optboolean(L, 2); - - if (newtan) - { - // HACK: add ANGLE_90 to make tan() in Lua start at 0 like it should - // use & 4095 instead of & FINEMASK (8191), so it doesn't go out of the array's bounds - lua_pushfixed(L, FINETANGENT(((luaL_checkangle(L, 1)+ANGLE_90)>>ANGLETOFINESHIFT) & 4095)); - } - else - { - LUA_Deprecated(L, "tan(angle)", "tan(angle, true)"); - lua_pushfixed(L, FINETANGENT((luaL_checkangle(L, 1)>>ANGLETOFINESHIFT) & 4095)); - } + // HACK: add ANGLE_90 to make tan() in Lua start at 0 like it should + // use & 4095 instead of & FINEMASK (8191), so it doesn't go out of the array's bounds + lua_pushfixed(L, FINETANGENT(((luaL_checkangle(L, 1)+ANGLE_90)>>ANGLETOFINESHIFT) & 4095)); return 1; } @@ -124,12 +111,6 @@ static int lib_fixeddiv(lua_State *L) return 1; } -static int lib_fixedrem(lua_State *L) -{ - lua_pushfixed(L, FixedRem(luaL_checkfixed(L, 1), luaL_checkfixed(L, 2))); - return 1; -} - static int lib_fixedsqrt(lua_State *L) { fixed_t i = luaL_checkfixed(L, 1); @@ -185,15 +166,14 @@ static int lib_all7emeralds(lua_State *L) return 1; } -// Whee, special Lua-exclusive function for making use of Color_Opposite[] without needing *2 or +1 -// Returns both color and frame numbers! +// Returns both color and signpost shade numbers! static int lib_coloropposite(lua_State *L) { - UINT8 colornum = (UINT8)luaL_checkinteger(L, 1); - if (colornum >= MAXSKINCOLORS) - return luaL_error(L, "skincolor %d out of range (0 - %d).", colornum, MAXSKINCOLORS-1); - lua_pushinteger(L, KartColor_Opposite[colornum*2]); // push color - lua_pushinteger(L, KartColor_Opposite[colornum*2+1]); // push frame + UINT16 colornum = (UINT16)luaL_checkinteger(L, 1); + if (!colornum || colornum >= numskincolors) + return luaL_error(L, "skincolor %d out of range (1 - %d).", colornum, numskincolors-1); + lua_pushinteger(L, skincolors[colornum].invcolor); // push color + lua_pushinteger(L, skincolors[colornum].invshade); // push sign shade index, 0-15 return 2; } @@ -210,7 +190,6 @@ static luaL_Reg lib[] = { {"FixedMul", lib_fixedmul}, {"FixedInt", lib_fixedint}, {"FixedDiv", lib_fixeddiv}, - {"FixedRem", lib_fixedrem}, {"FixedSqrt", lib_fixedsqrt}, {"FixedHypot", lib_fixedhypot}, {"FixedFloor", lib_fixedfloor}, @@ -229,5 +208,3 @@ int LUA_MathLib(lua_State *L) luaL_register(L, NULL, lib); return 0; } - -#endif diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index 3c85c358b..f37fb93dc 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,9 +11,8 @@ /// \brief mobj/thing library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA #include "fastcmp.h" -#include "r_things.h" +#include "r_skins.h" #include "p_local.h" #include "g_game.h" #include "p_setup.h" @@ -21,7 +20,7 @@ #include "lua_script.h" #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#include "lua_hook.h" // cmd errors +#include "lua_hook.h" // hook_cmd_running errors static const char *const array_opt[] ={"iterate",NULL}; @@ -33,13 +32,19 @@ enum mobj_e { mobj_snext, mobj_sprev, mobj_angle, + mobj_pitch, + mobj_roll, + mobj_rollangle, mobj_sprite, mobj_frame, + mobj_sprite2, mobj_anim_duration, mobj_touching_sectorlist, mobj_subsector, mobj_floorz, mobj_ceilingz, + mobj_floorrover, + mobj_ceilingrover, mobj_radius, mobj_height, mobj_momx, @@ -83,10 +88,9 @@ enum mobj_e { mobj_extravalue2, mobj_cusval, mobj_cvmem, -#ifdef ESLOPE mobj_standingslope, -#endif mobj_colorized, + mobj_mirrored, mobj_shadowscale, mobj_whiteshadow, mobj_sprxoff, @@ -102,13 +106,19 @@ static const char *const mobj_opt[] = { "snext", "sprev", "angle", + "pitch", + "roll", + "rollangle", "sprite", "frame", + "sprite2", "anim_duration", "touching_sectorlist", "subsector", "floorz", "ceilingz", + "floorrover", + "ceilingrover", "radius", "height", "momx", @@ -152,10 +162,9 @@ static const char *const mobj_opt[] = { "extravalue2", "cusval", "cvmem", -#ifdef ESLOPE "standingslope", -#endif "colorized", + "mirrored", "shadowscale", "whiteshadow", "sprxoff", @@ -171,12 +180,15 @@ static int mobj_get(lua_State *L) enum mobj_e field = Lua_optoption(L, 2, NULL, mobj_opt); lua_settop(L, 2); - if (!mo) { + if (!mo || !ISINLEVEL) { if (field == mobj_valid) { lua_pushboolean(L, 0); return 1; } - return LUA_ErrInvalid(L, "mobj_t"); + if (!mo) { + return LUA_ErrInvalid(L, "mobj_t"); + } else + return luaL_error(L, "Do not access an mobj_t field outside a level!"); } switch(field) @@ -204,12 +216,24 @@ static int mobj_get(lua_State *L) case mobj_angle: lua_pushangle(L, mo->angle); break; + case mobj_pitch: + lua_pushangle(L, mo->pitch); + break; + case mobj_roll: + lua_pushangle(L, mo->roll); + break; + case mobj_rollangle: + lua_pushangle(L, mo->rollangle); + break; case mobj_sprite: lua_pushinteger(L, mo->sprite); break; case mobj_frame: lua_pushinteger(L, mo->frame); break; + case mobj_sprite2: + lua_pushinteger(L, mo->sprite2); + break; case mobj_anim_duration: lua_pushinteger(L, mo->anim_duration); break; @@ -224,6 +248,12 @@ static int mobj_get(lua_State *L) case mobj_ceilingz: lua_pushfixed(L, mo->ceilingz); break; + case mobj_floorrover: + LUA_PushUserdata(L, mo->floorrover, META_FFLOOR); + break; + case mobj_ceilingrover: + LUA_PushUserdata(L, mo->ceilingrover, META_FFLOOR); + break; case mobj_radius: lua_pushfixed(L, mo->radius); break; @@ -275,10 +305,19 @@ static int mobj_get(lua_State *L) // bprev -- same deal as sprev above, but for the blockmap. return UNIMPLEMENTED; case mobj_hnext: + if (mo->hnext && P_MobjWasRemoved(mo->hnext)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->hnext, NULL); + return 0; + } LUA_PushUserdata(L, mo->hnext, META_MOBJ); break; case mobj_hprev: - // implimented differently from sprev and bprev because SSNTails. + if (mo->hprev && P_MobjWasRemoved(mo->hprev)) + { // don't put invalid mobj back into Lua. + P_SetTarget(&mo->hprev, NULL); + return 0; + } LUA_PushUserdata(L, mo->hprev, META_MOBJ); break; case mobj_type: @@ -367,14 +406,15 @@ static int mobj_get(lua_State *L) case mobj_cvmem: lua_pushinteger(L, mo->cvmem); break; -#ifdef ESLOPE case mobj_standingslope: LUA_PushUserdata(L, mo->standingslope, META_SLOPE); break; -#endif case mobj_colorized: lua_pushboolean(L, mo->colorized); break; + case mobj_mirrored: + lua_pushboolean(L, mo->mirrored); + break; case mobj_shadowscale: lua_pushfixed(L, mo->shadowscale); break; @@ -416,11 +456,15 @@ static int mobj_set(lua_State *L) enum mobj_e field = Lua_optoption(L, 2, mobj_opt[0], mobj_opt); lua_settop(L, 3); + INLEVEL + if (!mo) return LUA_ErrInvalid(L, "mobj_t"); if (hud_running) return luaL_error(L, "Do not alter mobj_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter mobj_t in CMD building code!"); if (hook_cmd_running) return luaL_error(L, "Do not alter mobj_t in BuildCMD code!"); @@ -441,6 +485,8 @@ static int mobj_set(lua_State *L) P_CheckPosition(mo, mo->x, mo->y); mo->floorz = tmfloorz; mo->ceilingz = tmceilingz; + mo->floorrover = tmfloorrover; + mo->ceilingrover = tmceilingrover; P_SetTarget(&tmthing, ptmthing); break; } @@ -450,14 +496,17 @@ static int mobj_set(lua_State *L) return UNIMPLEMENTED; case mobj_angle: mo->angle = luaL_checkangle(L, 3); - if (mo->player == &players[consoleplayer]) - localangle[0] = mo->angle; - else if (mo->player == &players[displayplayers[1]]) - localangle[1] = mo->angle; - else if (mo->player == &players[displayplayers[2]]) - localangle[2] = mo->angle; - else if (mo->player == &players[displayplayers[3]]) - localangle[3] = mo->angle; + if (mo->player) + P_SetPlayerAngle(mo->player, mo->angle); + break; + case mobj_pitch: + mo->pitch = luaL_checkangle(L, 3); + break; + case mobj_roll: + mo->roll = luaL_checkangle(L, 3); + break; + case mobj_rollangle: + mo->rollangle = luaL_checkangle(L, 3); break; case mobj_sprite: mo->sprite = luaL_checkinteger(L, 3); @@ -465,6 +514,9 @@ static int mobj_set(lua_State *L) case mobj_frame: mo->frame = (UINT32)luaL_checkinteger(L, 3); break; + case mobj_sprite2: + mo->sprite2 = P_GetSkinSprite2(((skin_t *)mo->skin), (UINT8)luaL_checkinteger(L, 3), mo->player); + break; case mobj_anim_duration: mo->anim_duration = (UINT16)luaL_checkinteger(L, 3); break; @@ -476,6 +528,10 @@ static int mobj_set(lua_State *L) return NOSETPOS; case mobj_ceilingz: return NOSETPOS; + case mobj_floorrover: + return NOSET; + case mobj_ceilingrover: + return NOSET; case mobj_radius: { mobj_t *ptmthing = tmthing; @@ -485,6 +541,8 @@ static int mobj_set(lua_State *L) P_CheckPosition(mo, mo->x, mo->y); mo->floorz = tmfloorz; mo->ceilingz = tmceilingz; + mo->floorrover = tmfloorrover; + mo->ceilingrover = tmceilingrover; P_SetTarget(&tmthing, ptmthing); break; } @@ -497,6 +555,8 @@ static int mobj_set(lua_State *L) P_CheckPosition(mo, mo->x, mo->y); mo->floorz = tmfloorz; mo->ceilingz = tmceilingz; + mo->floorrover = tmfloorrover; + mo->ceilingrover = tmceilingrover; P_SetTarget(&tmthing, ptmthing); break; } @@ -560,16 +620,17 @@ static int mobj_set(lua_State *L) for (i = 0; i < numskins; i++) if (fastcmp(skins[i].name, skin)) { - mo->skin = &skins[i]; + if (!mo->player || R_SkinUsable(mo->player-players, i)) + mo->skin = &skins[i]; return 0; } return luaL_error(L, "mobj.skin '%s' not found!", skin); } case mobj_color: { - UINT8 newcolor = (UINT8)luaL_checkinteger(L,3); - if (newcolor >= MAXTRANSLATIONS) - return luaL_error(L, "mobj.color %d out of range (0 - %d).", newcolor, MAXTRANSLATIONS-1); + UINT16 newcolor = (UINT16)luaL_checkinteger(L,3); + if (newcolor >= numskincolors) + return luaL_error(L, "mobj.color %d out of range (0 - %d).", newcolor, numskincolors-1); mo->color = newcolor; break; } @@ -703,13 +764,14 @@ static int mobj_set(lua_State *L) case mobj_cvmem: mo->cvmem = luaL_checkinteger(L, 3); break; -#ifdef ESLOPE case mobj_standingslope: return NOSET; -#endif case mobj_colorized: mo->colorized = luaL_checkboolean(L, 3); break; + case mobj_mirrored: + mo->mirrored = luaL_checkboolean(L, 3); + break; case mobj_shadowscale: mo->shadowscale = luaL_checkfixed(L, 3); break; @@ -753,6 +815,42 @@ static int mobj_set(lua_State *L) #undef NOSETPOS #undef NOFIELD +// args, i -> args[i] +static int thingargs_get(lua_State *L) +{ + INT32 *args = *((INT32**)luaL_checkudata(L, 1, META_THINGARGS)); + int i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMMAPTHINGARGS) + return luaL_error(L, LUA_QL("mapthing_t.args") " index cannot be %d", i); + lua_pushinteger(L, args[i]); + return 1; +} + +// #args -> NUMMAPTHINGARGS +static int thingargs_len(lua_State* L) +{ + lua_pushinteger(L, NUMMAPTHINGARGS); + return 1; +} + +// stringargs, i -> stringargs[i] +static int thingstringargs_get(lua_State *L) +{ + char **stringargs = *((char***)luaL_checkudata(L, 1, META_THINGSTRINGARGS)); + int i = luaL_checkinteger(L, 2); + if (i < 0 || i >= NUMMAPTHINGSTRINGARGS) + return luaL_error(L, LUA_QL("mapthing_t.stringargs") " index cannot be %d", i); + lua_pushstring(L, stringargs[i]); + return 1; +} + +// #stringargs -> NUMMAPTHINGSTRINGARGS +static int thingstringargs_len(lua_State *L) +{ + lua_pushinteger(L, NUMMAPTHINGSTRINGARGS); + return 1; +} + static int mapthing_get(lua_State *L) { mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)); @@ -778,14 +876,32 @@ static int mapthing_get(lua_State *L) number = mt->y; else if(fastcmp(field,"angle")) number = mt->angle; + else if(fastcmp(field,"pitch")) + number = mt->pitch; + else if(fastcmp(field,"roll")) + number = mt->roll; else if(fastcmp(field,"type")) number = mt->type; else if(fastcmp(field,"options")) number = mt->options; + else if(fastcmp(field,"scale")) + number = mt->scale; else if(fastcmp(field,"z")) number = mt->z; else if(fastcmp(field,"extrainfo")) number = mt->extrainfo; + else if(fastcmp(field,"tag")) + number = mt->tag; + else if(fastcmp(field,"args")) + { + LUA_PushUserdata(L, mt->args, META_THINGARGS); + return 1; + } + else if(fastcmp(field,"stringargs")) + { + LUA_PushUserdata(L, mt->stringargs, META_THINGSTRINGARGS); + return 1; + } else if(fastcmp(field,"mobj")) { LUA_PushUserdata(L, mt->mobj, META_MOBJ); return 1; @@ -809,7 +925,7 @@ static int mapthing_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter mapthing_t in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter mapthing_t in BuildCMD code!"); + return luaL_error(L, "Do not alter mapthing_t in CMD building code!"); if(fastcmp(field,"x")) mt->x = (INT16)luaL_checkinteger(L, 3); @@ -817,14 +933,27 @@ static int mapthing_set(lua_State *L) mt->y = (INT16)luaL_checkinteger(L, 3); else if(fastcmp(field,"angle")) mt->angle = (INT16)luaL_checkinteger(L, 3); + else if(fastcmp(field,"pitch")) + mt->pitch = (INT16)luaL_checkinteger(L, 3); + else if(fastcmp(field,"roll")) + mt->roll = (INT16)luaL_checkinteger(L, 3); else if(fastcmp(field,"type")) mt->type = (UINT16)luaL_checkinteger(L, 3); else if(fastcmp(field,"options")) mt->options = (UINT16)luaL_checkinteger(L, 3); + else if(fastcmp(field,"scale")) + mt->scale = luaL_checkfixed(L, 3); else if(fastcmp(field,"z")) mt->z = (INT16)luaL_checkinteger(L, 3); else if(fastcmp(field,"extrainfo")) - mt->extrainfo = (UINT8)luaL_checkinteger(L, 3); + { + INT32 extrainfo = luaL_checkinteger(L, 3); + if (extrainfo & ~15) + return luaL_error(L, "mapthing_t extrainfo set %d out of range (%d - %d)", extrainfo, 0, 15); + mt->extrainfo = (UINT8)extrainfo; + } + else if (fastcmp(field,"tag")) + mt->tag = (INT16)luaL_checkinteger(L, 3); else if(fastcmp(field,"mobj")) mt->mobj = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); else @@ -833,9 +962,19 @@ static int mapthing_set(lua_State *L) return 0; } +static int mapthing_num(lua_State *L) +{ + mapthing_t *mt = *((mapthing_t **)luaL_checkudata(L, 1, META_MAPTHING)); + if (!mt) + return luaL_error(L, "accessed mapthing_t doesn't exist anymore."); + lua_pushinteger(L, mt-mapthings); + return 1; +} + static int lib_iterateMapthings(lua_State *L) { size_t i = 0; + INLEVEL if (lua_gettop(L) < 2) return luaL_error(L, "Don't call mapthings.iterate() directly, use it as 'for mapthing in mapthings.iterate do end'."); lua_settop(L, 2); @@ -853,6 +992,7 @@ static int lib_iterateMapthings(lua_State *L) static int lib_getMapthing(lua_State *L) { int field; + INLEVEL lua_settop(L, 2); lua_remove(L, 1); // dummy userdata table is unused. if (lua_isnumber(L, 1)) @@ -889,12 +1029,31 @@ int LUA_MobjLib(lua_State *L) lua_setfield(L, -2, "__newindex"); lua_pop(L,1); + luaL_newmetatable(L, META_THINGARGS); + lua_pushcfunction(L, thingargs_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, thingargs_len); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_THINGSTRINGARGS); + lua_pushcfunction(L, thingstringargs_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, thingstringargs_len); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + luaL_newmetatable(L, META_MAPTHING); lua_pushcfunction(L, mapthing_get); lua_setfield(L, -2, "__index"); lua_pushcfunction(L, mapthing_set); lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, mapthing_num); + lua_setfield(L, -2, "__len"); lua_pop(L,1); lua_newuserdata(L, 0); @@ -908,5 +1067,3 @@ int LUA_MobjLib(lua_State *L) lua_setglobal(L, "mapthings"); return 0; } - -#endif diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 0d5a30cab..7a6e7d93e 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,7 +11,6 @@ /// \brief player object library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA #include "fastcmp.h" #include "p_mobj.h" #include "d_player.h" @@ -22,7 +21,7 @@ #include "lua_script.h" #include "lua_libs.h" #include "lua_hud.h" // hud_running errors -#include "lua_hook.h" // hook_cmd_running +#include "lua_hook.h" // hook_cmd_running errors static int lib_iteratePlayers(lua_State *L) { @@ -183,6 +182,10 @@ static int player_get(lua_State *L) lua_pushboolean(L, true); else if (fastcmp(field,"name")) lua_pushstring(L, player_names[plr-players]); + else if (fastcmp(field,"realmo")) + LUA_PushUserdata(L, plr->mo, META_MOBJ); + // Kept for backward-compatibility + // Should be fixed to work like "realmo" later else if (fastcmp(field,"mo")) { if (plr->spectator) @@ -198,26 +201,18 @@ static int player_get(lua_State *L) lua_pushfixed(L, plr->viewz); else if (fastcmp(field,"viewheight")) lua_pushfixed(L, plr->viewheight); - /*else if (fastcmp(field,"deltaviewheight")) - lua_pushfixed(L, plr->deltaviewheight); - else if (fastcmp(field,"bob")) - lua_pushfixed(L, plr->bob);*/ + else if (fastcmp(field,"viewrollangle")) + lua_pushangle(L, plr->viewrollangle); else if (fastcmp(field,"aiming")) lua_pushangle(L, plr->aiming); - else if (fastcmp(field,"health")) - lua_pushinteger(L, plr->health); - else if (fastcmp(field,"pity")) - lua_pushinteger(L, plr->pity); - else if (fastcmp(field,"currentweapon")) - lua_pushinteger(L, plr->currentweapon); - else if (fastcmp(field,"ringweapons")) - lua_pushinteger(L, plr->ringweapons); + else if (fastcmp(field,"drawangle")) + lua_pushangle(L, plr->drawangle); + else if (fastcmp(field,"rings")) + lua_pushinteger(L, plr->rings); else if (fastcmp(field,"powers")) LUA_PushUserdata(L, plr->powers, META_POWERS); else if (fastcmp(field,"kartstuff")) LUA_PushUserdata(L, plr->kartstuff, META_KARTSTUFF); - else if (fastcmp(field,"frameangle")) - lua_pushangle(L, plr->frameangle); else if (fastcmp(field,"airtime")) lua_pushinteger(L, plr->airtime); else if (fastcmp(field,"trickpanel")) @@ -236,10 +231,6 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->skincolor); else if (fastcmp(field,"score")) lua_pushinteger(L, plr->score); - else if (fastcmp(field,"dashspeed")) - lua_pushfixed(L, plr->dashspeed); - else if (fastcmp(field,"dashtime")) - lua_pushinteger(L, plr->dashtime); // SRB2kart else if (fastcmp(field,"kartspeed")) lua_pushinteger(L, plr->kartspeed); @@ -256,6 +247,10 @@ static int player_get(lua_State *L) // else if (fastcmp(field,"charflags")) lua_pushinteger(L, plr->charflags); + else if (fastcmp(field,"followitem")) + lua_pushinteger(L, plr->followitem); + else if (fastcmp(field,"followmobj")) + LUA_PushUserdata(L, plr->followmobj, META_MOBJ); else if (fastcmp(field,"lives")) lua_pushinteger(L, plr->lives); else if (fastcmp(field,"lostlife")) @@ -268,8 +263,6 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->gotcontinue); else if (fastcmp(field,"speed")) lua_pushfixed(L, plr->speed); - else if (fastcmp(field,"jumping")) - lua_pushboolean(L, plr->jumping); else if (fastcmp(field,"secondjump")) lua_pushinteger(L, plr->secondjump); else if (fastcmp(field,"fly1")) @@ -286,6 +279,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->exiting); else if (fastcmp(field,"homing")) lua_pushinteger(L, plr->homing); + else if (fastcmp(field,"dashmode")) + lua_pushinteger(L, plr->dashmode); else if (fastcmp(field,"skidtime")) lua_pushinteger(L, plr->skidtime); else if (fastcmp(field,"cmomx")) @@ -344,22 +339,46 @@ static int player_get(lua_State *L) lua_pushboolean(L, plr->bonustime); else if (fastcmp(field,"capsule")) LUA_PushUserdata(L, plr->capsule, META_MOBJ); + else if (fastcmp(field,"drone")) + LUA_PushUserdata(L, plr->drone, META_MOBJ); + else if (fastcmp(field,"oldscale")) + lua_pushfixed(L, plr->oldscale); else if (fastcmp(field,"mare")) lua_pushinteger(L, plr->mare); + else if (fastcmp(field,"marelap")) + lua_pushinteger(L, plr->marelap); + else if (fastcmp(field,"marebonuslap")) + lua_pushinteger(L, plr->marebonuslap); else if (fastcmp(field,"marebegunat")) lua_pushinteger(L, plr->marebegunat); else if (fastcmp(field,"startedtime")) lua_pushinteger(L, plr->startedtime); else if (fastcmp(field,"finishedtime")) lua_pushinteger(L, plr->finishedtime); + else if (fastcmp(field,"lapbegunat")) + lua_pushinteger(L, plr->lapbegunat); + else if (fastcmp(field,"lapstartedtime")) + lua_pushinteger(L, plr->lapstartedtime); + else if (fastcmp(field,"finishedspheres")) + lua_pushinteger(L, plr->finishedspheres); else if (fastcmp(field,"finishedrings")) lua_pushinteger(L, plr->finishedrings); else if (fastcmp(field,"marescore")) lua_pushinteger(L, plr->marescore); else if (fastcmp(field,"lastmarescore")) lua_pushinteger(L, plr->lastmarescore); + else if (fastcmp(field,"totalmarescore")) + lua_pushinteger(L, plr->totalmarescore); else if (fastcmp(field,"lastmare")) lua_pushinteger(L, plr->lastmare); + else if (fastcmp(field,"lastmarelap")) + lua_pushinteger(L, plr->lastmarelap); + else if (fastcmp(field,"lastmarebonuslap")) + lua_pushinteger(L, plr->lastmarebonuslap); + else if (fastcmp(field,"totalmarelap")) + lua_pushinteger(L, plr->totalmarelap); + else if (fastcmp(field,"totalmarebonuslap")) + lua_pushinteger(L, plr->totalmarebonuslap); else if (fastcmp(field,"maxlink")) lua_pushinteger(L, plr->maxlink); else if (fastcmp(field,"texttimer")) @@ -391,6 +410,8 @@ static int player_get(lua_State *L) lua_pushinteger(L, plr->jointime); else if (fastcmp(field,"splitscreenindex")) lua_pushinteger(L, plr->splitscreenindex); + else if (fastcmp(field,"quittime")) + lua_pushinteger(L, plr->quittime); #ifdef HWRENDER else if (fastcmp(field,"fovadd")) lua_pushfixed(L, plr->fovadd); @@ -424,11 +445,13 @@ static int player_set(lua_State *L) if (hud_running) return luaL_error(L, "Do not alter player_t in HUD rendering code!"); + if (hook_cmd_running) + return luaL_error(L, "Do not alter player_t in CMD building code!"); if (hook_cmd_running) return luaL_error(L, "Do not alter player_t in BuildCMD code!"); - if (fastcmp(field,"mo")) { + if (fastcmp(field,"mo") || fastcmp(field,"realmo")) { mobj_t *newmo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); plr->mo->player = NULL; // remove player pointer from old mobj (newmo->player = plr)->mo = newmo; // set player pointer for new mobj, and set new mobj as the player's mobj @@ -441,29 +464,24 @@ static int player_set(lua_State *L) plr->viewz = luaL_checkfixed(L, 3); else if (fastcmp(field,"viewheight")) plr->viewheight = luaL_checkfixed(L, 3); - /*else if (fastcmp(field,"deltaviewheight")) - plr->deltaviewheight = luaL_checkfixed(L, 3); - else if (fastcmp(field,"bob")) - plr->bob = luaL_checkfixed(L, 3);*/ + else if (fastcmp(field,"viewrollangle")) + plr->viewrollangle = luaL_checkangle(L, 3); else if (fastcmp(field,"aiming")) { + UINT8 i; plr->aiming = luaL_checkangle(L, 3); - if (plr == &players[consoleplayer]) - localaiming[0] = plr->aiming; - else if (plr == &players[displayplayers[1]]) - localaiming[1] = plr->aiming; - else if (plr == &players[displayplayers[2]]) - localaiming[2] = plr->aiming; - else if (plr == &players[displayplayers[3]]) - localaiming[3] = plr->aiming; + for (i = 0; i <= r_splitscreen; i++) + { + if (plr == &players[displayplayers[i]]) + { + localaiming[i] = plr->aiming; + break; + } + } } - else if (fastcmp(field,"health")) - plr->health = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"pity")) - plr->pity = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"currentweapon")) - plr->currentweapon = (INT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"ringweapons")) - plr->ringweapons = (INT32)luaL_checkinteger(L, 3); + else if (fastcmp(field,"drawangle")) + plr->drawangle = luaL_checkangle(L, 3); + else if (fastcmp(field,"rings")) + plr->rings = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"powers")) return NOSET; else if (fastcmp(field,"pflags")) @@ -476,22 +494,16 @@ static int player_set(lua_State *L) plr->flashpal = (UINT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"skincolor")) { - UINT8 newcolor = (UINT8)luaL_checkinteger(L,3); - if (newcolor >= MAXSKINCOLORS) - return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, MAXSKINCOLORS-1); + UINT16 newcolor = (UINT16)luaL_checkinteger(L,3); + if (newcolor >= numskincolors) + return luaL_error(L, "player.skincolor %d out of range (0 - %d).", newcolor, numskincolors-1); plr->skincolor = newcolor; } else if (fastcmp(field,"score")) plr->score = (UINT32)luaL_checkinteger(L, 3); - else if (fastcmp(field,"dashspeed")) - plr->dashspeed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"dashtime")) - plr->dashtime = (INT32)luaL_checkinteger(L, 3); // SRB2kart else if (fastcmp(field,"kartstuff")) return NOSET; - else if (fastcmp(field,"frameangle")) - plr->frameangle = luaL_checkangle(L, 3); else if (fastcmp(field,"airtime")) plr->airtime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"trickpanel")) @@ -513,6 +525,15 @@ static int player_set(lua_State *L) // else if (fastcmp(field,"charflags")) plr->charflags = (UINT32)luaL_checkinteger(L, 3); + else if (fastcmp(field,"followitem")) + plr->followitem = luaL_checkinteger(L, 3); + else if (fastcmp(field,"followmobj")) + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->followmobj, mo); + } else if (fastcmp(field,"lives")) plr->lives = (SINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"lostlife")) @@ -525,8 +546,6 @@ static int player_set(lua_State *L) plr->gotcontinue = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"speed")) plr->speed = luaL_checkfixed(L, 3); - else if (fastcmp(field,"jumping")) - plr->jumping = luaL_checkboolean(L, 3); else if (fastcmp(field,"secondjump")) plr->secondjump = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"fly1")) @@ -543,6 +562,8 @@ static int player_set(lua_State *L) plr->exiting = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"homing")) plr->homing = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"dashmode")) + plr->dashmode = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"skidtime")) plr->skidtime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"cmomx")) @@ -576,9 +597,19 @@ static int player_set(lua_State *L) else if (fastcmp(field,"old_angle_pos")) plr->old_angle_pos = luaL_checkangle(L, 3); else if (fastcmp(field,"axis1")) - P_SetTarget(&plr->axis1, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->axis1, mo); + } else if (fastcmp(field,"axis2")) - P_SetTarget(&plr->axis2, *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ))); + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->axis2, mo); + } else if (fastcmp(field,"bumpertime")) plr->bumpertime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"flyangle")) @@ -606,22 +637,51 @@ static int player_set(lua_State *L) mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); P_SetTarget(&plr->capsule, mo); } + else if (fastcmp(field,"drone")) + { + mobj_t *mo = NULL; + if (!lua_isnil(L, 3)) + mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ)); + P_SetTarget(&plr->drone, mo); + } + else if (fastcmp(field,"oldscale")) + plr->oldscale = luaL_checkfixed(L, 3); else if (fastcmp(field,"mare")) plr->mare = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"marelap")) + plr->marelap = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"marebonuslap")) + plr->marebonuslap = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"marebegunat")) plr->marebegunat = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"startedtime")) plr->startedtime = (tic_t)luaL_checkinteger(L, 3); else if (fastcmp(field,"finishedtime")) plr->finishedtime = (tic_t)luaL_checkinteger(L, 3); + else if (fastcmp(field,"lapbegunat")) + plr->lapbegunat = (tic_t)luaL_checkinteger(L, 3); + else if (fastcmp(field,"lapstartedtime")) + plr->lapstartedtime = (tic_t)luaL_checkinteger(L, 3); + else if (fastcmp(field,"finishedspheres")) + plr->finishedspheres = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"finishedrings")) plr->finishedrings = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"marescore")) plr->marescore = (UINT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"lastmarescore")) plr->lastmarescore = (UINT32)luaL_checkinteger(L, 3); + else if (fastcmp(field,"totalmarescore")) + plr->totalmarescore = (UINT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"lastmare")) plr->lastmare = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"lastmarelap")) + plr->lastmarelap = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"lastmarebonuslap")) + plr->lastmarebonuslap = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"totalmarelap")) + plr->totalmarelap = (UINT8)luaL_checkinteger(L, 3); + else if (fastcmp(field,"totalmarebonuslap")) + plr->totalmarebonuslap = (UINT8)luaL_checkinteger(L, 3); else if (fastcmp(field,"maxlink")) plr->maxlink = (INT32)luaL_checkinteger(L, 3); else if (fastcmp(field,"texttimer")) @@ -704,7 +764,7 @@ static int power_get(lua_State *L) UINT16 *powers = *((UINT16 **)luaL_checkudata(L, 1, META_POWERS)); powertype_t p = luaL_checkinteger(L, 2); if (p >= NUMPOWERS) - return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p); + return luaL_error(L, LUA_QL("powertype_t") " cannot be %d", (INT16)p); lua_pushinteger(L, powers[p]); return 1; } @@ -716,11 +776,11 @@ static int power_set(lua_State *L) powertype_t p = luaL_checkinteger(L, 2); UINT16 i = (UINT16)luaL_checkinteger(L, 3); if (p >= NUMPOWERS) - return luaL_error(L, LUA_QL("powertype_t") " cannot be %u", p); + return luaL_error(L, LUA_QL("powertype_t") " cannot be %d", (INT16)p); if (hud_running) return luaL_error(L, "Do not alter player_t in HUD rendering code!"); if (hook_cmd_running) - return luaL_error(L, "Do not alter player_t in BuildCMD code!"); + return luaL_error(L, "Do not alter player_t in CMD building code!"); powers[p] = i; return 0; } @@ -767,6 +827,7 @@ static int kartstuff_len(lua_State *L) } #define NOFIELD luaL_error(L, LUA_QL("ticcmd_t") " has no field named " LUA_QS, field) +#define NOSET luaL_error(L, LUA_QL("ticcmd_t") " field " LUA_QS " cannot be set.", field) static int ticcmd_get(lua_State *L) { @@ -777,16 +838,16 @@ static int ticcmd_get(lua_State *L) if (fastcmp(field,"forwardmove")) lua_pushinteger(L, cmd->forwardmove); - else if (fastcmp(field,"angleturn")) - lua_pushinteger(L, cmd->angleturn); + else if (fastcmp(field,"turning")) + lua_pushinteger(L, cmd->turning); else if (fastcmp(field,"aiming")) lua_pushinteger(L, cmd->aiming); else if (fastcmp(field,"buttons")) lua_pushinteger(L, cmd->buttons); - else if (fastcmp(field,"driftturn")) - lua_pushinteger(L, cmd->driftturn); else if (fastcmp(field,"latency")) lua_pushinteger(L, cmd->latency); + else if (fastcmp(field,"flags")) + lua_pushinteger(L, cmd->flags); else return NOFIELD; @@ -805,14 +866,16 @@ static int ticcmd_set(lua_State *L) if (fastcmp(field,"forwardmove")) cmd->forwardmove = (SINT8)luaL_checkinteger(L, 3); - else if (fastcmp(field,"angleturn")) - cmd->angleturn = (INT16)luaL_checkinteger(L, 3); + else if (fastcmp(field,"turning")) + cmd->turning = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"aiming")) cmd->aiming = (INT16)luaL_checkinteger(L, 3); else if (fastcmp(field,"buttons")) cmd->buttons = (UINT16)luaL_checkinteger(L, 3); - else if (fastcmp(field,"driftturn")) - cmd->driftturn = (INT16)luaL_checkinteger(L, 3); + else if (fastcmp(field,"latency")) + return NOSET; + else if (fastcmp(field,"flags")) + return NOSET; else return NOFIELD; @@ -887,5 +950,3 @@ int LUA_PlayerLib(lua_State *L) return 0; } - -#endif diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c new file mode 100644 index 000000000..365d97056 --- /dev/null +++ b/src/lua_polyobjlib.c @@ -0,0 +1,486 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by Iestyn "Monster Iestyn" Jealous. +// Copyright (C) 2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file lua_polyobjlib.c +/// \brief polyobject library for Lua scripting + +#include "doomdef.h" +#include "fastcmp.h" +#include "p_local.h" +#include "p_polyobj.h" +#include "lua_script.h" +#include "lua_libs.h" +#include "lua_hud.h" // hud_running errors + +#define NOHUD if (hud_running)\ +return luaL_error(L, "HUD rendering code should not call this function!"); + +enum polyobj_e { + // properties + polyobj_valid = 0, + polyobj_id, + polyobj_parent, + polyobj_vertices, + polyobj_lines, + polyobj_sector, + polyobj_angle, + polyobj_damage, + polyobj_thrust, + polyobj_flags, + polyobj_translucency, + polyobj_triggertag, + // special functions - utility + polyobj_pointInside, + polyobj_mobjTouching, + polyobj_mobjInside, + // special functions - manipulation + polyobj_moveXY, + polyobj_rotate +}; +static const char *const polyobj_opt[] = { + // properties + "valid", + "id", + "parent", + "vertices", + "lines", + "sector", + "angle", + "damage", + "thrust", + "flags", + "translucency", + "triggertag", + // special functions - utility + "pointInside", + "mobjTouching", + "mobjInside", + // special functions - manipulation + "moveXY", + "rotate", + NULL}; + +static const char *const valid_opt[] ={"valid",NULL}; + +//////////////////////// +// polyobj.vertices[] // +//////////////////////// + +// polyobj.vertices, i -> polyobj.vertices[i] +// polyobj.vertices.valid, for validity checking +// +// see sectorlines_get in lua_maplib.c +// +static int polyobjvertices_get(lua_State *L) +{ + vertex_t ***polyverts = *((vertex_t ****)luaL_checkudata(L, 1, META_POLYOBJVERTICES)); + size_t i; + size_t numofverts = 0; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!polyverts || !(*polyverts)) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + numofverts = *(size_t *)FIELDFROM (polyobj_t, polyverts, vertices,/* -> */numVertices); + + if (!numofverts) + return luaL_error(L, "no vertices found!"); + + i = (size_t)lua_tointeger(L, 2); + if (i >= numofverts) + return 0; + LUA_PushUserdata(L, (*polyverts)[i], META_VERTEX); + return 1; +} + +// #(polyobj.vertices) -> polyobj.numVertices +static int polyobjvertices_num(lua_State *L) +{ + vertex_t ***polyverts = *((vertex_t ****)luaL_checkudata(L, 1, META_POLYOBJVERTICES)); + size_t numofverts = 0; + + if (!polyverts || !(*polyverts)) + return luaL_error(L, "accessed polyobj_t.vertices doesn't exist anymore."); + + numofverts = *(size_t *)FIELDFROM (polyobj_t, polyverts, vertices,/* -> */numVertices); + lua_pushinteger(L, numofverts); + return 1; +} + +///////////////////// +// polyobj.lines[] // +///////////////////// + +// polyobj.lines, i -> polyobj.lines[i] +// polyobj.lines.valid, for validity checking +// +// see sectorlines_get in lua_maplib.c +// +static int polyobjlines_get(lua_State *L) +{ + line_t ***polylines = *((line_t ****)luaL_checkudata(L, 1, META_POLYOBJLINES)); + size_t i; + size_t numoflines = 0; + lua_settop(L, 2); + if (!lua_isnumber(L, 2)) + { + int field = luaL_checkoption(L, 2, NULL, valid_opt); + if (!polylines || !(*polylines)) + { + if (field == 0) { + lua_pushboolean(L, 0); + return 1; + } + return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore."); + } else if (field == 0) { + lua_pushboolean(L, 1); + return 1; + } + } + + numoflines = *(size_t *)FIELDFROM (polyobj_t, polylines, lines,/* -> */numLines); + + if (!numoflines) + return luaL_error(L, "no lines found!"); + + i = (size_t)lua_tointeger(L, 2); + if (i >= numoflines) + return 0; + LUA_PushUserdata(L, (*polylines)[i], META_LINE); + return 1; +} + +// #(polyobj.lines) -> polyobj.numLines +static int polyobjlines_num(lua_State *L) +{ + line_t ***polylines = *((line_t ****)luaL_checkudata(L, 1, META_POLYOBJLINES)); + size_t numoflines = 0; + + if (!polylines || !(*polylines)) + return luaL_error(L, "accessed polyobj_t.lines doesn't exist anymore."); + + numoflines = *(size_t *)FIELDFROM (polyobj_t, polylines, lines,/* -> */numLines); + lua_pushinteger(L, numoflines); + return 1; +} + +///////////////////////////////// +// polyobj_t function wrappers // +///////////////////////////////// + +// special functions - utility +static int lib_polyobj_PointInside(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + fixed_t x = luaL_checkfixed(L, 2); + fixed_t y = luaL_checkfixed(L, 3); + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + lua_pushboolean(L, P_PointInsidePolyobj(po, x, y)); + return 1; +} + +static int lib_polyobj_MobjTouching(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, P_MobjTouchingPolyobj(po, mo)); + return 1; +} + +static int lib_polyobj_MobjInside(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + if (!mo) + return LUA_ErrInvalid(L, "mobj_t"); + lua_pushboolean(L, P_MobjInsidePolyobj(po, mo)); + return 1; +} + +// special functions - manipulation +static int lib_polyobj_moveXY(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + fixed_t x = luaL_checkfixed(L, 2); + fixed_t y = luaL_checkfixed(L, 3); + boolean checkmobjs = lua_opttrueboolean(L, 4); + NOHUD + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + lua_pushboolean(L, Polyobj_moveXY(po, x, y, checkmobjs)); + return 1; +} + +static int lib_polyobj_rotate(lua_State *L) +{ + polyobj_t *po = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + angle_t delta = luaL_checkangle(L, 2); + UINT8 turnthings = (UINT8)luaL_optinteger(L, 3, 0); // don't turn anything by default? (could change this if not desired) + boolean checkmobjs = lua_opttrueboolean(L, 4); + NOHUD + INLEVEL + if (!po) + return LUA_ErrInvalid(L, "polyobj_t"); + lua_pushboolean(L, Polyobj_rotate(po, delta, turnthings, checkmobjs)); + return 1; +} + +/////////////// +// polyobj_t // +/////////////// + +static int polyobj_get(lua_State *L) +{ + polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + enum polyobj_e field = luaL_checkoption(L, 2, NULL, polyobj_opt); + + if (!polyobj) { + if (field == polyobj_valid) { + lua_pushboolean(L, false); + return 1; + } + return LUA_ErrInvalid(L, "polyobj_t"); + } + + switch (field) + { + // properties + case polyobj_valid: + lua_pushboolean(L, true); + break; + case polyobj_id: + lua_pushinteger(L, polyobj->id); + break; + case polyobj_parent: + lua_pushinteger(L, polyobj->parent); + break; + case polyobj_vertices: // vertices + LUA_PushUserdata(L, &polyobj->vertices, META_POLYOBJVERTICES); // push the address of the "vertices" member in the struct, to allow our hacks to work + break; + case polyobj_lines: // lines + LUA_PushUserdata(L, &polyobj->lines, META_POLYOBJLINES); // push the address of the "lines" member in the struct, to allow our hacks to work + break; + case polyobj_sector: // shortcut that exists only in Lua! + LUA_PushUserdata(L, polyobj->lines[0]->backsector, META_SECTOR); + break; + case polyobj_angle: + lua_pushangle(L, polyobj->angle); + break; + case polyobj_damage: + lua_pushinteger(L, polyobj->damage); + break; + case polyobj_thrust: + lua_pushfixed(L, polyobj->thrust); + break; + case polyobj_flags: + lua_pushinteger(L, polyobj->flags); + break; + case polyobj_translucency: + lua_pushinteger(L, polyobj->translucency); + break; + case polyobj_triggertag: + lua_pushinteger(L, polyobj->triggertag); + break; + // special functions - utility + case polyobj_pointInside: + lua_pushcfunction(L, lib_polyobj_PointInside); + break; + case polyobj_mobjTouching: + lua_pushcfunction(L, lib_polyobj_MobjTouching); + break; + case polyobj_mobjInside: + lua_pushcfunction(L, lib_polyobj_MobjInside); + break; + // special functions - manipulation + case polyobj_moveXY: + lua_pushcfunction(L, lib_polyobj_moveXY); + break; + case polyobj_rotate: + lua_pushcfunction(L, lib_polyobj_rotate); + break; + } + return 1; +} + +static int polyobj_set(lua_State *L) +{ + polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + enum polyobj_e field = luaL_checkoption(L, 2, NULL, polyobj_opt); + + if (!polyobj) + return LUA_ErrInvalid(L, "polyobj_t"); + + if (hud_running) + return luaL_error(L, "Do not alter polyobj_t in HUD rendering code!"); + + switch (field) + { + default: + return luaL_error(L, LUA_QL("polyobj_t") " field " LUA_QS " cannot be modified.", polyobj_opt[field]); + case polyobj_angle: + return luaL_error(L, LUA_QL("polyobj_t") " field " LUA_QS " should not be set directly. Use the function " LUA_QL("polyobj:rotate(angle)") " instead.", polyobj_opt[field]); + case polyobj_parent: + polyobj->parent = luaL_checkinteger(L, 3); + break; + case polyobj_flags: + polyobj->flags = luaL_checkinteger(L, 3); + break; + case polyobj_translucency: + polyobj->translucency = luaL_checkinteger(L, 3); + break; + } + + return 0; +} + +static int polyobj_num(lua_State *L) +{ + polyobj_t *polyobj = *((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)); + if (!polyobj) + return luaL_error(L, "accessed polyobj_t doesn't exist anymore."); + lua_pushinteger(L, polyobj-PolyObjects); + return 1; +} + +/////////////////// +// PolyObjects[] // +/////////////////// + +static int lib_iteratePolyObjects(lua_State *L) +{ + INT32 i = -1; + if (lua_gettop(L) < 2) + { + //return luaL_error(L, "Don't call PolyObjects.iterate() directly, use it as 'for polyobj in PolyObjects.iterate do end'."); + lua_pushcfunction(L, lib_iteratePolyObjects); + return 1; + } + lua_settop(L, 2); + lua_remove(L, 1); // state is unused. + if (!lua_isnil(L, 1)) + i = (INT32)(*((polyobj_t **)luaL_checkudata(L, 1, META_POLYOBJ)) - PolyObjects); + for (i++; i < numPolyObjects; i++) + { + LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ); + return 1; + } + return 0; +} + +static int lib_PolyObject_getfornum(lua_State *L) +{ + INT32 id = (INT32)luaL_checkinteger(L, 1); + + if (!numPolyObjects) + return 0; // if there's no PolyObjects then bail out here + + LUA_PushUserdata(L, Polyobj_GetForNum(id), META_POLYOBJ); + return 1; +} + +static int lib_getPolyObject(lua_State *L) +{ + const char *field; + INT32 i; + + // find PolyObject by number + if (lua_type(L, 2) == LUA_TNUMBER) + { + i = luaL_checkinteger(L, 2); + if (i < 0 || i >= numPolyObjects) + return luaL_error(L, "PolyObjects[] index %d out of range (0 - %d)", i, numPolyObjects-1); + LUA_PushUserdata(L, &PolyObjects[i], META_POLYOBJ); + return 1; + } + + field = luaL_checkstring(L, 2); + // special function iterate + if (fastcmp(field,"iterate")) + { + lua_pushcfunction(L, lib_iteratePolyObjects); + return 1; + } + // find PolyObject by ID + else if (fastcmp(field,"GetForNum")) // name could probably be better + { + lua_pushcfunction(L, lib_PolyObject_getfornum); + return 1; + } + return 0; +} + +static int lib_numPolyObjects(lua_State *L) +{ + lua_pushinteger(L, numPolyObjects); + return 1; +} + +int LUA_PolyObjLib(lua_State *L) +{ + luaL_newmetatable(L, META_POLYOBJVERTICES); + lua_pushcfunction(L, polyobjvertices_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, polyobjvertices_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_POLYOBJLINES); + lua_pushcfunction(L, polyobjlines_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, polyobjlines_num); + lua_setfield(L, -2, "__len"); + lua_pop(L, 1); + + luaL_newmetatable(L, META_POLYOBJ); + lua_pushcfunction(L, polyobj_get); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, polyobj_set); + lua_setfield(L, -2, "__newindex"); + + lua_pushcfunction(L, polyobj_num); + lua_setfield(L, -2, "__len"); + lua_pop(L,1); + + lua_newuserdata(L, 0); + lua_createtable(L, 0, 2); + lua_pushcfunction(L, lib_getPolyObject); + lua_setfield(L, -2, "__index"); + + lua_pushcfunction(L, lib_numPolyObjects); + lua_setfield(L, -2, "__len"); + lua_setmetatable(L, -2); + lua_setglobal(L, "PolyObjects"); + return 0; +} diff --git a/src/lua_script.c b/src/lua_script.c index 6961f2e97..0b964e5ea 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,20 +11,20 @@ /// \brief Lua scripting basics #include "doomdef.h" -#ifdef HAVE_BLUA #include "fastcmp.h" #include "dehacked.h" #include "z_zone.h" #include "w_wad.h" #include "p_setup.h" #include "r_state.h" +#include "r_sky.h" #include "g_game.h" +#include "f_finale.h" #include "byteptr.h" #include "p_saveg.h" #include "p_local.h" -#ifdef ESLOPE #include "p_slopes.h" // for P_SlopeById -#endif +#include "p_polyobj.h" // polyobj_t, PolyObjects #ifdef LUA_ALLOW_BYTECODE #include "d_netfil.h" // for LUA_DumpFile #endif @@ -51,6 +51,7 @@ static lua_CFunction liblist[] = { LUA_SkinLib, // skin_t, skins[] LUA_ThinkerLib, // thinker_t LUA_MapLib, // line_t, side_t, sector_t, subsector_t + LUA_PolyObjLib, // polyobj_t LUA_BlockmapLib, // blockmap stuff LUA_HudLib, // HUD stuff NULL @@ -79,8 +80,331 @@ FUNCNORETURN static int LUA_Panic(lua_State *L) #endif } +#define LEVELS1 12 // size of the first part of the stack +#define LEVELS2 10 // size of the second part of the stack + +// Error handler used with pcall() when loading scripts or calling hooks +// Takes a string with the original error message, +// appends the traceback to it, and return the result +int LUA_GetErrorMessage(lua_State *L) +{ + int level = 1; + int firstpart = 1; // still before eventual `...' + lua_Debug ar; + + lua_pushliteral(L, "\nstack traceback:"); + while (lua_getstack(L, level++, &ar)) + { + if (level > LEVELS1 && firstpart) + { + // no more than `LEVELS2' more levels? + if (!lua_getstack(L, level + LEVELS2, &ar)) + level--; // keep going + else + { + lua_pushliteral(L, "\n ..."); // too many levels + while (lua_getstack(L, level + LEVELS2, &ar)) // find last levels + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n "); + lua_getinfo(L, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + if (*ar.namewhat != '\0') // is there a name? + lua_pushfstring(L, " in function " LUA_QS, ar.name); + else + { + if (*ar.what == 'm') // main? + lua_pushfstring(L, " in main chunk"); + else if (*ar.what == 'C' || *ar.what == 't') + lua_pushliteral(L, " ?"); // C function or tail call + else + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + lua_concat(L, lua_gettop(L)); + } + lua_concat(L, lua_gettop(L)); + return 1; +} + +// Moved here from lib_getenum. +int LUA_PushGlobals(lua_State *L, const char *word) +{ + if (fastcmp(word,"gamemap")) { + lua_pushinteger(L, gamemap); + return 1; + } else if (fastcmp(word,"udmf")) { + lua_pushboolean(L, udmf); + return 1; + } else if (fastcmp(word,"maptol")) { + lua_pushinteger(L, maptol); + return 1; + } else if (fastcmp(word,"circuitmap")) { + lua_pushboolean(L, circuitmap); + return 1; + } else if (fastcmp(word,"stoppedclock")) { + lua_pushboolean(L, stoppedclock); + return 1; + } else if (fastcmp(word,"netgame")) { + lua_pushboolean(L, netgame); + return 1; + } else if (fastcmp(word,"multiplayer")) { + lua_pushboolean(L, multiplayer); + return 1; + } else if (fastcmp(word,"modeattacking")) { + lua_pushboolean(L, modeattacking); + return 1; + } else if (fastcmp(word,"splitscreen")) { + lua_pushboolean(L, splitscreen); + return 1; + } else if (fastcmp(word,"gamecomplete")) { + lua_pushboolean(L, (gamecomplete != 0)); + return 1; + } else if (fastcmp(word,"marathonmode")) { + lua_pushinteger(L, marathonmode); + return 1; + } else if (fastcmp(word,"devparm")) { + lua_pushboolean(L, devparm); + return 1; + } else if (fastcmp(word,"modifiedgame")) { + lua_pushboolean(L, modifiedgame && !savemoddata); + return 1; + } else if (fastcmp(word,"menuactive")) { + lua_pushboolean(L, menuactive); + return 1; + } else if (fastcmp(word,"paused")) { + lua_pushboolean(L, paused); + return 1; + } else if (fastcmp(word,"bluescore")) { + lua_pushinteger(L, bluescore); + return 1; + } else if (fastcmp(word,"redscore")) { + lua_pushinteger(L, redscore); + return 1; + } else if (fastcmp(word,"timelimit")) { + lua_pushinteger(L, cv_timelimit.value); + return 1; + } else if (fastcmp(word,"pointlimit")) { + lua_pushinteger(L, cv_pointlimit.value); + return 1; + // begin map vars + } else if (fastcmp(word,"spstage_start")) { + lua_pushinteger(L, spstage_start); + return 1; + } else if (fastcmp(word,"spmarathon_start")) { + lua_pushinteger(L, spmarathon_start); + return 1; + } else if (fastcmp(word,"sstage_start")) { + lua_pushinteger(L, sstage_start); + return 1; + } else if (fastcmp(word,"sstage_end")) { + lua_pushinteger(L, sstage_end); + return 1; + } else if (fastcmp(word,"smpstage_start")) { + lua_pushinteger(L, smpstage_start); + return 1; + } else if (fastcmp(word,"smpstage_end")) { + lua_pushinteger(L, smpstage_end); + return 1; + } else if (fastcmp(word,"titlemap")) { + lua_pushinteger(L, titlemap); + return 1; + } else if (fastcmp(word,"titlemapinaction")) { + lua_pushboolean(L, (titlemapinaction != TITLEMAP_OFF)); + return 1; + } else if (fastcmp(word,"bootmap")) { + lua_pushinteger(L, bootmap); + return 1; + } else if (fastcmp(word,"tutorialmap")) { + lua_pushinteger(L, tutorialmap); + return 1; + } else if (fastcmp(word,"tutorialmode")) { + lua_pushboolean(L, tutorialmode); + return 1; + // end map vars + // begin CTF colors + } else if (fastcmp(word,"skincolor_redteam")) { + lua_pushinteger(L, skincolor_redteam); + return 1; + } else if (fastcmp(word,"skincolor_blueteam")) { + lua_pushinteger(L, skincolor_blueteam); + return 1; + } else if (fastcmp(word,"skincolor_redring")) { + lua_pushinteger(L, skincolor_redring); + return 1; + } else if (fastcmp(word,"skincolor_bluering")) { + lua_pushinteger(L, skincolor_bluering); + return 1; + // end CTF colors + // begin timers + } else if (fastcmp(word,"invulntics")) { + lua_pushinteger(L, invulntics); + return 1; + } else if (fastcmp(word,"sneakertics")) { + lua_pushinteger(L, sneakertics); + return 1; + } else if (fastcmp(word,"flashingtics")) { + lua_pushinteger(L, flashingtics); + return 1; + } else if (fastcmp(word,"tailsflytics")) { + lua_pushinteger(L, tailsflytics); + return 1; + } else if (fastcmp(word,"underwatertics")) { + lua_pushinteger(L, underwatertics); + return 1; + } else if (fastcmp(word,"spacetimetics")) { + lua_pushinteger(L, spacetimetics); + return 1; + } else if (fastcmp(word,"extralifetics")) { + lua_pushinteger(L, extralifetics); + return 1; + } else if (fastcmp(word,"nightslinktics")) { + lua_pushinteger(L, nightslinktics); + return 1; + } else if (fastcmp(word,"gameovertics")) { + lua_pushinteger(L, gameovertics); + return 1; + } else if (fastcmp(word,"ammoremovaltics")) { + lua_pushinteger(L, ammoremovaltics); + return 1; + // end timers + } else if (fastcmp(word,"gametype")) { + lua_pushinteger(L, gametype); + return 1; + } else if (fastcmp(word,"gametyperules")) { + lua_pushinteger(L, gametyperules); + return 1; + } else if (fastcmp(word,"leveltime")) { + lua_pushinteger(L, leveltime); + return 1; + } else if (fastcmp(word,"curWeather")) { + lua_pushinteger(L, curWeather); + return 1; + } else if (fastcmp(word,"globalweather")) { + lua_pushinteger(L, globalweather); + return 1; + } else if (fastcmp(word,"levelskytexture")) { + lua_pushstring(L, levelskytexture); + return 1; + } else if (fastcmp(word,"globallevelskytexture")) { + lua_pushstring(L, globallevelskytexture); + return 1; + } else if (fastcmp(word,"mapmusname")) { + lua_pushstring(L, mapmusname); + return 1; + } else if (fastcmp(word,"mapmusflags")) { + lua_pushinteger(L, mapmusflags); + return 1; + } else if (fastcmp(word,"mapmusposition")) { + lua_pushinteger(L, mapmusposition); + return 1; + // local player variables, by popular request + } else if (fastcmp(word,"consoleplayer")) { // player controlling console (aka local player 1) + if (consoleplayer < 0 || !playeringame[consoleplayer]) + return 0; + LUA_PushUserdata(L, &players[consoleplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"isserver")) { + lua_pushboolean(L, server); + return 1; + } else if (fastcmp(word,"isdedicatedserver")) { + lua_pushboolean(L, dedicated); + return 1; + // end local player variables + } else if (fastcmp(word,"server")) { + if ((!multiplayer || !netgame) && !playeringame[serverplayer]) + return 0; + LUA_PushUserdata(L, &players[serverplayer], META_PLAYER); + return 1; + } else if (fastcmp(word,"gravity")) { + lua_pushinteger(L, gravity); + return 1; + } else if (fastcmp(word,"VERSION")) { + lua_pushinteger(L, VERSION); + return 1; + } else if (fastcmp(word,"SUBVERSION")) { + lua_pushinteger(L, SUBVERSION); + return 1; + } else if (fastcmp(word,"VERSIONSTRING")) { + lua_pushstring(L, VERSIONSTRING); + return 1; + } else if (fastcmp(word,"gamespeed")) { + lua_pushinteger(L, gamespeed); + return 1; + } else if (fastcmp(word,"encoremode")) { + lua_pushboolean(L, encoremode); + return 1; + } else if (fastcmp(word,"franticitems")) { + lua_pushboolean(L, franticitems); + return 1; + } else if (fastcmp(word,"comeback")) { + lua_pushboolean(L, comeback); + return 1; + } else if (fastcmp(word,"wantedcalcdelay")) { + lua_pushinteger(L, wantedcalcdelay); + return 1; + } else if (fastcmp(word,"indirectitemcooldown")) { + lua_pushinteger(L, indirectitemcooldown); + return 1; + } else if (fastcmp(word,"hyubgone")) { + lua_pushinteger(L, hyubgone); + return 1; + } else if (fastcmp(word,"thwompsactive")) { + lua_pushboolean(L, thwompsactive); + return 1; + } else if (fastcmp(word,"spbplace")) { + lua_pushinteger(L, spbplace); + return 1; + } else if (fastcmp(word,"mapobjectscale")) { + lua_pushinteger(L, mapobjectscale); + return 1; + } else if (fastcmp(word,"numlaps")) { + lua_pushinteger(L, cv_numlaps.value); + return 1; + } else if (fastcmp(word,"racecountdown")) { + lua_pushinteger(L, racecountdown); + return 1; + } else if (fastcmp(word,"exitcountdown")) { + lua_pushinteger(L, exitcountdown); // This name is pretty dumb. Hence why we'll prefer more descriptive names at least in Lua... + return 1; + } else if (fastcmp(word,"replayplayback")) { + lua_pushboolean(L, demo.playback); + return 1; + } + + return 0; +} + +// See the above. +int LUA_WriteGlobals(lua_State *L, const char *word) +{ + if (fastcmp(word, "redscore")) + redscore = (UINT32)luaL_checkinteger(L, 2); + else if (fastcmp(word, "bluescore")) + bluescore = (UINT32)luaL_checkinteger(L, 2); + // SRB2Kart + else if (fastcmp(word,"racecountdown")) + racecountdown = (tic_t)luaL_checkinteger(L, 2); + else if (fastcmp(word,"exitcountdown")) + exitcountdown = (tic_t)luaL_checkinteger(L, 2); + else if (fastcmp(word,"indirectitemcooldown")) + indirectitemcooldown = (tic_t)luaL_checkinteger(L, 2); + else if (fastcmp(word,"hyubgone")) + hyubgone = (tic_t)luaL_checkinteger(L, 2); + else + return 0; + + // Global variable set, so return and don't error. + return 1; +} + // This function decides which global variables you are allowed to set. -static int noglobals(lua_State *L) +static int setglobals(lua_State *L) { const char *csname; char *name; @@ -106,6 +430,9 @@ static int noglobals(lua_State *L) return 0; } + if (LUA_WriteGlobals(L, csname)) + return 0; + Z_Free(name); return luaL_error(L, "Implicit global " LUA_QS " prevented. Create a local variable instead.", csname); } @@ -144,7 +471,7 @@ void LUA_ClearState(void) // lock the global namespace lua_getmetatable(L, LUA_GLOBALSINDEX); - lua_pushcfunction(L, noglobals); + lua_pushcfunction(L, setglobals); lua_setfield(L, -2, "__newindex"); lua_newtable(L); lua_setfield(L, -2, "__metatable"); @@ -164,9 +491,16 @@ void LUA_ClearExtVars(void) } #endif +// Use this variable to prevent certain functions from running +// if they were not called on lump load +// (i.e. they were called in hooks or coroutines etc) +INT32 lua_lumploading = 0; + // Load a script from a MYFILE -static inline void LUA_LoadFile(MYFILE *f, char *name) +static inline void LUA_LoadFile(MYFILE *f, char *name, boolean noresults) { + int errorhandlerindex; + if (!name) name = wadfiles[f->wad]->filename; CONS_Printf("Loading Lua script from %s\n", name); @@ -175,15 +509,22 @@ static inline void LUA_LoadFile(MYFILE *f, char *name) lua_pushinteger(gL, f->wad); lua_setfield(gL, LUA_REGISTRYINDEX, "WAD"); - if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, 0, 0)) { + lua_lumploading++; // turn on loading flag + + lua_pushcfunction(gL, LUA_GetErrorMessage); + errorhandlerindex = lua_gettop(gL); + if (luaL_loadbuffer(gL, f->data, f->size, va("@%s",name)) || lua_pcall(gL, 0, noresults ? 0 : LUA_MULTRET, lua_gettop(gL) - 1)) { CONS_Alert(CONS_WARNING,"%s\n",lua_tostring(gL,-1)); lua_pop(gL,1); } lua_gc(gL, LUA_GCCOLLECT, 0); + lua_remove(gL, errorhandlerindex); + + lua_lumploading--; // turn off again } // Load a script from a lump -void LUA_LoadLump(UINT16 wad, UINT16 lump) +void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults) { MYFILE f; char *name; @@ -204,13 +545,13 @@ void LUA_LoadLump(UINT16 wad, UINT16 lump) else // If it's not a .lua file, copy the lump name in too. { lumpinfo_t *lump_p = &wadfiles[wad]->lumpinfo[lump]; - len += 1 + strlen(lump_p->name2); // length of file name, '|', and lump name + len += 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name name = malloc(len+1); - sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->name2); + sprintf(name, "%s|%s", wadfiles[wad]->filename, lump_p->fullname); name[len] = '\0'; } - LUA_LoadFile(&f, name); // actually load file! + LUA_LoadFile(&f, name, noresults); // actually load file! // Okay, we've modified the game beyond the point of no return. G_SetGameModified(multiplayer, true); @@ -334,6 +675,27 @@ fixed_t LUA_EvalMath(const char *word) return res; } +/* +LUA_PushUserdata but no userdata is created. +You can't invalidate it therefore. +*/ + +void LUA_PushLightUserdata (lua_State *L, void *data, const char *meta) +{ + if (data) + { + lua_pushlightuserdata(L, data); + luaL_getmetatable(L, meta); + /* + The metatable is the last value on the stack, so this + applies it to the second value, which is the userdata. + */ + lua_setmetatable(L, -2); + } + else + lua_pushnil(L); +} + // Takes a pointer, any pointer, and a metatable name // Creates a userdata for that pointer with the given metatable // Pushes it to the stack and stores it in the registry. @@ -411,18 +773,27 @@ void LUA_InvalidateLevel(void) { thinker_t *th; size_t i; + ffloor_t *rover = NULL; if (!gL) return; - - for (th = thinkercap.next; th && th != &thinkercap; th = th->next) - LUA_InvalidateUserdata(th); + for (i = 0; i < NUM_THINKERLISTS; i++) + for (th = thlist[i].next; th && th != &thlist[i]; th = th->next) + LUA_InvalidateUserdata(th); LUA_InvalidateMapthings(); for (i = 0; i < numsubsectors; i++) LUA_InvalidateUserdata(&subsectors[i]); for (i = 0; i < numsectors; i++) + { LUA_InvalidateUserdata(§ors[i]); + LUA_InvalidateUserdata(§ors[i].lines); + if (sectors[i].ffloors) + { + for (rover = sectors[i].ffloors; rover; rover = rover->next) + LUA_InvalidateUserdata(rover); + } + } for (i = 0; i < numlines; i++) { LUA_InvalidateUserdata(&lines[i]); @@ -432,6 +803,22 @@ void LUA_InvalidateLevel(void) LUA_InvalidateUserdata(&sides[i]); for (i = 0; i < numvertexes; i++) LUA_InvalidateUserdata(&vertexes[i]); + for (i = 0; i < (size_t)numPolyObjects; i++) + { + LUA_InvalidateUserdata(&PolyObjects[i]); + LUA_InvalidateUserdata(&PolyObjects[i].vertices); + LUA_InvalidateUserdata(&PolyObjects[i].lines); + } +#ifdef HAVE_LUA_SEGS + for (i = 0; i < numsegs; i++) + LUA_InvalidateUserdata(&segs[i]); + for (i = 0; i < numnodes; i++) + { + LUA_InvalidateUserdata(&nodes[i]); + LUA_InvalidateUserdata(nodes[i].bbox); + LUA_InvalidateUserdata(nodes[i].children); + } +#endif } void LUA_InvalidateMapthings(void) @@ -457,9 +844,13 @@ void LUA_InvalidatePlayer(player_t *player) enum { ARCH_NULL=0, - ARCH_BOOLEAN, - ARCH_SIGNED, - ARCH_STRING, + ARCH_TRUE, + ARCH_FALSE, + ARCH_INT8, + ARCH_INT16, + ARCH_INT32, + ARCH_SMALLSTRING, + ARCH_LARGESTRING, ARCH_TABLE, ARCH_MOBJINFO, @@ -472,10 +863,15 @@ enum ARCH_SIDE, ARCH_SUBSECTOR, ARCH_SECTOR, -#ifdef ESLOPE - ARCH_SLOPE, +#ifdef HAVE_LUA_SEGS + ARCH_SEG, + ARCH_NODE, #endif + ARCH_FFLOOR, + ARCH_POLYOBJ, + ARCH_SLOPE, ARCH_MAPHEADER, + ARCH_SKINCOLOR, ARCH_TEND=0xFF, }; @@ -494,10 +890,15 @@ static const struct { {META_SIDE, ARCH_SIDE}, {META_SUBSECTOR,ARCH_SUBSECTOR}, {META_SECTOR, ARCH_SECTOR}, -#ifdef ESLOPE - {META_SLOPE, ARCH_SLOPE}, +#ifdef HAVE_LUA_SEGS + {META_SEG, ARCH_SEG}, + {META_NODE, ARCH_NODE}, #endif + {META_FFLOOR, ARCH_FFLOOR}, + {META_POLYOBJ, ARCH_POLYOBJ}, + {META_SLOPE, ARCH_SLOPE}, {META_MAPHEADER, ARCH_MAPHEADER}, + {META_SKINCOLOR, ARCH_SKINCOLOR}, {NULL, ARCH_NULL} }; @@ -521,7 +922,7 @@ static UINT8 GetUserdataArchType(int index) return ARCH_NULL; } -static UINT8 ArchiveValue(int TABLESINDEX, int myindex) +static UINT8 ArchiveValue(UINT8 **p, int TABLESINDEX, int myindex) { if (myindex < 0) myindex = lua_gettop(gL)+1+myindex; @@ -529,31 +930,42 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { case LUA_TNONE: case LUA_TNIL: - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); break; // This might be a problem. D: case LUA_TLIGHTUSERDATA: case LUA_TTHREAD: case LUA_TFUNCTION: - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); return 2; case LUA_TBOOLEAN: - WRITEUINT8(save_p, ARCH_BOOLEAN); - WRITEUINT8(save_p, lua_toboolean(gL, myindex)); + WRITEUINT8(*p, lua_toboolean(gL, myindex) ? ARCH_TRUE : ARCH_FALSE); break; case LUA_TNUMBER: { lua_Integer number = lua_tointeger(gL, myindex); - WRITEUINT8(save_p, ARCH_SIGNED); - WRITEFIXED(save_p, number); + if (number >= INT8_MIN && number <= INT8_MAX) + { + WRITEUINT8(*p, ARCH_INT8); + WRITESINT8(*p, number); + } + else if (number >= INT16_MIN && number <= INT16_MAX) + { + WRITEUINT8(*p, ARCH_INT16); + WRITEINT16(*p, number); + } + else + { + WRITEUINT8(*p, ARCH_INT32); + WRITEFIXED(*p, number); + } break; } case LUA_TSTRING: { - UINT16 len = (UINT16)lua_objlen(gL, myindex); // get length of string, including embedded zeros + UINT32 len = (UINT32)lua_objlen(gL, myindex); // get length of string, including embedded zeros const char *s = lua_tostring(gL, myindex); - UINT16 i = 0; - WRITEUINT8(save_p, ARCH_STRING); + UINT32 i = 0; // if you're wondering why we're writing a string to save_p this way, // it turns out that Lua can have embedded zeros ('\0') in the strings, // so we can't use WRITESTRING as that cuts off when it finds a '\0'. @@ -561,9 +973,18 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) // fixing the awful crashes previously encountered for reading strings longer than 1024 // (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?) // -- Monster Iestyn 05/08/18 - WRITEUINT16(save_p, len); // save size of string + if (len < 255) + { + WRITEUINT8(*p, ARCH_SMALLSTRING); + WRITEUINT8(*p, len); // save size of string + } + else + { + WRITEUINT8(*p, ARCH_LARGESTRING); + WRITEUINT32(*p, len); // save size of string + } while (i < len) - WRITECHAR(save_p, s[i++]); // write chars individually, including the embedded zeros + WRITECHAR(*p, s[i++]); // write chars individually, including the embedded zeros break; } case LUA_TTABLE: @@ -585,8 +1006,8 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) if (!found) t++; - WRITEUINT8(save_p, ARCH_TABLE); - WRITEUINT16(save_p, t); + WRITEUINT8(*p, ARCH_TABLE); + WRITEUINT16(*p, t); if (!found) { @@ -602,25 +1023,25 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) case ARCH_MOBJINFO: { mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_MOBJINFO); - WRITEUINT16(save_p, info - mobjinfo); + WRITEUINT8(*p, ARCH_MOBJINFO); + WRITEUINT16(*p, info - mobjinfo); break; } case ARCH_STATE: { state_t *state = *((state_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(save_p, ARCH_STATE); - WRITEUINT16(save_p, state - states); + WRITEUINT8(*p, ARCH_STATE); + WRITEUINT16(*p, state - states); break; } case ARCH_MOBJ: { mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex)); if (!mobj) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MOBJ); - WRITEUINT32(save_p, mobj->mobjnum); + WRITEUINT8(*p, ARCH_MOBJ); + WRITEUINT32(*p, mobj->mobjnum); } break; } @@ -628,10 +1049,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { player_t *player = *((player_t **)lua_touserdata(gL, myindex)); if (!player) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_PLAYER); - WRITEUINT8(save_p, player - players); + WRITEUINT8(*p, ARCH_PLAYER); + WRITEUINT8(*p, player - players); } break; } @@ -639,10 +1060,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex)); if (!mapthing) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MAPTHING); - WRITEUINT16(save_p, mapthing - mapthings); + WRITEUINT8(*p, ARCH_MAPTHING); + WRITEUINT16(*p, mapthing - mapthings); } break; } @@ -650,10 +1071,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex)); if (!vertex) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_VERTEX); - WRITEUINT16(save_p, vertex - vertexes); + WRITEUINT8(*p, ARCH_VERTEX); + WRITEUINT16(*p, vertex - vertexes); } break; } @@ -661,10 +1082,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { line_t *line = *((line_t **)lua_touserdata(gL, myindex)); if (!line) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_LINE); - WRITEUINT16(save_p, line - lines); + WRITEUINT8(*p, ARCH_LINE); + WRITEUINT16(*p, line - lines); } break; } @@ -672,10 +1093,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { side_t *side = *((side_t **)lua_touserdata(gL, myindex)); if (!side) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SIDE); - WRITEUINT16(save_p, side - sides); + WRITEUINT8(*p, ARCH_SIDE); + WRITEUINT16(*p, side - sides); } break; } @@ -683,10 +1104,10 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex)); if (!subsector) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SUBSECTOR); - WRITEUINT16(save_p, subsector - subsectors); + WRITEUINT8(*p, ARCH_SUBSECTOR); + WRITEUINT16(*p, subsector - subsectors); } break; } @@ -694,39 +1115,98 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) { sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex)); if (!sector) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SECTOR); - WRITEUINT16(save_p, sector - sectors); + WRITEUINT8(*p, ARCH_SECTOR); + WRITEUINT16(*p, sector - sectors); } break; } -#ifdef ESLOPE - case ARCH_SLOPE: +#ifdef HAVE_LUA_SEGS + case ARCH_SEG: { - pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); - if (!slope) - WRITEUINT8(save_p, ARCH_NULL); + seg_t *seg = *((seg_t **)lua_touserdata(gL, myindex)); + if (!seg) + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_SLOPE); - WRITEUINT16(save_p, slope->id); + WRITEUINT8(*p, ARCH_SEG); + WRITEUINT16(*p, seg - segs); + } + break; + } + case ARCH_NODE: + { + node_t *node = *((node_t **)lua_touserdata(gL, myindex)); + if (!node) + WRITEUINT8(*p, ARCH_NULL); + else { + WRITEUINT8(*p, ARCH_NODE); + WRITEUINT16(*p, node - nodes); } break; } #endif + case ARCH_FFLOOR: + { + ffloor_t *rover = *((ffloor_t **)lua_touserdata(gL, myindex)); + if (!rover) + WRITEUINT8(*p, ARCH_NULL); + else { + UINT16 i = P_GetFFloorID(rover); + if (i == UINT16_MAX) // invalid ID + WRITEUINT8(*p, ARCH_NULL); + else + { + WRITEUINT8(*p, ARCH_FFLOOR); + WRITEUINT16(*p, rover->target - sectors); + WRITEUINT16(*p, i); + } + } + break; + } + case ARCH_POLYOBJ: + { + polyobj_t *polyobj = *((polyobj_t **)lua_touserdata(gL, myindex)); + if (!polyobj) + WRITEUINT8(save_p, ARCH_NULL); + else { + WRITEUINT8(save_p, ARCH_POLYOBJ); + WRITEUINT16(save_p, polyobj-PolyObjects); + } + break; + } + case ARCH_SLOPE: + { + pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); + if (!slope) + WRITEUINT8(*p, ARCH_NULL); + else { + WRITEUINT8(*p, ARCH_SLOPE); + WRITEUINT16(*p, slope->id); + } + break; + } case ARCH_MAPHEADER: { mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); if (!header) - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); else { - WRITEUINT8(save_p, ARCH_MAPHEADER); - WRITEUINT16(save_p, header - *mapheaderinfo); + WRITEUINT8(*p, ARCH_MAPHEADER); + WRITEUINT16(*p, header - *mapheaderinfo); } break; } + + case ARCH_SKINCOLOR: + { + skincolor_t *info = *((skincolor_t **)lua_touserdata(gL, myindex)); + WRITEUINT8(*p, ARCH_SKINCOLOR); + WRITEUINT16(*p, info - skincolors); + break; + } default: - WRITEUINT8(save_p, ARCH_NULL); + WRITEUINT8(*p, ARCH_NULL); return 2; } break; @@ -734,228 +1214,14 @@ static UINT8 ArchiveValue(int TABLESINDEX, int myindex) return 0; } -// because of how this function works it has to be pasted allll over again just to save to demo_p since it returns an uint8 to begin with -static UINT8 ArchiveValueDemo(int TABLESINDEX, int myindex) -{ - if (myindex < 0) - myindex = lua_gettop(gL)+1+myindex; - switch (lua_type(gL, myindex)) - { - case LUA_TNONE: - case LUA_TNIL: - WRITEUINT8(demo_p, ARCH_NULL); - break; - // This might be a problem. D: - case LUA_TLIGHTUSERDATA: - case LUA_TTHREAD: - case LUA_TFUNCTION: - WRITEUINT8(demo_p, ARCH_NULL); - return 2; - case LUA_TBOOLEAN: - WRITEUINT8(demo_p, ARCH_BOOLEAN); - WRITEUINT8(demo_p, lua_toboolean(gL, myindex)); - break; - case LUA_TNUMBER: - { - lua_Integer number = lua_tointeger(gL, myindex); - WRITEUINT8(demo_p, ARCH_SIGNED); - WRITEFIXED(demo_p, number); - break; - } - case LUA_TSTRING: - { - UINT16 len = (UINT16)lua_objlen(gL, myindex); // get length of string, including embedded zeros - const char *s = lua_tostring(gL, myindex); - UINT16 i = 0; - WRITEUINT8(demo_p, ARCH_STRING); - // if you're wondering why we're writing a string to demo_p this way, - // it turns out that Lua can have embedded zeros ('\0') in the strings, - // so we can't use WRITESTRING as that cuts off when it finds a '\0'. - // Saving the size of the string also allows us to get the size of the string on the other end, - // fixing the awful crashes previously encountered for reading strings longer than 1024 - // (yes I know that's kind of a stupid thing to care about, but it'd be evil to trim or ignore them?) - // -- Monster Iestyn 05/08/18 - WRITEUINT16(demo_p, len); // save size of string - while (i < len) - WRITECHAR(demo_p, s[i++]); // write chars individually, including the embedded zeros - break; - } - case LUA_TTABLE: - { - boolean found = false; - INT32 i; - UINT16 t = (UINT16)lua_objlen(gL, TABLESINDEX); - - for (i = 1; i <= t && !found; i++) - { - lua_rawgeti(gL, TABLESINDEX, i); - if (lua_rawequal(gL, myindex, -1)) - { - t = i; - found = true; - } - lua_pop(gL, 1); - } - if (!found) - t++; - - WRITEUINT8(demo_p, ARCH_TABLE); - WRITEUINT16(demo_p, t); - - if (!found) - { - lua_pushvalue(gL, myindex); - lua_rawseti(gL, TABLESINDEX, t); - return 1; - } - break; - } - case LUA_TUSERDATA: - switch (GetUserdataArchType(myindex)) - { - case ARCH_MOBJINFO: - { - mobjinfo_t *info = *((mobjinfo_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(demo_p, ARCH_MOBJINFO); - WRITEUINT16(demo_p, info - mobjinfo); - break; - } - case ARCH_STATE: - { - state_t *state = *((state_t **)lua_touserdata(gL, myindex)); - WRITEUINT8(demo_p, ARCH_STATE); - WRITEUINT16(demo_p, state - states); - break; - } - case ARCH_MOBJ: - { - mobj_t *mobj = *((mobj_t **)lua_touserdata(gL, myindex)); - if (!mobj) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_MOBJ); - WRITEUINT32(demo_p, mobj->mobjnum); - } - break; - } - case ARCH_PLAYER: - { - player_t *player = *((player_t **)lua_touserdata(gL, myindex)); - if (!player) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_PLAYER); - WRITEUINT8(demo_p, player - players); - } - break; - } - case ARCH_MAPTHING: - { - mapthing_t *mapthing = *((mapthing_t **)lua_touserdata(gL, myindex)); - if (!mapthing) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_MAPTHING); - WRITEUINT16(demo_p, mapthing - mapthings); - } - break; - } - case ARCH_VERTEX: - { - vertex_t *vertex = *((vertex_t **)lua_touserdata(gL, myindex)); - if (!vertex) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_VERTEX); - WRITEUINT16(demo_p, vertex - vertexes); - } - break; - } - case ARCH_LINE: - { - line_t *line = *((line_t **)lua_touserdata(gL, myindex)); - if (!line) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_LINE); - WRITEUINT16(demo_p, line - lines); - } - break; - } - case ARCH_SIDE: - { - side_t *side = *((side_t **)lua_touserdata(gL, myindex)); - if (!side) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_SIDE); - WRITEUINT16(demo_p, side - sides); - } - break; - } - case ARCH_SUBSECTOR: - { - subsector_t *subsector = *((subsector_t **)lua_touserdata(gL, myindex)); - if (!subsector) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_SUBSECTOR); - WRITEUINT16(demo_p, subsector - subsectors); - } - break; - } - case ARCH_SECTOR: - { - sector_t *sector = *((sector_t **)lua_touserdata(gL, myindex)); - if (!sector) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_SECTOR); - WRITEUINT16(demo_p, sector - sectors); - } - break; - } -#ifdef ESLOPE - case ARCH_SLOPE: - { - pslope_t *slope = *((pslope_t **)lua_touserdata(gL, myindex)); - if (!slope) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_SLOPE); - WRITEUINT16(demo_p, slope->id); - } - break; - } -#endif - case ARCH_MAPHEADER: - { - mapheader_t *header = *((mapheader_t **)lua_touserdata(gL, myindex)); - if (!header) - WRITEUINT8(demo_p, ARCH_NULL); - else { - WRITEUINT8(demo_p, ARCH_MAPHEADER); - WRITEUINT16(demo_p, header - *mapheaderinfo); - } - break; - } - default: - WRITEUINT8(demo_p, ARCH_NULL); - return 2; - } - break; - } - return 0; -} - -static void ArchiveExtVars(void *pointer, const char *ptype) +static void ArchiveExtVars(UINT8 **p, void *pointer, const char *ptype) { int TABLESINDEX; UINT16 i; if (!gL) { if (fastcmp(ptype,"player")) // players must always be included, even if no vars - WRITEUINT16(save_p, 0); + WRITEUINT16(*p, 0); return; } @@ -971,7 +1237,7 @@ static void ArchiveExtVars(void *pointer, const char *ptype) { // no extra values table lua_pop(gL, 1); if (fastcmp(ptype,"player")) // players must always be included, even if no vars - WRITEUINT16(save_p, 0); + WRITEUINT16(*p, 0); return; } @@ -983,77 +1249,20 @@ static void ArchiveExtVars(void *pointer, const char *ptype) if (i == 0) { if (fastcmp(ptype,"player")) // always include players even if they have no extra variables - WRITEUINT16(save_p, 0); + WRITEUINT16(*p, 0); lua_pop(gL, 1); return; } if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header - WRITEUINT32(save_p, ((mobj_t *)pointer)->mobjnum); - WRITEUINT16(save_p, i); + WRITEUINT32(*p, ((mobj_t *)pointer)->mobjnum); + WRITEUINT16(*p, i); lua_pushnil(gL); while (lua_next(gL, -2)) { I_Assert(lua_type(gL, -2) == LUA_TSTRING); - WRITESTRING(save_p, lua_tostring(gL, -2)); - if (ArchiveValue(TABLESINDEX, -1) == 2) - CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1)); - lua_pop(gL, 1); - } - - lua_pop(gL, 1); -} - -// simplified for demos -static void ArchiveExtVarsDemo(void *pointer, const char *ptype) -{ - int TABLESINDEX; - UINT16 i; - - if (!gL) { - if (fastcmp(ptype,"player")) // players must always be included, even if no vars - WRITEUINT16(demo_p, 0); - return; - } - - TABLESINDEX = lua_gettop(gL); - - lua_getfield(gL, LUA_REGISTRYINDEX, LREG_EXTVARS); - I_Assert(lua_istable(gL, -1)); - lua_pushlightuserdata(gL, pointer); - lua_rawget(gL, -2); - lua_remove(gL, -2); // pop LREG_EXTVARS - - if (!lua_istable(gL, -1)) - { // no extra values table - lua_pop(gL, 1); - if (fastcmp(ptype,"player")) // players must always be included, even if no vars - WRITEUINT16(demo_p, 0); - return; - } - - lua_pushnil(gL); - for (i = 0; lua_next(gL, -2); i++) - lua_pop(gL, 1); - - // skip anything that has an empty table and isn't a player. - if (i == 0) - { - if (fastcmp(ptype,"player")) // always include players even if they have no extra variables - WRITEUINT16(demo_p, 0); - lua_pop(gL, 1); - return; - } - - if (fastcmp(ptype,"mobj")) // mobjs must write their mobjnum as a header - WRITEUINT32(demo_p, ((mobj_t *)pointer)->mobjnum); - WRITEUINT16(demo_p, i); - lua_pushnil(gL); - while (lua_next(gL, -2)) - { - I_Assert(lua_type(gL, -2) == LUA_TSTRING); - WRITESTRING(demo_p, lua_tostring(gL, -2)); - if (ArchiveValueDemo(TABLESINDEX, -1) == 2) + WRITESTRING(*p, lua_tostring(gL, -2)); + if (ArchiveValue(p, TABLESINDEX, -1) == 2) CONS_Alert(CONS_ERROR, "Type of value for %s entry '%s' (%s) could not be archived!\n", ptype, lua_tostring(gL, -2), luaL_typename(gL, -1)); lua_pop(gL, 1); } @@ -1066,11 +1275,11 @@ static int NetArchive(lua_State *L) int TABLESINDEX = lua_upvalueindex(1); int i, n = lua_gettop(L); for (i = 1; i <= n; i++) - ArchiveValue(TABLESINDEX, i); + ArchiveValue(&save_p, TABLESINDEX, i); return n; } -static void ArchiveTables(void) +static void ArchiveTables(UINT8 **p) { int TABLESINDEX; UINT16 i, n; @@ -1089,7 +1298,7 @@ static void ArchiveTables(void) while (lua_next(gL, -2)) { // Write key - e = ArchiveValue(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. + e = ArchiveValue(p, TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise) { lua_pushvalue(gL, -2); @@ -1097,7 +1306,7 @@ static void ArchiveTables(void) lua_pop(gL, 1); } // Write value - e = ArchiveValue(TABLESINDEX, -1); + e = ArchiveValue(p, TABLESINDEX, -1); if (e == 1) n++; // the table contained a new table we'll have to archive. :( else if (e == 2) // invalid value type @@ -1110,239 +1319,128 @@ static void ArchiveTables(void) lua_pop(gL, 1); } lua_pop(gL, 1); - WRITEUINT8(save_p, ARCH_TEND); + WRITEUINT8(*p, ARCH_TEND); } } -static void ArchiveTablesDemo(void) +static UINT8 UnArchiveValue(UINT8 **p, int TABLESINDEX) { - int TABLESINDEX; - UINT16 i, n; - UINT8 e; - - if (!gL) - return; - - TABLESINDEX = lua_gettop(gL); - - n = (UINT16)lua_objlen(gL, TABLESINDEX); - for (i = 1; i <= n; i++) - { - lua_rawgeti(gL, TABLESINDEX, i); - lua_pushnil(gL); - while (lua_next(gL, -2)) - { - // Write key - e = ArchiveValueDemo(TABLESINDEX, -2); // key should be either a number or a string, ArchiveValue can handle this. - if (e == 2) // invalid key type (function, thread, lightuserdata, or anything we don't recognise) - { - lua_pushvalue(gL, -2); - CONS_Alert(CONS_ERROR, "Index '%s' (%s) of table %d could not be archived!\n", lua_tostring(gL, -1), luaL_typename(gL, -1), i); - lua_pop(gL, 1); - } - // Write value - e = ArchiveValueDemo(TABLESINDEX, -1); - if (e == 1) - n++; // the table contained a new table we'll have to archive. :( - else if (e == 2) // invalid value type - { - lua_pushvalue(gL, -2); - CONS_Alert(CONS_ERROR, "Type of value for table %d entry '%s' (%s) could not be archived!\n", i, lua_tostring(gL, -1), luaL_typename(gL, -1)); - lua_pop(gL, 1); - } - - lua_pop(gL, 1); - } - lua_pop(gL, 1); - WRITEUINT8(demo_p, ARCH_TEND); - } -} - -static UINT8 UnArchiveValue(int TABLESINDEX) -{ - UINT8 type = READUINT8(save_p); + UINT8 type = READUINT8(*p); switch (type) { case ARCH_NULL: lua_pushnil(gL); break; - case ARCH_BOOLEAN: - lua_pushboolean(gL, READUINT8(save_p)); + case ARCH_TRUE: + lua_pushboolean(gL, true); break; - case ARCH_SIGNED: - lua_pushinteger(gL, READFIXED(save_p)); + case ARCH_FALSE: + lua_pushboolean(gL, false); break; - case ARCH_STRING: + case ARCH_INT8: + lua_pushinteger(gL, READSINT8(*p)); + break; + case ARCH_INT16: + lua_pushinteger(gL, READINT16(*p)); + break; + case ARCH_INT32: + lua_pushinteger(gL, READFIXED(*p)); + break; + case ARCH_SMALLSTRING: + case ARCH_LARGESTRING: { - UINT16 len = READUINT16(save_p); // length of string, including embedded zeros + UINT32 len; char *value; - UINT16 i = 0; + UINT32 i = 0; + // See my comments in the ArchiveValue function; // it's much the same for reading strings as writing them! // (i.e. we can't use READSTRING either) // -- Monster Iestyn 05/08/18 - value = malloc(len); // make temp buffer of size len - // now read the actual string - while (i < len) - value[i++] = READCHAR(save_p); // read chars individually, including the embedded zeros - lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros) - free(value); // free the buffer - break; - } - case ARCH_TABLE: - { - UINT16 tid = READUINT16(save_p); - lua_rawgeti(gL, TABLESINDEX, tid); - if (lua_isnil(gL, -1)) - { - lua_pop(gL, 1); - lua_newtable(gL); - lua_pushvalue(gL, -1); - lua_rawseti(gL, TABLESINDEX, tid); - return 2; - } - break; - } - case ARCH_MOBJINFO: - LUA_PushUserdata(gL, &mobjinfo[READUINT16(save_p)], META_MOBJINFO); - break; - case ARCH_STATE: - LUA_PushUserdata(gL, &states[READUINT16(save_p)], META_STATE); - break; - case ARCH_MOBJ: - LUA_PushUserdata(gL, P_FindNewPosition(READUINT32(save_p)), META_MOBJ); - break; - case ARCH_PLAYER: - LUA_PushUserdata(gL, &players[READUINT8(save_p)], META_PLAYER); - break; - case ARCH_MAPTHING: - LUA_PushUserdata(gL, &mapthings[READUINT16(save_p)], META_MAPTHING); - break; - case ARCH_VERTEX: - LUA_PushUserdata(gL, &vertexes[READUINT16(save_p)], META_VERTEX); - break; - case ARCH_LINE: - LUA_PushUserdata(gL, &lines[READUINT16(save_p)], META_LINE); - break; - case ARCH_SIDE: - LUA_PushUserdata(gL, &sides[READUINT16(save_p)], META_SIDE); - break; - case ARCH_SUBSECTOR: - LUA_PushUserdata(gL, &subsectors[READUINT16(save_p)], META_SUBSECTOR); - break; - case ARCH_SECTOR: - LUA_PushUserdata(gL, §ors[READUINT16(save_p)], META_SECTOR); - break; -#ifdef ESLOPE - case ARCH_SLOPE: - LUA_PushUserdata(gL, P_SlopeById(READUINT16(save_p)), META_SLOPE); - break; -#endif - case ARCH_MAPHEADER: - LUA_PushUserdata(gL, mapheaderinfo[READUINT16(save_p)], META_MAPHEADER); - break; - case ARCH_TEND: - return 1; - } - return 0; -} - - -// Unarchives from demo_p: -// Return values: -// 0: Normal -// 1: Read table key -// 2: Read table value -// 3: Don't use setfield - -static UINT8 UnArchiveValueDemo(int TABLESINDEX, char field[1024]) -{ - UINT8 type = READUINT8(demo_p); - switch (type) - { - case ARCH_NULL: - lua_pushnil(gL); - break; - case ARCH_BOOLEAN: - lua_pushboolean(gL, READUINT8(demo_p)); - break; - case ARCH_SIGNED: - lua_pushinteger(gL, READFIXED(demo_p)); - break; - case ARCH_STRING: - { - UINT16 len = READUINT16(demo_p); // length of string, including embedded zeros - char *value; - UINT16 i = 0; - // See my comments in the ArchiveValue function; - // it's much the same for reading strings as writing them! - // (i.e. we can't use READSTRING either) - // -- Monster Iestyn 05/08/18 - value = malloc(len); // make temp buffer of size len - // now read the actual string - while (i < len) - value[i++] = READCHAR(demo_p); // read chars individually, including the embedded zeros - lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros) - free(value); // free the buffer - break; - } - case ARCH_TABLE: - { - UINT16 tid = READUINT16(demo_p); - lua_rawgeti(gL, TABLESINDEX, tid); - if (lua_isnil(gL, -1)) - { - lua_pop(gL, 1); - lua_newtable(gL); - lua_pushvalue(gL, -1); - lua_rawseti(gL, TABLESINDEX, tid); - return 2; - } - break; - } - case ARCH_MOBJINFO: - LUA_PushUserdata(gL, &mobjinfo[READUINT16(demo_p)], META_MOBJINFO); - break; - case ARCH_STATE: - LUA_PushUserdata(gL, &states[READUINT16(demo_p)], META_STATE); - break; - case ARCH_MOBJ: - demo_p += sizeof(UINT32); // Skip this data, we can't read a mobj here, it'd point to garbage and crash the game. - if (field) - CONS_Alert(CONS_WARNING,"Cannot read mobj_t stored in player variable \'%s\'. Desyncs may occur.\n", field); + if (type == ARCH_SMALLSTRING) + len = READUINT8(*p); // length of string, including embedded zeros else - CONS_Alert(CONS_WARNING,"Couldn't read mobj_t\n"); - - return 3; // Don't set the field - + len = READUINT32(*p); // length of string, including embedded zeros + value = malloc(len); // make temp buffer of size len + // now read the actual string + while (i < len) + value[i++] = READCHAR(*p); // read chars individually, including the embedded zeros + lua_pushlstring(gL, value, len); // push the string (note: this function supports embedded zeros) + free(value); // free the buffer + break; + } + case ARCH_TABLE: + { + UINT16 tid = READUINT16(*p); + lua_rawgeti(gL, TABLESINDEX, tid); + if (lua_isnil(gL, -1)) + { + lua_pop(gL, 1); + lua_newtable(gL); + lua_pushvalue(gL, -1); + lua_rawseti(gL, TABLESINDEX, tid); + return 2; + } + break; + } + case ARCH_MOBJINFO: + LUA_PushUserdata(gL, &mobjinfo[READUINT16(*p)], META_MOBJINFO); + break; + case ARCH_STATE: + LUA_PushUserdata(gL, &states[READUINT16(*p)], META_STATE); + break; + case ARCH_MOBJ: + LUA_PushUserdata(gL, P_FindNewPosition(READUINT32(*p)), META_MOBJ); + break; case ARCH_PLAYER: - LUA_PushUserdata(gL, &players[READUINT8(demo_p)], META_PLAYER); + LUA_PushUserdata(gL, &players[READUINT8(*p)], META_PLAYER); break; case ARCH_MAPTHING: - LUA_PushUserdata(gL, &mapthings[READUINT16(demo_p)], META_MAPTHING); + LUA_PushUserdata(gL, &mapthings[READUINT16(*p)], META_MAPTHING); break; case ARCH_VERTEX: - LUA_PushUserdata(gL, &vertexes[READUINT16(demo_p)], META_VERTEX); + LUA_PushUserdata(gL, &vertexes[READUINT16(*p)], META_VERTEX); break; case ARCH_LINE: - LUA_PushUserdata(gL, &lines[READUINT16(demo_p)], META_LINE); + LUA_PushUserdata(gL, &lines[READUINT16(*p)], META_LINE); break; case ARCH_SIDE: - LUA_PushUserdata(gL, &sides[READUINT16(demo_p)], META_SIDE); + LUA_PushUserdata(gL, &sides[READUINT16(*p)], META_SIDE); break; case ARCH_SUBSECTOR: - LUA_PushUserdata(gL, &subsectors[READUINT16(demo_p)], META_SUBSECTOR); + LUA_PushUserdata(gL, &subsectors[READUINT16(*p)], META_SUBSECTOR); break; case ARCH_SECTOR: - LUA_PushUserdata(gL, §ors[READUINT16(demo_p)], META_SECTOR); + LUA_PushUserdata(gL, §ors[READUINT16(*p)], META_SECTOR); break; -#ifdef ESLOPE - case ARCH_SLOPE: - LUA_PushUserdata(gL, P_SlopeById(READUINT16(demo_p)), META_SLOPE); +#ifdef HAVE_LUA_SEGS + case ARCH_SEG: + LUA_PushUserdata(gL, &segs[READUINT16(*p)], META_SEG); + break; + case ARCH_NODE: + LUA_PushUserdata(gL, &nodes[READUINT16(*p)], META_NODE); break; #endif + case ARCH_FFLOOR: + { + sector_t *sector = §ors[READUINT16(*p)]; + UINT16 id = READUINT16(*p); + ffloor_t *rover = P_GetFFloorByID(sector, id); + if (rover) + LUA_PushUserdata(gL, rover, META_FFLOOR); + break; + } + case ARCH_POLYOBJ: + LUA_PushUserdata(gL, &PolyObjects[READUINT16(save_p)], META_POLYOBJ); + break; + case ARCH_SLOPE: + LUA_PushUserdata(gL, P_SlopeById(READUINT16(*p)), META_SLOPE); + break; case ARCH_MAPHEADER: - LUA_PushUserdata(gL, mapheaderinfo[READUINT16(demo_p)], META_MAPHEADER); + LUA_PushUserdata(gL, mapheaderinfo[READUINT16(*p)], META_MAPHEADER); + break; + case ARCH_SKINCOLOR: + LUA_PushUserdata(gL, &skincolors[READUINT16(*p)], META_SKINCOLOR); break; case ARCH_TEND: return 1; @@ -1350,10 +1448,10 @@ static UINT8 UnArchiveValueDemo(int TABLESINDEX, char field[1024]) return 0; } -static void UnArchiveExtVars(void *pointer) +static void UnArchiveExtVars(UINT8 **p, void *pointer) { int TABLESINDEX; - UINT16 field_count = READUINT16(save_p); + UINT16 field_count = READUINT16(*p); UINT16 i; char field[1024]; @@ -1366,8 +1464,8 @@ static void UnArchiveExtVars(void *pointer) for (i = 0; i < field_count; i++) { - READSTRING(save_p, field); - UnArchiveValue(TABLESINDEX); + READSTRING(*p, field); + UnArchiveValue(p, TABLESINDEX); lua_setfield(gL, -2, field); } @@ -1379,45 +1477,16 @@ static void UnArchiveExtVars(void *pointer) lua_pop(gL, 2); // pop LREG_EXTVARS and pointer's subtable } -static void UnArchiveExtVarsDemo(void *pointer) -{ - int TABLESINDEX; - UINT16 field_count = READUINT16(demo_p); - UINT16 i; - char field[1024]; - - if (field_count == 0) - return; - I_Assert(gL != NULL); - - TABLESINDEX = lua_gettop(gL); - lua_createtable(gL, 0, field_count); // pointer's ext vars subtable - - for (i = 0; i < field_count; i++) - { - READSTRING(demo_p, field); - if (UnArchiveValueDemo(TABLESINDEX, field) != 3) // This will return 3 if we shouldn't set this field. - lua_setfield(gL, -2, field); - } - - lua_getfield(gL, LUA_REGISTRYINDEX, LREG_EXTVARS); - I_Assert(lua_istable(gL, -1)); - lua_pushlightuserdata(gL, pointer); - lua_pushvalue(gL, -3); // pointer's ext vars subtable - lua_rawset(gL, -3); - lua_pop(gL, 2); // pop LREG_EXTVARS and pointer's subtable -} - static int NetUnArchive(lua_State *L) { int TABLESINDEX = lua_upvalueindex(1); int i, n = lua_gettop(L); for (i = 1; i <= n; i++) - UnArchiveValue(TABLESINDEX); + UnArchiveValue(&save_p, TABLESINDEX); return n; } -static void UnArchiveTables(void) +static void UnArchiveTables(UINT8 **p) { int TABLESINDEX; UINT16 i, n; @@ -1433,41 +1502,9 @@ static void UnArchiveTables(void) lua_rawgeti(gL, TABLESINDEX, i); while (true) { - if (UnArchiveValue(TABLESINDEX) == 1) // read key + if (UnArchiveValue(p, TABLESINDEX) == 1) // read key break; - if (UnArchiveValue(TABLESINDEX) == 2) // read value - n++; - if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved) - { - CONS_Alert(CONS_ERROR, "A nil key in table %d was found! (Invalid key type or corrupted save?)\n", i); - lua_pop(gL, 2); // pop key and value instead of setting them in the table, to prevent Lua panic errors - } - else - lua_rawset(gL, -3); - } - lua_pop(gL, 1); - } -} - -static void UnArchiveTablesDemo(void) -{ - int TABLESINDEX; - UINT16 i, n; - - if (!gL) - return; - - TABLESINDEX = lua_gettop(gL); - - n = (UINT16)lua_objlen(gL, TABLESINDEX); - for (i = 1; i <= n; i++) - { - lua_rawgeti(gL, TABLESINDEX, i); - while (true) - { - if (UnArchiveValueDemo(TABLESINDEX, NULL) == 1) // read key - break; - if (UnArchiveValueDemo(TABLESINDEX, NULL) == 2) // read value + if (UnArchiveValue(p, TABLESINDEX) == 2) // read value n++; if (lua_isnil(gL, -2)) // if key is nil (if a function etc was accidentally saved) { @@ -1489,7 +1526,7 @@ void LUA_Step(void) lua_gc(gL, LUA_GCSTEP, 1); } -void LUA_Archive(void) +void LUA_Archive(UINT8 **p) { INT32 i; thinker_t *th; @@ -1502,29 +1539,36 @@ void LUA_Archive(void) if (!playeringame[i] && i > 0) // NEVER skip player 0, this is for dedi servs. continue; // all players in game will be archived, even if they just add a 0. - ArchiveExtVars(&players[i], "player"); + ArchiveExtVars(p, &players[i], "player"); } - if (gamestate == GS_LEVEL) + if (p == &save_p) { - for (th = thinkercap.next; th != &thinkercap; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker) + if (gamestate == GS_LEVEL) + { + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + // archive function will determine when to skip mobjs, // and write mobjnum in otherwise. - ArchiveExtVars(th, "mobj"); + ArchiveExtVars(p, th, "mobj"); } - } - WRITEUINT32(save_p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. + } + + WRITEUINT32(*p, UINT32_MAX); // end of mobjs marker, replaces mobjnum. - LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode - ArchiveTables(); + LUAh_NetArchiveHook(NetArchive); // call the NetArchive hook in archive mode + } + + ArchiveTables(p); if (gL) lua_pop(gL, 1); // pop tables } -void LUA_UnArchive(void) +void LUA_UnArchive(UINT8 **p) { UINT32 mobjnum; INT32 i; @@ -1537,62 +1581,27 @@ void LUA_UnArchive(void) { if (!playeringame[i] && i > 0) // same here, this is to synch dediservs properly. continue; - UnArchiveExtVars(&players[i]); + UnArchiveExtVars(p, &players[i]); } - do { - mobjnum = READUINT32(save_p); // read a mobjnum - for (th = thinkercap.next; th != &thinkercap; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker - && ((mobj_t *)th)->mobjnum == mobjnum) // find matching mobj - UnArchiveExtVars(th); // apply variables - } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. - - LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode - UnArchiveTables(); - - if (gL) - lua_pop(gL, 1); // pop tables -} - -// simplified versions of LUA_Archive for demos -void LUA_ArchiveDemo(void) -{ - INT32 i; - - if (gL) - lua_newtable(gL); // tables to be archived. - - for (i = 0; i < MAXPLAYERS; i++) + if (p == &save_p) { - if (!playeringame[i] && i > 0) // NEVER skip player 0, this is for dedi servs. - continue; - // all players in game will be archived, even if they just add a 0. - ArchiveExtVarsDemo(&players[i], "player"); + do { + mobjnum = READUINT32(*p); // read a mobjnum + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + if (((mobj_t *)th)->mobjnum != mobjnum) // find matching mobj + continue; + UnArchiveExtVars(p, th); // apply variables + } + } while(mobjnum != UINT32_MAX); // repeat until end of mobjs marker. + + LUAh_NetArchiveHook(NetUnArchive); // call the NetArchive hook in unarchive mode } - ArchiveTablesDemo(); - - if (gL) - lua_pop(gL, 1); // pop tables -} - -// this time make sure we read from demo_p -void LUA_UnArchiveDemo(void) -{ - INT32 i; - - if (gL) - lua_newtable(gL); // tables to be read - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] && i > 0) // same here, this is to synch dediservs properly. - continue; - UnArchiveExtVarsDemo(&players[i]); - } - - UnArchiveTablesDemo(); + UnArchiveTables(p); if (gL) lua_pop(gL, 1); // pop tables @@ -1609,5 +1618,3 @@ int Lua_optoption(lua_State *L, int narg, return i; return -1; } - -#endif // HAVE_BLUA diff --git a/src/lua_script.h b/src/lua_script.h index b3ca16bc0..cf4efcccd 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -10,11 +10,10 @@ /// \file lua_script.h /// \brief Lua scripting basics -#ifdef HAVE_BLUA - #include "m_fixed.h" #include "doomtype.h" #include "d_player.h" +#include "g_state.h" #include "blua/lua.h" #include "blua/lualib.h" @@ -40,22 +39,26 @@ void LUA_ClearExtVars(void); void LUA_ClearState(void); -void LUA_LoadLump(UINT16 wad, UINT16 lump); +extern INT32 lua_lumploading; // is LUA_LoadLump being called? + +int LUA_GetErrorMessage(lua_State *L); +void LUA_LoadLump(UINT16 wad, UINT16 lump, boolean noresults); #ifdef LUA_ALLOW_BYTECODE void LUA_DumpFile(const char *filename); #endif fixed_t LUA_EvalMath(const char *word); +void LUA_PushLightUserdata(lua_State *L, void *data, const char *meta); void LUA_PushUserdata(lua_State *L, void *data, const char *meta); void LUA_InvalidateUserdata(void *data); void LUA_InvalidateLevel(void); void LUA_InvalidateMapthings(void); void LUA_InvalidatePlayer(player_t *player); void LUA_Step(void); -void LUA_Archive(void); -void LUA_UnArchive(void); +void LUA_Archive(UINT8 **p); +void LUA_UnArchive(UINT8 **p); -void LUA_ArchiveDemo(void); -void LUA_UnArchiveDemo(void); +int LUA_PushGlobals(lua_State *L, const char *word); +int LUA_WriteGlobals(lua_State *L, const char *word); void Got_Luacmd(UINT8 **cp, INT32 playernum); // lua_consolelib.c void LUA_CVarChanged(const char *name); // lua_consolelib.c @@ -98,4 +101,11 @@ void COM_Lua_f(void); }\ } -#endif +// uncomment if you want seg_t/node_t in Lua +// #define HAVE_LUA_SEGS + +#define ISINLEVEL \ + (gamestate == GS_LEVEL || titlemapinaction) + +#define INLEVEL if (! ISINLEVEL)\ +return luaL_error(L, "This can only be used in a level!"); diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index f44e97afe..c8da7f4d8 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2014-2016 by John "JTE" Muniz. -// Copyright (C) 2014-2018 by Sonic Team Junior. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,9 +11,8 @@ /// \brief player skin structure library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA #include "fastcmp.h" -#include "r_things.h" +#include "r_skins.h" #include "sounds.h" #include "lua_script.h" @@ -26,17 +25,17 @@ enum skin { skin_wadnum, skin_flags, skin_realname, - skin_hudname, - skin_facerank, - skin_facewant, - skin_facemmap, // SRB2kart skin_kartspeed, skin_kartweight, // + skin_followitem, skin_starttranscolor, skin_prefcolor, + skin_supercolor, + skin_prefoppositecolor, skin_highresscale, + skin_rivals, skin_soundsid }; static const char *const skin_opt[] = { @@ -46,17 +45,15 @@ static const char *const skin_opt[] = { "wadnum", "flags", "realname", - "hudname", - "facerank", - "facewant", - "facemmap", - // SRB2kart "kartspeed", "kartweight", - // + "followitem", "starttranscolor", "prefcolor", + "supercolor", + "prefoppositecolor", "highresscale", + "rivals", "soundsid", NULL}; @@ -66,7 +63,6 @@ static int skin_get(lua_State *L) { skin_t *skin = *((skin_t **)luaL_checkudata(L, 1, META_SKIN)); enum skin field = luaL_checkoption(L, 2, NULL, skin_opt); - INT32 i; // skins are always valid, only added, never removed I_Assert(skin != NULL); @@ -90,27 +86,6 @@ static int skin_get(lua_State *L) case skin_realname: lua_pushstring(L, skin->realname); break; - case skin_hudname: - lua_pushstring(L, skin->hudname); - break; - case skin_facerank: - for (i = 0; i < 8; i++) - if (!skin->facerank[i]) - break; - lua_pushlstring(L, skin->facerank, i); - break; - case skin_facewant: - for (i = 0; i < 8; i++) - if (!skin->facewant[i]) - break; - lua_pushlstring(L, skin->facewant, i); - break; - case skin_facemmap: - for (i = 0; i < 8; i++) - if (!skin->facemmap[i]) - break; - lua_pushlstring(L, skin->facemmap, i); - break; // SRB2kart case skin_kartspeed: lua_pushinteger(L, skin->kartspeed); @@ -118,16 +93,28 @@ static int skin_get(lua_State *L) case skin_kartweight: lua_pushinteger(L, skin->kartweight); break; - // + // + case skin_followitem: + lua_pushinteger(L, skin->followitem); + break; case skin_starttranscolor: lua_pushinteger(L, skin->starttranscolor); break; case skin_prefcolor: lua_pushinteger(L, skin->prefcolor); break; + case skin_supercolor: + lua_pushinteger(L, skin->supercolor); + break; + case skin_prefoppositecolor: + lua_pushinteger(L, skin->prefoppositecolor); + break; case skin_highresscale: lua_pushinteger(L, skin->highresscale); break; + case skin_rivals: + // This would be pretty cool to push + return UNIMPLEMENTED; case skin_soundsid: LUA_PushUserdata(L, skin->soundsid, META_SOUNDSID); break; @@ -274,5 +261,3 @@ int LUA_SkinLib(lua_State *L) return 0; } - -#endif diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index ae859d46e..82baa6469 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2012-2016 by John "JTE" Muniz. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,14 +11,13 @@ /// \brief thinker library for Lua scripting #include "doomdef.h" -#ifdef HAVE_BLUA #include "p_local.h" #include "lua_script.h" #include "lua_libs.h" #define META_ITERATIONSTATE "iteration state" -static const char *const iter_opt[] = { +/*static const char *const iter_opt[] = { "all", "mobj", NULL}; @@ -26,7 +25,7 @@ static const char *const iter_opt[] = { static const actionf_p1 iter_funcs[] = { NULL, (actionf_p1)P_MobjThinker -}; +};*/ struct iterationState { actionf_p1 filter; @@ -54,11 +53,16 @@ static int iterationState_gc(lua_State *L) static int lib_iterateThinkers(lua_State *L) { thinker_t *th = NULL, *next = NULL; - struct iterationState *it = luaL_checkudata(L, 1, META_ITERATIONSTATE); + struct iterationState *it; + + INLEVEL + + it = luaL_checkudata(L, 1, META_ITERATIONSTATE); + lua_settop(L, 2); if (lua_isnil(L, 2)) - th = &thinkercap; + th = &thlist[THINK_MOBJ]; else if (lua_isuserdata(L, 2)) { if (lua_islightuserdata(L, 2)) @@ -88,11 +92,11 @@ static int lib_iterateThinkers(lua_State *L) if (!next) return luaL_error(L, "next thinker invalidated during iteration"); - for (; next != &thinkercap; next = next->next) + for (; next != &thlist[THINK_MOBJ]; next = next->next) if (!it->filter || next->function.acp1 == it->filter) { push_thinker(next); - if (next->next != &thinkercap) + if (next->next != &thlist[THINK_MOBJ]) { push_thinker(next->next); it->next = luaL_ref(L, LUA_REGISTRYINDEX); @@ -106,12 +110,14 @@ static int lib_startIterate(lua_State *L) { struct iterationState *it; + INLEVEL + lua_pushvalue(L, lua_upvalueindex(1)); it = lua_newuserdata(L, sizeof(struct iterationState)); luaL_getmetatable(L, META_ITERATIONSTATE); lua_setmetatable(L, -2); - it->filter = iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)]; + it->filter = (actionf_p1)P_MobjThinker; //iter_funcs[luaL_checkoption(L, 1, "mobj", iter_opt)]; it->next = LUA_REFNIL; return 2; } @@ -129,8 +135,6 @@ int LUA_ThinkerLib(lua_State *L) lua_pushcfunction(L, lib_iterateThinkers); lua_pushcclosure(L, lib_startIterate, 1); lua_setfield(L, -2, "iterate"); - lua_setglobal(L, "thinkers"); + lua_setglobal(L, "mobjs"); return 0; } - -#endif diff --git a/src/lzf.c b/src/lzf.c index 272174f30..f81c3ee0a 100644 --- a/src/lzf.c +++ b/src/lzf.c @@ -119,9 +119,7 @@ /*****************************************************************************/ /* nothing should be changed below */ -#ifndef _NDS typedef unsigned char u8; -#endif typedef const u8 *LZF_STATE[1 << (HLOG)]; @@ -159,7 +157,7 @@ typedef const u8 *LZF_STATE[1 << (HLOG)]; * lzfP.h ends here. lzf_d.c follows. */ -#if AVOID_ERRNO || defined(_WIN32_WCE) +#if AVOID_ERRNO # define SET_ERRNO(n) #else # include diff --git a/src/m_aatree.c b/src/m_aatree.c index f19fa1dc0..c0bb739f8 100644 --- a/src/m_aatree.c +++ b/src/m_aatree.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_aatree.h b/src/m_aatree.h index e7f1eba05..b784eb17a 100644 --- a/src/m_aatree.h +++ b/src/m_aatree.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_anigif.c b/src/m_anigif.c index f0cab1c17..85118790b 100644 --- a/src/m_anigif.c +++ b/src/m_anigif.c @@ -1,8 +1,8 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2013-2016 by Matthew "Inuyasha" Walsh. +// Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. // Copyright (C) 2013 by "Ninji". -// Copyright (C) 2013-2018 by Sonic Team Junior. +// Copyright (C) 2013-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,6 +18,7 @@ #include "z_zone.h" #include "v_video.h" #include "i_video.h" +#include "i_system.h" // I_GetTimeMicros #include "m_misc.h" #include "st_stuff.h" // st_palette @@ -25,20 +26,18 @@ #include "hardware/hw_main.h" #endif -#ifdef HWRENDER -#include "hardware/hw_main.h" -#endif - // GIFs are always little-endian #include "byteptr.h" -consvar_t cv_gif_optimize = {"gif_optimize", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_gif_downscale = {"gif_downscale", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_gif_localcolortable = {"gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_gif_optimize = CVAR_INIT ("gif_optimize", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_gif_downscale = CVAR_INIT ("gif_downscale", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_gif_dynamicdelay = CVAR_INIT ("gif_dynamicdelay", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_gif_localcolortable = CVAR_INIT ("gif_localcolortable", "On", CV_SAVE, CV_OnOff, NULL); #ifdef HAVE_ANIGIF static boolean gif_optimize = false; // So nobody can do something dumb static boolean gif_downscale = false; // like changing cvars mid output +static boolean gif_dynamicdelay = false; // and messing something up // Palette handling static boolean gif_localcolortable = false; @@ -48,6 +47,7 @@ static RGBA_t *gif_framepalette = NULL; static FILE *gif_out = NULL; static INT32 gif_frames = 0; +static UINT32 gif_prevframems = 0; static UINT8 gif_writeover = 0; @@ -411,13 +411,13 @@ const UINT8 gifhead_nsid[19] = {0x21,0xFF,0x0B, // extension block + size // static RGBA_t *GIF_getpalette(size_t palnum) { - // In hardware mode, uses the master palette - return ((gif_colorprofile + // In hardware mode, always returns the local palette #ifdef HWRENDER - && (rendermode == render_soft) + if (rendermode == render_opengl) + return pLocalPalette; + else #endif - ) ? &pLocalPalette[palnum*256] - : &pMasterPalette[palnum*256]); + return (gif_colorprofile ? &pLocalPalette[palnum*256] : &pMasterPalette[palnum*256]); } // @@ -470,10 +470,6 @@ static void GIF_headwrite(void) WRITEUINT16(p, rheight); // colors, aspect, etc - /* - also these are magical values, check out - https://tronche.com/computer-graphics/gif/gif89a.html#screen-descriptor - */ WRITEUINT8(p, 0xF7); // (0xF7 = 1111 0111) WRITEUINT8(p, 0x00); WRITEUINT8(p, 0x00); @@ -498,29 +494,30 @@ const UINT8 gifframe_gchead[4] = {0x21,0xF9,0x04,0x04}; // GCE, bytes, packed by static UINT8 *gifframe_data = NULL; static size_t gifframe_size = 8192; +// +// GIF_rgbconvert +// converts an RGB frame to a frame with a palette. +// #ifdef HWRENDER -static void hwrconvert(void) +static colorlookup_t gif_colorlookup; + +static void GIF_rgbconvert(UINT8 *linear, UINT8 *scr) { - UINT8 *linear = HWR_GetScreenshot(); - UINT8 *dest = screens[2]; UINT8 r, g, b; - INT32 x, y; - size_t i = 0; + size_t src = 0, dest = 0; + size_t size = (vid.width * vid.height * 3); - InitColorLUT(gif_framepalette); + InitColorLUT(&gif_colorlookup, (gif_localcolortable) ? gif_framepalette : gif_headerpalette, true); - for (y = 0; y < vid.height; y++) + while (src < size) { - for (x = 0; x < vid.width; x++, i += 3) - { - r = (UINT8)linear[i]; - g = (UINT8)linear[i + 1]; - b = (UINT8)linear[i + 2]; - dest[(y * vid.width) + x] = colorlookup[r >> SHIFTCOLORBITS][g >> SHIFTCOLORBITS][b >> SHIFTCOLORBITS]; - } + r = (UINT8)linear[src]; + g = (UINT8)linear[src + 1]; + b = (UINT8)linear[src + 2]; + scr[dest] = GetColorLUTDirect(&gif_colorlookup, r, g, b); + src += (3 * scrbuf_downscaleamt); + dest += scrbuf_downscaleamt; } - - free(linear); } #endif @@ -564,7 +561,11 @@ static void GIF_framewrite(void) I_ReadScreen(movie_screen); #ifdef HWRENDER else if (rendermode == render_opengl) - hwrconvert(); + { + UINT8 *linear = HWR_GetScreenshot(); + GIF_rgbconvert(linear, movie_screen); + free(linear); + } #endif } else @@ -573,29 +574,45 @@ static void GIF_framewrite(void) blitw = vid.width; blith = vid.height; - if (gif_frames == 0) - { - if (rendermode == render_soft) - I_ReadScreen(movie_screen); #ifdef HWRENDER - else if (rendermode == render_opengl) - { - hwrconvert(); - VID_BlitLinearScreen(screens[2], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); - } -#endif + // Copy the current OpenGL frame into the base screen + if (rendermode == render_opengl) + { + UINT8 *linear = HWR_GetScreenshot(); + GIF_rgbconvert(linear, screens[0]); + free(linear); } +#endif + + // Copy the first frame into the movie screen + // OpenGL already does the same above. + if (gif_frames == 0 && rendermode == render_soft) + I_ReadScreen(movie_screen); movie_screen = screens[0]; } // screen regions are handled in GIF_lzw { - int d1 = (int)((100.0f/NEWTICRATE)*(gif_frames+1)); - int d2 = (int)((100.0f/NEWTICRATE)*(gif_frames)); - UINT16 delay = d1-d2; + UINT16 delay; INT32 startline; + if (gif_dynamicdelay) { + // golden's attempt at creating a "dynamic delay" + float delayf = ceil(100.0f/NEWTICRATE); + + delay = (UINT16)((I_GetTimeMicros() - gif_prevframems)/10/1000); + if (delay < (int)(delayf)) + delay = (int)(delayf); + } + else + { + // the original code + int d1 = (int)((100.0f/NEWTICRATE)*(gif_frames+1)); + int d2 = (int)((100.0f/NEWTICRATE)*(gif_frames)); + delay = d1-d2; + } + WRITEMEM(p, gifframe_gchead, 4); WRITEUINT16(p, delay); @@ -673,6 +690,7 @@ static void GIF_framewrite(void) } fwrite(gifframe_data, 1, (p - gifframe_data), gif_out); ++gif_frames; + gif_prevframems = I_GetTimeMicros(); } @@ -687,26 +705,20 @@ static void GIF_framewrite(void) // INT32 GIF_open(const char *filename) { -#if 0 - if (rendermode != render_soft) - { - CONS_Alert(CONS_WARNING, M_GetText("GIFs cannot be taken in non-software modes!\n")); - return 0; - } -#endif - gif_out = fopen(filename, "wb"); if (!gif_out) return 0; gif_optimize = (!!cv_gif_optimize.value); gif_downscale = (!!cv_gif_downscale.value); + gif_dynamicdelay = (!!cv_gif_dynamicdelay.value); gif_localcolortable = (!!cv_gif_localcolortable.value); gif_colorprofile = (!!cv_screenshot_colorprofile.value); gif_headerpalette = GIF_getpalette(0); GIF_headwrite(); gif_frames = 0; + gif_prevframems = I_GetTimeMicros(); return 1; } diff --git a/src/m_anigif.h b/src/m_anigif.h index bec481d59..abe05dd96 100644 --- a/src/m_anigif.h +++ b/src/m_anigif.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2013-2016 by Matthew "Inuyasha" Walsh. -// Copyright (C) 2013-2018 by Sonic Team Junior. +// Copyright (C) 2013-2016 by Matthew "Kaito Sinclaire" Walsh. +// Copyright (C) 2013-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,6 +27,6 @@ void GIF_frame(void); INT32 GIF_close(void); #endif -extern consvar_t cv_gif_optimize, cv_gif_downscale, cv_gif_localcolortable; +extern consvar_t cv_gif_optimize, cv_gif_downscale, cv_gif_dynamicdelay, cv_gif_localcolortable; #endif diff --git a/src/m_argv.c b/src/m_argv.c index e1046f8a7..7d43d96bc 100644 --- a/src/m_argv.c +++ b/src/m_argv.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -34,6 +34,25 @@ boolean myargmalloc = false; */ static INT32 found; +/** \brief Parses a server URL (such as srb2://127.0.0.1) as may be passed to the game via a web browser, etc. + + \return the contents of the URL after the protocol (a server to join), or NULL if not found +*/ +const char *M_GetUrlProtocolArg(void) +{ + INT32 i; + const size_t len = strlen(SERVER_URL_PROTOCOL); + + for (i = 1; i < myargc; i++) + { + if (strlen(myargv[i]) > len && !strnicmp(myargv[i], SERVER_URL_PROTOCOL, len)) + { + return &myargv[i][len]; + } + } + + return NULL; +} /** \brief The M_CheckParm function @@ -92,48 +111,28 @@ const char *M_GetNextParm(void) void M_PushSpecialParameters(void) { INT32 i; - char s[256]; - boolean onetime = false; - for (i = 1; i < myargc; i++) { if (myargv[i][0] == '+') { - strcpy(s, &myargv[i][1]); + COM_BufAddText(&myargv[i][1]); i++; // get the parameters of the command too for (; i < myargc && myargv[i][0] != '+' && myargv[i][0] != '-'; i++) { - strcat(s, " "); - if (!onetime) - { - strcat(s, "\""); - onetime = true; - } - strcat(s, myargv[i]); + COM_BufAddText(va(" \"%s\"", myargv[i])); } - if (onetime) - { - strcat(s, "\""); - onetime = false; - } - strcat(s, "\n"); // push it - COM_BufAddText(s); + COM_BufAddText("\n"); i--; } } } /// \brief max args - -#if defined (_arch_dreamcast) || defined (_XBOX) || defined (_WII) -#define MAXARGVS 1 -#else #define MAXARGVS 256 -#endif /** \brief the M_FindResponseFile function Find a response file diff --git a/src/m_argv.h b/src/m_argv.h index d654dcc19..92770f4e9 100644 --- a/src/m_argv.h +++ b/src/m_argv.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -21,6 +21,9 @@ extern INT32 myargc; extern char **myargv; extern boolean myargmalloc; +// Looks for an srb2:// (or similar) URL passed in as an argument and returns the IP to connect to if found. +const char *M_GetUrlProtocolArg(void); + // Returns the position of the given parameter in the arg list (0 if not found). INT32 M_CheckParm(const char *check); diff --git a/src/m_bbox.c b/src/m_bbox.c index 0c57de43e..02d534164 100644 --- a/src/m_bbox.c +++ b/src/m_bbox.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_bbox.h b/src/m_bbox.h index db5c2b4a7..9b63c61b6 100644 --- a/src/m_bbox.h +++ b/src/m_bbox.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_cheat.c b/src/m_cheat.c index 01e9ae5fa..ff5f86968 100644 --- a/src/m_cheat.c +++ b/src/m_cheat.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -63,7 +63,7 @@ typedef struct if (menuactive && (currentMenu != &MainDef && currentMenu != &SP_LoadDef)) return 0; // Only on the main menu, or the save select! - S_StartSound(0, sfx_itemup); + BwehHehHe(); ultimate_selectable = (!ultimate_selectable); // If on the save select, move to what is now Ultimate Mode! @@ -97,7 +97,7 @@ static UINT8 cheatf_warp(void) if (success) { - G_SaveGameData(true); //G_SetGameModified(false); + G_SaveGameData(); //G_SetGameModified(false); S_StartSound(0, sfx_kc42); } @@ -279,9 +279,6 @@ boolean cht_Responder(event_t *ev) #define REQUIRE_SINGLEPLAYER if (netgame || multiplayer)\ { CONS_Printf(M_GetText("This only works in single player.\n")); return; } -#define REQUIRE_NOULTIMATE if (ultimatemode)\ -{ CONS_Printf(M_GetText("You're too good to be cheating!\n")); return; } - // command that can be typed at the console! void Command_CheatNoClip_f(void) { @@ -289,7 +286,6 @@ void Command_CheatNoClip_f(void) REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; - REQUIRE_NOULTIMATE; plyr = &players[consoleplayer]; @@ -313,11 +309,10 @@ void Command_CheatGod_f(void) REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; - REQUIRE_NOULTIMATE; plyr = &players[consoleplayer]; plyr->pflags ^= PF_GODMODE; - CONS_Printf(M_GetText("Sissy Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); + CONS_Printf(M_GetText("Cheese Mode %s\n"), plyr->pflags & PF_GODMODE ? M_GetText("On") : M_GetText("Off")); G_SetGameModified(multiplayer, true); } @@ -328,7 +323,6 @@ void Command_CheatNoTarget_f(void) REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; - REQUIRE_NOULTIMATE; plyr = &players[consoleplayer]; plyr->pflags ^= PF_INVIS; @@ -382,73 +376,9 @@ void Command_Hurtme_f(void) return; } - P_DamageMobj(players[consoleplayer].mo, NULL, NULL, atoi(COM_Argv(1))); + P_DamageMobj(players[consoleplayer].mo, NULL, NULL, atoi(COM_Argv(1)), DMG_NORMAL); } -// Moves the NiGHTS player to another axis within the current mare -/*void Command_JumpToAxis_f(void) -{ - REQUIRE_DEVMODE; - REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; - - if (COM_Argc() != 2) - { - CONS_Printf(M_GetText("jumptoaxis : Jump to axis within current mare.\n")); - return; - } - - P_TransferToAxis(&players[consoleplayer], atoi(COM_Argv(1))); -} - -void Command_Charability_f(void) -{ - REQUIRE_DEVMODE; - REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; - - if (COM_Argc() < 3) - { - CONS_Printf(M_GetText("charability <1/2> : change character abilities\n")); - return; - } - - if (atoi(COM_Argv(1)) == 1) - players[consoleplayer].charability = (UINT8)atoi(COM_Argv(2)); - else if (atoi(COM_Argv(1)) == 2) - players[consoleplayer].charability2 = (UINT8)atoi(COM_Argv(2)); - else - CONS_Printf(M_GetText("charability <1/2> : change character abilities\n")); -} - -void Command_Charspeed_f(void) -{ - REQUIRE_DEVMODE; - REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; - - if (COM_Argc() < 3) - { - CONS_Printf(M_GetText("charspeed : set character speed\n")); - return; - } - - if (!strcasecmp(COM_Argv(1), "normalspeed")) - players[consoleplayer].normalspeed = atoi(COM_Argv(2))< : set character speed\n")); -}*/ - void Command_RTeleport_f(void) { fixed_t intx, inty, intz; @@ -481,7 +411,7 @@ void Command_RTeleport_f(void) else inty = 0; - ss = R_IsPointInSubsector(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT); + ss = R_PointInSubsectorOrNull(p->mo->x + intx*FRACUNIT, p->mo->y + inty*FRACUNIT); if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height) { CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n")); @@ -522,56 +452,210 @@ void Command_Teleport_f(void) REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; - if (COM_Argc() < 3 || COM_Argc() > 7) + if (COM_Argc() < 3 || COM_Argc() > 11) { - CONS_Printf(M_GetText("teleport -x -y -z : teleport to a location\n")); + CONS_Printf(M_GetText("teleport -x -y -z -ang -aim : teleport to a location\nteleport -sp : teleport to specified checkpoint\n")); return; } if (!p->mo) return; - i = COM_CheckParm("-x"); - if (i) - intx = atoi(COM_Argv(i + 1)); - else - { - CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "X"); - return; - } - - i = COM_CheckParm("-y"); - if (i) - inty = atoi(COM_Argv(i + 1)); - else - { - CONS_Alert(CONS_NOTICE, M_GetText("%s value not specified\n"), "Y"); - return; - } - - ss = R_PointInSubsector(intx*FRACUNIT, inty*FRACUNIT); - if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height) - { - CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n")); - return; - } - i = COM_CheckParm("-z"); + i = COM_CheckParm("-sp"); if (i) { - intz = atoi(COM_Argv(i + 1)); - intz <<= FRACBITS; - if (intz < ss->sector->floorheight) - intz = ss->sector->floorheight; - if (intz > ss->sector->ceilingheight - p->mo->height) - intz = ss->sector->ceilingheight - p->mo->height; + INT32 starpostnum = atoi(COM_Argv(i + 1)); // starpost number + INT32 starpostpath = atoi(COM_Argv(i + 2)); // quick, dirty way to distinguish between paths + + if (starpostnum < 0 || starpostpath < 0) + { + CONS_Alert(CONS_NOTICE, M_GetText("Negative starpost indexing is not valid.\n")); + return; + } + + if (!starpostnum) // spawnpoints... + { + mapthing_t *mt; + fixed_t offset; + + if (starpostpath >= numcoopstarts) + { + CONS_Alert(CONS_NOTICE, M_GetText("Player %d spawnpoint not found (%d max).\n"), starpostpath+1, numcoopstarts-1); + return; + } + + mt = playerstarts[starpostpath]; // Given above check, should never be NULL. + intx = mt->x<y<z<sector->ceilingheight - ss->sector->floorheight < p->mo->height) + { + CONS_Alert(CONS_NOTICE, M_GetText("Spawnpoint not in a valid location.\n")); + return; + } + + // Flagging a player's ambush will make them start on the ceiling + // Objectflip inverts + if (!!(mt->options & MTF_AMBUSH) ^ !!(mt->options & MTF_OBJECTFLIP)) + intz = ss->sector->ceilingheight - p->mo->height - offset; + else + intz = ss->sector->floorheight + offset; + + if (mt->options & MTF_OBJECTFLIP) // flip the player! + { + p->mo->eflags |= MFE_VERTICALFLIP; + p->mo->flags2 |= MF2_OBJECTFLIP; + } + else + { + p->mo->eflags &= ~MFE_VERTICALFLIP; + p->mo->flags2 &= ~MF2_OBJECTFLIP; + } + + p->mo->angle = p->drawangle = FixedAngle(mt->angle<mo->angle); + } + else // scan the thinkers to find starposts... + { + mobj_t *mo2 = NULL; + thinker_t *th; + + INT32 starpostmax = 0; + intz = starpostpath; // variable reuse - counting down for selection purposes + + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_STARPOST) + continue; + + if (mo2->health != starpostnum) + { + if (mo2->health > starpostmax) + starpostmax = mo2->health; + continue; + } + + if (intz--) + continue; + + break; + } + + if (th == &thlist[THINK_MOBJ]) + { + if (intz == starpostpath) + CONS_Alert(CONS_NOTICE, M_GetText("No starpost of position %d found (%d max).\n"), starpostnum, starpostmax); + else + CONS_Alert(CONS_NOTICE, M_GetText("Starpost of position %d, %d not found (%d, %d max).\n"), starpostnum, starpostpath, starpostmax, (starpostpath-intz)-1); + return; + } + + ss = R_PointInSubsectorOrNull(mo2->x, mo2->y); + if (!ss || ss->sector->ceilingheight - ss->sector->floorheight < p->mo->height) + { + CONS_Alert(CONS_NOTICE, M_GetText("Starpost not in a valid location.\n")); + return; + } + + intx = mo2->x; + inty = mo2->y; + intz = mo2->z; + + if (mo2->flags2 & MF2_OBJECTFLIP) // flip the player! + { + p->mo->eflags |= MFE_VERTICALFLIP; + p->mo->flags2 |= MF2_OBJECTFLIP; + } + else + { + p->mo->eflags &= ~MFE_VERTICALFLIP; + p->mo->flags2 &= ~MF2_OBJECTFLIP; + } + + p->mo->angle = p->drawangle = mo2->angle; + P_SetPlayerAngle(p, p->mo->angle); + } + + CONS_Printf(M_GetText("Teleporting to checkpoint %d, %d...\n"), starpostnum, starpostpath); } else - intz = ss->sector->floorheight; + { + i = COM_CheckParm("-nop"); // undocumented stupid addition to allow pivoting on the spot with -ang and -aim + if (i) + { + intx = p->mo->x; + inty = p->mo->y; + } + else + { + i = COM_CheckParm("-x"); + if (i) + intx = atoi(COM_Argv(i + 1))<sector->ceilingheight - ss->sector->floorheight < p->mo->height) + { + CONS_Alert(CONS_NOTICE, M_GetText("Not a valid location.\n")); + return; + } + i = COM_CheckParm("-z"); + if (i) + { + intz = atoi(COM_Argv(i + 1))<sector->floorheight) + intz = ss->sector->floorheight; + if (intz > ss->sector->ceilingheight - p->mo->height) + intz = ss->sector->ceilingheight - p->mo->height; + } + else + intz = ((p->mo->eflags & MFE_VERTICALFLIP) ? ss->sector->ceilingheight : ss->sector->floorheight); + + i = COM_CheckParm("-ang"); + if (i) + { + p->drawangle = p->mo->angle = FixedAngle(atoi(COM_Argv(i + 1))<mo->angle); + } + + i = COM_CheckParm("-aim"); + if (i) + { + angle_t aim = FixedAngle(atoi(COM_Argv(i + 1))<= ANGLE_90 && aim <= ANGLE_270) + { + CONS_Alert(CONS_NOTICE, M_GetText("Not a valid aiming angle (between +/-90).\n")); + return; + } + localaiming[0] = p->aiming = aim; + } + + CONS_Printf(M_GetText("Teleporting to %d, %d, %d...\n"), FixedInt(intx), FixedInt(inty), FixedInt(intz)); + } P_MapStart(); - if (!P_TeleportMove(p->mo, intx*FRACUNIT, inty*FRACUNIT, intz)) + if (!P_TeleportMove(p->mo, intx, inty, intz)) CONS_Alert(CONS_WARNING, M_GetText("Unable to teleport to that spot!\n")); else S_StartSound(p->mo, sfx_mixup); @@ -614,6 +698,18 @@ void Command_Weather_f(void) P_SwitchWeather(atoi(COM_Argv(1))); } +void Command_Toggletwod_f(void) +{ + player_t *p = &players[consoleplayer]; + + REQUIRE_DEVMODE; + REQUIRE_INLEVEL; + REQUIRE_SINGLEPLAYER; + + if (p->mo) + p->mo->flags2 ^= MF2_TWOD; +} + #ifdef _DEBUG // You never thought you needed this, did you? >=D // Yes, this has the specific purpose of completely screwing you up @@ -635,28 +731,13 @@ void Command_CauseCfail_f(void) players[consoleplayer].mo->y = 123311; //cfail cansuled kthxbye players[consoleplayer].mo->z = 123311; players[consoleplayer].score = 1337; - players[consoleplayer].health = 1337; + players[consoleplayer].rings = 1337; players[consoleplayer].mo->destscale = 25; P_SetThingPosition(players[consoleplayer].mo); - - // CTF consistency test - if (gametype == GT_CTF) - { - if (blueflag) { - P_RemoveMobj(blueflag); - blueflag = NULL; - } - if (redflag) - { - redflag->x = 423423; - redflag->y = 666; - redflag->z = 123311; - } - } } #endif -#if defined(HAVE_BLUA) && defined(LUA_ALLOW_BYTECODE) +#ifdef LUA_ALLOW_BYTECODE void Command_Dumplua_f(void) { if (modifiedgame) @@ -693,7 +774,6 @@ void Command_Savecheckpoint_f(void) /*void Command_Getallemeralds_f(void) { REQUIRE_SINGLEPLAYER; - REQUIRE_NOULTIMATE; REQUIRE_PANDORA; emeralds = ((EMERALD7)*2)-1; @@ -704,7 +784,6 @@ void Command_Savecheckpoint_f(void) void Command_Resetemeralds_f(void) { REQUIRE_SINGLEPLAYER; - REQUIRE_PANDORA; emeralds = 0; @@ -716,7 +795,6 @@ void Command_Devmode_f(void) #ifndef _DEBUG REQUIRE_SINGLEPLAYER; #endif - REQUIRE_NOULTIMATE; if (COM_Argc() > 1) { @@ -737,22 +815,20 @@ void Command_Devmode_f(void) G_SetGameModified(multiplayer, true); } -/*void Command_Setrings_f(void) +void Command_Setrings_f(void) { REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; - REQUIRE_NOULTIMATE; REQUIRE_PANDORA; if (COM_Argc() > 1) { // P_GivePlayerRings does value clamping - players[consoleplayer].health = players[consoleplayer].mo->health = 1; + players[consoleplayer].rings = 0; P_GivePlayerRings(&players[consoleplayer], atoi(COM_Argv(1))); - if (!G_IsSpecialStage(gamemap) || !useNightsSS) - players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings + players[consoleplayer].totalring -= atoi(COM_Argv(1)); //undo totalring addition done in P_GivePlayerRings - G_SetGameModified(multiplayer); + G_SetGameModified(multiplayer, true); } } @@ -760,50 +836,38 @@ void Command_Setlives_f(void) { REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; - REQUIRE_NOULTIMATE; REQUIRE_PANDORA; if (COM_Argc() > 1) { - // P_GivePlayerLives does value clamping - players[consoleplayer].lives = 0; - P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1))); + SINT8 lives = atoi(COM_Argv(1)); + if (lives == -1) + { + players[consoleplayer].lives = INFLIVES; // infinity! + } + else + { + // P_GivePlayerLives does value clamping + players[consoleplayer].lives = 0; + P_GivePlayerLives(&players[consoleplayer], atoi(COM_Argv(1))); + } - G_SetGameModified(multiplayer); + G_SetGameModified(multiplayer, true); } } -void Command_Setcontinues_f(void) -{ - REQUIRE_INLEVEL; - REQUIRE_SINGLEPLAYER; - REQUIRE_NOULTIMATE; - REQUIRE_PANDORA; - - if (COM_Argc() > 1) - { - INT32 numcontinues = atoi(COM_Argv(1)); - if (numcontinues > 99) - numcontinues = 99; - else if (numcontinues < 0) - numcontinues = 0; - - players[consoleplayer].continues = numcontinues; - - G_SetGameModified(multiplayer); - } -}*/ - // // OBJECTPLACE (and related variables) // static CV_PossibleValue_t op_mapthing_t[] = {{0, "MIN"}, {4095, "MAX"}, {0, NULL}}; static CV_PossibleValue_t op_speed_t[] = {{1, "MIN"}, {128, "MAX"}, {0, NULL}}; static CV_PossibleValue_t op_flags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t op_hoopflags_t[] = {{0, "MIN"}, {15, "MAX"}, {0, NULL}}; -consvar_t cv_mapthingnum = {"op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_speed = {"op_speed", "16", CV_NOTINNET, op_speed_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_opflags = {"op_flags", "0", CV_NOTINNET, op_flags_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_mapthingnum = CVAR_INIT ("op_mapthingnum", "0", CV_NOTINNET, op_mapthing_t, NULL); +consvar_t cv_speed = CVAR_INIT ("op_speed", "16", CV_NOTINNET, op_speed_t, NULL); +consvar_t cv_opflags = CVAR_INIT ("op_flags", "0", CV_NOTINNET, op_flags_t, NULL); +consvar_t cv_ophoopflags = CVAR_INIT ("op_hoopflags", "4", CV_NOTINNET, op_hoopflags_t, NULL); boolean objectplacing = false; mobjtype_t op_currentthing = 0; // For the object placement mode @@ -816,7 +880,7 @@ static mobjflag2_t op_oldflags2 = 0; static UINT32 op_oldeflags = 0; static fixed_t op_oldmomx = 0, op_oldmomy = 0, op_oldmomz = 0, op_oldheight = 0; static statenum_t op_oldstate = 0; -static UINT8 op_oldcolor = 0; +static UINT16 op_oldcolor = 0; // // Static calculation / common output help @@ -856,8 +920,8 @@ static void OP_CycleThings(INT32 amt) states[S_OBJPLACE_DUMMY].frame = states[mobjinfo[op_currentthing].spawnstate].frame; } if (players[0].mo->eflags & MFE_VERTICALFLIP) // correct z when flipped - players[0].mo->z += players[0].mo->height - mobjinfo[op_currentthing].height; - players[0].mo->height = mobjinfo[op_currentthing].height; + players[0].mo->z += players[0].mo->height - FixedMul(mobjinfo[op_currentthing].height, players[0].mo->scale); + players[0].mo->height = FixedMul(mobjinfo[op_currentthing].height, players[0].mo->scale); P_SetPlayerMobjState(players[0].mo, S_OBJPLACE_DUMMY); op_currentdoomednum = mobjinfo[op_currentthing].doomednum; @@ -869,13 +933,9 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling) if (ceiling) { -#ifdef ESLOPE // Truncate position to match where mapthing would be when spawned - // (this applies to every further P_GetZAt call as well) - fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight; -#else - fixed_t cheight = sec->ceilingheight; -#endif + // (this applies to every further P_GetSlopeZAt call as well) + fixed_t cheight = P_GetSectorCeilingZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000); if (((cheight - player->mo->z - player->mo->height)>>FRACBITS) >= (1 << (16-ZSHIFT))) { @@ -886,11 +946,7 @@ static boolean OP_HeightOkay(player_t *player, UINT8 ceiling) } else { -#ifdef ESLOPE - fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight; -#else - fixed_t fheight = sec->floorheight; -#endif + fixed_t fheight = P_GetSectorFloorZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000); if (((player->mo->z - fheight)>>FRACBITS) >= (1 << (16-ZSHIFT))) { CONS_Printf(M_GetText("Sorry, you're too %s to place this object (max: %d %s).\n"), M_GetText("high"), @@ -906,9 +962,7 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c mapthing_t *mt = mapthings; sector_t *sec = player->mo->subsector->sector; -#ifdef HAVE_BLUA LUA_InvalidateMapthings(); -#endif mapthings = Z_Realloc(mapthings, ++nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); @@ -919,15 +973,16 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c thinker_t *th; mobj_t *mo; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo = (mobj_t *)th; // get offset from mt, which points to old mapthings, then add new location - if (mo->spawnpoint) - mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; + if (!mo->spawnpoint) + continue; + mo->spawnpoint = (mo->spawnpoint - mt) + mapthings; } } @@ -938,26 +993,22 @@ static mapthing_t *OP_CreateNewMapThing(player_t *player, UINT16 type, boolean c mt->y = (INT16)(player->mo->y>>FRACBITS); if (ceiling) { -#ifdef ESLOPE - fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->ceilingheight; -#else - fixed_t cheight = sec->ceilingheight; -#endif - mt->options = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS); + fixed_t cheight = P_GetSectorCeilingZAt(sec, mt->x << FRACBITS, mt->y << FRACBITS); + mt->z = (UINT16)((cheight - player->mo->z - player->mo->height)>>FRACBITS); } else { -#ifdef ESLOPE - fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : sec->floorheight; -#else - fixed_t fheight = sec->floorheight; -#endif - mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS); + fixed_t fheight = P_GetSectorFloorZAt(sec, mt->x << FRACBITS, mt->y << FRACBITS); + mt->z = (UINT16)((player->mo->z - fheight)>>FRACBITS); } - mt->options <<= ZSHIFT; mt->angle = (INT16)(FixedInt(AngleFixed(player->mo->angle))); - mt->options |= (UINT16)cv_opflags.value; + mt->options = (mt->z << ZSHIFT) | (UINT16)cv_opflags.value; + mt->scale = player->mo->scale; + mt->tag = 0; + memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); + memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); + mt->pitch = mt->roll = 0; return mt; } @@ -969,9 +1020,6 @@ boolean OP_FreezeObjectplace(void) if (!objectplacing) return false; - if ((maptol & TOL_NIGHTS) && (players[consoleplayer].pflags & PF_NIGHTSMODE)) - return false; - return true; } @@ -981,135 +1029,6 @@ void OP_ResetObjectplace(void) op_currentthing = 0; } -// -// Main meat of objectplace: handling functions -// -void OP_NightsObjectplace(player_t *player) -{ - ticcmd_t *cmd = &player->cmd; - mapthing_t *mt; - - player->nightstime = 3*TICRATE; - player->drillmeter = TICRATE; - - if (player->pflags & PF_ATTACKDOWN) - { - // Are ANY objectplace buttons pressed? If no, remove flag. - if (!(cmd->buttons & (BT_ATTACK|BT_ACCELERATE|BT_BRAKE|BT_FORWARD|BT_BACKWARD))) - player->pflags &= ~PF_ATTACKDOWN; - - // Do nothing. - return; - } - - // This places a hoop! - if (cmd->buttons & BT_ATTACK) - { - UINT16 angle = (UINT16)(player->anotherflyangle % 360); - INT16 temp = (INT16)FixedInt(AngleFixed(player->mo->angle)); // Traditional 2D Angle - sector_t *sec = player->mo->subsector->sector; -#ifdef ESLOPE - fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight; -#else - fixed_t fheight = sec->floorheight; -#endif - - - player->pflags |= PF_ATTACKDOWN; - - mt = OP_CreateNewMapThing(player, 1705, false); - - // Tilt - mt->angle = (INT16)FixedInt(FixedDiv(angle*FRACUNIT, 360*(FRACUNIT/256))); - - if (player->anotherflyangle < 90 || player->anotherflyangle > 270) - temp -= 90; - else - temp += 90; - temp %= 360; - - mt->options = (UINT16)((player->mo->z - fheight)>>FRACBITS); - mt->angle = (INT16)(mt->angle+(INT16)((FixedInt(FixedDiv(temp*FRACUNIT, 360*(FRACUNIT/256))))<<8)); - - P_SpawnHoopsAndRings(mt); - } - - // This places a bumper! - /*if (cmd->buttons & BT_SPECTATE) - { - player->pflags |= PF_ATTACKDOWN; - if (!OP_HeightOkay(player, false)) - return; - - mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSBUMPER].doomednum, false); - P_SpawnMapThing(mt); - }*/ - - // This places a ring! - if (cmd->buttons & BT_BACKWARD) - { - player->pflags |= PF_ATTACKDOWN; - if (!OP_HeightOkay(player, false)) - return; - - mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_RING].doomednum, false); - P_SpawnHoopsAndRings(mt); - } - - // This places a wing item! - if (cmd->buttons & BT_FORWARD) - { - player->pflags |= PF_ATTACKDOWN; - if (!OP_HeightOkay(player, false)) - return; - - mt = OP_CreateNewMapThing(player, (UINT16)mobjinfo[MT_NIGHTSWING].doomednum, false); - P_SpawnHoopsAndRings(mt); - } - - // This places a custom object as defined in the console cv_mapthingnum. - if (cmd->buttons & BT_BRAKE) - { - UINT16 angle; - - player->pflags |= PF_ATTACKDOWN; - if (!cv_mapthingnum.value) - { - CONS_Alert(CONS_WARNING, "Set op_mapthingnum first!\n"); - return; - } - if (!OP_HeightOkay(player, false)) - return; - - if (player->mo->target->flags2 & MF2_AMBUSH) - angle = (UINT16)player->anotherflyangle; - else - { - angle = (UINT16)((360-player->anotherflyangle) % 360); - if (angle > 90 && angle < 270) - { - angle += 180; - angle %= 360; - } - } - - mt = OP_CreateNewMapThing(player, (UINT16)cv_mapthingnum.value, false); - mt->angle = angle; - - if (mt->type == 300 // Ring - || mt->type == 308 || mt->type == 309 // Team Rings - || mt->type == 1706 // Nights Wing - || (mt->type >= 600 && mt->type <= 609) // Placement patterns - || mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops - || mt->type == 1800) // Mario Coin - { - P_SpawnHoopsAndRings(mt); - } - else - P_SpawnMapThing(mt); - } -} - // // OP_ObjectplaceMovement // @@ -1119,30 +1038,23 @@ void OP_ObjectplaceMovement(player_t *player) { ticcmd_t *cmd = &player->cmd; - if (!player->climbing && (netgame || !cv_analog.value || (player->pflags & PF_SPINNING))) - player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */); + player->drawangle = player->mo->angle = player->angleturn; ticruned++; - if (!(cmd->angleturn & TICCMD_RECEIVED)) + if (!(cmd->flags & TICCMD_RECEIVED)) ticmiss++; if (cmd->buttons & BT_ACCELERATE) - player->mo->z += FRACUNIT*cv_speed.value; + player->mo->z += player->mo->scale * cv_speed.value; else if (cmd->buttons & BT_BRAKE) - player->mo->z -= FRACUNIT*cv_speed.value; + player->mo->z -= player->mo->scale * cv_speed.value; if (cmd->forwardmove != 0) { - P_Thrust(player->mo, player->mo->angle, (cmd->forwardmove*FRACUNIT/MAXPLMOVE)*cv_speed.value); + P_Thrust(player->mo, player->mo->angle, (cmd->forwardmove*player->mo->scale/MAXPLMOVE)*cv_speed.value); P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z); player->mo->momx = player->mo->momy = 0; } - /*if (cmd->sidemove != 0) -- was disabled in practice anyways, since sidemove was suppressed - { - P_Thrust(player->mo, player->mo->angle-ANGLE_90, (cmd->sidemove*FRACUNIT/MAXPLMOVE)*cv_speed.value); - P_TeleportMove(player->mo, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, player->mo->z); - player->mo->momx = player->mo->momy = 0; - }*/ if (player->mo->z > player->mo->ceilingz - player->mo->height) player->mo->z = player->mo->ceilingz - player->mo->height; @@ -1155,8 +1067,8 @@ void OP_ObjectplaceMovement(player_t *player) player->mo->eflags &= ~MFE_VERTICALFLIP; // make sure viewz follows player if in 1st person mode - //player->deltaviewheight = 0; - player->viewheight = FixedMul(32 << FRACBITS, player->mo->scale); + player->deltaviewheight = 0; + player->viewheight = P_GetPlayerViewHeight(player); if (player->mo->eflags & MFE_VERTICALFLIP) player->viewz = player->mo->z + player->mo->height - player->viewheight; else @@ -1169,26 +1081,19 @@ void OP_ObjectplaceMovement(player_t *player) if (!!(mobjinfo[op_currentthing].flags & MF_SPAWNCEILING) ^ !!(cv_opflags.value & MTF_OBJECTFLIP)) { -#ifdef ESLOPE - fixed_t cheight = sec->c_slope ? P_GetZAt(sec->c_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->ceilingheight; -#else - fixed_t cheight = sec->ceilingheight; -#endif + fixed_t cheight = P_GetSectorCeilingZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000); op_displayflags = (UINT16)((cheight - player->mo->z - mobjinfo[op_currentthing].height)>>FRACBITS); } else { -#ifdef ESLOPE - fixed_t fheight = sec->f_slope ? P_GetZAt(sec->f_slope, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000) : sec->floorheight; -#else - fixed_t fheight = sec->floorheight; -#endif + fixed_t fheight = P_GetSectorFloorZAt(sec, player->mo->x & 0xFFFF0000, player->mo->y & 0xFFFF0000); op_displayflags = (UINT16)((player->mo->z - fheight)>>FRACBITS); } op_displayflags <<= ZSHIFT; op_displayflags |= (UINT16)cv_opflags.value; } + if (player->pflags & PF_ATTACKDOWN) { // Are ANY objectplace buttons pressed? If no, remove flag. @@ -1240,19 +1145,14 @@ void OP_ObjectplaceMovement(player_t *player) return; mt = OP_CreateNewMapThing(player, (UINT16)spawnthing, ceiling); - if (mt->type == 300 // Ring - || mt->type == 308 || mt->type == 309 // Team Rings - || mt->type == 1706 // Nights Wing - || (mt->type >= 600 && mt->type <= 609) // Placement patterns - || mt->type == 1705 || mt->type == 1713 // NiGHTS Hoops - || mt->type == 1800) // Mario Coin - { - P_SpawnHoopsAndRings(mt); - } + if (mt->type >= 600 && mt->type <= 609) // Placement patterns + P_SpawnItemPattern(mt, false); + else if (mt->type == 1705 || mt->type == 1713) // NiGHTS Hoops + P_SpawnHoop(mt); else P_SpawnMapThing(mt); - CONS_Printf(M_GetText("Placed object type %d at %d, %d, %d, %d\n"), mt->type, mt->x, mt->y, mt->options>>ZSHIFT, mt->angle); + CONS_Printf(M_GetText("Placed object type %d at %d, %d, %d, %d\n"), mt->type, mt->x, mt->y, mt->z, mt->angle); } } @@ -1272,67 +1172,76 @@ void Command_ObjectPlace_f(void) { REQUIRE_INLEVEL; REQUIRE_SINGLEPLAYER; - REQUIRE_NOULTIMATE; G_SetGameModified(multiplayer, true); // Entering objectplace? - if (!objectplacing) + if (!objectplacing || COM_Argc() > 1) { - objectplacing = true; - - if ((players[0].pflags & PF_NIGHTSMODE)) - return; - - if (!COM_CheckParm("-silent")) + if (!objectplacing) { - HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE); - HU_SetCEchoDuration(10); - HU_DoCEcho(va(M_GetText( - "\\\\\\\\\\\\\\\\\\\\\\\\\x82" - " Objectplace Controls: \x80\\\\" - " Drift: Cycle mapthings\\" - "Accelerate: Float up \\" - " Brake: Float down \\" - " Item: Place object \\"))); + objectplacing = true; + + if (!COM_CheckParm("-silent")) + { + HU_SetCEchoFlags(V_RETURN8|V_MONOSPACE); + HU_SetCEchoDuration(10); + HU_DoCEcho(va(M_GetText( + "\\\\\\\\\\\\\\\\\\\\\\\\\x82" + " Objectplace Controls: \x80\\\\" + "Weapon Next/Prev: Cycle mapthings\\" + " Jump: Float up \\" + " Spin: Float down \\" + " Fire Ring: Place object \\"))); + } + + // Save all the player's data. + op_oldflags1 = players[0].mo->flags; + op_oldflags2 = players[0].mo->flags2; + op_oldeflags = players[0].mo->eflags; + op_oldpflags = players[0].pflags; + op_oldmomx = players[0].mo->momx; + op_oldmomy = players[0].mo->momy; + op_oldmomz = players[0].mo->momz; + op_oldheight = players[0].mo->height; + op_oldstate = S_KART_STILL; + op_oldcolor = players[0].mo->color; // save color too in case of super/fireflower + + // Remove ALL flags and motion. + P_UnsetThingPosition(players[0].mo); + players[0].pflags = 0; + players[0].mo->flags2 = 0; + players[0].mo->eflags = 0; + players[0].mo->flags = (MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP); + players[0].mo->momx = players[0].mo->momy = players[0].mo->momz = 0; + P_SetThingPosition(players[0].mo); + + // Take away color so things display properly + players[0].mo->color = 0; + + // Like the classics, recover from death by entering objectplace + if (players[0].mo->health <= 0) + { + players[0].mo->health = 1; + players[0].deadtimer = 0; + op_oldflags1 = mobjinfo[MT_PLAYER].flags; + ++players[0].lives; + players[0].playerstate = PST_LIVE; + P_RestoreMusic(&players[0]); + } + else + op_oldstate = (statenum_t)(players[0].mo->state-states); } - // Save all the player's data. - op_oldflags1 = players[0].mo->flags; - op_oldflags2 = players[0].mo->flags2; - op_oldeflags = players[0].mo->eflags; - op_oldpflags = players[0].pflags; - op_oldmomx = players[0].mo->momx; - op_oldmomy = players[0].mo->momy; - op_oldmomz = players[0].mo->momz; - op_oldheight = players[0].mo->height; - op_oldstate = S_KART_STILL1; // SRB2kart - was S_PLAY_STND - op_oldcolor = players[0].mo->color; // save color too in case of super/fireflower - - // Remove ALL flags and motion. - P_UnsetThingPosition(players[0].mo); - players[0].pflags = 0; - players[0].mo->flags2 = 0; - players[0].mo->eflags = 0; - players[0].mo->flags = (MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP); - players[0].mo->momx = players[0].mo->momy = players[0].mo->momz = 0; - P_SetThingPosition(players[0].mo); - - // Take away color so things display properly - players[0].mo->color = 0; - - // Like the classics, recover from death by entering objectplace - if (players[0].mo->health <= 0) + if (COM_Argc() > 1) { - players[0].mo->health = players[0].health = 1; - players[0].deadtimer = 0; - op_oldflags1 = mobjinfo[MT_PLAYER].flags; - ++players[0].lives; - players[0].playerstate = PST_LIVE; - P_RestoreMusic(&players[0]); + UINT16 mapthingnum = atoi(COM_Argv(1)); + mobjtype_t type = P_GetMobjtype(mapthingnum); + if (type == MT_UNKNOWN) + CONS_Printf(M_GetText("No mobj type delegated to thing type %d.\n"), mapthingnum); + else + op_currentthing = type; } - else - op_oldstate = (statenum_t)(players[0].mo->state-states); // If no thing set, then cycle a little if (!op_currentthing) @@ -1340,8 +1249,8 @@ void Command_ObjectPlace_f(void) op_currentthing = 1; OP_CycleThings(1); } - else // Cycle things sets this for the former. - players[0].mo->height = mobjinfo[op_currentthing].height; + else + OP_CycleThings(0); // sets all necessary height values without cycling op_currentthing P_SetPlayerMobjState(players[0].mo, S_OBJPLACE_DUMMY); } @@ -1350,9 +1259,8 @@ void Command_ObjectPlace_f(void) { objectplacing = false; - // Don't touch the NiGHTS Objectplace stuff. - // ... or if the mo mysteriously vanished. - if (!players[0].mo || (players[0].pflags & PF_NIGHTSMODE)) + // Don't touch if the mo mysteriously vanished. + if (!players[0].mo) return; // If still in dummy state, get out of it. @@ -1375,7 +1283,6 @@ void Command_ObjectPlace_f(void) players[0].mo->color = op_oldcolor; // This is necessary for recovery of dying players. - if (players[0].powers[pw_flashing] >= K_GetKartFlashing(&players[0])) - players[0].powers[pw_flashing] = K_GetKartFlashing(&players[0]) - 1; + players[0].powers[pw_flashing] = K_GetKartFlashing(&players[0]); } } diff --git a/src/m_cheat.h b/src/m_cheat.h index 95c0060dd..de34d8a41 100644 --- a/src/m_cheat.h +++ b/src/m_cheat.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,7 +28,7 @@ void cht_Init(void); void Command_ObjectPlace_f(void); void Command_Writethings_f(void); -extern consvar_t cv_opflags, cv_mapthingnum, cv_speed; +extern consvar_t cv_opflags, cv_ophoopflags, cv_mapthingnum, cv_speed; //extern consvar_t cv_snapto, cv_grid; extern boolean objectplacing; @@ -38,7 +38,6 @@ extern UINT32 op_displayflags; boolean OP_FreezeObjectplace(void); void OP_ResetObjectplace(void); -void OP_NightsObjectplace(player_t *player); void OP_ObjectplaceMovement(player_t *player); // @@ -48,26 +47,21 @@ void Command_CheatNoClip_f(void); void Command_CheatGod_f(void); void Command_CheatNoTarget_f(void); void Command_Savecheckpoint_f(void); -/*void Command_Getallemeralds_f(void); -void Command_Resetemeralds_f(void); void Command_Setrings_f(void); void Command_Setlives_f(void); -void Command_Setcontinues_f(void);*/ void Command_Devmode_f(void); void Command_Scale_f(void); void Command_Gravflip_f(void); void Command_Hurtme_f(void); -/*void Command_JumpToAxis_f(void); -void Command_Charability_f(void); -void Command_Charspeed_f(void);*/ void Command_Teleport_f(void); void Command_RTeleport_f(void); void Command_Skynum_f(void); void Command_Weather_f(void); +void Command_Toggletwod_f(void); #ifdef _DEBUG void Command_CauseCfail_f(void); #endif -#if defined(HAVE_BLUA) && defined(LUA_ALLOW_BYTECODE) +#ifdef LUA_ALLOW_BYTECODE void Command_Dumplua_f(void); #endif diff --git a/src/m_cond.c b/src/m_cond.c index 6ed684ea9..8ffe3c378 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2012-2016 by Matthew "Inuyasha" Walsh. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,9 +18,8 @@ #include "v_video.h" // video flags #include "g_game.h" // record info -#include "r_things.h" // numskins -//#include "r_draw.h" // R_GetColorByName -#include "k_color.h" // K_GetKartColorByName +#include "r_skins.h" // numskins +#include "r_draw.h" // R_GetColorByName #include "k_pwrlv.h" // Map triggers for linedef executors @@ -30,201 +29,18 @@ UINT32 unlocktriggers; // The meat of this system lies in condition sets conditionset_t conditionSets[MAXCONDITIONSETS]; -// Default Emblem locations -emblem_t emblemlocations[MAXEMBLEMS] = -{ - // GOLD DEV MEDALS - // These values are directly lifted from the Champion ghost, through the power of hex editing! - {ET_TIME, 0,0,0, 1, 'A', SKINCOLOR_GOLD, 3021, "", 0}, // Green Hills Zone - 1'26"31 - {ET_TIME, 0,0,0, 2, 'A', SKINCOLOR_GOLD, 4466, "", 0}, // Dark Race - 2'07"60 - {ET_TIME, 0,0,0, 3, 'A', SKINCOLOR_GOLD, 4337, "", 0}, // Northern District Zone - 2'03"91 - {ET_TIME, 0,0,0, 4, 'A', SKINCOLOR_GOLD, 3452, "", 0}, // Darkvile Garden Zone - 1'38"62 - {ET_TIME, 0,0,0, 5, 'A', SKINCOLOR_GOLD, 3525, "", 0}, // Daytona Speedway Zone - 1'40"71 - {ET_TIME, 0,0,0, 6, 'A', SKINCOLOR_GOLD, 4047, "", 0}, // Egg Zeppelin Zone - 1'55"62 - {ET_TIME, 0,0,0, 7, 'A', SKINCOLOR_GOLD, 4041, "", 0}, // Sonic Speedway Zone - 1'55"45 - {ET_TIME, 0,0,0, 8, 'A', SKINCOLOR_GOLD, 3281, "", 0}, // Hill Top Zone - 1'33"74 - {ET_TIME, 0,0,0, 9, 'A', SKINCOLOR_GOLD, 4764, "", 0}, // Misty Maze Zone - 2'16"11 - {ET_TIME, 0,0,0, 10, 'A', SKINCOLOR_GOLD, 4378, "", 0}, // Grand Metropolis - 2'05"08 - {ET_TIME, 0,0,0, 11, 'A', SKINCOLOR_GOLD, 3678, "", 0}, // Sunbeam Paradise Zone - 1'45"08 - {ET_TIME, 0,0,0, 12, 'A', SKINCOLOR_GOLD, 3928, "", 0}, // Diamond Square Zone - 1'52"22 - {ET_TIME, 0,0,0, 13, 'A', SKINCOLOR_GOLD, 3846, "", 0}, // Midnight Meadow Zone - 1'49"88 - {ET_TIME, 0,0,0, 14, 'A', SKINCOLOR_GOLD, 3278, "", 0}, // Twinkle Cart - 1'33"65 - {ET_TIME, 0,0,0, 15, 'A', SKINCOLOR_GOLD, 3591, "", 0}, // Pleasure Castle - 1'42"60 - {ET_TIME, 0,0,0, 16, 'A', SKINCOLOR_GOLD, 5187, "", 0}, // Paradise Hill Zone - 2'28"20 - {ET_TIME, 0,0,0, 17, 'A', SKINCOLOR_GOLD, 4976, "", 0}, // Sub-Zero Peak Zone - 2'22"17 - {ET_TIME, 0,0,0, 18, 'A', SKINCOLOR_GOLD, 3696, "", 0}, // Sapphire Coast Zone - 1'45"60 - {ET_TIME, 0,0,0, 19, 'A', SKINCOLOR_GOLD, 4931, "", 0}, // Sand Valley Zone - 2'20"88 - {ET_TIME, 0,0,0, 20, 'A', SKINCOLOR_GOLD, 4220, "", 0}, // Megablock Castle Zone - 2'00"57 - {ET_TIME, 0,0,0, 21, 'A', SKINCOLOR_GOLD, 4053, "", 0}, // Canyon Rush Zone - 1'55"80 - {ET_TIME, 0,0,0, 22, 'A', SKINCOLOR_GOLD, 3613, "", 0}, // Casino Resort Zone - 1'43"22 - {ET_TIME, 0,0,0, 23, 'A', SKINCOLOR_GOLD, 4385, "", 0}, // Silvercloud Island Zone - 2'05"28 - {ET_TIME, 0,0,0, 24, 'A', SKINCOLOR_GOLD, 5321, "", 0}, // Blue Mountain Zone - 2'32"02 - {ET_TIME, 0,0,0, 25, 'A', SKINCOLOR_GOLD, 4476, "", 0}, // Petroleum Refinery Zone - 2'07"88 - {ET_TIME, 0,0,0, 26, 'A', SKINCOLOR_GOLD, 3295, "", 0}, // Desert Palace Zone - 1'34"14 - {ET_TIME, 0,0,0, 27, 'A', SKINCOLOR_GOLD, 4765, "", 0}, // Aurora Atoll Zone - 2'16"14 - {ET_TIME, 0,0,0, 28, 'A', SKINCOLOR_GOLD, 4670, "", 0}, // Barren Badlands Zone - 2'13"42 - {ET_TIME, 0,0,0, 29, 'A', SKINCOLOR_GOLD, 5888, "", 0}, // Red Barrage Area - 2'48"22 - {ET_TIME, 0,0,0, 30, 'A', SKINCOLOR_GOLD, 4047, "", 0}, // Midnight Channel - 1'55"62 - {ET_TIME, 0,0,0, 31, 'A', SKINCOLOR_GOLD, 4944, "", 0}, // Vanilla Hotel Zone - 2'21"25 - {ET_TIME, 0,0,0, 32, 'A', SKINCOLOR_GOLD, 4638, "", 0}, // Toxic Palace Zone - 2'12"51 - {ET_TIME, 0,0,0, 33, 'A', SKINCOLOR_GOLD, 4036, "", 0}, // Ancient Tomb Zone - 1'55"31 - {ET_TIME, 0,0,0, 34, 'A', SKINCOLOR_GOLD, 3595, "", 0}, // Cloud Cradle Zone K - 1'42"71 - {ET_TIME, 0,0,0, 35, 'A', SKINCOLOR_GOLD, 4705, "", 0}, // Volcanic Valley Zone - 2'14"42 - {ET_TIME, 0,0,0, 36, 'A', SKINCOLOR_GOLD, 3314, "", 0}, // Kodachrome Void Zone - 1'34"68 - {ET_TIME, 0,0,0, 37, 'A', SKINCOLOR_GOLD, 3501, "", 0}, // Boiling Bedrock Zone - 1'40"02 - {ET_TIME, 0,0,0, 38, 'A', SKINCOLOR_GOLD, 4920, "", 0}, // Egg Quarters - 2'20"57 - {ET_TIME, 0,0,0, 39, 'A', SKINCOLOR_GOLD, 4318, "", 0}, // Virtual Highway Zone - 2'03"37 - {ET_TIME, 0,0,0, 40, 'A', SKINCOLOR_GOLD, 3550, "", 0}, // Eggman's Nightclub Zone - 1'41"42 - {ET_TIME, 0,0,0, 41, 'A', SKINCOLOR_GOLD, 2572, "", 0}, // KKR Ganbare Dochu 2 - 1'13"48 - {ET_TIME, 0,0,0, 42, 'A', SKINCOLOR_GOLD, 3091, "", 0}, // CK Chao Circuit 1 - 1'28"31 - {ET_TIME, 0,0,0, 43, 'A', SKINCOLOR_GOLD, 3454, "", 0}, // CK Chao Circuit 2 - 1'38"68 - {ET_TIME, 0,0,0, 44, 'A', SKINCOLOR_GOLD, 2958, "", 0}, // CK Cloud Tops 2 - 1'24"51 - {ET_TIME, 0,0,0, 45, 'A', SKINCOLOR_GOLD, 3693, "", 0}, // CK Regal Raceway - 1'45"51 - {ET_TIME, 0,0,0, 46, 'A', SKINCOLOR_GOLD, 3437, "", 0}, // SD2 Balloon Panic - 1'38"20 - {ET_TIME, 0,0,0, 47, 'A', SKINCOLOR_GOLD, 3238, "", 0}, // SM Dimension Heist - 1'32"51 - {ET_TIME, 0,0,0, 48, 'A', SKINCOLOR_GOLD, 3063, "", 0}, // MKSC Sky Garden - 1'27"51 - {ET_TIME, 0,0,0, 49, 'A', SKINCOLOR_GOLD, 2980, "", 0}, // MKDS Peach Gardens - 1'25"14 - {ET_TIME, 0,0,0, 50, 'A', SKINCOLOR_GOLD, 2914, "", 0}, // MKSC Rainbow Road - 1'23"25 - {ET_TIME, 0,0,0, 51, 'A', SKINCOLOR_GOLD, 3003, "", 0}, // SMK Donut Plains 1 - 1'25"80 - {ET_TIME, 0,0,0, 52, 'A', SKINCOLOR_GOLD, 2930, "", 0}, // SMK Mario Circuit 2 - 1'23"71 - {ET_TIME, 0,0,0, 53, 'A', SKINCOLOR_GOLD, 2389, "", 0}, // SMK Ghost Valley 2 - 1'08"25 - {ET_TIME, 0,0,0, 54, 'A', SKINCOLOR_GOLD, 4292, "", 0}, // SMK Bowser Castle 3 - 2'02"62 - {ET_TIME, 0,0,0, 55, 'A', SKINCOLOR_GOLD, 2346, "", 0}, // SMK Vanilla Lake 2 - 1'07"02 +// Emblem locations +emblem_t emblemlocations[MAXEMBLEMS]; - // SILVER NORMAL MEDALS - // The general "guideline" of how good we want a player to be at a map. - {ET_TIME, 0,0,0, 1, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Green Hills Zone - 1'50"00 - {ET_TIME, 0,0,0, 2, 'B', SKINCOLOR_GREY, 160*TICRATE, "", 0}, // Dark Race - 2'40"00 - {ET_TIME, 0,0,0, 3, 'B', SKINCOLOR_GREY, 160*TICRATE, "", 0}, // Northern District Zone - 2'40"00 - {ET_TIME, 0,0,0, 4, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Darkvile Garden Zone - 2'00"00 - {ET_TIME, 0,0,0, 5, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Daytona Speedway Zone - 2'10"00 - {ET_TIME, 0,0,0, 6, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Egg Zeppelin Zone - 2'20"00 - {ET_TIME, 0,0,0, 7, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Sonic Speedway Zone - 2'20"00 - {ET_TIME, 0,0,0, 8, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Hill Top Zone - 1'50"00 - {ET_TIME, 0,0,0, 9, 'B', SKINCOLOR_GREY, 170*TICRATE, "", 0}, // Misty Maze Zone - 2'50"00 - {ET_TIME, 0,0,0, 10, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Grand Metropolis - 2'20"00 - {ET_TIME, 0,0,0, 11, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Sunbeam Paradise Zone - 2'00"00 - {ET_TIME, 0,0,0, 12, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Diamond Square Zone - 2'10"00 - {ET_TIME, 0,0,0, 13, 'B', SKINCOLOR_GREY, 135*TICRATE, "", 0}, // Midnight Meadow Zone - 2'15"00 - {ET_TIME, 0,0,0, 14, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Twinkle Cart - 2'00"00 - {ET_TIME, 0,0,0, 15, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Pleasure Castle - 2'00"00 - {ET_TIME, 0,0,0, 16, 'B', SKINCOLOR_GREY, 160*TICRATE, "", 0}, // Paradise Hill Zone - 2'40"00 - {ET_TIME, 0,0,0, 17, 'B', SKINCOLOR_GREY, 170*TICRATE, "", 0}, // Sub-Zero Peak Zone - 2'50"00 - {ET_TIME, 0,0,0, 18, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Sapphire Coast Zone - 2'10"00 - {ET_TIME, 0,0,0, 19, 'B', SKINCOLOR_GREY, 170*TICRATE, "", 0}, // Sand Valley Zone - 2'50"00 - {ET_TIME, 0,0,0, 20, 'B', SKINCOLOR_GREY, 145*TICRATE, "", 0}, // Megablock Castle Zone - 2'25"00 - {ET_TIME, 0,0,0, 21, 'B', SKINCOLOR_GREY, 140*TICRATE, "", 0}, // Canyon Rush Zone - 2'20"00 - {ET_TIME, 0,0,0, 22, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Casino Resort Zone - 2'00"00 - {ET_TIME, 0,0,0, 23, 'B', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // Silvercloud Island Zone - 2'30"00 - {ET_TIME, 0,0,0, 24, 'B', SKINCOLOR_GREY, 170*TICRATE, "", 0}, // Blue Mountain Zone - 2'50"00 - {ET_TIME, 0,0,0, 25, 'B', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // Petroleum Refinery Zone - 2'30"00 - {ET_TIME, 0,0,0, 26, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Desert Palace Zone - 2'00"00 - {ET_TIME, 0,0,0, 27, 'B', SKINCOLOR_GREY, 160*TICRATE, "", 0}, // Aurora Atoll Zone - 2'40"00 - {ET_TIME, 0,0,0, 28, 'B', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // Barren Badlands Zone - 2'30"00 - {ET_TIME, 0,0,0, 29, 'B', SKINCOLOR_GREY, 170*TICRATE, "", 0}, // Red Barrage Area - 2'50"00 - {ET_TIME, 0,0,0, 30, 'B', SKINCOLOR_GREY, 135*TICRATE, "", 0}, // Midnight Channel - 2'15"00 - {ET_TIME, 0,0,0, 31, 'B', SKINCOLOR_GREY, 160*TICRATE, "", 0}, // Vanilla Hotel Zone - 2'40"00 - {ET_TIME, 0,0,0, 32, 'B', SKINCOLOR_GREY, 160*TICRATE, "", 0}, // Toxic Palace Zone - 2'40"00 - {ET_TIME, 0,0,0, 33, 'B', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // Ancient Tomb Zone - 2'30"00 - {ET_TIME, 0,0,0, 34, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Cloud Cradle Zone K - 2'00"00 - {ET_TIME, 0,0,0, 35, 'B', SKINCOLOR_GREY, 165*TICRATE, "", 0}, // Volcanic Valley Zone - 2'45"00 - {ET_TIME, 0,0,0, 36, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // Kodachrome Void Zone - 1'50"00 - {ET_TIME, 0,0,0, 37, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // Boiling Bedrock Zone - 2'10"00 - {ET_TIME, 0,0,0, 38, 'B', SKINCOLOR_GREY, 165*TICRATE, "", 0}, // Egg Quarters - 2'45"00 - {ET_TIME, 0,0,0, 39, 'B', SKINCOLOR_GREY, 145*TICRATE, "", 0}, // Virtual Highway Zone - 2'25"00 - {ET_TIME, 0,0,0, 40, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // Eggman's Nightclub Zone - 2'00"00 - {ET_TIME, 0,0,0, 41, 'B', SKINCOLOR_GREY, 100*TICRATE, "", 0}, // KKR Ganbare Dochu 2 - 1'40"00 - {ET_TIME, 0,0,0, 42, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // CK Chao Circuit 1 - 1'50"00 - {ET_TIME, 0,0,0, 43, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // CK Chao Circuit 2 - 2'00"00 - {ET_TIME, 0,0,0, 44, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // CK Cloud Tops 2 - 1'50"00 - {ET_TIME, 0,0,0, 45, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // CK Regal Raceway - 2'10"00 - {ET_TIME, 0,0,0, 46, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // SD2 Balloon Panic - 1'50"00 - {ET_TIME, 0,0,0, 47, 'B', SKINCOLOR_GREY, 130*TICRATE, "", 0}, // SM Dimension Heist - 2'10"00 - {ET_TIME, 0,0,0, 48, 'B', SKINCOLOR_GREY, 110*TICRATE, "", 0}, // MKSC Sky Garden - 1'50"00 - {ET_TIME, 0,0,0, 49, 'B', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // MKDS Peach Gardens - 1'45"00 - {ET_TIME, 0,0,0, 50, 'B', SKINCOLOR_GREY, 120*TICRATE, "", 0}, // MKSC Rainbow Road - 2'00"00 - {ET_TIME, 0,0,0, 51, 'B', SKINCOLOR_GREY, 100*TICRATE, "", 0}, // SMK Donut Plains 1 - 1'40"00 - {ET_TIME, 0,0,0, 52, 'B', SKINCOLOR_GREY, 105*TICRATE, "", 0}, // SMK Mario Circuit 2 - 1'45"00 - {ET_TIME, 0,0,0, 53, 'B', SKINCOLOR_GREY, 90*TICRATE, "", 0}, // SMK Ghost Valley 2 - 1'30"00 - {ET_TIME, 0,0,0, 54, 'B', SKINCOLOR_GREY, 150*TICRATE, "", 0}, // SMK Bowser Castle 3 - 2'30"00 - {ET_TIME, 0,0,0, 55, 'B', SKINCOLOR_GREY, 90*TICRATE, "", 0} // SMK Vanilla Lake 2 - 1'30"00 -}; +// Extra emblems +extraemblem_t extraemblems[MAXEXTRAEMBLEMS]; -// Default Extra Emblems -extraemblem_t extraemblems[MAXEXTRAEMBLEMS] = -{ - {"Novice", "Play 100 matches", 10, 'C', SKINCOLOR_RED, 0}, - {"Standard", "Play 250 matches", 11, 'C', SKINCOLOR_RED, 0}, - {"Expert", "Play 500 matches", 12, 'C', SKINCOLOR_RED, 0}, - {"Master", "Play 750 matches", 13, 'C', SKINCOLOR_RED, 0}, - {"Nightmare", "Play 1000 matches", 14, 'C', SKINCOLOR_RED, 0}, -}; +// Unlockables +unlockable_t unlockables[MAXUNLOCKABLES]; -// Default Unlockables -unlockable_t unlockables[MAXUNLOCKABLES] = -{ - // Name, Objective, Showing Conditionset, ConditionSet, Unlock Type, Variable, NoCecho, NoChecklist - /* 01 */ {"Egg Cup", "", -1, 1, SECRET_NONE, 0, false, false, 0}, - /* 02 */ {"Chao Cup", "", -1, 2, SECRET_NONE, 0, false, false, 0}, - /* 03 */ {"SMK Cup", "", 2, 3, SECRET_NONE, 0, false, false, 0}, - - /* 04 */ {"Hard Game Speed", "", -1, 4, SECRET_HARDSPEED, 0, false, false, 0}, - /* 05 */ {"Encore Mode", "", 4, 5, SECRET_ENCORE, 0, false, false, 0}, - /* 06 */ {"Hell Attack", "", 6, 6, SECRET_HELLATTACK, 0, false, false, 0}, - - /* 07 */ {"Time Attack", "", -1, -1, SECRET_TIMEATTACK, 0, true, true, 0}, - /* 08 */ {"Break the Capsules", "", -1, -1, SECRET_BREAKTHECAPSULES, 0, true, true, 0}, -}; - -// Default number of emblems and extra emblems -INT32 numemblems = 110; -INT32 numextraemblems = 5; - -// DEFAULT CONDITION SETS FOR SRB2KART: -void M_SetupDefaultConditionSets(void) -{ - memset(conditionSets, 0, sizeof(conditionSets)); - - // UNLOCKABLES - // -- 1: Collect 5 medals OR play 25 matches - M_AddRawCondition(1, 1, UC_TOTALEMBLEMS, 5, 0, 0); - M_AddRawCondition(1, 2, UC_MATCHESPLAYED, 25, 0, 0); - - // -- 2: Collect 15 medals OR play 50 matches - M_AddRawCondition(2, 1, UC_TOTALEMBLEMS, 15, 0, 0); - M_AddRawCondition(2, 2, UC_MATCHESPLAYED, 50, 0, 0); - - // -- 3: Collect 30 medals OR play 150 matches - M_AddRawCondition(3, 1, UC_TOTALEMBLEMS, 30, 0, 0); - M_AddRawCondition(3, 2, UC_MATCHESPLAYED, 150, 0, 0); - - // -- 4: Collect 50 medals OR play 200 matches - M_AddRawCondition(4, 1, UC_TOTALEMBLEMS, 50, 0, 0); - M_AddRawCondition(4, 2, UC_MATCHESPLAYED, 200, 0, 0); - - // -- 5: Collect 70 medals OR play 300 matches - M_AddRawCondition(5, 1, UC_TOTALEMBLEMS, 70, 0, 0); - M_AddRawCondition(5, 2, UC_MATCHESPLAYED, 300, 0, 0); - - // -- 6: Collect 110 medals ONLY - M_AddRawCondition(6, 1, UC_TOTALEMBLEMS, 110, 0, 0); - - // MILESTONES - // -- 10: Play 100 matches - M_AddRawCondition(10, 1, UC_MATCHESPLAYED, 100, 0, 0); - - // -- 11: Play 250 matches - M_AddRawCondition(11, 1, UC_MATCHESPLAYED, 250, 0, 0); - - // -- 12: Play 500 matches - M_AddRawCondition(12, 1, UC_MATCHESPLAYED, 500, 0, 0); - - // -- 13: Play 750 matches - M_AddRawCondition(13, 1, UC_MATCHESPLAYED, 750, 0, 0); - - // -- 14: Play 1000 matches - M_AddRawCondition(14, 1, UC_MATCHESPLAYED, 1000, 0, 0); -} +// Number of emblems and extra emblems +INT32 numemblems = 0; +INT32 numextraemblems = 0; void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2) { @@ -274,7 +90,7 @@ void M_ClearSecrets(void) for (i = 0; i < MAXCONDITIONSETS; ++i) conditionSets[i].achieved = false; - timesBeaten = timesBeatenWithEmeralds = 0; + timesBeaten = 0; // Re-unlock any always unlocked things M_SilentUpdateUnlockablesAndEmblems(); @@ -295,38 +111,16 @@ UINT8 M_CheckCondition(condition_t *cn) return (vspowerlevel[cn->extrainfo1] >= (unsigned)cn->requirement); case UC_GAMECLEAR: // Requires game beaten >= x times return (timesBeaten >= (unsigned)cn->requirement); - case UC_ALLEMERALDS: // Requires game beaten with all 7 emeralds >= x times - return (timesBeatenWithEmeralds >= (unsigned)cn->requirement); - /*case UC_ULTIMATECLEAR: // Requires game beaten on ultimate >= x times (in other words, never) - return (timesBeatenUltimate >= (unsigned)cn->requirement);*/ case UC_OVERALLTIME: // Requires overall time <= x return (M_GotLowEnoughTime(cn->requirement)); - /*case UC_OVERALLSCORE: // Requires overall score >= x - return (M_GotHighEnoughScore(cn->requirement)); - case UC_OVERALLRINGS: // Requires overall rings >= x - return (M_GotHighEnoughRings(cn->requirement));*/ case UC_MAPVISITED: // Requires map x to be visited return ((mapvisited[cn->requirement - 1] & MV_VISITED) == MV_VISITED); case UC_MAPBEATEN: // Requires map x to be beaten return ((mapvisited[cn->requirement - 1] & MV_BEATEN) == MV_BEATEN); - case UC_MAPALLEMERALDS: // Requires map x to be beaten with all emeralds in possession - return ((mapvisited[cn->requirement - 1] & MV_ALLEMERALDS) == MV_ALLEMERALDS); - /*case UC_MAPULTIMATE: // Requires map x to be beaten on ultimate - return ((mapvisited[cn->requirement - 1] & MV_ULTIMATE) == MV_ULTIMATE); - case UC_MAPPERFECT: // Requires map x to be beaten with a perfect bonus - return ((mapvisited[cn->requirement - 1] & MV_PERFECT) == MV_PERFECT);*/ + case UC_MAPENCORE: // Requires map x to be beaten in encore + return ((mapvisited[cn->requirement - 1] & MV_ENCORE) == MV_ENCORE); case UC_MAPTIME: // Requires time on map <= x return (G_GetBestTime(cn->extrainfo1) <= (unsigned)cn->requirement); - /*case UC_MAPSCORE: // Requires score on map >= x - return (G_GetBestScore(cn->extrainfo1) >= (unsigned)cn->requirement); - case UC_MAPRINGS: // Requires rings on map >= x - return (G_GetBestRings(cn->extrainfo1) >= cn->requirement); - case UC_NIGHTSSCORE: - return (G_GetBestNightsScore(cn->extrainfo1, (UINT8)cn->extrainfo2) >= (unsigned)cn->requirement); - case UC_NIGHTSTIME: - return (G_GetBestNightsTime(cn->extrainfo1, (UINT8)cn->extrainfo2) <= (unsigned)cn->requirement); - case UC_NIGHTSGRADE: - return (G_GetBestNightsGrade(cn->extrainfo1, (UINT8)cn->extrainfo2) >= cn->requirement);*/ case UC_TRIGGER: // requires map trigger set return !!(unlocktriggers & (1 << cn->requirement)); case UC_TOTALEMBLEMS: // Requires number of emblems >= x @@ -383,15 +177,12 @@ void M_CheckUnlockConditions(void) } } -UINT8 M_UpdateUnlockablesAndExtraEmblems(boolean force) +UINT8 M_UpdateUnlockablesAndExtraEmblems(void) { INT32 i; char cechoText[992] = ""; UINT8 cechoLines = 0; - if (majormods && !force) // SRB2Kart: for enabling unlocks online in modified servers - return false; - M_CheckUnlockConditions(); // Go through extra emblems @@ -429,7 +220,7 @@ UINT8 M_UpdateUnlockablesAndExtraEmblems(boolean force) if (cechoLines) { char slashed[1024] = ""; - for (i = 0; (i < 21) && (i < 24 - cechoLines); ++i) + for (i = 0; (i < 19) && (i < 24 - cechoLines); ++i) slashed[i] = '\\'; slashed[i] = 0; @@ -473,6 +264,11 @@ void M_SilentUpdateUnlockablesAndEmblems(void) continue; unlockables[i].unlocked = M_Achieved(unlockables[i].conditionset - 1); } + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + players[g_localplayers[i]].availabilities = R_GetSkinAvailabilities(); + } } // Emblem unlocking shit @@ -487,7 +283,7 @@ UINT8 M_CheckLevelEmblems(void) // Update Score, Time, Rings emblems for (i = 0; i < numemblems; ++i) { - if (emblemlocations[i].type <= ET_SKIN || emblemlocations[i].collected) + if (emblemlocations[i].type < ET_TIME || emblemlocations[i].collected) continue; levelnum = emblemlocations[i].level; @@ -495,21 +291,9 @@ UINT8 M_CheckLevelEmblems(void) switch (emblemlocations[i].type) { - /*case ET_SCORE: // Requires score on map >= x - res = (G_GetBestScore(levelnum) >= (unsigned)valToReach); - break;*/ case ET_TIME: // Requires time on map <= x res = (G_GetBestTime(levelnum) <= (unsigned)valToReach); break; - /*case ET_RINGS: // Requires rings on map >= x - res = (G_GetBestRings(levelnum) >= valToReach); - break; - case ET_NGRADE: // Requires NiGHTS grade on map >= x - res = (G_GetBestNightsGrade(levelnum, 0) >= valToReach); - break; - case ET_NTIME: // Requires NiGHTS time on map <= x - res = (G_GetBestNightsTime(levelnum, 0) <= (unsigned)valToReach); - break;*/ default: // unreachable but shuts the compiler up. continue; } @@ -521,6 +305,36 @@ UINT8 M_CheckLevelEmblems(void) return somethingUnlocked; } +UINT8 M_CompletionEmblems(void) // Bah! Duplication sucks, but it's for a separate print when awarding emblems and it's sorta different enough. +{ + INT32 i; + INT32 embtype; + INT16 levelnum; + UINT8 res; + UINT8 somethingUnlocked = 0; + UINT8 flags; + + for (i = 0; i < numemblems; ++i) + { + if (emblemlocations[i].type != ET_MAP || emblemlocations[i].collected) + continue; + + levelnum = emblemlocations[i].level; + embtype = emblemlocations[i].var; + flags = MV_BEATEN; + + if (embtype & ME_ENCORE) + flags |= MV_ENCORE; + + res = ((mapvisited[levelnum - 1] & flags) == flags); + + emblemlocations[i].collected = res; + if (res) + ++somethingUnlocked; + } + return somethingUnlocked; +} + // ------------------- // Quick unlock checks // ------------------- @@ -544,12 +358,20 @@ UINT8 M_SecretUnlocked(INT32 type) return true; #endif +#ifdef DEVELOP +#define CHADYES true +#else +#define CHADYES false +#endif + for (i = 0; i < MAXUNLOCKABLES; ++i) { - if (unlockables[i].type == type && unlockables[i].unlocked) - return true; + if (unlockables[i].type == type && unlockables[i].unlocked != CHADYES) + return !CHADYES; } - return false; + return CHADYES; + +#undef CHADYES } UINT8 M_MapLocked(INT32 mapnum) @@ -599,24 +421,6 @@ UINT8 M_GotEnoughEmblems(INT32 number) return false; } -/*UINT8 M_GotHighEnoughScore(INT32 tscore) -{ - INT32 mscore = 0; - INT32 i; - - for (i = 0; i < NUMMAPS; ++i) - { - if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) - continue; - if (!mainrecords[i]) - continue; - - if ((mscore += mainrecords[i]->score) > tscore) - return true; - } - return false; -}*/ - UINT8 M_GotLowEnoughTime(INT32 tictime) { INT32 curtics = 0; @@ -624,7 +428,7 @@ UINT8 M_GotLowEnoughTime(INT32 tictime) for (i = 0; i < NUMMAPS; ++i) { - if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) + if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_TIMEATTACK)) continue; if (!mainrecords[i] || !mainrecords[i]->time) @@ -635,24 +439,6 @@ UINT8 M_GotLowEnoughTime(INT32 tictime) return true; } -/*UINT8 M_GotHighEnoughRings(INT32 trings) -{ - INT32 mrings = 0; - INT32 i; - - for (i = 0; i < NUMMAPS; ++i) - { - if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) - continue; - if (!mainrecords[i]) - continue; - - if ((mrings += mainrecords[i]->rings) > trings) - return true; - } - return false; -}*/ - // ---------------- // Misc Emblem shit // ---------------- @@ -680,34 +466,54 @@ emblem_t *M_GetLevelEmblems(INT32 mapnum) return NULL; } -skincolors_t M_GetEmblemColor(emblem_t *em) +skincolornum_t M_GetEmblemColor(emblem_t *em) { - if (!em || em->color >= MAXSKINCOLORS) + if (!em || em->color >= numskincolors) return SKINCOLOR_NONE; return em->color; } -const char *M_GetEmblemPatch(emblem_t *em) +const char *M_GetEmblemPatch(emblem_t *em, boolean big) { - static char pnamebuf[7] = "GOTITn"; + static char pnamebuf[7]; + + if (!big) + strcpy(pnamebuf, "GOTITn"); + else + strcpy(pnamebuf, "EMBMn0"); I_Assert(em->sprite >= 'A' && em->sprite <= 'Z'); - pnamebuf[5] = em->sprite; + + if (!big) + pnamebuf[5] = em->sprite; + else + pnamebuf[4] = em->sprite; + return pnamebuf; } -skincolors_t M_GetExtraEmblemColor(extraemblem_t *em) +skincolornum_t M_GetExtraEmblemColor(extraemblem_t *em) { - if (!em || em->color >= MAXSKINCOLORS) + if (!em || em->color >= numskincolors) return SKINCOLOR_NONE; return em->color; } -const char *M_GetExtraEmblemPatch(extraemblem_t *em) +const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big) { - static char pnamebuf[7] = "GOTITn"; + static char pnamebuf[7]; + + if (!big) + strcpy(pnamebuf, "GOTITn"); + else + strcpy(pnamebuf, "EMBMn0"); I_Assert(em->sprite >= 'A' && em->sprite <= 'Z'); - pnamebuf[5] = em->sprite; + + if (!big) + pnamebuf[5] = em->sprite; + else + pnamebuf[4] = em->sprite; + return pnamebuf; } diff --git a/src/m_cond.h b/src/m_cond.h index 82e776632..ed29fe326 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2012-2016 by Matthew "Inuyasha" Walsh. -// Copyright (C) 2012-2018 by Sonic Team Junior. +// Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. +// Copyright (C) 2012-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -20,26 +20,15 @@ // [required] typedef enum { - UC_PLAYTIME, // PLAYTIME [tics] - UC_MATCHESPLAYED, // SRB2Kart: MATCHESPLAYED [x played] + UC_PLAYTIME, // PLAYTIME [tics] + UC_MATCHESPLAYED, // SRB2Kart: MATCHESPLAYED [x played] UC_POWERLEVEL, // SRB2Kart: POWERLEVEL [power level to reach] [gametype, "0" for race, "1" for battle] UC_GAMECLEAR, // GAMECLEAR - UC_ALLEMERALDS, // ALLEMERALDS - //UC_ULTIMATECLEAR, // ULTIMATECLEAR - //UC_OVERALLSCORE, // OVERALLSCORE [score to beat] UC_OVERALLTIME, // OVERALLTIME [time to beat, tics] - //UC_OVERALLRINGS, // OVERALLRINGS [rings to beat] UC_MAPVISITED, // MAPVISITED [map number] UC_MAPBEATEN, // MAPBEATEN [map number] - UC_MAPALLEMERALDS, // MAPALLEMERALDS [map number] - //UC_MAPULTIMATE, // MAPULTIMATE [map number] - //UC_MAPPERFECT, // MAPPERFECT [map number] - //UC_MAPSCORE, // MAPSCORE [map number] [score to beat] + UC_MAPENCORE, // MAPENCORE [map number] UC_MAPTIME, // MAPTIME [map number] [time to beat, tics] - //UC_MAPRINGS, // MAPRINGS [map number] [rings to beat] - //UC_NIGHTSSCORE, // NIGHTSSCORE [map number] [score to beat] - //UC_NIGHTSTIME, // NIGHTSTIME [map number] [time to beat, tics] - //UC_NIGHTSGRADE, // NIGHTSGRADE [map number] [grade] UC_TRIGGER, // TRIGGER [trigger number] UC_TOTALEMBLEMS, // TOTALEMBLEMS [number of emblems] UC_EMBLEM, // EMBLEM [emblem number] @@ -68,35 +57,38 @@ typedef struct } conditionset_t; // Emblem information -#define ET_GLOBAL 0 // Global map emblem, var == color -#define ET_SKIN 1 // Skin specific emblem, var == skin -//#define ET_SCORE 2 -#define ET_TIME 2 -//#define ET_RINGS 4 -//#define ET_NGRADE 5 -//#define ET_NTIME 6 +#define ET_GLOBAL 0 // Emblem with a position in space +#define ET_MAP 1 // Beat the map +#define ET_TIME 2 // Get the time +//#define ET_DEVTIME 3 // Time, but the value is tied to a Time Trial demo, not pre-defined + +// Global emblem flags +// (N/A to Kart yet) +//#define GE_OH 1 + +// Map emblem flags +#define ME_ENCORE 1 typedef struct { UINT8 type; ///< Emblem type - INT16 x; ///< X coordinate. - INT16 y; ///< Y coordinate. - INT16 z; ///< Z coordinate. + INT16 tag; ///< Tag of emblem mapthing INT16 level; ///< Level on which this emblem can be found. UINT8 sprite; ///< emblem sprite to use, 0 - 25 - UINT8 color; ///< skincolor to use + UINT16 color; ///< skincolor to use INT32 var; ///< If needed, specifies information on the target amount to achieve (or target skin) char hint[110]; ///< Hint for emblem hints menu UINT8 collected; ///< Do you have this emblem? } emblem_t; typedef struct { - char name[20]; ///< Name of the goal (used in the "emblem awarded" cecho) - char description[40];///< Description of goal (used in statistics) - UINT8 conditionset; ///< Condition set that awards this emblem. - UINT8 sprite; ///< emblem sprite to use, 0 - 25 - UINT8 color; ///< skincolor to use - UINT8 collected; ///< Do you have this emblem? + char name[20]; ///< Name of the goal (used in the "emblem awarded" cecho) + char description[40]; ///< Description of goal (used in statistics) + UINT8 conditionset; ///< Condition set that awards this emblem. + UINT8 showconditionset; ///< Condition set that shows this emblem. + UINT8 sprite; ///< emblem sprite to use, 0 - 25 + UINT16 color; ///< skincolor to use + UINT8 collected; ///< Do you have this emblem? } extraemblem_t; // Unlockable information @@ -104,8 +96,8 @@ typedef struct { char name[64]; char objective[64]; - UINT8 showconditionset; UINT8 conditionset; + UINT8 showconditionset; INT16 type; INT16 variable; UINT8 nocecho; @@ -113,21 +105,26 @@ typedef struct UINT8 unlocked; } unlockable_t; -// I have NO idea why these are going negative, but whatever. -#define SECRET_NONE -6 // Does nil. Use with levels locked by UnlockRequired -#define SECRET_ITEMFINDER -5 // Enables Item Finder/Emblem Radar -#define SECRET_EMBLEMHINTS -4 // Enables Emblem Hints -#define SECRET_PANDORA -3 // Enables Pandora's Box -#define SECRET_TIMEATTACK -2 // Enables Time Attack on the main menu -#define SECRET_BREAKTHECAPSULES -1 // Enables Break the Capsules on the main menu -#define SECRET_HEADER 0 // Does nothing on its own, just serves as a header for the menu -#define SECRET_LEVELSELECT 1 // Selectable level select -#define SECRET_WARP 2 // Selectable warp -#define SECRET_SOUNDTEST 3 // Sound Test -#define SECRET_CREDITS 4 // Enables Credits -#define SECRET_ENCORE 5 // Enables Encore mode cvar -#define SECRET_HELLATTACK 6 // Map Hell in record attack -#define SECRET_HARDSPEED 7 // Enables Hard gamespeed +#define SECRET_NONE 0 // Does nil. Use with levels locked by UnlockRequired +#define SECRET_HEADER 1 // Does nothing on its own, just serves as a header for the menu + +#define SECRET_SKIN 2 // Allow this character to be selected +#define SECRET_WARP 3 // Selectable warp +#define SECRET_LEVELSELECT 4 // Selectable level select + +#define SECRET_TIMEATTACK 5 // Enables Time Attack on the main menu +#define SECRET_BREAKTHECAPSULES 6 // Enables Break the Capsules on the main menu +#define SECRET_SOUNDTEST 7 // Sound Test +#define SECRET_CREDITS 8 // Enables Credits + +#define SECRET_ITEMFINDER 9 // Enables Item Finder/Emblem Radar +#define SECRET_EMBLEMHINTS 10 // Enables Emblem Hints + +#define SECRET_ENCORE 11 // Enables Encore mode cvar +#define SECRET_HARDSPEED 12 // Enables Hard gamespeed +#define SECRET_HELLATTACK 13 // Map Hell in record attack + +#define SECRET_PANDORA 14 // Enables Pandora's Box // If you have more secrets than these variables allow in your game, // you seriously need to get a life. @@ -146,8 +143,7 @@ extern INT32 numextraemblems; extern UINT32 unlocktriggers; -// Condition Set Setup -void M_SetupDefaultConditionSets(void); +// Condition set setup void M_AddRawCondition(UINT8 set, UINT8 id, conditiontype_t c, INT32 r, INT16 x1, INT16 x2); // Clearing secrets @@ -157,9 +153,10 @@ void M_ClearSecrets(void); // Updating conditions and unlockables void M_CheckUnlockConditions(void); UINT8 M_CheckCondition(condition_t *cn); -UINT8 M_UpdateUnlockablesAndExtraEmblems(boolean force); +UINT8 M_UpdateUnlockablesAndExtraEmblems(void); void M_SilentUpdateUnlockablesAndEmblems(void); UINT8 M_CheckLevelEmblems(void); +UINT8 M_CompletionEmblems(void); // Checking unlockable status UINT8 M_AnySecretUnlocked(void); @@ -169,17 +166,15 @@ INT32 M_CountEmblems(void); // Emblem shit emblem_t *M_GetLevelEmblems(INT32 mapnum); -skincolors_t M_GetEmblemColor(emblem_t *em); -const char *M_GetEmblemPatch(emblem_t *em); -skincolors_t M_GetExtraEmblemColor(extraemblem_t *em); -const char *M_GetExtraEmblemPatch(extraemblem_t *em); +skincolornum_t M_GetEmblemColor(emblem_t *em); +const char *M_GetEmblemPatch(emblem_t *em, boolean big); +skincolornum_t M_GetExtraEmblemColor(extraemblem_t *em); +const char *M_GetExtraEmblemPatch(extraemblem_t *em, boolean big); // If you're looking to compare stats for unlocks or what not, use these // They stop checking upon reaching the target number so they // should be (theoretically?) slightly faster. UINT8 M_GotEnoughEmblems(INT32 number); -//UINT8 M_GotHighEnoughScore(INT32 tscore); UINT8 M_GotLowEnoughTime(INT32 tictime); -//UINT8 M_GotHighEnoughRings(INT32 trings); #define M_Achieved(a) ((a) >= MAXCONDITIONSETS || conditionSets[a].achieved) diff --git a/src/m_dllist.h b/src/m_dllist.h index 18f351144..680c2cd80 100644 --- a/src/m_dllist.h +++ b/src/m_dllist.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2005 by James Haley -// Copyright (C) 2005-2018 by Sonic Team Junior. +// Copyright (C) 2005-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_fixed.c b/src/m_fixed.c index 7241be9c0..eb10fd5f8 100644 --- a/src/m_fixed.c +++ b/src/m_fixed.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -411,19 +411,6 @@ boolean FV3_Equal(const vector3_t *a_1, const vector3_t *a_2) return false; } -// ClosestPointOnVector -// -// Similar to ClosestPointOnLine, but uses a vector instead of two points. -// -void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out) -{ - fixed_t t = FV3_Dot(dir, p); - - // Return the point on the line closest - FV3_MulEx(dir, t, out); - return; -} - fixed_t FV3_Dot(const vector3_t *a_1, const vector3_t *a_2) { return (FixedMul(a_1->x, a_2->x) + FixedMul(a_1->y, a_2->y) + FixedMul(a_1->z, a_2->z)); @@ -471,6 +458,19 @@ vector3_t *FV3_ClosestPointOnLine(const vector3_t *Line, const vector3_t *p, vec return FV3_AddEx(&Line[0], &V, out); } +// +// ClosestPointOnVector +// +// Similar to ClosestPointOnLine, but uses a vector instead of two points. +// +void FV3_ClosestPointOnVector(const vector3_t *dir, const vector3_t *p, vector3_t *out) +{ + fixed_t t = FV3_Dot(dir, p); + + // Return the point on the line closest + FV3_MulEx(dir, t, out); + return; +} // // ClosestPointOnTriangle diff --git a/src/m_fixed.h b/src/m_fixed.h index 8145a6917..289ca442a 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -20,11 +20,6 @@ #include #endif -// Was this just for the #define USEASM? -//#ifdef _WIN32_WCE -//#include "sdl12/SRB2CE/cehelp.h" -//#endif - /*! \brief bits of the fraction */ @@ -43,8 +38,20 @@ typedef INT32 fixed_t; /*! \brief convert fixed_t into floating number */ -#define FIXED_TO_FLOAT(x) (((float)(x)) / ((float)FRACUNIT)) -#define FLOAT_TO_FIXED(f) (fixed_t)((f) * ((float)FRACUNIT)) + +FUNCMATH FUNCINLINE static ATTRINLINE float FixedToFloat(fixed_t x) +{ + return x / (float)FRACUNIT; +} + +FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FloatToFixed(float f) +{ + return (fixed_t)(f * FRACUNIT); +} + +// for backwards compat +#define FIXED_TO_FLOAT(x) FixedToFloat(x) // (((float)(x)) / ((float)FRACUNIT)) +#define FLOAT_TO_FIXED(f) FloatToFixed(f) // (fixed_t)((f) * ((float)FRACUNIT)) #if defined (__WATCOMC__) && FRACBITS == 16 @@ -197,25 +204,6 @@ FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedDiv(fixed_t a, fixed_t b) return FixedDiv2(a, b); } -/** \brief The FixedRem function - - \param x fixed_t number - \param y fixed_t number - - \return remainder of dividing x by y -*/ -FUNCMATH FUNCINLINE static ATTRINLINE fixed_t FixedRem(fixed_t x, fixed_t y) -{ - const boolean n = x < 0; - x = abs(x); - while (x >= y) - x -= y; - if (n) - return -x; - else - return x; -} - /** \brief The FixedSqrt function \param x fixed_t number diff --git a/src/m_menu.c b/src/m_menu.c index 432889e4c..7f6f542c6 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -85,6 +85,11 @@ int snprintf(char *str, size_t n, const char *fmt, ...); //int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); #endif +#ifdef HAVE_DISCORDRPC +//#include "discord_rpc.h" +#include "discord.h" +#endif + #define SKULLXOFF -32 #define LINEHEIGHT 16 #define STRINGHEIGHT 8 @@ -186,7 +191,6 @@ static void M_StopMessage(INT32 choice); #ifndef NONET static void M_HandleServerPage(INT32 choice); -static void M_RoomMenu(INT32 choice); #endif // Prototyping is fun, innit? @@ -194,9 +198,18 @@ static void M_RoomMenu(INT32 choice); // NEEDED FUNCTION PROTOTYPES GO HERE // ========================================================================== +void M_SetWaitingMode(int mode); +int M_GetWaitingMode(void); + // the haxor message menu menu_t MessageDef; +#ifdef HAVE_DISCORDRPC +menu_t MISC_DiscordRequestsDef; +static void M_HandleDiscordRequests(INT32 choice); +static void M_DrawDiscordRequests(void); +#endif + menu_t SPauseDef; #define lsheadingheight 16 @@ -263,7 +276,6 @@ static void M_ConnectMenu(INT32 choice); static void M_ConnectMenuModChecks(INT32 choice); static void M_Refresh(INT32 choice); static void M_Connect(INT32 choice); -static void M_ChooseRoom(INT32 choice); #endif #ifndef TESTERS static void M_StartOfflineServerMenu(INT32 choice); @@ -279,7 +291,7 @@ static void M_SetupMultiHandler(INT32 choice); // Split into multiple parts due to size // Controls menu_t OP_ControlsDef, OP_AllControlsDef; -menu_t OP_MouseOptionsDef, OP_Mouse2OptionsDef; +menu_t OP_MouseOptionsDef; menu_t OP_Joystick1Def, OP_Joystick2Def, OP_Joystick3Def, OP_Joystick4Def; static void M_VideoModeMenu(INT32 choice); static void M_Setup1PControlsMenu(INT32 choice); @@ -299,13 +311,17 @@ static void M_ResetControls(INT32 choice); // Video & Sound menu_t OP_VideoOptionsDef, OP_VideoModeDef; #ifdef HWRENDER -menu_t OP_OpenGLOptionsDef, OP_OpenGLColorDef; +static void M_OpenGLOptionsMenu(void); +menu_t OP_OpenGLOptionsDef; #endif menu_t OP_SoundOptionsDef; //static void M_RestartAudio(void); //Misc menu_t OP_DataOptionsDef, OP_ScreenshotOptionsDef, OP_EraseDataDef; +#ifdef HAVE_DISCORDRPC +menu_t OP_DiscordOptionsDef; +#endif menu_t OP_HUDOptionsDef, OP_ChatOptionsDef; menu_t OP_GameOptionsDef, OP_ServerOptionsDef; #ifndef NONET @@ -365,13 +381,9 @@ static void M_DrawVideoMenu(void); static void M_DrawHUDOptions(void); static void M_DrawVideoMode(void); static void M_DrawMonitorToggles(void); -#ifdef HWRENDER -static void M_OGL_DrawColorMenu(void); -#endif static void M_DrawMPMainMenu(void); #ifndef NONET static void M_DrawConnectMenu(void); -static void M_DrawRoomMenu(void); #endif static void M_DrawJoystick(void); static void M_DrawSetupMultiPlayerMenu(void); @@ -395,7 +407,6 @@ static void M_HandleVideoMode(INT32 choice); static void M_HandleMonitorToggles(INT32 choice); // Consvar onchange functions -static void Nextmap_OnChange(void); static void Newgametype_OnChange(void); static void Dummymenuplayer_OnChange(void); //static void Dummymares_OnChange(void); @@ -405,23 +416,23 @@ static void Dummystaff_OnChange(void); // CONSOLE VARIABLES AND THEIR POSSIBLE VALUES GO HERE. // ========================================================================== -consvar_t cv_showfocuslost = {"showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL }; +consvar_t cv_showfocuslost = CVAR_INIT ("showfocuslost", "Yes", CV_SAVE, CV_YesNo, NULL); static CV_PossibleValue_t map_cons_t[] = { {0,"MIN"}, {NUMMAPS, "MAX"}, {0, NULL} }; -consvar_t cv_nextmap = {"nextmap", "1", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_nextmap = CVAR_INIT ("nextmap", "1", CV_HIDEN|CV_CALL, map_cons_t, Nextmap_OnChange); static CV_PossibleValue_t skins_cons_t[MAXSKINS+1] = {{1, DEFAULTSKIN}}; -consvar_t cv_chooseskin = {"chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_chooseskin = CVAR_INIT ("chooseskin", DEFAULTSKIN, CV_HIDEN|CV_CALL, skins_cons_t, Nextmap_OnChange); // This gametype list is integral for many different reasons. // When you add gametypes here, don't forget to update them in dehacked.c and doomstat.h! CV_PossibleValue_t gametype_cons_t[NUMGAMETYPES+1]; -consvar_t cv_newgametype = {"newgametype", "Race", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_newgametype = CVAR_INIT ("newgametype", "Race", CV_HIDEN|CV_CALL, gametype_cons_t, Newgametype_OnChange); static CV_PossibleValue_t serversort_cons_t[] = { {0,"Ping"}, @@ -432,54 +443,55 @@ static CV_PossibleValue_t serversort_cons_t[] = { {5,"Gametype"}, {0,NULL} }; -consvar_t cv_serversort = {"serversort", "Ping", CV_CALL, serversort_cons_t, M_SortServerList, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_serversort = CVAR_INIT ("serversort", "Ping", CV_CALL, serversort_cons_t, M_SortServerList); + +// first time memory +consvar_t cv_tutorialprompt = CVAR_INIT ("tutorialprompt", "On", CV_SAVE, CV_OnOff, NULL); // autorecord demos for time attack -static consvar_t cv_autorecord = {"autorecord", "Yes", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +static consvar_t cv_autorecord = CVAR_INIT ("autorecord", "Yes", 0, CV_YesNo, NULL); CV_PossibleValue_t ghost_cons_t[] = {{0, "Hide"}, {1, "Show Character"}, {2, "Show All"}, {0, NULL}}; CV_PossibleValue_t ghost2_cons_t[] = {{0, "Hide"}, {1, "Show"}, {0, NULL}}; -consvar_t cv_ghost_besttime = {"ghost_besttime", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghost_bestlap = {"ghost_bestlap", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghost_last = {"ghost_last", "Show All", CV_SAVE, ghost_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghost_guest = {"ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghost_staff = {"ghost_staff", "Show", CV_SAVE, ghost2_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ghost_besttime = CVAR_INIT ("ghost_besttime", "Show All", CV_SAVE, ghost_cons_t, NULL); +consvar_t cv_ghost_bestlap = CVAR_INIT ("ghost_bestlap", "Show All", CV_SAVE, ghost_cons_t, NULL); +consvar_t cv_ghost_last = CVAR_INIT ("ghost_last", "Show All", CV_SAVE, ghost_cons_t, NULL); +consvar_t cv_ghost_guest = CVAR_INIT ("ghost_guest", "Show", CV_SAVE, ghost2_cons_t, NULL); +consvar_t cv_ghost_staff = CVAR_INIT ("ghost_staff", "Show", CV_SAVE, ghost2_cons_t, NULL); //Console variables used solely in the menu system. //todo: add a way to use non-console variables in the menu // or make these consvars legitimate like color or skin. static void Splitplayers_OnChange(void); CV_PossibleValue_t splitplayers_cons_t[] = {{1, "One"}, {2, "Two"}, {3, "Three"}, {4, "Four"}, {0, NULL}}; -consvar_t cv_splitplayers = {"splitplayers", "One", CV_CALL, splitplayers_cons_t, Splitplayers_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_splitplayers = CVAR_INIT ("splitplayers", "One", CV_CALL, splitplayers_cons_t, Splitplayers_OnChange); static CV_PossibleValue_t dummymenuplayer_cons_t[] = {{0, "NOPE"}, {1, "P1"}, {2, "P2"}, {3, "P3"}, {4, "P4"}, {0, NULL}}; static CV_PossibleValue_t dummyteam_cons_t[] = {{0, "Spectator"}, {1, "Red"}, {2, "Blue"}, {0, NULL}}; static CV_PossibleValue_t dummyspectate_cons_t[] = {{0, "Spectator"}, {1, "Playing"}, {0, NULL}}; static CV_PossibleValue_t dummyscramble_cons_t[] = {{0, "Random"}, {1, "Points"}, {0, NULL}}; -static CV_PossibleValue_t ringlimit_cons_t[] = {{0, "MIN"}, {9999, "MAX"}, {0, NULL}}; -static CV_PossibleValue_t liveslimit_cons_t[] = {{0, "MIN"}, {99, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t ringlimit_cons_t[] = {{-20, "MIN"}, {20, "MAX"}, {0, NULL}}; +static CV_PossibleValue_t liveslimit_cons_t[] = {{-1, "MIN"}, {9, "MAX"}, {0, NULL}}; /*static CV_PossibleValue_t dummymares_cons_t[] = { {-1, "END"}, {0,"Overall"}, {1,"Mare 1"}, {2,"Mare 2"}, {3,"Mare 3"}, {4,"Mare 4"}, {5,"Mare 5"}, {6,"Mare 6"}, {7,"Mare 7"}, {8,"Mare 8"}, {0,NULL} };*/ static CV_PossibleValue_t dummystaff_cons_t[] = {{0, "MIN"}, {100, "MAX"}, {0, NULL}}; -static consvar_t cv_dummymenuplayer = {"dummymenuplayer", "P1", CV_HIDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummyteam = {"dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummyspectate = {"dummyspectate", "Spectator", CV_HIDEN, dummyspectate_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummyscramble = {"dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummyrings = {"dummyrings", "0", CV_HIDEN, ringlimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummylives = {"dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummycontinues = {"dummycontinues", "0", CV_HIDEN, liveslimit_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -//static consvar_t cv_dummymares = {"dummymares", "Overall", CV_HIDEN|CV_CALL, dummymares_cons_t, Dummymares_OnChange, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummystaff = {"dummystaff", "0", CV_HIDEN|CV_CALL, dummystaff_cons_t, Dummystaff_OnChange, 0, NULL, NULL, 0, 0, NULL}; +static consvar_t cv_dummymenuplayer = CVAR_INIT ("dummymenuplayer", "P1", CV_HIDEN|CV_CALL, dummymenuplayer_cons_t, Dummymenuplayer_OnChange); +static consvar_t cv_dummyteam = CVAR_INIT ("dummyteam", "Spectator", CV_HIDEN, dummyteam_cons_t, NULL); +static consvar_t cv_dummyspectate = CVAR_INIT ("dummyspectate", "Spectator", CV_HIDEN, dummyspectate_cons_t, NULL); +static consvar_t cv_dummyscramble = CVAR_INIT ("dummyscramble", "Random", CV_HIDEN, dummyscramble_cons_t, NULL); +static consvar_t cv_dummyrings = CVAR_INIT ("dummyrings", "0", CV_HIDEN, ringlimit_cons_t, NULL); +static consvar_t cv_dummylives = CVAR_INIT ("dummylives", "0", CV_HIDEN, liveslimit_cons_t, NULL); +static consvar_t cv_dummystaff = CVAR_INIT ("dummystaff", "0", CV_HIDEN|CV_CALL, dummystaff_cons_t, Dummystaff_OnChange); static CV_PossibleValue_t dummygpdifficulty_cons_t[] = {{0, "Easy"}, {1, "Normal"}, {2, "Hard"}, {3, "Master"}, {0, NULL}}; static CV_PossibleValue_t dummygpcup_cons_t[50] = {{1, "TEMP"}}; // A REALLY BIG NUMBER, SINCE THIS IS TEMP UNTIL NEW MENUS -static consvar_t cv_dummygpdifficulty = {"dummygpdifficulty", "Normal", CV_HIDEN, dummygpdifficulty_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummygpencore = {"dummygpencore", "Off", CV_HIDEN, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_dummygpcup = {"dummygpcup", "TEMP", CV_HIDEN, dummygpcup_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +static consvar_t cv_dummygpdifficulty = CVAR_INIT ("dummygpdifficulty", "Normal", CV_HIDEN, dummygpdifficulty_cons_t, NULL); +static consvar_t cv_dummygpencore = CVAR_INIT ("dummygpencore", "Off", CV_HIDEN, CV_OnOff, NULL); +static consvar_t cv_dummygpcup = CVAR_INIT ("dummygpcup", "TEMP", CV_HIDEN, dummygpcup_cons_t, NULL); // ========================================================================== // ORGANIZATION START. @@ -609,6 +621,10 @@ static menuitem_t MPauseMenu[] = {IT_STRING | IT_SUBMENU, NULL, "Scramble Teams...", &MISC_ScrambleTeamDef, 16}, {IT_STRING | IT_CALL, NULL, "Switch Map..." , M_MapChange, 24}, +#ifdef HAVE_DISCORDRPC + {IT_STRING | IT_SUBMENU, NULL, "Ask To Join Requests...", &MISC_DiscordRequestsDef, 24}, +#endif + {IT_CALL | IT_STRING, NULL, "Continue", M_SelectableClearMenus, 40}, {IT_CALL | IT_STRING, NULL, "P1 Setup...", M_SetupMultiPlayer, 48}, // splitscreen {IT_CALL | IT_STRING, NULL, "P2 Setup...", M_SetupMultiPlayer2, 56}, // splitscreen @@ -632,6 +648,9 @@ typedef enum mpause_addons = 0, mpause_scramble, mpause_switchmap, +#ifdef HAVE_DISCORDRPC + mpause_discordrequests, +#endif mpause_continue, mpause_psetupsplit, @@ -682,6 +701,13 @@ typedef enum spause_quit } spause_e; +#ifdef HAVE_DISCORDRPC +static menuitem_t MISC_DiscordRequestsMenu[] = +{ + {IT_KEYHANDLER|IT_NOTHING, NULL, "", M_HandleDiscordRequests, 0}, +}; +#endif + // ----------------- // Misc menu options // ----------------- @@ -741,10 +767,8 @@ static menuitem_t SR_PandorasBox[] = { {IT_STRING | IT_CVAR, NULL, "Rings", &cv_dummyrings, 20}, {IT_STRING | IT_CVAR, NULL, "Lives", &cv_dummylives, 30}, - {IT_STRING | IT_CVAR, NULL, "Continues", &cv_dummycontinues, 40}, {IT_STRING | IT_CVAR, NULL, "Gravity", &cv_gravity, 60}, - {IT_STRING | IT_CVAR, NULL, "Throw Rings", &cv_ringslinger, 70}, {IT_STRING | IT_CALL, NULL, "Get All Emeralds", M_GetAllEmeralds, 90}, {IT_STRING | IT_CALL, NULL, "Destroy All Robots", M_DestroyRobots, 100}, @@ -836,7 +860,7 @@ enum static menuitem_t SP_GrandPrixPlaceholderMenu[] = { {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 10}, - {IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor, 20}, + {IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor[0], 20}, {IT_STRING|IT_CVAR, NULL, "Difficulty", &cv_dummygpdifficulty, 40}, {IT_STRING|IT_CVAR, NULL, "Encore Mode", &cv_dummygpencore, 50}, @@ -848,9 +872,9 @@ static menuitem_t SP_GrandPrixPlaceholderMenu[] = // Single Player Time Attack static menuitem_t SP_TimeAttackMenu[] = { - {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Name", &cv_playername, 0}, + {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Name", &cv_playername[0], 0}, {IT_STRING|IT_CVAR, NULL, "Character", &cv_chooseskin, 13}, - {IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor, 26}, + {IT_STRING|IT_CVAR, NULL, "Color", &cv_playercolor[0], 26}, {IT_STRING|IT_CVAR, NULL, "Level", &cv_nextmap, 78}, {IT_DISABLED, NULL, "Guest...", &SP_GuestReplayDef, 98}, @@ -1017,7 +1041,7 @@ static menuitem_t MP_MainMenu[] = static menuitem_t MP_ServerMenu[] = { {IT_STRING|IT_CVAR, NULL, "Max. Player Count", &cv_maxplayers, 10}, - {IT_STRING|IT_CALL, NULL, "Room...", M_RoomMenu, 20}, + {IT_STRING|IT_CVAR, NULL, "Advertise", &cv_advertise, 20}, {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Server Name", &cv_servername, 30}, {IT_STRING|IT_CVAR, NULL, "Game Type", &cv_newgametype, 68}, @@ -1048,54 +1072,30 @@ static menuitem_t MP_PlayerSetupMenu[] = #ifndef NONET static menuitem_t MP_ConnectMenu[] = { - {IT_STRING | IT_CALL, NULL, "Room...", M_RoomMenu, 4}, - {IT_STRING | IT_CVAR, NULL, "Sort By", &cv_serversort, 12}, - {IT_STRING | IT_KEYHANDLER, NULL, "Page", M_HandleServerPage, 20}, - {IT_STRING | IT_CALL, NULL, "Refresh", M_Refresh, 28}, + {IT_STRING | IT_CVAR, NULL, "Sort By", &cv_serversort, 4}, + {IT_STRING | IT_KEYHANDLER, NULL, "Page", M_HandleServerPage, 12}, + {IT_STRING | IT_CALL, NULL, "Refresh", M_Refresh, 20}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 48-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 60-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 72-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 84-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 96-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 108-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 120-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 132-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 144-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 156-4}, - {IT_STRING | IT_SPACE, NULL, "", M_Connect, 168-4}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 36}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 48}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 60}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 72}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 84}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 96}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 108}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 120}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 132}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 144}, + {IT_STRING | IT_SPACE, NULL, "", M_Connect, 156}, }; enum { - mp_connect_room, mp_connect_sort, mp_connect_page, mp_connect_refresh, FIRSTSERVERLINE }; - -menuitem_t MP_RoomMenu[] = -{ - {IT_STRING | IT_CALL, NULL, "", M_ChooseRoom, 9}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 18}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 27}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 36}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 45}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 54}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 63}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 72}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 81}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 90}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 99}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 108}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 117}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 126}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 135}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 144}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 153}, - {IT_DISABLED, NULL, "", M_ChooseRoom, 162}, -}; #endif // ------------------------------------ @@ -1175,49 +1175,49 @@ static menuitem_t OP_AllControlsMenu[] = static menuitem_t OP_Joystick1Menu[] = { {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup1PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis , 30}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis , 40}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis , 50}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis , 60}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis , 70}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis , 80}, - {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis , 90}, + {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[0] , 30}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[0] , 40}, + {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[0] , 50}, + {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[0] , 60}, + {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[0] , 70}, + {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[0] , 80}, + {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[0] , 90}, }; static menuitem_t OP_Joystick2Menu[] = { {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup2PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis2 , 30}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis2 , 40}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis2 , 50}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis2 , 60}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis2 , 70}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis2 , 80}, - {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis2 , 90}, + {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[1] , 30}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[1] , 40}, + {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[1] , 50}, + {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[1] , 60}, + {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[1] , 70}, + {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[1] , 80}, + {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[1] , 90}, }; static menuitem_t OP_Joystick3Menu[] = { {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup3PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis3 , 30}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis3 , 40}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis3 , 50}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis3 , 60}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis3 , 70}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis3 , 80}, - {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis3 , 90}, + {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[2] , 30}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[2] , 40}, + {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[2] , 50}, + {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[2] , 60}, + {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[2] , 70}, + {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[2] , 80}, + {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[2] , 90}, }; static menuitem_t OP_Joystick4Menu[] = { {IT_STRING | IT_CALL, NULL, "Select Gamepad..." , M_Setup4PJoystickMenu, 10}, - {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis4 , 30}, - {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis4 , 40}, - {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis4 , 50}, - {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis4 , 60}, - {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis4 , 70}, - {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis4 , 80}, - {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis4 , 90}, + {IT_STRING | IT_CVAR, NULL, "Aim Forward/Back" , &cv_aimaxis[3] , 30}, + {IT_STRING | IT_CVAR, NULL, "Turn Left/Right" , &cv_turnaxis[3] , 40}, + {IT_STRING | IT_CVAR, NULL, "Accelerate" , &cv_moveaxis[3] , 50}, + {IT_STRING | IT_CVAR, NULL, "Brake" , &cv_brakeaxis[3] , 60}, + {IT_STRING | IT_CVAR, NULL, "Drift" , &cv_driftaxis[3] , 70}, + {IT_STRING | IT_CVAR, NULL, "Use Item" , &cv_fireaxis[3] , 80}, + {IT_STRING | IT_CVAR, NULL, "Look Up/Down" , &cv_lookaxis[3] , 90}, }; static menuitem_t OP_JoystickSetMenu[] = @@ -1232,7 +1232,8 @@ static menuitem_t OP_JoystickSetMenu[] = {IT_CALL | IT_NOTHING, "", NULL, M_AssignJoystick, (LINEHEIGHT*8)+5}, }; -/*static menuitem_t OP_MouseOptionsMenu[] = +/* +static menuitem_t OP_MouseOptionsMenu[] = { {IT_STRING | IT_CVAR, NULL, "Use Mouse", &cv_usemouse, 10}, @@ -1246,43 +1247,31 @@ static menuitem_t OP_JoystickSetMenu[] = {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "Mouse Y Speed", &cv_mouseysens, 80}, }; - -static menuitem_t OP_Mouse2OptionsMenu[] = -{ - {IT_STRING | IT_CVAR, NULL, "Use Mouse 2", &cv_usemouse2, 10}, - {IT_STRING | IT_CVAR, NULL, "Second Mouse Serial Port", - &cv_mouse2port, 20}, - {IT_STRING | IT_CVAR, NULL, "First-Person MouseLook", &cv_alwaysfreelook2, 30}, - {IT_STRING | IT_CVAR, NULL, "Third-Person MouseLook", &cv_chasefreelook2, 40}, - {IT_STRING | IT_CVAR, NULL, "Mouse Move", &cv_mousemove2, 50}, - {IT_STRING | IT_CVAR, NULL, "Invert Mouse", &cv_invertmouse2, 60}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse X Speed", &cv_mousesens2, 70}, - {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Mouse Y Speed", &cv_mouseysens2, 80}, -};*/ +*/ static menuitem_t OP_VideoOptionsMenu[] = { {IT_STRING | IT_CALL, NULL, "Set Resolution...", M_VideoModeMenu, 10}, #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) {IT_STRING|IT_CVAR, NULL, "Fullscreen", &cv_fullscreen, 20}, +#endif +#ifdef HWRENDER + {IT_STRING | IT_CVAR, NULL, "Renderer", &cv_renderer, 30}, +#else + {IT_TRANSTEXT | IT_PAIR, "Renderer", "Software", &cv_renderer, 30}, #endif {IT_STRING | IT_CVAR | IT_CV_SLIDER, - NULL, "Gamma", &cv_globalgamma, 30}, + NULL, "Gamma", &cv_globalgamma, 50}, - {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 45}, - //{IT_STRING | IT_CVAR, NULL, "NiGHTS Draw Dist", &cv_drawdist_nights, 55}, - {IT_STRING | IT_CVAR, NULL, "Weather Draw Distance",&cv_drawdist_precip, 55}, - //{IT_STRING | IT_CVAR, NULL, "Weather Density", &cv_precipdensity, 65}, - {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 65}, - {IT_STRING | IT_CVAR, NULL, "Field of View", &cv_fov, 75}, + {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 60}, + {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 70}, - {IT_STRING | IT_CVAR, NULL, "Show FPS", &cv_ticrate, 90}, - {IT_STRING | IT_CVAR, NULL, "Vertical Sync", &cv_vidwait, 100}, + {IT_STRING | IT_CVAR, NULL, "Draw Distance", &cv_drawdist, 90}, + {IT_STRING | IT_CVAR, NULL, "Weather Draw Distance",&cv_drawdist_precip, 100}, + {IT_STRING | IT_CVAR, NULL, "Skyboxes", &cv_skybox, 110}, #ifdef HWRENDER - {IT_SUBMENU|IT_STRING, NULL, "OpenGL Options...", &OP_OpenGLOptionsDef, 120}, + {IT_CALL | IT_STRING, NULL, "OpenGL Options...", &M_OpenGLOptionsMenu, 140}, #endif }; @@ -1297,7 +1286,6 @@ enum op_video_wdd, //op_video_wd, op_video_skybox, - op_video_fov, op_video_fps, op_video_vsync, #ifdef HWRENDER @@ -1313,26 +1301,16 @@ static menuitem_t OP_VideoModeMenu[] = #ifdef HWRENDER static menuitem_t OP_OpenGLOptionsMenu[] = { - {IT_STRING | IT_CVAR, NULL, "3D Models", &cv_grmdls, 10}, - {IT_STRING | IT_CVAR, NULL, "Fallback Player 3D Model", &cv_grfallbackplayermodel, 20}, - {IT_STRING|IT_CVAR, NULL, "Shaders", &cv_grshaders, 30}, + {IT_STRING | IT_CVAR, NULL, "3D Models", &cv_glmodels, 10}, + {IT_STRING|IT_CVAR, NULL, "Shaders", &cv_glshaders, 20}, - {IT_STRING|IT_CVAR, NULL, "Texture Quality", &cv_scr_depth, 50}, - {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_grfiltermode, 60}, - {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_granisotropicmode, 70}, + {IT_STRING|IT_CVAR, NULL, "Texture Quality", &cv_scr_depth, 40}, + {IT_STRING|IT_CVAR, NULL, "Texture Filter", &cv_glfiltermode, 50}, + {IT_STRING|IT_CVAR, NULL, "Anisotropic", &cv_glanisotropicmode, 60}, - {IT_STRING|IT_CVAR, NULL, "Wall Contrast Style", &cv_grfakecontrast, 90}, - {IT_STRING|IT_CVAR, NULL, "Sprite Billboarding", &cv_grspritebillboarding, 100}, - {IT_STRING|IT_CVAR, NULL, "Software Perspective", &cv_grshearing, 110}, - - {IT_SUBMENU|IT_STRING, NULL, "Gamma...", &OP_OpenGLColorDef, 130}, -}; - -static menuitem_t OP_OpenGLColorMenu[] = -{ - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Red", &cv_grgammared, 10}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Green", &cv_grgammagreen, 20}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Blue", &cv_grgammablue, 30}, + {IT_STRING|IT_CVAR, NULL, "Wall Contrast Style", &cv_glfakecontrast, 80}, + {IT_STRING|IT_CVAR, NULL, "Sprite Billboarding", &cv_glspritebillboarding, 90}, + {IT_STRING|IT_CVAR, NULL, "Software Perspective", &cv_glshearing, 100}, }; #endif @@ -1346,15 +1324,6 @@ static menuitem_t OP_SoundOptionsMenu[] = {IT_STRING|IT_CVAR|IT_CV_SLIDER, NULL, "Music Volume", &cv_digmusicvolume, 38}, -/* -- :nonnathisshit: - {IT_STRING|IT_CVAR, NULL, "MIDI", &cv_gamemidimusic, 50}, - {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "MIDI Volume", &cv_midimusicvolume, 58}, -#ifdef PC_DOS - {IT_STRING|IT_CVAR|IT_CV_SLIDER, - NULL, "CD Volume", &cd_volume, 40}, -#endif*/ - //{IT_STRING|IT_CALL, NULL, "Restart Audio System", M_RestartAudio, 50}, {IT_STRING|IT_CVAR, NULL, "Reverse L/R Channels", &stereoreverse, 50}, @@ -1372,11 +1341,17 @@ static menuitem_t OP_SoundOptionsMenu[] = static menuitem_t OP_DataOptionsMenu[] = { + {IT_STRING | IT_CALL, NULL, "Screenshot Options...", M_ScreenshotOptions, 10}, {IT_STRING | IT_CALL, NULL, "Addon Options...", M_AddonsOptions, 20}, {IT_STRING | IT_SUBMENU, NULL, "Replay Options...", &MISC_ReplayOptionsDef, 30}, +#ifdef HAVE_DISCORDRPC + {IT_STRING | IT_SUBMENU, NULL, "Discord Options...", &OP_DiscordOptionsDef, 40}, + {IT_STRING | IT_SUBMENU, NULL, "Erase Data...", &OP_EraseDataDef, 60}, +#else {IT_STRING | IT_SUBMENU, NULL, "Erase Data...", &OP_EraseDataDef, 50}, +#endif }; static menuitem_t OP_ScreenshotOptionsMenu[] = @@ -1425,7 +1400,7 @@ static menuitem_t OP_AddonsOptionsMenu[] = {IT_HEADER, NULL, "Menu", NULL, 0}, {IT_STRING|IT_CVAR, NULL, "Location", &cv_addons_option, 10}, {IT_STRING|IT_CVAR|IT_CV_STRING, NULL, "Custom Folder", &cv_addons_folder, 20}, - {IT_STRING|IT_CVAR, NULL, "Identify addons via", &cv_addons_md5, 48}, + {IT_STRING|IT_CVAR, NULL, "Identify addons via", &cv_addons_md5, 48}, {IT_STRING|IT_CVAR, NULL, "Show unsupported file types", &cv_addons_showall, 58}, {IT_HEADER, NULL, "Search", NULL, 76}, @@ -1438,11 +1413,21 @@ enum op_addons_folder = 2, }; +#ifdef HAVE_DISCORDRPC +static menuitem_t OP_DiscordOptionsMenu[] = +{ + {IT_STRING | IT_CVAR, NULL, "Rich Presence", &cv_discordrp, 10}, + + {IT_HEADER, NULL, "Rich Presence Settings", NULL, 30}, + {IT_STRING | IT_CVAR, NULL, "Streamer Mode", &cv_discordstreamer, 40}, + + {IT_STRING | IT_CVAR, NULL, "Allow Ask To Join", &cv_discordasks, 60}, + {IT_STRING | IT_CVAR, NULL, "Allow Invites", &cv_discordinvites, 70}, +}; +#endif + static menuitem_t OP_HUDOptionsMenu[] = { - - {IT_STRING | IT_CVAR, NULL, "Show Followers", &cv_showfollowers, 10}, - {IT_STRING | IT_CVAR, NULL, "Show HUD (F3)", &cv_showhud, 20}, {IT_STRING | IT_CVAR | IT_CV_SLIDER, NULL, "HUD Visibility", &cv_translucenthud, 30}, @@ -1615,10 +1600,11 @@ static menuitem_t OP_MonitorToggleMenu[] = // ========================================================================== // Main Menu and related -menu_t MainDef = CENTERMENUSTYLE(NULL, MainMenu, NULL, 72); +menu_t MainDef = CENTERMENUSTYLE(MN_NONE, NULL, MainMenu, NULL, 72); menu_t MISC_AddonsDef = { + MN_NONE, NULL, sizeof (MISC_AddonsMenu)/sizeof (menuitem_t), &OP_DataOptionsDef, @@ -1631,6 +1617,7 @@ menu_t MISC_AddonsDef = menu_t MISC_ReplayHutDef = { + MN_NONE, NULL, sizeof (MISC_ReplayHutMenu)/sizeof (menuitem_t), NULL, @@ -1643,6 +1630,7 @@ menu_t MISC_ReplayHutDef = menu_t MISC_ReplayOptionsDef = { + MN_NONE, "M_REPOPT", sizeof (MISC_ReplayOptionsMenu)/sizeof (menuitem_t), &OP_DataOptionsDef, @@ -1655,6 +1643,7 @@ menu_t MISC_ReplayOptionsDef = menu_t MISC_ReplayStartDef = { + MN_NONE, NULL, sizeof (MISC_ReplayStartMenu)/sizeof (menuitem_t), &MISC_ReplayHutDef, @@ -1666,6 +1655,7 @@ menu_t MISC_ReplayStartDef = }; menu_t PlaybackMenuDef = { + MN_NONE, NULL, sizeof (PlaybackMenu)/sizeof (menuitem_t), NULL, @@ -1681,10 +1671,24 @@ menu_t MAPauseDef = PAUSEMENUSTYLE(MAPauseMenu, 40, 72); menu_t SPauseDef = PAUSEMENUSTYLE(SPauseMenu, 40, 72); menu_t MPauseDef = PAUSEMENUSTYLE(MPauseMenu, 40, 72); +#ifdef HAVE_DISCORDRPC +menu_t MISC_DiscordRequestsDef = { + MN_NONE, + NULL, + sizeof (MISC_DiscordRequestsMenu)/sizeof (menuitem_t), + &MPauseDef, + MISC_DiscordRequestsMenu, + M_DrawDiscordRequests, + 0, 0, + 0, + NULL +}; +#endif + // Misc Main Menu -menu_t MISC_ScrambleTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ScrambleTeamMenu, &MPauseDef, 27, 40); -menu_t MISC_ChangeTeamDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeTeamMenu, &MPauseDef, 27, 40); -menu_t MISC_ChangeSpectateDef = DEFAULTMENUSTYLE(NULL, MISC_ChangeSpectateMenu, &MPauseDef, 27, 40); +menu_t MISC_ScrambleTeamDef = DEFAULTMENUSTYLE(MN_NONE, NULL, MISC_ScrambleTeamMenu, &MPauseDef, 27, 40); +menu_t MISC_ChangeTeamDef = DEFAULTMENUSTYLE(MN_NONE, NULL, MISC_ChangeTeamMenu, &MPauseDef, 27, 40); +menu_t MISC_ChangeSpectateDef = DEFAULTMENUSTYLE(MN_NONE, NULL, MISC_ChangeSpectateMenu, &MPauseDef, 27, 40); menu_t MISC_ChangeLevelDef = MAPICONMENUSTYLE(NULL, MISC_ChangeLevelMenu, &MPauseDef); menu_t MISC_HelpDef = IMAGEDEF(MISC_HelpMenu); @@ -1723,7 +1727,7 @@ inline static void M_GetGametypeColor(void) warningflags = V_REDMAP; recommendedflags = V_GREENMAP; - if (modeattacking // == ATTACKING_RECORD + if (modeattacking // == ATTACKING_TIME || gamestate == GS_TIMEATTACK) { highlightflags = V_ORANGEMAP; @@ -1740,7 +1744,7 @@ inline static void M_GetGametypeColor(void) else gt = gametype; - if (gt == GT_MATCH) + if (gt == GT_BATTLE) { highlightflags = V_REDMAP; warningflags = V_ORANGEMAP; @@ -1765,6 +1769,7 @@ INT32 HU_GetHighlightColor(void) // Sky Room menu_t SR_PandoraDef = { + MN_NONE, "M_PANDRA", sizeof (SR_PandorasBox)/sizeof (menuitem_t), &SPauseDef, @@ -1774,12 +1779,13 @@ menu_t SR_PandoraDef = 0, M_ExitPandorasBox }; -menu_t SR_MainDef = CENTERMENUSTYLE(NULL, SR_MainMenu, &MainDef, 72); +menu_t SR_MainDef = CENTERMENUSTYLE(MN_NONE, NULL, SR_MainMenu, &MainDef, 72); //menu_t SR_LevelSelectDef = MAPICONMENUSTYLE(NULL, SR_LevelSelectMenu, &SR_MainDef); menu_t SR_UnlockChecklistDef = { + MN_NONE, NULL, 1, &SR_MainDef, @@ -1791,6 +1797,7 @@ menu_t SR_UnlockChecklistDef = }; menu_t SR_EmblemHintDef = { + MN_NONE, NULL, sizeof (SR_EmblemHintMenu)/sizeof (menuitem_t), &SPauseDef, @@ -1802,9 +1809,10 @@ menu_t SR_EmblemHintDef = }; // Single Player -menu_t SP_MainDef = CENTERMENUSTYLE(NULL, SP_MainMenu, &MainDef, 72); +menu_t SP_MainDef = CENTERMENUSTYLE(MN_NONE, NULL, SP_MainMenu, &MainDef, 72); /*menu_t SP_LoadDef = { + MN_NONE, "M_PICKG", 1, &SP_MainDef, @@ -1818,6 +1826,7 @@ menu_t SP_LevelSelectDef = MAPICONMENUSTYLE(NULL, SP_LevelSelectMenu, &SP_LoadDe menu_t SP_LevelStatsDef = { + MN_NONE, "M_STATS", 1, &SR_MainDef, @@ -1828,10 +1837,11 @@ menu_t SP_LevelStatsDef = NULL }; -static menu_t SP_GrandPrixTempDef = DEFAULTMENUSTYLE(NULL, SP_GrandPrixPlaceholderMenu, &MainDef, 60, 30); +static menu_t SP_GrandPrixTempDef = DEFAULTMENUSTYLE(MN_NONE, NULL, SP_GrandPrixPlaceholderMenu, &MainDef, 60, 30); static menu_t SP_TimeAttackDef = { + MN_NONE, "M_ATTACK", sizeof (SP_TimeAttackMenu)/sizeof (menuitem_t), &MainDef, // Doesn't matter. @@ -1843,6 +1853,7 @@ static menu_t SP_TimeAttackDef = }; static menu_t SP_ReplayDef = { + MN_NONE, "M_ATTACK", sizeof(SP_ReplayMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, @@ -1854,6 +1865,7 @@ static menu_t SP_ReplayDef = }; static menu_t SP_GuestReplayDef = { + MN_NONE, "M_ATTACK", sizeof(SP_GuestReplayMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, @@ -1865,6 +1877,7 @@ static menu_t SP_GuestReplayDef = }; static menu_t SP_GhostDef = { + MN_NONE, "M_ATTACK", sizeof(SP_GhostMenu)/sizeof(menuitem_t), &SP_TimeAttackDef, @@ -1877,6 +1890,7 @@ static menu_t SP_GhostDef = /*menu_t SP_PlayerDef = { + MN_NONE, "M_PICKP", sizeof (PlayerMenu)/sizeof (menuitem_t),//player_end, &SP_MainDef, @@ -1890,6 +1904,7 @@ static menu_t SP_GhostDef = // Multiplayer menu_t MP_MainDef = { + MN_NONE, "M_MULTI", sizeof (MP_MainMenu)/sizeof (menuitem_t), &MainDef, @@ -1911,6 +1926,7 @@ menu_t MP_ServerDef = MAPICONMENUSTYLE("M_MULTI", MP_ServerMenu, &MP_MainDef); menu_t MP_ConnectDef = { + MN_NONE, "M_MULTI", sizeof (MP_ConnectMenu)/sizeof (menuitem_t), &MP_MainDef, @@ -1920,20 +1936,10 @@ menu_t MP_ConnectDef = 0, M_CancelConnect }; -menu_t MP_RoomDef = -{ - "M_MULTI", - sizeof (MP_RoomMenu)/sizeof (menuitem_t), - &MP_ConnectDef, - MP_RoomMenu, - M_DrawRoomMenu, - 27, 32, - 0, - NULL -}; #endif menu_t MP_PlayerSetupDef = { + MN_NONE, NULL, //"M_SPLAYR" sizeof (MP_PlayerSetupMenu)/sizeof (menuitem_t), &MP_MainDef, @@ -1947,6 +1953,7 @@ menu_t MP_PlayerSetupDef = // Options menu_t OP_MainDef = { + MN_NONE, "M_OPTTTL", sizeof (OP_MainMenu)/sizeof (menuitem_t), &MainDef, @@ -1957,14 +1964,15 @@ menu_t OP_MainDef = NULL }; -menu_t OP_ControlsDef = DEFAULTMENUSTYLE("M_CONTRO", OP_ControlsMenu, &OP_MainDef, 60, 30); -menu_t OP_AllControlsDef = CONTROLMENUSTYLE(OP_AllControlsMenu, &OP_ControlsDef); -menu_t OP_Joystick1Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick1Menu, &OP_AllControlsDef, 60, 30); -menu_t OP_Joystick2Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick2Menu, &OP_AllControlsDef, 60, 30); -menu_t OP_Joystick3Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick3Menu, &OP_AllControlsDef, 60, 30); -menu_t OP_Joystick4Def = DEFAULTMENUSTYLE("M_CONTRO", OP_Joystick4Menu, &OP_AllControlsDef, 60, 30); +menu_t OP_ControlsDef = DEFAULTMENUSTYLE(MN_NONE, "M_CONTRO", OP_ControlsMenu, &OP_MainDef, 60, 30); +menu_t OP_AllControlsDef = CONTROLMENUSTYLE(MN_NONE, OP_AllControlsMenu, &OP_ControlsDef); +menu_t OP_Joystick1Def = DEFAULTMENUSTYLE(MN_NONE, "M_CONTRO", OP_Joystick1Menu, &OP_AllControlsDef, 60, 30); +menu_t OP_Joystick2Def = DEFAULTMENUSTYLE(MN_NONE, "M_CONTRO", OP_Joystick2Menu, &OP_AllControlsDef, 60, 30); +menu_t OP_Joystick3Def = DEFAULTMENUSTYLE(MN_NONE, "M_CONTRO", OP_Joystick3Menu, &OP_AllControlsDef, 60, 30); +menu_t OP_Joystick4Def = DEFAULTMENUSTYLE(MN_NONE, "M_CONTRO", OP_Joystick4Menu, &OP_AllControlsDef, 60, 30); menu_t OP_JoystickSetDef = { + MN_NONE, "M_CONTRO", sizeof (OP_JoystickSetMenu)/sizeof (menuitem_t), &OP_Joystick1Def, @@ -1977,6 +1985,7 @@ menu_t OP_JoystickSetDef = menu_t OP_VideoOptionsDef = { + MN_NONE, "M_VIDEO", sizeof(OP_VideoOptionsMenu)/sizeof(menuitem_t), &OP_MainDef, @@ -1989,6 +1998,7 @@ menu_t OP_VideoOptionsDef = menu_t OP_VideoModeDef = { + MN_NONE, "M_VIDEO", 1, &OP_VideoOptionsDef, @@ -2001,6 +2011,7 @@ menu_t OP_VideoModeDef = menu_t OP_SoundOptionsDef = { + MN_NONE, "M_SOUND", sizeof (OP_SoundOptionsMenu)/sizeof (menuitem_t), &OP_MainDef, @@ -2013,6 +2024,7 @@ menu_t OP_SoundOptionsDef = menu_t OP_HUDOptionsDef = { + MN_NONE, "M_HUD", sizeof (OP_HUDOptionsMenu)/sizeof (menuitem_t), &OP_MainDef, @@ -2023,19 +2035,20 @@ menu_t OP_HUDOptionsDef = NULL }; -menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_HUD", OP_ChatOptionsMenu, &OP_HUDOptionsDef, 30, 30); +menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_HUD", OP_ChatOptionsMenu, &OP_HUDOptionsDef, 30, 30); -menu_t OP_GameOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_GameOptionsMenu, &OP_MainDef, 30, 30); -menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 24, 30); +menu_t OP_GameOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_GAME", OP_GameOptionsMenu, &OP_MainDef, 30, 30); +menu_t OP_ServerOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_SERVER", OP_ServerOptionsMenu, &OP_MainDef, 24, 30); #ifndef NONET -menu_t OP_AdvServerOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_AdvServerOptionsMenu, &OP_ServerOptionsDef, 24, 30); +menu_t OP_AdvServerOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_SERVER", OP_AdvServerOptionsMenu, &OP_ServerOptionsDef, 24, 30); #endif -//menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30); -//menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE("M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30); -//menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE("M_GAME", OP_ChatOptionsMenu, &OP_GameOptionsDef, 30, 30); +//menu_t OP_NetgameOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_SERVER", OP_NetgameOptionsMenu, &OP_ServerOptionsDef, 30, 30); +//menu_t OP_GametypeOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_SERVER", OP_GametypeOptionsMenu, &OP_ServerOptionsDef, 30, 30); +//menu_t OP_ChatOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_GAME", OP_ChatOptionsMenu, &OP_GameOptionsDef, 30, 30); menu_t OP_MonitorToggleDef = { + MN_NONE, "M_GAME", sizeof (OP_MonitorToggleMenu)/sizeof (menuitem_t), &OP_GameOptionsDef, @@ -2047,23 +2060,23 @@ menu_t OP_MonitorToggleDef = }; #ifdef HWRENDER -menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE("M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); -menu_t OP_OpenGLColorDef = +static void M_OpenGLOptionsMenu(void) { - "M_VIDEO", - sizeof (OP_OpenGLColorMenu)/sizeof (menuitem_t), - &OP_OpenGLOptionsDef, - OP_OpenGLColorMenu, - M_OGL_DrawColorMenu, - 60, 40, - 0, - NULL -}; + if (rendermode == render_opengl) + M_SetupNextMenu(&OP_OpenGLOptionsDef); + else + M_StartMessage(M_GetText("You must be in OpenGL mode\nto access this menu.\n\n(Press a key)\n"), NULL, MM_NOTHING); +} + +menu_t OP_OpenGLOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_VIDEO", OP_OpenGLOptionsMenu, &OP_VideoOptionsDef, 30, 30); #endif -menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE("M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); -menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE("M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30); -menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE("M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30); -menu_t OP_EraseDataDef = DEFAULTMENUSTYLE("M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 30, 30); +menu_t OP_DataOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_DATA", OP_DataOptionsMenu, &OP_MainDef, 60, 30); +menu_t OP_ScreenshotOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_SCSHOT", OP_ScreenshotOptionsMenu, &OP_DataOptionsDef, 30, 30); +menu_t OP_AddonsOptionsDef = DEFAULTMENUSTYLE(MN_NONE, "M_ADDONS", OP_AddonsOptionsMenu, &OP_DataOptionsDef, 30, 30); +#ifdef HAVE_DISCORDRPC +menu_t OP_DiscordOptionsDef = DEFAULTMENUSTYLE(MN_NONE, NULL, OP_DiscordOptionsMenu, &OP_DataOptionsDef, 30, 30); +#endif +menu_t OP_EraseDataDef = DEFAULTMENUSTYLE(MN_NONE, "M_DATA", OP_EraseDataMenu, &OP_DataOptionsDef, 30, 30); // ========================================================================== // CVAR ONCHANGE EVENTS GO HERE @@ -2075,7 +2088,7 @@ static INT32 M_FindFirstMap(INT32 gtype); static INT32 M_GetFirstLevelInList(void); // Nextmap. Used for Time Attack. -static void Nextmap_OnChange(void) +void Nextmap_OnChange(void) { char *leveltitle; UINT8 active; @@ -2237,48 +2250,15 @@ static void Dummystaff_OnChange(void) // Newgametype. Used for gametype changes. static void Newgametype_OnChange(void) { - if (cv_nextmap.value && menuactive) + if (menuactive && cv_nextmap.value) { + INT32 gt = cv_newgametype.value; + if (!mapheaderinfo[cv_nextmap.value-1]) P_AllocMapHeader((INT16)(cv_nextmap.value-1)); - if ((cv_newgametype.value == GT_RACE && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_RACE)) || // SRB2kart - //(cv_newgametype.value == GT_COMPETITION && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_COMPETITION)) || - //(cv_newgametype.value == GT_RACE && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_RACE)) || - ((cv_newgametype.value == GT_MATCH || cv_newgametype.value == GT_TEAMMATCH) && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_MATCH))) // || - //((cv_newgametype.value == GT_TAG || cv_newgametype.value == GT_HIDEANDSEEK) && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_TAG)) || - //(cv_newgametype.value == GT_CTF && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & TOL_CTF))) - { - INT32 value = 0; - - switch (cv_newgametype.value) - { - case GT_COOP: - value = TOL_RACE; // SRB2kart - break; - case GT_COMPETITION: - value = TOL_COMPETITION; - break; - case GT_RACE: - value = TOL_RACE; - break; - case GT_MATCH: - case GT_TEAMMATCH: - value = TOL_MATCH; - break; - case GT_TAG: - case GT_HIDEANDSEEK: - value = TOL_TAG; - break; - case GT_CTF: - value = TOL_CTF; - break; - } - - CV_SetValue(&cv_nextmap, M_FindFirstMap(value)); - //CV_AddValue(&cv_nextmap, -1); - //CV_AddValue(&cv_nextmap, 1); - } + if (gt >= 0 && gt < gametypecount && !(mapheaderinfo[cv_nextmap.value-1]->typeoflevel & gametypetol[gt])) + CV_SetValue(&cv_nextmap, M_FindFirstMap(gt)); } } @@ -2317,6 +2297,11 @@ void Addons_option_Onchange(void) (cv_addons_option.value == 3 ? IT_CVAR|IT_STRING|IT_CV_STRING : IT_DISABLED); } +void Moviemode_option_Onchange(void) +{ + ; +} + // ========================================================================== // END ORGANIZATION STUFF. // ========================================================================== @@ -2324,6 +2309,64 @@ void Addons_option_Onchange(void) // current menudef menu_t *currentMenu = &MainDef; +// ========================================================================= +// MENU PRESENTATION PARAMETER HANDLING (BACKGROUNDS) +// ========================================================================= + +// menu IDs are equal to current/prevMenu in most cases, except MN_SPECIAL when we don't want to operate on Message, Pause, etc. +UINT32 prevMenuId = 0; +UINT32 activeMenuId = 0; + +menupres_t menupres[NUMMENUTYPES]; + +void M_InitMenuPresTables(void) +{ + INT32 i; + + // Called in d_main before SOC can get to the tables + // Set menupres defaults + for (i = 0; i < NUMMENUTYPES; i++) + { + // so-called "undefined" + menupres[i].fadestrength = -1; + menupres[i].hidetitlepics = -1; // inherits global hidetitlepics + menupres[i].ttmode = TTMODE_NONE; + menupres[i].ttscale = UINT8_MAX; + menupres[i].ttname[0] = 0; + menupres[i].ttx = INT16_MAX; + menupres[i].tty = INT16_MAX; + menupres[i].ttloop = INT16_MAX; + menupres[i].tttics = UINT16_MAX; + menupres[i].enterwipe = -1; + menupres[i].exitwipe = -1; + menupres[i].bgcolor = -1; + menupres[i].titlescrollxspeed = INT32_MAX; + menupres[i].titlescrollyspeed = INT32_MAX; + menupres[i].bghide = true; + // default true + menupres[i].enterbubble = true; + menupres[i].exitbubble = true; + + if (i != MN_MAIN) + { + menupres[i].muslooping = true; + } + if (i == MN_SP_TIMEATTACK) + strncpy(menupres[i].musname, "_recat", 7); + else if (i == MN_SP_NIGHTSATTACK) + strncpy(menupres[i].musname, "_nitat", 7); + else if (i == MN_SP_MARATHON) + strncpy(menupres[i].musname, "spec8", 6); + else if (i == MN_SP_PLAYER || i == MN_SR_PLAYER) + strncpy(menupres[i].musname, "_chsel", 7); + else if (i == MN_SR_SOUNDTEST) + { + *menupres[i].musname = '\0'; + menupres[i].musstop = true; + } + } +} + // ========================================================================= // BASIC MENU HANDLING // ========================================================================= @@ -2334,7 +2377,7 @@ static void M_ChangeCvar(INT32 choice) if (choice == -1) { - if (cv == &cv_playercolor) + if (cv == &cv_playercolor[0]) { SINT8 skinno = R_SkinAvailable(cv_chooseskin.string); if (skinno != -1) @@ -2351,6 +2394,11 @@ static void M_ChangeCvar(INT32 choice) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_INVISSLIDER) ||((currentMenu->menuitems[itemOn].status & IT_CVARTYPE) == IT_CV_NOMOD)) { + if (cv == &cv_digmusicvolume || cv == &cv_soundvolume) + { + choice *= 5; + } + CV_SetValue(cv,cv->value+choice); } else if (cv->flags & CV_FLOAT) @@ -2520,10 +2568,10 @@ boolean M_Responder(event_t *ev) { if (ev->type == ev_joystick && ev->data1 == 0 && joywait < I_GetTime()) { - const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone.value) >> FRACBITS; + const INT32 jdeadzone = ((JOYAXISRANGE-1) * cv_deadzone[0].value) >> FRACBITS; if (ev->data3 != INT32_MAX) { - if (Joystick.bGamepadStyle || abs(ev->data3) > jdeadzone) + if (Joystick[0].bGamepadStyle || abs(ev->data3) > jdeadzone) { if (ev->data3 < 0 && pjoyy >= 0) { @@ -2543,7 +2591,7 @@ boolean M_Responder(event_t *ev) if (ev->data2 != INT32_MAX) { - if (Joystick.bGamepadStyle || abs(ev->data2) > jdeadzone) + if (Joystick[0].bGamepadStyle || abs(ev->data2) > jdeadzone) { if (ev->data2 < 0 && pjoyx >= 0) { @@ -2595,9 +2643,9 @@ boolean M_Responder(event_t *ev) if (ch == -1) return false; - else if (ch == gamecontrol[gc_systemmenu][0] || ch == gamecontrol[gc_systemmenu][1]) // allow remappable ESC key + else if (ch == gamecontrol[0][gc_systemmenu][0] || ch == gamecontrol[0][gc_systemmenu][1]) // allow remappable ESC key ch = KEY_ESCAPE; - else if ((ch == gamecontrol[gc_accelerate][0] || ch == gamecontrol[gc_accelerate][1]) && ch >= KEY_MOUSE1) + else if ((ch == gamecontrol[0][gc_accelerate][0] || ch == gamecontrol[0][gc_accelerate][1]) && ch >= KEY_MOUSE1) ch = KEY_ENTER; // F-Keys @@ -2675,7 +2723,7 @@ boolean M_Responder(event_t *ev) return false; } - if ((ch == gamecontrol[gc_brake][0] || ch == gamecontrol[gc_brake][1]) && ch >= KEY_MOUSE1) // do this here, otherwise brake opens the menu mid-game + if ((ch == gamecontrol[0][gc_brake][0] || ch == gamecontrol[0][gc_brake][1]) && ch >= KEY_MOUSE1) // do this here, otherwise brake opens the menu mid-game ch = KEY_ESCAPE; routine = currentMenu->menuitems[itemOn].itemaction; @@ -2706,8 +2754,11 @@ boolean M_Responder(event_t *ev) else { // dirty hack: for customising controls, I want only buttons/keys, not moves - if (ev->type == ev_mouse || ev->type == ev_mouse2 || ev->type == ev_joystick - || ev->type == ev_joystick2 || ev->type == ev_joystick3 || ev->type == ev_joystick4) + if (ev->type == ev_mouse + || ev->type == ev_joystick + || ev->type == ev_joystick2 + || ev->type == ev_joystick3 + || ev->type == ev_joystick4) return true; if (routine) { @@ -3190,12 +3241,18 @@ void M_StartControlPanel(void) MPauseMenu[mpause_psetup].status = IT_DISABLED; MISC_ChangeTeamMenu[0].status = IT_DISABLED; MISC_ChangeSpectateMenu[0].status = IT_DISABLED; + // Reset these in case splitscreen messes things up + MPauseMenu[mpause_addons].alphaKey = 8; + MPauseMenu[mpause_scramble].alphaKey = 8; + MPauseMenu[mpause_switchmap].alphaKey = 24; + MPauseMenu[mpause_switchteam].alphaKey = 48; MPauseMenu[mpause_switchspectate].alphaKey = 48; MPauseMenu[mpause_options].alphaKey = 64; MPauseMenu[mpause_title].alphaKey = 80; MPauseMenu[mpause_quit].alphaKey = 88; + Dummymenuplayer_OnChange(); if ((server || IsPlayerAdmin(consoleplayer))) @@ -3267,6 +3324,19 @@ void M_StartControlPanel(void) MPauseMenu[mpause_spectate].status = IT_GRAYEDOUT; } +#ifdef HAVE_DISCORDRPC + { + UINT8 i; + + for (i = 0; i < mpause_discordrequests; i++) + MPauseMenu[i].alphaKey -= 8; + + MPauseMenu[mpause_discordrequests].alphaKey = MPauseMenu[i].alphaKey; + + M_RefreshPauseMenu(); + } +#endif + currentMenu = &MPauseDef; itemOn = mpause_continue; } @@ -3297,6 +3367,7 @@ void M_ClearMenus(boolean callexitmenufunc) if (currentMenu == &MessageDef) // Oh sod off! currentMenu = &MainDef; // Not like it matters menuactive = false; + hidetitlemap = false; } // @@ -3306,30 +3377,6 @@ void M_SetupNextMenu(menu_t *menudef) { INT16 i; -#ifdef HAVE_THREADS - if (currentMenu == &MP_RoomDef || currentMenu == &MP_ConnectDef) - { - I_lock_mutex(&ms_QueryId_mutex); - { - ms_QueryId++; - } - I_unlock_mutex(ms_QueryId_mutex); - } - - if (currentMenu == &MP_ConnectDef) - { - I_lock_mutex(&ms_ServerList_mutex); - { - if (ms_ServerList) - { - free(ms_ServerList); - ms_ServerList = NULL; - } - } - I_unlock_mutex(ms_ServerList_mutex); - } -#endif/*HAVE_THREADS*/ - if (currentMenu->quitroutine) { // If you're going from a menu to itself, why are you running the quitroutine? You're not quitting it! -SH @@ -3356,6 +3403,14 @@ void M_SetupNextMenu(menu_t *menudef) } } } + + hidetitlemap = false; +} + +// Guess I'll put this here, idk +boolean M_MouseNeeded(void) +{ + return false; } // @@ -3390,7 +3445,7 @@ void M_Ticker(void) setmodeneeded = vidm_previousmode + 1; } -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) I_lock_mutex(&ms_ServerList_mutex); { if (ms_ServerList) @@ -3428,8 +3483,6 @@ void M_Init(void) CV_RegisterVar(&cv_dummyscramble); CV_RegisterVar(&cv_dummyrings); CV_RegisterVar(&cv_dummylives); - CV_RegisterVar(&cv_dummycontinues); - //CV_RegisterVar(&cv_dummymares); CV_RegisterVar(&cv_dummystaff); CV_RegisterVar(&cv_dummygpdifficulty); @@ -3753,7 +3806,7 @@ static void M_DrawMapEmblems(INT32 mapnum, INT32 x, INT32 y) lasttype = curtype; if (emblem->collected) - V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), + V_DrawSmallMappedPatch(x, y, 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE)); else V_DrawSmallScaledPatch(x, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -3960,15 +4013,15 @@ static void M_DrawPauseMenu(void) if (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) { - if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) - V_DrawString(40, 28, highlightflags, va("%s %s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum)); + if (mapheaderinfo[gamemap-1]->actnum > 0) + V_DrawString(40, 28, highlightflags, va("%s %s %d", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl, mapheaderinfo[gamemap-1]->actnum)); else V_DrawString(40, 28, highlightflags, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->zonttl)); } else { - if (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) - V_DrawString(40, 28, highlightflags, va("%s %s", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum)); + if (mapheaderinfo[gamemap-1]->actnum > 0) + V_DrawString(40, 28, highlightflags, va("%s %d", mapheaderinfo[gamemap-1]->lvlttl, mapheaderinfo[gamemap-1]->actnum)); else V_DrawString(40, 28, highlightflags, mapheaderinfo[gamemap-1]->lvlttl); } @@ -4073,7 +4126,7 @@ static void M_DrawPauseMenu(void) continue; if (emblem->collected) - V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), + V_DrawSmallMappedPatch(40, 44 + (i*8), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE)); else V_DrawSmallScaledPatch(40, 44 + (i*8), 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -4097,6 +4150,25 @@ static void M_DrawPauseMenu(void) } #endif +#ifdef HAVE_DISCORDRPC + // kind of hackily baked in here + if (currentMenu == &MPauseDef && discordRequestList != NULL) + { + const tic_t freq = TICRATE/2; + + if ((leveltime % freq) >= freq/2) + { + V_DrawFixedPatch(204 * FRACUNIT, + (currentMenu->y + MPauseMenu[mpause_discordrequests].alphaKey - 1) * FRACUNIT, + FRACUNIT, + 0, + W_CachePatchName("K_REQUE2", PU_CACHE), + NULL + ); + } + } +#endif + M_DrawGenericMenu(); } @@ -4272,7 +4344,7 @@ static void M_PatchSkinNameTable(void) } } - j = R_SkinAvailable(cv_skin.string); + j = R_SkinAvailable(cv_skin[0].string); if (j == -1) j = 0; @@ -4349,22 +4421,7 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) if (M_MapLocked(mapnum+1)) return false; // not unlocked - /*if (gt == GT_COOP && (mapheaderinfo[mapnum]->typeoflevel & TOL_COOP)) - return true; - - if (gt == GT_COMPETITION && (mapheaderinfo[mapnum]->typeoflevel & TOL_COMPETITION)) - return true; - - if (gt == GT_CTF && (mapheaderinfo[mapnum]->typeoflevel & TOL_CTF)) - return true; - - if ((gt == GT_TAG || gt == GT_HIDEANDSEEK) && (mapheaderinfo[mapnum]->typeoflevel & TOL_TAG)) - return true;*/ - - if ((gt == GT_MATCH || gt == GT_TEAMMATCH) && (mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH)) - return true; - - if (gt == GT_RACE && (mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) + if (gt >= 0 && gt < gametypecount && mapheaderinfo[mapnum]->typeoflevel & gametypetol[gt]) return true; return false; @@ -4379,11 +4436,11 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) return true;*/ case LLM_TIMEATTACK: case LLM_BREAKTHECAPSULES: - /*if (!(mapheaderinfo[mapnum]->menuflags & LF2_RECORDATTACK)) - return false;*/ + if (!(mapheaderinfo[mapnum]->menuflags & LF2_TIMEATTACK)) + return false; if ((levellistmode == LLM_TIMEATTACK && !(mapheaderinfo[mapnum]->typeoflevel & TOL_RACE)) - || (levellistmode == LLM_BREAKTHECAPSULES && !(mapheaderinfo[mapnum]->typeoflevel & TOL_MATCH))) + || (levellistmode == LLM_BREAKTHECAPSULES && !(mapheaderinfo[mapnum]->typeoflevel & TOL_BATTLE))) return false; if (M_MapLocked(mapnum+1)) @@ -4395,11 +4452,8 @@ boolean M_CanShowLevelInList(INT32 mapnum, INT32 gt) if (mapheaderinfo[mapnum]->menuflags & LF2_HIDEINMENU) return false; // map hell - /*if (mapheaderinfo[mapnum]->menuflags & LF2_NOVISITNEEDED) - return true; - - if (!mapvisited[mapnum]) - return false;*/ + if ((mapheaderinfo[mapnum]->menuflags & LF2_VISITNEEDED) && !mapvisited[mapnum]) + return false; return true; default: @@ -4441,11 +4495,12 @@ static void M_DrawMessageMenu(void); static menuitem_t MessageMenu[] = { // TO HACK - {0,NULL, NULL, NULL,0} + {0,NULL,NULL,NULL,0} }; menu_t MessageDef = { + MN_NONE, // id NULL, // title 1, // # of menu items NULL, // previous menu (TO HACK) @@ -5209,12 +5264,6 @@ static void M_HandleAddons(INT32 choice) M_AddonExec(KEY_ENTER); break; case EXT_LUA: -#ifndef HAVE_BLUA - S_StartSound(NULL, sfx_s26d); - M_StartMessage(va("%c%s\x80\nThis version of SRB2Kart does not\nhave support for .lua files.\n\n(Press a key)\n", ('\x80' + (highlightflags>>V_CHARCOLORSHIFT)), dirmenu[dir_on[menudepthleft]]+DIR_STRING),NULL,MM_NOTHING); - break; -#endif - // else intentional fallthrough case EXT_SOC: case EXT_WAD: #ifdef USE_KART @@ -5315,6 +5364,7 @@ void M_ReplayHut(INT32 choice) menuactive = true; M_SetupNextMenu(&MISC_ReplayHutDef); G_SetGamestate(GS_TIMEATTACK); + titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please demo.rewinding = false; CL_ClearRewinds(); @@ -5467,7 +5517,7 @@ static void DrawReplayHutReplayInfo(void) case MD_OUTDATED: V_DrawThinString(17, 64, V_SNAPTOTOP|V_ALLOWLOWERCASE|V_TRANSLUCENT|highlightflags, "Recorded on an outdated version."); - /*fallthru*/ + /* FALLTHRU */ default: // Draw level stuff x = 15; y = 15; @@ -5542,9 +5592,9 @@ static void DrawReplayHutReplayInfo(void) // Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this) // and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid. - if (demolist[dir_on[menudepthleft]].standings[0].skin != 0xFF && W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[0].skin].facewant) != LUMPERROR) + if (demolist[dir_on[menudepthleft]].standings[0].skin != 0xFF) { - patch = facewantprefix[demolist[dir_on[menudepthleft]].standings[0].skin]; + patch = faceprefix[demolist[dir_on[menudepthleft]].standings[0].skin][FACE_WANTED]; colormap = R_GetTranslationColormap( demolist[dir_on[menudepthleft]].standings[0].skin, demolist[dir_on[menudepthleft]].standings[0].color, @@ -5744,9 +5794,9 @@ static void M_DrawReplayStartMenu(void) // Lat: 08/06/2020: For some reason missing skins have their value set to 255 (don't even ask me why I didn't write this) // and for an even STRANGER reason this passes the first check below, so we're going to make sure that the skin here ISN'T 255 before we do anything stupid. - if (demolist[dir_on[menudepthleft]].standings[i].skin != 0xFF && W_CheckNumForName(skins[demolist[dir_on[menudepthleft]].standings[i].skin].facerank) != LUMPERROR) + if (demolist[dir_on[menudepthleft]].standings[i].skin != 0xFF) { - patch = facerankprefix[demolist[dir_on[menudepthleft]].standings[i].skin]; + patch = faceprefix[demolist[dir_on[menudepthleft]].standings[i].skin][FACE_RANK]; colormap = R_GetTranslationColormap( demolist[dir_on[menudepthleft]].standings[i].skin, demolist[dir_on[menudepthleft]].standings[i].color, @@ -5920,7 +5970,7 @@ static void M_DrawPlaybackMenu(void) { INT32 ply = displayplayers[i - playback_view1]; - icon = facerankprefix[players[ply].skin]; + icon = faceprefix[players[ply].skin][FACE_RANK]; if (i != itemOn) inactivemap = R_GetTranslationColormap(players[ply].skin, players[ply].skincolor, GTC_MENUCACHE); } @@ -6121,20 +6171,17 @@ static void M_PlaybackQuit(INT32 choice) static void M_PandorasBox(INT32 choice) { (void)choice; - CV_StealthSetValue(&cv_dummyrings, max(players[consoleplayer].health - 1, 0)); + CV_StealthSetValue(&cv_dummyrings, players[consoleplayer].rings); CV_StealthSetValue(&cv_dummylives, players[consoleplayer].lives); - CV_StealthSetValue(&cv_dummycontinues, players[consoleplayer].continues); M_SetupNextMenu(&SR_PandoraDef); } static boolean M_ExitPandorasBox(void) { - if (cv_dummyrings.value != max(players[consoleplayer].health - 1, 0)) + if (cv_dummyrings.value != players[consoleplayer].rings) COM_ImmedExecute(va("setrings %d", cv_dummyrings.value)); if (cv_dummylives.value != players[consoleplayer].lives) COM_ImmedExecute(va("setlives %d", cv_dummylives.value)); - if (cv_dummycontinues.value != players[consoleplayer].continues) - COM_ImmedExecute(va("setcontinues %d", cv_dummycontinues.value)); return true; } @@ -6253,7 +6300,12 @@ static void M_Options(INT32 choice) OP_MainMenu[4].status = OP_MainMenu[5].status = (Playing() && !(server || IsPlayerAdmin(consoleplayer))) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); OP_MainMenu[8].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_CALL); // Play credits + +#ifdef HAVE_DISCORDRPC + OP_DataOptionsMenu[4].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); // Erase data +#else OP_DataOptionsMenu[3].status = (Playing()) ? (IT_GRAYEDOUT) : (IT_STRING|IT_SUBMENU); // Erase data +#endif OP_GameOptionsMenu[3].status = (M_SecretUnlocked(SECRET_ENCORE)) ? (IT_CVAR|IT_STRING) : IT_SECRET; // cv_kartencore @@ -6294,6 +6346,20 @@ static void M_SelectableClearMenus(INT32 choice) M_ClearMenus(true); } +void M_RefreshPauseMenu(void) +{ +#ifdef HAVE_DISCORDRPC + if (discordRequestList != NULL) + { + MPauseMenu[mpause_discordrequests].status = IT_STRING | IT_SUBMENU; + } + else + { + MPauseMenu[mpause_discordrequests].status = IT_GRAYEDOUT; + } +#endif +} + // ====== // CHEATS // ====== @@ -6381,13 +6447,8 @@ static char *M_GetConditionString(condition_t cond) return va("Beat game %d times", cond.requirement); else return va("Beat the game"); - case UC_ALLEMERALDS: - if (cond.requirement > 1) - return va("Beat game w/ all emeralds %d times", cond.requirement); - else - return va("Beat game w/ all emeralds"); case UC_OVERALLTIME: - return va("Get overall time of %i:%02i:%02i", + return va("Get overall Time Attack of %i:%02i:%02i", G_TicsToHours(cond.requirement), G_TicsToMinutes(cond.requirement, false), G_TicsToSeconds(cond.requirement)); @@ -6395,8 +6456,8 @@ static char *M_GetConditionString(condition_t cond) return va("Visit %s", G_BuildMapTitle(cond.requirement-1)); case UC_MAPBEATEN: return va("Beat %s", G_BuildMapTitle(cond.requirement-1)); - case UC_MAPALLEMERALDS: - return va("Beat %s w/ all emeralds", G_BuildMapTitle(cond.requirement-1)); + case UC_MAPENCORE: + return va("Beat %s in Encore Mode", G_BuildMapTitle(cond.requirement-1)); case UC_MAPTIME: return va("Beat %s in %i:%02i.%02i", G_BuildMapTitle(cond.extrainfo1-1), G_TicsToMinutes(cond.requirement, true), @@ -6493,13 +6554,13 @@ static void M_DrawEmblemHints(void) for (i = 0; i < numemblems; i++) { emblem = &emblemlocations[i]; - if (emblem->level != gamemap || emblem->type > ET_SKIN) + if (emblem->level != gamemap || emblem->type != ET_GLOBAL) continue; if (emblem->collected) { collected = recommendedflags; - V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem), PU_CACHE), + V_DrawMappedPatch(12, 12+(28*j), 0, W_CachePatchName(M_GetEmblemPatch(emblem, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(emblem), GTC_MENUCACHE)); } else @@ -6543,17 +6604,10 @@ static void M_DrawSkyRoom(void) (digital_disabled ? warningflags : highlightflags), (digital_disabled ? "OFF" : "ON")); - /*V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, - currentMenu->y+currentMenu->menuitems[5].alphaKey, - (midi_disabled ? warningflags : highlightflags), - (midi_disabled ? "OFF" : "ON"));*/ - if (itemOn == 0) lengthstring = 8*(sound_disabled ? 3 : 2); else if (itemOn == 2) lengthstring = 8*(digital_disabled ? 3 : 2); - /*else if (itemOn == 5) - lengthstring = 8*(midi_disabled ? 3 : 2);*/ } for (i = 0; i < currentMenu->numitems; ++i) @@ -7439,8 +7493,7 @@ static void M_Statistics(INT32 choice) if (!mapheaderinfo[i] || mapheaderinfo[i]->lvlttl[0] == '\0') continue; - if (!(mapheaderinfo[i]->typeoflevel & TOL_RACE) // TOL_SP - || (mapheaderinfo[i]->menuflags & (LF2_HIDEINSTATS|LF2_HIDEINMENU))) + if (mapheaderinfo[i]->menuflags & (LF2_HIDEINSTATS|LF2_HIDEINMENU)) continue; if (M_MapLocked(i+1)) // !mapvisited[i] @@ -7488,13 +7541,13 @@ static void M_DrawStatsMaps(int location) M_DrawMapEmblems(mnum+1, 295, y); if (mapheaderinfo[mnum]->levelflags & LF_NOZONE) - V_DrawString(20, y, 0, va("%s %s", + V_DrawString(20, y, 0, va("%s %d", mapheaderinfo[mnum]->lvlttl, mapheaderinfo[mnum]->actnum)); else - V_DrawString(20, y, 0, va("%s %s %s", + V_DrawString(20, y, 0, va("%s %s %d", mapheaderinfo[mnum]->lvlttl, - (mapheaderinfo[mnum]->zonttl[0] ? mapheaderinfo[mnum]->zonttl : "ZONE"), + (mapheaderinfo[mnum]->zonttl[0] ? mapheaderinfo[mnum]->zonttl : "Zone"), mapheaderinfo[mnum]->actnum)); y += 8; @@ -7534,7 +7587,7 @@ static void M_DrawStatsMaps(int location) exemblem = &extraemblems[i]; if (exemblem->collected) - V_DrawSmallMappedPatch(295, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem), PU_CACHE), + V_DrawSmallMappedPatch(295, y, 0, W_CachePatchName(M_GetExtraEmblemPatch(exemblem, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetExtraEmblemColor(exemblem), GTC_MENUCACHE)); else V_DrawSmallScaledPatch(295, y, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -7579,7 +7632,7 @@ static void M_DrawLevelStats(void) for (i = 0; i < NUMMAPS; i++) { - if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_RECORDATTACK)) + if (!mapheaderinfo[i] || !(mapheaderinfo[i]->menuflags & LF2_TIMEATTACK)) continue; if (!mainrecords[i] || mainrecords[i]->time <= 0) @@ -7677,21 +7730,19 @@ static void M_StartGrandPrix(INT32 choice) switch (cv_dummygpdifficulty.value) { - case 0: - grandprixinfo.gamespeed = KARTSPEED_EASY; + case KARTSPEED_EASY: + case KARTSPEED_NORMAL: + case KARTSPEED_HARD: + grandprixinfo.gamespeed = cv_dummygpdifficulty.value; break; - case 1: - default: - grandprixinfo.gamespeed = KARTSPEED_NORMAL; - break; - case 2: - grandprixinfo.gamespeed = KARTSPEED_HARD; - break; - case 3: + case KARTGP_MASTER: grandprixinfo.gamespeed = KARTSPEED_HARD; grandprixinfo.masterbots = true; break; - + default: + CONS_Alert(CONS_WARNING, "Invalid GP difficulty\n"); + grandprixinfo.gamespeed = KARTSPEED_NORMAL; + break; } grandprixinfo.encore = (boolean)(cv_dummygpencore.value); @@ -7747,10 +7798,9 @@ void M_DrawTimeAttackMenu(void) y = currentMenu->y; // Character face! - if (W_CheckNumForName(skins[cv_chooseskin.value-1].facewant) != LUMPERROR) { - UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor.value, GTC_MENUCACHE); - V_DrawMappedPatch(BASEVIDWIDTH-x - SHORT(facewantprefix[cv_chooseskin.value-1]->width), y, 0, facewantprefix[cv_chooseskin.value-1], colormap); + UINT8 *colormap = R_GetTranslationColormap(cv_chooseskin.value-1, cv_playercolor[0].value, GTC_MENUCACHE); + V_DrawMappedPatch(BASEVIDWIDTH-x - SHORT(faceprefix[cv_chooseskin.value-1][FACE_WANTED]->width), y, 0, faceprefix[cv_chooseskin.value-1][FACE_WANTED], colormap); } for (i = 0; i < currentMenu->numitems; ++i) @@ -7876,7 +7926,7 @@ void M_DrawTimeAttackMenu(void) } if (em->collected) - V_DrawMappedPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), + V_DrawMappedPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName(M_GetEmblemPatch(em, false), PU_CACHE), R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_MENUCACHE)); else V_DrawScaledPatch(BASEVIDWIDTH - 64 - 24, y+48, 0, W_CachePatchName("NEEDIT", PU_CACHE)); @@ -7938,6 +7988,7 @@ static void M_TimeAttack(INT32 choice) M_SetupNextMenu(&SP_TimeAttackDef); G_SetGamestate(GS_TIMEATTACK); + titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please if (cv_nextmap.value) Nextmap_OnChange(); @@ -7970,6 +8021,7 @@ static void M_BreakTheCapsules(INT32 choice) M_SetupNextMenu(&SP_TimeAttackDef); G_SetGamestate(GS_TIMEATTACK); + titlemapinaction = TITLEMAP_OFF; // Nope don't give us HOMs please if (cv_nextmap.value) Nextmap_OnChange(); @@ -7988,161 +8040,6 @@ static boolean M_QuitTimeAttackMenu(void) return true; } -// Drawing function for Nights Attack -/*void M_DrawNightsAttackMenu(void) -{ - patch_t *PictureOfLevel; - lumpnum_t lumpnum; - char beststr[40]; - - S_ChangeMusicInternal("racent", true); // Eww, but needed for when user hits escape during demo playback - - V_DrawPatchFill(W_CachePatchName("SRB2BACK", PU_CACHE)); - - // draw menu (everything else goes on top of it) - M_DrawGenericMenu(); - - // A 160x100 image of the level as entry MAPxxP - lumpnum = W_CheckNumForName(va("%sP", G_BuildMapName(cv_nextmap.value))); - - if (lumpnum != LUMPERROR) - PictureOfLevel = W_CachePatchNum(lumpnum, PU_CACHE); - else - PictureOfLevel = W_CachePatchName("BLANKLVL", PU_CACHE); - - V_DrawSmallScaledPatch(90, 28, 0, PictureOfLevel); - - // Level record list - if (cv_nextmap.value) - { - emblem_t *em; - INT32 yHeight; - - UINT8 bestoverall = G_GetBestNightsGrade(cv_nextmap.value, 0); - UINT8 bestgrade = G_GetBestNightsGrade(cv_nextmap.value, cv_dummymares.value); - UINT32 bestscore = G_GetBestNightsScore(cv_nextmap.value, cv_dummymares.value); - tic_t besttime = G_GetBestNightsTime(cv_nextmap.value, cv_dummymares.value); - - if (P_HasGrades(cv_nextmap.value, 0)) - V_DrawScaledPatch(200, 28 + 8, 0, ngradeletters[bestoverall]); - - if (currentMenu == &SP_NightsAttackDef) - { - if (P_HasGrades(cv_nextmap.value, cv_dummymares.value)) - { - V_DrawString(160-88, 112, highlightflags, "BEST GRADE:"); - V_DrawSmallScaledPatch(160 + 86 - (ngradeletters[bestgrade]->width/2), - 112 + 8 - (ngradeletters[bestgrade]->height/2), - 0, ngradeletters[bestgrade]); - } - - if (!bestscore) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%u", bestscore); - - V_DrawString(160 - 88, 122, highlightflags, "BEST SCORE:"); - V_DrawRightAlignedString(160 + 88, 122, V_ALLOWLOWERCASE, beststr); - - if (besttime == UINT32_MAX) - sprintf(beststr, "(none)"); - else - sprintf(beststr, "%i:%02i.%02i", G_TicsToMinutes(besttime, true), - G_TicsToSeconds(besttime), - G_TicsToCentiseconds(besttime)); - - V_DrawString(160-88, 132, highlightflags, "BEST TIME:"); - V_DrawRightAlignedString(160+88, 132, V_ALLOWLOWERCASE, beststr); - - if (cv_dummymares.value == 0) { - // Draw record emblems. - em = M_GetLevelEmblems(cv_nextmap.value); - while (em) - { - switch (em->type) - { - case ET_NGRADE: yHeight = 112; break; - case ET_NTIME: yHeight = 132; break; - default: - goto skipThisOne; - } - - if (em->collected) - V_DrawSmallMappedPatch(160+88, yHeight, 0, W_CachePatchName(M_GetEmblemPatch(em), PU_CACHE), - R_GetTranslationColormap(TC_DEFAULT, M_GetEmblemColor(em), GTC_MENUCACHE)); - else - V_DrawSmallScaledPatch(160+88, yHeight, 0, W_CachePatchName("NEEDIT", PU_CACHE)); - - skipThisOne: - em = M_GetLevelEmblems(-1); - } - } - } - // ALWAYS DRAW level name even when not on this menu! - else - { - consvar_t *ncv; - INT32 x = SP_NightsAttackDef.x; - INT32 y = SP_NightsAttackDef.y; - - ncv = (consvar_t *)SP_NightsAttackMenu[0].itemaction; - V_DrawString(x, y + SP_NightsAttackMenu[0].alphaKey, V_TRANSLUCENT, SP_NightsAttackMenu[0].text); - V_DrawString(BASEVIDWIDTH - x - V_StringWidth(ncv->string, 0), - y + SP_NightsAttackMenu[0].alphaKey, highlightflags|V_TRANSLUCENT, ncv->string); - } - } -}*/ - -// Going to Nights Attack menu... -/*static void M_BreakTheCapsules(INT32 choice) -{ - (void)choice; - - memset(skins_cons_t, 0, sizeof (skins_cons_t)); - - levellistmode = LLM_BREAKTHECAPSULES; // Don't be dependent on cv_newgametype - - if (M_CountLevelsToShowInList() == 0) - { - M_StartMessage(M_GetText("No NiGHTS-attackable levels found.\n"),NULL,MM_NOTHING); - return; - } - - // This is really just to make sure Sonic is the played character, just in case - M_PatchSkinNameTable(); - - M_PrepareLevelSelect(); - M_SetupNextMenu(&SP_NightsAttackDef); - Nextmap_OnChange(); - - itemOn = nastart; // "Start" is selected. - - G_SetGamestate(GS_TIMEATTACK); - S_ChangeMusicInternal("racent", true); -}*/ - -// Player has selected the "START" from the nights attack screen -/*static void M_ChooseNightsAttack(INT32 choice) -{ - char nameofdemo[256]; - (void)choice; - emeralds = 0; - M_ClearMenus(true); - modeattacking = ATTACKING_CAPSULES; - - I_mkdir(va("%s"PATHSEP"replay", srb2home), 0755); - I_mkdir(va("%s"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder), 0755); - - snprintf(nameofdemo, sizeof nameofdemo, "replay"PATHSEP"%s"PATHSEP"%s-last", timeattackfolder, G_BuildMapName(cv_nextmap.value)); - - if (!cv_autorecord.value) - remove(va("%s"PATHSEP"%s.lmp", srb2home, nameofdemo)); - else - G_RecordDemo(nameofdemo); - - G_DeferedInitNew(false, G_BuildMapName(cv_nextmap.value), 0, 0, false); -}*/ - // Player has selected the "START" from the time attack screen static void M_ChooseTimeAttack(INT32 choice) { @@ -8152,7 +8049,7 @@ static void M_ChooseTimeAttack(INT32 choice) (void)choice; emeralds = 0; M_ClearMenus(true); - modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD); + modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_TIME); gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s", srb2home, timeattackfolder); @@ -8203,7 +8100,7 @@ static void M_HandleStaffReplay(INT32 choice) if (l == LUMPERROR) break; M_ClearMenus(true); - modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD); + modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_TIME); demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed G_DoPlayDemo(va("%sS%02u",G_BuildMapName(cv_nextmap.value),cv_dummystaff.value)); break; @@ -8224,7 +8121,7 @@ static void M_ReplayTimeAttack(INT32 choice) { const char *which; M_ClearMenus(true); - modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_RECORD); // set modeattacking before G_DoPlayDemo so the map loader knows + modeattacking = (levellistmode == LLM_BREAKTHECAPSULES ? ATTACKING_CAPSULES : ATTACKING_TIME); // set modeattacking before G_DoPlayDemo so the map loader knows demo.loadfiles = false; demo.ignorefiles = true; // Just assume that record attack replays have the files needed if (currentMenu == &SP_ReplayDef) @@ -8427,7 +8324,118 @@ static void M_EndGame(INT32 choice) // Connect Menu //=========================================================================== -#define SERVERHEADERHEIGHT 44 +void +M_SetWaitingMode (int mode) +{ +#ifdef HAVE_THREADS + I_lock_mutex(&m_menu_mutex); +#endif + { + m_waiting_mode = mode; + } +#ifdef HAVE_THREADS + I_unlock_mutex(m_menu_mutex); +#endif +} + +int +M_GetWaitingMode (void) +{ + int mode; + +#ifdef HAVE_THREADS + I_lock_mutex(&m_menu_mutex); +#endif + { + mode = m_waiting_mode; + } +#ifdef HAVE_THREADS + I_unlock_mutex(m_menu_mutex); +#endif + + return mode; +} + +#ifdef MASTERSERVER +#ifdef HAVE_THREADS +static void +Spawn_masterserver_thread (const char *name, void (*thread)(int*)) +{ + int *id = malloc(sizeof *id); + + I_lock_mutex(&ms_QueryId_mutex); + { + *id = ms_QueryId; + } + I_unlock_mutex(ms_QueryId_mutex); + + I_spawn_thread(name, (I_thread_fn)thread, id); +} + +static int +Same_instance (int id) +{ + int okay; + + I_lock_mutex(&ms_QueryId_mutex); + { + okay = ( id == ms_QueryId ); + } + I_unlock_mutex(ms_QueryId_mutex); + + return okay; +} +#endif/*HAVE_THREADS*/ + +static void +Fetch_servers_thread (int *id) +{ + msg_server_t * server_list; + + (void)id; + + M_SetWaitingMode(M_WAITING_SERVERS); + +#ifdef HAVE_THREADS + server_list = GetShortServersList(*id); +#else + server_list = GetShortServersList(0); +#endif + + if (server_list) + { +#ifdef HAVE_THREADS + if (Same_instance(*id)) +#endif + { + M_SetWaitingMode(M_NOT_WAITING); + +#ifdef HAVE_THREADS + I_lock_mutex(&ms_ServerList_mutex); + { + ms_ServerList = server_list; + } + I_unlock_mutex(ms_ServerList_mutex); +#else + CL_QueryServerList(server_list); + free(server_list); +#endif + } +#ifdef HAVE_THREADS + else + { + free(server_list); + } +#endif + } + +#ifdef HAVE_THREADS + free(id); +#endif +} +#endif/*MASTERSERVER*/ + +#define SERVERHEADERHEIGHT 36 #define SERVERLINEHEIGHT 12 #define S_LINEY(n) currentMenu->y + SERVERHEADERHEIGHT + (n * SERVERLINEHEIGHT) @@ -8499,86 +8507,28 @@ static void M_Refresh(INT32 choice) if (rendermode == render_soft) I_FinishUpdate(); // page flip or blit buffer - // note: this is the one case where 0 is a valid room number - // because it corresponds to "All" - CL_UpdateServerList(!(ms_RoomId < 0), ms_RoomId); - // first page of servers serverlistpage = 0; -} -static INT32 menuRoomIndex = 0; - -static void M_DrawRoomMenu(void) -{ - static int frame = -12; - int dot_frame; - char text[4]; - - const char *rmotd; - const char *waiting_message; - - int dots; - - if (m_waiting_mode) - { - dot_frame = frame / 4; - dots = dot_frame + 3; - - strcpy(text, " "); - - if (dots > 0) - { - if (dot_frame < 0) - dot_frame = 0; - - strncpy(&text[dot_frame], "...", min(dots, 3 - dot_frame)); - } - - if (++frame == 12) - frame = -12; - - currentMenu->menuitems[0].text = text; - } - - // use generic drawer for cursor, items and title - M_DrawGenericMenu(); - - V_DrawString(currentMenu->x - 16, currentMenu->y, highlightflags, M_GetText("Select a room")); - - if (m_waiting_mode == M_NOT_WAITING) - { - M_DrawTextBox(144, 24, 20, 20); - - if (itemOn == 0) - rmotd = M_GetText("Don't connect to the Master Server."); - else - rmotd = room_list[itemOn-1].motd; - - rmotd = V_WordWrap(0, 20*8, 0, rmotd); - V_DrawString(144+8, 32, V_ALLOWLOWERCASE|V_RETURN8, rmotd); - } - - if (m_waiting_mode) - { - // Display a little "please wait" message. - M_DrawTextBox(52, BASEVIDHEIGHT/2-10, 25, 3); - if (m_waiting_mode == M_WAITING_VERSION) - waiting_message = "Checking for updates..."; - else - waiting_message = "Fetching room info..."; - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, 0, waiting_message); - V_DrawCenteredString(BASEVIDWIDTH/2, (BASEVIDHEIGHT/2)+12, 0, "Please wait."); - } +#ifdef MASTERSERVER +#ifdef HAVE_THREADS + Spawn_masterserver_thread("fetch-servers", Fetch_servers_thread); +#else/*HAVE_THREADS*/ + Fetch_servers_thread(NULL); +#endif/*HAVE_THREADS*/ +#else/*MASTERSERVER*/ + CL_UpdateServerList(); +#endif/*MASTERSERVER*/ } static void M_DrawConnectMenu(void) { UINT16 i; - const char *gt = "Unknown"; - const char *spd = ""; + //const char *gt = "Unknown"; + //const char *spd = ""; const char *pwr = "----"; INT32 numPages = (serverlistcount+(SERVERS_PER_PAGE-1))/SERVERS_PER_PAGE; + int waiting; for (i = FIRSTSERVERLINE; i < min(localservercount, SERVERS_PER_PAGE)+FIRSTSERVERLINE; i++) MP_ConnectMenu[i].status = IT_STRING | IT_SPACE; @@ -8586,20 +8536,12 @@ static void M_DrawConnectMenu(void) if (!numPages) numPages = 1; - // Room name - if (ms_RoomId < 0) - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ConnectMenu[mp_connect_room].alphaKey, - highlightflags, (itemOn == mp_connect_room) ? "" : ""); - else - V_DrawRightAlignedString(BASEVIDWIDTH - currentMenu->x, currentMenu->y + MP_ServerMenu[mp_server_room].alphaKey, - highlightflags, room_list[menuRoomIndex].name); -#undef mp_server_room - } -#endif } static void M_MapChange(INT32 choice) @@ -9185,7 +9034,6 @@ static void M_StartServerMenu(INT32 choice) (void)choice; levellistmode = LLM_CREATESERVER; M_PrepareLevelSelect(); - ms_RoomId = -1; M_SetupNextMenu(&MP_ServerDef); } @@ -9253,25 +9101,8 @@ Update the maxplayers label... while (++i <= 4) { - switch (i) - { - default: - pskin = R_SkinAvailable(cv_skin.string); - pcol = cv_playercolor.value; - break; - case 2: - pskin = R_SkinAvailable(cv_skin2.string); - pcol = cv_playercolor2.value; - break; - case 3: - pskin = R_SkinAvailable(cv_skin3.string); - pcol = cv_playercolor3.value; - break; - case 4: - pskin = R_SkinAvailable(cv_skin4.string); - pcol = cv_playercolor4.value; - break; - } + pskin = R_SkinAvailable(cv_skin[i-1].string); + pcol = cv_playercolor[i-1].value; if (pskin >= MAXSKINS) pskin = 0; @@ -9281,7 +9112,7 @@ Update the maxplayers label... colmap = R_GetTranslationColormap(pskin, pcol, GTC_MENUCACHE); - V_DrawFixedPatch(x<color].name, 0); + V_DrawString(BASEVIDWIDTH - mx - st, my + 152, highlightflags|V_ALLOWLOWERCASE, skincolors[setupm_fakecolor->color].name); // SRB2kart if (itemOn == 3) { V_DrawCharacter(BASEVIDWIDTH - mx - 10 - st - (skullAnimCounter/5), my + 152, @@ -9618,44 +9450,57 @@ static void M_DrawSetupMultiPlayerMenu(void) V_DrawFixedPatch(((BASEVIDWIDTH - mx - 80) + ((speed-1)*8))<color) + V_DrawFixedPatch(((BASEVIDWIDTH - mx - 80) + ((speed-1)*8))<color, GTC_MENUCACHE)); // 2.2 color bar backported with permission #define charw 72 #define indexwidth 8 { - const INT32 colwidth = ((BASEVIDWIDTH-(2*mx))-charw)/(2*indexwidth); - INT32 j = -colwidth; - INT16 col = setupm_fakecolor - colwidth; + const INT32 numcolors = (250-charw)/(2*indexwidth); // Number of colors per side INT32 x = mx; - INT32 w = indexwidth; + INT32 w = indexwidth; // Width of a singular color block + menucolor_t *mc = setupm_fakecolor->prev; // Last accessed color UINT8 h; - while (col < 1) - col += MAXSKINCOLORS-1; - while (j <= colwidth) - { - if (!(j++)) - w = charw; - else - w = indexwidth; + // Draw color in the middle + x += numcolors*w; + for (h = 0; h < 16; h++) + V_DrawFill(x, my+162+h, charw, 1, skincolors[setupm_fakecolor->color].ramp[h]); + + //Draw colors from middle to left + for (i=0; icolor].accessible) + mc = mc->prev; for (h = 0; h < 16; h++) - V_DrawFill(x, my+162+h, w, 1, colortranslations[col][h]); - if (++col >= MAXSKINCOLORS) - col -= MAXSKINCOLORS-1; + V_DrawFill(x, my+162+h, w, 1, skincolors[mc->color].ramp[h]); + mc = mc->prev; + } + + // Draw colors from middle to right + mc = setupm_fakecolor->next; + x += numcolors*w + charw; + for (i=0; icolor].accessible) + mc = mc->next; + for (h = 0; h < 16; h++) + V_DrawFill(x, my+162+h, w, 1, skincolors[mc->color].ramp[h]); x += w; + mc = mc->next; } } #undef indexwidth // character bar, ripped off the color bar :V - if (setupm_fakecolor) // inverse should never happen + if (setupm_fakecolor->color) // inverse should never happen #define iconwidth 32 { const INT32 icons = 4; INT32 k = -icons; - INT16 col = setupm_fakeskin - icons; + INT16 col = (setupm_fakeskin - icons) % numskins; INT32 x = BASEVIDWIDTH/2 - ((icons+1)*24) - 4; fixed_t scale = FRACUNIT/2; INT32 offx = 8, offy = 8; @@ -9678,19 +9523,20 @@ static void M_DrawSetupMultiPlayerMenu(void) if (!(k++)) { scale = FRACUNIT; - face = facewantprefix[col]; + face = faceprefix[col][FACE_WANTED]; offx = 12; offy = 0; } else { scale = FRACUNIT/2; - face = facerankprefix[col]; + face = faceprefix[col][FACE_RANK]; offx = 8; offy = 8; } - colmap = R_GetTranslationColormap(col, setupm_fakecolor, GTC_MENUCACHE); - V_DrawFixedPatch((x+offx)<color, GTC_MENUCACHE); + if (face) + V_DrawFixedPatch((x+offx)<= numskins) @@ -9712,10 +9558,7 @@ static void M_DrawSetupMultiPlayerMenu(void) } // skin 0 is default player sprite - if (R_SkinAvailable(skins[setupm_fakeskin].name) != -1) - sprdef = &skins[R_SkinAvailable(skins[setupm_fakeskin].name)].spritedef; - else - sprdef = &skins[0].spritedef; + sprdef = &skins[setupm_fakeskin].sprites[multi_spr2]; if (!sprdef->numframes) // No frames ?? return; // Can't render! @@ -9733,9 +9576,9 @@ static void M_DrawSetupMultiPlayerMenu(void) V_DrawFill(mx + 43 - (charw/2), my+65, charw, 84, 159); // draw player sprite - if (setupm_fakecolor) // inverse should never happen + if (setupm_fakecolor->color) // inverse should never happen { - UINT8 *colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor, GTC_MENUCACHE); + UINT8 *colormap = R_GetTranslationColormap(setupm_fakeskin, setupm_fakecolor->color, GTC_MENUCACHE); if (skins[setupm_fakeskin].flags & SF_HIRES) { @@ -9790,7 +9633,7 @@ static void M_DrawSetupMultiPlayerMenu(void) // @TODO: Reminder that followers on the menu right now do NOT support the 'followercolor' command, considering this whole menu is getting remade anyway, I see no point in incorporating it in right now. // draw follower sprite - if (setupm_fakecolor) // inverse should never happen + if (setupm_fakecolor->color) // inverse should never happen { // Fake the follower's in game appearance by now also applying some of its variables! coolio, eh? @@ -9799,7 +9642,7 @@ static void M_DrawSetupMultiPlayerMenu(void) const fixed_t pi = (22<>ANGLETOFINESHIFT) & FINEMASK); - UINT8 *colormap = R_GetTranslationColormap(-1, setupm_fakecolor, 0); + UINT8 *colormap = R_GetTranslationColormap(-1, setupm_fakecolor->color, 0); V_DrawFixedPatch((mx+65)*FRACUNIT, (my+131-fl.zoffs)*FRACUNIT+sine, fl.scale, flags, patch, colormap); Z_Free(colormap); } @@ -9833,9 +9676,10 @@ static void M_GetFollowerState(void) static void M_HandleSetupMultiPlayer(INT32 choice) { size_t l; + INT32 prev_setupm_fakeskin; boolean exitmenu = false; // exit to previous menu and send name change - if ((choice == gamecontrol[gc_fire][0] || choice == gamecontrol[gc_fire][1]) && itemOn == 2) + if ((choice == gamecontrol[0][gc_fire][0] || choice == gamecontrol[0][gc_fire][1]) && itemOn == 2) choice = KEY_BACKSPACE; // Hack to allow resetting prefcolor on controllers switch (choice) @@ -9854,7 +9698,15 @@ static void M_HandleSetupMultiPlayer(INT32 choice) if (itemOn == 1) //player skin { S_StartSound(NULL,sfx_menu1); // Tails - setupm_fakeskin--; + prev_setupm_fakeskin = setupm_fakeskin; + do + { + setupm_fakeskin--; + if (setupm_fakeskin < 0) + setupm_fakeskin = numskins-1; + } + while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); + multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_FSTN, NULL); } else if (itemOn == 2) // follower { @@ -9865,7 +9717,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) else if (itemOn == 3) // player color { S_StartSound(NULL,sfx_menu1); // Tails - setupm_fakecolor--; + setupm_fakecolor = setupm_fakecolor->prev; } break; @@ -9873,8 +9725,15 @@ static void M_HandleSetupMultiPlayer(INT32 choice) if (itemOn == 1) //player skin { S_StartSound(NULL,sfx_menu1); // Tails - setupm_fakeskin++; - M_GetFollowerState(); // update follower state + prev_setupm_fakeskin = setupm_fakeskin; + do + { + setupm_fakeskin++; + if (setupm_fakeskin > numskins-1) + setupm_fakeskin = 0; + } + while ((prev_setupm_fakeskin != setupm_fakeskin) && !(R_SkinUsable(-1, setupm_fakeskin))); + multi_spr2 = P_GetSkinSprite2(&skins[setupm_fakeskin], SPR2_FSTN, NULL); } else if (itemOn == 2) // follower { @@ -9885,7 +9744,7 @@ static void M_HandleSetupMultiPlayer(INT32 choice) else if (itemOn == 3) // player color { S_StartSound(NULL,sfx_menu1); // Tails - setupm_fakecolor++; + setupm_fakecolor = setupm_fakecolor->next; } break; @@ -9909,11 +9768,13 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } else if (itemOn == 3) { - UINT8 col = skins[setupm_fakeskin].prefcolor; - if (setupm_fakecolor != col) + UINT16 col = skins[setupm_fakeskin].prefcolor; + if ((setupm_fakecolor->color != col) && skincolors[col].accessible) { S_StartSound(NULL,sfx_menu1); // Tails - setupm_fakecolor = col; + for (setupm_fakecolor=menucolorhead;;setupm_fakecolor=setupm_fakecolor->next) + if (setupm_fakecolor->color == col || setupm_fakecolor == menucolortail) + break; } } break; @@ -9939,12 +9800,6 @@ static void M_HandleSetupMultiPlayer(INT32 choice) break; } - // check skin - if (setupm_fakeskin < 0) - setupm_fakeskin = numskins-1; - if (setupm_fakeskin > numskins-1) - setupm_fakeskin = 0; - // check followers: if (setupm_fakefollower < -1) { @@ -9958,10 +9813,14 @@ static void M_HandleSetupMultiPlayer(INT32 choice) } // check color - if (setupm_fakecolor < 1) - setupm_fakecolor = MAXSKINCOLORS-1; - if (setupm_fakecolor > MAXSKINCOLORS-1) - setupm_fakecolor = 1; + if (itemOn == 2 && !skincolors[setupm_fakecolor->color].accessible) { + if (choice == KEY_LEFTARROW) + while (!skincolors[setupm_fakecolor->color].accessible) + setupm_fakecolor = setupm_fakecolor->prev; + else if (choice == KEY_RIGHTARROW || choice == KEY_ENTER) + while (!skincolors[setupm_fakecolor->color].accessible) + setupm_fakecolor = setupm_fakecolor->next; + } if (exitmenu) { @@ -9980,14 +9839,14 @@ static void M_SetupMultiPlayer(INT32 choice) multi_state = &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics; - strcpy(setupm_name, cv_playername.string); + strcpy(setupm_name, cv_playername[0].string); // set for player 1 setupm_player = &players[consoleplayer]; - setupm_cvskin = &cv_skin; - setupm_cvcolor = &cv_playercolor; - setupm_cvname = &cv_playername; - setupm_cvfollower = &cv_follower; + setupm_cvskin = &cv_skin[0]; + setupm_cvcolor = &cv_playercolor[0]; + setupm_cvname = &cv_playername[0]; + setupm_cvfollower = &cv_follower[0]; setupm_fakefollower = atoi(setupm_cvfollower->string); // update fake follower value @@ -10001,7 +9860,10 @@ static void M_SetupMultiPlayer(INT32 choice) setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); if (setupm_fakeskin == -1) setupm_fakeskin = 0; - setupm_fakecolor = setupm_cvcolor->value; + + for (setupm_fakecolor=menucolorhead;;setupm_fakecolor=setupm_fakecolor->next) + if (setupm_fakecolor->color == setupm_cvcolor->value || setupm_fakecolor == menucolortail) + break; // disable skin changes if we can't actually change skins if (!CanChangeSkin(consoleplayer)) @@ -10020,14 +9882,14 @@ static void M_SetupMultiPlayer2(INT32 choice) multi_state = &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics; - strcpy (setupm_name, cv_playername2.string); + strcpy (setupm_name, cv_playername[1].string); // set for splitscreen secondary player setupm_player = &players[g_localplayers[1]]; - setupm_cvskin = &cv_skin2; - setupm_cvcolor = &cv_playercolor2; - setupm_cvname = &cv_playername2; - setupm_cvfollower = &cv_follower2; + setupm_cvskin = &cv_skin[1]; + setupm_cvcolor = &cv_playercolor[1]; + setupm_cvname = &cv_playername[1]; + setupm_cvfollower = &cv_follower[1]; setupm_fakefollower = atoi(setupm_cvfollower->string); // update fake follower value @@ -10041,7 +9903,10 @@ static void M_SetupMultiPlayer2(INT32 choice) setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); if (setupm_fakeskin == -1) setupm_fakeskin = 0; - setupm_fakecolor = setupm_cvcolor->value; + + for (setupm_fakecolor=menucolorhead;;setupm_fakecolor=setupm_fakecolor->next) + if (setupm_fakecolor->color == setupm_cvcolor->value || setupm_fakecolor == menucolortail) + break; // disable skin changes if we can't actually change skins if (splitscreen && !CanChangeSkin(g_localplayers[1])) @@ -10060,14 +9925,14 @@ static void M_SetupMultiPlayer3(INT32 choice) multi_state = &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics; - strcpy(setupm_name, cv_playername3.string); + strcpy(setupm_name, cv_playername[2].string); // set for splitscreen third player setupm_player = &players[g_localplayers[2]]; - setupm_cvskin = &cv_skin3; - setupm_cvcolor = &cv_playercolor3; - setupm_cvname = &cv_playername3; - setupm_cvfollower = &cv_follower3; + setupm_cvskin = &cv_skin[2]; + setupm_cvcolor = &cv_playercolor[2]; + setupm_cvname = &cv_playername[2]; + setupm_cvfollower = &cv_follower[2]; setupm_fakefollower = atoi(setupm_cvfollower->string); // update fake follower value @@ -10081,7 +9946,10 @@ static void M_SetupMultiPlayer3(INT32 choice) setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); if (setupm_fakeskin == -1) setupm_fakeskin = 0; - setupm_fakecolor = setupm_cvcolor->value; + + for (setupm_fakecolor=menucolorhead;;setupm_fakecolor=setupm_fakecolor->next) + if (setupm_fakecolor->color == setupm_cvcolor->value || setupm_fakecolor == menucolortail) + break; // disable skin changes if we can't actually change skins if (splitscreen > 1 && !CanChangeSkin(g_localplayers[2])) @@ -10100,14 +9968,14 @@ static void M_SetupMultiPlayer4(INT32 choice) multi_state = &states[mobjinfo[MT_PLAYER].seestate]; multi_tics = multi_state->tics; - strcpy(setupm_name, cv_playername4.string); + strcpy(setupm_name, cv_playername[3].string); // set for splitscreen fourth player setupm_player = &players[g_localplayers[3]]; - setupm_cvskin = &cv_skin4; - setupm_cvcolor = &cv_playercolor4; - setupm_cvname = &cv_playername4; - setupm_cvfollower = &cv_follower4; + setupm_cvskin = &cv_skin[3]; + setupm_cvcolor = &cv_playercolor[3]; + setupm_cvname = &cv_playername[3]; + setupm_cvfollower = &cv_follower[3]; setupm_fakefollower = atoi(setupm_cvfollower->string); // update fake follower value @@ -10121,7 +9989,10 @@ static void M_SetupMultiPlayer4(INT32 choice) setupm_fakeskin = R_SkinAvailable(setupm_cvskin->string); if (setupm_fakeskin == -1) setupm_fakeskin = 0; - setupm_fakecolor = setupm_cvcolor->value; + + for (setupm_fakecolor=menucolorhead;;setupm_fakecolor=setupm_fakecolor->next) + if (setupm_fakecolor->color == setupm_cvcolor->value || setupm_fakecolor == menucolortail) + break; // disable skin changes if we can't actually change skins if (splitscreen > 2 && !CanChangeSkin(g_localplayers[3])) @@ -10147,11 +10018,184 @@ static boolean M_QuitMultiPlayerMenu(void) } // you know what? always putting these in the buffer won't hurt anything. COM_BufAddText (va("%s \"%s\"\n",setupm_cvskin->name,skins[setupm_fakeskin].name)); - COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor)); + COM_BufAddText (va("%s %d\n",setupm_cvcolor->name,setupm_fakecolor->color)); COM_BufAddText (va("%s %d\n",setupm_cvfollower->name,setupm_fakefollower)); return true; } +void M_AddMenuColor(UINT16 color) { + menucolor_t *c; + + // SRB2Kart: I do not understand vanilla doesn't need this but WE do???!?!??! + if (!skincolors[color].accessible) { + return; + } + + if (color >= numskincolors) { + CONS_Printf("M_AddMenuColor: color %d does not exist.",color); + return; + } + + c = (menucolor_t *)malloc(sizeof(menucolor_t)); + c->color = color; + if (menucolorhead == NULL) { + c->next = c; + c->prev = c; + menucolorhead = c; + menucolortail = c; + } else { + c->next = menucolorhead; + c->prev = menucolortail; + menucolortail->next = c; + menucolorhead->prev = c; + menucolortail = c; + } +} + +void M_MoveColorBefore(UINT16 color, UINT16 targ) { + menucolor_t *look, *c = NULL, *t = NULL; + + if (color == targ) + return; + if (color >= numskincolors) { + CONS_Printf("M_MoveColorBefore: color %d does not exist.",color); + return; + } + if (targ >= numskincolors) { + CONS_Printf("M_MoveColorBefore: target color %d does not exist.",targ); + return; + } + + for (look=menucolorhead;;look=look->next) { + if (look->color == color) + c = look; + else if (look->color == targ) + t = look; + if (c != NULL && t != NULL) + break; + if (look==menucolortail) + return; + } + + if (c == t->prev) + return; + + if (t==menucolorhead) + menucolorhead = c; + if (c==menucolortail) + menucolortail = c->prev; + + c->prev->next = c->next; + c->next->prev = c->prev; + + c->prev = t->prev; + c->next = t; + t->prev->next = c; + t->prev = c; +} + +void M_MoveColorAfter(UINT16 color, UINT16 targ) { + menucolor_t *look, *c = NULL, *t = NULL; + + if (color == targ) + return; + if (color >= numskincolors) { + CONS_Printf("M_MoveColorAfter: color %d does not exist.\n",color); + return; + } + if (targ >= numskincolors) { + CONS_Printf("M_MoveColorAfter: target color %d does not exist.\n",targ); + return; + } + + for (look=menucolorhead;;look=look->next) { + if (look->color == color) + c = look; + else if (look->color == targ) + t = look; + if (c != NULL && t != NULL) + break; + if (look==menucolortail) + return; + } + + if (t == c->prev) + return; + + if (t==menucolortail) + menucolortail = c; + else if (c==menucolortail) + menucolortail = c->prev; + + c->prev->next = c->next; + c->next->prev = c->prev; + + c->next = t->next; + c->prev = t; + t->next->prev = c; + t->next = c; +} + +UINT16 M_GetColorBefore(UINT16 color) { + menucolor_t *look; + + if (color >= numskincolors) { + CONS_Printf("M_GetColorBefore: color %d does not exist.\n",color); + return 0; + } + + for (look=menucolorhead;;look=look->next) { + if (look->color == color) + return look->prev->color; + if (look==menucolortail) + return 0; + } +} + +UINT16 M_GetColorAfter(UINT16 color) { + menucolor_t *look; + + if (color >= numskincolors) { + CONS_Printf("M_GetColorAfter: color %d does not exist.\n",color); + return 0; + } + + for (look=menucolorhead;;look=look->next) { + if (look->color == color) + return look->next->color; + if (look==menucolortail) + return 0; + } +} + +void M_InitPlayerSetupColors(void) { + UINT8 i; + numskincolors = SKINCOLOR_FIRSTFREESLOT; + menucolorhead = menucolortail = NULL; + for (i=0; inext; + free(tmp); + } else { + free(look); + return; + } + } + + menucolorhead = menucolortail = NULL; +} + // ================= // DATA OPTIONS MENU // ================= @@ -10217,7 +10261,8 @@ static void M_ScreenshotOptions(INT32 choice) static void M_DrawJoystick(void) { - INT32 i, compareval4, compareval3, compareval2, compareval; + INT32 i; + INT32 compareval; M_DrawGenericMenu(); @@ -10227,47 +10272,24 @@ static void M_DrawJoystick(void) //M_DrawSaveLoadBorder(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i); #ifdef JOYSTICK_HOTPLUG - if (atoi(cv_usejoystick4.string) > I_NumJoys()) - compareval4 = atoi(cv_usejoystick4.string); + if (atoi(cv_usejoystick[setupcontrolplayer-1].string) > I_NumJoys()) + compareval = atoi(cv_usejoystick[setupcontrolplayer-1].string); else - compareval4 = cv_usejoystick4.value; - - if (atoi(cv_usejoystick3.string) > I_NumJoys()) - compareval3 = atoi(cv_usejoystick3.string); - else - compareval3 = cv_usejoystick3.value; - - if (atoi(cv_usejoystick2.string) > I_NumJoys()) - compareval2 = atoi(cv_usejoystick2.string); - else - compareval2 = cv_usejoystick2.value; - - if (atoi(cv_usejoystick.string) > I_NumJoys()) - compareval = atoi(cv_usejoystick.string); - else - compareval = cv_usejoystick.value; -#else - compareval4 = cv_usejoystick4.value; - compareval3 = cv_usejoystick3.value; - compareval2 = cv_usejoystick2.value; - compareval = cv_usejoystick.value #endif + compareval = cv_usejoystick[setupcontrolplayer-1].value; - if ((setupcontrolplayer == 4 && (i == compareval4)) - || (setupcontrolplayer == 3 && (i == compareval3)) - || (setupcontrolplayer == 2 && (i == compareval2)) - || (setupcontrolplayer == 1 && (i == compareval))) - V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,V_GREENMAP,joystickInfo[i]); - else - V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4,0,joystickInfo[i]); + V_DrawString(OP_JoystickSetDef.x, OP_JoystickSetDef.y+LINEHEIGHT*i-4, (i == compareval) ? V_GREENMAP : 0, joystickInfo[i]); } } void M_SetupJoystickMenu(INT32 choice) { - INT32 i = 0; const char *joyNA = "Unavailable"; - INT32 n = I_NumJoys(); + const INT32 n = I_NumJoys(); + + INT32 i = 0; + INT32 j; + (void)choice; strcpy(joystickInfo[i], "None"); @@ -10288,14 +10310,11 @@ void M_SetupJoystickMenu(INT32 choice) // // Update cv_usejoystick.string here so that the user can // properly change this value. - if (i == cv_usejoystick.value) - CV_SetValue(&cv_usejoystick, i); - if (i == cv_usejoystick2.value) - CV_SetValue(&cv_usejoystick2, i); - if (i == cv_usejoystick3.value) - CV_SetValue(&cv_usejoystick3, i); - if (i == cv_usejoystick4.value) - CV_SetValue(&cv_usejoystick4, i); + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + { + if (i == cv_usejoystick[j].value) + CV_SetValue(&cv_usejoystick[j], i); + } #endif } @@ -10332,139 +10351,41 @@ static void M_Setup4PJoystickMenu(INT32 choice) static void M_AssignJoystick(INT32 choice) { + const UINT8 p = setupcontrolplayer-1; + #ifdef JOYSTICK_HOTPLUG INT32 oldchoice, oldstringchoice; INT32 numjoys = I_NumJoys(); - if (setupcontrolplayer == 4) + oldchoice = oldstringchoice = atoi(cv_usejoystick[p].string) > numjoys ? atoi(cv_usejoystick[p].string) : cv_usejoystick[p].value; + CV_SetValue(&cv_usejoystick[p], choice); + + // Just in case last-minute changes were made to cv_usejoystick.value, + // update the string too + // But don't do this if we're intentionally setting higher than numjoys + if (choice <= numjoys) { - oldchoice = oldstringchoice = atoi(cv_usejoystick4.string) > numjoys ? atoi(cv_usejoystick4.string) : cv_usejoystick4.value; - CV_SetValue(&cv_usejoystick4, choice); + CV_SetValue(&cv_usejoystick[p], cv_usejoystick[p].value); - // Just in case last-minute changes were made to cv_usejoystick.value, - // update the string too - // But don't do this if we're intentionally setting higher than numjoys - if (choice <= numjoys) + // reset this so the comparison is valid + if (oldchoice > numjoys) + oldchoice = cv_usejoystick[p].value; + + if (oldchoice != choice) { - CV_SetValue(&cv_usejoystick4, cv_usejoystick4.value); + if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device + CV_SetValue(&cv_usejoystick[p], (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - // reset this so the comparison is valid - if (oldchoice > numjoys) - oldchoice = cv_usejoystick4.value; - - if (oldchoice != choice) - { - if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick4, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - - if (oldstringchoice == - (atoi(cv_usejoystick4.string) > numjoys ? atoi(cv_usejoystick4.string) : cv_usejoystick4.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - } - } - } - else if (setupcontrolplayer == 3) - { - oldchoice = oldstringchoice = atoi(cv_usejoystick3.string) > numjoys ? atoi(cv_usejoystick3.string) : cv_usejoystick3.value; - CV_SetValue(&cv_usejoystick3, choice); - - // Just in case last-minute changes were made to cv_usejoystick.value, - // update the string too - // But don't do this if we're intentionally setting higher than numjoys - if (choice <= numjoys) - { - CV_SetValue(&cv_usejoystick3, cv_usejoystick3.value); - - // reset this so the comparison is valid - if (oldchoice > numjoys) - oldchoice = cv_usejoystick3.value; - - if (oldchoice != choice) - { - if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick3, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - - if (oldstringchoice == - (atoi(cv_usejoystick3.string) > numjoys ? atoi(cv_usejoystick3.string) : cv_usejoystick3.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - } - } - } - else if (setupcontrolplayer == 2) - { - oldchoice = oldstringchoice = atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value; - CV_SetValue(&cv_usejoystick2, choice); - - // Just in case last-minute changes were made to cv_usejoystick.value, - // update the string too - // But don't do this if we're intentionally setting higher than numjoys - if (choice <= numjoys) - { - CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); - - // reset this so the comparison is valid - if (oldchoice > numjoys) - oldchoice = cv_usejoystick2.value; - - if (oldchoice != choice) - { - if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick2, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - - if (oldstringchoice == - (atoi(cv_usejoystick2.string) > numjoys ? atoi(cv_usejoystick2.string) : cv_usejoystick2.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - } - } - } - else if (setupcontrolplayer == 1) - { - oldchoice = oldstringchoice = atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value; - CV_SetValue(&cv_usejoystick, choice); - - // Just in case last-minute changes were made to cv_usejoystick.value, - // update the string too - // But don't do this if we're intentionally setting higher than numjoys - if (choice <= numjoys) - { - CV_SetValue(&cv_usejoystick, cv_usejoystick.value); - - // reset this so the comparison is valid - if (oldchoice > numjoys) - oldchoice = cv_usejoystick.value; - - if (oldchoice != choice) - { - if (choice && oldstringchoice > numjoys) // if we did not select "None", we likely selected a used device - CV_SetValue(&cv_usejoystick, (oldstringchoice > numjoys ? oldstringchoice : oldchoice)); - - if (oldstringchoice == - (atoi(cv_usejoystick.string) > numjoys ? atoi(cv_usejoystick.string) : cv_usejoystick.value)) - M_StartMessage("This joystick is used by another\n" - "player. Reset the joystick\n" - "for that player first.\n\n" - "(Press a key)\n", NULL, MM_NOTHING); - } + if (oldstringchoice == + (atoi(cv_usejoystick[p].string) > numjoys ? atoi(cv_usejoystick[p].string) : cv_usejoystick[p].value)) + M_StartMessage("This joystick is used by another\n" + "player. Reset the joystick\n" + "for that player first.\n\n" + "(Press a key)\n", NULL, MM_NOTHING); } } #else - if (setupcontrolplayer == 4) - CV_SetValue(&cv_usejoystick4, choice); - else if (setupcontrolplayer == 3) - CV_SetValue(&cv_usejoystick3, choice); - else if (setupcontrolplayer == 2) - CV_SetValue(&cv_usejoystick2, choice); - else if (setupcontrolplayer == 1) - CV_SetValue(&cv_usejoystick, choice); + CV_SetValue(&cv_usejoystick[p], choice); #endif } @@ -10476,7 +10397,7 @@ static void M_Setup1PControlsMenu(INT32 choice) { (void)choice; setupcontrolplayer = 1; - setupcontrols = gamecontrol; // was called from main Options (for console player, then) + setupcontrols = gamecontrol[0]; // was called from main Options (for console player, then) currentMenu->lastOn = itemOn; // Set proper gamepad options @@ -10508,7 +10429,7 @@ static void M_Setup2PControlsMenu(INT32 choice) { (void)choice; setupcontrolplayer = 2; - setupcontrols = gamecontrolbis; + setupcontrols = gamecontrol[1]; currentMenu->lastOn = itemOn; // Set proper gamepad options @@ -10540,7 +10461,7 @@ static void M_Setup3PControlsMenu(INT32 choice) { (void)choice; setupcontrolplayer = 3; - setupcontrols = gamecontrol3; + setupcontrols = gamecontrol[2]; currentMenu->lastOn = itemOn; // Set proper gamepad options @@ -10572,7 +10493,7 @@ static void M_Setup4PControlsMenu(INT32 choice) { (void)choice; setupcontrolplayer = 4; - setupcontrols = gamecontrol4; + setupcontrols = gamecontrol[3]; currentMenu->lastOn = itemOn; // Set proper gamepad options @@ -10733,7 +10654,6 @@ static void M_ChangecontrolResponse(event_t *ev) { // ignore mouse/joy movements, just get buttons case ev_mouse: - case ev_mouse2: case ev_joystick: case ev_joystick2: case ev_joystick3: @@ -10834,6 +10754,7 @@ static void M_ChangeControl(INT32 choice) static void M_ResetControlsResponse(INT32 ch) { + const UINT8 p = setupcontrolplayer-1; INT32 i; if (ch != 'y' && ch != KEY_ENTER) @@ -10842,72 +10763,21 @@ static void M_ResetControlsResponse(INT32 ch) // clear all controls for (i = 0; i < num_gamecontrols; i++) { - switch (setupcontrolplayer) - { - case 4: - G_ClearControlKeys(gamecontrol4, i); - break; - case 3: - G_ClearControlKeys(gamecontrol3, i); - break; - case 2: - G_ClearControlKeys(gamecontrolbis, i); - break; - case 1: - default: - G_ClearControlKeys(gamecontrol, i); - break; - } + G_ClearControlKeys(gamecontrol[p], i); } // Setup original defaults - G_Controldefault(setupcontrolplayer); + G_CopyControls(gamecontrol[p], gamecontroldefault[p][gcs_kart], NULL, 0); // Setup gamepad option defaults (yucky) - switch (setupcontrolplayer) - { - case 4: - CV_StealthSet(&cv_usejoystick4, cv_usejoystick4.defaultvalue); - CV_StealthSet(&cv_turnaxis4, cv_turnaxis4.defaultvalue); - CV_StealthSet(&cv_moveaxis4, cv_moveaxis4.defaultvalue); - CV_StealthSet(&cv_brakeaxis4, cv_brakeaxis4.defaultvalue); - CV_StealthSet(&cv_aimaxis4, cv_aimaxis4.defaultvalue); - CV_StealthSet(&cv_lookaxis4, cv_lookaxis4.defaultvalue); - CV_StealthSet(&cv_fireaxis4, cv_fireaxis4.defaultvalue); - CV_StealthSet(&cv_driftaxis4, cv_driftaxis4.defaultvalue); - break; - case 3: - CV_StealthSet(&cv_usejoystick3, cv_usejoystick3.defaultvalue); - CV_StealthSet(&cv_turnaxis3, cv_turnaxis3.defaultvalue); - CV_StealthSet(&cv_moveaxis3, cv_moveaxis3.defaultvalue); - CV_StealthSet(&cv_brakeaxis3, cv_brakeaxis3.defaultvalue); - CV_StealthSet(&cv_aimaxis3, cv_aimaxis3.defaultvalue); - CV_StealthSet(&cv_lookaxis3, cv_lookaxis3.defaultvalue); - CV_StealthSet(&cv_fireaxis3, cv_fireaxis3.defaultvalue); - CV_StealthSet(&cv_driftaxis3, cv_driftaxis3.defaultvalue); - break; - case 2: - CV_StealthSet(&cv_usejoystick2, cv_usejoystick2.defaultvalue); - CV_StealthSet(&cv_turnaxis2, cv_turnaxis2.defaultvalue); - CV_StealthSet(&cv_moveaxis2, cv_moveaxis2.defaultvalue); - CV_StealthSet(&cv_brakeaxis2, cv_brakeaxis2.defaultvalue); - CV_StealthSet(&cv_aimaxis2, cv_aimaxis2.defaultvalue); - CV_StealthSet(&cv_lookaxis2, cv_lookaxis2.defaultvalue); - CV_StealthSet(&cv_fireaxis2, cv_fireaxis2.defaultvalue); - CV_StealthSet(&cv_driftaxis2, cv_driftaxis2.defaultvalue); - break; - case 1: - default: - CV_StealthSet(&cv_usejoystick, cv_usejoystick.defaultvalue); - CV_StealthSet(&cv_turnaxis, cv_turnaxis.defaultvalue); - CV_StealthSet(&cv_moveaxis, cv_moveaxis.defaultvalue); - CV_StealthSet(&cv_brakeaxis, cv_brakeaxis.defaultvalue); - CV_StealthSet(&cv_aimaxis, cv_aimaxis.defaultvalue); - CV_StealthSet(&cv_lookaxis, cv_lookaxis.defaultvalue); - CV_StealthSet(&cv_fireaxis, cv_fireaxis.defaultvalue); - CV_StealthSet(&cv_driftaxis, cv_driftaxis.defaultvalue); - break; - } + CV_StealthSet(&cv_usejoystick[p], cv_usejoystick[p].defaultvalue); + CV_StealthSet(&cv_turnaxis[p], cv_turnaxis[p].defaultvalue); + CV_StealthSet(&cv_moveaxis[p], cv_moveaxis[p].defaultvalue); + CV_StealthSet(&cv_brakeaxis[p], cv_brakeaxis[p].defaultvalue); + CV_StealthSet(&cv_aimaxis[p], cv_aimaxis[p].defaultvalue); + CV_StealthSet(&cv_lookaxis[p], cv_lookaxis[p].defaultvalue); + CV_StealthSet(&cv_fireaxis[p], cv_fireaxis[p].defaultvalue); + CV_StealthSet(&cv_driftaxis[p], cv_driftaxis[p].defaultvalue); S_StartSound(NULL, sfx_s224); } @@ -11546,22 +11416,160 @@ static void M_QuitSRB2(INT32 choice) M_StartMessage(quitmsg[M_RandomKey(NUM_QUITMESSAGES)], M_QuitResponse, MM_YESNO); } -#ifdef HWRENDER -// ===================================================================== -// OpenGL specific options -// ===================================================================== +#ifdef HAVE_DISCORDRPC +static const tic_t confirmLength = 3*TICRATE/4; +static tic_t confirmDelay = 0; +static boolean confirmAccept = false; -// ===================== -// M_OGL_DrawColorMenu() -// ===================== -static void M_OGL_DrawColorMenu(void) +static void M_HandleDiscordRequests(INT32 choice) { - INT32 mx, my; + if (confirmDelay > 0) + return; - mx = currentMenu->x; - my = currentMenu->y; - M_DrawGenericMenu(); // use generic drawer for cursor, items and title - V_DrawString(mx, my + currentMenu->menuitems[0].alphaKey - 10, - highlightflags, "Gamma correction"); + switch (choice) + { + case KEY_ENTER: + Discord_Respond(discordRequestList->userID, DISCORD_REPLY_YES); + confirmAccept = true; + confirmDelay = confirmLength; + S_StartSound(NULL, sfx_s3k63); + break; + + case KEY_ESCAPE: + Discord_Respond(discordRequestList->userID, DISCORD_REPLY_NO); + confirmAccept = false; + confirmDelay = confirmLength; + S_StartSound(NULL, sfx_s3kb2); + break; + } +} + +static const char *M_GetDiscordName(discordRequest_t *r) +{ + if (r == NULL) + return ""; + + if (cv_discordstreamer.value) + return r->username; + + return va("%s#%s", r->username, r->discriminator); +} + +// (this goes in k_hud.c when merged into v2) +static void M_DrawSticker(INT32 x, INT32 y, INT32 width, INT32 flags, boolean isSmall) +{ + patch_t *stickerEnd; + INT32 height; + + if (isSmall == true) + { + stickerEnd = W_CachePatchName("K_STIKE2", PU_CACHE); + height = 6; + } + else + { + stickerEnd = W_CachePatchName("K_STIKEN", PU_CACHE); + height = 11; + } + + V_DrawFixedPatch(x*FRACUNIT, y*FRACUNIT, FRACUNIT, flags, stickerEnd, NULL); + V_DrawFill(x, y, width, height, 24|flags); + V_DrawFixedPatch((x + width)*FRACUNIT, y*FRACUNIT, FRACUNIT, flags|V_FLIP, stickerEnd, NULL); +} + +static void M_DrawDiscordRequests(void) +{ + discordRequest_t *curRequest = discordRequestList; + UINT8 *colormap; + patch_t *hand = NULL; + boolean removeRequest = false; + + const char *wantText = "...would like to join!"; + const char *controlText = "\x82" "ENTER" "\x80" " - Accept " "\x82" "ESC" "\x80" " - Decline"; + + INT32 x = 100; + INT32 y = 133; + + INT32 slide = 0; + INT32 maxYSlide = 18; + + if (confirmDelay > 0) + { + if (confirmAccept == true) + { + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_GREEN, GTC_MENUCACHE); + hand = W_CachePatchName("K_LAPH02", PU_CACHE); + } + else + { + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_RED, GTC_MENUCACHE); + hand = W_CachePatchName("K_LAPH03", PU_CACHE); + } + + slide = confirmLength - confirmDelay; + + confirmDelay--; + + if (confirmDelay == 0) + removeRequest = true; + } + else + { + colormap = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_GREY, GTC_MENUCACHE); + } + + V_DrawFixedPatch(56*FRACUNIT, 150*FRACUNIT, FRACUNIT, 0, W_CachePatchName("K_LAPE01", PU_CACHE), colormap); + + if (hand != NULL) + { + fixed_t handoffset = (4 - abs((signed)(skullAnimCounter - 4))) * FRACUNIT; + V_DrawFixedPatch(56*FRACUNIT, 150*FRACUNIT + handoffset, FRACUNIT, 0, hand, NULL); + } + + M_DrawSticker(x + (slide * 32), y - 1, V_ThinStringWidth(M_GetDiscordName(curRequest), V_ALLOWLOWERCASE|V_6WIDTHSPACE), 0, false); + V_DrawThinString(x + (slide * 32), y, V_ALLOWLOWERCASE|V_6WIDTHSPACE|V_YELLOWMAP, M_GetDiscordName(curRequest)); + + M_DrawSticker(x, y + 12, V_ThinStringWidth(wantText, V_ALLOWLOWERCASE|V_6WIDTHSPACE), 0, true); + V_DrawThinString(x, y + 10, V_ALLOWLOWERCASE|V_6WIDTHSPACE, wantText); + + M_DrawSticker(x, y + 26, V_ThinStringWidth(controlText, V_ALLOWLOWERCASE|V_6WIDTHSPACE), 0, true); + V_DrawThinString(x, y + 24, V_ALLOWLOWERCASE|V_6WIDTHSPACE, controlText); + + y -= 18; + + while (curRequest->next != NULL) + { + INT32 ySlide = min(slide * 4, maxYSlide); + + curRequest = curRequest->next; + + M_DrawSticker(x, y - 1 + ySlide, V_ThinStringWidth(M_GetDiscordName(curRequest), V_ALLOWLOWERCASE|V_6WIDTHSPACE), 0, false); + V_DrawThinString(x, y + ySlide, V_ALLOWLOWERCASE|V_6WIDTHSPACE, M_GetDiscordName(curRequest)); + + y -= 12; + maxYSlide = 12; + } + + if (removeRequest == true) + { + DRPC_RemoveRequest(discordRequestList); + + if (discordRequestList == NULL) + { + // No other requests + MPauseMenu[mpause_discordrequests].status = IT_GRAYEDOUT; + + if (currentMenu->prevMenu) + { + M_SetupNextMenu(currentMenu->prevMenu); + if (currentMenu == &MPauseDef) + itemOn = mpause_continue; + } + else + M_ClearMenus(true); + + return; + } + } } #endif diff --git a/src/m_menu.h b/src/m_menu.h index 1ad20c777..3c2d7fb47 100644 --- a/src/m_menu.h +++ b/src/m_menu.h @@ -2,8 +2,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2011-2016 by Matthew "Inuyasha" Walsh. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 2011-2016 by Matthew "Kaito Sinclaire" Walsh. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,15 +15,175 @@ #ifndef __X_MENU__ #define __X_MENU__ +#include "doomstat.h" // for NUMGAMETYPES #include "d_event.h" #include "command.h" +#include "f_finale.h" // for ttmode_enum #include "i_threads.h" #include "mserv.h" -#include "r_things.h" // for SKINNAMESIZE +#include "r_skins.h" // for SKINNAMESIZE + +// Compatibility with old-style named NiGHTS replay files. +#define OLDNREPLAYNAME // // MENUS // + +// If menu hierarchies go deeper, change this up to 5. +// Zero-based, inclusive. +#define NUMMENULEVELS 3 +#define MENUBITS 6 + +// Menu IDs sectioned by numeric places to signify hierarchy +/** + * IF YOU MODIFY THIS, MODIFY MENUTYPES_LIST[] IN dehacked.c TO MATCH. + */ +typedef enum +{ + MN_NONE, + + MN_MAIN, + + // Single Player + MN_SP_MAIN, + + MN_SP_LOAD, + MN_SP_PLAYER, + + MN_SP_LEVELSELECT, + MN_SP_LEVELSTATS, + + MN_SP_TIMEATTACK, + MN_SP_TIMEATTACK_LEVELSELECT, + MN_SP_GUESTREPLAY, + MN_SP_REPLAY, + MN_SP_GHOST, + + MN_SP_NIGHTSATTACK, + MN_SP_NIGHTS_LEVELSELECT, + MN_SP_NIGHTS_GUESTREPLAY, + MN_SP_NIGHTS_REPLAY, + MN_SP_NIGHTS_GHOST, + + MN_SP_MARATHON, + + // Multiplayer + MN_MP_MAIN, + MN_MP_SPLITSCREEN, // SplitServer + MN_MP_SERVER, + MN_MP_CONNECT, + MN_MP_ROOM, + MN_MP_PLAYERSETUP, // MP_PlayerSetupDef shared with SPLITSCREEN if #defined NONET + MN_MP_SERVER_OPTIONS, + + // Options + MN_OP_MAIN, + + MN_OP_P1CONTROLS, + MN_OP_CHANGECONTROLS, // OP_ChangeControlsDef shared with P2 + MN_OP_P1MOUSE, + MN_OP_P1JOYSTICK, + MN_OP_JOYSTICKSET, // OP_JoystickSetDef shared with P2 + MN_OP_P1CAMERA, + + MN_OP_P2CONTROLS, + MN_OP_P2MOUSE, + MN_OP_P2JOYSTICK, + MN_OP_P2CAMERA, + + MN_OP_PLAYSTYLE, + + MN_OP_VIDEO, + MN_OP_VIDEOMODE, + MN_OP_COLOR, + MN_OP_OPENGL, + MN_OP_OPENGL_LIGHTING, + + MN_OP_SOUND, + + MN_OP_SERVER, + MN_OP_MONITORTOGGLE, + + MN_OP_DATA, + MN_OP_ADDONS, + MN_OP_SCREENSHOTS, + MN_OP_ERASEDATA, + + // Extras + MN_SR_MAIN, + MN_SR_PANDORA, + MN_SR_LEVELSELECT, + MN_SR_UNLOCKCHECKLIST, + MN_SR_EMBLEMHINT, + MN_SR_PLAYER, + MN_SR_SOUNDTEST, + + // Addons (Part of MISC, but let's make it our own) + MN_AD_MAIN, + + // MISC + // MN_MESSAGE, + // MN_SPAUSE, + + // MN_MPAUSE, + // MN_SCRAMBLETEAM, + // MN_CHANGETEAM, + // MN_CHANGELEVEL, + + // MN_MAPAUSE, + // MN_HELP, + + MN_SPECIAL, + NUMMENUTYPES, +} menutype_t; // up to 63; MN_SPECIAL = 53 +#define MTREE2(a,b) (a | (b< : load config from a file\n")); @@ -453,7 +491,11 @@ void Command_LoadConfig_f(void) // load default control G_ClearAllControlKeys(); - G_Controldefault(0); + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + G_CopyControls(gamecontrol[i], gamecontroldefault[i][gcs_kart], NULL, 0); + } // temporarily reset execversion to default CV_ToggleExecVersion(true); @@ -490,6 +532,8 @@ void Command_ChangeConfig_f(void) */ void M_FirstLoadConfig(void) { + UINT8 i; + // configfile is initialised by d_main when searching for the wad? // check for a custom config file @@ -500,7 +544,12 @@ void M_FirstLoadConfig(void) } // load default control - G_Controldefault(0); + G_DefineDefaultControls(); + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + G_CopyControls(gamecontrol[i], gamecontroldefault[i][gcs_kart], NULL, 0); + } // register execversion here before we load any configs CV_RegisterVar(&cv_execversion); @@ -522,6 +571,15 @@ void M_FirstLoadConfig(void) // make sure I_Quit() will write back the correct config // (do not write back the config if it crash before) gameconfig_loaded = true; + + // reset to default player stuff +#if 0 + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + COM_BufAddText (va("%s \"%s\"\n",cv_skin[i].name,cv_skin[i].defaultvalue)); + COM_BufAddText (va("%s \"%s\"\n",cv_playercolor[i].name,cv_playercolor[i].defaultvalue)); + } +#endif } /** Saves the game configuration. @@ -589,7 +647,19 @@ void M_SaveConfig(const char *filename) // FIXME: save key aliases if ever implemented.. CV_SaveVariables(f); - if (!dedicated) G_SaveKeySetting(f); + + if (!dedicated) + { + if (tutorialmode && tutorialgcs) + { + // using gcs_custom as temp storage + G_SaveKeySetting(f, gamecontroldefault[0][gcs_custom], gamecontrol[1], gamecontrol[2], gamecontrol[3]); + } + else + { + G_SaveKeySetting(f, gamecontrol[0], gamecontrol[1], gamecontrol[2], gamecontrol[3]); + } + } fclose(f); } @@ -603,7 +673,9 @@ static void M_CreateScreenShotPalette(void) size_t i, j; for (i = 0, j = 0; i < 768; i += 3, j++) { - RGBA_t locpal = pLocalPalette[(max(st_palette,0)*256)+j]; + RGBA_t locpal = ((cv_screenshot_colorprofile.value) + ? pLocalPalette[(max(st_palette,0)*256)+j] + : pMasterPalette[(max(st_palette,0)*256)+j]); screenshot_palette[i] = locpal.s.red; screenshot_palette[i+1] = locpal.s.green; screenshot_palette[i+2] = locpal.s.blue; @@ -720,7 +792,7 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png "Title", "Description", "Playername", "Mapnum", "Mapname", "Location", "Interface", "Render Mode", "Revision", "Build Date", "Build Time"}; char titletxt[] = "SRB2Kart " VERSIONSTRING; - png_charp playertxt = cv_playername.zstring; + png_charp playertxt = cv_playername[0].zstring; char desctxt[] = "SRB2Kart Screenshot"; char Movietxt[] = "SRB2Kart Movie"; size_t i; @@ -729,8 +801,6 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png "SDL"; #elif defined (_WINDOWS) "DirectX"; -#elif defined (PC_DOS) - "Allegro"; #else "Unknown"; #endif @@ -763,9 +833,9 @@ static void M_PNGText(png_structp png_ptr, png_infop png_info_ptr, PNG_CONST png if (gamestate == GS_LEVEL && mapheaderinfo[gamemap-1]->lvlttl[0] != '\0') snprintf(lvlttltext, 48, "%s%s%s", mapheaderinfo[gamemap-1]->lvlttl, - (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) ? va(" %s",mapheaderinfo[gamemap-1]->zonttl) : // SRB2kart - ((mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE"), - (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) ? va(" %s",mapheaderinfo[gamemap-1]->actnum) : ""); + (mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : + (mapheaderinfo[gamemap-1]->zonttl[0] != '\0') ? va(" %s",mapheaderinfo[gamemap-1]->zonttl) : " Zone", + (mapheaderinfo[gamemap-1]->actnum > 0) ? va(" %d",mapheaderinfo[gamemap-1]->actnum) : ""); else snprintf(lvlttltext, 48, "Unknown"); @@ -1043,7 +1113,7 @@ static boolean M_SetupaPNG(png_const_charp filename, png_bytep pal) static inline moviemode_t M_StartMovieAPNG(const char *pathname) { #ifdef USE_APNG - UINT8 *palette; + UINT8 *palette = NULL; const char *freename = NULL; boolean ret = false; @@ -1059,8 +1129,13 @@ static inline moviemode_t M_StartMovieAPNG(const char *pathname) return MM_OFF; } - if (rendermode == render_soft) M_CreateScreenShotPalette(); - ret = M_SetupaPNG(va(pandf,pathname,freename), (palette = screenshot_palette)); + if (rendermode == render_soft) + { + M_CreateScreenShotPalette(); + palette = screenshot_palette; + } + + ret = M_SetupaPNG(va(pandf,pathname,freename), palette); if (!ret) { @@ -1380,7 +1455,7 @@ typedef struct * \param palette Palette of image data */ #if NUMSCREENS > 2 -static boolean WritePCXfile(const char *filename, const UINT8 *data, int width, int height) +static boolean WritePCXfile(const char *filename, const UINT8 *data, int width, int height, const UINT8 *pal) { int i; size_t length; @@ -1424,15 +1499,11 @@ static boolean WritePCXfile(const char *filename, const UINT8 *data, int width, // write color table { - RGBA_t *pal = ((cv_screenshot_colorprofile.value) - ? pLocalPalette - : pMasterPalette); - for (i = 0; i < 256; i++) { - *pack++ = pal[i].s.red; - *pack++ = pal[i].s.green; - *pack++ = pal[i].s.blue; + *pack++ = *pal; pal++; + *pack++ = *pal; pal++; + *pack++ = *pal; pal++; } } @@ -1551,9 +1622,9 @@ boolean M_ScreenshotResponder(event_t *ev) if (ch >= KEY_MOUSE1 && menuactive) // If it's not a keyboard key, then don't allow it in the menus! return false; - if (ch == KEY_F8 || ch == gamecontrol[gc_screenshot][0] || ch == gamecontrol[gc_screenshot][1]) // remappable F8 + if (ch == KEY_F8 || ch == gamecontrol[0][gc_screenshot][0] || ch == gamecontrol[0][gc_screenshot][1]) // remappable F8 M_ScreenShot(); - else if (ch == KEY_F9 || ch == gamecontrol[gc_recordgif][0] || ch == gamecontrol[gc_recordgif][1]) // remappable F9 + else if (ch == KEY_F9 || ch == gamecontrol[0][gc_recordgif][0] || ch == gamecontrol[0][gc_recordgif][1]) // remappable F9 ((moviemode) ? M_StopMovie : M_StartMovie)(); else return false; @@ -1567,16 +1638,19 @@ boolean M_ScreenshotResponder(event_t *ev) // M_StartupLocale. // Sets up gettext to translate SRB2's strings. #ifdef GETTEXT -#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) -#define GETTEXTDOMAIN1 "/usr/share/locale" -#define GETTEXTDOMAIN2 "/usr/local/share/locale" -#elif defined (_WIN32) -#define GETTEXTDOMAIN1 "." -#endif + #if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + #define GETTEXTDOMAIN1 "/usr/share/locale" + #define GETTEXTDOMAIN2 "/usr/local/share/locale" + #elif defined (_WIN32) + #define GETTEXTDOMAIN1 "." + #endif +#endif // GETTEXT void M_StartupLocale(void) { +#ifdef GETTEXT char *textdomhandle = NULL; +#endif //GETTEXT CONS_Printf("M_StartupLocale...\n"); @@ -1585,6 +1659,7 @@ void M_StartupLocale(void) // Do not set numeric locale as that affects atof setlocale(LC_NUMERIC, "C"); +#ifdef GETTEXT // FIXME: global name define anywhere? #ifdef GETTEXTDOMAIN1 textdomhandle = bindtextdomain("srb2", GETTEXTDOMAIN1); @@ -1605,8 +1680,8 @@ void M_StartupLocale(void) textdomain("srb2"); else CONS_Printf("Could not find locale text domain!\n"); +#endif //GETTEXT } -#endif // ========================================================================== // MISC STRING FUNCTIONS @@ -1689,6 +1764,11 @@ INT32 axtoi(const char *hexStg) return intValue; } +// Token parser variables + +static UINT32 oldendPos = 0; // old value of endPos, used by M_UnGetToken +static UINT32 endPos = 0; // now external to M_GetToken, but still static + /** Token parser for TEXTURES, ANIMDEFS, and potentially other lumps later down the line. * Was originally R_GetTexturesToken when I was coding up the TEXTURES parser, until I realized I needed it for ANIMDEFS too. * Parses up to the next whitespace character or comma. When finding the start of the next token, whitespace is skipped. @@ -1703,7 +1783,7 @@ char *M_GetToken(const char *inputString) { static const char *stringToUse = NULL; // Populated if inputString != NULL; used otherwise static UINT32 startPos = 0; - static UINT32 endPos = 0; +// static UINT32 endPos = 0; static UINT32 stringLength = 0; static UINT8 inComment = 0; // 0 = not in comment, 1 = // Single-line, 2 = /* Multi-line */ char *texturesToken = NULL; @@ -1713,12 +1793,12 @@ char *M_GetToken(const char *inputString) { stringToUse = inputString; startPos = 0; - endPos = 0; + oldendPos = endPos = 0; stringLength = strlen(inputString); } else { - startPos = endPos; + startPos = oldendPos = endPos; } if (stringToUse == NULL) return NULL; @@ -1747,7 +1827,7 @@ char *M_GetToken(const char *inputString) || stringToUse[startPos] == '\r' || stringToUse[startPos] == '\n' || stringToUse[startPos] == '\0' - || stringToUse[startPos] == '"' // we're treating this as whitespace because SLADE likes adding it for no good reason + || stringToUse[startPos] == '=' || stringToUse[startPos] == ';' // UDMF TEXTMAP. || inComment != 0) && startPos < stringLength) { @@ -1805,6 +1885,23 @@ char *M_GetToken(const char *inputString) texturesToken[1] = '\0'; return texturesToken; } + // Return entire string within quotes, except without the quotes. + else if (stringToUse[startPos] == '"') + { + endPos = ++startPos; + while (stringToUse[endPos] != '"' && endPos < stringLength) + endPos++; + + texturesTokenLength = endPos++ - startPos; + // Assign the memory. Don't forget an extra byte for the end of the string! + texturesToken = (char *)Z_Malloc((texturesTokenLength+1)*sizeof(char),PU_STATIC,NULL); + // Copy the string. + M_Memcpy(texturesToken, stringToUse+startPos, (size_t)texturesTokenLength); + // Make the final character NUL. + texturesToken[texturesTokenLength] = '\0'; + + return texturesToken; + } // Now find the end of the token. This includes several additional characters that are okay to capture as one character, but not trailing at the end of another token. endPos = startPos + 1; @@ -1815,7 +1912,7 @@ char *M_GetToken(const char *inputString) && stringToUse[endPos] != ',' && stringToUse[endPos] != '{' && stringToUse[endPos] != '}' - && stringToUse[endPos] != '"' // see above + && stringToUse[endPos] != '=' && stringToUse[endPos] != ';' // UDMF TEXTMAP. && inComment == 0) && endPos < stringLength) { @@ -1849,6 +1946,30 @@ char *M_GetToken(const char *inputString) return texturesToken; } +/** Undoes the last M_GetToken call + * The current position along the string being parsed is reset to the last saved position. + * This exists mostly because of R_ParseTexture/R_ParsePatch honestly, but could be useful elsewhere? + * -Monster Iestyn (22/10/16) + */ +void M_UnGetToken(void) +{ + endPos = oldendPos; +} + +/** Returns the current token's position. + */ +UINT32 M_GetTokenPos(void) +{ + return endPos; +} + +/** Sets the current token's position. + */ +void M_SetTokenPos(UINT32 newPos) +{ + endPos = newPos; +} + /** Count bits in a number. */ UINT8 M_CountBits(UINT32 num, UINT8 size) @@ -2498,3 +2619,58 @@ void M_MkdirEach(const char *path, int start, int mode) { M_MkdirEachUntil(path, start, -1, mode); } + +int M_JumpWord(const char *line) +{ + int c; + + c = line[0]; + + if (isspace(c)) + return strspn(line, " "); + else if (ispunct(c)) + return strspn(line, PUNCTUATION); + else + { + if (isspace(line[1])) + return 1 + strspn(&line[1], " "); + else + return strcspn(line, " "PUNCTUATION); + } +} + +int M_JumpWordReverse(const char *line, int offset) +{ + int (*is)(int); + int c; + c = line[--offset]; + if (isspace(c)) + is = isspace; + else if (ispunct(c)) + is = ispunct; + else + is = isalnum; + c = (*is)(line[offset]); + while (offset > 0 && + (*is)(line[offset - 1]) == c) + offset--; + return offset; +} + +const char * M_Ftrim (double f) +{ + static char dig[9];/* "0." + 6 digits (6 is printf's default) */ + int i; + /* I know I said it's the default, but just in case... */ + sprintf(dig, "%.6f", fabs(modf(f, &f))); + /* trim trailing zeroes */ + for (i = strlen(dig)-1; dig[i] == '0'; --i) + ; + if (dig[i] == '.')/* :NOTHING: */ + return ""; + else + { + dig[i + 1] = '\0'; + return &dig[1];/* skip the 0 */ + } +} \ No newline at end of file diff --git a/src/m_misc.h b/src/m_misc.h index 456aa0a4f..cfcd0f3f7 100644 --- a/src/m_misc.h +++ b/src/m_misc.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -40,13 +40,7 @@ void M_SaveFrame(void); void M_StopMovie(void); // the file where game vars and settings are saved -#ifdef DC -#define CONFIGFILENAME "srb2dc.cfg" -#elif defined (PSP) -#define CONFIGFILENAME "srb2psp.cfg" -#else #define CONFIGFILENAME "kartconfig.cfg" -#endif INT32 M_MapNumber(char first, char second); @@ -54,6 +48,8 @@ boolean FIL_WriteFile(char const *name, const void *source, size_t length); size_t FIL_ReadFileTag(char const *name, UINT8 **buffer, INT32 tag); #define FIL_ReadFile(n, b) FIL_ReadFileTag(n, b, PU_STATIC) +boolean FIL_ConvertTextFileToBinary(const char *textfilename, const char *binfilename); + boolean FIL_FileExists(const char *name); boolean FIL_WriteFileOK(char const *name); boolean FIL_ReadFileOK(char const *name); @@ -107,6 +103,20 @@ boolean M_IsPathAbsolute (const char *path); void M_MkdirEach (const char *path, int start, int mode); void M_MkdirEachUntil (const char *path, int start, int end, int mode); +/* Return offset to the first word in a string. */ +/* E.g. cursor += M_JumpWord(line + cursor); */ +int M_JumpWord (const char *s); + +/* Return index of the last word behind offset bytes in a string. */ +/* E.g. cursor = M_JumpWordReverse(line, cursor); */ +int M_JumpWordReverse (const char *line, int offset); + +/* +Return dot and then the fractional part of a float, without +trailing zeros, or "" if the fractional part is zero. +*/ +const char * M_Ftrim (double); + // counting bits, for weapon ammo code, usually FUNCMATH UINT8 M_CountBits(UINT32 num, UINT8 size); diff --git a/src/m_perfstats.c b/src/m_perfstats.c new file mode 100644 index 000000000..df1e31b5e --- /dev/null +++ b/src/m_perfstats.c @@ -0,0 +1,541 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_perfstats.c +/// \brief Performance measurement tools. + +#include "m_perfstats.h" +#include "v_video.h" +#include "i_video.h" +#include "d_netcmd.h" +#include "r_main.h" +#include "i_system.h" +#include "z_zone.h" +#include "p_local.h" + +#ifdef HWRENDER +#include "hardware/hw_main.h" +#endif + +int ps_tictime = 0; + +int ps_playerthink_time = 0; +int ps_thinkertime = 0; + +int ps_thlist_times[NUM_THINKERLISTS]; +static const char* thlist_names[] = { + "Polyobjects: %d", + "Main: %d", + "Mobjs: %d", + "Dynamic slopes: %d", + "Precipitation: %d", + NULL +}; +static const char* thlist_shortnames[] = { + "plyobjs %d", + "main %d", + "mobjs %d", + "dynslop %d", + "precip %d", + NULL +}; + +int ps_checkposition_calls = 0; + +int ps_lua_thinkframe_time = 0; +int ps_lua_mobjhooks = 0; + +// dynamically allocated resizeable array for thinkframe hook stats +ps_hookinfo_t *thinkframe_hooks = NULL; +int thinkframe_hooks_length = 0; +int thinkframe_hooks_capacity = 16; + +void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src) +{ + if (!thinkframe_hooks) + { + // array needs to be initialized + thinkframe_hooks = Z_Malloc(sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL); + } + if (index >= thinkframe_hooks_capacity) + { + // array needs more space, realloc with double size + thinkframe_hooks_capacity *= 2; + thinkframe_hooks = Z_Realloc(thinkframe_hooks, + sizeof(ps_hookinfo_t) * thinkframe_hooks_capacity, PU_STATIC, NULL); + } + thinkframe_hooks[index].time_taken = time_taken; + memcpy(thinkframe_hooks[index].short_src, short_src, LUA_IDSIZE * sizeof(char)); + // since the values are set sequentially from begin to end, the last call should leave + // the correct value to this variable + thinkframe_hooks_length = index + 1; +} + +void M_DrawPerfStats(void) +{ + char s[100]; + int currenttime = I_GetTimeMicros(); + int frametime = currenttime - ps_prevframetime; + ps_prevframetime = currenttime; + + if (cv_perfstats.value == 1) // rendering + { + if (vid.width < 640 || vid.height < 400) // low resolution + { + snprintf(s, sizeof s - 1, "frmtime %d", frametime); + V_DrawThinString(20, 10, V_MONOSPACE | V_YELLOWMAP, s); + if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) + { + snprintf(s, sizeof s - 1, "ui %d", ps_uitime); + V_DrawThinString(20, 18, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "finupdt %d", ps_swaptime); + V_DrawThinString(20, 26, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "logic %d", ps_tictime); + V_DrawThinString(20, 38, V_MONOSPACE | V_GRAYMAP, s); + return; + } + snprintf(s, sizeof s - 1, "drwtime %d", ps_rendercalltime); + V_DrawThinString(20, 18, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "bspcall %d", ps_numbspcalls); + V_DrawThinString(90, 10, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "sprites %d", ps_numsprites); + V_DrawThinString(90, 18, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "drwnode %d", ps_numdrawnodes); + V_DrawThinString(90, 26, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "plyobjs %d", ps_numpolyobjects); + V_DrawThinString(90, 34, V_MONOSPACE | V_BLUEMAP, s); +#ifdef HWRENDER + if (rendermode == render_opengl) // OpenGL specific stats + { + snprintf(s, sizeof s - 1, "skybox %d", ps_hw_skyboxtime); + V_DrawThinString(24, 26, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "bsptime %d", ps_bsptime); + V_DrawThinString(24, 34, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "nodesrt %d", ps_hw_nodesorttime); + V_DrawThinString(24, 42, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "nodedrw %d", ps_hw_nodedrawtime); + V_DrawThinString(24, 50, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "sprsort %d", ps_hw_spritesorttime); + V_DrawThinString(24, 58, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "sprdraw %d", ps_hw_spritedrawtime); + V_DrawThinString(24, 66, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "other %d", + ps_rendercalltime - ps_hw_skyboxtime - ps_bsptime - ps_hw_nodesorttime + - ps_hw_nodedrawtime - ps_hw_spritesorttime - ps_hw_spritedrawtime + - ps_hw_batchsorttime - ps_hw_batchdrawtime); + V_DrawThinString(24, 74, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "ui %d", ps_uitime); + V_DrawThinString(20, 82, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "finupdt %d", ps_swaptime); + V_DrawThinString(20, 90, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "logic %d", ps_tictime); + V_DrawThinString(20, 102, V_MONOSPACE | V_GRAYMAP, s); + if (cv_glbatching.value) + { + snprintf(s, sizeof s - 1, "batsort %d", ps_hw_batchsorttime); + V_DrawThinString(90, 46, V_MONOSPACE | V_REDMAP, s); + snprintf(s, sizeof s - 1, "batdraw %d", ps_hw_batchdrawtime); + V_DrawThinString(90, 54, V_MONOSPACE | V_REDMAP, s); + + snprintf(s, sizeof s - 1, "polygon %d", ps_hw_numpolys); + V_DrawThinString(155, 10, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "drwcall %d", ps_hw_numcalls); + V_DrawThinString(155, 18, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "shaders %d", ps_hw_numshaders); + V_DrawThinString(155, 26, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "vertex %d", ps_hw_numverts); + V_DrawThinString(155, 34, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "texture %d", ps_hw_numtextures); + V_DrawThinString(220, 10, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "polyflg %d", ps_hw_numpolyflags); + V_DrawThinString(220, 18, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "colors %d", ps_hw_numcolors); + V_DrawThinString(220, 26, V_MONOSPACE | V_PURPLEMAP, s); + } + else + { + // reset these vars so the "other" measurement isn't off + ps_hw_batchsorttime = 0; + ps_hw_batchdrawtime = 0; + } + } + else // software specific stats +#endif + { + snprintf(s, sizeof s - 1, "bsptime %d", ps_bsptime); + V_DrawThinString(24, 26, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "sprclip %d", ps_sw_spritecliptime); + V_DrawThinString(24, 34, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "portals %d", ps_sw_portaltime); + V_DrawThinString(24, 42, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "planes %d", ps_sw_planetime); + V_DrawThinString(24, 50, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "masked %d", ps_sw_maskedtime); + V_DrawThinString(24, 58, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "other %d", + ps_rendercalltime - ps_bsptime - ps_sw_spritecliptime + - ps_sw_portaltime - ps_sw_planetime - ps_sw_maskedtime); + V_DrawThinString(24, 66, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "ui %d", ps_uitime); + V_DrawThinString(20, 74, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "finupdt %d", ps_swaptime); + V_DrawThinString(20, 82, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "logic %d", ps_tictime); + V_DrawThinString(20, 94, V_MONOSPACE | V_GRAYMAP, s); + } + } + else // high resolution + { + snprintf(s, sizeof s - 1, "Frame time: %d", frametime); + V_DrawSmallString(20, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) + { + snprintf(s, sizeof s - 1, "UI render: %d", ps_uitime); + V_DrawSmallString(20, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "I_FinishUpdate: %d", ps_swaptime); + V_DrawSmallString(20, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Game logic: %d", ps_tictime); + V_DrawSmallString(20, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + return; + } + snprintf(s, sizeof s - 1, "3d rendering: %d", ps_rendercalltime); + V_DrawSmallString(20, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "BSP calls: %d", ps_numbspcalls); + V_DrawSmallString(115, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Sprites: %d", ps_numsprites); + V_DrawSmallString(115, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Drawnodes: %d", ps_numdrawnodes); + V_DrawSmallString(115, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Polyobjects: %d", ps_numpolyobjects); + V_DrawSmallString(115, 25, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); +#ifdef HWRENDER + if (rendermode == render_opengl) // OpenGL specific stats + { + snprintf(s, sizeof s - 1, "Skybox render: %d", ps_hw_skyboxtime); + V_DrawSmallString(24, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "RenderBSPNode: %d", ps_bsptime); + V_DrawSmallString(24, 25, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Drwnode sort: %d", ps_hw_nodesorttime); + V_DrawSmallString(24, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Drwnode render: %d", ps_hw_nodedrawtime); + V_DrawSmallString(24, 35, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Sprite sort: %d", ps_hw_spritesorttime); + V_DrawSmallString(24, 40, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Sprite render: %d", ps_hw_spritedrawtime); + V_DrawSmallString(24, 45, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + // Remember to update this calculation when adding more 3d rendering stats! + snprintf(s, sizeof s - 1, "Other: %d", + ps_rendercalltime - ps_hw_skyboxtime - ps_bsptime - ps_hw_nodesorttime + - ps_hw_nodedrawtime - ps_hw_spritesorttime - ps_hw_spritedrawtime + - ps_hw_batchsorttime - ps_hw_batchdrawtime); + V_DrawSmallString(24, 50, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "UI render: %d", ps_uitime); + V_DrawSmallString(20, 55, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "I_FinishUpdate: %d", ps_swaptime); + V_DrawSmallString(20, 60, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Game logic: %d", ps_tictime); + V_DrawSmallString(20, 70, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + if (cv_glbatching.value) + { + snprintf(s, sizeof s - 1, "Batch sort: %d", ps_hw_batchsorttime); + V_DrawSmallString(115, 35, V_MONOSPACE | V_ALLOWLOWERCASE | V_REDMAP, s); + snprintf(s, sizeof s - 1, "Batch render: %d", ps_hw_batchdrawtime); + V_DrawSmallString(115, 40, V_MONOSPACE | V_ALLOWLOWERCASE | V_REDMAP, s); + + snprintf(s, sizeof s - 1, "Polygons: %d", ps_hw_numpolys); + V_DrawSmallString(200, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "Vertices: %d", ps_hw_numverts); + V_DrawSmallString(200, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "Draw calls: %d", ps_hw_numcalls); + V_DrawSmallString(200, 25, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "Shaders: %d", ps_hw_numshaders); + V_DrawSmallString(200, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "Textures: %d", ps_hw_numtextures); + V_DrawSmallString(200, 35, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "Polyflags: %d", ps_hw_numpolyflags); + V_DrawSmallString(200, 40, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "Colors: %d", ps_hw_numcolors); + V_DrawSmallString(200, 45, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + } + else + { + // reset these vars so the "other" measurement isn't off + ps_hw_batchsorttime = 0; + ps_hw_batchdrawtime = 0; + } + } + else // software specific stats +#endif + { + snprintf(s, sizeof s - 1, "RenderBSPNode: %d", ps_bsptime); + V_DrawSmallString(24, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "R_ClipSprites: %d", ps_sw_spritecliptime); + V_DrawSmallString(24, 25, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Portals+Skybox: %d", ps_sw_portaltime); + V_DrawSmallString(24, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "R_DrawPlanes: %d", ps_sw_planetime); + V_DrawSmallString(24, 35, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "R_DrawMasked: %d", ps_sw_maskedtime); + V_DrawSmallString(24, 40, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + // Remember to update this calculation when adding more 3d rendering stats! + snprintf(s, sizeof s - 1, "Other: %d", + ps_rendercalltime - ps_bsptime - ps_sw_spritecliptime + - ps_sw_portaltime - ps_sw_planetime - ps_sw_maskedtime); + V_DrawSmallString(24, 45, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "UI render: %d", ps_uitime); + V_DrawSmallString(20, 50, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "I_FinishUpdate: %d", ps_swaptime); + V_DrawSmallString(20, 55, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Game logic: %d", ps_tictime); + V_DrawSmallString(20, 65, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + } + } + } + else if (cv_perfstats.value == 2) // logic + { + int i = 0; + thinker_t *thinker; + int thinkercount = 0; + int polythcount = 0; + int mainthcount = 0; + int mobjcount = 0; + int nothinkcount = 0; + int scenerycount = 0; + int dynslopethcount = 0; + int precipcount = 0; + int removecount = 0; + // y offset for drawing columns + int yoffset1 = 0; + int yoffset2 = 0; + + for (i = 0; i < NUM_THINKERLISTS; i++) + { + for (thinker = thlist[i].next; thinker != &thlist[i]; thinker = thinker->next) + { + thinkercount++; + if (thinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + removecount++; + else if (i == THINK_POLYOBJ) + polythcount++; + else if (i == THINK_MAIN) + mainthcount++; + else if (i == THINK_MOBJ) + { + if (thinker->function.acp1 == (actionf_p1)P_MobjThinker) + { + mobj_t *mobj = (mobj_t*)thinker; + mobjcount++; + if (mobj->flags & MF_NOTHINK) + nothinkcount++; + else if (mobj->flags & MF_SCENERY) + scenerycount++; + } + } + else if (i == THINK_DYNSLOPE) + dynslopethcount++; + else if (i == THINK_PRECIP) + precipcount++; + } + } + + if (vid.width < 640 || vid.height < 400) // low resolution + { + snprintf(s, sizeof s - 1, "logic %d", ps_tictime); + V_DrawThinString(20, 10, V_MONOSPACE | V_YELLOWMAP, s); + if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) + return; + snprintf(s, sizeof s - 1, "plrthnk %d", ps_playerthink_time); + V_DrawThinString(24, 18, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "thnkers %d", ps_thinkertime); + V_DrawThinString(24, 26, V_MONOSPACE | V_YELLOWMAP, s); + for (i = 0; i < NUM_THINKERLISTS; i++) + { + yoffset1 += 8; + snprintf(s, sizeof s - 1, thlist_shortnames[i], ps_thlist_times[i]); + V_DrawThinString(28, 26+yoffset1, V_MONOSPACE | V_YELLOWMAP, s); + } + snprintf(s, sizeof s - 1, "lthinkf %d", ps_lua_thinkframe_time); + V_DrawThinString(24, 34+yoffset1, V_MONOSPACE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "other %d", + ps_tictime - ps_playerthink_time - ps_thinkertime - ps_lua_thinkframe_time); + V_DrawThinString(24, 42+yoffset1, V_MONOSPACE | V_YELLOWMAP, s); + + snprintf(s, sizeof s - 1, "thnkers %d", thinkercount); + V_DrawThinString(90, 10, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "plyobjs %d", polythcount); + V_DrawThinString(94, 18, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "main %d", mainthcount); + V_DrawThinString(94, 26, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "mobjs %d", mobjcount); + V_DrawThinString(94, 34, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "regular %d", mobjcount - scenerycount - nothinkcount); + V_DrawThinString(98, 42, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "scenery %d", scenerycount); + V_DrawThinString(98, 50, V_MONOSPACE | V_BLUEMAP, s); + if (nothinkcount) + { + snprintf(s, sizeof s - 1, "nothink %d", nothinkcount); + V_DrawThinString(98, 58, V_MONOSPACE | V_BLUEMAP, s); + yoffset2 += 8; + } + snprintf(s, sizeof s - 1, "dynslop %d", dynslopethcount); + V_DrawThinString(94, 58+yoffset2, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "precip %d", precipcount); + V_DrawThinString(94, 66+yoffset2, V_MONOSPACE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "remove %d", removecount); + V_DrawThinString(94, 74+yoffset2, V_MONOSPACE | V_BLUEMAP, s); + + snprintf(s, sizeof s - 1, "lmhooks %d", ps_lua_mobjhooks); + V_DrawThinString(170, 10, V_MONOSPACE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "chkpos %d", ps_checkposition_calls); + V_DrawThinString(170, 18, V_MONOSPACE | V_PURPLEMAP, s); + } + else // high resolution + { + snprintf(s, sizeof s - 1, "Game logic: %d", ps_tictime); + V_DrawSmallString(20, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) + return; + snprintf(s, sizeof s - 1, "P_PlayerThink: %d", ps_playerthink_time); + V_DrawSmallString(24, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "P_RunThinkers: %d", ps_thinkertime); + V_DrawSmallString(24, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + for (i = 0; i < NUM_THINKERLISTS; i++) + { + yoffset1 += 5; + snprintf(s, sizeof s - 1, thlist_names[i], ps_thlist_times[i]); + V_DrawSmallString(28, 20+yoffset1, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + } + snprintf(s, sizeof s - 1, "LUAh_ThinkFrame: %d", ps_lua_thinkframe_time); + V_DrawSmallString(24, 25+yoffset1, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + snprintf(s, sizeof s - 1, "Other: %d", + ps_tictime - ps_playerthink_time - ps_thinkertime - ps_lua_thinkframe_time); + V_DrawSmallString(24, 30+yoffset1, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, s); + + snprintf(s, sizeof s - 1, "Thinkers: %d", thinkercount); + V_DrawSmallString(115, 10+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Polyobjects: %d", polythcount); + V_DrawSmallString(119, 15+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Main: %d", mainthcount); + V_DrawSmallString(119, 20+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Mobjs: %d", mobjcount); + V_DrawSmallString(119, 25+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Regular: %d", mobjcount - scenerycount - nothinkcount); + V_DrawSmallString(123, 30+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Scenery: %d", scenerycount); + V_DrawSmallString(123, 35+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + if (nothinkcount) + { + snprintf(s, sizeof s - 1, "Nothink: %d", nothinkcount); + V_DrawSmallString(123, 40+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + yoffset2 += 5; + } + snprintf(s, sizeof s - 1, "Dynamic slopes: %d", dynslopethcount); + V_DrawSmallString(119, 40+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Precipitation: %d", precipcount); + V_DrawSmallString(119, 45+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + snprintf(s, sizeof s - 1, "Pending removal: %d", removecount); + V_DrawSmallString(119, 50+yoffset2, V_MONOSPACE | V_ALLOWLOWERCASE | V_BLUEMAP, s); + + snprintf(s, sizeof s - 1, "Calls:"); + V_DrawSmallString(212, 10, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "Lua mobj hooks: %d", ps_lua_mobjhooks); + V_DrawSmallString(216, 15, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + snprintf(s, sizeof s - 1, "P_CheckPosition: %d", ps_checkposition_calls); + V_DrawSmallString(216, 20, V_MONOSPACE | V_ALLOWLOWERCASE | V_PURPLEMAP, s); + } + } + else if (cv_perfstats.value == 3) // lua thinkframe + { + if (!(gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction))) + return; + if (vid.width < 640 || vid.height < 400) // low resolution + { + // it's not gonna fit very well.. + V_DrawThinString(30, 30, V_MONOSPACE | V_ALLOWLOWERCASE | V_YELLOWMAP, "Not available for resolutions below 640x400"); + } + else // high resolution + { + int i; + // text writing position + int x = 2; + int y = 4; + UINT32 text_color; + char tempbuffer[LUA_IDSIZE]; + char last_mod_name[LUA_IDSIZE]; + last_mod_name[0] = '\0'; + for (i = 0; i < thinkframe_hooks_length; i++) + { + char* str = thinkframe_hooks[i].short_src; + char* tempstr = tempbuffer; + int len = (int)strlen(str); + char* str_ptr; + if (strcmp(".lua", str + len - 4) == 0) + { + str[len-4] = '\0'; // remove .lua at end + len -= 4; + } + // we locate the wad/pk3 name in the string and compare it to + // what we found on the previous iteration. + // if the name has changed, print it out on the screen + strcpy(tempstr, str); + str_ptr = strrchr(tempstr, '|'); + if (str_ptr) + { + *str_ptr = '\0'; + str = str_ptr + 1; // this is the name of the hook without the mod file name + str_ptr = strrchr(tempstr, PATHSEP[0]); + if (str_ptr) + tempstr = str_ptr + 1; + // tempstr should now point to the mod name, (wad/pk3) possibly truncated + if (strcmp(tempstr, last_mod_name) != 0) + { + strcpy(last_mod_name, tempstr); + len = (int)strlen(tempstr); + if (len > 25) + tempstr += len - 25; + snprintf(s, sizeof s - 1, "%s", tempstr); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | V_GRAYMAP, s); + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + } + text_color = V_YELLOWMAP; + } + else + { + // probably a standalone lua file + // cut off the folder if it's there + str_ptr = strrchr(tempstr, PATHSEP[0]); + if (str_ptr) + str = str_ptr + 1; + text_color = 0; // white + } + len = (int)strlen(str); + if (len > 20) + str += len - 20; + snprintf(s, sizeof s - 1, "%20s: %u", str, thinkframe_hooks[i].time_taken); + V_DrawSmallString(x, y, V_MONOSPACE | V_ALLOWLOWERCASE | text_color, s); + y += 4; // repeated code! + if (y > 192) + { + y = 4; + x += 106; + if (x > 214) + break; + } + } + } + } +} diff --git a/src/m_perfstats.h b/src/m_perfstats.h new file mode 100644 index 000000000..1db46025e --- /dev/null +++ b/src/m_perfstats.h @@ -0,0 +1,42 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file m_perfstats.h +/// \brief Performance measurement tools. + +#ifndef __M_PERFSTATS_H__ +#define __M_PERFSTATS_H__ + +#include "doomdef.h" +#include "lua_script.h" +#include "p_local.h" + +extern int ps_tictime; + +extern int ps_playerthink_time; +extern int ps_thinkertime; + +extern int ps_thlist_times[]; + +extern int ps_checkposition_calls; + +extern int ps_lua_thinkframe_time; +extern int ps_lua_mobjhooks; + +typedef struct +{ + UINT32 time_taken; + char short_src[LUA_IDSIZE]; +} ps_hookinfo_t; + +void PS_SetThinkFrameHookInfo(int index, UINT32 time_taken, char* short_src); + +void M_DrawPerfStats(void); + +#endif diff --git a/src/m_queue.c b/src/m_queue.c index a3aa04871..8603ab202 100644 --- a/src/m_queue.c +++ b/src/m_queue.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2003 by James Haley -// Copyright (C) 2003-2018 by Sonic Team Junior. +// Copyright (C) 2003-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_queue.h b/src/m_queue.h index eebb21468..3e9579e11 100644 --- a/src/m_queue.h +++ b/src/m_queue.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2003 by James Haley -// Copyright (C) 2003-2018 by Sonic Team Junior. +// Copyright (C) 2003-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_random.c b/src/m_random.c index 3d46f76b7..481fdb72b 100644 --- a/src/m_random.c +++ b/src/m_random.c @@ -2,8 +2,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2012-2016 by Matthew "Inuyasha" Walsh. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_random.h b/src/m_random.h index 6187bcf1c..01190e046 100644 --- a/src/m_random.h +++ b/src/m_random.h @@ -2,8 +2,8 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2012-2016 by Matthew "Inuyasha" Walsh. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 2012-2016 by Matthew "Kaito Sinclaire" Walsh. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/m_swap.h b/src/m_swap.h index 2d42f6138..b44d6de8c 100644 --- a/src/m_swap.h +++ b/src/m_swap.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -14,29 +14,39 @@ #ifndef __M_SWAP__ #define __M_SWAP__ -#include "endian.h" - // Endianess handling. // WAD files are stored little endian. +#include "endian.h" + +// Little to big endian #ifdef SRB2_BIG_ENDIAN -#define SHORT(x) ((INT16)(\ -(((UINT16)(x) & (UINT16)0x00ffU) << 8) \ -| \ -(((UINT16)(x) & (UINT16)0xff00U) >> 8))) \ + #define SHORT(x) ((INT16)(\ + (((UINT16)(x) & (UINT16)0x00ffU) << 8) \ + | \ + (((UINT16)(x) & (UINT16)0xff00U) >> 8))) \ -#define LONG(x) ((INT32)(\ -(((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \ -| \ -(((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \ -| \ -(((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \ -| \ -(((UINT32)(x) & (UINT32)0xff000000UL) >> 24))) + #define LONG(x) ((INT32)(\ + (((UINT32)(x) & (UINT32)0x000000ffUL) << 24) \ + | \ + (((UINT32)(x) & (UINT32)0x0000ff00UL) << 8) \ + | \ + (((UINT32)(x) & (UINT32)0x00ff0000UL) >> 8) \ + | \ + (((UINT32)(x) & (UINT32)0xff000000UL) >> 24))) #else -#define SHORT(x) ((INT16)(x)) -#define LONG(x) ((INT32)(x)) + #define SHORT(x) ((INT16)(x)) + #define LONG(x) ((INT32)(x)) +#endif + +// Big to little endian +#ifdef SRB2_LITTLE_ENDIAN + #define BIGENDIAN_LONG(x) ((INT32)(((x)>>24)&0xff)|(((x)<<8)&0xff0000)|(((x)>>8)&0xff00)|(((x)<<24)&0xff000000)) + #define BIGENDIAN_SHORT(x) ((INT16)(((x)>>8)|((x)<<8))) +#else + #define BIGENDIAN_LONG(x) ((INT32)(x)) + #define BIGENDIAN_SHORT(x) ((INT16)(x)) #endif #endif diff --git a/src/md5.c b/src/md5.c index 8031650e6..66d563666 100644 --- a/src/md5.c +++ b/src/md5.c @@ -19,9 +19,7 @@ #endif #include -#ifndef _WIN32_WCE #include -#endif #ifdef _MSC_VER #pragma warning(disable : 4127) #endif @@ -30,7 +28,7 @@ #include #else #ifndef HAVE_MEMCPY - #if !((defined (_WIN32) || defined (_WIN32_WCE)) && !defined (__CYGWIN__)) && !defined (__APPLE__) + #if !(defined (_WIN32) && !defined (__CYGWIN__)) && !defined (__APPLE__) #define memcpy(d, s, n) bcopy ((s), (d), (n)) #endif #endif diff --git a/src/mserv.c b/src/mserv.c index f3d414c92..88cede440 100644 --- a/src/mserv.c +++ b/src/mserv.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // Copyright (C) 2020 by James R. // // This program is free software distributed under the @@ -23,6 +23,12 @@ #include "m_menu.h" #include "z_zone.h" +#ifdef HAVE_DISCORDRPC +#include "discord.h" +#endif + +#ifdef MASTERSERVER + static int MSId; static int MSRegisteredId = -1; @@ -43,27 +49,33 @@ static I_cond MSCond; # define Unlock_state() #endif/*HAVE_THREADS*/ -static void Update_parameters (void); - #ifndef NONET static void Command_Listserv_f(void); #endif + +#endif/*MASTERSERVER*/ + +static void Update_parameters (void); + static void MasterServer_OnChange(void); +static void Advertise_OnChange(void); + static CV_PossibleValue_t masterserver_update_rate_cons_t[] = { {2, "MIN"}, {60, "MAX"}, - {0} + {0, NULL} }; -consvar_t cv_masterserver = {"masterserver", "https://mb.srb2.org/MS/0", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_servername = {"servername", "SRB2Kart server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ms.kartkrew.org/ms/api", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange); +consvar_t cv_servername = CVAR_INIT ("servername", "SRB2Kart server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters); +consvar_t cv_server_contact = CVAR_INIT ("server_contact", "", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters); -consvar_t cv_masterserver_update_rate = {"masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, Update_parameters, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_masterserver_update_rate = CVAR_INIT ("masterserver_update_rate", "15", CV_SAVE|CV_CALL|CV_NOINIT, masterserver_update_rate_cons_t, MasterClient_Ticker); -INT16 ms_RoomId = -1; +consvar_t cv_advertise = CVAR_INIT ("advertise", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, Advertise_OnChange); -#ifdef HAVE_THREADS +#if defined (MASTERSERVER) && defined (HAVE_THREADS) int ms_QueryId; I_mutex ms_QueryId_mutex; @@ -73,10 +85,6 @@ I_mutex ms_ServerList_mutex; UINT16 current_port = 0; -// Room list is an external variable now. -// Avoiding having to get info ten thousand times... -msg_rooms_t room_list[NUM_LIST_ROOMS+1]; // +1 for easy test - /** Adds variables and commands relating to the master server. * * \sa cv_masterserver, cv_servername, @@ -90,11 +98,17 @@ void AddMServCommands(void) CV_RegisterVar(&cv_masterserver_timeout); CV_RegisterVar(&cv_masterserver_debug); CV_RegisterVar(&cv_masterserver_token); + CV_RegisterVar(&cv_advertise); CV_RegisterVar(&cv_servername); + CV_RegisterVar(&cv_server_contact); +#ifdef MASTERSERVER COM_AddCommand("listserv", Command_Listserv_f); #endif +#endif } +#ifdef MASTERSERVER + static void WarnGUI (void) { #ifdef HAVE_THREADS @@ -107,14 +121,14 @@ static void WarnGUI (void) } #define NUM_LIST_SERVER MAXSERVERLIST -msg_server_t *GetShortServersList(INT32 room, int id) +msg_server_t *GetShortServersList(int id) { msg_server_t *server_list; // +1 for easy test server_list = malloc(( NUM_LIST_SERVER + 1 ) * sizeof *server_list); - if (HMS_fetch_servers(server_list, room, id)) + if (HMS_fetch_servers(server_list, id)) return server_list; else { @@ -124,17 +138,6 @@ msg_server_t *GetShortServersList(INT32 room, int id) } } -INT32 GetRoomsList(boolean hosting, int id) -{ - if (HMS_fetch_rooms( ! hosting, id)) - return 1; - else - { - WarnGUI(); - return -1; - } -} - #ifdef UPDATE_ALERT char *GetMODVersion(int id) { @@ -168,15 +171,6 @@ char *GetMODVersion(int id) return NULL; } } - -// Console only version of the above (used before game init) -void GetMODVersion_Console(void) -{ - char buffer[16]; - - if (HMS_compare_mod_version(buffer, sizeof buffer) > 0) - I_Error(UPDATE_ALERT_STRING_CONSOLE, VERSIONSTRING, buffer); -} #endif #ifndef NONET @@ -267,6 +261,9 @@ Finish_unlist (void) Lock_state(); { registered = MSRegistered; + + if (MSId == MSRegisteredId) + MSId++; } Unlock_state(); @@ -287,13 +284,6 @@ Finish_unlist (void) I_wake_all_cond(&MSCond); #endif } - - Lock_state(); - { - if (MSId == MSRegisteredId) - MSId++; - } - Unlock_state(); } #ifdef HAVE_THREADS @@ -395,6 +385,7 @@ Change_masterserver_thread (char *api) void RegisterServer(void) { +#ifdef MASTERSERVER #ifdef HAVE_THREADS I_spawn_thread( "register-server", @@ -404,6 +395,7 @@ void RegisterServer(void) #else Finish_registration(); #endif +#endif/*MASTERSERVER*/ } static void UpdateServer(void) @@ -421,6 +413,7 @@ static void UpdateServer(void) void UnregisterServer(void) { +#ifdef MASTERSERVER #ifdef HAVE_THREADS I_spawn_thread( "unlist-server", @@ -430,12 +423,13 @@ void UnregisterServer(void) #else Finish_unlist(); #endif +#endif/*MASTERSERVER*/ } static boolean Online (void) { - return ( serverrunning && ms_RoomId > 0 ); + return ( serverrunning && cv_advertise.value ); } static inline void SendPingToMasterServer(void) @@ -465,9 +459,33 @@ static inline void SendPingToMasterServer(void) } } +void MasterClient_Ticker(void) +{ +#ifdef MASTERSERVER + SendPingToMasterServer(); +#endif +} + +static void +Set_api (const char *api) +{ +#ifdef HAVE_THREADS + I_spawn_thread( + "change-masterserver", + (I_thread_fn)Change_masterserver_thread, + strdup(api) + ); +#else + HMS_set_api(strdup(api)); +#endif +} + +#endif/*MASTERSERVER*/ + static void Update_parameters (void) { +#ifdef MASTERSERVER int registered; int delayed; @@ -487,29 +505,12 @@ Update_parameters (void) if (! delayed && registered) UpdateServer(); } -} - -void MasterClient_Ticker(void) -{ - SendPingToMasterServer(); -} - -static void -Set_api (const char *api) -{ -#ifdef HAVE_THREADS - I_spawn_thread( - "change-masterserver", - (I_thread_fn)Change_masterserver_thread, - strdup(api) - ); -#else - HMS_set_api(strdup(api)); -#endif +#endif/*MASTERSERVER*/ } static void MasterServer_OnChange(void) { +#ifdef MASTERSERVER UnregisterServer(); /* @@ -527,4 +528,36 @@ static void MasterServer_OnChange(void) if (Online()) RegisterServer(); +#endif/*MASTERSERVER*/ +} + +static void +Advertise_OnChange(void) +{ + int different; + + if (cv_advertise.value) + { + if (serverrunning) + { + Lock_state(); + { + different = ( MSId != MSRegisteredId ); + } + Unlock_state(); + + if (different) + { + RegisterServer(); + } + } + } + else + { + UnregisterServer(); + } + +#ifdef HAVE_DISCORDRPC + DRPC_UpdatePresence(); +#endif } diff --git a/src/mserv.h b/src/mserv.h index 9269c408a..2a0afd1b3 100644 --- a/src/mserv.h +++ b/src/mserv.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // Copyright (C) 2020 by James R. // // This program is free software distributed under the @@ -16,9 +16,6 @@ #include "i_threads.h" -// lowered from 32 due to menu changes -#define NUM_LIST_ROOMS 16 - #if defined(_MSC_VER) #pragma pack(1) #endif @@ -35,19 +32,10 @@ typedef struct msg_header_t header; char ip[16]; char port[8]; - char name[32]; - INT32 room; + char contact[32]; char version[8]; // format is: x.yy.z (like 1.30.2 or 1.31) } ATTRPACK msg_server_t; -typedef struct -{ - msg_header_t header; - INT32 id; - char name[32]; - char motd[255]; -} ATTRPACK msg_rooms_t; - typedef struct { msg_header_t header; @@ -65,15 +53,13 @@ typedef struct // ================================ GLOBALS =============================== extern consvar_t cv_masterserver, cv_servername; +extern consvar_t cv_server_contact; extern consvar_t cv_masterserver_update_rate; extern consvar_t cv_masterserver_timeout; extern consvar_t cv_masterserver_debug; extern consvar_t cv_masterserver_token; -// < 0 to not connect (usually -1) (offline mode) -// == 0 to show all rooms, not a valid hosting room -// anything else is whatever room the MS assigns to that number (online mode) -extern INT16 ms_RoomId; +extern consvar_t cv_advertise; #ifdef HAVE_THREADS extern int ms_QueryId; @@ -88,24 +74,20 @@ void UnregisterServer(void); void MasterClient_Ticker(void); -msg_server_t *GetShortServersList(INT32 room, int id); -INT32 GetRoomsList(boolean hosting, int id); +msg_server_t *GetShortServersList(int id); #ifdef UPDATE_ALERT char *GetMODVersion(int id); -void GetMODVersion_Console(void); #endif -extern msg_rooms_t room_list[NUM_LIST_ROOMS+1]; void AddMServCommands(void); /* HTTP */ void HMS_set_api (char *api); -int HMS_fetch_rooms (int joining, int id); int HMS_register (void); int HMS_unlist (void); int HMS_update (void); void HMS_list_servers (void); -msg_server_t * HMS_fetch_servers (msg_server_t *list, int room, int id); +msg_server_t * HMS_fetch_servers (msg_server_t *list, int id); int HMS_compare_mod_version (char *buffer, size_t size_of_buffer); #endif diff --git a/src/nds/Makefile.cfg b/src/nds/Makefile.cfg deleted file mode 100644 index c2d915924..000000000 --- a/src/nds/Makefile.cfg +++ /dev/null @@ -1,31 +0,0 @@ -# Adapted in part from devkitPRO makefiles. - -NOMD5=1 - -# Check if DEVKITARM is set in the environment. If so, continue with compilation. -.SUFFIXES: - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -# use absolute paths because changing PATH variable breaks distcc -PREFIX := $(DEVKITARM)/bin/arm-eabi -NDSTOOL := $(DEVKITARM)/bin/ndstool - -# Disable same warning flags -WFLAGS+=-Wno-inline -Wno-cast-align -WFLAGS+=-Wno-shadow -Wno-char-subscripts -WFLAGS+=-Wno-declaration-after-statement -WFLAGS+=-Wno-old-style-definition -WFLAGS+=-Wno-undef -WFLAGS+=-Wno-unsuffixed-float-constants - -ifndef NOHW - OBJS+=$(OBJDIR)/r_nds3d.o -endif - -ARCH = -mthumb -mthumb-interwork -LDFLAGS += -L$(DEVKITPRO)/libnds/lib -specs=ds_arm9.specs -g $(ARCH) -mno-fpu -LIBS += -lfat -lnds9 -CFLAGS += -D_NDS -DARM9 -I$(DEVKITPRO)/libnds/include $(ARCH) -march=armv5te -mtune=arm946e-s -fomit-frame-pointer -ffast-math diff --git a/src/nds/i_cdmus.c b/src/nds/i_cdmus.c deleted file mode 100644 index f3f703667..000000000 --- a/src/nds/i_cdmus.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "../command.h" -#include "../s_sound.h" -#include "../i_sound.h" - -// -// CD MUSIC I/O -// - -UINT8 cdaudio_started = 0; - -consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; - - -void I_InitCD(void){} - -void I_StopCD(void){} - -void I_PauseCD(void){} - -void I_ResumeCD(void){} - -void I_ShutdownCD(void){} - -void I_UpdateCD(void){} - -void I_PlayCD(UINT8 track, UINT8 looping) -{ - (void)track; - (void)looping; -} - -boolean I_SetVolumeCD(int volume) -{ - (void)volume; - return false; -} diff --git a/src/nds/i_main.c b/src/nds/i_main.c deleted file mode 100644 index 292a5f91d..000000000 --- a/src/nds/i_main.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "../doomdef.h" -#include "../d_main.h" -#include "../m_argv.h" -#include "../i_system.h" - -int main(int argc, char **argv) -{ - myargc = argc; - myargv = argv; /// \todo pull out path to exe from this string - - CONS_Printf("I_StartupSystem..."); - I_StartupSystem(); - - // startup SRB2 - CONS_Printf("Setting up SRB2...\n"); - D_SRB2Main(); - CONS_Printf("Entering main game loop...\n"); - // never return - D_SRB2Loop(); - - // return to OS -#ifndef __GNUC__ - return 0; -#endif -} diff --git a/src/nds/i_net.c b/src/nds/i_net.c deleted file mode 100644 index f6e642022..000000000 --- a/src/nds/i_net.c +++ /dev/null @@ -1,6 +0,0 @@ -#include "../i_net.h" - -boolean I_InitNetwork(void) -{ - return false; -} diff --git a/src/nds/i_sound.c b/src/nds/i_sound.c deleted file mode 100644 index a17c7f66a..000000000 --- a/src/nds/i_sound.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "../i_sound.h" - -UINT8 sound_started = 0; - -void *I_GetSfx(sfxinfo_t *sfx) -{ - (void)sfx; - return NULL; -} - -void I_FreeSfx(sfxinfo_t *sfx) -{ - (void)sfx; -} - -void I_StartupSound(void){} - -void I_ShutdownSound(void){} - -// -// SFX I/O -// - -INT32 I_StartSound(sfxenum_t id, INT32 vol, INT32 sep, INT32 pitch, INT32 priority, INT32 channel) -{ - (void)id; - (void)vol; - (void)sep; - (void)pitch; - (void)priority; - (void)channel; - return -1; -} - -void I_StopSound(INT32 handle) -{ - (void)handle; -} - -INT32 I_SoundIsPlaying(INT32 handle) -{ - (void)handle; - return false; -} - -void I_UpdateSoundParams(INT32 handle, INT32 vol, INT32 sep, INT32 pitch) -{ - (void)handle; - (void)vol; - (void)sep; - (void)pitch; -} - -void I_SetSfxVolume(INT32 volume) -{ - (void)volume; -} - -// -// MUSIC I/O -// -UINT8 music_started = 0; - -void I_InitMusic(void){} - -void I_ShutdownMusic(void){} - -void I_PauseSong(INT32 handle) -{ - (void)handle; -} - -void I_ResumeSong(INT32 handle) -{ - (void)handle; -} - -// -// MIDI I/O -// - -UINT8 midimusic_started = 0; - -void I_InitMIDIMusic(void){} - -void I_ShutdownMIDIMusic(void){} - -void I_SetMIDIMusicVolume(INT32 volume) -{ - (void)volume; -} - -INT32 I_RegisterSong(void *data, size_t len) -{ - (void)data; - (void)len; - return -1; -} - -boolean I_PlaySong(INT32 handle, INT32 looping) -{ - (void)handle; - (void)looping; - return false; -} - -void I_StopSong(INT32 handle) -{ - (void)handle; -} - -void I_UnRegisterSong(INT32 handle) -{ - (void)handle; -} - -// -// DIGMUSIC I/O -// - -UINT8 digmusic_started = 0; - -void I_InitDigMusic(void){} - -void I_ShutdownDigMusic(void){} - -boolean I_StartDigSong(const char *musicname, INT32 looping) -{ - (void)musicname; - (void)looping; - return false; -} - -void I_StopDigSong(void){} - -void I_SetDigMusicVolume(INT32 volume) -{ - (void)volume; -} - -boolean I_SetSongSpeed(float speed) -{ - (void)speed; - return false; -} - -boolean I_SetSongTrack(int track) -{ - (void)track; - return false; -} diff --git a/src/nds/i_system.c b/src/nds/i_system.c deleted file mode 100644 index 3e5c4b8c6..000000000 --- a/src/nds/i_system.c +++ /dev/null @@ -1,286 +0,0 @@ -#include -#include - -#include "../doomdef.h" -#include "../d_main.h" -#include "../i_system.h" -#include "../i_joy.h" - -UINT8 graphics_started = 0; - -UINT8 keyboard_started = 0; - -static volatile tic_t ticcount; - - -UINT32 I_GetFreeMem(UINT32 *total) -{ - *total = 0; - return 0; -} - -tic_t I_GetTime(void) -{ - return ticcount; -} - -void I_Sleep(void){} - -void I_GetEvent(void) -{ - // Mappings of DS keys to SRB2 keys - UINT32 dskeys[] = - { - KEY_A, - KEY_B, - KEY_X, - KEY_Y, - KEY_L, - KEY_R, - KEY_START, - KEY_SELECT - }; - - event_t event; - UINT32 held, up, down; - UINT32 i; - - // Check how the state has changed since last time - scanKeys(); - - // For the d-pad, we only care about the current state - held = keysHeld(); - event.type = ev_joystick; - event.data1 = 0; // First (and only) axis set - - if (held & KEY_LEFT) event.data2 = -1; - else if (held & KEY_RIGHT) event.data2 = 1; - else event.data2 = 0; - - if (held & KEY_UP) event.data3 = -1; - else if (held & KEY_DOWN) event.data3 = 1; - else event.data3 = 0; - - D_PostEvent(&event); - - // For the buttons, we need to report changes in state - up = keysUp(); - down = keysDown(); - for (i = 0; i < sizeof(dskeys)/sizeof(dskeys[0]); i++) - { - // Has this button's state changed? - if ((up | down) & dskeys[i]) - { - event.type = (up & dskeys[i]) ? ev_keyup : ev_keydown; - event.data1 = KEY_JOY1 + i; - D_PostEvent(&event); - } - } -} - -void I_OsPolling(void) -{ - I_GetEvent(); -} - -ticcmd_t *I_BaseTiccmd(void) -{ - static ticcmd_t emptyticcmd; - return &emptyticcmd; -} - -ticcmd_t *I_BaseTiccmd2(void) -{ - static ticcmd_t emptyticcmd2; - return &emptyticcmd2; -} - -void I_Quit(void) -{ - exit(0); -} - -void I_Error(const char *error, ...) -{ - va_list argptr; - - va_start(argptr, error); - viprintf(error, argptr); - va_end(argptr); - - for(;;); -} - -void I_Tactile(FFType Type, const JoyFF_t *Effect) -{ - (void)Type; - (void)Effect; -} - -void I_Tactile2(FFType Type, const JoyFF_t *Effect) -{ - (void)Type; - (void)Effect; -} - -void I_JoyScale(void){} - -void I_JoyScale2(void){} - -void I_InitJoystick(void) -{ - Joystick.bGamepadStyle = true; -} - -void I_InitJoystick2(void){} - -INT32 I_NumJoys(void) -{ - return 0; -} - -const char *I_GetJoyName(INT32 joyindex) -{ - (void)joyindex; - return NULL; -} - -void I_SetupMumble(void) -{ -} - -#ifndef NOMUMBLE -void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) -{ - (void)mobj; - (void)listener; -} -#endif - -void I_OutputMsg(const char *error, ...) -{ - va_list argptr; - - va_start(argptr, error); - viprintf(error, argptr); - va_end(argptr); -} - -void I_StartupMouse(void){} - -void I_StartupMouse2(void){} - -void I_StartupKeyboard(void){} - -INT32 I_GetKey(void) -{ - return 0; -} - -static void NDS_VBlankHandler(void) -{ - ticcount++; -} - -void I_StartupTimer(void) -{ - irqSet(IRQ_VBLANK, NDS_VBlankHandler); -} - -void I_AddExitFunc(void (*func)()) -{ - (void)func; -} - -void I_RemoveExitFunc(void (*func)()) -{ - (void)func; -} - -// Adapted in part from the devkitPro examples. -INT32 I_StartupSystem(void) -{ - lcdMainOnTop(); - - videoSetModeSub(MODE_0_2D); - vramSetBankC(VRAM_C_MAIN_BG); // Get this mapped *out* of the sub BG - vramSetBankI(VRAM_I_SUB_BG_0x06208000); - - // The background VRAM that's mapped starts at 0x06208000. - // The map base is specified in an offset of multiples of 2 KB - // from 0x06200000, and the tile base in multiples of 16 KB. - // We put the tiles at the start and the map 2 KB from the end - // (i.e. 14 KB from the start). - // The map base is then at 0x0620B800 = 0x06200000 + 16 * 0x800 + 7 * 0x800, - // and the tile base is at 0x06208000 = 0x06200000 + 2 * 0x4000. - consoleInit(NULL, 0, BgType_Text4bpp, BgSize_T_256x256, 16+7, 2, false, true); - - // start FAT filesystem code, required for reading SD card - if(!fatInitDefault()) - I_Error("Couldn't init FAT."); - - return 0; -} - -void I_ShutdownSystem(void){} - -void I_GetDiskFreeSpace(INT64* freespace) -{ - *freespace = 0; -} - -char *I_GetUserName(void) -{ - return NULL; -} - -INT32 I_mkdir(const char *dirname, INT32 unixright) -{ - (void)dirname; - (void)unixright; - return -1; -} - -const CPUInfoFlags *I_CPUInfo(void) -{ - return NULL; -} - -const char *I_LocateWad(void) -{ - return NULL; -} - -void I_GetJoystickEvents(void){} - -void I_GetJoystick2Events(void){} - -void I_GetMouseEvents(void){} - -char *I_GetEnv(const char *name) -{ - (void)name; - return NULL; -} - -INT32 I_PutEnv(char *variable) -{ - (void)variable; - return -1; -} - -INT32 I_ClipboardCopy(const char *data, size_t size) -{ - (void)data; - (void)size; - return -1; -} - -char *I_ClipboardPaste(void) -{ - return NULL; -} - -void I_RegisterSysCommands(void) {} - -#include "../sdl/dosstr.c" diff --git a/src/nds/r_nds3d.h b/src/nds/r_nds3d.h deleted file mode 100644 index 3a7075bcd..000000000 --- a/src/nds/r_nds3d.h +++ /dev/null @@ -1,55 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief NDS 3D API for SRB2. - -#ifndef __R_NDS3D__ -#define __R_NDS3D__ - -#include "../doomtype.h" -#include "../hardware/hw_defs.h" -#include "../hardware/hw_dll.h" -#include "../hardware/hw_md2.h" - -#define FAR_CLIPPING_PLANE 150000.0f -#define ASPECT_RATIO 1.0f - -typedef float FCOORD; - -extern FCOORD NEAR_CLIPPING_PLANE; -extern float fov; - -boolean NDS3D_Init(I_Error_t ErrorFunction); -void NDS3D_Shutdown(void); -void NDS3D_SetPalette(RGBA_t *ppal, RGBA_t *pgamma); -void NDS3D_FinishUpdate(INT32 waitvbl); -void NDS3D_Draw2DLine(F2DCoord *v1, F2DCoord *v2, RGBA_t Color); -void NDS3D_DrawPolygon(FSurfaceInfo *pSurf, FOutVector *pOutVerts, FUINT iNumPts, FBITFIELD PolyFlags); -void NDS3D_SetBlend(FBITFIELD PolyFlags); -void NDS3D_ClearBuffer(FBOOLEAN ColorMask, FBOOLEAN DepthMask, FRGBAFloat *ClearColor); -void NDS3D_SetTexture(FTextureInfo *TexInfo); -void NDS3D_ReadRect(INT32 x, INT32 y, INT32 width, INT32 height, INT32 dst_stride, UINT16 *dst_data); -void NDS3D_GClipRect(INT32 minx, INT32 miny, INT32 maxx, INT32 maxy, float nearclip); -void NDS3D_ClearMipMapCache(void); -void NDS3D_SetSpecialState(hwdspecialstate_t IdState, INT32 Value); -void NDS3D_DrawMD2(INT32 *gl_cmd_buffer, md2_frame_t *frame, FTransform *pos, float scale); -void NDS3D_DrawMD2i(INT32 *gl_cmd_buffer, md2_frame_t *frame, UINT32 duration, UINT32 tics, md2_frame_t *nextframe, FTransform *pos, float scale, UINT8 flipped, UINT8 *color); -void NDS3D_SetTransform(FTransform *ptransform); -INT32 NDS3D_GetTextureUsed(void); -INT32 NDS3D_GetRenderVersion(void); - -#endif diff --git a/src/p_ceilng.c b/src/p_ceilng.c index a2db42b2d..532263adb 100644 --- a/src/p_ceilng.c +++ b/src/p_ceilng.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -47,8 +47,7 @@ void T_MoveCeiling(ceiling_t *ceiling) case 0: // IN STASIS break; case 1: // UP - res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, - 1, ceiling->direction); + res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, true, ceiling->direction); if (ceiling->type == bounceCeiling) { @@ -159,8 +158,7 @@ void T_MoveCeiling(ceiling_t *ceiling) break; case -1: // DOWN - res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, - ceiling->crush, 1, ceiling->direction); + res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, true, ceiling->direction); if (ceiling->type == bounceCeiling) { @@ -314,11 +312,10 @@ void T_CrushCeiling(ceiling_t *ceiling) if (ceiling->type == crushBothOnce) { // Move the floor - T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight-(ceiling->topheight-ceiling->bottomheight), false, 0, -ceiling->direction); + T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight-(ceiling->topheight-ceiling->bottomheight), false, false, -ceiling->direction); } - res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, - false, 1, ceiling->direction); + res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topheight, false, true, ceiling->direction); if (res == pastdest) { @@ -357,11 +354,10 @@ void T_CrushCeiling(ceiling_t *ceiling) if (ceiling->type == crushBothOnce) { // Move the floor - T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, 0, -ceiling->direction); + T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, false, -ceiling->direction); } - res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, - ceiling->crush, 1, ceiling->direction); + res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomheight, ceiling->crush, true, ceiling->direction); if (res == pastdest) { @@ -399,7 +395,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) sector_t *sec; ceiling_t *ceiling; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) { sec = §ors[secnum]; @@ -409,7 +405,7 @@ INT32 EV_DoCeiling(line_t *line, ceiling_e type) // new door thinker rtn = 1; ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); - P_AddThinker(&ceiling->thinker); + P_AddThinker(THINK_MAIN, &ceiling->thinker); sec->ceilingdata = ceiling; ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling; ceiling->sector = sec; @@ -619,7 +615,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type) sector_t *sec; ceiling_t *ceiling; - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) { sec = §ors[secnum]; @@ -629,7 +625,7 @@ INT32 EV_DoCrush(line_t *line, ceiling_e type) // new door thinker rtn = 1; ceiling = Z_Calloc(sizeof (*ceiling), PU_LEVSPEC, NULL); - P_AddThinker(&ceiling->thinker); + P_AddThinker(THINK_MAIN, &ceiling->thinker); sec->ceilingdata = ceiling; ceiling->thinker.function.acp1 = (actionf_p1)T_CrushCeiling; ceiling->sector = sec; diff --git a/src/p_enemy.c b/src/p_enemy.c index 611e45c40..c71de030b 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,13 +15,15 @@ #include "doomdef.h" #include "g_game.h" #include "p_local.h" +#include "p_setup.h" #include "r_main.h" #include "r_state.h" #include "s_sound.h" #include "m_random.h" #include "m_misc.h" -#include "r_things.h" +#include "r_skins.h" #include "i_video.h" +#include "z_zone.h" #include "lua_hook.h" #include "k_kart.h" // SRB2kart #include "k_waypoint.h" @@ -32,13 +34,12 @@ #include "hardware/hw3sound.h" #endif -#ifdef HAVE_BLUA boolean LUA_CallAction(const char *action, mobj_t *actor); -#endif player_t *stplyr; INT32 var1; INT32 var2; +INT32 modulothing; // // P_NewChaseDir related LUT. @@ -59,17 +60,31 @@ void A_Fall(mobj_t *actor); void A_Look(mobj_t *actor); void A_Chase(mobj_t *actor); void A_FaceStabChase(mobj_t *actor); +void A_FaceStabRev(mobj_t *actor); +void A_FaceStabHurl(mobj_t *actor); +void A_FaceStabMiss(mobj_t *actor); +void A_StatueBurst(mobj_t *actor); void A_JetJawRoam(mobj_t *actor); void A_JetJawChomp(mobj_t *actor); void A_PointyThink(mobj_t *actor); void A_CheckBuddy(mobj_t *actor); +void A_HoodFire(mobj_t *actor); void A_HoodThink(mobj_t *actor); -void A_ArrowCheck(mobj_t *actor); +void A_HoodFall(mobj_t *actor); +void A_ArrowBonks(mobj_t *actor); void A_SnailerThink(mobj_t *actor); void A_SharpChase(mobj_t *actor); void A_SharpSpin(mobj_t *actor); +void A_SharpDecel(mobj_t *actor); +void A_CrushstaceanWalk(mobj_t *actor); +void A_CrushstaceanPunch(mobj_t *actor); +void A_CrushclawAim(mobj_t *actor); +void A_CrushclawLaunch(mobj_t *actor); void A_VultureVtol(mobj_t *actor); void A_VultureCheck(mobj_t *actor); +void A_VultureHover(mobj_t *actor); +void A_VultureBlast(mobj_t *actor); +void A_VultureFly(mobj_t *actor); void A_SkimChase(mobj_t *actor); void A_FaceTarget(mobj_t *actor); void A_FaceTracer(mobj_t *actor); @@ -88,26 +103,16 @@ void A_BossZoom(mobj_t *actor); void A_BossScream(mobj_t *actor); void A_Scream(mobj_t *actor); void A_Pain(mobj_t *actor); -void A_1upThinker(mobj_t *actor); -void A_MonitorPop(mobj_t *actor); void A_Explode(mobj_t *actor); void A_BossDeath(mobj_t *actor); void A_CustomPower(mobj_t *actor); -void A_GiveWeapon(mobj_t *actor); -void A_JumpShield(mobj_t *actor); -void A_RingShield(mobj_t *actor); void A_RingBox(mobj_t *actor); void A_Invincibility(mobj_t *actor); void A_SuperSneakers(mobj_t *actor); void A_AwardScore(mobj_t *actor); -void A_ExtraLife(mobj_t *actor); -void A_BombShield(mobj_t *actor); -void A_WaterShield(mobj_t *actor); -void A_ForceShield(mobj_t *actor); -void A_PityShield(mobj_t *actor); +void A_GiveShield(mobj_t *actor); void A_GravityBox(mobj_t *actor); void A_ScoreRise(mobj_t *actor); -void A_ParticleSpawn(mobj_t *actor); void A_BunnyHop(mobj_t *actor); void A_BubbleSpawn(mobj_t *actor); void A_FanBubbleSpawn(mobj_t *actor); @@ -116,7 +121,6 @@ void A_BubbleCheck(mobj_t *actor); void A_AttractChase(mobj_t *actor); void A_DropMine(mobj_t *actor); void A_FishJump(mobj_t *actor); -void A_ThrownRing(mobj_t *actor); void A_GrenadeRing(mobj_t *actor); void A_SetSolidSteam(mobj_t *actor); void A_UnsetSolidSteam(mobj_t *actor); @@ -135,7 +139,6 @@ void A_DetonChase(mobj_t *actor); void A_CapeChase(mobj_t *actor); void A_RotateSpikeBall(mobj_t *actor); void A_SlingAppear(mobj_t *actor); -void A_MaceRotate(mobj_t *actor); void A_UnidusBall(mobj_t *actor); void A_RockSpawn(mobj_t *actor); void A_SetFuse(mobj_t *actor); @@ -143,7 +146,6 @@ void A_CrawlaCommanderThink(mobj_t *actor); void A_RingExplode(mobj_t *actor); void A_OldRingExplode(mobj_t *actor); void A_MixUp(mobj_t *actor); -void A_RecyclePowers(mobj_t *actor); void A_Boss2TakeDamage(mobj_t *actor); void A_Boss7Chase(mobj_t *actor); void A_GoopSplat(mobj_t *actor); @@ -161,6 +163,7 @@ void A_SetReactionTime(mobj_t *actor); void A_Boss1Spikeballs(mobj_t *actor); void A_Boss3TakeDamage(mobj_t *actor); void A_Boss3Path(mobj_t *actor); +void A_Boss3ShockThink(mobj_t *actor); void A_LinedefExecute(mobj_t *actor); void A_PlaySeeSound(mobj_t *actor); void A_PlayAttackSound(mobj_t *actor); @@ -170,6 +173,9 @@ void A_SpawnObjectAbsolute(mobj_t *actor); void A_SpawnObjectRelative(mobj_t *actor); void A_ChangeAngleRelative(mobj_t *actor); void A_ChangeAngleAbsolute(mobj_t *actor); +void A_RollAngle(mobj_t *actor); +void A_ChangeRollAngleRelative(mobj_t *actor); +void A_ChangeRollAngleAbsolute(mobj_t *actor); void A_PlaySound(mobj_t *actor); void A_FindTarget(mobj_t *actor); void A_FindTracer(mobj_t *actor); @@ -177,6 +183,7 @@ void A_SetTics(mobj_t *actor); void A_SetRandomTics(mobj_t *actor); void A_ChangeColorRelative(mobj_t *actor); void A_ChangeColorAbsolute(mobj_t *actor); +void A_Dye(mobj_t *actor); void A_MoveRelative(mobj_t *actor); void A_MoveAbsolute(mobj_t *actor); void A_Thrust(mobj_t *actor); @@ -193,7 +200,7 @@ void A_ItemPop(mobj_t *actor); // SRB2kart void A_JawzChase(mobj_t *actor); // SRB2kart void A_JawzExplode(mobj_t *actor); // SRB2kart void A_SPBChase(mobj_t *actor); // SRB2kart -void A_MineExplode(mobj_t *actor); // SRB2kart +void A_SSMineExplode(mobj_t *actor); // SRB2kart void A_BallhogExplode(mobj_t *actor); // SRB2kart void A_LightningFollowPlayer(mobj_t *actor); // SRB2kart void A_FZBoomFlash(mobj_t *actor); // SRB2kart @@ -203,7 +210,6 @@ void A_RoamingShadowThinker(mobj_t *actor); //SRB2kart void A_MayonakaArrow(mobj_t *actor); //SRB2kart void A_ReaperThinker(mobj_t *actor); //SRB2kart void A_MementosTPParticles(mobj_t *actor); //SRB2kart -void A_FlameParticle(mobj_t *actor); // SRB2kart void A_FlameShieldPaper(mobj_t *actor); // SRB2kart void A_OrbitNights(mobj_t *actor); void A_GhostMe(mobj_t *actor); @@ -243,7 +249,6 @@ void A_SetScale(mobj_t *actor); void A_RemoteDamage(mobj_t *actor); void A_HomingChase(mobj_t *actor); void A_TrapShot(mobj_t *actor); -//for p_enemy.c void A_Boss1Chase(mobj_t *actor); void A_Boss2Chase(mobj_t *actor); void A_Boss2Pogo(mobj_t *actor); @@ -256,6 +261,68 @@ void A_BrakFireShot(mobj_t *actor); void A_BrakLobShot(mobj_t *actor); void A_NapalmScatter(mobj_t *actor); void A_SpawnFreshCopy(mobj_t *actor); +void A_FlickySpawn(mobj_t *actor); +void A_FlickyCenter(mobj_t *actor); +void A_FlickyAim(mobj_t *actor); +void A_FlickyFly(mobj_t *actor); +void A_FlickySoar(mobj_t *actor); +void A_FlickyCoast(mobj_t *actor); +void A_FlickyHop(mobj_t *actor); +void A_FlickyFlounder(mobj_t *actor); +void A_FlickyCheck(mobj_t *actor); +void A_FlickyHeightCheck(mobj_t *actor); +void A_FlickyFlutter(mobj_t *actor); +void A_FlameParticle(mobj_t *actor); +void A_FadeOverlay(mobj_t *actor); +void A_Boss5Jump(mobj_t *actor); +void A_LightBeamReset(mobj_t *actor); +void A_MineExplode(mobj_t *actor); +void A_MineRange(mobj_t *actor); +void A_ConnectToGround(mobj_t *actor); +void A_SpawnParticleRelative(mobj_t *actor); +void A_MultiShotDist(mobj_t *actor); +void A_WhoCaresIfYourSonIsABee(mobj_t *actor); +void A_ParentTriesToSleep(mobj_t *actor); +void A_CryingToMomma(mobj_t *actor); +void A_CheckFlags2(mobj_t *actor); +void A_Boss5FindWaypoint(mobj_t *actor); +void A_DoNPCSkid(mobj_t *actor); +void A_DoNPCPain(mobj_t *actor); +void A_PrepareRepeat(mobj_t *actor); +void A_Boss5ExtraRepeat(mobj_t *actor); +void A_Boss5Calm(mobj_t *actor); +void A_Boss5CheckOnGround(mobj_t *actor); +void A_Boss5CheckFalling(mobj_t *actor); +void A_Boss5PinchShot(mobj_t *actor); +void A_Boss5MakeItRain(mobj_t *actor); +void A_Boss5MakeJunk(mobj_t *actor); +void A_LookForBetter(mobj_t *actor); +void A_Boss5BombExplode(mobj_t *actor); +void A_TNTExplode(mobj_t *actor); +void A_DebrisRandom(mobj_t *actor); +void A_TrainCameo(mobj_t *actor); +void A_TrainCameo2(mobj_t *actor); +void A_CanarivoreGas(mobj_t *actor); +void A_KillSegments(mobj_t *actor); +void A_SnapperSpawn(mobj_t *actor); +void A_SnapperThinker(mobj_t *actor); +void A_SaloonDoorSpawn(mobj_t *actor); +void A_MinecartSparkThink(mobj_t *actor); +void A_ModuloToState(mobj_t *actor); +void A_LavafallRocks(mobj_t *actor); +void A_LavafallLava(mobj_t *actor); +void A_FallingLavaCheck(mobj_t *actor); +void A_FireShrink(mobj_t *actor); +void A_SpawnPterabytes(mobj_t *actor); +void A_PterabyteHover(mobj_t *actor); +void A_RolloutSpawn(mobj_t *actor); +void A_RolloutRock(mobj_t *actor); +void A_DragonbomberSpawn(mobj_t *actor); +void A_DragonWing(mobj_t *actor); +void A_DragonSegment(mobj_t *actor); +void A_ChangeHeight(mobj_t *actor); + +//for p_enemy.c // // ENEMY THINKING @@ -462,10 +529,7 @@ boolean P_Move(mobj_t *actor, fixed_t speed) I_Assert(movedir < NUMDIRS); tryx = actor->x + FixedMul(speed*xspeed[movedir], actor->scale); - if (twodlevel || actor->flags2 & MF2_TWOD) - tryy = actor->y; - else - tryy = actor->y + FixedMul(speed*yspeed[movedir], actor->scale); + tryy = actor->y + FixedMul(speed*yspeed[movedir], actor->scale); if (actor->type == MT_SKIM && !P_WaterInSector(actor, tryx, tryy)) // bail out if sector lacks water return false; @@ -539,8 +603,6 @@ void P_NewChaseDir(mobj_t *actor) else d[1] = DI_NODIR; - if (twodlevel || actor->flags2 & MF2_TWOD) - d[2] = DI_NODIR; if (deltay < -FixedMul(10*FRACUNIT, actor->scale)) d[2] = DI_SOUTH; else if (deltay > FixedMul(10*FRACUNIT, actor->scale)) @@ -675,15 +737,21 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed if ((netgame || multiplayer) && player->spectator) continue; - if (player->health <= 0) - continue; // dead - if (player->pflags & PF_INVIS) continue; // ignore notarget if (!player->mo || P_MobjWasRemoved(player->mo)) continue; + if (player->mo->health <= 0) + continue; // dead + + if (player->bot) + continue; // ignore bots + + if (player->quittime) + continue; // Ignore uncontrolled bodies + if (dist > 0 && P_AproxDistance(P_AproxDistance(player->mo->x - actor->x, player->mo->y - actor->y), player->mo->z - actor->z) > dist) continue; // Too far away @@ -713,78 +781,6 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed //return false; } -#ifdef WEIGHTEDRECYCLER -// Compares players to see who currently has the "best" items, etc. -static int P_RecycleCompare(const void *p1, const void *p2) -{ - player_t *player1 = &players[*(const UINT8 *)p1]; - player_t *player2 = &players[*(const UINT8 *)p2]; - - // Non-shooting gametypes - if (!G_RaceGametype()) - { - // Invincibility. - if (player1->powers[pw_invulnerability] > player2->powers[pw_invulnerability]) return -1; - else if (player2->powers[pw_invulnerability] > player1->powers[pw_invulnerability]) return 1; - - // One has a shield, the other doesn't. - if (player1->powers[pw_shield] && !player2->powers[pw_shield]) return -1; - else if (player2->powers[pw_shield] && !player1->powers[pw_shield]) return 1; - - // Sneakers. - if (player1->powers[pw_sneakers] > player2->powers[pw_sneakers]) return -1; - else if (player2->powers[pw_sneakers] > player1->powers[pw_sneakers]) return 1; - } - else // Match, Team Match, CTF, Tag, Etc. - { - UINT8 player1_em = M_CountBits((UINT32)player1->powers[pw_emeralds], 7); - UINT8 player2_em = M_CountBits((UINT32)player2->powers[pw_emeralds], 7); - - UINT8 player1_rw = M_CountBits((UINT32)player1->ringweapons, NUM_WEAPONS-1); - UINT8 player2_rw = M_CountBits((UINT32)player2->ringweapons, NUM_WEAPONS-1); - - UINT16 player1_am = player1->powers[pw_infinityring] // max 800 - + player1->powers[pw_automaticring] // max 300 - + (player1->powers[pw_bouncering] * 3) // max 100 - + (player1->powers[pw_explosionring] * 6) // max 50 - + (player1->powers[pw_scatterring] * 3) // max 100 - + (player1->powers[pw_grenadering] * 6) // max 50 - + (player1->powers[pw_railring] * 6); // max 50 - UINT16 player2_am = player2->powers[pw_infinityring] // max 800 - + player2->powers[pw_automaticring] // max 300 - + (player2->powers[pw_bouncering] * 3) // max 100 - + (player2->powers[pw_explosionring] * 6) // max 50 - + (player2->powers[pw_scatterring] * 3) // max 100 - + (player2->powers[pw_grenadering] * 6) // max 50 - + (player2->powers[pw_railring] * 6); // max 50 - - // Super trumps everything. - if (player1->powers[pw_super] && !player2->powers[pw_super]) return -1; - else if (player2->powers[pw_super] && !player1->powers[pw_super]) return 1; - - // Emerald count if neither player is Super. - if (player1_em > player2_em) return -1; - else if (player1_em < player2_em) return 1; - - // One has a shield, the other doesn't. - // (the likelihood of a shielded player being worse off than one without one is low.) - if (player1->powers[pw_shield] && !player2->powers[pw_shield]) return -1; - else if (player2->powers[pw_shield] && !player1->powers[pw_shield]) return 1; - - // Ring weapons count - if (player1_rw > player2_rw) return -1; - else if (player1_rw < player2_rw) return 1; - - // Ring ammo if they have the same number of weapons - if (player1_am > player2_am) return -1; - else if (player1_am < player2_am) return 1; - } - - // Identical for our purposes - return 0; -} -#endif - // // ACTION ROUTINES // @@ -803,10 +799,8 @@ void A_Look(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_Look", actor)) return; -#endif if (leveltime < starttime) // SRB2kart - no looking before race starts return; @@ -841,10 +835,8 @@ void A_Chase(mobj_t *actor) INT32 delta; INT32 locvar1 = var1; -#ifdef HAVE_BLUA if (LUA_CallAction("A_Chase", actor)) return; -#endif I_Assert(actor != NULL); I_Assert(!P_MobjWasRemoved(actor)); @@ -925,7 +917,7 @@ nomissile: // Function: A_FaceStabChase // -// Description: A_Chase for CastleBot FaceStabber. +// Description: Unused variant of A_Chase for Castlebot Facestabber. // // var1 = unused // var2 = unused @@ -934,10 +926,8 @@ void A_FaceStabChase(mobj_t *actor) { INT32 delta; -#ifdef HAVE_BLUA if (LUA_CallAction("A_FaceStabChase", actor)) return; -#endif if (actor->reactiontime) actor->reactiontime--; @@ -1013,6 +1003,260 @@ nomissile: P_NewChaseDir(actor); } +static void P_SharpDust(mobj_t *actor, mobjtype_t type, angle_t ang) +{ + mobj_t *dust; + + if (!type || !P_IsObjectOnGround(actor)) + return; + + dust = P_SpawnMobjFromMobj(actor, + -P_ReturnThrustX(actor, ang, 16<angle, actor->radius), + -P_ReturnThrustY(actor, actor->angle, actor->radius), + actor->height/3, + MT_PARTICLE); + flume->destscale = actor->scale*3; + P_SetScale(flume, flume->destscale); + P_SetTarget(&flume->target, actor); + flume->sprite = SPR_JETF; + flume->frame = FF_FULLBRIGHT; + flume->tics = 2; +} + +// Function: A_FaceStabRev +// +// Description: Facestabber rev action +// +// var1 = effective duration +// var2 = effective nextstate +// +void A_FaceStabRev(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FaceStabRev", actor)) + return; + + if (!actor->target) + { + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + actor->extravalue1 = 0; + + if (!actor->reactiontime) + { + actor->reactiontime = locvar1; + S_StartSound(actor, actor->info->activesound); + } + else + { + if ((--actor->reactiontime) == 0) + { + S_StartSound(actor, actor->info->attacksound); + P_SetMobjState(actor, locvar2); + } + else + { + P_TryMove(actor, actor->x - P_ReturnThrustX(actor, actor->angle, 2<y - P_ReturnThrustY(actor, actor->angle, 2<target) + { + angle_t visang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + // Calculate new direction. + angle_t dirang = actor->angle; + angle_t diffang = visang - dirang; + + if (locvar1) // Allow homing? + { + if (diffang > ANGLE_180) + { + angle_t workang = locvar1*(InvAngle(diffang)>>5); + diffang += InvAngle(workang); + } + else + diffang += (locvar1*(diffang>>5)); + } + diffang += ANGLE_45; + + // Check the sight cone. + if (diffang < ANGLE_90) + { + actor->angle = dirang; + if (++actor->extravalue2 < 4) + actor->extravalue2 = 4; + else if (actor->extravalue2 > 26) + actor->extravalue2 = 26; + + if (P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, dirang, actor->extravalue2<y + P_ReturnThrustY(actor, dirang, actor->extravalue2<extravalue1); + fixed_t basesize = FRACUNIT/MAXVAL; + mobj_t *hwork = actor; + INT32 dist = 113; + fixed_t xo = P_ReturnThrustX(actor, actor->angle, dist*basesize); + fixed_t yo = P_ReturnThrustY(actor, actor->angle, dist*basesize); + + while (step > 0) + { + if (!hwork->hnext) + P_SetTarget(&hwork->hnext, P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_FACESTABBERSPEAR)); + hwork = hwork->hnext; + hwork->angle = actor->angle + ANGLE_90; + hwork->destscale = FixedSqrt(step*basesize); + P_SetScale(hwork, hwork->destscale); + hwork->fuse = 2; + P_TeleportMove(hwork, actor->x + xo*(15-step), actor->y + yo*(15-step), actor->z + (actor->height - hwork->height)/2 + (P_MobjFlip(actor)*(8<extravalue1 >= MAXVAL) + actor->extravalue1 -= NUMGRADS; + + if ((step % 5) == 0) + P_SharpDust(actor, MT_SPINDUST, actor->angle); + + P_FaceStabFlume(actor); + return; +#undef MAXVAL +#undef NUMGRADS +#undef NUMSTEPS + } + } + } + + P_SetMobjState(actor, locvar2); + actor->reactiontime = actor->info->reactiontime; +} + +// Function: A_FaceStabMiss +// +// Description: Facestabber miss action +// +// var1 = unused +// var2 = effective nextstate +// +void A_FaceStabMiss(mobj_t *actor) +{ + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FaceStabMiss", actor)) + return; + + if (++actor->extravalue1 >= 3) + { + actor->extravalue2 -= 2; + actor->extravalue1 = 0; + S_StartSound(actor, sfx_s3k47); + P_SharpDust(actor, MT_SPINDUST, actor->angle); + } + + if (actor->extravalue2 <= 0 || !P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, actor->angle, actor->extravalue2<y + P_ReturnThrustY(actor, actor->angle, actor->extravalue2<extravalue2 = 0; + P_SetMobjState(actor, locvar2); + } +} + +// Function: A_StatueBurst +// +// Description: For suspicious statues only... +// +// var1 = object to create +// var2 = effective nextstate for created object +// +void A_StatueBurst(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobjtype_t chunktype = (mobjtype_t)actor->info->raisestate; + mobj_t *new; + + if (LUA_CallAction("A_StatueBurst", actor)) + return; + + if (!locvar1 || !(new = P_SpawnMobjFromMobj(actor, 0, 0, 0, locvar1))) + return; + + new->angle = actor->angle; + P_SetTarget(&new->target, actor->target); + if (locvar2) + P_SetMobjState(new, (statenum_t)locvar2); + S_StartSound(new, new->info->attacksound); + S_StopSound(actor); + S_StartSound(actor, sfx_s3k96); + + { + fixed_t a, b; + fixed_t c = (actor->height>>2) - FixedMul(actor->scale, mobjinfo[chunktype].height>>1); + fixed_t v = 4<radius>>1); + mobj_t *spawned; + UINT8 i; + for (i = 0; i < 8; i++) + { + a = ((i & 1) ? r : (-r)); + b = ((i & 2) ? r : (-r)); + if (i == 4) + { + c += (actor->height>>1); + v = 8<fuse = 3*TICRATE; + } + } +} + // Function: A_JetJawRoam // // Description: Roaming routine for JetJaw @@ -1022,10 +1266,9 @@ nomissile: // void A_JetJawRoam(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_JetJawRoam", actor)) return; -#endif + if (actor->reactiontime) { actor->reactiontime--; @@ -1051,10 +1294,9 @@ void A_JetJawRoam(mobj_t *actor) void A_JetJawChomp(mobj_t *actor) { INT32 delta; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetJawChomp", actor)) return; -#endif // turn towards movement direction if not there yet if (actor->movedir < NUMDIRS) @@ -1100,10 +1342,9 @@ void A_PointyThink(mobj_t *actor) boolean firsttime = true; INT32 sign; -#ifdef HAVE_BLUA if (LUA_CallAction("A_PointyThink", actor)) return; -#endif + actor->momx = actor->momy = actor->momz = 0; // Find nearest player @@ -1199,16 +1440,69 @@ void A_CheckBuddy(mobj_t *actor) { INT32 locvar1 = var1; -#ifdef HAVE_BLUA if (LUA_CallAction("A_CheckBuddy", actor)) return; -#endif + if (locvar1 && (!actor->tracer || actor->tracer->health <= 0)) P_RemoveMobj(actor); else if (!locvar1 && (!actor->target || actor->target->health <= 0)) P_RemoveMobj(actor); } +// Helper function for the Robo Hood. +// Don't ask me how it works. Nev3r made it with dark majyks. +static void P_ParabolicMove(mobj_t *actor, fixed_t x, fixed_t y, fixed_t z, fixed_t speed) +{ + fixed_t dh; + + x -= actor->x; + y -= actor->y; + z -= actor->z; + + dh = P_AproxDistance(x, y); + + actor->momx = FixedMul(FixedDiv(x, dh), speed); + actor->momy = FixedMul(FixedDiv(y, dh), speed); + + if (!gravity) + return; + + dh = FixedDiv(FixedMul(dh, gravity), speed); + actor->momz = (dh>>1) + FixedDiv(z, dh<<1); +} + +// Function: A_HoodFire +// +// Description: Firing Robo-Hood +// +// var1 = object type to fire +// var2 = unused +// +void A_HoodFire(mobj_t *actor) +{ + mobj_t *arrow; + INT32 locvar1 = var1; + + if (LUA_CallAction("A_HoodFire", actor)) + return; + + // Check target first. + if (!actor->target) + { + actor->reactiontime = actor->info->reactiontime; + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + A_FaceTarget(actor); + + if (!(arrow = P_SpawnMissile(actor, actor->target, (mobjtype_t)locvar1))) + return; + + // Set a parabolic trajectory for the arrow. + P_ParabolicMove(arrow, actor->target->x, actor->target->y, actor->target->z, arrow->info->speed); +} + // Function: A_HoodThink // // Description: Thinker for Robo-Hood @@ -1218,97 +1512,108 @@ void A_CheckBuddy(mobj_t *actor) // void A_HoodThink(mobj_t *actor) { -#ifdef HAVE_BLUA + fixed_t dx, dy, dz, dm; + boolean checksight; + if (LUA_CallAction("A_HoodThink", actor)) return; -#endif - // Currently in the air... - if (!(actor->eflags & MFE_VERTICALFLIP) && actor->z > actor->floorz) - { - if (actor->momz > 0) - P_SetMobjStateNF(actor, actor->info->xdeathstate); // Rising - else - P_SetMobjStateNF(actor, actor->info->raisestate); // Falling - - return; - } - else if ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height < actor->ceilingz) - { - if (actor->momz < 0) - P_SetMobjStateNF(actor, actor->info->xdeathstate); // Rising - else - P_SetMobjStateNF(actor, actor->info->raisestate); // Falling - - return; - } - - if (actor->state == &states[actor->info->xdeathstate] - || actor->state == &states[actor->info->raisestate]) - P_SetMobjStateNF(actor, actor->info->seestate); + // Check target first. if (!actor->target) { + actor->reactiontime = actor->info->reactiontime; P_SetMobjState(actor, actor->info->spawnstate); return; } - A_FaceTarget(actor); // Aiming... aiming... - - if (--actor->reactiontime > 0) + dx = (actor->target->x - actor->x), dy = (actor->target->y - actor->y), dz = (actor->target->z - actor->z); + dm = P_AproxDistance(dx, dy); + // Target dangerously close to robohood, retreat then. + if ((dm < 256<info->attacksound); + P_SetMobjState(actor, actor->info->raisestate); return; + } - // Shoot, if not too close (cheap shots are lame) - if ((P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) > FixedMul(192*FRACUNIT, actor->scale)) - || (actor->spawnpoint && (actor->spawnpoint->options & MTF_AMBUSH))) // If you can't jump, might as well shoot regardless of distance! - P_SetMobjState(actor, actor->info->missilestate); - else if (!(actor->spawnpoint && (actor->spawnpoint->options & MTF_AMBUSH)))// But we WILL jump! - P_SetMobjState(actor, actor->info->painstate); + // If target on sight, look at it. + if ((checksight = P_CheckSight(actor, actor->target))) + { + angle_t dang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + if (actor->angle >= ANGLE_180) + { + actor->angle = InvAngle(actor->angle)>>1; + actor->angle = InvAngle(actor->angle); + } + else + actor->angle >>= 1; - actor->reactiontime = actor->info->reactiontime; + if (dang >= ANGLE_180) + { + dang = InvAngle(dang)>>1; + dang = InvAngle(dang); + } + else + dang >>= 1; + + actor->angle += dang; + } + + // Check whether to do anything. + if ((--actor->reactiontime) <= 0) + { + actor->reactiontime = actor->info->reactiontime; + + // If way too far, don't shoot. + if ((dm < (3072<info->missilestate); + return; + } + } } -// Function: A_ArrowCheck +// Function: A_HoodFall // -// Description: Checks arrow direction and adjusts sprite accordingly +// Description: Falling Robo-Hood // // var1 = unused // var2 = unused // -void A_ArrowCheck(mobj_t *actor) +void A_HoodFall(mobj_t *actor) { - fixed_t x,y,z; - angle_t angle; - fixed_t dist; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ArrowCheck", actor)) + if (LUA_CallAction("A_HoodFall", actor)) return; -#endif - // Movement vector - x = actor->momx; - y = actor->momy; - z = actor->momz; + if (!P_IsObjectOnGround(actor)) + return; - // Calculate the angle of movement. - /* - Z - / | - / | - / | - 0------dist(X,Y) - */ + actor->momx = actor->momy = 0; + actor->reactiontime = actor->info->reactiontime; + P_SetMobjState(actor, actor->info->seestate); +} - dist = P_AproxDistance(x, y); +// Function: A_ArrowBonks +// +// Description: Arrow momentum setting on collision +// +// var1 = unused +// var2 = unused +// +void A_ArrowBonks(mobj_t *actor) +{ + if (LUA_CallAction("A_ArrowBonks", actor)) + return; - angle = R_PointToAngle2(0, 0, dist, z); + if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) + || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) + actor->angle += ANGLE_180; - if (angle > ANG20 && angle <= ANGLE_180) - P_SetMobjStateNF(actor, actor->info->raisestate); - else if (angle < ANG340 && angle > ANGLE_180) - P_SetMobjStateNF(actor, actor->info->xdeathstate); - else - P_SetMobjStateNF(actor, actor->info->spawnstate); + P_SetObjectMomZ(actor, 8*actor->scale, false); + P_InstaThrust(actor, actor->angle, -6*actor->scale); + + actor->flags = (actor->flags|MF_NOCLIPHEIGHT) & ~MF_NOGRAVITY; + actor->z += P_MobjFlip(actor); } // Function: A_SnailerThink @@ -1320,10 +1625,8 @@ void A_ArrowCheck(mobj_t *actor) // void A_SnailerThink(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_SnailerThink", actor)) return; -#endif if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { @@ -1388,23 +1691,15 @@ void A_SnailerThink(mobj_t *actor) // Function: A_SharpChase // -// Description: Thinker/Chase routine for Sharps +// Description: Thinker/Chase routine for Spincushions // // var1 = unused // var2 = unused // void A_SharpChase(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_SharpChase", actor)) return; -#endif - - if (!actor->health) - { - P_SetMobjState(actor, actor->info->deathstate); - return; - } if (actor->reactiontime) { @@ -1448,40 +1743,317 @@ void A_SharpChase(mobj_t *actor) // Function: A_SharpSpin // -// Description: Spin chase routine for Sharps +// Description: Spin chase routine for Spincushions // -// var1 = unused -// var2 = unused +// var1 = object # to spawn as dust (if not provided not done) +// var2 = if nonzero, do the old-style spinning using this as the angle difference // void A_SharpSpin(mobj_t *actor) { -#ifdef HAVE_BLUA + INT32 locvar1 = var1; + INT32 locvar2 = var2; + angle_t oldang = actor->angle; + if (LUA_CallAction("A_SharpSpin", actor)) return; -#endif - - if (!actor->health) - { - P_SetMobjState(actor, actor->info->deathstate); - return; - } if (actor->threshold && actor->target) { - actor->angle += ANGLE_22h; - P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y), FixedMul(actor->info->speed*FRACUNIT, actor->scale)); + angle_t ang = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_Thrust(actor, ang, actor->info->speed*actor->scale); + if (locvar2) + actor->angle += locvar2; // ANGLE_22h; + else + actor->angle = ang; actor->threshold--; + if (leveltime & 1) + S_StartSound(actor, actor->info->painsound); } else { actor->reactiontime = actor->info->reactiontime; - P_SetMobjState(actor, actor->info->spawnstate); - - var1 = 1; - A_Look(actor); - if (actor->target) - actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_SetMobjState(actor, actor->info->meleestate); } + + P_SharpDust(actor, locvar1, oldang); +} + +// Function: A_SharpDecel +// +// Description: Slow down the Spincushion +// +// var1 = unused +// var2 = unused +// +void A_SharpDecel(mobj_t *actor) +{ + if (LUA_CallAction("A_SharpDecel", actor)) + return; + + if (actor->momx > 2 || actor->momy > 2) + { + actor->momx >>= 1; + actor->momy >>= 1; + } + else + P_SetMobjState(actor, actor->info->xdeathstate); +} + +// Function: A_CrushstaceanWalk +// +// Description: Crushstacean movement +// +// var1 = speed (actor info's speed if 0) +// var2 = state to switch to when blocked (spawnstate if 0) +// +void A_CrushstaceanWalk(mobj_t *actor) +{ + INT32 locvar1 = (var1 ? var1 : (INT32)actor->info->speed); + INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); + angle_t ang = actor->angle + ((actor->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); + + if (LUA_CallAction("A_CrushstaceanWalk", actor)) + return; + + actor->reactiontime--; + + if (!P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, ang, locvar1*actor->scale), + actor->y + P_ReturnThrustY(actor, ang, locvar1*actor->scale), + false) + || (actor->reactiontime-- <= 0)) + { + actor->flags2 ^= MF2_AMBUSH; + P_SetTarget(&actor->target, NULL); + P_SetMobjState(actor, locvar2); + actor->reactiontime = actor->info->reactiontime; + } +} + +// Function: A_CrushstaceanPunch +// +// Description: Crushstacean attack +// +// var1 = unused +// var2 = state to go to if unsuccessful (spawnstate if 0) +// +void A_CrushstaceanPunch(mobj_t *actor) +{ + INT32 locvar2 = (var2 ? var2 : (INT32)actor->info->spawnstate); + + if (LUA_CallAction("A_CrushstaceanPunch", actor)) + return; + + if (!actor->tracer) + return; + + if (!actor->target) + { + P_SetMobjState(actor, locvar2); + return; + } + + actor->tracer->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + P_SetMobjState(actor->tracer, actor->tracer->info->missilestate); + actor->tracer->extravalue1 = actor->tracer->extravalue2 = 0; + S_StartSound(actor, actor->info->attacksound); +} + +// Function: A_CrushclawAim +// +// Description: Crushstacean claw aiming +// +// var1 = sideways offset +// var2 = vertical offset +// +void A_CrushclawAim(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *crab = actor->tracer; + angle_t ang; + + if (LUA_CallAction("A_CrushclawAim", actor)) + return; + + if (!crab) + { + P_RemoveMobj(actor); + return; // there is only one step and it is crab + } + + if (crab->target || P_LookForPlayers(crab, true, false, actor->info->speed*crab->scale)) + ang = R_PointToAngle2(crab->x, crab->y, crab->target->x, crab->target->y); + else + ang = crab->angle + ((crab->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270); + ang -= actor->angle; + +#define anglimit ANGLE_22h +#define angfactor 5 + if (ang < ANGLE_180) + { + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + } + else + { + ang = InvAngle(ang); + if (ang > anglimit) + ang = anglimit; + ang = InvAngle(ang/angfactor); + } + actor->angle += ang; +#undef anglimit +#undef angfactor + + P_TeleportMove(actor, + crab->x + P_ReturnThrustX(actor, actor->angle, locvar1*crab->scale), + crab->y + P_ReturnThrustY(actor, actor->angle, locvar1*crab->scale), + crab->z + locvar2*crab->scale); + + if (!crab->target || !crab->info->missilestate || (statenum_t)(crab->state-states) == crab->info->missilestate) + return; + + if (((ang + ANG1) < ANG2) || P_AproxDistance(crab->x - crab->target->x, crab->y - crab->target->y) < 333*crab->scale) + P_SetMobjState(crab, crab->info->missilestate); +} + +// Function: A_CrushclawLaunch +// +// Description: Crushstacean claw launching +// +// var1: +// 0 - forwards +// anything else - backwards +// var2 = state to change to when done +// +void A_CrushclawLaunch(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *crab = actor->tracer; + + if (LUA_CallAction("A_CrushclawLaunch", actor)) + return; + + if (!crab) + { + mobj_t *chainnext; + while (actor) + { + chainnext = actor->target; + P_RemoveMobj(actor); + actor = chainnext; + } + return; // there is only one step and it is crab + } + + if (!actor->extravalue1) + { + S_StartSound(actor, actor->info->activesound); + actor->extravalue1 = ((locvar1) ? -1 : 32); + } + else if (actor->extravalue1 != 1) + actor->extravalue1 -= 1; + +#define CSEGS 5 + if (!actor->target) + { + mobj_t *prevchain = actor; + UINT8 i = 0; + for (i = 0; (i < CSEGS); i++) + { + mobj_t *newchain = P_SpawnMobjFromMobj(actor, 0, 0, 0, (mobjtype_t)actor->info->raisestate); + P_SetTarget(&prevchain->target, newchain); + prevchain = newchain; + } + actor->target->angle = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y); + } + + if ((!locvar1) && crab->target) + { +#define anglimit ANGLE_22h +#define angfactor 7 + angle_t ang = R_PointToAngle2(actor->target->x, actor->target->y, crab->target->x, crab->target->y) - actor->target->angle; + if (ang < ANGLE_180) + { + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + } + else + { + ang = InvAngle(ang); + if (ang > anglimit) + ang = anglimit; + ang /= angfactor; + ang = InvAngle(ang); + } + actor->target->angle += ang; + actor->angle = actor->target->angle; + } + + actor->extravalue2 += actor->extravalue1; + + if (!P_TryMove(actor, + actor->target->x + P_ReturnThrustX(actor, actor->target->angle, actor->extravalue2*actor->scale), + actor->target->y + P_ReturnThrustY(actor, actor->target->angle, actor->extravalue2*actor->scale), + true) + && !locvar1) + { + actor->extravalue1 = 0; + actor->extravalue2 = FixedHypot(actor->x - actor->target->x, actor->y - actor->target->y)>>FRACBITS; + P_SetMobjState(actor, locvar2); + S_StopSound(actor); + S_StartSound(actor, sfx_s3k49); + } + else + { + actor->z = actor->target->z; + if ((!locvar1 && (actor->extravalue2 > 256)) || (locvar1 && (actor->extravalue2 < 16))) + { + if (locvar1) // In case of retracting, resume crab and remove the chain. + { + mobj_t *chain = actor->target, *chainnext; + while (chain) + { + chainnext = chain->target; + P_RemoveMobj(chain); + chain = chainnext; + } + actor->extravalue2 = 0; + actor->angle = R_PointToAngle2(crab->x, crab->y, actor->x, actor->y); + P_SetTarget(&actor->target, NULL); + P_SetTarget(&crab->target, NULL); + P_SetMobjState(crab, crab->state->nextstate); + } + actor->extravalue1 = 0; + P_SetMobjState(actor, locvar2); + S_StopSound(actor); + if (!locvar1) + S_StartSound(actor, sfx_s3k64); + } + } + + if (!actor->target) + return; + + { + mobj_t *chain = actor->target->target; + fixed_t dx = (actor->x - actor->target->x)/CSEGS, dy = (actor->y - actor->target->y)/CSEGS, dz = (actor->z - actor->target->z)/CSEGS; + fixed_t idx = dx, idy = dy, idz = dz; + while (chain) + { + P_TeleportMove(chain, actor->target->x + idx, actor->target->y + idy, actor->target->z + idz); + chain->movefactor = chain->z; + idx += dx; + idy += dy; + idz += dz; + chain = chain->target; + } + } +#undef CSEGS } // Function: A_VultureVtol @@ -1493,10 +2065,8 @@ void A_SharpSpin(mobj_t *actor) // void A_VultureVtol(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_VultureVtol", actor)) return; -#endif if (!actor->target) return; @@ -1530,10 +2100,8 @@ void A_VultureVtol(mobj_t *actor) // void A_VultureCheck(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_VultureCheck", actor)) return; -#endif if (actor->momx || actor->momy) return; @@ -1547,6 +2115,229 @@ void A_VultureCheck(mobj_t *actor) } } +static void P_VultureHoverParticle(mobj_t *actor) +{ + fixed_t fdist = actor->z - P_FloorzAtPos(actor->x, actor->y, actor->z, actor->height); + + if (fdist < 128*FRACUNIT) + { + mobj_t *dust; + UINT8 i; + angle_t angle = (leveltime % 2)*ANGLE_45/2; + + for (i = 0; i <= 7; i++) + { + angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t px = actor->x + FixedMul(fdist + 64*FRACUNIT, FINECOSINE(fa)); + fixed_t py = actor->y + FixedMul(fdist + 64*FRACUNIT, FINESINE(fa)); + fixed_t pz = P_FloorzAtPos(px, py, actor->z, actor->height); + + dust = P_SpawnMobj(px, py, pz, MT_ARIDDUST); + P_SetMobjState(dust, (statenum_t)(dust->state - states + P_RandomRange(0, 2))); + P_Thrust(dust, angle, FixedDiv(12*FRACUNIT, max(FRACUNIT, fdist/2))); + dust->momx += actor->momx; + dust->momy += actor->momy; + angle += ANGLE_45; + } + } +} + +// Function: A_VultureHover +// +// Description: Vulture hovering and checking whether to attack. +// +// var1 = unused +// var2 = unused +// +void A_VultureHover(mobj_t *actor) +{ + fixed_t targetz; + fixed_t distdif; + fixed_t memz = actor->z; + SINT8 i; + + if (LUA_CallAction("A_VultureHover", actor)) + return; + + if (!actor->target || P_MobjWasRemoved(actor->target)) + { + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + actor->flags |= MF_NOGRAVITY; + + actor->momx -= actor->momx/24; + actor->momy -= actor->momy/24; + + P_VultureHoverParticle(actor); + + A_FaceTarget(actor); + targetz = actor->target->z + actor->target->height / 2; + for (i = -1; i <= 1; i++) + { + actor->z = targetz - i * 128 * FRACUNIT; + if (P_CheckSight(actor, actor->target)) + { + targetz -= i * 128 * FRACUNIT; + break; + } + } + actor->z = memz; + + distdif = (actor->z + actor->height/2) - targetz; + + if (abs(actor->momz*16) > abs(distdif)) + actor->momz -= actor->momz/16; + else if (distdif < 0) + actor->momz = min(actor->momz+FRACUNIT/8, actor->info->speed*FRACUNIT); + else + actor->momz = max(actor->momz-FRACUNIT/8, -actor->info->speed*FRACUNIT); + + if (abs(distdif) < 128*FRACUNIT && abs(actor->momz) < FRACUNIT && P_CheckSight(actor, actor->target)) + { + P_SetMobjState(actor, actor->info->missilestate); + actor->momx = 0; + actor->momy = 0; + actor->momz = 0; + actor->extravalue1 = 0; + } +} + +// Function: A_VultureBlast +// +// Description: Vulture spawning a dust cloud. +// +// var1 = unused +// var2 = unused +// +void A_VultureBlast(mobj_t *actor) +{ + mobj_t *dust; + UINT8 i; + angle_t faa; + fixed_t faacos, faasin; + + if (LUA_CallAction("A_VultureBlast", actor)) + return; + + S_StartSound(actor, actor->info->attacksound); + + faa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; + faacos = FINECOSINE(faa); + faasin = FINESINE(faa); + + for (i = 0; i <= 7; i++) + { + angle_t fa = ((i*(angle_t)ANGLE_45) >> ANGLETOFINESHIFT) & FINEMASK; + dust = P_SpawnMobj(actor->x + 48*FixedMul(FINECOSINE(fa), -faasin), actor->y + 48*FixedMul(FINECOSINE(fa), faacos), actor->z + actor->height/2 + 48*FINESINE(fa), MT_PARTICLE); + + P_SetScale(dust, 4*FRACUNIT); + dust->destscale = FRACUNIT; + dust->scalespeed = 4*FRACUNIT/TICRATE; + dust->fuse = TICRATE; + dust->momx = FixedMul(FINECOSINE(fa), -faasin)*3; + dust->momy = FixedMul(FINECOSINE(fa), faacos)*3; + dust->momz = FINESINE(fa)*6; + } +} + +// Function: A_VultureFly +// +// Description: Vulture charging towards target. +// +// var1 = unused +// var2 = unused +// +void A_VultureFly(mobj_t *actor) +{ + fixed_t speedmax = 18*FRACUNIT; + angle_t angledif; + fixed_t dx, dy, dz, dxy, dm; + mobj_t *dust; + fixed_t momm; + + if (LUA_CallAction("A_VultureFly", actor)) + return; + + if (!actor->target || P_MobjWasRemoved(actor->target)) + { + P_SetMobjState(actor, actor->info->spawnstate); + return; + } + + angledif = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) - actor->angle; + dx = actor->target->x - actor->x; + dy = actor->target->y - actor->y; + dz = actor->target->z - actor->z; + dxy = FixedHypot(dx, dy); + + if (leveltime % 4 == 0) + S_StartSound(actor, actor->info->activesound); + + if (angledif > ANGLE_180) + angledif = InvAngle(angledif); + + // Tweak the target height according to the position. + if (angledif < ANGLE_45) // Centered? + { + actor->reactiontime = actor->info->reactiontime; + if (dxy > 768*FRACUNIT) + dz = max(P_FloorzAtPos(actor->target->x, actor->target->y, actor->target->z, 0) - actor->z + min(dxy/8, 128*FRACUNIT), dz); + } + else + { + actor->reactiontime--; + + if (angledif < ANGLE_90) + dz = max(P_FloorzAtPos(actor->target->x, actor->target->y, actor->target->z, 0) - actor->z + min(dxy/2, 192*FRACUNIT), dz); + else + dz = max(P_FloorzAtPos(actor->target->x, actor->target->y, actor->target->z, 0) - actor->z + 232*FRACUNIT, dz); + } + + dm = FixedHypot(dz, dxy); + + P_VultureHoverParticle(actor); + + dust = P_SpawnMobj(actor->x + P_RandomFixed() - FRACUNIT/2, actor->y + P_RandomFixed() - FRACUNIT/2, actor->z + actor->height/2 + P_RandomFixed() - FRACUNIT/2, MT_PARTICLE); + P_SetScale(dust, 2*FRACUNIT); + dust->destscale = FRACUNIT/3; + dust->scalespeed = FRACUNIT/40; + dust->fuse = TICRATE*2; + + actor->momx += FixedDiv(dx, dm)*2; + actor->momy += FixedDiv(dy, dm)*2; + actor->momz += FixedDiv(dz, dm)*2; + + momm = FixedHypot(actor->momz, FixedHypot(actor->momx, actor->momy)); + + if (momm > speedmax/2 && actor->reactiontime == 0) + { + P_SetMobjState(actor, actor->info->seestate); + return; + } + + //Hits a wall hard? + if (actor->extravalue1 - momm > 15*FRACUNIT) + { + actor->flags &= ~MF_NOGRAVITY; + P_SetMobjState(actor, actor->info->painstate); + S_StopSound(actor); + S_StartSound(actor, actor->info->painsound); + return; + } + actor->extravalue1 = momm; + + if (momm > speedmax) + { + actor->momx = FixedMul(FixedDiv(actor->momx, momm), speedmax); + actor->momy = FixedMul(FixedDiv(actor->momy, momm), speedmax); + actor->momz = FixedMul(FixedDiv(actor->momz, momm), speedmax); + } + + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); +} + // Function: A_SkimChase // // Description: Thinker/Chase routine for Skims @@ -1558,10 +2349,9 @@ void A_SkimChase(mobj_t *actor) { INT32 delta; -#ifdef HAVE_BLUA if (LUA_CallAction("A_SkimChase", actor)) return; -#endif + if (actor->reactiontime) actor->reactiontime--; @@ -1645,10 +2435,9 @@ nomissile: // void A_FaceTarget(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_FaceTarget", actor)) return; -#endif + if (!actor->target) return; @@ -1664,10 +2453,9 @@ void A_FaceTarget(mobj_t *actor) // void A_FaceTracer(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_FaceTracer", actor)) return; -#endif + if (!actor->tracer) return; @@ -1694,10 +2482,9 @@ void A_LobShot(mobj_t *actor) fixed_t vertical, horizontal; fixed_t airtime = var2 & 65535; -#ifdef HAVE_BLUA if (LUA_CallAction("A_LobShot", actor)) return; -#endif + if (!actor->target) return; @@ -1795,10 +2582,9 @@ void A_FireShot(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_FireShot", actor)) return; -#endif + if (!actor->target) return; @@ -1834,10 +2620,9 @@ void A_SuperFireShot(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_SuperFireShot", actor)) return; -#endif + if (!actor->target) return; @@ -1880,11 +2665,11 @@ void A_BossFireShot(mobj_t *actor) fixed_t x, y, z; INT32 locvar1 = var1; INT32 locvar2 = var2; + mobj_t *missile; -#ifdef HAVE_BLUA if (LUA_CallAction("A_BossFireShot", actor)) return; -#endif + if (!actor->target) return; @@ -1947,7 +2732,10 @@ void A_BossFireShot(mobj_t *actor) break; } - P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z); + missile = P_SpawnXYZMissile(actor, actor->target, locvar1, x, y, z); + + if (missile && actor->tracer && (actor->tracer->flags & MF_BOSS)) // Don't harm your papa. + P_SetTarget(&missile->target, actor->tracer); } // Function: A_Boss7FireMissiles @@ -1963,10 +2751,8 @@ void A_Boss7FireMissiles(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_Boss7FireMissiles", actor)) return; -#endif if (!actor->target) { @@ -2012,41 +2798,82 @@ void A_Boss7FireMissiles(mobj_t *actor) // var2: // 0 - Boss 1 Left side // 1 - Boss 1 Right side +// 2 - Triple laser +// 3 - Boss 1 Middle +// >=3 - Generic middle // void A_Boss1Laser(mobj_t *actor) { fixed_t x, y, z, floorz, speed; INT32 locvar1 = var1; - INT32 locvar2 = var2; + INT32 locvar2 = (var2 & 65535); + INT32 upperend = (var2>>16); INT32 i; angle_t angle; mobj_t *point; + tic_t dur; + static const UINT8 LASERCOLORS[] = + { + SKINCOLOR_SUPERRED3, + SKINCOLOR_SUPERRED4, + SKINCOLOR_SUPERRED5, + SKINCOLOR_KETCHUP, + SKINCOLOR_RED, + SKINCOLOR_RED, + SKINCOLOR_KETCHUP, + SKINCOLOR_SUPERRED5, + SKINCOLOR_SUPERRED4, + SKINCOLOR_SUPERRED3, + }; -#ifdef HAVE_BLUA if (LUA_CallAction("A_Boss1Laser", actor)) return; -#endif + if (!actor->target) return; + if (actor->state->tics > 1) + dur = actor->tics; + else + { + if ((upperend & 1) && (actor->extravalue2 > 1)) + actor->extravalue2--; + + dur = actor->extravalue2; + } + switch (locvar2) { case 0: - x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + x = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; else z = actor->z + FixedMul(56*FRACUNIT, actor->scale); break; case 1: - x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); - y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(43*FRACUNIT, actor->scale)); + x = actor->x + P_ReturnThrustX(actor, actor->angle-ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle-ANGLE_90, FixedMul(44*FRACUNIT, actor->scale)); if (actor->eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - FixedMul(56*FRACUNIT, actor->scale) - mobjinfo[locvar1].height; else z = actor->z + FixedMul(56*FRACUNIT, actor->scale); break; + case 2: + var1 = locvar1; var2 = 3; // Fire middle laser + A_Boss1Laser(actor); + var1 = locvar1; var2 = 0; // Fire left laser + A_Boss1Laser(actor); + var1 = locvar1; var2 = 1; // Fire right laser + A_Boss1Laser(actor); + return; + break; + case 3: + x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(42*FRACUNIT, actor->scale)); + y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(42*FRACUNIT, actor->scale)); + z = actor->z + actor->height/2; + break; default: x = actor->x; y = actor->y; @@ -2054,30 +2881,25 @@ void A_Boss1Laser(mobj_t *actor) break; } - if (!(actor->flags2 & MF2_FIRING)) + if (!(actor->flags2 & MF2_FIRING) && dur > 1) { actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); if (mobjinfo[locvar1].seesound) S_StartSound(actor, mobjinfo[locvar1].seesound); - if (!(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) - { - point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); - point->fuse = actor->tics+1; - P_SetTarget(&point->target, actor->target); - P_SetTarget(&actor->target, point); - } - } - else if (actor->target && !(actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH)) - actor->angle = R_PointToAngle2(x, y, actor->target->x, actor->target->y); - if (actor->spawnpoint && actor->spawnpoint->options & MTF_AMBUSH) - angle = FixedAngle(FixedDiv(actor->tics*160*FRACUNIT, actor->state->tics*FRACUNIT) + 10*FRACUNIT); - else - angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); + point = P_SpawnMobj(x + P_ReturnThrustX(actor, actor->angle, actor->radius), y + P_ReturnThrustY(actor, actor->angle, actor->radius), actor->z - actor->height / 2, MT_EGGMOBILE_TARGET); + point->angle = actor->angle; + point->fuse = dur+1; + P_SetTarget(&point->target, actor->target); + P_SetTarget(&actor->target, point); + } + + angle = R_PointToAngle2(z + (mobjinfo[locvar1].height>>1), 0, actor->target->z, R_PointToDist2(x, y, actor->target->x, actor->target->y)); + point = P_SpawnMobj(x, y, z, locvar1); P_SetTarget(&point->target, actor); point->angle = actor->angle; - speed = point->radius*2; + speed = point->radius; point->momz = FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT), speed); point->momx = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(point->angle>>ANGLETOFINESHIFT), speed)); point->momy = FixedMul(FINESINE(angle>>ANGLETOFINESHIFT), FixedMul(FINESINE(point->angle>>ANGLETOFINESHIFT), speed)); @@ -2086,26 +2908,72 @@ void A_Boss1Laser(mobj_t *actor) { mobj_t *mo = P_SpawnMobj(point->x, point->y, point->z, point->type); mo->angle = point->angle; + mo->color = LASERCOLORS[((UINT8)(i + 3*dur) >> 2) % sizeof(LASERCOLORS)]; // codeing P_UnsetThingPosition(mo); - mo->flags = MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY; + mo->flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY|MF_SCENERY; P_SetThingPosition(mo); + if (dur & 1 && mo->info->missilestate) + { + P_SetMobjState(mo, mo->info->missilestate); + if (mo->info->meleestate) + { + mobj_t *mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_PARTICLE); + mo2->flags2 |= MF2_LINKDRAW; + P_SetTarget(&mo2->tracer, actor); + P_SetMobjState(mo2, mo->info->meleestate); + } + } + + if (dur == 1) + P_SpawnGhostMobj(mo); + x = point->x, y = point->y, z = point->z; if (P_RailThinker(point)) break; } + x += point->momx; + y += point->momy; floorz = P_FloorzAtPos(x, y, z, mobjinfo[MT_EGGMOBILE_FIRE].height); - if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1) + if (z - floorz < mobjinfo[MT_EGGMOBILE_FIRE].height>>1 && dur & 1) { - point = P_SpawnMobj(x, y, floorz+1, MT_EGGMOBILE_FIRE); - point->target = actor; - point->destscale = 3*FRACUNIT; - point->scalespeed = FRACUNIT>>2; - point->fuse = TICRATE; + point = P_SpawnMobj(x, y, floorz, MT_EGGMOBILE_FIRE); + point->angle = actor->angle; + point->destscale = actor->scale; + P_SetScale(point, point->destscale); + P_SetTarget(&point->target, actor); + P_MobjCheckWater(point); + if (point->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER)) + { + for (i = 0; i < 2; i++) + { + UINT8 size = 3; + mobj_t *steam = P_SpawnMobj(x, y, point->watertop - size*mobjinfo[MT_DUST].height, MT_DUST); + P_SetScale(steam, size*actor->scale); + P_SetObjectMomZ(steam, FRACUNIT + 2*P_RandomFixed(), true); + P_InstaThrust(steam, FixedAngle(P_RandomKey(360)*FRACUNIT), 2*P_RandomFixed()); + if (point->info->painsound) + S_StartSound(steam, point->info->painsound); + } + } + else + { + fixed_t distx = P_ReturnThrustX(point, point->angle, point->radius); + fixed_t disty = P_ReturnThrustY(point, point->angle, point->radius); + if (P_TryMove(point, point->x + distx, point->y + disty, false) // prevents the sprite from clipping into the wall or dangling off ledges + && P_TryMove(point, point->x - 2*distx, point->y - 2*disty, false) + && P_TryMove(point, point->x + distx, point->y + disty, false)) + { + if (point->info->seesound) + S_StartSound(point, point->info->seesound); + } + else + P_RemoveMobj(point); + } } - if (actor->tics > 1) + if (dur > 1) actor->flags2 |= MF2_FIRING; else actor->flags2 &= ~MF2_FIRING; @@ -2118,22 +2986,26 @@ void A_Boss1Laser(mobj_t *actor) // var1: // 0 - accelerative focus with friction // 1 - steady focus with fixed movement speed -// var2 = unused +// anything else - don't move +// var2: +// 0 - don't trace target, just move forwards +// & 1 - change horizontal angle +// & 2 - change vertical angle // void A_FocusTarget(mobj_t *actor) { INT32 locvar1 = var1; -#ifdef HAVE_BLUA + INT32 locvar2 = var2; + if (LUA_CallAction("A_FocusTarget", actor)) return; -#endif if (actor->target) { fixed_t speed = FixedMul(actor->info->speed, actor->scale); - fixed_t dist = R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y); - angle_t vangle = R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist); - angle_t hangle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + fixed_t dist = (locvar2 ? R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) : speed+1); + angle_t hangle = ((locvar2 & 1) ? R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y) : actor->angle); + angle_t vangle = ((locvar2 & 2) ? R_PointToAngle2(actor->z , 0, actor->target->z + (actor->target->height>>1), dist) : ANGLE_90); switch(locvar1) { case 0: @@ -2169,21 +3041,35 @@ void A_FocusTarget(mobj_t *actor) // Description: Reverse arms direction. // // var1 = sfx to play -// var2 = unused +// var2 = sfx to play in pinch // void A_Boss4Reverse(mobj_t *actor) { sfxenum_t locvar1 = (sfxenum_t)var1; -#ifdef HAVE_BLUA + sfxenum_t locvar2 = (sfxenum_t)var2; + if (LUA_CallAction("A_Boss4Reverse", actor)) return; -#endif - S_StartSound(NULL, locvar1); + actor->reactiontime = 0; - if (actor->movedir == 1) - actor->movedir = 2; + if (actor->movedir < 3) + { + S_StartSound(NULL, locvar1); + if (actor->movedir == 1) + actor->movedir = 2; + else + actor->movedir = 1; + } else - actor->movedir = 1; + { + S_StartSound(NULL, locvar2); + if (actor->movedir == 4) + actor->movedir = 5; + else + actor->movedir = 4; + actor->angle += ANGLE_180; + actor->movefactor = -actor->movefactor; + } } // Function: A_Boss4SpeedUp @@ -2196,10 +3082,10 @@ void A_Boss4Reverse(mobj_t *actor) void A_Boss4SpeedUp(mobj_t *actor) { sfxenum_t locvar1 = (sfxenum_t)var1; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss4SpeedUp", actor)) return; -#endif + S_StartSound(NULL, locvar1); actor->reactiontime = 2; } @@ -2214,10 +3100,10 @@ void A_Boss4SpeedUp(mobj_t *actor) void A_Boss4Raise(mobj_t *actor) { sfxenum_t locvar1 = (sfxenum_t)var1; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss4Raise", actor)) return; -#endif + S_StartSound(NULL, locvar1); actor->reactiontime = 1; } @@ -2230,6 +3116,7 @@ void A_Boss4Raise(mobj_t *actor) // 0 - Fly at the player // 1 - Fly away from the player // 2 - Strafe in relation to the player +// 3 - Dynamic mode - don't get too close to walls // var2: // 0 - Fly horizontally and vertically // 1 - Fly horizontal-only (momz = 0) @@ -2245,10 +3132,9 @@ void A_SkullAttack(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_SkullAttack", actor)) return; -#endif + if (!actor->target) return; @@ -2260,16 +3146,84 @@ void A_SkullAttack(mobj_t *actor) S_StartSound(actor, actor->info->activesound); A_FaceTarget(actor); + dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); + if (locvar1 == 1) actor->angle += ANGLE_180; else if (locvar1 == 2) actor->angle += (P_RandomChance(FRACUNIT/2)) ? ANGLE_90 : -ANGLE_90; + else if (locvar1 == 3) + { + statenum_t oldspawnstate = mobjinfo[MT_NULL].spawnstate; + UINT32 oldflags = mobjinfo[MT_NULL].flags; + fixed_t oldradius = mobjinfo[MT_NULL].radius; + fixed_t oldheight = mobjinfo[MT_NULL].height; + mobj_t *check; + INT32 i, j; + static INT32 k;/* static for (at least) GCC 9.1 weirdness */ + boolean allow; + angle_t testang = 0; + + mobjinfo[MT_NULL].spawnstate = S_INVISIBLE; + mobjinfo[MT_NULL].flags = MF_NOGRAVITY|MF_NOTHINK|MF_NOCLIPTHING|MF_NOBLOCKMAP; + mobjinfo[MT_NULL].radius = mobjinfo[actor->type].radius; + mobjinfo[MT_NULL].height = mobjinfo[actor->type].height; + + if (P_RandomChance(FRACUNIT/2)) // port priority 1? + { + i = 9; + j = 27; + } + else + { + i = 27; + j = 9; + } + +#define dostuff(q) check = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_NULL);\ + testang = actor->angle + ((i+(q))*ANG10);\ + allow = (P_TryMove(check,\ + P_ReturnThrustX(check, testang, dist + 2*actor->radius),\ + P_ReturnThrustY(check, testang, dist + 2*actor->radius),\ + true));\ + P_RemoveMobj(check);\ + if (allow)\ + break; + + if (P_RandomChance(FRACUNIT/2)) // port priority 2? + { + for (k = 0; k < 9; k++) + { + dostuff(i+k) + dostuff(i-k) + dostuff(j+k) + dostuff(j-k) + } + } + else + { + for (k = 0; k < 9; k++) + { + dostuff(i-k) + dostuff(i+k) + dostuff(j-k) + dostuff(j+k) + } + } + actor->angle = testang; + +#undef dostuff + + mobjinfo[MT_NULL].spawnstate = oldspawnstate; + mobjinfo[MT_NULL].flags = oldflags; + mobjinfo[MT_NULL].radius = oldradius; + mobjinfo[MT_NULL].height = oldheight; + } an = actor->angle >> ANGLETOFINESHIFT; actor->momx = FixedMul(speed, FINECOSINE(an)); actor->momy = FixedMul(speed, FINESINE(an)); - dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); dist = dist / speed; if (dist < 1) @@ -2296,10 +3250,9 @@ void A_BossZoom(mobj_t *actor) angle_t an; INT32 dist; -#ifdef HAVE_BLUA if (LUA_CallAction("A_BossZoom", actor)) return; -#endif + if (!actor->target) return; @@ -2324,9 +3277,9 @@ void A_BossZoom(mobj_t *actor) // Description: Spawns explosions and plays appropriate sounds around the defeated boss. // // var1: -// 0 - Use movecount to spawn explosions evenly -// 1 - Use P_Random to spawn explosions at complete random -// var2 = Object to spawn. Default is MT_BOSSEXPLODE. +// & 1 - Use P_Random to spawn explosions at complete random +// & 2 - Use entire vertical range of object to spawn +// var2 = Object to spawn. Default is MT_SONIC3KBOSSEXPLODE. // void A_BossScream(mobj_t *actor) { @@ -2337,32 +3290,29 @@ void A_BossScream(mobj_t *actor) INT32 locvar2 = var2; mobjtype_t explodetype; -#ifdef HAVE_BLUA if (LUA_CallAction("A_BossScream", actor)) return; -#endif - switch (locvar1) + + if (locvar1 & 1) + fa = (FixedAngle(P_RandomKey(360)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; + else { - default: - case 0: actor->movecount += 4*16; actor->movecount %= 360; fa = (FixedAngle(actor->movecount*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - break; - case 1: - fa = (FixedAngle(P_RandomKey(360)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - break; } x = actor->x + FixedMul(FINECOSINE(fa),actor->radius); y = actor->y + FixedMul(FINESINE(fa),actor->radius); // Determine what mobj to spawn. If undefined or invalid, use MT_BOSSEXPLODE as default. if (locvar2 <= 0 || locvar2 >= NUMMOBJTYPES) - explodetype = MT_BOSSEXPLODE; + explodetype = MT_SONIC3KBOSSEXPLODE; //MT_BOSSEXPLODE; -- piss to you, sonic 2 else explodetype = (mobjtype_t)locvar2; - if (actor->eflags & MFE_VERTICALFLIP) + if (locvar1 & 2) + z = actor->z + (P_RandomKey((actor->height - mobjinfo[explodetype].height)>>FRACBITS)<eflags & MFE_VERTICALFLIP) z = actor->z + actor->height - mobjinfo[explodetype].height - FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale); else z = actor->z + FixedMul((P_RandomByte()<<(FRACBITS-2)) - 8*FRACUNIT, actor->scale); @@ -2385,10 +3335,9 @@ void A_BossScream(mobj_t *actor) // void A_Scream(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_Scream", actor)) return; -#endif + if (actor->tracer && (actor->tracer->type == MT_SHELL || actor->tracer->type == MT_FIREBALL)) S_StartScreamSound(actor, sfx_mario2); else if (actor->info->deathsound) @@ -2404,10 +3353,9 @@ void A_Scream(mobj_t *actor) // void A_Pain(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_Pain", actor)) return; -#endif + if (actor->info->painsound) S_StartSound(actor, actor->info->painsound); @@ -2419,15 +3367,16 @@ void A_Pain(mobj_t *actor) // // Description: Changes a dying object's flags to reflect its having fallen to the ground. // -// var1 = unused +// var1 = value to set repeat to if nonzero // var2 = unused // void A_Fall(mobj_t *actor) { -#ifdef HAVE_BLUA + INT32 locvar1 = var1; + if (LUA_CallAction("A_Fall", actor)) return; -#endif + // actor is on ground, it can be walked over actor->flags &= ~MF_SOLID; @@ -2436,227 +3385,26 @@ void A_Fall(mobj_t *actor) // So change this if corpse objects // are meant to be obstacles. -} -#define LIVESBOXDISPLAYPLAYER // Use displayplayer instead of closest player - -// Function: A_1upThinker -// -// Description: Used by the 1up box to show the player's face. -// -// var1 = unused -// var2 = unused -// -void A_1upThinker(mobj_t *actor) -{ - INT32 i; - fixed_t dist = INT32_MAX; - fixed_t temp; - INT32 closestplayer = -1; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_1upThinker", actor)) - return; -#endif - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].bot || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if ((netgame || multiplayer) && players[i].playerstate != PST_LIVE) - continue; - - temp = P_AproxDistance(players[i].mo->x-actor->x, players[i].mo->y-actor->y); - - if (temp < dist) - { - closestplayer = i; - dist = temp; - } - } - - if (closestplayer == -1 || skins[players[closestplayer].skin].spritedef.numframes <= states[S_PLAY_BOX1].frame) - { // Closest player not found (no players in game?? may be empty dedicated server!), or does not have correct sprite. - actor->frame = 0; - if (actor->tracer) { - P_RemoveMobj(actor->tracer); - actor->tracer = NULL; - } - return; - } - - if (!actor->tracer) - { - P_SetTarget(&actor->tracer, P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY)); - P_SetTarget(&actor->tracer->target, actor); - P_SetMobjState(actor->tracer, actor->info->seestate); - } - - actor->tracer->color = players[closestplayer].mo->color; - actor->tracer->skin = &skins[players[closestplayer].skin]; -} - -// Function: A_MonitorPop -// -// Description: Used by monitors when they explode. -// -// var1 = unused -// var2 = unused -// -void A_MonitorPop(mobj_t *actor) -{ - mobj_t *remains; - mobjtype_t explode; - mobjtype_t item = 0; - //mobjtype_t newbox; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MonitorPop", actor)) - return; -#endif - - // de-solidify - actor->health = 0; - P_UnsetThingPosition(actor); - actor->flags &= ~MF_SOLID; - actor->flags |= MF_NOCLIP; - P_SetThingPosition(actor); - - // Monitor explosion - explode = mobjinfo[actor->info->speed].mass; - remains = P_SpawnMobj(actor->x, actor->y, - ((actor->eflags & MFE_VERTICALFLIP) ? (actor->z + 3*(actor->height/4) - FixedMul(mobjinfo[explode].height, actor->scale)) : (actor->z + actor->height/4)), explode); - if (actor->eflags & MFE_VERTICALFLIP) - { - remains->eflags |= MFE_VERTICALFLIP; - remains->flags2 |= MF2_OBJECTFLIP; - } - remains->destscale = actor->destscale; - P_SetScale(remains, actor->scale); - - remains = P_SpawnMobj(actor->x, actor->y, - ((actor->eflags & MFE_VERTICALFLIP) ? (actor->z + actor->height - FixedMul(mobjinfo[actor->info->speed].height, actor->scale)) : actor->z), - actor->info->speed); - remains->type = actor->type; // Transfer type information - P_UnsetThingPosition(remains); - if (sector_list) - { - P_DelSeclist(sector_list); - sector_list = NULL; - } - P_SetThingPosition(remains); - remains->destscale = actor->destscale; - P_SetScale(remains, actor->scale); - remains->flags = actor->flags; // Transfer flags - remains->flags2 = actor->flags2; // Transfer flags2 - remains->fuse = actor->fuse; // Transfer respawn timer - remains->threshold = 68; - remains->skin = NULL; - - P_SetTarget(&tmthing, remains); - - if (actor->info->deathsound) - S_StartSound(remains, actor->info->deathsound); - - switch (actor->type) - { - /*case MT_QUESTIONBOX: // Random! - { - mobjtype_t spawnchance[256]; - INT32 numchoices = 0, i = 0; - -#define QUESTIONBOXCHANCES(type, cvar) \ -for (i = cvar.value; i; --i) spawnchance[numchoices++] = type - - QUESTIONBOXCHANCES(MT_SUPERRINGBOX, cv_superring); - QUESTIONBOXCHANCES(MT_SNEAKERTV, cv_supersneakers); - QUESTIONBOXCHANCES(MT_INV, cv_invincibility); - QUESTIONBOXCHANCES(MT_WHITETV, cv_jumpshield); - QUESTIONBOXCHANCES(MT_GREENTV, cv_watershield); - QUESTIONBOXCHANCES(MT_YELLOWTV, cv_ringshield); - QUESTIONBOXCHANCES(MT_BLUETV, cv_forceshield); - QUESTIONBOXCHANCES(MT_BLACKTV, cv_bombshield); - QUESTIONBOXCHANCES(MT_PRUP, cv_1up); - QUESTIONBOXCHANCES(MT_EGGMANBOX, cv_eggmanbox); - QUESTIONBOXCHANCES(MT_MIXUPBOX, cv_teleporters); - QUESTIONBOXCHANCES(MT_RECYCLETV, cv_recycler); - -#undef QUESTIONBOXCHANCES - - if (numchoices == 0) - { - CONS_Alert(CONS_WARNING, M_GetText("All monitors turned off.\n")); - return; - } - - newbox = spawnchance[P_RandomKey(numchoices)]; - item = mobjinfo[newbox].damage; - - remains->flags2 &= ~MF2_AMBUSH; - break; - }*/ - default: - item = actor->info->damage; - break; - } - - if (item != 0) - { - mobj_t *newmobj; - - if (actor->eflags & MFE_VERTICALFLIP) - { - newmobj = P_SpawnMobj(actor->x, actor->y, actor->z + actor->height - FixedMul(13*FRACUNIT + mobjinfo[item].height, actor->scale), item); - newmobj->eflags |= MFE_VERTICALFLIP; - } - else - newmobj = P_SpawnMobj(actor->x, actor->y, actor->z + FixedMul(13*FRACUNIT, actor->scale), item); - - newmobj->destscale = actor->destscale; - P_SetScale(newmobj, actor->scale); - P_SetTarget(&newmobj->target, actor->target); // Transfer target - if (item == MT_1UPICO && newmobj->target->player) - { - if (actor->tracer) // Remove the old lives icon. - P_RemoveMobj(actor->tracer); - - if (!newmobj->target->skin || ((skin_t *)newmobj->target->skin)->spritedef.numframes <= states[S_PLAY_BOX1].frame) - newmobj->frame -= 2; // No lives icon for this player, use the default. - else - { // Spawn the lives icon. - remains = P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_OVERLAY); - P_SetTarget(&remains->target, newmobj); - P_SetTarget(&newmobj->tracer, remains); - - remains->color = newmobj->target->player->mo->color; - remains->skin = &skins[newmobj->target->player->skin]; - P_SetMobjState(remains, newmobj->info->seestate); - } - } - } - else - CONS_Debug(DBG_GAMELOGIC, "Powerup item not defined in 'damage' field for A_MonitorPop\n"); - - P_RemoveMobj(actor); + if (locvar1) + actor->extravalue2 = locvar1; } // Function: A_Explode // // Description: Explodes an object, doing damage to any objects nearby. The target is used as the cause of the explosion. Damage value is used as explosion range. // -// var1 = unused +// var1 = damagetype // var2 = unused // void A_Explode(mobj_t *actor) { -#ifdef HAVE_BLUA + INT32 locvar1 = var1; + if (LUA_CallAction("A_Explode", actor)) return; -#endif - P_RadiusAttack(actor, actor->target, actor->info->damage); + + P_RadiusAttack(actor, actor->target, actor->info->damage, locvar1, true); } // Function: A_BossDeath @@ -2672,12 +3420,14 @@ void A_BossDeath(mobj_t *mo) mobj_t *mo2; line_t junk; INT32 i; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_BossDeath", mo)) return; -#endif - P_LinedefExecute(LE_BOSSDEAD, mo, NULL); + if (mo->spawnpoint && mo->spawnpoint->extrainfo) + P_LinedefExecute(LE_BOSSDEAD+(mo->spawnpoint->extrainfo*LE_PARAMWIDTH), mo, NULL); + else + P_LinedefExecute(LE_BOSSDEAD, mo, NULL); mo->health = 0; // Boss is dead (but not necessarily fleeing...) @@ -2686,8 +3436,8 @@ void A_BossDeath(mobj_t *mo) // make sure there is a player alive for victory for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (players[i].health > 0 - || ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0)))) + if (playeringame[i] && ((players[i].mo && players[i].mo->health) + || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) break; if (i == MAXPLAYERS) @@ -2695,9 +3445,9 @@ void A_BossDeath(mobj_t *mo) // scan the remaining thinkers to see // if all bosses are dead - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -2707,126 +3457,261 @@ void A_BossDeath(mobj_t *mo) // victory! P_LinedefExecute(LE_ALLBOSSESDEAD, mo, NULL); + if (stoppedclock && modeattacking) // if you're just time attacking, skip making the capsule appear since you don't need to step on it anyways. + goto bossjustdie; if (mo->flags2 & MF2_BOSSNOTRAP) { for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; P_DoPlayerExit(&players[i]); + } } else { // Bring the egg trap up to the surface - junk.tag = 680; + junk.tag = LE_CAPSULE0; EV_DoElevator(&junk, elevateHighest, false); - junk.tag = 681; + junk.tag = LE_CAPSULE1; EV_DoElevator(&junk, elevateUp, false); - junk.tag = 682; + junk.tag = LE_CAPSULE2; EV_DoElevator(&junk, elevateHighest, false); + + if (mapheaderinfo[gamemap-1]->muspostbossname[0] && + S_MusicExists(mapheaderinfo[gamemap-1]->muspostbossname)) + { + // Touching the egg trap button calls P_DoPlayerExit, which calls P_RestoreMusic. + // So just park ourselves in the mapmus variables. + // But don't change the mapmus variables if they were modified from their level header values (e.g., TUNES). + boolean changed = strnicmp(mapheaderinfo[gamemap-1]->musname, S_MusicName(), 7); + if (!strnicmp(mapheaderinfo[gamemap-1]->musname, mapmusname, 7)) + { + strncpy(mapmusname, mapheaderinfo[gamemap-1]->muspostbossname, 7); + mapmusname[6] = 0; + mapmusflags = (mapheaderinfo[gamemap-1]->muspostbosstrack & MUSIC_TRACKMASK) | MUSIC_RELOADRESET; + mapmusposition = mapheaderinfo[gamemap-1]->muspostbosspos; + } + + // don't change if we're in another tune + // but in case we're in jingle, use our parked mapmus variables so the correct track restores + if (!changed) + S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, (1*MUSICRATE)+(MUSICRATE/2), + mapheaderinfo[gamemap-1]->muspostbossfadein); + } } bossjustdie: -#ifdef HAVE_BLUA if (LUAh_BossDeath(mo)) return; else if (P_MobjWasRemoved(mo)) return; -#endif - if (mo->type == MT_BLACKEGGMAN || mo->type == MT_CYBRAKDEMON) + + // Spawn your junk + switch (mo->type) { - mo->flags |= MF_NOCLIP; - mo->flags &= ~MF_SPECIAL; - - S_StartSound(NULL, sfx_befall); - } - else if (mo->type == MT_KOOPA) - { - junk.tag = 650; - EV_DoCeiling(&junk, raiseToHighest); - return; - } - else // eggmobiles - { - // Stop exploding and prepare to run. - P_SetMobjState(mo, mo->info->xdeathstate); - if (P_MobjWasRemoved(mo)) - return; - - P_SetTarget(&mo->target, NULL); - - // Flee! Flee! Find a point to escape to! If none, just shoot upward! - // scan the thinkers to find the runaway point - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_BOSSFLYPOINT) + default: + break; + case MT_EGGMOBILE: // twin laser pods { - // If this one's closer then the last one, go for it. - if (!mo->target || - P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) < - P_AproxDistance(P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y), mo->z - mo->target->z)) - P_SetTarget(&mo->target, mo2); - // Otherwise... Don't! + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSEGLZ1); + + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSEGLZ2); } - } + break; + case MT_EGGMOBILE2: // twin tanks + spigot + { + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle - ANGLE_90, 32<angle - ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle - ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSTANK1); - mo->flags |= MF_NOGRAVITY|MF_NOCLIP; - mo->flags |= MF_NOCLIPHEIGHT; + mo2 = P_SpawnMobjFromMobj(mo, + P_ReturnThrustX(mo, mo->angle + ANGLE_90, 32<angle + ANGLE_90, 32<angle = mo->angle; + P_InstaThrust(mo2, mo2->angle + ANGLE_90, 4*mo2->scale); + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + P_SetMobjState(mo2, S_BOSSTANK2); - if (mo->target) - { - mo->angle = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y); - mo->flags2 |= MF2_BOSSFLEE; - mo->momz = FixedMul(FixedDiv(mo->target->z - mo->z, P_AproxDistance(mo->x-mo->target->x,mo->y-mo->target->y)), FixedMul(2*FRACUNIT, mo->scale)); - } - else - mo->momz = FixedMul(2*FRACUNIT, mo->scale); + mo2 = P_SpawnMobjFromMobj(mo, 0, 0, + mobjinfo[MT_EGGMOBILE2].height + (32<angle = mo->angle; + P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + mo2->momz += mo->momz; + P_SetMobjState(mo2, S_BOSSSPIGOT); + } + break; + case MT_EGGMOBILE3: + { + mo2 = P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_BOSSJUNK); + mo2->angle = mo->angle; + P_SetMobjState(mo2, S_BOSSSEBH1); + } + break; } - if (mo->type == MT_EGGMOBILE2) + // now do another switch case for escaping + switch (mo->type) { - mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->y + P_ReturnThrustY(mo, mo->angle - ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK1].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK1); // Right tank - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) + case MT_BLACKEGGMAN: { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; - } - P_InstaThrust(mo2, mo2->angle - ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + mo->flags |= MF_NOCLIP; + mo->flags &= ~MF_SPECIAL; - mo2 = P_SpawnMobj(mo->x + P_ReturnThrustX(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->y + P_ReturnThrustY(mo, mo->angle + ANGLE_90, FixedMul(32*FRACUNIT, mo->scale)), - mo->z + mo->height/2 + ((mo->eflags & MFE_VERTICALFLIP)? FixedMul(8*FRACUNIT, mo->scale)-mobjinfo[MT_BOSSTANK2].height : -FixedMul(8*FRACUNIT, mo->scale)), MT_BOSSTANK2); // Left tank - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; + S_StartSound(NULL, sfx_befall); + break; } - P_InstaThrust(mo2, mo2->angle + ANGLE_90, FixedMul(4*FRACUNIT, mo2->scale)); - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); + case MT_CYBRAKDEMON: + { + mo->flags |= MF_NOCLIP; + mo->flags &= ~(MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT); - mo2 = P_SpawnMobj(mo->x, mo->y, - mo->z + ((mo->eflags & MFE_VERTICALFLIP)? mobjinfo[MT_BOSSSPIGOT].height-FixedMul(32*FRACUNIT,mo->scale): mo->height + FixedMul(32*FRACUNIT, mo->scale)), MT_BOSSSPIGOT); - mo2->angle = mo->angle; - mo2->destscale = mo->scale; - P_SetScale(mo2, mo2->destscale); - if (mo->eflags & MFE_VERTICALFLIP) - { - mo2->eflags |= MFE_VERTICALFLIP; - mo2->flags2 |= MF2_OBJECTFLIP; + S_StartSound(NULL, sfx_bedie2); + P_SpawnMobjFromMobj(mo, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); + mo->z += P_MobjFlip(mo); + P_SetObjectMomZ(mo, 12*FRACUNIT, false); + S_StartSound(mo, sfx_bgxpld); + if (mo->spawnpoint && !(mo->spawnpoint->options & MTF_EXTRA)) + P_InstaThrust(mo, R_PointToAngle2(0, 0, mo->x, mo->y), 14*FRACUNIT); + break; + } + case MT_KOOPA: + { + junk.tag = LE_KOOPA; + EV_DoCeiling(&junk, raiseToHighest); + return; + } + case MT_FANG: + { + if (mo->flags2 & MF2_SLIDEPUSH) + { + P_RemoveMobj(mo); + return; + } + if (mo->tracer) + { + var1 = var2 = 0; + A_Boss5Jump(mo); + mo->momx = ((16 - 1)*mo->momx)/16; + mo->momy = ((16 - 1)*mo->momy)/16; + { + const fixed_t time = FixedHypot(mo->tracer->x - mo->x, mo->tracer->y - mo->y)/FixedHypot(mo->momx, mo->momy); + const fixed_t speed = 64*FRACUNIT; + mobj_t *pole = P_SpawnMobj( + mo->tracer->x - P_ReturnThrustX(mo->tracer, mo->tracer->angle, speed*time), + mo->tracer->y - P_ReturnThrustY(mo->tracer, mo->tracer->angle, speed*time), + mo->tracer->floorz + (256+1)*FRACUNIT, + MT_FSGNB); + P_SetTarget(&pole->tracer, P_SpawnMobj( + pole->x, pole->y, + pole->z - 256*FRACUNIT, + MT_FSGNB)); + P_SetTarget(&pole->tracer->tracer, P_SpawnMobj( + pole->x + P_ReturnThrustX(pole, mo->tracer->angle, FRACUNIT), + pole->y + P_ReturnThrustY(pole, mo->tracer->angle, FRACUNIT), + pole->z + 256*FRACUNIT, + MT_FSGNA)); + pole->tracer->flags |= MF_NOCLIPTHING; + P_SetScale(pole, (pole->destscale = 2*FRACUNIT)); + P_SetScale(pole->tracer, (pole->tracer->destscale = 2*FRACUNIT)); + pole->angle = pole->tracer->angle = mo->tracer->angle; + pole->tracer->tracer->angle = pole->angle - ANGLE_90; + pole->momx = P_ReturnThrustX(pole, pole->angle, speed); + pole->momy = P_ReturnThrustY(pole, pole->angle, speed); + pole->tracer->momx = pole->momx; + pole->tracer->momy = pole->momy; + pole->tracer->tracer->momx = pole->momx; + pole->tracer->tracer->momy = pole->momy; + } + } + else + { + P_SetObjectMomZ(mo, 10*FRACUNIT, false); + mo->flags |= MF_NOGRAVITY; + } + mo->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; + return; + } + default: //eggmobiles + { + UINT8 extrainfo = (mo->spawnpoint ? mo->spawnpoint->extrainfo : 0); + + // Stop exploding and prepare to run. + P_SetMobjState(mo, mo->info->xdeathstate); + if (P_MobjWasRemoved(mo)) + return; + + P_SetTarget(&mo->target, NULL); + + // Flee! Flee! Find a point to escape to! If none, just shoot upward! + // scan the thinkers to find the runaway point + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_BOSSFLYPOINT) + continue; + + if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo) + continue; + + // If this one's further then the last one, don't go for it. + if (mo->target && + P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z) > + P_AproxDistance(P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y), mo->z - mo->target->z)) + continue; + + // Otherwise... Do! + P_SetTarget(&mo->target, mo2); + } + + mo->flags |= MF_NOGRAVITY|MF_NOCLIP; + mo->flags |= MF_NOCLIPHEIGHT; + + mo->movedir = 0; + mo->extravalue1 = 35; + mo->flags2 |= MF2_BOSSFLEE; + mo->momz = P_MobjFlip(mo)*2*mo->scale; + + if (mo->target) + { + angle_t diff = R_PointToAngle2(mo->x, mo->y, mo->target->x, mo->target->y) - mo->angle; + if (diff) + { + if (diff > ANGLE_180) + diff = InvAngle(InvAngle(diff)/mo->extravalue1); + else + diff /= mo->extravalue1; + mo->movedir = diff; + } + } + + break; } - P_SetObjectMomZ(mo2, 4*FRACUNIT, false); - return; } } @@ -2844,10 +3729,9 @@ void A_CustomPower(mobj_t *actor) INT32 locvar2 = var2; boolean spawnshield = false; -#ifdef HAVE_BLUA if (LUA_CallAction("A_CustomPower", actor)) return; -#endif + if (!actor->target || !actor->target->player) { CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); @@ -2873,106 +3757,6 @@ void A_CustomPower(mobj_t *actor) P_SpawnShieldOrb(player); } -// Function: A_GiveWeapon -// -// Description: Gives the player the specified weapon panels. -// -// var1 = Weapon index # -// var2 = unused -// -void A_GiveWeapon(mobj_t *actor) -{ - player_t *player; - INT32 locvar1 = var1; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_GiveWeapon", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - if (locvar1 >= 1<<(NUM_WEAPONS-1)) - { - CONS_Debug(DBG_GAMELOGIC, "Weapon #%d out of range!\n", locvar1); - return; - } - - player = actor->target->player; - - player->ringweapons |= locvar1; - if (actor->info->seesound) - S_StartSound(player->mo, actor->info->seesound); -} - -// Function: A_JumpShield -// -// Description: Awards the player a jump shield. -// -// var1 = unused -// var2 = unused -// -void A_JumpShield(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_JumpShield", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_JUMP) - { - player->powers[pw_shield] = SH_JUMP|(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(player); - } - - S_StartSound(player->mo, actor->info->seesound); -} - -// Function: A_RingShield -// -// Description: Awards the player a ring shield. -// -// var1 = unused -// var2 = unused -// -void A_RingShield(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RingShield", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ATTRACT) - { - player->powers[pw_shield] = SH_ATTRACT|(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(player); - } - - if (!player->exiting) // SRB2kart - S_StartSound(player->mo, actor->info->seesound); -} - // Function: A_RingBox // // Description: Awards the player 10 rings. @@ -2984,10 +3768,9 @@ void A_RingBox(mobj_t *actor) { player_t *player; -#ifdef HAVE_BLUA if (LUA_CallAction("A_RingBox", actor)) return; -#endif + if (!actor->target || !actor->target->player) { CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); @@ -3012,10 +3795,9 @@ void A_Invincibility(mobj_t *actor) { player_t *player; -#ifdef HAVE_BLUA if (LUA_CallAction("A_Invincibility", actor)) return; -#endif + if (!actor->target || !actor->target->player) { CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); @@ -3027,10 +3809,9 @@ void A_Invincibility(mobj_t *actor) if (P_IsLocalPlayer(player) && !player->powers[pw_super]) { - S_StopMusic(); - if (mariomode) - G_GhostAddColor((INT32) (player - players), GHC_INVINCIBLE); - S_ChangeMusicInternal((mariomode) ? "minvnc" : "invinc", false); + P_PlayJingle(player, JT_INV); + strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14); + S_StartCaption(sfx_None, -1, player->powers[pw_invulnerability]); } } @@ -3045,10 +3826,9 @@ void A_SuperSneakers(mobj_t *actor) { player_t *player; -#ifdef HAVE_BLUA if (LUA_CallAction("A_SuperSneakers", actor)) return; -#endif + if (!actor->target || !actor->target->player) { CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); @@ -3061,13 +3841,10 @@ void A_SuperSneakers(mobj_t *actor) if (P_IsLocalPlayer(player) && !player->powers[pw_super]) { - if (S_SpeedMusic(0.0f) && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) + if (S_SpeedMusic(0.0f)) S_SpeedMusic(1.4f); - else - { - S_StopMusic(); - S_ChangeMusicInternal("shoes", false); - } + strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12); + S_StartCaption(sfx_None, -1, player->powers[pw_sneakers]); } } @@ -3082,10 +3859,9 @@ void A_AwardScore(mobj_t *actor) { player_t *player; -#ifdef HAVE_BLUA if (LUA_CallAction("A_AwardScore", actor)) return; -#endif + if (!actor->target || !actor->target->player) { CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); @@ -3099,21 +3875,21 @@ void A_AwardScore(mobj_t *actor) S_StartSound(player->mo, actor->info->seesound); } -// Function: A_ExtraLife +// Function: A_GiveShield // -// Description: Awards the player an extra life. +// Description: Awards the player a specified shield. // -// var1 = unused +// var1 = Shield type (make with SH_ constants) // var2 = unused // -void A_ExtraLife(mobj_t *actor) +void A_GiveShield(mobj_t *actor) { player_t *player; + UINT16 locvar1 = var1; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ExtraLife", actor)) + if (LUA_CallAction("A_GiveShield", actor)) return; -#endif + if (!actor->target || !actor->target->player) { CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); @@ -3122,170 +3898,10 @@ void A_ExtraLife(mobj_t *actor) player = actor->target->player; - if (actor->type == MT_1UPICO && !actor->tracer) - actor->frame -= 2; // No lives icon for this player, use the default. - - if (ultimatemode) //I don't THINK so! - { - S_StartSound(player->mo, sfx_lose); - return; - } - - // In shooter gametypes, give the player 100 rings instead of an extra life. - if (gametype != GT_COOP && gametype != GT_COMPETITION) - P_GivePlayerRings(player, 100); - else - P_GivePlayerLives(player, 1); - P_PlayLivesJingle(player); -} - -// Function: A_BombShield -// -// Description: Awards the player a bomb shield. -// -// var1 = unused -// var2 = unused -// -void A_BombShield(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_BombShield", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_BOMB) - { - player->powers[pw_shield] = SH_BOMB|(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(player); - } - + P_SwitchShield(player, locvar1); S_StartSound(player->mo, actor->info->seesound); } -// Function: A_WaterShield -// -// Description: Awards the player a water shield. -// -// var1 = unused -// var2 = unused -// -void A_WaterShield(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_WaterShield", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_ELEMENTAL) - { - player->powers[pw_shield] = SH_ELEMENTAL|(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(player); - } - - /* // SRB2kart - Can't drown. - if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1) - P_RestoreMusic(player); - */ - - player->powers[pw_underwater] = 0; - - if (player->powers[pw_spacetime] > 1) - { - player->powers[pw_spacetime] = 0; - P_RestoreMusic(player); - } - S_StartSound(player->mo, actor->info->seesound); -} - -// Function: A_ForceShield -// -// Description: Awards the player a force shield. -// -// var1 = unused -// var2 = unused -// -void A_ForceShield(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ForceShield", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - if (!(player->powers[pw_shield] & SH_FORCE)) - { - player->powers[pw_shield] = SH_FORCE|(player->powers[pw_shield] & SH_STACK)|0x01; - P_SpawnShieldOrb(player); - } - else - player->powers[pw_shield] = SH_FORCE|(player->powers[pw_shield] & SH_STACK)|0x01; - - S_StartSound(player->mo, actor->info->seesound); -} - -// Function: A_PityShield -// -// Description: Awards the player a pity shield. -// Because you fail it. -// Your skill is not enough. -// See you next time. -// Bye-bye. -// -// var1 = unused -// var2 = unused -// -void A_PityShield(mobj_t *actor) -{ - player_t *player; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_PityShield", actor)) - return; -#endif - if (!actor->target || !actor->target->player) - { - CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); - return; - } - - player = actor->target->player; - - if ((player->powers[pw_shield] & SH_NOSTACK) != SH_PITY) - { - player->powers[pw_shield] = SH_PITY+(player->powers[pw_shield] & SH_STACK); - P_SpawnShieldOrb(player); - } - - S_StartSound(player->mo, actor->info->seesound); -} - - // Function: A_GravityBox // // Description: Awards the player gravity boots. @@ -3297,10 +3913,9 @@ void A_GravityBox(mobj_t *actor) { player_t *player; -#ifdef HAVE_BLUA if (LUA_CallAction("A_GravityBox", actor)) return; -#endif + if (!actor->target || !actor->target->player) { CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); @@ -3308,9 +3923,10 @@ void A_GravityBox(mobj_t *actor) } player = actor->target->player; - player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1); S_StartSound(player, actor->info->activesound); + + player->powers[pw_gravityboots] = (UINT16)(actor->info->reactiontime + 1); } // Function: A_ScoreRise @@ -3322,53 +3938,13 @@ void A_GravityBox(mobj_t *actor) // void A_ScoreRise(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_ScoreRise", actor)) return; -#endif + // make logo rise! P_SetObjectMomZ(actor, actor->info->speed, false); } -// Function: A_ParticleSpawn -// -// Description: Spawns a particle at a specified interval -// -// var1 = type (if 0, defaults to MT_PARTICLE) -// var2 = unused -// -void A_ParticleSpawn(mobj_t *actor) -{ - INT32 locvar1 = var1; - fixed_t speed; - mobjtype_t type; - mobj_t *spawn; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ParticleSpawn", actor)) - return; -#endif - if (!actor->spawnpoint) - { - P_RemoveMobj(actor); - return; - } - - if (locvar1) - type = (mobjtype_t)locvar1; - else - type = MT_PARTICLE; - - speed = FixedMul((actor->spawnpoint->angle >> 12)<scale); - - spawn = P_SpawnMobj(actor->x, actor->y, actor->z, type); - P_SetScale(spawn, actor->scale); - spawn->momz = speed; - spawn->destscale = FixedDiv(spawn->scale<scalespeed = FixedDiv(((actor->spawnpoint->angle >> 8) & 63) * actor->scale, 100<tics = actor->spawnpoint->extrainfo + 1; -} - // Function: A_BunnyHop // // Description: Makes object hop like a bunny. @@ -3381,10 +3957,9 @@ void A_BunnyHop(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_BunnyHop", actor)) return; -#endif + if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) { @@ -3405,10 +3980,10 @@ void A_BubbleSpawn(mobj_t *actor) INT32 i, locvar1 = var1; UINT8 prandom; mobj_t *bubble = NULL; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_BubbleSpawn", actor)) return; -#endif + if (!(actor->eflags & MFE_UNDERWATER)) { // Don't draw or spawn bubbles above water @@ -3420,7 +3995,7 @@ void A_BubbleSpawn(mobj_t *actor) if (!(actor->flags2 & MF2_AMBUSH)) { // Quick! Look through players! - // Don't spawn bubbles unless a player is relatively close by (var2). + // Don't spawn bubbles unless a player is relatively close by (var1). for (i = 0; i < MAXPLAYERS; ++i) if (playeringame[i] && players[i].mo && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (locvar1<z + (4*actor->height)/5; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_FanBubbleSpawn", actor)) return; -#endif + if (!(actor->eflags & MFE_UNDERWATER)) return; @@ -3505,10 +4080,9 @@ void A_BubbleRise(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_BubbleRise", actor)) return; -#endif + if (actor->type == MT_EXTRALARGEBUBBLE) P_SetObjectMomZ(actor, FixedDiv(6*FRACUNIT,5*FRACUNIT), false); // make bubbles rise! else @@ -3542,10 +4116,9 @@ void A_BubbleRise(mobj_t *actor) // void A_BubbleCheck(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_BubbleCheck", actor)) return; -#endif + if (actor->eflags & MFE_UNDERWATER) actor->drawflags &= ~MFD_DONTDRAW; // underwater so draw else @@ -3561,10 +4134,8 @@ void A_BubbleCheck(mobj_t *actor) // void A_AttractChase(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_AttractChase", actor)) return; -#endif if (actor->flags2 & MF2_NIGHTSPULL || !actor->health) return; @@ -3596,7 +4167,7 @@ void A_AttractChase(mobj_t *actor) sparkle->angle = (actor->target->angle + (offset>>1)) + (offset * actor->target->player->kartstuff[k_sparkleanim]); actor->target->player->kartstuff[k_sparkleanim] = (actor->target->player->kartstuff[k_sparkleanim]+1) % 20; - P_KillMobj(actor, actor->target, actor->target); + P_KillMobj(actor, actor->target, actor->target, DMG_NORMAL); return; } else @@ -3615,7 +4186,7 @@ void A_AttractChase(mobj_t *actor) { if (actor->extravalue1 >= 16) { - if (actor->target->player->kartstuff[k_rings] >= 20) + if (actor->target->player->rings >= 20) actor->target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player)+3; else P_GivePlayerRings(actor->target->player, 1); @@ -3743,10 +4314,9 @@ void A_DropMine(mobj_t *actor) INT32 locvar2 = var2; fixed_t z; mobj_t *mine; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_DropMine", actor)) return; -#endif if (locvar2 & 65535) { @@ -3786,15 +4356,30 @@ void A_DropMine(mobj_t *actor) // Description: Makes the stupid harmless fish in Greenflower Zone jump. // // var1 = Jump strength (in FRACBITS), if specified. Otherwise, uses the angle value. -// var2 = unused +// var2 = Trail object to spawn, if desired. // void A_FishJump(mobj_t *actor) { INT32 locvar1 = var1; -#ifdef HAVE_BLUA + INT32 locvar2 = var2; + if (LUA_CallAction("A_FishJump", actor)) return; -#endif + + if (locvar2) + { + UINT8 i; + // Don't spawn trail unless a player is nearby. + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (actor->info->speed)) + break; // Stop looking. + if (i < MAXPLAYERS) + { + fixed_t rad = actor->radius>>FRACBITS; + P_SpawnMobjFromMobj(actor, P_RandomRange(rad, -rad)<z <= actor->floorz) || (actor->z <= actor->watertop - FixedMul((64 << FRACBITS), actor->scale))) { @@ -3815,171 +4400,6 @@ void A_FishJump(mobj_t *actor) P_SetMobjStateNF(actor, actor->info->meleestate); } -// Function:A_ThrownRing -// -// Description: Thinker for thrown rings/sparkle trail -// -// var1 = unused -// var2 = unused -// -void A_ThrownRing(mobj_t *actor) -{ - INT32 c = 0; - INT32 stop; - player_t *player; - fixed_t dist; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_ThrownRing", actor)) - return; -#endif - - if (leveltime % (TICRATE/7) == 0) - { - mobj_t *ring = NULL; - - if (actor->flags2 & MF2_EXPLOSION) - { - if (actor->momx != 0 || actor->momy != 0) - ring = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOKE); - // Else spawn nothing because it's totally stationary and constantly smoking would be weird -SH - } - else if (actor->flags2 & MF2_AUTOMATIC) - ring = P_SpawnGhostMobj(actor); - else if (!(actor->flags2 & MF2_RAILRING)) - ring = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SPARK); - - if (ring) - { - /* - P_SetTarget(&ring->target, actor); - ring->color = actor->color; //copy color - */ - ring->destscale = actor->scale; - P_SetScale(ring, actor->scale); - } - } - - // A_GrenadeRing beeping lives once moooooore -SH - if (actor->type == MT_THROWNGRENADE && actor->fuse % TICRATE == 0) - S_StartSound(actor, actor->info->attacksound); - - // decrement bounce ring time - if (actor->flags2 & MF2_BOUNCERING) - { - if (actor->fuse) - actor->fuse--; - else { - P_RemoveMobj(actor); - return; - } - } - - // spilled rings (and thrown bounce) flicker before disappearing - if (leveltime & 1 && actor->fuse > 0 && actor->fuse < 2*TICRATE - && actor->type != MT_THROWNGRENADE) - actor->drawflags |= MFD_DONTDRAW; - else - actor->drawflags &= ~MFD_DONTDRAW; - - if (actor->tracer && actor->tracer->health <= 0) - P_SetTarget(&actor->tracer, NULL); - - // Updated homing ring special capability - // If you have a ring shield, all rings thrown - // at you become homing (except rail)! - if (actor->tracer) - { - // A non-homing ring getting attracted by a - // magnetic player. If he gets too far away, make - // sure to stop the attraction! - if ((!actor->tracer->health) // || (actor->tracer->player && (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT - || P_AproxDistance(P_AproxDistance(actor->tracer->x-actor->x, - actor->tracer->y-actor->y), actor->tracer->z-actor->z) > FixedMul(RING_DIST, actor->tracer->scale)) // SRB2kart - { - P_SetTarget(&actor->tracer, NULL); - } - - if (actor->tracer && (actor->tracer->health)) // SRB2kart - jawz always follow - //&& (actor->tracer->player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT)// Already found someone to follow. - { - const INT32 temp = actor->threshold; - actor->threshold = 32000; - P_HomingAttack(actor, actor->tracer); - actor->threshold = temp; - return; - } - } - - // first time init, this allow minimum lastlook changes - if (actor->lastlook < 0) - actor->lastlook = P_RandomByte(); - - actor->lastlook %= MAXPLAYERS; - - stop = (actor->lastlook - 1) & PLAYERSMASK; - - for (; ; actor->lastlook = (actor->lastlook + 1) & PLAYERSMASK) - { - // done looking - if (actor->lastlook == stop) - return; - - if (!playeringame[actor->lastlook]) - continue; - - if (c++ == 2) - return; - - player = &players[actor->lastlook]; - - if (!player->mo) - continue; - - if (player->mo->health <= 0) - continue; // dead - - if ((netgame || multiplayer) && player->spectator) - continue; // spectator - - if (actor->target && actor->target->player) - { - if (player->mo == actor->target) - continue; - - // Don't home in on teammates. - if (gametype == GT_CTF - && actor->target->player->ctfteam == player->ctfteam) - continue; - - if (actor->target->player->kartstuff[k_position] < player->kartstuff[k_position]) // SRB2kart - Jawz only go after people ahead of you - continue; - - } - - dist = P_AproxDistance(P_AproxDistance(player->mo->x-actor->x, - player->mo->y-actor->y), player->mo->z-actor->z); - - // check distance - if (actor->flags2 & MF2_RAILRING) - { - if (dist > FixedMul(RING_DIST/2, player->mo->scale)) - continue; - } - else if (dist > FixedMul(RING_DIST, player->mo->scale)) - continue; - - // do this after distance check because it's more computationally expensive - if (!P_CheckSight(actor, player->mo)) - continue; // out of sight - - if (dist < FixedMul(2048*FRACUNIT, player->mo->scale)) // SRB2kart // (player->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT && - P_SetTarget(&actor->tracer, player->mo); - return; - } - - return; -} - //{ SRB2kart - A_GRENADERING static mobj_t *grenade; static fixed_t explodedist; @@ -4008,12 +4428,7 @@ static inline boolean PIT_GrenadeRing(mobj_t *thing) return true; if (thing->player && (thing->player->kartstuff[k_hyudorotimer] - || (G_BattleGametype() && thing->player && thing->player->kartstuff[k_bumper] <= 0 && thing->player->kartstuff[k_comebacktimer]))) - return true; - - if ((gametype == GT_CTF || gametype == GT_TEAMMATCH) - && !cv_friendlyfire.value && grenade->target->player && thing->player - && grenade->target->player->ctfteam == thing->player->ctfteam) // Don't blow up at your teammates, unless friendlyfire is on + || ((gametyperules & GTR_BUMPERS) && thing->player && thing->player->kartstuff[k_bumper] <= 0 && thing->player->kartstuff[k_comebacktimer]))) return true; // see if it went over / under @@ -4035,10 +4450,9 @@ void A_GrenadeRing(mobj_t *actor) { INT32 bx, by, xl, xh, yl, yh; explodedist = FixedMul(actor->info->painchance, mapobjectscale); -#ifdef HAVE_BLUA + if (LUA_CallAction("A_GrenadeRing", actor)) return; -#endif if (actor->flags2 & MF2_DEBRIS) return; @@ -4079,7 +4493,7 @@ static inline boolean PIT_MineExplode(mobj_t *thing) if (netgame && thing->player && thing->player->spectator) return true; - if (G_BattleGametype() && grenade->target && grenade->target->player && grenade->target->player->kartstuff[k_bumper] <= 0 && thing == grenade->target) + if ((gametyperules & GTR_BUMPERS) && grenade->target && grenade->target->player && grenade->target->player->kartstuff[k_bumper] <= 0 && thing == grenade->target) return true; // see if it went over / under @@ -4092,25 +4506,20 @@ static inline boolean PIT_MineExplode(mobj_t *thing) thing->z - grenade->z) > explodedist) return true; // Too far away - if (thing->player) // Looks like we're going to have to need a seperate function for this too - K_ExplodePlayer(thing->player, grenade->target, grenade); - else - P_DamageMobj(thing, grenade, grenade->target, 1); - + P_DamageMobj(thing, grenade, grenade->target, 1, DMG_EXPLODE); return true; } -void A_MineExplode(mobj_t *actor) +void A_SSMineExplode(mobj_t *actor) { INT32 bx, by, xl, xh, yl, yh; INT32 d; INT32 locvar1 = var1; mobjtype_t type; explodedist = FixedMul((3*actor->info->painchance)/2, mapobjectscale); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MineExplode", actor)) + + if (LUA_CallAction("A_SSMineExplode", actor)) return; -#endif if (actor->flags2 & MF2_DEBRIS) return; @@ -4154,14 +4563,13 @@ void A_MineExplode(mobj_t *actor) // void A_SetSolidSteam(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_SetSolidSteam", actor)) return; -#endif + actor->flags &= ~MF_NOCLIP; actor->flags |= MF_SOLID; - if (!(actor->flags2 & MF2_AMBUSH)) // Don't be so obnoxious. + if (!(actor->flags2 & MF2_AMBUSH)) { if (P_RandomChance(FRACUNIT/8)) { @@ -4187,10 +4595,9 @@ void A_SetSolidSteam(mobj_t *actor) // void A_UnsetSolidSteam(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_UnsetSolidSteam", actor)) return; -#endif + actor->flags &= ~MF_SOLID; actor->flags |= MF_NOCLIP; } @@ -4205,10 +4612,10 @@ void A_UnsetSolidSteam(mobj_t *actor) void A_OverlayThink(mobj_t *actor) { fixed_t destx, desty; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_OverlayThink", actor)) return; -#endif + if (!actor->target) return; @@ -4239,7 +4646,7 @@ void A_OverlayThink(mobj_t *actor) actor->z = actor->target->z + actor->target->height - mobjinfo[actor->type].height - ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; else actor->z = actor->target->z + ((var2>>16) ? -1 : 1)*(var2&0xFFFF)*FRACUNIT; - actor->angle = actor->target->angle; + actor->angle = actor->target->angle + actor->movedir; actor->eflags = actor->target->eflags; actor->momx = actor->target->momx; @@ -4257,10 +4664,9 @@ void A_OverlayThink(mobj_t *actor) void A_JetChase(mobj_t *actor) { fixed_t thefloor; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetChase", actor)) return; -#endif if (actor->flags2 & MF2_AMBUSH) return; @@ -4354,10 +4760,9 @@ void A_JetbThink(mobj_t *actor) { sector_t *nextsector; fixed_t thefloor; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetbThink", actor)) return; -#endif if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) @@ -4369,7 +4774,8 @@ void A_JetbThink(mobj_t *actor) { A_JetChase(actor); // check for melee attack - if ((actor->z > (actor->floorz + FixedMul((32<scale))) + if (actor->info->raisestate + && (actor->z > (actor->floorz + FixedMul((32<scale))) && P_JetbCheckMeleeRange(actor) && !actor->reactiontime && (actor->target->z >= actor->floorz)) { @@ -4419,10 +4825,9 @@ void A_JetbThink(mobj_t *actor) void A_JetgShoot(mobj_t *actor) { fixed_t dist; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetgShoot", actor)) return; -#endif if (!actor->target) return; @@ -4460,10 +4865,9 @@ void A_JetgShoot(mobj_t *actor) void A_ShootBullet(mobj_t *actor) { fixed_t dist; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_ShootBullet", actor)) return; -#endif if (!actor->target) return; @@ -4480,56 +4884,114 @@ void A_ShootBullet(mobj_t *actor) S_StartSound(actor, actor->info->attacksound); } +static mobj_t *minus; + +static boolean PIT_MinusCarry(mobj_t *thing) +{ + if (minus->tracer) + return true; + + if (minus->type == thing->type) + return true; + + if (!(thing->flags & (MF_PUSHABLE|MF_ENEMY))) + return true; + + if (P_AproxDistance(minus->x - thing->x, minus->y - thing->y) >= minus->radius*3) + return true; + + if (abs(thing->z - minus->z) > minus->height) + return true; + + P_SetTarget(&minus->tracer, thing); + + return true; +} + // Function: A_MinusDigging // // Description: Minus digging in the ground. // -// var1 = unused +// var1 = If 1, play digging sound. // var2 = unused // void A_MinusDigging(mobj_t *actor) { -#ifdef HAVE_BLUA + INT32 locvar1 = var1; + INT32 rad = 32; + angle_t fa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t dis = actor->info->speed*4; + fixed_t x = FINECOSINE(fa)*dis + actor->x + FRACUNIT*P_RandomRange(-rad, rad); + fixed_t y = FINESINE(fa)*dis + actor->y + FRACUNIT*P_RandomRange(-rad, rad); + fixed_t mz = (actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz : actor->floorz; + mobj_t *par; + if (LUA_CallAction("A_MinusDigging", actor)) return; -#endif - actor->flags &= ~MF_SPECIAL; - actor->flags &= ~MF_SHOOTABLE; if (!actor->target) { - A_Look(actor); + P_SetMobjState(actor, actor->info->spawnstate); return; } - if (actor->reactiontime) + par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT); + if (actor->eflags & MFE_VERTICALFLIP) + par->eflags |= MFE_VERTICALFLIP; + P_TryMove(par, x, y, false); + + // If close enough, prepare to attack + if (P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) < actor->radius*2) { - actor->reactiontime--; + P_SetMobjState(actor, actor->info->meleestate); + P_TryMove(actor, actor->target->x, actor->target->y, false); + S_StartSound(actor, actor->info->attacksound); + + // Spawn growing dirt pile. + par = P_SpawnMobj(actor->x, actor->y, mz, MT_MINUSDIRT); + P_SetMobjState(par, actor->info->raisestate); + P_SetScale(par, actor->scale*2); + if (actor->eflags & MFE_VERTICALFLIP) + par->eflags |= MFE_VERTICALFLIP; return; } - // Dirt trail - P_SpawnGhostMobj(actor); - - actor->flags |= MF_NOCLIPTHING; - var1 = 3; - A_Chase(actor); - actor->flags &= ~MF_NOCLIPTHING; - // Play digging sound - if (!(leveltime & 15)) - S_StartSound(actor, actor->info->activesound); + if (locvar1 == 1) + A_PlayActiveSound(actor); - // If we're close enough to our target, pop out of the ground - if (P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) < actor->radius - && abs(actor->target->z - actor->z) < actor->height) - P_SetMobjState(actor, actor->info->missilestate); + // Move + var1 = 3; + A_Chase(actor); - // Snap to ground - if (actor->eflags & MFE_VERTICALFLIP) - actor->z = actor->ceilingz - actor->height; + // Carry over shit, maybe + if (P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) + P_SetTarget(&actor->tracer, NULL); + + if (!actor->tracer) + { + fixed_t radius = 3*actor->radius; + fixed_t yh = (unsigned)(actor->y + radius - bmaporgy) >> MAPBLOCKSHIFT; + fixed_t yl = (unsigned)(actor->y - radius - bmaporgy) >> MAPBLOCKSHIFT; + fixed_t xh = (unsigned)(actor->x + radius - bmaporgx) >> MAPBLOCKSHIFT; + fixed_t xl = (unsigned)(actor->x - radius - bmaporgx) >> MAPBLOCKSHIFT; + fixed_t bx, by; + + BMBOUNDFIX(xl, xh, yl, yh); + + minus = actor; + + for (bx = xl; bx <= xh; bx++) + for (by = yl; by <= yh; by++) + P_BlockThingsIterator(bx, by, PIT_MinusCarry); + } else - actor->z = actor->floorz; + { + if (P_TryMove(actor->tracer, actor->x, actor->y, false)) + actor->tracer->z = mz; + else + P_SetTarget(&actor->tracer, NULL); + } } // Function: A_MinusPopup @@ -4541,45 +5003,65 @@ void A_MinusDigging(mobj_t *actor) // void A_MinusPopup(mobj_t *actor) { -#ifdef HAVE_BLUA + INT32 num = 6; + angle_t ani = FixedAngle(FRACUNIT*360/num); + INT32 i; + if (LUA_CallAction("A_MinusPopup", actor)) return; -#endif - P_SetObjectMomZ(actor, 10*FRACUNIT, false); - actor->flags |= MF_SPECIAL; - actor->flags |= MF_SHOOTABLE; + if (actor->eflags & MFE_VERTICALFLIP) + actor->momz = -10*FRACUNIT; + else + actor->momz = 10*FRACUNIT; - // Sound for busting out of the ground. - S_StartSound(actor, actor->info->attacksound); + S_StartSound(actor, sfx_s3k82); + for (i = 1; i <= num; i++) + { + mobj_t *rock = P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_ROCKCRUMBLE1); + P_Thrust(rock, ani*i, FRACUNIT); + P_SetObjectMomZ(rock, 3*FRACUNIT, false); + P_SetScale(rock, rock->scale/3); + } + P_RadiusAttack(actor, actor, 2*actor->radius, 0, true); + if (actor->tracer) + P_DamageMobj(actor->tracer, actor, actor, 1, DMG_NORMAL); + + actor->flags = (actor->flags & ~MF_NOCLIPTHING)|MF_SPECIAL|MF_SHOOTABLE; } // Function: A_MinusCheck // // Description: If the minus hits the floor, dig back into the ground. // -// var1 = unused -// var2 = unused +// var1 = State to switch to (if 0, use seestate). +// var2 = If not 0, spawn debris when hitting the floor. // void A_MinusCheck(mobj_t *actor) { -#ifdef HAVE_BLUA + INT32 locvar1 = var1; + INT32 locvar2 = var2; + if (LUA_CallAction("A_MinusCheck", actor)) return; -#endif - if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) - || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz)) - { - actor->flags &= ~MF_SPECIAL; - actor->flags &= ~MF_SHOOTABLE; - actor->reactiontime = TICRATE; - P_SetMobjState(actor, actor->info->seestate); - return; - } - // 'Falling' animation - if (P_MobjFlip(actor)*actor->momz < 0 && actor->state < &states[actor->info->meleestate]) - P_SetMobjState(actor, actor->info->meleestate); + if (((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz) || (!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz)) + { + P_SetMobjState(actor, locvar1 ? (statenum_t)locvar1 : actor->info->seestate); + actor->flags = actor->info->flags; + if (locvar2) + { + INT32 i, num = 6; + angle_t ani = FixedAngle(FRACUNIT*360/num); + for (i = 1; i <= num; i++) + { + mobj_t *rock = P_SpawnMobjFromMobj(actor, 0, 0, actor->height/4, MT_ROCKCRUMBLE1); + P_Thrust(rock, ani*i, FRACUNIT); + P_SetObjectMomZ(rock, 3*FRACUNIT, false); + P_SetScale(rock, rock->scale/3); + } + } + } } // Function: A_ChickenCheck @@ -4591,10 +5073,9 @@ void A_MinusCheck(mobj_t *actor) // void A_ChickenCheck(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_ChickenCheck", actor)) return; -#endif + if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) || (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height >= actor->ceilingz)) { @@ -4622,10 +5103,9 @@ void A_JetgThink(mobj_t *actor) sector_t *nextsector; fixed_t thefloor; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_JetgThink", actor)) return; -#endif if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) @@ -4674,10 +5154,8 @@ void A_JetgThink(mobj_t *actor) // void A_MouseThink(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_MouseThink", actor)) return; -#endif if (actor->reactiontime) actor->reactiontime--; @@ -4686,12 +5164,7 @@ void A_MouseThink(mobj_t *actor) || (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height == actor->ceilingz)) && !actor->reactiontime) { - if (twodlevel || actor->flags2 & MF2_TWOD) - { - if (P_RandomChance(FRACUNIT/2)) - actor->angle += ANGLE_180; - } - else if (P_RandomChance(FRACUNIT/2)) + if (P_RandomChance(FRACUNIT/2)) actor->angle += ANGLE_90; else actor->angle -= ANGLE_90; @@ -4712,10 +5185,9 @@ void A_DetonChase(mobj_t *actor) { angle_t exact; fixed_t xydist, dist; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_DetonChase", actor)) return; -#endif // modify tracer threshold if (!actor->tracer || actor->tracer->health <= 0) @@ -4859,10 +5331,10 @@ void A_CapeChase(mobj_t *actor) fixed_t foffsetx, foffsety, boffsetx, boffsety; INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + angle_t angle; + if (LUA_CallAction("A_CapeChase", actor)) return; -#endif CONS_Debug(DBG_GAMELOGIC, "A_CapeChase called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); @@ -4880,11 +5352,13 @@ void A_CapeChase(mobj_t *actor) return; } - foffsetx = P_ReturnThrustX(chaser, chaser->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); - foffsety = P_ReturnThrustY(chaser, chaser->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + angle = (chaser->player ? chaser->player->drawangle : chaser->angle); - boffsetx = P_ReturnThrustX(chaser, chaser->angle-ANGLE_90, FixedMul((locvar2 & 65535)*FRACUNIT, actor->scale)); - boffsety = P_ReturnThrustY(chaser, chaser->angle-ANGLE_90, FixedMul((locvar2 & 65535)*FRACUNIT, actor->scale)); + foffsetx = P_ReturnThrustX(chaser, angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + foffsety = P_ReturnThrustY(chaser, angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + + boffsetx = P_ReturnThrustX(chaser, angle-ANGLE_90, FixedMul((locvar2 & 65535)*FRACUNIT, actor->scale)); + boffsety = P_ReturnThrustY(chaser, angle-ANGLE_90, FixedMul((locvar2 & 65535)*FRACUNIT, actor->scale)); P_UnsetThingPosition(actor); actor->x = chaser->x + foffsetx + boffsetx; @@ -4901,7 +5375,7 @@ void A_CapeChase(mobj_t *actor) actor->flags2 &= ~MF2_OBJECTFLIP; actor->z = chaser->z + FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale); } - actor->angle = chaser->angle; + actor->angle = angle; P_SetThingPosition(actor); } @@ -4918,12 +5392,8 @@ void A_RotateSpikeBall(mobj_t *actor) { INT32 locvar1 = var1; const fixed_t radius = FixedMul(12*actor->info->speed, actor->scale); -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RotateSpikeBall", actor)) - return; -#endif - if (actor->type == MT_SPECIALSPIKEBALL) // don't remove this, these spikeballs share the same states as the rotating spikeballs + if (LUA_CallAction("A_RotateSpikeBall", actor)) return; if (!((!locvar1 && (actor->target)) || (locvar1 && (actor->tracer))))// This should NEVER happen. @@ -4974,10 +5444,8 @@ void A_UnidusBall(mobj_t *actor) INT32 locvar1 = var1; boolean canthrow = false; -#ifdef HAVE_BLUA if (LUA_CallAction("A_UnidusBall", actor)) return; -#endif actor->angle += ANGLE_11hh; @@ -5028,7 +5496,7 @@ void A_UnidusBall(mobj_t *actor) boolean skull = (actor->target->flags2 & MF2_SKULLFLY) == MF2_SKULLFLY; if (actor->target->state == &states[actor->target->info->painstate]) { - P_KillMobj(actor, NULL, NULL); + P_KillMobj(actor, NULL, NULL, DMG_NORMAL); return; } switch(actor->extravalue2) @@ -5072,10 +5540,9 @@ void A_RockSpawn(mobj_t *actor) line_t *line; fixed_t dist; fixed_t randomoomph; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_RockSpawn", actor)) return; -#endif if (i == -1) { @@ -5124,170 +5591,45 @@ void A_RockSpawn(mobj_t *actor) // void A_SlingAppear(mobj_t *actor) { - boolean firsttime = true; UINT8 mlength = 4; - mobj_t *spawnee; -#ifdef HAVE_BLUA + mobj_t *spawnee, *hprev; + if (LUA_CallAction("A_SlingAppear", actor)) return; -#endif P_UnsetThingPosition(actor); actor->flags &= ~(MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_NOCLIPHEIGHT); P_SetThingPosition(actor); actor->lastlook = 128; actor->movecount = actor->lastlook; - actor->health = actor->angle>>ANGLETOFINESHIFT; actor->threshold = 0; actor->movefactor = actor->threshold; actor->friction = 128; - actor->flags |= MF_SLIDEME; + hprev = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLGRABCHAIN); + P_SetTarget(&hprev->tracer, actor); + P_SetTarget(&hprev->hprev, actor); + P_SetTarget(&actor->hnext, hprev); + hprev->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; + hprev->movecount = mlength; + + mlength--; while (mlength > 0) { spawnee = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMALLMACECHAIN); + P_SetTarget(&spawnee->tracer, actor); + P_SetTarget(&spawnee->hprev, hprev); + P_SetTarget(&hprev->hnext, spawnee); + hprev = spawnee; - P_SetTarget(&spawnee->target, actor); - - spawnee->movecount = 0; - spawnee->threshold = 0; - spawnee->reactiontime = mlength; - - if (firsttime) - { - // This is the outermost link in the chain - spawnee->flags2 |= MF2_AMBUSH; - firsttime = false; - } + spawnee->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; + spawnee->movecount = mlength; mlength--; } } -// -// Function: A_MaceRotate -// -// Spins an object around its target, or, swings it from side to side. -// -// var1 = unused -// var2 = unused -// -// So NOBODY forgets: -// actor-> -// threshold - X tilt -// movecount - Z tilt -// reactiontime - link # in the chain (1 is closest) -// lastlook - speed -// friction - top speed -// movedir - current angle holder -// extravalue1 - smoothly move link into place -// -void A_MaceRotate(mobj_t *actor) -{ - TVector v; - TVector *res; - fixed_t radius; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_MaceRotate", actor)) - return; -#endif - - // Target was removed. - if (!actor->target) - { - P_RemoveMobj(actor); - return; - } - - P_UnsetThingPosition(actor); - - // Radius of the link's rotation. - radius = FixedMul(actor->info->speed * actor->reactiontime, actor->target->scale); - - // Double the radius if the chain links are made up of maces. - if (actor->target->type == MT_AXIS && (actor->type == MT_SMALLMACE || actor->type == MT_BIGMACE)) - radius *= 2; - - // Axis offset for the axis. - radius += actor->target->extravalue1; - - // Smoothly move the link into position. - if (actor->extravalue1) - { - radius = FixedMul(radius, FixedDiv(actor->extravalue1, 100)); - actor->extravalue1 += 1; - if (actor->extravalue1 >= 100) - actor->extravalue1 = 0; - } - - actor->x = actor->target->x; - actor->y = actor->target->y; - actor->z = actor->target->z; - - // Cut the height to align the link with the axis. - if (actor->type == MT_SMALLMACECHAIN || actor->type == MT_BIGMACECHAIN) - actor->z -= actor->height/4; - else - actor->z -= actor->height/2; - - // Set the top speed for the link if it happens to be over that speed. - if (actor->target->lastlook > actor->target->friction) - actor->target->lastlook = actor->target->friction; - - // Swinging Chain. - if (actor->target->type == MT_HANGMACEPOINT || actor->target->type == MT_SWINGMACEPOINT) - { - actor->movecount += actor->target->lastlook; - actor->movecount &= FINEMASK; - - actor->threshold = FixedMul(FINECOSINE(actor->movecount), actor->target->lastlook << FRACBITS); - - v[0] = FRACUNIT; - v[1] = 0; - v[2] = -radius; - v[3] = FRACUNIT; - - // Calculate the angle matrixes for the link. - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(actor->threshold))); - M_Memcpy(&v, res, sizeof(v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT)); - M_Memcpy(&v, res, sizeof(v)); - } - // Rotating Chain. - else - { - angle_t fa; - - actor->threshold += actor->target->lastlook; - actor->threshold &= FINEMASK; - actor->target->health &= FINEMASK; - - fa = actor->threshold; - v[0] = FixedMul(FINECOSINE(fa), radius); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), radius); - v[3] = FRACUNIT; - - // Calculate the angle matrixes for the link. - res = VectorMatrixMultiply(v, *RotateXMatrix(actor->target->threshold << ANGLETOFINESHIFT)); - M_Memcpy(&v, res, sizeof(v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(actor->target->health << ANGLETOFINESHIFT)); - M_Memcpy(&v, res, sizeof(v)); - } - - // Add on the appropriate distances to the actor's co-ordinates. - actor->x += v[0]; - actor->y += v[1]; - actor->z += v[2]; - - P_SetThingPosition(actor); - - if (!(actor->target->flags2 & MF2_BOSSNOTRAP) // flag that makes maces shut up on request - && !(leveltime & 63) && (actor->type == MT_BIGMACE || actor->type == MT_SMALLMACE) && actor->target->type == MT_MACEPOINT) - S_StartSound(actor, actor->info->activesound); -} - // Function: A_SetFuse // // Description: Sets the actor's fuse timer if not set already. May also change state when fuse reaches the last tic, otherwise by default the actor will die or disappear. (Replaces A_SnowBall) @@ -5301,10 +5643,9 @@ void A_SetFuse(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetFuse", actor)) return; -#endif if ((!actor->fuse || (locvar2 >> 16)) && (locvar2 >> 16) != 2) // set the actor's fuse value actor->fuse = locvar1; @@ -5330,10 +5671,10 @@ void A_CrawlaCommanderThink(mobj_t *actor) fixed_t thefloor; INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + boolean hovermode = (actor->health > 1 || actor->fuse); + if (LUA_CallAction("A_CrawlaCommanderThink", actor)) return; -#endif if (actor->z >= actor->waterbottom && actor->watertop > actor->floorz && actor->z > actor->watertop - FixedMul(256*FRACUNIT, actor->scale)) @@ -5341,10 +5682,16 @@ void A_CrawlaCommanderThink(mobj_t *actor) else thefloor = actor->floorz; - if (actor->fuse & 1) - actor->drawflags |= MFD_DONTDRAW; - else - actor->drawflags &= ~MFD_DONTDRAW; + if (!actor->fuse && actor->flags2 & MF2_FRET) + { + if (actor->info->painsound) + S_StartSound(actor, actor->info->painsound); + + actor->fuse = TICRATE/2; + actor->momz = 0; + + P_InstaThrust(actor, actor->angle-ANGLE_180, FixedMul(5*FRACUNIT, actor->scale)); + } if (actor->reactiontime > 0) actor->reactiontime--; @@ -5356,7 +5703,7 @@ void A_CrawlaCommanderThink(mobj_t *actor) } // Hover mode - if (actor->health > 1 || actor->fuse) + if (hovermode) { if (actor->z < thefloor + FixedMul(16*FRACUNIT, actor->scale)) actor->momz += FixedMul(FRACUNIT, actor->scale); @@ -5366,7 +5713,7 @@ void A_CrawlaCommanderThink(mobj_t *actor) actor->momz += FixedMul(16, actor->scale); } - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + if (!actor->target) { // look for a new target if (P_LookForPlayers(actor, true, false, 0)) @@ -5379,18 +5726,6 @@ void A_CrawlaCommanderThink(mobj_t *actor) dist = P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y); - if (actor->target->player && actor->health > 1) - { - if (dist < FixedMul(128*FRACUNIT, actor->scale) - && ((actor->target->player->pflags & PF_JUMPED) || (actor->target->player->pflags & PF_SPINNING))) - { - // Auugh! He's trying to kill you! Strafe! STRAAAAFFEEE!! - if (actor->target->momx || actor->target->momy) - P_InstaThrust(actor, actor->angle - ANGLE_180, FixedMul(20*FRACUNIT, actor->scale)); - return; - } - } - if (locvar1) { if (actor->health < 2 && P_RandomChance(FRACUNIT/128)) @@ -5411,29 +5746,44 @@ void A_CrawlaCommanderThink(mobj_t *actor) actor->angle += (P_RandomByte()<<10); actor->angle -= (P_RandomByte()<<10); - if (actor->health > 1) - P_InstaThrust(actor, actor->angle, FixedMul(10*FRACUNIT, actor->scale)); + if (hovermode) + { + fixed_t mom; + P_Thrust(actor, actor->angle, 2*actor->scale); + mom = P_AproxDistance(actor->momx, actor->momy); + if (mom > 20*actor->scale) + { + mom += 20*actor->scale; + mom >>= 1; + P_InstaThrust(actor, R_PointToAngle2(0, 0, actor->momx, actor->momy), mom); + } + } } else if (!actor->reactiontime) { - if (actor->health > 1) // Hover Mode + if (hovermode && !(actor->flags2 & MF2_FRET)) // Hover Mode { if (dist < FixedMul(512*FRACUNIT, actor->scale)) { actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); - P_InstaThrust(actor, actor->angle, FixedMul(60*FRACUNIT, actor->scale)); + P_InstaThrust(actor, actor->angle, FixedMul(40*FRACUNIT, actor->scale)); actor->threshold = 1; + if (actor->info->attacksound) + S_StartSound(actor, actor->info->attacksound); } } - actor->reactiontime = 2*TICRATE + P_RandomByte()/2; + actor->reactiontime = 3*TICRATE + (P_RandomByte()>>2); } if (actor->health == 1) P_Thrust(actor, actor->angle, 1); // Pogo Mode - if (!actor->fuse && actor->health == 1 && actor->z <= actor->floorz) + if (!hovermode && actor->z <= actor->floorz) { + if (actor->info->activesound) + S_StartSound(actor, actor->info->activesound); + if (dist < FixedMul(256*FRACUNIT, actor->scale)) { actor->momz = FixedMul(locvar2, actor->scale); @@ -5469,19 +5819,18 @@ void A_RingExplode(mobj_t *actor) mobj_t *mo2; thinker_t *th; angle_t d; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_RingExplode", actor)) return; -#endif for (d = 0; d < 16; d++) P_SpawnParaloop(actor->x, actor->y, actor->z + actor->height, FixedMul(actor->info->painchance, actor->scale), 16, MT_NIGHTSPARKLE, S_NULL, d*(ANGLE_22h), true); S_StartSound(actor, sfx_prloop); - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -5495,7 +5844,7 @@ void A_RingExplode(mobj_t *actor) if (mo2->flags & MF_SHOOTABLE) { actor->flags2 |= MF2_DEBRIS; - P_DamageMobj(mo2, actor, actor->target, 1); + P_DamageMobj(mo2, actor, actor->target, 1, DMG_NORMAL); continue; } } @@ -5514,12 +5863,10 @@ void A_OldRingExplode(mobj_t *actor) { mobj_t *mo; const fixed_t ns = FixedMul(20 * FRACUNIT, actor->scale); INT32 locvar1 = var1; - //INT32 locvar2 = var2; boolean changecolor = (actor->target && actor->target->player); -#ifdef HAVE_BLUA + if (LUA_CallAction("A_OldRingExplode", actor)) return; -#endif for (i = 0; i < 32; i++) { @@ -5544,7 +5891,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; @@ -5560,7 +5907,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; @@ -5575,7 +5922,7 @@ void A_OldRingExplode(mobj_t *actor) { if (changecolor) { - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMS)) mo->color = actor->target->color; //copy color else if (actor->target->player->ctfteam == 2) mo->color = skincolor_bluering; @@ -5593,20 +5940,19 @@ void A_MixUp(mobj_t *actor) { boolean teleported[MAXPLAYERS]; INT32 i, numplayers = 0, prandom = 0; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_MixUp", actor)) return; -#else - (void)actor; -#endif if (!multiplayer) return; - // No mix-up monitors in hide and seek or time only race. // The random factor is okay for other game modes, but in these, it is cripplingly unfair. - if (gametype == GT_HIDEANDSEEK || gametype == GT_RACE) + if (gametyperules & GTR_CIRCUIT) + { + S_StartSound(actor, sfx_lose); return; + } numplayers = 0; memset(teleported, 0, sizeof (teleported)); @@ -5614,8 +5960,7 @@ void A_MixUp(mobj_t *actor) // Count the number of players in the game // and grab their xyz coords for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !players[i].powers[pw_super]) + if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE && !players[i].exiting) { if ((netgame || multiplayer) && players[i].spectator) // Ignore spectators continue; @@ -5624,17 +5969,20 @@ void A_MixUp(mobj_t *actor) } if (numplayers <= 1) // Not enough players to mix up. + { + S_StartSound(actor, sfx_lose); return; + } else if (numplayers == 2) // Special case -- simple swap { fixed_t x, y, z; - angle_t angle; + angle_t angle, drawangle; INT32 one = -1, two = 0; // default value 0 to make the compiler shut up // Zoom tube stuff mobj_t *tempthing = NULL; //tracer - pflags_t flags1,flags2; //player pflags - INT32 transspeed; //player speed + UINT16 carry1,carry2; //carry + INT32 transspeed; //player speed // Starpost stuff fixed_t starpostx, starposty, starpostz; @@ -5669,13 +6017,14 @@ void A_MixUp(mobj_t *actor) players[two].speed = transspeed; //set flags variables now but DON'T set them. - flags1 = (players[one].pflags & (PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG)); - flags2 = (players[two].pflags & (PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG)); + carry1 = players[one].powers[pw_carry]; + carry2 = players[two].powers[pw_carry]; x = players[one].mo->x; y = players[one].mo->y; z = players[one].mo->z; angle = players[one].mo->angle; + drawangle = players[one].drawangle; starpostx = players[one].respawn.pointx; starposty = players[one].respawn.pointy; @@ -5687,18 +6036,16 @@ void A_MixUp(mobj_t *actor) P_MixUp(players[one].mo, players[two].mo->x, players[two].mo->y, players[two].mo->z, players[two].mo->angle, players[two].respawn.pointx, players[two].respawn.pointy, players[two].respawn.pointz, players[two].starpostnum, 0, 0, - players[two].mo->flags2); + FRACUNIT, players[two].drawangle, players[two].mo->flags2); P_MixUp(players[two].mo, x, y, z, angle, starpostx, starposty, starpostz, starpostnum, 0, 0, - mflags2); + FRACUNIT, drawangle, mflags2); - //flags set after mixup. Stupid P_ResetPlayer() takes away some of the flags we look for... - //but not all of them! So we need to make sure they aren't set wrong or anything. - players[one].pflags &= ~(PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG); - players[one].pflags |= flags2; - players[two].pflags &= ~(PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG); - players[two].pflags |= flags1; + //carry set after mixup. Stupid P_ResetPlayer() takes away some of the stuff we look for... + //but not all of it! So we need to make sure they aren't set wrong or anything. + players[one].powers[pw_carry] = carry2; + players[two].powers[pw_carry] = carry1; teleported[one] = true; teleported[two] = true; @@ -5706,12 +6053,13 @@ void A_MixUp(mobj_t *actor) else { fixed_t position[MAXPLAYERS][3]; - angle_t anglepos[MAXPLAYERS]; + angle_t anglepos[MAXPLAYERS][2]; INT32 pindex[MAXPLAYERS], counter = 0, teleportfrom = 0; // Zoom tube stuff - mobj_t *transtracer[MAXPLAYERS]; //tracer - pflags_t transflag[MAXPLAYERS]; //player pflags + mobj_t *transtracer[MAXPLAYERS]; //tracer + //pflags_t transflag[MAXPLAYERS]; //cyan pink white pink cyan + UINT16 transcarry[MAXPLAYERS]; //player carry INT32 transspeed[MAXPLAYERS]; //player speed // Star post stuff @@ -5722,14 +6070,14 @@ void A_MixUp(mobj_t *actor) for (i = 0; i < MAXPLAYERS; i++) { - position[i][0] = position[i][1] = position[i][2] = anglepos[i] = pindex[i] = -1; + position[i][0] = position[i][1] = position[i][2] = anglepos[i][0] = anglepos[i][1] = pindex[i] = -1; teleported[i] = false; } for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]) + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting) { if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators continue; @@ -5738,12 +6086,13 @@ void A_MixUp(mobj_t *actor) position[counter][1] = players[i].mo->y; position[counter][2] = players[i].mo->z; pindex[counter] = i; - anglepos[counter] = players[i].mo->angle; + anglepos[counter][0] = players[i].mo->angle; + anglepos[counter][1] = players[i].drawangle; players[i].mo->momx = players[i].mo->momy = players[i].mo->momz = players[i].rmomx = players[i].rmomy = 1; players[i].cmomx = players[i].cmomy = 0; - transflag[counter] = (players[i].pflags & (PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG)); + transcarry[counter] = players[i].powers[pw_carry]; transspeed[counter] = players[i].speed; transtracer[counter] = players[i].mo->tracer; @@ -5777,7 +6126,7 @@ void A_MixUp(mobj_t *actor) for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]) + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting) { if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators continue; @@ -5788,14 +6137,13 @@ void A_MixUp(mobj_t *actor) players[i].speed = transspeed[teleportfrom]; P_SetTarget(&players[i].mo->tracer, transtracer[teleportfrom]); - P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom], + P_MixUp(players[i].mo, position[teleportfrom][0], position[teleportfrom][1], position[teleportfrom][2], anglepos[teleportfrom][0], spposition[teleportfrom][0], spposition[teleportfrom][1], spposition[teleportfrom][2], starpostnum[teleportfrom], 0, 0, - flags2[teleportfrom]); + FRACUNIT, anglepos[teleportfrom][1], flags2[teleportfrom]); - //...flags after. same reasoning. - players[i].pflags &= ~(PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG); - players[i].pflags |= transflag[teleportfrom]; + //...carry after. same reasoning. + players[i].powers[pw_carry] = transcarry[teleportfrom]; teleported[i] = true; counter++; @@ -5808,20 +6156,15 @@ void A_MixUp(mobj_t *actor) if (teleported[i]) { if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo && players[i].mo->health > 0 && !players[i].exiting && !players[i].powers[pw_super]) + && players[i].mo && players[i].mo->health > 0 && !players[i].exiting) { if ((netgame || multiplayer) && players[i].spectator)// Ignore spectators continue; P_SetThingPosition(players[i].mo); -#ifdef ESLOPE players[i].mo->floorz = P_GetFloorZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL); players[i].mo->ceilingz = P_GetCeilingZ(players[i].mo, players[i].mo->subsector->sector, players[i].mo->x, players[i].mo->y, NULL); -#else - players[i].mo->floorz = players[i].mo->subsector->sector->floorheight; - players[i].mo->ceilingz = players[i].mo->subsector->sector->ceilingheight; -#endif P_CheckPosition(players[i].mo, players[i].mo->x, players[i].mo->y); } @@ -5832,143 +6175,6 @@ void A_MixUp(mobj_t *actor) S_StartSound(NULL, sfx_mixup); } -// Function: A_RecyclePowers -// -// Description: Take all player's powers, and swap 'em. -// -// var1 = unused -// var2 = unused -// -void A_RecyclePowers(mobj_t *actor) -{ - INT32 i, j, k, numplayers = 0; - -#ifdef WEIGHTEDRECYCLER - UINT8 beneficiary = 255; -#endif - UINT8 playerslist[MAXPLAYERS]; - UINT8 postscramble[MAXPLAYERS]; - - UINT16 powers[MAXPLAYERS][NUMPOWERS]; - INT32 weapons[MAXPLAYERS]; - INT32 weaponheld[MAXPLAYERS]; - -#ifdef HAVE_BLUA - if (LUA_CallAction("A_RecyclePowers", actor)) - return; -#endif - -#if !defined(WEIGHTEDRECYCLER) && !defined(HAVE_BLUA) - // actor is used in all scenarios but this one, funny enough - (void)actor; -#endif - - if (!multiplayer) - return; - - numplayers = 0; - - // Count the number of players in the game - for (i = 0, j = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE - && !players[i].exiting && !((netgame || multiplayer) && players[i].spectator)) - { -#ifndef WEIGHTEDRECYCLER - if (players[i].powers[pw_super]) - continue; // Ignore super players -#endif - - numplayers++; - postscramble[j] = playerslist[j] = (UINT8)i; - -#ifdef WEIGHTEDRECYCLER - // The guy who started the recycle gets the best result - if (actor && actor->target && actor->target->player && &players[i] == actor->target->player) - beneficiary = (UINT8)i; -#endif - - // Save powers - for (k = 0; k < NUMPOWERS; k++) - powers[i][k] = players[i].powers[k]; - //1.1: ring weapons too - weapons[i] = players[i].ringweapons; - weaponheld[i] = players[i].currentweapon; - - j++; - } - } - - if (numplayers <= 1) - return; //nobody to touch! - - //shuffle the post scramble list, whee! - // hardcoded 0-1 to 1-0 for two players - if (numplayers == 2) - { - postscramble[0] = playerslist[1]; - postscramble[1] = playerslist[0]; - } - else - for (j = 0; j < numplayers; j++) - { - UINT8 tempint; - - i = j + ((P_RandomByte() + leveltime) % (numplayers - j)); - tempint = postscramble[j]; - postscramble[j] = postscramble[i]; - postscramble[i] = tempint; - } - -#ifdef WEIGHTEDRECYCLER - //the joys of qsort... - if (beneficiary != 255) { - qsort(playerslist, numplayers, sizeof(UINT8), P_RecycleCompare); - - // now, make sure the benificiary is in the best slot - // swap out whatever poor sap was going to get the best items - for (i = 0; i < numplayers; i++) - { - if (postscramble[i] == beneficiary) - { - postscramble[i] = postscramble[0]; - postscramble[0] = beneficiary; - break; - } - } - } -#endif - - // now assign! - for (i = 0; i < numplayers; i++) - { - UINT8 send_pl = playerslist[i]; - UINT8 recv_pl = postscramble[i]; - - // debugF - CONS_Debug(DBG_GAMELOGIC, "sending player %hu's items to %hu\n", (UINT16)send_pl, (UINT16)recv_pl); - - for (j = 0; j < NUMPOWERS; j++) - { - if (j == pw_flashing || j == pw_underwater || j == pw_spacetime - || j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super) - continue; - players[recv_pl].powers[j] = powers[send_pl][j]; - } - - //1.1: weapon rings too - players[recv_pl].ringweapons = weapons[send_pl]; - players[recv_pl].currentweapon = weaponheld[send_pl]; - - P_SpawnShieldOrb(&players[recv_pl]); - if (P_IsLocalPlayer(&players[recv_pl])) - P_RestoreMusic(&players[recv_pl]); - P_FlashPal(&players[recv_pl], PAL_RECYCLE, 10); - } - - S_StartSound(NULL, sfx_gravch); //heh, the sound effect I used is already in -} - // Function: A_Boss1Chase // // Description: Like A_Chase, but for Boss 1. @@ -5979,10 +6185,9 @@ void A_RecyclePowers(mobj_t *actor) void A_Boss1Chase(mobj_t *actor) { INT32 delta; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss1Chase", actor)) return; -#endif if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { @@ -6034,7 +6239,10 @@ void A_Boss1Chase(mobj_t *actor) } else { - P_LinedefExecute(LE_PINCHPHASE, actor, NULL); + if (actor->spawnpoint && actor->spawnpoint->extrainfo) + P_LinedefExecute(LE_PINCHPHASE+(actor->spawnpoint->extrainfo*LE_PARAMWIDTH), actor, NULL); + else + P_LinedefExecute(LE_PINCHPHASE, actor, NULL); P_SetMobjState(actor, actor->info->raisestate); } @@ -6100,10 +6308,9 @@ void A_Boss2Chase(mobj_t *actor) fixed_t radius; boolean reverse = false; INT32 speedvar; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss2Chase", actor)) return; -#endif if (actor->health <= 0) return; @@ -6228,10 +6435,9 @@ void A_Boss2Chase(mobj_t *actor) // void A_Boss2Pogo(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_Boss2Pogo", actor)) return; -#endif + if (actor->z <= actor->floorz + FixedMul(8*FRACUNIT, actor->scale) && actor->momz <= 0) { if (actor->state != &states[actor->info->raisestate]) @@ -6276,10 +6482,10 @@ void A_Boss2Pogo(mobj_t *actor) void A_Boss2TakeDamage(mobj_t *actor) { INT32 locvar1 = var1; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss2TakeDamage", actor)) return; -#endif + A_Pain(actor); actor->reactiontime = 1; // turn around if (locvar1 == 0) // old A_Invincibilerize behavior @@ -6299,10 +6505,9 @@ void A_Boss7Chase(mobj_t *actor) { INT32 delta; INT32 i; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss7Chase", actor)) return; -#endif if (actor->z != actor->floorz) return; @@ -6359,17 +6564,6 @@ void A_Boss7Chase(mobj_t *actor) } } - if (actor->health <= actor->info->damage - && actor->target - && actor->target->player - && (actor->target->player->pflags & PF_ITEMHANG)) - { - A_FaceTarget(actor); - P_SetMobjState(actor, S_BLACKEGG_SHOOT1); - actor->movecount = TICRATE + P_RandomByte()/2; - return; - } - if (actor->reactiontime) actor->reactiontime--; @@ -6431,10 +6625,9 @@ void A_Boss7Chase(mobj_t *actor) // void A_GoopSplat(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_GoopSplat", actor)) return; -#endif + P_UnsetThingPosition(actor); if (sector_list) { @@ -6456,10 +6649,9 @@ void A_Boss2PogoSFX(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Boss2PogoSFX", actor)) return; -#endif if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { @@ -6500,10 +6692,8 @@ void A_Boss2PogoTarget(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_Boss2PogoTarget", actor)) return; -#endif if (!actor->target || !(actor->target->flags & MF_SHOOTABLE) || (actor->target->player && actor->target->player->powers[pw_flashing]) || P_AproxDistance(actor->x-actor->target->x, actor->y-actor->target->y) >= FixedMul(512*FRACUNIT, actor->scale)) @@ -6551,7 +6741,7 @@ void A_Boss2PogoTarget(mobj_t *actor) // Remember, kids! // Reduced down Calculus lets you avoid bad 'logic math' loops! //airtime = FixedDiv(-actor->momz<<1, gravityadd)<<1; // going from 0 to 0 is much simpler - zoffs = (P_GetPlayerHeight(actor->target->player)>>1) + (actor->target->floorz - actor->floorz); // offset by the difference in floor height plus half the player height, + zoffs = (actor->target->height>>1) + (actor->target->floorz - actor->floorz); // offset by the difference in floor height plus half the player height, airtime = FixedDiv((-actor->momz - FixedSqrt(FixedMul(actor->momz,actor->momz)+zoffs)), gravityadd)<<1; // to try and land on their head rather than on their feet actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); @@ -6572,7 +6762,7 @@ void A_Boss2PogoTarget(mobj_t *actor) if (actor->info->missilestate) // spawn the pogo stick collision box { mobj_t *pogo = P_SpawnMobj(actor->x, actor->y, actor->z - mobjinfo[actor->info->missilestate].height, (mobjtype_t)actor->info->missilestate); - pogo->target = actor; + P_SetTarget(&pogo->target, actor); } actor->reactiontime = 1; @@ -6587,17 +6777,16 @@ void A_Boss2PogoTarget(mobj_t *actor) // void A_EggmanBox(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_EggmanBox", actor)) return; -#endif + if (!actor->target || !actor->target->player) { CONS_Debug(DBG_GAMELOGIC, "Powerup has no target.\n"); return; } - P_DamageMobj(actor->target, actor, actor, 1); // Ow! + P_DamageMobj(actor->target, actor, actor, 1, DMG_NORMAL); // Ow! } // Function: A_TurretFire @@ -6613,10 +6802,9 @@ void A_TurretFire(mobj_t *actor) fixed_t dist; INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_TurretFire", actor)) return; -#endif if (locvar2) dist = FixedMul(locvar2*FRACUNIT, actor->scale); @@ -6652,10 +6840,9 @@ void A_SuperTurretFire(mobj_t *actor) fixed_t dist; INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SuperTurretFire", actor)) return; -#endif if (locvar2) dist = FixedMul(locvar2*FRACUNIT, actor->scale); @@ -6689,10 +6876,9 @@ void A_SuperTurretFire(mobj_t *actor) void A_TurretStop(mobj_t *actor) { INT32 locvar1 = var1; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_TurretStop", actor)) return; -#endif actor->flags2 &= ~MF2_FIRING; actor->flags2 &= ~MF2_SUPERFIRE; @@ -6710,10 +6896,8 @@ void A_TurretStop(mobj_t *actor) // void A_SparkFollow(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_SparkFollow", actor)) return; -#endif if ((!actor->target || (actor->target->health <= 0)) || (actor->target->player && !actor->target->player->powers[pw_super])) @@ -6747,10 +6931,10 @@ void A_BuzzFly(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_BuzzFly", actor)) return; -#endif + if (actor->flags2 & MF2_AMBUSH) return; @@ -6846,55 +7030,84 @@ void A_BuzzFly(mobj_t *actor) void A_GuardChase(mobj_t *actor) { INT32 delta; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_GuardChase", actor)) return; -#endif if (actor->reactiontime) actor->reactiontime--; - if ((!actor->tracer || !actor->tracer->health) && actor->threshold != 42) + if (actor->threshold != 42) // In formation... { - P_SetTarget(&actor->tracer, NULL); - actor->threshold = 42; - P_SetMobjState(actor, actor->info->painstate); - actor->flags |= MF_SPECIAL|MF_SHOOTABLE; - return; + fixed_t speed; + + if (!actor->tracer || !actor->tracer->health) + { + P_SetTarget(&actor->tracer, NULL); + actor->threshold = 42; + P_SetMobjState(actor, actor->info->painstate); + actor->flags |= MF_SPECIAL|MF_SHOOTABLE; + return; + } + + speed = actor->extravalue1*actor->scale; + + if (actor->flags2 & MF2_AMBUSH) + speed <<= 1; + + if (speed + && !P_TryMove(actor, + actor->x + P_ReturnThrustX(actor, actor->angle, speed), + actor->y + P_ReturnThrustY(actor, actor->angle, speed), + false) + && speed > 0) // can't be the same check as previous so that P_TryMove gets to happen. + { + if (actor->spawnpoint && ((actor->spawnpoint->options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_OBJECTSPECIAL)) + actor->angle += ANGLE_90; + else if (actor->spawnpoint && ((actor->spawnpoint->options & (MTF_EXTRA|MTF_OBJECTSPECIAL)) == MTF_EXTRA)) + actor->angle -= ANGLE_90; + else + actor->angle += ANGLE_180; + } + + if (actor->extravalue1 < actor->info->speed) + actor->extravalue1++; } - - // turn towards movement direction if not there yet - if (actor->movedir < NUMDIRS) + else // Break ranks! { - actor->angle &= (7<<29); - delta = actor->angle - (actor->movedir << 29); + // turn towards movement direction if not there yet + if (actor->movedir < NUMDIRS) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); - if (delta > 0) - actor->angle -= ANGLE_45; - else if (delta < 0) - actor->angle += ANGLE_45; - } + if (delta > 0) + actor->angle -= ANGLE_45; + else if (delta < 0) + actor->angle += ANGLE_45; + } - if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_LookForPlayers(actor, true, false, 0)) + if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) + { + // look for a new target + if (P_LookForPlayers(actor, true, false, 0)) + return; // got a new target + + P_SetMobjStateNF(actor, actor->info->spawnstate); + return; + } + + // possibly choose another target + if (multiplayer && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) + && P_LookForPlayers(actor, true, false, 0)) return; // got a new target - P_SetMobjStateNF(actor, actor->info->spawnstate); - return; - } - - // possibly choose another target - if (multiplayer && (actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) - && P_LookForPlayers(actor, true, false, 0)) - return; // got a new target - - // chase towards player - if (--actor->movecount < 0 || !P_Move(actor, (actor->flags2 & MF2_AMBUSH) ? actor->info->speed * 2 : actor->info->speed)) - { - P_NewChaseDir(actor); - actor->movecount += 5; // Increase tics before change in direction allowed. + // chase towards player + if (--actor->movecount < 0 || !P_Move(actor, (actor->flags2 & MF2_AMBUSH) ? actor->info->speed * 2 : actor->info->speed)) + { + P_NewChaseDir(actor); + actor->movecount += 5; // Increase tics before change in direction allowed. + } } // Now that we've moved, its time for our shield to move! @@ -6922,10 +7135,9 @@ void A_EggShield(mobj_t *actor) fixed_t newx, newy; fixed_t movex, movey; angle_t angle; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_EggShield", actor)) return; -#endif if (!actor->target || !actor->target->health) { @@ -7006,10 +7218,9 @@ void A_EggShield(mobj_t *actor) // void A_SetReactionTime(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_SetReactionTime", actor)) return; -#endif + if (var1) actor->reactiontime = var2; else @@ -7029,10 +7240,8 @@ void A_Boss1Spikeballs(mobj_t *actor) INT32 locvar2 = var2; mobj_t *ball; -#ifdef HAVE_BLUA if (LUA_CallAction("A_Boss1Spikeballs", actor)) return; -#endif ball = P_SpawnMobj(actor->x, actor->y, actor->z, MT_EGGMOBILE_BALL); P_SetTarget(&ball->target, actor); @@ -7053,14 +7262,15 @@ void A_Boss1Spikeballs(mobj_t *actor) // void A_Boss3TakeDamage(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_Boss3TakeDamage", actor)) return; -#endif - actor->movecount = var1; - if (actor->target && actor->target->spawnpoint) - actor->threshold = actor->target->spawnpoint->extrainfo; + actor->movecount = var1; + actor->movefactor = -512*FRACUNIT; + + /*if (actor->target && actor->target->spawnpoint) + actor->threshold = actor->target->spawnpoint->extrainfo;*/ + } // Function: A_Boss3Path @@ -7072,10 +7282,8 @@ void A_Boss3TakeDamage(mobj_t *actor) // void A_Boss3Path(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_Boss3Path", actor)) return; -#endif if (actor->tracer && actor->tracer->health && actor->tracer->movecount) actor->movecount |= 1; @@ -7097,24 +7305,34 @@ void A_Boss3Path(mobj_t *actor) } else if (actor->threshold >= 0) // Traveling mode { - thinker_t *th; - mobj_t *mo2; - fixed_t dist, dist2; + fixed_t dist = 0; fixed_t speed; - P_SetTarget(&actor->target, NULL); - - // scan the thinkers - // to find a point that matches - // the number - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (!(actor->flags2 & MF2_STRONGBOX)) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; + thinker_t *th; + mobj_t *mo2; - mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == actor->threshold) + P_SetTarget(&actor->target, NULL); + + // scan the thinkers + // to find a point that matches + // the number + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + if (mo2->type != MT_BOSS3WAYPOINT) + continue; + if (!mo2->spawnpoint) + continue; + if (mo2->spawnpoint->angle != actor->threshold) + continue; + if (mo2->spawnpoint->extrainfo != actor->cusval) + continue; + P_SetTarget(&actor->target, mo2); break; } @@ -7122,67 +7340,111 @@ void A_Boss3Path(mobj_t *actor) if (!actor->target) // Should NEVER happen { - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d\n", actor->threshold); + CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy was unable to find specified waypoint: %d, %d\n", actor->threshold, actor->cusval); return; } - dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z - actor->z); - - if (dist < 1) - dist = 1; - if (actor->tracer && ((actor->tracer->movedir) || (actor->tracer->health <= actor->tracer->info->damage))) speed = actor->info->speed * 2; else speed = actor->info->speed; - actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed); - actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed); - actor->momz = FixedMul(FixedDiv(actor->target->z - actor->z, dist), speed); + if (actor->target->x == actor->x && actor->target->y == actor->y) + { + dist = P_AproxDistance(P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y), actor->target->z + actor->movefactor - actor->z); - if (actor->momx != 0 || actor->momy != 0) - actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + if (dist < 1) + dist = 1; - dist2 = P_AproxDistance(P_AproxDistance(actor->target->x - (actor->x + actor->momx), actor->target->y - (actor->y + actor->momy)), actor->target->z - (actor->z + actor->momz)); + actor->momx = FixedMul(FixedDiv(actor->target->x - actor->x, dist), speed); + actor->momy = FixedMul(FixedDiv(actor->target->y - actor->y, dist), speed); + actor->momz = FixedMul(FixedDiv(actor->target->z + actor->movefactor - actor->z, dist), speed); - if (dist2 < 1) - dist2 = 1; + if (actor->momx != 0 || actor->momy != 0) + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); + } - if ((dist >> FRACBITS) <= (dist2 >> FRACBITS)) + if (dist <= speed) { // If further away, set XYZ of mobj to waypoint location P_UnsetThingPosition(actor); actor->x = actor->target->x; actor->y = actor->target->y; - actor->z = actor->target->z; + actor->z = actor->target->z + actor->movefactor; actor->momx = actor->momy = actor->momz = 0; P_SetThingPosition(actor); - if (actor->threshold == 0) + if (!actor->movefactor) // firing mode + { + actor->movecount |= 2; + actor->movefactor = -512*FRACUNIT; + actor->flags2 &= ~MF2_STRONGBOX; + } + else if (!(actor->flags2 & MF2_STRONGBOX)) // just spawned or going down + { + actor->flags2 |= MF2_STRONGBOX; + actor->movefactor = -512*FRACUNIT; + } + else if (!(actor->flags2 & MF2_AMBUSH)) // just shifted tube + { + actor->flags2 |= MF2_AMBUSH; + actor->movefactor = 0; + } + else // just hit the bottom of your tube { P_RemoveMobj(actor); // Cycle completed. Dummy removed. return; } + } + } +} - // Set to next waypoint in sequence - if (actor->target->spawnpoint) - { - // From the center point, choose one of the five paths - if (actor->target->spawnpoint->angle == 0) - { - P_RemoveMobj(actor); // Cycle completed. Dummy removed. - return; - } - else - actor->threshold = actor->target->spawnpoint->extrainfo; +// Function: A_Boss3ShockThink +// +// Description: Inserts new interstitial shockwave objects when the space between others spreads too much. +// +// var1 = unused +// var2 = unused +// +void A_Boss3ShockThink(mobj_t *actor) +{ + if (LUA_CallAction("A_Boss3ShockThink", actor)) + return; - // If the deaf flag is set, go into firing mode - if (actor->target->spawnpoint->options & MTF_AMBUSH) - actor->movecount |= 2; - } - else // This should never happen, as well - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 Dummy waypoint has no spawnpoint associated with it.\n"); + if (actor->momx || actor->momy) + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy) + ANGLE_90; + + if (actor->hnext && !P_MobjWasRemoved(actor->hnext)) + { + mobj_t *snext = actor->hnext; + mobj_t *snew; + fixed_t x0, y0, x1, y1; + + // Break the link if movements are too different + if (FixedHypot(snext->momx - actor->momx, snext->momy - actor->momy) > 12*actor->scale) + { + P_SetTarget(&actor->hnext, NULL); + return; + } + + // Check distance between shockwave objects to determine whether interstitial ones should be spawned + x0 = actor->x; + y0 = actor->y; + x1 = snext->x; + y1 = snext->y; + if (FixedHypot(x1 - x0, y1 - y0) > 2*actor->radius) + { + snew = P_SpawnMobj((x0 + x1) >> 1, (y0 + y1) >> 1, (actor->z + snext->z) >> 1, actor->type); + snew->momx = (actor->momx + snext->momx) >> 1; + snew->momy = (actor->momy + snext->momy) >> 1; + snew->momz = (actor->momz + snext->momz) >> 1; // is this really needed? + snew->angle = (actor->angle + snext->angle) >> 1; + P_SetTarget(&snew->target, actor->target); + snew->fuse = actor->fuse; + + P_SetTarget(&actor->hnext, snew); + P_SetTarget(&snew->hnext, snext); } } } @@ -7199,16 +7461,17 @@ void A_LinedefExecute(mobj_t *actor) INT32 tagnum; INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_LinedefExecute", actor)) return; -#endif tagnum = locvar1; // state numbers option is no more, custom states cannot be guaranteed to stay the same number anymore, now that they can be defined by names instead if (locvar2) tagnum += locvar2*(AngleFixed(actor->angle)>>FRACBITS); + else if (actor->spawnpoint && actor->spawnpoint->extrainfo) + tagnum += (actor->spawnpoint->extrainfo*LE_PARAMWIDTH); CONS_Debug(DBG_GAMELOGIC, "A_LinedefExecute: Running mobjtype %d's sector with tag %d\n", actor->type, tagnum); @@ -7225,10 +7488,9 @@ void A_LinedefExecute(mobj_t *actor) // void A_PlaySeeSound(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_PlaySeeSound", actor)) return; -#endif + if (actor->info->seesound) S_StartScreamSound(actor, actor->info->seesound); } @@ -7242,10 +7504,9 @@ void A_PlaySeeSound(mobj_t *actor) // void A_PlayAttackSound(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_PlayAttackSound", actor)) return; -#endif + if (actor->info->attacksound) S_StartAttackSound(actor, actor->info->attacksound); } @@ -7259,10 +7520,9 @@ void A_PlayAttackSound(mobj_t *actor) // void A_PlayActiveSound(mobj_t *actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_PlayActiveSound", actor)) return; -#endif + if (actor->info->activesound) S_StartSound(actor, actor->info->activesound); } @@ -7278,10 +7538,9 @@ void A_SmokeTrailer(mobj_t *actor) { mobj_t *th; INT32 locvar1 = var1; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SmokeTrailer", actor)) return; -#endif if (leveltime % 4) return; @@ -7320,10 +7579,9 @@ void A_SpawnObjectAbsolute(mobj_t *actor) mobj_t *mo; INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpawnObjectAbsolute", actor)) return; -#endif x = (INT16)(locvar1>>16); y = (INT16)(locvar1&65535); @@ -7357,10 +7615,9 @@ void A_SpawnObjectRelative(mobj_t *actor) mobj_t *mo; INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpawnObjectRelative", actor)) return; -#endif CONS_Debug(DBG_GAMELOGIC, "A_SpawnObjectRelative called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); @@ -7380,6 +7637,7 @@ void A_SpawnObjectRelative(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) mo->flags2 |= MF2_OBJECTFLIP; + } // Function: A_ChangeAngleRelative @@ -7401,14 +7659,13 @@ void A_ChangeAngleRelative(mobj_t *actor) const fixed_t amax = locvar2*FRACUNIT; //const angle_t amin = FixedAngle(locvar1*FRACUNIT); //const angle_t amax = FixedAngle(locvar2*FRACUNIT); -#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChangeAngleRelative", actor)) return; -#endif #ifdef PARANOIA if (amin > amax) - I_Error("A_ChangeAngleRelative: var1 is greater then var2"); + I_Error("A_ChangeAngleRelative: var1 is greater than var2"); #endif /* if (angle < amin) @@ -7435,14 +7692,13 @@ void A_ChangeAngleAbsolute(mobj_t *actor) const fixed_t amax = locvar2*FRACUNIT; //const angle_t amin = FixedAngle(locvar1*FRACUNIT); //const angle_t amax = FixedAngle(locvar2*FRACUNIT); -#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChangeAngleAbsolute", actor)) return; -#endif #ifdef PARANOIA if (amin > amax) - I_Error("A_ChangeAngleAbsolute: var1 is greater then var2"); + I_Error("A_ChangeAngleAbsolute: var1 is greater than var2"); #endif /* if (angle < amin) @@ -7453,25 +7709,101 @@ void A_ChangeAngleAbsolute(mobj_t *actor) actor->angle = FixedAngle(P_RandomRange(amin, amax)); } +// Function: A_RollAngle +// +// Description: Changes the roll angle. +// +// var1 = angle +// var2 = relative? (default) +// +void A_RollAngle(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + const angle_t angle = FixedAngle(locvar1*FRACUNIT); + + if (LUA_CallAction("A_RollAngle", actor)) + return; + + // relative (default) + if (!locvar2) + actor->rollangle += angle; + // absolute + else + actor->rollangle = angle; +} + +// Function: A_ChangeRollAngleRelative +// +// Description: Changes the roll angle to a random relative value between the min and max. Set min and max to the same value to eliminate randomness +// +// var1 = min +// var2 = max +// +void A_ChangeRollAngleRelative(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + const fixed_t amin = locvar1*FRACUNIT; + const fixed_t amax = locvar2*FRACUNIT; + + if (LUA_CallAction("A_ChangeRollAngleRelative", actor)) + return; + +#ifdef PARANOIA + if (amin > amax) + I_Error("A_ChangeRollAngleRelative: var1 is greater than var2"); +#endif + + actor->rollangle += FixedAngle(P_RandomRange(amin, amax)); +} + +// Function: A_ChangeRollAngleAbsolute +// +// Description: Changes the roll angle to a random absolute value between the min and max. Set min and max to the same value to eliminate randomness +// +// var1 = min +// var2 = max +// +void A_ChangeRollAngleAbsolute(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + const fixed_t amin = locvar1*FRACUNIT; + const fixed_t amax = locvar2*FRACUNIT; + + if (LUA_CallAction("A_ChangeRollAngleAbsolute", actor)) + return; + +#ifdef PARANOIA + if (amin > amax) + I_Error("A_ChangeRollAngleAbsolute: var1 is greater than var2"); +#endif + + actor->rollangle = FixedAngle(P_RandomRange(amin, amax)); +} + // Function: A_PlaySound // // Description: Plays a sound // // var1 = sound # to play // var2: -// 0 = Play sound without an origin -// 1 = Play sound using calling object as origin +// lower 16 bits = If 1, play sound using calling object as origin. If 0, play sound without an origin +// upper 16 bits = If 1, do not play sound during preticker. // void A_PlaySound(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_PlaySound", actor)) return; -#endif - S_StartSound(locvar2 ? actor : NULL, locvar1); + if (leveltime < 2 && (locvar2 >> 16)) + return; + + S_StartSound((locvar2 & 65535) ? actor : NULL, locvar1); } // Function: A_FindTarget @@ -7489,17 +7821,16 @@ void A_FindTarget(mobj_t *actor) thinker_t *th; mobj_t *mo2; fixed_t dist1 = 0, dist2 = 0; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_FindTarget", actor)) return; -#endif CONS_Debug(DBG_GAMELOGIC, "A_FindTarget called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -7554,17 +7885,16 @@ void A_FindTracer(mobj_t *actor) thinker_t *th; mobj_t *mo2; fixed_t dist1 = 0, dist2 = 0; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_FindTracer", actor)) return; -#endif CONS_Debug(DBG_GAMELOGIC, "A_FindTracer called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -7615,10 +7945,9 @@ void A_SetTics(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetTics", actor)) return; -#endif if (locvar1) actor->tics = locvar1; @@ -7637,10 +7966,9 @@ void A_SetRandomTics(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetRandomTics", actor)) return; -#endif actor->tics = P_RandomRange(locvar1, locvar2); } @@ -7656,19 +7984,18 @@ void A_ChangeColorRelative(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChangeColorRelative", actor)) return; -#endif if (locvar1) { // Have you ever seen anything so hideous? if (actor->target) - actor->color = (UINT8)(actor->color + actor->target->color); + actor->color = (UINT16)(actor->color + actor->target->color); } else - actor->color = (UINT8)(actor->color + locvar2); + actor->color = (UINT16)(actor->color + locvar2); } // Function: A_ChangeColorAbsolute @@ -7682,10 +8009,9 @@ void A_ChangeColorAbsolute(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_ChangeColorAbsolute", actor)) return; -#endif if (locvar1) { @@ -7693,7 +8019,42 @@ void A_ChangeColorAbsolute(mobj_t *actor) actor->color = actor->target->color; } else - actor->color = (UINT8)locvar2; + actor->color = (UINT16)locvar2; +} + +// Function: A_Dye +// +// Description: Colorizes an object. +// +// var1 = if (var1 != 0), dye your target instead of yourself +// var2 = color value to dye +// +void A_Dye(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + mobj_t *target = ((locvar1 && actor->target) ? actor->target : actor); + UINT16 color = (UINT16)locvar2; + if (LUA_CallAction("A_Dye", actor)) + return; + if (color >= numskincolors) + return; + + // What if it's a player? + if (target->player) + target->player->powers[pw_dye] = color; + + if (!color) + { + target->colorized = false; + target->color = target->player ? target->player->skincolor : SKINCOLOR_NONE; + } + else if (!(target->player)) + { + target->colorized = true; + target->color = color; + } } // Function: A_MoveRelative @@ -7707,10 +8068,9 @@ void A_MoveRelative(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_MoveRelative", actor)) return; -#endif P_Thrust(actor, actor->angle+FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale)); } @@ -7726,10 +8086,9 @@ void A_MoveAbsolute(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_MoveAbsolute", actor)) return; -#endif P_InstaThrust(actor, FixedAngle(locvar1*FRACUNIT), FixedMul(locvar2*FRACUNIT, actor->scale)); } @@ -7745,10 +8104,9 @@ void A_Thrust(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Thrust", actor)) return; -#endif if (!locvar1) CONS_Debug(DBG_GAMELOGIC, "A_Thrust: Var1 not specified!\n"); @@ -7772,10 +8130,9 @@ void A_ZThrust(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_ZThrust", actor)) return; -#endif if (!locvar1) CONS_Debug(DBG_GAMELOGIC, "A_ZThrust: Var1 not specified!\n"); @@ -7807,10 +8164,9 @@ void A_SetTargetsTarget(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; mobj_t *oldtarg = NULL, *newtarg = NULL; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetTargetsTarget", actor)) return; -#endif // actor's target if (locvar1) // or tracer @@ -7852,10 +8208,9 @@ void A_SetObjectFlags(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; boolean unlinkthings = false; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetObjectFlags", actor)) return; -#endif if (locvar2 == 2) locvar1 = actor->flags | locvar1; @@ -7894,10 +8249,9 @@ void A_SetObjectFlags2(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetObjectFlags2", actor)) return; -#endif if (locvar2 == 2) actor->flags2 |= locvar1; @@ -7913,7 +8267,7 @@ void A_SetObjectFlags2(mobj_t *actor) // // var1: // 0 - Triple jet fume pattern -// 1 - Boss 3's propeller +// 1 - Unused (formerly Boss 3's propeller) // 2 - Metal Sonic jet fume // 3 - Boss 4 jet flame // var2 = unused @@ -7922,10 +8276,9 @@ void A_BossJetFume(mobj_t *actor) { mobj_t *filler; INT32 locvar1 = var1; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_BossJetFume", actor)) return; -#endif if (locvar1 == 0) // Boss1 jet fumes { @@ -7973,12 +8326,12 @@ void A_BossJetFume(mobj_t *actor) P_SetTarget(&actor->tracer, filler); } - else if (locvar1 == 1) // Boss 3 propeller + /*else if (locvar1 == 1) // Boss 3 propeller { fixed_t jetx, jety, jetz; - jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale)); - jety = actor->y + P_ReturnThrustY(actor, actor->angle, -FixedMul(60*FRACUNIT, actor->scale)); + jetx = actor->x + P_ReturnThrustX(actor, actor->angle, -60*actor->scale); + jety = actor->y + P_ReturnThrustY(actor, actor->angle, -60*actor->scale); if (actor->eflags & MFE_VERTICALFLIP) jetz = actor->z + actor->height - FixedMul(17*FRACUNIT + mobjinfo[MT_PROPELLER].height, actor->scale); else @@ -7993,17 +8346,18 @@ void A_BossJetFume(mobj_t *actor) filler->angle = actor->angle - ANGLE_180; P_SetTarget(&actor->tracer, filler); - } + }*/ else if (locvar1 == 2) // Metal Sonic jet fumes { filler = P_SpawnMobj(actor->x, actor->y, actor->z, MT_JETFUME1); P_SetTarget(&filler->target, actor); filler->fuse = 59; P_SetTarget(&actor->tracer, filler); - filler->destscale = actor->scale/2; - P_SetScale(filler, filler->destscale); + P_SetScale(filler, (filler->destscale = actor->scale/3)); if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; + filler->color = SKINCOLOR_CYAN; + filler->colorized = true; } else if (locvar1 == 3) // Boss 4 jet flame { @@ -8011,7 +8365,7 @@ void A_BossJetFume(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) jetz = actor->z + actor->height + FixedMul(50*FRACUNIT - mobjinfo[MT_JETFLAME].height, actor->scale); else - jetz = actor->z - FixedMul(50*FRACUNIT, actor->scale); + jetz = actor->z - 50*actor->scale; filler = P_SpawnMobj(actor->x, actor->y, jetz, MT_JETFLAME); P_SetTarget(&filler->target, actor); // Boss 4 already uses its tracer for other things @@ -8020,6 +8374,30 @@ void A_BossJetFume(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) filler->flags2 |= MF2_OBJECTFLIP; } + else if (locvar1 == 4) // Boss 4 Spectator Eggrobo jet flame + { + fixed_t jetx, jety, jetz, movefactor = 12; + + jetz = actor->z; + if (actor->eflags & MFE_VERTICALFLIP) + jetz += (actor->height - FixedMul(mobjinfo[MT_EGGROBO1JET].height, actor->scale)); + + while (true) + { + jetx = actor->x + P_ReturnThrustX(actor, actor->angle+ANGLE_90, movefactor*actor->scale) - P_ReturnThrustX(actor, actor->angle, 19*actor->scale); + jety = actor->y + P_ReturnThrustY(actor, actor->angle+ANGLE_90, movefactor*actor->scale) - P_ReturnThrustY(actor, actor->angle, 19*actor->scale); + filler = P_SpawnMobj(jetx, jety, jetz, MT_EGGROBO1JET); + filler->movefactor = movefactor; + P_SetTarget(&filler->target, actor); + filler->destscale = actor->scale; + P_SetScale(filler, filler->destscale); + if (actor->eflags & MFE_VERTICALFLIP) + filler->flags2 |= MF2_OBJECTFLIP; + if (movefactor <= 0) + break; + movefactor = -movefactor; + } + } } // Function: A_RandomState @@ -8033,10 +8411,9 @@ void A_RandomState(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_RandomState", actor)) return; -#endif P_SetMobjState(actor, P_RandomChance(FRACUNIT/2) ? locvar1 : locvar2); } @@ -8053,10 +8430,8 @@ void A_RandomStateRange(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_RandomStateRange", actor)) return; -#endif P_SetMobjState(actor, P_RandomRange(locvar1, locvar2)); } @@ -8072,27 +8447,22 @@ void A_DualAction(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_DualAction", actor)) return; -#endif CONS_Debug(DBG_GAMELOGIC, "A_DualAction called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); var1 = states[locvar1].var1; var2 = states[locvar1].var2; -#ifdef HAVE_BLUA astate = &states[locvar1]; -#endif CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling First Action (state %d)...\n", locvar1); states[locvar1].action.acp1(actor); var1 = states[locvar2].var1; var2 = states[locvar2].var2; -#ifdef HAVE_BLUA astate = &states[locvar2]; -#endif CONS_Debug(DBG_GAMELOGIC, "A_DualAction: Calling Second Action (state %d)...\n", locvar2); states[locvar2].action.acp1(actor); @@ -8110,10 +8480,9 @@ void A_RemoteAction(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; mobj_t *originaltarget = actor->target; // Hold on to the target for later. -#ifdef HAVE_BLUA + if (LUA_CallAction("A_RemoteAction", actor)) return; -#endif // If >=0, find the closest target. if (locvar1 >= 0) @@ -8125,9 +8494,9 @@ void A_RemoteAction(mobj_t *actor) fixed_t dist1 = 0, dist2 = 0; // scan the thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -8175,9 +8544,7 @@ void A_RemoteAction(mobj_t *actor) // Steal the var1 and var2 from "locvar2" var1 = states[locvar2].var1; var2 = states[locvar2].var2; -#ifdef HAVE_BLUA astate = &states[locvar2]; -#endif CONS_Debug(DBG_GAMELOGIC, "A_RemoteAction: Calling action on %p\n" "var1 is %d\nvar2 is %d\n", actor->target, var1, var2); @@ -8196,10 +8563,9 @@ void A_RemoteAction(mobj_t *actor) // void A_ToggleFlameJet(mobj_t* actor) { -#ifdef HAVE_BLUA if (LUA_CallAction("A_ToggleFlameJet", actor)) return; -#endif + // threshold - off delay // movecount - on timer @@ -8224,10 +8590,9 @@ void A_ItemPop(mobj_t *actor) { mobj_t *remains; mobjtype_t explode; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_ItemPop", actor)) return; -#endif if (!(actor->target && actor->target->player)) { @@ -8277,12 +8642,12 @@ void A_ItemPop(mobj_t *actor) if (actor->info->deathsound) S_StartSound(remains, actor->info->deathsound); - if (!(G_BattleGametype() && actor->target->player->kartstuff[k_bumper] <= 0)) + if (!((gametyperules & GTR_BUMPERS) && actor->target->player->kartstuff[k_bumper] <= 0)) actor->target->player->kartstuff[k_itemroulette] = 1; remains->flags2 &= ~MF2_AMBUSH; - if (G_BattleGametype() && (actor->threshold != 69 && actor->threshold != 70)) + if ((gametyperules & GTR_BUMPERS) && (actor->threshold != 69 && actor->threshold != 70)) numgotboxes++; P_RemoveMobj(actor); @@ -8295,14 +8660,13 @@ void A_JawzChase(mobj_t *actor) fixed_t thrustamount = 0; fixed_t frictionsafety = (actor->friction == 0) ? 1 : actor->friction; fixed_t topspeed = actor->movefactor; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_JawzChase", actor)) return; -#endif if (actor->tracer) { - /*if (G_RaceGametype()) // Stop looking after first target in race + /*if ((gametyperules & GTR_CIRCUIT)) // Stop looking after first target in race actor->extravalue1 = 1;*/ if (actor->tracer->health) @@ -8312,7 +8676,7 @@ void A_JawzChase(mobj_t *actor) angle_t angledelta = actor->angle - targetangle; boolean turnclockwise = true; - if (G_RaceGametype()) + if ((gametyperules & GTR_CIRCUIT)) { const fixed_t distbarrier = FixedMul(512*mapobjectscale, FRACUNIT + ((gamespeed-1) * (FRACUNIT/4))); const fixed_t distaway = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); @@ -8419,10 +8783,8 @@ void A_JawzExplode(mobj_t *actor) INT32 shrapnel = 2; mobj_t *truc; -#ifdef HAVE_BLUA if (LUA_CallAction("A_JawzExplode", actor)) return; -#endif truc = P_SpawnMobj(actor->x, actor->y, actor->z, MT_BOOMEXPLODE); truc->scale = actor->scale*2; @@ -8574,10 +8936,8 @@ void A_SPBChase(mobj_t *actor) fixed_t pdist = 1536<x, actor->y, actor->z, MT_BALLHOGBOOM); P_SetScale(mo2, actor->scale*2); @@ -8978,10 +9337,10 @@ void A_BallhogExplode(mobj_t *actor) void A_LightningFollowPlayer(mobj_t *actor) { fixed_t sx, sy; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_LightningFollowPlayer", actor)) return; -#endif + if (!actor->target) return; @@ -9007,10 +9366,10 @@ void A_LightningFollowPlayer(mobj_t *actor) void A_FZBoomFlash(mobj_t *actor) { UINT8 i; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_FZBoomFlash", actor)) return; -#endif + for (i = 0; i < MAXPLAYERS; i++) { fixed_t dist; @@ -9030,10 +9389,10 @@ void A_FZBoomSmoke(mobj_t *actor) { INT32 i; INT32 rad = 47+(23*var1); -#ifdef HAVE_BLUA + if (LUA_CallAction("A_FZBoomSmoke", actor)) return; -#endif + for (i = 0; i < 8+(4*var1); i++) { mobj_t *smoke = P_SpawnMobj(actor->x + (P_RandomRange(-rad, rad)*actor->scale), actor->y + (P_RandomRange(-rad, rad)*actor->scale), @@ -9052,10 +9411,9 @@ void A_RandomShadowFrame(mobj_t *actor) { mobj_t *fire; mobj_t *fake; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_RandomShadowFrame", (actor))) return; -#endif if (!actor->extravalue1) // Hack that spawns thoks that look like random shadows. Otherwise the state would overwrite our frame and that's a pain. { @@ -9083,7 +9441,7 @@ void A_RandomShadowFrame(mobj_t *actor) && P_IsObjectOnGround(actor->target) && actor->z == actor->target->z) { - P_DamageMobj(actor->target, actor, actor, 1); + P_DamageMobj(actor->target, actor, actor, 1, DMG_NORMAL); P_InstaThrust(actor->target, actor->angle, 16<target->x, actor->target->y, actor->target->z, MT_THOK); P_SetMobjStateNF(fire, S_QUICKBOOM1); @@ -9101,10 +9459,9 @@ void A_RoamingShadowThinker(mobj_t *actor) { mobj_t *wind; -#ifdef HAVE_BLUA if (LUA_CallAction("A_RoamingShadowThinker", (actor))) return; -#endif + // extravalue1 replaces "movetimer" // extravalue2 replaces "stoptimer" @@ -9129,7 +9486,7 @@ void A_RoamingShadowThinker(mobj_t *actor) { // send them flying and spawn the WIND! P_InstaThrust(actor->target, 0, 0); - P_DamageMobj(actor->target, actor, actor, 1); + P_DamageMobj(actor->target, actor, actor, 1, DMG_NORMAL); P_SetObjectMomZ(actor->target, 16<target, sfx_wind1); @@ -9159,10 +9516,9 @@ void A_MayonakaArrow(mobj_t *actor) { INT32 flip = 0; INT32 iswarning; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_MayonakaArrow", (actor))) return; -#endif iswarning = actor->spawnpoint->options & MTF_OBJECTSPECIAL; // is our object a warning sign? // "animtimer" is replaced by "extravalue1" here. @@ -9201,10 +9557,8 @@ void A_MementosTPParticles(mobj_t *actor) int i = 0; thinker_t *th; -#ifdef HAVE_BLUA if (LUA_CallAction("A_MementosTPParticles", (actor))) return; -#endif for (; i<4; i++) { @@ -9212,16 +9566,16 @@ void A_MementosTPParticles(mobj_t *actor) particle->frame = 0; particle->color = ((i%2) ? (SKINCOLOR_RED) : (SKINCOLOR_BLACK)); particle->destscale = 1; - P_HomingAttack(particle, actor); + //P_HomingAttack(particle, actor); // Really now, Lat... } // Although this is mostly used to spawn particles, we will also save the OTHER teleport inside actor->target. That way teleporting doesn't require a thinker iteration. // Doesn't seem like much given the small amount of mobjs this map has but heh. if (!actor->target) { - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -9252,11 +9606,8 @@ void A_ReaperThinker(mobj_t *actor) player_t *player; // used as a shortcut in a loop. mobj_t *targetplayermo = NULL; // the player mo we can eventually target, or whatever. - -#ifdef HAVE_BLUA if (LUA_CallAction("A_ReaperThinker", (actor))) return; -#endif // We don't have custom variables or whatever so we'll do with whatever the fuck we have left. @@ -9321,9 +9672,9 @@ void A_ReaperThinker(mobj_t *actor) } // We have no target and oughta find one, so let's scan through thinkers for a waypoint of angle 0, or something. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -9381,15 +9732,14 @@ void A_ReaperThinker(mobj_t *actor) // Waypoint behavior. if (actor->target->type == MT_REAPERWAYPOINT) { - if (R_PointToDist2(actor->x, actor->y, actor->target->x, actor->target->y) < 22<target, NULL); // remove target so we can default back to first waypoint if things go ham. // If we reach close to a waypoint, then we should go to the NEXT one. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -9421,23 +9771,6 @@ void A_ReaperThinker(mobj_t *actor) } } -void A_FlameParticle(mobj_t *actor) -{ - fixed_t rad = actor->radius>>FRACBITS, hei = actor->radius>>FRACBITS; - mobj_t *par; -#ifdef HAVE_BLUA - if (LUA_CallAction("A_FlameParticle", actor)) - return; -#endif - - par = P_SpawnMobj( - actor->x + (P_RandomRange(-rad, rad)<y + (P_RandomRange(-rad, rad)<z + (P_RandomRange(hei/2, hei)<info->painchance); - par->momz = actor->scale<<1; -} - void A_FlameShieldPaper(mobj_t *actor) { INT32 framea = 0; @@ -9446,10 +9779,8 @@ void A_FlameShieldPaper(mobj_t *actor) INT32 locvar2 = var2; UINT8 i; -#ifdef HAVE_BLUA if (LUA_CallAction("A_FlameShieldPaper", actor)) return; -#endif framea = (locvar1 & FF_FRAMEMASK); frameb = (locvar2 & FF_FRAMEMASK); @@ -9491,23 +9822,48 @@ void A_FlameShieldPaper(mobj_t *actor) // Description: Used by Chaos Emeralds to orbit around Nights (aka Super Sonic.) // // var1 = Angle adjustment (aka orbit speed) -// var2 = Lower four bits: height offset, Upper 4 bits = set if object is Nightopian Helper +// var2: +// Bits 1-10: height offset, max 1023 +// Bits 11-16: X radius factor (max 63, default 20) +// Bit 17: set if object is Nightopian Helper +// Bit 18: set to define X/Y/Z rotation factor +// Bits 19-20: Unused +// Bits 21-26: Y radius factor (max 63, default 32) +// Bits 27-32: Z radius factor (max 63, default 32) // +// If MF_GRENADEBOUNCE is flagged on mobj, use actor->threshold to define X/Y/Z radius factor, max 1023 each: +// Bits 1-10: X factor +// Bits 11-20: Y factor +// Bits 21-30: Z factor void A_OrbitNights(mobj_t* actor) { - INT32 ofs = (var2 & 0xFFFF); - boolean ishelper = (var2 & 0xFFFF0000); -#ifdef HAVE_BLUA + INT32 ofs = (var2 & 0x3FF); + boolean ishelper = (var2 & 0x10000); + boolean donotrescale = (var2 & 0x40000); + INT32 xfactor = 32, yfactor = 32, zfactor = 20; + + (void)ishelper; + if (LUA_CallAction("A_OrbitNights", actor)) return; -#endif - if (!actor->target || !actor->target->player || - !actor->target->tracer || !actor->target->player->nightstime - // Also remove this object if they no longer have a NiGHTS helper - || (ishelper && !actor->target->player->powers[pw_nights_helper])) + if (actor->flags & MF_GRENADEBOUNCE) { - P_RemoveMobj(actor); + xfactor = (actor->threshold & 0x3FF); + yfactor = (actor->threshold & 0xFFC00) >> 10; + zfactor = (actor->threshold & 0x3FF00000) >> 20; + } + else if (var2 & 0x20000) + { + xfactor = (var2 & 0xFC00) >> 10; + yfactor = (var2 & 0x3F00000) >> 20; + zfactor = (var2 & 0xFC000000) >> 26; + } + + if (!actor->target) + { + if (cv_debug && !(actor->target && actor->target->player)) + CONS_Printf("ERROR: Powerup has no target!\n"); return; } else @@ -9518,18 +9874,21 @@ void A_OrbitNights(mobj_t* actor) const angle_t fa = (angle_t)actor->extravalue1 >> ANGLETOFINESHIFT; const angle_t ofa = ((angle_t)actor->extravalue1 + (ofs*ANG1)) >> ANGLETOFINESHIFT; - const fixed_t fc = FixedMul(FINECOSINE(fa),FixedMul(32*FRACUNIT, actor->scale)); - const fixed_t fh = FixedMul(FINECOSINE(ofa),FixedMul(20*FRACUNIT, actor->scale)); - const fixed_t fs = FixedMul(FINESINE(fa),FixedMul(32*FRACUNIT, actor->scale)); + const fixed_t fc = FixedMul(FINECOSINE(fa),FixedMul(xfactor*FRACUNIT, actor->scale)); + const fixed_t fh = FixedMul(FINECOSINE(ofa),FixedMul(zfactor*FRACUNIT, actor->scale)); + const fixed_t fs = FixedMul(FINESINE(fa),FixedMul(yfactor*FRACUNIT, actor->scale)); - actor->x = actor->target->tracer->x + fc; - actor->y = actor->target->tracer->y + fs; - actor->z = actor->target->tracer->z + fh + FixedMul(16*FRACUNIT, actor->scale); + actor->x = actor->target->x + fc; + actor->y = actor->target->y + fs; + actor->z = actor->target->z + fh + FixedMul(16*FRACUNIT, actor->scale); // Semi-lazy hack actor->angle = (angle_t)actor->extravalue1 + ANGLE_90; } P_SetThingPosition(actor); + + if (!donotrescale && actor->destscale != actor->target->destscale) + actor->destscale = actor->target->destscale; } } @@ -9537,16 +9896,20 @@ void A_OrbitNights(mobj_t* actor) // // Description: Spawns a "ghost" mobj of this actor, ala spindash trails and the minus's digging "trails" // -// var1 = unused +// var1 = duration in tics // var2 = unused // void A_GhostMe(mobj_t *actor) { -#ifdef HAVE_BLUA + INT32 locvar1 = var1; + mobj_t *ghost; + if (LUA_CallAction("A_GhostMe", actor)) return; -#endif - P_SpawnGhostMobj(actor); + + ghost = P_SpawnGhostMobj(actor); + if (ghost && locvar1 > 0) + ghost->fuse = locvar1; } // Function: A_SetObjectState @@ -9563,10 +9926,9 @@ void A_SetObjectState(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; mobj_t *target; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetObjectState", actor)) return; -#endif if ((!locvar2 && !actor->target) || (locvar2 && !actor->tracer)) { @@ -9609,14 +9971,12 @@ void A_SetObjectTypeState(mobj_t *actor) mobj_t *mo2; fixed_t dist = 0; -#ifdef HAVE_BLUA if (LUA_CallAction("A_SetObjectTypeState", actor)) return; -#endif - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -9652,10 +10012,9 @@ void A_KnockBack(mobj_t *actor) { INT32 locvar1 = var1; mobj_t *target; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_KnockBack", actor)) return; -#endif if (!locvar1) target = actor->target; @@ -9688,10 +10047,9 @@ void A_PushAway(mobj_t *actor) INT32 locvar2 = var2; mobj_t *target; // target angle_t an; // actor to target angle -#ifdef HAVE_BLUA + if (LUA_CallAction("A_PushAway", actor)) return; -#endif if ((!(locvar2 >> 16) && !actor->target) || ((locvar2 >> 16) && !actor->tracer)) return; @@ -9723,10 +10081,9 @@ void A_RingDrain(mobj_t *actor) { INT32 locvar1 = var1; player_t *player; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_RingDrain", actor)) return; -#endif if (!actor->target || !actor->target->player) { @@ -9736,7 +10093,7 @@ void A_RingDrain(mobj_t *actor) } player = actor->target->player; - P_GivePlayerRings(player, -min(locvar1, player->mo->health-1)); + P_GivePlayerRings(player, -min(locvar1, player->rings)); } // Function: A_SplitShot @@ -9756,10 +10113,12 @@ void A_SplitShot(mobj_t *actor) const UINT16 loc2up = (UINT16)(locvar2 >> 16); const fixed_t offs = (fixed_t)(locvar1*FRACUNIT); const fixed_t hoffs = (fixed_t)(loc2up*FRACUNIT); -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SplitShot", actor)) return; -#endif + + if (!actor->target) + return; A_FaceTarget(actor); { @@ -9791,10 +10150,10 @@ void A_MissileSplit(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_MissileSplit", actor)) return; -#endif + if (actor->eflags & MFE_VERTICALFLIP) P_SpawnAlteredDirectionMissile(actor, locvar1, actor->x, actor->y, actor->z+actor->height, locvar2); else @@ -9819,10 +10178,9 @@ void A_MultiShot(mobj_t *actor) const UINT16 loc1up = (UINT16)(locvar1 >> 16); INT32 count = 0; fixed_t ad; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_MultiShot", actor)) return; -#endif if (actor->target) A_FaceTarget(actor); @@ -9881,10 +10239,9 @@ void A_InstaLoop(mobj_t *actor) const angle_t fa = FixedAngleC(loc1lw*FRACUNIT*360, loc1up*FRACUNIT)>>ANGLETOFINESHIFT; const fixed_t ac = FINECOSINE(fa); const fixed_t as = FINESINE(fa); -#ifdef HAVE_BLUA + if (LUA_CallAction("A_InstaLoop", actor)) return; -#endif P_InstaThrust(actor, actor->angle, FixedMul(ac, FixedMul(force, actor->scale))); P_SetObjectMomZ(actor, FixedMul(as, force), false); @@ -9915,10 +10272,9 @@ void A_Custom3DRotate(mobj_t *actor) const fixed_t hOff = FixedMul(loc1up*FRACUNIT, actor->scale); const fixed_t hspeed = FixedMul(loc2up*FRACUNIT/10, actor->scale); const fixed_t vspeed = FixedMul(loc2lw*FRACUNIT/10, actor->scale); -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Custom3DRotate", actor)) return; -#endif if (actor->target->health == 0) { @@ -9975,10 +10331,9 @@ void A_SearchForPlayers(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SearchForPlayers", actor)) return; -#endif if (!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { @@ -10009,10 +10364,9 @@ void A_CheckRandom(mobj_t *actor) INT32 locvar2 = var2; fixed_t chance = FRACUNIT; -#ifdef HAVE_BLUA if (LUA_CallAction("A_CheckRandom", actor)) return; -#endif + if ((locvar1 & 0xFFFF) == 0) return; @@ -10036,15 +10390,14 @@ void A_CheckTargetRings(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckTargetRings", actor)) return; -#endif if (!(actor->target) || !(actor->target->player)) return; - if (actor->target->player->health >= locvar1) + if (actor->target->player->rings >= locvar1) P_SetMobjState(actor, locvar2); } @@ -10060,13 +10413,12 @@ void A_CheckRings(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; INT32 i, cntr = 0; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckRings", actor)) return; -#endif for (i = 0; i < MAXPLAYERS; i++) - cntr += players[i].health-1; + cntr += players[i].rings; if (cntr >= locvar1) P_SetMobjState(actor, locvar2); @@ -10085,10 +10437,9 @@ void A_CheckTotalRings(mobj_t *actor) INT32 locvar2 = var2; INT32 i, cntr = 0; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckTotalRings", actor)) return; -#endif for (i = 0; i < MAXPLAYERS; i++) cntr += players[i].totalring; @@ -10108,10 +10459,9 @@ void A_CheckHealth(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckHealth", actor)) return; -#endif if (actor->health <= locvar1) P_SetMobjState(actor, locvar2); @@ -10131,10 +10481,9 @@ void A_CheckRange(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; fixed_t dist; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckRange", actor)) return; -#endif if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) return; @@ -10162,10 +10511,9 @@ void A_CheckHeight(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; fixed_t height; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckHeight", actor)) return; -#endif if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) return; @@ -10195,10 +10543,9 @@ void A_CheckTrueRange(mobj_t *actor) fixed_t height; // vertical range fixed_t dist; // horizontal range fixed_t l; // true range -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckTrueRange", actor)) return; -#endif if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) return; @@ -10247,14 +10594,13 @@ void A_CheckThingCount(mobj_t *actor) thinker_t *th; mobj_t *mo2; fixed_t dist = 0; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckThingCount", actor)) return; -#endif - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -10294,10 +10640,8 @@ void A_CheckAmbush(mobj_t *actor) angle_t atp; // actor to target angle angle_t an; // angle between at and atp -#ifdef HAVE_BLUA if (LUA_CallAction("A_CheckAmbush", actor)) return; -#endif if ((!locvar1 && !actor->target) || (locvar1 && !actor->tracer)) return; @@ -10333,10 +10677,9 @@ void A_CheckCustomValue(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckCustomValue", actor)) return; -#endif if (actor->cusval >= locvar1) P_SetMobjState(actor, locvar2); @@ -10353,10 +10696,9 @@ void A_CheckCusValMemo(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CheckCusValMemo", actor)) return; -#endif if (actor->cvmem >= locvar1) P_SetMobjState(actor, locvar2); @@ -10379,10 +10721,9 @@ void A_SetCustomValue(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetCustomValue", actor)) return; -#endif if (cv_debug) CONS_Printf("Init custom value is %d\n", actor->cusval); @@ -10430,10 +10771,9 @@ void A_UseCusValMemo(mobj_t *actor) INT32 temp = actor->cusval; // value being manipulated INT32 tempM = actor->cvmem; // value used to manipulate temp with -#ifdef HAVE_BLUA + if (LUA_CallAction("A_UseCusValMemo", actor)) return; -#endif if (locvar1 == 1) // cvmem being changed using cusval { @@ -10494,10 +10834,9 @@ void A_RelayCustomValue(mobj_t *actor) INT32 temp; // reference value - var1 lower 16 bits changes this INT32 tempT; // target's value - changed to tracer if var1 upper 16 bits set, then modified to become final value -#ifdef HAVE_BLUA + if (LUA_CallAction("A_RelayCustomValue", actor)) return; -#endif if ((!(locvar1 >> 16) && !actor->target) || ((locvar1 >> 16) && !actor->tracer)) return; @@ -10554,10 +10893,9 @@ void A_CusValAction(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_CusValAction", actor)) return; -#endif if (locvar2 == 5) { @@ -10590,9 +10928,7 @@ void A_CusValAction(mobj_t *actor) var2 = states[locvar1].var2; } -#ifdef HAVE_BLUA astate = &states[locvar1]; -#endif states[locvar1].action.acp1(actor); } @@ -10608,10 +10944,9 @@ void A_CusValAction(mobj_t *actor) void A_ForceStop(mobj_t *actor) { INT32 locvar1 = var1; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_ForceStop", actor)) return; -#endif actor->momx = actor->momy = 0; if (locvar1 == 0) @@ -10629,17 +10964,13 @@ void A_ForceWin(mobj_t *actor) { INT32 i; -#ifdef HAVE_BLUA if (LUA_CallAction("A_ForceWin", actor)) return; -#else - (void)actor; -#endif for (i = 0; i < MAXPLAYERS; i++) { - if (playeringame[i] && (players[i].health > 0 - || ((netgame || multiplayer) && (players[i].lives > 0 || players[i].continues > 0)))) + if (playeringame[i] && ((players[i].mo && players[i].mo->health) + || ((netgame || multiplayer) && (players[i].lives || players[i].continues)))) break; } @@ -10647,7 +10978,11 @@ void A_ForceWin(mobj_t *actor) return; for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; P_DoPlayerExit(&players[i]); + } } // Function: A_SpikeRetract @@ -10662,10 +10997,9 @@ void A_ForceWin(mobj_t *actor) void A_SpikeRetract(mobj_t *actor) { INT32 locvar1 = var1; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SpikeRetract", actor)) return; -#endif if (actor->flags & MF_NOBLOCKMAP) return; @@ -10747,12 +11081,11 @@ void A_Repeat(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_Repeat", actor)) return; -#endif - if ((!(actor->extravalue2)) || actor->extravalue2 > locvar1) + if (locvar1 && (!actor->extravalue2 || actor->extravalue2 > locvar1)) actor->extravalue2 = locvar1; if (--actor->extravalue2 > 0) @@ -10773,10 +11106,9 @@ void A_SetScale(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; mobj_t *target; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_SetScale", actor)) return; -#endif if (locvar1 <= 0) { @@ -10819,10 +11151,10 @@ void A_RemoteDamage(mobj_t *actor) INT32 locvar2 = var2; mobj_t *target; // we MUST have a target mobj_t *source = NULL; // on the other hand we don't necessarily need a source -#ifdef HAVE_BLUA + if (LUA_CallAction("A_RemoteDamage", actor)) return; -#endif + if (locvar1 == 1) target = actor->target; else if (locvar1 == 2) @@ -10845,7 +11177,7 @@ void A_RemoteDamage(mobj_t *actor) if (target->player) K_DoIngameRespawn(target->player); else - P_KillMobj(target, source, source); + P_KillMobj(target, source, source, DMG_NORMAL); } else if (locvar2 == 2) // Remove mobj! { @@ -10855,7 +11187,7 @@ void A_RemoteDamage(mobj_t *actor) P_RemoveMobj(target); } else // default: Damage mobj! - P_DamageMobj(target, source, source, 1); + P_DamageMobj(target, source, source, 1, DMG_NORMAL); } // Function: A_HomingChase @@ -10872,10 +11204,9 @@ void A_HomingChase(mobj_t *actor) mobj_t *dest; fixed_t dist; fixed_t speedmul; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_HomingChase", actor)) return; -#endif if (locvar2 == 1) dest = actor->tracer; @@ -10907,33 +11238,34 @@ void A_HomingChase(mobj_t *actor) // lower 16 bits = object # to fire // upper 16 bits = front offset // var2: -// lower 16 bits = vertical angle +// lower 15 bits = vertical angle variable +// 16th bit: +// - 0: use vertical angle variable as vertical angle in degrees +// - 1: mimic P_SpawnXYZMissile +// use z of actor minus z of missile as vertical distance to cover during momz calculation +// use vertical angle variable as horizontal distance to cover during momz calculation // upper 16 bits = height offset // void A_TrapShot(mobj_t *actor) { INT32 locvar1 = var1; INT32 locvar2 = var2; - angle_t vertang = FixedAngle(((INT16)(locvar2 & 65535))*FRACUNIT); + boolean oldstyle = (locvar2 & 32768) ? true : false; mobjtype_t type = (mobjtype_t)(locvar1 & 65535); mobj_t *missile; INT16 frontoff = (INT16)(locvar1 >> 16); INT16 vertoff = (INT16)(locvar2 >> 16); fixed_t x, y, z; fixed_t speed; -#ifdef HAVE_BLUA + if (LUA_CallAction("A_TrapShot", actor)) return; -#endif x = actor->x + P_ReturnThrustX(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale)); y = actor->y + P_ReturnThrustY(actor, actor->angle, FixedMul(frontoff*FRACUNIT, actor->scale)); if (actor->eflags & MFE_VERTICALFLIP) - { z = actor->z + actor->height - FixedMul(vertoff*FRACUNIT, actor->scale) - FixedMul(mobjinfo[type].height, actor->scale); - vertang = InvAngle(vertang); // flip firing angle - } else z = actor->z + FixedMul(vertoff*FRACUNIT, actor->scale); @@ -10944,20 +11276,35 @@ void A_TrapShot(mobj_t *actor) if (actor->eflags & MFE_VERTICALFLIP) missile->flags2 |= MF2_OBJECTFLIP; - missile->destscale = actor->destscale; - P_SetScale(missile, missile->destscale); + + missile->destscale = actor->scale; + P_SetScale(missile, actor->scale); if (missile->info->seesound) - S_StartSound(actor, missile->info->seesound); + S_StartSound(missile, missile->info->seesound); P_SetTarget(&missile->target, actor); missile->angle = actor->angle; speed = FixedMul(missile->info->speed, missile->scale); - missile->momx = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed)); - missile->momy = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed)); - missile->momz = FixedMul(FINESINE(vertang>>ANGLETOFINESHIFT), speed); + if (oldstyle) + { + missile->momx = FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed); + missile->momy = FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed); + // The below line basically mimics P_SpawnXYZMissile's momz calculation. + missile->momz = (actor->z + ((actor->eflags & MFE_VERTICALFLIP) ? actor->height : 0) - z) / ((fixed_t)(locvar2 & 32767)*FRACUNIT / speed); + P_CheckMissileSpawn(missile); + } + else + { + angle_t vertang = FixedAngle(((INT16)(locvar2 & 32767))*FRACUNIT); + if (actor->eflags & MFE_VERTICALFLIP) + vertang = InvAngle(vertang); // flip firing angle + missile->momx = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(missile->angle>>ANGLETOFINESHIFT), speed)); + missile->momy = FixedMul(FINECOSINE(vertang>>ANGLETOFINESHIFT), FixedMul(FINESINE(missile->angle>>ANGLETOFINESHIFT), speed)); + missile->momz = FixedMul(FINESINE(vertang>>ANGLETOFINESHIFT), speed); + } } // Function: A_VileTarget @@ -10976,10 +11323,8 @@ void A_VileTarget(mobj_t *actor) mobjtype_t fogtype; INT32 i; -#ifdef HAVE_BLUA if (LUA_CallAction("A_VileTarget", actor)) return; -#endif if (!actor->target) return; @@ -11065,10 +11410,8 @@ void A_VileAttack(mobj_t *actor) mobj_t *fire; INT32 i; -#ifdef HAVE_BLUA if (LUA_CallAction("A_VileAttack", actor)) return; -#endif if (!actor->target) return; @@ -11090,7 +11433,7 @@ void A_VileAttack(mobj_t *actor) return; S_StartSound(actor, soundtoplay); - P_DamageMobj(actor->target, actor, actor, 1); + P_DamageMobj(actor->target, actor, actor, 1, DMG_NORMAL); //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it actor->target->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(actor->target); // How we're doing it if (explosionType != MT_NULL) @@ -11111,7 +11454,7 @@ void A_VileAttack(mobj_t *actor) actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), fire->z); - P_RadiusAttack(fire, actor, 70*FRACUNIT); + P_RadiusAttack(fire, actor, 70*FRACUNIT, 0, true); } else { @@ -11131,7 +11474,7 @@ void A_VileAttack(mobj_t *actor) continue; S_StartSound(actor, soundtoplay); - P_DamageMobj(players[i].mo, actor, actor, 1); + P_DamageMobj(players[i].mo, actor, actor, 1, DMG_NORMAL); //actor->target->momz = 1000*FRACUNIT/actor->target->info->mass; // How id did it players[i].mo->momz += FixedMul(10*FRACUNIT, actor->scale)*P_MobjFlip(players[i].mo); // How we're doing it if (explosionType != MT_NULL) @@ -11156,7 +11499,7 @@ void A_VileAttack(mobj_t *actor) actor->target->x - P_ReturnThrustX(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), actor->target->y - P_ReturnThrustY(fire, actor->angle, FixedMul(24*FRACUNIT, fire->scale)), fire->z); - P_RadiusAttack(fire, actor, 70*FRACUNIT); + P_RadiusAttack(fire, actor, 70*FRACUNIT, 0, true); } } @@ -11179,10 +11522,8 @@ void A_VileFire(mobj_t *actor) INT32 locvar2 = var2; mobj_t *dest; -#ifdef HAVE_BLUA if (LUA_CallAction("A_VileFire", actor)) return; -#endif dest = actor->tracer; if (!dest) @@ -11267,10 +11608,8 @@ void A_BrakChase(mobj_t *actor) INT32 locvar1 = var1; INT32 locvar2 = var2; -#ifdef HAVE_BLUA if (LUA_CallAction("A_BrakChase", actor)) return; -#endif // Set new tics NOW, in case the state changes while we're doing this and we try applying this to the painstate or something silly if (actor->tics > 1 && locvar1 < actor->tics) // Not much point, otherwise @@ -11389,10 +11728,9 @@ void A_BrakFireShot(mobj_t *actor) fixed_t x, y, z; INT32 locvar1 = var1; -#ifdef HAVE_BLUA if (LUA_CallAction("A_BrakFireShot", actor)) return; -#endif + if (!actor->target) return; @@ -11453,10 +11791,8 @@ void A_BrakLobShot(mobj_t *actor) INT32 locvar2 = var2 & 0x0000FFFF; INT32 aimDirect = var2 & 0xFFFF0000; -#ifdef HAVE_BLUA if (LUA_CallAction("A_BrakLobShot", actor)) return; -#endif if (!actor->target) return; // Don't even bother if we've got nothing to aim at. @@ -11561,10 +11897,8 @@ void A_NapalmScatter(mobj_t *actor) INT32 i; // for-loop cursor mobj_t *mo; // each and every spawned napalm burst -#ifdef HAVE_BLUA if (LUA_CallAction("A_NapalmScatter", actor)) return; -#endif // Some quick sanity-checking if (typeOfShot >= NUMMOBJTYPES) // I'd add a <0 check, too, but 0x0000FFFF isn't negative in this case @@ -11615,15 +11949,13 @@ void A_SpawnFreshCopy(mobj_t *actor) { mobj_t *newObject; -#ifdef HAVE_BLUA if (LUA_CallAction("A_SpawnFreshCopy", actor)) return; -#endif - newObject = P_SpawnMobj(actor->x, actor->y, actor->z, actor->type); + newObject = P_SpawnMobjFromMobj(actor, 0, 0, 0, actor->type); + newObject->flags2 = actor->flags2 & MF2_AMBUSH; newObject->angle = actor->angle; - P_SetScale(newObject, actor->scale); - newObject->destscale = actor->destscale; + newObject->color = actor->color; P_SetTarget(&newObject->target, actor->target); P_SetTarget(&newObject->tracer, actor->tracer); @@ -11632,3 +11964,2822 @@ void A_SpawnFreshCopy(mobj_t *actor) newObject->color = actor->color; // SRB2Kart } + +// Internal Flicky spawning function. +mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers, SINT8 moveforward) +{ + mobj_t *flicky; + fixed_t offsx = 0, offsy = 0; + + if (!flickytype) + { + if (!mapheaderinfo[gamemap-1] || !mapheaderinfo[gamemap-1]->numFlickies) // No mapheader, no shoes, no service. + return NULL; + else + { + INT32 prandom = P_RandomKey(mapheaderinfo[gamemap-1]->numFlickies); + flickytype = mapheaderinfo[gamemap-1]->flickies[prandom]; + } + } + + if (moveforward) + { + fixed_t scal = mobjinfo[flickytype].radius*((fixed_t)moveforward); + offsx = P_ReturnThrustX(actor, actor->angle, scal); + offsy = P_ReturnThrustY(actor, actor->angle, scal); + } + + flicky = P_SpawnMobjFromMobj(actor, offsx, offsy, 0, flickytype); + flicky->angle = actor->angle; + + if (flickytype == MT_SEED) + flicky->z += P_MobjFlip(actor)*(actor->height - flicky->height)/2; + + if (actor->eflags & MFE_UNDERWATER) + momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT)); + + P_SetObjectMomZ(flicky, momz, false); + flicky->movedir = (P_RandomChance(FRACUNIT/2) ? -1 : 1); + flicky->fuse = P_RandomRange(595, 700); // originally 300, 350 + flicky->threshold = 0; + + if (lookforplayers) + P_LookForPlayers(flicky, true, false, 0); + + return flicky; +} + +// Function: A_FlickySpawn +// +// Description: Flicky spawning function. +// +// var1: +// lower 16 bits: if 0, spawns random flicky based on level header. Else, spawns the designated thing type. +// bit 17: if 0, no sound is played. Else, A_Scream is called. +// bit 18: if 1, spawn flicky slightly forward from spawn position, to avoid being stuck in wall. doesn't stack with 19. (snailers) +// bit 19: if 1, spawn flicky slightly backward from spawn position. doesn't stack with 18. +// var2 = upwards thrust for spawned flicky. If zero, default value is provided. +// +void A_FlickySpawn(mobj_t *actor) +{ + INT32 locvar1 = var1 & 65535; + INT32 locvar2 = var2; + INT32 test = (var1 >> 16); + SINT8 moveforward = 0; + + if (LUA_CallAction("A_FlickySpawn", actor)) + return; + + if (test & 1) + A_Scream(actor); // A shortcut for the truly lazy. + if (test & 2) + moveforward = 1; + else if (test & 4) + moveforward = -1; + + P_InternalFlickySpawn(actor, locvar1, ((locvar2) ? locvar2 : 8*FRACUNIT), true, moveforward); +} + +// Internal Flicky color setting +void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo) +{ + UINT8 flickycolors[] = { + SKINCOLOR_RED, + SKINCOLOR_CYAN, + SKINCOLOR_BLUE, + SKINCOLOR_PASTEL, + SKINCOLOR_PURPLE, + SKINCOLOR_VIOLET, + SKINCOLOR_FUCHSIA, + SKINCOLOR_BLACK, + SKINCOLOR_BEIGE, + SKINCOLOR_LAVENDER, + SKINCOLOR_RUBY, + SKINCOLOR_BLOSSOM, + SKINCOLOR_SUNSLAM, + SKINCOLOR_ORANGE, + SKINCOLOR_YELLOW, + }; + + if (extrainfo == 0) + // until we can customize flicky colors by level header, just stick to SRB2's defaults + actor->color = flickycolors[P_RandomKey(2)]; //flickycolors[P_RandomKey(sizeof(flickycolors))]; + else + actor->color = flickycolors[min(extrainfo-1, 14)]; // sizeof(flickycolors)-1 +} + +// Function: A_FlickyCenter +// +// Description: Place flickies in-level. +// +// var1: +// Lower 16 bits = if 0, spawns random flicky based on level header. Else, spawns the designated thing type. +// Bits 17-20 = Flicky color, up to 15. Applies to fish. +// Bit 21 = Flag MF_SLIDEME (see below) +// Bit 22 = Flag MF_GRENADEBOUNCE (see below) +// Bit 23 = Flag MF_NOCLIPTHING (see below) +// +// If actor is placed from a spawnpoint (map Thing), the Thing's properties take precedence. +// +// var2 = maximum default distance away from spawn the flickies are allowed to travel. If angle != 0, then that's the radius. +// +// If MTF_EXTRA (MF_SLIDEME): is flagged, Flickies move aimlessly. Else, orbit around the target. +// If MTF_OBJECTSPECIAL (MF_GRENADEBOUNCE): Flickies stand in-place without gravity (unless they hop, then gravity is applied.) +// If MTF_AMBUSH (MF_NOCLIPTHING): is flagged, Flickies hop. +// +void A_FlickyCenter(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + UINT16 flickytype = (locvar1 & 0xFFFF); + UINT8 flickycolor = ((locvar1 >> 16) & 0xFF); + UINT8 flickyflags = ((locvar1 >> 20) & 0xF); + + if (LUA_CallAction("A_FlickyCenter", actor)) + return; + + if (!actor->tracer) + { + mobj_t *flicky = P_InternalFlickySpawn(actor, locvar1, 1, false, 0); + P_SetTarget(&flicky->target, actor); + P_SetTarget(&actor->tracer, flicky); + + if (actor->spawnpoint) + { + actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING); + actor->flags |= ( + ((actor->spawnpoint->options & MTF_EXTRA) ? MF_SLIDEME : 0) + | ((actor->spawnpoint->options & MTF_OBJECTSPECIAL) ? MF_GRENADEBOUNCE : 0) + | ((actor->spawnpoint->options & MTF_AMBUSH) ? MF_NOCLIPTHING : 0) + ); + actor->extravalue1 = actor->spawnpoint->angle ? abs(actor->spawnpoint->angle) * FRACUNIT + : locvar2 ? abs(locvar2) : 384 * FRACUNIT; + actor->extravalue2 = actor->spawnpoint->extrainfo; + actor->friction = actor->spawnpoint->x*FRACUNIT; + actor->movefactor = actor->spawnpoint->y*FRACUNIT; + actor->watertop = actor->spawnpoint->z*FRACUNIT; + } + else + { + actor->flags &= ~(MF_SLIDEME|MF_GRENADEBOUNCE|MF_NOCLIPTHING); + actor->flags |= ( + ((flickyflags & 1) ? MF_SLIDEME : 0) + | ((flickyflags & 2) ? MF_GRENADEBOUNCE : 0) + | ((flickyflags & 4) ? MF_NOCLIPTHING : 0) + ); + actor->extravalue1 = abs(locvar2); + actor->extravalue2 = flickycolor; + actor->friction = actor->x; + actor->movefactor = actor->y; + actor->watertop = actor->z; + locvar1 = flickytype; + } + + if (actor->flags & MF_GRENADEBOUNCE) // in-place + actor->tracer->fuse = 0; + else if (actor->flags & MF_SLIDEME) // aimless + { + actor->tracer->fuse = 0; // less than 2*TICRATE means move aimlessly. + actor->tracer->angle = P_RandomKey(180)*ANG2; + } + else //orbit + actor->tracer->fuse = FRACUNIT; + + if (locvar1 == MT_FLICKY_08) + P_InternalFlickySetColor(actor->tracer, actor->extravalue2); + + actor->extravalue2 = 0; + } + + if (!(actor->flags & MF_SLIDEME) && !(actor->flags & MF_GRENADEBOUNCE)) + { + fixed_t originx = actor->friction; + fixed_t originy = actor->movefactor; + fixed_t originz = actor->watertop; + + actor->tracer->fuse = FRACUNIT; + + // Impose default home radius if flicky orbits around player + if (!actor->extravalue1) + actor->extravalue1 = locvar2 ? abs(locvar2) : 384 * FRACUNIT; + + P_LookForPlayers(actor, true, false, actor->extravalue1); + + if (actor->target && P_AproxDistance(actor->target->x - originx, actor->target->y - originy) < actor->extravalue1) + { + actor->extravalue2 = 1; + P_TeleportMove(actor, actor->target->x, actor->target->y, actor->target->z); + tmthing = NULL; + } + else if(actor->extravalue2) + { + actor->extravalue2 = 0; + P_TeleportMove(actor, originx, originy, originz); + tmthing = NULL; + } + } +} + +// Internal Flicky bubbling function. +void P_InternalFlickyBubble(mobj_t *actor) +{ + if (actor->eflags & MFE_UNDERWATER) + { + mobj_t *overlay; + + if (!((actor->z + 3*actor->height/2) < actor->watertop) || !mobjinfo[actor->type].raisestate || actor->tracer) + return; + + overlay = P_SpawnMobj(actor->x, actor->y, actor->z, MT_OVERLAY); + P_SetMobjStateNF(overlay, mobjinfo[actor->type].raisestate); + P_SetTarget(&actor->tracer, overlay); + P_SetTarget(&overlay->target, actor); + return; + } + + if (!actor->tracer || P_MobjWasRemoved(actor->tracer)) + return; + + P_RemoveMobj(actor->tracer); + P_SetTarget(&actor->tracer, NULL); +} + +// Function: A_FlickyAim +// +// Description: Flicky aiming function. +// +// var1 = how far around the target (in angle constants) the flicky should look +// var2 = distance from target to aim for +// +void A_FlickyAim(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + boolean flickyhitwall = false; + + if (LUA_CallAction("A_FlickyAim", actor)) + return; + + if ((actor->momx == actor->momy && actor->momy == 0) + || (actor->target && P_IsFlickyCenter(actor->target->type) + && actor->target->extravalue1 && (actor->target->flags & MF_SLIDEME) + && P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) >= actor->target->extravalue1)) + flickyhitwall = true; + + P_InternalFlickyBubble(actor); + P_InstaThrust(actor, 0, 0); + + if (!actor->target) + { + P_LookForPlayers(actor, true, false, 0); + actor->angle = P_RandomKey(36)*ANG10; + return; + } + + if (actor->fuse > 2*TICRATE) + { + angle_t posvar; + fixed_t chasevar, chasex, chasey; + + if (flickyhitwall) + actor->movedir *= -1; + + posvar = ((R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + actor->movedir*locvar1) >> ANGLETOFINESHIFT) & FINEMASK; + chasevar = FixedSqrt(max(FRACUNIT, P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y) - locvar2)) + locvar2; + + chasex = actor->target->x + FixedMul(FINECOSINE(posvar), chasevar); + chasey = actor->target->y + FixedMul(FINESINE(posvar), chasevar); + + if (P_AproxDistance(chasex - actor->x, chasey - actor->y)) + actor->angle = R_PointToAngle2(actor->x, actor->y, chasex, chasey); + } + else if (flickyhitwall) + { + if (actor->target && P_IsFlickyCenter(actor->target->type)) + actor->angle = R_PointToAngle2(actor->target->x, actor->target->y, actor->x, actor->y) + P_RandomRange(112, 248) * ANG1; + else + actor->angle += P_RandomRange(112, 248)*ANG1; + actor->threshold = 0; + } +} + +//Internal Flicky flying function. Also usuable as an underwater swim thrust. +void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez) +{ + angle_t vertangle; + + flyspeed = FixedMul(flyspeed, actor->scale); + actor->flags |= MF_NOGRAVITY; + + var1 = ANG30; + var2 = 32*FRACUNIT; + A_FlickyAim(actor); + + chasez *= 8; + if (!actor->target || !(actor->fuse > 2*TICRATE)) + chasez += ((actor->eflags & MFE_VERTICALFLIP) ? actor->ceilingz - 24*FRACUNIT : actor->floorz + 24*FRACUNIT); + else + { + fixed_t add = actor->target->z + (actor->target->height - actor->height)/2; + if (add > (actor->ceilingz - 24*actor->scale - actor->height)) + add = actor->ceilingz - 24*actor->scale - actor->height; + else if (add < (actor->floorz + 24*actor->scale)) + add = actor->floorz + 24*actor->scale; + chasez += add; + } + + if (!targetdist) + targetdist = 16*FRACUNIT; //Default! + + if (actor->target && abs(chasez - actor->z) > targetdist) + targetdist = P_AproxDistance(actor->target->x - actor->x, actor->target->y - actor->y); + + if (actor->target + && P_IsFlickyCenter(actor->target->type) + && (actor->target->flags & MF_SLIDEME)) + vertangle = 0; + else + vertangle = (R_PointToAngle2(0, actor->z, targetdist, chasez) >> ANGLETOFINESHIFT) & FINEMASK; + + P_InstaThrust(actor, actor->angle, FixedMul(FINECOSINE(vertangle), flyspeed)); + actor->momz = FixedMul(FINESINE(vertangle), flyspeed); +} + +// Function: A_FlickyFly +// +// Description: Flicky flying function. +// +// var1 = how fast to fly +// var2 = how far ahead the target should be considered +// +void A_FlickyFly(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FlickyFly", actor)) + return; + + P_InternalFlickyFly(actor, locvar1, locvar2, + FINECOSINE((((actor->fuse % 36) * ANG10) >> ANGLETOFINESHIFT) & FINEMASK) + ); +} + +// Function: A_FlickySoar +// +// Description: Flicky soaring function - specific to puffin. +// +// var1 = how fast to fly +// var2 = how far ahead the target should be considered +// +void A_FlickySoar(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FlickySoar", actor)) + return; + + P_InternalFlickyFly(actor, locvar1, locvar2, + 2*(FRACUNIT/2 - abs(FINECOSINE((((actor->fuse % 144) * 5*ANG1/2) >> ANGLETOFINESHIFT) & FINEMASK))) + ); + + if (P_MobjFlip(actor)*actor->momz > 0 && actor->frame == 1 && actor->sprite == SPR_FL10) + actor->frame = 3; +} + +//Function: A_FlickyCoast +// +// Description: Flicky swim-coasting function. +// +// var1 = speed to change state upon reaching +// var2 = state to change to upon slowing down +// the spawnstate of the mobj = state to change to when above water +// +void A_FlickyCoast(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FlickyCoast", actor)) + return; + + if (actor->eflags & MFE_UNDERWATER) + { + actor->momx = (11*actor->momx)/12; + actor->momy = (11*actor->momy)/12; + actor->momz = (11*actor->momz)/12; + + if (P_AproxDistance(P_AproxDistance(actor->momx, actor->momy), actor->momz) < locvar1) + P_SetMobjState(actor, locvar2); + + return; + } + + actor->flags &= ~MF_NOGRAVITY; + P_SetMobjState(actor, mobjinfo[actor->type].spawnstate); +} + +// Internal Flicky hopping function. +void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle) +{ + if (((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) + { + if (momz) + { + if (actor->eflags & MFE_UNDERWATER) + momz = FixedDiv(momz, FixedSqrt(3*FRACUNIT)); + P_SetObjectMomZ(actor, momz, false); + } + P_InstaThrust(actor, angle, FixedMul(momh, actor->scale)); + } +} + +// Function: A_FlickyHop +// +// Description: Flicky hopping function. +// +// var1 = vertical thrust +// var2 = horizontal thrust +// +void A_FlickyHop(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FlickyHop", actor)) + return; + + P_InternalFlickyHop(actor, locvar1, locvar2, actor->angle); +} + +// Function: A_FlickyFlounder +// +// Description: Flicky floundering function. +// +// var1 = intended vertical thrust +// var2 = intended horizontal thrust +// +void A_FlickyFlounder(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + angle_t hopangle; + + if (LUA_CallAction("A_FlickyFlounder", actor)) + return; + + locvar1 *= (P_RandomKey(2) + 1); + locvar2 *= (P_RandomKey(2) + 1); + hopangle = (actor->angle + (P_RandomKey(9) - 4)*ANG2); + P_InternalFlickyHop(actor, locvar1, locvar2, hopangle); +} + +// Function: A_FlickyCheck +// +// Description: Flicky airtime check function. +// +// var1 = state to change to upon touching the floor +// var2 = state to change to upon falling +// the meleestate of the mobj = state to change to when underwater +// +void A_FlickyCheck(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FlickyCheck", actor)) + return; + + if (actor->target + && P_IsFlickyCenter(actor->target->type) + && (actor->target->flags & MF_GRENADEBOUNCE)) + { + if (!(actor->target->flags & MF_NOCLIPTHING)) // no hopping + { + actor->momz = 0; + actor->flags |= MF_NOGRAVITY; + } + actor->flags |= MF_NOCLIP | MF_NOBLOCKMAP | MF_SCENERY; + P_SetMobjState(actor, mobjinfo[actor->type].seestate); + } + else if (locvar2 && P_MobjFlip(actor)*actor->momz < 1) + P_SetMobjState(actor, locvar2); + else if (locvar1 && ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || ((actor->eflags & MFE_VERTICALFLIP) && actor->z + actor->height >= actor->ceilingz))) + P_SetMobjState(actor, locvar1); + else if (mobjinfo[actor->type].meleestate && (actor->eflags & MFE_UNDERWATER)) + P_SetMobjState(actor, mobjinfo[actor->type].meleestate); + P_InternalFlickyBubble(actor); +} + +// Function: A_FlickyHeightCheck +// +// Description: Flicky height check function. +// +// var1 = state to change to when falling below height relative to target +// var2 = height relative to target to change state at +// +void A_FlickyHeightCheck(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FlickyHeightCheck", actor)) + return; + + if (actor->target + && P_IsFlickyCenter(actor->target->type) + && (actor->target->flags & MF_GRENADEBOUNCE)) + { + if (!(actor->target->flags & MF_NOCLIPTHING)) // no hopping + { + actor->momz = 0; + actor->flags |= MF_NOGRAVITY; + } + actor->flags |= MF_NOCLIP | MF_NOBLOCKMAP | MF_SCENERY; + P_SetMobjState(actor, mobjinfo[actor->type].seestate); + } + else if (locvar1 && actor->target && P_MobjFlip(actor)*actor->momz < 1 + && ((P_MobjFlip(actor)*((actor->z + actor->height/2) - (actor->target->z + actor->target->height/2)) < locvar2) + || (actor->z - actor->height < actor->floorz) || (actor->z + 2*actor->height > actor->ceilingz))) + P_SetMobjState(actor, locvar1); + P_InternalFlickyBubble(actor); +} + +// Function: A_FlickyFlutter +// +// Description: Flicky fluttering function - specific to chicken. +// +// var1 = state to change to upon touching the floor +// var2 = state to change to upon falling +// the meleestate of the mobj = state to change to when underwater +// +void A_FlickyFlutter(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FlickyFlutter", actor)) + return; + + var1 = locvar1; + var2 = locvar2; + A_FlickyCheck(actor); + + var1 = ANG30; + var2 = 32*FRACUNIT; + A_FlickyAim(actor); + + P_InstaThrust(actor, actor->angle, 2*actor->scale); + if (P_MobjFlip(actor)*actor->momz < -FRACUNIT/2) + actor->momz = -P_MobjFlip(actor)*actor->scale/2; +} + +#undef FLICKYHITWALL + +// Function: A_FlameParticle +// +// Description: Creates the mobj's painchance at a random position around the object's radius. +// +// var1 = unused +// var2 = unused +// +void A_FlameParticle(mobj_t *actor) +{ + mobjtype_t type = (mobjtype_t)(mobjinfo[actor->type].painchance); + fixed_t rad, hei; + mobj_t *particle; + + if (LUA_CallAction("A_FlameParticle", actor)) + return; + + if (!type) + return; + + rad = actor->radius>>FRACBITS; + hei = actor->height>>FRACBITS; + particle = P_SpawnMobjFromMobj(actor, + P_RandomRange(rad, -rad)<frame = actor->frame; + + if (!(locvar1 & 1)) + { + fade->fuse = 15; + fade->flags2 |= MF2_BOSSNOTRAP; + } + else + fade->fuse = 20; + + if (!(locvar1 & 2)) + P_SetTarget(&actor->tracer, fade); +} + +// Function: A_Boss5Jump +// +// Description: Makes an object jump in an arc to land on their tracer precicely. +// Adapted from A_BrakLobShot, see there for explanation. +// +// var1 = unused +// var2 = unused +// +void A_Boss5Jump(mobj_t *actor) +{ + fixed_t v; // Velocity to jump at + fixed_t a1, a2, aToUse; // Velocity squared + fixed_t g; // Gravity + fixed_t x; // Horizontal difference + INT32 x_int; // x! But in integer form! + fixed_t y; // Vertical difference (yes that's normally z in SRB2 shut up) + INT32 y_int; // y! But in integer form! + INT32 intHypotenuse; // x^2 + y^2. Frequently overflows fixed point, hence why we need integers proper. + fixed_t fixedHypotenuse; // However, we can work around that and still get a fixed-point number. + angle_t theta; // Angle of attack + // INT32 locvar1 = var1; + // INT32 locvar2 = var2; + + if (LUA_CallAction("A_Boss5Jump", actor)) + return; + + if (!actor->tracer) + return; // Don't even bother if we've got nothing to aim at. + + // Look up actor's current gravity situation + if (actor->subsector->sector->gravity) + g = FixedMul(gravity,(FixedDiv(*actor->subsector->sector->gravity>>FRACBITS, 1000))); + else + g = gravity; + + // Look up distance between actor and its tracer + x = P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y); + // Look up height difference between actor and its tracer + y = actor->tracer->z - actor->z; + + // Get x^2 + y^2. Have to do it in a roundabout manner, because this overflows fixed_t way too easily otherwise. + x_int = x>>FRACBITS; + y_int = y>>FRACBITS; + intHypotenuse = (x_int*x_int) + (y_int*y_int); + fixedHypotenuse = FixedSqrt(intHypotenuse) *256; + + // a = g(y+/-sqrt(x^2+y^2)). a1 can be +, a2 can be -. + a1 = FixedMul(g,y+fixedHypotenuse); + a2 = FixedMul(g,y-fixedHypotenuse); + + // Determine which one isn't actually an imaginary number (or the smaller of the two, if both are real), and use that for v. + if (a1 < 0 || a2 < 0) + { + if (a1 < 0 && a2 < 0) + { + //Somehow, v^2 is negative in both cases. v is therefore imaginary and something is horribly wrong. Abort! + return; + } + // Just find which one's NOT negative, and use that + aToUse = max(a1,a2); + } + else + { + // Both are positive; use whichever's smaller so it can decay faster + aToUse = min(a1,a2); + } + v = FixedSqrt(aToUse); + // Okay, so we know the velocity. Let's actually find theta. + // We can cut the "+/- sqrt" part out entirely, since v was calculated specifically for it to equal zero. So: + //theta = tantoangle[FixedDiv(aToUse,FixedMul(g,x)) >> DBITS]; + theta = tantoangle[SlopeDiv(aToUse,FixedMul(g,x))]; + + // Okay, complicated math done. Let's make this object jump already. + A_FaceTracer(actor); + + if (actor->eflags & MFE_VERTICALFLIP) + actor->z--; + else + actor->z++; + + // Horizontal axes first. First parameter is initial horizontal impulse, second is to correct its angle. + fixedHypotenuse = FixedMul(v, FINECOSINE(theta >> ANGLETOFINESHIFT)); // variable reuse + actor->momx = FixedMul(fixedHypotenuse, FINECOSINE(actor->angle >> ANGLETOFINESHIFT)); + actor->momy = FixedMul(fixedHypotenuse, FINESINE(actor->angle >> ANGLETOFINESHIFT)); + // Then the vertical axis. No angle-correction needed here. + actor->momz = FixedMul(v, FINESINE(theta >> ANGLETOFINESHIFT)); + // I hope that's all that's needed, ugh +} + +// Function: A_LightBeamReset +// Description: Resets momentum and position for DSZ's projecting light beams +// +// var1 = unused +// var2 = unused +// +void A_LightBeamReset(mobj_t *actor) +{ + // INT32 locvar1 = var1; + // INT32 locvar2 = var2; + + if (LUA_CallAction("A_LightBeamReset", actor)) + return; + + actor->destscale = FRACUNIT + P_SignedRandom()*FRACUNIT/256; + P_SetScale(actor, actor->destscale); + + if (!actor->spawnpoint) + return; // this can't work properly welp + + actor->momx = -(P_SignedRandom()*FINESINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/128; + actor->momy = (P_SignedRandom()*FINECOSINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/128; + actor->momz = (P_SignedRandom()*FRACUNIT)/128; + + P_TeleportMove(actor, + actor->spawnpoint->x*FRACUNIT - (P_SignedRandom()*FINESINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/2, + actor->spawnpoint->y*FRACUNIT + (P_SignedRandom()*FINECOSINE(((actor->spawnpoint->angle*ANG1)>>ANGLETOFINESHIFT) & FINEMASK))/2, + actor->spawnpoint->z*FRACUNIT + (P_SignedRandom()*FRACUNIT)/2); +} + +// Function: A_MineExplode +// Description: Handles the explosion of a DSZ mine. +// +// var1 = unused +// var2 = unused +// +void A_MineExplode(mobj_t *actor) +{ + // INT32 locvar1 = var1; + // INT32 locvar2 = var2; + + if (LUA_CallAction("A_MineExplode", actor)) + return; + + A_Scream(actor); + actor->flags = MF_NOGRAVITY|MF_NOCLIP; + + quake.epicenter = NULL; + quake.radius = 512*FRACUNIT; + quake.intensity = 8*FRACUNIT; + quake.time = TICRATE/3; + + P_RadiusAttack(actor, actor->tracer, 192*FRACUNIT, 0, true); + P_MobjCheckWater(actor); + + { +#define dist 64 + UINT8 i; + mobjtype_t type = ((actor->eflags & MFE_UNDERWATER) ? MT_UWEXPLODE : MT_SONIC3KBOSSEXPLODE); + S_StartSound(actor, ((actor->eflags & MFE_UNDERWATER) ? sfx_s3k57 : sfx_s3k4e)); + P_SpawnMobj(actor->x, actor->y, actor->z, type); + for (i = 0; i < 16; i++) + { + mobj_t *b = P_SpawnMobj(actor->x+P_RandomRange(-dist, dist)*FRACUNIT, + actor->y+P_RandomRange(-dist, dist)*FRACUNIT, + actor->z+P_RandomRange(((actor->eflags & MFE_UNDERWATER) ? -dist : 0), dist)*FRACUNIT, + type); + fixed_t dx = b->x - actor->x, dy = b->y - actor->y, dz = b->z - actor->z; + fixed_t dm = P_AproxDistance(dz, P_AproxDistance(dy, dx)); + b->momx = FixedDiv(dx, dm)*3; + b->momy = FixedDiv(dy, dm)*3; + b->momz = FixedDiv(dz, dm)*3; + if ((actor->watertop == INT32_MAX) || (b->z + b->height > actor->watertop)) + b->flags &= ~MF_NOGRAVITY; + } +#undef dist + + if (actor->watertop != INT32_MAX) + P_SpawnMobj(actor->x, actor->y, actor->watertop, (actor->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH); + } +} + +// Function: A_MineRange +// Description: If the target gets too close, change the state to meleestate. +// +// var1 = Distance to alert at +// var2 = unused +// +void A_MineRange(mobj_t *actor) +{ + fixed_t dm; + INT32 locvar1 = var1; + // INT32 locvar2 = var2; + + if (LUA_CallAction("A_MineRange", actor)) + return; + + if (!actor->target) + return; + + dm = P_AproxDistance(actor->z - actor->target->z, P_AproxDistance(actor->y - actor->target->y, actor->x - actor->target->x)); + if ((dm>>FRACBITS) < locvar1) + P_SetMobjState(actor, actor->info->meleestate); +} + +// Function: A_ConnectToGround +// Description: Create a palm tree trunk/mine chain. +// +// var1 = Object type to connect to ground +// var2 = Object type to place on ground +// +void A_ConnectToGround(mobj_t *actor) +{ + mobj_t *work; + fixed_t workz; + fixed_t workh; + angle_t ang; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_ConnectToGround", actor)) + return; + + if (actor->subsector->sector->ffloors) + P_AdjustMobjFloorZ_FFloors(actor, actor->subsector->sector, 2); + + if (actor->flags2 & MF2_OBJECTFLIP) + workz = (actor->z + actor->height) - actor->ceilingz; + else + workz = actor->floorz - actor->z; + + if (locvar2) + { + workh = FixedMul(mobjinfo[locvar2].height, actor->scale); + if (actor->flags2 & MF2_OBJECTFLIP) + workz += workh; + work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar2); + workz += workh; + } + + if (!locvar1) + return; + + if (!(workh = FixedMul(mobjinfo[locvar1].height, actor->scale))) + return; + + ang = actor->angle + ANGLE_45; + while (workz < 0) + { + work = P_SpawnMobjFromMobj(actor, 0, 0, workz, locvar1); + if (work) + work->angle = ang; + ang += ANGLE_90; + workz += workh; + } + + if (workz != 0) + actor->z += P_MobjFlip(actor)*workz; +} + +// Function: A_SpawnParticleRelative +// +// Description: Spawns a particle effect relative to the location of the actor +// +// var1: +// var1 >> 16 = x +// var1 & 65535 = y +// var2: +// var2 >> 16 = z +// var2 & 65535 = state +// +void A_SpawnParticleRelative(mobj_t *actor) +{ + INT16 x, y, z; // Want to be sure we can use negative values + statenum_t state; + mobj_t *mo; + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_SpawnParticleRelative", actor)) + return; + + + CONS_Debug(DBG_GAMELOGIC, "A_SpawnParticleRelative called from object type %d, var1: %d, var2: %d\n", actor->type, locvar1, locvar2); + + x = (INT16)(locvar1>>16); + y = (INT16)(locvar1&65535); + z = (INT16)(locvar2>>16); + state = (statenum_t)(locvar2&65535); + + // Spawn objects correctly in reverse gravity. + // NOTE: Doing actor->z + actor->height is the bottom of the object while the object has reverse gravity. - Flame + mo = P_SpawnMobj(actor->x + FixedMul(x<scale), + actor->y + FixedMul(y<scale), + (actor->eflags & MFE_VERTICALFLIP) ? ((actor->z + actor->height - mobjinfo[MT_PARTICLE].height) - FixedMul(z<scale)) : (actor->z + FixedMul(z<scale)), MT_PARTICLE); + + // Spawn objects with an angle matching the spawner's, rather than spawning Eastwards - Monster Iestyn + mo->angle = actor->angle; + + if (actor->eflags & MFE_VERTICALFLIP) + mo->flags2 |= MF2_OBJECTFLIP; + + P_SetMobjState(mo, state); +} + +// Function: A_MultiShotDist +// +// Description: Spawns multiple shots based on player proximity +// +// var1 = same as A_MultiShot +// var2 = same as A_MultiShot +// +void A_MultiShotDist(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_MultiShotDist", actor)) + return; + + { + UINT8 i; + // Quick! Look through players! + // Don't spawn dust unless a player is relatively close by (var1). + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (1600<> 16 = mobjtype of child +// var2 & 65535 = vertical momentum +// var2: +// var2 >> 16 = forward offset +// var2 & 65535 = vertical offset +// +void A_WhoCaresIfYourSonIsABee(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t foffsetx; + fixed_t foffsety; + mobj_t *son; + + if (LUA_CallAction("A_WhoCaresIfYourSonIsABee", actor)) + return; + + A_FaceTarget(actor); + + if (actor->extravalue1) + actor->extravalue1--; + + if (actor->info->attacksound) + S_StartSound(actor, actor->info->attacksound); + + foffsetx = P_ReturnThrustX(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + foffsety = P_ReturnThrustY(actor, actor->angle, FixedMul((locvar2 >> 16)*FRACUNIT, actor->scale)); + + if (!(son = P_SpawnMobjFromMobj(actor, foffsetx, foffsety, (locvar2&65535)*FRACUNIT, (mobjtype_t)(locvar1 >> 16)))) + return; + + P_SetObjectMomZ(son, (locvar1 & 65535)<tracer, actor); + P_SetTarget(&son->target, actor->target); +} + +// Function: A_ParentTriesToSleep +// +// Description: If extravalue1 is less than or equal to var1, go to var2. +// +// var1 = state to go to when extravalue1 +// var2 = unused +// +void A_ParentTriesToSleep(mobj_t *actor) +{ + INT32 locvar1 = var1; + + if (LUA_CallAction("A_ParentTriesToSleep", actor)) + return; + + if (actor->extravalue1) + { + if (actor->info->seesound) + S_StartSound(actor, actor->info->seesound); + actor->reactiontime = 0; + P_SetMobjState(actor, locvar1); + } + else if (!actor->reactiontime) + { + actor->reactiontime = 1; + if (actor->info->activesound) // more like INactivesound doy hoy hoy + S_StartSound(actor, actor->info->activesound); + } +} + + +// Function: A_CryingToMomma +// +// Description: If you're a child, let your parent know something's happened to you through extravalue1. Also, prepare to die. +// +// var1 = unused +// var2 = unused +// +void A_CryingToMomma(mobj_t *actor) +{ + if (LUA_CallAction("A_CryingToMomma", actor)) + return; + + if (actor->tracer) + actor->tracer->extravalue1++; + + actor->momx = actor->momy = actor->momz = 0; + + P_UnsetThingPosition(actor); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } + actor->flags = MF_NOBLOCKMAP|MF_NOCLIPTHING; + P_SetThingPosition(actor); +} + +// Function: A_CheckFlags2 +// +// Description: If actor->flags2 & var1, goto var2. +// +// var1 = mask +// var2 = state to go +// +void A_CheckFlags2(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_CheckFlags2", actor)) + return; + + if (actor->flags2 & locvar1) + P_SetMobjState(actor, (statenum_t)locvar2); +} + +// Function: A_Boss5FindWaypoint +// +// Description: Finds the next waypoint in sequence and sets it as its tracer. +// +// var1 = if 1, always go to ambush-marked waypoint. if 2, go to MT_BOSSFLYPOINT. +// var2 = unused +// +void A_Boss5FindWaypoint(mobj_t *actor) +{ + INT32 locvar1 = var1; + boolean avoidcenter; + UINT32 i; + UINT8 extrainfo = (actor->spawnpoint ? actor->spawnpoint->extrainfo : 0); + + if (LUA_CallAction("A_Boss5FindWaypoint", actor)) + return; + + avoidcenter = !actor->tracer || (actor->health == actor->info->damage+1); + + if (locvar1 == 2) // look for the boss waypoint + { + thinker_t *th; + mobj_t *mo2; + P_SetTarget(&actor->tracer, NULL); + // Flee! Flee! Find a point to escape to! If none, just shoot upward! + // scan the thinkers to find the runaway point + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_BOSSFLYPOINT) + continue; + + if (mo2->spawnpoint && mo2->spawnpoint->extrainfo != extrainfo) + continue; + + // If this one's further then the last one, don't go for it. + if (actor->tracer && + P_AproxDistance(P_AproxDistance(actor->x - mo2->x, actor->y - mo2->y), actor->z - mo2->z) > + P_AproxDistance(P_AproxDistance(actor->x - actor->tracer->x, actor->y - actor->tracer->y), actor->z - actor->tracer->z)) + continue; + + // Otherwise... Do! + P_SetTarget(&actor->tracer, mo2); + } + if (!actor->tracer) + return; // no boss flypoints found + } + else if (locvar1 == 1) // always go to ambush-marked waypoint + { + if (avoidcenter) + goto nowaypoints; // if we can't go the center, why on earth are we doing this? + + for (i = 0; i < nummapthings; i++) + { + if (!mapthings[i].mobj) + continue; + if (mapthings[i].mobj->type != MT_FANGWAYPOINT) + continue; + if (mapthings[i].extrainfo != extrainfo) + continue; + if (!(mapthings[i].options & MTF_AMBUSH)) + continue; + + P_SetTarget(&actor->tracer, mapthings[i].mobj); + break; + } + + if (i == nummapthings) + goto nowaypoints; + } + else // locvar1 == 0 + { + fixed_t hackoffset = P_MobjFlip(actor)*56*FRACUNIT; + INT32 numfangwaypoints = 0; + mobj_t **fangwaypoints; + INT32 key; + + actor->z += hackoffset; + + // first, count how many waypoints we have + for (i = 0; i < nummapthings; i++) + { + if (!mapthings[i].mobj) + continue; + if (mapthings[i].mobj->type != MT_FANGWAYPOINT) + continue; + if (actor->tracer == mapthings[i].mobj) // this was your tracer last time + continue; + if (mapthings[i].extrainfo != extrainfo) + continue; + if (mapthings[i].options & MTF_AMBUSH) + { + if (avoidcenter) + continue; + } + else if (mapthings[i].mobj->reactiontime > 0) + continue; + if (!P_CheckSight(actor, mapthings[i].mobj)) + continue; + numfangwaypoints++; + } + + // players also count as waypoints apparently + if (actor->extravalue2 > 1) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].spectator) + continue; + if (players[i].mo->health <= 0) + continue; + if (players[i].powers[pw_flashing]) + continue; + if (actor->tracer == players[i].mo) // this was your tracer last time + continue; + if (!P_CheckSight(actor, players[i].mo)) + continue; + numfangwaypoints++; + } + } + + if (!numfangwaypoints) + { + // restore z position + actor->z -= hackoffset; + goto nowaypoints; // no waypoints :( + } + + // allocate the table and reset count to zero + fangwaypoints = Z_Calloc(sizeof(*tubewaypoints)*numfangwaypoints, PU_STATIC, NULL); + numfangwaypoints = 0; + + // now find them again and add them to the table! + for (i = 0; i < nummapthings; i++) + { + if (!mapthings[i].mobj) + continue; + if (mapthings[i].mobj->type != MT_FANGWAYPOINT) + continue; + if (actor->tracer == mapthings[i].mobj) // this was your tracer last time + continue; + if (mapthings[i].extrainfo != extrainfo) + continue; + if (mapthings[i].options & MTF_AMBUSH) + { + if (avoidcenter) + continue; + } + else if (mapthings[i].mobj->reactiontime > 0) + { + mapthings[i].mobj->reactiontime--; + continue; + } + if (!P_CheckSight(actor, mapthings[i].mobj)) + continue; + fangwaypoints[numfangwaypoints++] = mapthings[i].mobj; + } + + if (actor->extravalue2 > 1) + { + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].spectator) + continue; + if (players[i].mo->health <= 0) + continue; + if (players[i].powers[pw_flashing]) + continue; + if (actor->tracer == players[i].mo) // this was your tracer last time + continue; + if (!P_CheckSight(actor, players[i].mo)) + continue; + fangwaypoints[numfangwaypoints++] = players[i].mo; + } + } + + // restore z position + actor->z -= hackoffset; + + if (!numfangwaypoints) + { + Z_Free(fangwaypoints); // free table + goto nowaypoints; // ??? + } + + key = P_RandomKey(numfangwaypoints); + + P_SetTarget(&actor->tracer, fangwaypoints[key]); + if (actor->tracer->type == MT_FANGWAYPOINT) + actor->tracer->reactiontime = numfangwaypoints/4; // Monster Iestyn: is this how it should be? I count center waypoints as waypoints unlike the original Lua script + Z_Free(fangwaypoints); // free table + } + + // now face the tracer you just set! + A_FaceTracer(actor); + return; + +nowaypoints: + // no waypoints at all, guess the mobj has to disappear + if (actor->health) + P_KillMobj(actor, NULL, NULL, DMG_NORMAL); + else + P_RemoveMobj(actor); + return; +} + +// Function: A_DoNPCSkid +// +// Description: Something that looks like a player is skidding. +// +// var1 = state to change to upon being slow enough +// var2 = minimum speed +// +void A_DoNPCSkid(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t x, y, z; + + if (LUA_CallAction("A_DoNPCSkid", actor)) + return; + + x = actor->x; + y = actor->y; + z = actor->z; + + if (!locvar2) + locvar2 = FRACUNIT/2; + + if ((FixedHypot(actor->momx, actor->momy) < locvar2) + || !P_TryMove(actor, actor->x + actor->momx, actor->y + actor->momy, false)) + { + actor->momx = actor->momy = 0; + P_SetMobjState(actor, locvar1); + return; + } + else + { + actor->momx = (2*actor->momx)/3; + actor->momy = (2*actor->momy)/3; + } + + P_TeleportMove(actor, x, y, z); + + // Spawn a particle every 3 tics. + if (!(leveltime % 3)) + { + mobj_t *particle = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_SPINDUST); + particle->tics = 10; + + P_SetScale(particle, 2*actor->scale/3); + particle->destscale = actor->scale; + P_SetObjectMomZ(particle, FRACUNIT, false); + } +} + +// Function: A_DoNPCPain +// +// Description: Something that looks like a player was hit, put them in pain. +// +// var1 = If zero, always fling the same amount. +// Otherwise, slowly reduce the vertical +// and horizontal speed to the base value +// multiplied by this the more damage is done. +// var2 = If zero, use default fling values. +// Otherwise, vertical and horizontal speed +// will be multiplied by this. +// +void A_DoNPCPain(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t vspeed = 0; + fixed_t hspeed = FixedMul(4*FRACUNIT, actor->scale); + + if (LUA_CallAction("A_DoNPCPain", actor)) + return; + + actor->flags &= ~(MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT); + + var1 = var2 = 0; + A_Pain(actor); + + actor->z += P_MobjFlip(actor); + + if (actor->eflags & MFE_UNDERWATER) + vspeed = FixedDiv(10511*FRACUNIT,2600*FRACUNIT); + else + vspeed = FixedDiv(69*FRACUNIT,10*FRACUNIT); + + if (actor->target) + actor->angle = R_PointToAngle2(actor->x, actor->y, actor->target->x + actor->target->momx, actor->target->y + actor->target->momy); + + if (locvar1) + { + if (!actor->info->spawnhealth) + return; // there's something very wrong here if you're using this action on something with no starting health + locvar1 += ((FRACUNIT - locvar1)/actor->info->spawnhealth)*actor->health; + hspeed = FixedMul(hspeed, locvar1); + vspeed = FixedMul(vspeed, locvar1); + } + + if (locvar2) + { + hspeed = FixedMul(hspeed, locvar2); + vspeed = FixedMul(vspeed, locvar2); + } + + P_SetObjectMomZ(actor, vspeed, false); + P_InstaThrust(actor, actor->angle, -hspeed); +} + +// Function: A_PrepareRepeat +// +// Description: Simple way to prepare A_Repeat. +// +// var1 = value to set extravalue2 to +// var2 = unused +// +void A_PrepareRepeat(mobj_t *actor) +{ + INT32 locvar1 = var1; + + if (LUA_CallAction("A_PrepareRepeat", actor)) + return; + + actor->extravalue2 = locvar1; +} + +// Function: A_Boss5ExtraRepeat +// +// Description: Simple way to prepare A_Repeat. +// +// var1 = maximum value to setextravalue2 to (normally) +// var2 = pinch annoyance +// +void A_Boss5ExtraRepeat(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + INT32 calc; + INT32 locspawn; + INT32 lochealth; + + if (LUA_CallAction("A_Boss5ExtraRepeat", actor)) + return; + + if (actor->extravalue2 > 0 && !(actor->flags2 & MF2_FRET)) + return; + + locspawn = actor->info->spawnhealth - actor->info->damage; + lochealth = actor->health - actor->info->damage; + + if (locspawn <= 0 || lochealth <= 0) + calc = locvar1; + else + calc = (locvar1*(locspawn - lochealth))/locspawn; + + if (calc > 2) + actor->extravalue2 = 1 + calc/2 + P_RandomKey(calc/2); + else + actor->extravalue2 = 1 + calc; + + if (lochealth <= 0) + actor->extravalue2 += locvar2; +} + +// Function: A_Boss5Calm +// +// Description: Simple way to disable MF2_FRET (and enable MF_SHOOTABLE the first time it's called) +// +// var1 = unused +// var2 = unused +// +void A_Boss5Calm(mobj_t *actor) +{ + if (LUA_CallAction("A_Boss5Calm", actor)) + return; + + actor->flags |= MF_SHOOTABLE; + actor->flags2 &= ~MF2_FRET; +} + +// Function: A_Boss5CheckOnGround +// +// Description: Ground checker. +// +// var1 = state to change to upon hitting ground. +// var2 = state to change to upon hitting ground if health == pinchhealth, assuming it exists +// +void A_Boss5CheckOnGround(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_Boss5CheckOnGround", actor)) + return; + + if ((!(actor->eflags & MFE_VERTICALFLIP) && actor->z <= actor->floorz) + || (actor->eflags & MFE_VERTICALFLIP && actor->z + actor->height >= actor->ceilingz)) + { + if (locvar2 && (!actor->health || (actor->health == actor->info->damage && !(actor->flags2 & MF2_STRONGBOX)))) + P_SetMobjState(actor, locvar2); + else + P_SetMobjState(actor, locvar1); + } + + if (actor->tracer && P_AproxDistance(actor->tracer->x - actor->x, actor->tracer->y - actor->y) < 2*actor->radius) + { + actor->momx = (4*actor->momx)/5; + actor->momy = (4*actor->momy)/5; + } +} + +// Function: A_Boss5CheckFalling +// +// Description: Falling checker. +// +// var1 = state to change to when hitting ground. +// var2 = state to change to when falling. +// +void A_Boss5CheckFalling(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_Boss5CheckFalling", actor)) + return; + + if (actor->health && actor->extravalue2 > 1) + { + var1 = locvar1; + var2 = 0; + A_Boss5CheckOnGround(actor); + return; + } + + if (P_MobjFlip(actor)*actor->momz <= 0) + P_SetMobjState(actor, locvar2); +} + +// Function: A_Boss5PinchShot +// +// Description: Fires a missile directly upwards if in pinch. +// +// var1 = object # to shoot +// var2 = height offset (from default of +48 FU) +// +void A_Boss5PinchShot(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t zoffset; + mobj_t *missile; + + if (LUA_CallAction("A_Boss5PinchShot", actor)) + return; + + if (actor->health > actor->info->damage) + return; + + if (actor->eflags & MFE_VERTICALFLIP) + zoffset = actor->z + actor->height - FixedMul((48 + locvar2)*FRACUNIT, actor->scale); + else + zoffset = actor->z + FixedMul((48 + locvar2)*FRACUNIT, actor->scale); + + missile = P_SpawnPointMissile(actor, actor->x, actor->y, zoffset, locvar1, + actor->x, actor->y, zoffset); + + if (!missile) + return; + + missile->momx = missile->momy = 0; + missile->momz = P_MobjFlip(actor)*missile->info->speed/2; +} + +// Function: A_Boss5MakeItRain +// +// Description: Pinch crisis. +// +// var1 = object # to shoot +// var2 = height offset (from default of +48 FU) +// +void A_Boss5MakeItRain(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + INT32 offset = (48 + locvar2)<<16; // upper 16 bits, not fixed_t! + INT32 i; + + if (LUA_CallAction("A_Boss5MakeItRain", actor)) + return; + + actor->flags2 |= MF2_STRONGBOX; + + var1 = locvar1; + var2 = offset + 90; + A_TrapShot(actor); + + for (i = 0; i < 8; i++) + { + actor->angle += ANGLE_45; + + var1 = locvar1; + var2 = offset + (i & 1) ? 80 : 85; + A_TrapShot(actor); + } + + actor->extravalue2 = 0; +} + +// Function: A_Boss5MakeJunk +// +// Description: Make a mess. +// +// var1 = state # to set on MT_BROKENROBOT (if 0 do nothing, if -1 go to if colorized) +// var2 = mode (-1 = spin, 0 = make 1, & 1 make 8, & 2 alart mode) +// +void A_Boss5MakeJunk(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + mobj_t *broked = NULL; + angle_t ang; + INT32 i = ((locvar2 & 1) ? 8 : 1); + + if (LUA_CallAction("A_Boss5MakeJunk", actor)) + return; + + if (locvar1 < 0 && (actor->flags2 & MF2_SLIDEPUSH)) // this entire action is a hack, don't judge me + { + INT32 curextravalue2 = actor->extravalue2; + P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_PROJECTORLIGHT); + actor->z += P_MobjFlip(actor)*actor->height; + actor->flags |= MF_NOGRAVITY; + S_StartSound(actor, sfx_vwre); + actor->extravalue2 = 49; + P_SetMobjState(actor, -locvar1); + actor->extravalue2 = curextravalue2; + actor->angle -= FixedAngle((49*45)<extravalue2)/50; + if (trans > 9) + trans = 9; + if (trans < 0) + trans = 0; + if (!(actor->extravalue2 & 1)) + { + if (actor->extravalue2 > 10) + { + mobj_t *front = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_VWREF); + broked = P_SpawnMobjFromMobj(front, 0, 0, 0, MT_VWREB); + front->z = broked->z = front->z - broked->height; + P_SetObjectMomZ(front, (4<momz = front->momz; + broked->fuse = front->fuse = (actor->height+(2*front->height))/front->momz; + } + if (!(actor->colorized = !actor->colorized)) + actor->frame |= FF_FULLBRIGHT; + } + actor->angle += ANGLE_45; + actor->frame = (actor->frame & ~FF_TRANSMASK)|(trans<fuse = TICRATE; + else + broked->fuse = (((locvar2 & 1) ? 4 : 2)*TICRATE)/3; + broked->angle = ang; + P_InstaThrust(broked, ang, ((locvar2 & 2) ? 8 : 5)*actor->scale); + P_SetObjectMomZ(broked, (((locvar2) ? 4 : 0) + P_RandomRange(2, 5))< 0) + P_SetMobjState(broked, locvar1); + if (!P_MobjWasRemoved(broked)) + P_TeleportMove(broked, broked->x + broked->momx, broked->y + broked->momy, broked->z); + ang += ANGLE_45; + } + + if (locvar2 & 2) + { + broked = P_SpawnMobjFromMobj(actor, 0, 0, 64<fuse = states[S_FANG_INTRO12].tics+10; + P_SetMobjState(broked, S_ALART1); + } + else if (locvar2 & 1) + { + broked->z += broked->momz; + S_StartSound(actor, sfx_s3kccs); + actor->flags &= ~MF_NOCLIPTHING; + } + else + S_StartSound(actor, sfx_s3kd3s); +} + +// Function: A_LookForBetter +// +// Description: A_Look, except it finds a better target in multiplayer, and doesn't lose the target in singleplayer. +// +// var1 lower 16 bits = 0 - looks only in front, 1 - looks all around +// var1 upper 16 bits = distance limit +// var2 = unused +// +void A_LookForBetter(mobj_t *actor) +{ + INT32 locvar1 = var1; + + if (LUA_CallAction("A_LookForBetter", actor)) + return; + + P_LookForPlayers(actor, (locvar1 & 65535), false, FixedMul((locvar1 >> 16)*FRACUNIT, actor->scale)); + A_FaceTarget(actor); +} + +/* * Spawns a dust ring. + * The dust ring behaves slightly randomly so it doesn't look too uniform. + * + * \param mobjtype Thing type to make a ring of. + * \param div Amount of things to spawn on the ring. + * \param x Center X coordinates. + * \param y Center Y coordinates. + * \param z Center Z coordinates. + * \param radius Radius. + * \param speed Additional thrust on particles. + * \param initscale Initial scale when spawning. + * \param scale "Default" scale. + */ +static void P_DustRing(mobjtype_t mobjtype, UINT32 div, fixed_t x, fixed_t y, fixed_t z, fixed_t radius, fixed_t speed, fixed_t initscale, fixed_t scale) +{ + angle_t ang = FixedAngle(FixedDiv(360*FRACUNIT, div*FRACUNIT)); //(ANGLE_180/div)*2; + UINT32 i; + + // it turned out the radius was effectively nullified thanks to errors in the original script + // BUT people preferred how it looked before I "fixed" it, so I got rid of the radius calculations altogether + // this was a bit of a mess to sort out, but at least it's probably somewhat fine now? + // -- Monster Iestyn (21/05/19) + (void)radius; + + for (i = 0; i < div; i++) + { + mobj_t *dust = P_SpawnMobj( + x, //+ FixedMul(radius, FINECOSINE((ang*i) >> ANGLETOFINESHIFT)), + y, //+ FixedMul(radius, FINESINE((ang*i) >> ANGLETOFINESHIFT)), + z, + mobjtype + ); + + dust->angle = ang*i + ANGLE_90; + P_SetScale(dust, FixedMul(initscale, scale)); + dust->destscale = FixedMul(4*FRACUNIT + P_RandomFixed(), scale); + dust->scalespeed = scale/24; + P_Thrust(dust, ang*i, speed + FixedMul(P_RandomFixed(), scale)); + dust->momz = P_SignedRandom()*scale/64; + } +} + +// Function: A_Boss5BombExplode +// +// Description: Boss 5's bomb exploding. +// +// var1 = Thing type to spawn as dust +// var2 = unused +// +void A_Boss5BombExplode(mobj_t *actor) +{ + INT32 locvar1 = var1; + + if (LUA_CallAction("A_Boss5BombExplode", actor)) + return; + + // The original Lua script did not use |= to add flags but just set these flags exactly apparently? + // (I may modify this later) + // -- Monster Iestyn (21/05/19) + actor->flags = MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP; + actor->flags2 = MF2_EXPLOSION; + + if (actor->target) + P_RadiusAttack(actor, actor->target, 7*actor->radius, 0, true); + + P_DustRing(locvar1, 4, actor->x, actor->y, actor->z+actor->height, 2*actor->radius, 0, FRACUNIT, actor->scale); + P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 3*actor->radius, FRACUNIT, FRACUNIT, actor->scale); + //P_StartQuake(9*actor->scale, TICRATE/6, {actor->x, actor->y, actor->z}, 20*actor->radius); + // the above does not exist, so we set the quake values directly instead + quake.intensity = 9*actor->scale; + quake.time = TICRATE/6; + // the following quake values have no effect atm? ah well, may as well set them anyway + { + mappoint_t q_epicenter = {actor->x, actor->y, actor->z}; + quake.epicenter = &q_epicenter; + } + quake.radius = 20*actor->radius; +} + +// stuff used by A_TNTExplode +static mobj_t *barrel; +static fixed_t exploderadius; +static fixed_t explodethrust; + +static boolean PIT_TNTExplode(mobj_t *nearby) +{ + fixed_t dx, dy, dz; + fixed_t dm; + + if (nearby == barrel) + return true; + + dx = nearby->x - barrel->x; + dy = nearby->y - barrel->y; + dz = nearby->z - barrel->z + (nearby->height - barrel->height/2)/2; + dm = P_AproxDistance(P_AproxDistance(dx, dy), dz); + + if (dm >= exploderadius || !P_CheckSight(barrel, nearby)) // out of range or not visible + return true; + + if (barrel->type == nearby->type) // nearby is also a barrel + { + if (nearby->state == &states[nearby->info->spawnstate]) + { + if (barrel->info->attacksound) + S_StartSound(nearby, barrel->info->attacksound); + nearby->momx = FixedMul(FixedDiv(dx, dm), explodethrust); + nearby->momy = FixedMul(FixedDiv(dy, dm), explodethrust); + nearby->momz = FixedMul(FixedDiv(dz, dm), explodethrust); + P_UnsetThingPosition(nearby); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } + nearby->flags = MF_NOBLOCKMAP|MF_MISSILE; + P_SetThingPosition(nearby); + P_SetMobjState(nearby, nearby->info->missilestate); + } + } + else + { + if (barrel->target == nearby) + { + mobj_t *tar = barrel->target; // temporarily store barrel's target + P_SetTarget(&barrel->target, NULL); + P_DamageMobj(nearby, barrel, NULL, 1, DMG_NORMAL); + if (!P_MobjWasRemoved(barrel)) + P_SetTarget(&barrel->target, tar); + } + else + { + P_DamageMobj(nearby, + (barrel->target) ? barrel->target : barrel, + (barrel->target) ? barrel->target : barrel, + 1, DMG_NORMAL); + } + } + + return true; +} + +// Function: A_TNTExplode +// +// Description: Creates a TNT explosion. Used by TNT barrels and the like. +// +// var1 = Thing type to spawn as dust. +// var2 = unused +// +void A_TNTExplode(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 x, y; + INT32 xl, xh, yl, yh; + static mappoint_t epicenter = {0,0,0}; + + if (LUA_CallAction("A_TNTExplode", actor)) + return; + + if (actor->tracer) + { + P_SetTarget(&actor->tracer->tracer, NULL); + P_SetTarget(&actor->tracer, NULL); + } + + P_UnsetThingPosition(actor); + if (sector_list) + { + P_DelSeclist(sector_list); + sector_list = NULL; + } + actor->flags = MF_NOCLIP|MF_NOGRAVITY|MF_NOBLOCKMAP; + P_SetThingPosition(actor); + actor->flags2 = MF2_EXPLOSION; + if (actor->info->deathsound) + S_StartSound(actor, actor->info->deathsound); + + explodethrust = 32*FRACUNIT; + exploderadius = 256*FRACUNIT; + + xl = (unsigned)(actor->x - exploderadius - bmaporgx)>>MAPBLOCKSHIFT; + xh = (unsigned)(actor->x + exploderadius - bmaporgx)>>MAPBLOCKSHIFT; + yl = (unsigned)(actor->y - exploderadius - bmaporgy)>>MAPBLOCKSHIFT; + yh = (unsigned)(actor->y + exploderadius - bmaporgy)>>MAPBLOCKSHIFT; + + BMBOUNDFIX(xl, xh, yl, yh); + + barrel = actor; + + for (x = xl; x <= xh; x++) + for (y = yl; y <= yh; y++) + P_BlockThingsIterator(x, y, PIT_TNTExplode); + + // cause a quake -- P_StartQuake does not exist yet + epicenter.x = actor->x; + epicenter.y = actor->y; + epicenter.z = actor->z; + quake.intensity = 9*FRACUNIT; + quake.time = TICRATE/6; + quake.epicenter = &epicenter; + quake.radius = 512*FRACUNIT; + + if (locvar1) + { + P_DustRing(locvar1, 4, actor->x, actor->y, actor->z+actor->height, 64, 0, FRACUNIT, actor->scale); + P_DustRing(locvar1, 6, actor->x, actor->y, actor->z+actor->height/2, 96, FRACUNIT, FRACUNIT, actor->scale); + } + + actor->destscale *= 4; +} + +// Function: A_DebrisRandom +// +// Description: Randomizes debris frame and movement. +// +// var1 = Frame range. +// var2 = unused +// +void A_DebrisRandom(mobj_t *actor) +{ + INT32 locvar1 = var1; + + if (LUA_CallAction("A_DebrisRandom", actor)) + return; + + actor->frame |= P_RandomRange(0, locvar1); + var1 = 0; + var2 = 359; + A_ChangeAngleAbsolute(actor); + P_Thrust(actor, actor->angle, FRACUNIT * 2); +} + +static mobj_t *P_TrainSeg(mobj_t *src, fixed_t x, fixed_t y, fixed_t z, angle_t ang, spritenum_t spr, UINT32 frame) +{ + mobj_t *s = P_SpawnMobj(x, y, z, MT_TRAINSEG); + s->fuse = 16*TICRATE; + s->sprite = spr; + s->frame = frame|FF_PAPERSPRITE; + s->angle = ang; + P_Thrust(s, src->angle, 7*FRACUNIT); + return s; +} + +// Function: A_TrainCameo +// +// Description: Sets up train cameo locomotive. +// +// var1 = Train width. +// var2 = Train length. +// +void A_TrainCameo(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t x = actor->x; + fixed_t y = actor->y; + fixed_t z = actor->z; + angle_t ang = actor->angle; + mobj_t *m; + spritenum_t spr = SPR_TRAE; + fixed_t span = locvar1*FRACUNIT; + fixed_t len = locvar2*FRACUNIT; + + if (LUA_CallAction("A_TrainCameo", actor)) + return; + + //Spawn sides. + P_TrainSeg(actor, x, y + span, z, ang, spr, 0); + P_TrainSeg(actor, x, y - span, z, ang, spr, 0); + + //Center. + P_TrainSeg(actor, x, y, z, ang, spr, 1); + + //Front and back. + P_TrainSeg(actor, x + len, y, z, ang + ANGLE_90, spr, 2); + P_TrainSeg(actor, x - len, y, z, ang + ANGLE_90, spr, 2); + + //Smoke spawner. + m = P_TrainSeg(actor, x - (20 * FRACUNIT), y, z + (30 * FRACUNIT), ang + ANGLE_90, spr, 0); + P_SetMobjState(m, S_TRAINPUFFMAKER); +} + +// Function: A_TrainCameo2 +// +// Description: Sets up train cameo wagon. +// +// var1 = Train width. +// var2 = Train length. +// +void A_TrainCameo2(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t x = actor->x; + fixed_t y = actor->y; + fixed_t z = actor->z; + angle_t ang = actor->angle; + spritenum_t spr = SPR_TRAI; + fixed_t span = locvar1*FRACUNIT; + fixed_t len = locvar2*FRACUNIT; + + if (LUA_CallAction("A_TrainCameo2", actor)) + return; + + //Spawn sides. + P_TrainSeg(actor, x, y + span, z, ang, spr, 0); + P_TrainSeg(actor, x, y - span, z, ang, spr, 0); + + //Center. + P_TrainSeg(actor, x, y, z, ang, spr, 1); + + //Front and back. + P_TrainSeg(actor, x + len, y, z, ang + ANGLE_90, spr, 2); + P_TrainSeg(actor, x - len, y, z, ang + ANGLE_90, spr, 2); +} + +// Function: A_CanarivoreGas +// +// Description: Releases gas clouds. Used by the Canarivore. +// +// var1 = Mobj type. +// var2 = Unused +// +void A_CanarivoreGas(mobj_t *actor) +{ + INT32 locvar1 = var1; + + if (LUA_CallAction("A_CanarivoreGas", actor)) + return; + + P_DustRing(locvar1, 4, actor->x, actor->y, actor->z + actor->height / 5, 18, 0, FRACUNIT/10, actor->scale); + P_DustRing(locvar1, 6, actor->x, actor->y, actor->z + actor->height / 5, 28, FRACUNIT, FRACUNIT/10, actor->scale); +} + +// +// Function: A_KillSegments +// +// Description: Causes segments attached via tracer chain to be killed. +// +// var1 = Fuse (if 0, default to TICRATE/2). +// var2 = Unused +// +void A_KillSegments(mobj_t *actor) +{ + INT32 locvar1 = var1; + mobj_t *seg = actor->tracer; + INT32 fuse = locvar1 ? locvar1 : TICRATE/2; + + if (LUA_CallAction("A_KillSegments", actor)) + return; + + while (seg) + { + mobj_t *kseg = seg; + seg = seg->tracer; + + kseg->flags = MF_NOBLOCKMAP; + kseg->flags2 = 0; + kseg->fuse = fuse; + P_Thrust(kseg, R_PointToAngle2(actor->x, actor->y, kseg->x, kseg->y), 3*actor->scale); + kseg->momz = 3*actor->scale; + } +} + +static void P_SnapperLegPlace(mobj_t *mo) +{ + mobj_t *seg = mo->tracer; + angle_t a = mo->angle; + angle_t fa = (a >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t c = FINECOSINE(fa); + fixed_t s = FINESINE(fa); + fixed_t x, y; + INT32 o1, o2; + INT32 woffset = mo->extravalue1; + INT32 side = mo->extravalue2; + INT32 alt; + + // Move head first. + fixed_t rad = mo->radius; + INT32 necklen = (32*(mo->info->reactiontime - mo->reactiontime))/mo->info->reactiontime; // Not in FU + + seg->z = mo->z + ((mo->eflags & MFE_VERTICALFLIP) ? (((mo->height<<1)/3) - seg->height) : mo->height/3); + P_TryMove(seg, mo->x + FixedMul(c, rad) + necklen*c, mo->y + FixedMul(s, rad) + necklen*s, true); + seg->angle = a; + + // Move as many legs as available. + seg = seg->tracer; + do + { + o1 = seg->extravalue1; + o2 = seg->extravalue2; + alt = seg->cusval; + + if (alt == 1) + o2 += woffset; + else + o2 -= woffset; + + if (alt != side) + { + x = c*o2 + s*o1; + y = s*o2 - c*o1; + seg->z = mo->z + (((mo->eflags & MFE_VERTICALFLIP) ? (mo->height - seg->height) : 0)); + P_TryMove(seg, mo->x + x, mo->y + y, true); + P_SetMobjState(seg, seg->info->raisestate); + } + else + P_SetMobjState(seg, seg->info->spawnstate); + + seg->angle = R_PointToAngle2(mo->x, mo->y, seg->x, seg->y); + + seg = seg->tracer; + } while (seg); +} + +// +// Function: A_SnapperSpawn +// +// Description: Sets up Green Snapper legs and head. +// +// var1 = Leg mobj type. +// var2 = Head mobj type. +// +void A_SnapperSpawn(mobj_t *actor) +{ + mobjtype_t legtype = (mobjtype_t)var1; + mobjtype_t headtype = (mobjtype_t)var2; + mobj_t *ptr = actor; + INT32 i; + mobj_t *seg; + + if (LUA_CallAction("A_SnapperSpawn", actor)) + return; + + // It spawns 1 head. + seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, headtype); + P_SetTarget(&ptr->tracer, seg); + ptr = seg; + + // It spawns 4 legs which will be handled in the thinker function. + for (i = 1; i <= 4; i++) + { + seg = P_SpawnMobjFromMobj(actor, 0, 0, 0, legtype); + P_SetTarget(&ptr->tracer, seg); + ptr = seg; + + // The legs' base offsets are stored as extravalues, as relative coordinates in xy space. + seg->extravalue1 = 28; + seg->extravalue2 = 28; + if (i % 2) + seg->extravalue1 = -seg->extravalue1; + + if ((i/2) % 2) + seg->extravalue2 = -seg->extravalue2; + + // Alternating motion stuff. + seg->cusval = ((i + 1)/2) % 2; + } + + actor->extravalue1 = 0; + actor->extravalue2 = 0; + P_SnapperLegPlace(actor); +} + +// +// Function: A_SnapperThinker +// +// Description: Thinker for Green Snapper. +// +// var1 = Unused +// var2 = Unused +// +void A_SnapperThinker(mobj_t *actor) +{ + fixed_t x0 = actor->x; + fixed_t y0 = actor->y; + fixed_t xs, ys; + fixed_t x1, y1; + fixed_t dist; + boolean chasing; + + if (LUA_CallAction("A_SnapperThinker", actor)) + return; + + // We make a check just in case there's no spawnpoint. + if (actor->spawnpoint) + { + xs = actor->spawnpoint->x*FRACUNIT; + ys = actor->spawnpoint->y*FRACUNIT; + } + else + { + xs = x0; + ys = y0; + } + + // Look for nearby, valid players to chase angrily at. + if ((actor->target || P_LookForPlayers(actor, true, false, 1024*FRACUNIT)) + && P_AproxDistance(actor->target->x - xs, actor->target->y - ys) < 2048*FRACUNIT + && abs(actor->target->z - actor->z) < 80*FRACUNIT + && P_CheckSight(actor, actor->target)) + { + chasing = true; + x1 = actor->target->x; + y1 = actor->target->y; + } + else + { + chasing = false; + x1 = xs; + y1 = ys; + } + + dist = P_AproxDistance(x1 - x0, y1 - y0); + + // The snapper either chases what it considers to be a nearby player, or instead decides to go back to its spawnpoint. + if (chasing || dist > 32*FRACUNIT) + { + INT32 speed = actor->info->speed + actor->info->reactiontime - actor->reactiontime; + + angle_t maxang = FixedAngle(speed*FRACUNIT/2); + angle_t ang = actor->angle; + angle_t realang = R_PointToAngle2(x0, y0, x1, y1); + angle_t dif = realang - ang; + angle_t fa; + fixed_t c, s; + + if (dif < ANGLE_180 && dif > maxang) + actor->angle += maxang; + else if (dif >= ANGLE_180 && dif < InvAngle(maxang)) + actor->angle -= maxang; + else + actor->angle = realang; + + fa = (actor->angle >> ANGLETOFINESHIFT) & FINEMASK; + c = FINECOSINE(fa); + s = FINESINE(fa); + + P_TryMove(actor, actor->x + c*speed, actor->y + s*speed, false); + + // The snapper spawns dust if going fast! + if (actor->reactiontime < 4) + { + mobj_t *dust = P_SpawnMobj(x0, y0, actor->z, MT_SPINDUST); + P_Thrust(dust, ang + ANGLE_180 + FixedAngle(P_RandomRange(-20, 20)*FRACUNIT), speed*FRACUNIT); + } + + if (actor->extravalue2 == 0) + { + if (actor->extravalue1 > 16) + { + A_PlayActiveSound(actor); + actor->extravalue2 = 1; + + // If the snapper is chasing, accelerate; otherwise, decelerate. + if (chasing) + actor->reactiontime = max(0, actor->reactiontime - 1); + else + actor->reactiontime = min(actor->info->reactiontime, actor->reactiontime + 1); + } + else + actor->extravalue1 += speed; + } + else + { + if (actor->extravalue1 < -16) + { + A_PlayActiveSound(actor); + actor->extravalue2 = 0; + + // If the snapper is chasing, accelerate; otherwise, decelerate. + if (chasing) + actor->reactiontime = max(0, actor->reactiontime - 1); + else + actor->reactiontime = min(actor->info->reactiontime, actor->reactiontime + 1); + } + else + actor->extravalue1 -= speed; + } + } + + P_SnapperLegPlace(actor); +} + +// Function: A_SaloonDoorSpawn +// +// Description: Spawns a saloon door. +// +// var1 = mobjtype for sides +// var2 = distance sides should be placed apart +// +void A_SaloonDoorSpawn(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + angle_t ang = actor->angle; + angle_t fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t c = FINECOSINE(fa)*locvar2; + fixed_t s = FINESINE(fa)*locvar2; + mobj_t *door; + mobjflag2_t ambush = (actor->flags2 & MF2_AMBUSH); + + if (LUA_CallAction("A_SaloonDoorSpawn", actor)) + return; + + if (!locvar1) + return; + + // One door... + if (!(door = P_SpawnMobjFromMobj(actor, c, s, 0, locvar1))) return; + door->angle = ang + ANGLE_180; + door->extravalue1 = AngleFixed(door->angle); // Origin angle + door->extravalue2 = 0; // Angular speed + P_SetTarget(&door->tracer, actor); // Origin door + door->flags2 |= ambush; // Can be opened by normal players? + + // ...two door! + if (!(door = P_SpawnMobjFromMobj(actor, -c, -s, 0, locvar1))) return; + door->angle = ang; + door->extravalue1 = AngleFixed(door->angle); // Origin angle + door->extravalue2 = 0; // Angular speed + P_SetTarget(&door->tracer, actor); // Origin door + door->flags2 |= ambush; // Can be opened by normal players? +} + +// Function: A_MinecartSparkThink +// +// Description: Thinker for the minecart spark. +// +// var1 = unused +// var2 = unused +// +void A_MinecartSparkThink(mobj_t *actor) +{ + fixed_t dx = actor->momx; + fixed_t dy = actor->momy; + fixed_t dz, dm; + UINT8 i; + + if (LUA_CallAction("A_MinecartSparkThink", actor)) + return; + + if (actor->momz == 0 && P_IsObjectOnGround(actor)) + actor->momz = P_RandomRange(2, 4)*FRACUNIT; + + dz = actor->momz; + dm = FixedHypot(FixedHypot(dx, dy), dz); + dx = FixedDiv(dx, dm); + dy = FixedDiv(dy, dm); + dz = FixedDiv(dz, dm); + + for (i = 1; i <= 8; i++) + { + mobj_t *trail = P_SpawnMobj(actor->x - dx*i, actor->y - dy*i, actor->z - dz*i, MT_PARTICLE); + trail->tics = 2; + trail->sprite = actor->sprite; + P_SetScale(trail, trail->scale/4); + trail->destscale = trail->scale; + } +} + +// Function: A_ModuloToState +// +// Description: Modulo operation to state +// +// var1 = Modulo +// var2 = State +// +void A_ModuloToState(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_ModuloToState", actor)) + return; + + if ((modulothing % locvar1 == 0)) + P_SetMobjState(actor, (locvar2)); + modulothing++; +} + +// Function: A_LavafallRocks +// +// Description: Spawn random rock particles. +// +// var1 = unused +// var2 = unused +// +void A_LavafallRocks(mobj_t *actor) +{ + UINT8 i; + + if (LUA_CallAction("A_LavafallRocks", actor)) + return; + + // Don't spawn rocks unless a player is relatively close by. + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (actor->info->speed >> 1)) + break; // Stop looking. + + if (i < MAXPLAYERS) + { + angle_t fa = (FixedAngle(P_RandomKey(360) << FRACBITS) >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t offset = P_RandomRange(4, 12) << FRACBITS; + fixed_t xoffs = FixedMul(FINECOSINE(fa), actor->radius + offset); + fixed_t yoffs = FixedMul(FINESINE(fa), actor->radius + offset); + P_SpawnMobjFromMobj(actor, xoffs, yoffs, 0, MT_LAVAFALLROCK); + } +} + +// Function: A_LavafallLava +// +// Description: Spawn lava from lavafall. +// +// var1 = unused +// var2 = unused +// +void A_LavafallLava(mobj_t *actor) +{ + mobj_t *lavafall; + UINT8 i; + + if (LUA_CallAction("A_LavafallLava", actor)) + return; + + if ((40 - actor->fuse) % (2*(actor->scale >> FRACBITS))) + return; + + // Don't spawn lava unless a player is nearby. + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(actor->x - players[i].mo->x, actor->y - players[i].mo->y) < (actor->info->speed)) + break; // Stop looking. + + if (i >= MAXPLAYERS) + return; + + lavafall = P_SpawnMobjFromMobj(actor, 0, 0, -8*FRACUNIT, MT_LAVAFALL_LAVA); + lavafall->momz = -P_MobjFlip(actor)*25*FRACUNIT; +} + +// Function: A_FallingLavaCheck +// +// Description: If actor hits the ground or a water surface, enter the death animation. +// +// var1 = unused +// var2 = unused +// +void A_FallingLavaCheck(mobj_t *actor) +{ + if (LUA_CallAction("A_FallingLavaCheck", actor)) + return; + + if (actor->eflags & MFE_TOUCHWATER || P_IsObjectOnGround(actor)) + { + actor->flags = MF_NOGRAVITY|MF_NOCLIPTHING; + actor->momz = 0; + if (actor->eflags & MFE_TOUCHWATER) + actor->z = (actor->eflags & MFE_VERTICALFLIP) ? actor->waterbottom : actor->watertop; + P_SetMobjState(actor, actor->info->deathstate); + } +} + +// Function: A_FireShrink +// +// Description: Shrink the actor down to the specified scale at the specified speed. +// +// var1 = Scale to shrink to +// var2 = Shrinking speed +// +void A_FireShrink(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_FireShrink", actor)) + return; + + actor->destscale = locvar1; + actor->scalespeed = FRACUNIT/locvar2; +} + +// Function: A_SpawnPterabytes +// +// Description: Spawn Pterabytes around the actor in a circle. +// +// var1 = unused +// var2 = unused +// +void A_SpawnPterabytes(mobj_t *actor) +{ + mobj_t *waypoint, *ptera; + fixed_t c, s; + fixed_t rad = 280*FRACUNIT; + angle_t ang = 0; + angle_t interval, fa; + UINT8 amount = 1; + UINT8 i; + + if (LUA_CallAction("A_SpawnPterabytes", actor)) + return; + + if (actor->spawnpoint) + amount = actor->spawnpoint->extrainfo + 1; + + interval = FixedAngle(FRACUNIT*360/amount); + + for (i = 0; i < amount; i++) + { + fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; + c = FINECOSINE(fa); + s = FINESINE(fa); + waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT); + waypoint->angle = ang + ANGLE_90; + P_SetTarget(&waypoint->tracer, actor); + ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE); + ptera->angle = waypoint->angle; + P_SetTarget(&ptera->tracer, waypoint); + ptera->extravalue1 = 0; + ang += interval; + } +} + +// Function: A_PterabyteHover +// +// Description: Hover in a circular fashion, bobbing up and down slightly. +// +// var1 = unused +// var2 = unused +// +void A_PterabyteHover(mobj_t *actor) +{ + angle_t ang, fa; + + if (LUA_CallAction("A_PterabyteHover", actor)) + return; + + P_InstaThrust(actor, actor->angle, actor->info->speed); + actor->angle += ANG1; + actor->extravalue1 = (actor->extravalue1 + 3) % 360; + ang = actor->extravalue1*ANG1; + fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; + actor->z += FINESINE(fa); +} +// Function: A_RolloutSpawn +// +// Description: Spawns a new Rollout Rock when the currently spawned rock is destroyed or moves far enough away. +// +// var1 = Distance currently spawned rock should travel before spawning a new one +// var2 = Object type to spawn +// +void A_RolloutSpawn(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + + if (LUA_CallAction("A_RolloutSpawn", actor)) + return; + + if (!(actor->target) + || P_MobjWasRemoved(actor->target) + || P_AproxDistance(actor->x - actor->target->x, actor->y - actor->target->y) > locvar1) + { + actor->target = P_SpawnMobj(actor->x, actor->y, actor->z, locvar2); + actor->target->flags2 |= (actor->flags2 & (MF2_AMBUSH | MF2_OBJECTFLIP)) | MF2_SLIDEPUSH; + actor->target->eflags |= (actor->eflags & MFE_VERTICALFLIP); + + if (actor->target->flags2 & MF2_AMBUSH) + { + actor->target->color = SKINCOLOR_SUPERRUST3; + actor->target->colorized = true; + } + } +} + +// Function: A_RolloutRock +// +// Description: Thinker for Rollout Rock. +// +// var1 = Drag +// var2 = Vertical bobbing speed factor +// +void A_RolloutRock(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + UINT8 maxframes = actor->info->reactiontime; // number of frames the mobj cycles through + fixed_t pi = (22*FRACUNIT/7); + fixed_t circumference = FixedMul(2 * pi, actor->radius); // used to calculate when to change frame + fixed_t speed = P_AproxDistance(actor->momx, actor->momy), topspeed = FixedMul(actor->info->speed, actor->scale); + boolean inwater = actor->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER); + + if (LUA_CallAction("A_RolloutRock", actor)) + return; + + actor->friction = FRACUNIT; // turns out riding on solids sucks, so let's just make it easier on ourselves + + if (actor->eflags & MFE_JUSTHITFLOOR) + S_StartSound(actor, actor->info->painsound); + + if (actor->threshold) + actor->threshold--; + + if (inwater && !(actor->flags2 & MF2_AMBUSH)) // buoyancy in water (or lava) + { + UINT8 flip = P_MobjFlip(actor); + fixed_t prevmomz = actor->momz; + actor->momz = FixedMul(actor->momz, locvar2); + actor->momz += flip * FixedMul(locvar2, actor->scale); + if (flip*prevmomz < 0 && flip*actor->momz >= 0 && !actor->threshold) + { + if (actor->eflags & MFE_UNDERWATER) + S_StartSound(actor, sfx_splash); + else if (!actor->threshold) + S_StartSound(actor, sfx_splish); + actor->threshold = max((topspeed - speed) >> FRACBITS, 8); + } + } + + if (speed > topspeed) // cap speed + { + actor->momx = FixedMul(FixedDiv(actor->momx, speed), topspeed); + actor->momy = FixedMul(FixedDiv(actor->momy, speed), topspeed); + } + + if (P_IsObjectOnGround(actor) || inwater) // apply drag to speed (compensates for lack of friction but also works in liquids) + { + actor->momx = FixedMul(actor->momx, locvar1); + actor->momy = FixedMul(actor->momy, locvar1); + } + + speed = P_AproxDistance(actor->momx, actor->momy); // recalculate speed for visual rolling + + if (speed < actor->scale >> 1) // stop moving if speed is insignificant + { + actor->momx = 0; + actor->momy = 0; + } + else if (speed > actor->scale) + { + actor->movecount = 1; // rock has moved; fuse should be set so we don't have a trillion rocks lying around + actor->angle = R_PointToAngle2(0, 0, actor->momx, actor->momy); // set rock's angle to movement direction + actor->movefactor += speed; + if (actor->movefactor > circumference / maxframes) // if distance moved is enough to change frame, change it! + { + actor->reactiontime++; + actor->reactiontime %= maxframes; + actor->movefactor = 0; + } + } + + actor->frame = actor->reactiontime % maxframes; // set frame + + if (!actor->tracer || P_MobjWasRemoved(actor->tracer) || !actor->tracer->health) + actor->flags |= MF_PUSHABLE; + + if (!(actor->flags & MF_PUSHABLE) || (actor->movecount != 1)) // if being ridden or haven't moved, don't disappear + actor->fuse = actor->info->painchance; + else if (actor->fuse < 2*TICRATE) + actor->drawflags ^= MFD_DONTDRAW; + +} + +// Function: A_DragonbomberSpawn +// +// Description: Spawns the body parts for Dragonbomber +// +// var1 = Tail segments to spawn +// var2 = unused +// +void A_DragonbomberSpawn(mobj_t *actor) +{ + UINT8 i; + mobj_t *mo = actor; + + if (LUA_CallAction("A_DragonbomberSpawn", actor)) + return; + + for (i = 0; i < var1; i++) // spawn tail segments + { + mobj_t *segment; + fixed_t x, y; + x = P_ReturnThrustX(mo, mo->angle, -mo->radius << 1); + y = P_ReturnThrustY(mo, mo->angle, -mo->radius << 1); + segment = P_SpawnMobjFromMobj(mo, x, y, 0, MT_DRAGONTAIL); + P_SetTarget(&segment->target, mo); + P_SetTarget(&mo->tracer, segment); + segment->angle = mo->angle; + mo = segment; + } + for (i = 0; i < 2; i++) // spawn wings + { + mo = P_SpawnMobjFromMobj(actor, 0, 0, 0, MT_DRAGONWING); + P_SetTarget(&mo->target, actor); + mo->movedir = ANGLE_90 + i * ANGLE_180; + } +} + +// Function: A_DragonWing +// +// Description: Moves actor such that it is placed away from its target at a distance equal to the target's radius in the direction of its target's angle. +// The actor's movedir can be used to offset the angle. +// +// var1 = unused +// var2 = unused +// +void A_DragonWing(mobj_t *actor) +{ + mobj_t *target = actor->target; + fixed_t x, y; + + if (LUA_CallAction("A_DragonWing", actor)) + return; + + if (target == NULL || !target->health) + { + P_RemoveMobj(actor); + return; + } + actor->angle = target->angle + actor->movedir; + x = target->x + P_ReturnThrustX(actor, actor->angle, -target->radius); + y = target->y + P_ReturnThrustY(actor, actor->angle, -target->radius); + P_TeleportMove(actor, x, y, target->z); +} + +// Function: A_DragonSegment +// +// Description: Moves actor such that it is placed away from its target at an absolute distance equal to the sum of the two mobjs' radii. +// +// var1 = unused +// var2 = unused +// +void A_DragonSegment(mobj_t *actor) +{ + mobj_t *target = actor->target; + fixed_t dist; + fixed_t radius; + angle_t hangle; + angle_t zangle; + fixed_t hdist; + fixed_t xdist; + fixed_t ydist; + fixed_t zdist; + + if (LUA_CallAction("A_DragonSegment", actor)) + return; + + if (target == NULL || !target->health) + { + P_RemoveMobj(actor); + return; + } + + dist = P_AproxDistance(P_AproxDistance(actor->x - target->x, actor->y - target->y), actor->z - target->z); + radius = actor->radius + target->radius; + hangle = R_PointToAngle2(target->x, target->y, actor->x, actor->y); + zangle = R_PointToAngle2(0, target->z, dist, actor->z); + hdist = P_ReturnThrustX(target, zangle, radius); + xdist = P_ReturnThrustX(target, hangle, hdist); + ydist = P_ReturnThrustY(target, hangle, hdist); + zdist = P_ReturnThrustY(target, zangle, radius); + + actor->angle = hangle; + P_TeleportMove(actor, target->x + xdist, target->y + ydist, target->z + zdist); +} + +// Function: A_ChangeHeight +// +// Description: Changes the actor's height by var1 +// +// var1 = height +// var2 = +// &1: height is absolute +// &2: scale with actor's scale +// +void A_ChangeHeight(mobj_t *actor) +{ + INT32 locvar1 = var1; + INT32 locvar2 = var2; + fixed_t height = locvar1; + boolean reverse; + + if (LUA_CallAction("A_ChangeHeight", actor)) + return; + + reverse = (actor->eflags & MFE_VERTICALFLIP) || (actor->flags2 & MF2_OBJECTFLIP); + + if (locvar2 & 2) + height = FixedMul(height, actor->scale); + + P_UnsetThingPosition(actor); + if (locvar2 & 1) + { + if (reverse) + actor->z += actor->height - locvar1; + actor->height = locvar1; + } + else + { + if (reverse) + actor->z -= locvar1; + actor->height += locvar1; + } + P_SetThingPosition(actor); +} diff --git a/src/p_floor.c b/src/p_floor.c index 11ffe270d..f8f7fef2d 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -13,7 +13,9 @@ #include "doomdef.h" #include "doomstat.h" +#include "m_random.h" #include "p_local.h" +#include "p_slopes.h" #include "r_state.h" #include "s_sound.h" #include "z_zone.h" @@ -24,247 +26,129 @@ // FLOORS // ========================================================================== -// -// Mini-P_IsObjectOnGroundIn for T_MovePlane hack -// -static inline boolean P_MobjReadyToMove(mobj_t *mo, sector_t *sec, boolean sectorisffloor, boolean sectorisquicksand) -{ - if (sectorisquicksand) - return (mo->z > sec->floorheight && mo->z < sec->ceilingheight); - else if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP)) - return ((sectorisffloor) ? (mo->z+mo->height != sec->floorheight) : (mo->z+mo->height != sec->ceilingheight)); - else - return ((sectorisffloor) ? (mo->z != sec->ceilingheight) : (mo->z != sec->floorheight)); -} - // // Move a plane (floor or ceiling) and check for crushing // result_e T_MovePlane(sector_t *sector, fixed_t speed, fixed_t dest, boolean crush, - INT32 floorOrCeiling, INT32 direction) + boolean ceiling, INT32 direction) { - boolean flag; fixed_t lastpos; fixed_t destheight; // used to keep floors/ceilings from moving through each other - // Stuff used for mobj hacks. - INT32 secnum = -1; - mobj_t *mo = NULL; - sector_t *sec = NULL; - ffloor_t *rover = NULL; - boolean sectorisffloor = false; - boolean sectorisquicksand = false; - sector->moved = true; - switch (floorOrCeiling) + if (ceiling) { - case 0: - // moving a floor - switch (direction) - { - case -1: - // Moving a floor down - if (sector->floorheight - speed < dest) - { - lastpos = sector->floorheight; - sector->floorheight = dest; - flag = P_CheckSector(sector, crush); - if (flag && sector->numattached) - { - sector->floorheight = lastpos; - P_CheckSector(sector, crush); - } - return pastdest; - } - else - { - lastpos = sector->floorheight; - sector->floorheight -= speed; - flag = P_CheckSector(sector, crush); - if (flag && sector->numattached) - { - sector->floorheight = lastpos; - P_CheckSector(sector, crush); - return crushed; - } - } - break; - - case 1: - // Moving a floor up - // keep floor from moving through ceilings - destheight = (dest < sector->ceilingheight) ? dest : sector->ceilingheight; - if (sector->floorheight + speed > destheight) - { - lastpos = sector->floorheight; - sector->floorheight = destheight; - flag = P_CheckSector(sector, crush); - if (flag) - { - sector->floorheight = lastpos; - P_CheckSector(sector, crush); - } - return pastdest; - } - else - { - // crushing is possible - lastpos = sector->floorheight; - sector->floorheight += speed; - flag = P_CheckSector(sector, crush); - if (flag) - { - sector->floorheight = lastpos; - P_CheckSector(sector, crush); - return crushed; - } - } - break; - } - break; - - case 1: - // moving a ceiling - switch (direction) - { - case -1: - // moving a ceiling down - // keep ceiling from moving through floors - destheight = (dest > sector->floorheight) ? dest : sector->floorheight; - if (sector->ceilingheight - speed < destheight) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = destheight; - flag = P_CheckSector(sector, crush); - - if (flag) - { - sector->ceilingheight = lastpos; - P_CheckSector(sector, crush); - } - return pastdest; - } - else - { - // crushing is possible - lastpos = sector->ceilingheight; - sector->ceilingheight -= speed; - flag = P_CheckSector(sector, crush); - - if (flag) - { - sector->ceilingheight = lastpos; - P_CheckSector(sector, crush); - return crushed; - } - } - break; - - case 1: - // moving a ceiling up - if (sector->ceilingheight + speed > dest) - { - lastpos = sector->ceilingheight; - sector->ceilingheight = dest; - flag = P_CheckSector(sector, crush); - if (flag && sector->numattached) - { - sector->ceilingheight = lastpos; - P_CheckSector(sector, crush); - } - return pastdest; - } - else - { - lastpos = sector->ceilingheight; - sector->ceilingheight += speed; - flag = P_CheckSector(sector, crush); - if (flag && sector->numattached) - { - sector->ceilingheight = lastpos; - P_CheckSector(sector, crush); - return crushed; - } - } - break; - } - break; - } - - // Hack for buggy mobjs to move by gravity with moving planes. - if (sector->tagline) - sectorisffloor = true; - - // Optimization condition. If the sector is not an FOF, declare sec as the main sector outside of the loop. - if (!sectorisffloor) - sec = sector; - - // Optimization condition. Only run the logic if there is any Things in the sector. - if (sectorisffloor || sec->thinglist) - { - // If this is an FOF being checked, check all the affected sectors for moving mobjs. - while ((sectorisffloor ? (secnum = P_FindSectorFromLineTag(sector->tagline, secnum)) : (secnum = 1)) >= 0) + lastpos = sector->ceilingheight; + // moving a ceiling + switch (direction) { - if (sectorisffloor) - { - // Get actual sector from the list of sectors. - sec = §ors[secnum]; - - // Can't use P_InQuicksand because it will return the incorrect result - // because of checking for heights. - for (rover = sec->ffloors; rover; rover = rover->next) + case -1: + // moving a ceiling down + // keep ceiling from moving through floors + destheight = (dest > sector->floorheight) ? dest : sector->floorheight; + if (sector->ceilingheight - speed < destheight) { - if (rover->target == sec && (rover->flags & FF_QUICKSAND)) + sector->ceilingheight = destheight; + if (P_CheckSector(sector, crush)) { - sectorisquicksand = true; - break; + sector->ceilingheight = lastpos; + P_CheckSector(sector, crush); + } + return pastdest; + } + else + { + // crushing is possible + sector->ceilingheight -= speed; + if (P_CheckSector(sector, crush)) + { + sector->ceilingheight = lastpos; + P_CheckSector(sector, crush); + return crushed; } } - } + break; - for (mo = sec->thinglist; mo; mo = mo->snext) - { - // The object should be ready to move as defined by this function. - if (!P_MobjReadyToMove(mo, sec, sectorisffloor, sectorisquicksand)) - continue; - - // The object should not be moving at all. - if (mo->momx || mo->momy || mo->momz) - continue; - - // These objects will be affected by this condition. - switch (mo->type) + case 1: + // moving a ceiling up + if (sector->ceilingheight + speed > dest) { - case MT_GOOP: // Egg Slimer's goop objects - case MT_SPINFIRE: // Elemental Shield flame balls - case MT_SNEAKERTRAIL: - case MT_SPIKE: // Floor Spike - // Is the object hang from the ceiling? - // In that case, swap the planes used. - // verticalflip inverts - if (!!(mo->flags & MF_SPAWNCEILING) ^ !!(mo->eflags & MFE_VERTICALFLIP)) - { - if (sectorisffloor && !sectorisquicksand) - mo->z = mo->ceilingz - mo->height; - else - mo->z = mo->ceilingz = mo->subsector->sector->ceilingheight - mo->height; - } - else - { - if (sectorisffloor && !sectorisquicksand) - mo->z = mo->floorz; - else - mo->z = mo->floorz = mo->subsector->sector->floorheight; - } - break; - // Kill warnings... - default: - break; + sector->ceilingheight = dest; + if (P_CheckSector(sector, crush) && sector->numattached) + { + sector->ceilingheight = lastpos; + P_CheckSector(sector, crush); + } + return pastdest; } - } + else + { + sector->ceilingheight += speed; + if (P_CheckSector(sector, crush) && sector->numattached) + { + sector->ceilingheight = lastpos; + P_CheckSector(sector, crush); + return crushed; + } + } + break; + } + } + else + { + lastpos = sector->floorheight; + // moving a floor + switch (direction) + { + case -1: + // Moving a floor down + if (sector->floorheight - speed < dest) + { + sector->floorheight = dest; + if (P_CheckSector(sector, crush) && sector->numattached) + { + sector->floorheight = lastpos; + P_CheckSector(sector, crush); + } + return pastdest; + } + else + { + sector->floorheight -= speed; + if (P_CheckSector(sector, crush) && sector->numattached) + { + sector->floorheight = lastpos; + P_CheckSector(sector, crush); + return crushed; + } + } + break; - // Break from loop if there is no FOFs to check. - if (!sectorisffloor) + case 1: + // Moving a floor up + // keep floor from moving through ceilings + destheight = (dest < sector->ceilingheight) ? dest : sector->ceilingheight; + if (sector->floorheight + speed > destheight) + { + sector->floorheight = destheight; + if (P_CheckSector(sector, crush)) + { + sector->floorheight = lastpos; + P_CheckSector(sector, crush); + } + return pastdest; + } + else + { + // crushing is possible + sector->floorheight += speed; + if (P_CheckSector(sector, crush)) + { + sector->floorheight = lastpos; + P_CheckSector(sector, crush); + return crushed; + } + } break; } } @@ -289,7 +173,7 @@ void T_MoveFloor(floormove_t *movefloor) res = T_MovePlane(movefloor->sector, movefloor->speed, movefloor->floordestheight, - movefloor->crush, 0, movefloor->direction); + movefloor->crush, false, movefloor->direction); if (movefloor->type == bounceFloor) { @@ -482,7 +366,7 @@ void T_MoveElevator(elevator_t *elevator) elevator->speed, elevator->ceilingdestheight, elevator->distance, - 1, // move floor + true, // move ceiling elevator->direction ); @@ -492,7 +376,7 @@ void T_MoveElevator(elevator_t *elevator) elevator->speed, elevator->floordestheight, elevator->distance, - 0, // move ceiling + false, // move floor elevator->direction ); @@ -544,7 +428,7 @@ void T_MoveElevator(elevator_t *elevator) elevator->speed, elevator->floordestheight, elevator->distance, - 0, // move ceiling + false, // move floor elevator->direction ); @@ -556,7 +440,7 @@ void T_MoveElevator(elevator_t *elevator) elevator->speed, elevator->ceilingdestheight, elevator->distance, - 1, // move floor + true, // move ceiling elevator->direction ); } @@ -677,54 +561,25 @@ void T_MoveElevator(elevator_t *elevator) // // Useful for things like intermittent falling lava. // -void T_ContinuousFalling(levelspecthink_t *faller) +void T_ContinuousFalling(continuousfall_t *faller) { -#define speed vars[0] -#define direction vars[1] -#define floorwasheight vars[2] -#define ceilingwasheight vars[3] -#define floordestheight vars[4] -#define ceilingdestheight vars[5] - - if (faller->direction == -1) - { - faller->sector->ceilingheight -= faller->speed; - faller->sector->floorheight -= faller->speed; - } - else - { - faller->sector->ceilingheight += faller->speed; - faller->sector->floorheight += faller->speed; - } + faller->sector->ceilingheight += faller->speed*faller->direction; + faller->sector->floorheight += faller->speed*faller->direction; P_CheckSector(faller->sector, false); - if (faller->direction == -1) // Down + if ((faller->direction == -1 && faller->sector->ceilingheight <= faller->destheight) + || (faller->direction == 1 && faller->sector->floorheight >= faller->destheight)) { - if (faller->sector->ceilingheight <= faller->ceilingdestheight) // if destination height acheived - { - faller->sector->ceilingheight = faller->ceilingwasheight; - faller->sector->floorheight = faller->floorwasheight; - } - } - else // Up - { - if (faller->sector->floorheight >= faller->floordestheight) // if destination height acheived - { - faller->sector->ceilingheight = faller->ceilingwasheight; - faller->sector->floorheight = faller->floorwasheight; - } + faller->sector->ceilingheight = faller->ceilingstartheight; + faller->sector->floorheight = faller->floorstartheight; } + P_CheckSector(faller->sector, false); // you might think this is irrelevant. you would be wrong + faller->sector->floorspeed = faller->speed*faller->direction; faller->sector->ceilspeed = 42; faller->sector->moved = true; -#undef speed -#undef direction -#undef floorwasheight -#undef ceilingwasheight -#undef floordestheight -#undef ceilingdestheight } // @@ -770,23 +625,20 @@ static fixed_t P_SectorCheckWater(sector_t *analyzesector, ////////////////////////////////////////////////// // Bounces a floating cheese -void T_BounceCheese(levelspecthink_t *bouncer) +void T_BounceCheese(bouncecheese_t *bouncer) { -#define speed vars[0] -#define distance vars[1] -#define low vars[2] -#define ceilingwasheight vars[3] -#define floorwasheight vars[4] + fixed_t sectorheight; fixed_t halfheight; fixed_t waterheight; fixed_t floorheight; sector_t *actionsector; INT32 i; + boolean remove; - if (bouncer->sector->crumblestate == 4 || bouncer->sector->crumblestate == 1 - || bouncer->sector->crumblestate == 2) // Oops! Crumbler says to remove yourself! + if (bouncer->sector->crumblestate == CRUMBLE_RESTORE || bouncer->sector->crumblestate == CRUMBLE_WAIT + || bouncer->sector->crumblestate == CRUMBLE_ACTIVATED) // Oops! Crumbler says to remove yourself! { - bouncer->sector->crumblestate = 1; + bouncer->sector->crumblestate = CRUMBLE_WAIT; bouncer->sector->ceilingdata = NULL; bouncer->sector->ceilspeed = 0; bouncer->sector->floordata = NULL; @@ -801,43 +653,28 @@ void T_BounceCheese(levelspecthink_t *bouncer) actionsector = §ors[i]; actionsector->moved = true; - halfheight = abs(bouncer->sector->ceilingheight - bouncer->sector->floorheight) >> 1; + sectorheight = abs(bouncer->sector->ceilingheight - bouncer->sector->floorheight); + halfheight = sectorheight/2; waterheight = P_SectorCheckWater(actionsector, bouncer->sector); // sorts itself out if there's no suitable water in the sector - floorheight = P_FloorzAtPos(actionsector->soundorg.x, actionsector->soundorg.y, bouncer->sector->floorheight, halfheight << 1); + floorheight = P_FloorzAtPos(actionsector->soundorg.x, actionsector->soundorg.y, bouncer->sector->floorheight, sectorheight); + + remove = false; // Water level is up to the ceiling. if (waterheight > bouncer->sector->ceilingheight - halfheight && bouncer->sector->ceilingheight >= actionsector->ceilingheight) // Tails 01-08-2004 { bouncer->sector->ceilingheight = actionsector->ceilingheight; - bouncer->sector->floorheight = bouncer->sector->ceilingheight - (halfheight*2); - T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling - T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor - P_RecalcPrecipInSector(actionsector); - bouncer->sector->ceilingdata = NULL; - bouncer->sector->floordata = NULL; - bouncer->sector->floorspeed = 0; - bouncer->sector->ceilspeed = 0; - bouncer->sector->moved = true; - P_RemoveThinker(&bouncer->thinker); // remove bouncer from actives - return; + bouncer->sector->floorheight = actionsector->ceilingheight - sectorheight; + remove = true; } // Water level is too shallow. else if (waterheight < bouncer->sector->floorheight + halfheight && bouncer->sector->floorheight <= floorheight) { - bouncer->sector->ceilingheight = floorheight + (halfheight << 1); + bouncer->sector->ceilingheight = floorheight + sectorheight; bouncer->sector->floorheight = floorheight; - T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling - T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor - P_RecalcPrecipInSector(actionsector); - bouncer->sector->ceilingdata = NULL; - bouncer->sector->floordata = NULL; - bouncer->sector->floorspeed = 0; - bouncer->sector->ceilspeed = 0; - bouncer->sector->moved = true; - P_RemoveThinker(&bouncer->thinker); // remove bouncer from actives - return; + remove = true; } else { @@ -845,37 +682,47 @@ void T_BounceCheese(levelspecthink_t *bouncer) bouncer->floorwasheight = waterheight - halfheight; } - T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight - - 70*FRACUNIT, 0, 1, -1); // move ceiling - T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT, - 0, 0, -1); // move floor + if (remove) + { + T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, false, true, -1); // update things on ceiling + T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, false, false, -1); // update things on floor + P_RecalcPrecipInSector(actionsector); + bouncer->sector->ceilingdata = NULL; + bouncer->sector->floordata = NULL; + bouncer->sector->floorspeed = 0; + bouncer->sector->ceilspeed = 0; + bouncer->sector->moved = true; + P_RemoveThinker(&bouncer->thinker); // remove bouncer from actives + return; + } + + if (bouncer->speed >= 0) // move floor first to fix height desync and any bizarre bugs following that + { + T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT, + false, false, -1); // move floor + T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight - + 70*FRACUNIT, false, true, -1); // move ceiling + } + else + { + T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->ceilingheight - + 70*FRACUNIT, false, true, -1); // move ceiling + T_MovePlane(bouncer->sector, bouncer->speed/2, bouncer->sector->floorheight - 70*FRACUNIT, + false, false, -1); // move floor + } bouncer->sector->floorspeed = -bouncer->speed/2; bouncer->sector->ceilspeed = 42; - if (bouncer->sector->ceilingheight < bouncer->ceilingwasheight && bouncer->low == 0) // Down + if ((bouncer->sector->ceilingheight < bouncer->ceilingwasheight && !bouncer->low) // Down + || (bouncer->sector->ceilingheight > bouncer->ceilingwasheight && bouncer->low)) // Up { if (abs(bouncer->speed) < 6*FRACUNIT) bouncer->speed -= bouncer->speed/3; else bouncer->speed -= bouncer->speed/2; - bouncer->low = 1; - if (abs(bouncer->speed) > 6*FRACUNIT) - { - mobj_t *mp = (void *)&actionsector->soundorg; - actionsector->soundorg.z = bouncer->sector->floorheight; - S_StartSound(mp, sfx_splash); - } - } - else if (bouncer->sector->ceilingheight > bouncer->ceilingwasheight && bouncer->low) // Up - { - if (abs(bouncer->speed) < 6*FRACUNIT) - bouncer->speed -= bouncer->speed/3; - else - bouncer->speed -= bouncer->speed/2; - - bouncer->low = 0; + bouncer->low = !bouncer->low; if (abs(bouncer->speed) > 6*FRACUNIT) { mobj_t *mp = (void *)&actionsector->soundorg; @@ -898,8 +745,8 @@ void T_BounceCheese(levelspecthink_t *bouncer) { bouncer->sector->floorheight = bouncer->floorwasheight; bouncer->sector->ceilingheight = bouncer->ceilingwasheight; - T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, 0, 1, -1); // update things on ceiling - T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, 0, 0, -1); // update things on floor + T_MovePlane(bouncer->sector, 0, bouncer->sector->ceilingheight, false, true, -1); // update things on ceiling + T_MovePlane(bouncer->sector, 0, bouncer->sector->floorheight, false, false, -1); // update things on floor bouncer->sector->ceilingdata = NULL; bouncer->sector->floordata = NULL; bouncer->sector->floorspeed = 0; @@ -914,27 +761,13 @@ void T_BounceCheese(levelspecthink_t *bouncer) if (actionsector) P_RecalcPrecipInSector(actionsector); } -#undef speed -#undef distance -#undef low -#undef ceilingwasheight -#undef floorwasheight } ////////////////////////////////////////////////// // T_StartCrumble //////////////////////////////// ////////////////////////////////////////////////// // Crumbling platform Tails 03-11-2002 -// -// DEFINITION OF THE 'CRUMBLESTATE'S: -// -// 0 - No crumble thinker -// 1 - Don't float on water because this is supposed to wait for a crumble -// 2 - Crumble thinker activated, but hasn't fallen yet -// 3 - Crumble thinker is falling -// 4 - Crumble thinker is about to restore to original position -// -void T_StartCrumble(elevator_t *elevator) +void T_StartCrumble(crumble_t *crumble) { ffloor_t *rover; sector_t *sector; @@ -942,84 +775,96 @@ void T_StartCrumble(elevator_t *elevator) // Once done, the no-return thinker just sits there, // constantly 'returning'... kind of an oxymoron, isn't it? - if (((elevator->floordestheight == 1 && elevator->direction == -1) - || (elevator->floordestheight == 0 && elevator->direction == 1)) - && elevator->type == elevateContinuous) // No return crumbler + if ((((crumble->flags & CF_REVERSE) && crumble->direction == -1) + || (!(crumble->flags & CF_REVERSE) && crumble->direction == 1)) + && !(crumble->flags & CF_RETURN)) { - elevator->sector->ceilspeed = 0; - elevator->sector->floorspeed = 0; + crumble->sector->ceilspeed = 0; + crumble->sector->floorspeed = 0; return; } - if (elevator->distance != 0) + if (crumble->timer != 0) { - if (elevator->distance > 0) // Count down the timer + if (crumble->timer > 0) // Count down the timer { - elevator->distance--; - if (elevator->distance <= 0) - elevator->distance = -15*TICRATE; // Timer until platform returns to original position. + if (--crumble->timer <= 0) + crumble->timer = -15*TICRATE; // Timer until platform returns to original position. else { // Timer isn't up yet, so just keep waiting. - elevator->sector->ceilspeed = 0; - elevator->sector->floorspeed = 0; + crumble->sector->ceilspeed = 0; + crumble->sector->floorspeed = 0; return; } } - else if (++elevator->distance == 0) // Reposition back to original spot + else if (++crumble->timer == 0) // Reposition back to original spot { - for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) { sector = §ors[i]; for (rover = sector->ffloors; rover; rover = rover->next) { - if (rover->flags & FF_CRUMBLE && rover->flags & FF_FLOATBOB - && rover->master == elevator->sourceline) - { - rover->alpha = elevator->origspeed; + if (!(rover->flags & FF_CRUMBLE)) + continue; - if (rover->alpha == 0xff) - rover->flags &= ~FF_TRANSLUCENT; - } + if (!(rover->flags & FF_FLOATBOB)) + continue; + + if (rover->master != crumble->sourceline) + continue; + + rover->alpha = crumble->origalpha; + + if (rover->alpha == 0xff) + rover->flags &= ~FF_TRANSLUCENT; } } // Up! - if (elevator->floordestheight == 1) - elevator->direction = -1; + if (crumble->flags & CF_REVERSE) + crumble->direction = -1; else - elevator->direction = 1; + crumble->direction = 1; - elevator->sector->ceilspeed = 0; - elevator->sector->floorspeed = 0; + crumble->sector->ceilspeed = 0; + crumble->sector->floorspeed = 0; return; } // Flash to indicate that the platform is about to return. - if (elevator->distance > -224 && (leveltime % ((abs(elevator->distance)/8) + 1) == 0)) + if (crumble->timer > -224 && (leveltime % ((abs(crumble->timer)/8) + 1) == 0)) { - for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) { sector = §ors[i]; for (rover = sector->ffloors; rover; rover = rover->next) { - if (!(rover->flags & FF_NORETURN) && rover->flags & FF_CRUMBLE && rover->flags & FF_FLOATBOB - && rover->master == elevator->sourceline) - { - if (rover->alpha == elevator->origspeed) - { - rover->flags |= FF_TRANSLUCENT; - rover->alpha = 0x00; - } - else - { - if (elevator->origspeed == 0xff) - rover->flags &= ~FF_TRANSLUCENT; + if (rover->flags & FF_NORETURN) + continue; - rover->alpha = elevator->origspeed; - } + if (!(rover->flags & FF_CRUMBLE)) + continue; + + if (!(rover->flags & FF_FLOATBOB)) + continue; + + if (rover->master != crumble->sourceline) + continue; + + if (rover->alpha == crumble->origalpha) + { + rover->flags |= FF_TRANSLUCENT; + rover->alpha = 0x00; + } + else + { + rover->alpha = crumble->origalpha; + + if (rover->alpha == 0xff) + rover->flags &= ~FF_TRANSLUCENT; } } } @@ -1028,74 +873,62 @@ void T_StartCrumble(elevator_t *elevator) // We're about to go back to the original position, // so set this to let other thinkers know what is // about to happen. - if (elevator->distance < 0 && elevator->distance > -3) - elevator->sector->crumblestate = 4; // makes T_BounceCheese remove itself + if (crumble->timer < 0 && crumble->timer > -3) + crumble->sector->crumblestate = CRUMBLE_RESTORE; // makes T_BounceCheese remove itself } - if ((elevator->floordestheight == 0 && elevator->direction == -1) - || (elevator->floordestheight == 1 && elevator->direction == 1)) // Down + if ((!(crumble->flags & CF_REVERSE) && crumble->direction == -1) + || ((crumble->flags & CF_REVERSE) && crumble->direction == 1)) // Down { - elevator->sector->crumblestate = 3; // Allow floating now. + crumble->sector->crumblestate = CRUMBLE_FALL; // Allow floating now. // Only fall like this if it isn't meant to float on water - if (elevator->high != 42) + if (!(crumble->flags & CF_FLOATBOB)) { - elevator->speed += gravity; // Gain more and more speed + crumble->speed += gravity; // Gain more and more speed - if ((elevator->floordestheight == 0 && !(elevator->sector->ceilingheight < -16384*FRACUNIT)) - || (elevator->floordestheight == 1 && !(elevator->sector->ceilingheight > 16384*FRACUNIT))) + if ((!(crumble->flags & CF_REVERSE) && crumble->sector->ceilingheight >= -16384*FRACUNIT) + || ((crumble->flags & CF_REVERSE) && crumble->sector->ceilingheight <= 16384*FRACUNIT)) { - fixed_t dest; - - if (elevator->floordestheight == 1) - dest = elevator->sector->ceilingheight + (elevator->speed*2); - else - dest = elevator->sector->ceilingheight - (elevator->speed*2); - T_MovePlane //jff 4/7/98 reverse order of ceiling/floor ( - elevator->sector, - elevator->speed, - dest, - 0, - 1, // move floor - elevator->direction + crumble->sector, + crumble->speed, + crumble->sector->ceilingheight + crumble->direction*crumble->speed*2, + false, + true, // move ceiling + crumble->direction ); - if (elevator->floordestheight == 1) - dest = elevator->sector->floorheight + (elevator->speed*2); - else - dest = elevator->sector->floorheight - (elevator->speed*2); - - T_MovePlane - ( - elevator->sector, - elevator->speed, - dest, - 0, - 0, // move ceiling - elevator->direction + T_MovePlane + ( + crumble->sector, + crumble->speed, + crumble->sector->floorheight + crumble->direction*crumble->speed*2, + false, + false, // move floor + crumble->direction ); - elevator->sector->ceilspeed = 42; - elevator->sector->floorspeed = elevator->speed*elevator->direction; + crumble->sector->ceilspeed = 42; + crumble->sector->floorspeed = crumble->speed*crumble->direction; } } } else // Up (restore to original position) { - elevator->sector->crumblestate = 1; - elevator->sector->ceilingheight = elevator->ceilingwasheight; - elevator->sector->floorheight = elevator->floorwasheight; - elevator->sector->floordata = NULL; - elevator->sector->ceilingdata = NULL; - elevator->sector->ceilspeed = 0; - elevator->sector->floorspeed = 0; - elevator->sector->moved = true; - P_RemoveThinker(&elevator->thinker); + crumble->sector->crumblestate = CRUMBLE_WAIT; + crumble->sector->ceilingheight = crumble->ceilingwasheight; + crumble->sector->floorheight = crumble->floorwasheight; + crumble->sector->floordata = NULL; + crumble->sector->ceilingdata = NULL; + crumble->sector->ceilspeed = 0; + crumble->sector->floorspeed = 0; + crumble->sector->moved = true; + P_RemoveThinker(&crumble->thinker); } - for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) { sector = §ors[i]; sector->moved = true; @@ -1108,24 +941,17 @@ void T_StartCrumble(elevator_t *elevator) ////////////////////////////////////////////////// // Mario hits a block! // -void T_MarioBlock(levelspecthink_t *block) +void T_MarioBlock(mariothink_t *block) { INT32 i; -#define speed vars[1] -#define direction vars[2] -#define floorwasheight vars[3] -#define ceilingwasheight vars[4] -#define distance vars[5] -#define low vars[6] - T_MovePlane ( block->sector, block->speed, block->sector->ceilingheight + 70*FRACUNIT * block->direction, - 0, - 1, // move floor + false, + true, // move ceiling block->direction ); @@ -1134,615 +960,60 @@ void T_MarioBlock(levelspecthink_t *block) block->sector, block->speed, block->sector->floorheight + 70*FRACUNIT * block->direction, - 0, - 0, // move ceiling + false, + false, // move floor block->direction ); - if (block->sector->ceilingheight >= block->ceilingwasheight + 32*FRACUNIT) // Go back down now.. - block->direction = -block->direction; - else if (block->sector->ceilingheight <= block->ceilingwasheight) + if (block->sector->ceilingheight >= block->ceilingstartheight + 32*FRACUNIT) // Go back down now.. + block->direction *= -1; + else if (block->sector->ceilingheight <= block->ceilingstartheight) { - block->sector->ceilingheight = block->ceilingwasheight; - block->sector->floorheight = block->floorwasheight; + block->sector->ceilingheight = block->ceilingstartheight; + block->sector->floorheight = block->floorstartheight; P_RemoveThinker(&block->thinker); block->sector->floordata = NULL; block->sector->ceilingdata = NULL; block->sector->floorspeed = 0; block->sector->ceilspeed = 0; + block->direction = 0; } - for (i = -1; (i = P_FindSectorFromTag((INT16)block->vars[0], i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(block->tag, i)) >= 0 ;) P_RecalcPrecipInSector(§ors[i]); - -#undef speed -#undef direction -#undef floorwasheight -#undef ceilingwasheight -#undef distance -#undef low } -void T_SpikeSector(levelspecthink_t *spikes) -{ - mobj_t *thing; - msecnode_t *node; - boolean dothepain; - sector_t *affectsec; - - node = spikes->sector->touching_thinglist; // things touching this sector - - for (; node; node = node->m_thinglist_next) - { - thing = node->m_thing; - if (!thing->player) - continue; - - dothepain = false; - affectsec = §ors[spikes->vars[0]]; - - if (affectsec == spikes->sector) // Applied to an actual sector - { - fixed_t affectfloor = P_GetSpecialBottomZ(thing, affectsec, affectsec); - fixed_t affectceil = P_GetSpecialTopZ(thing, affectsec, affectsec); - - if (affectsec->flags & SF_FLIPSPECIAL_FLOOR) - { - if (!(thing->eflags & MFE_VERTICALFLIP) && thing->momz > 0) - continue; - - if (thing->z == affectfloor) - dothepain = true; - } - - if (affectsec->flags & SF_FLIPSPECIAL_CEILING) - { - if ((thing->eflags & MFE_VERTICALFLIP) && thing->momz < 0) - continue; - - if (thing->z + thing->height == affectceil) - dothepain = true; - } - } - else - { - fixed_t affectfloor = P_GetSpecialBottomZ(thing, affectsec, spikes->sector); - fixed_t affectceil = P_GetSpecialTopZ(thing, affectsec, spikes->sector); - if (affectsec->flags & SF_FLIPSPECIAL_FLOOR) - { - if (!(thing->eflags & MFE_VERTICALFLIP) && thing->momz > 0) - continue; - - if (thing->z == affectceil) - dothepain = true; - } - - if (affectsec->flags & SF_FLIPSPECIAL_CEILING) - { - if ((thing->eflags & MFE_VERTICALFLIP) && thing->momz < 0) - continue; - - if (thing->z + thing->height == affectfloor) - dothepain = true; - } - } - - if (dothepain) - { - mobj_t *killer = P_SpawnMobj(thing->x, thing->y, thing->z, MT_NULL); - killer->threshold = 43; // Special flag that it was spikes which hurt you. - P_DamageMobj(thing, killer, killer, 1); - break; - } - } -} - -void T_FloatSector(levelspecthink_t *floater) +void T_FloatSector(floatthink_t *floater) { fixed_t cheeseheight; + fixed_t waterheight; sector_t *actionsector; INT32 secnum; - cheeseheight = (floater->sector->ceilingheight + floater->sector->floorheight)>>1; - // Just find the first sector with the tag. // Doesn't work with multiple sectors that have different floor/ceiling heights. - secnum = P_FindSectorFromTag((INT16)floater->vars[0], -1); + secnum = P_FindSectorFromTag(floater->tag, -1); + if (secnum <= 0) + return; + actionsector = §ors[secnum]; - if (secnum > 0) - actionsector = §ors[secnum]; - else - actionsector = NULL; + cheeseheight = (floater->sector->ceilingheight + floater->sector->floorheight)>>1; - if (actionsector) - { - //boolean floatanyway = false; // Ignore the crumblestate setting. - fixed_t waterheight = P_SectorCheckWater(actionsector, floater->sector); // find the highest suitable water block around + //boolean floatanyway = false; // Ignore the crumblestate setting. + waterheight = P_SectorCheckWater(actionsector, floater->sector); // find the highest suitable water block around - if (waterheight == cheeseheight) // same height, no floating needed - ; - else if (floater->sector->floorheight == actionsector->floorheight && waterheight < cheeseheight) // too low - ; - else if (floater->sector->ceilingheight == actionsector->ceilingheight && waterheight > cheeseheight) // too high - ; - // we have something to float in! Or we're for some reason above the ground, let's fall anyway - else if (floater->sector->crumblestate == 0 || floater->sector->crumblestate >= 3/* || floatanyway*/) - EV_BounceSector(floater->sector, FRACUNIT, floater->sourceline); + if (waterheight == cheeseheight) // same height, no floating needed + return; - P_RecalcPrecipInSector(actionsector); - } -} + if (floater->sector->floorheight == actionsector->floorheight && waterheight < cheeseheight) // too low + return; -// -// T_BridgeThinker -// -// Kind of like T_RaiseSector, -// but spreads out across -// multiple FOFs at varying -// intensity. -// -void T_BridgeThinker(levelspecthink_t *bridge) -{ - msecnode_t *node; - mobj_t *thing; - sector_t *sector; - sector_t *controlsec = NULL; - INT32 i, k; + if (floater->sector->ceilingheight == actionsector->ceilingheight && waterheight > cheeseheight) // too high + return; - INT16 j; - boolean playeronme = false; - fixed_t ceilingdestination = 0, floordestination = 0; - result_e res = 0; - -#define ORIGFLOORHEIGHT (bridge->vars[0]) -#define ORIGCEILINGHEIGHT (bridge->vars[1]) -#define BASESPEED (bridge->vars[2]) -#define CURSPEED (bridge->vars[3]) -#define STARTTAG ((INT16)bridge->vars[4]) -#define ENDTAG ((INT16)bridge->vars[5]) -#define DIRECTION (bridge->vars[8]) -#define SAGAMT (8*FRACUNIT) - fixed_t lowceilheight = ORIGCEILINGHEIGHT - SAGAMT; - fixed_t lowfloorheight = ORIGFLOORHEIGHT - SAGAMT; -#define LOWCEILINGHEIGHT (lowceilheight) -#define LOWFLOORHEIGHT (lowfloorheight) -#define STARTCONTROLTAG (ENDTAG + 1) -#define ENDCONTROLTAG (ENDTAG + (ENDTAG - STARTTAG) + 1) - - // Is someone standing on it? - for (j = STARTTAG; j <= ENDTAG; j++) - { - for (i = -1; (i = P_FindSectorFromTag(j, i)) >= 0 ;) - { - sector = §ors[i]; - - // Nab the control sector that this sector belongs to. - k = P_FindSectorFromTag((INT16)(j + (ENDTAG-STARTTAG) + 1), -1); - - if (k == -1) - break; - - controlsec = §ors[k]; - - // Is a player standing on me? - for (node = sector->touching_thinglist; node; node = node->m_thinglist_next) - { - thing = node->m_thing; - - if (!thing->player) - continue; - - if (!(thing->z == controlsec->ceilingheight)) - continue; - - playeronme = true; - goto wegotit; // Just take the first one? - } - } - } -wegotit: - if (playeronme) - { - // Lower controlsec like a regular T_RaiseSector - // Set the heights of all the other control sectors to - // be a gradient of this height toward the edges - } - else - { - // Raise controlsec like a regular T_RaiseSector - // Set the heights of all the other control sectors to - // be a gradient of this height toward the edges. - } - - if (playeronme && controlsec) - { - INT32 dist; - - bridge->sector = controlsec; - CURSPEED = BASESPEED; - - { - // Translate tags to - 0 + range - /*so you have a number in [min, max]. - let range = max - min, subtract min - from your number to get [0, range]. - subtract range/2 to get [-range/2, range/2]. - take absolute value and get [0, range/2] where - lower number = closer to midpoint. divide by - range/2 to get [0, 1]. subtract that number - from 1 to get [0, 1] with higher number = closer - to midpoint. multiply this by max sag amount*/ - - INT32 midpoint = STARTCONTROLTAG + ((ENDCONTROLTAG-STARTCONTROLTAG) + 1)/2; -// INT32 tagstart = STARTTAG - midpoint; -// INT32 tagend = ENDTAG - midpoint; - -// CONS_Debug(DBG_GAMELOGIC, "tagstart is %d, tagend is %d\n", tagstart, tagend); - - // Sag is adjusted by how close you are to the center - dist = ((ENDCONTROLTAG - STARTCONTROLTAG))/2 - abs(bridge->sector->tag - midpoint); - -// CONS_Debug(DBG_GAMELOGIC, "Dist is %d\n", dist); - LOWCEILINGHEIGHT -= (SAGAMT) * dist; - LOWFLOORHEIGHT -= (SAGAMT) * dist; - } - - // go down - if (bridge->sector->ceilingheight <= LOWCEILINGHEIGHT) - { - bridge->sector->floorheight = LOWCEILINGHEIGHT - (bridge->sector->ceilingheight - bridge->sector->floorheight); - bridge->sector->ceilingheight = LOWCEILINGHEIGHT; - bridge->sector->ceilspeed = 0; - bridge->sector->floorspeed = 0; - goto dorest; - } - - DIRECTION = -1; - ceilingdestination = LOWCEILINGHEIGHT; - floordestination = LOWFLOORHEIGHT; - - if ((bridge->sector->ceilingheight - LOWCEILINGHEIGHT) - < (ORIGCEILINGHEIGHT - bridge->sector->ceilingheight)) - { - fixed_t origspeed = CURSPEED; - - // Slow down as you get closer to the bottom - CURSPEED = FixedMul(CURSPEED,FixedDiv(bridge->sector->ceilingheight - LOWCEILINGHEIGHT, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5)); - - if (CURSPEED <= origspeed/16) - CURSPEED = origspeed/16; - else if (CURSPEED > origspeed) - CURSPEED = origspeed; - } - else - { - fixed_t origspeed = CURSPEED; - // Slow down as you get closer to the top - CURSPEED = FixedMul(CURSPEED,FixedDiv(ORIGCEILINGHEIGHT - bridge->sector->ceilingheight, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5)); - - if (CURSPEED <= origspeed/16) - CURSPEED = origspeed/16; - else if (CURSPEED > origspeed) - CURSPEED = origspeed; - } - -// CONS_Debug(DBG_GAMELOGIC, "Curspeed is %d\n", CURSPEED>>FRACBITS); - - res = T_MovePlane - ( - bridge->sector, // sector - CURSPEED, // speed - ceilingdestination, // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - DIRECTION // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - bridge->sector, // sector - CURSPEED, // speed - floordestination, // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - DIRECTION // direction - ); - - bridge->sector->ceilspeed = 42; - bridge->sector->floorspeed = CURSPEED*DIRECTION; - - dorest: - // Adjust joined sector heights - { - sector_t *sourcesec = bridge->sector; - - INT32 divisor = sourcesec->tag - ENDTAG + 1; - fixed_t heightdiff = ORIGCEILINGHEIGHT - sourcesec->ceilingheight; - fixed_t interval; - INT32 plusplusme = 0; - - if (divisor > 0) - { - interval = heightdiff/divisor; - -// CONS_Debug(DBG_GAMELOGIC, "interval is %d\n", interval>>FRACBITS); - - // TODO: Use T_MovePlane - - for (j = (INT16)(ENDTAG+1); j <= sourcesec->tag; j++, plusplusme++) - { - for (i = -1; (i = P_FindSectorFromTag(j, i)) >= 0 ;) - { - if (sectors[i].ceilingheight >= sourcesec->ceilingheight) - { - sectors[i].ceilingheight = ORIGCEILINGHEIGHT - (interval*plusplusme); - sectors[i].floorheight = ORIGFLOORHEIGHT - (interval*plusplusme); - } - else // Do the regular rise - { - bridge->sector = §ors[i]; - - CURSPEED = BASESPEED/2; - - // rise back up - if (bridge->sector->ceilingheight >= ORIGCEILINGHEIGHT) - { - bridge->sector->floorheight = ORIGCEILINGHEIGHT - (bridge->sector->ceilingheight - bridge->sector->floorheight); - bridge->sector->ceilingheight = ORIGCEILINGHEIGHT; - bridge->sector->ceilspeed = 0; - bridge->sector->floorspeed = 0; - continue; - } - - DIRECTION = 1; - ceilingdestination = ORIGCEILINGHEIGHT; - floordestination = ORIGFLOORHEIGHT; - -// CONS_Debug(DBG_GAMELOGIC, "ceildest: %d, floordest: %d\n", ceilingdestination>>FRACBITS, floordestination>>FRACBITS); - - if ((bridge->sector->ceilingheight - LOWCEILINGHEIGHT) - < (ORIGCEILINGHEIGHT - bridge->sector->ceilingheight)) - { - fixed_t origspeed = CURSPEED; - - // Slow down as you get closer to the bottom - CURSPEED = FixedMul(CURSPEED,FixedDiv(bridge->sector->ceilingheight - LOWCEILINGHEIGHT, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5)); - - if (CURSPEED <= origspeed/16) - CURSPEED = origspeed/16; - else if (CURSPEED > origspeed) - CURSPEED = origspeed; - } - else - { - fixed_t origspeed = CURSPEED; - // Slow down as you get closer to the top - CURSPEED = FixedMul(CURSPEED,FixedDiv(ORIGCEILINGHEIGHT - bridge->sector->ceilingheight, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5)); - - if (CURSPEED <= origspeed/16) - CURSPEED = origspeed/16; - else if (CURSPEED > origspeed) - CURSPEED = origspeed; - } - - res = T_MovePlane - ( - bridge->sector, // sector - CURSPEED, // speed - ceilingdestination, // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - DIRECTION // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - bridge->sector, // sector - CURSPEED, // speed - floordestination, // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - DIRECTION // direction - ); - - bridge->sector->ceilspeed = 42; - bridge->sector->floorspeed = CURSPEED*DIRECTION; - } - } - } - } - - // Now the other side - divisor = ENDTAG + (ENDTAG-STARTTAG) + 1; - divisor -= sourcesec->tag; - - if (divisor > 0) - { - interval = heightdiff/divisor; - plusplusme = 0; - -// CONS_Debug(DBG_GAMELOGIC, "interval2 is %d\n", interval>>FRACBITS); - - for (j = (INT16)(sourcesec->tag+1); j <= ENDTAG + (ENDTAG-STARTTAG) + 1; j++, plusplusme++) - { - for (i = -1; (i = P_FindSectorFromTag(j, i)) >= 0 ;) - { - if (sectors[i].ceilingheight >= sourcesec->ceilingheight) - { - sectors[i].ceilingheight = sourcesec->ceilingheight + (interval*plusplusme); - sectors[i].floorheight = sourcesec->floorheight + (interval*plusplusme); - } - else // Do the regular rise - { - bridge->sector = §ors[i]; - - CURSPEED = BASESPEED/2; - - // rise back up - if (bridge->sector->ceilingheight >= ORIGCEILINGHEIGHT) - { - bridge->sector->floorheight = ORIGCEILINGHEIGHT - (bridge->sector->ceilingheight - bridge->sector->floorheight); - bridge->sector->ceilingheight = ORIGCEILINGHEIGHT; - bridge->sector->ceilspeed = 0; - bridge->sector->floorspeed = 0; - continue; - } - - DIRECTION = 1; - ceilingdestination = ORIGCEILINGHEIGHT; - floordestination = ORIGFLOORHEIGHT; - -// CONS_Debug(DBG_GAMELOGIC, "ceildest: %d, floordest: %d\n", ceilingdestination>>FRACBITS, floordestination>>FRACBITS); - - if ((bridge->sector->ceilingheight - LOWCEILINGHEIGHT) - < (ORIGCEILINGHEIGHT - bridge->sector->ceilingheight)) - { - fixed_t origspeed = CURSPEED; - - // Slow down as you get closer to the bottom - CURSPEED = FixedMul(CURSPEED,FixedDiv(bridge->sector->ceilingheight - LOWCEILINGHEIGHT, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5)); - - if (CURSPEED <= origspeed/16) - CURSPEED = origspeed/16; - else if (CURSPEED > origspeed) - CURSPEED = origspeed; - } - else - { - fixed_t origspeed = CURSPEED; - // Slow down as you get closer to the top - CURSPEED = FixedMul(CURSPEED,FixedDiv(ORIGCEILINGHEIGHT - bridge->sector->ceilingheight, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5)); - - if (CURSPEED <= origspeed/16) - CURSPEED = origspeed/16; - else if (CURSPEED > origspeed) - CURSPEED = origspeed; - } - - res = T_MovePlane - ( - bridge->sector, // sector - CURSPEED, // speed - ceilingdestination, // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - DIRECTION // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - bridge->sector, // sector - CURSPEED, // speed - floordestination, // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - DIRECTION // direction - ); - - bridge->sector->ceilspeed = 42; - bridge->sector->floorspeed = CURSPEED*DIRECTION; - } - } - } - } - } - - // for (i = -1; (i = P_FindSectorFromTag(bridge->sourceline->tag, i)) >= 0 ;) - // P_RecalcPrecipInSector(§ors[i]); - } - else - { - // Iterate control sectors - for (j = (INT16)(ENDTAG+1); j <= (ENDTAG+(ENDTAG-STARTTAG)+1); j++) - { - for (i = -1; (i = P_FindSectorFromTag(j, i)) >= 0 ;) - { - bridge->sector = §ors[i]; - - CURSPEED = BASESPEED/2; - - // rise back up - if (bridge->sector->ceilingheight >= ORIGCEILINGHEIGHT) - { - bridge->sector->floorheight = ORIGCEILINGHEIGHT - (bridge->sector->ceilingheight - bridge->sector->floorheight); - bridge->sector->ceilingheight = ORIGCEILINGHEIGHT; - bridge->sector->ceilspeed = 0; - bridge->sector->floorspeed = 0; - continue; - } - - DIRECTION = 1; - ceilingdestination = ORIGCEILINGHEIGHT; - floordestination = ORIGFLOORHEIGHT; - -// CONS_Debug(DBG_GAMELOGIC, "ceildest: %d, floordest: %d\n", ceilingdestination>>FRACBITS, floordestination>>FRACBITS); - - if ((bridge->sector->ceilingheight - LOWCEILINGHEIGHT) - < (ORIGCEILINGHEIGHT - bridge->sector->ceilingheight)) - { - fixed_t origspeed = CURSPEED; - - // Slow down as you get closer to the bottom - CURSPEED = FixedMul(CURSPEED,FixedDiv(bridge->sector->ceilingheight - LOWCEILINGHEIGHT, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5)); - - if (CURSPEED <= origspeed/16) - CURSPEED = origspeed/16; - else if (CURSPEED > origspeed) - CURSPEED = origspeed; - } - else - { - fixed_t origspeed = CURSPEED; - // Slow down as you get closer to the top - CURSPEED = FixedMul(CURSPEED,FixedDiv(ORIGCEILINGHEIGHT - bridge->sector->ceilingheight, (ORIGCEILINGHEIGHT - LOWCEILINGHEIGHT)>>5)); - - if (CURSPEED <= origspeed/16) - CURSPEED = origspeed/16; - else if (CURSPEED > origspeed) - CURSPEED = origspeed; - } - - res = T_MovePlane - ( - bridge->sector, // sector - CURSPEED, // speed - ceilingdestination, // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - DIRECTION // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - bridge->sector, // sector - CURSPEED, // speed - floordestination, // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - DIRECTION // direction - ); - - bridge->sector->ceilspeed = 42; - bridge->sector->floorspeed = CURSPEED*DIRECTION; - } - } - // Update precip - } - -#undef SAGAMT -#undef LOWFLOORHEIGHT -#undef LOWCEILINGHEIGHT -#undef ORIGFLOORHEIGHT -#undef ORIGCEILINGHEIGHT -#undef BASESPEED -#undef CURSPEED -#undef STARTTAG -#undef ENDTAG -#undef DIRECTION + // we have something to float in! Or we're for some reason above the ground, let's fall anyway + if (floater->sector->crumblestate == CRUMBLE_NONE || floater->sector->crumblestate >= CRUMBLE_FALL/* || floatanyway*/) + EV_BounceSector(floater->sector, FRACUNIT, floater->sourceline); } static mobj_t *SearchMarioNode(msecnode_t *node) @@ -1759,18 +1030,22 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_GHOST: case MT_OVERLAY: case MT_EMERALDSPAWN: - case MT_GREENORB: - case MT_YELLOWORB: - case MT_BLUEORB: - case MT_BLACKORB: - case MT_WHITEORB: - case MT_PITYORB: + case MT_ELEMENTAL_ORB: + case MT_ATTRACT_ORB: + case MT_FORCE_ORB: + case MT_ARMAGEDDON_ORB: + case MT_WHIRLWIND_ORB: + case MT_PITY_ORB: + case MT_FLAMEAURA_ORB: + case MT_BUBBLEWRAP_ORB: + case MT_THUNDERCOIN_ORB: case MT_IVSP: case MT_SUPERSPARK: case MT_RAIN: case MT_SNOWFLAKE: case MT_BLIZZARDSNOW: case MT_SPLISH: + case MT_LAVASPLISH: case MT_SMOKE: case MT_SMALLBUBBLE: case MT_MEDIUMBUBBLE: @@ -1780,9 +1055,9 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_SCORE: case MT_DROWNNUMBERS: case MT_GOTEMERALD: + case MT_LOCKON: case MT_TAG: case MT_GOTFLAG: - case MT_GOTFLAG2: case MT_HOOP: case MT_HOOPCOLLIDE: case MT_NIGHTSCORE: @@ -1794,8 +1069,9 @@ static mobj_t *SearchMarioNode(msecnode_t *node) break; } // Ignore popped monitors, too. - if ((node->m_thing->flags & MF_MONITOR || node->m_thing->type == MT_RANDOMITEM) - && node->m_thing->threshold == 68) + if (node->m_thing->health == 0 // this only really applies for monitors + || (!(node->m_thing->flags & MF_MONITOR) && (mobjinfo[node->m_thing->type].flags & MF_MONITOR)) // gold monitor support + || (node->m_thing->type == MT_RANDOMITEM)) continue; // Okay, we found something valid. if (!thing // take either the first thing @@ -1806,28 +1082,49 @@ static mobj_t *SearchMarioNode(msecnode_t *node) return thing; } -void T_MarioBlockChecker(levelspecthink_t *block) +void T_MarioBlockChecker(mariocheck_t *block) { line_t *masterline = block->sourceline; if (SearchMarioNode(block->sector->touching_thinglist)) - sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; + { + sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].bottomtexture; // Update textures + if (masterline->backsector) + block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->ceilingpic; // Update flats to be backside's ceiling + } else + { sides[masterline->sidenum[0]].midtexture = sides[masterline->sidenum[0]].toptexture; + if (masterline->backsector) + block->sector->ceilingpic = block->sector->floorpic = masterline->backsector->floorpic; // Update flats to be backside's floor + } +} + +static boolean P_IsPlayerValid(size_t playernum) +{ + if (!playeringame[playernum]) + return false; + + if (!players[playernum].mo) + return false; + + if (players[playernum].mo->health <= 0) + return false; + + if (players[playernum].spectator) + return false; + + return true; } // This is the Thwomp's 'brain'. It looks around for players nearby, and if // it finds any, **SMASH**!!! Muahahhaa.... -void T_ThwompSector(levelspecthink_t *thwomp) +void T_ThwompSector(thwomp_t *thwomp) { -#define speed vars[1] -#define direction vars[2] -#define distance vars[3] -#define floorwasheight vars[4] -#define ceilingwasheight vars[5] fixed_t thwompx, thwompy; sector_t *actionsector; ffloor_t *rover = NULL; INT32 secnum; + fixed_t speed; // SRB2kart 170217 - Thwomps are automatic. // Put up a timer before you start falling down. @@ -1839,169 +1136,140 @@ void T_ThwompSector(levelspecthink_t *thwomp) thwomp->direction = 0; // If you just crashed down, wait a second before coming back up. - if (--thwomp->distance > 0) - { - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture; - //sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; + if (--thwomp->delay > 0) return; - } // Just find the first sector with the tag. // Doesn't work with multiple sectors that have different floor/ceiling heights. - secnum = P_FindSectorFromTag((INT16)thwomp->vars[0], -1); + secnum = P_FindSectorFromTag(thwomp->tag, -1); - if (secnum > 0) - { - actionsector = §ors[secnum]; - - // Look for thwomp FFloor - for (rover = actionsector->ffloors; rover; rover = rover->next) - { - if (rover->master == thwomp->sourceline) - break; - } - } - else + if (secnum <= 0) return; // Bad bad bad! + actionsector = §ors[secnum]; + + // Look for thwomp FOF + for (rover = actionsector->ffloors; rover; rover = rover->next) + { + if (rover->master == thwomp->sourceline) + break; + } + + if (!rover) + return; // Didn't find any FOFs, so bail out + thwompx = actionsector->soundorg.x; thwompy = actionsector->soundorg.y; - if (thwomp->direction > 0) // Moving back up.. + if (thwomp->direction == 0) // Not going anywhere, so go back up. { - result_e res = 0; - - // Set the texture from the lower one (normal) - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; - /// \note this should only have to be done once, but is already done repeatedly, above - - if (thwomp->sourceline->flags & ML_EFFECT5) - thwomp->speed = thwomp->sourceline->dx/8; - else - thwomp->speed = 2*FRACUNIT; - - res = T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - thwomp->floorwasheight, // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - thwomp->direction // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - thwomp->ceilingwasheight, // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - thwomp->direction // direction - ); - - if (res == pastdest) - thwomp->direction = 0; // stop moving - - thwomp->sector->ceilspeed = 42; - thwomp->sector->floorspeed = thwomp->speed*thwomp->direction; - } - else if (thwomp->direction < 0) // Crashing down! - { - result_e res = 0; - - // Set the texture from the upper one (angry) - sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture; - - if (thwomp->sourceline->flags & ML_EFFECT5) - thwomp->speed = thwomp->sourceline->dy/8; - else - thwomp->speed = 10*FRACUNIT; - - res = T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, - thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - thwomp->direction // direction - ); - - if (res == ok || res == pastdest) - T_MovePlane - ( - thwomp->sector, // sector - thwomp->speed, // speed - P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, - thwomp->sector->ceilingheight - - (thwomp->sector->floorheight + thwomp->speed)) - + (thwomp->sector->ceilingheight - - (thwomp->sector->floorheight + thwomp->speed/2)), // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - thwomp->direction // direction - ); - - if (res == pastdest) - { - mobj_t *mp = (void *)&actionsector->soundorg; - - if (!rover || (rover->flags & FF_EXISTS)) - { - if (thwomp->sourceline->flags & ML_EFFECT4) - S_StartSound(mp, sides[thwomp->sourceline->sidenum[0]].textureoffset>>FRACBITS); - else - S_StartSound(mp, sfx_thwomp); - } - - thwomp->direction = 1; // start heading back up - thwomp->distance = TICRATE; // but only after a small delay - } - - thwomp->sector->ceilspeed = 42; - thwomp->sector->floorspeed = thwomp->speed*thwomp->direction; - } - else // Not going anywhere, so look for players. - { - //thinker_t *th; - //mobj_t *mo; - thwomp->direction = -1; - - /* // SRB2kart 170217 - Thwomps are automatic. - // scan the thinkers to find players! - if (!rover || (rover->flags & FF_EXISTS)) - { - // scan the thinkers to find players! - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo = (mobj_t *)th; - if (mo->type == MT_PLAYER && mo->health && mo->player && !mo->player->spectator - && mo->z <= thwomp->sector->ceilingheight - && P_AproxDistance(thwompx - mo->x, thwompy - mo->y) <= 96*FRACUNIT) - { - thwomp->direction = -1; - break; - } - } - }*/ - thwomp->sector->ceilspeed = 0; thwomp->sector->floorspeed = 0; } + else + { + result_e res = 0; + + if (thwomp->direction > 0) //Moving back up.. + { + // Set the texture from the lower one (normal) + sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].bottomtexture; + + speed = thwomp->retractspeed; + + res = T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + thwomp->floorstartheight, // dest + false, // crush + false, // ceiling? + thwomp->direction // direction + ); + + if (res == ok || res == pastdest) + T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + thwomp->ceilingstartheight, // dest + false, // crush + true, // ceiling? + thwomp->direction // direction + ); + + if (res == pastdest) + thwomp->direction = 0; // stop moving + } + else // Crashing down! + { + // Set the texture from the upper one (angry) + sides[thwomp->sourceline->sidenum[0]].midtexture = sides[thwomp->sourceline->sidenum[0]].toptexture; + + speed = thwomp->crushspeed; + + res = T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, + thwomp->sector->ceilingheight - thwomp->sector->floorheight), // dest + false, // crush + false, // ceiling? + thwomp->direction // direction + ); + + if (res == ok || res == pastdest) + T_MovePlane + ( + thwomp->sector, // sector + speed, // speed + P_FloorzAtPos(thwompx, thwompy, thwomp->sector->floorheight, + thwomp->sector->ceilingheight + - (thwomp->sector->floorheight + speed)) + + (thwomp->sector->ceilingheight + - (thwomp->sector->floorheight + speed/2)), // dest + false, // crush + true, // ceiling? + thwomp->direction // direction + ); + + if (res == pastdest) + { + if (rover->flags & FF_EXISTS) + S_StartSound((void *)&actionsector->soundorg, thwomp->sound); + + thwomp->direction = 1; // start heading back up + thwomp->delay = TICRATE; // but only after a small delay + } + } + + thwomp->sector->ceilspeed = 42; + thwomp->sector->floorspeed = speed*thwomp->direction; + } P_RecalcPrecipInSector(actionsector); -#undef speed -#undef direction -#undef distance -#undef floorwasheight -#undef ceilingwasheight +} + +static boolean T_SectorHasEnemies(sector_t *sec) +{ + msecnode_t *node = sec->touching_thinglist; // things touching this sector + mobj_t *mo; + while (node) + { + mo = node->m_thing; + + if ((mo->flags & (MF_ENEMY|MF_BOSS)) + && mo->health > 0 + && mo->z < sec->ceilingheight + && mo->z + mo->height > sec->floorheight) + return true; + + node = node->m_thinglist_next; + } + + return false; } // @@ -2010,82 +1278,64 @@ void T_ThwompSector(levelspecthink_t *thwomp) // Runs a linedef exec when no more MF_ENEMY/MF_BOSS objects with health are in the area // \sa P_AddNoEnemiesThinker // -void T_NoEnemiesSector(levelspecthink_t *nobaddies) +void T_NoEnemiesSector(noenemies_t *nobaddies) { size_t i; - fixed_t upperbound, lowerbound; - INT32 s; - sector_t *checksector; - msecnode_t *node; - mobj_t *thing; - boolean exists = false; + sector_t *sec = NULL; + INT32 secnum = -1; + boolean FOFsector = false; - for (i = 0; i < nobaddies->sector->linecount; i++) + while ((secnum = P_FindSectorFromTag(nobaddies->sourceline->tag, secnum)) >= 0) { - if (nobaddies->sector->lines[i]->special == 223) + sec = §ors[secnum]; + + FOFsector = false; + + // Check the lines of this sector, to see if it is a FOF control sector. + for (i = 0; i < sec->linecount; i++) { + INT32 targetsecnum = -1; - upperbound = nobaddies->sector->ceilingheight; - lowerbound = nobaddies->sector->floorheight; + if (sec->lines[i]->special < 100 || sec->lines[i]->special >= 300) + continue; - for (s = -1; (s = P_FindSectorFromLineTag(nobaddies->sector->lines[i], s)) >= 0 ;) + FOFsector = true; + + while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0) { - checksector = §ors[s]; - - node = checksector->touching_thinglist; // things touching this sector - while (node) - { - thing = node->m_thing; - - if ((thing->flags & (MF_ENEMY|MF_BOSS)) && thing->health > 0 - && thing->z < upperbound && thing->z+thing->height > lowerbound) - { - exists = true; - goto foundenemy; - } - - node = node->m_thinglist_next; - } + if (T_SectorHasEnemies(§ors[targetsecnum])) + return; } } + + if (!FOFsector && T_SectorHasEnemies(sec)) + return; } -foundenemy: - if (exists) - return; - s = P_AproxDistance(nobaddies->sourceline->dx, nobaddies->sourceline->dy)>>FRACBITS; + CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", nobaddies->sourceline->tag); - CONS_Debug(DBG_GAMELOGIC, "Running no-more-enemies exec with tag of %d\n", s); - - // Otherwise, run the linedef exec and terminate this thinker - P_LinedefExecute((INT16)s, NULL, NULL); + // No enemies found, run the linedef exec and terminate this thinker + P_RunTriggerLinedef(nobaddies->sourceline, NULL, NULL); P_RemoveThinker(&nobaddies->thinker); } -// -// P_HavePlayersEnteredArea -// -// Helper function for T_EachTimeThinker -// -static INT32 P_HavePlayersEnteredArea(boolean *curPlayers, boolean *oldPlayers, boolean inAndOut) +static boolean P_IsMobjTouchingSector(mobj_t *mo, sector_t *sec) { - INT32 i; + msecnode_t *node; - // Easy check... nothing has changed - if (!memcmp(curPlayers, oldPlayers, sizeof(boolean)*MAXPLAYERS)) - return -1; + if (mo->subsector->sector == sec) + return true; - // Otherwise, we have to check if any new players have entered - for (i = 0; i < MAXPLAYERS; i++) + if (!(sec->flags & SF_TRIGGERSPECIAL_TOUCH)) + return false; + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) { - if (inAndOut && !curPlayers[i] && oldPlayers[i]) - return i; - - if (curPlayers[i] && !oldPlayers[i]) - return i; + if (node->m_sector == sec) + return true; } - return -1; + return false; } // @@ -2096,47 +1346,30 @@ static INT32 P_HavePlayersEnteredArea(boolean *curPlayers, boolean *oldPlayers, // // \sa P_AddEachTimeThinker // -void T_EachTimeThinker(levelspecthink_t *eachtime) +void T_EachTimeThinker(eachtime_t *eachtime) { size_t i, j; sector_t *sec = NULL; sector_t *targetsec = NULL; - //sector_t *usesec = NULL; INT32 secnum = -1; - INT32 affectPlayer = 0; boolean oldPlayersInArea[MAXPLAYERS]; - boolean playersInArea[MAXPLAYERS]; boolean oldPlayersOnArea[MAXPLAYERS]; - boolean playersOnArea[MAXPLAYERS]; boolean *oldPlayersArea; boolean *playersArea; boolean FOFsector = false; - boolean inAndOut = false; boolean floortouch = false; fixed_t bottomheight, topheight; - msecnode_t *node; ffloor_t *rover; for (i = 0; i < MAXPLAYERS; i++) { - if (i & 1) - { - oldPlayersInArea[i] = eachtime->vars[i/2] & 65535; - oldPlayersOnArea[i] = eachtime->var2s[i/2] & 65535; - eachtime->vars[i/2] = 0; - eachtime->var2s[i/2] = 0; - } - else - { - oldPlayersInArea[i] = eachtime->vars[i/2] >> 16; - oldPlayersOnArea[i] = eachtime->var2s[i/2] >> 16; - } - - playersInArea[i] = false; - playersOnArea[i] = false; + oldPlayersInArea[i] = eachtime->playersInArea[i]; + oldPlayersOnArea[i] = eachtime->playersOnArea[i]; + eachtime->playersInArea[i] = false; + eachtime->playersOnArea[i] = false; } - while ((secnum = P_FindSectorFromLineTag(eachtime->sourceline, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(eachtime->sourceline->tag, secnum)) >= 0) { sec = §ors[secnum]; @@ -2159,7 +1392,7 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) FOFsector = true; - while ((targetsecnum = P_FindSectorFromLineTag(sec->lines[i], targetsecnum)) >= 0) + while ((targetsecnum = P_FindSectorFromTag(sec->lines[i]->tag, targetsecnum)) >= 0) { targetsec = §ors[targetsecnum]; @@ -2178,35 +1411,10 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) for (j = 0; j < MAXPLAYERS; j++) { - if (!playeringame[j]) + if (!P_IsPlayerValid(j)) continue; - if (!players[j].mo) - continue; - - if (players[j].mo->health <= 0) - continue; - - if ((netgame || multiplayer) && players[j].spectator) - continue; - - if (players[j].mo->subsector->sector == targetsec) - ; - else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH) - { - boolean insector = false; - for (node = players[j].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector == targetsec) - { - insector = true; - break; - } - } - if (!insector) - continue; - } - else + if (!P_IsMobjTouchingSector(players[j].mo, targetsec)) continue; topheight = P_GetSpecialTopZ(players[j].mo, sec, targetsec); @@ -2218,24 +1426,10 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) if (players[j].mo->z + players[j].mo->height < bottomheight) continue; - if (floortouch == true && P_IsObjectOnGroundIn(players[j].mo, targetsec)) - { - if (j & 1) - eachtime->var2s[j/2] |= 1; - else - eachtime->var2s[j/2] |= 1 << 16; - - playersOnArea[j] = true; - } + if (floortouch && P_IsObjectOnGroundIn(players[j].mo, targetsec)) + eachtime->playersOnArea[j] = true; else - { - if (j & 1) - eachtime->vars[j/2] |= 1; - else - eachtime->vars[j/2] |= 1 << 16; - - playersInArea[j] = true; - } + eachtime->playersInArea[j] = true; } } } @@ -2244,102 +1438,61 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) { for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i]) + if (!P_IsPlayerValid(i)) continue; - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if ((netgame || multiplayer) && players[i].spectator) - continue; - - if (players[i].mo->subsector->sector == sec) - ; - else if (sec->flags & SF_TRIGGERSPECIAL_TOUCH) - { - boolean insector = false; - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector == sec) - { - insector = true; - break; - } - } - if (!insector) - continue; - } - else + if (!P_IsMobjTouchingSector(players[i].mo, sec)) continue; if (!(players[i].mo->subsector->sector == sec || P_MobjTouchingSectorSpecial(players[i].mo, 2, (GETSECSPECIAL(sec->special, 2)), false) == sec)) continue; - if (floortouch == true && P_IsObjectOnRealGround(players[i].mo, sec)) - { - if (i & 1) - eachtime->var2s[i/2] |= 1; - else - eachtime->var2s[i/2] |= 1 << 16; - - playersOnArea[i] = true; - } + if (floortouch && P_IsObjectOnRealGround(players[i].mo, sec)) + eachtime->playersOnArea[i] = true; else - { - if (i & 1) - eachtime->vars[i/2] |= 1; - else - eachtime->vars[i/2] |= 1 << 16; - - playersInArea[i] = true; - } + eachtime->playersInArea[i] = true; } } } - if ((eachtime->sourceline->flags & ML_BOUNCY) == ML_BOUNCY) - inAndOut = true; - // Check if a new player entered. // If not, check if a player hit the floor. // If either condition is true, execute. - if (floortouch == true) + if (floortouch) { - playersArea = playersOnArea; + playersArea = eachtime->playersOnArea; oldPlayersArea = oldPlayersOnArea; } else { - playersArea = playersInArea; + playersArea = eachtime->playersInArea; oldPlayersArea = oldPlayersInArea; } - while ((affectPlayer = P_HavePlayersEnteredArea(playersArea, oldPlayersArea, inAndOut)) != -1) + // Easy check... nothing has changed + if (!memcmp(playersArea, oldPlayersArea, sizeof(boolean)*MAXPLAYERS)) + return; + + // If sector has an "all players" trigger type, all players need to be in area + if (GETSECSPECIAL(sec->special, 2) == 2 || GETSECSPECIAL(sec->special, 2) == 3) { - if (GETSECSPECIAL(sec->special, 2) == 2 || GETSECSPECIAL(sec->special, 2) == 3) + for (i = 0; i < MAXPLAYERS; i++) { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if ((netgame || multiplayer) && players[i].spectator) - continue; - - if (!playersArea[i]) - return; - } + if (P_IsPlayerValid(i) && playersArea[i]) + continue; } + } + + // Trigger for every player who has entered (and exited, if triggerOnExit) + for (i = 0; i < MAXPLAYERS; i++) + { + if (playersArea[i] == oldPlayersArea[i]) + continue; + + // If player has just left, check if still valid + if (!playersArea[i] && (!eachtime->triggerOnExit || !P_IsPlayerValid(i))) + continue; CONS_Debug(DBG_GAMELOGIC, "Trying to activate each time executor with tag %d\n", eachtime->sourceline->tag); @@ -2347,12 +1500,10 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) // No more stupid hacks involving changing eachtime->sourceline's tag or special or whatever! // This should now run ONLY the stuff for eachtime->sourceline itself, instead of all trigger linedefs sharing the same tag. // Makes much more sense doing it this way, honestly. - P_RunTriggerLinedef(eachtime->sourceline, players[affectPlayer].mo, sec); + P_RunTriggerLinedef(eachtime->sourceline, players[i].mo, sec); if (!eachtime->sourceline->special) // this happens only for "Trigger on X calls" linedefs P_RemoveThinker(&eachtime->thinker); - - oldPlayersArea[affectPlayer]=playersArea[affectPlayer]; } } @@ -2362,20 +1513,24 @@ void T_EachTimeThinker(levelspecthink_t *eachtime) // Rises up to its topmost position when a // player steps on it. Lowers otherwise. // -void T_RaiseSector(levelspecthink_t *raise) +void T_RaiseSector(raise_t *raise) { msecnode_t *node; mobj_t *thing; sector_t *sector; INT32 i; - boolean playeronme = false; + boolean playeronme = false, active = false; + boolean moveUp; fixed_t ceilingdestination, floordestination; + fixed_t speed, origspeed; + fixed_t distToNearestEndpoint; + INT32 direction; result_e res = 0; - if (raise->sector->crumblestate >= 3 || raise->sector->ceilingdata) + if (raise->sector->crumblestate >= CRUMBLE_FALL || raise->sector->ceilingdata) return; - for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;) { sector = §ors[i]; @@ -2392,7 +1547,7 @@ void T_RaiseSector(levelspecthink_t *raise) continue; // Option to require spindashing. - if (raise->vars[1] && !(thing->player->pflags & PF_STARTDASH)) + if (raise->flags & RF_SPINDASH && !(thing->player->pflags & PF_STARTDASH)) continue; if (!(thing->z == P_GetSpecialTopZ(thing, raise->sector, sector))) @@ -2403,125 +1558,106 @@ void T_RaiseSector(levelspecthink_t *raise) } } - if (playeronme) + if (raise->flags & RF_DYNAMIC) // Dynamically Sinking Platform^tm { - raise->vars[3] = raise->vars[2]; - - if (raise->vars[0] == 1) +#define shaketime 10 + if (raise->shaketimer > shaketime) // State: moving { - if (raise->sector->ceilingheight <= raise->vars[7]) + if (playeronme) // If player is standing on the platform, accelerate { - raise->sector->floorheight = raise->vars[7] - (raise->sector->ceilingheight - raise->sector->floorheight); - raise->sector->ceilingheight = raise->vars[7]; - raise->sector->ceilspeed = 0; - raise->sector->floorspeed = 0; - return; + raise->extraspeed += (FRACUNIT >> 5); } - - raise->vars[8] = -1; - ceilingdestination = raise->vars[7]; - floordestination = raise->vars[6]; + else // otherwise, decelerate until inflection + { + raise->extraspeed -= FRACUNIT >> 3; + if (raise->extraspeed <= 0) // inflection! + { + raise->extraspeed = 0; + raise->shaketimer = 0; // allow the shake to occur again (fucks over players attempting to jump-cheese) + } + } + active = raise->extraspeed > 0; } - else // elevateUp + else // State: shaking { - if (raise->sector->ceilingheight >= raise->vars[5]) + if (playeronme || raise->shaketimer) { - raise->sector->floorheight = raise->vars[5] - (raise->sector->ceilingheight - raise->sector->floorheight); - raise->sector->ceilingheight = raise->vars[5]; - raise->sector->ceilspeed = 0; - raise->sector->floorspeed = 0; - return; + active = true; + if (++raise->shaketimer > shaketime) + { + if (playeronme) + raise->extraspeed = FRACUNIT >> 5; + else + raise->extraspeed = FRACUNIT << 1; + } + else + { + raise->extraspeed = ((shaketime/2) - raise->shaketimer) << FRACBITS; + if (raise->extraspeed < -raise->basespeed/2) + raise->extraspeed = -raise->basespeed/2; + } } - - raise->vars[8] = 1; - ceilingdestination = raise->vars[5]; - floordestination = raise->vars[4]; } +#undef shaketime } - else + else // Air bobbing platform (not a Dynamically Sinking Platform^tm) + active = playeronme; + + moveUp = active ^ (raise->flags & RF_REVERSE); + ceilingdestination = moveUp ? raise->ceilingtop : raise->ceilingbottom; + floordestination = ceilingdestination - (raise->sector->ceilingheight - raise->sector->floorheight); + + if ((moveUp && raise->sector->ceilingheight >= ceilingdestination) + || (!moveUp && raise->sector->ceilingheight <= ceilingdestination)) { - raise->vars[3] = raise->vars[2]/2; - - if (raise->vars[0] == 1) - { - if (raise->sector->ceilingheight >= raise->vars[5]) - { - raise->sector->floorheight = raise->vars[5] - (raise->sector->ceilingheight - raise->sector->floorheight); - raise->sector->ceilingheight = raise->vars[5]; - raise->sector->ceilspeed = 0; - raise->sector->floorspeed = 0; - return; - } - raise->vars[8] = 1; - ceilingdestination = raise->vars[5]; - floordestination = raise->vars[4]; - } - else // elevateUp - { - if (raise->sector->ceilingheight <= raise->vars[7]) - { - raise->sector->floorheight = raise->vars[7] - (raise->sector->ceilingheight - raise->sector->floorheight); - raise->sector->ceilingheight = raise->vars[7]; - raise->sector->ceilspeed = 0; - raise->sector->floorspeed = 0; - return; - } - raise->vars[8] = -1; - ceilingdestination = raise->vars[7]; - floordestination = raise->vars[6]; - } + raise->sector->floorheight = floordestination; + raise->sector->ceilingheight = ceilingdestination; + raise->sector->ceilspeed = 0; + raise->sector->floorspeed = 0; + return; } + direction = moveUp ? 1 : -1; - if ((raise->sector->ceilingheight - raise->vars[7]) - < (raise->vars[5] - raise->sector->ceilingheight)) - { - fixed_t origspeed = raise->vars[3]; + origspeed = raise->basespeed; + if (!active) + origspeed /= 2; - // Slow down as you get closer to the bottom - raise->vars[3] = FixedMul(raise->vars[3],FixedDiv(raise->sector->ceilingheight - raise->vars[7], (raise->vars[5] - raise->vars[7])>>5)); + // Speed up as you get closer to the middle, then slow down again + distToNearestEndpoint = min(raise->sector->ceilingheight - raise->ceilingbottom, raise->ceilingtop - raise->sector->ceilingheight); + speed = FixedMul(origspeed, FixedDiv(distToNearestEndpoint, (raise->ceilingtop - raise->ceilingbottom) >> 5)); - if (raise->vars[3] <= origspeed/16) - raise->vars[3] = origspeed/16; - else if (raise->vars[3] > origspeed) - raise->vars[3] = origspeed; - } - else - { - fixed_t origspeed = raise->vars[3]; - // Slow down as you get closer to the top - raise->vars[3] = FixedMul(raise->vars[3],FixedDiv(raise->vars[5] - raise->sector->ceilingheight, (raise->vars[5] - raise->vars[7])>>5)); + if (speed <= origspeed/16) + speed = origspeed/16; + else if (speed > origspeed) + speed = origspeed; - if (raise->vars[3] <= origspeed/16) - raise->vars[3] = origspeed/16; - else if (raise->vars[3] > origspeed) - raise->vars[3] = origspeed; - } + speed += raise->extraspeed; res = T_MovePlane ( - raise->sector, // sector - raise->vars[3], // speed + raise->sector, // sector + speed, // speed ceilingdestination, // dest - 0, // crush - 1, // floor or ceiling (1 for ceiling) - raise->vars[8] // direction + false, // crush + true, // ceiling? + direction // direction ); if (res == ok || res == pastdest) T_MovePlane ( - raise->sector, // sector - raise->vars[3], // speed + raise->sector, // sector + speed, // speed floordestination, // dest - 0, // crush - 0, // floor or ceiling (0 for floor) - raise->vars[8] // direction + false, // crush + false, // ceiling? + direction // direction ); raise->sector->ceilspeed = 42; - raise->sector->floorspeed = raise->vars[3]*raise->vars[8]; + raise->sector->floorspeed = speed*direction; - for (i = -1; (i = P_FindSectorFromTag(raise->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(raise->tag, i)) >= 0 ;) P_RecalcPrecipInSector(§ors[i]); } @@ -2529,125 +1665,74 @@ void T_CameraScanner(elevator_t *elevator) { // leveltime is compared to make multiple scanners in one map function correctly. static tic_t lastleveltime = 32000; // any number other than 0 should do here - static boolean camerascanned, camerascanned2, camerascanned3, camerascanned4; + static boolean camerascanned[MAXSPLITSCREENPLAYERS]; + UINT8 i; if (leveltime != lastleveltime) // Back on the first camera scanner { - camerascanned = camerascanned2 = camerascanned3 = camerascanned4 = false; + memset(camerascanned, false, sizeof (camerascanned)); lastleveltime = leveltime; } - if (players[g_localplayers[0]].mo) + for (i = 0; i <= r_splitscreen; i++) { - if (players[g_localplayers[0]].mo->subsector->sector == elevator->actionsector) - { - if (t_cam_dist == -42) - t_cam_dist = cv_cam_dist.value; - if (t_cam_height == -42) - t_cam_height = cv_cam_height.value; - if (t_cam_rotate == -42) - t_cam_rotate = cv_cam_rotate.value; - CV_SetValue(&cv_cam_height, FixedInt(elevator->sector->floorheight)); - CV_SetValue(&cv_cam_dist, FixedInt(elevator->sector->ceilingheight)); - CV_SetValue(&cv_cam_rotate, elevator->distance); - camerascanned = true; - } - else if (!camerascanned) - { - if (t_cam_height != -42 && cv_cam_height.value != t_cam_height) - CV_Set(&cv_cam_height, va("%f", (double)FIXED_TO_FLOAT(t_cam_height))); - if (t_cam_dist != -42 && cv_cam_dist.value != t_cam_dist) - CV_Set(&cv_cam_dist, va("%f", (double)FIXED_TO_FLOAT(t_cam_dist))); - if (t_cam_rotate != -42 && cv_cam_rotate.value != t_cam_rotate) - CV_Set(&cv_cam_rotate, va("%f", (double)t_cam_rotate)); + if (!players[displayplayers[i]].mo || P_MobjWasRemoved(players[displayplayers[i]].mo)) + continue; - t_cam_dist = t_cam_height = t_cam_rotate = -42; + if (players[displayplayers[i]].mo->subsector->sector == elevator->actionsector) + { + if (t_cam_dist[i] == -42) + t_cam_dist[i] = cv_cam_dist[i].value; + if (t_cam_height[i] == -42) + t_cam_height[i] = cv_cam_height[i].value; + if (t_cam_rotate[i] == -42) + t_cam_rotate[i] = cv_cam_rotate[i].value; + CV_SetValue(&cv_cam_height[i], FixedInt(elevator->sector->floorheight)); + CV_SetValue(&cv_cam_dist[i], FixedInt(elevator->sector->ceilingheight)); + CV_SetValue(&cv_cam_rotate[i], elevator->distance); + camerascanned[i] = true; + } + else if (!camerascanned[i]) + { + if (t_cam_height[i] != -42 && cv_cam_height[i].value != t_cam_height[i]) + CV_Set(&cv_cam_height[i], va("%f", (double)FIXED_TO_FLOAT(t_cam_height[i]))); + if (t_cam_dist[i] != -42 && cv_cam_dist[i].value != t_cam_dist[i]) + CV_Set(&cv_cam_dist[i], va("%f", (double)FIXED_TO_FLOAT(t_cam_dist[i]))); + if (t_cam_rotate[i] != -42 && cv_cam_rotate[i].value != t_cam_rotate[i]) + CV_Set(&cv_cam_rotate[i], va("%f", (double)t_cam_rotate[i])); + + t_cam_dist[i] = t_cam_height[i] = t_cam_rotate[i] = -42; } } +} - if (splitscreen && players[g_localplayers[1]].mo) +void T_PlaneDisplace(planedisplace_t *pd) +{ + sector_t *control, *target; + INT32 direction; + fixed_t diff; + + control = §ors[pd->control]; + target = §ors[pd->affectee]; + + if (control->floorheight == pd->last_height) + return; // no change, no movement + + direction = (control->floorheight > pd->last_height) ? 1 : -1; + diff = FixedMul(control->floorheight-pd->last_height, pd->speed); + + if (pd->reverse) // reverse direction? { - if (players[g_localplayers[1]].mo->subsector->sector == elevator->actionsector) - { - if (t_cam2_rotate == -42) - t_cam2_dist = cv_cam2_dist.value; - if (t_cam2_rotate == -42) - t_cam2_height = cv_cam2_height.value; - if (t_cam2_rotate == -42) - t_cam2_rotate = cv_cam2_rotate.value; - CV_SetValue(&cv_cam2_height, FixedInt(elevator->sector->floorheight)); - CV_SetValue(&cv_cam2_dist, FixedInt(elevator->sector->ceilingheight)); - CV_SetValue(&cv_cam2_rotate, elevator->distance); - camerascanned2 = true; - } - else if (!camerascanned2) - { - if (t_cam2_height != -42 && cv_cam2_height.value != t_cam2_height) - CV_Set(&cv_cam2_height, va("%f", (double)FIXED_TO_FLOAT(t_cam2_height))); - if (t_cam2_dist != -42 && cv_cam2_dist.value != t_cam2_dist) - CV_Set(&cv_cam2_dist, va("%f", (double)FIXED_TO_FLOAT(t_cam2_dist))); - if (t_cam2_rotate != -42 && cv_cam2_rotate.value != t_cam2_rotate) - CV_Set(&cv_cam2_rotate, va("%f", (double)t_cam2_rotate)); - - t_cam2_dist = t_cam2_height = t_cam2_rotate = -42; - } + direction *= -1; + diff *= -1; } - if (splitscreen > 1 && players[g_localplayers[2]].mo) - { - if (players[g_localplayers[2]].mo->subsector->sector == elevator->actionsector) - { - if (t_cam3_rotate == -42) - t_cam3_dist = cv_cam3_dist.value; - if (t_cam3_rotate == -42) - t_cam3_height = cv_cam3_height.value; - if (t_cam3_rotate == -42) - t_cam3_rotate = cv_cam3_rotate.value; - CV_SetValue(&cv_cam3_height, FixedInt(elevator->sector->floorheight)); - CV_SetValue(&cv_cam3_dist, FixedInt(elevator->sector->ceilingheight)); - CV_SetValue(&cv_cam3_rotate, elevator->distance); - camerascanned3 = true; - } - else if (!camerascanned3) - { - if (t_cam3_height != -42 && cv_cam3_height.value != t_cam3_height) - CV_Set(&cv_cam3_height, va("%f", (double)FIXED_TO_FLOAT(t_cam3_height))); - if (t_cam3_dist != -42 && cv_cam3_dist.value != t_cam3_dist) - CV_Set(&cv_cam3_dist, va("%f", (double)FIXED_TO_FLOAT(t_cam3_dist))); - if (t_cam3_rotate != -42 && cv_cam3_rotate.value != t_cam3_rotate) - CV_Set(&cv_cam3_rotate, va("%f", (double)t_cam3_rotate)); + if (pd->type == pd_floor || pd->type == pd_both) + T_MovePlane(target, INT32_MAX/2, target->floorheight+diff, false, false, direction); // move floor + if (pd->type == pd_ceiling || pd->type == pd_both) + T_MovePlane(target, INT32_MAX/2, target->ceilingheight+diff, false, true, direction); // move ceiling - t_cam3_dist = t_cam3_height = t_cam3_rotate = -42; - } - } - - if (splitscreen > 2 && players[g_localplayers[3]].mo) - { - if (players[g_localplayers[3]].mo->subsector->sector == elevator->actionsector) - { - if (t_cam4_rotate == -42) - t_cam4_dist = cv_cam4_dist.value; - if (t_cam4_rotate == -42) - t_cam4_height = cv_cam4_height.value; - if (t_cam4_rotate == -42) - t_cam4_rotate = cv_cam4_rotate.value; - CV_SetValue(&cv_cam4_height, FixedInt(elevator->sector->floorheight)); - CV_SetValue(&cv_cam4_dist, FixedInt(elevator->sector->ceilingheight)); - CV_SetValue(&cv_cam4_rotate, elevator->distance); - camerascanned4 = true; - } - else if (!camerascanned4) - { - if (t_cam4_height != -42 && cv_cam4_height.value != t_cam4_height) - CV_Set(&cv_cam4_height, va("%f", (double)FIXED_TO_FLOAT(t_cam4_height))); - if (t_cam4_dist != -42 && cv_cam4_dist.value != t_cam4_dist) - CV_Set(&cv_cam4_dist, va("%f", (double)FIXED_TO_FLOAT(t_cam4_dist))); - if (t_cam4_rotate != -42 && cv_cam4_rotate.value != t_cam4_rotate) - CV_Set(&cv_cam4_rotate, va("%f", (double)t_cam4_rotate)); - - t_cam4_dist = t_cam4_height = t_cam4_rotate = -42; - } - } + pd->last_height = control->floorheight; } // @@ -2659,14 +1744,14 @@ void T_CameraScanner(elevator_t *elevator) // (egg capsule button), P_PlayerInSpecialSector (buttons), // and P_SpawnSpecials (continuous floor movers and instant lower). // -INT32 EV_DoFloor(line_t *line, floor_e floortype) +void EV_DoFloor(line_t *line, floor_e floortype) { - INT32 rtn = 0, firstone = 1; + INT32 firstone = 1; INT32 secnum = -1; sector_t *sec; floormove_t *dofloor; - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { sec = §ors[secnum]; @@ -2674,9 +1759,8 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype) continue; // then don't add another one // new floor thinker - rtn = 1; dofloor = Z_Calloc(sizeof (*dofloor), PU_LEVSPEC, NULL); - P_AddThinker(&dofloor->thinker); + P_AddThinker(THINK_MAIN, &dofloor->thinker); // make sure another floor thinker won't get started over this one sec->floordata = dofloor; @@ -2864,8 +1948,6 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype) firstone = 0; } - - return rtn; } // SoM: Boom elevator support. @@ -2878,15 +1960,14 @@ INT32 EV_DoFloor(line_t *line, floor_e floortype) // // jff 2/22/98 new type to move floor and ceiling in parallel // -INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) +void EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) { INT32 secnum = -1; - INT32 rtn = 0; sector_t *sec; elevator_t *elevator; // act on all sectors with the same tag as the triggering linedef - while ((secnum = P_FindSectorFromLineTag(line,secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag,secnum)) >= 0) { sec = §ors[secnum]; @@ -2895,9 +1976,8 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) continue; // create and initialize new elevator thinker - rtn = 1; elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); - P_AddThinker(&elevator->thinker); + P_AddThinker(THINK_MAIN, &elevator->thinker); sec->floordata = elevator; sec->ceilingdata = elevator; elevator->thinker.function.acp1 = (actionf_p1)T_MoveElevator; @@ -2997,29 +2077,70 @@ INT32 EV_DoElevator(line_t *line, elevator_e elevtype, boolean customspeed) break; } } - return rtn; } void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) { - size_t i; - size_t leftmostvertex = 0, rightmostvertex = 0; - size_t topmostvertex = 0, bottommostvertex = 0; - fixed_t leftx, rightx; - fixed_t topy, bottomy; - fixed_t topz; - fixed_t a, b, c; - mobjtype_t type = MT_ROCKCRUMBLE1; - const fixed_t spacing = 48*mapobjectscale; + size_t i, leftmostvertex, rightmostvertex, topmostvertex, bottommostvertex; + fixed_t leftx, rightx, topy, bottomy, topz, bottomz, widthfactor, heightfactor, a, b, c, spacing; + mobjtype_t type; + tic_t lifetime; + INT16 flags; - // If the control sector has a special - // of Section3:7-15, use the custom debris. - if (GETSECSPECIAL(rover->master->frontsector->special, 3) >= 8) - type = MT_ROCKCRUMBLE1+(GETSECSPECIAL(rover->master->frontsector->special, 3)-7); + sector_t *controlsec = rover->master->frontsector; + + if (sec == NULL) + { + if (controlsec->numattached) + { + for (i = 0; i < controlsec->numattached; i++) + { + sec = §ors[controlsec->attached[i]]; + if (!sec->ffloors) + continue; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector == controlsec) + EV_CrumbleChain(sec, rover); + } + } + } + return; + } + + leftmostvertex = rightmostvertex = topmostvertex = bottommostvertex = 0; + widthfactor = heightfactor = FRACUNIT; + spacing = (32<tag != 0) + { + INT32 tagline = P_FindSpecialLineFromTag(14, controlsec->tag, -1); + if (tagline != -1) + { + if (sides[lines[tagline].sidenum[0]].toptexture) + type = (mobjtype_t)sides[lines[tagline].sidenum[0]].toptexture; // Set as object type in p_setup.c... + if (sides[lines[tagline].sidenum[0]].textureoffset) + spacing = sides[lines[tagline].sidenum[0]].textureoffset; + if (sides[lines[tagline].sidenum[0]].rowoffset) + { + if (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS != -1) + lifetime = (sides[lines[tagline].sidenum[0]].rowoffset>>FRACBITS); + else + lifetime = 0; + } + flags = lines[tagline].flags; + } + } + +#undef controlsec // soundorg z height never gets set normally, so MEH. sec->soundorg.z = sec->floorheight; - S_StartSound(&sec->soundorg, sfx_crumbl); + S_StartSound(&sec->soundorg, mobjinfo[type].activesound); // Find the outermost vertexes in the subsector for (i = 0; i < sec->linecount; i++) @@ -3038,11 +2159,19 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) bottommostvertex = i; } - leftx = sec->lines[leftmostvertex]->v1->x+(16<lines[leftmostvertex]->v1->x+(spacing>>1); rightx = sec->lines[rightmostvertex]->v1->x; - topy = sec->lines[topmostvertex]->v1->y-(16<lines[topmostvertex]->v1->y-(spacing>>1); bottomy = sec->lines[bottommostvertex]->v1->y; - topz = *rover->topheight-(spacing/2); + + topz = *rover->topheight-(spacing>>1); + bottomz = *rover->bottomheight; + + if (flags & ML_EFFECT1) + { + widthfactor = (rightx + topy - leftx - bottomy)>>3; + heightfactor = (topz - *rover->bottomheight)>>2; + } for (a = leftx; a < rightx; a += spacing) { @@ -3051,10 +2180,24 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) if (R_PointInSubsector(a, b)->sector == sec) { mobj_t *spawned = NULL; - for (c = topz; c > *rover->bottomheight; c -= spacing) + + if (*rover->t_slope) + topz = P_GetSlopeZAt(*rover->t_slope, a, b) - (spacing>>1); + if (*rover->b_slope) + bottomz = P_GetSlopeZAt(*rover->b_slope, a, b); + + for (c = topz; c > bottomz; c -= spacing) { spawned = P_SpawnMobj(a, b, c, type); - spawned->fuse = 3*TICRATE; + spawned->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones + + if (flags & ML_EFFECT1) + { + P_InstaThrust(spawned, R_PointToAngle2(sec->soundorg.x, sec->soundorg.y, a, b), FixedDiv(P_AproxDistance(a - sec->soundorg.x, b - sec->soundorg.y), widthfactor)); + P_SetObjectMomZ(spawned, FixedDiv((c - bottomz), heightfactor), false); + } + + spawned->fuse = lifetime; } } } @@ -3063,93 +2206,61 @@ void EV_CrumbleChain(sector_t *sec, ffloor_t *rover) // no longer exists (can't collide with again) rover->flags &= ~FF_EXISTS; rover->master->frontsector->moved = true; - sec->moved = true; + P_RecalcPrecipInSector(sec); } // Used for bobbing platforms on the water -INT32 EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline) +void EV_BounceSector(sector_t *sec, fixed_t momz, line_t *sourceline) { -#define speed vars[0] -#define distance vars[1] -#define low vars[2] - levelspecthink_t *bouncer; + bouncecheese_t *bouncer; // create and initialize new thinker if (sec->ceilingdata) // One at a time, ma'am. - return 0; + return; bouncer = Z_Calloc(sizeof (*bouncer), PU_LEVSPEC, NULL); - P_AddThinker(&bouncer->thinker); + P_AddThinker(THINK_MAIN, &bouncer->thinker); sec->ceilingdata = bouncer; bouncer->thinker.function.acp1 = (actionf_p1)T_BounceCheese; // set up the fields according to the type of elevator action + bouncer->sourceline = sourceline; bouncer->sector = sec; bouncer->speed = momz/2; - bouncer->sourceline = sourceline; bouncer->distance = FRACUNIT; - bouncer->low = 1; - - return 1; -#undef speed -#undef distance -#undef low + bouncer->low = true; } // For T_ContinuousFalling special -INT32 EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boolean backwards) +void EV_DoContinuousFall(sector_t *sec, sector_t *backsector, fixed_t spd, boolean backwards) { -#define speed vars[0] -#define direction vars[1] -#define floorwasheight vars[2] -#define ceilingwasheight vars[3] -#define floordestheight vars[4] -#define ceilingdestheight vars[5] - levelspecthink_t *faller; + continuousfall_t *faller; // workaround for when there is no back sector - if (backsector == NULL) + if (!backsector) backsector = sec; // create and initialize new thinker faller = Z_Calloc(sizeof (*faller), PU_LEVSPEC, NULL); - P_AddThinker(&faller->thinker); + P_AddThinker(THINK_MAIN, &faller->thinker); faller->thinker.function.acp1 = (actionf_p1)T_ContinuousFalling; // set up the fields faller->sector = sec; faller->speed = spd; - faller->floorwasheight = sec->floorheight; - faller->ceilingwasheight = sec->ceilingheight; + faller->floorstartheight = sec->floorheight; + faller->ceilingstartheight = sec->ceilingheight; - if (backwards) - { - faller->ceilingdestheight = backsector->ceilingheight; - faller->floordestheight = faller->ceilingdestheight; - faller->direction = 1; // Up! - } - else - { - faller->floordestheight = backsector->floorheight; - faller->ceilingdestheight = faller->floordestheight; - faller->direction = -1; - } - - return 1; -#undef speed -#undef direction -#undef floorwasheight -#undef ceilingwasheight -#undef floordestheight -#undef ceilingdestheight + faller->destheight = backwards ? backsector->ceilingheight : backsector->floorheight; + faller->direction = backwards ? 1 : -1; } // Some other 3dfloor special things Tails 03-11-2002 (Search p_mobj.c for description) INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, player_t *player, fixed_t origalpha, boolean crumblereturn) { - elevator_t *elevator; + crumble_t *crumble; sector_t *foundsec; INT32 i; @@ -3157,99 +2268,93 @@ INT32 EV_StartCrumble(sector_t *sec, ffloor_t *rover, boolean floating, if (sec->floordata) return 0; - if (sec->crumblestate > 1) + if (sec->crumblestate >= CRUMBLE_ACTIVATED) return 0; - // create and initialize new elevator thinker - elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); - P_AddThinker(&elevator->thinker); - elevator->thinker.function.acp1 = (actionf_p1)T_StartCrumble; + // create and initialize new crumble thinker + crumble = Z_Calloc(sizeof (*crumble), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &crumble->thinker); + crumble->thinker.function.acp1 = (actionf_p1)T_StartCrumble; - // Does this crumbler return? - if (crumblereturn) - elevator->type = elevateBounce; - else - elevator->type = elevateContinuous; - - // set up the fields according to the type of elevator action - elevator->sector = sec; - elevator->speed = 0; + // set up the fields + crumble->sector = sec; + crumble->speed = 0; if (player && player->mo && (player->mo->eflags & MFE_VERTICALFLIP)) { - elevator->direction = 1; // Up - elevator->floordestheight = 1; + crumble->direction = 1; // Up + crumble->flags |= CF_REVERSE; } else - { - elevator->direction = -1; // Down - elevator->floordestheight = 0; - } + crumble->direction = -1; // Down - elevator->floorwasheight = elevator->sector->floorheight; - elevator->ceilingwasheight = elevator->sector->ceilingheight; - elevator->distance = TICRATE; // Used for delay time - elevator->low = 0; - elevator->player = player; - elevator->origspeed = origalpha; + crumble->floorwasheight = crumble->sector->floorheight; + crumble->ceilingwasheight = crumble->sector->ceilingheight; + crumble->timer = TICRATE; + crumble->player = player; + crumble->origalpha = origalpha; - elevator->sourceline = rover->master; + crumble->sourceline = rover->master; - sec->floordata = elevator; + sec->floordata = crumble; + if (crumblereturn) + crumble->flags |= CF_RETURN; if (floating) - elevator->high = 42; - else - elevator->high = 0; + crumble->flags |= CF_FLOATBOB; - elevator->sector->crumblestate = 2; + crumble->sector->crumblestate = CRUMBLE_ACTIVATED; - for (i = -1; (i = P_FindSectorFromTag(elevator->sourceline->tag, i)) >= 0 ;) + for (i = -1; (i = P_FindSectorFromTag(crumble->sourceline->tag, i)) >= 0 ;) { foundsec = §ors[i]; - P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, elevator->direction == 1 ? elevator->sector->floorheight : elevator->sector->ceilingheight, MT_CRUMBLEOBJ); + P_SpawnMobj(foundsec->soundorg.x, foundsec->soundorg.y, crumble->direction == 1 ? crumble->sector->floorheight : crumble->sector->ceilingheight, MT_CRUMBLEOBJ); } return 1; } -INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mobj_t *puncher) +void EV_MarioBlock(ffloor_t *rover, sector_t *sector, mobj_t *puncher) { - levelspecthink_t *block; + sector_t *roversec = rover->master->frontsector; + fixed_t topheight = *rover->topheight; + mariothink_t *block; mobj_t *thing; fixed_t oldx = 0, oldy = 0, oldz = 0; I_Assert(puncher != NULL); I_Assert(puncher->player != NULL); - if (sec->floordata || sec->ceilingdata) - return 0; + if (roversec->floordata || roversec->ceilingdata) + return; + + if (!(rover->flags & FF_SOLID)) + rover->flags |= (FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); // Find an item to pop out! - thing = SearchMarioNode(sec->touching_thinglist); + thing = SearchMarioNode(roversec->touching_thinglist); - // Found something! - if (thing) + if (!thing) + S_StartSound(puncher, sfx_mario1); // "Thunk!" sound - puncher is "close enough". + else // Found something! { const boolean itsamonitor = (thing->flags & MF_MONITOR) == MF_MONITOR; // create and initialize new elevator thinker block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); - P_AddThinker(&block->thinker); - sec->floordata = block; - sec->ceilingdata = block; + P_AddThinker(THINK_MAIN, &block->thinker); + roversec->floordata = block; + roversec->ceilingdata = block; block->thinker.function.acp1 = (actionf_p1)T_MarioBlock; // Set up the fields - block->sector = sec; - block->vars[0] = roversector->tag; // actionsector - block->vars[1] = 4*FRACUNIT; // speed - block->vars[2] = 1; // Up // direction - block->vars[3] = block->sector->floorheight; // floorwasheight - block->vars[4] = block->sector->ceilingheight; // ceilingwasheight - block->vars[5] = FRACUNIT; // distance - block->vars[6] = 1; // low + block->sector = roversec; + block->speed = 4*FRACUNIT; + block->direction = 1; + block->floorstartheight = block->sector->floorheight; + block->ceilingstartheight = block->sector->ceilingheight; + block->tag = (INT16)sector->tag; if (itsamonitor) { @@ -3259,13 +2364,13 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob } P_UnsetThingPosition(thing); - thing->x = roversector->soundorg.x; - thing->y = roversector->soundorg.y; + thing->x = sector->soundorg.x; + thing->y = sector->soundorg.y; thing->z = topheight; thing->momz = FixedMul(6*FRACUNIT, thing->scale); P_SetThingPosition(thing); if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, puncher, puncher, 1); + P_DamageMobj(thing, puncher, puncher, 1, DMG_NORMAL); else if (thing->type == MT_RING || thing->type == MT_COIN || thing->type == MT_RANDOMITEM) { thing->momz = FixedMul(3*FRACUNIT, thing->scale); @@ -3275,31 +2380,19 @@ INT32 EV_MarioBlock(sector_t *sec, sector_t *roversector, fixed_t topheight, mob } else { - if (thing->type == MT_EMMY && thing->spawnpoint && (thing->spawnpoint->options & MTF_OBJECTSPECIAL)) - { - mobj_t *tokenobj = P_SpawnMobj(roversector->soundorg.x, roversector->soundorg.y, topheight, MT_TOKEN); - P_SetTarget(&thing->tracer, tokenobj); - P_SetTarget(&tokenobj->target, thing); - P_SetMobjState(tokenobj, mobjinfo[MT_TOKEN].seestate); - } - // "Powerup rise" sound S_StartSound(puncher, sfx_mario9); // Puncher is "close enough" } - if (itsamonitor) + if (itsamonitor && thing) { - P_UnsetThingPosition(tmthing); - tmthing->x = oldx; - tmthing->y = oldy; - tmthing->z = oldz; - tmthing->momx = 1; - tmthing->momy = 1; - P_SetThingPosition(tmthing); + P_UnsetThingPosition(thing); + thing->x = oldx; + thing->y = oldy; + thing->z = oldz; + thing->momx = 1; + thing->momy = 1; + P_SetThingPosition(thing); } } - else - S_StartSound(puncher, sfx_mario1); // "Thunk!" sound - puncher is "close enough". - - return 1; } diff --git a/src/p_inter.c b/src/p_inter.c index 5ad39ea6b..09eb659a2 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -23,17 +23,19 @@ #include "hu_stuff.h" #include "lua_hook.h" #include "m_cond.h" // unlockables, emblems, etc +#include "p_setup.h" #include "m_cheat.h" // objectplace #include "m_misc.h" #include "v_video.h" // video flags for CEchos -#include "k_kart.h" // SRB2kart +#include "f_finale.h" + +// SRB2kart +#include "k_kart.h" #include "k_battle.h" #include "k_pwrlv.h" #include "k_grandprix.h" - -// CTF player names -#define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" -#define CTFTEAMENDCODE(pl) pl->ctfteam ? "\x80" : "" +#include "k_respawn.h" +#include "p_spec.h" // CTF player names #define CTFTEAMCODE(pl) pl->ctfteam ? (pl->ctfteam == 1 ? "\x85" : "\x84") : "" @@ -109,7 +111,7 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) if (player->exiting || mapreset) return false; - /*if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) // No bumpers in Match + /*if ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0) // No bumpers in Match return false;*/ if (weapon) @@ -148,77 +150,6 @@ boolean P_CanPickupItem(player_t *player, UINT8 weapon) return true; } -// -// P_DoNightsScore -// -// When you pick up some items in nights, it displays -// a score sign, and awards you some drill time. -// -void P_DoNightsScore(player_t *player) -{ - mobj_t *dummymo; - - if (player->exiting) - return; // Don't do any fancy shit for failures. - - dummymo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+player->mo->height/2, MT_NIGHTSCORE); - - if (G_IsSpecialStage(gamemap)) // Global link count? Maybe not a good idea... - { - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - if (++players[i].linkcount > players[i].maxlink) - players[i].maxlink = players[i].linkcount; - players[i].linktimer = 2*TICRATE; - } - } - else // Individual link counts - { - if (++player->linkcount > player->maxlink) - player->maxlink = player->linkcount; - player->linktimer = 2*TICRATE; - } - - if (player->linkcount < 10) - { - if (player->bonustime) - { - P_AddPlayerScore(player, player->linkcount*20); - P_SetMobjState(dummymo, dummymo->info->xdeathstate+player->linkcount-1); - } - else - { - P_AddPlayerScore(player, player->linkcount*10); - P_SetMobjState(dummymo, dummymo->info->spawnstate+player->linkcount-1); - } - } - else - { - if (player->bonustime) - { - P_AddPlayerScore(player, 200); - P_SetMobjState(dummymo, dummymo->info->xdeathstate+9); - } - else - { - P_AddPlayerScore(player, 100); - P_SetMobjState(dummymo, dummymo->info->spawnstate+9); - } - } - - // Hoops are the only things that should add to your drill meter - //player->drillmeter += TICRATE; - dummymo->momz = FRACUNIT; - dummymo->fuse = 3*TICRATE; - - // What?! NO, don't use the camera! Scale up instead! - //P_InstaThrust(dummymo, R_PointToAngle2(dummymo->x, dummymo->y, camera[0].x, camera[0].y), 3*FRACUNIT); - dummymo->scalespeed = FRACUNIT/25; - dummymo->destscale = 2*FRACUNIT; -} - /** Takes action based on a ::MF_SPECIAL thing touched by a player. * Actually, this just checks a few things (heights, toucher->player, no * objectplace, no dead or disappearing things) @@ -246,92 +177,43 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Can happen with a sliding player corpse. if (toucher->health <= 0) return; + if (special->health <= 0) + return; if (heightcheck) { - /*if (special->type == MT_FLINGEMERALD) // little hack here... - { // flingemerald sprites are low to the ground, so extend collision radius down some. - if (toucher->z > (special->z + special->height)) + if (toucher->momz < 0) { + if (toucher->z + toucher->momz > special->z + special->height) return; - if (special->z - special->height > (toucher->z + toucher->height)) + } else if (toucher->z > special->z + special->height) + return; + if (toucher->momz > 0) { + if (toucher->z + toucher->height + toucher->momz < special->z) return; - } - else*/ - { - if (toucher->momz < 0) { - if (toucher->z + toucher->momz > special->z + special->height) - return; - } else if (toucher->z > special->z + special->height) - return; - if (toucher->momz > 0) { - if (toucher->z + toucher->height + toucher->momz < special->z) - return; - } else if (toucher->z + toucher->height < special->z) - return; - } + } else if (toucher->z + toucher->height < special->z) + return; } - if (special->health <= 0) - return; - player = toucher->player; I_Assert(player != NULL); // Only players can touch stuff! if (player->spectator) return; - // Ignore eggman in "ouchie" mode - if (special->flags & MF_BOSS && special->flags2 & MF2_FRET) + // Ignore multihits in "ouchie" mode + if (special->flags & (MF_ENEMY|MF_BOSS) && special->flags2 & MF2_FRET) return; -#ifdef HAVE_BLUA if (LUAh_TouchSpecial(special, toucher) || P_MobjWasRemoved(special)) return; -#endif - if (special->flags & MF_BOSS) + if ((special->flags & (MF_ENEMY|MF_BOSS)) && !(special->flags & MF_MISSILE)) { - /*if (special->type == MT_BLACKEGGMAN) - { - P_DamageMobj(toucher, special, special, 1); // ouch - return; - } + //////////////////////////////////////////////////////// + /////ENEMIES & BOSSES!!///////////////////////////////// + //////////////////////////////////////////////////////// - if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) - || (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING)) - || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? - { - if (P_MobjFlip(toucher)*toucher->momz < 0) - toucher->momz = -toucher->momz; - toucher->momx = -toucher->momx; - toucher->momy = -toucher->momy; - P_DamageMobj(special, toucher, toucher, 1); - } - else if (((toucher->z < special->z && !(toucher->eflags & MFE_VERTICALFLIP)) - || (toucher->z + toucher->height > special->z + special->height && (toucher->eflags & MFE_VERTICALFLIP))) - && player->charability == CA_FLY - && (player->powers[pw_tailsfly] - || (toucher->state >= &states[S_PLAY_SPC1] && toucher->state <= &states[S_PLAY_SPC4]))) // Tails can shred stuff with his propeller. - { - toucher->momz = -toucher->momz/2; - - P_DamageMobj(special, toucher, toucher, 1); - } - // SRB2kart - Removed: No more fly states - else*/ - P_DamageMobj(toucher, special, special, 1); - - return; - } - else if ((special->flags & MF_ENEMY) && !(special->flags & MF_MISSILE) - && (special->type != MT_SPRINGSHELL)) // Kart: prevent random hits from these things - { - P_DamageMobj(toucher, special, special, 1); - return; - } - else if (special->flags & MF_FIRE) - { - P_DamageMobj(toucher, special, special, 1); + P_DamageMobj(toucher, special, special, 1, DMG_NORMAL); return; } else @@ -353,7 +235,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!P_CanPickupItem(player, 3) || (player->kartstuff[k_itemamount] && player->kartstuff[k_itemtype] != special->threshold)) return; - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + if ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0) return; player->kartstuff[k_itemtype] = special->threshold; @@ -374,7 +256,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (!P_CanPickupItem(player, 1)) return; - if (G_BattleGametype() && player->kartstuff[k_bumper] <= 0) + if ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0) { if (player->kartstuff[k_comebackmode] || player->kartstuff[k_comebacktimer]) return; @@ -383,7 +265,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->momx = special->momy = special->momz = 0; P_SetTarget(&special->target, toucher); - P_KillMobj(special, toucher, toucher); + P_KillMobj(special, toucher, toucher, DMG_NORMAL); break; case MT_KARMAHITBOX: if (!special->target->player) @@ -395,15 +277,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (special->target->player->exiting || player->exiting) return; - if (special->target->player->kartstuff[k_comebacktimer] - || special->target->player->kartstuff[k_spinouttimer] - || special->target->player->kartstuff[k_squishedtimer]) + if (P_PlayerInPain(special->target->player)) return; if (!special->target->player->kartstuff[k_comebackmode]) { if (player->kartstuff[k_growshrinktimer] || player->kartstuff[k_squishedtimer] - || player->kartstuff[k_hyudorotimer] || player->kartstuff[k_spinouttimer] + || player->kartstuff[k_hyudorotimer] || P_PlayerInPain(player) || player->kartstuff[k_invincibilitytimer] || player->powers[pw_flashing]) return; else @@ -441,11 +321,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->karthud[khud_yougotem] = 2*TICRATE; if (special->target->player->kartstuff[k_comebackpoints] >= 2) - K_StealBumper(special->target->player, player, true); + K_StealBumper(special->target->player, player); special->target->player->kartstuff[k_comebacktimer] = comebacktime; - K_ExplodePlayer(player, special->target, special); + P_DamageMobj(toucher, special, special->target, 1, DMG_EXPLODE); } } else if (special->target->player->kartstuff[k_comebackmode] == 1 && P_CanPickupItem(player, 1)) @@ -469,7 +349,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->kartstuff[k_comebackpoints]++; if (special->target->player->kartstuff[k_comebackpoints] >= 2) - K_StealBumper(special->target->player, player, true); + K_StealBumper(special->target->player, player); special->target->player->kartstuff[k_comebacktimer] = comebacktime; player->kartstuff[k_itemroulette] = 1; @@ -504,7 +384,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->target->player->karthud[khud_yougotem] = 2*TICRATE; if (special->target->player->kartstuff[k_comebackpoints] >= 2) - K_StealBumper(special->target->player, player, true); + K_StealBumper(special->target->player, player); special->target->player->kartstuff[k_comebacktimer] = comebacktime; @@ -557,7 +437,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_RemoveMobj(special); } else - K_SpinPlayer(player, special->target, 0, special, false); + { + P_DamageMobj(player->mo, special, special->target, 1, DMG_NORMAL); + } return; /*case MT_EERIEFOG: special->frame &= ~FF_TRANS80; @@ -578,13 +460,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_flamedash] > 0) { - P_KillMobj(special, toucher, toucher); + P_KillMobj(special, toucher, toucher, DMG_NORMAL); return; } // no interaction if (player->powers[pw_flashing] > 0 || player->kartstuff[k_hyudorotimer] > 0 - || player->kartstuff[k_squishedtimer] > 0 || player->kartstuff[k_spinouttimer] > 0) + || player->kartstuff[k_squishedtimer] > 0 || P_PlayerInPain(player)) return; // attach to player! @@ -592,7 +474,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) S_StartSound(special, sfx_s1a2); return; case MT_CDUFO: // SRB2kart - if (special->fuse || !P_CanPickupItem(player, 1) || (G_BattleGametype() && player->kartstuff[k_bumper] <= 0)) + if (special->fuse || !P_CanPickupItem(player, 1) || ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0)) return; player->kartstuff[k_itemroulette] = 1; @@ -617,9 +499,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) //P_SetTarget(&special->target, toucher); special->fuse = 2*TICRATE; break; + case MT_BALLOON: // SRB2kart P_SetObjectMomZ(toucher, 20<target == toucher || special->target == toucher->target) && (special->threshold > 0)) return; @@ -640,17 +524,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) S_StartSound(toucher, sfx_s1b2); return; -// ***************************************** // -// Rings, coins, spheres, weapon panels, etc // -// ***************************************** // - case MT_REDTEAMRING: - if (player->ctfteam != 1) - return; - /* FALLTHRU */ - case MT_BLUETEAMRING: // Yes, I'm lazy. Oh well, deal with it. - if (special->type == MT_BLUETEAMRING && player->ctfteam != 2) - return; - /* FALLTHRU */ case MT_RING: case MT_FLINGRING: if (special->extravalue1) @@ -661,9 +534,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; // Don't immediately pick up spilled rings - if (special->threshold > 0 - || player->kartstuff[k_squishedtimer] - || player->kartstuff[k_spinouttimer]) + if (special->threshold > 0 || P_PlayerInPain(player)) return; if (!(P_CanPickupItem(player, 0))) @@ -682,149 +553,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; - case MT_COIN: - case MT_FLINGCOIN: - if (!(P_CanPickupItem(player, 0))) - return; - - special->momx = special->momy = 0; - P_GivePlayerRings(player, 1); - - if ((maptol & TOL_NIGHTS) && special->type != MT_FLINGCOIN) - P_DoNightsScore(player); - break; - case MT_BLUEBALL: - if (!(P_CanPickupItem(player, 0))) - return; - - P_GivePlayerRings(player, 1); - - special->momx = special->momy = special->momz = 0; - special->destscale = FixedMul(8*FRACUNIT, special->scale); - if (states[special->info->deathstate].tics > 0) - special->scalespeed = FixedDiv(FixedDiv(special->destscale, special->scale), states[special->info->deathstate].tics<scalespeed = 4*FRACUNIT/5; - - if (maptol & TOL_NIGHTS) - P_DoNightsScore(player); - break; - case MT_AUTOPICKUP: - case MT_BOUNCEPICKUP: - case MT_SCATTERPICKUP: - case MT_GRENADEPICKUP: - case MT_EXPLODEPICKUP: - case MT_RAILPICKUP: - if (!(P_CanPickupItem(player, 1))) - return; - - // Give the power and ringweapon - if (special->info->mass >= pw_infinityring && special->info->mass <= pw_railring) - { - INT32 pindex = special->info->mass - (INT32)pw_infinityring; - - player->powers[special->info->mass] += (UINT16)special->info->reactiontime; - player->ringweapons |= 1 << (pindex-1); - - if (player->powers[special->info->mass] > rw_maximums[pindex]) - player->powers[special->info->mass] = rw_maximums[pindex]; - } - break; - - // Ammo pickups - case MT_INFINITYRING: - case MT_AUTOMATICRING: - case MT_BOUNCERING: - case MT_SCATTERRING: - case MT_GRENADERING: - case MT_EXPLOSIONRING: - case MT_RAILRING: - if (!(P_CanPickupItem(player, 1))) - return; - - if (special->info->mass >= pw_infinityring && special->info->mass <= pw_railring) - { - INT32 pindex = special->info->mass - (INT32)pw_infinityring; - - player->powers[special->info->mass] += (UINT16)special->health; - if (player->powers[special->info->mass] > rw_maximums[pindex]) - player->powers[special->info->mass] = rw_maximums[pindex]; - } - break; - -// ***************************** // -// Gameplay related collectibles // -// ***************************** // - // Special Stage Token - case MT_EMMY: - tokenlist += special->health; - - if (ALL7EMERALDS(emeralds)) // Got all 7 - { - P_GivePlayerRings(player, 50); - nummaprings += 50; // no cheating towards Perfect! - } - else - token++; - - if (special->tracer) // token BG - P_RemoveMobj(special->tracer); - break; - - // Emerald Hunt - case MT_EMERHUNT: - if (hunt1 == special) - hunt1 = NULL; - else if (hunt2 == special) - hunt2 = NULL; - else if (hunt3 == special) - hunt3 = NULL; - - if (!hunt1 && !hunt2 && !hunt3) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - players[i].exiting = raceexittime+1; - } - S_StartSound(NULL, sfx_lvpass); - } - break; - - // Collectible emeralds - case MT_EMERALD1: - case MT_EMERALD2: - case MT_EMERALD3: - case MT_EMERALD4: - case MT_EMERALD5: - case MT_EMERALD6: - case MT_EMERALD7: - if (special->threshold) - player->powers[pw_emeralds] |= special->info->speed; - else - emeralds |= special->info->speed; - - if (special->target && special->target->type == MT_EMERALDSPAWN) - { - if (special->target->target) - P_SetTarget(&special->target->target, NULL); - - special->target->threshold = 0; - - P_SetTarget(&special->target, NULL); - } - break; - - // Power stones / Match emeralds - case MT_FLINGEMERALD: - if (!(P_CanPickupItem(player, 1)) || player->tossdelay) - return; - - player->powers[pw_emeralds] |= special->threshold; - break; - // Secret emblem thingy case MT_EMBLEM: { @@ -832,8 +560,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; emblemlocations[special->health-1].collected = true; - M_UpdateUnlockablesAndExtraEmblems(false); - G_SaveGameData(false); + M_UpdateUnlockablesAndExtraEmblems(); + G_SaveGameData(); break; } @@ -906,635 +634,8 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } return; -// ********************************** // -// NiGHTS gameplay items and powerups // -// ********************************** // - /*case MT_NIGHTSDRONE: - if (player->exiting) - return; - if (player->bonustime) - { - if (G_IsSpecialStage(gamemap)) //After-mare bonus time/emerald reward in special stages. - { - // only allow the player with the emerald in-hand to leave. - if (toucher->tracer && toucher->tracer->target - && toucher->tracer->target->type == MT_GOTEMERALD) - { - } - else // Make sure that SOMEONE has the emerald, at least! - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].playerstate == PST_LIVE - && players[i].mo->tracer && players[i].mo->tracer->target - && players[i].mo->tracer->target->type == MT_GOTEMERALD) - return; - // Well no one has an emerald, so exit anyway! - } - P_GiveEmerald(false); - // Don't play Ideya sound in special stage mode - } - else - S_StartSound(toucher, special->info->activesound); - } - else //Initial transformation. Don't allow second chances in special stages! - { - if (player->pflags & PF_NIGHTSMODE) - return; - - S_StartSound(toucher, sfx_supert); - } - if (!(netgame || multiplayer) && !(player->pflags & PF_NIGHTSMODE)) - P_SetTarget(&special->tracer, toucher); - P_NightserizePlayer(player, special->health); // Transform! - return; - case MT_NIGHTSLOOPHELPER: - // One second delay - if (special->fuse < toucher->fuse - TICRATE) - { - thinker_t *th; - mobj_t *mo2; - INT32 count; - fixed_t x,y,z, gatherradius; - angle_t d; - statenum_t sparklestate = S_NULL; - - if (special->target != toucher) // These ain't your helpers, pal! - return; - - x = special->x>>FRACBITS; - y = special->y>>FRACBITS; - z = special->z>>FRACBITS; - count = 1; - - // scan the remaining thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2 == special) - continue; - - // Not our stuff! - if (mo2->target != toucher) - continue; - - if (mo2->type == MT_NIGHTSPARKLE) - mo2->tics = 1; - else if (mo2->type == MT_NIGHTSLOOPHELPER) - { - if (mo2->fuse >= special->fuse) - { - count++; - x += mo2->x>>FRACBITS; - y += mo2->y>>FRACBITS; - z += mo2->z>>FRACBITS; - } - P_RemoveMobj(mo2); - } - } - x = (x/count)<x - x, special->y - y), special->z - z); - P_RemoveMobj(special); - - if (player->powers[pw_nights_superloop]) - { - gatherradius *= 2; - sparklestate = mobjinfo[MT_NIGHTSPARKLE].seestate; - } - - if (gatherradius < 30*FRACUNIT) // Player is probably just sitting there. - return; - - for (d = 0; d < 16; d++) - P_SpawnParaloop(x, y, z, gatherradius, 16, MT_NIGHTSPARKLE, sparklestate, d*ANGLE_22h, false); - - S_StartSound(toucher, sfx_prloop); - - // Now we RE-scan all the thinkers to find close objects to pull - // in from the paraloop. Isn't this just so efficient? - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > gatherradius) - continue; - - if (mo2->flags & MF_SHOOTABLE) - { - P_DamageMobj(mo2, toucher, toucher, 1); - continue; - } - - // Make these APPEAR! - // Tails 12-15-2003 - if (mo2->flags & MF_NIGHTSITEM) - { - // Requires Bonus Time - if ((mo2->flags2 & MF2_STRONGBOX) && !player->bonustime) - continue; - - if (!(mo2->flags & MF_SPECIAL) && mo2->health) - { - P_SetMobjState(mo2, mo2->info->seestate); - mo2->flags |= MF_SPECIAL; - mo2->flags &= ~MF_NIGHTSITEM; - S_StartSound(toucher, sfx_hidden); - continue; - } - } - - if (!(mo2->type == MT_NIGHTSWING || mo2->type == MT_RING || mo2->type == MT_COIN - || mo2->type == MT_BLUEBALL)) - continue; - - // Yay! The thing's in reach! Pull it in! - mo2->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; - mo2->flags2 |= MF2_NIGHTSPULL; - P_SetTarget(&mo2->tracer, toucher); - } - } - return; - case MT_EGGCAPSULE: - // make sure everything is as it should be, THEN take rings from players in special stages - if (player->pflags & PF_NIGHTSMODE && !toucher->target) - return; - - if (player->mare != special->threshold) // wrong mare - return; - - if (special->reactiontime > 0) // capsule already has a player attacking it, ignore - return; - - if (G_IsSpecialStage(gamemap) && !player->exiting) - { // In special stages, share rings. Everyone gives up theirs to the player who touched the capsule - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (&players[i] != player) && players[i].mo->health > 1) - { - toucher->health += players[i].mo->health-1; - player->health = toucher->health; - players[i].mo->health = 1; - players[i].health = players[i].mo->health; - } - } - - if (!(player->health > 1) || player->exiting) - return; - - // Mark the player as 'pull into the capsule' - P_SetTarget(&player->capsule, special); - special->reactiontime = (player-players)+1; - P_SetTarget(&special->target, NULL); - - // Clear text - player->texttimer = 0; - return;*/ - case MT_NIGHTSBUMPER: - // Don't trigger if the stage is ended/failed - if (player->exiting) - return; - - if (player->bumpertime < TICRATE/4) - { - S_StartSound(toucher, special->info->seesound); - if (player->pflags & PF_NIGHTSMODE) - { - player->bumpertime = TICRATE/2; - if (special->threshold > 0) - player->flyangle = (special->threshold*30)-1; - else - player->flyangle = special->threshold; - - player->speed = FixedMul(special->info->speed, special->scale); - // Potentially causes axis transfer failures. - // Also rarely worked properly anyway. - //P_UnsetThingPosition(player->mo); - //player->mo->x = special->x; - //player->mo->y = special->y; - //P_SetThingPosition(player->mo); - toucher->z = special->z+(special->height/4); - } - else // More like a spring - { - angle_t fa; - fixed_t xspeed, yspeed; - const fixed_t speed = FixedMul(FixedDiv(special->info->speed*FRACUNIT,75*FRACUNIT), FixedSqrt(FixedMul(toucher->scale,special->scale))); - - player->bumpertime = TICRATE/2; - - P_UnsetThingPosition(toucher); - toucher->x = special->x; - toucher->y = special->y; - P_SetThingPosition(toucher); - toucher->z = special->z+(special->height/4); - - if (special->threshold > 0) - fa = (FixedAngle(((special->threshold*30)-1)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - else - fa = 0; - - xspeed = FixedMul(FINECOSINE(fa),speed); - yspeed = FixedMul(FINESINE(fa),speed); - - P_InstaThrust(toucher, special->angle, xspeed/10); - toucher->momz = yspeed/11; - - toucher->angle = special->angle; - - if (player == &players[consoleplayer]) - localangle[0] = toucher->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = toucher->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = toucher->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = toucher->angle; - - P_ResetPlayer(player); - - P_SetPlayerMobjState(toucher, S_KART_STILL1); // SRB2kart - was S_PLAY_FALL1 - } - } - return; - /*case MT_NIGHTSSUPERLOOP: - if (!(player->pflags & PF_NIGHTSMODE)) - return; - if (!G_IsSpecialStage(gamemap)) - player->powers[pw_nights_superloop] = (UINT16)special->info->speed; - else - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) - players[i].powers[pw_nights_superloop] = (UINT16)special->info->speed; - if (special->info->deathsound != sfx_None) - S_StartSound(NULL, special->info->deathsound); - } - - // CECHO showing you what this item is - if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap)) - { - HU_SetCEchoFlags(V_AUTOFADEOUT); - HU_SetCEchoDuration(4); - HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Super Paraloop")); - } - break; - case MT_NIGHTSDRILLREFILL: - if (!(player->pflags & PF_NIGHTSMODE)) - return; - if (!G_IsSpecialStage(gamemap)) - player->drillmeter = special->info->speed; - else - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) - players[i].drillmeter = special->info->speed; - if (special->info->deathsound != sfx_None) - S_StartSound(NULL, special->info->deathsound); - } - - // CECHO showing you what this item is - if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap)) - { - HU_SetCEchoFlags(V_AUTOFADEOUT); - HU_SetCEchoDuration(4); - HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Drill Refill")); - } - break; - case MT_NIGHTSHELPER: - if (!(player->pflags & PF_NIGHTSMODE)) - return; - if (!G_IsSpecialStage(gamemap)) - { - // A flicky orbits us now - mobj_t *flickyobj = P_SpawnMobj(toucher->x, toucher->y, toucher->z + toucher->info->height, MT_NIGHTOPIANHELPER); - P_SetTarget(&flickyobj->target, toucher); - - player->powers[pw_nights_helper] = (UINT16)special->info->speed; - } - else - { - mobj_t *flickyobj; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].pflags & PF_NIGHTSMODE) { - players[i].powers[pw_nights_helper] = (UINT16)special->info->speed; - flickyobj = P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_NIGHTOPIANHELPER); - P_SetTarget(&flickyobj->target, players[i].mo); - } - if (special->info->deathsound != sfx_None) - S_StartSound(NULL, special->info->deathsound); - } - - // CECHO showing you what this item is - if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap)) - { - HU_SetCEchoFlags(V_AUTOFADEOUT); - HU_SetCEchoDuration(4); - HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Nightopian Helper")); - } - break; - case MT_NIGHTSEXTRATIME: - if (!(player->pflags & PF_NIGHTSMODE)) - return; - if (!G_IsSpecialStage(gamemap)) - { - player->nightstime += special->info->speed; - player->startedtime += special->info->speed; - P_RestoreMusic(player); - } - else - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) - { - players[i].nightstime += special->info->speed; - players[i].startedtime += special->info->speed; - P_RestoreMusic(&players[i]); - } - if (special->info->deathsound != sfx_None) - S_StartSound(NULL, special->info->deathsound); - } - - // CECHO showing you what this item is - if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap)) - { - HU_SetCEchoFlags(V_AUTOFADEOUT); - HU_SetCEchoDuration(4); - HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Extra Time")); - } - break; - case MT_NIGHTSLINKFREEZE: - if (!(player->pflags & PF_NIGHTSMODE)) - return; - if (!G_IsSpecialStage(gamemap)) - { - player->powers[pw_nights_linkfreeze] = (UINT16)special->info->speed; - player->linktimer = 2*TICRATE; - } - else - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) - { - players[i].powers[pw_nights_linkfreeze] += (UINT16)special->info->speed; - players[i].linktimer = 2*TICRATE; - } - if (special->info->deathsound != sfx_None) - S_StartSound(NULL, special->info->deathsound); - } - - // CECHO showing you what this item is - if (player == &players[displayplayers[0]] || G_IsSpecialStage(gamemap)) - { - HU_SetCEchoFlags(V_AUTOFADEOUT); - HU_SetCEchoDuration(4); - HU_DoCEcho(M_GetText("\\\\\\\\\\\\\\\\Link Freeze")); - } - break;*/ - case MT_NIGHTSWING: - if (G_IsSpecialStage(gamemap) && useNightsSS) - { // Pseudo-ring. - S_StartSound(toucher, special->info->painsound); - player->totalring++; - } - else - S_StartSound(toucher, special->info->activesound); - - P_DoNightsScore(player); - break; - case MT_HOOPCOLLIDE: - // This produces a kind of 'domino effect' with the hoop's pieces. - for (; special->hprev != NULL; special = special->hprev); // Move to the first sprite in the hoop - i = 0; - for (; special->type == MT_HOOP; special = special->hnext) - { - special->fuse = 11; - special->movedir = i; - special->extravalue1 = special->target->extravalue1; - special->extravalue2 = special->target->extravalue2; - special->target->threshold = 4242; - i++; - } - // Make the collision detectors disappear. - { - mobj_t *hnext; - for (; special != NULL; special = hnext) - { - hnext = special->hnext; - P_RemoveMobj(special); - } - } - - P_DoNightsScore(player); - - // Hoops are the only things that should add to the drill meter - // Also, one tic's worth of drill is too much. - if (G_IsSpecialStage(gamemap)) - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) - players[i].drillmeter += TICRATE/2; - } - else - player->drillmeter += TICRATE/2; - - // Play hoop sound -- pick one depending on the current link. - if (player->linkcount <= 5) - S_StartSound(toucher, sfx_hoop1); - else if (player->linkcount <= 10) - S_StartSound(toucher, sfx_hoop2); - else - S_StartSound(toucher, sfx_hoop3); - return; - -// ***** // -// Mario // -// ***** // - case MT_SHELL: - if (special->state == &states[S_SHELL]) // Resting anim - { - // Kick that sucker around! - special->angle = toucher->angle; - P_InstaThrust(special, special->angle, FixedMul(special->info->speed, special->scale)); - S_StartSound(toucher, sfx_mario2); - P_SetMobjState(special, S_SHELL1); - P_SetTarget(&special->target, toucher); - special->threshold = (3*TICRATE)/2; - } - return; - case MT_AXE: - { - line_t junk; - thinker_t *th; - mobj_t *mo2; - - junk.tag = 649; - EV_DoElevator(&junk, bridgeFall, false); - - // scan the remaining thinkers to find koopa - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2->type == MT_KOOPA) - { - mo2->momz = 5*FRACUNIT; - break; - } - } - } - break; - case MT_FIREFLOWER: - player->powers[pw_shield] |= SH_FIREFLOWER; - toucher->color = SKINCOLOR_WHITE; - G_GhostAddColor(player - players, GHC_FIREFLOWER); - break; - -// *************** // -// Misc touchables // -// *************** // case MT_STARPOST: - if (circuitmap && special->health - player->starpostnum > 1) - { - // blatant reuse of a variable that's normally unused in circuit - if (!player->tossdelay) - S_StartSound(toucher, sfx_s26d); - player->tossdelay = 3; - return; - } - - // We could technically have 91.1 Star Posts. 90 is cleaner. - if (special->health > 90) - { - CONS_Debug(DBG_GAMELOGIC, "Bad Starpost Number!\n"); - return; - } - - if (player->starpostnum >= special->health) - return; // Already hit this post - - player->starpostnum = special->health; - - return; - - case MT_FAKEMOBILE: - { - fixed_t touchx, touchy, touchspeed; - angle_t angle; - - if (P_AproxDistance(toucher->x-special->x, toucher->y-special->y) > - P_AproxDistance((toucher->x-toucher->momx)-special->x, (toucher->y-toucher->momy)-special->y)) - { - touchx = toucher->x + toucher->momx; - touchy = toucher->y + toucher->momy; - } - else - { - touchx = toucher->x; - touchy = toucher->y; - } - - angle = R_PointToAngle2(special->x, special->y, touchx, touchy); - touchspeed = P_AproxDistance(toucher->momx, toucher->momy); - - toucher->momx = P_ReturnThrustX(special, angle, touchspeed); - toucher->momy = P_ReturnThrustY(special, angle, touchspeed); - toucher->momz = -toucher->momz; - if (player->pflags & PF_GLIDING) - { - player->pflags &= ~(PF_GLIDING|PF_JUMPED); - P_SetPlayerMobjState(toucher, S_KART_STILL1); // SRB2kart - was S_PLAY_FALL1 - } - - // Play a bounce sound? - S_StartSound(toucher, special->info->painsound); - } - return; - - case MT_BLACKEGGMAN_GOOPFIRE: - if (!player->powers[pw_flashing]) // SRB2kart - { - toucher->momx = 0; - toucher->momy = 0; - - if (toucher->momz != 0) - special->momz = toucher->momz; - - player->powers[pw_ingoop] = 2; - - if (player->pflags & PF_ITEMHANG) - { - P_SetTarget(&toucher->tracer, NULL); - player->pflags &= ~PF_ITEMHANG; - } - - P_ResetPlayer(player); - - if (special->target && special->target->state == &states[S_BLACKEGG_SHOOT1]) - { - if (special->target->health <= 2 && P_RandomChance(FRACUNIT/2)) - P_SetMobjState(special->target, special->target->info->missilestate); - else - P_SetMobjState(special->target, special->target->info->raisestate); - } - } - else - player->powers[pw_ingoop] = 0; - return; - case MT_EGGSHIELD: - { - fixed_t touchx, touchy, touchspeed; - angle_t angle; - - if (P_AproxDistance(toucher->x-special->x, toucher->y-special->y) > - P_AproxDistance((toucher->x-toucher->momx)-special->x, (toucher->y-toucher->momy)-special->y)) - { - touchx = toucher->x + toucher->momx; - touchy = toucher->y + toucher->momy; - } - else - { - touchx = toucher->x; - touchy = toucher->y; - } - - angle = R_PointToAngle2(special->x, special->y, touchx, touchy) - special->angle; - touchspeed = P_AproxDistance(toucher->momx, toucher->momy); - - // Blocked by the shield? - if (!(angle > ANGLE_90 && angle < ANGLE_270)) - { - toucher->momx = P_ReturnThrustX(special, special->angle, touchspeed); - toucher->momy = P_ReturnThrustY(special, special->angle, touchspeed); - toucher->momz = -toucher->momz; - if (player->pflags & PF_GLIDING) - { - player->pflags &= ~(PF_GLIDING|PF_JUMPED); - P_SetPlayerMobjState(toucher, S_KART_STILL1); // SRB2kart - was S_PLAY_FALL1 - } - - // Play a bounce sound? - S_StartSound(toucher, special->info->painsound); - return; - } - else if (((player->pflags & PF_NIGHTSMODE) && (player->pflags & PF_DRILLING)) || (player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING)) - || player->powers[pw_invulnerability] || player->powers[pw_super]) // Do you possess the ability to subdue the object? - { - // Shatter the shield! - toucher->momx = -toucher->momx/2; - toucher->momy = -toucher->momy/2; - toucher->momz = -toucher->momz; - break; - } - } + P_TouchStarPost(special, player, special->spawnpoint && (special->spawnpoint->options & MTF_OBJECTSPECIAL)); return; case MT_BIGTUMBLEWEED: @@ -1551,127 +652,6 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) P_SetMobjState(special, special->info->seestate); } return; - case MT_SMALLMACECHAIN: - case MT_BIGMACECHAIN: - // Is this the last link in the chain? - if (toucher->momz > 0 || !(special->flags2 & MF2_AMBUSH) - || (player->pflags & PF_ITEMHANG) || (player->pflags & PF_MACESPIN)) - return; - - if (toucher->z > special->z + special->height/2) - return; - - if (toucher->z + toucher->height/2 < special->z) - return; - - if (player->powers[pw_flashing]) - return; - - P_ResetPlayer(player); - P_SetTarget(&toucher->tracer, special); - - if (special->target && (special->target->type == MT_SPINMACEPOINT || special->target->type == MT_HIDDEN_SLING)) - { - player->pflags |= PF_MACESPIN; - S_StartSound(toucher, sfx_spin); - P_SetPlayerMobjState(toucher, S_KART_STILL1); // SRB2kart - was S_PLAY_ATK1 - } - else - player->pflags |= PF_ITEMHANG; - - // Can't jump first frame - player->pflags |= PF_JUMPSTASIS; - return; - case MT_BIGMINE: - case MT_BIGAIRMINE: - // Spawn explosion! - P_SpawnMobj(special->x, special->y, special->z, special->info->mass); - P_RadiusAttack(special, special, special->info->damage); - S_StartSound(special, special->info->deathsound); - P_SetMobjState(special, special->info->deathstate); - return; - case MT_SPECIALSPIKEBALL: - if (!(!useNightsSS && G_IsSpecialStage(gamemap))) // Only for old special stages - { - P_DamageMobj(toucher, special, special, 1); - return; - } - - if (player->powers[pw_invulnerability] || player->powers[pw_flashing] - || (player->powers[pw_super] && !(ALL7EMERALDS(player->powers[pw_emeralds])))) - return; - if (player->powers[pw_shield]) //If One-Hit Shield - { - P_RemoveShield(player); - S_StartSound(toucher, sfx_shldls); // Ba-Dum! Shield loss. - } - else - { - P_PlayRinglossSound(toucher); - if (toucher->health > 10) - toucher->health -= 10; - else - toucher->health = 1; - player->health = toucher->health; - } - - P_DoPlayerPain(player, special, NULL); - return; - case MT_EGGMOBILE2_POGO: - // sanity checks - if (!special->target || !special->target->health) - return; - // Goomba Stomp'd! - if (special->target->momz < 0) - { - P_DamageMobj(toucher, special, special->target, 1); - //special->target->momz = -special->target->momz; - special->target->momx = special->target->momy = 0; - special->target->momz = 0; - special->target->flags |= MF_NOGRAVITY; - P_SetMobjState(special->target, special->info->raisestate); - S_StartSound(special->target, special->info->activesound); - P_RemoveMobj(special); - } - return; - - case MT_EXTRALARGEBUBBLE: - return; // SRB2kart - don't need bubbles mucking with the player - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) - return; - if (maptol & TOL_NIGHTS) - return; - if (mariomode) - return; - else if (toucher->eflags & MFE_VERTICALFLIP) - { - if (special->z+special->height < toucher->z + toucher->height / 3 - || special->z+special->height > toucher->z + (toucher->height*2/3)) - return; // Only go in the mouth - } - else if (special->z < toucher->z + toucher->height / 3 - || special->z > toucher->z + (toucher->height*2/3)) - return; // Only go in the mouth - - /* // SRB2kart - Can't drown. - // Eaten by player! - if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1) - P_RestoreMusic(player); - - if (player->powers[pw_underwater] < underwatertics + 1) - player->powers[pw_underwater] = underwatertics + 1; - */ - - /* - if (!player->climbing) - { - P_SetPlayerMobjState(toucher, S_PLAY_GASP); - P_ResetPlayer(player); - } - */ - - toucher->momx = toucher->momy = toucher->momz = 0; - break; case MT_WATERDROP: if (special->state == &states[special->info->spawnstate]) @@ -1690,11 +670,47 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) } } - if (!P_MobjWasRemoved(special)) + S_StartSound(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings + P_KillMobj(special, NULL, toucher, DMG_NORMAL); + special->shadowscale = 0; +} + +/** Saves a player's level progress at a star post + * + * \param post The star post to trigger + * \param player The player that should receive the checkpoint + * \param snaptopost If true, the respawn point will use the star post's position, otherwise player x/y and star post z + */ +void P_TouchStarPost(mobj_t *post, player_t *player, boolean snaptopost) +{ + mobj_t *toucher = player->mo; + + (void)snaptopost; + + if (player->bot) + return; + + // Player must have touched all previous starposts + if (post->health - player->starpostnum > 1) { - S_StartSound(toucher, special->info->deathsound); // was NULL, but changed to player so you could hear others pick up rings - P_KillMobj(special, NULL, toucher); + // blatant reuse of a variable that's normally unused in circuit + if (!player->tossdelay) + S_StartSound(toucher, sfx_lose); + player->tossdelay = 3; + return; } + + // With the parameter + angle setup, we can go up to 1365 star posts. Who needs that many? + if (post->health > 1365) + { + CONS_Debug(DBG_GAMELOGIC, "Bad Starpost Number!\n"); + return; + } + + if (player->starpostnum >= post->health) + return; // Already hit this post + + player->starpostnum = post->health; } // Easily make it so that overtime works offline @@ -1718,7 +734,10 @@ void P_CheckTimeLimit(void) if (!(multiplayer || netgame)) return; - if (G_RaceGametype() || battlecapsules) + if (battlecapsules) // capsules override any time limit settings + return; + + if (!(gametyperules & GTR_TIMELIMIT)) return; if (leveltime < (timelimitintics + starttime)) @@ -1727,27 +746,7 @@ void P_CheckTimeLimit(void) if (gameaction == ga_completed) return; - //Tagmode round end but only on the tic before the - //XD_EXITLEVEL packet is received by all players. - /*if (G_TagGametype()) - { - if (leveltime == (timelimitintics + 1)) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator - || (players[i].pflags & PF_TAGGED) || (players[i].pflags & PF_TAGIT)) - continue; - - CONS_Printf(M_GetText("%s received double points for surviving the round.\n"), player_names[i]); - P_AddPlayerScore(&players[i], players[i].score); - } - } - } - else*/ - - //Optional tie-breaker for Match/CTF - if (cv_overtime.value) + if ((cv_overtime.value) && (gametyperules & GTR_OVERTIME)) { #ifndef TESTOVERTIMEINFREEPLAY boolean foundone = false; // Overtime is used for closing off down to a specific item. @@ -1768,10 +767,10 @@ void P_CheckTimeLimit(void) P_RespawnBattleBoxes(); // FORCE THESE TO BE RESPAWNED FOR THIS!!!!!!! // Find us an item box to center on. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { mobj_t *thismo; - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; thismo = (mobj_t *)th; @@ -1842,11 +841,11 @@ void P_CheckPointLimit(void) if (!(multiplayer || netgame)) return; - if (G_RaceGametype()) + if (!(gametyperules & GTR_POINTLIMIT)) return; // pointlimit is nonzero, check if it's been reached by this player - /*if (G_GametypeHasTeams()) + if (G_GametypeHasTeams()) { // Just check both teams if ((UINT32)cv_pointlimit.value <= redscore || (UINT32)cv_pointlimit.value <= bluescore) @@ -1855,7 +854,7 @@ void P_CheckPointLimit(void) SendNetXCmd(XD_EXITLEVEL, NULL, 0); } } - else*/ + else { for (i = 0; i < MAXPLAYERS; i++) { @@ -1881,91 +880,6 @@ void P_CheckPointLimit(void) } } -/*Checks for untagged remaining players in both tag derivitave modes. - *If no untagged players remain, end the round. - *Also serves as error checking if the only IT player leaves.*/ -/*void P_CheckSurvivors(void) -{ - INT32 i; - INT32 survivors = 0; - INT32 taggers = 0; - INT32 spectators = 0; - INT32 survivorarray[MAXPLAYERS]; - - if (!D_NumPlayers()) //no players in the game, no check performed. - return; - - for (i=0; i < MAXPLAYERS; i++) //figure out counts of taggers, survivors and spectators. - { - if (playeringame[i]) - { - if (players[i].spectator) - spectators++; - else if (players[i].pflags & PF_TAGIT) - taggers++; - else if (!(players[i].pflags & PF_TAGGED)) - { - survivorarray[survivors] = i; - survivors++; - } - } - } - - if (!taggers) //If there are no taggers, pick a survivor at random to be it. - { - // Exception for hide and seek. If a round has started and the IT player leaves, end the round. - if (gametype == GT_HIDEANDSEEK && (leveltime >= (hidetime * TICRATE))) - { - CONS_Printf(M_GetText("The IT player has left the game.\n")); - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); - - return; - } - - if (survivors) - { - INT32 newtagger = survivorarray[P_RandomKey(survivors)]; - - CONS_Printf(M_GetText("%s is now IT!\n"), player_names[newtagger]); // Tell everyone who is it! - players[newtagger].pflags |= PF_TAGIT; - - survivors--; //Get rid of the guy we just made IT. - - //Yeah, we have an eligible tagger, but we may not have anybody for him to tag! - //If there is only one guy waiting on the game to fill or spectators to enter game, don't bother. - if (!survivors && (D_NumPlayers() - spectators) > 1) - { - CONS_Printf(M_GetText("All players have been tagged!\n")); - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); - } - - return; - } - - //If we reach this point, no player can replace the one that was IT. - //Unless it is one player waiting on a game, end the round. - if ((D_NumPlayers() - spectators) > 1) - { - CONS_Printf(M_GetText("There are no players able to become IT.\n")); - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); - } - - return; - } - - //If there are taggers, but no survivors, end the round. - //Except when the tagger is by himself and the rest of the game are spectators. - if (!survivors && (D_NumPlayers() - spectators) > 1) - { - CONS_Printf(M_GetText("All players have been tagged!\n")); - if (server) - SendNetXCmd(XD_EXITLEVEL, NULL, 0); - } -}*/ - // Checks whether or not to end a race netgame. boolean P_CheckRacers(void) { @@ -1993,7 +907,7 @@ boolean P_CheckRacers(void) numplayersingame++; - if (players[i].exiting || (players[i].pflags & PF_TIMEOVER)) + if (players[i].exiting || (players[i].pflags & PF_GAMETYPEOVER)) { numexiting++; } @@ -2040,20 +954,20 @@ boolean P_CheckRacers(void) } } - if (eliminatelast == true && (numplayersingame <= numexiting-1)) + if (eliminatelast == true && (numexiting >= numplayersingame-1)) { // Everyone's done playing but one guy apparently. // Just kill everyone who is still playing. for (i = 0; i < MAXPLAYERS; i++) { - if (!playeringame[i] || players[i].spectator || players[i].lives <= 0) // Not playing + if (!playeringame[i] || players[i].spectator || players[i].lives <= 0) { // Y'all aren't even playing continue; } - if (players[i].exiting || (players[i].pflags & PF_TIMEOVER)) + if (players[i].exiting || (players[i].pflags & PF_GAMETYPEOVER)) { // You're done, you're free to go. continue; @@ -2117,19 +1031,19 @@ boolean P_CheckRacers(void) * \param target The victim. * \param inflictor The attack weapon. May be NULL (environmental damage). * \param source The attacker. May be NULL. + * \param damagetype The type of damage dealt that killed the target. If bit 7 (0x80) was set, this was an instant-death. * \todo Cleanup, refactor, split up. * \sa P_DamageMobj */ -void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) +void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype) { - mobjtype_t item; mobj_t *mo; //if (inflictor && (inflictor->type == MT_SHELL || inflictor->type == MT_FIREBALL)) // P_SetTarget(&target->tracer, inflictor); - if (!useNightsSS && G_IsSpecialStage(gamemap) && target->player && sstimer > 6) - sstimer = 6; // Just let P_Ticker take care of the rest. + if (G_IsSpecialStage(gamemap) && target->player && target->player->nightstime > 6) + target->player->nightstime = 6; // Just let P_Ticker take care of the rest. if (target->flags & (MF_ENEMY|MF_BOSS)) target->momx = target->momy = target->momz = 0; @@ -2147,7 +1061,10 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) // if (target->flags2 & MF2_NIGHTSPULL) + { P_SetTarget(&target->tracer, NULL); + target->movefactor = 0; // reset NightsItemChase timer + } // dead target is no more shootable target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SPECIAL); @@ -2155,10 +1072,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) target->health = 0; // This makes it easy to check if something's dead elsewhere. target->shadowscale = 0; -#ifdef HAVE_BLUA - if (LUAh_MobjDeath(target, inflictor, source) || P_MobjWasRemoved(target)) + if (LUAh_MobjDeath(target, inflictor, source, damagetype) || P_MobjWasRemoved(target)) return; -#endif // SRB2kart // I wish I knew a better way to do this @@ -2208,15 +1123,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) if (target->player && !target->player->spectator) { if (metalrecording) // Ack! Metal Sonic shouldn't die! Cut the tape, end recording! - G_StopMetalRecording(); - /*if (gametype == GT_MATCH && cv_match_scoring.value == 0 // note, no team match suicide penalty - && ((target == source) || (source == NULL && inflictor == NULL) || (source && !source->player))) - { // Suicide penalty - Not in Kart - if (target->player->score >= 50) - target->player->score -= 50; - else - target->player->score = 0; - }*/ + G_StopMetalRecording(true); target->drawflags &= ~MFD_DONTDRAW; } @@ -2250,94 +1157,19 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) target->fuse = 2*TICRATE + 2; } } - - // Award Score Tails - /*{ // Enemies shouldn't award points in Kart - INT32 score = 0; - - if (maptol & TOL_NIGHTS) // Enemies always worth 200, bosses don't do anything. - { - if ((target->flags & MF_ENEMY) && !(target->flags & (MF_MISSILE|MF_BOSS))) - { - score = 200; - - if (source->player->bonustime) - score *= 2; - - // Also, add to the link. - // I don't know if NiGHTS did this, but - // Sonic Time Attacked did and it seems like a good enough incentive - // to make people want to actually dash towards/paraloop enemies - if (++source->player->linkcount > source->player->maxlink) - source->player->maxlink = source->player->linkcount; - source->player->linktimer = 2*TICRATE; - } - } - else - { - if (target->flags & MF_BOSS) - score = 1000; - else if ((target->flags & MF_ENEMY) && !(target->flags & MF_MISSILE)) - { - mobj_t *scoremobj; - UINT32 scorestate = mobjinfo[MT_SCORE].spawnstate; - - scoremobj = P_SpawnMobj(target->x, target->y, target->z + (target->height / 2), MT_SCORE); - - // On ground? No chain starts. - if (!source->player->powers[pw_invulnerability] && P_IsObjectOnGround(source)) - { - source->player->scoreadd = 0; - score = 100; - } - // Mario Mode has Mario-like chain point values - else if (mariomode) switch (++source->player->scoreadd) - { - case 1: score = 100; break; - case 2: score = 200; scorestate += 1; break; - case 3: score = 400; scorestate += 5; break; - case 4: score = 800; scorestate += 6; break; - case 5: score = 1000; scorestate += 3; break; - case 6: score = 2000; scorestate += 7; break; - case 7: score = 4000; scorestate += 8; break; - case 8: score = 8000; scorestate += 9; break; - default: // 1up for a chain this long - if (modeattacking) // but 1ups don't exist in record attack! - { // So we just go back to 10k points. - score = 10000; scorestate += 4; break; - } - P_GivePlayerLives(source->player, 1); - P_PlayLivesJingle(source->player); - scorestate += 10; - break; - } - // More Sonic-like point system - else switch (++source->player->scoreadd) - { - case 1: score = 100; break; - case 2: score = 200; scorestate += 1; break; - case 3: score = 500; scorestate += 2; break; - case 4: case 5: case 6: case 7: case 8: case 9: - case 10: case 11: case 12: case 13: case 14: - score = 1000; scorestate += 3; break; - default: score = 10000; scorestate += 4; break; - } - - P_SetMobjState(scoremobj, scorestate); - } - } - - P_AddPlayerScore(source->player, score); - }*/ } // if a player avatar dies... if (target->player) { + UINT8 i; + target->flags &= ~(MF_SOLID|MF_SHOOTABLE); // does not block P_UnsetThingPosition(target); - target->flags |= MF_NOBLOCKMAP|MF_NOCLIPHEIGHT; + target->flags |= MF_NOBLOCKMAP|MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOGRAVITY; P_SetThingPosition(target); + target->standingslope = NULL; + target->pmomz = 0; target->player->playerstate = PST_DEAD; @@ -2347,56 +1179,19 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) // switch view prior to dying if (automapactive) AM_Stop(); - - //added : 22-02-98: recenter view for next life... - localaiming[0] = 0; } - if (target->player == &players[displayplayers[1]]) - { - // added : 22-02-98: recenter view for next life... - localaiming[1] = 0; - } - if (target->player == &players[displayplayers[2]]) - localaiming[2] = 0; - if (target->player == &players[displayplayers[3]]) - localaiming[3] = 0; - //tag deaths handled differently in suicide cases. Don't count spectators! - /*if (G_TagGametype() - && !(target->player->pflags & PF_TAGIT) && (!source || !source->player) && !(target->player->spectator)) + //added : 22-02-98: recenter view for next life... + for (i = 0; i <= r_splitscreen; i++) { - // if you accidentally die before you run out of time to hide, ignore it. - // allow them to try again, rather than sitting the whole thing out. - if (leveltime >= hidetime * TICRATE) + if (target->player == &players[displayplayers[i]]) { - if (gametype == GT_TAG)//suiciding in survivor makes you IT. - { - target->player->pflags |= PF_TAGIT; - CONS_Printf(M_GetText("%s is now IT!\n"), player_names[target->player-players]); // Tell everyone who is it! - P_CheckSurvivors(); - } - else - { - if (!(target->player->pflags & PF_TAGGED)) - { - //otherwise, increment the tagger's score. - //in hide and seek, suiciding players are counted as found. - INT32 w; - - for (w=0; w < MAXPLAYERS; w++) - { - if (players[w].pflags & PF_TAGIT) - P_AddPlayerScore(&players[w], 1); - } - - target->player->pflags |= PF_TAGGED; - CONS_Printf(M_GetText("%s was found!\n"), player_names[target->player-players]); - P_CheckSurvivors(); - } - } + localaiming[i] = 0; + break; } } - else*/ if (G_BattleGametype()) + + if ((gametyperules & GTR_BUMPERS)) K_CheckBumpers(); target->player->trickpanel = 0; @@ -2405,81 +1200,8 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) if (source && target && target->player && source->player) P_PlayVictorySound(source); // Killer laughs at you. LAUGHS! BWAHAHAHA! - // Drop stuff. - // This determines the kind of object spawned - // during the death frame of a thing. - if (!mariomode // Don't show birds, etc. in Mario Mode Tails 12-23-2001 - && target->flags & MF_ENEMY) - { - if (cv_soniccd.value) - item = MT_SEED; - else - { - INT32 prandom; - - switch (target->type) - { - case MT_REDCRAWLA: - case MT_GOLDBUZZ: - case MT_SKIM: - case MT_UNIDUS: - item = MT_BUNNY; - break; - - case MT_BLUECRAWLA: - case MT_JETTBOMBER: - case MT_GFZFISH: - item = MT_BIRD; - break; - - case MT_JETTGUNNER: - case MT_CRAWLACOMMANDER: - case MT_REDBUZZ: - case MT_DETON: - item = MT_MOUSE; - break; - - case MT_GSNAPPER: - case MT_EGGGUARD: - case MT_SPRINGSHELL: - item = MT_COW; - break; - - case MT_MINUS: - case MT_VULTURE: - case MT_POINTY: - case MT_YELLOWSHELL: - item = MT_CHICKEN; - break; - - case MT_AQUABUZZ: - item = MT_REDBIRD; - break; - - default: - if (target->info->doomednum) - prandom = target->info->doomednum%5; // "Random" animal for new enemies. - else - prandom = P_RandomKey(5); // No placable object, just use a random number. - - switch(prandom) - { - default: item = MT_BUNNY; break; - case 1: item = MT_BIRD; break; - case 2: item = MT_MOUSE; break; - case 3: item = MT_COW; break; - case 4: item = MT_CHICKEN; break; - } - break; - } - } - - mo = P_SpawnMobj(target->x, target->y, target->z + (target->height / 2) - FixedMul(mobjinfo[item].height / 2, target->scale), item); - mo->destscale = target->scale; - P_SetScale(mo, mo->destscale); - } // Other death animation effects - else switch(target->type) + switch(target->type) { case MT_BOUNCEPICKUP: case MT_RAILPICKUP: @@ -2491,27 +1213,158 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) target->fuse = target->info->damage; break; + case MT_BUGGLE: + if (inflictor && inflictor->player // did a player kill you? Spawn relative to the player so they're bound to get it + && P_AproxDistance(inflictor->x - target->x, inflictor->y - target->y) <= inflictor->radius + target->radius + FixedMul(8*FRACUNIT, inflictor->scale) // close enough? + && inflictor->z <= target->z + target->height + FixedMul(8*FRACUNIT, inflictor->scale) + && inflictor->z + inflictor->height >= target->z - FixedMul(8*FRACUNIT, inflictor->scale)) + mo = P_SpawnMobj(inflictor->x + inflictor->momx, inflictor->y + inflictor->momy, inflictor->z + (inflictor->height / 2) + inflictor->momz, MT_EXTRALARGEBUBBLE); + else + mo = P_SpawnMobj(target->x, target->y, target->z, MT_EXTRALARGEBUBBLE); + mo->destscale = target->scale; + P_SetScale(mo, mo->destscale); + P_SetMobjState(mo, mo->info->raisestate); + break; + + case MT_YELLOWSHELL: + P_SpawnMobjFromMobj(target, 0, 0, 0, MT_YELLOWSPRING); + break; + + case MT_CRAWLACOMMANDER: + target->momx = target->momy = target->momz = 0; + break; + + case MT_CRUSHSTACEAN: + if (target->tracer) + { + mobj_t *chain = target->tracer->target, *chainnext; + while (chain) + { + chainnext = chain->target; + P_RemoveMobj(chain); + chain = chainnext; + } + S_StopSound(target->tracer); + P_KillMobj(target->tracer, inflictor, source, damagetype); + } + break; + + case MT_BANPYURA: + if (target->tracer) + { + S_StopSound(target->tracer); + P_KillMobj(target->tracer, inflictor, source, damagetype); + } + break; + + case MT_EGGSHIELD: + P_SetObjectMomZ(target, 4*target->scale, false); + P_InstaThrust(target, target->angle, 3*target->scale); + target->flags = (target->flags|MF_NOCLIPHEIGHT) & ~MF_NOGRAVITY; + break; + + case MT_DRAGONBOMBER: + { + mobj_t *segment = target; + while (segment->tracer != NULL) + { + P_KillMobj(segment->tracer, NULL, NULL, DMG_NORMAL); + segment = segment->tracer; + } + break; + } + + case MT_EGGMOBILE3: + { + mobj_t *mo2; + thinker_t *th; + UINT32 i = 0; // to check how many clones we've removed + + // scan the thinkers to make sure all the old pinch dummies are gone on death + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)th; + if (mo->type != (mobjtype_t)target->info->mass) + continue; + if (mo->tracer != target) + continue; + + P_KillMobj(mo, inflictor, source, damagetype); + mo->destscale = mo->scale/8; + mo->scalespeed = (mo->scale - mo->destscale)/(2*TICRATE); + mo->momz = mo->info->speed; + mo->angle = FixedAngle((P_RandomKey(36)*10)<angle = mo->angle; + P_SetMobjState(mo2, S_BOSSSEBH2); + + if (++i == 2) // we've already removed 2 of these, let's stop now + break; + else + S_StartSound(mo, mo->info->deathsound); // done once to prevent sound stacking + } + } + break; + + case MT_BIGMINE: + if (inflictor) + { + fixed_t dx = target->x - inflictor->x, dy = target->y - inflictor->y, dz = target->z - inflictor->z; + fixed_t dm = FixedHypot(dz, FixedHypot(dy, dx)); + target->momx = FixedDiv(FixedDiv(dx, dm), dm)*512; + target->momy = FixedDiv(FixedDiv(dy, dm), dm)*512; + target->momz = FixedDiv(FixedDiv(dz, dm), dm)*512; + } + if (source) + P_SetTarget(&target->tracer, source); + break; + + case MT_BLASTEXECUTOR: + if (target->spawnpoint) + P_LinedefExecute(target->spawnpoint->angle, (source ? source : inflictor), target->subsector->sector); + break; + + case MT_SPINBOBERT: + if (target->hnext) + P_KillMobj(target->hnext, inflictor, source, damagetype); + if (target->hprev) + P_KillMobj(target->hprev, inflictor, source, damagetype); + break; + case MT_EGGTRAP: // Time for birdies! Yaaaaaaaay! - target->fuse = TICRATE*2; + target->fuse = TICRATE; + break; + + case MT_MINECART: + A_Scream(target); + target->momx = target->momy = target->momz = 0; + if (target->target && target->target->health) + P_KillMobj(target->target, target, source, DMG_NORMAL); break; case MT_PLAYER: - target->momx = target->momy = target->momz = 0; + { + target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player) + target->momx = target->momy = target->momz = 0; - if (target->player && target->player->pflags & PF_TIMEOVER) - break; + if (target->player && target->player->pflags & PF_GAMETYPEOVER) + break; - target->fuse = TICRATE*3; // timer before mobj disappears from view (even if not an actual player) - if (!(source && source->type == MT_NULL && source->threshold == 42)) // Don't jump up when drowning P_SetObjectMomZ(target, 14*FRACUNIT, false); - - if (source && source->type == MT_NULL && source->threshold == 42) // drowned - S_StartSound(target, sfx_drown); - else if (source && (source->type == MT_SPIKE || (source->type == MT_NULL && source->threshold == 43))) // Spikes - S_StartSound(target, sfx_spkdth); - else P_PlayDeathSound(target); + } + break; + + case MT_METALSONIC_RACE: + target->fuse = TICRATE*3; + target->momx = target->momy = target->momz = 0; + P_SetObjectMomZ(target, 14*FRACUNIT, false); + target->flags = (target->flags & ~MF_NOGRAVITY)|(MF_NOCLIP|MF_NOCLIPTHING); break; // SRB2Kart: @@ -2527,6 +1380,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) S_StartSound(target, sfx_s3k80); } break; + case MT_BATTLECAPSULE: { mobj_t *cur; @@ -2571,57 +1425,6 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) break; } - // Enemy drops that ALWAYS occur regardless of mode - if (target->type == MT_AQUABUZZ) // Additionally spawns breathable bubble for players to get - { - if (inflictor && inflictor->player // did a player kill you? Spawn relative to the player so he's bound to get it - && P_AproxDistance(inflictor->x - target->x, inflictor->y - target->y) <= inflictor->radius + target->radius + FixedMul(8*FRACUNIT, inflictor->scale) // close enough? - && inflictor->z <= target->z + target->height + FixedMul(8*FRACUNIT, inflictor->scale) - && inflictor->z + inflictor->height >= target->z - FixedMul(8*FRACUNIT, inflictor->scale)) - mo = P_SpawnMobj(inflictor->x + inflictor->momx, inflictor->y + inflictor->momy, inflictor->z + (inflictor->height / 2) + inflictor->momz, MT_EXTRALARGEBUBBLE); - else - mo = P_SpawnMobj(target->x, target->y, target->z, MT_EXTRALARGEBUBBLE); - mo->destscale = target->scale; - P_SetScale(mo, mo->destscale); - } - else if (target->type == MT_YELLOWSHELL) // Spawns a spring that falls to the ground - { - mobjtype_t spawnspring = MT_YELLOWSPRING; - fixed_t spawnheight = target->z; - if (!(target->eflags & MFE_VERTICALFLIP)) - spawnheight += target->height; - - mo = P_SpawnMobj(target->x, target->y, spawnheight, spawnspring); - mo->destscale = target->scale; - P_SetScale(mo, mo->destscale); - - if (target->flags2 & MF2_OBJECTFLIP) - mo->flags2 |= MF2_OBJECTFLIP; - } - - if (target->type == MT_EGGMOBILE3) - { - thinker_t *th; - UINT32 i = 0; // to check how many clones we've removed - - // scan the thinkers to make sure all the old pinch dummies are gone on death - // this can happen if the boss was hurt earlier than expected - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo = (mobj_t *)th; - if (mo->type == (mobjtype_t)target->info->mass && mo->tracer == target) - { - P_RemoveMobj(mo); - i++; - } - if (i == 2) // we've already removed 2 of these, let's stop now - break; - } - } - if ((target->type == MT_JAWZ || target->type == MT_JAWZ_DUD || target->type == MT_JAWZ_SHIELD) && !(target->flags2 & MF2_AMBUSH)) { target->z += P_MobjFlip(target)*20*target->scale; @@ -2631,7 +1434,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) if (target->type == MT_FROGGER) { if (target->tracer && !P_MobjWasRemoved(target->tracer)) - P_KillMobj(target->tracer, inflictor, source); + P_KillMobj(target->tracer, inflictor, source, DMG_NORMAL); } if (target->type == MT_FROGGER || target->type == MT_ROBRA_HEAD || target->type == MT_BLUEROBRA_HEAD) // clean hnext list @@ -2639,7 +1442,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) mobj_t *cur = target->hnext; while (cur && !P_MobjWasRemoved(cur)) { - P_KillMobj(cur, inflictor, source); + P_KillMobj(cur, inflictor, source, DMG_NORMAL); cur = cur->hnext; } } @@ -2661,93 +1464,153 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) P_InstaThrust(target, R_PointToAngle2(inflictor->x, inflictor->y, target->x, target->y)+ANGLE_90, 16<type == MT_SPIKE && inflictor && target->info->deathstate != S_NULL) + // Final state setting - do something instead of P_SetMobjState; + // Final state setting - do something instead of P_SetMobjState; + if (target->type == MT_SPIKE && target->info->deathstate != S_NULL) { - const fixed_t x=target->x,y=target->y,z=target->z; - const fixed_t scale=target->scale; - const boolean flip=(target->eflags & MFE_VERTICALFLIP) == MFE_VERTICALFLIP; - S_StartSound(target,target->info->deathsound); + const angle_t ang = ((inflictor) ? inflictor->angle : 0) + ANGLE_90; + const fixed_t scale = target->scale; + const fixed_t xoffs = P_ReturnThrustX(target, ang, 8*scale), yoffs = P_ReturnThrustY(target, ang, 8*scale); + const UINT16 flip = (target->eflags & MFE_VERTICALFLIP); + mobj_t *chunk; + fixed_t momz; - P_SetMobjState(target, target->info->deathstate); - target->health = 0; - target->angle = inflictor->angle + ANGLE_90; - P_UnsetThingPosition(target); - target->flags = MF_NOCLIP; - target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - if (flip) - target->z -= FixedMul(12*FRACUNIT, target->scale); - else - target->z += FixedMul(12*FRACUNIT, target->scale); - P_SetThingPosition(target); - P_InstaThrust(target,target->angle,FixedMul(2*FRACUNIT, target->scale)); - target->momz = FixedMul(7*FRACUNIT, target->scale); - if (flip) - target->momz = -target->momz; - - if (flip) - { - target = P_SpawnMobj(x,y,z-FixedMul(12*FRACUNIT, target->scale),MT_SPIKE); - target->eflags |= MFE_VERTICALFLIP; - } - else - target = P_SpawnMobj(x,y,z+FixedMul(12*FRACUNIT, target->scale),MT_SPIKE); - P_SetMobjState(target, target->info->deathstate); - target->health = 0; - target->angle = inflictor->angle - ANGLE_90; - target->destscale = scale; - P_SetScale(target, scale); - P_UnsetThingPosition(target); - target->flags = MF_NOCLIP; - target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - P_SetThingPosition(target); - P_InstaThrust(target,target->angle,FixedMul(2*FRACUNIT, target->scale)); - target->momz = FixedMul(7*FRACUNIT, target->scale); - if (flip) - target->momz = -target->momz; + S_StartSound(target, target->info->deathsound); if (target->info->xdeathstate != S_NULL) { - target = P_SpawnMobj(x,y,z,MT_SPIKE); + momz = 6*scale; if (flip) - target->eflags |= MFE_VERTICALFLIP; - P_SetMobjState(target, target->info->xdeathstate); - target->health = 0; - target->angle = inflictor->angle + ANGLE_90; - target->destscale = scale; - P_SetScale(target, scale); - P_UnsetThingPosition(target); - target->flags = MF_NOCLIP; - target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - P_SetThingPosition(target); - P_InstaThrust(target,target->angle,FixedMul(4*FRACUNIT, target->scale)); - target->momz = FixedMul(6*FRACUNIT, target->scale); - if (flip) - target->momz = -target->momz; + momz *= -1; +#define makechunk(angtweak, xmov, ymov) \ + chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_SPIKE);\ + P_SetMobjState(chunk, target->info->xdeathstate);\ + chunk->health = 0;\ + chunk->angle = angtweak;\ + P_UnsetThingPosition(chunk);\ + chunk->flags = MF_NOCLIP;\ + chunk->x += xmov;\ + chunk->y += ymov;\ + P_SetThingPosition(chunk);\ + P_InstaThrust(chunk,chunk->angle, 4*scale);\ + chunk->momz = momz - target = P_SpawnMobj(x,y,z,MT_SPIKE); - if (flip) - target->eflags |= MFE_VERTICALFLIP; - P_SetMobjState(target, target->info->xdeathstate); - target->health = 0; - target->angle = inflictor->angle - ANGLE_90; - target->destscale = scale; - P_SetScale(target, scale); - P_UnsetThingPosition(target); - target->flags = MF_NOCLIP; - target->x += P_ReturnThrustX(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - target->y += P_ReturnThrustY(target, target->angle, FixedMul(8*FRACUNIT, target->scale)); - P_SetThingPosition(target); - P_InstaThrust(target,target->angle,FixedMul(4*FRACUNIT, target->scale)); - target->momz = FixedMul(6*FRACUNIT, target->scale); - if (flip) - target->momz = -target->momz; + makechunk(ang + ANGLE_180, -xoffs, -yoffs); + makechunk(ang, xoffs, yoffs); + +#undef makechunk } + + momz = 7*scale; + if (flip) + momz *= -1; + + chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_SPIKE); + P_SetMobjState(chunk, target->info->deathstate); + chunk->health = 0; + chunk->angle = ang + ANGLE_180; + P_UnsetThingPosition(chunk); + chunk->flags = MF_NOCLIP; + chunk->x -= xoffs; + chunk->y -= yoffs; + if (flip) + chunk->z -= 12*scale; + else + chunk->z += 12*scale; + P_SetThingPosition(chunk); + P_InstaThrust(chunk, chunk->angle, 2*scale); + chunk->momz = momz; + + P_SetMobjState(target, target->info->deathstate); + target->health = 0; + target->angle = ang; + P_UnsetThingPosition(target); + target->flags = MF_NOCLIP; + target->x += xoffs; + target->y += yoffs; + target->z = chunk->z; + P_SetThingPosition(target); + P_InstaThrust(target, target->angle, 2*scale); + target->momz = momz; + } + else if (target->type == MT_WALLSPIKE && target->info->deathstate != S_NULL) + { + const angle_t ang = (/*(inflictor) ? inflictor->angle : */target->angle) + ANGLE_90; + const fixed_t scale = target->scale; + const fixed_t xoffs = P_ReturnThrustX(target, ang, 8*scale), yoffs = P_ReturnThrustY(target, ang, 8*scale), forwardxoffs = P_ReturnThrustX(target, target->angle, 7*scale), forwardyoffs = P_ReturnThrustY(target, target->angle, 7*scale); + const UINT16 flip = (target->eflags & MFE_VERTICALFLIP); + mobj_t *chunk; + boolean sprflip; + + S_StartSound(target, target->info->deathsound); + if (!P_MobjWasRemoved(target->tracer)) + P_RemoveMobj(target->tracer); + + if (target->info->xdeathstate != S_NULL) + { + sprflip = P_RandomChance(FRACUNIT/2); + +#define makechunk(angtweak, xmov, ymov) \ + chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_WALLSPIKE);\ + P_SetMobjState(chunk, target->info->xdeathstate);\ + chunk->health = 0;\ + chunk->angle = target->angle;\ + P_UnsetThingPosition(chunk);\ + chunk->flags = MF_NOCLIP;\ + chunk->x += xmov - forwardxoffs;\ + chunk->y += ymov - forwardyoffs;\ + P_SetThingPosition(chunk);\ + P_InstaThrust(chunk, angtweak, 4*scale);\ + chunk->momz = P_RandomRange(5, 7)*scale;\ + if (flip)\ + chunk->momz *= -1;\ + if (sprflip)\ + chunk->frame |= FF_VERTICALFLIP + + makechunk(ang + ANGLE_180, -xoffs, -yoffs); + sprflip = !sprflip; + makechunk(ang, xoffs, yoffs); + +#undef makechunk + } + + sprflip = P_RandomChance(FRACUNIT/2); + + chunk = P_SpawnMobjFromMobj(target, 0, 0, 0, MT_WALLSPIKE); + + P_SetMobjState(chunk, target->info->deathstate); + chunk->health = 0; + chunk->angle = target->angle; + P_UnsetThingPosition(chunk); + chunk->flags = MF_NOCLIP; + chunk->x += forwardxoffs - xoffs; + chunk->y += forwardyoffs - yoffs; + P_SetThingPosition(chunk); + P_InstaThrust(chunk, ang + ANGLE_180, 2*scale); + chunk->momz = P_RandomRange(5, 7)*scale; + if (flip) + chunk->momz *= -1; + if (sprflip) + chunk->frame |= FF_VERTICALFLIP; + + P_SetMobjState(target, target->info->deathstate); + target->health = 0; + P_UnsetThingPosition(target); + target->flags = MF_NOCLIP; + target->x += forwardxoffs + xoffs; + target->y += forwardyoffs + yoffs; + P_SetThingPosition(target); + P_InstaThrust(target, ang, 2*scale); + target->momz = P_RandomRange(5, 7)*scale; + if (flip) + target->momz *= -1; + if (!sprflip) + target->frame |= FF_VERTICALFLIP; } else if (target->player) + { P_SetPlayerMobjState(target, target->info->deathstate); + } else #ifdef DEBUG_NULL_DEATHSTATE P_SetMobjState(target, S_NULL); @@ -2760,287 +1623,135 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source) Graue 12-22-2003 */ } -static inline void P_NiGHTSDamage(mobj_t *target, mobj_t *source) +static boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { - player_t *player = target->player; - tic_t oldnightstime = player->nightstime; + (void)inflictor; + (void)damage; - if (!player->powers[pw_flashing] - && !(player->pflags & PF_GODMODE)) + // SRB2Kart: We want to hurt ourselves, so it's now DMG_CANTHURTSELF + if (damagetype & DMG_CANTHURTSELF) { - angle_t fa; - - player->angle_pos = player->old_angle_pos; - player->speed /= 5; - player->flyangle += 180; // Shuffle's BETTERNIGHTSMOVEMENT? - player->flyangle %= 360; - - if (G_RaceGametype()) - player->drillmeter -= 5*20; - else - { - if (source && source->player) - { - if (player->nightstime > 20*TICRATE) - player->nightstime -= 20*TICRATE; - else - player->nightstime = 1; - } - else - { - if (player->nightstime > 5*TICRATE) - player->nightstime -= 5*TICRATE; - else - player->nightstime = 1; - } - } - - if (player->pflags & PF_TRANSFERTOCLOSEST) - { - target->momx = -target->momx; - target->momy = -target->momy; - } - else - { - fa = player->old_angle_pos>>ANGLETOFINESHIFT; - - target->momx = FixedMul(FINECOSINE(fa),target->target->radius); - target->momy = FixedMul(FINESINE(fa),target->target->radius); - } - - player->powers[pw_flashing] = K_GetKartFlashing(player); - P_SetMobjState(target->tracer, S_NIGHTSHURT1); - S_StartSound(target, sfx_nghurt); - - if (oldnightstime > 10*TICRATE - && player->nightstime < 10*TICRATE) - { - //S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH - S_ChangeMusicInternal("drown",false); - } - } -} - -static inline boolean P_TagDamage(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) -{ - player_t *player = target->player; - (void)damage; //unused parm - - // If flashing or invulnerable, ignore the tag, - if (player->powers[pw_flashing] || player->powers[pw_invulnerability]) - return false; - - // Ignore IT players shooting each other, unless friendlyfire is on. - if ((player->pflags & PF_TAGIT && !(cv_friendlyfire.value && - source && source->player && source->player->pflags & PF_TAGIT))) - return false; - - // Don't allow any damage before the round starts. - if (leveltime <= hidetime * TICRATE) - return false; - - // Don't allow players on the same team to hurt one another, - // unless cv_friendlyfire is on. - if (!cv_friendlyfire.value && (player->pflags & PF_TAGIT) == (source->player->pflags & PF_TAGIT)) - { - if (!(inflictor->flags & MF_FIRE)) - P_GivePlayerRings(player, 1); - if (inflictor->flags2 & MF2_BOUNCERING) - inflictor->fuse = 0; // bounce ring disappears at -1 not 0 - return false; - } - - // The tag occurs so long as you aren't shooting another tagger with friendlyfire on. - /*if (source->player->pflags & PF_TAGIT && !(player->pflags & PF_TAGIT)) - { - P_AddPlayerScore(source->player, 1); //award points to tagger. - - if (gametype == GT_TAG) //survivor - { - player->pflags |= PF_TAGIT; //in survivor, the player becomes IT and helps hunt down the survivors. - CONS_Printf(M_GetText("%s is now IT!\n"), player_names[player-players]); // Tell everyone who is it! - } - else - { - player->pflags |= PF_TAGGED; //in hide and seek, the player is tagged and stays stationary. - CONS_Printf(M_GetText("%s was found!\n"), player_names[player-players]); // Tell everyone who is it! - } - - //checks if tagger has tagged all players, if so, end round early. - P_CheckSurvivors(); - }*/ - - P_DoPlayerPain(player, source, inflictor); - - // Check for a shield - if (player->powers[pw_shield]) - { - P_RemoveShield(player); - S_StartSound(target, sfx_shldls); - return true; - } - - P_PlayRinglossSound(target); - P_PlayerRingBurst(player, 5); - - if (inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player) && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - { - player->health -= 10; - if (player->health < 2) - player->health = 2; - target->health = player->health; - } - else - player->health = target->health = 1; - - return true; -} - -static inline boolean P_PlayerHitsPlayer(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) -{ - player_t *player = target->player; - - // You can't kill yourself, idiot... // Unless it's Mario kart. Which it is. In this mod. All the time. - //if (source == target) - // return false; - - // In COOP/RACE/CHAOS, you can't hurt other players unless cv_friendlyfire is on - // ...But in SRB2kart, you can! - //if (!cv_friendlyfire.value && (G_RaceGametype())) - // return false; - - // Tag handling - if (G_TagGametype()) - return P_TagDamage(target, inflictor, source, damage); - else if (G_GametypeHasTeams()) // CTF + Team Match - { - // Don't allow players on the same team to hurt one another, - // unless cv_friendlyfire is on. - if (!cv_friendlyfire.value && target->player->ctfteam == source->player->ctfteam) - { - if (!(inflictor->flags & MF_FIRE)) - P_GivePlayerRings(target->player, 1); - if (inflictor->flags2 & MF2_BOUNCERING) - inflictor->fuse = 0; // bounce ring disappears at -1 not 0 - + // You can't kill yourself, idiot... + if (source == target) return false; + + if (G_GametypeHasTeams()) + { + // Don't hurt your team, either! + if (source->player->ctfteam == target->player->ctfteam) + return false; } } - // Add pity. - if (!player->powers[pw_flashing] && !player->powers[pw_invulnerability] && !player->powers[pw_super] - && source->player->score > player->score) - player->pity++; - return true; } -static void P_KillPlayer(player_t *player, mobj_t *source, INT32 damage) +static boolean P_KillPlayer(player_t *player, UINT8 type) { - (void)source; + if (player->exiting) + { + player->mo->destscale = 1; + player->mo->flags |= MF_NOCLIPTHING; + return false; + } - player->pflags &= ~(PF_CARRIED|PF_SLIDING|PF_ITEMHANG|PF_MACESPIN|PF_ROPEHANG|PF_NIGHTSMODE); + K_RemoveBumper(player, NULL, NULL); + + switch (type) + { + case DMG_DEATHPIT: + // Respawn kill types + K_DoIngameRespawn(player); + return false; + default: + // Everything else REALLY kills + break; + } + + player->pflags &= ~PF_SLIDING; + player->powers[pw_carry] = CR_NONE; // Get rid of shield player->powers[pw_shield] = SH_NONE; + player->mo->color = player->skincolor; player->mo->colorized = false; - // Get rid of emeralds - player->powers[pw_emeralds] = 0; - - P_ForceFeed(player, 40, 10, TICRATE, 40 + min(damage, 100)*2); - P_ResetPlayer(player); + if (player->spectator == false) + { + player->mo->drawflags &= ~MFD_DONTDRAW; + } + P_SetPlayerMobjState(player->mo, player->mo->info->deathstate); - if (player->pflags & PF_TIMEOVER) + if (type == DMG_TIMEOVER) { mobj_t *boom; + player->mo->flags |= (MF_NOGRAVITY|MF_NOCLIP); player->mo->drawflags |= MFD_DONTDRAW; + boom = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_FZEROBOOM); boom->scale = player->mo->scale; boom->angle = player->mo->angle; P_SetTarget(&boom->target, player->mo); } - if (G_BattleGametype()) - { - if (player->kartstuff[k_bumper] > 0) - { - if (player->kartstuff[k_bumper] == 1) - { - mobj_t *karmahitbox = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_KARMAHITBOX); // Player hitbox is too small!! - P_SetTarget(&karmahitbox->target, player->mo); - karmahitbox->destscale = player->mo->scale; - P_SetScale(karmahitbox, player->mo->scale); - CONS_Printf(M_GetText("%s lost all of their bumpers!\n"), player_names[player-players]); - } - player->kartstuff[k_bumper]--; - if (K_IsPlayerWanted(player)) - K_CalculateBattleWanted(); - } - - K_CheckBumpers(); - } + return true; } void P_RemoveShield(player_t *player) { if (player->powers[pw_shield] & SH_FORCE) { // Multi-hit - if ((player->powers[pw_shield] & 0xFF) == 0) - player->powers[pw_shield] &= ~SH_FORCE; - else + if (player->powers[pw_shield] & SH_FORCEHP) player->powers[pw_shield]--; + else + player->powers[pw_shield] &= SH_STACK; } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_NONE) + else if (player->powers[pw_shield] & SH_NOSTACK) + { // First layer shields + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ARMAGEDDON) // Give them what's coming to them! + { + player->pflags |= PF_JUMPDOWN; + } + else + player->powers[pw_shield] &= SH_STACK; + } + else { // Second layer shields - player->powers[pw_shield] = SH_NONE; - // Reset fireflower - if (!player->powers[pw_super]) + if (((player->powers[pw_shield] & SH_STACK) == SH_FIREFLOWER) && !player->powers[pw_super]) { player->mo->color = player->skincolor; G_GhostAddColor((INT32) (player - players), GHC_NORMAL); } + player->powers[pw_shield] = SH_NONE; } - else if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) // Give them what's coming to them! - { - P_BlackOw(player); // BAM! - player->pflags |= PF_JUMPDOWN; - } - else - player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK; } - /** Damages an object, which may or may not be a player. * For melee attacks, source and inflictor are the same. * - * \param target The object being damaged. - * \param inflictor The thing that caused the damage: creature, missile, - * gargoyle, and so forth. Can be NULL in the case of - * environmental damage, such as slime or crushing. - * \param source The creature or person responsible. For example, if a - * player is hit by a ring, the player who shot it. In some - * cases, the target will go after this object after - * receiving damage. This can be NULL. - * \param damage Amount of damage to be dealt. 10000 is instant death. + * \param target The object being damaged. + * \param inflictor The thing that caused the damage: creature, missile, + * gargoyle, and so forth. Can be NULL in the case of + * environmental damage, such as slime or crushing. + * \param source The creature or person responsible. For example, if a + * player is hit by a ring, the player who shot it. In some + * cases, the target will go after this object after + * receiving damage. This can be NULL. + * \param damage Amount of damage to be dealt. + * \param damagetype Type of damage to be dealt. If bit 7 (0x80) is set, this is an instant-kill. * \return True if the target sustained damage, otherwise false. * \todo Clean up this mess, split into multiple functions. - * \todo Get rid of the magic number 10000. * \sa P_KillMobj */ -boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage) +boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype) { player_t *player; -#ifdef HAVE_BLUA boolean force = false; -#else - static const boolean force = false; -#endif if (objectplacing) return false; @@ -3049,22 +1760,19 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da return false; // Spectator handling - if (netgame) + if (multiplayer) { - if (damage == 42000 && target->player && target->player->spectator) - damage = 10000; - else if (target->player && target->player->spectator) + if (damagetype != DMG_SPECTATOR && target->player && target->player->spectator) return false; if (source && source->player && source->player->spectator) return false; } -#ifdef HAVE_BLUA // Everything above here can't be forced. if (!metalrecording) { - UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage); + UINT8 shouldForce = LUAh_ShouldDamage(target, inflictor, source, damage, damagetype); if (P_MobjWasRemoved(target)) return (shouldForce == 1); // mobj was removed if (shouldForce == 1) @@ -3072,16 +1780,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da else if (shouldForce == 2) return false; } -#endif if (!force) { if (!(target->flags & MF_SHOOTABLE)) return false; // shouldn't happen... - if (target->type == MT_BLACKEGGMAN) - return false; - // Make sure that boxes cannot be popped by enemies, red rings, etc. if (target->flags & MF_MONITOR && ((!source || !source->player) || (inflictor && !inflictor->player))) return false; @@ -3090,175 +1794,168 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (target->flags2 & MF2_SKULLFLY) target->momx = target->momy = target->momz = 0; - if (!force) - { - // Special case for team ring boxes - if (target->type == MT_REDRINGBOX && !(source->player->ctfteam == 1)) - return false; - - if (target->type == MT_BLUERINGBOX && !(source->player->ctfteam == 2)) - return false; - } - - // Special case for Crawla Commander - if (target->type == MT_CRAWLACOMMANDER) - { - if (!force && target->fuse) // Invincible - return false; - -#ifdef HAVE_BLUA - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) - return true; -#endif - - if (target->health > 1) - { - if (target->info->painsound) - S_StartSound(target, target->info->painsound); - - target->fuse = TICRATE/2; - target->flags2 |= MF2_FRET; - } - else - { - target->flags |= MF_NOGRAVITY; - target->fuse = 0; - } - - target->momx = target->momy = target->momz = 0; - - P_InstaThrust(target, target->angle-ANGLE_180, FixedMul(5*FRACUNIT, target->scale)); - } - else if (target->flags & MF_BOSS) + if (target->flags & (MF_ENEMY|MF_BOSS)) { if (!force && target->flags2 & MF2_FRET) // Currently flashing from being hit return false; -#ifdef HAVE_BLUA - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) + if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype) || P_MobjWasRemoved(target)) return true; -#endif if (target->health > 1) target->flags2 |= MF2_FRET; } -#ifdef HAVE_BLUA - else if (target->flags & MF_ENEMY) - { - if (LUAh_MobjDamage(target, inflictor, source, damage) || P_MobjWasRemoved(target)) - return true; - } -#endif player = target->player; if (player) // Player is the target { - if (!force) - { - if (player->exiting) - return false; + const UINT8 type = (damagetype & DMG_TYPEMASK); + const boolean combo = (type == DMG_EXPLODE); // This damage type can be comboed from other damage + INT16 ringburst = 5; - if (!(target->player->pflags & (PF_NIGHTSMODE|PF_NIGHTSFALL)) && (maptol & TOL_NIGHTS)) - return false; - } - - if (player->pflags & PF_NIGHTSMODE) // NiGHTS damage handling - { - if (!force) - { - if (source == target) - return false; // Don't hit yourself with your own paraloop, baka - if (source && source->player && !cv_friendlyfire.value - && (gametype == GT_COOP - || (G_GametypeHasTeams() && target->player->ctfteam == source->player->ctfteam))) - return false; // Don't run eachother over in special stages and team games and such - } -#ifdef HAVE_BLUA - if (LUAh_MobjDamage(target, inflictor, source, damage)) - return true; -#endif - P_NiGHTSDamage(target, source); // -5s :( - return true; - } - -#ifdef HAVE_BLUA // Add this back here for ACTUAL NORMAL DAMAGE. The funny shit is that the player is barely ever "actually" damaged. - if (LUAh_MobjDamage(target, inflictor, source, damage)) - return true; -#endif - - if (!force && inflictor && (inflictor->flags & MF_FIRE)) - { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL) - return false; // Invincible to fire objects - - if (G_RaceGametype() && source && source->player) - return false; // Don't get hurt by fire generated from friends. - } - - // Sudden-Death mode - if (source && source->type == MT_PLAYER) - { - if ((G_BattleGametype()) && cv_suddendeath.value - && !player->powers[pw_flashing] && !player->powers[pw_invulnerability]) - damage = 10000; - } - - // Player hits another player - if (!force && source && source->player) - { - if (!P_PlayerHitsPlayer(target, inflictor, source, damage)) - return false; - } - - if (!force && player->pflags & PF_GODMODE) + if (player->pflags & PF_GODMODE) return false; - // Instant-Death - if (damage == 10000) - P_KillPlayer(player, source, damage); - else if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->powers[pw_flashing]) + if (!force) { - if (!force) // shoulddamage bypasses all of that. + // Player hits another player + if (source && source->player) { - K_DoInstashield(player); - return false; + if (!P_PlayerHitsPlayer(target, inflictor, source, damage, damagetype)) + return false; } } + + // Instant-Death + if ((damagetype & DMG_DEATHMASK)) + { + if (!P_KillPlayer(player, damagetype)) + return false; + } + else if (LUAh_MobjDamage(target, inflictor, source, damage, damagetype)) + { + return true; + } else { - if (inflictor && (inflictor->type == MT_ORBINAUT || inflictor->type == MT_ORBINAUT_SHIELD - || inflictor->type == MT_JAWZ || inflictor->type == MT_JAWZ_SHIELD || inflictor->type == MT_JAWZ_DUD - || inflictor->type == MT_SMK_THWOMP || inflictor->player)) + // Check if the player is allowed to be damaged! + // If not, then spawn the instashield effect instead. + if (!force) { - player->kartstuff[k_sneakertimer] = 0; - player->kartstuff[k_numsneakers] = 0; + if (gametyperules & GTR_BUMPERS) + { + if ((player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || player->kartstuff[k_comebackmode] == 1) + { + // No bumpers, can't be hurt + K_DoInstashield(player); + return false; + } + } + else + { + if (damagetype & DMG_STEAL) + { + // Gametype does not have bumpers, steal damage is intended to not do anything + // (No instashield is intentional) + return false; + } + } - K_SpinPlayer(player, source, 1, inflictor, false); - K_KartPainEnergyFling(player); + if (player->kartstuff[k_invincibilitytimer] > 0 || player->kartstuff[k_growshrinktimer] > 0 || player->kartstuff[k_hyudorotimer] > 0) + { + // Full invulnerability + K_DoInstashield(player); + return false; + } - if (P_IsDisplayPlayer(player)) - P_StartQuake(32<powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2)) + { + // Post-hit invincibility + K_DoInstashield(player); + return false; + } + } + } + + // We successfully hit 'em! + if (type != DMG_STING) + { + if (source && source != player->mo && source->player) + { + K_PlayHitEmSound(source); + + if (damagetype & DMG_STEAL) + { + K_StealBumper(source->player, player); + } + } + + K_RemoveBumper(player, inflictor, source); + } + + player->kartstuff[k_sneakertimer] = player->kartstuff[k_numsneakers] = 0; + player->kartstuff[k_driftboost] = 0; + player->kartstuff[k_ringboost] = 0; + + switch (type) + { + case DMG_STING: + K_DebtStingPlayer(player, source); + K_KartPainEnergyFling(player); + ringburst = 0; + break; + case DMG_EXPLODE: + K_ExplodePlayer(player, inflictor, source); + break; + case DMG_WIPEOUT: + if (P_IsDisplayPlayer(player)) + P_StartQuake(32<powers[pw_flashing] = K_GetKartFlashing(player); + + P_PlayRinglossSound(player->mo); + if (ringburst > 0) + P_PlayerRingBurst(player, ringburst); + K_PlayPainSound(player->mo); + + if ((type == DMG_EXPLODE) || (cv_kartdebughuddrop.value && !modeattacking)) + { + K_DropItems(player); } else - K_SpinPlayer(player, source, 0, inflictor, false); + { + K_DropHnextList(player, false); + } + player->kartstuff[k_instashield] = 15; return true; } } - - // Killing dead. Just for kicks. - // Require source and inflictor be player. Don't hurt for firing rings. - if (cv_killingdead.value && (source && source->player) && (inflictor && inflictor->player) && P_RandomChance(5*FRACUNIT/16)) - P_DamageMobj(source, target, target, 1); + else + { + if (damagetype & DMG_STEAL) + { + // Not a player, steal damage is intended to not do anything + return false; + } + } // do the damage - if (player && player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && inflictor && ((inflictor->flags & MF_MISSILE) || inflictor->player)) - { - target->health -= (10 * (1 << (INT32)(player->powers[pw_super] / 10500))); - if (target->health < 2) - target->health = 2; - } + if (damagetype & DMG_DEATHMASK) + target->health = 0; else target->health -= damage; @@ -3267,50 +1964,20 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (target->health <= 0) { - P_KillMobj(target, inflictor, source); + P_KillMobj(target, inflictor, source, damagetype); return true; } if (player) - { - if (!(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) - P_ResetPlayer(target->player); - } + P_ResetPlayer(target->player); else - switch (target->type) - { - case MT_EGGMOBILE2: // egg slimer - if (target->health < target->info->damage) // in pinch phase - { - P_SetMobjState(target, target->info->meleestate); // go to pinch pain state - break; - } - /* FALLTHRU */ - default: - P_SetMobjState(target, target->info->painstate); - break; - } + P_SetMobjState(target, target->info->painstate); if (!P_MobjWasRemoved(target)) { - target->reactiontime = 0; // we're awake now... - - if (source && source != target) - { - // if not intent on another player, - // chase after this one - P_SetTarget(&target->target, source); - if (target->state == &states[target->info->spawnstate] && target->info->seestate != S_NULL) - { - if (player) - { - if (!(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) - P_SetPlayerMobjState(target, target->info->seestate); - } - else - P_SetMobjState(target, target->info->seestate); - } - } + // if not intent on another player, + // chase after this one + P_SetTarget(&target->target, source); } return true; @@ -3333,7 +2000,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) fixed_t momxy = 5<kartstuff[k_rings] <= 0 && num_rings > 2) + if (player->rings <= 0 && num_rings > 2) num_rings = 2; P_GivePlayerRings(player, -num_rings); @@ -3370,7 +2037,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) mo = P_SpawnMobj(player->mo->x, player->mo->y, z, objType); mo->threshold = 10; - mo->fuse = 120*TICRATE; + mo->fuse = 60*TICRATE; P_SetTarget(&mo->target, player->mo); mo->destscale = player->mo->scale; @@ -3384,6 +2051,7 @@ void P_PlayerRingBurst(player_t *player, INT32 num_rings) momxy -= FRACUNIT; momz += 2<momz *= -1; } } - -/** Makes an injured or dead player lose possession of the flag. - * - * \param player The player with the flag, about to lose it. - * \sa P_PlayerRingBurst - */ -void P_PlayerFlagBurst(player_t *player, boolean toss) -{ - mobj_t *flag; - mobjtype_t type; - - if (!(player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - return; - - if (player->gotflag & GF_REDFLAG) - type = MT_REDFLAG; - else - type = MT_BLUEFLAG; - - flag = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, type); - - if (player->mo->eflags & MFE_VERTICALFLIP) - flag->z += player->mo->height - flag->height; - - if (toss) - P_InstaThrust(flag, player->mo->angle, FixedMul(6*FRACUNIT, player->mo->scale)); - else - { - angle_t fa = P_RandomByte()*FINEANGLES/256; - flag->momx = FixedMul(FINECOSINE(fa), FixedMul(6*FRACUNIT, player->mo->scale)); - if (!(twodlevel || (player->mo->flags2 & MF2_TWOD))) - flag->momy = FixedMul(FINESINE(fa), FixedMul(6*FRACUNIT, player->mo->scale)); - } - - flag->momz = FixedMul(8*FRACUNIT, player->mo->scale); - if (player->mo->eflags & MFE_VERTICALFLIP) - flag->momz = -flag->momz; - - if (type == MT_REDFLAG) - flag->spawnpoint = rflagpoint; - else - flag->spawnpoint = bflagpoint; - - flag->fuse = cv_flagtime.value * TICRATE; - P_SetTarget(&flag->target, player->mo); - - // Flag text - { - char plname[MAXPLAYERNAME+4]; - const char *flagtext; - char flagcolor; - - snprintf(plname, sizeof(plname), "%s%s%s", - CTFTEAMCODE(player), - player_names[player - players], - CTFTEAMENDCODE(player)); - - if (type == MT_REDFLAG) - { - flagtext = M_GetText("Red flag"); - flagcolor = '\x85'; - } - else - { - flagtext = M_GetText("Blue flag"); - flagcolor = '\x84'; - } - - if (toss) - CONS_Printf(M_GetText("%s tossed the %c%s%c.\n"), plname, flagcolor, flagtext, 0x80); - else - CONS_Printf(M_GetText("%s dropped the %c%s%c.\n"), plname, flagcolor, flagtext, 0x80); - } - - player->gotflag = 0; - - // Pointers set for displaying time value and for consistency restoration. - if (type == MT_REDFLAG) - redflag = flag; - else - blueflag = flag; - - if (toss) - player->tossdelay = 2*TICRATE; - - return; -} diff --git a/src/p_lights.c b/src/p_lights.c index 2da38d1dc..371077a30 100644 --- a/src/p_lights.c +++ b/src/p_lights.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -23,7 +23,7 @@ * * \param sector The sector to remove effects from. */ -static void P_RemoveLighting(sector_t *sector) +void P_RemoveLighting(sector_t *sector) { if (sector->lightingdata) { @@ -76,7 +76,7 @@ fireflicker_t *P_SpawnAdjustableFireFlicker(sector_t *minsector, sector_t *maxse P_RemoveLighting(maxsector); // out with the old, in with the new flick = Z_Calloc(sizeof (*flick), PU_LEVSPEC, NULL); - P_AddThinker(&flick->thinker); + P_AddThinker(THINK_MAIN, &flick->thinker); flick->thinker.function.acp1 = (actionf_p1)T_FireFlicker; flick->sector = maxsector; @@ -155,7 +155,7 @@ void P_SpawnLightningFlash(sector_t *sector) flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); - P_AddThinker(&flash->thinker); + P_AddThinker(THINK_MAIN, &flash->thinker); flash->thinker.function.acp1 = (actionf_p1)T_LightningFlash; flash->sector = sector; @@ -214,7 +214,7 @@ strobe_t *P_SpawnAdjustableStrobeFlash(sector_t *minsector, sector_t *maxsector, P_RemoveLighting(maxsector); // out with the old, in with the new flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); - P_AddThinker(&flash->thinker); + P_AddThinker(THINK_MAIN, &flash->thinker); flash->sector = maxsector; flash->darktime = darktime; @@ -289,7 +289,7 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, P_RemoveLighting(maxsector); // out with the old, in with the new g = Z_Calloc(sizeof (*g), PU_LEVSPEC, NULL); - P_AddThinker(&g->thinker); + P_AddThinker(THINK_MAIN, &g->thinker); g->sector = maxsector; g->minlight = minsector->lightlevel; @@ -322,39 +322,70 @@ glow_t *P_SpawnAdjustableGlowingLight(sector_t *minsector, sector_t *maxsector, return g; } -/** Fades all the lights in sectors with a particular tag to a new +/** Fades all the lights in specified sector to a new * value. * - * \param tag Tag to look for sectors by. + * \param sector Target sector * \param destvalue The final light value in these sectors. - * \param speed Speed of the fade; the change to the ligh + * \param speed If tic-based: total duration of effect. + * If speed-based: Speed of the fade; the change to the ligh * level in each sector per tic. - * \todo Calculate speed better so that it is possible to specify - * the time for completion of the fade, and all lights fade - * in this time regardless of initial values. + * \param ticbased Use a specific duration for the fade, defined by speed * \sa T_LightFade */ -void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed) +void P_FadeLightBySector(sector_t *sector, INT32 destvalue, INT32 speed, boolean ticbased) +{ + lightlevel_t *ll; + + P_RemoveLighting(sector); // remove the old lighting effect first + + if ((ticbased && !speed) || sector->lightlevel == destvalue) // set immediately + { + sector->lightlevel = destvalue; + return; + } + + ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL); + ll->thinker.function.acp1 = (actionf_p1)T_LightFade; + sector->lightingdata = ll; // set it to the lightlevel_t + + P_AddThinker(THINK_MAIN, &ll->thinker); // add thinker + + ll->sector = sector; + ll->sourcelevel = sector->lightlevel; + ll->destlevel = destvalue; + + ll->fixedcurlevel = sector->lightlevel<timer = abs(speed); + ll->fixedpertic = FixedDiv((destvalue<fixedcurlevel, speed<timer = FixedDiv((destvalue<fixedcurlevel, speed<>FRACBITS; + ll->fixedpertic = speed<= 0 ;) { - sector = §ors[i]; - - P_RemoveLighting(sector); // remove the old lighting effect first - ll = Z_Calloc(sizeof (*ll), PU_LEVSPEC, NULL); - ll->thinker.function.acp1 = (actionf_p1)T_LightFade; - sector->lightingdata = ll; // set it to the lightlevel_t - - P_AddThinker(&ll->thinker); // add thinker - - ll->sector = sector; - ll->destlevel = destvalue; - ll->speed = speed; + if (!force && ticbased // always let speed fader execute + && sectors[i].lightingdata + && ((lightlevel_t*)sectors[i].lightingdata)->thinker.function.acp1 == (actionf_p1)T_LightFade) + // && ((lightlevel_t*)sectors[i].lightingdata)->timer > 2) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 420 Executor: Fade light thinker already exists, timer: %d\n", ((lightlevel_t*)sectors[i].lightingdata)->timer); + continue; + } + P_FadeLightBySector(§ors[i], destvalue, speed, ticbased); } } @@ -365,30 +396,13 @@ void P_FadeLight(INT16 tag, INT32 destvalue, INT32 speed) */ void T_LightFade(lightlevel_t *ll) { - if (ll->sector->lightlevel < ll->destlevel) + if (--ll->timer <= 0) { - // increase the lightlevel - if (ll->sector->lightlevel + ll->speed >= ll->destlevel) - { - // stop changing light level - ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel - - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - } - else - ll->sector->lightlevel = (INT16)(ll->sector->lightlevel + (INT16)ll->speed); // move lightlevel + ll->sector->lightlevel = ll->destlevel; // set to dest lightlevel + P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker + return; } - else - { - // decrease lightlevel - if (ll->sector->lightlevel - ll->speed <= ll->destlevel) - { - // stop changing light level - ll->sector->lightlevel = (INT16)ll->destlevel; // set to dest lightlevel - P_RemoveLighting(ll->sector); // clear lightingdata, remove thinker - } - else - ll->sector->lightlevel = (INT16)(ll->sector->lightlevel - (INT16)ll->speed); // move lightlevel - } + ll->fixedcurlevel = ll->fixedcurlevel + ll->fixedpertic; + ll->sector->lightlevel = (ll->fixedcurlevel)>>FRACBITS; } diff --git a/src/p_local.h b/src/p_local.h index 50b1cfa8d..bdc28075a 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -29,7 +29,7 @@ //#define VIEWHEIGHTS "41" // Maximum player score. -#define MAXSCORE 999999990 +#define MAXSCORE 99999990 // 999999990 // mapblocks are used to check movement // against lines and things @@ -57,18 +57,21 @@ #define AIMINGTOSLOPE(aiming) FINESINE((aiming>>ANGLETOFINESHIFT) & FINEMASK) -#define mariomode (maptol & TOL_MARIO) -#define twodlevel (maptol & TOL_2D) +#define P_GetPlayerViewHeight(player) (41*player->mo->height/48) -// -// P_TICK -// - -// both the head and tail of the thinker list -extern thinker_t thinkercap; +typedef enum +{ + THINK_POLYOBJ, + THINK_MAIN, + THINK_MOBJ, + THINK_DYNSLOPE, + THINK_PRECIP, + NUM_THINKERLISTS +} thinklistnum_t; /**< Thinker lists. */ +extern thinker_t thlist[]; void P_InitThinkers(void); -void P_AddThinker(thinker_t *thinker); +void P_AddThinker(const thinklistnum_t n, thinker_t *thinker); void P_RemoveThinker(thinker_t *thinker); // @@ -126,25 +129,11 @@ struct demofreecam_s { extern struct demofreecam_s democam; extern camera_t camera[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_cam_dist, cv_cam_still, cv_cam_height; -extern consvar_t cv_cam_speed, cv_cam_rotate, cv_cam_rotspeed; +extern consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS], cv_cam_still[MAXSPLITSCREENPLAYERS], cv_cam_height[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_cam_speed[MAXSPLITSCREENPLAYERS], cv_cam_rotate[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_cam2_dist, cv_cam2_still, cv_cam2_height; -extern consvar_t cv_cam2_speed, cv_cam2_rotate, cv_cam2_rotspeed; +extern fixed_t t_cam_dist[MAXSPLITSCREENPLAYERS], t_cam_height[MAXSPLITSCREENPLAYERS], t_cam_rotate[MAXSPLITSCREENPLAYERS]; -extern consvar_t cv_cam3_dist, cv_cam3_still, cv_cam3_height; -extern consvar_t cv_cam3_speed, cv_cam3_rotate, cv_cam3_rotspeed; - -extern consvar_t cv_cam4_dist, cv_cam4_still, cv_cam4_height; -extern consvar_t cv_cam4_speed, cv_cam4_rotate, cv_cam4_rotspeed; - -extern fixed_t t_cam_dist, t_cam_height, t_cam_rotate; -extern fixed_t t_cam2_dist, t_cam2_height, t_cam2_rotate; -extern fixed_t t_cam3_dist, t_cam3_height, t_cam3_rotate; -extern fixed_t t_cam4_dist, t_cam4_height, t_cam4_rotate; - -fixed_t P_GetPlayerHeight(player_t *player); -fixed_t P_GetPlayerSpinHeight(player_t *player); void P_AddPlayerScore(player_t *player, UINT32 amount); void P_ResetCamera(player_t *player, camera_t *thiscam); boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam); @@ -152,66 +141,116 @@ void P_SlideCameraMove(camera_t *thiscam); void P_DemoCameraMovement(camera_t *cam); boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcalled); void P_InitCameraCmd(void); + boolean P_PlayerInPain(player_t *player); -void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor); void P_ResetPlayer(player_t *player); +boolean P_PlayerCanDamage(player_t *player, mobj_t *thing); + boolean P_IsLocalPlayer(player_t *player); boolean P_IsDisplayPlayer(player_t *player); -boolean P_SpectatorJoinGame(player_t *player); + +void P_SetPlayerAngle(player_t *player, angle_t angle); +angle_t P_GetLocalAngle(player_t *player); +void P_ForceLocalAngle(player_t *player, angle_t angle); +boolean P_PlayerFullbright(player_t *player); boolean P_IsObjectInGoop(mobj_t *mo); boolean P_IsObjectOnGround(mobj_t *mo); boolean P_IsObjectOnGroundIn(mobj_t *mo, sector_t *sec); boolean P_IsObjectOnRealGround(mobj_t *mo, sector_t *sec); // SRB2Kart -boolean P_InSpaceSector(mobj_t *mo); boolean P_InQuicksand(mobj_t *mo); +boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff); void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative); void P_RestoreMusic(player_t *player); boolean P_EndingMusic(player_t *player); void P_SpawnShieldOrb(player_t *player); +void P_SwitchShield(player_t *player, UINT16 shieldtype); mobj_t *P_SpawnGhostMobj(mobj_t *mobj); void P_GivePlayerRings(player_t *player, INT32 num_rings); +void P_GivePlayerSpheres(player_t *player, INT32 num_spheres); void P_GivePlayerLives(player_t *player, INT32 numlives); UINT8 P_GetNextEmerald(void); void P_GiveEmerald(boolean spawnObj); +void P_GiveFinishFlags(player_t *player); +#if 0 void P_ResetScore(player_t *player); +#else +#define P_ResetScore(player) player->scoreadd = 0 +#endif boolean P_AutoPause(void); -void P_DoJumpShield(player_t *player); -void P_BlackOw(player_t *player); -void P_ElementalFireTrail(player_t *player); +void P_ElementalFire(player_t *player, boolean cropcircle); +void P_SpawnSkidDust(player_t *player, fixed_t radius, boolean sound); -//void P_DoPityCheck(player_t *player); +void P_MovePlayer(player_t *player); void P_PlayerThink(player_t *player); void P_PlayerAfterThink(player_t *player); void P_DoPlayerExit(player_t *player); void P_DoTimeOver(player_t *player); -//void P_NightserizePlayer(player_t *player, INT32 ptime); void P_InstaThrust(mobj_t *mo, angle_t angle, fixed_t move); fixed_t P_ReturnThrustX(mobj_t *mo, angle_t angle, fixed_t move); fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move); -void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move); -boolean P_LookForEnemies(player_t *player); +mobj_t *P_LookForFocusTarget(player_t *player, mobj_t *exclude, SINT8 direction, UINT8 lockonflags); + void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius); -void P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user -//boolean P_SuperReady(player_t *player); -/*boolean P_TransferToNextMare(player_t *player); -UINT8 P_FindLowestMare(void);*/ + UINT8 P_FindLowestLap(void); UINT8 P_FindHighestLap(void); -void P_FindEmerald(void); -//void P_TransferToAxis(player_t *player, INT32 axisnum); + boolean P_PlayerMoving(INT32 pnum); -void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range); void P_PlayLivesJingle(player_t *player); void P_PlayRinglossSound(mobj_t *source); void P_PlayDeathSound(mobj_t *source); void P_PlayVictorySound(mobj_t *source); +boolean P_GetLives(player_t *player); +boolean P_SpectatorJoinGame(player_t *player); +void P_RestoreMultiMusic(player_t *player); + +/// ------------------------ +/// Jingle stuff +/// ------------------------ + +typedef enum +{ + JT_NONE, // Null state + JT_OTHER, // Other state + JT_MASTER, // Main level music + JT_1UP, // Extra life + JT_SHOES, // Speed shoes + JT_INV, // Invincibility + JT_MINV, // Mario Invincibility + JT_DROWN, // Drowning + JT_SUPER, // Super Sonic + JT_GOVER, // Game Over + JT_NIGHTSTIMEOUT, // NiGHTS Time Out (10 seconds) + JT_SSTIMEOUT, // NiGHTS Special Stage Time Out (10 seconds) + + // these are not jingles + // JT_LCLEAR, // Level Clear + // JT_RACENT, // Multiplayer Intermission + // JT_CONTSC, // Continue + + NUMJINGLES +} jingletype_t; + +typedef struct +{ + char musname[7]; + boolean looping; +} jingle_t; + +extern jingle_t jingleinfo[NUMJINGLES]; + +#define JINGLEPOSTFADE 1000 + +void P_PlayJingle(player_t *player, jingletype_t jingletype); +boolean P_EvaluateMusicStatus(UINT16 status, const char *musname); +void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, boolean looping, UINT16 status); // // P_MOBJ @@ -226,9 +265,11 @@ void P_PlayVictorySound(mobj_t *source); extern mapthing_t *itemrespawnque[ITEMQUESIZE]; extern tic_t itemrespawntime[ITEMQUESIZE]; extern size_t iquehead, iquetail; -extern consvar_t cv_gravity/*, cv_viewheight*/; +extern consvar_t cv_gravity, cv_movebob; void P_RespawnBattleBoxes(void); +mobjtype_t P_GetMobjtype(UINT16 mthingtype); + void P_RespawnSpecials(void); mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); @@ -241,8 +282,9 @@ boolean P_MobjWasRemoved(mobj_t *th); void P_RemoveSavegameMobj(mobj_t *th); boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state); boolean P_SetMobjState(mobj_t *mobj, statenum_t state); -//void P_RunShields(void); +void P_RunShields(void); void P_RunOverlays(void); +void P_HandleMinecartSegments(mobj_t *mobj); void P_MobjThinker(mobj_t *mobj); boolean P_RailThinker(mobj_t *mobj); void P_PushableThinker(mobj_t *mobj); @@ -267,7 +309,10 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover); boolean P_CheckDeathPitCollide(mobj_t *mo); -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover); +boolean P_CheckSolidLava(ffloor_t *rover); +void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype); + +mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type); mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type); mobj_t *P_SpawnXYZMissile(mobj_t *source, mobj_t *dest, mobjtype_t type, fixed_t x, fixed_t y, fixed_t z); @@ -281,13 +326,17 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 aimtype void P_ColorTeamMissile(mobj_t *missile, player_t *source); SINT8 P_MobjFlip(mobj_t *mobj); fixed_t P_GetMobjGravity(mobj_t *mo); -FUNCMATH boolean P_WeaponOrPanel(mobjtype_t type); +void P_CalcChasePostImg(player_t *player, camera_t *thiscam); boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled); void P_Attract(mobj_t *source, mobj_t *enemy, boolean nightsgrab); mobj_t *P_GetClosestAxis(mobj_t *source); +boolean P_CanRunOnWater(player_t *player, ffloor_t *rover); + +void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot); + void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration); #define PAL_WHITE 1 #define PAL_MIXUP 2 @@ -314,6 +363,13 @@ boolean P_CheckMissileRange(mobj_t *actor); void P_NewChaseDir(mobj_t *actor); boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed_t dist); +mobj_t *P_InternalFlickySpawn(mobj_t *actor, mobjtype_t flickytype, fixed_t momz, boolean lookforplayers, SINT8 moveforward); +void P_InternalFlickySetColor(mobj_t *actor, UINT8 extrainfo); +#define P_IsFlickyCenter(type) (type > MT_FLICKY_01 && type < MT_SEED && (type - MT_FLICKY_01) % 2 ? 1 : 0) +void P_InternalFlickyBubble(mobj_t *actor); +void P_InternalFlickyFly(mobj_t *actor, fixed_t flyspeed, fixed_t targetdist, fixed_t chasez); +void P_InternalFlickyHop(mobj_t *actor, fixed_t momz, fixed_t momh, angle_t angle); + // // P_MAP // @@ -323,13 +379,12 @@ boolean P_LookForPlayers(mobj_t *actor, boolean allaround, boolean tracer, fixed extern boolean floatok; extern fixed_t tmfloorz; extern fixed_t tmceilingz; +extern ffloor_t *tmfloorrover, *tmceilingrover; extern mobj_t *tmfloorthing, *tmhitthing, *tmthing; extern camera_t *mapcampointer; extern fixed_t tmx; extern fixed_t tmy; -#ifdef ESLOPE extern pslope_t *tmfloorslope, *tmceilingslope; -#endif /* cphipps 2004/08/30 */ extern void P_MapStart(void); @@ -350,7 +405,7 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam); boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff); boolean P_Move(mobj_t *actor, fixed_t speed); boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z); -void P_SlideMove(mobj_t *mo, boolean forceslide); +void P_SlideMove(mobj_t *mo); void P_BouncePlayerMove(mobj_t *mo); void P_BounceMove(mobj_t *mo); boolean P_CheckSight(mobj_t *t1, mobj_t *t2); @@ -364,9 +419,10 @@ void P_DelPrecipSeclist(mprecipsecnode_t *node); void P_CreateSecNodeList(mobj_t *thing, fixed_t x, fixed_t y); void P_Initsecnode(void); -void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist); +void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype, boolean sightcheck); fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height); +fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height); boolean PIT_PushableMoved(mobj_t *thing); boolean P_DoSpring(mobj_t *spring, mobj_t *object); @@ -404,23 +460,41 @@ typedef struct BasicFF_s INT32 Magnitude; ///< Magnitude of the effect, in the range from 0 through 10,000. } BasicFF_t; +/* Damage/death types, for P_DamageMobj and related */ +//// Damage types +#define DMG_NORMAL 0x00 +#define DMG_WIPEOUT 0x01 // Normal, but with extra flashy effects +#define DMG_EXPLODE 0x02 +#define DMG_SQUISH 0x03 +#define DMG_STING 0x04 +//// Death types - cannot be combined with damage types +#define DMG_INSTAKILL 0x80 +#define DMG_DEATHPIT 0x81 +#define DMG_CRUSHED 0x82 +#define DMG_SPECTATOR 0x83 +#define DMG_TIMEOVER 0x84 +// Masks +#define DMG_STEAL 0x20 // Flag - can steal bumpers, will only deal damage to players, and will not deal damage outside Battle Mode. +#define DMG_CANTHURTSELF 0x40 // Flag - cannot hurt your self or your team +#define DMG_DEATHMASK DMG_INSTAKILL // if bit 7 is set, this is a death type instead of a damage type +#define DMG_TYPEMASK 0x0F // Get type without any flags + void P_ForceFeed(const player_t *player, INT32 attack, INT32 fade, tic_t duration, INT32 period); void P_ForceConstant(const BasicFF_t *FFInfo); void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End); void P_RemoveShield(player_t *player); -boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage); -void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source); +void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source); +boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype); +void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype); void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck); -void P_PlayerFlagBurst(player_t *player, boolean toss); +void P_TouchStarPost(mobj_t *starpost, player_t *player, boolean snaptopost); void P_CheckTimeLimit(void); void P_CheckPointLimit(void); -//void P_CheckSurvivors(void); boolean P_CheckRacers(void); boolean P_CanPickupItem(player_t *player, UINT8 weapon); -void P_DoNightsScore(player_t *player); // // P_SPEC @@ -436,12 +510,11 @@ extern INT32 ceilmovesound; void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, INT16 starpostx, INT16 starposty, INT16 starpostz, INT32 starpostnum, tic_t starposttime, angle_t starpostangle, - INT32 flags2); + fixed_t starpostscale, angle_t drawangle, INT32 flags2); boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, boolean flash, boolean dontstopmove); boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state); boolean P_CheckMissileSpawn(mobj_t *th); void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); -void P_DoSuperTransformation(player_t *player, boolean giverings); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); diff --git a/src/p_map.c b/src/p_map.c index 0b071a17f..eb47f6d89 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -33,14 +33,14 @@ #include "r_splats.h" -#ifdef ESLOPE #include "p_slopes.h" -#endif #include "z_zone.h" #include "lua_hook.h" +#include "m_perfstats.h" // ps_checkposition_calls + fixed_t tmbbox[4]; mobj_t *tmthing; static INT32 tmflags; @@ -58,9 +58,10 @@ fixed_t tmfloorz, tmceilingz; static fixed_t tmdropoffz, tmdrpoffceilz; // drop-off floor/ceiling heights mobj_t *tmfloorthing; // the thing corresponding to tmfloorz or NULL if tmfloorz is from a sector mobj_t *tmhitthing; // the solid thing you bumped into (for collisions) -#ifdef ESLOPE +ffloor_t *tmfloorrover, *tmceilingrover; pslope_t *tmfloorslope, *tmceilingslope; -#endif +static fixed_t tmfloorstep; +static fixed_t tmceilingstep; // keep track of the line that lowers the ceiling, // so missiles don't explode against sky hack walls @@ -123,6 +124,8 @@ boolean P_TeleportMove(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; + thing->floorrover = tmfloorrover; + thing->ceilingrover = tmceilingrover; return true; } @@ -225,8 +228,14 @@ static boolean P_SpecialIsLinedefCrossType(UINT16 ldspecial) return linedefcrossspecial; } -//#define TELEPORTJANK - +// +// P_DoSpring +// +// mass = vertical speed +// damage = horizontal speed +// raisestate = state to change spring to on collision +// painchance = star effect color +// boolean P_DoSpring(mobj_t *spring, mobj_t *object) { //INT32 pflags; @@ -234,29 +243,21 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) const fixed_t vscale = mapobjectscale + (object->scale - mapobjectscale); fixed_t vertispeed = spring->info->mass; fixed_t horizspeed = spring->info->damage; - UINT8 starcolor = (spring->info->painchance % MAXTRANSLATIONS); + UINT16 starcolor = (spring->info->painchance % numskincolors); fixed_t savemomx = 0; fixed_t savemomy = 0; - if (object->eflags & MFE_SPRUNG) // Object was already sprung this tic + // Object was already sprung this tic + if (object->eflags & MFE_SPRUNG) return false; // Spectators don't trigger springs. if (object->player && object->player->spectator) return false; - if (object->player && (object->player->pflags & PF_NIGHTSMODE)) - { - /*Someone want to make these work like bumpers?*/ + // "Even in Death" is a song from Volume 8, not a command. + if (!spring->health || !object->health) return false; - } - -#ifdef ESLOPE - object->standingslope = NULL; // Okay, now we can't return - no launching off at silly angles for you. -#endif - - object->eflags |= MFE_SPRUNG; // apply this flag asap! - spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify #if 0 if (horizspeed && vertispeed) // Mimic SA @@ -266,14 +267,29 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) } #endif + // Does nothing? + if (!vertispeed && !horizspeed) + { + return false; + } + + object->standingslope = NULL; // Okay, now we know it's not going to be relevant - no launching off at silly angles for you. + + object->eflags |= MFE_SPRUNG; // apply this flag asap! + spring->flags &= ~(MF_SOLID|MF_SPECIAL); // De-solidify + if (spring->eflags & MFE_VERTICALFLIP) vertispeed *= -1; // Vertical springs teleport you on TOP of them. if (vertispeed > 0) + { object->z = spring->z + spring->height + 1; + } else if (vertispeed < 0) + { object->z = spring->z - object->height - 1; + } else { fixed_t offx, offy; @@ -293,16 +309,13 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) else if (offx < -(spring->radius + object->radius + 1)) offx = -(spring->radius + object->radius + 1); - if (offy > (spring->radius + object->radius + 1)) - offy = spring->radius + object->radius + 1; - else if (offy < -(spring->radius + object->radius + 1)) - offy = -(spring->radius + object->radius + 1); - P_TryMove(object, spring->x + offx, spring->y + offy, true); } if (vertispeed) + { object->momz = FixedMul(vertispeed, FixedSqrt(FixedMul(vscale, spring->scale))); + } if (horizspeed) { @@ -356,18 +369,20 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object) // Horizontal speed is used as a minimum thrust, not a direct replacement finalSpeed = max(objectSpeed, finalSpeed); - P_InstaThrustEvenIn2D(object, finalAngle, finalSpeed); + P_InstaThrust(object, finalAngle, finalSpeed); } // Re-solidify - spring->flags |= (spring->info->flags & (MF_SPECIAL|MF_SOLID)); + spring->flags |= (spring->info->flags & (MF_SPRING|MF_SPECIAL)); P_SetMobjState(spring, spring->info->raisestate); if (object->player) { if (spring->flags & MF_ENEMY) // Spring shells + { P_SetTarget(&spring->target, object); + } P_ResetPlayer(object->player); @@ -402,9 +417,7 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) zdist = object->z - spring->z; } -#ifdef ESLOPE object->standingslope = NULL; // No launching off at silly angles for you. -#endif switch (spring->type) { @@ -421,15 +434,6 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) // limit the speed if too high if (flipval*object->momz > FixedMul(speed, spring->scale)) object->momz = flipval*FixedMul(speed, spring->scale); - - /* // SRB2kart - don't need state change - if (p && !p->powers[pw_tailsfly]) // doesn't reset anim for Tails' flight - { - P_ResetPlayer(p); - if (p->panim != PA_FALL) - P_SetPlayerMobjState(object, S_PLAY_FALL1); - } - */ break; case MT_STEAM: // Steam if (zdist > FixedMul(16*FRACUNIT, spring->scale)) @@ -453,15 +457,6 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) } else object->momz = flipval*FixedMul(speed, FixedSqrt(FixedMul(spring->scale, object->scale))); // scale the speed with both objects' scales, just like with springs! - - /* // SRB2kart - don't need state change - if (p) - { - P_ResetPlayer(p); - if (p->panim != PA_FALL) - P_SetPlayerMobjState(object, S_PLAY_FALL1); - } - */ break; default: break; @@ -474,7 +469,6 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object) static boolean PIT_CheckThing(mobj_t *thing) { fixed_t blockdist; - boolean iwassprung = false; // don't clip against self if (thing == tmthing) @@ -493,13 +487,12 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; #ifdef SEENAMES - // Do name checks all the way up here - // So that NOTHING ELSE can see MT_NAMECHECK because it is client-side. + // Do name checks all the way up here + // So that NOTHING ELSE can see MT_NAMECHECK because it is client-side. if (tmthing->type == MT_NAMECHECK) { - // Ignore things that aren't players, ignore spectators, ignore yourself. - // (also don't bother to check that tmthing->target->player is non-NULL because we're not actually using it here.) - if (!thing->player || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player)) + // Ignore things that aren't players, ignore spectators, ignore yourself. + if (!thing->player || !(tmthing->target && tmthing->target->player) || thing->player->spectator || (tmthing->target && thing->player == tmthing->target->player)) return true; // Now check that you actually hit them. @@ -512,46 +505,16 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->z + tmthing->height < thing->z) return true; // underneath + // REX HAS SEEN YOU + if (!LUAh_SeenPlayer(tmthing->target->player, thing->player)) + return false; + seenplayer = thing->player; return false; } #endif - // Metal Sonic destroys tiny baby objects. - /*if (tmthing->type == MT_METALSONIC_RACE - && (thing->flags & (MF_MISSILE|MF_ENEMY|MF_BOSS) || thing->type == MT_SPIKE)) - { - if ((thing->flags & (MF_ENEMY|MF_BOSS)) && (thing->health <= 0 || !(thing->flags & MF_SHOOTABLE))) - return true; - blockdist = thing->radius + tmthing->radius; - if (abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist) - return true; // didn't hit it - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath - if (thing->type == MT_SPIKE) - { - S_StartSound(tmthing, thing->info->deathsound); - for (thing = thing->subsector->sector->thinglist; thing; thing = thing->snext) - if (thing->type == MT_SPIKE && thing->health > 0 && thing->flags & MF_SOLID && P_AproxDistance(thing->x - tmthing->x, thing->y - tmthing->y) < FixedMul(56*FRACUNIT, thing->scale)) - P_KillMobj(thing, tmthing, tmthing); - } - else - { - thing->health = 0; - P_KillMobj(thing, tmthing, tmthing); - } - return true; - }*/ - - if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE)) || (thing->flags & MF_NOCLIPTHING)) - return true; - - // Don't collide with your buddies while NiGHTS-flying. - if (tmthing->player && thing->player && (maptol & TOL_NIGHTS) - && ((tmthing->player->pflags & PF_NIGHTSMODE) || (thing->player->pflags & PF_NIGHTSMODE))) + if ((thing->flags & MF_NOCLIPTHING) || !(thing->flags & (MF_SOLID|MF_SPECIAL|MF_PAIN|MF_SHOOTABLE|MF_SPRING))) return true; blockdist = thing->radius + tmthing->radius; @@ -564,6 +527,7 @@ static boolean PIT_CheckThing(mobj_t *thing) fixed_t cosradius, sinradius; vertex_t v1, v2; // fake vertexes line_t junk; // fake linedef + cosradius = FixedMul(thing->radius, FINECOSINE(thing->angle>>ANGLETOFINESHIFT)); sinradius = FixedMul(thing->radius, FINESINE(thing->angle>>ANGLETOFINESHIFT)); @@ -574,23 +538,27 @@ static boolean PIT_CheckThing(mobj_t *thing) junk.v1 = &v1; junk.v2 = &v2; - junk.dx = v2.x - v1.x; - junk.dy = v2.y - v1.y; + junk.dx = 2*cosradius; // v2.x - v1.x; + junk.dy = 2*sinradius; // v2.y - v1.y; if (tmthing->flags & MF_PAPERCOLLISION) // more strenuous checking to prevent clipping issues { INT32 check1, check2, check3, check4; - cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); - sinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); - check1 = P_PointOnLineSide(tmx - cosradius, tmy - sinradius, &junk); - check2 = P_PointOnLineSide(tmx + cosradius, tmy + sinradius, &junk); - check3 = P_PointOnLineSide(tmx + tmthing->momx - cosradius, tmy + tmthing->momy - sinradius, &junk); - check4 = P_PointOnLineSide(tmx + tmthing->momx + cosradius, tmy + tmthing->momy + sinradius, &junk); + fixed_t tmcosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); + fixed_t tmsinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); + if (abs(thing->x - tmx) >= (abs(tmcosradius) + abs(cosradius)) || abs(thing->y - tmy) >= (abs(tmsinradius) + abs(sinradius))) + return true; // didn't hit it + check1 = P_PointOnLineSide(tmx - tmcosradius, tmy - tmsinradius, &junk); + check2 = P_PointOnLineSide(tmx + tmcosradius, tmy + tmsinradius, &junk); + check3 = P_PointOnLineSide(tmx + tmthing->momx - tmcosradius, tmy + tmthing->momy - tmsinradius, &junk); + check4 = P_PointOnLineSide(tmx + tmthing->momx + tmcosradius, tmy + tmthing->momy + tmsinradius, &junk); if ((check1 == check2) && (check2 == check3) && (check3 == check4)) return true; // the line doesn't cross between collider's start or end } else { + if (abs(thing->x - tmx) >= (tmthing->radius + abs(cosradius)) || abs(thing->y - tmy) >= (tmthing->radius + abs(sinradius))) + return true; // didn't hit it if ((P_PointOnLineSide(tmx - tmthing->radius, tmy - tmthing->radius, &junk) == P_PointOnLineSide(tmx + tmthing->radius, tmy + tmthing->radius, &junk)) && (P_PointOnLineSide(tmx + tmthing->radius, tmy - tmthing->radius, &junk) @@ -600,25 +568,27 @@ static boolean PIT_CheckThing(mobj_t *thing) } else if (tmthing->flags & MF_PAPERCOLLISION) { - fixed_t cosradius, sinradius; + fixed_t tmcosradius, tmsinradius; vertex_t v1, v2; // fake vertexes line_t junk; // fake linedef - cosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); - sinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); + tmcosradius = FixedMul(tmthing->radius, FINECOSINE(tmthing->angle>>ANGLETOFINESHIFT)); + tmsinradius = FixedMul(tmthing->radius, FINESINE(tmthing->angle>>ANGLETOFINESHIFT)); - v1.x = tmx - cosradius; - v1.y = tmy - sinradius; - v2.x = tmx + cosradius; - v2.y = tmy + sinradius; + if (abs(thing->x - tmx) >= (thing->radius + abs(tmcosradius)) || abs(thing->y - tmy) >= (thing->radius + abs(tmsinradius))) + return true; // didn't hit it + + v1.x = tmx - tmcosradius; + v1.y = tmy - tmsinradius; + v2.x = tmx + tmcosradius; + v2.y = tmy + tmsinradius; junk.v1 = &v1; junk.v2 = &v2; - junk.dx = v2.x - v1.x; - junk.dy = v2.y - v1.y; - - // no need to check whether thing has MF_PAPERCOLLISION, since checked above + junk.dx = 2*tmcosradius; // v2.x - v1.x; + junk.dy = 2*tmsinradius; // v2.y - v1.y; + // no need to check whether other thing has MF_PAPERCOLLISION, since would fall under other condition if ((P_PointOnLineSide(thing->x - thing->radius, thing->y - thing->radius, &junk) == P_PointOnLineSide(thing->x + thing->radius, thing->y + thing->radius, &junk)) && (P_PointOnLineSide(thing->x + thing->radius, thing->y - thing->radius, &junk) @@ -626,7 +596,6 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // the line doesn't cross between either pair of opposite corners } -#ifdef HAVE_BLUA { UINT8 shouldCollide = LUAh_MobjCollide(thing, tmthing); // checks hook for thing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) @@ -635,9 +604,8 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; // force collide else if (shouldCollide == 2) return true; // force no collide - } - { - UINT8 shouldCollide = LUAh_MobjMoveCollide(tmthing, thing); // checks hook for tmthing's type + + shouldCollide = LUAh_MobjMoveCollide(tmthing, thing); // checks hook for tmthing's type if (P_MobjWasRemoved(tmthing) || P_MobjWasRemoved(thing)) return true; // one of them was removed??? if (shouldCollide == 1) @@ -645,7 +613,6 @@ static boolean PIT_CheckThing(mobj_t *thing) else if (shouldCollide == 2) return true; // force no collide } -#endif // When solid spikes move, assume they just popped up and teleport things on top of them to hurt. if (tmthing->type == MT_SPIKE && tmthing->flags & MF_SOLID) @@ -660,7 +627,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else thing->z = tmthing->z + tmthing->height + FixedMul(FRACUNIT, tmthing->scale); if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, tmthing, tmthing, 1); + P_DamageMobj(thing, tmthing, tmthing, 1, 0); return true; } @@ -671,45 +638,44 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; // overhead if (thing->z + thing->height < tmthing->z) return true; // underneath - if (tmthing->player && tmthing->flags & MF_SHOOTABLE && thing->health > 0) - P_DamageMobj(tmthing, thing, thing, 1); + if (tmthing->flags & MF_SHOOTABLE && thing->health > 0) + { + UINT32 damagetype = (thing->info->mass & 0xFF); + + if (P_DamageMobj(tmthing, thing, thing, 1, damagetype) && (damagetype = (thing->info->mass>>8))) + S_StartSound(thing, damagetype); + } return true; } - else if (tmthing->flags & MF_PAIN) + else if (tmthing->flags & MF_PAIN && thing->player) { // Painful thing splats player in the face // see if it went over / under if (tmthing->z > thing->z + thing->height) return true; // overhead if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (thing->player && thing->flags & MF_SHOOTABLE && tmthing->health > 0) - P_DamageMobj(thing, tmthing, tmthing, 1); - return true; - } + if (thing->flags & MF_SHOOTABLE && tmthing->health > 0) + { + UINT32 damagetype = (tmthing->info->mass & 0xFF); - if (thing->type == MT_HOOPCOLLIDE && thing->flags & MF_SPECIAL && tmthing->player) - { - P_TouchSpecialThing(thing, tmthing, true); + if (P_DamageMobj(thing, tmthing, tmthing, 1, damagetype) && (damagetype = (tmthing->info->mass>>8))) + S_StartSound(tmthing, damagetype); + } return true; } // check for skulls slamming into things if (tmthing->flags2 & MF2_SKULLFLY) { - /*if (tmthing->type == MT_EGGMOBILE) // Don't make Eggman stop! - return true; // Let him RUN YOU RIGHT OVER. >:3 - else*/ - { - // see if it went over / under - if (tmthing->z > thing->z + thing->height) - return true; // overhead - if (tmthing->z + tmthing->height < thing->z) - return true; // underneath + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z + tmthing->height < thing->z) + return true; // underneath - tmthing->flags2 &= ~MF2_SKULLFLY; - tmthing->momx = tmthing->momy = tmthing->momz = 0; - return false; // stop moving - } + tmthing->flags2 &= ~MF2_SKULLFLY; + tmthing->momx = tmthing->momy = tmthing->momz = 0; + return false; // stop moving } // SRB2kart 011617 - Colission[sic] code for kart items //{ @@ -784,13 +750,13 @@ static boolean PIT_CheckThing(mobj_t *thing) thing = oldthing; P_SetTarget(&tmthing, oldtmthing);*/ - if (tmthing->player->kartstuff[k_spinouttimer] || tmthing->player->kartstuff[k_squishedtimer] + if (P_PlayerInPain(tmthing->player) || tmthing->player->powers[pw_flashing] || tmthing->player->kartstuff[k_hyudorotimer] || tmthing->player->kartstuff[k_justbumped] || tmthing->scale > thing->scale + (mapobjectscale/8)) return true; // Player Damage - K_SpinPlayer(tmthing->player, thing, 0, ((thing->type == MT_BUBBLESHIELD) ? thing->target : thing), false); + P_DamageMobj(tmthing, ((thing->type == MT_BUBBLESHIELD) ? thing->target : thing), thing, 1, DMG_NORMAL); S_StartSound(thing, sfx_s3k44); } else @@ -842,13 +808,13 @@ static boolean PIT_CheckThing(mobj_t *thing) thing = oldthing; P_SetTarget(&tmthing, oldtmthing);*/ - if (thing->player->kartstuff[k_spinouttimer] || thing->player->kartstuff[k_squishedtimer] + if (P_PlayerInPain(thing->player) || thing->player->powers[pw_flashing] || thing->player->kartstuff[k_hyudorotimer] || thing->player->kartstuff[k_justbumped] || thing->scale > tmthing->scale + (mapobjectscale/8)) return true; // Player Damage - K_SpinPlayer(thing->player, tmthing, 0, ((tmthing->type == MT_BUBBLESHIELD) ? tmthing->target : tmthing), false); + P_DamageMobj(thing, ((tmthing->type == MT_BUBBLESHIELD) ? tmthing->target : tmthing), tmthing, 1, DMG_NORMAL); S_StartSound(tmthing, sfx_s3k44); } else @@ -1031,15 +997,17 @@ static boolean PIT_CheckThing(mobj_t *thing) } // missiles can hit other things - if (tmthing->flags & MF_MISSILE || tmthing->type == MT_SHELL) + if (tmthing->flags & MF_MISSILE) { + UINT8 damagetype = tmthing->info->mass; + // see if it went over / under if (tmthing->z > thing->z + thing->height) return true; // overhead if (tmthing->z + tmthing->height < thing->z) return true; // underneath - if (tmthing->type != MT_SHELL && tmthing->target && tmthing->target->type == thing->type) + if (tmthing->target && tmthing->target->type == thing->type) { // Don't hit same species as originator. if (thing == tmthing->target) @@ -1053,115 +1021,17 @@ static boolean PIT_CheckThing(mobj_t *thing) } } - // Special case for bounce rings so they don't get caught behind solid objects. - if ((tmthing->type == MT_THROWNBOUNCE && tmthing->fuse > 8*TICRATE) && thing->flags & MF_SOLID) - return true; - - // Missiles ignore Brak's helper. - /*if (thing->type == MT_BLACKEGGMAN_HELPER) - return true; - - // Hurting Brak - if (tmthing->type == MT_BLACKEGGMAN_MISSILE - && thing->type == MT_BLACKEGGMAN && tmthing->target != thing) - { - // Not if Brak's already in pain - if (!(thing->state >= &states[S_BLACKEGG_PAIN1] && thing->state <= &states[S_BLACKEGG_PAIN35])) - P_SetMobjState(thing, thing->info->painstate); - return false; - }*/ - - if (!(thing->flags & MF_SHOOTABLE)/* && !(thing->type == MT_EGGSHIELD)*/) + if (!(thing->flags & MF_SHOOTABLE)) { // didn't do any damage return !(thing->flags & MF_SOLID); } - if (tmthing->flags & MF_MISSILE && thing->player && tmthing->target && tmthing->target->player - && thing->player->ctfteam == tmthing->target->player->ctfteam - && thing->player->pflags & PF_CARRIED && thing->tracer == tmthing->target) - return true; // Don't give rings to your carry player by accident. - - /*if (thing->type == MT_EGGSHIELD) - { - fixed_t touchx, touchy; - angle_t angle; - - if (P_AproxDistance(tmthing->x-thing->x, tmthing->y-thing->y) > - P_AproxDistance((tmthing->x-tmthing->momx)-thing->x, (tmthing->y-tmthing->momy)-thing->y)) - { - touchx = tmthing->x + tmthing->momx; - touchy = tmthing->y + tmthing->momy; - } - else - { - touchx = tmthing->x; - touchy = tmthing->y; - } - - angle = R_PointToAngle2(thing->x, thing->y, touchx, touchy) - thing->angle; - - if (!(angle > ANGLE_90 && angle < ANGLE_270)) // hit front of shield, didn't destroy it - return false; - else // hit shield from behind, shield is destroyed! - { - P_KillMobj(thing, tmthing, tmthing); - return false; - } - }*/ - - if (tmthing->type == MT_SHELL && tmthing->threshold > TICRATE) - return true; // damage / explode - if (tmthing->flags & MF_ENEMY) // An actual ENEMY! (Like the deton, for example) - P_DamageMobj(thing, tmthing, tmthing, 1); - /*else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player - && (thing->player->pflags & PF_JUMPED) - && !thing->player->powers[pw_flashing] - && thing->tracer != tmthing - && tmthing->target != thing) - { - // Hop on the missile for a ride! - thing->player->pflags |= PF_ITEMHANG; - thing->player->pflags &= ~PF_JUMPED; - P_SetTarget(&thing->tracer, tmthing); - P_SetTarget(&tmthing->target, thing); // Set owner to the player - P_SetTarget(&tmthing->tracer, NULL); // Disable homing-ness - tmthing->momz = 0; - - thing->angle = tmthing->angle; - - if (!demo.playback) - { - if (thing->player == &players[consoleplayer]) - localangle[0] = thing->angle; - else if (thing->player == &players[displayplayers[1]]) - localangle[1] = thing->angle; - else if (thing->player == &players[displayplayers[2]]) - localangle[2] = thing->angle; - else if (thing->player == &players[displayplayers[3]]) - localangle[3] = thing->angle; - } - - return true; - } - else if (tmthing->type == MT_BLACKEGGMAN_MISSILE && thing->player && ((thing->player->pflags & PF_ITEMHANG) || (thing->player->pflags & PF_JUMPED))) - { - // Ignore - } - else if (tmthing->type == MT_BLACKEGGMAN_GOOPFIRE) - { - P_UnsetThingPosition(tmthing); - tmthing->x = thing->x; - tmthing->y = thing->y; - P_SetThingPosition(tmthing); - }*/ - else - P_DamageMobj(thing, tmthing, tmthing->target, 1); + P_DamageMobj(thing, tmthing, tmthing->target, 1, damagetype); // don't traverse any more - - return (tmthing->type == MT_SHELL); + return false; } if (thing->flags & MF_PUSHABLE && (tmthing->player || tmthing->flags & MF_PUSHABLE) @@ -1224,29 +1094,6 @@ static boolean PIT_CheckThing(mobj_t *thing) P_SetTarget(&thing->target, tmthing); } - // Respawn rings and items - /*if ((tmthing->type == MT_NIGHTSDRONE || thing->type == MT_NIGHTSDRONE) - && (tmthing->player || thing->player)) - { - mobj_t *droneobj = (tmthing->type == MT_NIGHTSDRONE) ? tmthing : thing; - player_t *pl = (droneobj == thing) ? tmthing->player : thing->player; - - // Must be in bonus time, and must be NiGHTS, must wait about a second - // must be flying in the SAME DIRECTION as the last time you came through. - // not (your direction) xor (stored direction) - // In other words, you can't u-turn and respawn rings near the drone. - if (pl->bonustime && (pl->pflags & PF_NIGHTSMODE) && (INT32)leveltime > droneobj->extravalue2 && ( - !(pl->flyangle > 90 && pl->flyangle < 270) - ^ (droneobj->extravalue1 > 90 && droneobj->extravalue1 < 270) - )) - { - // Reload all the fancy ring stuff! - P_ReloadRings(); - } - droneobj->extravalue1 = pl->flyangle; - droneobj->extravalue2 = (INT32)leveltime + TICRATE; - }*/ - // check for special pickup if (thing->flags & MF_SPECIAL && tmthing->player) { @@ -1268,11 +1115,11 @@ static boolean PIT_CheckThing(mobj_t *thing) { if (thing->z + thing->height <= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) && thing->z + thing->height + thing->momz >= tmthing->z + FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) - P_DamageMobj(thing, tmthing, tmthing, 1); + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_NORMAL); } else if (thing->z >= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) && thing->z + thing->momz <= tmthing->z + tmthing->height - FixedMul(FRACUNIT, tmthing->scale) + tmthing->momz) - P_DamageMobj(thing, tmthing, tmthing, 1); + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_NORMAL); } else if (thing->type == MT_SPIKE && thing->flags & MF_SOLID && tmthing->player) // unfortunate player falls into spike?! { @@ -1280,11 +1127,60 @@ static boolean PIT_CheckThing(mobj_t *thing) { if (tmthing->z + tmthing->height <= thing->z - FixedMul(FRACUNIT, thing->scale) && tmthing->z + tmthing->height + tmthing->momz >= thing->z - FixedMul(FRACUNIT, thing->scale)) - P_DamageMobj(tmthing, thing, thing, 1); + P_DamageMobj(tmthing, thing, thing, 1, DMG_NORMAL); } else if (tmthing->z >= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) && tmthing->z + tmthing->momz <= thing->z + thing->height + FixedMul(FRACUNIT, thing->scale)) - P_DamageMobj(tmthing, thing, thing, 1); + P_DamageMobj(tmthing, thing, thing, 1, DMG_NORMAL); + } + + if (tmthing->type == MT_WALLSPIKE && tmthing->flags & MF_SOLID && thing->player) // wall spike impales player + { + fixed_t bottomz, topz; + bottomz = tmthing->z; + topz = tmthing->z + tmthing->height; + if (tmthing->eflags & MFE_VERTICALFLIP) + bottomz -= FixedMul(FRACUNIT, tmthing->scale); + else + topz += FixedMul(FRACUNIT, tmthing->scale); + + if (thing->z + thing->height > bottomz // above bottom + && thing->z < topz) // below top + // don't check angle, the player was clearly in the way in this case + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_NORMAL); + } + else if (thing->type == MT_WALLSPIKE && thing->flags & MF_SOLID && tmthing->player) + { + fixed_t bottomz, topz; + angle_t touchangle = R_PointToAngle2(thing->tracer->x, thing->tracer->y, tmthing->x, tmthing->y); + + if (P_PlayerInPain(tmthing->player) && (tmthing->momx || tmthing->momy)) + { + angle_t playerangle = R_PointToAngle2(0, 0, tmthing->momx, tmthing->momy) - touchangle; + if (playerangle > ANGLE_180) + playerangle = InvAngle(playerangle); + if (playerangle < ANGLE_90) + return true; // Yes, this is intentionally outside the z-height check. No standing on spikes whilst moving away from them. + } + + bottomz = thing->z; + topz = thing->z + thing->height; + + if (thing->eflags & MFE_VERTICALFLIP) + bottomz -= FixedMul(FRACUNIT, thing->scale); + else + topz += FixedMul(FRACUNIT, thing->scale); + + if (tmthing->z + tmthing->height > bottomz // above bottom + && tmthing->z < topz // below top + && !P_MobjWasRemoved(thing->tracer)) // this probably wouldn't work if we didn't have a tracer + { // use base as a reference point to determine what angle you touched the spike at + touchangle = thing->angle - touchangle; + if (touchangle > ANGLE_180) + touchangle = InvAngle(touchangle); + if (touchangle <= ANGLE_22h) // if you touched it at this close an angle, you get poked! + P_DamageMobj(tmthing, thing, thing, 1, DMG_NORMAL); + } } if (thing->flags & MF_PUSHABLE) @@ -1296,74 +1192,56 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->flags & MF_PUSHABLE) { if (thing->type == MT_FAN || thing->type == MT_STEAM) + { P_DoFanAndGasJet(thing, tmthing); + return true; + } else if (thing->flags & MF_SPRING) { if ( thing->z <= tmthing->z + tmthing->height && tmthing->z <= thing->z + thing->height) - iwassprung = P_DoSpring(thing, tmthing); + if (P_DoSpring(thing, tmthing)) + return false; + return true; } } + // thanks to sal for solidenemies dot lua + if (thing->flags & (MF_ENEMY|MF_BOSS) && tmthing->flags & (MF_ENEMY|MF_BOSS)) + { + if ((thing->z + thing->height >= tmthing->z) + && (tmthing->z + tmthing->height >= thing->z)) + return false; + } + // Damage other players when invincible if (tmthing->player && thing->player // Make sure they aren't able to damage you ANYWHERE along the Z axis, you have to be TOUCHING the person. && !(thing->z + thing->height < tmthing->z || thing->z > tmthing->z + tmthing->height)) { - if (tmthing->scale > thing->scale + (mapobjectscale/8)) // SRB2kart - Handle squishes first! - K_SquishPlayer(thing->player, tmthing, tmthing); - else if (thing->scale > tmthing->scale + (mapobjectscale/8)) - K_SquishPlayer(tmthing->player, thing, tmthing); - else if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer]) // SRB2kart - Then invincibility! - P_DamageMobj(thing, tmthing, tmthing, 1); - else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer]) - P_DamageMobj(tmthing, thing, thing, 1); - else if ((tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD) - && !(thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)) // SRB2kart - Then flame shield! - P_DamageMobj(thing, tmthing, tmthing, 1); - else if ((thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD) - && !(tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)) // SRB2kart - Then flame shield! - P_DamageMobj(tmthing, thing, thing, 1); - - /*if (G_BattleGametype() && (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam)) + if (!G_GametypeHasTeams() || tmthing->player->ctfteam != thing->player->ctfteam) { - if ((tmthing->player->powers[pw_invulnerability] || tmthing->player->powers[pw_super]) - && !thing->player->powers[pw_super]) - P_DamageMobj(thing, tmthing, tmthing, 1); - else if ((thing->player->powers[pw_invulnerability] || thing->player->powers[pw_super]) - && !tmthing->player->powers[pw_super]) - P_DamageMobj(tmthing, thing, thing, 1); - } - - // If players are using touch tag, seekers damage hiders. - if (G_TagGametype() && cv_touchtag.value && - ((thing->player->pflags & PF_TAGIT) != (tmthing->player->pflags & PF_TAGIT))) - { - if ((tmthing->player->pflags & PF_TAGIT) && !(thing->player->pflags & PF_TAGIT)) - P_DamageMobj(thing, tmthing, tmthing, 1); - else if ((thing->player->pflags & PF_TAGIT) && !(tmthing->player->pflags & PF_TAGIT)) - P_DamageMobj(tmthing, thing, tmthing, 1); - }*/ - } - - // Force solid players in hide and seek to avoid corner stacking. - // Kart: No Tailspickup ever, players are always solid - /*if (cv_tailspickup.value && gametype != GT_HIDEANDSEEK) - { - if (tmthing->player && thing->player) - { - P_DoTailsCarry(thing->player, tmthing->player); - return true; + if (tmthing->scale > thing->scale + (mapobjectscale/8)) // SRB2kart - Handle squishes first! + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_SQUISH); + else if (thing->scale > tmthing->scale + (mapobjectscale/8)) + P_DamageMobj(tmthing, thing, thing, 1, DMG_SQUISH); + else if (tmthing->player->kartstuff[k_invincibilitytimer] && !thing->player->kartstuff[k_invincibilitytimer]) // SRB2kart - Then invincibility! + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT); + else if (thing->player->kartstuff[k_invincibilitytimer] && !tmthing->player->kartstuff[k_invincibilitytimer]) + P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT); + else if ((tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD) + && !(thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)) // SRB2kart - Then flame shield! + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT); + else if ((thing->player->kartstuff[k_flamedash] && thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD) + && !(tmthing->player->kartstuff[k_flamedash] && tmthing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD)) + P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT); } } - else if (thing->player) { - thing->player->pflags &= ~PF_CARRIED; - }*/ if (thing->player) { // Doesn't matter what gravity player's following! Just do your stuff in YOUR direction only - /*if (tmthing->eflags & MFE_VERTICALFLIP + if (tmthing->eflags & MFE_VERTICALFLIP && (tmthing->z + tmthing->height + tmthing->momz < thing->z || tmthing->z + tmthing->height + tmthing->momz >= thing->z + thing->height)) ; @@ -1379,13 +1257,13 @@ static boolean PIT_CheckThing(mobj_t *thing) { // Objects kill you if it falls from above. if (thing != tmthing->target) - K_DoIngameRespawn(thing->player); + P_DamageMobj(thing, tmthing, tmthing->target, 1, DMG_CRUSHED); tmthing->momz = -tmthing->momz/2; // Bounce, just for fun! // The tmthing->target allows the pusher of the object // to get the point if he topples it on an opponent. } - }*/ + } if (tmthing->type == MT_FAN || tmthing->type == MT_STEAM) P_DoFanAndGasJet(tmthing, thing); @@ -1402,7 +1280,9 @@ static boolean PIT_CheckThing(mobj_t *thing) { if ( thing->z <= tmthing->z + tmthing->height && tmthing->z <= thing->z + thing->height) - iwassprung = P_DoSpring(thing, tmthing); + if (P_DoSpring(thing, tmthing)) + return false; + return true; } else if (thing->player) // bounce when players collide { @@ -1420,7 +1300,7 @@ static boolean PIT_CheckThing(mobj_t *thing) return true; } - if (G_BattleGametype() + if ((gametyperules & GTR_BUMPERS) && ((thing->player->kartstuff[k_bumper] && !tmthing->player->kartstuff[k_bumper]) || (tmthing->player->kartstuff[k_bumper] && !thing->player->kartstuff[k_bumper]))) { @@ -1439,34 +1319,26 @@ static boolean PIT_CheckThing(mobj_t *thing) mo1 = thing; mo2 = tmthing; - if (G_BattleGametype() && tmthing->player->trickpanel) - { - K_StealBumper(tmthing->player, thing->player, false); - K_SpinPlayer(thing->player, tmthing, 0, tmthing, false); - } + if (tmthing->player->trickpanel) + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT|DMG_STEAL); } else if (P_IsObjectOnGround(tmthing) && thing->momz < 0) { zbounce = true; - if (G_BattleGametype() && thing->player->trickpanel) - { - K_StealBumper(thing->player, tmthing->player, false); - K_SpinPlayer(tmthing->player, thing, 0, thing, false); - } + if (thing->player->trickpanel) + P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); } - if (G_BattleGametype()) + if ((gametyperules & GTR_BUMPERS)) { if (thing->player->kartstuff[k_sneakertimer] && !(tmthing->player->kartstuff[k_sneakertimer]) && !(thing->player->powers[pw_flashing])) // Don't steal bumpers while intangible { - K_StealBumper(thing->player, tmthing->player, false); - K_SpinPlayer(tmthing->player, thing, 0, tmthing, false); + P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT|DMG_STEAL); } else if (tmthing->player->kartstuff[k_sneakertimer] && !(thing->player->kartstuff[k_sneakertimer]) && !(tmthing->player->powers[pw_flashing])) { - K_StealBumper(tmthing->player, thing->player, false); - K_SpinPlayer(thing->player, tmthing, 0, thing, false); + P_DamageMobj(thing, tmthing, tmthing, 1, DMG_WIPEOUT|DMG_STEAL); } } @@ -1490,9 +1362,9 @@ static boolean PIT_CheckThing(mobj_t *thing) || tmthing->player->kartstuff[k_growshrinktimer] > 0) { if (thing->type == MT_BLUEROBRA_JOINT) - P_KillMobj(thing->target, tmthing, tmthing); + P_KillMobj(thing->target, tmthing, tmthing, DMG_NORMAL); else - P_KillMobj(thing, tmthing, tmthing); + P_KillMobj(thing, tmthing, tmthing, DMG_NORMAL); return true; } else @@ -1515,7 +1387,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->player->kartstuff[k_invincibilitytimer] > 0 || tmthing->player->kartstuff[k_growshrinktimer] > 0) { - P_KillMobj(thing, tmthing, tmthing); + P_KillMobj(thing, tmthing, tmthing, DMG_NORMAL); return true; // kill } @@ -1546,7 +1418,7 @@ static boolean PIT_CheckThing(mobj_t *thing) if (tmthing->player->kartstuff[k_invincibilitytimer] > 0 || tmthing->player->kartstuff[k_growshrinktimer] > 0) { - P_KillMobj(thing, tmthing, tmthing); + P_KillMobj(thing, tmthing, tmthing, DMG_NORMAL); return true; } @@ -1569,7 +1441,7 @@ static boolean PIT_CheckThing(mobj_t *thing) else { if (thing->flags2 & MF2_AMBUSH) - P_DamageMobj(tmthing, thing, thing, 1); + P_DamageMobj(tmthing, thing, thing, 1, DMG_WIPEOUT); K_KartBouncing(tmthing, thing, false, true); } @@ -1590,38 +1462,10 @@ static boolean PIT_CheckThing(mobj_t *thing) return false; } - // Are you touching the side of the object you're interacting with? - else if (thing->z - FixedMul(FRACUNIT, thing->scale) <= tmthing->z + tmthing->height - && thing->z + thing->height + FixedMul(FRACUNIT, thing->scale) >= tmthing->z) - { - if (thing->flags & MF_MONITOR - && tmthing->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING)) - { - SINT8 flipval = P_MobjFlip(thing); // Save this value in case monitor gets removed. - fixed_t *momz = &tmthing->momz; // tmthing gets changed by P_DamageMobj, so we need a new pointer?! X_x;; - P_DamageMobj(thing, tmthing, tmthing, 1); // break the monitor - // Going down? Then bounce back up. - if ((P_MobjWasRemoved(thing) // Monitor was removed - || !thing->health) // or otherwise popped - && (flipval*(*momz) < 0)) // monitor is on the floor and you're going down, or on the ceiling and you're going up - *momz = -*momz; // Therefore, you should be thrust in the opposite direction, vertically. - return false; - } - } } - if (thing->flags & MF_SPRING && (tmthing->player || tmthing->flags & MF_PUSHABLE)) - { - if (iwassprung) // this spring caused you to gain MFE_SPRUNG just now... - return false; // "cancel" P_TryMove via blocking so you keep your current position - } - else if (tmthing->flags & MF_SPRING && (thing->player || thing->flags & MF_PUSHABLE)) - ; // Fix a few nasty spring-jumping bugs that happen sometimes. - // Monitors are not treated as solid to players who are jumping, spinning or gliding, - // unless it's a CTF team monitor and you're on the wrong team - /*else if (thing->flags & MF_MONITOR && tmthing->player && tmthing->player->pflags & (PF_JUMPED|PF_SPINNING|PF_GLIDING) - && !((thing->type == MT_REDRINGBOX && tmthing->player->ctfteam != 1) || (thing->type == MT_BLUERINGBOX && tmthing->player->ctfteam != 2))) - ;*/ + if ((tmthing->flags & MF_SPRING || tmthing->type == MT_STEAM || tmthing->type == MT_SPIKE || tmthing->type == MT_WALLSPIKE) && (thing->player)) + ; // springs, gas jets and springs should never be able to step up onto a player // z checking at last // Treat noclip things as non-solid! else if ((thing->flags & (MF_SOLID|MF_NOCLIP)) == MF_SOLID @@ -1639,36 +1483,34 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z + thing->height > tmfloorz) { tmfloorz = thing->z + thing->height; -#ifdef ESLOPE + tmfloorrover = NULL; tmfloorslope = NULL; -#endif } return true; } topz = thing->z - thing->scale; // FixedMul(FRACUNIT, thing->scale), but thing->scale == FRACUNIT in base scale anyways - if (thing->flags & MF_SPRING) - ; // block only when jumping not high enough, // (dont climb max. 24units while already in air) // since return false doesn't handle momentum properly, // we lie to P_TryMove() so it's always too high - else if (tmthing->player && tmthing->z + tmthing->height > topz + if (tmthing->player && tmthing->z + tmthing->height > topz && tmthing->z + tmthing->height < tmthing->ceilingz) { + if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->info->flags & MF_MONITOR)) // Gold monitor hack... + return false; + tmfloorz = tmceilingz = topz; // block while in air -#ifdef ESLOPE + tmceilingrover = NULL; tmceilingslope = NULL; -#endif tmfloorthing = thing; // needed for side collision } else if (topz < tmceilingz && tmthing->z <= thing->z+thing->height) { tmceilingz = topz; -#ifdef ESLOPE + tmceilingrover = NULL; tmceilingslope = NULL; -#endif tmfloorthing = thing; // thing we may stand on } } @@ -1682,36 +1524,34 @@ static boolean PIT_CheckThing(mobj_t *thing) if (thing->z < tmceilingz) { tmceilingz = thing->z; -#ifdef ESLOPE + tmceilingrover = NULL; tmceilingslope = NULL; -#endif } return true; } topz = thing->z + thing->height + thing->scale; // FixedMul(FRACUNIT, thing->scale), but thing->scale == FRACUNIT in base scale anyways - if (thing->flags & MF_SPRING) - ; // block only when jumping not high enough, // (dont climb max. 24units while already in air) // since return false doesn't handle momentum properly, // we lie to P_TryMove() so it's always too high - else if (tmthing->player && tmthing->z < topz + if (tmthing->player && tmthing->z < topz && tmthing->z > tmthing->floorz) { + if (thing->flags & MF_GRENADEBOUNCE && (thing->flags & MF_MONITOR || thing->info->flags & MF_MONITOR)) // Gold monitor hack... + return false; + tmfloorz = tmceilingz = topz; // block while in air -#ifdef ESLOPE + tmfloorrover = NULL; tmfloorslope = NULL; -#endif tmfloorthing = thing; // needed for side collision } else if (topz > tmfloorz && tmthing->z+tmthing->height >= thing->z) { tmfloorz = topz; -#ifdef ESLOPE + tmfloorrover = NULL; tmfloorslope = NULL; -#endif tmfloorthing = thing; // thing we may stand on } } @@ -1787,6 +1627,8 @@ static boolean PIT_CheckCameraLine(line_t *ld) // static boolean PIT_CheckLine(line_t *ld) { + const fixed_t thingtop = tmthing->z + tmthing->height; + if (ld->polyobj && !(ld->polyobj->flags & POF_SOLID)) return true; @@ -1805,7 +1647,22 @@ static boolean PIT_CheckLine(line_t *ld) if (P_PointOnLineSide(tmx - cosradius, tmy - sinradius, ld) == P_PointOnLineSide(tmx + cosradius, tmy + sinradius, ld)) return true; // the line doesn't cross between collider's start or end - +#ifdef PAPER_COLLISIONCORRECTION + { + fixed_t dist; + vertex_t result; + angle_t langle; + P_ClosestPointOnLine(tmx, tmy, ld, &result); + langle = R_PointToAngle2(ld->v1->x, ld->v1->y, ld->v2->x, ld->v2->y); + langle += ANGLE_90*(P_PointOnLineSide(tmx, tmy, ld) ? -1 : 1); + dist = abs(FixedMul(tmthing->radius, FINECOSINE((tmthing->angle - langle)>>ANGLETOFINESHIFT))); + cosradius = FixedMul(dist, FINECOSINE(langle>>ANGLETOFINESHIFT)); + sinradius = FixedMul(dist, FINESINE(langle>>ANGLETOFINESHIFT)); + tmthing->flags |= MF_NOCLIP; + P_TeleportMove(tmthing, result.x + cosradius - tmthing->momx, result.y + sinradius - tmthing->momy, tmthing->z); + tmthing->flags &= ~MF_NOCLIP; + } +#endif } // A line has been hit @@ -1821,6 +1678,17 @@ static boolean PIT_CheckLine(line_t *ld) // this line is out of the if so upper and lower textures can be hit by a splat blockingline = ld; + + { + UINT8 shouldCollide = LUAh_MobjLineCollide(tmthing, blockingline); // checks hook for thing's type + if (P_MobjWasRemoved(tmthing)) + return true; // one of them was removed??? + if (shouldCollide == 1) + return false; // force collide + else if (shouldCollide == 2) + return true; // force no collide + } + if (!ld->backsector) // one sided line { if (P_PointOnLineSide(tmthing->x, tmthing->y, ld)) @@ -1845,17 +1713,25 @@ static boolean PIT_CheckLine(line_t *ld) { tmceilingz = opentop; ceilingline = ld; -#ifdef ESLOPE + tmceilingrover = openceilingrover; tmceilingslope = opentopslope; -#endif + tmceilingstep = openceilingstep; + if (thingtop == tmthing->ceilingz) + { + tmthing->ceilingdrop = openceilingdrop; + } } if (openbottom > tmfloorz) { tmfloorz = openbottom; -#ifdef ESLOPE + tmfloorrover = openfloorrover; tmfloorslope = openbottomslope; -#endif + tmfloorstep = openfloorstep; + if (tmthing->z == tmthing->floorz) + { + tmthing->floordrop = openfloordrop; + } } if (highceiling > tmdrpoffceilz) @@ -1910,10 +1786,13 @@ static boolean PIT_CheckLine(line_t *ld) // boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { + INT32 thingtop = thing->z + thing->height; INT32 xl, xh, yl, yh, bx, by; subsector_t *newsubsec; boolean blockval = true; + ps_checkposition_calls++; + I_Assert(thing != NULL); #ifdef PARANOIA if (P_MobjWasRemoved(thing)) @@ -1940,17 +1819,29 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) // will adjust them. tmfloorz = tmdropoffz = P_GetFloorZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->floorheight; tmceilingz = P_GetCeilingZ(thing, newsubsec->sector, x, y, NULL); //newsubsec->sector->ceilingheight; -#ifdef ESLOPE + tmfloorrover = NULL; + tmceilingrover = NULL; tmfloorslope = newsubsec->sector->f_slope; tmceilingslope = newsubsec->sector->c_slope; -#endif + + tmfloorstep = 0; + tmceilingstep = 0; + + if (thingtop < thing->ceilingz) + { + thing->ceilingdrop = 0; + } + + if (thing->z > thing->floorz) + { + thing->floordrop = 0; + } // Check list of fake floors and see if tmfloorz/tmceilingz need to be altered. if (newsubsec->sector->ffloors) { ffloor_t *rover; fixed_t delta1, delta2; - INT32 thingtop = thing->z + thing->height; for (rover = newsubsec->sector->ffloors; rover; rover = rover->next) { @@ -1983,30 +1874,28 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmfloorz < topheight - sinklevel) { tmfloorz = topheight - sinklevel; -#ifdef ESLOPE + tmfloorrover = rover; tmfloorslope = *rover->t_slope; -#endif } } else if (thing->eflags & MFE_VERTICALFLIP && thingtop <= bottomheight + sinklevel && thing->momz >= 0) { if (tmceilingz > bottomheight + sinklevel) { tmceilingz = bottomheight + sinklevel; -#ifdef ESLOPE + tmceilingrover = rover; tmceilingslope = *rover->b_slope; -#endif } } } continue; } - if (thing->player && P_CheckSolidLava(thing, rover)) + if (thing->player && P_CheckSolidLava(rover)) ; else if (thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE)) ; else if (!((rover->flags & FF_BLOCKPLAYER && thing->player) - || (rover->flags & FF_BLOCKOTHERS && !thing->player) + || (rover->flags & FF_BLOCKOTHERS && !thing->player) || rover->flags & FF_QUICKSAND)) continue; @@ -2016,9 +1905,8 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) { if (tmfloorz < thing->z) { tmfloorz = thing->z; -#ifdef ESLOPE + tmfloorrover = rover; tmfloorslope = NULL; -#endif } } // Quicksand blocks never change heights otherwise. @@ -2034,18 +1922,16 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) && !(rover->flags & FF_REVERSEPLATFORM)) { tmfloorz = tmdropoffz = topheight; -#ifdef ESLOPE + tmfloorrover = rover; tmfloorslope = *rover->t_slope; -#endif } if (bottomheight < tmceilingz && abs(delta1) >= abs(delta2) && !(rover->flags & FF_PLATFORM) && !(thing->type == MT_SKIM && (rover->flags & FF_SWIMMABLE))) { tmceilingz = tmdrpoffceilz = bottomheight; -#ifdef ESLOPE + tmceilingrover = rover; tmceilingslope = *rover->b_slope; -#endif } } } @@ -2062,7 +1948,6 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) BMBOUNDFIX(xl, xh, yl, yh); -#ifdef POLYOBJECTS // Check polyobjects and see if tmfloorz/tmceilingz need to be altered { validcount++; @@ -2088,7 +1973,7 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) if (po->validcount != validcount) // if polyobj hasn't been checked { sector_t *polysec; - fixed_t delta1, delta2, thingtop; + fixed_t delta1, delta2; fixed_t polytop, polybottom; po->validcount = validcount; @@ -2114,29 +1999,25 @@ boolean P_CheckPosition(mobj_t *thing, fixed_t x, fixed_t y) polybottom = INT32_MIN; } - thingtop = thing->z + thing->height; delta1 = thing->z - (polybottom + ((polytop - polybottom)/2)); delta2 = thingtop - (polybottom + ((polytop - polybottom)/2)); if (polytop > tmfloorz && abs(delta1) < abs(delta2)) { tmfloorz = tmdropoffz = polytop; -#ifdef ESLOPE tmfloorslope = NULL; -#endif + tmfloorrover = NULL; } if (polybottom < tmceilingz && abs(delta1) >= abs(delta2)) { tmceilingz = tmdrpoffceilz = polybottom; -#ifdef ESLOPE tmceilingslope = NULL; -#endif + tmceilingrover = NULL; } } plink = (polymaplink_t *)(plink->link.next); } } } -#endif // tmfloorthing is set when tmfloorz comes from a thing's top tmfloorthing = NULL; @@ -2297,7 +2178,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) BMBOUNDFIX(xl, xh, yl, yh); -#ifdef POLYOBJECTS // Check polyobjects and see if tmfloorz/tmceilingz need to be altered { validcount++; @@ -2368,7 +2248,6 @@ boolean P_CheckCameraPosition(fixed_t x, fixed_t y, camera_t *thiscam) } } } -#endif // check lines for (bx = xl; bx <= xh; bx++) @@ -2393,47 +2272,44 @@ boolean P_TryCameraMove(fixed_t x, fixed_t y, camera_t *thiscam) { subsector_t *s = R_PointInSubsector(x, y); boolean retval = true; - boolean itsatwodlevel = false; + UINT8 i; floatok = false; - if (twodlevel) - itsatwodlevel = true; - else + for (i = 0; i <= r_splitscreen; i++) { - for (i = 0; i <= r_splitscreen; i++) + if (thiscam == &camera[i]) { - if (thiscam == &camera[i] && players[displayplayers[i]].mo - && (players[displayplayers[i]].mo->flags2 & MF2_TWOD)) - { - itsatwodlevel = true; - break; - } + // i is now splitscreen cam num + break; } } - if (!itsatwodlevel && players[displayplayers[0]].mo) + if (i > r_splitscreen) + { + // Shouldn't happen + return false; + } + + if (players[displayplayers[i]].mo) { fixed_t tryx = thiscam->x; fixed_t tryy = thiscam->y; - for (i = 0; i <= r_splitscreen; i++) - { #ifndef NOCLIPCAM - if ((thiscam == &camera[i] && (players[displayplayers[i]].pflags & PF_NOCLIP)) || (leveltime < introtime)) // Noclipping player camera noclips too!! + if ((players[displayplayers[i]].pflags & PF_NOCLIP) || (leveltime < introtime)) // Noclipping player camera noclips too!! #else - if (thiscam == &camera[i] && !(players[displayplayers[i]].pflags & PF_TIMEOVER)) // Time Over should not clip through walls + if (!(players[displayplayers[i]].pflags & PF_GAMETYPEOVER)) // Time Over should not clip through walls #endif - { - floatok = true; - thiscam->floorz = thiscam->z; - thiscam->ceilingz = thiscam->z + thiscam->height; - thiscam->x = x; - thiscam->y = y; - thiscam->subsector = s; - return true; - } + { + floatok = true; + thiscam->floorz = thiscam->z; + thiscam->ceilingz = thiscam->z + thiscam->height; + thiscam->x = x; + thiscam->y = y; + thiscam->subsector = s; + return true; } do { @@ -2547,10 +2423,10 @@ boolean PIT_PushableMoved(mobj_t *thing) mobj_t *oldthing = tmthing; line_t *oldceilline = ceilingline; line_t *oldblockline = blockingline; -#ifdef ESLOPE + ffloor_t *oldflrrover = tmfloorrover; + ffloor_t *oldceilrover = tmceilingrover; pslope_t *oldfslope = tmfloorslope; pslope_t *oldcslope = tmceilingslope; -#endif // Move the player P_TryMove(thing, thing->x+stand->momx, thing->y+stand->momy, true); @@ -2563,10 +2439,10 @@ boolean PIT_PushableMoved(mobj_t *thing) P_SetTarget(&tmthing, oldthing); ceilingline = oldceilline; blockingline = oldblockline; -#ifdef ESLOPE + tmfloorrover = oldflrrover; + tmceilingrover = oldceilrover; tmfloorslope = oldfslope; tmceilingslope = oldcslope; -#endif thing->momz = stand->momz; } else @@ -2589,10 +2465,8 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) fixed_t oldx = tryx; fixed_t oldy = tryy; fixed_t radius = thing->radius; - fixed_t thingtop = thing->z + thing->height; -#ifdef ESLOPE + fixed_t thingtop; fixed_t startingonground = P_IsObjectOnGround(thing); -#endif floatok = false; // reset this to 0 at the start of each trymove call as it's only used here @@ -2656,63 +2530,57 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) floatok = true; - if (thing->eflags & MFE_VERTICALFLIP) + if (maxstep > 0) { + thingtop = thing->z + thing->height; + + // Step up if (thing->z < tmfloorz) - return false; // mobj must raise itself to fit - } - else if (tmceilingz < thingtop) - return false; // mobj must lower itself to fit - - // Ramp test - if ((maxstep > 0) && !(P_MobjTouchingSectorSpecial(thing, 1, 14, false))) - { - // If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS - // step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more. - - if (thing->eflags & MFE_VERTICALFLIP) { + if (tmfloorstep <= maxstep) + { + thing->z = thing->floorz = tmfloorz; + thing->floorrover = tmfloorrover; + thing->eflags |= MFE_JUSTSTEPPEDDOWN; + } + else + { + return false; // mobj must raise itself to fit + } + } + else if (tmceilingz < thingtop) + { + if (tmceilingstep <= maxstep) + { + thing->z = ( thing->ceilingz = tmceilingz ) - thing->height; + thing->ceilingrover = tmceilingrover; + thing->eflags |= MFE_JUSTSTEPPEDDOWN; + } + else + { + return false; // mobj must lower itself to fit + } + } + else if (!(P_MobjTouchingSectorSpecial(thing, 1, 14, false))) // Step down + { + // If the floor difference is MAXSTEPMOVE or less, and the sector isn't Section1:14, ALWAYS + // step down! Formerly required a Section1:13 sector for the full MAXSTEPMOVE, but no more. + if (thingtop == thing->ceilingz && tmceilingz > thingtop && tmceilingz - thingtop <= maxstep) { - thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; + thing->z = (thing->ceilingz = tmceilingz) - thing->height; + thing->ceilingrover = tmceilingrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; + thing->ceilingdrop = 0; } -#ifdef ESLOPE - else if (tmceilingz < thingtop && thingtop - tmceilingz <= maxstep) + else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep) { - thing->z = (thing->ceilingz = thingtop = tmceilingz) - thing->height; + thing->z = thing->floorz = tmfloorz; + thing->floorrover = tmfloorrover; thing->eflags |= MFE_JUSTSTEPPEDDOWN; + thing->floordrop = 0; } -#endif } - else if (thing->z == thing->floorz && tmfloorz < thing->z && thing->z - tmfloorz <= maxstep) - { - thing->z = thing->floorz = tmfloorz; - thing->eflags |= MFE_JUSTSTEPPEDDOWN; - } -#ifdef ESLOPE - else if (tmfloorz > thing->z && tmfloorz - thing->z <= maxstep) - { - thing->z = thing->floorz = tmfloorz; - thing->eflags |= MFE_JUSTSTEPPEDDOWN; - } -#endif - } - - if (thing->eflags & MFE_VERTICALFLIP) - { - if (thingtop - tmceilingz > maxstep) - { - if (tmfloorthing) - tmhitthing = tmfloorthing; - return false; // too big a step up - } - } - else if (tmfloorz - thing->z > maxstep) - { - if (tmfloorthing) - tmhitthing = tmfloorthing; - return false; // too big a step up } if (!allowdropoff && !(thing->flags & MF_FLOAT) && thing->type != MT_SKIM && !tmfloorthing) @@ -2757,8 +2625,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; + thing->floorrover = tmfloorrover; + thing->ceilingrover = tmceilingrover; -#ifdef ESLOPE if (!(thing->flags & MF_NOCLIPHEIGHT)) { // Assign thing's standingslope if needed @@ -2772,6 +2641,9 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) #ifdef HWRENDER thing->modeltilt = thing->standingslope; #endif + + if (thing->momz == 0 && thing->player && !startingonground) + P_PlayerHitFloor(thing->player, true); } } else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) { @@ -2784,12 +2656,14 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff) #ifdef HWRENDER thing->modeltilt = thing->standingslope; #endif + + if (thing->momz == 0 && thing->player && !startingonground) + P_PlayerHitFloor(thing->player, true); } } } else // don't set standingslope if you're not going to clip against it thing->standingslope = NULL; -#endif thing->x = x; thing->y = y; @@ -2871,6 +2745,8 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; + thing->floorrover = tmfloorrover; + thing->ceilingrover = tmceilingrover; thing->x = x; thing->y = y; @@ -2990,8 +2866,12 @@ void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_ static boolean P_ThingHeightClip(mobj_t *thing) { boolean floormoved; - fixed_t oldfloorz = thing->floorz; + fixed_t oldfloorz = thing->floorz, oldz = thing->z; + ffloor_t *oldfloorrover = thing->floorrover; + ffloor_t *oldceilingrover = thing->ceilingrover; boolean onfloor = P_IsObjectOnGround(thing);//(thing->z <= thing->floorz); + ffloor_t *rover = NULL; + boolean hitfloor = false; if (thing->flags & MF_NOCLIPHEIGHT) return true; @@ -3006,6 +2886,8 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->floorz = tmfloorz; thing->ceilingz = tmceilingz; + thing->floorrover = tmfloorrover; + thing->ceilingrover = tmceilingrover; // Ugly hack?!?! As long as just ceilingz is the lowest, // you'll still get crushed, right? @@ -3014,16 +2896,24 @@ static boolean P_ThingHeightClip(mobj_t *thing) if (onfloor && !(thing->flags & MF_NOGRAVITY) && floormoved) { - if (thing->eflags & MFE_VERTICALFLIP) - thing->pmomz = thing->ceilingz - (thing->z + thing->height); - else - thing->pmomz = thing->floorz - thing->z; - thing->eflags |= MFE_APPLYPMOMZ; + rover = (thing->eflags & MFE_VERTICALFLIP) ? oldceilingrover : oldfloorrover; - if (thing->eflags & MFE_VERTICALFLIP) - thing->z = thing->ceilingz - thing->height; - else - thing->z = thing->floorz; + // Match the Thing's old floorz to an FOF and check for FF_EXISTS + // If ~FF_EXISTS, don't set mobj Z. + if (!rover || ((rover->flags & FF_EXISTS) && (rover->flags & FF_SOLID))) + { + hitfloor = false; + if (thing->eflags & MFE_VERTICALFLIP) + thing->pmomz = thing->ceilingz - (thing->z + thing->height); + else + thing->pmomz = thing->floorz - thing->z; + thing->eflags |= MFE_APPLYPMOMZ; + + if (thing->eflags & MFE_VERTICALFLIP) + thing->z = thing->ceilingz - thing->height; + else + thing->z = thing->floorz; + } } else if (!tmfloorthing) { @@ -3037,6 +2927,9 @@ static boolean P_ThingHeightClip(mobj_t *thing) thing->z = thing->ceilingz - thing->height; } + if ((P_MobjFlip(thing)*(thing->z - oldz) > 0 || hitfloor) && thing->player) + P_PlayerHitFloor(thing->player, !onfloor); + // debug: be sure it falls to the floor thing->eflags &= ~MFE_ONGROUND; @@ -3268,9 +3161,36 @@ isblocking: return false; // stop } -// -// PTR_SlideTraverse -// +static boolean PTR_LineIsBlocking(line_t *li) +{ + // one-sided linedefs are always solid to sliding movement. + if (!li->backsector) + return !P_PointOnLineSide(slidemo->x, slidemo->y, li); + + if (!(slidemo->flags & MF_MISSILE)) + { + if (li->flags & ML_IMPASSABLE) + return true; + + if (slidemo->player && !slidemo->player->spectator && li->flags & ML_BLOCKPLAYERS) + return true; + } + + // set openrange, opentop, openbottom + P_LineOpening(li, slidemo); + + if (openrange < slidemo->height) + return true; // doesn't fit + + if (opentop - slidemo->z < slidemo->height) + return true; // mobj is too high + + if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, mapobjectscale)) + return true; // too big a step up + + return false; +} + static boolean PTR_SlideTraverse(intercept_t *in) { line_t *li; @@ -3279,49 +3199,18 @@ static boolean PTR_SlideTraverse(intercept_t *in) li = in->d.line; - // one-sided linedefs are always solid to sliding movement. - // one-sided linedef - if (!li->backsector) - { - if (P_PointOnLineSide(slidemo->x, slidemo->y, li)) - return true; // don't hit the back side - goto isblocking; - } + if (!PTR_LineIsBlocking(li)) + return true; - if (!(slidemo->flags & MF_MISSILE)) - { - if (li->flags & ML_IMPASSABLE) - goto isblocking; - - if (slidemo->player && !slidemo->player->spectator && li->flags & ML_BLOCKPLAYERS) - goto isblocking; - } - - // set openrange, opentop, openbottom - P_LineOpening(li, slidemo); - - if (openrange < slidemo->height) - goto isblocking; // doesn't fit - - if (opentop - slidemo->z < slidemo->height) - goto isblocking; // mobj is too high - - if (openbottom - slidemo->z > FixedMul(MAXSTEPMOVE, mapobjectscale)) - goto isblocking; // too big a step up - - // this line doesn't block movement - return true; - - // the line does block movement, + // the line blocks movement, // see if it is closer than best so far -isblocking: if (li->polyobj && slidemo->player) { if ((li->polyobj->lines[0]->backsector->flags & SF_TRIGGERSPECIAL_TOUCH) && !(li->polyobj->flags & POF_NOSPECIALS)) P_ProcessSpecialSector(slidemo->player, slidemo->subsector->sector, li->polyobj->lines[0]->backsector); } - if (in->frac < bestslidefrac) + if (in->frac < bestslidefrac && (!slidemo->player || !slidemo->player->climbing)) { secondslidefrac = bestslidefrac; secondslideline = bestslideline; @@ -3431,6 +3320,56 @@ stairstep: goto retry; } +static void P_CheckLavaWall(mobj_t *mo, sector_t *sec) +{ + ffloor_t *rover; + fixed_t topheight, bottomheight; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!(rover->flags & FF_SWIMMABLE)) + continue; + + if (GETSECSPECIAL(rover->master->frontsector->special, 1) != 3) + continue; + + if (rover->master->flags & ML_BLOCKPLAYERS) + continue; + + topheight = P_GetFFloorTopZAt(rover, mo->x, mo->y); + + if (mo->eflags & MFE_VERTICALFLIP) + { + if (topheight < mo->z - mo->height) + continue; + } + else + { + if (topheight < mo->z) + continue; + } + + bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y); + + if (mo->eflags & MFE_VERTICALFLIP) + { + if (bottomheight > mo->z) + continue; + } + else + { + if (bottomheight > mo->z + mo->height) + continue; + } + + P_DamageMobj(mo, NULL, NULL, 1, DMG_NORMAL); + return; + } +} + // // P_SlideMove // The momx / momy move is bad, so try to slide @@ -3440,18 +3379,119 @@ stairstep: // // This is a kludgy mess. // -void P_SlideMove(mobj_t *mo, boolean forceslide) +void P_SlideMove(mobj_t *mo) { fixed_t leadx, leady, trailx, traily, newx, newy; INT16 hitcount = 0; boolean success = false; + boolean papercol = false; + vertex_t v1, v2; // fake vertexes + line_t junk; // fake linedef + if (tmhitthing && mo->z + mo->height > tmhitthing->z && mo->z < tmhitthing->z + tmhitthing->height) { // Don't mess with your momentum if it's a pushable object. Pushables do their own crazy things already. if (tmhitthing->flags & MF_PUSHABLE) return; + if (tmhitthing->flags & MF_PAPERCOLLISION) + { + fixed_t cosradius, sinradius, num, den; + + // trace along the three leading corners + if (mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if (mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + papercol = true; + slidemo = mo; + bestslideline = &junk; + + cosradius = FixedMul(tmhitthing->radius, FINECOSINE(tmhitthing->angle>>ANGLETOFINESHIFT)); + sinradius = FixedMul(tmhitthing->radius, FINESINE(tmhitthing->angle>>ANGLETOFINESHIFT)); + + v1.x = tmhitthing->x - cosradius; + v1.y = tmhitthing->y - sinradius; + v2.x = tmhitthing->x + cosradius; + v2.y = tmhitthing->y + sinradius; + + // Can we box collision our way into smooth movement..? + if (sinradius && mo->y + mo->radius <= min(v1.y, v2.y)) + { + mo->momy = 0; + P_TryMove(mo, mo->x + mo->momx, min(v1.y, v2.y) - mo->radius, true); + return; + } + else if (sinradius && mo->y - mo->radius >= max(v1.y, v2.y)) + { + mo->momy = 0; + P_TryMove(mo, mo->x + mo->momx, max(v1.y, v2.y) + mo->radius, true); + return; + } + else if (cosradius && mo->x + mo->radius <= min(v1.x, v2.x)) + { + mo->momx = 0; + P_TryMove(mo, min(v1.x, v2.x) - mo->radius, mo->y + mo->momy, true); + return; + } + else if (cosradius && mo->x - mo->radius >= max(v1.x, v2.x)) + { + mo->momx = 0; + P_TryMove(mo, max(v1.x, v2.x) + mo->radius, mo->y + mo->momy, true); + return; + } + + // nope, gotta fuck around with a fake linedef! + junk.v1 = &v1; + junk.v2 = &v2; + junk.dx = 2*cosradius; // v2.x - v1.x; + junk.dy = 2*sinradius; // v2.y - v1.y; + + junk.slopetype = !cosradius ? ST_VERTICAL : !sinradius ? ST_HORIZONTAL : + ((sinradius > 0) == (cosradius > 0)) ? ST_POSITIVE : ST_NEGATIVE; + + bestslidefrac = FRACUNIT+1; + + den = FixedMul(junk.dy>>8, mo->momx) - FixedMul(junk.dx>>8, mo->momy); + + if (!den) + bestslidefrac = 0; + else + { + fixed_t frac; +#define P_PaperTraverse(startx, starty) \ + num = FixedMul((v1.x - leadx)>>8, junk.dy) + FixedMul((leady - v1.y)>>8, junk.dx); \ + frac = FixedDiv(num, den); \ + if (frac < bestslidefrac) \ + bestslidefrac = frac + P_PaperTraverse(leadx, leady); + P_PaperTraverse(trailx, leady); + P_PaperTraverse(leadx, traily); +#undef dowork + } + + goto papercollision; + } + // Thankfully box collisions are a lot simpler than arbitrary lines. There's only four possible cases. if (mo->y + mo->radius <= tmhitthing->y - tmhitthing->radius) { @@ -3482,7 +3522,7 @@ void P_SlideMove(mobj_t *mo, boolean forceslide) bestslideline = NULL; retry: - if (++hitcount == 3) + if ((++hitcount == 3) || papercol) goto stairstep; // don't loop forever // trace along the three leading corners @@ -3517,13 +3557,13 @@ retry: P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, PT_ADDLINES, PTR_SlideTraverse); - // Some walls are bouncy even if you're not - if (!forceslide && bestslideline && !(bestslideline->flags & ML_BOUNCY)) // SRB2kart - All walls are bouncy unless specified otherwise + if (bestslideline && mo->player && bestslideline->sidenum[1] != 0xffff) { - P_BounceMove(mo); - return; + sector_t *sec = P_PointOnLineSide(mo->x, mo->y, bestslideline) ? bestslideline->frontsector : bestslideline->backsector; + P_CheckLavaWall(mo, sec); } +papercollision: // move up to the wall if (bestslidefrac == FRACUNIT+1) { @@ -3560,16 +3600,8 @@ stairstep: P_HitSlideLine(bestslideline); // clip the moves - if ((twodlevel || (mo->flags2 & MF2_TWOD)) && mo->player) - { - mo->momx = tmxmove; - tmymove = 0; - } - else - { - mo->momx = tmxmove; - mo->momy = tmymove; - } + mo->momx = tmxmove; + mo->momy = tmymove; do { if (tmxmove > mo->radius) { @@ -3620,7 +3652,7 @@ void P_BouncePlayerMove(mobj_t *mo) if (mo->player->spectator) { - P_SlideMove(mo, true); + P_SlideMove(mo); return; } @@ -3726,7 +3758,7 @@ void P_BounceMove(mobj_t *mo) if (mo->eflags & MFE_JUSTBOUNCEDWALL) { - P_SlideMove(mo, true); + P_SlideMove(mo); return; } @@ -3827,6 +3859,14 @@ bounceback: tmymove = FixedMul(mmomy, (FRACUNIT - (FRACUNIT>>2) - (FRACUNIT>>3))); } + // Some walls aren't bouncy even if you are + if (bestslideline && (bestslideline->flags & ML_NOTBOUNCY)) + { + // SRB2Kart: Non-bouncy line! + P_SlideMove(mo); + return; + } + P_HitBounceLine(bestslideline); // clip the moves mo->momx = tmxmove; @@ -3842,6 +3882,8 @@ bounceback: static fixed_t bombdamage; static mobj_t *bombsource; static mobj_t *bombspot; +static UINT8 bombdamagetype; +static boolean bombsightcheck; // // PIT_RadiusAttack @@ -3852,17 +3894,13 @@ static boolean PIT_RadiusAttack(mobj_t *thing) { fixed_t dx, dy, dz, dist; - if (thing == bombspot // ignore the bomb itself (Deton fix) - || (bombsource && thing->type == bombsource->type)) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.) + if (thing == bombspot) // ignore the bomb itself (Deton fix) return true; - if (!(thing->flags & MF_SHOOTABLE)) + if ((bombdamagetype & DMG_CANTHURTSELF) && bombsource && thing->type == bombsource->type) // ignore the type of guys who dropped the bomb (Jetty-Syn Bomber or Skim can bomb eachother, but not themselves.) return true; - if (thing->flags & MF_BOSS) - return true; - - if (thing->flags & MF_MONITOR) + if ((thing->flags & (MF_MONITOR|MF_SHOOTABLE)) != MF_SHOOTABLE) return true; dx = abs(thing->x - bombspot->x); @@ -3884,9 +3922,9 @@ static boolean PIT_RadiusAttack(mobj_t *thing) if (thing->ceilingz < bombspot->z && bombspot->floorz > thing->z) return true; - if (P_CheckSight(thing, bombspot)) + if (!bombsightcheck || P_CheckSight(thing, bombspot)) { // must be in direct path - P_DamageMobj(thing, bombspot, bombsource, 1); // Tails 01-11-2001 + P_DamageMobj(thing, bombspot, bombsource, 1, bombdamagetype); // Tails 01-11-2001 } return true; @@ -3896,7 +3934,7 @@ static boolean PIT_RadiusAttack(mobj_t *thing) // P_RadiusAttack // Source is the creature that caused the explosion at spot. // -void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist) +void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist, UINT8 damagetype, boolean sightcheck) { INT32 x, y; INT32 xl, xh, yl, yh; @@ -3913,6 +3951,8 @@ void P_RadiusAttack(mobj_t *spot, mobj_t *source, fixed_t damagedist) bombspot = spot; bombsource = source; bombdamage = FixedMul(damagedist, spot->scale); + bombdamagetype = damagetype; + bombsightcheck = sightcheck; for (y = yl; y <= yh; y++) for (x = xl; x <= xh; x++) @@ -3941,6 +3981,8 @@ static boolean nofit; static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) { mobj_t *killer = NULL; + //If a thing is both pushable and vulnerable, it doesn't block the crusher because it gets killed. + boolean immunepushable = ((thing->flags & (MF_PUSHABLE | MF_SHOOTABLE)) == MF_PUSHABLE); if (P_ThingHeightClip(thing)) { @@ -3959,7 +4001,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) // just be blocked by another object - check if it's really a ceiling! if (thing->z + thing->height > thing->ceilingz && thing->z <= thing->ceilingz) { - if (thing->flags & MF_PUSHABLE && thing->z + thing->height > thing->subsector->sector->ceilingheight) + if (immunepushable && thing->z + thing->height > thing->subsector->sector->ceilingheight) { //Thing is a pushable and blocks the moving ceiling nofit = true; @@ -3967,7 +4009,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) } //Check FOFs in the sector - if (thing->subsector->sector->ffloors && (realcrush || thing->flags & MF_PUSHABLE)) + if (thing->subsector->sector->ffloors && (realcrush || immunepushable)) { ffloor_t *rover; fixed_t topheight, bottomheight; @@ -3982,19 +4024,14 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) topheight = *rover->topheight; bottomheight = *rover->bottomheight; - -/*#ifdef ESLOPE - if (rover->t_slope) - topheight = P_GetZAt(rover->t_slope, thing->x, thing->y); - if (rover->b_slope) - bottomheight = P_GetZAt(rover->b_slope, thing->x, thing->y); -#endif*/ + //topheight = P_GetFFloorTopZAt (rover, thing->x, thing->y); + //bottomheight = P_GetFFloorBottomZAt(rover, thing->x, thing->y); delta1 = thing->z - (bottomheight + topheight)/2; delta2 = thingtop - (bottomheight + topheight)/2; if (bottomheight <= thing->ceilingz && abs(delta1) >= abs(delta2)) { - if (thing->flags & MF_PUSHABLE) + if (immunepushable) { //FOF is blocked by pushable nofit = true; @@ -4004,21 +4041,19 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) { //If the thing was crushed by a crumbling FOF, reward the player who made it crumble! thinker_t *think; - elevator_t *crumbler; + crumble_t *crumbler; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MAIN].next; think != &thlist[THINK_MAIN]; think = think->next) { if (think->function.acp1 != (actionf_p1)T_StartCrumble) continue; - crumbler = (elevator_t *)think; + crumbler = (crumble_t *)think; if (crumbler->player && crumbler->player->mo && crumbler->player->mo != thing && crumbler->actionsector == thing->subsector->sector - && crumbler->sector == rover->master->frontsector - && (crumbler->type == elevateBounce - || crumbler->type == elevateContinuous)) + && crumbler->sector == rover->master->frontsector) { killer = crumbler->player->mo; } @@ -4032,25 +4067,15 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) { // Crush the object if (netgame && thing->player && thing->player->spectator) - P_DamageMobj(thing, NULL, NULL, 42000); // Respawn crushed spectators + P_DamageMobj(thing, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators else - { - if (!killer) - { - //Nobody is responsible for crushing the object, so give a generic crush message - killer = P_SpawnMobj(thing->x, thing->y, thing->z, MT_NULL); - killer->threshold = 44; // Special flag for crushing - } - if (!thing->player) - P_DamageMobj(thing, killer, killer, 10000); - else - K_SquishPlayer(thing->player, killer, killer); // SRB2kart - Squish instead of kill - } + P_DamageMobj(thing, killer, killer, 1, DMG_CRUSHED); + return true; } } if (realcrush && crushchange) - P_DamageMobj(thing, NULL, NULL, 1); + P_DamageMobj(thing, NULL, NULL, 1, DMG_NORMAL); // keep checking (crush other things) return true; @@ -4062,6 +4087,7 @@ static boolean PIT_ChangeSector(mobj_t *thing, boolean realcrush) boolean P_CheckSector(sector_t *sector, boolean crunch) { msecnode_t *n; + size_t i; nofit = false; crushchange = crunch; @@ -4076,9 +4102,57 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) // First, let's see if anything will keep it from crushing. + + // Sal: This stupid function chain is required to fix polyobjects not being able to crush. + // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead + validcount++; + + for (i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->polyobj) + { + polyobj_t *po = sector->lines[i]->polyobj; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector + { + INT32 x, y; + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + { + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) + { + mobj_t *mo; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) + { + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect + + if (!P_MobjInsidePolyobj(po, mo)) + continue; + + if (!PIT_ChangeSector(mo, false)) + { + nofit = true; + return nofit; + } + } + } + } + } + } + } + if (sector->numattached) { - size_t i; sector_t *sec; for (i = 0; i < sector->numattached; i++) { @@ -4138,9 +4212,53 @@ boolean P_CheckSector(sector_t *sector, boolean crunch) } while (n); // repeat from scratch until all things left are marked valid // Nothing blocked us, so lets crush for real! + + // Sal: This stupid function chain is required to fix polyobjects not being able to crush. + // Monster Iestyn: don't use P_CheckSector actually just look for objects in the blockmap instead + validcount++; + + for (i = 0; i < sector->linecount; i++) + { + if (sector->lines[i]->polyobj) + { + polyobj_t *po = sector->lines[i]->polyobj; + if (po->validcount == validcount) + continue; // skip if already checked + if (!(po->flags & POF_SOLID)) + continue; + if (po->lines[0]->backsector == sector) // Make sure you're currently checking the control sector + { + INT32 x, y; + po->validcount = validcount; + + for (y = po->blockbox[BOXBOTTOM]; y <= po->blockbox[BOXTOP]; ++y) + { + for (x = po->blockbox[BOXLEFT]; x <= po->blockbox[BOXRIGHT]; ++x) + { + mobj_t *mo; + + if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) + continue; + + mo = blocklinks[y * bmapwidth + x]; + + for (; mo; mo = mo->bnext) + { + // Monster Iestyn: do we need to check if a mobj has already been checked? ...probably not I suspect + + if (!P_MobjInsidePolyobj(po, mo)) + continue; + + PIT_ChangeSector(mo, true); + return nofit; + } + } + } + } + } + } if (sector->numattached) { - size_t i; sector_t *sec; for (i = 0; i < sector->numattached; i++) { @@ -4679,17 +4797,12 @@ void P_MapEnd(void) } // P_FloorzAtPos -// Returns the floorz of the XYZ position // TODO: Need ceilingpos function too +// Returns the floorz of the XYZ position // Tails 05-26-2003 fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) { sector_t *sec = R_PointInSubsector(x, y)->sector; - fixed_t floorz = sec->floorheight; - -#ifdef ESLOPE - if (sec->f_slope) - floorz = P_GetZAt(sec->f_slope, x, y); -#endif + fixed_t floorz = P_GetSectorFloorZAt(sec, x, y); // Intercept the stupid 'fall through 3dfloors' bug Tails 03-17-2002 if (sec->ffloors) @@ -4706,15 +4819,8 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) if (!((rover->flags & FF_SOLID) || (rover->flags & FF_QUICKSAND)) || (rover->flags & FF_SWIMMABLE)) continue; - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; - -#ifdef ESLOPE - if (*rover->t_slope) - topheight = P_GetZAt(*rover->t_slope, x, y); - if (*rover->b_slope) - bottomheight = P_GetZAt(*rover->b_slope, x, y); -#endif + topheight = P_GetFFloorTopZAt (rover, x, y); + bottomheight = P_GetFFloorBottomZAt(rover, x, y); if (rover->flags & FF_QUICKSAND) { @@ -4736,50 +4842,64 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) return floorz; } -fixed_t -P_GetFOFTopZAt (ffloor_t *rover, fixed_t x, fixed_t y) +// P_CeilingZAtPos +// Returns the ceilingz of the XYZ position +fixed_t P_CeilingzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) { - (void)x; - (void)y; -#ifdef ESLOPE - if (*rover->t_slope) - return P_GetZAt(*rover->t_slope, x, y); - else -#endif - return *rover->topheight; -} + sector_t *sec = R_PointInSubsector(x, y)->sector; + fixed_t ceilingz = P_GetSectorCeilingZAt(sec, x, y); -fixed_t -P_GetFOFBottomZAt (ffloor_t *rover, fixed_t x, fixed_t y) -{ - (void)x; - (void)y; -#ifdef ESLOPE - if (*rover->b_slope) - return P_GetZAt(*rover->b_slope, x, y); - else -#endif - return *rover->bottomheight; + if (sec->ffloors) + { + ffloor_t *rover; + fixed_t delta1, delta2, thingtop = z + height; + + for (rover = sec->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + if (!(rover->flags & FF_EXISTS)) + continue; + + if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE))) + continue; + + topheight = P_GetFFloorTopZAt (rover, x, y); + bottomheight = P_GetFFloorBottomZAt(rover, x, y); + + if (rover->flags & FF_QUICKSAND) + { + if (thingtop > bottomheight && topheight > z) + { + if (ceilingz > z) + ceilingz = z; + } + continue; + } + + delta1 = z - (bottomheight + ((topheight - bottomheight)/2)); + delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); + if (bottomheight < ceilingz && abs(delta1) > abs(delta2)) + ceilingz = bottomheight; + } + } + + return ceilingz; } fixed_t P_VeryTopOfFOF (ffloor_t *rover) { -#ifdef ESLOPE if (*rover->t_slope) return (*rover->t_slope)->highz; else -#endif return *rover->topheight; } fixed_t P_VeryBottomOfFOF (ffloor_t *rover) { -#ifdef ESLOPE if (*rover->b_slope) return (*rover->b_slope)->lowz; else -#endif return *rover->bottomheight; } diff --git a/src/p_maputl.c b/src/p_maputl.c index 355c58db8..10115e4a1 100644 --- a/src/p_maputl.c +++ b/src/p_maputl.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,6 +18,7 @@ #include "p_local.h" #include "r_main.h" #include "r_data.h" +#include "r_textures.h" #include "p_maputl.h" #include "p_polyobj.h" #include "p_slopes.h" @@ -78,68 +79,37 @@ void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result) return; } -// -// P_ClosestPointOnLine3D -// Finds the closest point on a given line to the supplied point IN 3D!!! -// -void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result) +/// Similar to FV3_ClosestPointOnLine() except it actually works. +void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *Line, vector3_t *result) { - fixed_t startx = line->v1->x; - fixed_t starty = line->v1->y; - fixed_t startz = line->v1->z; - fixed_t dx = line->dx; - fixed_t dy = line->dy; - fixed_t dz = line->v2->z - line->v1->z; + const vector3_t* v1 = &Line[0]; + const vector3_t* v2 = &Line[1]; + vector3_t c, V, n; + fixed_t t, d; + FV3_SubEx(v2, v1, &V); + FV3_SubEx(p, v1, &c); - // Determine t (the length of the vector from �Line[0]� to �p�) - fixed_t cx, cy, cz; - fixed_t vx, vy, vz; - fixed_t magnitude; - fixed_t t; + d = R_PointToDist2(0, v2->z, R_PointToDist2(v2->x, v2->y, v1->x, v1->y), v1->z); + FV3_Copy(&n, &V); + FV3_Divide(&n, d); - //Sub (p, &Line[0], &c); - cx = x - startx; - cy = y - starty; - cz = z - startz; - - //Sub (&Line[1], &Line[0], &V); - vx = dx; - vy = dy; - vz = dz; - - //Normalize (&V, &V); - magnitude = R_PointToDist2(0, line->v2->z, R_PointToDist2(line->v2->x, line->v2->y, startx, starty), startz); - vx = FixedDiv(vx, magnitude); - vy = FixedDiv(vy, magnitude); - vz = FixedDiv(vz, magnitude); - - t = (FixedMul(vx, cx) + FixedMul(vy, cy) + FixedMul(vz, cz)); + t = FV3_Dot(&n, &c); // Set closest point to the end if it extends past -Red if (t <= 0) { - result->x = line->v1->x; - result->y = line->v1->y; - result->z = line->v1->z; + FV3_Copy(result, v1); return; } - else if (t >= magnitude) + else if (t >= d) { - result->x = line->v2->x; - result->y = line->v2->y; - result->z = line->v2->z; + FV3_Copy(result, v2); return; } - // Return the point between �Line[0]� and �Line[1]� - vx = FixedMul(vx, t); - vy = FixedMul(vy, t); - vz = FixedMul(vz, t); + FV3_Mul(&n, t); - //Add (&Line[0], &V, out); - result->x = startx + vx; - result->y = starty + vy; - result->z = startz + vz; + FV3_AddEx(v1, &n, result); return; } @@ -308,9 +278,12 @@ fixed_t P_InterceptVector(divline_t *v2, divline_t *v1) // OPTIMIZE: keep this precalculated // fixed_t opentop, openbottom, openrange, lowfloor, highceiling; -#ifdef ESLOPE pslope_t *opentopslope, *openbottomslope; -#endif +ffloor_t *openfloorrover, *openceilingrover; +fixed_t openceilingstep; +fixed_t openceilingdrop; +fixed_t openfloorstep; +fixed_t openfloordrop; // P_CameraLineOpening // P_LineOpening, but for camera @@ -335,53 +308,33 @@ void P_CameraLineOpening(line_t *linedef) // If you can see through it, why not move the camera through it too? if (front->camsec >= 0) { - frontfloor = sectors[front->camsec].floorheight; - frontceiling = sectors[front->camsec].ceilingheight; -#ifdef ESLOPE - if (sectors[front->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) - frontfloor = P_GetZAt(sectors[front->camsec].f_slope, camera[0].x, camera[0].y); - if (sectors[front->camsec].c_slope) - frontceiling = P_GetZAt(sectors[front->camsec].c_slope, camera[0].x, camera[0].y); -#endif - + // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) + frontfloor = P_GetSectorFloorZAt (§ors[front->camsec], camera[0].x, camera[0].y); + frontceiling = P_GetSectorCeilingZAt(§ors[front->camsec], camera[0].x, camera[0].y); } else if (front->heightsec >= 0) { - frontfloor = sectors[front->heightsec].floorheight; - frontceiling = sectors[front->heightsec].ceilingheight; -#ifdef ESLOPE - if (sectors[front->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) - frontfloor = P_GetZAt(sectors[front->heightsec].f_slope, camera[0].x, camera[0].y); - if (sectors[front->heightsec].c_slope) - frontceiling = P_GetZAt(sectors[front->heightsec].c_slope, camera[0].x, camera[0].y); -#endif + // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) + frontfloor = P_GetSectorFloorZAt (§ors[front->heightsec], camera[0].x, camera[0].y); + frontceiling = P_GetSectorCeilingZAt(§ors[front->heightsec], camera[0].x, camera[0].y); } else { - frontfloor = P_CameraGetFloorZ(mapcampointer, front, tmx, tmy, linedef); + frontfloor = P_CameraGetFloorZ (mapcampointer, front, tmx, tmy, linedef); frontceiling = P_CameraGetCeilingZ(mapcampointer, front, tmx, tmy, linedef); } + if (back->camsec >= 0) { - backfloor = sectors[back->camsec].floorheight; - backceiling = sectors[back->camsec].ceilingheight; -#ifdef ESLOPE - if (sectors[back->camsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) - frontfloor = P_GetZAt(sectors[back->camsec].f_slope, camera[0].x, camera[0].y); - if (sectors[back->camsec].c_slope) - frontceiling = P_GetZAt(sectors[back->camsec].c_slope, camera[0].x, camera[0].y); -#endif + // SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope) + backfloor = P_GetSectorFloorZAt (§ors[back->camsec], camera[0].x, camera[0].y); + backceiling = P_GetSectorCeilingZAt(§ors[back->camsec], camera[0].x, camera[0].y); } else if (back->heightsec >= 0) { - backfloor = sectors[back->heightsec].floorheight; - backceiling = sectors[back->heightsec].ceilingheight; -#ifdef ESLOPE - if (sectors[back->heightsec].f_slope) // SRB2CBTODO: ESLOPE (sectors[front->heightsec].f_slope) - frontfloor = P_GetZAt(sectors[back->heightsec].f_slope, camera[0].x, camera[0].y); - if (sectors[back->heightsec].c_slope) - frontceiling = P_GetZAt(sectors[back->heightsec].c_slope, camera[0].x, camera[0].y); -#endif + // SRB2CBTODO: ESLOPE (sectors[back->heightsec].f_slope) + backfloor = P_GetSectorFloorZAt (§ors[back->heightsec], camera[0].x, camera[0].y); + backceiling = P_GetSectorCeilingZAt(§ors[back->heightsec], camera[0].x, camera[0].y); } else { @@ -418,10 +371,6 @@ void P_CameraLineOpening(line_t *linedef) if (front->ffloors || back->ffloors) { ffloor_t *rover; - fixed_t highestceiling = highceiling; - fixed_t lowestceiling = opentop; - fixed_t highestfloor = openbottom; - fixed_t lowestfloor = lowfloor; fixed_t delta1, delta2; // Check for frontsector's fake floors @@ -437,15 +386,15 @@ void P_CameraLineOpening(line_t *linedef) delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (bottomheight < lowestceiling && delta1 >= delta2) - lowestceiling = bottomheight; - else if (bottomheight < highestceiling && delta1 >= delta2) - highestceiling = bottomheight; + if (bottomheight < opentop && delta1 >= delta2) + opentop = bottomheight; + else if (bottomheight < highceiling && delta1 >= delta2) + highceiling = bottomheight; - if (topheight > highestfloor && delta1 < delta2) - highestfloor = topheight; - else if (topheight > lowestfloor && delta1 < delta2) - lowestfloor = topheight; + if (topheight > openbottom && delta1 < delta2) + openbottom = topheight; + else if (topheight > lowfloor && delta1 < delta2) + lowfloor = topheight; } // Check for backsectors fake floors @@ -461,28 +410,16 @@ void P_CameraLineOpening(line_t *linedef) delta1 = abs(mapcampointer->z - (bottomheight + ((topheight - bottomheight)/2))); delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - if (bottomheight < lowestceiling && delta1 >= delta2) - lowestceiling = bottomheight; - else if (bottomheight < highestceiling && delta1 >= delta2) - highestceiling = bottomheight; + if (bottomheight < opentop && delta1 >= delta2) + opentop = bottomheight; + else if (bottomheight < highceiling && delta1 >= delta2) + highceiling = bottomheight; - if (topheight > highestfloor && delta1 < delta2) - highestfloor = topheight; - else if (topheight > lowestfloor && delta1 < delta2) - lowestfloor = topheight; + if (topheight > openbottom && delta1 < delta2) + openbottom = topheight; + else if (topheight > lowfloor && delta1 < delta2) + lowfloor = topheight; } - - if (highestceiling < highceiling) - highceiling = highestceiling; - - if (highestfloor > openbottom) - openbottom = highestfloor; - - if (lowestceiling < opentop) - opentop = lowestceiling; - - if (lowestfloor > lowfloor) - lowfloor = lowestfloor; } openrange = opentop - openbottom; return; @@ -491,7 +428,18 @@ void P_CameraLineOpening(line_t *linedef) void P_LineOpening(line_t *linedef, mobj_t *mobj) { + enum { FRONT, BACK }; + sector_t *front, *back; + fixed_t thingtop = 0; + vertex_t cross; + + /* these init to shut compiler up */ + fixed_t topedge[2] = {0}; + fixed_t botedge[2] = {0}; + + int hi = 0; + int lo = 0; if (linedef->sidenum[1] == 0xffff) { @@ -500,15 +448,15 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) return; } + P_ClosestPointOnLine(tmx, tmy, linedef, &cross); + // Treat polyobjects kind of like 3D Floors -#ifdef POLYOBJECTS if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { front = linedef->frontsector; back = linedef->frontsector; } else -#endif { front = linedef->frontsector; back = linedef->backsector; @@ -517,54 +465,71 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) I_Assert(front != NULL); I_Assert(back != NULL); + if (mobj) + { + thingtop = mobj->z + mobj->height; + } + + openfloorrover = openceilingrover = NULL; + if (linedef->polyobj) + { + // set these defaults so that polyobjects don't interfere with collision above or below them + opentop = INT32_MAX; + openbottom = INT32_MIN; + highceiling = INT32_MIN; + lowfloor = INT32_MAX; + opentopslope = openbottomslope = NULL; + openceilingstep = 0; + openceilingdrop = 0; + openfloorstep = 0; + openfloordrop = 0; + } + else { // Set open and high/low values here - fixed_t frontheight, backheight; + fixed_t height[2]; + const sector_t * sector[2] = { front, back }; - frontheight = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); - backheight = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); + height[FRONT] = P_GetCeilingZ(mobj, front, tmx, tmy, linedef); + height[BACK] = P_GetCeilingZ(mobj, back, tmx, tmy, linedef); - if (frontheight < backheight) + hi = ( height[0] < height[1] ); + lo = ! hi; + + opentop = height[lo]; + highceiling = height[hi]; + opentopslope = sector[lo]->c_slope; + + if (mobj) { - opentop = frontheight; - highceiling = backheight; -#ifdef ESLOPE - opentopslope = front->c_slope; -#endif - } - else - { - opentop = backheight; - highceiling = frontheight; -#ifdef ESLOPE - opentopslope = back->c_slope; -#endif + topedge[FRONT] = P_GetSectorCeilingZAt(front, cross.x, cross.y); + topedge[BACK] = P_GetSectorCeilingZAt(back, cross.x, cross.y); + + openceilingstep = ( thingtop - topedge[lo] ); + openceilingdrop = ( topedge[hi] - topedge[lo] ); } - frontheight = P_GetFloorZ(mobj, front, tmx, tmy, linedef); - backheight = P_GetFloorZ(mobj, back, tmx, tmy, linedef); + height[FRONT] = P_GetFloorZ(mobj, front, tmx, tmy, linedef); + height[BACK] = P_GetFloorZ(mobj, back, tmx, tmy, linedef); - if (frontheight > backheight) + hi = ( height[0] < height[1] ); + lo = ! hi; + + openbottom = height[hi]; + lowfloor = height[lo]; + openbottomslope = sector[hi]->f_slope; + + if (mobj) { - openbottom = frontheight; - lowfloor = backheight; -#ifdef ESLOPE - openbottomslope = front->f_slope; -#endif - } - else - { - openbottom = backheight; - lowfloor = frontheight; -#ifdef ESLOPE - openbottomslope = back->f_slope; -#endif + botedge[FRONT] = P_GetSectorFloorZAt(front, cross.x, cross.y); + botedge[BACK] = P_GetSectorFloorZAt(back, cross.x, cross.y); + + openfloorstep = ( botedge[hi] - mobj->z ); + openfloordrop = ( botedge[hi] - botedge[lo] ); } } if (mobj) { - fixed_t thingtop = mobj->z + mobj->height; - // Check for collision with front side's midtexture if Effect 4 is set if (linedef->flags & ML_EFFECT4 && !linedef->polyobj // don't do anything for polyobjects! ...for now @@ -579,7 +544,7 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) texheight = textures[texnum]->height << FRACBITS; // Set texbottom and textop to the Z coordinates of the texture's boundaries -#if 0 // #ifdef POLYOBJECTS +#if 0 // don't remove this code unless solid midtextures // on non-solid polyobjects should NEVER happen in the future if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) { @@ -615,167 +580,213 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj) if (delta1 > delta2) { // Below if (opentop > texbottom) + { + topedge[lo] -= ( opentop - texbottom ); + opentop = texbottom; + openceilingstep = ( thingtop - topedge[lo] ); + openceilingdrop = ( topedge[hi] - topedge[lo] ); + } } else { // Above if (openbottom < textop) + { + botedge[hi] += ( textop - openbottom ); + openbottom = textop; + openfloorstep = ( botedge[hi] - mobj->z ); + openfloordrop = ( botedge[hi] - botedge[lo] ); + } } } } - - // Check for fake floors in the sector. - if (front->ffloors || back->ffloors -#ifdef POLYOBJECTS - || linedef->polyobj -#endif - ) + if (linedef->polyobj) { - ffloor_t *rover; - - fixed_t highestceiling = highceiling; - fixed_t lowestceiling = opentop; - fixed_t highestfloor = openbottom; - fixed_t lowestfloor = lowfloor; - fixed_t delta1, delta2; -#ifdef ESLOPE - pslope_t *ceilingslope = opentopslope; - pslope_t *floorslope = openbottomslope; -#endif - - // Check for frontsector's fake floors - for (rover = front->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight; - if (!(rover->flags & FF_EXISTS)) - continue; - - if (mobj->player && P_CheckSolidLava(mobj, rover)) - ; - else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) - || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) - continue; - - topheight = P_GetFOFTopZ(mobj, front, rover, tmx, tmy, linedef); - bottomheight = P_GetFOFBottomZ(mobj, front, rover, tmx, tmy, linedef); - - delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); - delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - - if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF - { - if (bottomheight < lowestceiling) { - lowestceiling = bottomheight; -#ifdef ESLOPE - ceilingslope = *rover->b_slope; -#endif - } - else if (bottomheight < highestceiling) - highestceiling = bottomheight; - } - - if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF - { - if (topheight > highestfloor) { - highestfloor = topheight; -#ifdef ESLOPE - floorslope = *rover->t_slope; -#endif - } - else if (topheight > lowestfloor) - lowestfloor = topheight; - } - } - - // Check for backsectors fake floors - for (rover = back->ffloors; rover; rover = rover->next) - { - fixed_t topheight, bottomheight; - if (!(rover->flags & FF_EXISTS)) - continue; - - if (mobj->player && P_CheckSolidLava(mobj, rover)) - ; - else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) - || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) - continue; - - topheight = P_GetFOFTopZ(mobj, back, rover, tmx, tmy, linedef); - bottomheight = P_GetFOFBottomZ(mobj, back, rover, tmx, tmy, linedef); - - delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); - delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); - - if (delta1 >= delta2 && !(rover->flags & FF_PLATFORM)) // thing is below FOF - { - if (bottomheight < lowestceiling) { - lowestceiling = bottomheight; -#ifdef ESLOPE - ceilingslope = *rover->b_slope; -#endif - } - else if (bottomheight < highestceiling) - highestceiling = bottomheight; - } - - if (delta1 < delta2 && !(rover->flags & FF_REVERSEPLATFORM)) // thing is above FOF - { - if (topheight > highestfloor) { - highestfloor = topheight; -#ifdef ESLOPE - floorslope = *rover->t_slope; -#endif - } - else if (topheight > lowestfloor) - lowestfloor = topheight; - } - } - -#ifdef POLYOBJECTS // Treat polyobj's backsector like a 3D Floor - if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) + if (linedef->polyobj->flags & POF_TESTHEIGHT) { const sector_t *polysec = linedef->backsector; + fixed_t polytop, polybottom; + fixed_t delta1, delta2; - delta1 = abs(mobj->z - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2))); - delta2 = abs(thingtop - (polysec->floorheight + ((polysec->ceilingheight - polysec->floorheight)/2))); - if (polysec->floorheight < lowestceiling && delta1 >= delta2) { - lowestceiling = polysec->floorheight; -#ifdef ESLOPE - ceilingslope = NULL; -#endif + if (linedef->polyobj->flags & POF_CLIPPLANES) + { + polytop = polysec->ceilingheight; + polybottom = polysec->floorheight; } - else if (polysec->floorheight < highestceiling && delta1 >= delta2) - highestceiling = polysec->floorheight; - - if (polysec->ceilingheight > highestfloor && delta1 < delta2) { - highestfloor = polysec->ceilingheight; -#ifdef ESLOPE - floorslope = NULL; -#endif + else + { + polytop = INT32_MAX; + polybottom = INT32_MIN; } - else if (polysec->ceilingheight > lowestfloor && delta1 < delta2) - lowestfloor = polysec->ceilingheight; - } -#endif - if (highestceiling < highceiling) - highceiling = highestceiling; - if (highestfloor > openbottom) { - openbottom = highestfloor; -#ifdef ESLOPE - openbottomslope = floorslope; -#endif - } + delta1 = abs(mobj->z - (polybottom + ((polytop - polybottom)/2))); + delta2 = abs(thingtop - (polybottom + ((polytop - polybottom)/2))); - if (lowestceiling < opentop) { - opentop = lowestceiling; -#ifdef ESLOPE - opentopslope = ceilingslope; -#endif - } + if (polybottom < opentop && delta1 >= delta2) + { + opentop = polybottom; + } + else if (polybottom < highceiling && delta1 >= delta2) + { + highceiling = polybottom; + } - if (lowestfloor > lowfloor) - lowfloor = lowestfloor; + if (polytop > openbottom && delta1 < delta2) + { + openbottom = polytop; + } + else if (polytop > lowfloor && delta1 < delta2) + { + lowfloor = polytop; + } + } + // otherwise don't do anything special, pretend there's nothing else there + } + else + { + // Check for fake floors in the sector. + if (front->ffloors || back->ffloors) + { + ffloor_t *rover; + fixed_t delta1, delta2; + + /* yuck */ + struct + { + fixed_t top; + fixed_t bottom; + ffloor_t * ceilingrover; + ffloor_t * floorrover; + } open[2] = { + { INT32_MAX, INT32_MIN, NULL, NULL }, + { INT32_MAX, INT32_MIN, NULL, NULL }, + }; + + const fixed_t oldopentop = opentop; + const fixed_t oldopenbottom = openbottom; + + // Check for frontsector's fake floors + for (rover = front->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + if (!(rover->flags & FF_EXISTS)) + continue; + + if (mobj->player && P_CheckSolidLava(rover)) + ; + else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) + || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) + continue; + + topheight = P_GetFOFTopZ(mobj, front, rover, tmx, tmy, linedef); + bottomheight = P_GetFOFBottomZ(mobj, front, rover, tmx, tmy, linedef); + + delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); + delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); + + if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF + { + if (bottomheight < open[FRONT].top) { + open[FRONT].top = bottomheight; + opentopslope = *rover->b_slope; + open[FRONT].ceilingrover = rover; + } + else if (bottomheight < highceiling) + highceiling = bottomheight; + } + + if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF + { + if (topheight > open[FRONT].bottom) { + open[FRONT].bottom = topheight; + openbottomslope = *rover->t_slope; + open[FRONT].floorrover = rover; + } + else if (topheight > lowfloor) + lowfloor = topheight; + } + } + + // Check for backsectors fake floors + for (rover = back->ffloors; rover; rover = rover->next) + { + fixed_t topheight, bottomheight; + if (!(rover->flags & FF_EXISTS)) + continue; + + if (mobj->player && P_CheckSolidLava(rover)) + ; + else if (!((rover->flags & FF_BLOCKPLAYER && mobj->player) + || (rover->flags & FF_BLOCKOTHERS && !mobj->player))) + continue; + + topheight = P_GetFOFTopZ(mobj, back, rover, tmx, tmy, linedef); + bottomheight = P_GetFOFBottomZ(mobj, back, rover, tmx, tmy, linedef); + + delta1 = abs(mobj->z - (bottomheight + ((topheight - bottomheight)/2))); + delta2 = abs(thingtop - (bottomheight + ((topheight - bottomheight)/2))); + + if (delta1 >= delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_PLATFORM) // thing is below FOF + { + if (bottomheight < open[BACK].top) { + open[BACK].top = bottomheight; + opentopslope = *rover->b_slope; + open[BACK].ceilingrover = rover; + } + else if (bottomheight < highceiling) + highceiling = bottomheight; + } + + if (delta1 < delta2 && (rover->flags & FF_INTANGIBLEFLATS) != FF_REVERSEPLATFORM) // thing is above FOF + { + if (topheight > open[BACK].bottom) { + open[BACK].bottom = topheight; + openbottomslope = *rover->t_slope; + open[BACK].floorrover = rover; + } + else if (topheight > lowfloor) + lowfloor = topheight; + } + } + + lo = ( open[0].top > open[1].top ); + + if (open[lo].top <= oldopentop) + { + hi = ! lo; + + topedge[lo] = P_GetFFloorBottomZAt(open[lo].ceilingrover, cross.x, cross.y); + + if (open[hi].top < oldopentop) + { + topedge[hi] = P_GetFFloorBottomZAt(open[hi].ceilingrover, cross.x, cross.y); + } + + opentop = open[lo].top; + openceilingrover = open[lo].ceilingrover; + openceilingstep = ( thingtop - topedge[lo] ); + openceilingdrop = ( topedge[hi] - topedge[lo] ); + } + + hi = ( open[0].bottom < open[1].bottom ); + + if (open[hi].bottom >= oldopenbottom) + { + lo = ! hi; + + botedge[hi] = P_GetFFloorTopZAt(open[hi].floorrover, cross.x, cross.y); + + if (open[lo].bottom > oldopenbottom) + { + botedge[lo] = P_GetFFloorTopZAt(open[lo].floorrover, cross.x, cross.y); + } + + openbottom = open[hi].bottom; + openfloorrover = open[hi].floorrover; + openfloorstep = ( botedge[hi] - mobj->z ); + openfloordrop = ( botedge[hi] - botedge[lo] ); + } + } } } @@ -1023,9 +1034,7 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *)) { INT32 offset; const INT32 *list; // Big blockmap -#ifdef POLYOBJECTS polymaplink_t *plink; // haleyjd 02/22/06 -#endif line_t *ld; if (x < 0 || y < 0 || x >= bmapwidth || y >= bmapheight) @@ -1033,7 +1042,6 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *)) offset = y*bmapwidth + x; -#ifdef POLYOBJECTS // haleyjd 02/22/06: consider polyobject lines plink = polyblocklinks[offset]; @@ -1057,7 +1065,6 @@ boolean P_BlockLinesIterator(INT32 x, INT32 y, boolean (*func)(line_t *)) } plink = (polymaplink_t *)(plink->link.next); } -#endif offset = *(blockmap + offset); // offset = blockmap[y*bmapwidth+x]; @@ -1093,7 +1100,10 @@ boolean P_BlockThingsIterator(INT32 x, INT32 y, boolean (*func)(mobj_t *)) { P_SetTarget(&bnext, mobj->bnext); // We want to note our reference to bnext here incase it is MF_NOTHINK and gets removed! if (!func(mobj)) + { + P_SetTarget(&bnext, NULL); return false; + } if (P_MobjWasRemoved(tmthing) // func just popped our tmthing, cannot continue. || (bnext && P_MobjWasRemoved(bnext))) // func just broke blockmap chain, cannot continue. { diff --git a/src/p_maputl.h b/src/p_maputl.h index c8b628780..9349d0e53 100644 --- a/src/p_maputl.h +++ b/src/p_maputl.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -43,7 +43,7 @@ boolean P_PathTraverse(fixed_t px1, fixed_t py1, fixed_t px2, fixed_t py2, FUNCMATH fixed_t P_AproxDistance(fixed_t dx, fixed_t dy); void P_ClosestPointOnLine(fixed_t x, fixed_t y, line_t *line, vertex_t *result); -void P_ClosestPointOnLine3D(fixed_t x, fixed_t y, fixed_t z, line_t *line, vertex_t *result); +void P_ClosestPointOnLine3D(const vector3_t *p, const vector3_t *line, vector3_t *result); INT32 P_PointOnLineSide(fixed_t x, fixed_t y, line_t *line); void P_MakeDivline(line_t *li, divline_t *dl); void P_CameraLineOpening(line_t *plinedef); @@ -56,9 +56,12 @@ boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y); void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_t momy); extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling; -#ifdef ESLOPE extern pslope_t *opentopslope, *openbottomslope; -#endif +extern ffloor_t *openfloorrover, *openceilingrover; +extern fixed_t openceilingstep; +extern fixed_t openceilingdrop; +extern fixed_t openfloorstep; +extern fixed_t openfloordrop; void P_LineOpening(line_t *plinedef, mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index 94ed691fd..1280cbce5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,7 +19,7 @@ #include "p_local.h" #include "p_setup.h" #include "r_main.h" -#include "r_things.h" +#include "r_skins.h" #include "r_sky.h" #include "r_splats.h" #include "s_sound.h" @@ -30,21 +30,22 @@ #include "info.h" #include "i_video.h" #include "lua_hook.h" -#include "k_bot.h" -#ifdef ESLOPE #include "p_slopes.h" -#endif +#include "f_finale.h" +#include "m_cond.h" +// SRB2kart #include "k_kart.h" #include "k_battle.h" #include "k_color.h" #include "k_respawn.h" +#include "k_bot.h" + +static CV_PossibleValue_t CV_BobSpeed[] = {{0, "MIN"}, {4*FRACUNIT, "MAX"}, {0, NULL}}; +consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpeed, NULL); -// protos. -//static CV_PossibleValue_t viewheight_cons_t[] = {{16, "MIN"}, {56, "MAX"}, {0, NULL}}; -//consvar_t cv_viewheight = {"viewheight", VIEWHEIGHTS, 0, viewheight_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; #ifdef WALLSPLATS -consvar_t cv_splats = {"splats", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_splats = CVAR_INIT ("splats", "On", CV_SAVE, CV_OnOff, NULL); #endif actioncache_t actioncachehead; @@ -67,9 +68,7 @@ void P_RunCachedActions(void) { var1 = states[ac->statenum].var1; var2 = states[ac->statenum].var2; -#ifdef HAVE_BLUA astate = &states[ac->statenum]; -#endif if (ac->mobj && !P_MobjWasRemoved(ac->mobj)) // just in case... states[ac->statenum].action.acp1(ac->mobj); next = ac->next; @@ -93,10 +92,14 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum) // FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *st) { + INT32 animlength = (mobj->sprite == SPR_PLAY && mobj->skin) + ? (INT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes) - 1 + : st->var1; + if (!(st->frame & FF_ANIMATE)) return; - if (st->var1 <= 0 || st->var2 == 0) + if (animlength <= 0 || st->var2 == 0) { mobj->frame &= ~FF_ANIMATE; return; // Crash/stupidity prevention @@ -110,11 +113,11 @@ FUNCINLINE static ATTRINLINE void P_SetupStateAnimation(mobj_t *mobj, state_t *s if (!leveltime) return; mobj->anim_duration -= (leveltime + 2) % st->var2; // Duration synced to timer - mobj->frame += ((leveltime + 2) / st->var2) % (st->var1 + 1); // Frame synced to timer (duration taken into account) + mobj->frame += ((leveltime + 2) / st->var2) % (animlength + 1); // Frame synced to timer (duration taken into account) } else if (st->frame & FF_RANDOMANIM) { - mobj->frame += P_RandomKey(st->var1 + 1); // Random starting frame + mobj->frame += P_RandomKey(animlength + 1); // Random starting frame mobj->anim_duration -= P_RandomKey(st->var2); // Random duration for first frame } } @@ -130,11 +133,20 @@ FUNCINLINE static ATTRINLINE void P_CycleStateAnimation(mobj_t *mobj) mobj->anim_duration = (UINT16)mobj->state->var2; - // compare the current sprite frame to the one we started from - // if more than var1 away from it, swap back to the original - // else just advance by one - if (((++mobj->frame) & FF_FRAMEMASK) - (mobj->state->frame & FF_FRAMEMASK) > (UINT32)mobj->state->var1) - mobj->frame = (mobj->state->frame & FF_FRAMEMASK) | (mobj->frame & ~FF_FRAMEMASK); + if (mobj->sprite != SPR_PLAY) + { + // compare the current sprite frame to the one we started from + // if more than var1 away from it, swap back to the original + // else just advance by one + if (((++mobj->frame) & FF_FRAMEMASK) - (mobj->state->frame & FF_FRAMEMASK) > (UINT32)mobj->state->var1) + mobj->frame = (mobj->state->frame & FF_FRAMEMASK) | (mobj->frame & ~FF_FRAMEMASK); + + return; + } + + // sprite2 version of above + if (mobj->skin && (((++mobj->frame) & FF_FRAMEMASK) >= (UINT32)(((skin_t *)mobj->skin)->sprites[mobj->sprite2].numframes))) + mobj->frame &= ~FF_FRAMEMASK; } // @@ -202,31 +214,41 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) I_Error("P_SetPlayerMobjState used for non-player mobj. Use P_SetMobjState instead!\n(Mobj type: %d, State: %d)", mobj->type, state); #endif - // You were in pain state after taking a hit, and you're moving out of pain state now? - if (mobj->state == &states[mobj->info->painstate] && player->powers[pw_flashing] == K_GetKartFlashing(player) && state != mobj->info->painstate) - { - // Start flashing, since you've landed. - player->powers[pw_flashing] = K_GetKartFlashing(player)-1; - //P_DoPityCheck(player); - } - // Set animation state // The pflags version of this was just as convoluted. - // Rewriten for SRB2kart ... though I don't know what this is. - if ((state >= S_KART_STILL1 && state <= S_KART_STILL2_R) || state == S_KART_SQUISH || state == S_KART_SPIN) - player->panim = PA_IDLE; - else if (state >= S_KART_SLOW1 && state <= S_KART_SLOW2_R) - player->panim = PA_WALK; - else if (state >= S_KART_FAST1 && state <= S_KART_DRIFT2_R) - player->panim = PA_RUN; - //else if (state >= S_PLAY_ATK1 && state <= S_PLAY_ATK4) - // player->panim = PA_ROLL; - //else if (state >= S_PLAY_FALL1 && state <= S_PLAY_FALL2) - // player->panim = PA_FALL; - //else if (state >= S_PLAY_ABL1 && state <= S_PLAY_ABL2) - // player->panim = PA_ABILITY; - else - player->panim = PA_ETC; + switch(state) + { + case S_KART_STILL: + case S_KART_STILL_L: + case S_KART_STILL_R: + player->panim = PA_IDLE; + break; + case S_KART_SLOW: + case S_KART_SLOW_L: + case S_KART_SLOW_R: + player->panim = PA_WALK; + break; + case S_KART_FAST: + case S_KART_FAST_L: + case S_KART_FAST_R: + player->panim = PA_RUN; + break; + case S_KART_DRIFT_L: + case S_KART_DRIFT_L_OUT: + case S_KART_DRIFT_L_IN: + case S_KART_DRIFT_R: + case S_KART_DRIFT_R_OUT: + case S_KART_DRIFT_R_IN: + player->panim = PA_DASH; + break; + case S_KART_SPINOUT: + case S_KART_SQUISH: + player->panim = PA_PAIN; + break; + default: + player->panim = PA_ETC; + break; + } if (recursion++) // if recursion detected, memset(seenstate = tempstate, 0, sizeof tempstate); // clear state table @@ -245,8 +267,68 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) st = &states[state]; mobj->state = st; mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; + + // Player animations + if (st->sprite == SPR_PLAY) + { + skin_t *skin = ((skin_t *)mobj->skin); + UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; + UINT8 numframes, spr2; + + if (skin) + { + spr2 = P_GetSkinSprite2(skin, ((player->powers[pw_super] ? FF_SPR2SUPER : 0)|st->frame) & FF_FRAMEMASK, mobj->player); + numframes = skin->sprites[spr2].numframes; + } + else + { + spr2 = 0; + frame = 0; + numframes = 0; + } + + if (mobj->sprite != SPR_PLAY) + { + mobj->sprite = SPR_PLAY; + frame = 0; + } + else if (mobj->sprite2 != spr2) + { + if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) + frame = numframes/2; + else + frame = 0; + } + + if (frame >= numframes) + { + if (st->frame & FF_SPR2ENDSTATE) // no frame advancement + { + if (st->var1 == mobj->state-states) + frame--; + else + { + if (mobj->frame & FF_FRAMEMASK) + mobj->frame--; + return P_SetPlayerMobjState(mobj, st->var1); + } + } + else + frame = 0; + } + + mobj->sprite2 = spr2; + mobj->frame = frame|(st->frame&~FF_FRAMEMASK); + if (P_PlayerFullbright(player)) + mobj->frame |= FF_FULLBRIGHT; + } + // Regular sprites + else + { + mobj->sprite = st->sprite; + mobj->frame = st->frame; + } + P_SetupStateAnimation(mobj, st); // Modified handling. @@ -256,9 +338,7 @@ boolean P_SetPlayerMobjState(mobj_t *mobj, statenum_t state) { var1 = st->var1; var2 = st->var2; -#ifdef HAVE_BLUA astate = st; -#endif st->action.acp1(mobj); // woah. a player was removed by an action. @@ -313,8 +393,66 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) st = &states[state]; mobj->state = st; mobj->tics = st->tics; - mobj->sprite = st->sprite; - mobj->frame = st->frame; + + // Player animations + if (st->sprite == SPR_PLAY) + { + skin_t *skin = ((skin_t *)mobj->skin); + UINT16 frame = (mobj->frame & FF_FRAMEMASK)+1; + UINT8 numframes, spr2; + + if (skin) + { + spr2 = P_GetSkinSprite2(skin, st->frame & FF_FRAMEMASK, mobj->player); + numframes = skin->sprites[spr2].numframes; + } + else + { + spr2 = 0; + frame = 0; + numframes = 0; + } + + if (mobj->sprite != SPR_PLAY) + { + mobj->sprite = SPR_PLAY; + frame = 0; + } + else if (mobj->sprite2 != spr2) + { + if ((st->frame & FF_SPR2MIDSTART) && numframes && P_RandomChance(FRACUNIT/2)) + frame = numframes/2; + else + frame = 0; + } + + if (frame >= numframes) + { + if (st->frame & FF_SPR2ENDSTATE) // no frame advancement + { + if (st->var1 == mobj->state-states) + frame--; + else + { + if (mobj->frame & FF_FRAMEMASK) + mobj->frame--; + return P_SetMobjState(mobj, st->var1); + } + } + else + frame = 0; + } + + mobj->sprite2 = spr2; + mobj->frame = frame|(st->frame&~FF_FRAMEMASK); + } + // Regular sprites + else + { + mobj->sprite = st->sprite; + mobj->frame = st->frame; + } + P_SetupStateAnimation(mobj, st); // Modified handling. @@ -324,9 +462,7 @@ boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { var1 = st->var1; var2 = st->var2; -#ifdef HAVE_BLUA astate = st; -#endif st->action.acp1(mobj); if (P_MobjWasRemoved(mobj)) return false; @@ -405,214 +541,11 @@ SINT8 P_MobjFlip(mobj_t *mobj) return 1; } -// -// P_WeaponOrPanel -// -// Returns true if weapon ring/panel; otherwise returns false -// -boolean P_WeaponOrPanel(mobjtype_t type) -{ - if (type == MT_BOUNCERING - || type == MT_AUTOMATICRING - || type == MT_INFINITYRING - || type == MT_RAILRING - || type == MT_EXPLOSIONRING - || type == MT_SCATTERRING - || type == MT_GRENADERING - || type == MT_BOUNCEPICKUP - || type == MT_RAILPICKUP - || type == MT_AUTOPICKUP - || type == MT_EXPLODEPICKUP - || type == MT_SCATTERPICKUP - || type == MT_GRENADEPICKUP) - return true; - - return false; -} - -// -// P_EmeraldManager -// -// Power Stone emerald management -// -/*void P_EmeraldManager(void) -{ - thinker_t *think; - mobj_t *mo; - INT32 i,j; - INT32 numtospawn; - INT32 emeraldsspawned = 0; - - boolean hasemerald[MAXHUNTEMERALDS]; - INT32 numwithemerald = 0; - - // record empty spawn points - mobj_t *spawnpoints[MAXHUNTEMERALDS]; - INT32 numspawnpoints = 0; - - for (i = 0; i < MAXHUNTEMERALDS; i++) - { - hasemerald[i] = false; - spawnpoints[i] = NULL; - } - - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - - mo = (mobj_t *)think; - - if (mo->type == MT_EMERALDSPAWN) - { - if (mo->threshold || mo->target) // Either has the emerald spawned or is spawning - { - numwithemerald++; - emeraldsspawned |= mobjinfo[mo->reactiontime].speed; - } - else if (numspawnpoints < MAXHUNTEMERALDS) - spawnpoints[numspawnpoints++] = mo; // empty spawn points - } - else if (mo->type == MT_FLINGEMERALD) - { - numwithemerald++; - emeraldsspawned |= mo->threshold; - } - } - - if (numspawnpoints == 0) - return; - - // But wait! We need to check all the players too, to see if anyone has some of the emeralds. - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].powers[pw_emeralds] & EMERALD1) - { - numwithemerald++; - emeraldsspawned |= EMERALD1; - } - if (players[i].powers[pw_emeralds] & EMERALD2) - { - numwithemerald++; - emeraldsspawned |= EMERALD2; - } - if (players[i].powers[pw_emeralds] & EMERALD3) - { - numwithemerald++; - emeraldsspawned |= EMERALD3; - } - if (players[i].powers[pw_emeralds] & EMERALD4) - { - numwithemerald++; - emeraldsspawned |= EMERALD4; - } - if (players[i].powers[pw_emeralds] & EMERALD5) - { - numwithemerald++; - emeraldsspawned |= EMERALD5; - } - if (players[i].powers[pw_emeralds] & EMERALD6) - { - numwithemerald++; - emeraldsspawned |= EMERALD6; - } - if (players[i].powers[pw_emeralds] & EMERALD7) - { - numwithemerald++; - emeraldsspawned |= EMERALD7; - } - } - - // All emeralds spawned, no worries - if (numwithemerald >= 7) - return; - - // Set up spawning for the emeralds - numtospawn = 7 - numwithemerald; - -#ifdef PARANOIA - if (numtospawn <= 0) // ??? - I_Error("P_EmeraldManager: numtospawn is %d!\n", numtospawn); -#endif - - for (i = 0, j = 0; i < numtospawn; i++) - { - INT32 tries = 0; - while (true) - { - tries++; - - if (tries > 50) - break; - - j = P_RandomKey(numspawnpoints); - - if (hasemerald[j]) - continue; - - hasemerald[j] = true; - - if (!(emeraldsspawned & EMERALD1)) - { - spawnpoints[j]->reactiontime = MT_EMERALD1; - emeraldsspawned |= EMERALD1; - } - else if (!(emeraldsspawned & EMERALD2)) - { - spawnpoints[j]->reactiontime = MT_EMERALD2; - emeraldsspawned |= EMERALD2; - } - else if (!(emeraldsspawned & EMERALD3)) - { - spawnpoints[j]->reactiontime = MT_EMERALD3; - emeraldsspawned |= EMERALD3; - } - else if (!(emeraldsspawned & EMERALD4)) - { - spawnpoints[j]->reactiontime = MT_EMERALD4; - emeraldsspawned |= EMERALD4; - } - else if (!(emeraldsspawned & EMERALD5)) - { - spawnpoints[j]->reactiontime = MT_EMERALD5; - emeraldsspawned |= EMERALD5; - } - else if (!(emeraldsspawned & EMERALD6)) - { - spawnpoints[j]->reactiontime = MT_EMERALD6; - emeraldsspawned |= EMERALD6; - } - else if (!(emeraldsspawned & EMERALD7)) - { - spawnpoints[j]->reactiontime = MT_EMERALD7; - emeraldsspawned |= EMERALD7; - } - else - break; - - if (leveltime < TICRATE) // Start of map - spawnpoints[j]->threshold = 60*TICRATE + P_RandomByte() * (TICRATE/5); - else - spawnpoints[j]->threshold = P_RandomByte() * (TICRATE/5); - - break; - } - } -}*/ - // // P_ExplodeMissile // void P_ExplodeMissile(mobj_t *mo) { - mobj_t *explodemo; - I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -621,39 +554,6 @@ void P_ExplodeMissile(mobj_t *mo) if (mo->flags & MF_NOCLIPTHING) return; - if (mo->type == MT_DETON) - { - P_RadiusAttack(mo, mo, 96*FRACUNIT); - - explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - P_SetScale(explodemo, mo->scale); - explodemo->destscale = mo->destscale; - explodemo->momx += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); - explodemo->momy += (P_RandomByte() % 32) * FixedMul(FRACUNIT/8, explodemo->scale); - S_StartSound(explodemo, sfx_pop); - explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - P_SetScale(explodemo, mo->scale); - explodemo->destscale = mo->destscale; - explodemo->momx += (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); - explodemo->momy -= (P_RandomByte() % 64) * FixedMul(FRACUNIT/8, explodemo->scale); - S_StartSound(explodemo, sfx_dmpain); - explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - P_SetScale(explodemo, mo->scale); - explodemo->destscale = mo->destscale; - explodemo->momx -= (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); - explodemo->momy += (P_RandomByte() % 128) * FixedMul(FRACUNIT/8, explodemo->scale); - S_StartSound(explodemo, sfx_pop); - explodemo = P_SpawnMobj(mo->x, mo->y, mo->z, MT_EXPLODE); - P_SetScale(explodemo, mo->scale); - explodemo->destscale = mo->destscale; - explodemo->momx -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); - explodemo->momy -= (P_RandomByte() % 96) * FixedMul(FRACUNIT/8, explodemo->scale); - S_StartSound(explodemo, sfx_cybdth); - - // Hack: Release an animal. - P_DamageMobj(mo, NULL, NULL, 10000); - } - mo->flags &= ~MF_MISSILE; mo->flags |= MF_NOGRAVITY; // Dead missiles don't need to sink anymore. @@ -678,15 +578,8 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover) || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player))) return false; - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; - -#ifdef ESLOPE - if (*rover->t_slope) - topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y); - if (*rover->b_slope) - bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y); -#endif + topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y); + bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); if (mobj->z > topheight) return false; @@ -697,7 +590,6 @@ boolean P_InsideANonSolidFFloor(mobj_t *mobj, ffloor_t *rover) return true; } -#ifdef ESLOPE // P_GetFloorZ (and its ceiling counterpart) // Gets the floor height (or ceiling height) of the mobj's contact point in sector, assuming object's center if moved to [x, y] // If line is supplied, it's a divider line on the sector. Set it to NULL if you're not checking for collision with a line @@ -718,12 +610,12 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, /*CONS_Printf("BEFORE: v1 = %f %f %f\n", FIXED_TO_FLOAT(v1.x), FIXED_TO_FLOAT(v1.y), - FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y)) + FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v1.x, v1.y)) ); CONS_Printf(" v2 = %f %f %f\n", FIXED_TO_FLOAT(v2.x), FIXED_TO_FLOAT(v2.y), - FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y)) + FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v2.x, v2.y)) );*/ if (abs(v1.x-x) > radius) { @@ -781,35 +673,32 @@ static fixed_t HighestOnLine(fixed_t radius, fixed_t x, fixed_t y, line_t *line, /*CONS_Printf("AFTER: v1 = %f %f %f\n", FIXED_TO_FLOAT(v1.x), FIXED_TO_FLOAT(v1.y), - FIXED_TO_FLOAT(P_GetZAt(slope, v1.x, v1.y)) + FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v1.x, v1.y)) ); CONS_Printf(" v2 = %f %f %f\n", FIXED_TO_FLOAT(v2.x), FIXED_TO_FLOAT(v2.y), - FIXED_TO_FLOAT(P_GetZAt(slope, v2.x, v2.y)) + FIXED_TO_FLOAT(P_GetSlopeZAt(slope, v2.x, v2.y)) );*/ // Return the higher of the two points if (actuallylowest) return min( - P_GetZAt(slope, v1.x, v1.y), - P_GetZAt(slope, v2.x, v2.y) + P_GetSlopeZAt(slope, v1.x, v1.y), + P_GetSlopeZAt(slope, v2.x, v2.y) ); else return max( - P_GetZAt(slope, v1.x, v1.y), - P_GetZAt(slope, v2.x, v2.y) + P_GetSlopeZAt(slope, v1.x, v1.y), + P_GetSlopeZAt(slope, v2.x, v2.y) ); } -#endif fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) { -#ifdef ESLOPE I_Assert(mobj != NULL); -#endif I_Assert(sector != NULL); -#ifdef ESLOPE + if (sector->f_slope) { fixed_t testx, testy; pslope_t *slope = sector->f_slope; @@ -835,7 +724,7 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t // If the highest point is in the sector, then we have it easy! Just get the Z at that point if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector)) - return P_GetZAt(slope, testx, testy); + return P_GetSlopeZAt(slope, testx, testy); // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point if (perfect) { @@ -875,29 +764,18 @@ fixed_t P_MobjFloorZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t // If we're just testing for base sector location (no collision line), just go for the center's spot... // It'll get fixed when we test for collision anyway, and the final result can't be lower than this if (line == NULL) - return P_GetZAt(slope, x, y); + return P_GetSlopeZAt(slope, x, y); return HighestOnLine(mobj->radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the floor height -#else - (void)mobj; - (void)boundsec; - (void)x; - (void)y; - (void)line; - (void)lowest; - (void)perfect; -#endif return sector->floorheight; } fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) { -#ifdef ESLOPE I_Assert(mobj != NULL); -#endif I_Assert(sector != NULL); -#ifdef ESLOPE + if (sector->c_slope) { fixed_t testx, testy; pslope_t *slope = sector->c_slope; @@ -923,7 +801,7 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed // If the highest point is in the sector, then we have it easy! Just get the Z at that point if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector)) - return P_GetZAt(slope, testx, testy); + return P_GetSlopeZAt(slope, testx, testy); // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point if (perfect) { @@ -963,30 +841,19 @@ fixed_t P_MobjCeilingZ(mobj_t *mobj, sector_t *sector, sector_t *boundsec, fixed // If we're just testing for base sector location (no collision line), just go for the center's spot... // It'll get fixed when we test for collision anyway, and the final result can't be lower than this if (line == NULL) - return P_GetZAt(slope, x, y); + return P_GetSlopeZAt(slope, x, y); return HighestOnLine(mobj->radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the ceiling height -#else - (void)mobj; - (void)boundsec; - (void)x; - (void)y; - (void)line; - (void)lowest; - (void)perfect; -#endif return sector->ceilingheight; } // Now do the same as all above, but for cameras because apparently cameras are special? fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) { -#ifdef ESLOPE I_Assert(mobj != NULL); -#endif I_Assert(sector != NULL); -#ifdef ESLOPE + if (sector->f_slope) { fixed_t testx, testy; pslope_t *slope = sector->f_slope; @@ -1012,7 +879,7 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix // If the highest point is in the sector, then we have it easy! Just get the Z at that point if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector)) - return P_GetZAt(slope, testx, testy); + return P_GetSlopeZAt(slope, testx, testy); // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point if (perfect) { @@ -1052,29 +919,18 @@ fixed_t P_CameraFloorZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fix // If we're just testing for base sector location (no collision line), just go for the center's spot... // It'll get fixed when we test for collision anyway, and the final result can't be lower than this if (line == NULL) - return P_GetZAt(slope, x, y); + return P_GetSlopeZAt(slope, x, y); return HighestOnLine(mobj->radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the floor height -#else - (void)mobj; - (void)boundsec; - (void)x; - (void)y; - (void)line; - (void)lowest; - (void)perfect; -#endif return sector->floorheight; } fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, fixed_t x, fixed_t y, line_t *line, boolean lowest, boolean perfect) { -#ifdef ESLOPE I_Assert(mobj != NULL); -#endif I_Assert(sector != NULL); -#ifdef ESLOPE + if (sector->c_slope) { fixed_t testx, testy; pslope_t *slope = sector->c_slope; @@ -1100,7 +956,7 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f // If the highest point is in the sector, then we have it easy! Just get the Z at that point if (R_PointInSubsector(testx, testy)->sector == (boundsec ? boundsec : sector)) - return P_GetZAt(slope, testx, testy); + return P_GetSlopeZAt(slope, testx, testy); // If boundsec is set, we're looking for specials. In that case, iterate over every line in this sector to find the TRUE highest/lowest point if (perfect) { @@ -1140,19 +996,10 @@ fixed_t P_CameraCeilingZ(camera_t *mobj, sector_t *sector, sector_t *boundsec, f // If we're just testing for base sector location (no collision line), just go for the center's spot... // It'll get fixed when we test for collision anyway, and the final result can't be lower than this if (line == NULL) - return P_GetZAt(slope, x, y); + return P_GetSlopeZAt(slope, x, y); return HighestOnLine(mobj->radius, x, y, line, slope, lowest); } else // Well, that makes it easy. Just get the ceiling height -#else - (void)mobj; - (void)boundsec; - (void)x; - (void)y; - (void)line; - (void)lowest; - (void)perfect; -#endif return sector->ceilingheight; } static void P_PlayerFlip(mobj_t *mo) @@ -1162,12 +1009,6 @@ static void P_PlayerFlip(mobj_t *mo) G_GhostAddFlip((INT32) (mo->player - players)); // Flip aiming to match! - - if (mo->player->pflags & PF_NIGHTSMODE) // NiGHTS doesn't use flipcam - { - if (mo->tracer) - mo->tracer->eflags ^= MFE_VERTICALFLIP; - } } // @@ -1244,11 +1085,6 @@ fixed_t P_GetMobjGravity(mobj_t *mo) if (mo->player) { - if (mo->player->climbing || (mo->player->pflags & PF_NIGHTSMODE)) - { - return 0; - } - if (!(mo->flags2 & MF2_OBJECTFLIP) != !(mo->player->powers[pw_gravityboots])) // negated to turn numeric into bool - would be double negated, but not needed if both would be { gravityadd = -gravityadd; @@ -1292,6 +1128,8 @@ fixed_t P_GetMobjGravity(mobj_t *mo) { case MT_FLINGRING: case MT_FLINGCOIN: + case MT_FLINGBLUESPHERE: + case MT_FLINGNIGHTSCHIP: case MT_FLINGEMERALD: case MT_BOUNCERING: case MT_RAILRING: @@ -1319,6 +1157,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) } break; case MT_WATERDROP: + case MT_CYBRAKDEMON: gravityadd /= 2; break; case MT_BANANA: @@ -1345,7 +1184,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo) // Goop has slower, reversed gravity if (goopgravity) { - gravityadd = -gravityadd/5; + gravityadd = -((gravityadd/5) + (gravityadd/8)); } gravityadd = FixedMul(gravityadd, mo->scale); @@ -1378,7 +1217,6 @@ void P_CheckGravity(mobj_t *mo, boolean affect) } #define STOPSPEED (FRACUNIT) -//#define FRICTION (ORIG_FRICTION) // 0.90625 // // P_SceneryXYFriction @@ -1411,7 +1249,6 @@ static void P_SceneryXYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) { // Stolen from P_SpawnFriction mo->friction = FRACUNIT - 0x100; - //mo->movefactor = ((0x10092 - mo->friction)*(0x70))/0x158; } else mo->friction = ORIG_FRICTION; @@ -1433,37 +1270,38 @@ static void P_XYFriction(mobj_t *mo, fixed_t oldx, fixed_t oldy) player = mo->player; if (player) // valid only if player avatar { - // spinning friction - if (player->pflags & PF_SPINNING && (player->rmomx || player->rmomy) && !(player->pflags & PF_STARTDASH)) - { - const fixed_t ns = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); //const fixed_t ns = FixedDiv(549*FRICTION,500*FRACUNIT); - mo->momx = FixedMul(mo->momx, ns); - mo->momy = FixedMul(mo->momy, ns); - } - else if (abs(player->rmomx) < FixedMul(STOPSPEED, mo->scale) - && abs(player->rmomy) < FixedMul(STOPSPEED, mo->scale) - && (!(K_GetForwardMove(player) && !(twodlevel || mo->flags2 & MF2_TWOD)) && !(player->pflags & PF_SPINNING)) -#ifdef ESLOPE - && !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)))// && (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)) -#endif - ) + if (FixedHypot(player->rmomx, player->rmomy) < FixedMul(STOPSPEED, mo->scale) && (K_GetForwardMove(player) == 0) + && !(player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) /*&& (abs(player->mo->standingslope->zdelta) >= FRACUNIT/2)*/)) { // if in a walking frame, stop moving - if (player->panim == PA_WALK && player->kartstuff[k_spinouttimer] == 0) - P_SetPlayerMobjState(mo, S_KART_STILL1); // SRB2kart - was S_PLAY_STND + if (player->panim == PA_WALK) + { + P_SetPlayerMobjState(mo, S_KART_STILL); + } + mo->momx = player->cmomx; mo->momy = player->cmomy; } else { - mo->momx = FixedMul(mo->momx, mo->friction); - mo->momy = FixedMul(mo->momy, mo->friction); + if (oldx == mo->x && oldy == mo->y) + { + mo->momx = FixedMul(mo->momx, ORIG_FRICTION); + mo->momy = FixedMul(mo->momy, ORIG_FRICTION); + } + else + { + mo->momx = FixedMul(mo->momx, mo->friction); + mo->momy = FixedMul(mo->momy, mo->friction); + } mo->friction = ORIG_FRICTION; } } else + { P_SceneryXYFriction(mo, oldx, oldy); + } } static void P_PushableCheckBustables(mobj_t *mo) @@ -1488,70 +1326,74 @@ static void P_PushableCheckBustables(mobj_t *mo) for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) { + ffloor_t *rover; + fixed_t topheight, bottomheight; + if (!node->m_sector) break; - if (node->m_sector->ffloors) + if (!node->m_sector->ffloors) + continue; + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) { - ffloor_t *rover; - fixed_t topheight, bottomheight; + if (!(rover->flags & FF_EXISTS)) + continue; - for (rover = node->m_sector->ffloors; rover; rover = rover->next) + if (!(rover->flags & FF_BUSTUP)) + continue; + + // Needs ML_EFFECT4 flag for pushables to break it + if (!(rover->master->flags & ML_EFFECT4)) + continue; + + if (rover->master->frontsector->crumblestate != CRUMBLE_NONE) + continue; + + topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); + bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); + + // Height checks + if (rover->flags & FF_SHATTERBOTTOM) { - if (!(rover->flags & FF_EXISTS)) continue; + if (mo->z + mo->momz + mo->height < bottomheight) + continue; - if (!(rover->flags & FF_BUSTUP)) continue; - - // Needs ML_EFFECT4 flag for pushables to break it - if (!(rover->master->flags & ML_EFFECT4)) continue; - - if (!rover->master->frontsector->crumblestate) - { - topheight = P_GetFOFTopZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); - bottomheight = P_GetFOFBottomZ(mo, node->m_sector, rover, mo->x, mo->y, NULL); - // Height checks - if (rover->flags & FF_SHATTERBOTTOM) - { - if (mo->z+mo->momz + mo->height < bottomheight) - continue; - - if (mo->z+mo->height > bottomheight) - continue; - } - else if (rover->flags & FF_SPINBUST) - { - if (mo->z+mo->momz > topheight) - continue; - - if (mo->z+mo->height < bottomheight) - continue; - } - else if (rover->flags & FF_SHATTER) - { - if (mo->z+mo->momz > topheight) - continue; - - if (mo->z+mo->momz + mo->height < bottomheight) - continue; - } - else - { - if (mo->z >= topheight) - continue; - - if (mo->z+mo->height < bottomheight) - continue; - } - - EV_CrumbleChain(node->m_sector, rover); - - // Run a linedef executor?? - if (rover->master->flags & ML_EFFECT5) - P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), mo, node->m_sector); - - goto bustupdone; - } + if (mo->z + mo->height > bottomheight) + continue; } + else if (rover->flags & FF_SPINBUST) + { + if (mo->z + mo->momz > topheight) + continue; + + if (mo->z + mo->height < bottomheight) + continue; + } + else if (rover->flags & FF_SHATTER) + { + if (mo->z + mo->momz > topheight) + continue; + + if (mo->z + mo->momz + mo->height < bottomheight) + continue; + } + else + { + if (mo->z >= topheight) + continue; + + if (mo->z + mo->height < bottomheight) + continue; + } + + EV_CrumbleChain(NULL, rover); // node->m_sector + + // Run a linedef executor?? + if (rover->master->flags & ML_EFFECT5) + P_LinedefExecute((INT16)(P_AproxDistance(rover->master->dx, rover->master->dy)>>FRACBITS), mo, node->m_sector); + + goto bustupdone; } } bustupdone: @@ -1585,11 +1427,9 @@ void P_XYMovement(mobj_t *mo) fixed_t xmove, ymove; fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls boolean moved; -#ifdef ESLOPE pslope_t *oldslope = NULL; - vector3_t slopemom; + vector3_t slopemom = {0,0,0}; fixed_t predictedz = 0; -#endif I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -1619,7 +1459,9 @@ void P_XYMovement(mobj_t *mo) oldx = mo->x; oldy = mo->y; -#ifdef ESLOPE + if (mo->flags & MF_NOCLIPHEIGHT) + mo->standingslope = NULL; + // adjust various things based on slope if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) { if (!P_IsObjectOnGround(mo)) { // We fell off at some point? Do the twisty thing! @@ -1641,10 +1483,9 @@ void P_XYMovement(mobj_t *mo) } } else if (P_IsObjectOnGround(mo) && !mo->momz) predictedz = mo->z; -#endif // Pushables can break some blocks - if (CheckForBustableBlocks && mo->flags & MF_PUSHABLE) + if (CheckForBustableBlocks && ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse))) P_PushableCheckBustables(mo); //{ SRB2kart - Ballhogs @@ -1659,11 +1500,20 @@ void P_XYMovement(mobj_t *mo) } //} - if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) && !(mo->eflags & MFE_SPRUNG)) + if (!P_TryMove(mo, mo->x + xmove, mo->y + ymove, true) + && !(P_MobjWasRemoved(mo) || mo->eflags & MFE_SPRUNG)) { // blocked move moved = false; + if (LUAh_MobjMoveBlocked(mo)) + { + if (P_MobjWasRemoved(mo)) + return; + } + else if (P_MobjWasRemoved(mo)) + return; + //{ SRB2kart - Jawz if (mo->type == MT_JAWZ || mo->type == MT_JAWZ_DUD) { @@ -1671,107 +1521,13 @@ void P_XYMovement(mobj_t *mo) { // This Item Damage S_StartSound(mo, mo->info->deathsound); - P_KillMobj(mo, NULL, NULL); + P_KillMobj(mo, NULL, NULL, DMG_NORMAL); P_SetObjectMomZ(mo, 8*FRACUNIT, false); P_InstaThrust(mo, R_PointToAngle2(mo->x, mo->y, mo->x + xmove, mo->y + ymove)+ANGLE_90, 16*FRACUNIT); } } //} - else if (mo->flags & MF_BOUNCE) - { - P_BounceMove(mo); - xmove = ymove = 0; - S_StartSound(mo, mo->info->activesound); - - //{ SRB2kart - Orbinaut, Ballhog - // Bump sparks - if (mo->type == MT_ORBINAUT || mo->type == MT_BALLHOG) - { - mobj_t *fx; - fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); - if (mo->eflags & MFE_VERTICALFLIP) - fx->eflags |= MFE_VERTICALFLIP; - else - fx->eflags &= ~MFE_VERTICALFLIP; - fx->scale = mo->scale; - } - - if (mo->type == MT_ORBINAUT) // Orbinaut speed decreasing - { - if (mo->health > 1) - { - S_StartSound(mo, mo->info->attacksound); - mo->health--; - mo->threshold = 0; - } - else if (mo->health == 1) - { - // This Item Damage - S_StartSound(mo, mo->info->deathsound); - P_KillMobj(mo, NULL, NULL); - - P_SetObjectMomZ(mo, 8*FRACUNIT, false); - P_InstaThrust(mo, R_PointToAngle2(mo->x, mo->y, mo->x + xmove, mo->y + ymove)+ANGLE_90, 16*FRACUNIT); - } - } - - // Bubble bounce - if (mo->type == MT_BUBBLESHIELDTRAP) - S_StartSound(mo, sfx_s3k44); - //} - - // Bounce ring algorithm - if (mo->type == MT_THROWNBOUNCE) - { - mo->threshold++; - - // Gain lower amounts of time on each bounce. - if (mo->fuse && mo->threshold < 5) - mo->fuse += ((5 - mo->threshold) * TICRATE); - - // Check for hit against sky here - if (P_CheckSkyHit(mo)) - { - // Hack to prevent missiles exploding - // against the sky. - // Does not handle sky floors. - // Check frontsector as well. - - P_RemoveMobj(mo); - return; - } - } - } - else if (mo->flags & MF_STICKY) - { - S_StartSound(mo, mo->info->activesound); - mo->momx = mo->momy = mo->momz = 0; //Full stop! - mo->flags |= MF_NOGRAVITY; //Stay there! - mo->flags &= ~MF_STICKY; //Don't check again! - - // Check for hit against sky here - if (P_CheckSkyHit(mo)) - { - // Hack to prevent missiles exploding - // against the sky. - // Does not handle sky floors. - // Check frontsector as well. - - P_RemoveMobj(mo); - return; - } - } - else if (player || mo->flags & (MF_SLIDEME|MF_PUSHABLE)) - { // try to slide along it - P_SlideMove(mo, false); - xmove = ymove = 0; - } - else if (mo->type == MT_SPINFIRE) - { - P_RemoveMobj(mo); - return; - } else if (mo->flags & MF_MISSILE) { // explode a missile @@ -1812,8 +1568,123 @@ void P_XYMovement(mobj_t *mo) P_ExplodeMissile(mo); return; } + else if (mo->flags & MF_STICKY) + { + S_StartSound(mo, mo->info->activesound); + mo->momx = mo->momy = mo->momz = 0; //Full stop! + mo->flags |= MF_NOGRAVITY; //Stay there! + mo->flags &= ~MF_STICKY; //Don't check again! + + // Check for hit against sky here + if (P_CheckSkyHit(mo)) + { + // Hack to prevent missiles exploding + // against the sky. + // Does not handle sky floors. + // Check frontsector as well. + + P_RemoveMobj(mo); + return; + } + } else - mo->momx = mo->momy = 0; + { + boolean walltransferred = false; + + if (player || mo->flags & MF_SLIDEME) + { // try to slide along it + // Wall transfer part 1. + pslope_t *transferslope = NULL; + fixed_t transfermomz = 0; + if (oldslope && (P_MobjFlip(mo)*(predictedz - mo->z) > 0)) // Only for moving up (relative to gravity), otherwise there's a failed launch when going down slopes and hitting walls + { + transferslope = ((mo->standingslope) ? mo->standingslope : oldslope); + if (((transferslope->zangle < ANGLE_180) ? transferslope->zangle : InvAngle(transferslope->zangle)) >= ANGLE_45) // Prevent some weird stuff going on on shallow slopes. + transfermomz = P_GetWallTransferMomZ(mo, transferslope); + } + + // Wall transfer part 2. + if (transfermomz && transferslope) // Are we "transferring onto the wall" (really just a disguised vertical launch)? + { + angle_t relation; // Scale transfer momentum based on how head-on it is to the slope. + + walltransferred = true; + + P_SlideMove(mo); + + if (player) + player->powers[pw_pushing] = 3; + xmove = ymove = 0; + + if (mo->momx || mo->momy) // "Guess" the angle of the wall you hit using new momentum + relation = transferslope->xydirection - R_PointToAngle2(0, 0, mo->momx, mo->momy); + else // Give it for free, I guess. + relation = ANGLE_90; + transfermomz = FixedMul(transfermomz, + abs(FINESINE((relation >> ANGLETOFINESHIFT) & FINEMASK))); + if (P_MobjFlip(mo)*(transfermomz - mo->momz) > 2*FRACUNIT) // Do the actual launch! + { + mo->momz = transfermomz; + mo->standingslope = NULL; + if (player) + { + player->powers[pw_justlaunched] = 2; + } + } + } + } + + if (walltransferred == false) + { + if (mo->flags & MF_SLIDEME) + { + P_SlideMove(mo); + xmove = ymove = 0; + } + else + { + P_BounceMove(mo); + xmove = ymove = 0; + S_StartSound(mo, mo->info->activesound); + + //{ SRB2kart - Orbinaut, Ballhog + // Bump sparks + if (mo->type == MT_ORBINAUT || mo->type == MT_BALLHOG) + { + mobj_t *fx; + fx = P_SpawnMobj(mo->x, mo->y, mo->z, MT_BUMP); + if (mo->eflags & MFE_VERTICALFLIP) + fx->eflags |= MFE_VERTICALFLIP; + else + fx->eflags &= ~MFE_VERTICALFLIP; + fx->scale = mo->scale; + } + + if (mo->type == MT_ORBINAUT) // Orbinaut speed decreasing + { + if (mo->health > 1) + { + S_StartSound(mo, mo->info->attacksound); + mo->health--; + mo->threshold = 0; + } + else if (mo->health == 1) + { + // This Item Damage + S_StartSound(mo, mo->info->deathsound); + P_KillMobj(mo, NULL, NULL, DMG_NORMAL); + + P_SetObjectMomZ(mo, 8*FRACUNIT, false); + P_InstaThrust(mo, R_PointToAngle2(mo->x, mo->y, mo->x + xmove, mo->y + ymove)+ANGLE_90, 16*FRACUNIT); + } + } + + // Bubble bounce + if (mo->type == MT_BUBBLESHIELDTRAP) + S_StartSound(mo, sfx_s3k44); + } + } + } } else moved = true; @@ -1821,8 +1692,7 @@ void P_XYMovement(mobj_t *mo) if (P_MobjWasRemoved(mo)) // MF_SPECIAL touched a player! O_o;; return; -#ifdef ESLOPE - if (moved && oldslope) { // Check to see if we ran off + if (moved && oldslope && !(mo->flags & MF_NOCLIPHEIGHT)) { // Check to see if we ran off if (oldslope != mo->standingslope) { // First, compare different slopes angle_t oldangle, newangle; @@ -1872,68 +1742,26 @@ void P_XYMovement(mobj_t *mo) //CONS_Printf("Launched off of flat surface running into downward slope\n"); } } -#endif // Check the gravity status. P_CheckGravity(mo, false); - if (player && !moved && player->pflags & PF_NIGHTSMODE && mo->target) - { - angle_t fa; - - P_UnsetThingPosition(mo); - player->angle_pos = player->old_angle_pos; - player->speed = FixedMul(player->speed, 4*FRACUNIT/5); - if (player->flyangle >= 0 && player->flyangle < 90) - player->flyangle = 135; - else if (player->flyangle >= 90 && player->flyangle < 180) - player->flyangle = 45; - else if (player->flyangle >= 180 && player->flyangle < 270) - player->flyangle = 315; - else - player->flyangle = 225; - player->flyangle %= 360; - - if (player->pflags & PF_TRANSFERTOCLOSEST) - { - mo->x -= mo->momx; - mo->y -= mo->momy; - } - else - { - fa = player->old_angle_pos>>ANGLETOFINESHIFT; - - mo->x = mo->target->x + FixedMul(FINECOSINE(fa),mo->target->radius); - mo->y = mo->target->y + FixedMul(FINESINE(fa),mo->target->radius); - } - - mo->momx = mo->momy = 0; - P_SetThingPosition(mo); - } - if (mo->flags & MF_NOCLIPHEIGHT) return; // no frictions for objects that can pass through floors - if (mo->flags & MF_MISSILE || mo->flags2 & MF2_SKULLFLY || mo->type == MT_SHELL || mo->type == MT_VULTURE) + if (mo->flags & MF_MISSILE || mo->flags2 & MF2_SKULLFLY || mo->type == MT_SHELL || mo->type == MT_VULTURE || mo->type == MT_PENGUINATOR) return; // no friction for missiles ever - if (player && player->homing) // no friction for homing - return; - - if (player && player->pflags & PF_NIGHTSMODE) - return; // no friction for NiGHTS players - -#ifdef ESLOPE if ((mo->type == MT_BIGTUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED) && (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8)) // Special exception for tumbleweeds on slopes return; -#endif //{ SRB2kart stuff if (mo->type == MT_FLINGRING || mo->type == MT_BALLHOG || mo->type == MT_BUBBLESHIELDTRAP) return; - if (player && (player->kartstuff[k_spinouttimer] && !player->kartstuff[k_wipeoutslow]) && player->speed <= FixedDiv(20*mapobjectscale, player->kartstuff[k_offroad] + FRACUNIT)) + if (player && (player->kartstuff[k_spinouttimer] && !player->kartstuff[k_wipeoutslow]) + && player->speed <= FixedDiv(20*mapobjectscale, player->kartstuff[k_offroad] + FRACUNIT)) return; //} @@ -1944,16 +1772,16 @@ void P_XYMovement(mobj_t *mo) P_XYFriction(mo, oldx, oldy); } -static void P_RingXYMovement(mobj_t *mo) +void P_RingXYMovement(mobj_t *mo) { I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) - P_SlideMove(mo, false); + P_BounceMove(mo); } -static void P_SceneryXYMovement(mobj_t *mo) +void P_SceneryXYMovement(mobj_t *mo) { fixed_t oldx, oldy; // reducing bobbing/momentum on ice when up against walls @@ -1964,7 +1792,7 @@ static void P_SceneryXYMovement(mobj_t *mo) oldy = mo->y; if (!P_SceneryTryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) - P_SlideMove(mo, false); + P_BounceMove(mo); if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z > mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height < mo->ceilingz)) return; // no friction when airborne @@ -1989,7 +1817,7 @@ static void P_SceneryXYMovement(mobj_t *mo) // 1 - forces false check for water (rings) // 2 - forces false check for water + different quicksand behaviour (scenery) // -static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype) +void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motype) { ffloor_t *rover; fixed_t delta1, delta2, thingtop; @@ -2008,14 +1836,16 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp topheight = P_GetFOFTopZ(mo, sector, rover, mo->x, mo->y, NULL); bottomheight = P_GetFOFBottomZ(mo, sector, rover, mo->x, mo->y, NULL); - if (mo->player && P_CheckSolidLava(mo, rover)) // only the player should be affected + if (mo->player && P_CheckSolidLava(rover)) // only the player should stand on lava ; else if (motype != 0 && rover->flags & FF_SWIMMABLE) // "scenery" only continue; else if (rover->flags & FF_QUICKSAND) // quicksand ; - else if (!((rover->flags & FF_BLOCKPLAYER && mo->player) // solid to players? - || (rover->flags & FF_BLOCKOTHERS && !mo->player))) // solid to others? + else if (!( // if it's not either of the following... + (rover->flags & (FF_BLOCKPLAYER|FF_MARIO) && mo->player) // ...solid to players? (mario blocks are always solid from beneath to players) + || (rover->flags & FF_BLOCKOTHERS && !mo->player) // ...solid to others? + )) // ...don't take it into account. continue; if (rover->flags & FF_QUICKSAND) { @@ -2040,7 +1870,9 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp delta1 = mo->z - (bottomheight + ((topheight - bottomheight)/2)); delta2 = thingtop - (bottomheight + ((topheight - bottomheight)/2)); + if (topheight > mo->floorz && abs(delta1) < abs(delta2) + && (rover->flags & FF_SOLID) // Non-FF_SOLID Mario blocks are only solid from bottom && !(rover->flags & FF_REVERSEPLATFORM) && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_PLATFORM)))) // In reverse gravity, only clip for FOFs that are intangible from their bottom (the "top" you're falling through) if you're coming from above ("below" in your frame of reference) { @@ -2048,7 +1880,7 @@ static void P_AdjustMobjFloorZ_FFloors(mobj_t *mo, sector_t *sector, UINT8 motyp } if (bottomheight < mo->ceilingz && abs(delta1) >= abs(delta2) && !(rover->flags & FF_PLATFORM) - && ((P_MobjFlip(mo)*mo->momz >= 0) || (!(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below + && ((P_MobjFlip(mo)*mo->momz >= 0) || ((rover->flags & FF_SOLID) && !(rover->flags & FF_REVERSEPLATFORM)))) // In normal gravity, only clip for FOFs that are intangible from the top if you're coming from below { mo->ceilingz = bottomheight; } @@ -2108,7 +1940,7 @@ static void P_AdjustMobjFloorZ_PolyObjs(mobj_t *mo, subsector_t *subsec) } } -static void P_RingZMovement(mobj_t *mo) +void P_RingZMovement(mobj_t *mo) { I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -2148,10 +1980,13 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); + if (mo->player && mo->player->pflags & PF_GODMODE) + return false; + if (((mo->z <= mo->subsector->sector->floorheight - && !(mo->eflags & MFE_VERTICALFLIP) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR)) + && ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR)) || (mo->z + mo->height >= mo->subsector->sector->ceilingheight - && (mo->eflags & MFE_VERTICALFLIP) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING))) + && ((mo->subsector->sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->subsector->sector->flags & SF_FLIPSPECIAL_CEILING))) && (GETSECSPECIAL(mo->subsector->sector->special, 1) == 6 || GETSECSPECIAL(mo->subsector->sector->special, 1) == 7)) return true; @@ -2159,23 +1994,11 @@ boolean P_CheckDeathPitCollide(mobj_t *mo) return false; } -boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) +boolean P_CheckSolidLava(ffloor_t *rover) { - I_Assert(mo != NULL); - I_Assert(!P_MobjWasRemoved(mo)); - - { - fixed_t topheight = - #ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : - #endif - *rover->topheight; - - if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 - && !(rover->master->flags & ML_BLOCKPLAYERS) - && ((rover->master->flags & ML_EFFECT3) || mo->z-mo->momz > topheight - FixedMul(16*FRACUNIT, mo->scale))) - return true; - } + if (rover->flags & FF_SWIMMABLE && GETSECSPECIAL(rover->master->frontsector->special, 1) == 3 + && !(rover->master->flags & ML_BLOCKPLAYERS)) + return true; return false; } @@ -2184,9 +2007,10 @@ boolean P_CheckSolidLava(mobj_t *mo, ffloor_t *rover) // P_ZMovement // Returns false if the mobj was killed/exploded/removed, true otherwise. // -static boolean P_ZMovement(mobj_t *mo) +boolean P_ZMovement(mobj_t *mo) { fixed_t dist, delta; + boolean onground; I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -2205,33 +2029,18 @@ static boolean P_ZMovement(mobj_t *mo) mo->eflags &= ~MFE_APPLYPMOMZ; } mo->z += mo->momz; + onground = P_IsObjectOnGround(mo); -#ifdef ESLOPE if (mo->standingslope) { if (mo->flags & MF_NOCLIPHEIGHT) mo->standingslope = NULL; - else if (!P_IsObjectOnGround(mo)) + else if (!onground) P_SlopeLaunch(mo); } -#endif switch (mo->type) { - case MT_THROWNBOUNCE: - if ((mo->flags & MF_BOUNCE) && (mo->z <= mo->floorz || mo->z+mo->height >= mo->ceilingz)) - { - mo->momz = -mo->momz; - mo->z += mo->momz; - S_StartSound(mo, mo->info->activesound); - mo->threshold++; - - // Be sure to change the XY one too if you change this. - // Gain lower amounts of time on each bounce. - if (mo->fuse && mo->threshold < 5) - mo->fuse += ((5 - mo->threshold) * TICRATE); - } - break; case MT_SKIM: // skims don't bounce if (mo->z > mo->watertop && mo->z - mo->momz <= mo->watertop) @@ -2241,6 +2050,13 @@ static boolean P_ZMovement(mobj_t *mo) mo->flags |= MF_NOGRAVITY; } break; + case MT_SPINFIRE: + if (P_CheckDeathPitCollide(mo)) + { + P_RemoveMobj(mo); + return false; + } + break; case MT_GOOP: if (P_CheckDeathPitCollide(mo)) { @@ -2289,11 +2105,16 @@ static boolean P_ZMovement(mobj_t *mo) case MT_RING: // Ignore still rings case MT_COIN: - case MT_BLUEBALL: + case MT_BLUESPHERE: + case MT_BOMBSPHERE: + case MT_NIGHTSCHIP: + case MT_NIGHTSSTAR: case MT_REDTEAMRING: case MT_BLUETEAMRING: case MT_FLINGRING: case MT_FLINGCOIN: + case MT_FLINGBLUESPHERE: + case MT_FLINGNIGHTSCHIP: case MT_FLINGEMERALD: // Remove flinged stuff from death pits. if (P_CheckDeathPitCollide(mo)) @@ -2326,18 +2147,15 @@ static boolean P_ZMovement(mobj_t *mo) if (!(mo->momx || mo->momy || mo->momz)) return true; break; - case MT_NIGHTSWING: - if (!(mo->momx || mo->momy || mo->momz)) - return true; - break; case MT_FLAMEJET: case MT_VERTICALFLAMEJET: - if (!(mo->flags & MF_BOUNCE)) + if (mo->flags & MF_SLIDEME) return true; break; case MT_SPIKE: + case MT_WALLSPIKE: // Dead spike particles disappear upon ground contact - if ((mo->z <= mo->floorz || mo->z + mo->height >= mo->ceilingz) && mo->health <= 0) + if (!mo->health && (mo->z <= mo->floorz || mo->z + mo->height >= mo->ceilingz)) { P_RemoveMobj(mo); return false; @@ -2347,22 +2165,16 @@ static boolean P_ZMovement(mobj_t *mo) break; } - if (P_CheckDeathPitCollide(mo)) + if (!mo->player && P_CheckDeathPitCollide(mo)) { - if (mo->flags & MF_PUSHABLE) + if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS || mo->type == MT_MINECART) { - // Remove other pushable items from death pits. - P_RemoveMobj(mo); - return false; - } - else if (mo->flags & MF_ENEMY || mo->flags & MF_BOSS) - { - // Kill enemies and bosses that fall into death pits. + // Kill enemies, bosses and minecarts that fall into death pits. if (mo->health) { - P_KillMobj(mo, NULL, NULL); - return false; + P_KillMobj(mo, NULL, NULL, DMG_NORMAL); } + return false; } } @@ -2406,7 +2218,6 @@ static boolean P_ZMovement(mobj_t *mo) else mo->z = mo->floorz; -#ifdef ESLOPE if (!(mo->flags & MF_MISSILE) && mo->standingslope) // You're still on the ground; why are we here? { mo->momz = 0; @@ -2422,7 +2233,6 @@ static boolean P_ZMovement(mobj_t *mo) #endif P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope); } -#endif // hit the floor if (mo->type == MT_FIREBALL) // special case for the fireball @@ -2490,27 +2300,16 @@ static boolean P_ZMovement(mobj_t *mo) if (P_MobjFlip(mo)*mom.z < 0) // falling { - if (!tmfloorthing || tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER) - mo->eflags |= MFE_JUSTHITFLOOR; + mo->eflags |= MFE_JUSTHITFLOOR; if (mo->flags2 & MF2_SKULLFLY) // the skull slammed into something mom.z = -mom.z; - else - // Flingrings bounce - if (/*mo->type == MT_FLINGRING - || mo->type == MT_FLINGCOIN - || P_WeaponOrPanel(mo->type) - || mo->type == MT_FLINGEMERALD - ||*/ mo->type == MT_BIGTUMBLEWEED + else if (mo->type == MT_BIGTUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED || mo->type == MT_CANNONBALLDECOR || mo->type == MT_FALLINGROCK) { - if (maptol & TOL_NIGHTS) - mom.z = -FixedDiv(mom.z, 10*FRACUNIT); - else - mom.z = -FixedMul(mom.z, FixedDiv(17*FRACUNIT,20*FRACUNIT)); + mom.z = -FixedMul(mom.z, FixedDiv(17*FRACUNIT,20*FRACUNIT)); if (mo->type == MT_BIGTUMBLEWEED || mo->type == MT_LITTLETUMBLEWEED) { @@ -2533,13 +2332,11 @@ static boolean P_ZMovement(mobj_t *mo) else mom.y -= FixedMul(6*FRACUNIT, mo->scale); } -#ifdef ESLOPE else if (mo->standingslope && abs(mo->standingslope->zdelta) > FRACUNIT>>8) { // Pop the object up a bit to encourage bounciness //mom.z = P_MobjFlip(mo)*mo->scale; } -#endif else { mom.x = mom.y = mom.z = 0; @@ -2549,12 +2346,11 @@ static boolean P_ZMovement(mobj_t *mo) // Stolen from P_SpawnFriction mo->friction = FRACUNIT - 0x100; - //mo->movefactor = ((0x10092 - mo->friction)*(0x70))/0x158; } else if (mo->type == MT_FALLINGROCK) { if (P_MobjFlip(mo)*mom.z > FixedMul(2*FRACUNIT, mo->scale)) - S_StartSound(mo, mo->info->activesound + P_RandomKey(mo->info->mass)); + S_StartSound(mo, mo->info->activesound + P_RandomKey(mo->info->reactiontime)); mom.z /= 2; // Rocks not so bouncy @@ -2575,21 +2371,16 @@ static boolean P_ZMovement(mobj_t *mo) mom.z = 0; } } - else if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)) - mom.z = tmfloorthing->momz; - else if (!tmfloorthing) - mom.z = 0; + else + mom.z = (tmfloorthing ? tmfloorthing->momz : 0); + } - else if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)) + else if (tmfloorthing) mom.z = tmfloorthing->momz; -#ifdef ESLOPE if (mo->standingslope) { // MT_STEAM will never have a standingslope, see above. P_QuantizeMomentumToSlope(&mom, mo->standingslope); } -#endif mo->momx = mom.x; mo->momy = mom.y; @@ -2653,10 +2444,7 @@ static boolean P_ZMovement(mobj_t *mo) // Flags bounce if (mo->type == MT_REDFLAG || mo->type == MT_BLUEFLAG) { - if (maptol & TOL_NIGHTS) - mo->momz = -FixedDiv(mo->momz, 10*FRACUNIT); - else - mo->momz = -FixedMul(mo->momz, FixedDiv(17*FRACUNIT,20*FRACUNIT)); + mo->momz = -FixedMul(mo->momz, FixedDiv(17*FRACUNIT,20*FRACUNIT)); } else mo->momz = 0; @@ -2666,8 +2454,97 @@ static boolean P_ZMovement(mobj_t *mo) return true; } -static void P_PlayerZMovement(mobj_t *mo) +// Check for "Mario" blocks to hit and bounce them +static void P_CheckMarioBlocks(mobj_t *mo) { + msecnode_t *node; + + if (netgame && mo->player->spectator) + return; + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + ffloor_t *rover; + + if (!node->m_sector->ffloors) + continue; + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!(rover->flags & FF_MARIO)) + continue; + + if (mo->eflags & MFE_VERTICALFLIP) + continue; // if you were flipped, your head isn't actually hitting your ceilingz is it? + + if (*rover->bottomheight != mo->ceilingz) + continue; + + if (rover->flags & FF_SHATTERBOTTOM) // Brick block! + EV_CrumbleChain(node->m_sector, rover); + else // Question block! + EV_MarioBlock(rover, node->m_sector, mo); + } + } +} + +// Check if we're on a polyobject that triggers a linedef executor. +static boolean P_PlayerPolyObjectZMovement(mobj_t *mo) +{ + msecnode_t *node; + boolean stopmovecut = false; + + for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + sector_t *sec = node->m_sector; + subsector_t *newsubsec; + size_t i; + + for (i = 0; i < numsubsectors; i++) + { + polyobj_t *po; + sector_t *polysec; + newsubsec = &subsectors[i]; + + if (newsubsec->sector != sec) + continue; + + for (po = newsubsec->polyList; po; po = (polyobj_t *)(po->link.next)) + { + if (!(po->flags & POF_SOLID)) + continue; + + if (!P_MobjInsidePolyobj(po, mo)) + continue; + + polysec = po->lines[0]->backsector; + + // Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red + if ((mo->z == polysec->ceilingheight || mo->z + mo->height == polysec->floorheight) && po->thinker) + stopmovecut = true; + + if (!(po->flags & POF_LDEXEC)) + continue; + + if (mo->z != polysec->ceilingheight) + continue; + + // We're landing on a PO, so check for a linedef executor. + P_LinedefExecute(po->triggertag, mo, NULL); + } + } + } + + return stopmovecut; +} + +void P_PlayerZMovement(mobj_t *mo) +{ + boolean onground; + I_Assert(mo != NULL); I_Assert(!P_MobjWasRemoved(mo)); @@ -2689,8 +2566,8 @@ static void P_PlayerZMovement(mobj_t *mo) else mo->player->viewheight -= mo->floorz - mo->z; - /*mo->player->deltaviewheight = - (FixedMul(cv_viewheight.value<scale) - mo->player->viewheight)>>3;*/ + mo->player->deltaviewheight = + (P_GetPlayerViewHeight(mo->player) - mo->player->viewheight)>>3; } // adjust height @@ -2702,179 +2579,52 @@ static void P_PlayerZMovement(mobj_t *mo) } mo->z += mo->momz; + onground = P_IsObjectOnGround(mo); // Have player fall through floor? if (mo->player->playerstate == PST_DEAD || mo->player->playerstate == PST_REBORN) return; -#ifdef ESLOPE if (mo->standingslope) { if (mo->flags & MF_NOCLIPHEIGHT) mo->standingslope = NULL; - else if (!P_IsObjectOnGround(mo)) + else if (!onground) P_SlopeLaunch(mo); } -#endif // clip movement - if (P_IsObjectOnGround(mo) && !(mo->flags & MF_NOCLIPHEIGHT)) + if (onground && !(mo->flags & MF_NOCLIPHEIGHT)) { if (mo->eflags & MFE_VERTICALFLIP) mo->z = mo->ceilingz - mo->height; else mo->z = mo->floorz; - if (mo->player->pflags & PF_NIGHTSMODE) - { - // bounce off floor if you were flying towards it - if ((mo->eflags & MFE_VERTICALFLIP && mo->player->flyangle > 0 && mo->player->flyangle < 180) - || (!(mo->eflags & MFE_VERTICALFLIP) && mo->player->flyangle > 180 && mo->player->flyangle <= 359)) - { - if (mo->player->flyangle < 90 || mo->player->flyangle >= 270) - mo->player->flyangle += P_MobjFlip(mo)*90; - else - mo->player->flyangle -= P_MobjFlip(mo)*90; - mo->player->speed = FixedMul(mo->player->speed, 4*FRACUNIT/5); - } - goto nightsdone; - } // Get up if you fell. - if ((mo->state == &states[mo->info->painstate] || mo->state == &states[S_KART_SPIN]) - && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->kartstuff[k_squishedtimer] == 0) // SRB2kart - P_SetPlayerMobjState(mo, S_KART_STILL1); + if (mo->player->panim == PA_PAIN && mo->player->kartstuff[k_spinouttimer] == 0 && mo->player->kartstuff[k_squishedtimer] == 0) + P_SetPlayerMobjState(mo, S_KART_STILL); -#ifdef ESLOPE if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { // Handle landing on slope during Z movement P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)); } -#endif - -#ifdef ESLOPE - if (!mo->standingslope && (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)) { - // Handle landing on slope during Z movement - P_HandleSlopeLanding(mo, (mo->eflags & MFE_VERTICALFLIP ? tmceilingslope : tmfloorslope)); - } -#endif if (P_MobjFlip(mo)*mo->momz < 0) // falling { + boolean clipmomz = !(P_CheckDeathPitCollide(mo)); + mo->pmomz = 0; // We're on a new floor, don't keep doing platform movement. + mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack - // Squat down. Decrease viewheight for a moment after hitting the ground (hard), - /*if (P_MobjFlip(mo)*mo->momz < -FixedMul(8*FRACUNIT, mo->scale)) - mo->player->deltaviewheight = (P_MobjFlip(mo)*mo->momz)>>3; // make sure momz is negative - */ + clipmomz = P_PlayerHitFloor(mo->player, true); + P_PlayerPolyObjectZMovement(mo); - if (!tmfloorthing || tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER) // Spin Attack - { - mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack - - if (mo->eflags & MFE_JUSTHITFLOOR) - { -#ifdef POLYOBJECTS - // Check if we're on a polyobject - // that triggers a linedef executor. - msecnode_t *node; - - for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - sector_t *sec = node->m_sector; - subsector_t *newsubsec; - size_t i; - - for (i = 0; i < numsubsectors; i++) - { - newsubsec = &subsectors[i]; - - if (newsubsec->sector != sec) - continue; - - if (newsubsec->polyList) - { - polyobj_t *po = newsubsec->polyList; - sector_t *polysec; - - while(po) - { - if (!P_MobjInsidePolyobj(po, mo) || !(po->flags & POF_SOLID)) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - // We're inside it! Yess... - polysec = po->lines[0]->backsector; - - // Moving polyobjects should act like conveyors if the player lands on one. (I.E. none of the momentum cut thing below) -Red - /*if ((mo->z == polysec->ceilingheight || mo->z+mo->height == polysec->floorheight) && po->thinker) - stopmovecut = true;*/ - - if (!(po->flags & POF_LDEXEC)) - { - po = (polyobj_t *)(po->link.next); - continue; - } - - if (mo->z == polysec->ceilingheight) - { - // We're landing on a PO, so check for - // a linedef executor. - // Trigger tags are 32000 + the PO's ID number. - P_LinedefExecute((INT16)(32000 + po->id), mo, NULL); - } - - po = (polyobj_t *)(po->link.next); - } - } - } - } -#endif - } - - if (mo->health) - { - if (mo->player->pflags & PF_GLIDING) // ground gliding - { - mo->player->skidtime = TICRATE; - mo->tics = -1; - } - else if ((mo->player->pflags & PF_JUMPED || (mo->player->pflags & (PF_SPINNING|PF_USEDOWN)) != (PF_SPINNING|PF_USEDOWN) - || mo->player->powers[pw_tailsfly]) && (mo->player->kartstuff[k_spinouttimer] == 0)) // SRB2kart - { - K_KartMoveAnimation(mo->player); - } - - if (mo->player->pflags & PF_JUMPED) - mo->player->pflags &= ~PF_SPINNING; - else if (!(mo->player->pflags & PF_USEDOWN)) - mo->player->pflags &= ~PF_SPINNING; - - if (!(mo->player->pflags & PF_GLIDING)) - mo->player->pflags &= ~PF_JUMPED; - mo->player->pflags &= ~PF_THOKKED; - //mo->player->pflags &= ~PF_GLIDING; - mo->player->jumping = 0; - mo->player->secondjump = 0; - mo->player->glidetime = 0; - mo->player->climbing = 0; - mo->player->powers[pw_tailsfly] = 0; - } - } - if (!(mo->player->pflags & PF_SPINNING)) - mo->player->pflags &= ~PF_STARTDASH; - - if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)) - mo->momz = tmfloorthing->momz; - else if (!tmfloorthing) - mo->momz = 0; + if (clipmomz) + mo->momz = (tmfloorthing ? tmfloorthing->momz : 0); } - else if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)) + else if (tmfloorthing) mo->momz = tmfloorthing->momz; } else if (!(mo->flags & MF_NOGRAVITY)) // Gravity here! @@ -2897,8 +2647,6 @@ static void P_PlayerZMovement(mobj_t *mo) P_CheckGravity(mo, true); } -nightsdone: - if (((mo->eflags & MFE_VERTICALFLIP && mo->z < mo->floorz) || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z + mo->height > mo->ceilingz)) && !(mo->flags & MF_NOCLIPHEIGHT)) { @@ -2907,53 +2655,10 @@ nightsdone: else mo->z = mo->ceilingz - mo->height; - if (mo->player->pflags & PF_NIGHTSMODE) - { - // bounce off ceiling if you were flying towards it - if ((mo->eflags & MFE_VERTICALFLIP && mo->player->flyangle > 180 && mo->player->flyangle <= 359) - || (!(mo->eflags & MFE_VERTICALFLIP) && mo->player->flyangle > 0 && mo->player->flyangle < 180)) - { - if (mo->player->flyangle < 90 || mo->player->flyangle >= 270) - mo->player->flyangle -= P_MobjFlip(mo)*90; - else - mo->player->flyangle += P_MobjFlip(mo)*90; - mo->player->flyangle %= 360; - mo->player->speed = FixedMul(mo->player->speed, 4*FRACUNIT/5); - } - } - - // Check for "Mario" blocks to hit and bounce them if (P_MobjFlip(mo)*mo->momz > 0) { - msecnode_t *node; - - if (CheckForMarioBlocks && !(netgame && mo->player->spectator)) // Only let the player punch - { - // Search the touching sectors, from side-to-side... - for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - ffloor_t *rover; - if (!node->m_sector->ffloors) - continue; - - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - // Come on, it's time to go... - if (rover->flags & FF_MARIO - && !(mo->eflags & MFE_VERTICALFLIP) // if you were flipped, your head isn't actually hitting your ceilingz is it? - && *rover->bottomheight == mo->ceilingz) // The player's head hit the bottom! - // DO THE MARIO! - EV_MarioBlock(rover->master->frontsector, node->m_sector, *rover->topheight, mo); - } - } // Ugly ugly billions of braces! Argh! - } - - // hit the ceiling - if (mariomode) - S_StartSound(mo, sfx_mario1); + if (CheckForMarioBlocks) + P_CheckMarioBlocks(mo); if (!mo->player->climbing) mo->momz = 0; @@ -2961,7 +2666,7 @@ nightsdone: } } -static boolean P_SceneryZMovement(mobj_t *mo) +boolean P_SceneryZMovement(mobj_t *mo) { // Intercept the stupid 'fall through 3dfloors' bug if (mo->subsector->sector->ffloors) @@ -2982,12 +2687,11 @@ static boolean P_SceneryZMovement(mobj_t *mo) { case MT_BOOMEXPLODE: case MT_BOOMPARTICLE: - if ((mo->flags & MF_BOUNCE) && (mo->z <= mo->floorz || mo->z+mo->height >= mo->ceilingz)) + if (!(mo->flags & MF_SLIDEME) && (mo->z <= mo->floorz || mo->z+mo->height >= mo->ceilingz)) { // set standingslope P_TryMove(mo, mo->x, mo->y, true); mo->momz = -mo->momz; -#ifdef ESLOPE if (mo->standingslope) { if (mo->flags & MF_NOCLIPHEIGHT) @@ -2995,7 +2699,6 @@ static boolean P_SceneryZMovement(mobj_t *mo) else if (!P_IsObjectOnGround(mo)) P_SlopeLaunch(mo); } -#endif S_StartSound(mo, mo->info->activesound); } break; @@ -3055,36 +2758,22 @@ static boolean P_SceneryZMovement(mobj_t *mo) if ((!(mo->eflags & MFE_VERTICALFLIP) && mo->z <= mo->floorz) || (mo->eflags & MFE_VERTICALFLIP && mo->z+mo->height >= mo->ceilingz)) { - // DO NOT use random numbers here. - // SonicCD mode is console togglable and - // affects demos. - UINT8 rltime = (leveltime & 4); - - if (!rltime) - P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER3); - else if (rltime == 2) - P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER2); - else - P_SpawnMobj(mo->x, mo->y, mo->floorz, MT_GFZFLOWER1); + mobjtype_t flowertype = ((P_RandomChance(FRACUNIT/2)) ? MT_GFZFLOWER1 : MT_GFZFLOWER3); + mobj_t *flower = P_SpawnMobjFromMobj(mo, 0, 0, 0, flowertype); + if (flower) + { + P_SetScale(flower, mo->scale/16); + flower->destscale = mo->scale; + flower->scalespeed = mo->scale/8; + } P_RemoveMobj(mo); return false; } - default: break; } - // Fix for any silly pushables like the egg statues that are also scenery for some reason -- Monster Iestyn - if (P_CheckDeathPitCollide(mo)) - { - if (mo->flags & MF_PUSHABLE) - { - P_RemoveMobj(mo); - return false; - } - } - // clip movement if (((mo->z <= mo->floorz && !(mo->eflags & MFE_VERTICALFLIP)) || (mo->z + mo->height >= mo->ceilingz && mo->eflags & MFE_VERTICALFLIP)) @@ -3097,12 +2786,9 @@ static boolean P_SceneryZMovement(mobj_t *mo) if (P_MobjFlip(mo)*mo->momz < 0) // falling { - if (!tmfloorthing || tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER) - mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack + mo->eflags |= MFE_JUSTHITFLOOR; // Spin Attack - if (tmfloorthing && (tmfloorthing->flags & (MF_PUSHABLE|MF_MONITOR) - || tmfloorthing->flags2 & MF2_STANDONME || tmfloorthing->type == MT_PLAYER)) + if (tmfloorthing) mo->momz = tmfloorthing->momz; else if (!tmfloorthing) mo->momz = 0; @@ -3142,16 +2828,18 @@ void P_MobjCheckWater(mobj_t *mobj) boolean waterwasnotset = (mobj->watertop == INT32_MAX); boolean wasinwater = (mobj->eflags & MFE_UNDERWATER) == MFE_UNDERWATER; boolean wasingoo = (mobj->eflags & MFE_GOOWATER) == MFE_GOOWATER; - fixed_t thingtop = mobj->z + mobj->height; // especially for players, infotable height does not neccessarily match actual height + fixed_t thingtop = mobj->z + mobj->height; sector_t *sector = mobj->subsector->sector; ffloor_t *rover; player_t *p = mobj->player; // Will just be null if not a player. + fixed_t height = mobj->height; + boolean wasgroundpounding = (p && ((p->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL || (p->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP) && (p->pflags & PF_SHIELDABILITY)); // Default if no water exists. mobj->watertop = mobj->waterbottom = mobj->z - 1000*FRACUNIT; // Reset water state. - mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER); + mobj->eflags &= ~(MFE_UNDERWATER|MFE_TOUCHWATER|MFE_GOOWATER|MFE_TOUCHLAVA); for (rover = sector->ffloors; rover; rover = rover->next) { @@ -3161,27 +2849,19 @@ void P_MobjCheckWater(mobj_t *mobj) || ((rover->flags & FF_BLOCKOTHERS) && !mobj->player))) continue; - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; - -#ifdef ESLOPE - if (*rover->t_slope) - topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y); - - if (*rover->b_slope) - bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y); -#endif + topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y); + bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); if (mobj->eflags & MFE_VERTICALFLIP) { - if (topheight < (thingtop - FixedMul(mobj->info->height/2, mobj->scale)) + if (topheight < (thingtop - (height>>1)) || bottomheight > thingtop) continue; } else { if (topheight < mobj->z - || bottomheight > (mobj->z + FixedMul(mobj->info->height/2, mobj->scale))) + || bottomheight > (mobj->z + (height>>1))) continue; } @@ -3190,63 +2870,57 @@ void P_MobjCheckWater(mobj_t *mobj) mobj->waterbottom = bottomheight; // Just touching the water? - if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height, mobj->scale) < bottomheight) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height, mobj->scale) > topheight)) - { + if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - height < bottomheight) + || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + height > topheight)) mobj->eflags |= MFE_TOUCHWATER; - if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY)) - mobj->eflags |= MFE_GOOWATER; - } + // Actually in the water? - if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - FixedMul(mobj->info->height/2, mobj->scale) > bottomheight) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + FixedMul(mobj->info->height/2, mobj->scale) < topheight)) - { + if (((mobj->eflags & MFE_VERTICALFLIP) && thingtop - (height>>1) > bottomheight) + || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + (height>>1) < topheight)) mobj->eflags |= MFE_UNDERWATER; + + if (mobj->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER)) + { + if (GETSECSPECIAL(rover->master->frontsector->special, 1) == 3) + mobj->eflags |= MFE_TOUCHLAVA; + if (rover->flags & FF_GOOWATER && !(mobj->flags & MF_NOGRAVITY)) mobj->eflags |= MFE_GOOWATER; } } + // Spectators and dead players don't get to do any of the things after this. + if (p && (p->spectator || p->playerstate != PST_LIVE)) + return; + // Specific things for underwater players if (p && (mobj->eflags & MFE_UNDERWATER) == MFE_UNDERWATER) { if (!((p->powers[pw_super]) || (p->powers[pw_invulnerability]))) { - if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ATTRACT) - { // Water removes attract shield. + boolean electric = !!(p->powers[pw_shield] & SH_PROTECTELECTRIC); + if (electric || ((p->powers[pw_shield] & SH_PROTECTFIRE) && !(p->powers[pw_shield] & SH_PROTECTWATER) && !(mobj->eflags & MFE_TOUCHLAVA))) + { // Water removes electric and non-water fire shields... + P_FlashPal(p, + electric + ? PAL_WHITE + : PAL_NUKE, + 1); p->powers[pw_shield] = p->powers[pw_shield] & SH_STACK; - P_FlashPal(p, PAL_WHITE, 1); } } - // Drown timer setting - /* // SRB2kart - Can't drown. - if ((p->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL // Has elemental - || (p->exiting) // Or exiting - || (maptol & TOL_NIGHTS) // Or in NiGHTS mode - || (mariomode)) // Or in Mario mode... - */ + if ((wasgroundpounding = ((mobj->eflags & MFE_GOOWATER) && wasgroundpounding))) { - // Can't drown. - p->powers[pw_underwater] = 0; + p->pflags &= ~PF_SHIELDABILITY; + mobj->momz >>= 1; } - /* - else if (p->powers[pw_underwater] <= 0) // No underwater timer set - { - // Then we'll set it! - p->powers[pw_underwater] = underwatertics + 1; - } - */ } // The rest of this code only executes on a water state change. if (waterwasnotset || !!(mobj->eflags & MFE_UNDERWATER) == wasinwater) return; - // Spectators and dead players also don't count. - if (p && (p->spectator || p->playerstate != PST_LIVE)) - return; - if ((p) // Players || (mobj->flags & MF_PUSHABLE) // Pushables || ((mobj->info->flags & MF_PUSHABLE) && mobj->fuse) // Previously pushable, might be moving still @@ -3254,34 +2928,42 @@ void P_MobjCheckWater(mobj_t *mobj) { // Check to make sure you didn't just cross into a sector to jump out of // that has shallower water than the block you were originally in. - if (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->watertop-mobj->floorz <= FixedMul(mobj->info->height, mobj->scale)>>1) + if ((!(mobj->eflags & MFE_VERTICALFLIP) && mobj->watertop-mobj->floorz <= height>>1) + || ((mobj->eflags & MFE_VERTICALFLIP) && mobj->ceilingz-mobj->waterbottom <= height>>1)) return; - if ((mobj->eflags & MFE_VERTICALFLIP) && mobj->ceilingz-mobj->waterbottom <= FixedMul(mobj->info->height, mobj->scale)>>1) - return; - - if ((mobj->eflags & MFE_GOOWATER || wasingoo)) { // Decide what happens to your momentum when you enter/leave goopy water. - if (P_MobjFlip(mobj)*mobj->momz < 0) // You are entering the goo? - mobj->momz = FixedMul(mobj->momz, FixedDiv(2*FRACUNIT, 5*FRACUNIT)); // kill momentum significantly, to make the goo feel thick. + if (mobj->eflags & MFE_GOOWATER || wasingoo) { // Decide what happens to your momentum when you enter/leave goopy water. + if (P_MobjFlip(mobj)*mobj->momz > 0) + { + mobj->momz -= (mobj->momz/8); // cut momentum a little bit to prevent multiple bobs + //CONS_Printf("leaving\n"); + } + else + { + if (!wasgroundpounding) + mobj->momz >>= 1; // kill momentum significantly, to make the goo feel thick. + //CONS_Printf("entering\n"); + } } else if (wasinwater && P_MobjFlip(mobj)*mobj->momz > 0) mobj->momz = FixedMul(mobj->momz, FixedDiv(780*FRACUNIT, 457*FRACUNIT)); // Give the mobj a little out-of-water boost. if (P_MobjFlip(mobj)*mobj->momz < 0) { - if ((mobj->eflags & MFE_VERTICALFLIP && thingtop-(FixedMul(mobj->info->height, mobj->scale)>>1)-mobj->momz <= mobj->waterbottom) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z+(FixedMul(mobj->info->height, mobj->scale)>>1)-mobj->momz >= mobj->watertop)) + if ((mobj->eflags & MFE_VERTICALFLIP && thingtop-(height>>1)-mobj->momz <= mobj->waterbottom) + || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z+(height>>1)-mobj->momz >= mobj->watertop)) { // Spawn a splash mobj_t *splish; + mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; if (mobj->eflags & MFE_VERTICALFLIP) { - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale), MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); splish->flags2 |= MF2_OBJECTFLIP; splish->eflags |= MFE_VERTICALFLIP; } else - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); splish->destscale = mobj->scale; P_SetScale(splish, mobj->scale); } @@ -3309,20 +2991,21 @@ void P_MobjCheckWater(mobj_t *mobj) } else if (P_MobjFlip(mobj)*mobj->momz > 0) { - if (((mobj->eflags & MFE_VERTICALFLIP && thingtop-(FixedMul(mobj->info->height, mobj->scale)>>1)-mobj->momz > mobj->waterbottom) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z+(FixedMul(mobj->info->height, mobj->scale)>>1)-mobj->momz < mobj->watertop)) + if (((mobj->eflags & MFE_VERTICALFLIP && thingtop-(height>>1)-mobj->momz > mobj->waterbottom) + || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z+(height>>1)-mobj->momz < mobj->watertop)) && !(mobj->eflags & MFE_UNDERWATER)) // underwater check to prevent splashes on opposite side { // Spawn a splash mobj_t *splish; + mobjtype_t splishtype = (mobj->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; if (mobj->eflags & MFE_VERTICALFLIP) { - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[MT_SPLISH].height, mobj->scale), MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->waterbottom-FixedMul(mobjinfo[splishtype].height, mobj->scale), splishtype); splish->flags2 |= MF2_OBJECTFLIP; splish->eflags |= MFE_VERTICALFLIP; } else - splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, MT_SPLISH); + splish = P_SpawnMobj(mobj->x, mobj->y, mobj->watertop, splishtype); splish->destscale = mobj->scale; P_SetScale(splish, mobj->scale); } @@ -3338,6 +3021,8 @@ void P_MobjCheckWater(mobj_t *mobj) if (mobj->eflags & MFE_GOOWATER || wasingoo) S_StartSound(mobj, sfx_ghit); + else if (mobj->eflags & MFE_TOUCHLAVA) + S_StartSound(mobj, sfx_splash); else S_StartSound(mobj, sfx_splish); // And make a sound! @@ -3403,22 +3088,14 @@ static void P_SceneryCheckWater(mobj_t *mobj) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS) continue; - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; - -#ifdef ESLOPE - if (*rover->t_slope) - topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y); - - if (*rover->b_slope) - bottomheight = P_GetZAt(*rover->b_slope, mobj->x, mobj->y); -#endif + topheight = P_GetFFloorTopZAt (rover, mobj->x, mobj->y); + bottomheight = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); if (topheight <= mobj->z - || bottomheight > (mobj->z + FixedMul(mobj->info->height >> 1, mobj->scale))) + || bottomheight > (mobj->z + (mobj->height>>1))) continue; - if (mobj->z + FixedMul(mobj->info->height, mobj->scale) > topheight) + if (mobj->z + mobj->height > topheight) mobj->eflags |= MFE_TOUCHWATER; else mobj->eflags &= ~MFE_TOUCHWATER; @@ -3427,7 +3104,7 @@ static void P_SceneryCheckWater(mobj_t *mobj) mobj->watertop = topheight; mobj->waterbottom = bottomheight; - if (mobj->z + FixedMul(mobj->info->height >> 1, mobj->scale) < topheight) + if (mobj->z + (mobj->height>>1) < topheight) mobj->eflags |= MFE_UNDERWATER; else mobj->eflags &= ~MFE_UNDERWATER; @@ -3457,15 +3134,9 @@ static boolean P_CameraCheckHeat(camera_t *thiscam) if (!(rover->flags & FF_EXISTS)) continue; - if (halfheight >= ( -#ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) : -#endif - *rover->topheight) || halfheight <= ( -#ifdef ESLOPE - *rover->b_slope ? P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) : -#endif - *rover->bottomheight)) + if (halfheight >= P_GetFFloorTopZAt(rover, thiscam->x, thiscam->y)) + continue; + if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y)) continue; if (P_FindSpecialLineFromTag(13, rover->master->frontsector->tag, -1) != -1) @@ -3493,15 +3164,9 @@ static boolean P_CameraCheckWater(camera_t *thiscam) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKOTHERS) continue; - if (halfheight >= ( -#ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, thiscam->x, thiscam->y) : -#endif - *rover->topheight) || halfheight <= ( -#ifdef ESLOPE - *rover->b_slope ? P_GetZAt(*rover->b_slope, thiscam->x, thiscam->y) : -#endif - *rover->bottomheight)) + if (halfheight >= P_GetFFloorTopZAt(rover, thiscam->x, thiscam->y)) + continue; + if (halfheight <= P_GetFFloorBottomZAt(rover, thiscam->x, thiscam->y)) continue; return true; @@ -3517,53 +3182,37 @@ void P_DestroyRobots(void) mobj_t *mo; thinker_t *think; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; mo = (mobj_t *)think; - if (mo->health <= 0 || !(mo->flags & MF_ENEMY || mo->flags & MF_BOSS)) + if (mo->health <= 0 || !(mo->flags & (MF_ENEMY|MF_BOSS))) continue; // not a valid enemy if (mo->type == MT_PLAYER) // Don't chase after other players! continue; // Found a target enemy - P_KillMobj(mo, players[consoleplayer].mo, players[consoleplayer].mo); + P_KillMobj(mo, players[consoleplayer].mo, players[consoleplayer].mo, DMG_NORMAL); } } -// P_CameraThinker -// -// Process the mobj-ish required functions of the camera -boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled) +// the below is chasecam only, if you're curious. check out P_CalcPostImg in p_user.c for first person +void P_CalcChasePostImg(player_t *player, camera_t *thiscam) { - boolean itsatwodlevel = false; postimg_t postimg = postimg_none; UINT8 i; // This can happen when joining if (thiscam->subsector == NULL || thiscam->subsector->sector == NULL) - return true; - - if (twodlevel) - itsatwodlevel = true; - else - { - for (i = 0; i <= r_splitscreen; i++) - { - if (thiscam == &camera[i] && players[displayplayers[i]].mo - && (players[displayplayers[i]].mo->flags2 & MF2_TWOD)) - { - itsatwodlevel = true; - break; - } - } - } + return; if (encoremode) + { postimg = postimg_mirror; + } else if (player->awayviewtics && player->awayviewmobj && !P_MobjWasRemoved(player->awayviewmobj)) // Camera must obviously exist { camera_t dummycam; @@ -3596,10 +3245,18 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled postimgtype[i] = postimg; } } +} + +// P_CameraThinker +// +// Process the mobj-ish required functions of the camera +boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled) +{ + P_CalcChasePostImg(player, thiscam); if (thiscam->momx || thiscam->momy) { - if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) + if (!P_TryCameraMove(thiscam->x + thiscam->momx, thiscam->y + thiscam->momy, thiscam)) // Thanks for the greatly improved camera, Lach -- Sev { // Never fails for 2D mode. mobj_t dummy; dummy.thinker.function.acp1 = (actionf_p1)P_MobjThinker; @@ -3609,22 +3266,33 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled dummy.z = thiscam->z; dummy.height = thiscam->height; - if ((player->pflags & PF_TIMEOVER) && G_RaceGametype()) + if ((player->pflags & PF_GAMETYPEOVER) && (gametyperules & GTR_CIRCUIT)) + { player->karthud[khud_timeovercam] = (2*TICRATE)+1; + } if (!resetcalled && !(player->pflags & PF_NOCLIP || leveltime < introtime) && !P_CheckSight(&dummy, player->mo)) // TODO: "P_CheckCameraSight" instead. + { P_ResetCamera(player, thiscam); + } else + { + fixed_t camspeed = P_AproxDistance(thiscam->momx, thiscam->momy); + P_SlideCameraMove(thiscam); + if (!resetcalled && P_AproxDistance(thiscam->momx, thiscam->momy) == camspeed) + { + P_ResetCamera(player, thiscam); + resetcalled = true; + } + } + if (resetcalled) // Okay this means the camera is fully reset. return true; } } - if (!itsatwodlevel) - P_CheckCameraPosition(thiscam->x, thiscam->y, thiscam); - thiscam->subsector = R_PointInSubsector(thiscam->x, thiscam->y); thiscam->floorz = tmfloorz; thiscam->ceilingz = tmceilingz; @@ -3633,54 +3301,10 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled { // adjust height thiscam->z += thiscam->momz + player->mo->pmomz; - -#ifndef NOCLIPCAM - if (!itsatwodlevel && !(player->pflags & PF_NOCLIP || leveltime < introtime)) - { - // clip movement - if (thiscam->z <= thiscam->floorz) // hit the floor - { - fixed_t cam_height = cv_cam_height.value; - thiscam->z = thiscam->floorz; - - if (player == &players[g_localplayers[1]]) - cam_height = cv_cam2_height.value; - if (player == &players[g_localplayers[2]]) - cam_height = cv_cam3_height.value; - if (player == &players[g_localplayers[3]]) - cam_height = cv_cam4_height.value; - if (thiscam->z > player->mo->z + player->mo->height + FixedMul(cam_height*FRACUNIT + 16*FRACUNIT, player->mo->scale)) - { - if (!resetcalled) - P_ResetCamera(player, thiscam); - return true; - } - } - - if (thiscam->z + thiscam->height > thiscam->ceilingz) - { - if (thiscam->momz > 0) - { - // hit the ceiling - thiscam->momz = 0; - } - - thiscam->z = thiscam->ceilingz - thiscam->height; - - if (thiscam->z + thiscam->height < player->mo->z - player->mo->height) - { - if (!resetcalled) - P_ResetCamera(player, thiscam); - return true; - } - } - } -#endif } - if (itsatwodlevel - || (thiscam->ceilingz - thiscam->z < thiscam->height - && thiscam->ceilingz >= thiscam->z)) + if (thiscam->ceilingz - thiscam->z < thiscam->height + && thiscam->ceilingz >= thiscam->z) { thiscam->ceilingz = thiscam->z + thiscam->height; thiscam->floorz = thiscam->z; @@ -3688,29 +3312,128 @@ boolean P_CameraThinker(player_t *player, camera_t *thiscam, boolean resetcalled return false; } -// -// P_PlayerMobjThinker -// -static void P_PlayerMobjThinker(mobj_t *mobj) +static void P_CheckCrumblingPlatforms(mobj_t *mobj) { msecnode_t *node; + if (netgame && mobj->player->spectator) + return; + + for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next) + { + ffloor_t *rover; + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!(rover->flags & FF_CRUMBLE)) + continue; + + if (mobj->eflags & MFE_VERTICALFLIP) + { + if (P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z + mobj->height) + continue; + } + else + { + if (P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector) != mobj->z) + continue; + } + + EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN)); + } + } +} + +static boolean P_MobjTouchesSectorWithWater(mobj_t *mobj) +{ + msecnode_t *node; + + for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next) + { + ffloor_t *rover; + + if (!node->m_sector->ffloors) + continue; + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!(rover->flags & FF_SWIMMABLE)) + continue; + + return true; + } + } + + return false; +} + +// Check for floating water platforms and bounce them +static void P_CheckFloatbobPlatforms(mobj_t *mobj) +{ + msecnode_t *node; + + // Can't land on anything if you're not moving downwards + if (P_MobjFlip(mobj)*mobj->momz >= 0) + return; + + if (!P_MobjTouchesSectorWithWater(mobj)) + return; + + for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next) + { + ffloor_t *rover; + + if (!node->m_sector->ffloors) + continue; + + for (rover = node->m_sector->ffloors; rover; rover = rover->next) + { + if (!(rover->flags & FF_EXISTS)) + continue; + + if (!(rover->flags & FF_FLOATBOB)) + continue; + + + if (mobj->eflags & MFE_VERTICALFLIP) + { + if (abs(*rover->bottomheight - (mobj->z + mobj->height)) > abs(mobj->momz)) + continue; + } + else + { + if (abs(*rover->topheight - mobj->z) > abs(mobj->momz)) + continue; + } + + // Initiate a 'bouncy' elevator function which slowly diminishes. + EV_BounceSector(rover->master->frontsector, -mobj->momz, rover->master); + } + } +} + +static void P_PlayerMobjThinker(mobj_t *mobj) +{ I_Assert(mobj != NULL); I_Assert(mobj->player != NULL); I_Assert(!P_MobjWasRemoved(mobj)); P_MobjCheckWater(mobj); -#ifdef ESLOPE P_ButteredSlope(mobj); -#endif // momentum movement mobj->eflags &= ~MFE_JUSTSTEPPEDDOWN; // Zoom tube - if ((mobj->tracer && mobj->tracer->type == MT_TUBEWAYPOINT) - || (mobj->player->respawn.state == RESPAWNST_MOVE)) + if ((mobj->player->powers[pw_carry] == CR_ZOOMTUBE && mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + || mobj->player->respawn.state == RESPAWNST_MOVE) { P_HitSpecialLines(mobj, mobj->x, mobj->y, mobj->momx, mobj->momy); P_UnsetThingPosition(mobj); @@ -3723,17 +3446,11 @@ static void P_PlayerMobjThinker(mobj_t *mobj) mobj->ceilingz = tmceilingz; goto animonly; } - else if (mobj->player->pflags & PF_MACESPIN && mobj->tracer) - { - P_CheckPosition(mobj, mobj->x, mobj->y); - mobj->floorz = tmfloorz; - mobj->ceilingz = tmceilingz; - goto animonly; - } // Needed for gravity boots P_CheckGravity(mobj, false); + mobj->player->powers[pw_justlaunched] = 0; if (mobj->momx || mobj->momy) { P_XYMovement(mobj); @@ -3744,77 +3461,10 @@ static void P_PlayerMobjThinker(mobj_t *mobj) else P_TryMove(mobj, mobj->x, mobj->y, true); - if (!(netgame && mobj->player->spectator)) - { - // Crumbling platforms - for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next) - { - fixed_t topheight, bottomheight; - ffloor_t *rover; + P_CheckCrumblingPlatforms(mobj); - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_CRUMBLE)) - continue; - - topheight = P_GetSpecialTopZ(mobj, sectors + rover->secnum, node->m_sector); - bottomheight = P_GetSpecialBottomZ(mobj, sectors + rover->secnum, node->m_sector); - - if ((topheight == mobj->z && !(mobj->eflags & MFE_VERTICALFLIP)) - || (bottomheight == mobj->z + mobj->height && mobj->eflags & MFE_VERTICALFLIP)) // You nut. - EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), mobj->player, rover->alpha, !(rover->flags & FF_NORETURN)); - } - } - } - - // Check for floating water platforms and bounce them - if (CheckForFloatBob && P_MobjFlip(mobj)*mobj->momz < 0) - { - boolean thereiswater = false; - - for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector->ffloors) - { - ffloor_t *rover; - // Get water boundaries first - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - if (rover->flags & FF_SWIMMABLE) // Is there water? - { - thereiswater = true; - break; - } - } - } - } - if (thereiswater) - { - for (node = mobj->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector->ffloors) - { - ffloor_t *rover; - for (rover = node->m_sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_FLOATBOB)) - continue; - - if ((!(mobj->eflags & MFE_VERTICALFLIP) && abs(*rover->topheight-mobj->z) <= abs(mobj->momz)) // The player is landing on the cheese! - || (mobj->eflags & MFE_VERTICALFLIP && abs(*rover->bottomheight-(mobj->z+mobj->height)) <= abs(mobj->momz))) - { - // Initiate a 'bouncy' elevator function - // which slowly diminishes. - EV_BounceSector(rover->master->frontsector, -mobj->momz, rover->master); - } - } - } - } - } // Ugly ugly billions of braces! Argh! - } + if (CheckForFloatBob) + P_CheckFloatbobPlatforms(mobj); // always do the gravity bit now, that's simpler // BUT CheckPosition only if wasn't done before. @@ -3831,30 +3481,11 @@ static void P_PlayerMobjThinker(mobj_t *mobj) } else { - if (!(mobj->player->pflags & PF_NIGHTSMODE)) // "jumping" is used for drilling - mobj->player->jumping = 0; - mobj->player->pflags &= ~PF_JUMPED; - if (mobj->player->secondjump || mobj->player->powers[pw_tailsfly]) - { - mobj->player->secondjump = 0; - mobj->player->powers[pw_tailsfly] = 0; - P_SetPlayerMobjState(mobj, S_KART_SLOW1); // SRB2kart - was S_PLAY_RUN1 - } mobj->eflags &= ~MFE_JUSTHITFLOOR; } animonly: - // cycle through states, - // calling action functions at transitions - if (mobj->tics != -1) - { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetPlayerMobjState(mobj, mobj->state->nextstate)) - return; // freed itself - } + P_CyclePlayerMobjState(mobj); } static void CalculatePrecipFloor(precipmobj_t *mobj) @@ -3865,11 +3496,7 @@ static void CalculatePrecipFloor(precipmobj_t *mobj) mobjsecsubsec = mobj->subsector->sector; else return; - mobj->floorz = -#ifdef ESLOPE - mobjsecsubsec->f_slope ? P_GetZAt(mobjsecsubsec->f_slope, mobj->x, mobj->y) : -#endif - mobjsecsubsec->floorheight; + mobj->floorz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y); if (mobjsecsubsec->ffloors) { ffloor_t *rover; @@ -3884,13 +3511,7 @@ static void CalculatePrecipFloor(precipmobj_t *mobj) if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE)) continue; -#ifdef ESLOPE - if (*rover->t_slope) - topheight = P_GetZAt(*rover->t_slope, mobj->x, mobj->y); - else -#endif - topheight = *rover->topheight; - + topheight = P_GetFFloorTopZAt(rover, mobj->x, mobj->y); if (topheight > mobj->floorz) mobj->floorz = topheight; } @@ -3981,7 +3602,6 @@ void P_PrecipThinker(precipmobj_t *mobj) static void P_RingThinker(mobj_t *mobj) { - mobj_t *spark; // Ring Fuse if (mobj->momx || mobj->momy) @@ -4018,9 +3638,7 @@ static void P_RingThinker(mobj_t *mobj) if (!mobj->fuse) { -#ifdef HAVE_BLUA if (!LUAh_MobjFuse(mobj)) -#endif { mobj->drawflags &= ~MFD_DONTDRAW; spark = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SIGNSPARKLE); // Spawn a fancy sparkle @@ -4071,15 +3689,15 @@ boolean P_BossTargetPlayer(mobj_t *actor, boolean closest) player = &players[actor->lastlook]; - if (player->health <= 0) - continue; // dead - if (player->pflags & PF_INVIS || player->bot || player->spectator) continue; // ignore notarget if (!player->mo || P_MobjWasRemoved(player->mo)) continue; + if (player->mo->health <= 0) + continue; //dead + if (!P_CheckSight(actor, player->mo)) continue; // out of sight @@ -4107,17 +3725,17 @@ boolean P_SupermanLook4Players(mobj_t *actor) for (c = 0; c < MAXPLAYERS; c++) { - if (playeringame[c]) + if (playeringame[c] && !players[c].spectator) { - if (players[c].health <= 0) - continue; // dead - if (players[c].pflags & PF_INVIS) continue; // ignore notarget if (!players[c].mo || players[c].bot) continue; + if (players[c].mo->health <= 0) + continue; // dead + playersinthegame[stop] = &players[c]; stop++; } @@ -4139,12 +3757,7 @@ static void P_GenericBossThinker(mobj_t *mobj) if (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)) { if (mobj->health <= 0) - { - // look for a new target - if (P_BossTargetPlayer(mobj, false) && mobj->info->mass) // Bid farewell! - S_StartSound(mobj, mobj->info->mass); return; - } // look for a new target if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound) @@ -4163,1530 +3776,6 @@ static void P_GenericBossThinker(mobj_t *mobj) } } -// AI for the first boss. -static void P_Boss1Thinker(mobj_t *mobj) -{ - if (mobj->flags2 & MF2_FRET && (statenum_t)(mobj->state-states) == mobj->info->spawnstate) { - mobj->flags2 &= ~(MF2_FRET|MF2_SKULLFLY); - mobj->momx = mobj->momy = mobj->momz = 0; - } - - if (!mobj->tracer) - { - var1 = 0; - A_BossJetFume(mobj); - } - - if (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)) - { - if (mobj->target && mobj->target->health - && mobj->target->type == MT_EGGMOBILE_TARGET) // Oh, we're just firing our laser. - return; // It's okay, then. - - if (mobj->health <= 0) - { - if (P_BossTargetPlayer(mobj, false) && mobj->info->mass) // Bid farewell! - S_StartSound(mobj, mobj->info->mass); - return; - } - - // look for a new target - if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound) - S_StartSound(mobj, mobj->info->seesound); - - return; - } - - if (mobj->state != &states[mobj->info->spawnstate] && mobj->health > 0 && mobj->flags & MF_FLOAT && !(mobj->flags2 & MF2_SKULLFLY)) - mobj->momz = FixedMul(mobj->momz,7*FRACUNIT/8); - - if (mobj->state == &states[mobj->info->meleestate] - || (mobj->state == &states[mobj->info->missilestate] - && mobj->health > mobj->info->damage)) - { - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - } -} - -// AI for the second boss. -// No, it does NOT convert "Boss" to a "Thinker". =P -static void P_Boss2Thinker(mobj_t *mobj) -{ - if (mobj->movecount) - mobj->movecount--; - - if (!mobj->movecount) - mobj->flags2 &= ~MF2_FRET; - - if (!mobj->tracer) - { - var1 = 0; - A_BossJetFume(mobj); - } - - if (mobj->health <= mobj->info->damage && (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) - { - if (mobj->health <= 0) - { - // look for a new target - if (P_BossTargetPlayer(mobj, false) && mobj->info->mass) // Bid farewell! - S_StartSound(mobj, mobj->info->mass); - return; - } - - // look for a new target - if (P_BossTargetPlayer(mobj, false) && mobj->info->seesound) - S_StartSound(mobj, mobj->info->seesound); - - return; - } - - if (mobj->state == &states[mobj->info->spawnstate] && mobj->health > mobj->info->damage) - A_Boss2Chase(mobj); - else if (mobj->health > 0 && mobj->state != &states[mobj->info->painstate] && mobj->state != &states[mobjinfo[mobj->info->missilestate].raisestate]) - { - mobj->flags &= ~MF_NOGRAVITY; - A_Boss2Pogo(mobj); - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - } -} - -// AI for the third boss. -// -// Notes for reminders: -// movedir = move 2x fast? -// movecount = fire missiles? -// reactiontime = shock the water? -// threshold = next waypoint # -// extravalue1 = previous time shock sound was used -// -static void P_Boss3Thinker(mobj_t *mobj) -{ - if (mobj->state == &states[mobj->info->spawnstate]) - mobj->flags2 &= ~MF2_FRET; - - if (mobj->flags2 & MF2_FRET) - mobj->movedir = 1; - - if (!mobj->tracer) - { - var1 = 1; - A_BossJetFume(mobj); - } - - if (mobj->health <= 0) - { - mobj->movecount = 0; - mobj->reactiontime = 0; - - if (mobj->state < &states[mobj->info->xdeathstate]) - return; - - if (mobj->threshold == -1) - { - mobj->momz = mobj->info->speed; - return; - } - } - - if (mobj->reactiontime) // Shock mode - { - UINT32 i; - - if (mobj->state != &states[mobj->info->spawnstate]) - P_SetMobjState(mobj, mobj->info->spawnstate); - - mobj->reactiontime--; - if (!mobj->reactiontime) - { - ffloor_t *rover; - - // Shock the water - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (players[i].mo->eflags & MFE_UNDERWATER) - P_DamageMobj(players[i].mo, mobj, mobj, 1); - } - - // Make the water flash - for (i = 0; i < numsectors; i++) - { - if (!sectors[i].ffloors) - continue; - - for (rover = sectors[i].ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; - - if (!(rover->flags & FF_SWIMMABLE)) - continue; - - P_SpawnLightningFlash(rover->master->frontsector); - break; - } - } - - if ((UINT32)mobj->extravalue1 + TICRATE*2 < leveltime) - { - mobj->extravalue1 = (INT32)leveltime; - S_StartSound(0, sfx_buzz1); - } - - // If in the center, check to make sure - // none of the players are in the water - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo || players[i].bot) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (players[i].mo->eflags & MFE_UNDERWATER) - { // Stay put - mobj->reactiontime = 2*TICRATE; - return; - } - } - } - - if (!mobj->reactiontime && mobj->health <= mobj->info->damage) - { // Spawn pinch dummies from the center when we're leaving it. - thinker_t *th; - mobj_t *mo2; - mobj_t *dummy; - SINT8 way = mobj->threshold - 1; // 0 through 4. - SINT8 way2; - - i = 0; // reset i to 0 so we can check how many clones we've removed - - // scan the thinkers to make sure all the old pinch dummies are gone before making new ones - // this can happen if the boss was hurt earlier than expected - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2->type == (mobjtype_t)mobj->info->mass && mo2->tracer == mobj) - { - P_RemoveMobj(mo2); - i++; - } - if (i == 2) // we've already removed 2 of these, let's stop now - break; - } - - way = (way + P_RandomRange(1,3)) % 5; // dummy 1 at one of the first three options after eggmobile - dummy = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->mass); - dummy->angle = mobj->angle; - dummy->threshold = way + 1; - dummy->tracer = mobj; - - do - way2 = (way + P_RandomRange(1,3)) % 5; // dummy 2 has to be careful, - while (way2 == mobj->threshold - 1); // to make sure it doesn't try to go the Eggman Way if dummy 1 rolled high. - dummy = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->mass); - dummy->angle = mobj->angle; - dummy->threshold = way2 + 1; - dummy->tracer = mobj; - - CONS_Debug(DBG_GAMELOGIC, "Eggman path %d - Dummy selected paths %d and %d\n", mobj->threshold, way + 1, dummy->threshold); - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - } - } - else if (mobj->movecount) // Firing mode - { - UINT32 i; - - // look for a new target - P_BossTargetPlayer(mobj, false); - - if (!mobj->target || !mobj->target->player) - return; - - // Are there any players underwater? If so, shock them! - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo || players[i].bot) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (players[i].mo->eflags & MFE_UNDERWATER) - { - mobj->movecount = 0; - P_SetMobjState(mobj, mobj->info->spawnstate); - return; - } - } - - // Always face your target. - A_FaceTarget(mobj); - - // Check if the attack animation is running. If not, play it. - if (mobj->state < &states[mobj->info->missilestate] || mobj->state > &states[mobj->info->raisestate]) - { - if (mobj->health <= mobj->info->damage) // pinch phase - mobj->movecount--; // limited number of shots before diving again - if (mobj->movecount) - P_SetMobjState(mobj, mobj->info->missilestate); - } - } - else if (mobj->threshold >= 0) // Traveling mode - { - thinker_t *th; - mobj_t *mo2; - fixed_t dist, dist2; - fixed_t speed; - - P_SetTarget(&mobj->target, NULL); - - if (mobj->state != &states[mobj->info->spawnstate] && mobj->health > 0 - && !(mobj->flags2 & MF2_FRET)) - P_SetMobjState(mobj, mobj->info->spawnstate); - - // scan the thinkers - // to find a point that matches - // the number - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && mo2->spawnpoint->angle == mobj->threshold) - { - P_SetTarget(&mobj->target, mo2); - break; - } - } - - if (!mobj->target) // Should NEVER happen - { - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 was unable to find specified waypoint: %d\n", mobj->threshold); - return; - } - - dist = P_AproxDistance(P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y), mobj->target->z - mobj->z); - - if (dist < 1) - dist = 1; - - if ((mobj->movedir) || (mobj->health <= mobj->info->damage)) - speed = mobj->info->speed * 2; - else - speed = mobj->info->speed; - - mobj->momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); - mobj->momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); - mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); - - if (mobj->momx != 0 || mobj->momy != 0) - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - - dist2 = P_AproxDistance(P_AproxDistance(mobj->target->x - (mobj->x + mobj->momx), mobj->target->y - (mobj->y + mobj->momy)), mobj->target->z - (mobj->z + mobj->momz)); - - if (dist2 < 1) - dist2 = 1; - - if ((dist >> FRACBITS) <= (dist2 >> FRACBITS)) - { - // If further away, set XYZ of mobj to waypoint location - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - mobj->z = mobj->target->z; - mobj->momx = mobj->momy = mobj->momz = 0; - P_SetThingPosition(mobj); - - if (mobj->threshold == 0) - { - mobj->reactiontime = 1; // Bzzt! Shock the water! - mobj->movedir = 0; - - if (mobj->health <= 0) - { - mobj->flags |= MF_NOGRAVITY|MF_NOCLIP; - mobj->flags |= MF_NOCLIPHEIGHT; - mobj->threshold = -1; - return; - } - } - - // Set to next waypoint in sequence - if (mobj->target->spawnpoint) - { - // From the center point, choose one of the five paths - if (mobj->target->spawnpoint->angle == 0) - mobj->threshold = P_RandomRange(1,5); - else - mobj->threshold = mobj->target->spawnpoint->extrainfo; - - // If the deaf flag is set, go into firing mode - if (mobj->target->spawnpoint->options & MTF_AMBUSH) - mobj->movecount = mobj->health+1; - } - else // This should never happen, as well - CONS_Debug(DBG_GAMELOGIC, "Error: Boss 3 waypoint has no spawnpoint associated with it.\n"); - } - } -} - -// Move Boss4's sectors by delta. -static boolean P_Boss4MoveCage(fixed_t delta) -{ - const UINT16 tag = 65534; - INT32 snum; - sector_t *sector; - for (snum = sectors[tag%numsectors].firsttag; snum != -1; snum = sector->nexttag) - { - sector = §ors[snum]; - if (sector->tag != tag) - continue; - sector->floorheight += delta; - sector->ceilingheight += delta; - P_CheckSector(sector, true); - } - return sectors[tag%numsectors].firsttag != -1; -} - -// Move Boss4's arms to angle -static void P_Boss4MoveSpikeballs(mobj_t *mobj, angle_t angle, fixed_t fz) -{ - INT32 s; - mobj_t *base = mobj, *seg; - fixed_t dist, bz = mobj->watertop+(16<tracer)) - { - for (seg = base, dist = 172*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 124*FRACUNIT, --s) - P_TeleportMove(seg, mobj->x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), bz + FixedMul(fz, FixedDiv(s<watertop+(16<tracer)) - { - for (seg = base, dist = 112*FRACUNIT, s = 9; seg; seg = seg->hnext, dist += 132*FRACUNIT, --s) - { - seg->z = bz + FixedMul(fz, FixedDiv(s<x + P_ReturnThrustX(mobj, angle, dist), mobj->y + P_ReturnThrustY(mobj, angle, dist), true); - } - angle += ANGLE_MAX/3; - } -} - -// Destroy cage FOFs. -static void P_Boss4DestroyCage(void) -{ - const UINT16 tag = 65534; - INT32 snum, next; - size_t a; - sector_t *sector, *rsec; - ffloor_t *rover; - - // This will be the final iteration of sector tag. - // We'll destroy the tag list as we go. - next = sectors[tag%numsectors].firsttag; - sectors[tag%numsectors].firsttag = -1; - - for (snum = next; snum != -1; snum = next) - { - sector = §ors[snum]; - - next = sector->nexttag; - sector->nexttag = -1; - if (sector->tag != tag) - continue; - sector->tag = 0; - - // Destroy the FOFs. - for (a = 0; a < sector->numattached; a++) - { - rsec = §ors[sector->attached[a]]; - for (rover = rsec->ffloors; rover; rover = rover->next) - if (rover->flags & FF_EXISTS && rover->secnum == (size_t)snum) - { - if (rover->flags & FF_RENDERALL) // checking for FF_RENDERANY. - EV_CrumbleChain(rsec, rover); // This FOF is visible to some extent? Crumble it. - else // Completely invisible FOF - { - // no longer exists (can't collide with again) - rover->flags &= ~FF_EXISTS; - sector->moved = true; - rsec->moved = true; - } - } - } - } -} - -// Destroy Boss4's arms -static void P_Boss4PopSpikeballs(mobj_t *mobj) -{ - mobj_t *base = mobj->tracer, *seg, *next; - P_SetTarget(&mobj->tracer, NULL); - while(base) - { - next = base->tracer; - P_SetTarget(&base->tracer, NULL); - for (seg = base; seg; seg = seg->hnext) - if (seg->health) - P_KillMobj(seg, NULL, NULL); - base = next; - } -} - -// -// AI for the fourth boss. -// -static void P_Boss4Thinker(mobj_t *mobj) -{ - if ((statenum_t)(mobj->state-states) == mobj->info->spawnstate) - { - if (mobj->health > mobj->info->damage || mobj->movedir == 4) - mobj->flags2 &= ~MF2_FRET; - mobj->reactiontime = 0; // Drop the cage immediately. - } - - // Oh no, we dead? D: - if (!mobj->health) - { - if (mobj->tracer) // need to clean up! - { - P_Boss4DestroyCage(); // Just in case pinch phase was skipped. - P_Boss4PopSpikeballs(mobj); - } - return; - } - - // movedir == battle stage: - // 0: initialization - // 1: phase 1 forward - // 2: phase 1 reverse - // 3: pinch rise - // 4: pinch phase - switch(mobj->movedir) - { - // WELCOME to your DOOM! - case 0: - { - // For this stage only: - // movecount == cage height - // threshold == cage momz - if (mobj->movecount == 0) // Initialize stage! - { - fixed_t z; - INT32 i, arm; - mobj_t *seg, *base = mobj; - // First frame init, spawn all the things. - mobj->watertop = mobj->z; - z = mobj->z + mobj->height/2 - mobjinfo[MT_EGGMOBILE4_MACE].height/2; - for (arm = 0; arm <3 ; arm++) - { - seg = P_SpawnMobj(mobj->x, mobj->y, z, MT_EGGMOBILE4_MACE); - P_SetTarget(&base->tracer, seg); - base = seg; - P_SetTarget(&seg->target, mobj); - for (i = 0; i < 9; i++) - { - seg->hnext = P_SpawnMobj(mobj->x, mobj->y, z, MT_EGGMOBILE4_MACE); - seg->hnext->hprev = seg; - seg = seg->hnext; - } - } - // Move the cage up to the sky. - mobj->movecount = 800*FRACUNIT; - if (!P_Boss4MoveCage(mobj->movecount)) - { - mobj->movecount = 0; - mobj->threshold = 3*TICRATE; - mobj->extravalue1 = 1; - mobj->movedir++; // We don't have a cage, just continue. - } - else - P_Boss4MoveSpikeballs(mobj, 0, mobj->movecount); - } - else // Cage slams down over Eggman's head! - { - fixed_t oldz = mobj->movecount; - mobj->threshold -= 5*FRACUNIT; - mobj->movecount += mobj->threshold; - if (mobj->movecount < 0) - mobj->movecount = 0; - P_Boss4MoveCage(mobj->movecount - oldz); - P_Boss4MoveSpikeballs(mobj, 0, mobj->movecount); - if (mobj->movecount == 0) - { - mobj->threshold = 3*TICRATE; - mobj->extravalue1 = 1; - P_LinedefExecute(LE_BOSS4DROP, mobj, NULL); - mobj->movedir++; // Initialization complete, next phase! - } - } - return; - } - - // Normal operation - case 1: - case 2: - break; - - // Pinch phase init! - case 3: - { - fixed_t z; - if (mobj->z < mobj->watertop+(512<momz = 8*FRACUNIT; - else - { - mobj->momz = 0; - mobj->movedir++; - } - mobj->movecount += 400<<(FRACBITS>>1); - mobj->movecount %= 360*FRACUNIT; - z = mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2; - if (z < 0) // We haven't risen high enough to pull the spikeballs along yet - P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), 0); // So don't pull the spikeballs along yet. - else - P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), z); - return; - } - // Pinch phase! - case 4: - { - if (mobj->z < (mobj->watertop + ((512+128*(mobj->info->damage-mobj->health))<momz = 8*FRACUNIT; - else - mobj->momz = 0; - mobj->movecount += (800+800*(mobj->info->damage-mobj->health))<<(FRACBITS>>1); - mobj->movecount %= 360*FRACUNIT; - P_Boss4PinchSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->z - mobj->watertop - mobjinfo[MT_EGGMOBILE4_MACE].height - mobj->height/2); - - if (!mobj->target || !mobj->target->health) - P_SupermanLook4Players(mobj); - A_FaceTarget(mobj); - return; - } - - default: // ????? - return; - } - - // Haahahahahaaa, and let the FUN.. BEGIN! - // movedir == arms direction - // movecount == arms angle - // threshold == countdown to next attack - // reactiontime == cage raise, speed burst - // movefactor == cage z - // friction == turns until helm lift - - // Raise the cage! - if (mobj->reactiontime == 1) - { - fixed_t oldz = mobj->movefactor; - mobj->movefactor += 8*FRACUNIT; - if (mobj->movefactor > 128*FRACUNIT) - mobj->movefactor = 128*FRACUNIT; - P_Boss4MoveCage(mobj->movefactor - oldz); - } - // Drop the cage! - else if (mobj->movefactor) - { - fixed_t oldz = mobj->movefactor; - mobj->movefactor -= 4*FRACUNIT; - if (mobj->movefactor < 0) - mobj->movefactor = 0; - P_Boss4MoveCage(mobj->movefactor - oldz); - if (!mobj->movefactor) - { - if (mobj->health <= mobj->info->damage) - { // Proceed to pinch phase! - P_Boss4DestroyCage(); - mobj->movedir = 3; - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - return; - } - P_LinedefExecute(LE_BOSS4DROP, mobj, NULL); - } - } - - { - fixed_t movespeed = 170<<(FRACBITS>>1); - if (mobj->reactiontime == 2) - movespeed *= 3; - if (mobj->movedir == 2) - mobj->movecount -= movespeed; - else - mobj->movecount += movespeed; - } - mobj->movecount %= 360*FRACUNIT; - P_Boss4MoveSpikeballs(mobj, FixedAngle(mobj->movecount), mobj->movefactor); - - // Check for attacks, always tick the timer even while animating!! - if (!(mobj->flags2 & MF2_FRET) // but pause for pain so we don't interrupt pinch phase, eep! - && mobj->threshold-- == 0) - { - // 5 -> 2.5 second timer - mobj->threshold = 5*TICRATE-(TICRATE/2)*(mobj->info->spawnhealth-mobj->health); - if (mobj->threshold < 1) - mobj->threshold = 1; - - if (mobj->extravalue1-- == 0) - { - P_SetMobjState(mobj, mobj->info->raisestate); - mobj->extravalue1 = 3; - } - else - { - if (mobj->reactiontime == 1) // Cage is raised? - mobj->reactiontime = 0; // Drop it! - switch(P_RandomKey(10)) - { - // Telegraph Right (Speed Up!!) - case 1: - case 3: - case 4: - case 5: - case 6: - P_SetMobjState(mobj, mobj->info->missilestate); - break; - // Telegraph Left (Reverse Direction) - default: - P_SetMobjState(mobj, mobj->info->meleestate); - break; - } - } - } - - // Leave if animating. - if ((statenum_t)(mobj->state-states) != mobj->info->spawnstate) - return; - - // Map allows us to get killed despite cage being down? - if (mobj->health <= mobj->info->damage) - { // Proceed to pinch phase! - P_Boss4DestroyCage(); - // spawn jet's flame now you're flying upwards - // tracer is already used, so if this ever gets reached again we've got problems - var1 = 3; - A_BossJetFume(mobj); - mobj->movedir = 3; - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - return; - } - - mobj->reactiontime = 0; // Drop the cage if it hasn't been dropped already. - if (!mobj->target || !mobj->target->health) - P_SupermanLook4Players(mobj); - A_FaceTarget(mobj); -} - -// -// AI for Black Eggman -// Note: You CANNOT have more than ONE Black Eggman -// in a level! Just don't try it! -// -static void P_Boss7Thinker(mobj_t *mobj) -{ - if (!mobj->target || !(mobj->target->flags & MF_SHOOTABLE)) - { - // look for a new target - if (P_BossTargetPlayer(mobj, false)) - return; // got a new target - - P_SetMobjStateNF(mobj, mobj->info->spawnstate); - return; - } - - if (mobj->health >= mobj->info->spawnhealth && (leveltime & 14) == 0) - { - mobj_t *smoke = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height, MT_SMOKE); - smoke->destscale = mobj->destscale; - P_SetScale(smoke, smoke->destscale); - smoke->momz = FixedMul(FRACUNIT, smoke->scale); - } - - if (mobj->state == &states[S_BLACKEGG_STND] && mobj->tics == mobj->state->tics) - { - mobj->reactiontime += P_RandomByte(); - - if (mobj->health <= mobj->info->damage) - mobj->reactiontime /= 4; - } - else if (mobj->state == &states[S_BLACKEGG_DIE4] && mobj->tics == mobj->state->tics) - A_BossDeath(mobj); - else if (mobj->state >= &states[S_BLACKEGG_WALK1] - && mobj->state <= &states[S_BLACKEGG_WALK6]) - A_Boss7Chase(mobj); - else if (mobj->state == &states[S_BLACKEGG_PAIN1] && mobj->tics == mobj->state->tics) - { - if (mobj->health > 0) - mobj->health--; - - S_StartSound(0, (mobj->health) ? sfx_behurt : sfx_bedie2); - - mobj->reactiontime /= 3; - - if (mobj->health <= 0) - { - INT32 i; - - P_KillMobj(mobj, NULL, NULL); - - // It was a team effort - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i]) - continue; - - P_AddPlayerScore(&players[i], 1000); - } - } - } - else if (mobj->state == &states[S_BLACKEGG_PAIN35] && mobj->tics == 1) - { - if (mobj->health == mobj->info->damage) - { - // Begin platform destruction - mobj->flags2 |= MF2_FRET; - P_SetMobjState(mobj, mobj->info->raisestate); - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - } - } - else if (mobj->state == &states[S_BLACKEGG_HITFACE4] && mobj->tics == mobj->state->tics) - { - // This is where Black Eggman hits his face. - // If a player is on top of him, the player gets hurt. - // But, if the player has managed to escape, - // Black Eggman gets hurt! - INT32 i; - mobj->state->nextstate = mobj->info->painstate; // Reset - - S_StartSound(0, sfx_bedeen); - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y) > (mobj->radius + players[i].mo->radius)) - continue; - - if (players[i].mo->z > mobj->z + mobj->height - FRACUNIT - && players[i].mo->z < mobj->z + mobj->height + 128*FRACUNIT) // You can't be in the vicinity, either... - { - // Punch him! - P_DamageMobj(players[i].mo, mobj, mobj, 1); - mobj->state->nextstate = mobj->info->spawnstate; - - // Laugh - S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); - } - } - } - else if (mobj->state == &states[S_BLACKEGG_GOOP]) - { - // Lob cannon balls - if (mobj->movecount-- <= 0 || !mobj->target) - { - P_SetMobjState(mobj, mobj->info->spawnstate); - return; - } - - if ((leveltime & 15) == 0) - { - var1 = MT_CANNONBALL; - - var2 = 2*TICRATE + (80<<16); - - A_LobShot(mobj); - S_StartSound(0, sfx_begoop); - } - } - else if (mobj->state == &states[S_BLACKEGG_SHOOT2]) - { - // Chaingun goop - mobj_t *missile; - - if (mobj->movecount-- <= 0 || !mobj->target) - { - P_SetMobjState(mobj, mobj->info->spawnstate); - return; - } - - A_FaceTarget(mobj); - - missile = P_SpawnXYZMissile(mobj, mobj->target, MT_BLACKEGGMAN_GOOPFIRE, - mobj->x + P_ReturnThrustX(mobj, mobj->angle-ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)), - mobj->y + P_ReturnThrustY(mobj, mobj->angle-ANGLE_90, FixedDiv(mobj->radius, 3*FRACUNIT/2)+(4*FRACUNIT)), - mobj->z + FixedDiv(mobj->height, 3*FRACUNIT/2)); - - S_StopSound(missile); - - if (leveltime & 1) - S_StartSound(0, sfx_beshot); - } - else if (mobj->state == &states[S_BLACKEGG_JUMP1] && mobj->tics == 1) - { - mobj_t *hitspot = NULL, *mo2; - angle_t an; - fixed_t dist, closestdist; - fixed_t vertical, horizontal; - fixed_t airtime = 5*TICRATE; - INT32 waypointNum = 0; - thinker_t *th; - INT32 i; - boolean foundgoop = false; - INT32 closestNum; - - // Looks for players in goop. If you find one, try to jump on him. - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (players[i].powers[pw_ingoop]) - { - closestNum = -1; - closestdist = 16384*FRACUNIT; // Just in case... - - // Find waypoint he is closest to - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint) - { - dist = P_AproxDistance(players[i].mo->x - mo2->x, players[i].mo->y - mo2->y); - - if (closestNum == -1 || dist < closestdist) - { - closestNum = (mo2->spawnpoint->options & 7); - closestdist = dist; - foundgoop = true; - } - } - } - waypointNum = closestNum; - break; - } - } - - if (!foundgoop) - { - if (mobj->z > 1056*FRACUNIT) - waypointNum = 0; - else - waypointNum = 1 + P_RandomKey(4); - } - - // Don't jump to the center when health is low. - // Force the player to beat you with missiles. - if (mobj->health <= mobj->info->damage && waypointNum == 0) - waypointNum = 1 + P_RandomKey(4); - - if (mobj->tracer && mobj->tracer->type == MT_BOSS3WAYPOINT - && mobj->tracer->spawnpoint && (mobj->tracer->spawnpoint->options & 7) == waypointNum) - { - if (P_RandomChance(FRACUNIT/2)) - waypointNum++; - else - waypointNum--; - - waypointNum %= 5; - - if (waypointNum < 0) - waypointNum = 0; - } - - if (waypointNum == 0 && mobj->health <= mobj->info->damage) - waypointNum = 1 + (P_RandomFixed() & 1); - - // scan the thinkers to find - // the waypoint to use - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS3WAYPOINT && mo2->spawnpoint && (mo2->spawnpoint->options & 7) == waypointNum) - { - hitspot = mo2; - break; - } - } - - if (hitspot == NULL) - { - CONS_Debug(DBG_GAMELOGIC, "BlackEggman unable to find waypoint #%d!\n", waypointNum); - P_SetMobjState(mobj, mobj->info->spawnstate); - return; - } - - P_SetTarget(&mobj->tracer, hitspot); - - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, hitspot->x, hitspot->y); - - an = mobj->angle; - an >>= ANGLETOFINESHIFT; - - dist = P_AproxDistance(hitspot->x - mobj->x, hitspot->y - mobj->y); - - horizontal = dist / airtime; - vertical = (gravity*airtime)/2; - - mobj->momx = FixedMul(horizontal, FINECOSINE(an)); - mobj->momy = FixedMul(horizontal, FINESINE(an)); - mobj->momz = vertical; - -// mobj->momz = 10*FRACUNIT; - } - else if (mobj->state == &states[S_BLACKEGG_JUMP2] && mobj->z <= mobj->floorz) - { - // BANG! onto the ground - INT32 i,j; - fixed_t ns; - fixed_t x,y,z; - mobj_t *mo2; - - S_StartSound(0, sfx_befall); - - z = mobj->floorz; - for (j = 0; j < 2; j++) - { - for (i = 0; i < 32; i++) - { - const angle_t fa = (i*FINEANGLES/16) & FINEMASK; - ns = 64 * FRACUNIT; - x = mobj->x + FixedMul(FINESINE(fa),ns); - y = mobj->y + FixedMul(FINECOSINE(fa),ns); - - mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); - ns = 16 * FRACUNIT; - mo2->momx = FixedMul(FINESINE(fa),ns); - mo2->momy = FixedMul(FINECOSINE(fa),ns); - } - z -= 32*FRACUNIT; - } - - // Hurt player?? - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - if (players[i].mo->health <= 0) - continue; - - if (P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y) > mobj->radius*4) - continue; - - if (players[i].mo->z > mobj->z + 128*FRACUNIT) - continue; - - if (players[i].mo->z < mobj->z - 64*FRACUNIT) - continue; - - P_DamageMobj(players[i].mo, mobj, mobj, 1); - - // Laugh - S_StartSound(0, sfx_bewar1 + P_RandomKey(4)); - } - - P_SetMobjState(mobj, mobj->info->spawnstate); - } - else if (mobj->state == &states[mobj->info->deathstate] && mobj->tics == mobj->state->tics) - S_StartSound(0, sfx_bedie1 + (P_RandomFixed() & 1)); - -} - -// Metal Sonic battle boss -// You CAN put multiple Metal Sonics in a single map -// because I am a totally competent programmer who can do shit right. -static void P_Boss9Thinker(mobj_t *mobj) -{ - if ((statenum_t)(mobj->state-states) == mobj->info->spawnstate) - mobj->flags2 &= ~MF2_FRET; - - if (!mobj->tracer) - { - thinker_t *th; - mobj_t *mo2; - mobj_t *last=NULL; - - // Initialize the boss, spawn jet fumes, etc. - mobj->threshold = 0; - mobj->reactiontime = 0; - mobj->watertop = mobj->floorz + 32*FRACUNIT; - var1 = 2; - A_BossJetFume(mobj); - - // Run through the thinkers ONCE and find all of the MT_BOSS9GATHERPOINT in the map. - // Build a hoop linked list of 'em! - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (mo2->type == MT_BOSS9GATHERPOINT) - { - if (last) - last->hnext = mo2; - else - mobj->hnext = mo2; - mo2->hprev = last; - last = mo2; - } - } - } - - if (mobj->health <= 0) - return; - - if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) - { - P_BossTargetPlayer(mobj, false); - if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING)) - P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first - if (!mobj->target) // Still no target, aww. - { - // Reset the boss. - P_SetMobjState(mobj, mobj->info->spawnstate); - mobj->fuse = 0; - mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2)); - mobj->momy = FixedDiv(mobj->momy, FRACUNIT + (FRACUNIT>>2)); - mobj->momz = FixedDiv(mobj->momz, FRACUNIT + (FRACUNIT>>2)); - return; - } - else if (!mobj->fuse) - mobj->fuse = 10*TICRATE; - } - - // AI goes here. - { - boolean danger = true; - angle_t angle; - if (mobj->threshold) - mobj->momz = (mobj->watertop-mobj->z)/16; // Float to your desired position FASTER - else - mobj->momz = (mobj->watertop-mobj->z)/40; // Float to your desired position - - if (mobj->movecount == 2) { - mobj_t *spawner; - fixed_t dist = 0; - angle = 0x06000000*leveltime; - - // Alter your energy bubble's size/position - if (mobj->health > 3) { - mobj->tracer->destscale = FRACUNIT + (4*TICRATE - mobj->fuse)*(FRACUNIT/2)/TICRATE + FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),FRACUNIT/2); - P_SetScale(mobj->tracer, mobj->tracer->destscale); - P_TeleportMove(mobj->tracer, mobj->x, mobj->y, mobj->z + mobj->height/2 - mobj->tracer->height/2); - mobj->tracer->momx = mobj->momx; - mobj->tracer->momy = mobj->momy; - mobj->tracer->momz = mobj->momz; - } - - // Face your target - P_BossTargetPlayer(mobj, true); - angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); // absolute angle - angle = (angle-mobj->angle); // relative angle - if (angle < ANGLE_180) - mobj->angle += angle/8; - else - mobj->angle -= InvAngle(angle)/8; - - // Spawn energy particles - for (spawner = mobj->hnext; spawner; spawner = spawner->hnext) { - dist = P_AproxDistance(spawner->x - mobj->x, spawner->y - mobj->y); - if (P_RandomRange(1,(dist>>FRACBITS)/16) == 1) - break; - } - if (spawner) { - mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); - missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/4); - if (dist == 0) - missile->fuse = 0; - else - missile->fuse = (dist/P_AproxDistance(missile->momx, missile->momy)); - if (missile->fuse > mobj->fuse) - P_RemoveMobj(missile); - } - } - - // Pre-threshold reactiontime stuff for attack phases - if (mobj->reactiontime && mobj->movecount == 3) { - if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase - if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh? - mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3 - else - mobj->watertop = mobj->target->floorz + 16*FRACUNIT; - if (!(mobj->threshold%4)) - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); - } - // Pausing between energy ball shots - mobj->reactiontime--; - return; - } - - // threshold is used for attacks/maneuvers. - if (mobj->threshold) { - fixed_t speed = 20*FRACUNIT + FixedMul(40*FRACUNIT, FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth<movecount == 3 && mobj->movedir == 1) { - if (!(mobj->threshold&1)) { - mobj_t *missile; - if (mobj->info->seesound) - S_StartSound(mobj, mobj->info->seesound); - P_SetMobjState(mobj, mobj->info->missilestate); - if (mobj->extravalue1 == 3) - mobj->reactiontime = TICRATE/16; - else - mobj->reactiontime = TICRATE/8; - - A_FaceTarget(mobj); - missile = P_SpawnMissile(mobj, mobj->target, mobj->info->speed); - if (mobj->extravalue1 == 2 || mobj->extravalue1 == 3) { - missile->destscale = FRACUNIT>>1; - P_SetScale(missile, missile->destscale); - } - missile->fuse = 3*TICRATE; - missile->z -= missile->height/2; - - if (mobj->extravalue1 == 2) { - int i; - mobj_t *spread; - missile->flags |= MF_MISSILE; - for (i = 0; i < 5; i++) { - if (i == 2) - continue; - spread = P_SpawnMobj(missile->x, missile->y, missile->z, missile->type); - spread->angle = missile->angle+(ANGLE_11hh/2)*(i-2); - P_InstaThrust(spread,spread->angle,spread->info->speed); - spread->momz = missile->momz; - spread->destscale = FRACUNIT>>1; - P_SetScale(spread, spread->destscale); - spread->fuse = 3*TICRATE; - } - missile->flags &= ~MF_MISSILE; - } - } else { - P_SetMobjState(mobj, mobj->state->nextstate); - if (mobj->extravalue1 == 3) - mobj->reactiontime = TICRATE/8; - else - mobj->reactiontime = TICRATE/4; - } - mobj->threshold--; - return; - } - - P_SpawnGhostMobj(mobj); - - // Pinball attack! - if (mobj->movecount == 3 && (mobj->movedir == 0 || mobj->movedir == 2)) { - if ((statenum_t)(mobj->state-states) != mobj->info->seestate) - P_SetMobjState(mobj, mobj->info->seestate); - if (mobj->movedir == 0) // mobj health == 1 - P_InstaThrust(mobj, mobj->angle, 38*FRACUNIT); - else if (mobj->health == 3) - P_InstaThrust(mobj, mobj->angle, 22*FRACUNIT); - else // mobj health == 2 - P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT); - if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce - mobj->threshold--; - if (mobj->threshold) { - P_SetMobjState(mobj, mobj->state->nextstate); - if (mobj->info->mass) - S_StartSound(mobj, mobj->info->mass); - if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); - mobj->reactiontime = TICRATE; // targetting time - } else { // No homing, just use P_BounceMove - P_BounceMove(mobj); - mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); - mobj->reactiontime = TICRATE/4; // just a pause before you bounce away - } - mobj->momx = mobj->momy = 0; - } - } - return; - } - - // Vector form dodge! - mobj->angle += mobj->movedir; - P_InstaThrust(mobj, mobj->angle, -speed); - while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) { - mobj->angle += mobj->movedir; - P_InstaThrust(mobj, mobj->angle, -speed); - } - mobj->momx = mobj->momy = 0; - mobj->threshold--; - if (!mobj->threshold) - { // Go into stun after dodge. - // from 3*TICRATE down to 1.25*TICRATE - //mobj->reactiontime = 5*TICRATE/4 + (FixedMul((7*TICRATE/4)<health-1)<info->spawnhealth-1)<>FRACBITS); - // from 3*TICRATE down to 2*TICRATE - mobj->reactiontime = 2*TICRATE + (FixedMul((1*TICRATE)<health-1)<info->spawnhealth-1)<>FRACBITS); - mobj->flags |= MF_SPECIAL|MF_SHOOTABLE; - P_SetMobjState(mobj, mobj->state->nextstate); - } - return; - } - - angle = 0x06000000*leveltime; - mobj->momz += FixedMul(FINECOSINE(angle>>ANGLETOFINESHIFT),2*FRACUNIT); // Use that "angle" to bob gently in the air - // This is below threshold because we don't want to bob while zipping around - - // Ohh you're in for it now.. - if (mobj->flags2 & MF2_FRET && mobj->health <= mobj->info->damage) - mobj->fuse = 0; - - // reactiontime is used for delays. - if (mobj->reactiontime) - { - // Stunned after vector form - if (mobj->movedir > ANGLE_180) - mobj->angle -= FixedAngle(FixedMul(AngleFixed(InvAngle(mobj->movedir)),FixedDiv(mobj->reactiontime<angle += FixedAngle(FixedMul(AngleFixed(mobj->movedir),FixedDiv(mobj->reactiontime<reactiontime--; - if (!mobj->reactiontime) - // Out of stun. - P_SetMobjState(mobj, mobj->state->nextstate); - return; - } - - // Not stunned? Can hit. - // Here because stun won't always get the chance to complete due to pinch phase activating, being hit, etc. - mobj->flags &= ~(MF_SPECIAL|MF_SHOOTABLE); - - if (mobj->health <= mobj->info->damage && mobj->fuse && !(mobj->fuse%TICRATE)) - { - var1 = 1; - var2 = 0; - A_BossScream(mobj); - } - - // Don't move if we're still in pain! - if (mobj->flags2 & MF2_FRET) - return; - - if (mobj->state == &states[mobj->info->raisestate]) - { // Charging energy - if (mobj->momx != 0 || mobj->momy != 0) { // Apply the air breaks - if (abs(mobj->momx)+abs(mobj->momy) < FRACUNIT) - mobj->momx = mobj->momy = 0; - else - P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -6*FRACUNIT/8); - } - return; - } - - if (mobj->fuse == 0) - { - // It's time to attack! What are we gonna do?! - switch(mobj->movecount) - { - case 0: - default: - // Fly up and prepare for an attack! - // We have to charge up first, so let's go up into the air - P_SetMobjState(mobj, mobj->info->raisestate); - if (mobj->floorz >= mobj->target->floorz) - mobj->watertop = mobj->floorz + 256*FRACUNIT; - else - mobj->watertop = mobj->target->floorz + 256*FRACUNIT; - break; - - case 1: { - // Okay, we're up? Good, time to gather energy... - if (mobj->health > mobj->info->damage) - { // No more bubble if we're broken (pinch phase) - mobj_t *shield = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_MSSHIELD_FRONT); - P_SetTarget(&mobj->tracer, shield); - P_SetTarget(&shield->target, mobj); - } - else - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - mobj->fuse = 4*TICRATE; - mobj->flags |= MF_PAIN; - if (mobj->info->attacksound) - S_StartSound(mobj, mobj->info->attacksound); - A_FaceTarget(mobj); - break; - } - - case 2: - // We're all charged and ready now! Unleash the fury!! - if (mobj->health > mobj->info->damage) - { - mobj_t *removemobj = mobj->tracer; - P_SetTarget(&mobj->tracer, mobj->hnext); - P_RemoveMobj(removemobj); - } - if (mobj->health <= mobj->info->damage) { - // Attack 1: Pinball dash! - if (mobj->health == 1) - mobj->movedir = 0; - else - mobj->movedir = 2; - if (mobj->info->seesound) - S_StartSound(mobj, mobj->info->seesound); - P_SetMobjState(mobj, mobj->info->seestate); - if (mobj->movedir == 2) - mobj->threshold = 16; // bounce 16 times - else - mobj->threshold = 32; // bounce 32 times - mobj->watertop = mobj->target->floorz + 16*FRACUNIT; - P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); - } else { - // Attack 2: Energy shot! - mobj->movedir = 1; - - if (mobj->health >= 8) - mobj->extravalue1 = 0; - else if (mobj->health >= 5) - mobj->extravalue1 = 2; - else if (mobj->health >= 4) - mobj->extravalue1 = 1; - else - mobj->extravalue1 = 3; - - switch(mobj->extravalue1) { - case 0: // shoot once - case 2: // spread-shot - default: - mobj->threshold = 2; - break; - case 1: // shoot 3 times - mobj->threshold = 3*2; - break; - case 3: // shoot like a goddamn machinegun - mobj->threshold = 8*2; - break; - } - } - break; - - case 3: - // Return to idle. - mobj->watertop = mobj->target->floorz + 32*FRACUNIT; - P_SetMobjState(mobj, mobj->info->spawnstate); - mobj->flags &= ~MF_PAIN; - mobj->fuse = 10*TICRATE; - break; - } - mobj->movecount++; - mobj->movecount %= 4; - return; - } - - // Idle AI - if (mobj->state == &states[mobj->info->spawnstate]) - { - fixed_t dist; - - // Target the closest player - P_BossTargetPlayer(mobj, true); - - // Face your target - angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); // absolute angle - angle = (angle-mobj->angle); // relative angle - if (angle < ANGLE_180) - mobj->angle += angle/8; - else - mobj->angle -= InvAngle(angle)/8; - //A_FaceTarget(mobj); - - // Check if we're being attacked - if (!(mobj->target->player->pflags & (PF_JUMPED|PF_SPINNING) - || mobj->target->player->powers[pw_tailsfly] - || mobj->target->player->powers[pw_invulnerability] - || mobj->target->player->powers[pw_super])) - danger = false; - if (mobj->target->x+mobj->target->radius+abs(mobj->target->momx*2) < mobj->x-mobj->radius) - danger = false; - if (mobj->target->x-mobj->target->radius-abs(mobj->target->momx*2) > mobj->x+mobj->radius) - danger = false; - if (mobj->target->y+mobj->target->radius+abs(mobj->target->momy*2) < mobj->y-mobj->radius) - danger = false; - if (mobj->target->y-mobj->target->radius-abs(mobj->target->momy*2) > mobj->y+mobj->radius) - danger = false; - if (mobj->target->z+mobj->target->height+mobj->target->momz*2 < mobj->z) - danger = false; - if (mobj->target->z+mobj->target->momz*2 > mobj->z+mobj->height) - danger = false; - if (danger) { - // An incoming attack is detected! What should we do?! - // Go into vector form! - mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth-1)<movedir = InvAngle(mobj->movedir); - mobj->threshold = 6 + (FixedMul(24<info->spawnhealth - mobj->health)<info->spawnhealth-1)<>FRACBITS); - if (mobj->info->activesound) - S_StartSound(mobj, mobj->info->activesound); - if (mobj->info->painchance) - P_SetMobjState(mobj, mobj->info->painchance); - return; - } - - // Move normally: Approach the player using normal thrust and simulated friction. - dist = P_AproxDistance(mobj->x-mobj->target->x, mobj->y-mobj->target->y); - P_Thrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy), -3*FRACUNIT/8); - if (dist < 64*FRACUNIT) - P_Thrust(mobj, mobj->angle, -4*FRACUNIT); - else if (dist > 180*FRACUNIT) - P_Thrust(mobj, mobj->angle, FRACUNIT); - mobj->momz += P_AproxDistance(mobj->momx, mobj->momy)/12; // Move up higher the faster you're going. - } - } -} - // // P_GetClosestAxis // @@ -5699,9 +3788,9 @@ mobj_t *P_GetClosestAxis(mobj_t *source) fixed_t dist1, dist2 = 0; // scan the thinkers to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mo2 = (mobj_t *)th; @@ -5942,8 +4031,8 @@ void P_SetScale(mobj_t *mobj, fixed_t newscale) mobj->scale = newscale; - mobj->radius = FixedMul(mobj->info->radius, newscale); - mobj->height = FixedMul(mobj->info->height, newscale); + mobj->radius = FixedMul(FixedDiv(mobj->radius, oldscale), newscale); + mobj->height = FixedMul(FixedDiv(mobj->height, oldscale), newscale); player = mobj->player; @@ -5951,16 +4040,17 @@ void P_SetScale(mobj_t *mobj, fixed_t newscale) { G_GhostAddScale((INT32) (player - players), newscale); player->viewheight = FixedMul(FixedDiv(player->viewheight, oldscale), newscale); // Nonono don't calculate viewheight elsewhere, this is the best place for it! - player->dashspeed = FixedMul(FixedDiv(player->dashspeed, oldscale), newscale); // Prevents the player from having to re-charge up spindash if the player grew in size } } void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on your target { fixed_t dist, ndist, speedmul; + angle_t vangle; fixed_t tx = dest->x; fixed_t ty = dest->y; fixed_t tz = dest->z + (dest->height/2); // Aim for center + fixed_t xydist = P_AproxDistance(tx - source->x, ty - source->y); if (!dest || dest->health <= 0 || !dest->player || !source->tracer) return; @@ -5969,19 +4059,40 @@ void P_Attract(mobj_t *source, mobj_t *dest, boolean nightsgrab) // Home in on y //source->angle = R_PointToAngle2(source->x, source->y, tx, ty); // change slope - dist = P_AproxDistance(P_AproxDistance(tx - source->x, ty - source->y), tz - source->z); + dist = P_AproxDistance(xydist, tz - source->z); if (dist < 1) dist = 1; - if (nightsgrab) - speedmul = P_AproxDistance(dest->momx, dest->momy) + source->scale; - else - speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(source->info->speed, source->scale); + if (nightsgrab && source->movefactor) + { + source->movefactor += FRACUNIT/2; - source->momx = FixedMul(FixedDiv(tx - source->x, dist), speedmul); - source->momy = FixedMul(FixedDiv(ty - source->y, dist), speedmul); - source->momz = FixedMul(FixedDiv(tz - source->z, dist), speedmul); + if (dist < source->movefactor) + { + source->momx = source->momy = source->momz = 0; + P_TeleportMove(source, tx, ty, tz); + } + else + { + vangle = R_PointToAngle2(source->z, 0, tz, xydist); + + source->momx = FixedMul(FINESINE(vangle >> ANGLETOFINESHIFT), FixedMul(FINECOSINE(source->angle >> ANGLETOFINESHIFT), source->movefactor)); + source->momy = FixedMul(FINESINE(vangle >> ANGLETOFINESHIFT), FixedMul(FINESINE(source->angle >> ANGLETOFINESHIFT), source->movefactor)); + source->momz = FixedMul(FINECOSINE(vangle >> ANGLETOFINESHIFT), source->movefactor); + } + } + else + { + if (nightsgrab) + speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(8*FRACUNIT, source->scale); + else + speedmul = P_AproxDistance(dest->momx, dest->momy) + FixedMul(source->info->speed, source->scale); + + source->momx = FixedMul(FixedDiv(tx - source->x, dist), speedmul); + source->momy = FixedMul(FixedDiv(ty - source->y, dist), speedmul); + source->momz = FixedMul(FixedDiv(tz - source->z, dist), speedmul); + } // Instead of just unsetting NOCLIP like an idiot, let's check the distance to our target. ndist = P_AproxDistance(P_AproxDistance(tx - (source->x+source->momx), @@ -6006,6 +4117,7 @@ static void P_NightsItemChase(mobj_t *thing) { P_SetTarget(&thing->tracer, NULL); thing->flags2 &= ~MF2_NIGHTSPULL; + thing->movefactor = 0; return; } @@ -6015,7 +4127,223 @@ static void P_NightsItemChase(mobj_t *thing) P_Attract(thing, thing->tracer, true); } -/*static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) +// +// P_MaceRotate +// Spins a hnext-chain of objects around its centerpoint, side to side or periodically. +// +void P_MaceRotate(mobj_t *center, INT32 baserot, INT32 baseprevrot) +{ + TVector unit_lengthways, unit_sideways, pos_lengthways, pos_sideways; + TVector *res; + fixed_t radius, dist, zstore; + angle_t fa; + boolean dosound = false; + mobj_t *mobj = center->hnext, *hnext = NULL; + + INT32 lastthreshold = -1; // needs to never be equal at start of loop + fixed_t lastfriction = INT32_MIN; // ditto; almost certainly never, but... + + INT32 rot; + INT32 prevrot; + + dist = pos_sideways[0] = pos_sideways[1] = pos_sideways[2] = pos_sideways[3] = unit_sideways[3] =\ + pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0; + + while (mobj) + { + if (P_MobjWasRemoved(mobj) || !mobj->health) + { + mobj = mobj->hnext; + continue; + } + + mobj->momx = mobj->momy = mobj->momz = 0; + + if (mobj->threshold != lastthreshold + || mobj->friction != lastfriction) + { + rot = (baserot + mobj->threshold) & FINEMASK; + prevrot = (baseprevrot + mobj->threshold) & FINEMASK; + + pos_lengthways[0] = pos_lengthways[1] = pos_lengthways[2] = pos_lengthways[3] = 0; + + dist = ((mobj->info->speed) ? mobj->info->speed : mobjinfo[MT_SMALLMACECHAIN].speed); + dist = ((center->scale == FRACUNIT) ? dist : FixedMul(dist, center->scale)); + + fa = (FixedAngle(center->movefactor*FRACUNIT) >> ANGLETOFINESHIFT); + radius = FixedMul(dist, FINECOSINE(fa)); + unit_lengthways[1] = -FixedMul(dist, FINESINE(fa)); + unit_lengthways[3] = FRACUNIT; + + // Swinging Chain. + if (center->flags2 & MF2_STRONGBOX) + { + fixed_t swingmag = FixedMul(FINECOSINE(rot), center->lastlook << FRACBITS); + fixed_t prevswingmag = FINECOSINE(prevrot); + + if ((prevswingmag > 0) != (swingmag > 0)) // just passed its lowest point + dosound = true; + + fa = ((FixedAngle(swingmag) >> ANGLETOFINESHIFT) + mobj->friction) & FINEMASK; + + unit_lengthways[0] = FixedMul(FINESINE(fa), -radius); + unit_lengthways[2] = FixedMul(FINECOSINE(fa), -radius); + } + // Rotating Chain. + else + { + angle_t prevfa = (prevrot + mobj->friction) & FINEMASK; + fa = (rot + mobj->friction) & FINEMASK; + + if (!(prevfa > (FINEMASK/2)) && (fa > (FINEMASK/2))) // completed a full swing + dosound = true; + + unit_lengthways[0] = FixedMul(FINECOSINE(fa), radius); + unit_lengthways[2] = FixedMul(FINESINE(fa), radius); + } + + // Calculate the angle matrixes for the link. + res = VectorMatrixMultiply(unit_lengthways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT)); + M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways)); + res = VectorMatrixMultiply(unit_lengthways, *RotateZMatrix(center->angle)); + M_Memcpy(&unit_lengthways, res, sizeof(unit_lengthways)); + + lastthreshold = mobj->threshold; + lastfriction = mobj->friction; + } + + if (dosound && (mobj->flags2 & MF2_BOSSNOTRAP)) + { + S_StartSound(mobj, mobj->info->activesound); + dosound = false; + } + + if (pos_sideways[3] != mobj->movefactor) + { + if (!unit_sideways[3]) + { + unit_sideways[1] = dist; + unit_sideways[0] = unit_sideways[2] = 0; + unit_sideways[3] = FRACUNIT; + + res = VectorMatrixMultiply(unit_sideways, *RotateXMatrix(center->threshold << ANGLETOFINESHIFT)); + M_Memcpy(&unit_sideways, res, sizeof(unit_sideways)); + res = VectorMatrixMultiply(unit_sideways, *RotateZMatrix(center->angle)); + M_Memcpy(&unit_sideways, res, sizeof(unit_sideways)); + } + + if (pos_sideways[3] > mobj->movefactor) + { + do + { + pos_sideways[0] -= unit_sideways[0]; + pos_sideways[1] -= unit_sideways[1]; + pos_sideways[2] -= unit_sideways[2]; + } + while ((--pos_sideways[3]) != mobj->movefactor); + } + else + { + do + { + pos_sideways[0] += unit_sideways[0]; + pos_sideways[1] += unit_sideways[1]; + pos_sideways[2] += unit_sideways[2]; + } + while ((++pos_sideways[3]) != mobj->movefactor); + } + } + + hnext = mobj->hnext; // just in case the mobj is removed + + if (pos_lengthways[3] > mobj->movecount) + { + do + { + pos_lengthways[0] -= unit_lengthways[0]; + pos_lengthways[1] -= unit_lengthways[1]; + pos_lengthways[2] -= unit_lengthways[2]; + } + while ((--pos_lengthways[3]) != mobj->movecount); + } + else if (pos_lengthways[3] < mobj->movecount) + { + do + { + pos_lengthways[0] += unit_lengthways[0]; + pos_lengthways[1] += unit_lengthways[1]; + pos_lengthways[2] += unit_lengthways[2]; + } + while ((++pos_lengthways[3]) != mobj->movecount); + } + + P_UnsetThingPosition(mobj); + + mobj->x = center->x; + mobj->y = center->y; + mobj->z = center->z; + + // Add on the appropriate distances to the center's co-ordinates. + if (pos_lengthways[3]) + { + mobj->x += pos_lengthways[0]; + mobj->y += pos_lengthways[1]; + zstore = pos_lengthways[2] + pos_sideways[2]; + } + else + zstore = pos_sideways[2]; + + mobj->x += pos_sideways[0]; + mobj->y += pos_sideways[1]; + + // Cut the height to align the link with the axis. + if (mobj->type == MT_SMALLMACECHAIN || mobj->type == MT_BIGMACECHAIN || mobj->type == MT_SMALLGRABCHAIN || mobj->type == MT_BIGGRABCHAIN) + zstore -= P_MobjFlip(mobj)*mobj->height/4; + else + zstore -= P_MobjFlip(mobj)*mobj->height/2; + + mobj->z += zstore; + +#if 0 // toaster's testing flashie! + if (!(mobj->movecount & 1) && !(leveltime & TICRATE)) // I had a brainfart and the flashing isn't exactly what I expected it to be, but it's actually much more useful. + mobj->drawflags ^= MFD_DONTDRAW; +#endif + + P_SetThingPosition(mobj); + +#if 0 // toaster's height-clipping dealie! + if (!pos_lengthways[3] || P_MobjWasRemoved(mobj) || (mobj->flags & MF_NOCLIPHEIGHT)) + goto cont; + + if ((fa = ((center->threshold & (FINEMASK/2)) << ANGLETOFINESHIFT)) > ANGLE_45 && fa < ANGLE_135) // only move towards center when the motion is towards/away from the ground, rather than alongside it + goto cont; + + if (mobj->subsector->sector->ffloors) + P_AdjustMobjFloorZ_FFloors(mobj, mobj->subsector->sector, 2); + + if (mobj->floorz > mobj->z) + zstore = (mobj->floorz - zstore); + else if (mobj->ceilingz < mobj->z) + zstore = (mobj->ceilingz - mobj->height - zstore); + else + goto cont; + + zstore = FixedDiv(zstore, dist); // Still needs work... scaling factor is wrong! + + P_UnsetThingPosition(mobj); + + mobj->x -= FixedMul(unit_lengthways[0], zstore); + mobj->y -= FixedMul(unit_lengthways[1], zstore); + + P_SetThingPosition(mobj); + +cont: +#endif + mobj = hnext; + } +} + +static boolean P_ShieldLook(mobj_t *thing, shieldtype_t shield) { if (!thing->target || thing->target->health <= 0 || !thing->target->player || (thing->target->player->powers[pw_shield] & SH_NOSTACK) == SH_NONE || thing->target->player->powers[pw_super] @@ -6027,7 +4355,7 @@ static void P_NightsItemChase(mobj_t *thing) // TODO: Make an MT_SHIELDORB which changes color/states to always match the appropriate shield, // instead of having completely seperate mobjtypes. - if (shield != SH_FORCE) + if (!(shield & SH_FORCE)) { // Regular shields check for themselves only if ((shieldtype_t)(thing->target->player->powers[pw_shield] & SH_NOSTACK) != shield) { @@ -6041,9 +4369,9 @@ static void P_NightsItemChase(mobj_t *thing) return false; } - if (shield == SH_FORCE && thing->movecount != (thing->target->player->powers[pw_shield] & 0xFF)) + if (shield & SH_FORCE && thing->movecount != (thing->target->player->powers[pw_shield] & SH_FORCEHP)) { - thing->movecount = (thing->target->player->powers[pw_shield] & 0xFF); + thing->movecount = (thing->target->player->powers[pw_shield] & SH_FORCEHP); if (thing->movecount < 1) { if (thing->info->painstate) @@ -6064,13 +4392,14 @@ static void P_NightsItemChase(mobj_t *thing) thing->eflags = (thing->eflags & ~MFE_VERTICALFLIP)|(thing->target->eflags & MFE_VERTICALFLIP); P_SetScale(thing, thing->target->scale); + thing->destscale = thing->scale; P_UnsetThingPosition(thing); thing->x = thing->target->x; thing->y = thing->target->y; if (thing->eflags & MFE_VERTICALFLIP) - thing->z = thing->target->z + thing->target->height - thing->height + FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT) - FixedMul(2*FRACUNIT, thing->target->scale); + thing->z = thing->target->z + (thing->target->height - thing->height - FixedMul(2*FRACUNIT, thing->target->scale)); else - thing->z = thing->target->z - FixedDiv(P_GetPlayerHeight(thing->target->player) - thing->target->height, 3*FRACUNIT) + FixedMul(2*FRACUNIT, thing->target->scale); + thing->z = thing->target->z + FixedMul(2*FRACUNIT, thing->target->scale); P_SetThingPosition(thing); P_CheckPosition(thing, thing->x, thing->y); @@ -6093,7 +4422,7 @@ void P_RunShields(void) // run shields for (i = 0; i < numshields; i++) { - P_ShieldLook(shields[i], shields[i]->info->speed); + P_ShieldLook(shields[i], shields[i]->threshold); P_SetTarget(&shields[i], NULL); } numshields = 0; @@ -6101,7 +4430,7 @@ void P_RunShields(void) static boolean P_AddShield(mobj_t *thing) { - shieldtype_t shield = thing->info->speed; + shieldtype_t shield = thing->threshold; if (!thing->target || thing->target->health <= 0 || !thing->target->player || (thing->target->player->powers[pw_shield] & SH_NOSTACK) == SH_NONE || thing->target->player->powers[pw_super] @@ -6111,7 +4440,7 @@ static boolean P_AddShield(mobj_t *thing) return false; } - if (shield != SH_FORCE) + if (!(shield & SH_FORCE)) { // Regular shields check for themselves only if ((shieldtype_t)(thing->target->player->powers[pw_shield] & SH_NOSTACK) != shield) { @@ -6131,8 +4460,7 @@ static boolean P_AddShield(mobj_t *thing) P_SetTarget(&shields[numshields++], thing); return true; -}*/ - +} // Kartitem stuff. boolean P_IsKartItem(INT32 type) @@ -6214,6 +4542,13 @@ void P_RunOverlays(void) if (!mo->target) continue; + + if (P_MobjWasRemoved(mo->target)) + { + P_RemoveMobj(mo); + continue; + } + if (!r_splitscreen /*&& rendermode != render_soft*/) { angle_t viewingangle; @@ -6238,7 +4573,7 @@ void P_RunOverlays(void) mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP); mo->scale = mo->destscale = mo->target->scale; - mo->angle = mo->target->angle; + mo->angle = mo->target->angle + mo->movedir; if ((mo->flags & MF_DONTENCOREMAP) != (mo->target->flags & MF_DONTENCOREMAP)) mo->flags ^= MF_DONTENCOREMAP; @@ -6294,69 +4629,3767 @@ static void P_RemoveOverlay(mobj_t *thing) { mobj_t *mo; for (mo = overlaycap; mo; mo = mo->hnext) - if (mo->hnext == thing) - { - P_SetTarget(&mo->hnext, thing->hnext); - P_SetTarget(&thing->hnext, NULL); - return; - } -} - -void A_BossDeath(mobj_t *mo); -// AI for the Koopa boss. -static void P_KoopaThinker(mobj_t *koopa) -{ - P_MobjCheckWater(koopa); - - if (koopa->watertop > koopa->z + koopa->height + FixedMul(128*FRACUNIT, koopa->scale) && koopa->health > 0) { - A_BossDeath(koopa); - P_RemoveMobj(koopa); + if (mo->hnext != thing) + continue; + + P_SetTarget(&mo->hnext, thing->hnext); + P_SetTarget(&thing->hnext, NULL); return; } +} - // Koopa moves ONLY on the X axis! - if (koopa->threshold > 0) +static void P_MobjScaleThink(mobj_t *mobj) +{ + fixed_t oldheight = mobj->height; + UINT8 correctionType = 0; // Don't correct Z position, just gain height + + if (mobj->flags & MF_NOCLIPHEIGHT || (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz)) + correctionType = 1; // Correct Z position by centering + else if (mobj->eflags & MFE_VERTICALFLIP) + correctionType = 2; // Correct Z position by moving down + + if (abs(mobj->scale - mobj->destscale) < mobj->scalespeed) + P_SetScale(mobj, mobj->destscale); + else if (mobj->scale < mobj->destscale) + P_SetScale(mobj, mobj->scale + mobj->scalespeed); + else if (mobj->scale > mobj->destscale) + P_SetScale(mobj, mobj->scale - mobj->scalespeed); + + if (correctionType == 1) + mobj->z -= (mobj->height - oldheight)/2; + else if (correctionType == 2) + mobj->z -= mobj->height - oldheight; + + if (mobj->scale == mobj->destscale) { - koopa->threshold--; - koopa->momx = FixedMul(FRACUNIT, koopa->scale); - - if (!koopa->threshold) - koopa->threshold = -TICRATE*2; + /// \todo Lua hook for "reached destscale"? + switch (mobj->type) + { + default: + if (mobj->player) + { + if (mobj->scale <= 1) + { + mobj->drawflags |= MFD_DONTDRAW; + } + } + else + { + if (!mobj->player && mobj->scale == 0) + { + P_RemoveMobj(mobj); + return; + } + } + break; + } } - else if (koopa->threshold < 0) - { - koopa->threshold++; - koopa->momx = FixedMul(-FRACUNIT, koopa->scale); +} - if (!koopa->threshold) - koopa->threshold = TICRATE*2; +static void P_MaceSceneryThink(mobj_t *mobj) +{ + angle_t oldmovedir = mobj->movedir; + + // Always update movedir to prevent desyncing (in the traditional sense, not the netplay sense). + mobj->movedir = (mobj->movedir + mobj->lastlook) & FINEMASK; + + // If too far away and not deliberately spitting in the face of optimisation, don't think! + if (!(mobj->flags2 & MF2_BOSSNOTRAP)) + { + UINT8 i; + // Quick! Look through players! Don't move unless a player is relatively close by. + // The below is selected based on CEZ2's first room. I promise you it is a coincidence that it looks like the weed number. + for (i = 0; i < MAXPLAYERS; ++i) + if (playeringame[i] && players[i].mo + && P_AproxDistance(P_AproxDistance(mobj->x - players[i].mo->x, mobj->y - players[i].mo->y), mobj->z - players[i].mo->z) < (4200 << FRACBITS)) + break; // Stop looking. + if (i == MAXPLAYERS) + { + if (!(mobj->flags2 & MF2_BEYONDTHEGRAVE)) + { + mobj_t *ref = mobj; + + // stop/hide all your babies + while ((ref = ref->hnext)) + { + ref->eflags = (((ref->flags & MF_NOTHINK) ? 0 : 1) + | ((ref->flags & MF_NOCLIPTHING) ? 0 : 2) + | ((ref->drawflags & MFD_DONTDRAW) ? 0 : 4)); // oh my god this is nasty. + ref->flags |= MF_NOTHINK|MF_NOCLIPTHING; + ref->drawflags |= MFD_DONTDRAW; + ref->momx = ref->momy = ref->momz = 0; + } + + mobj->flags2 |= MF2_BEYONDTHEGRAVE; + } + return; // don't make bubble! + } + else if (mobj->flags2 & MF2_BEYONDTHEGRAVE) + { + mobj_t *ref = mobj; + + // start/show all your babies + while ((ref = ref->hnext)) + { + if (ref->eflags & 1) + ref->flags &= ~MF_NOTHINK; + if (ref->eflags & 2) + ref->flags &= ~MF_NOCLIPTHING; + if (ref->eflags & 4) + ref->drawflags &= ~MFD_DONTDRAW; + ref->eflags = 0; // le sign + } + + mobj->flags2 &= ~MF2_BEYONDTHEGRAVE; + } + } + + // Okay, time to MOVE + P_MaceRotate(mobj, mobj->movedir, oldmovedir); +} + +static void P_FlameJetSceneryThink(mobj_t *mobj) +{ + mobj_t *flame; + fixed_t strength; + + if (!(mobj->flags2 & MF2_FIRING)) + return; + + if ((leveltime & 3) != 0) + return; + + // Wave the flames back and forth. Reactiontime determines which direction it's going. + if (mobj->fuse <= -16) + mobj->reactiontime = 1; + else if (mobj->fuse >= 16) + mobj->reactiontime = 0; + + if (mobj->reactiontime) + mobj->fuse += 2; + else + mobj->fuse -= 2; + + flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); + P_SetMobjState(flame, S_FLAMEJETFLAME4); + + flame->angle = mobj->angle; + + if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side + flame->momz = mobj->fuse << (FRACBITS - 2); + else + flame->angle += FixedAngle(mobj->fuse<movedir; + + P_InstaThrust(flame, flame->angle, strength); + S_StartSound(flame, sfx_fire); +} + +static void P_VerticalFlameJetSceneryThink(mobj_t *mobj) +{ + mobj_t *flame; + fixed_t strength; + + if (!(mobj->flags2 & MF2_FIRING)) + return; + + if ((leveltime & 3) != 0) + return; + + // Wave the flames back and forth. Reactiontime determines which direction it's going. + if (mobj->fuse <= -16) + mobj->reactiontime = 1; + else if (mobj->fuse >= 16) + mobj->reactiontime = 0; + + if (mobj->reactiontime) + mobj->fuse++; + else + mobj->fuse--; + + flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); + + strength = 20*FRACUNIT; + strength -= ((20*FRACUNIT)/16)*mobj->movedir; + + // If deaf'd, the object spawns on the ceiling. + if (mobj->flags2 & MF2_AMBUSH) + { + mobj->z = mobj->ceilingz - mobj->height; + flame->momz = -strength; } else - koopa->threshold = TICRATE*2; - - P_XYMovement(koopa); - - if (P_RandomChance(FRACUNIT/32) && koopa->z <= koopa->floorz) - koopa->momz = FixedMul(5*FRACUNIT, koopa->scale); - - if (koopa->z > koopa->floorz) - koopa->momz += FixedMul(FRACUNIT/4, koopa->scale); - - if (P_RandomChance(FRACUNIT/64)) { - mobj_t *flame; - flame = P_SpawnMobj(koopa->x - koopa->radius + FixedMul(5*FRACUNIT, koopa->scale), koopa->y, koopa->z + (P_RandomByte()<<(FRACBITS-2)), MT_KOOPAFLAME); - flame->momx = -FixedMul(flame->info->speed, flame->scale); - S_StartSound(flame, sfx_koopfr); + flame->momz = strength; + P_SetMobjState(flame, S_FLAMEJETFLAME7); } - else if (P_RandomChance(5*FRACUNIT/256)) + + P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT, 3*FRACUNIT)); + S_StartSound(flame, sfx_fire); +} + +static boolean P_ParticleGenSceneryThink(mobj_t *mobj) +{ + if (!mobj->lastlook) + return false; + + if (!mobj->threshold) + return false; + + if (--mobj->fuse <= 0) { - mobj_t *hammer; - hammer = P_SpawnMobj(koopa->x - koopa->radius, koopa->y, koopa->z + koopa->height, MT_HAMMER); - hammer->momx = FixedMul(-5*FRACUNIT, hammer->scale); - hammer->momz = FixedMul(7*FRACUNIT, hammer->scale); + INT32 i = 0; + mobj_t *spawn; + fixed_t bottomheight, topheight; + INT32 type = mobj->threshold, line = mobj->cvmem; + + mobj->fuse = (tic_t)mobj->reactiontime; + + bottomheight = lines[line].frontsector->floorheight; + topheight = lines[line].frontsector->ceilingheight - mobjinfo[(mobjtype_t)type].height; + + if (mobj->waterbottom != bottomheight || mobj->watertop != topheight) + { + if (mobj->movefactor && (topheight > bottomheight)) + mobj->health = (tic_t)(FixedDiv((topheight - bottomheight), abs(mobj->movefactor)) >> FRACBITS); + else + mobj->health = 0; + + mobj->z = ((mobj->flags2 & MF2_OBJECTFLIP) ? topheight : bottomheight); + } + + if (!mobj->health) + return false; + + for (i = 0; i < mobj->lastlook; i++) + { + spawn = P_SpawnMobj( + mobj->x + FixedMul(FixedMul(mobj->friction, mobj->scale), FINECOSINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->y + FixedMul(FixedMul(mobj->friction, mobj->scale), FINESINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->z, + (mobjtype_t)mobj->threshold); + P_SetScale(spawn, mobj->scale); + spawn->momz = FixedMul(mobj->movefactor, spawn->scale); + spawn->destscale = spawn->scale/100; + spawn->scalespeed = spawn->scale/mobj->health; + spawn->tics = (tic_t)mobj->health; + spawn->flags2 |= (mobj->flags2 & MF2_OBJECTFLIP); + spawn->angle += P_RandomKey(36)*ANG10; // irrelevant for default objects but might make sense for some custom ones + + mobj->angle += mobj->movedir; + } + + mobj->angle += (angle_t)mobj->movecount; } + + return true; +} + +static void P_MobjSceneryThink(mobj_t *mobj) +{ + if (LUAh_MobjThinker(mobj)) + return; + if (P_MobjWasRemoved(mobj)) + return; + + if ((mobj->flags2 & MF2_SHIELD) && !P_AddShield(mobj)) + return; + + switch (mobj->type) + { + case MT_BOSSJUNK: + mobj->drawflags ^= MFD_DONTDRAW; + break; + case MT_MACEPOINT: + case MT_CHAINMACEPOINT: + case MT_SPRINGBALLPOINT: + case MT_CHAINPOINT: + case MT_FIREBARPOINT: + case MT_CUSTOMMACEPOINT: + case MT_HIDDEN_SLING: + P_MaceSceneryThink(mobj); + break; + case MT_HOOP: + if (mobj->fuse > 1) + P_MoveHoop(mobj); + else if (mobj->fuse == 1) + mobj->movecount = 1; + + if (mobj->movecount) + { + mobj->fuse++; + + if (mobj->fuse > 32) + { + // Don't kill the hoop center. For the sake of respawning. + //if (mobj->target) + // P_RemoveMobj(mobj->target); + + P_RemoveMobj(mobj); + } + } + else + mobj->fuse--; + return; + case MT_NIGHTSPARKLE: + if (mobj->tics != -1) + { + mobj->tics--; + + // you can cycle through multiple states in a tic + if (!mobj->tics) + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + return; // freed itself + } + + P_UnsetThingPosition(mobj); + mobj->x += mobj->momx; + mobj->y += mobj->momy; + mobj->z += mobj->momz; + P_SetThingPosition(mobj); + return; + case MT_NIGHTSLOOPHELPER: + if (--mobj->tics <= 0) + P_RemoveMobj(mobj); + + // Don't touch my fuse! + return; + case MT_OVERLAY: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return; + } + else + P_AddOverlay(mobj); + break; + case MT_PITY_ORB: + case MT_WHIRLWIND_ORB: + case MT_ARMAGEDDON_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + break; + case MT_ATTRACT_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (/*(mobj->target) -- the following is implicit by P_AddShield + && (mobj->target->player) + && */ (mobj->target->player->homing) && (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + } + break; + case MT_ELEMENTAL_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL */ + && mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->tracer->state - states) < mobj->info->raisestate + || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + break; + case MT_FORCE_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (/* + && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_FORCE) + && */ (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + mobj_t *whoosh = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_GHOST); // done here so the offset is correct + P_SetMobjState(whoosh, mobj->info->raisestate); + whoosh->destscale = whoosh->scale << 1; + whoosh->scalespeed = FixedMul(whoosh->scalespeed, whoosh->scale); + whoosh->height = 38*whoosh->scale; + whoosh->fuse = 10; + whoosh->flags |= MF_NOCLIPHEIGHT; + whoosh->momz = mobj->target->momz; // Stay reasonably centered for a few frames + mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal whoosh + } + /* FALLTHRU */ + case MT_FLAMEAURA_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if ((statenum_t)(mobj->state - states) < mobj->info->painstate) + mobj->angle = mobj->target->angle; // implicitly okay because of P_AddShield + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_FLAMEAURA */ + && mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->tracer->state - states) < mobj->info->raisestate + || (mobj->tracer->state->nextstate < mobj->info->raisestate && mobj->tracer->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + break; + case MT_BUBBLEWRAP_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_BUBBLEWRAP */ + ) + { + if (mobj->target->player->pflags & PF_SHIELDABILITY + && ((statenum_t)(mobj->state - states) < mobj->info->painstate + || (mobj->state->nextstate < mobj->info->painstate && mobj->tics == 1))) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + } + else if (mobj->target->eflags & MFE_JUSTHITFLOOR + && (statenum_t)(mobj->state - states) == mobj->info->painstate) + { + P_SetMobjState(mobj, mobj->info->painstate + 1); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate + 1); + mobj->tracer->tics++; + } + } + break; + case MT_THUNDERCOIN_ORB: + if (!(mobj->flags2 & MF2_SHIELD)) + return; + if (mobj->tracer + /* && mobj->target -- the following is implicit by P_AddShield + && mobj->target->player + && (mobj->target->player->powers[pw_shield] & SH_NOSTACK) == SH_THUNDERCOIN */ + && (mobj->target->player->pflags & PF_SHIELDABILITY)) + { + P_SetMobjState(mobj, mobj->info->painstate); + mobj->tics++; + P_SetMobjState(mobj->tracer, mobj->info->raisestate); + mobj->tracer->tics++; + mobj->target->player->pflags &= ~PF_SHIELDABILITY; // prevent eternal spark + } + break; + case MT_WATERDROP: + P_SceneryCheckWater(mobj); + if ((mobj->z <= mobj->floorz || mobj->z <= mobj->watertop) + && mobj->health > 0) + { + mobj->health = 0; + P_SetMobjState(mobj, mobj->info->deathstate); + S_StartSound(mobj, mobj->info->deathsound + P_RandomKey(mobj->info->mass)); + return; + } + break; + case MT_BUBBLES: + P_SceneryCheckWater(mobj); + break; + case MT_SMALLBUBBLE: + case MT_MEDIUMBUBBLE: + case MT_EXTRALARGEBUBBLE: // start bubble dissipate + P_SceneryCheckWater(mobj); + if (P_MobjWasRemoved(mobj)) // bubble was removed by not being in water + return; + if (!(mobj->eflags & MFE_UNDERWATER) + || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height >= mobj->ceilingz) + || (mobj->eflags & MFE_VERTICALFLIP && mobj->z <= mobj->floorz) + || (P_CheckDeathPitCollide(mobj)) + || --mobj->fuse <= 0) // Bubbles eventually dissipate if they can't reach the surface. + { + // no playing sound: no point; the object is being removed + P_RemoveMobj(mobj); + return; + } + break; + case MT_LOCKON: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return; + } + + mobj->drawflags &= ~MFD_DONTDRAW; + + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + mobj->eflags |= (mobj->target->eflags & MFE_VERTICALFLIP); + + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->target->z + mobj->target->height + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale); + else + mobj->z = mobj->target->z - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->target->scale) - mobj->height; + break; + case MT_LOCKONINF: + if (!(mobj->flags2 & MF2_STRONGBOX)) + { + mobj->threshold = mobj->z; + mobj->flags2 |= MF2_STRONGBOX; + } + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z = mobj->threshold + FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); + else + mobj->z = mobj->threshold - FixedMul((16 + abs((signed)(leveltime % TICRATE) - TICRATE/2))*FRACUNIT, mobj->scale); + break; + case MT_FLAMEJET: + P_FlameJetSceneryThink(mobj); + break; + case MT_VERTICALFLAMEJET: + P_VerticalFlameJetSceneryThink(mobj); + break; + case MT_FLICKY_01_CENTER: + case MT_FLICKY_02_CENTER: + case MT_FLICKY_03_CENTER: + case MT_FLICKY_04_CENTER: + case MT_FLICKY_05_CENTER: + case MT_FLICKY_06_CENTER: + case MT_FLICKY_07_CENTER: + case MT_FLICKY_08_CENTER: + case MT_FLICKY_09_CENTER: + case MT_FLICKY_10_CENTER: + case MT_FLICKY_11_CENTER: + case MT_FLICKY_12_CENTER: + case MT_FLICKY_13_CENTER: + case MT_FLICKY_14_CENTER: + case MT_FLICKY_15_CENTER: + case MT_FLICKY_16_CENTER: + case MT_SECRETFLICKY_01_CENTER: + case MT_SECRETFLICKY_02_CENTER: + if (mobj->tracer && (mobj->flags & MF_NOCLIPTHING) + && (mobj->flags & MF_GRENADEBOUNCE)) + // for now: only do this bounce routine if flicky is in-place. \todo allow in all movements + { + if (!(mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z <= mobj->tracer->floorz) + mobj->tracer->momz = 7*FRACUNIT; + else if ((mobj->tracer->flags2 & MF2_OBJECTFLIP) && mobj->tracer->z >= mobj->tracer->ceilingz - mobj->tracer->height) + mobj->tracer->momz = -7*FRACUNIT; + } + break; + case MT_SEED: + if (P_MobjFlip(mobj)*mobj->momz < mobj->info->speed) + mobj->momz = P_MobjFlip(mobj)*mobj->info->speed; + break; + case MT_ROCKCRUMBLE1: + case MT_ROCKCRUMBLE2: + case MT_ROCKCRUMBLE3: + case MT_ROCKCRUMBLE4: + case MT_ROCKCRUMBLE5: + case MT_ROCKCRUMBLE6: + case MT_ROCKCRUMBLE7: + case MT_ROCKCRUMBLE8: + case MT_ROCKCRUMBLE9: + case MT_ROCKCRUMBLE10: + case MT_ROCKCRUMBLE11: + case MT_ROCKCRUMBLE12: + case MT_ROCKCRUMBLE13: + case MT_ROCKCRUMBLE14: + case MT_ROCKCRUMBLE15: + case MT_ROCKCRUMBLE16: + case MT_WOODDEBRIS: + case MT_BRICKDEBRIS: + case MT_BROKENROBOT: + if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height) + && mobj->state != &states[mobj->info->deathstate]) + { + P_SetMobjState(mobj, mobj->info->deathstate); + return; + } + break; + case MT_PARTICLEGEN: + if (!P_ParticleGenSceneryThink(mobj)) + return; + break; + case MT_FSGNA: + if (mobj->movedir) + mobj->angle += mobj->movedir; + break; + case MT_ORBINAUT_SHIELD: // Kart orbit/trail items + case MT_JAWZ_SHIELD: + case MT_BANANA_SHIELD: + case MT_SSMINE_SHIELD: + case MT_EGGMANITEM_SHIELD: + case MT_SINK_SHIELD: + if ((mobj->health > 0 + && (!mobj->target || !mobj->target->player || mobj->target->health <= 0 || mobj->target->player->spectator)) + || (mobj->health <= 0 && P_IsObjectOnGround(mobj)) + || P_CheckDeathPitCollide(mobj)) // When in death state + { + P_RemoveMobj(mobj); + return; + } + break; + case MT_SMOLDERING: + if (leveltime % 2 == 0) + { + fixed_t x = P_RandomRange(-35, 35)*mobj->scale; + fixed_t y = P_RandomRange(-35, 35)*mobj->scale; + fixed_t z = P_RandomRange(0, 70)*mobj->scale; + mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); + P_SetMobjState(smoke, S_OPAQUESMOKE1); + K_MatchGenericExtraFlags(smoke, mobj); + smoke->scale = mobj->scale * 2; + smoke->destscale = mobj->scale * 6; + smoke->momz = P_RandomRange(4, 9)*FRACUNIT*P_MobjFlip(smoke); + } + break; + case MT_BOOMPARTICLE: + { + fixed_t x = P_RandomRange(-16, 16)*mobj->scale; + fixed_t y = P_RandomRange(-16, 16)*mobj->scale; + fixed_t z = P_RandomRange(0, 32)*mobj->scale*P_MobjFlip(mobj); + if (leveltime % 2 == 0) + { + mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_BOSSEXPLODE); + K_MatchGenericExtraFlags(smoke, mobj); + P_SetMobjState(smoke, S_QUICKBOOM1); + smoke->scale = mobj->scale/2; + smoke->destscale = mobj->scale; + smoke->color = mobj->color; + } + else + { + mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); + P_SetMobjState(smoke, S_OPAQUESMOKE1); + K_MatchGenericExtraFlags(smoke, mobj); + smoke->scale = mobj->scale; + smoke->destscale = mobj->scale*2; + } + if (mobj->tics <= TICRATE) + { + mobj->destscale = FixedDiv(mobj->scale, 100*FRACUNIT); + } + } + break; + case MT_BATTLEBUMPER: + if (mobj->health > 0 && mobj->target && mobj->target->player + && mobj->target->health > 0 && !mobj->target->player->spectator) + { + fixed_t rad = 32*mobj->target->scale; + fixed_t offz; + angle_t ang, diff; + + if (!((mobj->target->player-players) & 1)) + ang = (FixedAngle(mobj->info->speed) * -1); + else + ang = FixedAngle(mobj->info->speed); + + if (mobj->target->player->kartstuff[k_bumper] <= 1) + diff = 0; + else + diff = FixedAngle(360*FRACUNIT/mobj->target->player->kartstuff[k_bumper]); + + ang = (ang*leveltime) + (diff * (mobj->threshold-1)); + + // If the player is on the ceiling, then flip your items as well. + if (mobj->target->eflags & MFE_VERTICALFLIP) + { + mobj->eflags |= MFE_VERTICALFLIP; + offz = mobj->target->height / 2; + } + else + { + mobj->eflags &= ~MFE_VERTICALFLIP; + offz = mobj->target->height / 5; + } + + mobj->drawflags = (mobj->target->drawflags & MFD_DONTDRAW); + + if (mobj->target->eflags & MFE_VERTICALFLIP) + offz += 4*FRACUNIT; + else + offz -= 4*FRACUNIT; + + if (mobj->tracer && mobj->tracer->player && mobj->tracer->player->mo + && mobj->tracer->health > 0 && !mobj->tracer->player->spectator) // STOLEN + mobj->color = mobj->tracer->player->skincolor; // don't do star flashing for stolen bumpers + else + mobj->color = mobj->target->color; // but do so if it belongs to you :B + + if (mobj->target->player->kartstuff[k_bumper] < 2) + P_SetMobjState(mobj, S_BATTLEBUMPER3); + else if (mobj->target->player->kartstuff[k_bumper] < 3) + P_SetMobjState(mobj, S_BATTLEBUMPER2); + else + P_SetMobjState(mobj, S_BATTLEBUMPER1); + + // Shrink your items if the player shrunk too. + mobj->scale = mobj->target->scale; + + P_UnsetThingPosition(mobj); + { + const angle_t fa = ang>>ANGLETOFINESHIFT; + mobj->x = mobj->target->x + FixedMul(FINECOSINE(fa), rad); + mobj->y = mobj->target->y + FixedMul(FINESINE(fa), rad); + mobj->z = mobj->target->z + offz; + P_SetThingPosition(mobj); + } + + // Was this so hard? + if (mobj->target->player->kartstuff[k_bumper] <= mobj->threshold) + { + P_RemoveMobj(mobj); + return; + } + } + else if ((mobj->health > 0 + && (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->health <= 0 || mobj->target->player->spectator)) + || (mobj->health <= 0 && P_IsObjectOnGround(mobj)) + || P_CheckDeathPitCollide(mobj)) // When in death state + { + P_RemoveMobj(mobj); + return; + } + break; + case MT_PLAYERARROW: + if (mobj->target && mobj->target->health + && mobj->target->player && !mobj->target->player->spectator + && mobj->target->health && mobj->target->player->playerstate != PST_DEAD + /*&& players[displayplayers[0]].mo && !players[displayplayers[0]].spectator*/) + { + fixed_t scale = 3*mobj->target->scale; + mobj->color = mobj->target->color; + K_MatchGenericExtraFlags(mobj, mobj->target); + + if ((gametype == GT_RACE || mobj->target->player->kartstuff[k_bumper] <= 0) +#if 1 // Set to 0 to test without needing to host + || (P_IsDisplayPlayer(mobj->target->player)) +#endif + ) + mobj->drawflags |= MFD_DONTDRAW; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + mobj->angle = R_PointToAngle(mobj->x, mobj->y) + ANGLE_90; // literally only happened because i wanted to ^L^R the SPR_ITEM's + + if (!r_splitscreen && players[displayplayers[0]].mo) + { + scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x, + players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); + if (scale > 16*mobj->target->scale) + scale = 16*mobj->target->scale; + } + mobj->destscale = scale; + + if (!(mobj->target->eflags & MFE_VERTICALFLIP)) + { + mobj->z = mobj->target->z + mobj->target->height + (16*mobj->target->scale); + mobj->eflags &= ~MFE_VERTICALFLIP; + } + else + { + mobj->z = mobj->target->z - mobj->target->height - (16*mobj->target->scale); + mobj->eflags |= MFE_VERTICALFLIP; + } + P_SetThingPosition(mobj); + + if (!mobj->tracer) + { + mobj_t *overlay = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); + P_SetTarget(&mobj->tracer, overlay); + P_SetTarget(&mobj->tracer->target, mobj); + P_SetMobjState(mobj->tracer, S_PLAYERARROW_ITEM); + P_SetScale(mobj->tracer, (mobj->tracer->destscale = mobj->scale)); + } + + // Do this in an easy way + if (mobj->target->player->kartstuff[k_itemroulette]) + { + mobj->tracer->color = mobj->target->player->skincolor; + mobj->tracer->colorized = true; + } + else + { + mobj->tracer->color = SKINCOLOR_NONE; + mobj->tracer->colorized = false; + } + + if (!(mobj->drawflags & MFD_DONTDRAW)) + { + const INT32 numberdisplaymin = ((mobj->target->player->kartstuff[k_itemtype] == KITEM_ORBINAUT) ? 5 : 2); + + // Set it to use the correct states for its condition + if (mobj->target->player->kartstuff[k_itemroulette]) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|(((mobj->target->player->kartstuff[k_itemroulette] % (13*3)) / 3) + 1); + mobj->tracer->drawflags &= ~MFD_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_stolentimer] > 0) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_HYUDORO; + if (leveltime & 2) + mobj->tracer->drawflags &= ~MFD_DONTDRAW; + else + mobj->tracer->drawflags |= MFD_DONTDRAW; + } + else if ((mobj->target->player->kartstuff[k_stealingtimer] > 0) && (leveltime & 2)) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_HYUDORO; + mobj->tracer->drawflags &= ~MFD_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_eggmanexplode] > 1) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_EGGMAN; + if (leveltime & 1) + mobj->tracer->drawflags &= ~MFD_DONTDRAW; + else + mobj->tracer->drawflags |= MFD_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_rocketsneakertimer] > 1) + { + //itembar = mobj->target->player->kartstuff[k_rocketsneakertimer]; -- not today satan + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|KITEM_ROCKETSNEAKER; + if (leveltime & 1) + mobj->tracer->drawflags &= ~MFD_DONTDRAW; + else + mobj->tracer->drawflags |= MFD_DONTDRAW; + } + else if (mobj->target->player->kartstuff[k_itemtype] && mobj->target->player->kartstuff[k_itemamount] > 0) + { + P_SetMobjState(mobj, S_PLAYERARROW_BOX); + + switch (mobj->target->player->kartstuff[k_itemtype]) + { + case KITEM_ORBINAUT: + mobj->tracer->sprite = SPR_ITMO; + mobj->tracer->frame = FF_FULLBRIGHT|(min(mobj->target->player->kartstuff[k_itemamount]-1, 3)); + break; + case KITEM_INVINCIBILITY: + mobj->tracer->sprite = SPR_ITMI; + mobj->tracer->frame = FF_FULLBRIGHT|((leveltime % (7*3)) / 3); + break; + case KITEM_SAD: + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT; + break; + default: + mobj->tracer->sprite = SPR_ITEM; + mobj->tracer->frame = FF_FULLBRIGHT|(mobj->target->player->kartstuff[k_itemtype]); + break; + } + + if (mobj->target->player->kartstuff[k_itemheld]) + { + if (leveltime & 1) + mobj->tracer->drawflags &= ~MFD_DONTDRAW; + else + mobj->tracer->drawflags |= MFD_DONTDRAW; + } + else + mobj->tracer->drawflags &= ~MFD_DONTDRAW; + } + else + { + P_SetMobjState(mobj, S_PLAYERARROW); + P_SetMobjState(mobj->tracer, S_PLAYERARROW_ITEM); + } + + mobj->tracer->destscale = scale; + + if (mobj->target->player->kartstuff[k_itemamount] >= numberdisplaymin + && mobj->target->player->kartstuff[k_itemamount] <= 10) // Meh, too difficult to support greater than this; convert this to a decent HUD object and then maybe :V + { + mobj_t *number = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); + mobj_t *numx = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); + + P_SetTarget(&number->target, mobj); + P_SetMobjState(number, S_PLAYERARROW_NUMBER); + P_SetScale(number, mobj->scale); + number->destscale = scale; + number->frame = FF_FULLBRIGHT|(mobj->target->player->kartstuff[k_itemamount]); + + P_SetTarget(&numx->target, mobj); + P_SetMobjState(numx, S_PLAYERARROW_X); + P_SetScale(numx, mobj->scale); + numx->destscale = scale; + } + + if (K_IsPlayerWanted(mobj->target->player) && mobj->movecount != 1) + { + mobj_t *wanted = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PLAYERWANTED); + P_SetTarget(&wanted->target, mobj->target); + P_SetTarget(&wanted->tracer, mobj); + P_SetScale(wanted, mobj->scale); + wanted->destscale = scale; + mobj->movecount = 1; + } + else if (!K_IsPlayerWanted(mobj->target->player)) + mobj->movecount = 0; + } + else + mobj->tracer->drawflags |= MFD_DONTDRAW; + } + else if (mobj->health > 0) + { + P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); + return; + } + break; + case MT_PLAYERWANTED: + if (mobj->target && mobj->target->health && mobj->tracer + && mobj->target->player && !mobj->target->player->spectator + && mobj->target->health && mobj->target->player->playerstate != PST_DEAD + && players[g_localplayers[0]].mo && !players[g_localplayers[0]].spectator) + { + fixed_t scale = 3*mobj->target->scale; + + if (!K_IsPlayerWanted(mobj->target->player)) + { + mobj->tracer->movecount = 0; + P_RemoveMobj(mobj); + return; + } + + if (mobj->tracer->drawflags & MFD_DONTDRAW) + mobj->drawflags |= MFD_DONTDRAW; + else + mobj->drawflags &= ~MFD_DONTDRAW; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + + if (!r_splitscreen && players[displayplayers[0]].mo) + { + scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x, + players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); + if (scale > 16*mobj->target->scale) + scale = 16*mobj->target->scale; + } + mobj->destscale = scale; + + if (!(mobj->target->eflags & MFE_VERTICALFLIP)) + { + mobj->z = mobj->target->z + mobj->target->height + (16*mobj->target->scale) + (64*scale); + mobj->eflags &= ~MFE_VERTICALFLIP; + } + else + { + mobj->z = mobj->target->z - mobj->target->height - (16*mobj->target->scale) - (64*scale); + mobj->eflags |= MFE_VERTICALFLIP; + } + P_SetThingPosition(mobj); + } + else if (mobj->health > 0) + { + P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); + return; + } + break; + case MT_PETSMOKER: + if (!(leveltime % 10)) + { + mobj_t *smok = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PETSMOKE); + if (mobj->spawnpoint && mobj->spawnpoint->options & MTF_OBJECTSPECIAL) + P_SetMobjStateNF(smok, smok->info->painstate); // same function, diff sprite + } + break; + case MT_BATTLECAPSULE_PIECE: + if (mobj->extravalue2) + mobj->frame |= FF_VERTICALFLIP; + else + mobj->frame &= ~FF_VERTICALFLIP; + + if (mobj->flags2 & MF2_OBJECTFLIP) + mobj->eflags |= MFE_VERTICALFLIP; + + if (mobj->tics > 0) + mobj->drawflags ^= MFD_DONTDRAW; + break; + case MT_VWREF: + case MT_VWREB: + { + INT32 strength; + ++mobj->movedir; + mobj->frame &= ~FF_TRANSMASK; + strength = min(mobj->fuse, (INT32)mobj->movedir)*3; + if (strength < 10) + mobj->frame |= ((10 - strength) << (FF_TRANSSHIFT)); + } + /* FALLTHRU */ + default: + if (mobj->fuse) + { // Scenery object fuse! Very basic! + mobj->fuse--; + if (!mobj->fuse) + { + if (!LUAh_MobjFuse(mobj)) + P_RemoveMobj(mobj); + return; + } + } + break; + } + + P_SceneryThinker(mobj); +} + +static boolean P_MobjPushableThink(mobj_t *mobj) +{ + P_MobjCheckWater(mobj); + P_PushableThinker(mobj); + return true; +} + +static boolean P_MobjBossThink(mobj_t *mobj) +{ + if (LUAh_BossThinker(mobj)) + { + if (P_MobjWasRemoved(mobj)) + return false; + } + else if (P_MobjWasRemoved(mobj)) + return false; + else + switch (mobj->type) + { + // No SRB2Kart bosses... yet :) + default: // Generic SOC-made boss + if (mobj->flags2 & MF2_SKULLFLY) + P_SpawnGhostMobj(mobj); + P_GenericBossThinker(mobj); + break; + } + if (mobj->flags2 & MF2_BOSSFLEE) + { + if (mobj->extravalue1) + { + if (!(--mobj->extravalue1)) + { + if (mobj->target) + { + mobj->momz = FixedMul(FixedDiv(mobj->target->z - mobj->z, P_AproxDistance(mobj->x - mobj->target->x, mobj->y - mobj->target->y)), mobj->scale << 1); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + } + else + mobj->momz = 8*mobj->scale; + } + else + mobj->angle += mobj->movedir; + } + else if (mobj->target) + P_InstaThrust(mobj, mobj->angle, FixedMul(12*FRACUNIT, mobj->scale)); + } + return true; +} + +static boolean P_MobjDeadThink(mobj_t *mobj) +{ + switch (mobj->type) + { + case MT_PLAYER: + /// \todo Have the player's dead body completely finish its animation even if they've already respawned. + if (!mobj->fuse) + { // Go away. + /// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it. + mobj->momz = 0; + if (mobj->player) + mobj->drawflags |= MFD_DONTDRAW; + else // safe to remove, nobody's going to complain! + { + P_RemoveMobj(mobj); + return false; + } + } + else // Apply gravity to fall downwards. + { + if (mobj->player && !(mobj->fuse % 8) && (mobj->player->charflags & SF_MACHINE)) + { + fixed_t r = mobj->radius >> FRACBITS; + mobj_t *explosion = P_SpawnMobj( + mobj->x + (P_RandomRange(r, -r) << FRACBITS), + mobj->y + (P_RandomRange(r, -r) << FRACBITS), + mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), + MT_SONIC3KBOSSEXPLODE); + S_StartSound(explosion, sfx_s3kb4); + } + P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); + } + break; + case MT_METALSONIC_RACE: + { + if (!(mobj->fuse % 8)) + { + fixed_t r = mobj->radius >> FRACBITS; + mobj_t *explosion = P_SpawnMobj( + mobj->x + (P_RandomRange(r, -r) << FRACBITS), + mobj->y + (P_RandomRange(r, -r) << FRACBITS), + mobj->z + (P_RandomKey(mobj->height >> FRACBITS) << FRACBITS), + MT_SONIC3KBOSSEXPLODE); + S_StartSound(explosion, sfx_s3kb4); + } + P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); + } + break; + case MT_ORBINAUT: + case MT_BANANA: + case MT_EGGMANITEM: + case MT_SPB: + if (P_IsObjectOnGround(mobj)) + { + P_RemoveMobj(mobj); + return false; + } + /* FALLTHRU */ + case MT_ORBINAUT_SHIELD: + case MT_BANANA_SHIELD: + case MT_EGGMANITEM_SHIELD: + mobj->drawflags ^= MFD_DONTDRAW; + break; + case MT_JAWZ: + case MT_JAWZ_DUD: + if (P_IsObjectOnGround(mobj)) + P_SetMobjState(mobj, mobj->info->xdeathstate); + /* FALLTHRU */ + case MT_JAWZ_SHIELD: + mobj->drawflags ^= MFD_DONTDRAW; + break; + case MT_SSMINE: + case MT_SPBEXPLOSION: + if (mobj->extravalue2 != -100) + { + P_SetMobjState(mobj, mobj->info->deathstate); + mobj->extravalue2 = -100; + } + else + { + P_RemoveMobj(mobj); + return false; + } + break; + case MT_MINEEXPLOSIONSOUND: + P_RemoveMobj(mobj); + return false; + case MT_CDUFO: + if (mobj->fuse > TICRATE) + mobj->drawflags ^= MFD_DONTDRAW; // only by good fortune does this end with it having MFD_DONTDRAW... don't touch! + break; + case MT_SMK_PIPE: + if (mobj->flags2 & MF2_AMBUSH) + P_SetMobjStateNF(mobj, mobj->info->seestate); + else + P_SetMobjStateNF(mobj, mobj->info->spawnstate); + /* FALLTHRU */ + case MT_SMK_MOLE: + mobj->drawflags ^= MFD_DONTDRAW; + if (P_IsObjectOnGround(mobj)) + { + P_RemoveMobj(mobj); + return false; + } + break; + case MT_SMK_THWOMP: + if (mobj->flags2 & MF2_AMBUSH) + { + mobj->colorized = true; + mobj->color = K_RainbowColor(leveltime); + mobj->frame |= FF_FULLBRIGHT; + } + else + { + mobj->colorized = false; + mobj->color = SKINCOLOR_NONE; + mobj->frame &= (~FF_FULLBRIGHT); + } + + mobj->drawflags ^= MFD_DONTDRAW; + if (P_IsObjectOnGround(mobj)) + { + P_RemoveMobj(mobj); + return false; + } + break; + case MT_BATTLECAPSULE: + if (!(mobj->fuse & 1)) + { + const SINT8 amt = 96; + mobj_t *dust; + UINT8 i; + + for (i = 0; i < 2; i++) + { + fixed_t xoffset = P_RandomRange(-amt, amt) * mobj->scale; + fixed_t yoffset = P_RandomRange(-amt, amt) * mobj->scale; + fixed_t zoffset = P_RandomRange(-(amt >> 1), (amt >> 1)) * mobj->scale; + + dust = P_SpawnMobj(mobj->x + xoffset, mobj->y + yoffset, + mobj->z + (mobj->height >> 1) + zoffset, MT_EXPLODE); + } + + if (dust && !P_MobjWasRemoved(dust)) // Only do for 1 explosion + S_StartSound(dust, sfx_s3k3d); + } + break; + default: + break; + } + return true; +} + +// Angle-to-tracer to trigger a linedef exec +// See Linedef Exec 457 (Track mobj angle to point) +static void P_TracerAngleThink(mobj_t *mobj) +{ + angle_t looking; + angle_t ang; + + if (!mobj->tracer) + return; + + if (!mobj->extravalue2) + return; + + // mobj->lastlook - Don't disable behavior after first failure + // mobj->extravalue1 - Angle tolerance + // mobj->extravalue2 - Exec tag upon failure + // mobj->cvval - Allowable failure delay + // mobj->cvmem - Failure timer + + if (mobj->player) + looking = mobj->player->angleturn; + else + looking = mobj->angle; + + ang = looking - R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); + + // \todo account for distance between mobj and tracer + // Because closer mobjs can be facing beyond the angle tolerance + // yet tracer is still in the camera view + + // failure state: mobj is not facing tracer + // Reasaonable defaults: ANGLE_67h, ANGLE_292h + if (ang >= (angle_t)mobj->extravalue1 && ang <= ANGLE_MAX - (angle_t)mobj->extravalue1) + { + if (mobj->cvmem) + mobj->cvmem--; + else + { + INT32 exectag = mobj->extravalue2; // remember this before we erase the values + + if (mobj->lastlook) + mobj->cvmem = mobj->cusval; // reset timer for next failure + else + { + // disable after first failure + mobj->eflags &= ~MFE_TRACERANGLE; + mobj->lastlook = mobj->extravalue1 = mobj->extravalue2 = mobj->cvmem = mobj->cusval = 0; + } + + P_LinedefExecute(exectag, mobj, NULL); + } + } + else + mobj->cvmem = mobj->cusval; // reset failure timer +} + +static boolean P_MobjRegularThink(mobj_t *mobj) +{ + if ((mobj->flags & MF_ENEMY) && (mobj->state->nextstate == mobj->info->spawnstate && mobj->tics == 1)) + mobj->flags2 &= ~MF2_FRET; + + if (mobj->eflags & MFE_TRACERANGLE) + P_TracerAngleThink(mobj); + + switch (mobj->type) + { + case MT_WALLSPIKEBASE: + if (!mobj->target) { + P_RemoveMobj(mobj); + return false; + } + mobj->frame = (mobj->frame & ~FF_FRAMEMASK)|(mobj->target->frame & FF_FRAMEMASK); +#if 0 + if (mobj->angle != mobj->target->angle + ANGLE_90) // reposition if not the correct angle + { + mobj_t* target = mobj->target; // shortcut + const fixed_t baseradius = target->radius - (target->scale/2); //FixedMul(FRACUNIT/2, target->scale); + P_UnsetThingPosition(mobj); + mobj->x = target->x - P_ReturnThrustX(target, target->angle, baseradius); + mobj->y = target->y - P_ReturnThrustY(target, target->angle, baseradius); + P_SetThingPosition(mobj); + mobj->angle = target->angle + ANGLE_90; + } +#endif + break; + case MT_FALLINGROCK: + // Despawn rocks here in case zmovement code can't do so (blame slopes) + if (!mobj->momx && !mobj->momy && !mobj->momz + && ((mobj->eflags & MFE_VERTICALFLIP) ? + mobj->z + mobj->height >= mobj->ceilingz + : mobj->z <= mobj->floorz)) + { + mobj->fuse = TICRATE; + } + P_MobjCheckWater(mobj); + break; + case MT_FLAME: + if (mobj->flags2 & MF2_BOSSNOTRAP) + { + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + P_RemoveMobj(mobj->tracer); + P_RemoveMobj(mobj); + return false; + } + mobj->z = mobj->target->z + mobj->target->momz; + if (!(mobj->eflags & MFE_VERTICALFLIP)) + mobj->z += mobj->target->height; + } + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) + { + mobj->tracer->z = mobj->z + P_MobjFlip(mobj)*20*mobj->scale; + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->tracer->z += mobj->height; + } + break; + case MT_WAVINGFLAG1: + case MT_WAVINGFLAG2: + { + fixed_t base = (leveltime << (FRACBITS + 1)); + mobj_t *seg = mobj->tracer, *prev = mobj; + mobj->movedir = mobj->angle + + ((((FINESINE((FixedAngle(base << 1) >> ANGLETOFINESHIFT) & FINEMASK) + + FINESINE((FixedAngle(base << 4) >> ANGLETOFINESHIFT) & FINEMASK)) >> 1) + + FINESINE((FixedAngle(base*9) >> ANGLETOFINESHIFT) & FINEMASK) + + FINECOSINE(((FixedAngle(base*9)) >> ANGLETOFINESHIFT) & FINEMASK)) << 12); //*2^12 + while (seg) + { + seg->movedir = seg->angle; + seg->angle = prev->movedir; + P_UnsetThingPosition(seg); + seg->x = prev->x + P_ReturnThrustX(prev, prev->angle, prev->radius); + seg->y = prev->y + P_ReturnThrustY(prev, prev->angle, prev->radius); + seg->z = prev->z + prev->height - (seg->scale >> 1); + P_SetThingPosition(seg); + prev = seg; + seg = seg->tracer; + } + } + break; + case MT_SMASHINGSPIKEBALL: + mobj->momx = mobj->momy = 0; + if (mobj->state - states == S_SMASHSPIKE_FALL && P_IsObjectOnGround(mobj)) + { + P_SetMobjState(mobj, S_SMASHSPIKE_STOMP1); + S_StartSound(mobj, sfx_spsmsh); + } + else if (mobj->state - states == S_SMASHSPIKE_RISE2 && P_MobjFlip(mobj)*(mobj->z - mobj->movecount) >= 0) + { + mobj->momz = 0; + P_SetMobjState(mobj, S_SMASHSPIKE_FLOAT); + } + break; + case MT_PLAYER: + if (mobj->player) + P_PlayerMobjThinker(mobj); + return false; + case MT_RING: + if (P_MobjWasRemoved(mobj)) + return false; + + // No need to check water. Who cares? + P_RingThinker(mobj); + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + else + A_AttractChase(mobj); + return false; + // Flung items + case MT_FLINGRING: + if (P_MobjWasRemoved(mobj)) + return false; + + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + else + A_AttractChase(mobj); + break; + case MT_EMBLEM: + if (mobj->flags2 & MF2_NIGHTSPULL) + P_NightsItemChase(mobj); + break; + case MT_FLOATINGITEM: + { + if (mobj->flags & MF_NOCLIPTHING) + { + if (P_CheckDeathPitCollide(mobj)) + { + P_RemoveMobj(mobj); + return false; + } + else if (P_IsObjectOnGround(mobj)) + { + mobj->momx = 1; + mobj->momy = 0; + mobj->flags &= ~MF_NOCLIPTHING; + mobj->flags |= MF_NOGRAVITY; + } + } + else + { + mobj->angle += 2*ANG2; + if (mobj->flags2 & MF2_NIGHTSPULL) + { + if (!mobj->tracer || !mobj->tracer->health + || mobj->scale <= mapobjectscale>>4) + { + P_RemoveMobj(mobj); + return false; + } + P_Attract(mobj, mobj->tracer, true); + } + else + { + fixed_t adj = FixedMul(FRACUNIT - FINECOSINE((mobj->movedir>>ANGLETOFINESHIFT) & FINEMASK), (mapobjectscale<<3)); + mobj->movedir += 2*ANG2; + if (mobj->eflags & MFE_VERTICALFLIP) + mobj->z = mobj->ceilingz - mobj->height - adj; + else + mobj->z = mobj->floorz + adj; + } + } + + switch (mobj->threshold) + { + case KITEM_ORBINAUT: + mobj->sprite = SPR_ITMO; + mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(min(mobj->movecount-1, 3)); + break; + case KITEM_INVINCIBILITY: + mobj->sprite = SPR_ITMI; + mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|((leveltime % (7*3)) / 3); + break; + case KITEM_SAD: + mobj->sprite = SPR_ITEM; + mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE; + break; + case KITEM_SPB: + case KITEM_SHRINK: + indirectitemcooldown = 20*TICRATE; + /* FALLTHRU */ + default: + mobj->sprite = SPR_ITEM; + mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(mobj->threshold); + break; + } + break; + } + case MT_ORBINAUT: + { + boolean grounded = P_IsObjectOnGround(mobj); + + if (mobj->flags2 & MF2_AMBUSH) + { + if (grounded && (mobj->flags & MF_NOCLIPTHING)) + { + mobj->momx = 1; + mobj->momy = 0; + mobj->frame = 3; + S_StartSound(mobj, mobj->info->activesound); + mobj->flags &= ~MF_NOCLIPTHING; + } + else if (mobj->movecount) + mobj->movecount--; + else if (mobj->frame < 3) + { + mobj->movecount = 2; + mobj->frame++; + } + } + else + { + fixed_t finalspeed = mobj->movefactor; + const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); + fixed_t thrustamount = 0; + fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; + mobj_t *ghost = P_SpawnGhostMobj(mobj); + ghost->colorized = true; // already has color! + + if (!grounded) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + if (mobj->health <= 5) + { + INT32 i; + for (i = 5; i >= mobj->health; i--) + finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); + } + + if (currentspeed >= finalspeed) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(finalspeed - currentspeed, frictionsafety); + } + + P_Thrust(mobj, mobj->angle, thrustamount); + + if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) + K_DoPogoSpring(mobj, 0, 1); + + if (mobj->threshold > 0) + mobj->threshold--; + + if (leveltime % 6 == 0) + S_StartSound(mobj, mobj->info->activesound); + } + break; + } + case MT_JAWZ: + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + + if (mobj->threshold > 0) + mobj->threshold--; + if (leveltime % TICRATE == 0) + S_StartSound(mobj, mobj->info->activesound); + + // Movement handling has ALL been moved to A_JawzChase + + K_DriftDustHandling(mobj); + + if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) + K_DoPogoSpring(mobj, 0, 1); + + break; + } + case MT_JAWZ_DUD: + { + boolean grounded = P_IsObjectOnGround(mobj); + + if (mobj->flags2 & MF2_AMBUSH) + { + if (grounded && (mobj->flags & MF_NOCLIPTHING)) + { + mobj->momx = 1; + mobj->momy = 0; + S_StartSound(mobj, mobj->info->deathsound); + mobj->flags &= ~MF_NOCLIPTHING; + } + } + else + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); + fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; + fixed_t thrustamount = 0; + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + + if (!grounded) + { + // No friction in the air + frictionsafety = FRACUNIT; + } + + if (currentspeed >= mobj->movefactor) + { + // Thrust as if you were at top speed, slow down naturally + thrustamount = FixedDiv(mobj->movefactor, frictionsafety) - mobj->movefactor; + } + else + { + const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; + // Thrust to immediately get to top speed + thrustamount = beatfriction + FixedDiv(mobj->movefactor - currentspeed, frictionsafety); + } + + mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); + P_Thrust(mobj, mobj->angle, thrustamount); + + if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) + K_DoPogoSpring(mobj, 0, 1); + + if (mobj->threshold > 0) + mobj->threshold--; + + if (leveltime % TICRATE == 0) + S_StartSound(mobj, mobj->info->activesound); + } + + break; + } + case MT_EGGMANITEM: + { + player_t *player = K_GetItemBoxPlayer(mobj); + UINT8 color = SKINCOLOR_BLACK; + + if (player != NULL) + { + color = player->skincolor; + } + + mobj->color = color; + mobj->colorized = false; + } + /* FALLTHRU */ + case MT_BANANA: + mobj->friction = ORIG_FRICTION/4; + + if (mobj->momx || mobj->momy) + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + } + + if (P_IsObjectOnGround(mobj) && mobj->health > 1) + { + S_StartSound(mobj, mobj->info->activesound); + mobj->momx = mobj->momy = 0; + mobj->health = 1; + } + + if (mobj->threshold > 0) + mobj->threshold--; + break; + case MT_SPB: + indirectitemcooldown = 20*TICRATE; + /* FALLTHRU */ + case MT_BALLHOG: + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + ghost->fuse = 3; + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + + if (mobj->threshold > 0) + mobj->threshold--; + } + break; + case MT_SINK: + if (mobj->momx || mobj->momy) + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + } + + if (P_IsObjectOnGround(mobj)) + { + S_StartSound(mobj, mobj->info->deathsound); + P_SetMobjState(mobj, S_NULL); + } + + if (mobj->threshold > 0) + mobj->threshold--; + break; + case MT_SSMINE: + if (mobj->target && mobj->target->player) + mobj->color = mobj->target->player->skincolor; + else + mobj->color = SKINCOLOR_KETCHUP; + + if (mobj->momx || mobj->momy) + { + mobj_t *ghost = P_SpawnGhostMobj(mobj); + ghost->colorized = true; // already has color! + } + + if (P_IsObjectOnGround(mobj) && (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2])) + { + if (mobj->extravalue1 > 0) + mobj->extravalue1--; + else + { + mobj->momx = mobj->momy = 0; + S_StartSound(mobj, mobj->info->activesound); + P_SetMobjState(mobj, S_SSMINE_DEPLOY1); + } + } + + if ((mobj->state >= &states[S_SSMINE1] && mobj->state <= &states[S_SSMINE4]) + || (mobj->state >= &states[S_SSMINE_DEPLOY8] && mobj->state <= &states[S_SSMINE_DEPLOY13])) + A_GrenadeRing(mobj); + + if (mobj->threshold > 0) + mobj->threshold--; + break; + case MT_SPBEXPLOSION: + mobj->health--; + break; + case MT_MINEEXPLOSION: + if ((mobj->z < mobj->floorz - mobj->height) || (mobj->z > mobj->ceilingz + mobj->height)) + { + P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); + break; + } + + if (mobj->tics != -1) + { + mobj->tics--; + + // you can cycle through multiple states in a tic + if (!mobj->tics) + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + return false; // freed itself + } + + P_UnsetThingPosition(mobj); + mobj->x += mobj->momx; + mobj->y += mobj->momy; + mobj->z += mobj->momz; + P_SetThingPosition(mobj); + return false; + case MT_MINEEXPLOSIONSOUND: + if (mobj->health == 100) + S_StartSound(mobj, sfx_s3k4e); + mobj->health--; + break; + case MT_DRIFTEXPLODE: + if (!mobj->target || !mobj->target->health) + { + P_RemoveMobj(mobj); + return false; + } + + //mobj->angle = mobj->target->angle; + { + angle_t angle = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy); + fixed_t nudge; + + mobj->angle = angle; + + if (( mobj->fuse & 1 )) + { + nudge = 4*mobj->target->radius; + } + else + { + nudge = 2*mobj->target->radius; + /* rotate the papersprite frames to see the flat angle */ + mobj->angle += ANGLE_90; + } + + P_TeleportMove(mobj, + mobj->target->x + P_ReturnThrustX(mobj, angle + ANGLE_180, nudge), + mobj->target->y + P_ReturnThrustY(mobj, angle + ANGLE_180, nudge), + mobj->target->z); + } + P_SetScale(mobj, mobj->target->scale); +#ifdef HWRENDER + mobj->modeltilt = mobj->target->modeltilt; +#endif + + if (mobj->fuse <= 16) + { + mobj->color = SKINCOLOR_KETCHUP; + /* don't draw papersprite frames after blue boost */ + mobj->drawflags ^= MFD_DONTDRAW; + } + else if (mobj->fuse <= 32) + mobj->color = SKINCOLOR_SAPPHIRE; + else if (mobj->fuse > 32) + mobj->color = K_RainbowColor( + (SKINCOLOR_PURPLE - SKINCOLOR_PINK) // Smoothly transition into the other state + + ((mobj->fuse - 32) * 2) // Make the color flashing slow down while it runs out + ); + + switch (mobj->extravalue1) + { + case 3:/* rainbow boost */ + /* every 20 tics, bang! */ + if (( 120 - mobj->fuse ) % 10 == 0) + { + K_SpawnDriftBoostClip(mobj->target->player); + S_StartSound(mobj->target, sfx_s3k77); + } + break; + + case 2:/* blue boost */ + if (mobj->fuse == 16)/* to red*/ + K_SpawnDriftBoostClip(mobj->target->player); + break; + } + + { + player_t *p = NULL; + if (mobj->target->target && mobj->target->target->player) + p = mobj->target->target->player; + else if (mobj->target->player) + p = mobj->target->player; + + if (p) + { + if (p->kartstuff[k_driftboost] > mobj->movecount) + { + ; // reset animation + } + + mobj->movecount = p->kartstuff[k_driftboost]; + } + } + break; + case MT_BOOSTFLAME: + if (!mobj->target || !mobj->target->health) + { + P_RemoveMobj(mobj); + return false; + } + + mobj->angle = mobj->target->angle; + P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius), + mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z); + P_SetScale(mobj, mobj->target->scale); +#ifdef HWRENDER + mobj->modeltilt = mobj->target->modeltilt; +#endif + + { + player_t *p = NULL; + if (mobj->target->target && mobj->target->target->player) + p = mobj->target->target->player; + else if (mobj->target->player) + p = mobj->target->player; + + if (p) + { + if (p->kartstuff[k_sneakertimer] > mobj->movecount) + P_SetMobjState(mobj, S_BOOSTFLAME); + mobj->movecount = p->kartstuff[k_sneakertimer]; + } + } + + if (mobj->state == &states[S_BOOSTSMOKESPAWNER]) + { + mobj_t *smoke = P_SpawnMobj(mobj->x, mobj->y, mobj->z+(8<target->scale/2); + smoke->destscale = 3*mobj->target->scale/2; + smoke->scalespeed = mobj->target->scale/12; + + smoke->momx = mobj->target->momx/2; + smoke->momy = mobj->target->momy/2; + smoke->momz = mobj->target->momz/2; + + P_Thrust(smoke, mobj->angle+FixedAngle(P_RandomRange(135, 225)<target->scale); + } + break; + case MT_SPARKLETRAIL: + if (!mobj->target) + { + P_RemoveMobj(mobj); + return false; + } + mobj->color = mobj->target->color; + mobj->colorized = mobj->target->colorized; + break; + case MT_INVULNFLASH: + if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_invincibilitytimer])) + { + P_RemoveMobj(mobj); + return false; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + break; + case MT_BRAKEDRIFT: + if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target)) + || !mobj->target->player->kartstuff[k_drift] || !mobj->target->player->kartstuff[k_brakedrift] + || !((mobj->target->player->cmd.buttons & BT_BRAKE) + || !(mobj->target->player->cmd.buttons & BT_ACCELERATE))) // Letting go of accel functions about the same as brake-drifting + { + P_RemoveMobj(mobj); + return false; + } + else + { + UINT8 driftcolor = K_DriftSparkColor(mobj->target->player, mobj->target->player->kartstuff[k_driftcharge]); + fixed_t newx, newy; + angle_t travelangle; + + travelangle = mobj->target->angle - ((ANGLE_45/5)*mobj->target->player->kartstuff[k_drift]); + + newx = mobj->target->x + P_ReturnThrustX(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale); + newy = mobj->target->y + P_ReturnThrustY(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale); + P_TeleportMove(mobj, newx, newy, mobj->target->z); + + mobj->angle = travelangle - ((ANGLE_90/5)*mobj->target->player->kartstuff[k_drift]); + P_SetScale(mobj, (mobj->destscale = mobj->target->scale)); + + if (driftcolor != SKINCOLOR_NONE) + mobj->color = driftcolor; + else + mobj->color = SKINCOLOR_SILVER; + + if (!S_SoundPlaying(mobj, sfx_cdfm17)) + S_StartSound(mobj, sfx_cdfm17); + + K_MatchGenericExtraFlags(mobj, mobj->target); + if (leveltime & 1) + mobj->drawflags |= MFD_DONTDRAW; + } + break; + case MT_PLAYERRETICULE: + if (!mobj->target || !mobj->target->health) + { + P_RemoveMobj(mobj); + return false; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + break; + case MT_INSTASHIELDB: + mobj->drawflags ^= MFD_DONTDRAW; + K_MatchGenericExtraFlags(mobj, mobj->target); + /* FALLTHRU */ + case MT_INSTASHIELDA: + if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_instashield])) + { + P_RemoveMobj(mobj); + return false; + } + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + K_MatchGenericExtraFlags(mobj, mobj->target); + break; + case MT_BATTLEPOINT: + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + P_RemoveMobj(mobj); + return false; + } + + if (mobj->movefactor < 48*mobj->target->scale) + { + mobj->movefactor += (48*mobj->target->scale)/6; + if (mobj->movefactor > mobj->target->height) + mobj->movefactor = mobj->target->height; + } + else if (mobj->movefactor > 48*mobj->target->scale) + { + mobj->movefactor -= (48*mobj->target->scale)/6; + if (mobj->movefactor < mobj->target->height) + mobj->movefactor = mobj->target->height; + } + K_MatchGenericExtraFlags(mobj, mobj->target); + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor); + break; + case MT_RINGSPARKS: + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + P_RemoveMobj(mobj); + return false; + } + + mobj->z = mobj->target->z; + + K_MatchGenericExtraFlags(mobj, mobj->target); + + P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), + mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), + mobj->z + mobj->target->height * P_MobjFlip(mobj)); + break; + case MT_FLAMESHIELDPAPER: + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + P_RemoveMobj(mobj); + return false; + } + + mobj->z = mobj->target->z; + + K_MatchGenericExtraFlags(mobj, mobj->target); + + { + INT32 perpendicular = ((mobj->extravalue1 & 1) ? -ANGLE_90 : ANGLE_90); + fixed_t newx = mobj->target->x + P_ReturnThrustX(NULL, mobj->target->angle + perpendicular, 8*mobj->target->scale); + fixed_t newy = mobj->target->y + P_ReturnThrustY(NULL, mobj->target->angle + perpendicular, 8*mobj->target->scale); + + P_TeleportMove(mobj, newx, newy, mobj->target->z); + + if (mobj->extravalue1 & 1) + mobj->angle = mobj->target->angle - ANGLE_45; + else + mobj->angle = mobj->target->angle + ANGLE_45; + } + break; + case MT_TIREGREASE: + if (!mobj->target || P_MobjWasRemoved(mobj->target) || !mobj->target->player + || !mobj->target->player->kartstuff[k_tiregrease]) + { + P_RemoveMobj(mobj); + return false; + } + + K_MatchGenericExtraFlags(mobj, mobj->target); + + { + const angle_t off = FixedAngle(40*FRACUNIT); + angle_t ang = mobj->target->angle; + fixed_t z; + UINT8 trans = (mobj->target->player->kartstuff[k_tiregrease] * (NUMTRANSMAPS+1)) / greasetics; + + if (trans > NUMTRANSMAPS) + trans = NUMTRANSMAPS; + + trans = NUMTRANSMAPS - trans; + + z = mobj->target->z; + if (mobj->eflags & MFE_VERTICALFLIP) + z += mobj->target->height; + + if (mobj->target->momx || mobj->target->momy) + ang = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy); + + if (mobj->extravalue1) + ang = (signed)(ang - off); + else + ang = (signed)(ang + off); + + P_TeleportMove(mobj, + mobj->target->x - FixedMul(mobj->target->radius, FINECOSINE(ang >> ANGLETOFINESHIFT)), + mobj->target->y - FixedMul(mobj->target->radius, FINESINE(ang >> ANGLETOFINESHIFT)), + z); + mobj->angle = ang; + + if (leveltime & 1) + mobj->drawflags |= MFD_DONTDRAW; + + if (trans >= NUMTRANSMAPS) + mobj->drawflags |= MFD_DONTDRAW; + else if (trans == 0) + mobj->drawflags = (mobj->drawflags & ~MFD_TRANSMASK); + else + mobj->drawflags = (mobj->drawflags & ~MFD_TRANSMASK)|(trans << MFD_TRANSSHIFT); + } + break; + case MT_THUNDERSHIELD: + { + fixed_t destx, desty; + if (!mobj->target || !mobj->target->health || !mobj->target->player + || mobj->target->player->kartstuff[k_curshield] != KSHIELD_THUNDER) + { + P_RemoveMobj(mobj); + return false; + } + P_SetScale(mobj, (mobj->destscale = (5*mobj->target->scale)>>2)); + + if (!r_splitscreen /*&& rendermode != render_soft*/) + { + angle_t viewingangle; + statenum_t curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); + + if (players[displayplayers[0]].awayviewtics) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y); + else if (!camera[0].chase && players[displayplayers[0]].mo) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y); + else + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y); + + if (curstate > S_THUNDERSHIELD15 && curstate <= S_THUNDERSHIELD24) + viewingangle += ANGLE_180; + + destx = mobj->target->x + P_ReturnThrustX(mobj->target, viewingangle, mobj->scale>>4); + desty = mobj->target->y + P_ReturnThrustY(mobj->target, viewingangle, mobj->scale>>4); + } + else + { + destx = mobj->target->x; + desty = mobj->target->y; + } + + P_TeleportMove(mobj, destx, desty, mobj->target->z); + break; + } + case MT_BUBBLESHIELD: + { + fixed_t destx, desty; + fixed_t scale; + statenum_t curstate; + + if (!mobj->target || !mobj->target->health || !mobj->target->player + || mobj->target->player->kartstuff[k_curshield] != KSHIELD_BUBBLE) + { + P_RemoveMobj(mobj); + return false; + } + + scale = (5*mobj->target->scale)>>2; + curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); + + if (mobj->target->player->kartstuff[k_bubbleblowup]) + { + INT32 blow = mobj->target->player->kartstuff[k_bubbleblowup]; + if (blow > bubbletime) + blow = bubbletime; + + if (curstate != S_BUBBLESHIELDBLOWUP) + P_SetMobjState(mobj, S_BUBBLESHIELDBLOWUP); + + mobj->angle += ANGLE_22h; + mobj->drawflags &= ~MFD_SHADOW; + scale += (blow * (3*scale)) / bubbletime; + + mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + mobj->extravalue1); + if ((mobj->target->player->kartstuff[k_bubbleblowup] > bubbletime) && (leveltime & 1)) + mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + 5); + + if (mobj->extravalue1 < 4 && mobj->extravalue2 < blow && !mobj->cvmem && (leveltime & 1)) // Growing + { + mobj->extravalue1++; + if (mobj->extravalue1 >= 4) + mobj->cvmem = 1; // shrink back down + } + else if ((mobj->extravalue1 > -4 && mobj->extravalue2 > blow) + || (mobj->cvmem && mobj->extravalue1 > 0)) // Shrinking + mobj->extravalue1--; + + if (P_IsObjectOnGround(mobj->target)) + { + UINT8 i; + + for (i = 0; i < 2; i++) + { + angle_t a = mobj->angle + ((i & 1) ? ANGLE_180 : 0); + fixed_t ws = (mobj->target->scale>>1); + mobj_t *wave; + + ws += (blow * ws) / bubbletime; + + wave = P_SpawnMobj( + (mobj->target->x - mobj->target->momx) + P_ReturnThrustX(NULL, a, mobj->radius - (21*ws)), + (mobj->target->y - mobj->target->momy) + P_ReturnThrustY(NULL, a, mobj->radius - (21*ws)), + (mobj->target->z - mobj->target->momz), MT_THOK); + + wave->flags &= ~(MF_NOCLIPHEIGHT|MF_NOGRAVITY); + P_SetScale(wave, (wave->destscale = ws)); + + P_SetMobjState(wave, S_BUBBLESHIELDWAVE1); + + wave->momx = mobj->target->momx; + wave->momy = mobj->target->momy; + wave->momz = mobj->target->momz; + } + } + } + else + { + mobj->cvmem = 0; + mobj->angle = mobj->target->angle; + + if (curstate == S_BUBBLESHIELDBLOWUP) + { + if (mobj->extravalue1 != 0) + { + mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + mobj->extravalue1); + + if (mobj->extravalue1 < 0 && (leveltime & 1)) + mobj->extravalue1++; + else if (mobj->extravalue1 > 0) + mobj->extravalue1--; + } + else + { + P_SetMobjState(mobj, S_BUBBLESHIELD1); + mobj->extravalue1 = 0; + } + } + else + { + if (mobj->target->player->kartstuff[k_bubblecool] && ((curstate-S_BUBBLESHIELD1) & 1)) + mobj->drawflags |= MFD_SHADOW; + else + mobj->drawflags &= ~MFD_SHADOW; + } + } + + mobj->extravalue2 = mobj->target->player->kartstuff[k_bubbleblowup]; + P_SetScale(mobj, (mobj->destscale = scale)); + + if (!splitscreen /*&& rendermode != render_soft*/) + { + angle_t viewingangle; + + if (players[displayplayers[0]].awayviewtics) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y); + else if (!camera[0].chase && players[displayplayers[0]].mo) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y); + else + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y); + + destx = mobj->target->x + P_ReturnThrustX(mobj->target, viewingangle, mobj->scale>>4); + desty = mobj->target->y + P_ReturnThrustY(mobj->target, viewingangle, mobj->scale>>4); + } + else + { + destx = mobj->target->x; + desty = mobj->target->y; + } + + P_TeleportMove(mobj, destx, desty, mobj->target->z); + break; + } + case MT_FLAMESHIELD: + { + fixed_t destx, desty; + statenum_t curstate; + statenum_t underlayst = S_NULL; + INT32 flamemax = 0; + + if (!mobj->target || !mobj->target->health || !mobj->target->player + || mobj->target->player->kartstuff[k_curshield] != KSHIELD_FLAME) + { + P_RemoveMobj(mobj); + return false; + } + + flamemax = mobj->target->player->kartstuff[k_flamelength] * flameseg; + + P_SetScale(mobj, (mobj->destscale = (5*mobj->target->scale)>>2)); + + curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); + + if (mobj->target->player->kartstuff[k_flamedash]) + { + if (!(curstate >= S_FLAMESHIELDDASH1 && curstate <= S_FLAMESHIELDDASH12)) + P_SetMobjState(mobj, S_FLAMESHIELDDASH1); + + if (curstate == S_FLAMESHIELDDASH2) + underlayst = S_FLAMESHIELDDASH2_UNDERLAY; + else if (curstate == S_FLAMESHIELDDASH5) + underlayst = S_FLAMESHIELDDASH5_UNDERLAY; + else if (curstate == S_FLAMESHIELDDASH8) + underlayst = S_FLAMESHIELDDASH8_UNDERLAY; + else if (curstate == S_FLAMESHIELDDASH11) + underlayst = S_FLAMESHIELDDASH11_UNDERLAY; + + if (leveltime & 1) + { + UINT8 i; + UINT8 nl = 2; + + if (mobj->target->player->kartstuff[k_flamedash] > mobj->extravalue1) + nl = 3; + + for (i = 0; i < nl; i++) + { + mobj_t *fast = P_SpawnMobj(mobj->x + (P_RandomRange(-36,36) * mobj->scale), + mobj->y + (P_RandomRange(-36,36) * mobj->scale), + mobj->z + (mobj->height/2) + (P_RandomRange(-20,20) * mobj->scale), + MT_FASTLINE); + + fast->angle = mobj->angle; + fast->momx = 3*mobj->target->momx/4; + fast->momy = 3*mobj->target->momy/4; + fast->momz = 3*mobj->target->momz/4; + + K_MatchGenericExtraFlags(fast, mobj); + P_SetMobjState(fast, S_FLAMESHIELDLINE1 + i); + } + } + } + else + { + if (curstate >= S_FLAMESHIELDDASH1 && curstate <= S_FLAMESHIELDDASH12) + P_SetMobjState(mobj, S_FLAMESHIELD1); + } + + mobj->extravalue1 = mobj->target->player->kartstuff[k_flamedash]; + + if (mobj->target->player->kartstuff[k_flamemeter] > flamemax) + { + mobj_t *flash = P_SpawnMobj(mobj->x + mobj->target->momx, mobj->y + mobj->target->momy, mobj->z + mobj->target->momz, MT_THOK); + P_SetMobjState(flash, S_FLAMESHIELDFLASH); + + if (leveltime & 1) + { + flash->frame |= 2 + ((leveltime / 2) % 4); + } + else + { + flash->frame |= ((leveltime / 2) % 2); + } + } + + if (!splitscreen /*&& rendermode != render_soft*/) + { + angle_t viewingangle; + + if (players[displayplayers[0]].awayviewtics) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y); + else if (!camera[0].chase && players[displayplayers[0]].mo) + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y); + else + viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y); + + if (curstate >= S_FLAMESHIELD1 && curstate < S_FLAMESHIELDDASH1 && ((curstate-S_FLAMESHIELD1) & 1)) + viewingangle += ANGLE_180; + + destx = mobj->target->x + P_ReturnThrustX(mobj->target, viewingangle, mobj->scale>>4); + desty = mobj->target->y + P_ReturnThrustY(mobj->target, viewingangle, mobj->scale>>4); + } + else + { + destx = mobj->target->x; + desty = mobj->target->y; + } + + P_TeleportMove(mobj, destx, desty, mobj->target->z); + if (mobj->target->momx || mobj->target->momy) + mobj->angle = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy); + else + mobj->angle = mobj->target->angle; + + if (underlayst != S_NULL) + { + mobj_t *underlay = P_SpawnMobj(mobj->target->x, mobj->target->y, mobj->target->z, MT_FLAMESHIELDUNDERLAY); + underlay->angle = mobj->angle; + P_SetMobjState(underlay, underlayst); + } + break; + } + case MT_ROCKETSNEAKER: + if (!mobj->target || !mobj->target->health) + { + P_RemoveMobj(mobj); + return false; + } + if (mobj->target->player && !mobj->target->player->kartstuff[k_rocketsneakertimer]) + { + mobj->flags &= ~MF_NOGRAVITY; + mobj->angle += ANGLE_45; + + if (!mobj->extravalue2) + { + K_DropRocketSneaker(mobj->target->player); + } + else if (P_IsObjectOnGround(mobj)) + { + P_RemoveMobj(mobj); + return false; + } + } + break; + case MT_KARMAHITBOX: + { + statenum_t state = (mobj->state-states); + + if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator + || (gametype == GT_RACE || mobj->target->player->kartstuff[k_bumper])) + { + P_RemoveMobj(mobj); + return false; + } + + P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); + mobj->angle = mobj->target->angle; + mobj->scalespeed = mobj->target->scalespeed; + mobj->destscale = mobj->target->destscale; + P_SetScale(mobj, mobj->target->scale); + mobj->color = mobj->target->color; + mobj->colorized = true; + + // Give items an item-sized hitbox + if (mobj->target->player->kartstuff[k_comebackmode] == 1) + mobj->radius = 48*mobj->target->scale; + else + mobj->radius = 24*mobj->target->scale; + mobj->height = 2*mobj->radius; + + if (mobj->target->player->kartstuff[k_comebacktimer] > 0) + { + if (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20) + P_SetMobjState(mobj, S_PLAYERBOMB1); + if (mobj->target->player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1)) + mobj->drawflags &= ~MFD_DONTDRAW; + else + mobj->drawflags |= MFD_DONTDRAW; + } + else + { + if (!mobj->target->player->kartstuff[k_comebackmode] + && (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20)) + P_SetMobjState(mobj, S_PLAYERBOMB1); + else if (mobj->target->player->kartstuff[k_comebackmode] == 1 + && (state < S_PLAYERITEM1 || state > S_PLAYERITEM12)) + P_SetMobjState(mobj, S_PLAYERITEM1); + else if (mobj->target->player->kartstuff[k_comebackmode] == 2 + && (state < S_PLAYERFAKE1 || state > S_PLAYERFAKE12)) + P_SetMobjState(mobj, S_PLAYERFAKE1); + + if (mobj->target->player->powers[pw_flashing] && (leveltime & 1)) + mobj->drawflags |= MFD_DONTDRAW; + else + mobj->drawflags &= ~MFD_DONTDRAW; + } + + // Update mobj antigravity status: + mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); + mobj->flags2 = (mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP); + + // Now for the wheels + { + const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->target->scale); + mobj_t *cur = mobj->hnext; + + while (cur && !P_MobjWasRemoved(cur)) + { + fixed_t offx = rad; + fixed_t offy = rad; + + if (cur->lastlook == 1 || cur->lastlook == 3) + offx *= -1; + if (cur->lastlook == 2 || cur->lastlook == 3) + offy *= -1; + + P_TeleportMove(cur, mobj->x + offx, mobj->y + offy, mobj->z); + cur->scalespeed = mobj->target->scalespeed; + cur->destscale = mobj->target->destscale; + P_SetScale(cur, mobj->target->scale); + cur->color = mobj->target->color; + cur->colorized = true; + K_FlipFromObject(cur, mobj->target); + + if (mobj->drawflags & MFD_DONTDRAW) + cur->drawflags |= MFD_DONTDRAW; + else + cur->drawflags &= ~MFD_DONTDRAW; + + cur = cur->hnext; + } + } + } + break; + case MT_SIGN: // Kart's unique sign behavior + if (mobj->movecount != 0) + { + mobj_t *cur = mobj->hnext; + SINT8 newskin = -1; + UINT8 newcolor = SKINCOLOR_NONE; + angle_t endangle = FixedAngle(mobj->extravalue1 << FRACBITS); + + if (mobj->movecount == 1) + { + if (mobj->z + mobj->momz <= mobj->movefactor) + { + if (mobj->info->attacksound) + S_StartSound(mobj, mobj->info->attacksound); + + mobj->z = mobj->movefactor; + mobj->momz = 0; + mobj->movecount = 2; + + newskin = ((skin_t*)mobj->target->skin) - skins; + newcolor = mobj->target->player->skincolor; + } + else + { + fixed_t g = (6*mobj->scale); + UINT16 ticstilimpact = abs(mobj->z - mobj->movefactor) / g; + + P_SpawnMobj( + mobj->x + FixedMul(48*mobj->scale, FINECOSINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->y + FixedMul(48*mobj->scale, FINESINE(mobj->angle >> ANGLETOFINESHIFT)), + mobj->z + ((24 + ((leveltime % 4) * 8)) * mobj->scale), + MT_SIGNSPARKLE + ); + + if (ticstilimpact == (3*TICRATE/2)) + { + if (mobj->info->seesound) + S_StartSound(mobj, mobj->info->seesound); + } + + mobj->angle += ANGLE_45; + mobj->momz = -g; + + if (mobj->angle == endangle + ANGLE_180) + { + if (ticstilimpact <= 8) + { + newskin = ((skin_t*)mobj->target->skin) - skins; + newcolor = mobj->target->player->skincolor; + } + else + { + UINT8 plist[MAXPLAYERS]; + UINT8 plistlen = 0; + UINT8 i; + + memset(plist, 0, sizeof(plist)); + + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && !players[i].spectator) + { + plist[plistlen] = i; + plistlen++; + } + } + + if (plistlen <= 1) + { + // Default to the winner + newskin = ((skin_t*)mobj->target->skin) - skins; + newcolor = mobj->target->player->skincolor; + } + else + { + // Pick another player in the server! + player_t *p = &players[plist[P_RandomKey(plistlen)]]; + newskin = ((skin_t*)p->mo->skin) - skins; + newcolor = p->skincolor; + } + } + } + } + } + else if (mobj->movecount == 2) + { + if (mobj->angle != endangle) + mobj->angle += ANGLE_11hh; + } + + while (cur && !P_MobjWasRemoved(cur)) + { + fixed_t amt = cur->extravalue1 * mobj->scale; + angle_t dir = mobj->angle + (cur->extravalue2 * ANGLE_90); + fixed_t z = mobj->z + (23*mobj->scale); + + if (cur->state == &states[S_SIGN_FACE]) + { + if (newcolor != SKINCOLOR_NONE) + { + cur->color = skincolors[newcolor].invcolor; + cur->frame = cur->state->frame + skincolors[newcolor].invshade; + } + } + else if (cur->state == &states[S_KART_SIGN]) + { + z += (5*mobj->scale); + amt += 1; + + if (newskin != -1) + { + cur->skin = &skins[newskin]; + cur->color = newcolor; + } + } + else if (cur->state == &states[S_SIGN_ERROR]) + { + z += (5*mobj->scale); + amt += 1; + } + + P_TeleportMove( + cur, + mobj->x + FixedMul(amt, FINECOSINE(dir >> ANGLETOFINESHIFT)), + mobj->y + FixedMul(amt, FINESINE(dir >> ANGLETOFINESHIFT)), + z + ); + cur->angle = dir + ANGLE_90; + + cur = cur->hnext; + } + } + break; + case MT_CDUFO: + if (!mobj->spawnpoint || mobj->fuse) + break; + + if (mobj->movecount) + { + mobj->movecount--; + break; + } + else if (P_AproxDistance(mobj->x - (mobj->spawnpoint->x<y - (mobj->spawnpoint->y<movecount = 3; + + { + angle_t facing = P_RandomRange(0, 90); + if (facing >= 45) + facing = InvAngle((facing - 45)*ANG1); + else + facing *= ANG1; + + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->spawnpoint->x<spawnpoint->y<extravalue1) + { + fixed_t mx = P_ReturnThrustX(NULL, mobj->angle, 32*mobj->scale); + fixed_t my = P_ReturnThrustY(NULL, mobj->angle, 32*mobj->scale); + mobj_t *explosion = P_SpawnMobj(mobj->x + (2*mx), mobj->y + (2*my), mobj->z+(mobj->height/2), MT_THOK); + + P_SetMobjState(explosion, S_FZEROBOOM1); + explosion->scale = mobj->scale*2; + explosion->momx = mx; + explosion->momy = my; + + S_StartSound(mobj, mobj->info->seesound); + mobj->extravalue1 = 1; + } + + if (!S_SoundPlaying(mobj, mobj->info->attacksound)) + S_StartSound(mobj, mobj->info->attacksound); + + if (mobj->extravalue2 <= 8) // Short delay + mobj->extravalue2++; // flametimer + else // fire + smoke pillar + { + UINT8 i; + mobj_t *fire = P_SpawnMobj(mobj->x + (P_RandomRange(-32, 32)*mobj->scale), mobj->y + (P_RandomRange(-32, 32)*mobj->scale), mobj->z, MT_THOK); + + fire->sprite = SPR_FPRT; + fire->frame = FF_FULLBRIGHT|FF_TRANS30; + fire->scale = mobj->scale*4; + fire->momz = P_RandomRange(2, 3)*mobj->scale; + fire->scalespeed = mobj->scale/12; + fire->destscale = 1; + fire->tics = TICRATE; + + for (i = 0; i < 2; i++) + { + mobj_t *smoke = P_SpawnMobj(mobj->x + (P_RandomRange(-16, 16)*mobj->scale), mobj->y + (P_RandomRange(-16, 16)*mobj->scale), mobj->z, MT_SMOKE); + + P_SetMobjState(smoke, S_FZSLOWSMOKE1); + smoke->scale = mobj->scale; + smoke->momz = P_RandomRange(3, 10)*mobj->scale; + smoke->destscale = mobj->scale*4; + smoke->scalespeed = mobj->scale/24; + } + } + break; + case MT_EZZPROPELLER: + if (mobj->hnext) + { + mobj_t *cur = mobj->hnext; + + while (cur && !P_MobjWasRemoved(cur)) + { + cur->angle += FixedAngle(mobj->info->speed); + P_TeleportMove(cur, mobj->x + FINECOSINE((cur->angle*8)>>ANGLETOFINESHIFT), + mobj->y + FINESINE((cur->angle*8)>>ANGLETOFINESHIFT), mobj->z); + //P_SpawnGhostMobj(cur)->tics = 2; + + cur = cur->hnext; + } + } + if (!S_SoundPlaying(mobj, mobj->info->seesound)) + S_StartSound(mobj, mobj->info->seesound); + break; + case MT_FROGGER: + { + statenum_t frogstate = (mobj->state-states); + + // FROG ATTACK VALUES: + // threshold: distance + // movecount: time + // lastlook: direction + // extravalue1: x step + // extravalue2: y step + // cusval: z step + + if (frogstate == S_FROGGER) + { + mobj->threshold = mobj->movecount = mobj->lastlook = 0; // clear tongue attack + mobj->extravalue1 = mobj->extravalue2 = mobj->cusval = 0; + if (mobj->hnext) // Clean hnext list + { + mobj_t *cur = mobj->hnext; + while (cur && !P_MobjWasRemoved(cur)) + { + mobj_t *next = cur->hnext; + P_RemoveMobj(cur); + cur = next; + } + } + + if (mobj->reactiontime) + mobj->reactiontime--; + else + { + if (mobj->flags2 & MF2_AMBUSH) + { + mobj->momz = P_RandomRange(12, 16)<x, mobj->y, mobj->z + (mobj->height/2), MT_FROGTONGUE); + P_SetTarget(&mobj->tracer, tongue); + P_SetMobjState(mobj, S_FROGGER_ATTACK); + } + } + } + else if (frogstate == S_FROGGER_ATTACK) + { + if (!mobj->tracer || P_MobjWasRemoved(mobj->tracer)) + { + mobj->reactiontime = mobj->info->reactiontime; + P_SetMobjState(mobj, S_FROGGER); + break; + } + + if (mobj->threshold == 0) + { + fixed_t targetz = mobj->tracer->z; //mobj->z + (mobj->height/2) + + mobj->threshold = 256; + mobj->movecount = 1; + mobj->lastlook = 1; + + mobj->tracer->angle = mobj->angle; + + mobj->extravalue1 = FixedMul(FixedMul((mobj->threshold/16)<>ANGLETOFINESHIFT)), + FINECOSINE(mobj->angle>>ANGLETOFINESHIFT)) >> FRACBITS; + + mobj->extravalue2 = FixedMul(FixedMul((mobj->threshold/16)<>ANGLETOFINESHIFT)), + FINESINE(mobj->angle>>ANGLETOFINESHIFT)) >> FRACBITS; + + mobj->cusval = FixedMul((mobj->threshold/16)<>ANGLETOFINESHIFT)) >> FRACBITS; + + S_StartSound(mobj, sfx_s3k8c); // Play that tongue-y sound. + } + + mobj->movecount += mobj->lastlook; + + if (!(P_TryMove(mobj->tracer, mobj->x + ((mobj->extravalue1<movecount), mobj->y + ((mobj->extravalue2<movecount), true)) + || (mobj->movecount >= 16) // maximum travel time + || (mobj->tracer->z <= mobj->tracer->floorz) // Through the floor + || ((mobj->tracer->z + mobj->tracer->height) >= mobj->tracer->ceilingz)) // Through the ceiling + { + mobj->lastlook = -1; // Reverse direction. + } + + if (mobj->movecount == 0) // It's back to its source, time to reset. + { + mobj->threshold = mobj->lastlook = 0; + + P_RemoveMobj(mobj->tracer); + + if (mobj->hnext) // Clean hnext list + { + mobj_t *cur = mobj->hnext; + while (cur && !P_MobjWasRemoved(cur)) + { + mobj_t *next = cur->hnext; + P_RemoveMobj(cur); + cur = next; + } + } + + mobj->reactiontime = mobj->info->reactiontime; + P_SetMobjState(mobj, S_FROGGER); + } + else + { + const UINT8 numjoints = 11; + UINT8 joint = numjoints; + mobj_t *cur = mobj->hnext, *prev = mobj; + + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); + + for (; joint > 0; joint--) + { + fixed_t wx = mobj->tracer->x + (joint * (mobj->x - mobj->tracer->x) / (numjoints+1)); + fixed_t wy = mobj->tracer->y + (joint * (mobj->y - mobj->tracer->y) / (numjoints+1)); + fixed_t wz = mobj->tracer->z + (joint * ((mobj->z + (mobj->height/2)) - mobj->tracer->z) / (numjoints+1)); + + if (cur && !P_MobjWasRemoved(cur)) + P_TeleportMove(cur, wx, wy, wz); + else + cur = P_SpawnMobj(wx, wy, wz, MT_FROGTONGUE_JOINT); + + P_SetTarget(&cur->target, mobj); + + P_SetTarget(&prev->hnext, cur); + P_SetTarget(&cur->hprev, prev); + + prev = cur; + cur = cur->hnext; + } + } + } + else if (frogstate == S_FROGGER_JUMP) + { + if (P_IsObjectOnGround(mobj)) + { + mobj->reactiontime = mobj->info->reactiontime; + P_SetMobjState(mobj, S_FROGGER); + } + } + } + break; + case MT_ROBRA: + case MT_BLUEROBRA: + if (mobj->health) + { + boolean blue = (mobj->type == MT_BLUEROBRA); + + if (blue) + { + if (mobj->spawnpoint) + mobj->extravalue2 = mobj->spawnpoint->angle; + else + mobj->extravalue2 = 128; + } + else + { + if (!mobj->extravalue2) + mobj->extravalue2 = P_RandomRange(64, 192); + } + + if (mobj->reactiontime) + mobj->reactiontime--; + else + { + if (!mobj->extravalue1) + { + mobj_t *head = P_SpawnMobj(mobj->x, mobj->y, mobj->z, (blue ? MT_BLUEROBRA_HEAD : MT_ROBRA_HEAD)); + P_SetTarget(&mobj->tracer, head); + + mobj->destscale = mapobjectscale; + P_SetTarget(&mobj->tracer->target, mobj->target); + P_SetTarget(&mobj->tracer->tracer, mobj); + mobj->tracer->extravalue2 = mobj->extravalue2; + + if (!blue) + mobj->tracer->angle = mobj->angle; + + mobj->extravalue1 = 1; + } + } + + if ((mobj->extravalue1) && !(mobj->tracer && !P_MobjWasRemoved(mobj->tracer))) + { + mobj->reactiontime = 20*mobj->info->reactiontime; + P_SetTarget(&mobj->target, NULL); + mobj->extravalue1 = 0; + } + + if ((mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) && !(leveltime % 10)) + { + mobj_t *dust = P_SpawnMobj(mobj->x + (P_RandomRange(-4, 4)<y + (P_RandomRange(-4, 4)<z + (P_RandomRange(0, 2)<scale/2); + P_InstaThrust(dust, FixedAngle(P_RandomRange(0,359)<tracer->momz)/2); + + if (abs(mobj->tracer->momz) >= 2<health) + { + boolean blue = (mobj->type == MT_BLUEROBRA_HEAD); + UINT8 locnumsegs = abs(mobj->z - mobj->floorz) / (32 * mobj->scale); + UINT8 i; + mobj_t *cur = mobj->hnext, *prev = mobj; + + if (blue) + mobj->angle = (angle_t)mobj->extravalue1; + mobj->extravalue1 += (FixedAngle(2*mobj->momz) * (blue ? -1 : 1)); + + for (i = 0; i < locnumsegs*2; i++) // *2 to check for any extra segs still present + { + fixed_t segz = mobj->z - ((i+1) * (32 * mobj->scale)); + + if (cur && !P_MobjWasRemoved(cur)) + { + if (i >= locnumsegs) // Remove extras + { + mobj_t *next = cur->hnext; + P_RemoveMobj(cur); + cur = next; + continue; + } + else // Move into place + P_TeleportMove(cur, mobj->x, mobj->y, segz); + } + else + { + if (i >= locnumsegs) // We're done with this list + continue; //break; + else // Need another here! + cur = P_SpawnMobj(mobj->x, mobj->y, segz, (blue ? MT_BLUEROBRA_JOINT : MT_ROBRA_JOINT)); + } + + P_SetTarget(&cur->target, mobj); + P_SetScale(cur, (7*mobj->scale)/8); + + cur->angle = mobj->extravalue1; + mobj->extravalue1 += (FixedAngle(2*mobj->momz) * (blue ? -1 : 1)); + + P_SetTarget(&prev->hnext, cur); + P_SetTarget(&cur->hprev, prev); + + prev = cur; + cur = cur->hnext; + } + + { + //fixed_t ceilingheight = mobj->ceilingz - (72<floorz + (72<floorz + (mobj->extravalue2<z < targetheight) + { + mobj->momz += mobj->info->speed; + if ((mobj->z < floorheight) && (mobj->momz < 0)) + mobj->momz /= 2; + } + else + { + mobj->momz -= mobj->info->speed; + if ((mobj->z > (targetheight + (64<momz > 0)) + mobj->momz /= 2; + } + } + } + break; + case MT_ROBRA_JOINT: + case MT_BLUEROBRA_JOINT: + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + P_RemoveMobj(mobj); + return false; + } + break; + case MT_SMK_PIPE: + if (mobj->flags2 & MF2_AMBUSH) + P_SetMobjStateNF(mobj, mobj->info->seestate); + else + P_SetMobjStateNF(mobj, mobj->info->spawnstate); + break; + case MT_SMK_MOLESPAWNER: + if (!mobj->target || P_MobjWasRemoved(mobj->target)) + { + mobj_t *newmole = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_MOLE); + P_SetTarget(&mobj->target, newmole); + return false; + } + break; + case MT_SMK_MOLE: + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + player_t *player = mobj->target->player; + + mobj->extravalue1 = 1; + player->kartstuff[k_offroad] += 2<mo->x + P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius) + + P_ReturnThrustX(NULL, player->mo->angle+ANGLE_90, (mobj->threshold)<mo->y + P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius) + + P_ReturnThrustY(NULL, player->mo->angle+ANGLE_90, (mobj->threshold)<mo->z + (player->mo->height/2 * P_MobjFlip(player->mo)) + + (P_RandomRange(-abs(mobj->threshold), abs(mobj->threshold))<threshold /= 2; + mobj->momz = 0; + + if (mobj->movecount > 8*TICRATE) + { + P_KillMobj(mobj, mobj->target, mobj->target, DMG_NORMAL); + break; + } + + if (abs(player->cmd.turning) > 100) + { + INT32 lastsign = 0; + if (mobj->lastlook > 0) + lastsign = 1; + else if (mobj->lastlook < 0) + lastsign = -1; + + if ((player->cmd.turning > 0 && lastsign < 0) + || (player->cmd.turning < 0 && lastsign > 0)) + { + mobj->movecount += (TICRATE/2); + mobj->threshold = 16*lastsign; + S_StartSound(mobj, sfx_s1ab); + } + + mobj->lastlook = player->cmd.turning; + } + + mobj->movecount++; + } + else if (mobj->extravalue1) // lost your player somehow, DIE + { + P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); + break; + } + else + { + if (P_IsObjectOnGround(mobj)) + { + if (mobj->reactiontime) + mobj->reactiontime--; + else + { + mobj->momz = (mobj->info->speed * P_MobjFlip(mobj)); + mobj->reactiontime = mobj->info->reactiontime; + } + } + } + break; + case MT_SMK_THWOMP: + if (mobj->flags2 & MF2_AMBUSH) + { + mobj->colorized = true; + mobj->color = K_RainbowColor(leveltime); + mobj->frame |= FF_FULLBRIGHT; + } + else + { + mobj->colorized = false; + mobj->color = SKINCOLOR_NONE; + mobj->frame &= (~FF_FULLBRIGHT); + } + + if (!thwompsactive) + break; + + if (mobj->reactiontime) + mobj->reactiontime--; + else + { + if (mobj->extravalue1) + { + P_SpawnGhostMobj(mobj)->tics = 3; + + if (mobj->z == mobj->floorz) + { + UINT8 i; + + mobj->extravalue1 = 0; + mobj->reactiontime = mobj->info->reactiontime; + S_StartSound(mobj, sfx_s1bd); + + for (i = 0; i < 8; i++) + { + mobj_t *dust = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_DRIFTDUST); + P_InstaThrust(dust, FixedAngle(((360*FRACUNIT)/8) * i), mobj->info->speed/8); + dust->momz = P_MobjFlip(mobj) * (P_RandomRange(1,4)<scale = mobj->scale/2; + dust->destscale = mobj->scale*3; + } + } + else + mobj->momz = (-mobj->info->speed) * P_MobjFlip(mobj); + } + else + { + if (mobj->z > mobj->movefactor) + mobj->z = mobj->movefactor; + + if (mobj->z == mobj->movefactor) + { + mobj->extravalue1 = 1; + //S_StartSound(mobj, sfx_s1bb); + } + else + mobj->momz = (mobj->info->speed/16) * P_MobjFlip(mobj); + } + } + break; + case MT_BUBBLESHIELDTRAP: + if (leveltime % 180 == 0) + S_StartSound(mobj, sfx_s3kbfl); + + if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer) && mobj->tracer->player) + { + player_t *player = mobj->tracer->player; + fixed_t destx, desty, curfz, destfz; + boolean blockmove = false; + + mobj->flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP; + mobj->extravalue1 = 1; + + mobj->cvmem /= 2; + mobj->momz = 0; + mobj->destscale = ((5*mobj->tracer->scale)>>2) + (mobj->tracer->scale>>3); + + mobj->tracer->momz = (8*mobj->tracer->scale) * P_MobjFlip(mobj->tracer); + + mobj->tracer->momx = (31*mobj->tracer->momx)/32; + mobj->tracer->momy = (31*mobj->tracer->momy)/32; + + destx = mobj->x + mobj->tracer->momx; + desty = mobj->y + mobj->tracer->momy; + + if (mobj->tracer->eflags & MFE_VERTICALFLIP) + { + curfz = P_GetCeilingZ(mobj->tracer, mobj->tracer->subsector->sector, mobj->tracer->x, mobj->tracer->y, NULL); + destfz = P_GetCeilingZ(mobj->tracer, R_PointInSubsector(destx, desty)->sector, destx, desty, NULL); + blockmove = (curfz - destfz >= 24*mobj->scale); + } + else + { + curfz = P_GetFloorZ(mobj->tracer, mobj->tracer->subsector->sector, mobj->tracer->x, mobj->tracer->y, NULL); + destfz = P_GetFloorZ(mobj->tracer, R_PointInSubsector(destx, desty)->sector, destx, desty, NULL); + blockmove = (destfz - curfz >= 24*mobj->scale); + } + + if (blockmove) + { + mobj->tracer->momx = mobj->tracer->momy = 0; + } + + P_TeleportMove(mobj, + mobj->tracer->x + P_ReturnThrustX(NULL, mobj->tracer->angle+ANGLE_90, (mobj->cvmem)<tracer->y + P_ReturnThrustY(NULL, mobj->tracer->angle+ANGLE_90, (mobj->cvmem)<tracer->z - (4*mobj->tracer->scale) + (P_RandomRange(-abs(mobj->cvmem), abs(mobj->cvmem))<movecount > 4*TICRATE) + { + S_StartSound(mobj->tracer, sfx_s3k77); + mobj->tracer->flags &= ~MF_NOGRAVITY; + P_KillMobj(mobj, mobj->tracer, mobj->tracer, DMG_NORMAL); + break; + } + + if (abs(player->cmd.turning) > 100) + { + INT32 lastsign = 0; + if (mobj->lastlook > 0) + lastsign = 1; + else if (mobj->lastlook < 0) + lastsign = -1; + + if ((player->cmd.turning > 0 && lastsign < 0) + || (player->cmd.turning < 0 && lastsign > 0)) + { + mobj->movecount += (TICRATE/2); + mobj->cvmem = 8*lastsign; + S_StartSound(mobj, sfx_s3k7a); + } + + mobj->lastlook = player->cmd.turning; + } + + mobj->movecount++; + } + else if (mobj->extravalue1) // lost your player somehow, DIE + { + P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); + break; + } + else + { + mobj->destscale = (5*mapobjectscale)>>2; + + if (mobj->threshold > 0) + mobj->threshold--; + + if (abs(mobj->momx) < 8*mobj->destscale && abs(mobj->momy) < 8*mobj->destscale) + { + // Stop, give light gravity + mobj->momx = mobj->momy = 0; + mobj->momz = -(mobj->scale * P_MobjFlip(mobj)); + } + else + { + UINT8 i; + mobj_t *ghost = P_SpawnGhostMobj(mobj); + + if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) + { + ghost->color = mobj->target->player->skincolor; + ghost->colorized = true; + } + + mobj->momx = (23*mobj->momx)/24; + mobj->momy = (23*mobj->momy)/24; + + mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); + + if ((mobj->z - mobj->floorz) < (24*mobj->scale) && (leveltime % 3 != 0)) + { + // Cool wave effects! + for (i = 0; i < 2; i++) + { + angle_t aoff; + SINT8 sign = 1; + mobj_t *wave; + + if (i & 1) + sign = -1; + else + sign = 1; + + aoff = (mobj->angle + ANGLE_180) + (ANGLE_45 * sign); + + wave = P_SpawnMobj(mobj->x + FixedMul(mobj->radius, FINECOSINE(aoff>>ANGLETOFINESHIFT)), + mobj->y + FixedMul(mobj->radius, FINESINE(aoff>>ANGLETOFINESHIFT)), + mobj->z, MT_THOK); + + wave->flags &= ~(MF_NOCLIPHEIGHT|MF_NOGRAVITY); + P_SetScale(wave, (wave->destscale = mobj->scale/2)); + + P_SetMobjState(wave, S_BUBBLESHIELDWAVE1); + if (leveltime & 1) + wave->tics++; + + P_SetTarget(&wave->target, mobj); + wave->angle = mobj->angle - (ANGLE_90 * sign); // point completely perpendicular from the bubble + K_FlipFromObject(wave, mobj); + + P_Thrust(wave, wave->angle, 4*mobj->scale); + } + } + } + } + break; + case MT_KARMAFIREWORK: + if (mobj->flags & MF_NOGRAVITY) + break; + + if (mobj->momz == 0) + { + P_RemoveMobj(mobj); + return false; + } + else + { + mobj_t *trail = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_THOK); + P_SetMobjState(trail, S_KARMAFIREWORKTRAIL); + P_SetScale(trail, mobj->scale); + trail->destscale = 1; + trail->scalespeed = mobj->scale/12; + trail->color = mobj->color; + } + break; + case MT_BATTLECAPSULE: + { + SINT8 realflip = P_MobjFlip(mobj); + SINT8 flip = realflip; // Flying capsules needs flipped sprites, but not flipped gravity + fixed_t bottom; + mobj_t *cur; + + if (mobj->extravalue1) + { + const INT32 speed = 6*TICRATE; // longer is slower + const fixed_t pi = 22*FRACUNIT/7; // Inaccurate, but is close enough for our usage + fixed_t sine = FINESINE((((2*pi*speed) * leveltime) >> ANGLETOFINESHIFT) & FINEMASK) * flip; + + // Flying capsules are flipped upside-down, like S3K + flip = -flip; + + // ALL CAPSULE MOVEMENT NEEDS TO HAPPEN AFTER THIS & ADD TO MOMENTUM FOR BOBBING TO BE ACCURATE + mobj->momz = sine/2; + } + + // Moving capsules + if (mobj->target && !P_MobjWasRemoved(mobj->target)) + { + fixed_t speed = mobj->movefactor; + UINT8 sequence = mobj->lastlook; + UINT8 num = mobj->movecount; + boolean backandforth = (mobj->flags2 & MF2_AMBUSH); + SINT8 direction = mobj->cvmem; + mobj_t *next = NULL; + thinker_t *th; + fixed_t dist, momx, momy, momz; + + dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y); + if (mobj->extravalue1) + dist = P_AproxDistance(dist, mobj->target->z - mobj->z); + if (dist < 1) + dist = 1; + + if (speed <= dist) + { + momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); + momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); + if (mobj->extravalue1) + momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); + + mobj->momx = momx; + mobj->momy = momy; + if (mobj->extravalue1) + mobj->momz = momz; + } + else + { + mobj_t *mo2; + + speed -= dist; + + P_UnsetThingPosition(mobj); + mobj->x = mobj->target->x; + mobj->y = mobj->target->y; + mobj->z = mobj->target->z; + P_SetThingPosition(mobj); + + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + + // Onto the next waypoint! + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_TUBEWAYPOINT) + continue; + + if (mo2->threshold == sequence) + { + if (mo2->health == num + direction) + { + next = mo2; + break; + } + } + } + + // Are we at the end of the waypoint chain? + // If so, search again for the first/previous waypoint (depending on settings) + if (next == NULL) + { + if (backandforth) + { + mobj->cvmem = -mobj->cvmem; + direction = mobj->cvmem; + } + + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_TUBEWAYPOINT) + continue; + + if (mo2->threshold == sequence) + { + if (backandforth) + { + if (mo2->health == num + direction) + { + next = mo2; + break; + } + } + else + { + if (direction < 0) + { + if (next == NULL || mo2->health > next->health) + next = mo2; + } + else + { + if (next == NULL || mo2->health < next->health) + next = mo2; + } + } + } + } + } + + if (next && !P_MobjWasRemoved(next)) + { + P_SetTarget(&mobj->target, next); + mobj->movecount = next->health; + + dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y); + if (mobj->extravalue1) + dist = P_AproxDistance(dist, mobj->target->z - mobj->z); + if (dist < 1) + dist = 1; + + momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); + momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); + if (mobj->extravalue1) + momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); + + mobj->momx = momx; + mobj->momy = momy; + if (mobj->extravalue1) + mobj->momz = momz; + } + else + { + CONS_Alert(CONS_WARNING, "Moving capsule could not find next waypoint! (seq: %d)\n", sequence); + P_SetTarget(&mobj->target, NULL); + } + } + } + + if (flip == -1) + bottom = mobj->z + mobj->height; + else + bottom = mobj->z; + + cur = mobj->hnext; + + // Move each piece to the proper position + while (cur && !P_MobjWasRemoved(cur)) + { + fixed_t newx = mobj->x; + fixed_t newy = mobj->y; + fixed_t newz = bottom; + statenum_t state = (statenum_t)(cur->state-states); + + cur->scale = mobj->scale; + cur->destscale = mobj->destscale; + cur->scalespeed = mobj->scalespeed; + + cur->extravalue2 = mobj->extravalue1; + + cur->flags2 = (cur->flags2 & ~MF2_OBJECTFLIP)|(mobj->flags2 & MF2_OBJECTFLIP); + + if (state == S_BATTLECAPSULE_TOP) + newz += (80 * mobj->scale * flip); + else if (state == S_BATTLECAPSULE_BUTTON) + newz += (108 * mobj->scale * flip); + else if (state == S_BATTLECAPSULE_SUPPORT + || state == S_BATTLECAPSULE_SUPPORTFLY + || state == S_KARMAWHEEL) + { + fixed_t offx = mobj->radius; + fixed_t offy = mobj->radius; + + if (cur->extravalue1 & 1) + offx = -offx; + + if (cur->extravalue1 > 1) + offy = -offy; + + newx += offx; + newy += offy; + } + else if (state == S_BATTLECAPSULE_SIDE1 + || state == S_BATTLECAPSULE_SIDE2) + { + fixed_t offset = 48 * mobj->scale; + angle_t angle = (ANGLE_45 * cur->extravalue1); + + newx += FixedMul(offset, FINECOSINE(angle >> ANGLETOFINESHIFT)); + newy += FixedMul(offset, FINESINE(angle >> ANGLETOFINESHIFT)); + newz += (12 * mobj->scale * flip); + + cur->angle = angle + ANGLE_90; + } + + P_TeleportMove(cur, newx, newy, newz); + + cur = cur->hnext; + } + } + break; + case MT_RANDOMITEM: + if (gametype == GT_BATTLE && mobj->threshold == 70) + { + mobj->color = K_RainbowColor(leveltime); + mobj->colorized = true; + + if (battleovertime.enabled) + { + angle_t ang = FixedAngle((leveltime % 360) << FRACBITS); + fixed_t z = battleovertime.z; + fixed_t dist; + mobj_t *ghost; + + /*if (z < mobj->subsector->sector->floorheight) + z = mobj->subsector->sector->floorheight;*/ + + if (mobj->extravalue1 < 512) + mobj->extravalue1++; + dist = mobj->extravalue1 * mapobjectscale; + + P_TeleportMove(mobj, battleovertime.x + P_ReturnThrustX(NULL, ang, dist), + battleovertime.y + P_ReturnThrustY(NULL, ang, dist), z); + + ghost = P_SpawnGhostMobj(mobj); + ghost->fuse = 4; + ghost->frame |= FF_FULLBRIGHT; + } + } + else + { + player_t *player = K_GetItemBoxPlayer(mobj); + UINT8 color = SKINCOLOR_BLACK; + + if (player != NULL) + { + color = player->skincolor; + } + + mobj->color = color; + mobj->colorized = false; + } + break; + default: + // check mobj against possible water content, before movement code + P_MobjCheckWater(mobj); + break; + } + return true; +} + +static void P_FiringThink(mobj_t *mobj) +{ + if (!mobj->target) + return; + + if (mobj->health <= 0) + return; + + if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) + { + if (mobj->state->tics > 1) + { + var1 = mobj->state->var1; + var2 = mobj->state->var2 & 65535; + mobj->state->action.acp1(mobj); + } + } + else if (leveltime & 1) // Fire mode + { + mobj_t *missile; + + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); + missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); + + if (missile) + { + if (mobj->flags2 & MF2_SUPERFIRE) + missile->flags2 |= MF2_SUPERFIRE; + + if (mobj->info->attacksound) + S_StartSound(missile, mobj->info->attacksound); + } + } + else + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); +} + +static void P_MonitorFuseThink(mobj_t *mobj) +{ + mobj_t *newmobj; + + // Special case for ALL monitors. + // If a box's speed is nonzero, it's allowed to respawn as a WRM/SRM. + if (mobj->info->speed != 0 && (mobj->flags2 & (MF2_AMBUSH|MF2_STRONGBOX))) + { + mobjtype_t spawnchance[64]; + INT32 numchoices = 0, i = 0; + + // This define should make it a lot easier to organize and change monitor weights +#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \ +for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type + + // Type SRM WRM + SETMONITORCHANCES(MT_SNEAKERS_BOX, 0, 10); // Super Sneakers + SETMONITORCHANCES(MT_INVULN_BOX, 2, 0); // Invincibility + SETMONITORCHANCES(MT_WHIRLWIND_BOX, 3, 8); // Whirlwind Shield + SETMONITORCHANCES(MT_ELEMENTAL_BOX, 3, 8); // Elemental Shield + SETMONITORCHANCES(MT_ATTRACT_BOX, 2, 0); // Attraction Shield + SETMONITORCHANCES(MT_FORCE_BOX, 3, 3); // Force Shield + SETMONITORCHANCES(MT_ARMAGEDDON_BOX, 2, 0); // Armageddon Shield + SETMONITORCHANCES(MT_MIXUP_BOX, 0, 1); // Teleporters + SETMONITORCHANCES(MT_RECYCLER_BOX, 0, 1); // Recycler + SETMONITORCHANCES(MT_1UP_BOX, 1, 1); // 1-Up + // ======================================= + // Total 16 32 + +#undef SETMONITORCHANCES + + i = P_RandomKey(numchoices); // Gotta love those random numbers! + newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]); + } + else + newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); + + // Transfer flags2 (ambush, strongbox, objectflip) + newmobj->flags2 = mobj->flags2; + P_RemoveMobj(mobj); // make sure they disappear +} + +static boolean P_FuseThink(mobj_t *mobj) +{ + if (mobj->type == MT_SNAPPER_HEAD || mobj->type == MT_SNAPPER_LEG || mobj->type == MT_MINECARTSEG) + mobj->drawflags ^= MFD_DONTDRAW; + + if (mobj->fuse <= TICRATE && ((mobj->type == MT_RANDOMITEM && mobj->threshold == 69) || mobj->type == MT_EGGMANITEM || mobj->type == MT_FALLINGROCK)) + mobj->drawflags ^= MFD_DONTDRAW; + + mobj->fuse--; + + if (mobj->fuse) + return true; + + if (LUAh_MobjFuse(mobj) || P_MobjWasRemoved(mobj)) + ; + else if (mobj->info->flags & MF_MONITOR) + { + P_MonitorFuseThink(mobj); + return false; + } + else switch (mobj->type) + { + // gargoyle and snowman handled in P_PushableThinker, not here + case MT_SPIKE: + P_SetMobjState(mobj, mobj->state->nextstate); + mobj->fuse = mobj->info->speed; + if (mobj->spawnpoint) + mobj->fuse += mobj->spawnpoint->angle; + break; + case MT_WALLSPIKE: + P_SetMobjState(mobj, mobj->state->nextstate); + mobj->fuse = mobj->info->speed; + if (mobj->spawnpoint) + mobj->fuse += (mobj->spawnpoint->angle / 360); + break; + case MT_LAVAFALL: + if (mobj->state - states == S_LAVAFALL_DORMANT) + { + mobj->fuse = 30; + P_SetMobjState(mobj, S_LAVAFALL_TELL); + S_StartSound(mobj, mobj->info->seesound); + } + else if (mobj->state - states == S_LAVAFALL_TELL) + { + mobj->fuse = 40; + P_SetMobjState(mobj, S_LAVAFALL_SHOOT); + S_StopSound(mobj); + S_StartSound(mobj, mobj->info->attacksound); + } + else + { + mobj->fuse = 30; + P_SetMobjState(mobj, S_LAVAFALL_DORMANT); + S_StopSound(mobj); + } + return false; + case MT_RANDOMITEM: + if ((gametyperules & GTR_BUMPERS) && (mobj->threshold != 70)) + { + if (mobj->threshold != 69) + break; + } + else + { + mobj_t *newmobj; + + // Respawn from mapthing if you have one! + if (mobj->spawnpoint) + { + P_SpawnMapThing(mobj->spawnpoint); + newmobj = mobj->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing + } + else + newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); + + P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_EXPLODE); // poof into existance + // Transfer flags2 (strongbox, objectflip) + newmobj->flags2 = mobj->flags2; + if (mobj->threshold == 70) + newmobj->threshold = 70; + } + P_RemoveMobj(mobj); // make sure they disappear + return false; + case MT_SMK_ICEBLOCK: + { + mobj_t *cur = mobj->hnext, *next; + UINT8 i; + + for (i = 0; i < 5; i++) + { + mobj_t *debris = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_ICEBLOCK_DEBRIS); + debris->angle = FixedAngle(P_RandomRange(0,360)<angle, P_RandomRange(3,18)*(FRACUNIT/4)); + debris->momz = P_RandomRange(4,8)<hnext; + P_RemoveMobj(cur); + cur = next; + } + + P_RemoveMobj(mobj); + return false; + } + case MT_PLAYER: + break; // don't remove + default: + P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL. + break; + // Looking for monitors? They moved to a special condition above. + } + + return !P_MobjWasRemoved(mobj); } // @@ -6370,23 +8403,24 @@ void P_MobjThinker(mobj_t *mobj) if (mobj->flags & MF_NOTHINK) return; + if ((mobj->flags & MF_BOSS) && mobj->spawnpoint && (bossdisabled & (1<spawnpoint->extrainfo))) + return; + // Remove dead target/tracer. if (mobj->target && P_MobjWasRemoved(mobj->target)) P_SetTarget(&mobj->target, NULL); if (mobj->tracer && P_MobjWasRemoved(mobj->tracer)) P_SetTarget(&mobj->tracer, NULL); - // hnext/hprev changes suggested by toaster if (mobj->hnext && P_MobjWasRemoved(mobj->hnext)) P_SetTarget(&mobj->hnext, NULL); if (mobj->hprev && P_MobjWasRemoved(mobj->hprev)) P_SetTarget(&mobj->hprev, NULL); - mobj->flags2 &= ~MF2_PUSHED; - mobj->eflags &= ~(MFE_SPRUNG|MFE_JUSTBOUNCEDWALL); + mobj->eflags &= ~(MFE_PUSHED|MFE_SPRUNG|MFE_JUSTBOUNCEDWALL); tmfloorthing = tmhitthing = NULL; - // 970 allows ANY mobj to trigger a linedef exec + // Sector special (2,8) allows ANY mobj to trigger a linedef exec if (mobj->subsector && GETSECSPECIAL(mobj->subsector->sector->special, 2) == 8) { sector_t *sec2; @@ -6396,758 +8430,32 @@ void P_MobjThinker(mobj_t *mobj) P_LinedefExecute(sec2->tag, mobj, sec2); } - // Slowly scale up/down to reach your destscale. if (mobj->scale != mobj->destscale) + P_MobjScaleThink(mobj); // Slowly scale up/down to reach your destscale. + + if ((mobj->type == MT_GHOST || mobj->type == MT_THOK) && mobj->fuse > 0) // Not guaranteed to be MF_SCENERY or not MF_SCENERY! { - fixed_t oldheight = mobj->height; - UINT8 correctionType = 0; // Don't correct Z position, just gain height - - if (mobj->z > mobj->floorz && mobj->z + mobj->height < mobj->ceilingz - && mobj->type != MT_EGGMOBILE_FIRE) - correctionType = 1; // Correct Z position by centering - else if (mobj->eflags & MFE_VERTICALFLIP) - correctionType = 2; // Correct Z position by moving down - - if (abs(mobj->scale - mobj->destscale) < mobj->scalespeed) - P_SetScale(mobj, mobj->destscale); - else if (mobj->scale < mobj->destscale) - P_SetScale(mobj, mobj->scale + mobj->scalespeed); - else if (mobj->scale > mobj->destscale) - P_SetScale(mobj, mobj->scale - mobj->scalespeed); - - if (correctionType == 1) - mobj->z -= (mobj->height - oldheight)/2; - else if (correctionType == 2) - mobj->z -= mobj->height - oldheight; - - if (mobj->scale == mobj->destscale) + if (mobj->flags2 & MF2_BOSSNOTRAP) // "fast" flag { - /// \todo Lua hook for "reached destscale"? - - if (mobj->scale == 0) - { - P_RemoveMobj(mobj); - return; - } - - switch (mobj->type) - { - case MT_EGGMOBILE_FIRE: - mobj->destscale = FRACUNIT; - mobj->scalespeed = FRACUNIT>>4; - break; - default: - break; - } + if ((signed)((mobj->frame & FF_TRANSMASK) >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - (2*mobj->fuse)/3) + // fade out when nearing the end of fuse... + mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - (2*mobj->fuse)/3) << FF_TRANSSHIFT); + } + else + { + if ((signed)((mobj->frame & FF_TRANSMASK) >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - mobj->fuse / 2) + // fade out when nearing the end of fuse... + mobj->frame = (mobj->frame & ~FF_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << FF_TRANSSHIFT); } } - if (mobj->type == MT_GHOST && mobj->fuse > 0 // Not guaranteed to be MF_SCENERY or not MF_SCENERY! - && (signed)(mobj->frame >> FF_TRANSSHIFT) < (NUMTRANSMAPS-1) - mobj->fuse / 2) - // fade out when nearing the end of fuse... - mobj->drawflags = (mobj->drawflags & ~MFD_TRANSMASK) | (((NUMTRANSMAPS-1) - mobj->fuse / 2) << MFD_TRANSSHIFT); - // Special thinker for scenery objects if (mobj->flags & MF_SCENERY) { -#ifdef HAVE_BLUA - if (LUAh_MobjThinker(mobj)) - return; - if (P_MobjWasRemoved(mobj)) - return; -#endif - switch (mobj->type) - { - case MT_FOLLOWER: - // small thinker for follower: - // We cleanse ourselves from existence if our target player doesn't exist for whatever reason. (generally players leaving) - if (!mobj->target || P_MobjWasRemoved(mobj->target) || !mobj->target->player || mobj->target->player->spectator || mobj->target->player->followerskin < 0) - { - // Remove possible hnext list (bubble) - mobj_t *bub = mobj->hnext; - mobj_t *tmp; - - while (bub && !P_MobjWasRemoved(bub)) - { - tmp = bub->hnext; - P_RemoveMobj(bub); - bub = tmp; - } - - P_RemoveMobj(mobj); - } - - return; - - case MT_HOOP: - if (mobj->fuse > 1) - P_MoveHoop(mobj); - else if (mobj->fuse == 1) - mobj->movecount = 1; - - if (mobj->movecount) - { - mobj->fuse++; - - if (mobj->fuse > 32) - { - // Don't kill the hoop center. For the sake of respawning. - //if (mobj->target) - // P_RemoveMobj(mobj->target); - - P_RemoveMobj(mobj); - } - } - else - mobj->fuse--; - return; - case MT_NIGHTSPARKLE: - if (mobj->tics != -1) - { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - return; // freed itself - } - - P_UnsetThingPosition(mobj); - mobj->x += mobj->momx; - mobj->y += mobj->momy; - mobj->z += mobj->momz; - P_SetThingPosition(mobj); - return; - case MT_NIGHTSLOOPHELPER: - if (--mobj->tics <= 0) - P_RemoveMobj(mobj); - - // Don't touch my fuse! - return; - case MT_OVERLAY: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - - P_AddOverlay(mobj); - break; - /*case MT_BLACKORB: - case MT_WHITEORB: - case MT_GREENORB: - case MT_YELLOWORB: - case MT_BLUEORB: - case MT_PITYORB: - if (!P_AddShield(mobj)) - return; - break;*/ - //{ SRB2kart mobs - case MT_ORBINAUT_SHIELD: // Kart orbit/trail items - case MT_JAWZ_SHIELD: - case MT_BANANA_SHIELD: - case MT_SSMINE_SHIELD: - case MT_EGGMANITEM_SHIELD: - case MT_SINK_SHIELD: - if ((mobj->health > 0 - && (!mobj->target || !mobj->target->player || mobj->target->player->health <= 0 || mobj->target->player->spectator)) - || (mobj->health <= 0 && P_IsObjectOnGround(mobj)) - || P_CheckDeathPitCollide(mobj)) // When in death state - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_SMOLDERING: - if (leveltime % 2 == 0) - { - fixed_t x = P_RandomRange(-35, 35)*mobj->scale; - fixed_t y = P_RandomRange(-35, 35)*mobj->scale; - fixed_t z = P_RandomRange(0, 70)*mobj->scale; - mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); - P_SetMobjState(smoke, S_OPAQUESMOKE1); - K_MatchGenericExtraFlags(smoke, mobj); - smoke->scale = mobj->scale * 2; - smoke->destscale = mobj->scale * 6; - smoke->momz = P_RandomRange(4, 9)*FRACUNIT*P_MobjFlip(smoke); - } - break; - case MT_BOOMPARTICLE: - { - fixed_t x = P_RandomRange(-16, 16)*mobj->scale; - fixed_t y = P_RandomRange(-16, 16)*mobj->scale; - fixed_t z = P_RandomRange(0, 32)*mobj->scale*P_MobjFlip(mobj); - if (leveltime % 2 == 0) - { - mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_BOSSEXPLODE); - K_MatchGenericExtraFlags(smoke, mobj); - P_SetMobjState(smoke, S_QUICKBOOM1); - smoke->scale = mobj->scale/2; - smoke->destscale = mobj->scale; - smoke->color = mobj->color; - } - else - { - mobj_t *smoke = P_SpawnMobj(mobj->x + x, mobj->y + y, mobj->z + z, MT_SMOKE); - P_SetMobjState(smoke, S_OPAQUESMOKE1); - K_MatchGenericExtraFlags(smoke, mobj); - smoke->scale = mobj->scale; - smoke->destscale = mobj->scale*2; - } - if (mobj->tics <= TICRATE) - { - mobj->destscale = FixedDiv(mobj->scale, 100*FRACUNIT); - } - } - break; - case MT_BATTLEBUMPER: - if (mobj->health > 0 && mobj->target && mobj->target->player - && mobj->target->player->health > 0 && !mobj->target->player->spectator) - { - fixed_t rad = 32*mobj->target->scale; - fixed_t offz; - angle_t ang, diff; - - if (!((mobj->target->player-players) & 1)) - ang = (FixedAngle(mobj->info->speed) * -1); - else - ang = FixedAngle(mobj->info->speed); - - if (mobj->target->player->kartstuff[k_bumper] <= 1) - diff = 0; - else - diff = FixedAngle(360*FRACUNIT/mobj->target->player->kartstuff[k_bumper]); - - ang = (ang*leveltime) + (diff * (mobj->threshold-1)); - - // If the player is on the ceiling, then flip your items as well. - if (mobj->target->eflags & MFE_VERTICALFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - offz = mobj->target->height / 2; - } - else - { - mobj->eflags &= ~MFE_VERTICALFLIP; - offz = mobj->target->height / 5; - } - - mobj->drawflags = (mobj->target->drawflags & MFD_DONTDRAW); - - if (mobj->target->eflags & MFE_VERTICALFLIP) - offz += 4*FRACUNIT; - else - offz -= 4*FRACUNIT; - - if (mobj->tracer && mobj->tracer->player && mobj->tracer->player->mo - && mobj->tracer->player->health > 0 && !mobj->tracer->player->spectator) // STOLEN - mobj->color = mobj->tracer->player->skincolor; // don't do star flashing for stolen bumpers - else - mobj->color = mobj->target->color; // but do so if it belongs to you :B - - if (mobj->target->player->kartstuff[k_bumper] < 2) - P_SetMobjState(mobj, S_BATTLEBUMPER3); - else if (mobj->target->player->kartstuff[k_bumper] < 3) - P_SetMobjState(mobj, S_BATTLEBUMPER2); - else - P_SetMobjState(mobj, S_BATTLEBUMPER1); - - // Shrink your items if the player shrunk too. - mobj->scale = mobj->target->scale; - - P_UnsetThingPosition(mobj); - { - const angle_t fa = ang>>ANGLETOFINESHIFT; - mobj->x = mobj->target->x + FixedMul(FINECOSINE(fa), rad); - mobj->y = mobj->target->y + FixedMul(FINESINE(fa), rad); - mobj->z = mobj->target->z + offz; - P_SetThingPosition(mobj); - } - - // Was this so hard? - if (mobj->target->player->kartstuff[k_bumper] <= mobj->threshold) - { - P_RemoveMobj(mobj); - return; - } - } - else if ((mobj->health > 0 - && (!mobj->target || !mobj->target->player || !mobj->target->player->mo || mobj->target->player->health <= 0 || mobj->target->player->spectator)) - || (mobj->health <= 0 && P_IsObjectOnGround(mobj)) - || P_CheckDeathPitCollide(mobj)) // When in death state - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_PLAYERARROW: - if (mobj->target && mobj->target->health - && mobj->target->player && !mobj->target->player->spectator - && mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD - /*&& players[displayplayers[0]].mo && !players[displayplayers[0]].spectator*/) - { - fixed_t scale = 3*mobj->target->scale; - mobj->color = mobj->target->color; - K_MatchGenericExtraFlags(mobj, mobj->target); - - if ((G_RaceGametype() || mobj->target->player->kartstuff[k_bumper] <= 0) -#if 1 // Set to 0 to test without needing to host - || (P_IsDisplayPlayer(mobj->target->player)) -#endif - ) - mobj->drawflags |= MFD_DONTDRAW; - - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - - mobj->angle = R_PointToAngle(mobj->x, mobj->y) + ANGLE_90; // literally only happened because i wanted to ^L^R the SPR_ITEM's - - if (!r_splitscreen && players[displayplayers[0]].mo) - { - scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x, - players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); - if (scale > 16*mobj->target->scale) - scale = 16*mobj->target->scale; - } - mobj->destscale = scale; - - if (!(mobj->target->eflags & MFE_VERTICALFLIP)) - { - mobj->z = mobj->target->z + P_GetPlayerHeight(mobj->target->player) + (16*mobj->target->scale); - mobj->eflags &= ~MFE_VERTICALFLIP; - } - else - { - mobj->z = mobj->target->z - P_GetPlayerHeight(mobj->target->player) - (16*mobj->target->scale); - mobj->eflags |= MFE_VERTICALFLIP; - } - P_SetThingPosition(mobj); - - if (!mobj->tracer) - { - mobj_t *overlay = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); - P_SetTarget(&mobj->tracer, overlay); - P_SetTarget(&mobj->tracer->target, mobj); - P_SetMobjState(mobj->tracer, S_PLAYERARROW_ITEM); - P_SetScale(mobj->tracer, (mobj->tracer->destscale = mobj->scale)); - } - - // Do this in an easy way - if (mobj->target->player->kartstuff[k_itemroulette]) - { - mobj->tracer->color = mobj->target->player->skincolor; - mobj->tracer->colorized = true; - } - else - { - mobj->tracer->color = SKINCOLOR_NONE; - mobj->tracer->colorized = false; - } - - if (!(mobj->drawflags & MFD_DONTDRAW)) - { - const INT32 numberdisplaymin = ((mobj->target->player->kartstuff[k_itemtype] == KITEM_ORBINAUT) ? 5 : 2); - - // Set it to use the correct states for its condition - if (mobj->target->player->kartstuff[k_itemroulette]) - { - P_SetMobjState(mobj, S_PLAYERARROW_BOX); - mobj->tracer->sprite = SPR_ITEM; - mobj->tracer->frame = FF_FULLBRIGHT|(((mobj->target->player->kartstuff[k_itemroulette] % (13*3)) / 3) + 1); - mobj->tracer->drawflags &= ~MFD_DONTDRAW; - } - else if (mobj->target->player->kartstuff[k_stolentimer] > 0) - { - P_SetMobjState(mobj, S_PLAYERARROW_BOX); - mobj->tracer->sprite = SPR_ITEM; - mobj->tracer->frame = FF_FULLBRIGHT|KITEM_HYUDORO; - if (leveltime & 2) - mobj->tracer->drawflags &= ~MFD_DONTDRAW; - else - mobj->tracer->drawflags |= MFD_DONTDRAW; - } - else if ((mobj->target->player->kartstuff[k_stealingtimer] > 0) && (leveltime & 2)) - { - P_SetMobjState(mobj, S_PLAYERARROW_BOX); - mobj->tracer->sprite = SPR_ITEM; - mobj->tracer->frame = FF_FULLBRIGHT|KITEM_HYUDORO; - mobj->tracer->drawflags &= ~MFD_DONTDRAW; - } - else if (mobj->target->player->kartstuff[k_eggmanexplode] > 1) - { - P_SetMobjState(mobj, S_PLAYERARROW_BOX); - mobj->tracer->sprite = SPR_ITEM; - mobj->tracer->frame = FF_FULLBRIGHT|KITEM_EGGMAN; - if (leveltime & 1) - mobj->tracer->drawflags &= ~MFD_DONTDRAW; - else - mobj->tracer->drawflags |= MFD_DONTDRAW; - } - else if (mobj->target->player->kartstuff[k_rocketsneakertimer] > 1) - { - //itembar = mobj->target->player->kartstuff[k_rocketsneakertimer]; -- not today satan - P_SetMobjState(mobj, S_PLAYERARROW_BOX); - mobj->tracer->sprite = SPR_ITEM; - mobj->tracer->frame = FF_FULLBRIGHT|KITEM_ROCKETSNEAKER; - if (leveltime & 1) - mobj->tracer->drawflags &= ~MFD_DONTDRAW; - else - mobj->tracer->drawflags |= MFD_DONTDRAW; - } - else if (mobj->target->player->kartstuff[k_itemtype] && mobj->target->player->kartstuff[k_itemamount] > 0) - { - P_SetMobjState(mobj, S_PLAYERARROW_BOX); - - switch (mobj->target->player->kartstuff[k_itemtype]) - { - case KITEM_ORBINAUT: - mobj->tracer->sprite = SPR_ITMO; - mobj->tracer->frame = FF_FULLBRIGHT|(min(mobj->target->player->kartstuff[k_itemamount]-1, 3)); - break; - case KITEM_INVINCIBILITY: - mobj->tracer->sprite = SPR_ITMI; - mobj->tracer->frame = FF_FULLBRIGHT|((leveltime % (7*3)) / 3); - break; - case KITEM_SAD: - mobj->tracer->sprite = SPR_ITEM; - mobj->tracer->frame = FF_FULLBRIGHT; - break; - default: - mobj->tracer->sprite = SPR_ITEM; - mobj->tracer->frame = FF_FULLBRIGHT|(mobj->target->player->kartstuff[k_itemtype]); - break; - } - - if (mobj->target->player->kartstuff[k_itemheld]) - { - if (leveltime & 1) - mobj->tracer->drawflags &= ~MFD_DONTDRAW; - else - mobj->tracer->drawflags |= MFD_DONTDRAW; - } - else - mobj->tracer->drawflags &= ~MFD_DONTDRAW; - } - else - { - P_SetMobjState(mobj, S_PLAYERARROW); - P_SetMobjState(mobj->tracer, S_PLAYERARROW_ITEM); - } - - mobj->tracer->destscale = scale; - - if (mobj->target->player->kartstuff[k_itemamount] >= numberdisplaymin - && mobj->target->player->kartstuff[k_itemamount] <= 10) // Meh, too difficult to support greater than this; convert this to a decent HUD object and then maybe :V - { - mobj_t *number = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); - mobj_t *numx = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); - - P_SetTarget(&number->target, mobj); - P_SetMobjState(number, S_PLAYERARROW_NUMBER); - P_SetScale(number, mobj->scale); - number->destscale = scale; - number->frame = FF_FULLBRIGHT|(mobj->target->player->kartstuff[k_itemamount]); - - P_SetTarget(&numx->target, mobj); - P_SetMobjState(numx, S_PLAYERARROW_X); - P_SetScale(numx, mobj->scale); - numx->destscale = scale; - } - - if (K_IsPlayerWanted(mobj->target->player) && mobj->movecount != 1) - { - mobj_t *wanted = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PLAYERWANTED); - P_SetTarget(&wanted->target, mobj->target); - P_SetTarget(&wanted->tracer, mobj); - P_SetScale(wanted, mobj->scale); - wanted->destscale = scale; - mobj->movecount = 1; - } - else if (!K_IsPlayerWanted(mobj->target->player)) - mobj->movecount = 0; - } - else - mobj->tracer->drawflags |= MFD_DONTDRAW; - } - else if (mobj->health > 0) - { - P_KillMobj(mobj, NULL, NULL); - return; - } - break; - case MT_PLAYERWANTED: - if (mobj->target && mobj->target->health && mobj->tracer - && mobj->target->player && !mobj->target->player->spectator - && mobj->target->player->health && mobj->target->player->playerstate != PST_DEAD - && players[g_localplayers[0]].mo && !players[g_localplayers[0]].spectator) - { - fixed_t scale = 3*mobj->target->scale; - - if (!K_IsPlayerWanted(mobj->target->player)) - { - mobj->tracer->movecount = 0; - P_RemoveMobj(mobj); - return; - } - - if (mobj->tracer->drawflags & MFD_DONTDRAW) - mobj->drawflags |= MFD_DONTDRAW; - else - mobj->drawflags &= ~MFD_DONTDRAW; - - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - - if (!r_splitscreen && players[displayplayers[0]].mo) - { - scale = mobj->target->scale + FixedMul(FixedDiv(abs(P_AproxDistance(players[displayplayers[0]].mo->x-mobj->target->x, - players[displayplayers[0]].mo->y-mobj->target->y)), RING_DIST), mobj->target->scale); - if (scale > 16*mobj->target->scale) - scale = 16*mobj->target->scale; - } - mobj->destscale = scale; - - if (!(mobj->target->eflags & MFE_VERTICALFLIP)) - { - mobj->z = mobj->target->z + (P_GetPlayerHeight(mobj->target->player)) + (16*mobj->target->scale) + (64*scale); - mobj->eflags &= ~MFE_VERTICALFLIP; - } - else - { - mobj->z = mobj->target->z - (P_GetPlayerHeight(mobj->target->player)) - (16*mobj->target->scale) - (64*scale); - mobj->eflags |= MFE_VERTICALFLIP; - } - P_SetThingPosition(mobj); - } - else if (mobj->health > 0) - { - P_KillMobj(mobj, NULL, NULL); - return; - } - break; - case MT_PETSMOKER: - if (!(leveltime % 10)) - { - mobj_t *smok = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_PETSMOKE); - if (mobj->spawnpoint && mobj->spawnpoint->options & MTF_OBJECTSPECIAL) - P_SetMobjStateNF(smok, smok->info->painstate); // same function, diff sprite - } - break; - case MT_BATTLECAPSULE_PIECE: - if (mobj->extravalue2) - mobj->frame |= FF_VERTICALFLIP; - else - mobj->frame &= ~FF_VERTICALFLIP; - - if (mobj->flags2 & MF2_OBJECTFLIP) - mobj->eflags |= MFE_VERTICALFLIP; - - if (mobj->tics > 0) - mobj->drawflags ^= MFD_DONTDRAW; - break; - //} - case MT_WATERDROP: - P_SceneryCheckWater(mobj); - if ((mobj->z <= mobj->floorz || mobj->z <= mobj->watertop) - && mobj->health > 0) - { - mobj->health = 0; - P_SetMobjState(mobj, mobj->info->deathstate); - S_StartSound(mobj, mobj->info->deathsound+P_RandomKey(mobj->info->mass)); - return; - } - break; - case MT_BUBBLES: - P_SceneryCheckWater(mobj); - break; - case MT_SMALLBUBBLE: - case MT_MEDIUMBUBBLE: - case MT_EXTRALARGEBUBBLE: // start bubble dissipate - P_SceneryCheckWater(mobj); - if (P_MobjWasRemoved(mobj)) // bubble was removed by not being in water - return; - if (!(mobj->eflags & MFE_UNDERWATER) - || (!(mobj->eflags & MFE_VERTICALFLIP) && mobj->z + mobj->height >= mobj->ceilingz) - || (mobj->eflags & MFE_VERTICALFLIP && mobj->z <= mobj->floorz) - || (P_CheckDeathPitCollide(mobj)) - || --mobj->fuse <= 0) // Bubbles eventually dissipate if they can't reach the surface. - { - // no playing sound: no point; the object is being removed - P_RemoveMobj(mobj); - return; - } - break; - case MT_DROWNNUMBERS: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - if (!mobj->target->player || !(mobj->target->player->powers[pw_underwater] || mobj->target->player->powers[pw_spacetime])) - { - P_RemoveMobj(mobj); - return; - } - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - - mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); - - if (mobj->target->eflags & MFE_VERTICALFLIP) - { - mobj->z = mobj->target->z - FixedMul(16*FRACUNIT, mobj->target->scale) - mobj->height; - } - else - mobj->z = mobj->target->z + (mobj->target->height) + FixedMul(8*FRACUNIT, mobj->target->scale); // Adjust height for height changes - - if (mobj->threshold <= 35) - mobj->drawflags |= MFD_DONTDRAW; - else - mobj->drawflags &= ~MFD_DONTDRAW; - - if (mobj->threshold <= 30) - mobj->threshold = 40; - mobj->threshold--; - break; - case MT_FLAMEJET: - if ((mobj->flags2 & MF2_FIRING) && (leveltime & 3) == 0) - { - mobj_t *flame; - fixed_t strength; - - // Wave the flames back and forth. Reactiontime determines which direction it's going. - if (mobj->fuse <= -16) - mobj->reactiontime = 1; - else if (mobj->fuse >= 16) - mobj->reactiontime = 0; - - if (mobj->reactiontime) - mobj->fuse += 2; - else - mobj->fuse -= 2; - - flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - - flame->angle = mobj->angle; - - if (mobj->flags2 & MF2_AMBUSH) // Wave up and down instead of side-to-side - flame->momz = mobj->fuse << (FRACBITS-2); - else - flame->angle += FixedAngle(mobj->fuse*FRACUNIT); - - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; - - P_InstaThrust(flame, flame->angle, strength); - S_StartSound(flame, sfx_fire); - } - break; - case MT_VERTICALFLAMEJET: - if ((mobj->flags2 & MF2_FIRING) && (leveltime & 3) == 0) - { - mobj_t *flame; - fixed_t strength; - - // Wave the flames back and forth. Reactiontime determines which direction it's going. - if (mobj->fuse <= -16) - mobj->reactiontime = 1; - else if (mobj->fuse >= 16) - mobj->reactiontime = 0; - - if (mobj->reactiontime) - mobj->fuse++; - else - mobj->fuse--; - - flame = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_FLAMEJETFLAME); - - strength = 20*FRACUNIT; - strength -= ((20*FRACUNIT)/16)*mobj->movedir; - - // If deaf'd, the object spawns on the ceiling. - if (mobj->flags2 & MF2_AMBUSH) - { - mobj->z = mobj->ceilingz-mobj->height; - flame->momz = -strength; - } - else - flame->momz = strength; - P_InstaThrust(flame, mobj->angle, FixedDiv(mobj->fuse*FRACUNIT,3*FRACUNIT)); - S_StartSound(flame, sfx_fire); - } - break; - case MT_SEED: - mobj->momz = mobj->info->speed; - break; - case MT_ROCKCRUMBLE1: - case MT_ROCKCRUMBLE2: - case MT_ROCKCRUMBLE3: - case MT_ROCKCRUMBLE4: - case MT_ROCKCRUMBLE5: - case MT_ROCKCRUMBLE6: - case MT_ROCKCRUMBLE7: - case MT_ROCKCRUMBLE8: - case MT_ROCKCRUMBLE9: - case MT_ROCKCRUMBLE10: - case MT_ROCKCRUMBLE11: - case MT_ROCKCRUMBLE12: - case MT_ROCKCRUMBLE13: - case MT_ROCKCRUMBLE14: - case MT_ROCKCRUMBLE15: - case MT_ROCKCRUMBLE16: - if (mobj->z <= P_FloorzAtPos(mobj->x, mobj->y, mobj->z, mobj->height) - && mobj->state != &states[mobj->info->deathstate]) - { - P_SetMobjState(mobj, mobj->info->deathstate); - return; - } - break; - case MT_FIREDITEM: - if (mobj->target && !P_MobjWasRemoved(mobj->target)) - { - fixed_t x, y, z; - if (mobj->movecount) - { - x = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle + mobj->movedir, mobj->target->radius + mobj->radius); - y = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle + mobj->movedir, mobj->target->radius + mobj->radius); - z = mobj->target->z + mobj->target->height/3; - } - else - { - x = mobj->target->x; - y = mobj->target->y; - z = mobj->target->z + (80*mapobjectscale); - } - if (mobj->target->eflags & MFE_VERTICALFLIP) - z += mobj->target->height - FixedMul(mobj->target->scale, mobj->height); - - P_TeleportMove(mobj, x, y, z); - } - break; - default: - if (mobj->fuse) - { // Scenery object fuse! Very basic! - mobj->fuse--; - if (!mobj->fuse) - { -#ifdef HAVE_BLUA - if (!LUAh_MobjFuse(mobj)) -#endif - P_RemoveMobj(mobj); - return; - } - } - break; - } - - P_SceneryThinker(mobj); + P_MobjSceneryThink(mobj); return; } -#ifdef HAVE_BLUA // Check for a Lua thinker first if (!mobj->player) { @@ -7161,7 +8469,31 @@ void P_MobjThinker(mobj_t *mobj) if (P_MobjWasRemoved(mobj)) return; } -#endif + + // if it's pushable, or if it would be pushable other than temporary disablement, use the + // separate thinker + if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse)) + { + if (!P_MobjPushableThink(mobj)) + return; + } + else if (mobj->flags & MF_BOSS) + { + if (!P_MobjBossThink(mobj)) + return; + } + else if (mobj->health <= 0) // Dead things think differently than the living. + { + if (!P_MobjDeadThink(mobj)) + return; + } + else + { + if (!P_MobjRegularThink(mobj)) + return; + } + if (P_MobjWasRemoved(mobj)) + return; // Destroy items sector special if (mobj->type == MT_BANANA || mobj->type == MT_EGGMANITEM @@ -7176,7 +8508,7 @@ void P_MobjThinker(mobj_t *mobj) || mobj->type == MT_BALLHOG) { S_StartSound(mobj, mobj->info->deathsound); - P_KillMobj(mobj, NULL, NULL); + P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); } else { @@ -7187,7 +8519,7 @@ void P_MobjThinker(mobj_t *mobj) mobj->z += mobj->height; S_StartSound(mobj, mobj->info->deathsound); - P_KillMobj(mobj, NULL, NULL); + P_KillMobj(mobj, NULL, NULL, DMG_NORMAL); P_SetObjectMomZ(mobj, 8*FRACUNIT, false); P_InstaThrust(mobj, R_PointToAngle2(0, 0, mobj->momx, mobj->momy) + ANGLE_90, 16*FRACUNIT); @@ -7197,2959 +8529,8 @@ void P_MobjThinker(mobj_t *mobj) } } - // if it's pushable, or if it would be pushable other than temporary disablement, use the - // separate thinker - if (mobj->flags & MF_PUSHABLE || (mobj->info->flags & MF_PUSHABLE && mobj->fuse)) - { - P_MobjCheckWater(mobj); - P_PushableThinker(mobj); - - // Extinguish fire objects in water. (Yes, it's extraordinarily rare to have a pushable flame object, but Brak uses such a case.) - if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL - && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - { - P_KillMobj(mobj, NULL, NULL); - return; - } - } - else if (mobj->flags & MF_BOSS) - { -#ifdef HAVE_BLUA - if (LUAh_BossThinker(mobj)) - { - if (P_MobjWasRemoved(mobj)) - return; - } - else if (P_MobjWasRemoved(mobj)) - return; - else -#endif - switch (mobj->type) - { - case MT_EGGMOBILE: - if (mobj->health < mobj->info->damage+1 && leveltime & 1 && mobj->health > 0) - P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMOKE); - if (mobj->flags2 & MF2_SKULLFLY) -#if 1 - P_SpawnGhostMobj(mobj); -#else - { - mobj_t *spawnmobj; - spawnmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->info->painchance); - P_SetTarget(&spawnmobj->target, mobj); - spawnmobj->color = SKINCOLOR_GREY; - } -#endif - P_Boss1Thinker(mobj); - break; - case MT_EGGMOBILE2: - P_Boss2Thinker(mobj); - break; - case MT_EGGMOBILE3: - P_Boss3Thinker(mobj); - break; - case MT_EGGMOBILE4: - P_Boss4Thinker(mobj); - break; - case MT_BLACKEGGMAN: - P_Boss7Thinker(mobj); - break; - case MT_METALSONIC_BATTLE: - P_Boss9Thinker(mobj); - break; - default: // Generic SOC-made boss - if (mobj->flags2 & MF2_SKULLFLY) - P_SpawnGhostMobj(mobj); - P_GenericBossThinker(mobj); - break; - } - if (mobj->flags2 & MF2_BOSSFLEE) - P_InstaThrust(mobj, mobj->angle, FixedMul(12*FRACUNIT, mobj->scale)); - } - else if (mobj->health <= 0) // Dead things think differently than the living. - switch (mobj->type) - { - case MT_BLUEBALL: - if ((mobj->tics>>2)+1 > 0 && (mobj->tics>>2)+1 <= tr_trans60) // tr_trans50 through tr_trans90, shifting once every second frame - mobj->frame = (NUMTRANSMAPS-((mobj->tics>>2)+1))<frame = tr_trans60<z <= mobj->floorz) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_EGGTRAP: // Egg Capsule animal release - if (mobj->fuse > 0 && mobj->fuse < 2*TICRATE-(TICRATE/7) - && (mobj->fuse & 3)) - { - INT32 i,j; - fixed_t x,y,z; - fixed_t ns; - mobj_t *mo2; - - i = P_RandomByte(); - z = mobj->subsector->sector->floorheight + ((P_RandomByte()&63)*FRACUNIT); - for (j = 0; j < 2; j++) - { - const angle_t fa = (P_RandomByte()*FINEANGLES/16) & FINEMASK; - ns = 64 * FRACUNIT; - x = mobj->x + FixedMul(FINESINE(fa),ns); - y = mobj->y + FixedMul(FINECOSINE(fa),ns); - - mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); - ns = 4 * FRACUNIT; - mo2->momx = FixedMul(FINESINE(fa),ns); - mo2->momy = FixedMul(FINECOSINE(fa),ns); - - i = P_RandomByte(); - - if (i % 5 == 0) - P_SpawnMobj(x, y, z, MT_CHICKEN); - else if (i % 4 == 0) - P_SpawnMobj(x, y, z, MT_COW); - else if (i % 3 == 0) - { - P_SpawnMobj(x, y, z, MT_BIRD); - S_StartSound(mo2, mobj->info->deathsound); - } - else if ((i & 1) == 0) - P_SpawnMobj(x, y, z, MT_BUNNY); - else - P_SpawnMobj(x, y, z, MT_MOUSE); - } - - mobj->fuse--; - } - break; - case MT_PLAYER: - /// \todo Have the player's dead body completely finish its animation even if they've already respawned. - // This feels like it has some serious potential for breakage. Is there anything else we can base this off of instead of a drawing flag? - if (!(mobj->drawflags & MFD_DONTDRAW)) - { - if (!mobj->fuse) - { // Go away. - /// \todo Actually go ahead and remove mobj completely, and fix any bugs and crashes doing this creates. Chasecam should stop moving, and F12 should never return to it. - mobj->momz = 0; - if (mobj->player) - mobj->drawflags |= MFD_DONTDRAW; - else // safe to remove, nobody's going to complain! - { - P_RemoveMobj(mobj); - return; - } - } - else // Apply gravity to fall downwards. - { - P_SetObjectMomZ(mobj, -2*FRACUNIT/3, true); - if (mobj->player) - mobj->player->frameangle -= ANGLE_22h; - } - } - break; - //{ SRB2kart Items - Death States - case MT_ORBINAUT: - case MT_BANANA: - case MT_EGGMANITEM: - case MT_SPB: - if (P_IsObjectOnGround(mobj)) - { - P_RemoveMobj(mobj); - return; - } - // fallthru - case MT_ORBINAUT_SHIELD: - case MT_BANANA_SHIELD: - case MT_EGGMANITEM_SHIELD: - mobj->drawflags ^= MFD_DONTDRAW; - break; - case MT_JAWZ: - case MT_JAWZ_DUD: - if (P_IsObjectOnGround(mobj)) - P_SetMobjState(mobj, mobj->info->xdeathstate); - // fallthru - case MT_JAWZ_SHIELD: - mobj->drawflags ^= MFD_DONTDRAW; - break; - case MT_SSMINE: - case MT_SPBEXPLOSION: - if (mobj->extravalue2 != -100) - { - P_SetMobjState(mobj, mobj->info->deathstate); - mobj->extravalue2 = -100; - } - else - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_MINEEXPLOSIONSOUND: - P_RemoveMobj(mobj); - return; - case MT_CDUFO: - if (mobj->fuse > TICRATE) - mobj->drawflags ^= MFD_DONTDRAW; // only by good fortune does this end with it having MFD_DONTDRAW... don't touch! - break; - case MT_SMK_PIPE: - if (mobj->flags2 & MF2_AMBUSH) - P_SetMobjStateNF(mobj, mobj->info->seestate); - else - P_SetMobjStateNF(mobj, mobj->info->spawnstate); - /* FALLTHRU */ - case MT_SMK_MOLE: - mobj->drawflags ^= MFD_DONTDRAW; - if (P_IsObjectOnGround(mobj)) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_SMK_THWOMP: - if (mobj->flags2 & MF2_AMBUSH) - { - mobj->colorized = true; - mobj->color = (1 + (leveltime % (MAXSKINCOLORS-1))); - mobj->frame |= FF_FULLBRIGHT; - } - else - { - mobj->colorized = false; - mobj->color = SKINCOLOR_NONE; - mobj->frame &= (~FF_FULLBRIGHT); - } - - mobj->drawflags ^= MFD_DONTDRAW; - if (P_IsObjectOnGround(mobj)) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_BATTLECAPSULE: - if (!(mobj->fuse & 1)) - { - const SINT8 amt = 96; - mobj_t *dust; - UINT8 i; - - for (i = 0; i < 2; i++) - { - fixed_t xoffset = P_RandomRange(-amt, amt) * mobj->scale; - fixed_t yoffset = P_RandomRange(-amt, amt) * mobj->scale; - fixed_t zoffset = P_RandomRange(-(amt >> 1), (amt >> 1)) * mobj->scale; - - dust = P_SpawnMobj(mobj->x + xoffset, mobj->y + yoffset, - mobj->z + (mobj->height >> 1) + zoffset, MT_EXPLODE); - } - - if (dust && !P_MobjWasRemoved(dust)) // Only do for 1 explosion - S_StartSound(dust, sfx_s3k3d); - } - break; - //} - default: - break; - } - else switch (mobj->type) - { - case MT_FALLINGROCK: - // Despawn rocks here in case zmovement code can't do so (blame slopes) - if (!mobj->fuse && !mobj->momx && !mobj->momy && !mobj->momz - && ((mobj->eflags & MFE_VERTICALFLIP) ? - mobj->z + mobj->height >= mobj->ceilingz - : mobj->z <= mobj->floorz)) - { - //P_RemoveMobj(mobj); - //return; - mobj->fuse = TICRATE; - } - P_MobjCheckWater(mobj); - break; - case MT_EMERALDSPAWN: - if (mobj->threshold) - { - mobj->threshold--; - - if (!mobj->threshold && !mobj->target && mobj->reactiontime) - { - mobj_t *emerald = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->reactiontime); - emerald->threshold = 42; - P_SetTarget(&mobj->target, emerald); - P_SetTarget(&emerald->target, mobj); - } - } - break; - case MT_AQUABUZZ: - case MT_BIGAIRMINE: - { - if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 - && P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius * 16) - { - // Home in on the target. - P_HomingAttack(mobj, mobj->tracer); - - if (mobj->z < mobj->floorz) - mobj->z = mobj->floorz; - - if (leveltime % mobj->info->painchance == 0) - S_StartSound(mobj, mobj->info->activesound); - } - else - { - // Try to find a player - P_LookForPlayers(mobj, true, true, mobj->radius * 16); - mobj->momx >>= 1; - mobj->momy >>= 1; - mobj->momz >>= 1; - } - } - break; - case MT_BIGMINE: - { - if (mobj->tracer && mobj->tracer->player && mobj->tracer->health > 0 - && P_AproxDistance(P_AproxDistance(mobj->tracer->x - mobj->x, mobj->tracer->y - mobj->y), mobj->tracer->z - mobj->z) <= mobj->radius * 16) - { - P_MobjCheckWater(mobj); - - // Home in on the target. - P_HomingAttack(mobj, mobj->tracer); - - // Don't let it go out of water - if (mobj->z + mobj->height > mobj->watertop) - mobj->z = mobj->watertop - mobj->height; - - if (mobj->z < mobj->floorz) - mobj->z = mobj->floorz; - - if (leveltime % mobj->info->painchance == 0) - S_StartSound(mobj, mobj->info->activesound); - } - else - { - // Try to find a player - P_LookForPlayers(mobj, true, true, mobj->radius * 16); - mobj->momx >>= 1; - mobj->momy >>= 1; - mobj->momz >>= 1; - } - } - break; - case MT_SPINMACEPOINT: - if (leveltime & 1) - { - if (mobj->lastlook > mobj->movecount) - mobj->lastlook--; -/* - if (mobj->threshold > mobj->movefactor) - mobj->threshold -= FRACUNIT; - else if (mobj->threshold < mobj->movefactor) - mobj->threshold += FRACUNIT;*/ - } - break; - case MT_EGGCAPSULE: - if (!mobj->reactiontime) - { - // Target nearest player on your mare. - // (You can make it float up/down by adding MF_FLOAT, - // but beware level design pitfalls.) - fixed_t shortest = 1024*FRACUNIT; - INT32 i; - P_SetTarget(&mobj->target, NULL); - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo - && players[i].mare == mobj->threshold && players[i].health > 1) - { - fixed_t dist = P_AproxDistance(players[i].mo->x - mobj->x, players[i].mo->y - mobj->y); - if (dist < shortest) - { - P_SetTarget(&mobj->target, players[i].mo); - shortest = dist; - } - } - } - break; - case MT_EGGMOBILE2_POGO: - if (!mobj->target - || !mobj->target->health - || mobj->target->state == &states[mobj->target->info->spawnstate] - || mobj->target->state == &states[mobj->target->info->raisestate]) - { - P_RemoveMobj(mobj); - return; - } - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z - mobj->height); - break; - case MT_HAMMER: - if (mobj->z <= mobj->floorz) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_KOOPA: - P_KoopaThinker(mobj); - break; - case MT_REDRING: - if (((mobj->z < mobj->floorz) || (mobj->z + mobj->height > mobj->ceilingz)) - && mobj->flags & MF_MISSILE) - { - P_ExplodeMissile(mobj); - return; - } - break; - case MT_BOSSFLYPOINT: - return; - case MT_NIGHTSCORE: - mobj->color = (UINT8)(leveltime % SKINCOLOR_WHITE); - break; - case MT_JETFUME1: - { - fixed_t jetx, jety; - - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-64*FRACUNIT, mobj->target->scale)); - - if (mobj->fuse == 56) // First one - { - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(38*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(38*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 57) - { - P_UnsetThingPosition(mobj); - mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle-ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle-ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 58) - { - P_UnsetThingPosition(mobj); - mobj->x = jetx + P_ReturnThrustX(mobj->target, mobj->target->angle+ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - mobj->y = jety + P_ReturnThrustY(mobj->target, mobj->target->angle+ANGLE_90, FixedMul(24*FRACUNIT, mobj->target->scale)); - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height - mobj->height - FixedMul(12*FRACUNIT, mobj->target->scale); - else - mobj->z = mobj->target->z + FixedMul(12*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - else if (mobj->fuse == 59) - { - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, -mobj->target->radius); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, -mobj->target->radius); - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - if (mobj->target->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->target->z + mobj->target->height/2 + mobj->height/2; - else - mobj->z = mobj->target->z + mobj->target->height/2 - mobj->height/2; - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - mobj->fuse++; - } - break; - case MT_PROPELLER: - { - fixed_t jetx, jety; - - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - jetx = mobj->target->x + P_ReturnThrustX(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale)); - jety = mobj->target->y + P_ReturnThrustY(mobj->target, mobj->target->angle, FixedMul(-60*FRACUNIT, mobj->target->scale)); - - P_UnsetThingPosition(mobj); - mobj->x = jetx; - mobj->y = jety; - mobj->z = mobj->target->z + FixedMul(17*FRACUNIT, mobj->target->scale); - mobj->angle = mobj->target->angle - ANGLE_180; - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - break; - case MT_JETFLAME: - { - if (!mobj->target // if you have no target - || (!(mobj->target->flags & MF_BOSS) && mobj->target->health <= 0)) // or your target isn't a boss and it's popped now - { // then remove yourself as well! - P_RemoveMobj(mobj); - return; - } - - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - mobj->z = mobj->target->z - FixedMul(50*FRACUNIT, mobj->target->scale); - mobj->floorz = mobj->z; - mobj->ceilingz = mobj->z+mobj->height; - P_SetThingPosition(mobj); - } - break; - case MT_NIGHTSDRONE: - if (mobj->state >= &states[S_NIGHTSDRONE_SPARKLING1] && mobj->state <= &states[S_NIGHTSDRONE_SPARKLING16]) - { - mobj->drawflags &= ~MFD_DONTDRAW; - mobj->z = mobj->floorz + mobj->height + (mobj->spawnpoint->options >> ZSHIFT) * FRACUNIT; - mobj->angle = 0; - - if (!mobj->target) - { - mobj_t *goalpost = P_SpawnMobj(mobj->x, mobj->y, mobj->z + FRACUNIT, MT_NIGHTSGOAL); - CONS_Debug(DBG_NIGHTSBASIC, "Adding goal post\n"); - goalpost->angle = mobj->angle; - P_SetTarget(&mobj->target, goalpost); - } - - if (G_IsSpecialStage(gamemap)) - { // Never show the NiGHTS drone in special stages. Check ANYONE for bonustime. - INT32 i; - boolean bonustime = false; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].bonustime) - { - bonustime = true; - break; - } - if (!bonustime) - { - mobj->flags &= ~MF_NOGRAVITY; - P_SetMobjState(mobj, S_NIGHTSDRONE1); - mobj->drawflags |= MFD_DONTDRAW; - } - } - else if (mobj->tracer && mobj->tracer->player) - { - if (!(mobj->tracer->player->pflags & PF_NIGHTSMODE)) - { - mobj->flags &= ~MF_NOGRAVITY; - mobj->drawflags &= ~MFD_DONTDRAW; - P_SetMobjState(mobj, S_NIGHTSDRONE1); - } - else if (!mobj->tracer->player->bonustime) - { - mobj->flags &= ~MF_NOGRAVITY; - P_SetMobjState(mobj, S_NIGHTSDRONE1); - } - } - } - else - { - if (G_IsSpecialStage(gamemap)) - { // Never show the NiGHTS drone in special stages. Check ANYONE for bonustime. - INT32 i; - - boolean bonustime = false; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].bonustime) - { - bonustime = true; - break; - } - - if (bonustime) - { - P_SetMobjState(mobj, S_NIGHTSDRONE_SPARKLING1); - mobj->flags |= MF_NOGRAVITY; - } - else - { - if (mobj->target) - { - CONS_Debug(DBG_NIGHTSBASIC, "Removing goal post\n"); - P_RemoveMobj(mobj->target); - P_SetTarget(&mobj->target, NULL); - } - mobj->drawflags |= MFD_DONTDRAW; - } - } - else if (mobj->tracer && mobj->tracer->player) - { - if (mobj->target) - { - CONS_Debug(DBG_NIGHTSBASIC, "Removing goal post\n"); - P_RemoveMobj(mobj->target); - P_SetTarget(&mobj->target, NULL); - } - - if (mobj->tracer->player->pflags & PF_NIGHTSMODE) - { - if (mobj->tracer->player->bonustime) - { - P_SetMobjState(mobj, S_NIGHTSDRONE_SPARKLING1); - mobj->flags |= MF_NOGRAVITY; - } - else - mobj->drawflags |= MFD_DONTDRAW; - } - else // Not NiGHTS - mobj->drawflags &= ~MFD_DONTDRAW; - } - mobj->angle += ANG10; - if (mobj->z <= mobj->floorz) - mobj->momz = 5*FRACUNIT; - } - break; - case MT_PLAYER: - if (mobj->player) - P_PlayerMobjThinker(mobj); - return; - case MT_SKIM: - // check mobj against possible water content, before movement code - P_MobjCheckWater(mobj); - - // Keep Skim at water surface - if (mobj->z <= mobj->watertop) - { - mobj->flags |= MF_NOGRAVITY; - if (mobj->z < mobj->watertop) - { - if (mobj->watertop - mobj->z <= FixedMul(mobj->info->speed*FRACUNIT, mobj->scale)) - mobj->z = mobj->watertop; - else - mobj->momz = FixedMul(mobj->info->speed*FRACUNIT, mobj->scale); - } - } - else - { - mobj->flags &= ~MF_NOGRAVITY; - if (mobj->z > mobj->watertop && mobj->z - mobj->watertop < FixedMul(MAXSTEPMOVE, mapobjectscale)) - mobj->z = mobj->watertop; - } - break; - case MT_RING: - case MT_COIN: - case MT_BLUEBALL: - case MT_REDTEAMRING: - case MT_BLUETEAMRING: - // No need to check water. Who cares? - P_RingThinker(mobj); - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - else - A_AttractChase(mobj); - return; - // Flung items - case MT_FLINGRING: - case MT_FLINGCOIN: - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - else - A_AttractChase(mobj); - break; - case MT_NIGHTSWING: - if (mobj->flags2 & MF2_NIGHTSPULL) - P_NightsItemChase(mobj); - break; - case MT_SMALLMACE: - case MT_BIGMACE: - { - mobj_t *ghostmo = P_SpawnGhostMobj(mobj); - ghostmo->fuse = 4; - } - break; - case MT_SHELL: - if (mobj->threshold > TICRATE) - mobj->threshold--; - - if (mobj->state != &states[S_SHELL]) - { - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_InstaThrust(mobj, mobj->angle, FixedMul(mobj->info->speed, mobj->scale)); - } - break; - //{ SRB2kart Items - case MT_FLOATINGITEM: - { - if (mobj->flags & MF_NOCLIPTHING) - { - if (P_CheckDeathPitCollide(mobj)) - { - P_RemoveMobj(mobj); - return; - } - else if (P_IsObjectOnGround(mobj)) - { - mobj->momx = 1; - mobj->momy = 0; - mobj->flags &= ~MF_NOCLIPTHING; - mobj->flags |= MF_NOGRAVITY; - } - } - else - { - mobj->angle += 2*ANG2; - if (mobj->flags2 & MF2_NIGHTSPULL) - { - if (!mobj->tracer || !mobj->tracer->health - || mobj->scale <= mapobjectscale>>4) - { - P_RemoveMobj(mobj); - return; - } - P_Attract(mobj, mobj->tracer, true); - } - else - { - fixed_t adj = FixedMul(FRACUNIT - FINECOSINE((mobj->movedir>>ANGLETOFINESHIFT) & FINEMASK), (mapobjectscale<<3)); - mobj->movedir += 2*ANG2; - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->ceilingz - mobj->height - adj; - else - mobj->z = mobj->floorz + adj; - } - } - - switch (mobj->threshold) - { - case KITEM_ORBINAUT: - mobj->sprite = SPR_ITMO; - mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(min(mobj->movecount-1, 3)); - break; - case KITEM_INVINCIBILITY: - mobj->sprite = SPR_ITMI; - mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|((leveltime % (7*3)) / 3); - break; - case KITEM_SAD: - mobj->sprite = SPR_ITEM; - mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE; - break; - case KITEM_SPB: - case KITEM_SHRINK: - indirectitemcooldown = 20*TICRATE; - /* FALLTHRU */ - default: - mobj->sprite = SPR_ITEM; - mobj->frame = FF_FULLBRIGHT|FF_PAPERSPRITE|(mobj->threshold); - break; - } - break; - } - case MT_ORBINAUT: - { - boolean grounded = P_IsObjectOnGround(mobj); - - if (mobj->flags2 & MF2_AMBUSH) - { - if (grounded && (mobj->flags & MF_NOCLIPTHING)) - { - mobj->momx = 1; - mobj->momy = 0; - mobj->frame = 3; - S_StartSound(mobj, mobj->info->activesound); - mobj->flags &= ~MF_NOCLIPTHING; - } - else if (mobj->movecount) - mobj->movecount--; - else if (mobj->frame < 3) - { - mobj->movecount = 2; - mobj->frame++; - } - } - else - { - fixed_t finalspeed = mobj->movefactor; - const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); - fixed_t thrustamount = 0; - fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; - mobj_t *ghost = P_SpawnGhostMobj(mobj); - ghost->colorized = true; // already has color! - - if (!grounded) - { - // No friction in the air - frictionsafety = FRACUNIT; - } - - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - if (mobj->health <= 5) - { - INT32 i; - for (i = 5; i >= mobj->health; i--) - finalspeed = FixedMul(finalspeed, FRACUNIT-FRACUNIT/4); - } - - if (currentspeed >= finalspeed) - { - // Thrust as if you were at top speed, slow down naturally - thrustamount = FixedDiv(finalspeed, frictionsafety) - finalspeed; - } - else - { - const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; - // Thrust to immediately get to top speed - thrustamount = beatfriction + FixedDiv(finalspeed - currentspeed, frictionsafety); - } - - P_Thrust(mobj, mobj->angle, thrustamount); - - if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) - K_DoPogoSpring(mobj, 32<threshold > 0) - mobj->threshold--; - - if (leveltime % 6 == 0) - S_StartSound(mobj, mobj->info->activesound); - } - break; - } - case MT_JAWZ: - { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - ghost->color = mobj->target->player->skincolor; - ghost->colorized = true; - } - - if (mobj->threshold > 0) - mobj->threshold--; - if (leveltime % TICRATE == 0) - S_StartSound(mobj, mobj->info->activesound); - - // Movement handling has ALL been moved to A_JawzChase - - K_DriftDustHandling(mobj); - - if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) - K_DoPogoSpring(mobj, 32<flags2 & MF2_AMBUSH) - { - if (grounded && (mobj->flags & MF_NOCLIPTHING)) - { - mobj->momx = 1; - mobj->momy = 0; - S_StartSound(mobj, mobj->info->deathsound); - mobj->flags &= ~MF_NOCLIPTHING; - } - } - else - { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - const fixed_t currentspeed = R_PointToDist2(0, 0, mobj->momx, mobj->momy); - fixed_t frictionsafety = (mobj->friction == 0) ? 1 : mobj->friction; - fixed_t thrustamount = 0; - - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - ghost->color = mobj->target->player->skincolor; - ghost->colorized = true; - } - - if (!grounded) - { - // No friction in the air - frictionsafety = FRACUNIT; - } - - if (currentspeed >= mobj->movefactor) - { - // Thrust as if you were at top speed, slow down naturally - thrustamount = FixedDiv(mobj->movefactor, frictionsafety) - mobj->movefactor; - } - else - { - const fixed_t beatfriction = FixedDiv(currentspeed, frictionsafety) - currentspeed; - // Thrust to immediately get to top speed - thrustamount = beatfriction + FixedDiv(mobj->movefactor - currentspeed, frictionsafety); - } - - mobj->angle = R_PointToAngle2(0, 0, mobj->momx, mobj->momy); - P_Thrust(mobj, mobj->angle, thrustamount); - - if (P_MobjTouchingSectorSpecial(mobj, 3, 1, true)) - K_DoPogoSpring(mobj, 32<threshold > 0) - mobj->threshold--; - - if (leveltime % TICRATE == 0) - S_StartSound(mobj, mobj->info->activesound); - } - - break; - } - case MT_EGGMANITEM: - { - player_t *player = K_GetItemBoxPlayer(mobj); - UINT8 color = SKINCOLOR_BLACK; - - if (player != NULL) - { - color = player->skincolor; - } - - mobj->color = color; - mobj->colorized = false; - } - /* FALLTHRU */ - case MT_BANANA: - mobj->friction = ORIG_FRICTION/4; - - if (mobj->momx || mobj->momy) - { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - ghost->color = mobj->target->player->skincolor; - ghost->colorized = true; - } - } - - if (P_IsObjectOnGround(mobj) && mobj->health > 1) - { - S_StartSound(mobj, mobj->info->activesound); - mobj->momx = mobj->momy = 0; - mobj->health = 1; - } - - if (mobj->threshold > 0) - mobj->threshold--; - break; - case MT_SPB: - indirectitemcooldown = 20*TICRATE; - /* FALLTHRU */ - case MT_BALLHOG: - { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - ghost->fuse = 3; - - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - ghost->color = mobj->target->player->skincolor; - ghost->colorized = true; - } - - if (mobj->threshold > 0) - mobj->threshold--; - } - break; - case MT_SINK: - if (mobj->momx || mobj->momy) - { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - ghost->color = mobj->target->player->skincolor; - ghost->colorized = true; - } - } - - if (P_IsObjectOnGround(mobj)) - { - S_StartSound(mobj, mobj->info->deathsound); - P_SetMobjState(mobj, S_NULL); - } - - if (mobj->threshold > 0) - mobj->threshold--; - break; - case MT_SSMINE: - if (mobj->target && mobj->target->player) - mobj->color = mobj->target->player->skincolor; - else - mobj->color = SKINCOLOR_KETCHUP; - - if (mobj->momx || mobj->momy) - { - mobj_t *ghost = P_SpawnGhostMobj(mobj); - ghost->colorized = true; // already has color! - } - - if (P_IsObjectOnGround(mobj) && (mobj->state == &states[S_SSMINE_AIR1] || mobj->state == &states[S_SSMINE_AIR2])) - { - if (mobj->extravalue1 > 0) - mobj->extravalue1--; - else - { - mobj->momx = mobj->momy = 0; - S_StartSound(mobj, mobj->info->activesound); - P_SetMobjState(mobj, S_SSMINE_DEPLOY1); - } - } - - if ((mobj->state >= &states[S_SSMINE1] && mobj->state <= &states[S_SSMINE4]) - || (mobj->state >= &states[S_SSMINE_DEPLOY8] && mobj->state <= &states[S_SSMINE_DEPLOY13])) - A_GrenadeRing(mobj); - - if (mobj->threshold > 0) - mobj->threshold--; - break; - case MT_SPBEXPLOSION: - mobj->health--; - break; - case MT_MINEEXPLOSION: - if ((mobj->z < mobj->floorz - mobj->height) || (mobj->z > mobj->ceilingz + mobj->height)) - { - P_KillMobj(mobj, NULL, NULL); - break; - } - - if (mobj->tics != -1) - { - mobj->tics--; - - // you can cycle through multiple states in a tic - if (!mobj->tics) - if (!P_SetMobjState(mobj, mobj->state->nextstate)) - return; // freed itself - } - - P_UnsetThingPosition(mobj); - mobj->x += mobj->momx; - mobj->y += mobj->momy; - mobj->z += mobj->momz; - P_SetThingPosition(mobj); - return; - case MT_MINEEXPLOSIONSOUND: - if (mobj->health == 100) - S_StartSound(mobj, sfx_s3k4e); - mobj->health--; - break; - case MT_DRIFTEXPLODE: - if (!mobj->target || !mobj->target->health) - { - P_RemoveMobj(mobj); - return; - } - - //mobj->angle = mobj->target->angle; - { - angle_t angle = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy); - fixed_t nudge; - - mobj->angle = angle; - - if (( mobj->fuse & 1 )) - { - nudge = 4*mobj->target->radius; - } - else - { - nudge = 2*mobj->target->radius; - /* rotate the papersprite frames to see the flat angle */ - mobj->angle += ANGLE_90; - } - - P_TeleportMove(mobj, - mobj->target->x + P_ReturnThrustX(mobj, angle + ANGLE_180, nudge), - mobj->target->y + P_ReturnThrustY(mobj, angle + ANGLE_180, nudge), - mobj->target->z); - } - P_SetScale(mobj, mobj->target->scale); -#ifdef HWRENDER - mobj->modeltilt = mobj->target->modeltilt; -#endif - - if (mobj->fuse <= 16) - { - mobj->color = SKINCOLOR_KETCHUP; - /* don't draw papersprite frames after blue boost */ - mobj->drawflags ^= MFD_DONTDRAW; - } - else if (mobj->fuse <= 32) - mobj->color = SKINCOLOR_SAPPHIRE; - else if (mobj->fuse > 32) - mobj->color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); - - switch (mobj->extravalue1) - { - case 3:/* rainbow boost */ - /* every 20 tics, bang! */ - if (( 120 - mobj->fuse ) % 10 == 0) - { - K_SpawnDriftBoostClip(mobj->target->player); - S_StartSound(mobj->target, sfx_s3k77); - } - break; - - case 2:/* blue boost */ - if (mobj->fuse == 16)/* to red*/ - K_SpawnDriftBoostClip(mobj->target->player); - break; - } - - { - player_t *p = NULL; - if (mobj->target->target && mobj->target->target->player) - p = mobj->target->target->player; - else if (mobj->target->player) - p = mobj->target->player; - - if (p) - { - if (p->kartstuff[k_driftboost] > mobj->movecount) - { - ; // reset animation - } - - mobj->movecount = p->kartstuff[k_driftboost]; - } - } - break; - case MT_BOOSTFLAME: - if (!mobj->target || !mobj->target->health) - { - P_RemoveMobj(mobj); - return; - } - - mobj->angle = mobj->target->angle; - P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius), - mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z); - P_SetScale(mobj, mobj->target->scale); -#ifdef HWRENDER - mobj->modeltilt = mobj->target->modeltilt; -#endif - - { - player_t *p = NULL; - if (mobj->target->target && mobj->target->target->player) - p = mobj->target->target->player; - else if (mobj->target->player) - p = mobj->target->player; - - if (p) - { - if (p->kartstuff[k_sneakertimer] > mobj->movecount) - P_SetMobjState(mobj, S_BOOSTFLAME); - mobj->movecount = p->kartstuff[k_sneakertimer]; - } - } - - if (mobj->state == &states[S_BOOSTSMOKESPAWNER]) - { - mobj_t *smoke = P_SpawnMobj(mobj->x, mobj->y, mobj->z+(8<target->scale/2); - smoke->destscale = 3*mobj->target->scale/2; - smoke->scalespeed = mobj->target->scale/12; - - smoke->momx = mobj->target->momx/2; - smoke->momy = mobj->target->momy/2; - smoke->momz = mobj->target->momz/2; - - P_Thrust(smoke, mobj->angle+FixedAngle(P_RandomRange(135, 225)<target->scale); - } - break; - case MT_SPARKLETRAIL: - if (!mobj->target) - { - P_RemoveMobj(mobj); - return; - } - mobj->color = mobj->target->color; - mobj->colorized = mobj->target->colorized; - break; - case MT_INVULNFLASH: - if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_invincibilitytimer])) - { - P_RemoveMobj(mobj); - return; - } - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); - break; - case MT_BRAKEDRIFT: - if ((!mobj->target || !mobj->target->health || !mobj->target->player || !P_IsObjectOnGround(mobj->target)) - || !mobj->target->player->kartstuff[k_drift] || !mobj->target->player->kartstuff[k_brakedrift] - || !((mobj->target->player->cmd.buttons & BT_BRAKE) - || !(mobj->target->player->cmd.buttons & BT_ACCELERATE))) // Letting go of accel functions about the same as brake-drifting - { - P_RemoveMobj(mobj); - return; - } - else - { - UINT8 driftcolor = K_DriftSparkColor(mobj->target->player, mobj->target->player->kartstuff[k_driftcharge]); - fixed_t newx, newy; - angle_t travelangle; - - travelangle = mobj->target->angle - ((ANGLE_45/5)*mobj->target->player->kartstuff[k_drift]); - - newx = mobj->target->x + P_ReturnThrustX(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale); - newy = mobj->target->y + P_ReturnThrustY(mobj->target, travelangle+ANGLE_180, 24*mobj->target->scale); - P_TeleportMove(mobj, newx, newy, mobj->target->z); - - mobj->angle = travelangle - ((ANGLE_90/5)*mobj->target->player->kartstuff[k_drift]); - P_SetScale(mobj, (mobj->destscale = mobj->target->scale)); - - if (driftcolor != SKINCOLOR_NONE) - mobj->color = driftcolor; - else - mobj->color = SKINCOLOR_SILVER; - - if (!S_SoundPlaying(mobj, sfx_cdfm17)) - S_StartSound(mobj, sfx_cdfm17); - - K_MatchGenericExtraFlags(mobj, mobj->target); - if (leveltime & 1) - mobj->drawflags |= MFD_DONTDRAW; - } - break; - case MT_PLAYERRETICULE: - if (!mobj->target || !mobj->target->health) - { - P_RemoveMobj(mobj); - return; - } - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); - break; - case MT_INSTASHIELDB: - mobj->drawflags ^= MFD_DONTDRAW; - K_MatchGenericExtraFlags(mobj, mobj->target); - /* FALLTHRU */ - case MT_INSTASHIELDA: - if (!mobj->target || !mobj->target->health || (mobj->target->player && !mobj->target->player->kartstuff[k_instashield])) - { - P_RemoveMobj(mobj); - return; - } - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); - K_MatchGenericExtraFlags(mobj, mobj->target); - break; - case MT_BATTLEPOINT: - if (!mobj->target || P_MobjWasRemoved(mobj->target)) - { - P_RemoveMobj(mobj); - return; - } - - if (mobj->movefactor < 48*mobj->target->scale) - { - mobj->movefactor += (48*mobj->target->scale)/6; - if (mobj->movefactor > mobj->target->height) - mobj->movefactor = mobj->target->height; - } - else if (mobj->movefactor > 48*mobj->target->scale) - { - mobj->movefactor -= (48*mobj->target->scale)/6; - if (mobj->movefactor < mobj->target->height) - mobj->movefactor = mobj->target->height; - } - K_MatchGenericExtraFlags(mobj, mobj->target); - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z + (mobj->target->height/2) + mobj->movefactor); - break; - case MT_RINGSPARKS: - if (!mobj->target || P_MobjWasRemoved(mobj->target)) - { - P_RemoveMobj(mobj); - return; - } - - mobj->z = mobj->target->z; - - K_MatchGenericExtraFlags(mobj, mobj->target); - - P_TeleportMove(mobj, mobj->target->x + FINECOSINE(mobj->angle >> ANGLETOFINESHIFT), - mobj->target->y + FINESINE(mobj->angle >> ANGLETOFINESHIFT), - mobj->z + mobj->target->height * P_MobjFlip(mobj)); - break; - case MT_FLAMESHIELDPAPER: - if (!mobj->target || P_MobjWasRemoved(mobj->target)) - { - P_RemoveMobj(mobj); - return; - } - - mobj->z = mobj->target->z; - - K_MatchGenericExtraFlags(mobj, mobj->target); - - { - INT32 perpendicular = ((mobj->extravalue1 & 1) ? -ANGLE_90 : ANGLE_90); - fixed_t newx = mobj->target->x + P_ReturnThrustX(NULL, mobj->target->angle + perpendicular, 8*mobj->target->scale); - fixed_t newy = mobj->target->y + P_ReturnThrustY(NULL, mobj->target->angle + perpendicular, 8*mobj->target->scale); - - P_TeleportMove(mobj, newx, newy, mobj->target->z); - - if (mobj->extravalue1 & 1) - mobj->angle = mobj->target->angle - ANGLE_45; - else - mobj->angle = mobj->target->angle + ANGLE_45; - } - break; - case MT_TIREGREASE: - if (!mobj->target || P_MobjWasRemoved(mobj->target) || !mobj->target->player - || !mobj->target->player->kartstuff[k_tiregrease]) - { - P_RemoveMobj(mobj); - return; - } - - K_MatchGenericExtraFlags(mobj, mobj->target); - - { - const angle_t off = FixedAngle(40*FRACUNIT); - angle_t ang = mobj->target->angle; - fixed_t z; - UINT8 trans = (mobj->target->player->kartstuff[k_tiregrease] * (NUMTRANSMAPS+1)) / greasetics; - - if (trans > NUMTRANSMAPS) - trans = NUMTRANSMAPS; - - trans = NUMTRANSMAPS - trans; - - z = mobj->target->z; - if (mobj->eflags & MFE_VERTICALFLIP) - z += mobj->target->height; - - if (mobj->target->momx || mobj->target->momy) - ang = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy); - - if (mobj->extravalue1) - ang = (signed)(ang - off); - else - ang = (signed)(ang + off); - - P_TeleportMove(mobj, - mobj->target->x - FixedMul(mobj->target->radius, FINECOSINE(ang >> ANGLETOFINESHIFT)), - mobj->target->y - FixedMul(mobj->target->radius, FINESINE(ang >> ANGLETOFINESHIFT)), - z); - mobj->angle = ang; - - if (leveltime & 1) - mobj->drawflags |= MFD_DONTDRAW; - - if (trans >= NUMTRANSMAPS) - mobj->drawflags |= MFD_DONTDRAW; - else if (trans == 0) - mobj->drawflags = (mobj->drawflags & ~MFD_TRANSMASK); - else - mobj->drawflags = (mobj->drawflags & ~MFD_TRANSMASK)|(trans << MFD_TRANSSHIFT); - } - break; - case MT_THUNDERSHIELD: - { - fixed_t destx, desty; - if (!mobj->target || !mobj->target->health || !mobj->target->player - || mobj->target->player->kartstuff[k_curshield] != KSHIELD_THUNDER) - { - P_RemoveMobj(mobj); - return; - } - P_SetScale(mobj, (mobj->destscale = (5*mobj->target->scale)>>2)); - - if (!r_splitscreen /*&& rendermode != render_soft*/) - { - angle_t viewingangle; - statenum_t curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); - - if (players[displayplayers[0]].awayviewtics) - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y); - else if (!camera[0].chase && players[displayplayers[0]].mo) - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y); - else - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y); - - if (curstate > S_THUNDERSHIELD15 && curstate <= S_THUNDERSHIELD24) - viewingangle += ANGLE_180; - - destx = mobj->target->x + P_ReturnThrustX(mobj->target, viewingangle, mobj->scale>>4); - desty = mobj->target->y + P_ReturnThrustY(mobj->target, viewingangle, mobj->scale>>4); - } - else - { - destx = mobj->target->x; - desty = mobj->target->y; - } - - P_TeleportMove(mobj, destx, desty, mobj->target->z); - break; - } - case MT_BUBBLESHIELD: - { - fixed_t destx, desty; - fixed_t scale; - statenum_t curstate; - - if (!mobj->target || !mobj->target->health || !mobj->target->player - || mobj->target->player->kartstuff[k_curshield] != KSHIELD_BUBBLE) - { - P_RemoveMobj(mobj); - return; - } - - scale = (5*mobj->target->scale)>>2; - curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); - - if (mobj->target->player->kartstuff[k_bubbleblowup]) - { - INT32 blow = mobj->target->player->kartstuff[k_bubbleblowup]; - if (blow > bubbletime) - blow = bubbletime; - - if (curstate != S_BUBBLESHIELDBLOWUP) - P_SetMobjState(mobj, S_BUBBLESHIELDBLOWUP); - - mobj->angle += ANGLE_22h; - mobj->drawflags &= ~MFD_SHADOW; - scale += (blow * (3*scale)) / bubbletime; - - mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + mobj->extravalue1); - if ((mobj->target->player->kartstuff[k_bubbleblowup] > bubbletime) && (leveltime & 1)) - mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + 5); - - if (mobj->extravalue1 < 4 && mobj->extravalue2 < blow && !mobj->cvmem && (leveltime & 1)) // Growing - { - mobj->extravalue1++; - if (mobj->extravalue1 >= 4) - mobj->cvmem = 1; // shrink back down - } - else if ((mobj->extravalue1 > -4 && mobj->extravalue2 > blow) - || (mobj->cvmem && mobj->extravalue1 > 0)) // Shrinking - mobj->extravalue1--; - - if (P_IsObjectOnGround(mobj->target)) - { - UINT8 i; - - for (i = 0; i < 2; i++) - { - angle_t a = mobj->angle + ((i & 1) ? ANGLE_180 : 0); - fixed_t ws = (mobj->target->scale>>1); - mobj_t *wave; - - ws += (blow * ws) / bubbletime; - - wave = P_SpawnMobj( - (mobj->target->x - mobj->target->momx) + P_ReturnThrustX(NULL, a, mobj->radius - (21*ws)), - (mobj->target->y - mobj->target->momy) + P_ReturnThrustY(NULL, a, mobj->radius - (21*ws)), - (mobj->target->z - mobj->target->momz), MT_THOK); - - wave->flags &= ~(MF_NOCLIPHEIGHT|MF_NOGRAVITY); - P_SetScale(wave, (wave->destscale = ws)); - - P_SetMobjState(wave, S_BUBBLESHIELDWAVE1); - - wave->momx = mobj->target->momx; - wave->momy = mobj->target->momy; - wave->momz = mobj->target->momz; - } - } - } - else - { - mobj->cvmem = 0; - mobj->angle = mobj->target->angle; - - if (curstate == S_BUBBLESHIELDBLOWUP) - { - if (mobj->extravalue1 != 0) - { - mobj->frame = (states[S_BUBBLESHIELDBLOWUP].frame + mobj->extravalue1); - - if (mobj->extravalue1 < 0 && (leveltime & 1)) - mobj->extravalue1++; - else if (mobj->extravalue1 > 0) - mobj->extravalue1--; - } - else - { - P_SetMobjState(mobj, S_BUBBLESHIELD1); - mobj->extravalue1 = 0; - } - } - else - { - if (mobj->target->player->kartstuff[k_bubblecool] && ((curstate-S_BUBBLESHIELD1) & 1)) - mobj->drawflags |= MFD_SHADOW; - else - mobj->drawflags &= ~MFD_SHADOW; - } - } - - mobj->extravalue2 = mobj->target->player->kartstuff[k_bubbleblowup]; - P_SetScale(mobj, (mobj->destscale = scale)); - - if (!splitscreen /*&& rendermode != render_soft*/) - { - angle_t viewingangle; - - if (players[displayplayers[0]].awayviewtics) - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y); - else if (!camera[0].chase && players[displayplayers[0]].mo) - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y); - else - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y); - - destx = mobj->target->x + P_ReturnThrustX(mobj->target, viewingangle, mobj->scale>>4); - desty = mobj->target->y + P_ReturnThrustY(mobj->target, viewingangle, mobj->scale>>4); - } - else - { - destx = mobj->target->x; - desty = mobj->target->y; - } - - P_TeleportMove(mobj, destx, desty, mobj->target->z); - break; - } - case MT_FLAMESHIELD: - { - fixed_t destx, desty; - statenum_t curstate; - statenum_t underlayst = S_NULL; - INT32 flamemax = 0; - - if (!mobj->target || !mobj->target->health || !mobj->target->player - || mobj->target->player->kartstuff[k_curshield] != KSHIELD_FLAME) - { - P_RemoveMobj(mobj); - return; - } - - flamemax = mobj->target->player->kartstuff[k_flamelength] * flameseg; - - P_SetScale(mobj, (mobj->destscale = (5*mobj->target->scale)>>2)); - - curstate = ((mobj->tics == 1) ? (mobj->state->nextstate) : ((statenum_t)(mobj->state-states))); - - if (mobj->target->player->kartstuff[k_flamedash]) - { - if (!(curstate >= S_FLAMESHIELDDASH1 && curstate <= S_FLAMESHIELDDASH12)) - P_SetMobjState(mobj, S_FLAMESHIELDDASH1); - - if (curstate == S_FLAMESHIELDDASH2) - underlayst = S_FLAMESHIELDDASH2_UNDERLAY; - else if (curstate == S_FLAMESHIELDDASH5) - underlayst = S_FLAMESHIELDDASH5_UNDERLAY; - else if (curstate == S_FLAMESHIELDDASH8) - underlayst = S_FLAMESHIELDDASH8_UNDERLAY; - else if (curstate == S_FLAMESHIELDDASH11) - underlayst = S_FLAMESHIELDDASH11_UNDERLAY; - - if (leveltime & 1) - { - UINT8 i; - UINT8 nl = 2; - - if (mobj->target->player->kartstuff[k_flamedash] > mobj->extravalue1) - nl = 3; - - for (i = 0; i < nl; i++) - { - mobj_t *fast = P_SpawnMobj(mobj->x + (P_RandomRange(-36,36) * mobj->scale), - mobj->y + (P_RandomRange(-36,36) * mobj->scale), - mobj->z + (mobj->height/2) + (P_RandomRange(-20,20) * mobj->scale), - MT_FASTLINE); - - fast->angle = mobj->angle; - fast->momx = 3*mobj->target->momx/4; - fast->momy = 3*mobj->target->momy/4; - fast->momz = 3*mobj->target->momz/4; - - K_MatchGenericExtraFlags(fast, mobj); - P_SetMobjState(fast, S_FLAMESHIELDLINE1 + i); - } - } - } - else - { - if (curstate >= S_FLAMESHIELDDASH1 && curstate <= S_FLAMESHIELDDASH12) - P_SetMobjState(mobj, S_FLAMESHIELD1); - } - - mobj->extravalue1 = mobj->target->player->kartstuff[k_flamedash]; - - if (mobj->target->player->kartstuff[k_flamemeter] > flamemax) - { - mobj_t *flash = P_SpawnMobj(mobj->x + mobj->target->momx, mobj->y + mobj->target->momy, mobj->z + mobj->target->momz, MT_THOK); - P_SetMobjState(flash, S_FLAMESHIELDFLASH); - - if (leveltime & 1) - { - flash->frame |= 2 + ((leveltime / 2) % 4); - } - else - { - flash->frame |= ((leveltime / 2) % 2); - } - } - - if (!splitscreen /*&& rendermode != render_soft*/) - { - angle_t viewingangle; - - if (players[displayplayers[0]].awayviewtics) - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].awayviewmobj->x, players[displayplayers[0]].awayviewmobj->y); - else if (!camera[0].chase && players[displayplayers[0]].mo) - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, players[displayplayers[0]].mo->x, players[displayplayers[0]].mo->y); - else - viewingangle = R_PointToAngle2(mobj->target->x, mobj->target->y, camera[0].x, camera[0].y); - - if (curstate >= S_FLAMESHIELD1 && curstate < S_FLAMESHIELDDASH1 && ((curstate-S_FLAMESHIELD1) & 1)) - viewingangle += ANGLE_180; - - destx = mobj->target->x + P_ReturnThrustX(mobj->target, viewingangle, mobj->scale>>4); - desty = mobj->target->y + P_ReturnThrustY(mobj->target, viewingangle, mobj->scale>>4); - } - else - { - destx = mobj->target->x; - desty = mobj->target->y; - } - - P_TeleportMove(mobj, destx, desty, mobj->target->z); - if (mobj->target->momx || mobj->target->momy) - mobj->angle = R_PointToAngle2(0, 0, mobj->target->momx, mobj->target->momy); - else - mobj->angle = mobj->target->angle; - - if (underlayst != S_NULL) - { - mobj_t *underlay = P_SpawnMobj(mobj->target->x, mobj->target->y, mobj->target->z, MT_FLAMESHIELDUNDERLAY); - underlay->angle = mobj->angle; - P_SetMobjState(underlay, underlayst); - } - break; - } - case MT_ROCKETSNEAKER: - if (!mobj->target || !mobj->target->health) - { - P_RemoveMobj(mobj); - return; - } - if (mobj->target->player && !mobj->target->player->kartstuff[k_rocketsneakertimer]) - { - mobj->flags &= ~MF_NOGRAVITY; - mobj->angle += ANGLE_45; - - if (!mobj->extravalue2) - { - K_DropRocketSneaker(mobj->target->player); - } - else if (P_IsObjectOnGround(mobj)) - { - P_RemoveMobj(mobj); - return; - } - } - break; - case MT_KARMAHITBOX: - { - statenum_t state = (mobj->state-states); - - if (!mobj->target || !mobj->target->health || !mobj->target->player || mobj->target->player->spectator - || (G_RaceGametype() || mobj->target->player->kartstuff[k_bumper])) - { - P_RemoveMobj(mobj); - return; - } - - P_TeleportMove(mobj, mobj->target->x, mobj->target->y, mobj->target->z); - mobj->angle = mobj->target->angle; - mobj->scalespeed = mobj->target->scalespeed; - mobj->destscale = mobj->target->destscale; - P_SetScale(mobj, mobj->target->scale); - mobj->color = mobj->target->color; - mobj->colorized = true; - - // Give items an item-sized hitbox - if (mobj->target->player->kartstuff[k_comebackmode] == 1) - mobj->radius = 48*mobj->target->scale; - else - mobj->radius = 24*mobj->target->scale; - mobj->height = 2*mobj->radius; - - if (mobj->target->player->kartstuff[k_comebacktimer] > 0) - { - if (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20) - P_SetMobjState(mobj, S_PLAYERBOMB1); - if (mobj->target->player->kartstuff[k_comebacktimer] < TICRATE && (leveltime & 1)) - mobj->drawflags &= ~MFD_DONTDRAW; - else - mobj->drawflags |= MFD_DONTDRAW; - } - else - { - if (!mobj->target->player->kartstuff[k_comebackmode] - && (state < S_PLAYERBOMB1 || state > S_PLAYERBOMB20)) - P_SetMobjState(mobj, S_PLAYERBOMB1); - else if (mobj->target->player->kartstuff[k_comebackmode] == 1 - && (state < S_PLAYERITEM1 || state > S_PLAYERITEM12)) - P_SetMobjState(mobj, S_PLAYERITEM1); - else if (mobj->target->player->kartstuff[k_comebackmode] == 2 - && (state < S_PLAYERFAKE1 || state > S_PLAYERFAKE12)) - P_SetMobjState(mobj, S_PLAYERFAKE1); - - if (mobj->target->player->powers[pw_flashing] && (leveltime & 1)) - mobj->drawflags |= MFD_DONTDRAW; - else - mobj->drawflags &= ~MFD_DONTDRAW; - } - - // Update mobj antigravity status: - mobj->eflags = (mobj->eflags & ~MFE_VERTICALFLIP)|(mobj->target->eflags & MFE_VERTICALFLIP); - mobj->flags2 = (mobj->flags2 & ~MF2_OBJECTFLIP)|(mobj->target->flags2 & MF2_OBJECTFLIP); - - // Now for the wheels - { - const fixed_t rad = FixedMul(mobjinfo[MT_PLAYER].radius, mobj->target->scale); - mobj_t *cur = mobj->hnext; - - while (cur && !P_MobjWasRemoved(cur)) - { - fixed_t offx = rad; - fixed_t offy = rad; - - if (cur->lastlook == 1 || cur->lastlook == 3) - offx *= -1; - if (cur->lastlook == 2 || cur->lastlook == 3) - offy *= -1; - - P_TeleportMove(cur, mobj->x + offx, mobj->y + offy, mobj->z); - cur->scalespeed = mobj->target->scalespeed; - cur->destscale = mobj->target->destscale; - P_SetScale(cur, mobj->target->scale); - cur->color = mobj->target->color; - cur->colorized = true; - K_FlipFromObject(cur, mobj->target); - - if (mobj->drawflags & MFD_DONTDRAW) - cur->drawflags |= MFD_DONTDRAW; - else - cur->drawflags &= ~MFD_DONTDRAW; - - cur = cur->hnext; - } - } - } - break; - case MT_SIGN: // Kart's unique sign behavior - if (mobj->movecount != 0) - { - mobj_t *cur = mobj->hnext; - SINT8 newskin = -1; - UINT8 newcolor = SKINCOLOR_NONE; - angle_t endangle = FixedAngle(mobj->extravalue1 << FRACBITS); - - if (mobj->movecount == 1) - { - if (mobj->z + mobj->momz <= mobj->movefactor) - { - if (mobj->info->attacksound) - S_StartSound(mobj, mobj->info->attacksound); - - mobj->z = mobj->movefactor; - mobj->momz = 0; - mobj->movecount = 2; - - newskin = ((skin_t*)mobj->target->skin)-skins; - newcolor = mobj->target->player->skincolor; - } - else - { - fixed_t g = (6*mobj->scale); - UINT16 ticstilimpact = abs(mobj->z - mobj->movefactor) / g; - - P_SpawnMobj( - mobj->x + FixedMul(48*mobj->scale, FINECOSINE(mobj->angle >> ANGLETOFINESHIFT)), - mobj->y + FixedMul(48*mobj->scale, FINESINE(mobj->angle >> ANGLETOFINESHIFT)), - mobj->z + ((24 + ((leveltime % 4) * 8)) * mobj->scale), - MT_SIGNSPARKLE - ); - - if (ticstilimpact == (3*TICRATE/2)) - { - if (mobj->info->seesound) - S_StartSound(mobj, mobj->info->seesound); - } - - mobj->angle += ANGLE_45; - mobj->momz = -g; - - if (mobj->angle == endangle + ANGLE_180) - { - if (ticstilimpact <= 8) - { - newskin = mobj->target->player->skin; - newcolor = mobj->target->player->skincolor; - } - else - { - UINT8 plist[MAXPLAYERS]; - UINT8 plistlen = 0; - UINT8 i; - - memset(plist, 0, sizeof(plist)); - - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].spectator) - { - plist[plistlen] = i; - plistlen++; - } - } - - if (plistlen <= 1) - { - // Default to the winner - newskin = mobj->target->player->skin; - newcolor = mobj->target->player->skincolor; - } - else - { - // Pick another player in the server! - player_t *p = &players[plist[P_RandomKey(plistlen)]]; - newskin = p->skin; - newcolor = p->skincolor; - } - } - } - } - } - else if (mobj->movecount == 2) - { - if (mobj->angle != endangle) - mobj->angle += ANGLE_11hh; - } - - while (cur && !P_MobjWasRemoved(cur)) - { - fixed_t amt = cur->extravalue1 * mobj->scale; - angle_t dir = mobj->angle + (cur->extravalue2 * ANGLE_90); - fixed_t z = mobj->z + (23*mobj->scale); - - if (cur->state == &states[S_SIGN_FACE]) - { - if (newcolor != SKINCOLOR_NONE) - { - cur->color = KartColor_Opposite[newcolor*2]; - cur->frame = states[S_SIGN_FACE].frame + KartColor_Opposite[newcolor*2+1]; - } - } - else if (cur->state == &states[S_PLAY_SIGN]) - { - z += (5*mobj->scale); - amt += 1; - - if (newskin != -1) - cur->skin = &skins[newskin]; - - if (newcolor != SKINCOLOR_NONE) - cur->color = newcolor; - } - - P_TeleportMove( - cur, - mobj->x + FixedMul(amt, FINECOSINE(dir >> ANGLETOFINESHIFT)), - mobj->y + FixedMul(amt, FINESINE(dir >> ANGLETOFINESHIFT)), - z - ); - cur->angle = dir + ANGLE_90; - - cur = cur->hnext; - } - } - break; - case MT_CDUFO: - if (!mobj->spawnpoint || mobj->fuse) - break; - - if (mobj->movecount) - { - mobj->movecount--; - break; - } - else if (P_AproxDistance(mobj->x - (mobj->spawnpoint->x<y - (mobj->spawnpoint->y<movecount = 3; - - { - angle_t facing = P_RandomRange(0, 90); - if (facing >= 45) - facing = InvAngle((facing - 45)*ANG1); - else - facing *= ANG1; - - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->spawnpoint->x<spawnpoint->y<extravalue1) - { - fixed_t mx = P_ReturnThrustX(NULL, mobj->angle, 32*mobj->scale); - fixed_t my = P_ReturnThrustY(NULL, mobj->angle, 32*mobj->scale); - mobj_t *explosion = P_SpawnMobj(mobj->x + (2*mx), mobj->y + (2*my), mobj->z+(mobj->height/2), MT_THOK); - - P_SetMobjState(explosion, S_FZEROBOOM1); - explosion->scale = mobj->scale*2; - explosion->momx = mx; - explosion->momy = my; - - S_StartSound(mobj, mobj->info->seesound); - mobj->extravalue1 = 1; - } - - if (!S_SoundPlaying(mobj, mobj->info->attacksound)) - S_StartSound(mobj, mobj->info->attacksound); - - if (mobj->extravalue2 <= 8) // Short delay - mobj->extravalue2++; // flametimer - else // fire + smoke pillar - { - UINT8 i; - mobj_t *fire = P_SpawnMobj(mobj->x + (P_RandomRange(-32, 32)*mobj->scale), mobj->y + (P_RandomRange(-32, 32)*mobj->scale), mobj->z, MT_THOK); - - fire->sprite = SPR_FPRT; - fire->frame = FF_FULLBRIGHT|FF_TRANS30; - fire->scale = mobj->scale*4; - fire->momz = P_RandomRange(2, 3)*mobj->scale; - fire->scalespeed = mobj->scale/12; - fire->destscale = 1; - fire->tics = TICRATE; - - for (i = 0; i < 2; i++) - { - mobj_t *smoke = P_SpawnMobj(mobj->x + (P_RandomRange(-16, 16)*mobj->scale), mobj->y + (P_RandomRange(-16, 16)*mobj->scale), mobj->z, MT_SMOKE); - - P_SetMobjState(smoke, S_FZSLOWSMOKE1); - smoke->scale = mobj->scale; - smoke->momz = P_RandomRange(3, 10)*mobj->scale; - smoke->destscale = mobj->scale*4; - smoke->scalespeed = mobj->scale/24; - } - } - break; - case MT_EZZPROPELLER: - if (mobj->hnext) - { - mobj_t *cur = mobj->hnext; - - while (cur && !P_MobjWasRemoved(cur)) - { - cur->angle += FixedAngle(mobj->info->speed); - P_TeleportMove(cur, mobj->x + FINECOSINE((cur->angle*8)>>ANGLETOFINESHIFT), - mobj->y + FINESINE((cur->angle*8)>>ANGLETOFINESHIFT), mobj->z); - //P_SpawnGhostMobj(cur)->tics = 2; - - cur = cur->hnext; - } - } - if (!S_SoundPlaying(mobj, mobj->info->seesound)) - S_StartSound(mobj, mobj->info->seesound); - break; - case MT_FROGGER: - { - statenum_t frogstate = (mobj->state-states); - - // FROG ATTACK VALUES: - // threshold: distance - // movecount: time - // lastlook: direction - // extravalue1: x step - // extravalue2: y step - // cusval: z step - - if (frogstate == S_FROGGER) - { - mobj->threshold = mobj->movecount = mobj->lastlook = 0; // clear tongue attack - mobj->extravalue1 = mobj->extravalue2 = mobj->cusval = 0; - if (mobj->hnext) // Clean hnext list - { - mobj_t *cur = mobj->hnext; - while (cur && !P_MobjWasRemoved(cur)) - { - mobj_t *next = cur->hnext; - P_RemoveMobj(cur); - cur = next; - } - } - - if (mobj->reactiontime) - mobj->reactiontime--; - else - { - if (mobj->flags2 & MF2_AMBUSH) - { - mobj->momz = P_RandomRange(12, 16)<x, mobj->y, mobj->z + (mobj->height/2), MT_FROGTONGUE); - P_SetTarget(&mobj->tracer, tongue); - P_SetMobjState(mobj, S_FROGGER_ATTACK); - } - } - } - else if (frogstate == S_FROGGER_ATTACK) - { - if (!mobj->tracer || P_MobjWasRemoved(mobj->tracer)) - { - mobj->reactiontime = mobj->info->reactiontime; - P_SetMobjState(mobj, S_FROGGER); - break; - } - - if (mobj->threshold == 0) - { - fixed_t targetz = mobj->tracer->z; //mobj->z + (mobj->height/2) - - mobj->threshold = 256; - mobj->movecount = 1; - mobj->lastlook = 1; - - mobj->tracer->angle = mobj->angle; - - mobj->extravalue1 = FixedMul(FixedMul((mobj->threshold/16)<>ANGLETOFINESHIFT)), - FINECOSINE(mobj->angle>>ANGLETOFINESHIFT)) >> FRACBITS; - - mobj->extravalue2 = FixedMul(FixedMul((mobj->threshold/16)<>ANGLETOFINESHIFT)), - FINESINE(mobj->angle>>ANGLETOFINESHIFT)) >> FRACBITS; - - mobj->cusval = FixedMul((mobj->threshold/16)<>ANGLETOFINESHIFT)) >> FRACBITS; - - S_StartSound(mobj, sfx_s3k8c); // Play that tongue-y sound. - } - - mobj->movecount += mobj->lastlook; - - if (!(P_TryMove(mobj->tracer, mobj->x + ((mobj->extravalue1<movecount), mobj->y + ((mobj->extravalue2<movecount), true)) - || (mobj->movecount >= 16) // maximum travel time - || (mobj->tracer->z <= mobj->tracer->floorz) // Through the floor - || ((mobj->tracer->z + mobj->tracer->height) >= mobj->tracer->ceilingz)) // Through the ceiling - { - mobj->lastlook = -1; // Reverse direction. - } - - if (mobj->movecount == 0) // It's back to its source, time to reset. - { - mobj->threshold = mobj->lastlook = 0; - - P_RemoveMobj(mobj->tracer); - - if (mobj->hnext) // Clean hnext list - { - mobj_t *cur = mobj->hnext; - while (cur && !P_MobjWasRemoved(cur)) - { - mobj_t *next = cur->hnext; - P_RemoveMobj(cur); - cur = next; - } - } - - mobj->reactiontime = mobj->info->reactiontime; - P_SetMobjState(mobj, S_FROGGER); - } - else - { - const UINT8 numjoints = 11; - UINT8 joint = numjoints; - mobj_t *cur = mobj->hnext, *prev = mobj; - - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->tracer->x, mobj->tracer->y); - - for (; joint > 0; joint--) - { - fixed_t wx = mobj->tracer->x + (joint * (mobj->x - mobj->tracer->x) / (numjoints+1)); - fixed_t wy = mobj->tracer->y + (joint * (mobj->y - mobj->tracer->y) / (numjoints+1)); - fixed_t wz = mobj->tracer->z + (joint * ((mobj->z + (mobj->height/2)) - mobj->tracer->z) / (numjoints+1)); - - if (cur && !P_MobjWasRemoved(cur)) - P_TeleportMove(cur, wx, wy, wz); - else - cur = P_SpawnMobj(wx, wy, wz, MT_FROGTONGUE_JOINT); - - P_SetTarget(&cur->target, mobj); - - P_SetTarget(&prev->hnext, cur); - P_SetTarget(&cur->hprev, prev); - - prev = cur; - cur = cur->hnext; - } - } - } - else if (frogstate == S_FROGGER_JUMP) - { - if (P_IsObjectOnGround(mobj)) - { - mobj->reactiontime = mobj->info->reactiontime; - P_SetMobjState(mobj, S_FROGGER); - } - } - } - break; - case MT_ROBRA: - case MT_BLUEROBRA: - if (mobj->health) - { - boolean blue = (mobj->type == MT_BLUEROBRA); - - if (blue) - { - if (mobj->spawnpoint) - mobj->extravalue2 = mobj->spawnpoint->angle; - else - mobj->extravalue2 = 128; - } - else - { - if (!mobj->extravalue2) - mobj->extravalue2 = P_RandomRange(64, 192); - } - - if (mobj->reactiontime) - mobj->reactiontime--; - else - { - if (!mobj->extravalue1) - { - mobj_t *head = P_SpawnMobj(mobj->x, mobj->y, mobj->z, (blue ? MT_BLUEROBRA_HEAD : MT_ROBRA_HEAD)); - P_SetTarget(&mobj->tracer, head); - - mobj->destscale = mapobjectscale; - P_SetTarget(&mobj->tracer->target, mobj->target); - P_SetTarget(&mobj->tracer->tracer, mobj); - mobj->tracer->extravalue2 = mobj->extravalue2; - - if (!blue) - mobj->tracer->angle = mobj->angle; - - mobj->extravalue1 = 1; - } - } - - if ((mobj->extravalue1) && !(mobj->tracer && !P_MobjWasRemoved(mobj->tracer))) - { - mobj->reactiontime = 20*mobj->info->reactiontime; - P_SetTarget(&mobj->target, NULL); - mobj->extravalue1 = 0; - } - - if ((mobj->tracer && !P_MobjWasRemoved(mobj->tracer)) && !(leveltime % 10)) - { - mobj_t *dust = P_SpawnMobj(mobj->x + (P_RandomRange(-4, 4)<y + (P_RandomRange(-4, 4)<z + (P_RandomRange(0, 2)<scale/2); - P_InstaThrust(dust, FixedAngle(P_RandomRange(0,359)<tracer->momz)/2); - - if (abs(mobj->tracer->momz) >= 2<health) - { - boolean blue = (mobj->type == MT_BLUEROBRA_HEAD); - UINT8 locnumsegs = abs(mobj->z - mobj->floorz) / (32 * mobj->scale); - UINT8 i; - mobj_t *cur = mobj->hnext, *prev = mobj; - - if (blue) - mobj->angle = (angle_t)mobj->extravalue1; - mobj->extravalue1 += (FixedAngle(2*mobj->momz) * (blue ? -1 : 1)); - - for (i = 0; i < locnumsegs*2; i++) // *2 to check for any extra segs still present - { - fixed_t segz = mobj->z - ((i+1) * (32 * mobj->scale)); - - if (cur && !P_MobjWasRemoved(cur)) - { - if (i >= locnumsegs) // Remove extras - { - mobj_t *next = cur->hnext; - P_RemoveMobj(cur); - cur = next; - continue; - } - else // Move into place - P_TeleportMove(cur, mobj->x, mobj->y, segz); - } - else - { - if (i >= locnumsegs) // We're done with this list - continue; //break; - else // Need another here! - cur = P_SpawnMobj(mobj->x, mobj->y, segz, (blue ? MT_BLUEROBRA_JOINT : MT_ROBRA_JOINT)); - } - - P_SetTarget(&cur->target, mobj); - P_SetScale(cur, (7*mobj->scale)/8); - - cur->angle = mobj->extravalue1; - mobj->extravalue1 += (FixedAngle(2*mobj->momz) * (blue ? -1 : 1)); - - P_SetTarget(&prev->hnext, cur); - P_SetTarget(&cur->hprev, prev); - - prev = cur; - cur = cur->hnext; - } - - { - //fixed_t ceilingheight = mobj->ceilingz - (72<floorz + (72<floorz + (mobj->extravalue2<z < targetheight) - { - mobj->momz += mobj->info->speed; - if ((mobj->z < floorheight) && (mobj->momz < 0)) - mobj->momz /= 2; - } - else - { - mobj->momz -= mobj->info->speed; - if ((mobj->z > (targetheight + (64<momz > 0)) - mobj->momz /= 2; - } - } - } - break; - case MT_ROBRA_JOINT: - case MT_BLUEROBRA_JOINT: - if (!mobj->target || P_MobjWasRemoved(mobj->target)) - { - P_RemoveMobj(mobj); - return; - } - break; - case MT_SMK_PIPE: - if (mobj->flags2 & MF2_AMBUSH) - P_SetMobjStateNF(mobj, mobj->info->seestate); - else - P_SetMobjStateNF(mobj, mobj->info->spawnstate); - break; - case MT_SMK_MOLESPAWNER: - if (!mobj->target || P_MobjWasRemoved(mobj->target)) - { - mobj_t *newmole = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_MOLE); - P_SetTarget(&mobj->target, newmole); - return; - } - break; - case MT_SMK_MOLE: - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - player_t *player = mobj->target->player; - - mobj->extravalue1 = 1; - player->kartstuff[k_offroad] += 2<mo->x + P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius) - + P_ReturnThrustX(NULL, player->mo->angle+ANGLE_90, (mobj->threshold)<mo->y + P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius) - + P_ReturnThrustY(NULL, player->mo->angle+ANGLE_90, (mobj->threshold)<mo->z + (player->mo->height/2 * P_MobjFlip(player->mo)) - + (P_RandomRange(-abs(mobj->threshold), abs(mobj->threshold))<threshold /= 2; - mobj->momz = 0; - - if (mobj->movecount > 8*TICRATE) - { - P_KillMobj(mobj, mobj->target, mobj->target); - break; - } - - if (abs(player->cmd.driftturn) > 100) - { - INT32 lastsign = 0; - if (mobj->lastlook > 0) - lastsign = 1; - else if (mobj->lastlook < 0) - lastsign = -1; - - if ((player->cmd.driftturn > 0 && lastsign < 0) - || (player->cmd.driftturn < 0 && lastsign > 0)) - { - mobj->movecount += (TICRATE/2); - mobj->threshold = 16*lastsign; - S_StartSound(mobj, sfx_s1ab); - } - - mobj->lastlook = player->cmd.driftturn; - } - - mobj->movecount++; - } - else if (mobj->extravalue1) // lost your player somehow, DIE - { - P_KillMobj(mobj, NULL, NULL); - break; - } - else - { - if (P_IsObjectOnGround(mobj)) - { - if (mobj->reactiontime) - mobj->reactiontime--; - else - { - mobj->momz = (mobj->info->speed * P_MobjFlip(mobj)); - mobj->reactiontime = mobj->info->reactiontime; - } - } - } - break; - case MT_SMK_THWOMP: - if (mobj->flags2 & MF2_AMBUSH) - { - mobj->colorized = true; - mobj->color = (1 + (leveltime % (MAXSKINCOLORS-1))); - mobj->frame |= FF_FULLBRIGHT; - } - else - { - mobj->colorized = false; - mobj->color = SKINCOLOR_NONE; - mobj->frame &= (~FF_FULLBRIGHT); - } - - if (!thwompsactive) - break; - - if (mobj->reactiontime) - mobj->reactiontime--; - else - { - if (mobj->extravalue1) - { - P_SpawnGhostMobj(mobj)->tics = 3; - - if (mobj->z == mobj->floorz) - { - UINT8 i; - - mobj->extravalue1 = 0; - mobj->reactiontime = mobj->info->reactiontime; - S_StartSound(mobj, sfx_s1bd); - - for (i = 0; i < 8; i++) - { - mobj_t *dust = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_DRIFTDUST); - P_InstaThrust(dust, FixedAngle(((360*FRACUNIT)/8) * i), mobj->info->speed/8); - dust->momz = P_MobjFlip(mobj) * (P_RandomRange(1,4)<scale = mobj->scale/2; - dust->destscale = mobj->scale*3; - } - } - else - mobj->momz = (-mobj->info->speed) * P_MobjFlip(mobj); - } - else - { - if (mobj->z > mobj->movefactor) - mobj->z = mobj->movefactor; - - if (mobj->z == mobj->movefactor) - { - mobj->extravalue1 = 1; - //S_StartSound(mobj, sfx_s1bb); - } - else - mobj->momz = (mobj->info->speed/16) * P_MobjFlip(mobj); - } - } - break; - case MT_BUBBLESHIELDTRAP: - if (leveltime % 180 == 0) - S_StartSound(mobj, sfx_s3kbfl); - - if (mobj->tracer && !P_MobjWasRemoved(mobj->tracer) && mobj->tracer->player) - { - player_t *player = mobj->tracer->player; - fixed_t destx, desty, curfz, destfz; - boolean blockmove = false; - - mobj->flags = MF_NOCLIP|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_NOGRAVITY|MF_DONTENCOREMAP; - mobj->extravalue1 = 1; - - mobj->cvmem /= 2; - mobj->momz = 0; - mobj->destscale = ((5*mobj->tracer->scale)>>2) + (mobj->tracer->scale>>3); - - mobj->tracer->momz = (8*mobj->tracer->scale) * P_MobjFlip(mobj->tracer); - - mobj->tracer->momx = (31*mobj->tracer->momx)/32; - mobj->tracer->momy = (31*mobj->tracer->momy)/32; - - destx = mobj->x + mobj->tracer->momx; - desty = mobj->y + mobj->tracer->momy; - - if (mobj->tracer->eflags & MFE_VERTICALFLIP) - { - curfz = P_GetCeilingZ(mobj->tracer, mobj->tracer->subsector->sector, mobj->tracer->x, mobj->tracer->y, NULL); - destfz = P_GetCeilingZ(mobj->tracer, R_PointInSubsector(destx, desty)->sector, destx, desty, NULL); - blockmove = (curfz - destfz >= 24*mobj->scale); - } - else - { - curfz = P_GetFloorZ(mobj->tracer, mobj->tracer->subsector->sector, mobj->tracer->x, mobj->tracer->y, NULL); - destfz = P_GetFloorZ(mobj->tracer, R_PointInSubsector(destx, desty)->sector, destx, desty, NULL); - blockmove = (destfz - curfz >= 24*mobj->scale); - } - - if (blockmove) - { - mobj->tracer->momx = mobj->tracer->momy = 0; - } - - P_TeleportMove(mobj, - mobj->tracer->x + P_ReturnThrustX(NULL, mobj->tracer->angle+ANGLE_90, (mobj->cvmem)<tracer->y + P_ReturnThrustY(NULL, mobj->tracer->angle+ANGLE_90, (mobj->cvmem)<tracer->z - (4*mobj->tracer->scale) + (P_RandomRange(-abs(mobj->cvmem), abs(mobj->cvmem))<movecount > 4*TICRATE) - { - S_StartSound(mobj->tracer, sfx_s3k77); - mobj->tracer->flags &= ~MF_NOGRAVITY; - P_KillMobj(mobj, mobj->tracer, mobj->tracer); - break; - } - - if (abs(player->cmd.driftturn) > 100) - { - INT32 lastsign = 0; - if (mobj->lastlook > 0) - lastsign = 1; - else if (mobj->lastlook < 0) - lastsign = -1; - - if ((player->cmd.driftturn > 0 && lastsign < 0) - || (player->cmd.driftturn < 0 && lastsign > 0)) - { - mobj->movecount += (TICRATE/2); - mobj->cvmem = 8*lastsign; - S_StartSound(mobj, sfx_s3k7a); - } - - mobj->lastlook = player->cmd.driftturn; - } - - mobj->movecount++; - } - else if (mobj->extravalue1) // lost your player somehow, DIE - { - P_KillMobj(mobj, NULL, NULL); - break; - } - else - { - mobj->destscale = (5*mapobjectscale)>>2; - - if (mobj->threshold > 0) - mobj->threshold--; - - if (abs(mobj->momx) < 8*mobj->destscale && abs(mobj->momy) < 8*mobj->destscale) - { - // Stop, give light gravity - mobj->momx = mobj->momy = 0; - mobj->momz = -(mobj->scale * P_MobjFlip(mobj)); - } - else - { - UINT8 i; - mobj_t *ghost = P_SpawnGhostMobj(mobj); - - if (mobj->target && !P_MobjWasRemoved(mobj->target) && mobj->target->player) - { - ghost->color = mobj->target->player->skincolor; - ghost->colorized = true; - } - - mobj->momx = (23*mobj->momx)/24; - mobj->momy = (23*mobj->momy)/24; - - mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); - - if ((mobj->z - mobj->floorz) < (24*mobj->scale) && (leveltime % 3 != 0)) - { - // Cool wave effects! - for (i = 0; i < 2; i++) - { - angle_t aoff; - SINT8 sign = 1; - mobj_t *wave; - - if (i & 1) - sign = -1; - else - sign = 1; - - aoff = (mobj->angle + ANGLE_180) + (ANGLE_45 * sign); - - wave = P_SpawnMobj(mobj->x + FixedMul(mobj->radius, FINECOSINE(aoff>>ANGLETOFINESHIFT)), - mobj->y + FixedMul(mobj->radius, FINESINE(aoff>>ANGLETOFINESHIFT)), - mobj->z, MT_THOK); - - wave->flags &= ~(MF_NOCLIPHEIGHT|MF_NOGRAVITY); - P_SetScale(wave, (wave->destscale = mobj->scale/2)); - - P_SetMobjState(wave, S_BUBBLESHIELDWAVE1); - if (leveltime & 1) - wave->tics++; - - P_SetTarget(&wave->target, mobj); - wave->angle = mobj->angle - (ANGLE_90 * sign); // point completely perpendicular from the bubble - K_FlipFromObject(wave, mobj); - - P_Thrust(wave, wave->angle, 4*mobj->scale); - } - } - } - } - break; - case MT_KARMAFIREWORK: - if (mobj->flags & MF_NOGRAVITY) - break; - - if (mobj->momz == 0) - { - P_RemoveMobj(mobj); - return; - } - else - { - mobj_t *trail = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_THOK); - P_SetMobjState(trail, S_KARMAFIREWORKTRAIL); - P_SetScale(trail, mobj->scale); - trail->destscale = 1; - trail->scalespeed = mobj->scale/12; - trail->color = mobj->color; - } - break; - case MT_BATTLECAPSULE: - { - SINT8 realflip = P_MobjFlip(mobj); - SINT8 flip = realflip; // Flying capsules needs flipped sprites, but not flipped gravity - fixed_t bottom; - mobj_t *cur; - - if (mobj->extravalue1) - { - const INT32 speed = 6*TICRATE; // longer is slower - const fixed_t pi = 22*FRACUNIT/7; // Inaccurate, but is close enough for our usage - fixed_t sine = FINESINE((((2*pi*speed) * leveltime) >> ANGLETOFINESHIFT) & FINEMASK) * flip; - - // Flying capsules are flipped upside-down, like S3K - flip = -flip; - - // ALL CAPSULE MOVEMENT NEEDS TO HAPPEN AFTER THIS & ADD TO MOMENTUM FOR BOBBING TO BE ACCURATE - mobj->momz = sine/2; - } - - // Moving capsules - if (mobj->target && !P_MobjWasRemoved(mobj->target)) - { - fixed_t speed = mobj->movefactor; - UINT8 sequence = mobj->lastlook; - UINT8 num = mobj->movecount; - boolean backandforth = (mobj->flags2 & MF2_AMBUSH); - SINT8 direction = mobj->cvmem; - mobj_t *next = NULL; - thinker_t *th; - fixed_t dist, momx, momy, momz; - - dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y); - if (mobj->extravalue1) - dist = P_AproxDistance(dist, mobj->target->z - mobj->z); - if (dist < 1) - dist = 1; - - if (speed <= dist) - { - momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); - momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); - if (mobj->extravalue1) - momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); - - mobj->momx = momx; - mobj->momy = momy; - if (mobj->extravalue1) - mobj->momz = momz; - } - else - { - mobj_t *mo2; - - speed -= dist; - - P_UnsetThingPosition(mobj); - mobj->x = mobj->target->x; - mobj->y = mobj->target->y; - mobj->z = mobj->target->z; - P_SetThingPosition(mobj); - - mobj->floorz = mobj->subsector->sector->floorheight; - mobj->ceilingz = mobj->subsector->sector->ceilingheight; - - // Onto the next waypoint! - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == sequence) - { - if (mo2->health == num + direction) - { - next = mo2; - break; - } - } - } - - // Are we at the end of the waypoint chain? - // If so, search again for the first/previous waypoint (depending on settings) - if (next == NULL) - { - if (backandforth) - { - mobj->cvmem = -mobj->cvmem; - direction = mobj->cvmem; - } - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == sequence) - { - if (backandforth) - { - if (mo2->health == num + direction) - { - next = mo2; - break; - } - } - else - { - if (direction < 0) - { - if (next == NULL || mo2->health > next->health) - next = mo2; - } - else - { - if (next == NULL || mo2->health < next->health) - next = mo2; - } - } - } - } - } - - if (next && !P_MobjWasRemoved(next)) - { - P_SetTarget(&mobj->target, next); - mobj->movecount = next->health; - - dist = P_AproxDistance(mobj->target->x - mobj->x, mobj->target->y - mobj->y); - if (mobj->extravalue1) - dist = P_AproxDistance(dist, mobj->target->z - mobj->z); - if (dist < 1) - dist = 1; - - momx = FixedMul(FixedDiv(mobj->target->x - mobj->x, dist), speed); - momy = FixedMul(FixedDiv(mobj->target->y - mobj->y, dist), speed); - if (mobj->extravalue1) - momz = mobj->momz + FixedMul(FixedDiv(mobj->target->z - mobj->z, dist), speed); - - mobj->momx = momx; - mobj->momy = momy; - if (mobj->extravalue1) - mobj->momz = momz; - } - else - { - CONS_Alert(CONS_WARNING, "Moving capsule could not find next waypoint! (seq: %d)\n", sequence); - P_SetTarget(&mobj->target, NULL); - } - } - } - - if (flip == -1) - bottom = mobj->z + mobj->height; - else - bottom = mobj->z; - - cur = mobj->hnext; - - // Move each piece to the proper position - while (cur && !P_MobjWasRemoved(cur)) - { - fixed_t newx = mobj->x; - fixed_t newy = mobj->y; - fixed_t newz = bottom; - statenum_t state = (statenum_t)(cur->state-states); - - cur->scale = mobj->scale; - cur->destscale = mobj->destscale; - cur->scalespeed = mobj->scalespeed; - - cur->extravalue2 = mobj->extravalue1; - - cur->flags2 = (cur->flags2 & ~MF2_OBJECTFLIP)|(mobj->flags2 & MF2_OBJECTFLIP); - - if (state == S_BATTLECAPSULE_TOP) - newz += (80 * mobj->scale * flip); - else if (state == S_BATTLECAPSULE_BUTTON) - newz += (108 * mobj->scale * flip); - else if (state == S_BATTLECAPSULE_SUPPORT - || state == S_BATTLECAPSULE_SUPPORTFLY - || state == S_KARMAWHEEL) - { - fixed_t offx = mobj->radius; - fixed_t offy = mobj->radius; - - if (cur->extravalue1 & 1) - offx = -offx; - - if (cur->extravalue1 > 1) - offy = -offy; - - newx += offx; - newy += offy; - } - else if (state == S_BATTLECAPSULE_SIDE1 - || state == S_BATTLECAPSULE_SIDE2) - { - fixed_t offset = 48 * mobj->scale; - angle_t angle = (ANGLE_45 * cur->extravalue1); - - newx += FixedMul(offset, FINECOSINE(angle >> ANGLETOFINESHIFT)); - newy += FixedMul(offset, FINESINE(angle >> ANGLETOFINESHIFT)); - newz += (12 * mobj->scale * flip); - - cur->angle = angle + ANGLE_90; - } - - P_TeleportMove(cur, newx, newy, newz); - - cur = cur->hnext; - } - } - case MT_RANDOMITEM: - if (G_BattleGametype() && mobj->threshold == 70) - { - mobj->color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); - mobj->colorized = true; - - if (battleovertime.enabled) - { - angle_t ang = FixedAngle((leveltime % 360) << FRACBITS); - fixed_t z = battleovertime.z; - fixed_t dist; - mobj_t *ghost; - - /*if (z < mobj->subsector->sector->floorheight) - z = mobj->subsector->sector->floorheight;*/ - - if (mobj->extravalue1 < 512) - mobj->extravalue1++; - dist = mobj->extravalue1 * mapobjectscale; - - P_TeleportMove(mobj, battleovertime.x + P_ReturnThrustX(NULL, ang, dist), - battleovertime.y + P_ReturnThrustY(NULL, ang, dist), z); - - ghost = P_SpawnGhostMobj(mobj); - ghost->fuse = 4; - ghost->frame |= FF_FULLBRIGHT; - } - } - else - { - player_t *player = K_GetItemBoxPlayer(mobj); - UINT8 color = SKINCOLOR_BLACK; - - if (player != NULL) - { - color = player->skincolor; - } - - mobj->color = color; - mobj->colorized = false; - } - break; - //} - case MT_TURRET: - P_MobjCheckWater(mobj); - P_CheckPosition(mobj, mobj->x, mobj->y); - if (P_MobjWasRemoved(mobj)) - return; - mobj->floorz = tmfloorz; - mobj->ceilingz = tmceilingz; - - if ((mobj->eflags & MFE_UNDERWATER) && mobj->health > 0) - { - P_SetMobjState(mobj, mobj->info->deathstate); - mobj->health = 0; - mobj->flags2 &= ~MF2_FIRING; - } - else if (mobj->health > 0 && mobj->z + mobj->height > mobj->ceilingz) // Crushed - { - INT32 i,j; - fixed_t ns; - fixed_t x,y,z; - mobj_t *mo2; - - z = mobj->subsector->sector->floorheight + FixedMul(64*FRACUNIT, mobj->scale); - for (j = 0; j < 2; j++) - { - for (i = 0; i < 32; i++) - { - const angle_t fa = (i*FINEANGLES/16) & FINEMASK; - ns = FixedMul(64 * FRACUNIT, mobj->scale); - x = mobj->x + FixedMul(FINESINE(fa),ns); - y = mobj->y + FixedMul(FINECOSINE(fa),ns); - - mo2 = P_SpawnMobj(x, y, z, MT_EXPLODE); - ns = FixedMul(16 * FRACUNIT, mobj->scale); - mo2->momx = FixedMul(FINESINE(fa),ns); - mo2->momy = FixedMul(FINECOSINE(fa),ns); - } - z -= FixedMul(32*FRACUNIT, mobj->scale); - } - P_SetMobjState(mobj, mobj->info->deathstate); - mobj->health = 0; - mobj->flags2 &= ~MF2_FIRING; - } - break; - case MT_BLUEFLAG: - case MT_REDFLAG: - if (P_MobjTouchingSectorSpecial(mobj, 4, 2, false)) - mobj->fuse = 1; // Return to base. - break; - case MT_CANNONBALL: -#ifdef FLOORSPLATS - R_AddFloorSplat(mobj->tracer->subsector, mobj->tracer, "TARGET", mobj->tracer->x, - mobj->tracer->y, mobj->tracer->floorz, SPLATDRAWMODE_SHADE); -#endif - break; - case MT_SPINFIRE: - case MT_SNEAKERTRAIL: - if (mobj->eflags & MFE_VERTICALFLIP) - mobj->z = mobj->ceilingz - mobj->height; - else - mobj->z = mobj->floorz; - /* FALLTHRU */ - default: - // check mobj against possible water content, before movement code - P_MobjCheckWater(mobj); - - // Extinguish fire objects in water - if (mobj->flags & MF_FIRE && mobj->type != MT_PUMA && mobj->type != MT_FIREBALL - && (mobj->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - { - P_KillMobj(mobj, NULL, NULL); - return; - } - break; - } - if (P_MobjWasRemoved(mobj)) - return; - - if (mobj->flags2 & MF2_FIRING && mobj->target && mobj->health > 0) - { - if (mobj->state->action.acp1 == (actionf_p1)A_Boss1Laser) - { - var1 = mobj->state->var1; - var2 = mobj->state->var2; - mobj->state->action.acp1(mobj); - } - else if (leveltime & 1) // Fire mode - { - mobj_t *missile; - - if (mobj->target->player && mobj->target->player->nightstime) - { - fixed_t oldval = mobjinfo[mobj->extravalue1].speed; - - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x+mobj->target->momx, mobj->target->y+mobj->target->momy); - mobjinfo[mobj->extravalue1].speed = FixedMul(60*FRACUNIT, mobj->scale); - missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); - mobjinfo[mobj->extravalue1].speed = oldval; - } - else - { - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - missile = P_SpawnMissile(mobj, mobj->target, mobj->extravalue1); - } - - if (missile) - { - if (mobj->flags2 & MF2_SUPERFIRE) - missile->flags2 |= MF2_SUPERFIRE; - - if (mobj->info->attacksound) - S_StartSound(missile, mobj->info->attacksound); - } - } - else - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y); - } + if (mobj->flags2 & MF2_FIRING) + P_FiringThink(mobj); if (mobj->flags & MF_AMBIENT) { @@ -10159,212 +8540,8 @@ void P_MobjThinker(mobj_t *mobj) } // Check fuse - if (mobj->fuse) - { - mobj->fuse--; - if (!mobj->fuse) - { - subsector_t *ss; - fixed_t x, y, z; - mobj_t *flagmo, *newmobj; - -#ifdef HAVE_BLUA - if (!LUAh_MobjFuse(mobj) && !P_MobjWasRemoved(mobj)) -#endif - switch (mobj->type) - { - // gargoyle and snowman handled in P_PushableThinker, not here - case MT_THROWNGRENADE: - case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: - P_SetMobjState(mobj, mobj->info->deathstate); - break; - case MT_BLUEFLAG: - case MT_REDFLAG: - if (mobj->spawnpoint) - { - x = mobj->spawnpoint->x << FRACBITS; - y = mobj->spawnpoint->y << FRACBITS; - ss = R_PointInSubsector(x, y); - if (mobj->spawnpoint->options & MTF_OBJECTFLIP) - { - z = ss->sector->ceilingheight - mobjinfo[mobj->type].height; - if (mobj->spawnpoint->options >> ZSHIFT) - z -= (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; - } - else - { - z = ss->sector->floorheight; - if (mobj->spawnpoint->options >> ZSHIFT) - z += (mobj->spawnpoint->options >> ZSHIFT) << FRACBITS; - } - flagmo = P_SpawnMobj(x, y, z, mobj->type); - flagmo->spawnpoint = mobj->spawnpoint; - if (mobj->spawnpoint->options & MTF_OBJECTFLIP) - { - flagmo->eflags |= MFE_VERTICALFLIP; - flagmo->flags2 |= MF2_OBJECTFLIP; - } - - if (mobj->type == MT_REDFLAG) - { - if (!(mobj->flags2 & MF2_JUSTATTACKED)) - CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x85, M_GetText("Red flag"), 0x80); - - // Assumedly in splitscreen players will be on opposing teams - if (players[consoleplayer].ctfteam == 1 || splitscreen) - S_StartSound(NULL, sfx_hoop1); - else if (players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_hoop3); - - redflag = flagmo; - } - else // MT_BLUEFLAG - { - if (!(mobj->flags2 & MF2_JUSTATTACKED)) - CONS_Printf(M_GetText("The %c%s%c has returned to base.\n"), 0x84, M_GetText("Blue flag"), 0x80); - - // Assumedly in splitscreen players will be on opposing teams - if (players[consoleplayer].ctfteam == 2 || splitscreen) - S_StartSound(NULL, sfx_hoop1); - else if (players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_hoop3); - - blueflag = flagmo; - } - } - P_RemoveMobj(mobj); - return; - case MT_YELLOWTV: // Ring shield box - case MT_BLUETV: // Force shield box - case MT_GREENTV: // Water shield box - case MT_BLACKTV: // Bomb shield box - case MT_WHITETV: // Jump shield box - case MT_SNEAKERTV: // Super Sneaker box - case MT_SUPERRINGBOX: // 10-Ring box - case MT_REDRINGBOX: // Red Team 10-Ring box - case MT_BLUERINGBOX: // Blue Team 10-Ring box - case MT_INV: // Invincibility box - case MT_MIXUPBOX: // Teleporter Mixup box - case MT_RECYCLETV: // Recycler box - case MT_SCORETVSMALL: - case MT_SCORETVLARGE: - case MT_PRUP: // 1up! - case MT_EGGMANBOX: // Eggman box - case MT_GRAVITYBOX: // Gravity box - case MT_QUESTIONBOX: - if ((mobj->flags2 & MF2_AMBUSH || mobj->flags2 & MF2_STRONGBOX) && mobj->type != MT_QUESTIONBOX) - { - mobjtype_t spawnchance[64]; - INT32 numchoices = 0, i = 0; - -// This define should make it a lot easier to organize and change monitor weights -#define SETMONITORCHANCES(type, strongboxamt, weakboxamt) \ -for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) spawnchance[numchoices++] = type - - // Type SRM WRM - SETMONITORCHANCES(MT_SNEAKERTV, 0, 10); // Super Sneakers - SETMONITORCHANCES(MT_INV, 2, 0); // Invincibility - SETMONITORCHANCES(MT_WHITETV, 3, 8); // Whirlwind Shield - SETMONITORCHANCES(MT_GREENTV, 3, 8); // Elemental Shield - SETMONITORCHANCES(MT_YELLOWTV, 2, 0); // Attraction Shield - SETMONITORCHANCES(MT_BLUETV, 3, 3); // Force Shield - SETMONITORCHANCES(MT_BLACKTV, 2, 0); // Armageddon Shield - SETMONITORCHANCES(MT_MIXUPBOX, 0, 1); // Teleporters - SETMONITORCHANCES(MT_RECYCLETV, 0, 1); // Recycler - SETMONITORCHANCES(MT_PRUP, 1, 1); // 1-Up - // ====================================== - // Total 16 32 - -#undef SETMONITORCHANCES - - i = P_RandomKey(numchoices); // Gotta love those random numbers! - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, spawnchance[i]); - - // Transfer flags2 (strongbox, objectflip, ambush) - newmobj->flags2 = mobj->flags2; - } - else - { - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); - - // Transfer flags2 (strongbox, objectflip) - newmobj->flags2 = mobj->flags2; - } - P_RemoveMobj(mobj); // make sure they disappear - return; - case MT_RANDOMITEM: - if (G_BattleGametype() && (mobj->threshold != 70)) - { - if (mobj->threshold != 69) - break; - } - else - { - // Respawn from mapthing if you have one! - if (mobj->spawnpoint) - { - P_SpawnMapThing(mobj->spawnpoint); - newmobj = mobj->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing - } - else - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); - - P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_EXPLODE); // poof into existance - // Transfer flags2 (strongbox, objectflip) - newmobj->flags2 = mobj->flags2; - if (mobj->threshold == 70) - newmobj->threshold = 70; - } - P_RemoveMobj(mobj); // make sure they disappear - return; - case MT_METALSONIC_BATTLE: - break; // don't remove - case MT_SPIKE: - P_SetMobjState(mobj, mobj->state->nextstate); - mobj->fuse = mobj->info->speed; - if (mobj->spawnpoint) - mobj->fuse += mobj->spawnpoint->angle; - break; - case MT_NIGHTSCORE: - P_RemoveMobj(mobj); - return; - case MT_PLAYER: - break; // don't remove - case MT_SMK_ICEBLOCK: - { - mobj_t *cur = mobj->hnext, *next; - UINT8 i; - - for (i = 0; i < 5; i++) - { - mobj_t *debris = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_SMK_ICEBLOCK_DEBRIS); - debris->angle = FixedAngle(P_RandomRange(0,360)<angle, P_RandomRange(3,18)*(FRACUNIT/4)); - debris->momz = P_RandomRange(4,8)<hnext; - P_RemoveMobj(cur); - cur = next; - } - - P_RemoveMobj(mobj); - return; - } - default: - P_SetMobjState(mobj, mobj->info->xdeathstate); // will remove the mobj if S_NULL. - break; - } - if (P_MobjWasRemoved(mobj)) - return; - } - else if (((mobj->type == MT_RANDOMITEM && mobj->threshold == 69) || mobj->type == MT_EGGMANITEM || mobj->type == MT_FALLINGROCK) && mobj->fuse <= TICRATE) - mobj->drawflags ^= MFD_DONTDRAW; - } + if (mobj->fuse && !P_FuseThink(mobj)) + return; I_Assert(mobj != NULL); I_Assert(!P_MobjWasRemoved(mobj)); @@ -10395,10 +8572,11 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s mobj->eflags &= ~MFE_JUSTHITFLOOR; } -#ifdef ESLOPE // Sliding physics for slidey mobjs! + // Sliding physics for slidey mobjs! if (mobj->type == MT_FLINGRING || mobj->type == MT_FLINGCOIN - || P_WeaponOrPanel(mobj->type) + || mobj->type == MT_FLINGBLUESPHERE + || mobj->type == MT_FLINGNIGHTSCHIP || mobj->type == MT_FLINGEMERALD || mobj->type == MT_BIGTUMBLEWEED || mobj->type == MT_LITTLETUMBLEWEED @@ -10407,15 +8585,16 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s || mobj->type == MT_ORBINAUT || mobj->type == MT_JAWZ || mobj->type == MT_JAWZ_DUD) { P_TryMove(mobj, mobj->x, mobj->y, true); // Sets mo->standingslope correctly + if (P_MobjWasRemoved(mobj)) // anything that calls checkposition can be lethal + return; //if (mobj->standingslope) CONS_Printf("slope physics on mobj\n"); P_ButteredSlope(mobj); } -#endif if (mobj->flags & (MF_ENEMY|MF_BOSS) && mobj->health && P_CheckDeathPitCollide(mobj)) // extra pit check in case these didn't have momz { - P_KillMobj(mobj, NULL, NULL); + P_KillMobj(mobj, NULL, NULL, DMG_DEATHPIT); return; } @@ -10429,7 +8608,7 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s && !(mobj->flags & MF_NOCLIPHEIGHT) && mobj->health > 0) { - P_KillMobj(mobj, NULL, NULL); + P_KillMobj(mobj, NULL, NULL, DMG_CRUSHED); return; } } @@ -10626,6 +8805,8 @@ void P_SceneryThinker(mobj_t *mobj) return; mobj->floorz = tmfloorz; mobj->ceilingz = tmceilingz; + mobj->floorrover = tmfloorrover; + mobj->ceilingrover = tmceilingrover; } else { @@ -10647,7 +8828,7 @@ void P_SceneryThinker(mobj_t *mobj) if (!playeringame[mobj->threshold] || players[mobj->threshold].spectator) // focused on a valid player? return; - if (!(players[mobj->threshold].exiting) && !(players[mobj->threshold].pflags & PF_TIMEOVER)) // not finished yet? + if (!(players[mobj->threshold].exiting) && !(players[mobj->threshold].pflags & PF_GAMETYPEOVER)) // not finished yet? return; if (K_IsPlayerLosing(&players[mobj->threshold])) @@ -10746,6 +8927,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing) mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { const mobjinfo_t *info = &mobjinfo[type]; + SINT8 sc = -1; state_t *st; mobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); @@ -10761,7 +8943,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->height = info->height; mobj->flags = info->flags; - mobj->health = info->spawnhealth; + mobj->health = (info->spawnhealth ? info->spawnhealth : 1); mobj->reactiontime = info->reactiontime; @@ -10779,7 +8961,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->friction = ORIG_FRICTION; - mobj->movefactor = FRACUNIT; //mobj->movefactor = ORIG_FRICTION_FACTOR; + mobj->movefactor = FRACUNIT; // All mobjs are created at 100% scale. mobj->scale = FRACUNIT; @@ -10799,16 +8981,11 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // Make sure scale matches destscale immediately when spawned P_SetScale(mobj, mobj->destscale); - mobj->floorz = -#ifdef ESLOPE - mobj->subsector->sector->f_slope ? P_GetZAt(mobj->subsector->sector->f_slope, x, y) : -#endif - mobj->subsector->sector->floorheight; - mobj->ceilingz = -#ifdef ESLOPE - mobj->subsector->sector->c_slope ? P_GetZAt(mobj->subsector->sector->c_slope, x, y) : -#endif - mobj->subsector->sector->ceilingheight; + mobj->floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y); + mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y); + + mobj->floorrover = NULL; + mobj->ceilingrover = NULL; // Tells MobjCheckWater that the water height was not set. mobj->watertop = INT32_MAX; @@ -10843,7 +9020,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // Set shadowscale here, before spawn hook so that Lua can change it P_DefaultMobjShadowScale(mobj); -#ifdef HAVE_BLUA // DANGER! This can cause P_SpawnMobj to return NULL! // Avoid using P_RemoveMobj on the newly created mobj in "MobjSpawn" Lua hooks! if (LUAh_MobjSpawn(mobj)) @@ -10854,11 +9030,16 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) else if (P_MobjWasRemoved(mobj)) return NULL; else -#endif switch (mobj->type) { + case MT_ALTVIEWMAN: + if (titlemapinaction) mobj->flags &= ~MF_NOTHINK; + break; + case MT_LOCKONINF: + P_SetScale(mobj, (mobj->destscale = 3*mobj->scale)); + break; case MT_CYBRAKDEMON_NAPALM_BOMB_LARGE: - mobj->fuse = mobj->info->mass; + mobj->fuse = mobj->info->painchance; break; case MT_BLACKEGGMAN: { @@ -10868,12 +9049,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) P_SetTarget(&spawn->target, mobj); } break; - case MT_BLACKEGGMAN_HELPER: - // Collision helper can be stood on but not pushed - mobj->flags2 |= MF2_STANDONME; - break; - case MT_SPIKE: - mobj->flags2 |= MF2_STANDONME; + case MT_FAKEMOBILE: + case MT_EGGSHIELD: + mobj->flags2 |= MF2_INVERTAIMABLE; break; case MT_DETON: mobj->movedir = 0; @@ -10888,52 +9066,113 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) } break; case MT_UNIDUS: - { - INT32 i; - mobj_t *ball; - // Spawn "damage" number of "painchance" spikeball mobjs - // threshold is the distance they should keep from the MT_UNIDUS (touching radius + ball painchance) - for (i = 0; i < mobj->info->damage; i++) { - ball = P_SpawnMobj(x, y, z, mobj->info->painchance); - ball->destscale = mobj->scale; - P_SetScale(ball, mobj->scale); - P_SetTarget(&ball->target, mobj); - ball->movedir = FixedAngle(FixedMul(FixedDiv(i<info->damage<threshold = ball->radius + mobj->radius + FixedMul(ball->info->painchance, ball->scale); + INT32 i; + mobj_t *ball; + // Spawn "damage" number of "painchance" spikeball mobjs + // threshold is the distance they should keep from the MT_UNIDUS (touching radius + ball painchance) + for (i = 0; i < mobj->info->damage; i++) + { + ball = P_SpawnMobj(x, y, z, mobj->info->painchance); + ball->destscale = mobj->scale; + P_SetScale(ball, mobj->scale); + P_SetTarget(&ball->target, mobj); + ball->movedir = FixedAngle(FixedMul(FixedDiv(i<info->damage<threshold = ball->radius + mobj->radius + FixedMul(ball->info->painchance, ball->scale); - var1 = ball->state->var1, var2 = ball->state->var2; - ball->state->action.acp1(ball); + var1 = ball->state->var1, var2 = ball->state->var2; + ball->state->action.acp1(ball); + } } break; - } case MT_POINTY: - { - INT32 q; - mobj_t *ball, *lastball = mobj; - - for (q = 0; q < mobj->info->painchance; q++) { - ball = P_SpawnMobj(x, y, z, mobj->info->mass); - ball->destscale = mobj->scale; - P_SetScale(ball, mobj->scale); - P_SetTarget(&lastball->tracer, ball); - P_SetTarget(&ball->target, mobj); - lastball = ball; + INT32 q; + mobj_t *ball, *lastball = mobj; + + for (q = 0; q < mobj->info->painchance; q++) + { + ball = P_SpawnMobj(x, y, z, mobj->info->mass); + ball->destscale = mobj->scale; + P_SetScale(ball, mobj->scale); + P_SetTarget(&lastball->tracer, ball); + P_SetTarget(&ball->target, mobj); + lastball = ball; + } + } + break; + case MT_CRUSHSTACEAN: + { + mobj_t *bigmeatyclaw = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CRUSHCLAW); + bigmeatyclaw->angle = mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);; + P_SetTarget(&mobj->tracer, bigmeatyclaw); + P_SetTarget(&bigmeatyclaw->tracer, mobj); + mobj->reactiontime >>= 1; + } + break; + case MT_BANPYURA: + { + mobj_t *bigmeatyclaw = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_BANPSPRING); + bigmeatyclaw->angle = mobj->angle + ((mobj->flags2 & MF2_AMBUSH) ? ANGLE_90 : ANGLE_270);; + P_SetTarget(&mobj->tracer, bigmeatyclaw); + P_SetTarget(&bigmeatyclaw->tracer, mobj); + mobj->reactiontime >>= 1; + } + break; + case MT_BIGMINE: + mobj->extravalue1 = FixedHypot(mobj->x, mobj->y)>>FRACBITS; + break; + case MT_WAVINGFLAG1: + case MT_WAVINGFLAG2: + { + mobj_t *prev = mobj, *cur; + UINT8 i; + for (i = 0; i <= 16; i++) // probably should be < but staying authentic to the Lua version + { + cur = P_SpawnMobjFromMobj(mobj, 0, 0, 0, ((mobj->type == MT_WAVINGFLAG1) ? MT_WAVINGFLAGSEG1 : MT_WAVINGFLAGSEG2));; + P_SetTarget(&prev->tracer, cur); + cur->extravalue1 = i; + prev = cur; + } } break; - } case MT_EGGMOBILE2: // Special condition for the 2nd boss. mobj->watertop = mobj->info->speed; break; - case MT_BIRD: - case MT_BUNNY: - case MT_MOUSE: - case MT_CHICKEN: - case MT_COW: - case MT_REDBIRD: - mobj->fuse = P_RandomRange(300, 350); + case MT_EGGMOBILE3: + mobj->movefactor = -512*FRACUNIT; + mobj->flags2 |= MF2_CLASSICPUSH; + break; + case MT_EGGMOBILE4: + mobj->flags2 |= MF2_INVERTAIMABLE; + break; + case MT_FLICKY_08: + mobj->color = (P_RandomChance(FRACUNIT/2) ? SKINCOLOR_RED : SKINCOLOR_AQUAMARINE); + break; + case MT_BALLOON: + mobj->color = SKINCOLOR_RED; + break; + case MT_EGGROBO1: + mobj->movecount = P_RandomKey(13); + mobj->color = SKINCOLOR_RUBY + P_RandomKey(numskincolors - SKINCOLOR_RUBY); + break; + case MT_HIVEELEMENTAL: + mobj->extravalue1 = 5; + break; + case MT_SMASHINGSPIKEBALL: + mobj->movecount = mobj->z; + break; + case MT_SPINBOBERT: + { + mobj_t *fire; + fire = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_SPINBOBERT_FIRE1); + P_SetTarget(&fire->target, mobj); + P_SetTarget(&mobj->hnext, fire); + fire = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_SPINBOBERT_FIRE2); + P_SetTarget(&fire->target, mobj); + P_SetTarget(&mobj->hprev, fire); + } break; case MT_REDRING: // Make MT_REDRING red by default mobj->color = skincolor_redring; @@ -10943,8 +9182,14 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_EXTRALARGEBUBBLE: mobj->fuse += 30 * TICRATE; break; + case MT_NIGHTSDRONE: + nummaprings = -1; // no perfect bonus, rings are free + break; case MT_EGGCAPSULE: - mobj->extravalue1 = -1; // timer for how long a player has been at the capsule + mobj->reactiontime = 0; + mobj->extravalue1 = mobj->cvmem =\ + mobj->cusval = mobj->movecount =\ + mobj->lastlook = mobj->extravalue2 = -1; break; case MT_REDTEAMRING: mobj->color = skincolor_redteam; @@ -10954,8 +9199,54 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; case MT_RING: case MT_COIN: - case MT_BLUEBALL: - nummaprings++; + case MT_NIGHTSSTAR: + if (nummaprings >= 0) + nummaprings++; + break; + case MT_METALSONIC_RACE: + mobj->skin = &skins[5]; + /* FALLTHRU */ + case MT_METALSONIC_BATTLE: + mobj->color = skins[5].prefcolor; + sc = 5; + break; + case MT_FANG: + sc = 4; + break; + case MT_ROSY: + sc = 3; + break; + case MT_CORK: + mobj->flags2 |= MF2_SUPERFIRE; + break; + case MT_FBOMB: + mobj->flags2 |= MF2_EXPLOSION; + break; + case MT_OILLAMP: + { + mobj_t* overlay = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_OVERLAY); + P_SetTarget(&overlay->target, mobj); + P_SetMobjState(overlay, S_OILLAMPFLARE); + break; + } + case MT_TNTBARREL: + mobj->momx = 1; //stack hack + mobj->flags2 |= MF2_INVERTAIMABLE; + break; + case MT_MINECARTEND: + P_SetTarget(&mobj->tracer, P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_MINECARTENDSOLID)); + mobj->tracer->angle = mobj->angle + ANGLE_90; + break; + case MT_TORCHFLOWER: + { + mobj_t *fire = P_SpawnMobjFromMobj(mobj, 0, 0, 46*FRACUNIT, MT_FLAME); + P_SetTarget(&mobj->target, fire); + break; + } + case MT_PYREFLY: + mobj->extravalue1 = (FixedHypot(mobj->x, mobj->y)/FRACUNIT) % 360; + mobj->extravalue2 = 0; + mobj->fuse = 100; break; // SRB2Kart case MT_KARMAHITBOX: @@ -11018,7 +9309,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) if (randu > (FRACUNIT/2)) { - mobj->color = P_RandomKey(MAXSKINCOLORS-1)+1; + mobj->color = P_RandomKey(numskincolors-1)+1; break; } @@ -11031,7 +9322,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_RUSTYLAMP_ORANGE: P_SpawnMobj(mobj->x, mobj->y, mobj->z + (69*mobj->scale), MT_MARBLELIGHT); break; - case MT_PINETREE: + case MT_DAYTONAPINETREE: { angle_t diff = FixedAngle((360/mobj->info->mass)*FRACUNIT); UINT8 i; @@ -11040,7 +9331,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { angle_t ang = i * diff; mobj_t *side = P_SpawnMobj(mobj->x + FINECOSINE((ang>>ANGLETOFINESHIFT) & FINEMASK), - mobj->y + FINESINE((ang>>ANGLETOFINESHIFT) & FINEMASK), mobj->z, MT_PINETREE_SIDE); + mobj->y + FINESINE((ang>>ANGLETOFINESHIFT) & FINEMASK), mobj->z, MT_DAYTONAPINETREE_SIDE); side->angle = ang; side->target = mobj; side->threshold = i; @@ -11107,7 +9398,6 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) mobj->movefactor = mobj->z + (256<flags2 |= MF2_STANDONME; { mobj_t *cur, *prev = mobj; UINT8 i; @@ -11136,8 +9426,32 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; } + if (sc != -1 && !(mobj->flags2 & MF2_SLIDEPUSH)) + { + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i] || players[i].spectator) + continue; + + if (players[i].skin == sc) + { + mobj->color = SKINCOLOR_SILVER; + mobj->colorized = true; + mobj->flags2 |= MF2_SLIDEPUSH; + break; + } + } + } + if (!(mobj->flags & MF_NOTHINK)) - P_AddThinker(&mobj->thinker); + P_AddThinker(THINK_MOBJ, &mobj->thinker); + + if (mobj->skin) // correct inadequecies above. + { + mobj->sprite2 = P_GetSkinSprite2(mobj->skin, (mobj->frame & FF_FRAMEMASK), NULL); + mobj->frame &= ~FF_FRAMEMASK; + } // Call action functions when the state is set if (st->action.acp1 && (mobj->flags & MF_RUNSPAWNFUNC)) @@ -11154,9 +9468,7 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { var1 = st->var1; var2 = st->var2; -#ifdef HAVE_BLUA astate = st; -#endif st->action.acp1(mobj); // DANGER! This can cause P_SpawnMobj to return NULL! // Avoid using MF_RUNSPAWNFUNC on mobjs whose spawn state expects target or tracer to already be set! @@ -11198,22 +9510,17 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype // set subsector and/or block links P_SetPrecipitationThingPosition(mobj); - mobj->floorz = starting_floorz = -#ifdef ESLOPE - mobj->subsector->sector->f_slope ? P_GetZAt(mobj->subsector->sector->f_slope, x, y) : -#endif - mobj->subsector->sector->floorheight; - mobj->ceilingz = -#ifdef ESLOPE - mobj->subsector->sector->c_slope ? P_GetZAt(mobj->subsector->sector->c_slope, x, y) : -#endif - mobj->subsector->sector->ceilingheight; + mobj->floorz = starting_floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y); + mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y); + + mobj->floorrover = NULL; + mobj->ceilingrover = NULL; mobj->z = z; mobj->momz = info->speed; mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker; - P_AddThinker(&mobj->thinker); + P_AddThinker(THINK_PRECIP, &mobj->thinker); CalculatePrecipFloor(mobj); @@ -11240,25 +9547,20 @@ size_t iquehead, iquetail; void P_RemoveMobj(mobj_t *mobj) { I_Assert(mobj != NULL); -#ifdef HAVE_BLUA if (P_MobjWasRemoved(mobj)) return; // something already removing this mobj. mobj->thinker.function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; // shh. no recursing. LUAh_MobjRemoved(mobj); mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; // needed for P_UnsetThingPosition, etc. to work. -#else - I_Assert(!P_MobjWasRemoved(mobj)); -#endif // Rings only, please! if (mobj->spawnpoint && (mobj->type == MT_RING || mobj->type == MT_COIN - || mobj->type == MT_BLUEBALL + || mobj->type == MT_NIGHTSSTAR || mobj->type == MT_REDTEAMRING - || mobj->type == MT_BLUETEAMRING - || P_WeaponOrPanel(mobj->type)) + || mobj->type == MT_BLUETEAMRING) && !(mobj->flags2 & MF2_DONTRESPAWN)) { itemrespawnque[iquehead] = mobj->spawnpoint; @@ -11290,6 +9592,12 @@ void P_RemoveMobj(mobj_t *mobj) if (P_IsKartItem(mobj->type)) P_RemoveKartItem(mobj); + if (mobj->player && mobj->player->followmobj) + { + P_RemoveMobj(mobj->player->followmobj); + P_SetTarget(&mobj->player->followmobj, NULL); + } + mobj->health = 0; // Just because // unlink from sector and block lists @@ -11310,7 +9618,8 @@ void P_RemoveMobj(mobj_t *mobj) // killough 11/98: // // Remove any references to other mobjs. - P_SetTarget(&mobj->target, P_SetTarget(&mobj->tracer, NULL)); + P_SetTarget(&mobj->target, NULL); + P_SetTarget(&mobj->tracer, NULL); // repair hnext chain { @@ -11329,37 +9638,28 @@ void P_RemoveMobj(mobj_t *mobj) } } - // free block // DBG: set everything in mobj_t to 0xFF instead of leaving it. debug memory error. - if (mobj->flags & MF_NOTHINK && !mobj->thinker.next) +#ifdef SCRAMBLE_REMOVED + // Invalidate mobj_t data to cause crashes if accessed! + memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); +#endif + + // free block + if (!mobj->thinker.next) { // Uh-oh, the mobj doesn't think, P_RemoveThinker would never go through! + INT32 prevreferences; if (!mobj->thinker.references) { -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset(mobj, 0xff, sizeof(mobj_t)); -#endif - Z_Free(mobj); // No refrences? Can be removed immediately! :D - } - else - { // Add thinker just to delay removing it until refrences are gone. - mobj->flags &= ~MF_NOTHINK; - P_AddThinker((thinker_t *)mobj); -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); -#endif - P_RemoveThinker((thinker_t *)mobj); + Z_Free(mobj); // No refrrences? Can be removed immediately! :D + return; } + + prevreferences = mobj->thinker.references; + P_AddThinker(THINK_MOBJ, (thinker_t *)mobj); + mobj->thinker.references = prevreferences; } - else - { -#ifdef SCRAMBLE_REMOVED - // Invalidate mobj_t data to cause crashes if accessed! - memset((UINT8 *)mobj + sizeof(thinker_t), 0xff, sizeof(mobj_t) - sizeof(thinker_t)); -#endif - P_RemoveThinker((thinker_t *)mobj); - } + + P_RemoveThinker((thinker_t *)mobj); } // This does not need to be added to Lua. @@ -11406,9 +9706,9 @@ void P_RemoveSavegameMobj(mobj_t *mobj) P_RemoveThinker((thinker_t *)mobj); } -static CV_PossibleValue_t flagtime_cons_t[] = {{0, "MIN"}, {300, "MAX"}, {0, NULL}}; -consvar_t cv_flagtime = {"flagtime", "30", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, flagtime_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_suddendeath = {"suddendeath", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"}, {0, NULL}}; +consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "2", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL); +consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_NETVAR, CV_OnOff, NULL); void P_SpawnPrecipitation(void) { @@ -11419,7 +9719,7 @@ void P_SpawnPrecipitation(void) subsector_t *precipsector = NULL; precipmobj_t *rainmo = NULL; - if (dedicated || /*!cv_precipdensity*/!cv_drawdist_precip.value || curWeather == PRECIP_NONE) // SRB2Kart + if (dedicated || !cv_drawdist_precip.value || curWeather == PRECIP_NONE) // SRB2Kart return; // Use the blockmap to narrow down our placing patterns @@ -11434,7 +9734,7 @@ void P_SpawnPrecipitation(void) x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<>3); - precipsector = R_IsPointInSubsector(x, y); + precipsector = R_PointInSubsectorOrNull(x, y); // No sector? Stop wasting time, // move on to the next entry in the blockmap @@ -11601,15 +9901,15 @@ void P_RespawnBattleBoxes(void) { thinker_t *th; - if (!G_BattleGametype()) + if (!(gametyperules & GTR_BUMPERS)) return; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { mobj_t *box; mobj_t *newmobj; - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // not a mobj + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; box = (mobj_t *)th; @@ -11630,15 +9930,27 @@ void P_RespawnBattleBoxes(void) P_SpawnMobj(newmobj->x, newmobj->y, newmobj->z, MT_EXPLODE); // poof into existance } - // Transfer flags2 (strongbox, objectflip) - newmobj->flags2 = box->flags2; - P_RemoveMobj(box); // make sure they disappear - numgotboxes--; // you've restored a box, remove it from the count - //continue; -- irrelevant? - } + // Transfer flags2 (strongbox, objectflip) + newmobj->flags2 = box->flags2; + P_RemoveMobj(box); // make sure they disappear + numgotboxes--; // you've restored a box, remove it from the count if (numgotboxes < 0) numgotboxes = 0; + } +} + +/** Returns corresponding mobj type from mapthing number. + * \param mthingtype Mapthing number in question. + * \return Mobj type; MT_UNKNOWN if nothing found. + */ +mobjtype_t P_GetMobjtype(UINT16 mthingtype) +{ + mobjtype_t i; + for (i = 0; i < NUMMOBJTYPES; i++) + if (mthingtype == mobjinfo[i].doomednum) + return i; + return MT_UNKNOWN; } // @@ -11648,12 +9960,9 @@ void P_RespawnSpecials(void) { UINT8 p, pcount = 0; tic_t time = 30*TICRATE; // Respawn things in empty dedicated servers - fixed_t x, y, z; - subsector_t *ss; - mobj_t *mo = NULL; mapthing_t *mthing = NULL; - if (G_BattleGametype() && numgotboxes >= (4*nummapboxes/5)) // Battle Mode respawns all boxes in a different way + if (!(gametyperules & GTR_CIRCUIT) && numgotboxes >= (4*nummapboxes/5)) // Battle Mode respawns all boxes in a different way P_RespawnBattleBoxes(); // wait time depends on player count @@ -11698,68 +10007,8 @@ void P_RespawnSpecials(void) #endif if (mthing) - { - mobjtype_t i; - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - ss = R_PointInSubsector(x, y); + P_SpawnMapThing(mthing); - // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; - - if (i == NUMMOBJTYPES) // prevent creation of objects with this type -- Monster Iestyn 17/12/17 - { - // 3D Mode start Thing is unlikely to be added to the que, - // so don't bother checking for that specific type - CONS_Alert(CONS_WARNING, M_GetText("P_RespawnSpecials: Unknown thing type %d attempted to respawn at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - // pull it from the que - iquetail = (iquetail+1)&(ITEMQUESIZE-1); - return; - } - - //CTF rings should continue to respawn as normal rings outside of CTF. - if (gametype != GT_CTF) - { - if (i == MT_REDTEAMRING || i == MT_BLUETEAMRING) - i = MT_RING; - } - - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : -#endif - ss->sector->ceilingheight) - (mthing->options >> ZSHIFT) * FRACUNIT; - if (mthing->options & MTF_AMBUSH - && (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || P_WeaponOrPanel(i))) - z -= 24 * mapobjectscale; - z -= FixedMul(mobjinfo[i].height, mapobjectscale); // Don't forget the height! - } - else - { - z = ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight) + (mthing->options >> ZSHIFT) * FRACUNIT; - if (mthing->options & MTF_AMBUSH - && (i == MT_RING || i == MT_REDTEAMRING || i == MT_BLUETEAMRING || i == MT_COIN || P_WeaponOrPanel(i))) - z += 24 * mapobjectscale; - } - - mo = P_SpawnMobj(x, y, z, i); - mo->spawnpoint = mthing; - mo->angle = ANGLE_45 * (mthing->angle/45); - - if (mthing->options & MTF_OBJECTFLIP) - { - mo->eflags |= MFE_VERTICALFLIP; - mo->flags2 |= MF2_OBJECTFLIP; - } - } // pull it from the que iquetail = (iquetail+1)&(ITEMQUESIZE-1); } @@ -11776,7 +10025,7 @@ void P_SpawnPlayer(INT32 playernum) mobj_t *mobj; if (p->playerstate == PST_REBORN) - G_PlayerReborn(playernum); + G_PlayerReborn(playernum, false); for (i = 0; i < MAXPLAYERS; i++) { @@ -11794,23 +10043,29 @@ void P_SpawnPlayer(INT32 playernum) { ; // Don't mess with spectator values since the demo setup handles them already. } - else if (!G_GametypeHasSpectators()) - { - // We don't have spectators - p->spectator = false; - } else if (p->bot) { - // No point in a spectating bot! - p->spectator = false; + /* + if (bonusgame || specialstage) + { + // Bots should avoid + p->spectator = true; + } + */ + { + // No point in a spectating bot! + p->spectator = false; + } } else if (netgame && p->jointime <= 1 && pcount) { p->spectator = true; - // Oni doesn't want this - /*if (pcount == 1 || leveltime < starttime) + +#if 0 + if (pcount == 1 || leveltime < starttime) p->pflags |= PF_WANTSTOJOIN; - p->jointime = 2;*/ + p->jointime = 2; +#endif } else if (multiplayer && !netgame) { @@ -11836,7 +10091,9 @@ void P_SpawnPlayer(INT32 playernum) SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); } else // Otherwise, never spectator. + { p->spectator = false; + } } if (G_GametypeHasTeams()) @@ -11853,6 +10110,8 @@ void P_SpawnPlayer(INT32 playernum) p->skincolor = skincolor_blueteam; } + p->powers[pw_flashing] = K_GetKartFlashing(p); // Babysitting deterrent + mobj = P_SpawnMobj(0, 0, 0, MT_PLAYER); (mobj->player = p)->mo = mobj; @@ -11865,12 +10124,14 @@ void P_SpawnPlayer(INT32 playernum) // (usefulness: when body mobj is detached from player (who respawns), // the dead body mobj retains the skin through the 'spritedef' override). mobj->skin = &skins[p->skin]; + P_SetupStateAnimation(mobj, mobj->state); - mobj->health = p->health; + mobj->health = 1; p->playerstate = PST_LIVE; p->bonustime = false; p->realtime = leveltime; + p->followitem = skins[p->skin].followitem; //awayview stuff p->awayviewmobj = NULL; @@ -11884,12 +10145,9 @@ void P_SpawnPlayer(INT32 playernum) P_SetScale(mobj, mobj->destscale); P_FlashPal(p, 0, 0); // Resets - // Spawn with a pity shield if necessary. - //P_DoPityCheck(p); - - if (G_BattleGametype()) // SRB2kart + if ((gametyperules & GTR_BUMPERS)) // SRB2kart { - mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + P_GetPlayerHeight(p)+16*FRACUNIT, MT_PLAYERARROW); + mobj_t *overheadarrow = P_SpawnMobj(mobj->x, mobj->y, mobj->z + mobj->height + 16*FRACUNIT, MT_PLAYERARROW); P_SetTarget(&overheadarrow->target, mobj); overheadarrow->drawflags |= MFD_DONTDRAW; P_SetScale(overheadarrow, mobj->destscale); @@ -11940,30 +10198,15 @@ void P_AfterPlayerSpawn(INT32 playernum) mobj_t *mobj = p->mo; UINT8 i; - if (playernum == consoleplayer) - localangle[0] = mobj->angle; - else if (r_splitscreen) - { - for (i = 1; i <= r_splitscreen; i++) - { - if (playernum == displayplayers[i]) - { - localangle[i] = mobj->angle; - break; - } - } - } + P_SetPlayerAngle(p, mobj->angle); - p->viewheight = 32<viewheight = P_GetPlayerViewHeight(p); if (p->mo->eflags & MFE_VERTICALFLIP) p->viewz = p->mo->z + p->mo->height - p->viewheight; else p->viewz = p->mo->z + p->viewheight; - P_SetPlayerMobjState(p->mo, S_KART_STILL1); // SRB2kart - was S_PLAY_STND - p->pflags &= ~PF_SPINNING; - if (playernum == consoleplayer) { // wake up the status bar @@ -11972,7 +10215,7 @@ void P_AfterPlayerSpawn(INT32 playernum) HU_Start(); } - SV_SpawnPlayer(playernum, mobj->x, mobj->y, mobj->angle); + p->drawangle = mobj->angle; for (i = 0; i <= r_splitscreen; i++) { @@ -11995,7 +10238,7 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) fixed_t z; sector_t *sector; - fixed_t floor, ceiling; + fixed_t floor, ceiling, ceilingspawn; player_t *p = &players[playernum]; mobj_t *mobj = p->mo; @@ -12005,59 +10248,47 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) { x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; - angle = FixedAngle(mthing->angle*FRACUNIT); + angle = FixedAngle(mthing->angle<sector; - floor = -#ifdef ESLOPE - sector->f_slope ? P_GetZAt(sector->f_slope, x, y) : -#endif - sector->floorheight; - ceiling = -#ifdef ESLOPE - sector->c_slope ? P_GetZAt(sector->c_slope, x, y) : -#endif - sector->ceilingheight; + floor = P_GetSectorFloorZAt (sector, x, y); + ceiling = P_GetSectorCeilingZAt(sector, x, y); + ceilingspawn = ceiling - mobjinfo[MT_PLAYER].height; if (mthing) { + fixed_t offset = mthing->z << FRACBITS; + + if (p->respawn.state != RESPAWNST_NONE) + offset += K_RespawnOffset(p, (mthing->options & MTF_OBJECTFLIP)); + // Flagging a player's ambush will make them start on the ceiling // Objectflip inverts if (!!(mthing->options & MTF_AMBUSH) ^ !!(mthing->options & MTF_OBJECTFLIP)) - { - z = ceiling - mobjinfo[MT_PLAYER].height; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); - } + z = ceilingspawn - offset; else - { - z = floor; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - } + z = floor + offset; if (mthing->options & MTF_OBJECTFLIP) // flip the player! { mobj->eflags |= MFE_VERTICALFLIP; mobj->flags2 |= MF2_OBJECTFLIP; } + + if (mthing->options & MTF_AMBUSH) + P_SetPlayerMobjState(mobj, S_KART_SPINOUT); } else z = floor; - if (p->respawn.state != RESPAWNST_NONE) - { - z += K_RespawnOffset(p, (mthing->options & MTF_OBJECTFLIP)); - } - if (z < floor) z = floor; - else if (z > ceiling - mobjinfo[MT_PLAYER].height) - z = ceiling - mobjinfo[MT_PLAYER].height; + else if (z > ceilingspawn) + z = ceilingspawn; mobj->floorz = floor; mobj->ceilingz = ceiling; @@ -12068,7 +10299,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing) P_SetThingPosition(mobj); mobj->z = z; - if (mobj->z == mobj->floorz) + if (mobj->flags2 & MF2_OBJECTFLIP) + { + if (mobj->z + mobj->height == mobj->ceilingz) + mobj->eflags |= MFE_ONGROUND; + } + else if (mobj->z == mobj->floorz) mobj->eflags |= MFE_ONGROUND; mobj->angle = angle; @@ -12094,74 +10330,111 @@ void P_MovePlayerToStarpost(INT32 playernum) P_SetThingPosition(mobj); sector = R_PointInSubsector(mobj->x, mobj->y)->sector; - floor = -#ifdef ESLOPE - sector->f_slope ? P_GetZAt(sector->f_slope, mobj->x, mobj->y) : -#endif - sector->floorheight; - ceiling = -#ifdef ESLOPE - sector->c_slope ? P_GetZAt(sector->c_slope, mobj->x, mobj->y) : -#endif - sector->ceilingheight; + floor = P_GetSectorFloorZAt (sector, mobj->x, mobj->y); + ceiling = P_GetSectorCeilingZAt(sector, mobj->x, mobj->y); z = p->respawn.pointz; - if (z < floor) + if (z <= floor) + { + mobj->eflags |= MFE_ONGROUND; z = floor; - else if (z > ceiling - mobjinfo[MT_PLAYER].height) - z = ceiling - mobjinfo[MT_PLAYER].height; + } mobj->floorz = floor; mobj->ceilingz = ceiling; mobj->z = z; - if (mobj->z == mobj->floorz) - mobj->eflags |= MFE_ONGROUND; + + // Correct angle + if (p->respawn.wp != NULL) + { + size_t nwp = K_NextRespawnWaypointIndex(p->respawn.wp); + waypoint_t *wp; + + if (nwp != SIZE_MAX) + { + wp = p->respawn.wp->nextwaypoints[nwp]; + + mobj->angle = p->drawangle = R_PointToAngle2( + mobj->x, mobj->y, + wp->mobj->x, wp->mobj->y + ); + } + } P_AfterPlayerSpawn(playernum); } -#define MAXHUNTEMERALDS 64 -mapthing_t *huntemeralds[MAXHUNTEMERALDS]; -INT32 numhuntemeralds; - -// -// P_SpawnMapThing -// The fields of the mapthing should -// already be in host byte order. -// -void P_SpawnMapThing(mapthing_t *mthing) +fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale) { - mobjtype_t i; - mobj_t *mobj; - fixed_t x, y, z; - subsector_t *ss; + const subsector_t *ss = R_PointInSubsector(x, y); - if (!mthing->type) - return; // Ignore type-0 things as NOPs + // Axis objects snap to the floor. + if (mobjtype == MT_AXIS || mobjtype == MT_AXISTRANSFER || mobjtype == MT_AXISTRANSFERLINE) + return ONFLOORZ; - // Always spawn in objectplace. - // Skip all returning code. - if (objectplacing) + // Establish height. + if (flip) + return P_GetSectorCeilingZAt(ss->sector, x, y) - dz - FixedMul(scale, offset + mobjinfo[mobjtype].height); + else + return P_GetSectorFloorZAt(ss->sector, x, y) + dz + FixedMul(scale, offset); +} + +fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y) +{ + fixed_t dz = mthing->z << FRACBITS; // Base offset from the floor. + fixed_t offset = 0; // Specific scaling object offset. + boolean flip = (!!(mobjinfo[mobjtype].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); + + switch (mobjtype) { - // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; + // Objects with a non-zero default height. + // (None yet) - if (i == NUMMOBJTYPES) - { - if (mthing->type == 3328) // 3D Mode start Thing - return; - CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - i = MT_UNKNOWN; - } - goto noreturns; + // Horizontal springs, may float additional units with MTF_AMBUSH. + case MT_YELLOWHORIZ: + case MT_REDHORIZ: + case MT_BLUEHORIZ: + offset += mthing->options & MTF_AMBUSH ? 16*mapobjectscale : 0; + break; + + // Ring-like items, may float additional units with MTF_AMBUSH. + case MT_SPIKEBALL: + case MT_EMBLEM: + case MT_RING: + offset += mthing->options & MTF_AMBUSH ? 24*mapobjectscale : 0; + break; + + // This object does not have an offset + default: + break; } - // count deathmatch start positions - if (mthing->type == 33) + if (!(dz + offset)) // Snap to the surfaces when there's no offset set. + { + if (flip) + return ONCEILINGZ; + else + return ONFLOORZ; + } + + return P_GetMobjSpawnHeight(mobjtype, x, y, dz, offset, flip, mthing->scale); +} + +static boolean P_SpawnNonMobjMapThing(mapthing_t *mthing) +{ +#if MAXPLAYERS > 32 + You should think about modifying the deathmatch starts to take full advantage of this! +#endif + if (mthing->type <= MAXPLAYERS) // Player starts + { + // save spots for respawning in network games + if (!metalrecording) + playerstarts[mthing->type - 1] = mthing; + return true; + } + else if (mthing->type == 33) // Match starts { if (numdmstarts < MAX_DM_STARTS) { @@ -12169,10 +10442,9 @@ void P_SpawnMapThing(mapthing_t *mthing) mthing->type = 0; numdmstarts++; } - return; + return true; } - - else if (mthing->type == 34) // Red CTF Starts + else if (mthing->type == 34) // Red CTF starts { if (numredctfstarts < MAXPLAYERS) { @@ -12180,10 +10452,9 @@ void P_SpawnMapThing(mapthing_t *mthing) mthing->type = 0; numredctfstarts++; } - return; + return true; } - - else if (mthing->type == 35) // Blue CTF Starts + else if (mthing->type == 35) // Blue CTF starts { if (numbluectfstarts < MAXPLAYERS) { @@ -12191,321 +10462,570 @@ void P_SpawnMapThing(mapthing_t *mthing) mthing->type = 0; numbluectfstarts++; } - return; + return true; } - - else if (mthing->type == 750) // Slope vertex point (formerly chaos spawn) - return; - - else if (mthing->type == 300 // Ring - || mthing->type == 308 || mthing->type == 309 // Team Rings - || mthing->type == 1706 // Nights Wing - || (mthing->type >= 600 && mthing->type <= 609) // Placement patterns - || mthing->type == 1705 || mthing->type == 1713 // NiGHTS Hoops - || mthing->type == 1800) // Mario Coin - { - // Don't spawn hoops, wings, or rings yet! - return; - } - - // check for players specially - if (mthing->type > 0 && mthing->type <= 32) - { - // save spots for respawning in network games - if (!metalrecording) - playerstarts[mthing->type-1] = mthing; - return; - } - - if (metalrecording && mthing->type == mobjinfo[MT_METALSONIC_RACE].doomednum) + else if (metalrecording && mthing->type == mobjinfo[MT_METALSONIC_RACE].doomednum) { // If recording, you ARE Metal Sonic. Do not spawn it, do not save normal spawnpoints. playerstarts[0] = mthing; - return; + return true; + } + else if (mthing->type == 750 // Slope vertex point (formerly chaos spawn) + || (mthing->type == 777 || mthing->type == 778) // Slope anchors + || (mthing->type >= 600 && mthing->type <= 609) // Special placement patterns + || mthing->type == 1705 || mthing->type == 1713) // Hoops + { + return true; // These are handled elsewhere. } - // find which type to spawn - for (i = 0; i < NUMMOBJTYPES; i++) - if (mthing->type == mobjinfo[i].doomednum) - break; + return false; +} - if (i == NUMMOBJTYPES) +static boolean P_AllowMobjSpawn(mapthing_t* mthing, mobjtype_t i) +{ + (void)mthing; + + switch (i) { - if (mthing->type == 3328) // 3D Mode start Thing - return; - CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); - i = MT_UNKNOWN; + case MT_EMBLEM: + if (netgame || multiplayer) + return false; // Single player only + + if (modifiedgame && !savemoddata) + return false; // No cheating!! + + break; + default: + break; } if (metalrecording) // Metal Sonic can't use these things. - if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS) || i == MT_EMMY || i == MT_STARPOST) - return; - - if (i >= MT_EMERALD1 && i <= MT_EMERALD7) // Pickupable Emeralds { - if (gametype != GT_COOP) // Don't place emeralds in non-coop modes - return; - - if (metalrecording) - return; // Metal Sonic isn't for collecting emeralds. - - if (emeralds & mobjinfo[i].speed) // You already have this emerald! - return; + if (mobjinfo[i].flags & (MF_ENEMY|MF_BOSS)) + return false; } - if (!G_BattleGametype() || !cv_specialrings.value) - if (P_WeaponOrPanel(i)) - return; // Don't place weapons/panels in non-ringslinger modes + return true; +} - if (i == MT_EMERHUNT) +static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) +{ + // Don't need this for Kart YET! + (void)mthing; + return i; +} + +static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) +{ + INT32 j; + emblem_t* emblem = M_GetLevelEmblems(gamemap); + skincolornum_t emcolor; + + while (emblem) { - // Emerald Hunt is Coop only. - if (gametype != GT_COOP) - return; + if (emblem->type == ET_GLOBAL && emblem->tag == mthing->angle) + break; - ss = R_PointInSubsector(mthing->x << FRACBITS, mthing->y << FRACBITS); - mthing->z = (INT16)((( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, mthing->x << FRACBITS, mthing->y << FRACBITS) : -#endif - ss->sector->floorheight)>>FRACBITS) + (mthing->options >> ZSHIFT)); - - if (numhuntemeralds < MAXHUNTEMERALDS) - huntemeralds[numhuntemeralds++] = mthing; - return; + emblem = M_GetLevelEmblems(-1); } - if (i == MT_EMERALDSPAWN) + if (!emblem) { - if (!cv_powerstones.value) - return; - - if (!G_BattleGametype()) - return; - - runemeraldmanager = true; + CONS_Debug(DBG_GAMELOGIC, "No map emblem for map %d with tag %d found!\n", gamemap, mthing->angle); + return false; } - if (!G_RaceGametype()) // No enemies in match or CTF modes - if ((mobjinfo[i].flags & MF_ENEMY) || (mobjinfo[i].flags & MF_BOSS)) - return; + j = emblem - emblemlocations; - // Set powerup boxes to user settings for competition. - if (gametype == GT_COMPETITION) + I_Assert(emblemlocations[j].sprite >= 'A' && emblemlocations[j].sprite <= 'Z'); + P_SetMobjState(mobj, mobj->info->spawnstate + (emblemlocations[j].sprite - 'A')); + + mobj->health = j + 1; + emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting + mobj->color = (UINT16)emcolor; + + if (emblemlocations[j].collected) { - if ((mobjinfo[i].flags & MF_MONITOR) && cv_competitionboxes.value) // not Normal + P_UnsetThingPosition(mobj); + mobj->flags |= MF_NOCLIP; + mobj->flags &= ~MF_SPECIAL; + mobj->flags |= MF_NOBLOCKMAP; + mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); + P_SetThingPosition(mobj); + } + else + { + mobj->frame &= ~FF_TRANSMASK; + + if (emblemlocations[j].type == ET_GLOBAL) { - if (cv_competitionboxes.value == 1) // Random - i = MT_QUESTIONBOX; - else if (cv_competitionboxes.value == 2) // Teleports - i = MT_MIXUPBOX; - else if (cv_competitionboxes.value == 3) // None - return; // Don't spawn! + mobj->reactiontime = emblemlocations[j].var; } } + return true; +} - // Set powerup boxes to user settings for other netplay modes - else if (gametype != GT_COOP) +static boolean P_SetupMace(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) +{ + fixed_t mlength, mmaxlength, mlengthset, mspeed, mphase, myaw, mpitch, mminlength, mnumspokes, mpinch, mroll, mnumnospokes, mwidth, mwidthset, mmin, msound, radiusfactor, widthfactor; + angle_t mspokeangle; + mobjtype_t chainlink, macetype, firsttype, linktype; + boolean mdosound, mdocenter, mchainlike = false; + mobj_t *spawnee = NULL, *hprev = mobj; + mobjflag_t mflagsapply; + mobjflag2_t mflags2apply; + mobjeflag_t meflagsapply; + INT32 line; + const size_t mthingi = (size_t)(mthing - mapthings); + + // Find the corresponding linedef special, using angle as tag + // P_FindSpecialLineFromTag works here now =D + line = P_FindSpecialLineFromTag(9, mthing->angle, -1); + + if (line == -1) { - if ((mobjinfo[i].flags & MF_MONITOR) && cv_matchboxes.value) // not Normal + CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs to be tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); + return false; + } + /* + mapthing - + MTF_AMBUSH : + MT_SPRINGBALLPOINT - upgrade from yellow to red spring + anything else - bigger mace/chain theory + MTF_OBJECTSPECIAL - force silent + MTF_GRAVFLIP - flips objects, doesn't affect chain arrangements + Parameter value : number of "spokes" + + linedef - + ML_NOCLIMB : + MT_CHAINPOINT/MT_CHAINMACEPOINT with ML_EFFECT1 applied - Direction not controllable + anything else - no functionality + ML_EFFECT1 : Swings instead of spins + ML_EFFECT2 : Linktype is replaced with macetype for all spokes not ending in chains (inverted for MT_FIREBARPOINT) + ML_EFFECT3 : Spawn a bonus linktype at the hinge point + ML_EFFECT4 : Don't clip inside the ground + ML_EFFECT5 : Don't stop thinking when too far away + */ + mlength = abs(lines[line].dx >> FRACBITS); + mspeed = abs(lines[line].dy >> (FRACBITS - 4)); + mphase = (sides[lines[line].sidenum[0]].textureoffset >> FRACBITS) % 360; + if ((mminlength = -sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) < 0) + mminlength = 0; + else if (mminlength > mlength - 1) + mminlength = mlength - 1; + mpitch = (lines[line].frontsector->floorheight >> FRACBITS) % 360; + myaw = (lines[line].frontsector->ceilingheight >> FRACBITS) % 360; + + mnumspokes = mthing->extrainfo + 1; + mspokeangle = FixedAngle((360*FRACUNIT)/mnumspokes) >> ANGLETOFINESHIFT; + + if (lines[line].backsector) + { + mpinch = (lines[line].backsector->floorheight >> FRACBITS) % 360; + mroll = (lines[line].backsector->ceilingheight >> FRACBITS) % 360; + mnumnospokes = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS); + if ((mwidth = sides[lines[line].sidenum[1]].rowoffset >> FRACBITS) < 0) + mwidth = 0; + } + else + mpinch = mroll = mnumnospokes = mwidth = 0; + + CONS_Debug(DBG_GAMELOGIC, "Mace/Chain (mapthing #%s):\n" + "Length is %d (minus %d)\n" + "Speed is %d\n" + "Phase is %d\n" + "Yaw is %d\n" + "Pitch is %d\n" + "No. of spokes is %d (%d antispokes)\n" + "Pinch is %d\n" + "Roll is %d\n" + "Width is %d\n", + sizeu1(mthingi), mlength, mminlength, mspeed, mphase, myaw, mpitch, mnumspokes, mnumnospokes, mpinch, mroll, mwidth); + + if (mnumnospokes > 0 && (mnumnospokes < mnumspokes)) + mnumnospokes = mnumspokes/mnumnospokes; + else + mnumnospokes = ((mobj->type == MT_CHAINMACEPOINT) ? (mnumspokes) : 0); + + mobj->lastlook = mspeed; + mobj->movecount = mobj->lastlook; + mobj->angle = FixedAngle(myaw << FRACBITS); + *doangle = false; + mobj->threshold = (FixedAngle(mpitch << FRACBITS) >> ANGLETOFINESHIFT); + mobj->movefactor = mpinch; + mobj->movedir = 0; + + // Mobjtype selection + switch (mobj->type) + { + case MT_SPRINGBALLPOINT: + macetype = ((mthing->options & MTF_AMBUSH) + ? MT_REDSPRINGBALL + : MT_YELLOWSPRINGBALL); + chainlink = MT_SMALLMACECHAIN; + break; + case MT_FIREBARPOINT: + macetype = ((mthing->options & MTF_AMBUSH) + ? MT_BIGFIREBAR + : MT_SMALLFIREBAR); + chainlink = MT_NULL; + break; + case MT_CUSTOMMACEPOINT: + macetype = (mobjtype_t)sides[lines[line].sidenum[0]].toptexture; + if (lines[line].backsector) + chainlink = (mobjtype_t)sides[lines[line].sidenum[1]].toptexture; + else + chainlink = MT_NULL; + break; + case MT_CHAINPOINT: + if (mthing->options & MTF_AMBUSH) { - if (cv_matchboxes.value == 1) // Random - i = MT_QUESTIONBOX; - else if (cv_matchboxes.value == 3) // Don't spawn - return; - else // cv_matchboxes.value == 2, Non-Random + macetype = MT_BIGGRABCHAIN; + chainlink = MT_BIGMACECHAIN; + } + else + { + macetype = MT_SMALLGRABCHAIN; + chainlink = MT_SMALLMACECHAIN; + } + mchainlike = true; + break; + default: + if (mthing->options & MTF_AMBUSH) + { + macetype = MT_BIGMACE; + chainlink = MT_BIGMACECHAIN; + } + else + { + macetype = MT_SMALLMACE; + chainlink = MT_SMALLMACECHAIN; + } + break; + } + + if (!macetype && !chainlink) + return true; + + if (mobj->type == MT_CHAINPOINT) + { + if (!mlength) + return true; + } + else + mlength++; + + firsttype = macetype; + + // Adjustable direction + if (lines[line].flags & ML_NOCLIMB) + mobj->flags |= MF_SLIDEME; + + // Swinging + if (lines[line].flags & ML_EFFECT1) + { + mobj->flags2 |= MF2_STRONGBOX; + mmin = ((mnumnospokes > 1) ? 1 : 0); + } + else + mmin = mnumspokes; + + // If over distance away, don't move UNLESS this flag is applied + if (lines[line].flags & ML_EFFECT5) + mobj->flags2 |= MF2_BOSSNOTRAP; + + // Make the links the same type as the end - repeated below + if ((mobj->type != MT_CHAINPOINT) && (((lines[line].flags & ML_EFFECT2) == ML_EFFECT2) != (mobj->type == MT_FIREBARPOINT))) // exclusive or + { + linktype = macetype; + radiusfactor = 2; // Double the radius. + } + else + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); + + if (!mchainlike) + mchainlike = (firsttype == chainlink); + widthfactor = (mchainlike ? 1 : 2); + + mflagsapply = ((lines[line].flags & ML_EFFECT4) ? 0 : (MF_NOCLIP | MF_NOCLIPHEIGHT)); + mflags2apply = ((mthing->options & MTF_OBJECTFLIP) ? MF2_OBJECTFLIP : 0); + meflagsapply = ((mthing->options & MTF_OBJECTFLIP) ? MFE_VERTICALFLIP : 0); + + msound = (mchainlike ? 0 : (mwidth & 1)); + + // Quick and easy preparatory variable setting + mphase = (FixedAngle(mphase << FRACBITS) >> ANGLETOFINESHIFT); + mroll = (FixedAngle(mroll << FRACBITS) >> ANGLETOFINESHIFT); + +#define makemace(mobjtype, dist, moreflags2) {\ + spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobjtype);\ + P_SetTarget(&spawnee->tracer, mobj);\ + spawnee->threshold = mphase;\ + spawnee->friction = mroll;\ + spawnee->movefactor = mwidthset;\ + spawnee->movecount = dist;\ + spawnee->angle = myaw;\ + spawnee->flags |= (MF_NOGRAVITY|mflagsapply);\ + spawnee->flags2 |= (mflags2apply|moreflags2);\ + spawnee->eflags |= meflagsapply;\ + P_SetTarget(&hprev->hnext, spawnee);\ + P_SetTarget(&spawnee->hprev, hprev);\ + hprev = spawnee;\ +} + + mdosound = (mspeed && !(mthing->options & MTF_OBJECTSPECIAL)); + mdocenter = (macetype && (lines[line].flags & ML_EFFECT3)); + + // The actual spawning of spokes + while (mnumspokes-- > 0) + { + // Offsets + if (lines[line].flags & ML_EFFECT1) // Swinging + mroll = (mroll - mspokeangle) & FINEMASK; + else // Spinning + mphase = (mphase - mspokeangle) & FINEMASK; + + if (mnumnospokes && !(mnumspokes % mnumnospokes)) // Skipping a "missing" spoke + { + if (mobj->type != MT_CHAINMACEPOINT) + continue; + + linktype = chainlink; + firsttype = ((mthing->options & MTF_AMBUSH) ? MT_BIGGRABCHAIN : MT_SMALLGRABCHAIN); + mmaxlength = 1 + (mlength - 1) * radiusfactor; + radiusfactor = widthfactor = 1; + } + else + { + if (mobj->type == MT_CHAINMACEPOINT) { - if (i == MT_QUESTIONBOX) - return; // don't spawn in Non-Random + // Make the links the same type as the end - repeated above + if (lines[line].flags & ML_EFFECT2) + { + linktype = macetype; + radiusfactor = 2; + } + else + radiusfactor = (((linktype = chainlink) == MT_NULL) ? 2 : 1); - mthing->options &= ~(MTF_AMBUSH|MTF_OBJECTSPECIAL); // no random respawning! + firsttype = macetype; + widthfactor = 2; } + + mmaxlength = mlength; + } + + mwidthset = mwidth; + mlengthset = mminlength; + + if (mdocenter) // Innermost link + makemace(linktype, 0, 0); + + // Out from the center... + if (linktype) + { + while ((++mlengthset) < mmaxlength) + makemace(linktype, radiusfactor*mlengthset, 0); + } + else + mlengthset = mmaxlength; + + // Outermost mace/link + if (firsttype) + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + + if (!mwidth) + { + if (mdosound && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; + } + else + { + // Across the bar! + if (!firsttype) + mwidthset = -mwidth; + else if (mwidth > 0) + { + while ((mwidthset -= widthfactor) > -mwidth) + { + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; + } + } + else + { + while ((mwidthset += widthfactor) < -mwidth) + { + makemace(firsttype, radiusfactor*mlengthset, MF2_AMBUSH); + if (mdosound && (mwidthset == msound) && mnumspokes <= mmin) // Can it make a sound? + spawnee->flags2 |= MF2_BOSSNOTRAP; + } + } + mwidth = -mwidth; + + // Outermost mace/link again! + if (firsttype) + makemace(firsttype, radiusfactor*(mlengthset--), MF2_AMBUSH); + + // ...and then back into the center! + if (linktype) + while (mlengthset > mminlength) + makemace(linktype, radiusfactor*(mlengthset--), 0); + + if (mdocenter) // Innermost link + makemace(linktype, 0, 0); } } +#undef makemace + return true; +} - if (gametype != GT_CTF) // CTF specific things +static boolean P_SetupParticleGen(mapthing_t *mthing, mobj_t *mobj) +{ + fixed_t radius, speed; + INT32 type, numdivisions, anglespeed, ticcount; + angle_t angledivision; + INT32 line; + const size_t mthingi = (size_t)(mthing - mapthings); + + // Find the corresponding linedef special, using angle as tag + line = P_FindSpecialLineFromTag(15, mthing->angle, -1); + + if (line == -1) { - if (i == MT_BLUETEAMRING || i == MT_REDTEAMRING) - i = MT_RING; - else if (i == MT_BLUERINGBOX || i == MT_REDRINGBOX) - i = MT_SUPERRINGBOX; - else if (i == MT_BLUEFLAG || i == MT_REDFLAG) - return; // No flags in non-CTF modes! + CONS_Debug(DBG_GAMELOGIC, "Particle generator (mapthing #%s) needs to be tagged to a #15 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); + return false; + } + + if (sides[lines[line].sidenum[0]].toptexture) + type = sides[lines[line].sidenum[0]].toptexture; // Set as object type in p_setup.c... + else + type = (INT32)MT_PARTICLE; + + if (!lines[line].backsector + || (ticcount = (sides[lines[line].sidenum[1]].textureoffset >> FRACBITS)) < 1) + ticcount = 3; + + numdivisions = mthing->z; + + if (numdivisions) + { + radius = R_PointToDist2(lines[line].v1->x, lines[line].v1->y, lines[line].v2->x, lines[line].v2->y); + anglespeed = (sides[lines[line].sidenum[0]].rowoffset >> FRACBITS) % 360; + angledivision = 360/numdivisions; } else { - if ((i == MT_BLUEFLAG && blueflag) || (i == MT_REDFLAG && redflag)) - { - CONS_Alert(CONS_ERROR, M_GetText("Only one flag per team allowed in CTF!\n")); - return; - } + numdivisions = 1; // Simple trick to make A_ParticleSpawn simpler. + radius = 0; + anglespeed = 0; + angledivision = 0; } - if (!G_RaceGametype() && (i == MT_SIGN || i == MT_STARPOST)) - return; // Don't spawn exit signs or starposts in wrong game modes + speed = abs(sides[lines[line].sidenum[0]].textureoffset); + if (mthing->options & MTF_OBJECTFLIP) + speed *= -1; - if (modeattacking) // Record Attack special stuff + CONS_Debug(DBG_GAMELOGIC, "Particle Generator (mapthing #%s):\n" + "Radius is %d\n" + "Speed is %d\n" + "Anglespeed is %d\n" + "Numdivisions is %d\n" + "Angledivision is %d\n" + "Type is %d\n" + "Tic seperation is %d\n", + sizeu1(mthingi), radius, speed, anglespeed, numdivisions, angledivision, type, ticcount); + + mobj->angle = 0; + mobj->movefactor = speed; + mobj->lastlook = numdivisions; + mobj->movedir = angledivision*ANG1; + mobj->movecount = anglespeed*ANG1; + mobj->friction = radius; + mobj->threshold = type; + mobj->reactiontime = ticcount; + mobj->cvmem = line; + mobj->watertop = mobj->waterbottom = 0; + return true; +} + +static boolean P_SetupBooster(mapthing_t* mthing, mobj_t* mobj, boolean strong) +{ + angle_t angle = FixedAngle(mthing->angle << FRACBITS); + fixed_t x1 = FINECOSINE((angle >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t y1 = FINESINE((angle >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t x2 = FINECOSINE(((angle + ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); + fixed_t y2 = FINESINE(((angle + ANGLE_90) >> ANGLETOFINESHIFT) & FINEMASK); + statenum_t facestate = strong ? S_REDBOOSTERSEG_FACE : S_YELLOWBOOSTERSEG_FACE; + statenum_t leftstate = strong ? S_REDBOOSTERSEG_LEFT : S_YELLOWBOOSTERSEG_LEFT; + statenum_t rightstate = strong ? S_REDBOOSTERSEG_RIGHT : S_YELLOWBOOSTERSEG_RIGHT; + statenum_t rollerstate = strong ? S_REDBOOSTERROLLER : S_YELLOWBOOSTERROLLER; + + mobj_t *seg = P_SpawnMobjFromMobj(mobj, 26*x1, 26*y1, 0, MT_BOOSTERSEG); + seg->angle = angle - ANGLE_90; + P_SetMobjState(seg, facestate); + seg = P_SpawnMobjFromMobj(mobj, -26*x1, -26*y1, 0, MT_BOOSTERSEG); + seg->angle = angle + ANGLE_90; + P_SetMobjState(seg, facestate); + seg = P_SpawnMobjFromMobj(mobj, 21*x2, 21*y2, 0, MT_BOOSTERSEG); + seg->angle = angle; + P_SetMobjState(seg, leftstate); + seg = P_SpawnMobjFromMobj(mobj, -21*x2, -21*y2, 0, MT_BOOSTERSEG); + seg->angle = angle; + P_SetMobjState(seg, rightstate); + + seg = P_SpawnMobjFromMobj(mobj, 13*(x1 + x2), 13*(y1 + y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, 13*(x1 - x2), 13*(y1 - y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, -13*(x1 + x2), -13*(y1 + y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + seg = P_SpawnMobjFromMobj(mobj, -13*(x1 - x2), -13*(y1 - y2), 0, MT_BOOSTERROLLER); + seg->angle = angle; + P_SetMobjState(seg, rollerstate); + + return true; +} + +static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean *doangle) +{ + boolean override = LUAh_MapThingSpawn(mobj, mthing); + + if (P_MobjWasRemoved(mobj)) + return false; + + if (override) + return true; + + switch (mobj->type) { - // Emerald Tokens -->> Score Tokens - if (i == MT_EMMY) - return; /// \todo - - // 1UPs -->> Score TVs - else if (i == MT_PRUP) // 1UP - { - // Either or, doesn't matter which. - if (mthing->options & (MTF_AMBUSH|MTF_OBJECTSPECIAL)) - i = MT_SCORETVLARGE; // 10,000 - else - i = MT_SCORETVSMALL; // 1,000 - } + case MT_EMBLEM: + { + if (!P_SetupEmblem(mthing, mobj)) + return false; + break; } - - if (ultimatemode) - { - if (i == MT_PITYTV || i == MT_GREENTV || i == MT_YELLOWTV || i == MT_BLUETV || i == MT_BLACKTV || i == MT_WHITETV) - return; // No shields in Ultimate mode - - if (i == MT_SUPERRINGBOX && !G_IsSpecialStage(gamemap)) - return; // No rings in Ultimate mode (except special stages) - } - - if (i == MT_EMMY && (gametype != GT_COOP || ultimatemode || tokenbits == 30 || tokenlist & (1 << tokenbits++))) - return; // you already got this token, or there are too many, or the gametype's not right - - // Objectplace landing point - noreturns: - - // spawn it - x = mthing->x << FRACBITS; - y = mthing->y << FRACBITS; - ss = R_PointInSubsector(x, y); - - if (i == MT_NIGHTSBUMPER) - z = ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight) + ((mthing->options >> ZSHIFT) << FRACBITS); - else if (i == MT_AXIS || i == MT_AXISTRANSFER || i == MT_AXISTRANSFERLINE) - z = ONFLOORZ; - else if (i == MT_SPECIALSPIKEBALL || P_WeaponOrPanel(i) || i == MT_EMERALDSPAWN || i == MT_EMMY) - { - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : -#endif - ss->sector->ceilingheight); - - if (mthing->options & MTF_AMBUSH) // Special flag for rings - z -= 24*FRACUNIT; - if (mthing->options >> ZSHIFT) - z -= (mthing->options >> ZSHIFT)*FRACUNIT; - - z -= mobjinfo[i].height; //Don't forget the height! - } - else - { - z = ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight); - - if (mthing->options & MTF_AMBUSH) // Special flag for rings - z += 24*FRACUNIT; - if (mthing->options >> ZSHIFT) - z += (mthing->options >> ZSHIFT)*FRACUNIT; - } - - if (z == ONFLOORZ) - mthing->z = 0; - else - mthing->z = (INT16)(z>>FRACBITS); - } - else if (i == MT_WAYPOINT) - { - // just gets set on either the floor or ceiling - boolean flip = (!!(mobjinfo[i].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); - - // applying offsets! (if any) - if (flip) - { - z = ONCEILINGZ; - } - else - { - z = ONFLOORZ; - } - - if (z == ONFLOORZ) - mthing->z = 0; - else - mthing->z = (INT16)(z>>FRACBITS); - } - else - { - fixed_t offset = 0; - boolean flip = (!!(mobjinfo[i].flags & MF_SPAWNCEILING) ^ !!(mthing->options & MTF_OBJECTFLIP)); - - // base positions - if (flip) - z = ( -#ifdef ESLOPE - ss->sector->c_slope ? P_GetZAt(ss->sector->c_slope, x, y) : -#endif - ss->sector->ceilingheight) - mobjinfo[i].height; - else - z = ( -#ifdef ESLOPE - ss->sector->f_slope ? P_GetZAt(ss->sector->f_slope, x, y) : -#endif - ss->sector->floorheight); - - // offsetting - if (mthing->options >> ZSHIFT) - offset = ((mthing->options >> ZSHIFT) << FRACBITS); - else if (i == MT_CRAWLACOMMANDER || i == MT_DETON || i == MT_JETTBOMBER || i == MT_JETTGUNNER || i == MT_EGGMOBILE2) - offset = 33*FRACUNIT; - else if (i == MT_EGGMOBILE) - offset = 128*FRACUNIT; - else if (i == MT_GOLDBUZZ || i == MT_REDBUZZ) - offset = 288*FRACUNIT; - - // applying offsets! (if any) - if (flip) - { - if (offset) - z -= offset; - else - z = ONCEILINGZ; - } - else - { - if (offset) - z += offset; - else - z = ONFLOORZ; - } - - if (z == ONFLOORZ) - mthing->z = 0; - else - mthing->z = (INT16)(z>>FRACBITS); - } - - mobj = P_SpawnMobj(x, y, z, i); - mobj->spawnpoint = mthing; - - switch(mobj->type) - { case MT_SKYBOX: - mobj->angle = 0; + if (mthing->tag < 0 || mthing->tag > 15) + { + CONS_Debug(DBG_GAMELOGIC, "P_SetupSpawnedMapThing: Skybox ID %d of mapthing %s is not between 0 and 15!\n", mthing->tag, sizeu1((size_t)(mthing - mapthings))); + break; + } + if (mthing->options & MTF_OBJECTSPECIAL) - skyboxmo[1] = mobj; + skyboxcenterpnts[mthing->tag] = mobj; else - skyboxmo[0] = mobj; + skyboxviewpnts[mthing->tag] = mobj; + break; + case MT_EGGSTATUE: + if (mthing->options & MTF_EXTRA) + { + mobj->color = SKINCOLOR_GOLD; + mobj->colorized = true; + } break; case MT_FAN: if (mthing->options & MTF_OBJECTSPECIAL) @@ -12522,13 +11042,62 @@ void P_SpawnMapThing(mapthing_t *mthing) if (mthing->angle) mobj->health = mthing->angle; else - mobj->health = FixedMul(ss->sector->ceilingheight-ss->sector->floorheight, 3*(FRACUNIT/4))>>FRACBITS; + mobj->health = FixedMul(mobj->subsector->sector->ceilingheight - mobj->subsector->sector->floorheight, 3*(FRACUNIT/4)) >> FRACBITS; + break; + case MT_BALLOON: + if (mthing->angle > 0) + mobj->color = ((mthing->angle - 1) % (numskincolors - 1)) + 1; + break; +#define makesoftwarecorona(mo, h) \ + corona = P_SpawnMobjFromMobj(mo, 0, 0, h<sprite = SPR_FLAM;\ + corona->frame = (FF_FULLBRIGHT|FF_TRANS90|12);\ + corona->tics = -1 + case MT_FLAME: + if (mthing->options & MTF_EXTRA) + { + mobj_t *corona; + makesoftwarecorona(mobj, 20); + P_SetScale(corona, (corona->destscale = mobj->scale*3)); + P_SetTarget(&mobj->tracer, corona); + } + break; + case MT_FLAMEHOLDER: + if (!(mthing->options & MTF_OBJECTSPECIAL)) // Spawn the fire + { + mobj_t *flame = P_SpawnMobjFromMobj(mobj, 0, 0, mobj->height, MT_FLAME); + P_SetTarget(&flame->target, mobj); + flame->flags2 |= MF2_BOSSNOTRAP; + if (mthing->options & MTF_EXTRA) + { + mobj_t *corona; + makesoftwarecorona(flame, 20); + P_SetScale(corona, (corona->destscale = flame->scale*3)); + P_SetTarget(&flame->tracer, corona); + } + } + break; + case MT_CANDLE: + case MT_CANDLEPRICKET: + if (mthing->options & MTF_EXTRA) + { + mobj_t *corona; + makesoftwarecorona(mobj, ((mobj->type == MT_CANDLE) ? 42 : 176)); + } + break; +#undef makesoftwarecorona + case MT_JACKO1: + case MT_JACKO2: + case MT_JACKO3: + if (!(mthing->options & MTF_EXTRA)) // take the torch out of the crafting recipe + { + mobj_t *overlay = P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_OVERLAY); + P_SetTarget(&overlay->target, mobj); + P_SetMobjState(overlay, mobj->info->raisestate); + } break; case MT_WATERDRIP: - if (mthing->angle) - mobj->tics = 3*TICRATE + mthing->angle; - else - mobj->tics = 3*TICRATE; + mobj->tics = 3*TICRATE + mthing->angle; break; case MT_FLAMEJET: case MT_VERTICALFLAMEJET: @@ -12541,187 +11110,243 @@ void P_SpawnMapThing(mapthing_t *mthing) mobj->movedir = mthing->extrainfo; break; case MT_MACEPOINT: - case MT_SWINGMACEPOINT: - case MT_HANGMACEPOINT: - case MT_SPINMACEPOINT: - { - fixed_t mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed; - mobjtype_t chainlink = MT_SMALLMACECHAIN; - mobjtype_t macetype = MT_SMALLMACE; - boolean firsttime; - mobj_t *spawnee; - INT32 line; - const size_t mthingi = (size_t)(mthing - mapthings); - - // Find the corresponding linedef special, using angle as tag - // P_FindSpecialLineFromTag works here now =D - line = P_FindSpecialLineFromTag(9, mthing->angle, -1); - - if (line == -1) - { - CONS_Debug(DBG_GAMELOGIC, "Mace chain (mapthing #%s) needs to be tagged to a #9 parameter line (trying to find tag %d).\n", sizeu1(mthingi), mthing->angle); - return; - } -/* -No deaf - small mace -Deaf - big mace - -ML_NOCLIMB : Direction not controllable -*/ - mlength = abs(lines[line].dx >> FRACBITS); - mspeed = abs(lines[line].dy >> FRACBITS); - mxspeed = sides[lines[line].sidenum[0]].textureoffset >> FRACBITS; - mzspeed = sides[lines[line].sidenum[0]].rowoffset >> FRACBITS; - mstartangle = lines[line].frontsector->floorheight >> FRACBITS; - mmaxspeed = lines[line].frontsector->ceilingheight >> FRACBITS; - - mstartangle %= 360; - mxspeed %= 360; - mzspeed %= 360; - - CONS_Debug(DBG_GAMELOGIC, "Mace Chain (mapthing #%s):\n" - "Length is %d\n" - "Speed is %d\n" - "Xspeed is %d\n" - "Zspeed is %d\n" - "startangle is %d\n" - "maxspeed is %d\n", - sizeu1(mthingi), mlength, mspeed, mxspeed, mzspeed, mstartangle, mmaxspeed); - - mobj->lastlook = mspeed << 4; - mobj->movecount = mobj->lastlook; - mobj->health = (FixedAngle(mzspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); - mobj->threshold = (FixedAngle(mxspeed*FRACUNIT)>>ANGLETOFINESHIFT) + (FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT); - mobj->movefactor = mobj->threshold; - mobj->friction = mmaxspeed; - - if (lines[line].flags & ML_NOCLIMB) - mobj->flags |= MF_SLIDEME; - - mobj->reactiontime = 0; - - if (mthing->options & MTF_AMBUSH) - { - chainlink = MT_BIGMACECHAIN; - macetype = MT_BIGMACE; - } - - if (mthing->options & MTF_OBJECTSPECIAL) - mobj->flags2 |= MF2_BOSSNOTRAP; // shut up maces. - - if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SPINMACEPOINT) - firsttime = true; - else - { - firsttime = false; - - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, macetype); - P_SetTarget(&spawnee->target, mobj); - - if (mobj->type == MT_SWINGMACEPOINT) - spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - else - spawnee->movecount = 0; - - spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - spawnee->reactiontime = mlength+1; - } - - while (mlength > 0) - { - spawnee = P_SpawnMobj(mobj->x, mobj->y, mobj->z, chainlink); - - P_SetTarget(&spawnee->target, mobj); - - if (mobj->type == MT_HANGMACEPOINT || mobj->type == MT_SWINGMACEPOINT) - spawnee->movecount = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - else - spawnee->movecount = 0; - - spawnee->threshold = FixedAngle(mstartangle*FRACUNIT)>>ANGLETOFINESHIFT; - spawnee->reactiontime = mlength; - - if (firsttime) - { - // This is the outermost link in the chain - spawnee->flags2 |= MF2_AMBUSH; - firsttime = false; - } - - mlength--; - } + case MT_CHAINMACEPOINT: + case MT_SPRINGBALLPOINT: + case MT_CHAINPOINT: + case MT_FIREBARPOINT: + case MT_CUSTOMMACEPOINT: + if (!P_SetupMace(mthing, mobj, doangle)) + return false; + break; + case MT_PARTICLEGEN: + if (!P_SetupParticleGen(mthing, mobj)) + return false; break; - } case MT_ROCKSPAWNER: mobj->threshold = mthing->angle; mobj->movecount = mthing->extrainfo; break; - case MT_POPUPTURRET: - if (mthing->angle) - mobj->threshold = mthing->angle; - else - mobj->threshold = (TICRATE*2)-1; - break; - case MT_NIGHTSBUMPER: - // Lower 4 bits specify the angle of - // the bumper in 30 degree increments. - mobj->threshold = (mthing->options & 15) % 12; // It loops over, etc - P_SetMobjState(mobj, mobj->info->spawnstate+mobj->threshold); - break; - case MT_EGGCAPSULE: - if (mthing->angle <= 0) - mthing->angle = 20; // prevent 0 health - - mobj->health = mthing->angle; - mobj->threshold = min(mthing->extrainfo, 7); - break; case MT_TUBEWAYPOINT: - mobj->health = mthing->angle & 255; - mobj->threshold = mthing->angle >> 8; + { + UINT8 sequence = mthing->angle >> 8; + UINT8 id = mthing->angle & 255; + mobj->health = id; + mobj->threshold = sequence; + P_AddTubeWaypoint(sequence, id, mobj); break; - case MT_NIGHTSDRONE: + } + case MT_DSZSTALAGMITE: + case MT_DSZ2STALAGMITE: + case MT_KELP: + if (mthing->options & MTF_OBJECTSPECIAL) { // make mobj twice as big as normal + P_SetScale(mobj, 2*mobj->scale); // not 2*FRACUNIT in case of something like the old ERZ3 mode + mobj->destscale = mobj->scale; + } + break; + case MT_THZTREE: + { // Spawn the branches + angle_t mobjangle = FixedAngle((mthing->angle % 113) << FRACBITS); + P_SpawnMobjFromMobj(mobj, FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_22h; + P_SpawnMobjFromMobj(mobj, 0, FRACUNIT, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_157h; + P_SpawnMobjFromMobj(mobj, -FRACUNIT, 0, 0, MT_THZTREEBRANCH)->angle = mobjangle + ANGLE_270; + } + break; + case MT_CEZPOLE1: + case MT_CEZPOLE2: + { // Spawn the banner + angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS); + P_SpawnMobjFromMobj(mobj, + P_ReturnThrustX(mobj, mobjangle, 4 << FRACBITS), + P_ReturnThrustY(mobj, mobjangle, 4 << FRACBITS), + 0, ((mobj->type == MT_CEZPOLE1) ? MT_CEZBANNER1 : MT_CEZBANNER2))->angle = mobjangle + ANGLE_90; + } + break; + case MT_HHZTREE_TOP: + { // Spawn the branches + angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS) & (ANGLE_90 - 1); + mobj_t* leaf; +#define doleaf(x, y) \ + leaf = P_SpawnMobjFromMobj(mobj, x, y, 0, MT_HHZTREE_PART);\ + leaf->angle = mobjangle;\ + P_SetMobjState(leaf, leaf->info->seestate);\ + mobjangle += ANGLE_90 + doleaf(FRACUNIT, 0); + doleaf(0, FRACUNIT); + doleaf(-FRACUNIT, 0); + doleaf(0, -FRACUNIT); +#undef doleaf + } + break; + case MT_SMASHINGSPIKEBALL: if (mthing->angle > 0) - mobj->health = mthing->angle; + mobj->tics += mthing->angle; break; - case MT_TRAPGOYLE: - case MT_TRAPGOYLEUP: - case MT_TRAPGOYLEDOWN: - case MT_TRAPGOYLELONG: - if (mthing->angle >= 360) - mobj->tics += 7*(mthing->angle / 360) + 1; // starting delay + case MT_BIGFERN: + { + angle_t angle = FixedAngle(mthing->angle << FRACBITS); + UINT8 j; + for (j = 0; j < 8; j++) + { + angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t xoffs = FINECOSINE(fa); + fixed_t yoffs = FINESINE(fa); + mobj_t* leaf = P_SpawnMobjFromMobj(mobj, xoffs, yoffs, 0, MT_BIGFERNLEAF); + leaf->angle = angle; + angle += ANGLE_45; + } break; + } + case MT_REDBOOSTER: + case MT_YELLOWBOOSTER: + if (!P_SetupBooster(mthing, mobj, mobj->type == MT_REDBOOSTER)) + return false; + break; + case MT_AXIS: + // Inverted if uppermost bit is set + if (mthing->angle & 16384) + mobj->flags2 |= MF2_AMBUSH; + + if (mthing->angle > 0) + mobj->radius = (mthing->angle & 16383) << FRACBITS; + // FALLTHRU + case MT_AXISTRANSFER: + case MT_AXISTRANSFERLINE: + // Mare it belongs to + mobj->threshold = min(mthing->extrainfo, 7); + + // # in the mare + mobj->health = mthing->options; + + mobj->flags2 |= MF2_AXIS; + break; + case MT_STARPOST: + { + thinker_t* th; + mobj_t* mo2; + boolean foundanother = false; + + if (mthing->extrainfo) + // Allow thing Parameter to define star post num too! + // For starposts above param 15 (the 16th), add 360 to the angle like before and start parameter from 1 (NOT 0)! + // So the 16th starpost is angle=0 param=15, the 17th would be angle=360 param=1. + // This seems more intuitive for mappers to use until UDMF is ready, since most SP maps won't have over 16 consecutive star posts. + mobj->health = mthing->extrainfo + (mthing->angle/360)*15 + 1; + else + // Old behavior if Parameter is 0; add 360 to the angle for each consecutive star post. + mobj->health = (mthing->angle/360) + 1; + + // See if other starposts exist in this level that have the same value. + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t*)th; + + if (mo2 == mobj) + continue; + + if (mo2->type == MT_STARPOST && mo2->health == mobj->health) + { + foundanother = true; + break; + } + } + + if (!foundanother) + numstarposts++; + break; + } + case MT_SPIKE: + // Pop up spikes! + if (mthing->options & MTF_OBJECTSPECIAL) + { + mobj->flags &= ~MF_SCENERY; + mobj->fuse = (16 - mthing->extrainfo)*(mthing->angle + mobj->info->speed)/16; + if (mthing->options & MTF_EXTRA) + P_SetMobjState(mobj, mobj->info->meleestate); + } + // Use per-thing collision for spikes if the deaf flag isn't checked. + if (!(mthing->options & MTF_AMBUSH) && !metalrecording) + { + P_UnsetThingPosition(mobj); + mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT); + mobj->flags |= MF_SOLID; + P_SetThingPosition(mobj); + } + break; + case MT_WALLSPIKE: + // Pop up spikes! + if (mthing->options & MTF_OBJECTSPECIAL) + { + mobj->flags &= ~MF_SCENERY; + mobj->fuse = (16 - mthing->extrainfo)*((mthing->angle/360) + mobj->info->speed)/16; + if (mthing->options & MTF_EXTRA) + P_SetMobjState(mobj, mobj->info->meleestate); + } + // Use per-thing collision for spikes if the deaf flag isn't checked. + if (!(mthing->options & MTF_AMBUSH) && !metalrecording) + { + P_UnsetThingPosition(mobj); + mobj->flags &= ~(MF_NOBLOCKMAP | MF_NOCLIPHEIGHT); + mobj->flags |= MF_SOLID; + P_SetThingPosition(mobj); + } + + // spawn base + { + const angle_t mobjangle = FixedAngle(mthing->angle << FRACBITS); // the mobj's own angle hasn't been set quite yet so... + const fixed_t baseradius = mobj->radius - mobj->scale; + mobj_t* base = P_SpawnMobj( + mobj->x - P_ReturnThrustX(mobj, mobjangle, baseradius), + mobj->y - P_ReturnThrustY(mobj, mobjangle, baseradius), + mobj->z, MT_WALLSPIKEBASE); + base->angle = mobjangle + ANGLE_90; + base->destscale = mobj->destscale; + P_SetScale(base, mobj->scale); + P_SetTarget(&base->target, mobj); + P_SetTarget(&mobj->tracer, base); + } + break; + case MT_BIGTUMBLEWEED: + case MT_LITTLETUMBLEWEED: + if (mthing->options & MTF_AMBUSH) + { + fixed_t offset = FixedMul(16*FRACUNIT, mobj->scale); + mobj->momx += P_RandomChance(FRACUNIT/2) ? offset : -offset; + mobj->momy += P_RandomChance(FRACUNIT/2) ? offset : -offset; + mobj->momz += offset; + } + break; + case MT_REDFLAG: + redflag = mobj; + rflagpoint = mobj->spawnpoint; + break; + case MT_BLUEFLAG: + blueflag = mobj; + bflagpoint = mobj->spawnpoint; + break; + // SRB2Kart case MT_WAYPOINT: { const fixed_t mobjscale = mapheaderinfo[gamemap-1]->default_waypoint_radius; - // Just like MT_SPINMACEPOINT, this now works here too! - INT32 line = P_FindSpecialLineFromTag(2000, mthing->angle, -1); - - if (mobjscale == 0) - mobj->radius = DEFAULT_WAYPOINT_RADIUS * mapobjectscale; - else + if (mthing->args[1] > 0) + mobj->radius = (mthing->args[1]) * FRACUNIT; + else if (mobjscale > 0) mobj->radius = mobjscale; + else + mobj->radius = DEFAULT_WAYPOINT_RADIUS * mapobjectscale; - // Set the radius, mobj z, and mthing z to match what the parameters want - if (line != -1) - { - fixed_t lineradius = sides[lines[line].sidenum[0]].textureoffset; - fixed_t linez = sides[lines[line].sidenum[0]].rowoffset; - - if (lineradius > 0) - mobj->radius = lineradius; - mobj->z += linez; - mthing->z += linez >> FRACBITS; - } // Use threshold to store the next waypoint ID // movecount is being used for the current waypoint ID // reactiontime lets us know if we can respawn at it // lastlook is used for indicating the waypoint is a shortcut // extravalue1 is used for indicating the waypoint is disabled // extravalue2 is used for indicating the waypoint is the finishline - mobj->threshold = ((mthing->options >> ZSHIFT)); - mobj->movecount = mthing->angle; + mobj->threshold = mthing->args[0]; + mobj->movecount = mthing->tag; if (mthing->options & MTF_EXTRA) { mobj->extravalue1 = 0; // The waypoint is disabled if extra is on @@ -12746,9 +11371,9 @@ ML_NOCLIMB : Direction not controllable { mobj->reactiontime = 1; } - if (mthing->extrainfo == 1) + if (mthing->args[2] == 1) { - mobj->extravalue2 = 1; // extrainfo of 1 means the waypoint is at the finish line + mobj->extravalue2 = 1; // args[1] of 1 means the waypoint is at the finish line } else { @@ -12763,9 +11388,9 @@ ML_NOCLIMB : Direction not controllable case MT_BOTHINT: { // Change size - if (mthing->angle > 0) + if (mthing->args[0] > 0) { - mobj->radius = mthing->angle * FRACUNIT; + mobj->radius = mthing->args[0] * FRACUNIT; } else { @@ -12783,57 +11408,177 @@ ML_NOCLIMB : Direction not controllable } // Steering amount - if (mthing->extrainfo == 0) + if (mthing->args[1] == 0) { mobj->extravalue2 = 2; } else { - mobj->extravalue2 = mthing->extrainfo; + mobj->extravalue2 = mthing->args[1]; } break; } - // SRB2Kart - case MT_BALLOON: - mobj->color = (1 + (mthing->angle % (MAXSKINCOLORS-1))); - break; case MT_AAZTREE_HELPER: + { + fixed_t top = mobj->z; + UINT8 i; + UINT8 locnumsegs = (mthing->extrainfo)+2; + UINT8 numleaves = max(3, (abs(mthing->angle+1) % 6) + 3); + mobj_t *coconut; + + // Spawn tree segments + for (i = 0; i < locnumsegs; i++) { - fixed_t top = mobj->z; - UINT8 locnumsegs = (mthing->extrainfo)+2; - UINT8 numleaves = max(3, (abs(mthing->angle+1) % 6) + 3); - mobj_t *coconut; - - // Spawn tree segments - for (i = 0; i < locnumsegs; i++) - { - P_SpawnMobj(mobj->x, mobj->y, top, MT_AAZTREE_SEG); - top += FixedMul(mobjinfo[MT_AAZTREE_SEG].height, mobj->scale); - } - - // Big coconut topper - coconut = P_SpawnMobj(mobj->x, mobj->y, top - (8<destscale = (2*mobj->scale))); - - // Spawn all of the papersprite leaves - for (i = 0; i < numleaves; i++) - { - mobj_t *leaf; - - mobj->angle = FixedAngle((i * (360/numleaves))<x + FINECOSINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK), - mobj->y + FINESINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK), top, MT_AAZTREE_LEAF); - leaf->angle = mobj->angle; - - // Small coconut for each leaf - P_SpawnMobj(mobj->x + (32 * FINECOSINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK)), - mobj->y + (32 * FINESINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK)), top - (24<x, mobj->y, top, MT_AAZTREE_SEG); + top += FixedMul(mobjinfo[MT_AAZTREE_SEG].height, mobj->scale); } + + // Big coconut topper + coconut = P_SpawnMobj(mobj->x, mobj->y, top - (8<destscale = (2*mobj->scale))); + + // Spawn all of the papersprite leaves + for (i = 0; i < numleaves; i++) + { + mobj_t *leaf; + + mobj->angle = FixedAngle((i * (360/numleaves))<x + FINECOSINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK), + mobj->y + FINESINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK), top, MT_AAZTREE_LEAF); + leaf->angle = mobj->angle; + + // Small coconut for each leaf + P_SpawnMobj(mobj->x + (32 * FINECOSINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK)), + mobj->y + (32 * FINESINE((mobj->angle>>ANGLETOFINESHIFT) & FINEMASK)), top - (24<x, mobj->y)->sector; + mobj_t *cur, *prev = mobj; + fixed_t floorheights[MAXFFLOORS+1]; + UINT8 numfloors = 0; + boolean fly = true; + UINT8 i; + + // This floor height stuff is stupid but I couldn't get it to work any other way for whatever reason + if (mthing->options & MTF_OBJECTFLIP) + { + floorheights[numfloors] = P_GetSectorCeilingZAt(sec, mobj->x, mobj->y) - mobj->height; + } + else + { + floorheights[numfloors] = P_GetSectorFloorZAt(sec, mobj->x, mobj->y); + } + + numfloors++; + + if (sec->ffloors) + { + ffloor_t *rover; + for (rover = sec->ffloors; rover; rover = rover->next) + { + if ((rover->flags & FF_EXISTS) && (rover->flags & FF_BLOCKOTHERS)) + { + if (mthing->options & MTF_OBJECTFLIP) + { + floorheights[numfloors] = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y) - mobj->height; + } + else + { + floorheights[numfloors] = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y); + } + + numfloors++; + } + } + } + + for (i = 0; i < numfloors; i++) + { + if (mobj->z == floorheights[i]) + { + fly = false; + break; + } + } + + // Flying capsules + if (fly) + { + mobj->flags |= MF_NOGRAVITY; + mobj->extravalue1 = 1; // Set extravalue1 for later reference + } + + // Moving capsules! + if (mthing->args[0] && mthing->args[1]) + { + K_SetupMovingCapsule(mthing, mobj); + } + + // NOW FOR ALL OF THE PIECES!! + // Init hnext list + // Spherical top + cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); + P_SetMobjState(cur, S_BATTLECAPSULE_TOP); + + P_SetTarget(&cur->target, mobj); + P_SetTarget(&cur->hprev, prev); + P_SetTarget(&prev->hnext, cur); + prev = cur; + + // Tippity-top decorational button + cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); + P_SetMobjState(cur, S_BATTLECAPSULE_BUTTON); + + P_SetTarget(&cur->target, mobj); + P_SetTarget(&cur->hprev, prev); + P_SetTarget(&prev->hnext, cur); + prev = cur; + + // Supports on the bottom + for (i = 0; i < 4; i++) + { + cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); + cur->extravalue1 = i; + + if (mobj->extravalue1) // Flying capsule, moving or not + P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORTFLY); + else if (mobj->target && !P_MobjWasRemoved(mobj->target)) // Grounded, moving capsule + P_SetMobjState(cur, S_KARMAWHEEL); + else + P_SetMobjState(cur, S_BATTLECAPSULE_SUPPORT); // Grounded, stationary capsule + + P_SetTarget(&cur->target, mobj); + P_SetTarget(&cur->hprev, prev); + P_SetTarget(&prev->hnext, cur); + prev = cur; + } + + // Side paneling + for (i = 0; i < 8; i++) + { + cur = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_BATTLECAPSULE_PIECE); + cur->extravalue1 = i; + + if (i & 1) + P_SetMobjState(cur, S_BATTLECAPSULE_SIDE2); + else + P_SetMobjState(cur, S_BATTLECAPSULE_SIDE1); + + P_SetTarget(&cur->target, mobj); + P_SetTarget(&cur->hprev, prev); + P_SetTarget(&prev->hnext, cur); + prev = cur; + } + + // Increment no. of capsules on the map counter + maptargets++; + } default: break; } @@ -12844,170 +11589,79 @@ ML_NOCLIMB : Direction not controllable mobj->flags2 |= MF2_BOSSNOTRAP; } - if (i == MT_AXIS || i == MT_AXISTRANSFER || i == MT_AXISTRANSFERLINE) // Axis Points + return true; +} + +static void P_SetAmbush(mobj_t *mobj) +{ + if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG) + mobj->angle += ANGLE_22h; + + if (mobj->flags & MF_NIGHTSITEM) { - // Mare it belongs to - mobj->threshold = min(mthing->extrainfo, 7); - - // # in the mare - mobj->health = mthing->options; - - mobj->flags2 |= MF2_AXIS; - - if (i == MT_AXIS) - { - // Inverted if uppermost bit is set - if (mthing->angle & 16384) - mobj->flags2 |= MF2_AMBUSH; - - if (mthing->angle > 0) - mobj->radius = (mthing->angle & 16383)*FRACUNIT; - } - } - else if (i == MT_EMMY) - { - if (mthing->options & MTF_OBJECTSPECIAL) // Mario Block version - mobj->flags &= ~(MF_NOGRAVITY|MF_NOCLIPHEIGHT); - else - { - fixed_t zheight = mobj->z; - mobj_t *tokenobj; - - if (mthing->options & MTF_OBJECTFLIP) - zheight += mobj->height-FixedMul(mobjinfo[MT_TOKEN].height, mobj->scale); // align with emmy properly! - - tokenobj = P_SpawnMobj(x, y, zheight, MT_TOKEN); - P_SetTarget(&mobj->tracer, tokenobj); - tokenobj->destscale = mobj->scale; - P_SetScale(tokenobj, mobj->scale); - if (mthing->options & MTF_OBJECTFLIP) // flip token to match emmy - { - tokenobj->eflags |= MFE_VERTICALFLIP; - tokenobj->flags2 |= MF2_OBJECTFLIP; - } - } - - // We advanced tokenbits earlier due to the return check. - // Subtract 1 here for the correct value. - mobj->health = 1 << (tokenbits - 1); - } - else if (i == MT_CYBRAKDEMON && mthing->options & MTF_AMBUSH) - { - mobj_t *elecmobj; - elecmobj = P_SpawnMobj(x, y, z, MT_CYBRAKDEMON_ELECTRIC_BARRIER); - P_SetTarget(&elecmobj->target, mobj); - elecmobj->angle = FixedAngle(mthing->angle*FRACUNIT);; - elecmobj->destscale = mobj->scale*2; - P_SetScale(elecmobj, elecmobj->destscale); - } - else if (i == MT_STARPOST) - { - thinker_t *th; - mobj_t *mo2; - boolean foundanother = false; - mobj->health = (mthing->angle / 360) + 1; - - // See if other starposts exist in this level that have the same value. - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2 == mobj) - continue; - - if (mo2->type == MT_STARPOST && mo2->health == mobj->health) - { - foundanother = true; - break; - } - } - - if (!foundanother) - numstarposts++; - } - else if (i == MT_SPIKE) - { - // Pop up spikes! - if (mthing->options & MTF_OBJECTSPECIAL) - { - mobj->flags &= ~MF_SCENERY; - mobj->fuse = mthing->angle + mobj->info->speed; - } - // Use per-thing collision for spikes if the deaf flag is checked. - if (mthing->options & MTF_AMBUSH && !metalrecording) - { - P_UnsetThingPosition(mobj); - mobj->flags &= ~(MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOCLIPHEIGHT); - mobj->flags |= MF_SOLID; - P_SetThingPosition(mobj); - } + // Spawn already displayed + mobj->flags |= MF_SPECIAL; + mobj->flags &= ~MF_NIGHTSITEM; } - //count 10 ring boxes into the number of rings equation too. - if (i == MT_SUPERRINGBOX) - nummaprings += 10; + if (mobj->flags & MF_PUSHABLE) + mobj->flags &= ~MF_PUSHABLE; - if (i == MT_BIGTUMBLEWEED || i == MT_LITTLETUMBLEWEED) + if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) { - if (mthing->options & MTF_AMBUSH) - { - mobj->momz += FixedMul(16*FRACUNIT, mobj->scale); - - if (P_RandomChance(FRACUNIT/2)) - mobj->momx += FixedMul(16*FRACUNIT, mobj->scale); - else - mobj->momx -= FixedMul(16*FRACUNIT, mobj->scale); - - if (P_RandomChance(FRACUNIT/2)) - mobj->momy += FixedMul(16*FRACUNIT, mobj->scale); - else - mobj->momy -= FixedMul(16*FRACUNIT,mobj->scale); - } + // flag for strong/weak random boxes + // any monitor with nonzero speed is allowed to respawn like this + mobj->flags2 |= MF2_AMBUSH; } - // CTF flag pointers - if (i == MT_REDFLAG) + else if (mobj->type != MT_AXIS && + mobj->type != MT_AXISTRANSFER && + mobj->type != MT_AXISTRANSFERLINE && + mobj->type != MT_NIGHTSBUMPER && + mobj->type != MT_STARPOST) + mobj->flags2 |= MF2_AMBUSH; +} + +static void P_SetObjectSpecial(mobj_t *mobj) +{ + if (mobj->type == MT_YELLOWDIAG || mobj->type == MT_REDDIAG || mobj->type == MT_BLUEDIAG) + mobj->flags |= MF_NOGRAVITY; + + if ((mobj->flags & MF_MONITOR) && mobj->info->speed != 0) { - redflag = mobj; - rflagpoint = mobj->spawnpoint; - } - if (i == MT_BLUEFLAG) - { - blueflag = mobj; - bflagpoint = mobj->spawnpoint; + // flag for strong/weak random boxes + // any monitor with nonzero speed is allowed to respawn like this + mobj->flags2 |= MF2_STRONGBOX; } - // special push/pull stuff - if (i == MT_PUSH || i == MT_PULL) + // Requires you to be in bonus time to activate + if (mobj->flags & MF_NIGHTSITEM) + mobj->flags2 |= MF2_STRONGBOX; + + // Pushables bounce and slide coolly with object special flag set + if (mobj->flags & MF_PUSHABLE) { - mobj->health = 0; // Default behaviour: pushing uses XY, fading uses XYZ - - if (mthing->options & MTF_AMBUSH) - mobj->health |= 1; // If ambush is set, push using XYZ - if (mthing->options & MTF_OBJECTSPECIAL) - mobj->health |= 2; // If object special is set, fade using XY - - if (G_IsSpecialStage(gamemap)) - { - if (i == MT_PUSH) - P_SetMobjState(mobj, S_GRAVWELLGREEN); - if (i == MT_PULL) - P_SetMobjState(mobj, S_GRAVWELLRED); - } + mobj->flags2 |= MF2_SLIDEPUSH; + mobj->flags &= ~MF_SLIDEME; } +} - // ignore MTF_ flags and return early - if (i == MT_NIGHTSBUMPER) - { - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - mthing->mobj = mobj; - return; - } +static mobj_t *P_SpawnMobjFromMapThing(mapthing_t *mthing, fixed_t x, fixed_t y, fixed_t z, mobjtype_t i) +{ + mobj_t *mobj = NULL; + boolean doangle = true; - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); + mobj = P_SpawnMobj(x, y, z, i); + mobj->spawnpoint = mthing; + + P_SetScale(mobj, mthing->scale); + mobj->destscale = mthing->scale; + + if (!P_SetupSpawnedMapThing(mthing, mobj, &doangle)) + return mobj; + + if (doangle) + mobj->angle = FixedAngle(mthing->angle << FRACBITS); if ((mobj->flags & MF_SPRING) && mobj->info->damage != 0 @@ -13019,77 +11673,26 @@ ML_NOCLIMB : Direction not controllable mobj->spryoff = FixedMul(mobj->radius, FINESINE(a >> ANGLETOFINESHIFT)); } + mobj->pitch = FixedAngle(mthing->pitch << FRACBITS); + mobj->roll = FixedAngle(mthing->roll << FRACBITS); + + mthing->mobj = mobj; + + // ignore MTF_ flags and return early + if (i == MT_NIGHTSBUMPER) + return mobj; + if ((mthing->options & MTF_AMBUSH) - && (mthing->options & MTF_OBJECTSPECIAL) - && (mobj->flags & MF_PUSHABLE)) - { + && (mthing->options & MTF_OBJECTSPECIAL) + && (mobj->flags & MF_PUSHABLE)) mobj->flags2 |= MF2_CLASSICPUSH; - } else { if (mthing->options & MTF_AMBUSH) - { - if ((mobj->flags & MF_SPRING) && mobj->info->damage) - { - mobj->angle += ANGLE_22h; - } - - if (mobj->flags & MF_NIGHTSITEM) - { - // Spawn already displayed - mobj->flags |= MF_SPECIAL; - mobj->flags &= ~MF_NIGHTSITEM; - P_SetMobjState(mobj, mobj->info->seestate); - } - - if (mobj->flags & MF_PUSHABLE) - { - mobj->flags &= ~MF_PUSHABLE; - mobj->flags2 |= MF2_STANDONME; - } - - if (mobj->flags & MF_MONITOR) - { - // flag for strong/weak random boxes - if (mthing->type == mobjinfo[MT_SUPERRINGBOX].doomednum || mthing->type == mobjinfo[MT_PRUP].doomednum || - mthing->type == mobjinfo[MT_SNEAKERTV].doomednum || mthing->type == mobjinfo[MT_INV].doomednum || - mthing->type == mobjinfo[MT_WHITETV].doomednum || mthing->type == mobjinfo[MT_GREENTV].doomednum || - mthing->type == mobjinfo[MT_YELLOWTV].doomednum || mthing->type == mobjinfo[MT_BLUETV].doomednum || - mthing->type == mobjinfo[MT_BLACKTV].doomednum || mthing->type == mobjinfo[MT_PITYTV].doomednum || - mthing->type == mobjinfo[MT_RECYCLETV].doomednum || mthing->type == mobjinfo[MT_MIXUPBOX].doomednum) - mobj->flags2 |= MF2_AMBUSH; - } - - else if (mthing->type != mobjinfo[MT_AXIS].doomednum && - mthing->type != mobjinfo[MT_AXISTRANSFER].doomednum && - mthing->type != mobjinfo[MT_AXISTRANSFERLINE].doomednum && - mthing->type != mobjinfo[MT_NIGHTSBUMPER].doomednum && - mthing->type != mobjinfo[MT_STARPOST].doomednum) - mobj->flags2 |= MF2_AMBUSH; - } + P_SetAmbush(mobj); if (mthing->options & MTF_OBJECTSPECIAL) - { - // flag for strong/weak random boxes - if (mthing->type == mobjinfo[MT_SUPERRINGBOX].doomednum || mthing->type == mobjinfo[MT_PRUP].doomednum || - mthing->type == mobjinfo[MT_SNEAKERTV].doomednum || mthing->type == mobjinfo[MT_INV].doomednum || - mthing->type == mobjinfo[MT_WHITETV].doomednum || mthing->type == mobjinfo[MT_GREENTV].doomednum || - mthing->type == mobjinfo[MT_YELLOWTV].doomednum || mthing->type == mobjinfo[MT_BLUETV].doomednum || - mthing->type == mobjinfo[MT_BLACKTV].doomednum || mthing->type == mobjinfo[MT_PITYTV].doomednum || - mthing->type == mobjinfo[MT_RECYCLETV].doomednum || mthing->type == mobjinfo[MT_MIXUPBOX].doomednum) - mobj->flags2 |= MF2_STRONGBOX; - - // Requires you to be in bonus time to activate - if (mobj->flags & MF_NIGHTSITEM) - mobj->flags2 |= MF2_STRONGBOX; - - // Pushables bounce and slide coolly with object special flag set - if (mobj->flags & MF_PUSHABLE) - { - mobj->flags2 |= MF2_SLIDEPUSH; - mobj->flags |= MF_BOUNCE; - } - } + P_SetObjectSpecial(mobj); } // Generic reverse gravity for individual objects flag. @@ -13099,594 +11702,324 @@ ML_NOCLIMB : Direction not controllable mobj->flags2 |= MF2_OBJECTFLIP; } - mthing->mobj = mobj; + // Extra functionality + if (mthing->options & MTF_EXTRA) + { + if (mobj->flags & MF_MONITOR && (mthing->angle & 16384)) + { + // Store line exec tag to run upon popping + mobj->lastlook = (mthing->angle & 16383); + } + } + + // Final set of not being able to draw nightsitems. + if (mobj->flags & MF_NIGHTSITEM) + mobj->drawflags |= MFD_DONTDRAW; + + return mobj; } -void P_SpawnHoopsAndRings(mapthing_t *mthing) +// +// P_SpawnMapThing +// The fields of the mapthing should +// already be in host byte order. +// +mobj_t *P_SpawnMapThing(mapthing_t *mthing) { + mobjtype_t i; mobj_t *mobj = NULL; - INT32 r, i; - fixed_t x, y, z, finalx, finaly, finalz; - sector_t *sec; - TVector v, *res; - angle_t closestangle, fa; + fixed_t x, y, z; + + if (!mthing->type) + return mobj; // Ignore type-0 things as NOPs + + if (mthing->type == 3328) // 3D Mode start Thing + return mobj; + + if (!objectplacing && P_SpawnNonMobjMapThing(mthing)) + return mobj; + + i = P_GetMobjtype(mthing->type); + if (i == MT_UNKNOWN) + CONS_Alert(CONS_WARNING, M_GetText("Unknown thing type %d placed at (%d, %d)\n"), mthing->type, mthing->x, mthing->y); + + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(mthing, i)) + return mobj; + + i = P_GetMobjtypeSubstitute(mthing, i); + if (i == MT_NULL) // Don't spawn mobj + return mobj; + } x = mthing->x << FRACBITS; y = mthing->y << FRACBITS; + z = P_GetMapThingSpawnHeight(i, mthing, x, y); + return P_SpawnMobjFromMapThing(mthing, x, y, z, i); +} - sec = R_PointInSubsector(x, y)->sector; +static void P_SpawnHoopInternal(mapthing_t *mthing, INT32 hoopsize, fixed_t sizefactor) +{ + mobj_t *mobj = NULL; + mobj_t *nextmobj = NULL; + mobj_t *hoopcenter; + TMatrix *pitchmatrix, *yawmatrix; + fixed_t radius = hoopsize*sizefactor; + INT32 i; + angle_t fa; + TVector v, *res; + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = P_GetMobjSpawnHeight(MT_HOOP, x, y, mthing->z << FRACBITS, 0, false, mthing->scale); - // NiGHTS hoop! - if (mthing->type == 1705) + hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); + hoopcenter->spawnpoint = mthing; + hoopcenter->z -= hoopcenter->height/2; + + P_UnsetThingPosition(hoopcenter); + hoopcenter->x = x; + hoopcenter->y = y; + P_SetThingPosition(hoopcenter); + + // Scale 0-255 to 0-359 =( + hoopcenter->movedir = ((mthing->angle & 255)*360)/256; // Pitch + pitchmatrix = RotateXMatrix(FixedAngle(hoopcenter->movedir << FRACBITS)); + hoopcenter->movecount = (((UINT16)mthing->angle >> 8)*360)/256; // Yaw + yawmatrix = RotateZMatrix(FixedAngle(hoopcenter->movecount << FRACBITS)); + + // For the hoop when it flies away + hoopcenter->extravalue1 = hoopsize; + hoopcenter->extravalue2 = radius/12; + + // Create the hoop! + for (i = 0; i < hoopsize; i++) { - mobj_t *nextmobj = NULL; - mobj_t *hoopcenter; - INT16 spewangle; + fa = i*(FINEANGLES/hoopsize); + v[0] = FixedMul(FINECOSINE(fa), radius); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), radius); + v[3] = FRACUNIT; - z = mthing->options << FRACBITS; + res = VectorMatrixMultiply(v, *pitchmatrix); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *yawmatrix); + M_Memcpy(&v, res, sizeof(v)); - hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); + mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOP); + mobj->z -= mobj->height/2; - hoopcenter->spawnpoint = mthing; + P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. + mobj->fuse = 0; - // Screw these damn hoops, I need this thinker. - //hoopcenter->flags |= MF_NOTHINK; - - z += -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - - hoopcenter->z = z - hoopcenter->height/2; - - P_UnsetThingPosition(hoopcenter); - hoopcenter->x = x; - hoopcenter->y = y; - P_SetThingPosition(hoopcenter); - - // Scale 0-255 to 0-359 =( - closestangle = FixedAngle(FixedMul((mthing->angle>>8)*FRACUNIT, - 360*(FRACUNIT/256))); - - hoopcenter->movedir = FixedInt(FixedMul((mthing->angle&255)*FRACUNIT, - 360*(FRACUNIT/256))); - hoopcenter->movecount = FixedInt(AngleFixed(closestangle)); - - // For the hoop when it flies away - hoopcenter->extravalue1 = 32; - hoopcenter->extravalue2 = 8 * FRACUNIT; - - spewangle = (INT16)hoopcenter->movedir; - - // Create the hoop! - for (i = 0; i < 32; i++) + // Link all the sprites in the hoop together + if (nextmobj) { - fa = i*(FINEANGLES/32); - v[0] = FixedMul(FINECOSINE(fa),96*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),96*FRACUNIT); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); - - //if (maptol & TOL_XMAS) - //P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); - - mobj->z -= mobj->height/2; - P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. - mobj->fuse = 0; - - // Link all the sprites in the hoop together - if (nextmobj) - { - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - //mobj->hprev = nextmobj; - //mobj->hprev->hnext = mobj; - } - else - mobj->hprev = mobj->hnext = NULL; - - nextmobj = mobj; - } - - // Create the collision detectors! - for (i = 0; i < 16; i++) - { - fa = i*FINEANGLES/16; - v[0] = FixedMul(FINECOSINE(fa),32*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),32*FRACUNIT); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - mobj->hnext = NULL; P_SetTarget(&mobj->hprev, nextmobj); P_SetTarget(&mobj->hprev->hnext, mobj); - //mobj->hprev = nextmobj; - //mobj->hprev->hnext = mobj; - - nextmobj = mobj; } - // Create the collision detectors! - for (i = 0; i < 16; i++) - { - fa = i*FINEANGLES/16; - v[0] = FixedMul(FINECOSINE(fa),64*FRACUNIT); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),64*FRACUNIT); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); + else + P_SetTarget(&mobj->hprev, P_SetTarget(&mobj->hnext, NULL)); - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - mobj->hnext = NULL; - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - //mobj->hprev = nextmobj; - //mobj->hprev->hnext = mobj; - - nextmobj = mobj; - } - return; + nextmobj = mobj; } - // CUSTOMIZABLE NiGHTS hoop! - else if (mthing->type == 1713) + + // Create the collision detectors! + // Create them until the size is less than 8 + // But always create at least ONE set of collision detectors + do { - mobj_t *nextmobj = NULL; - mobj_t *hoopcenter; - INT16 spewangle; - INT32 hoopsize; - INT32 hoopplacement; + if (hoopsize >= 32) + hoopsize -= 16; + else + hoopsize /= 2; - // Save our flags! - z = (mthing->options>>ZSHIFT) << FRACBITS; + radius = hoopsize*sizefactor; - hoopcenter = P_SpawnMobj(x, y, z, MT_HOOPCENTER); - hoopcenter->spawnpoint = mthing; - - z += -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - hoopcenter->z = z - hoopcenter->height/2; - - P_UnsetThingPosition(hoopcenter); - hoopcenter->x = x; - hoopcenter->y = y; - P_SetThingPosition(hoopcenter); - - // Scale 0-255 to 0-359 =( - closestangle = FixedAngle(FixedMul((mthing->angle>>8)*FRACUNIT, - 360*(FRACUNIT/256))); - - hoopcenter->movedir = FixedInt(FixedMul((mthing->angle&255)*FRACUNIT, - 360*(FRACUNIT/256))); - hoopcenter->movecount = FixedInt(AngleFixed(closestangle)); - - spewangle = (INT16)hoopcenter->movedir; - - // Super happy fun time - // For each flag add 4 fracunits to the size - // Default (0 flags) is 8 fracunits - hoopsize = 8 + (4 * (mthing->options & 0xF)); - hoopplacement = hoopsize * (4*FRACUNIT); - - // For the hoop when it flies away - hoopcenter->extravalue1 = hoopsize; - hoopcenter->extravalue2 = FixedDiv(hoopplacement, 12*FRACUNIT); - - // Create the hoop! for (i = 0; i < hoopsize; i++) { fa = i*(FINEANGLES/hoopsize); - v[0] = FixedMul(FINECOSINE(fa), hoopplacement); + v[0] = FixedMul(FINECOSINE(fa), radius); v[1] = 0; - v[2] = FixedMul(FINESINE(fa), hoopplacement); + v[2] = FixedMul(FINESINE(fa), radius); v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOP); - - //if (maptol & TOL_XMAS) - //P_SetMobjState(mobj, mobj->info->seestate + (i & 1)); + res = VectorMatrixMultiply(v, *pitchmatrix); + M_Memcpy(&v, res, sizeof(v)); + res = VectorMatrixMultiply(v, *yawmatrix); + M_Memcpy(&v, res, sizeof(v)); + mobj = P_SpawnMobj(x + v[0], y + v[1], z + v[2], MT_HOOPCOLLIDE); mobj->z -= mobj->height/2; - P_SetTarget(&mobj->target, hoopcenter); // Link the sprite to the center. - mobj->fuse = 0; - // Link all the sprites in the hoop together - if (nextmobj) - { - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - //mobj->hprev = nextmobj; - //mobj->hprev->hnext = mobj; - } - else - mobj->hprev = mobj->hnext = NULL; + // Link all the collision sprites together. + P_SetTarget(&mobj->hnext, NULL); + P_SetTarget(&mobj->hprev, nextmobj); + P_SetTarget(&mobj->hprev->hnext, mobj); nextmobj = mobj; } + } while (hoopsize >= 8); +} - // Create the collision detectors! - // Create them until the size is less than 8 - // But always create at least ONE set of collision detectors - do - { - if (hoopsize >= 32) - hoopsize -= 16; - else - hoopsize /= 2; - - hoopplacement = hoopsize * (4*FRACUNIT); - - for (i = 0; i < hoopsize; i++) - { - fa = i*FINEANGLES/hoopsize; - v[0] = FixedMul(FINECOSINE(fa), hoopplacement); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa), hoopplacement); - v[3] = FRACUNIT; - res = VectorMatrixMultiply(v, *RotateXMatrix(FixedAngle(spewangle*FRACUNIT))); - M_Memcpy(&v, res, sizeof (v)); - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, MT_HOOPCOLLIDE); - mobj->z -= mobj->height/2; - - // Link all the collision sprites together. - mobj->hnext = NULL; - P_SetTarget(&mobj->hprev, nextmobj); - P_SetTarget(&mobj->hprev->hnext, mobj); - //mobj->hprev = nextmobj; - //mobj->hprev->hnext = mobj; - - nextmobj = mobj; - } - } while (hoopsize >= 8); - +void P_SpawnHoop(mapthing_t *mthing) +{ + if (metalrecording) return; - } - // Wing logo item. - else if (mthing->type == mobjinfo[MT_NIGHTSWING].doomednum) + + if (mthing->type == 1705) // Generic hoop + P_SpawnHoopInternal(mthing, 24, 4*FRACUNIT); + else // Customizable hoop + // For each flag add 16 fracunits to the size + // Default (0 flags) is 32 fracunits + P_SpawnHoopInternal(mthing, 8 + (4*(mthing->options & 0xF)), 4*FRACUNIT); +} + +static void P_SpawnItemRow(mapthing_t *mthing, mobjtype_t* itemtypes, UINT8 numitemtypes, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) +{ + mapthing_t dummything; + mobj_t *mobj = NULL; + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = mthing->z << FRACBITS; + INT32 r; + angle_t angle = FixedAngle(fixedangle << FRACBITS); + angle_t fineangle = (angle >> ANGLETOFINESHIFT) & FINEMASK; + + (void)bonustime; + + for (r = 0; r < numitemtypes; r++) { - z = -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); + dummything = *mthing; + dummything.type = mobjinfo[itemtypes[r]].doomednum; + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(&dummything, itemtypes[r])) + { + itemtypes[r] = MT_NULL; + continue; + } - mthing->z = (INT16)(z>>FRACBITS); - - mobj = P_SpawnMobj(x, y, z, MT_NIGHTSWING); - mobj->spawnpoint = mthing; - - if (G_IsSpecialStage(gamemap) && useNightsSS) - P_SetMobjState(mobj, mobj->info->meleestate); - else if (maptol & TOL_XMAS) - P_SetMobjState(mobj, mobj->info->seestate); - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - mobj->flags2 |= MF2_AMBUSH; - mthing->mobj = mobj; + itemtypes[r] = P_GetMobjtypeSubstitute(&dummything, itemtypes[r]); + } } - // All manners of rings and coins - else if (mthing->type == mobjinfo[MT_RING].doomednum || mthing->type == mobjinfo[MT_COIN].doomednum || - mthing->type == mobjinfo[MT_REDTEAMRING].doomednum || mthing->type == mobjinfo[MT_BLUETEAMRING].doomednum) + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, mthing->options & MTF_OBJECTFLIP, mthing->scale); + + for (r = 0; r < numitems; r++) { - mobjtype_t ringthing = MT_RING; + mobjtype_t itemtype = itemtypes[r % numitemtypes]; + if (itemtype == MT_NULL) + continue; + dummything.type = mobjinfo[itemtype].doomednum; - // No rings in Ultimate! - if (ultimatemode && !(G_IsSpecialStage(gamemap) || maptol & TOL_NIGHTS)) - return; + x += FixedMul(horizontalspacing, FINECOSINE(fineangle)); + y += FixedMul(horizontalspacing, FINESINE(fineangle)); + z += (mthing->options & MTF_OBJECTFLIP) ? -verticalspacing : verticalspacing; - // Which ringthing to use - switch (mthing->type) - { - case 1800: - ringthing = MT_COIN; - break; - case 308: // No team rings in non-CTF - ringthing = (gametype == GT_CTF) ? MT_REDTEAMRING : MT_RING; - break; - case 309: // No team rings in non-CTF - ringthing = (gametype == GT_CTF) ? MT_BLUETEAMRING : MT_RING; - break; - default: - // Spawn rings as blue spheres in special stages, ala S3+K. - if (G_IsSpecialStage(gamemap) && useNightsSS) - ringthing = MT_BLUEBALL; - break; - } + mobj = P_SpawnMobjFromMapThing(&dummything, x, y, z, itemtype); - // Set proper height - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); - } - else - { - z = -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - } + if (!mobj) + continue; - if (mthing->options & MTF_AMBUSH) // Special flag for rings - { - if (mthing->options & MTF_OBJECTFLIP) - z -= 24*FRACUNIT; - else - z += 24*FRACUNIT; - } - - mthing->z = (INT16)(z>>FRACBITS); - - mobj = P_SpawnMobj(x, y, z, ringthing); - mobj->spawnpoint = mthing; - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - mobj->flags2 |= MF2_AMBUSH; - mthing->mobj = mobj; + mobj->spawnpoint = NULL; } - // *** +} + +static void P_SpawnSingularItemRow(mapthing_t* mthing, mobjtype_t itemtype, INT32 numitems, fixed_t horizontalspacing, fixed_t verticalspacing, INT16 fixedangle, boolean bonustime) +{ + mobjtype_t itemtypes[1] = { itemtype }; + return P_SpawnItemRow(mthing, itemtypes, 1, numitems, horizontalspacing, verticalspacing, fixedangle, bonustime); +} + +static void P_SpawnItemCircle(mapthing_t *mthing, mobjtype_t *itemtypes, UINT8 numitemtypes, INT32 numitems, fixed_t size, boolean bonustime) +{ + mapthing_t dummything; + mobj_t* mobj = NULL; + fixed_t x = mthing->x << FRACBITS; + fixed_t y = mthing->y << FRACBITS; + fixed_t z = mthing->z << FRACBITS; + angle_t angle = FixedAngle(mthing->angle << FRACBITS); + angle_t fa; + INT32 i; + TVector v, *res; + + (void)bonustime; + + for (i = 0; i < numitemtypes; i++) + { + dummything = *mthing; + dummything.type = mobjinfo[itemtypes[i]].doomednum; + // Skip all returning/substitution code in objectplace. + if (!objectplacing) + { + if (!P_AllowMobjSpawn(&dummything, itemtypes[i])) + { + itemtypes[i] = MT_NULL; + continue; + } + + itemtypes[i] = P_GetMobjtypeSubstitute(&dummything, itemtypes[i]); + } + } + z = P_GetMobjSpawnHeight(itemtypes[0], x, y, z, 0, false, mthing->scale); + + for (i = 0; i < numitems; i++) + { + mobjtype_t itemtype = itemtypes[i % numitemtypes]; + if (itemtype == MT_NULL) + continue; + dummything.type = mobjinfo[itemtype].doomednum; + + fa = i*FINEANGLES/numitems; + v[0] = FixedMul(FINECOSINE(fa), size); + v[1] = 0; + v[2] = FixedMul(FINESINE(fa), size); + v[3] = FRACUNIT; + + res = VectorMatrixMultiply(v, *RotateZMatrix(angle)); + M_Memcpy(&v, res, sizeof(v)); + + mobj = P_SpawnMobjFromMapThing(&dummything, x + v[0], y + v[1], z + v[2], itemtype); + + if (!mobj) + continue; + + mobj->z -= mobj->height/2; + mobj->spawnpoint = NULL; + } +} + +void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime) +{ + switch (mthing->type) + { // Special placement patterns - // *** - - // Vertical Rings - Stack of 5 (handles both red and yellow) - else if (mthing->type == 600 || mthing->type == 601) + case 600: // 5 vertical rings (yellow spring) + P_SpawnSingularItemRow(mthing, MT_RING, 5, 0, 64*FRACUNIT, 0, bonustime); + return; + case 601: // 5 vertical rings (red spring) + P_SpawnSingularItemRow(mthing, MT_RING, 5, 0, 128*FRACUNIT, 0, bonustime); + return; + case 602: // 5 diagonal rings (yellow spring) + P_SpawnSingularItemRow(mthing, MT_RING, 5, 64*FRACUNIT, 64*FRACUNIT, mthing->angle, bonustime); + return; + case 603: // 10 diagonal rings (red spring) + P_SpawnSingularItemRow(mthing, MT_RING, 10, 64*FRACUNIT, 64*FRACUNIT, mthing->angle, bonustime); + return; + case 604: // Circle of rings (8 items) + case 605: // Circle of rings (16 items) { - INT32 dist = 64*FRACUNIT; - mobjtype_t ringthing = MT_RING; - if (mthing->type == 601) - dist = 128*FRACUNIT; - - // No rings in Ultimate! - if (ultimatemode && !(G_IsSpecialStage(gamemap) || maptol & TOL_NIGHTS)) - return; - - // Spawn rings as blue spheres in special stages, ala S3+K. - if (G_IsSpecialStage(gamemap) && useNightsSS) - ringthing = MT_BLUEBALL; - - for (r = 1; r <= 5; r++) - { - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height - dist*r; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight) + dist*r; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - } - - mobj = P_SpawnMobj(x, y, z, ringthing); - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - } - } - // Diagonal rings (handles both types) - else if (mthing->type == 602 || mthing->type == 603) // Diagonal rings (5) - { - angle_t angle = FixedAngle(mthing->angle*FRACUNIT); - mobjtype_t ringthing = MT_RING; - INT32 iterations = 5; - if (mthing->type == 603) - iterations = 10; - - // No rings in Ultimate! - if (ultimatemode && !(G_IsSpecialStage(gamemap) || maptol & TOL_NIGHTS)) - return; - - // Spawn rings as blue spheres in special stages, ala S3+K. - if (G_IsSpecialStage(gamemap) && useNightsSS) - ringthing = MT_BLUEBALL; - - angle >>= ANGLETOFINESHIFT; - - for (r = 1; r <= iterations; r++) - { - x += FixedMul(64*FRACUNIT, FINECOSINE(angle)); - y += FixedMul(64*FRACUNIT, FINESINE(angle)); - - if (mthing->options & MTF_OBJECTFLIP) - { - z = ( -#ifdef ESLOPE - sec->c_slope ? P_GetZAt(sec->c_slope, x, y) : -#endif - sec->ceilingheight) - mobjinfo[ringthing].height - 64*FRACUNIT*r; - if (mthing->options >> ZSHIFT) - z -= ((mthing->options >> ZSHIFT) << FRACBITS); - } - else - { - z = ( -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight) + 64*FRACUNIT*r; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - } - - mobj = P_SpawnMobj(x, y, z, ringthing); - - if (mthing->options & MTF_OBJECTFLIP) - { - mobj->eflags |= MFE_VERTICALFLIP; - mobj->flags2 |= MF2_OBJECTFLIP; - } - - mobj->angle = FixedAngle(mthing->angle*FRACUNIT); - if (mthing->options & MTF_AMBUSH) - mobj->flags2 |= MF2_AMBUSH; - } - } - // Rings of items (all six of them) - else if (mthing->type >= 604 && mthing->type <= 609) - { - INT32 numitems = 8; - INT32 size = 96*FRACUNIT; - mobjtype_t itemToSpawn = MT_NIGHTSWING; - - if (mthing->type & 1) - { - numitems = 16; - size = 192*FRACUNIT; - } - - z = -#ifdef ESLOPE - sec->f_slope ? P_GetZAt(sec->f_slope, x, y) : -#endif - sec->floorheight; - if (mthing->options >> ZSHIFT) - z += ((mthing->options >> ZSHIFT) << FRACBITS); - - closestangle = FixedAngle(mthing->angle*FRACUNIT); - - // Create the hoop! - for (i = 0; i < numitems; i++) - { - switch (mthing->type) - { - case 604: - case 605: - itemToSpawn = MT_RING; - break; - case 608: - case 609: - itemToSpawn = (i & 1) ? MT_NIGHTSWING : MT_RING; - break; - case 606: - case 607: - itemToSpawn = MT_NIGHTSWING; - break; - default: - break; - } - - // No rings in Ultimate! - if (itemToSpawn == MT_RING) - { - if (ultimatemode && !(G_IsSpecialStage(gamemap) || (maptol & TOL_NIGHTS))) - continue; - - // Spawn rings as blue spheres in special stages, ala S3+K. - if (G_IsSpecialStage(gamemap) && useNightsSS) - itemToSpawn = MT_BLUEBALL; - } - - fa = i*FINEANGLES/numitems; - v[0] = FixedMul(FINECOSINE(fa),size); - v[1] = 0; - v[2] = FixedMul(FINESINE(fa),size); - v[3] = FRACUNIT; - - res = VectorMatrixMultiply(v, *RotateZMatrix(closestangle)); - M_Memcpy(&v, res, sizeof (v)); - - finalx = x + v[0]; - finaly = y + v[1]; - finalz = z + v[2]; - - mobj = P_SpawnMobj(finalx, finaly, finalz, itemToSpawn); - mobj->z -= mobj->height/2; - - if (itemToSpawn == MT_NIGHTSWING) - { - if (G_IsSpecialStage(gamemap) && useNightsSS) - P_SetMobjState(mobj, mobj->info->meleestate); - else if ((maptol & TOL_XMAS)) - P_SetMobjState(mobj, mobj->info->seestate); - } - } + INT32 numitems = (mthing->type & 1) ? 16 : 8; + fixed_t size = (mthing->type & 1) ? 192*FRACUNIT : 96*FRACUNIT; + mobjtype_t itemtypes[1] = { MT_RING }; + P_SpawnItemCircle(mthing, itemtypes, 1, numitems, size, bonustime); + return; + } + default: return; } - else return; } // @@ -14012,7 +12345,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai { mobj_t *th; angle_t an; - fixed_t x, y, z, slope = 0; + fixed_t x, y, z, slope = 0, speed; // angle at which you fire, is player angle an = angle; @@ -14044,9 +12377,11 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai P_SetTarget(&th->target, source); + speed = th->info->speed; + th->angle = an; - th->momx = FixedMul(th->info->speed, FINECOSINE(an>>ANGLETOFINESHIFT)); - th->momy = FixedMul(th->info->speed, FINESINE(an>>ANGLETOFINESHIFT)); + th->momx = FixedMul(speed, FINECOSINE(an>>ANGLETOFINESHIFT)); + th->momy = FixedMul(speed, FINESINE(an>>ANGLETOFINESHIFT)); if (allowaim) { @@ -14054,7 +12389,7 @@ mobj_t *P_SPMAngle(mobj_t *source, mobjtype_t type, angle_t angle, UINT8 allowai th->momy = FixedMul(th->momy,FINECOSINE(source->player->aiming>>ANGLETOFINESHIFT)); } - th->momz = FixedMul(th->info->speed, slope); + th->momz = FixedMul(speed, slope); //scaling done here so it doesn't clutter up the code above th->momx = FixedMul(th->momx, th->scale); @@ -14077,3 +12412,34 @@ void P_FlashPal(player_t *pl, UINT16 type, UINT16 duration) pl->flashcount = duration; pl->flashpal = type; } + +// +// P_SpawnMobjFromMobj +// Spawns an object with offsets relative to the position of another object. +// Scale, gravity flip, etc. is taken into account automatically. +// +mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zofs, mobjtype_t type) +{ + mobj_t *newmobj; + + xofs = FixedMul(xofs, mobj->scale); + yofs = FixedMul(yofs, mobj->scale); + zofs = FixedMul(zofs, mobj->scale); + + newmobj = P_SpawnMobj(mobj->x + xofs, mobj->y + yofs, mobj->z + zofs, type); + if (!newmobj) + return NULL; + + if (mobj->eflags & MFE_VERTICALFLIP) + { + fixed_t elementheight = FixedMul(newmobj->info->height, mobj->scale); + + newmobj->eflags |= MFE_VERTICALFLIP; + newmobj->flags2 |= MF2_OBJECTFLIP; + newmobj->z = mobj->z + mobj->height - zofs - elementheight; + } + + newmobj->destscale = mobj->destscale; + P_SetScale(newmobj, mobj->scale); + return newmobj; +} diff --git a/src/p_mobj.h b/src/p_mobj.h index dbb3f4d58..6ffa393aa 100644 --- a/src/p_mobj.h +++ b/src/p_mobj.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -133,36 +133,31 @@ typedef enum MF_MISSILE = 1<<15, // Item is a spring. MF_SPRING = 1<<16, - // Bounce off walls and things. - MF_BOUNCE = 1<<17, // Item box - MF_MONITOR = 1<<18, + MF_MONITOR = 1<<17, // Don't run the thinker for this object. - MF_NOTHINK = 1<<19, - // Fire object. Doesn't harm if you have fire shield. - MF_FIRE = 1<<20, + MF_NOTHINK = 1<<18, // Don't adjust z if below or above floorz/ceilingz - MF_NOCLIPHEIGHT = 1<<21, + MF_NOCLIPHEIGHT = 1<<19, // This mobj is an enemy! - MF_ENEMY = 1<<22, + MF_ENEMY = 1<<20, // Scenery (uses scenery thinker). - MF_SCENERY = 1<<23, + MF_SCENERY = 1<<21, // Painful (shit hurts). - MF_PAIN = 1<<24, + MF_PAIN = 1<<22, // This mobj will stick to any surface or solid object it touches. - MF_STICKY = 1<<25, - // NiGHTS hidden item. Goes to seestate and turns MF_SPECIAL when paralooped. - MF_NIGHTSITEM = 1<<26, + MF_STICKY = 1<<23, + // NiGHTS hidden item. Goes to seestate and turns MF_SPECIAL when paralooped. + MF_NIGHTSITEM = 1<<24, // for chase camera, don't be blocked by things (partial clipping) - // (need comma at end of this for SOC editor) - MF_NOCLIPTHING = 1<<27, + MF_NOCLIPTHING = 1<<25, // Missile bounces like a grenade. - MF_GRENADEBOUNCE = 1<<28, + MF_GRENADEBOUNCE = 1<<26, // Run the action thinker on spawn. - MF_RUNSPAWNFUNC = 1<<29, + MF_RUNSPAWNFUNC = 1<<27, // Don't remap in Encore mode. (Not a drawflag so that it's settable by mobjinfo.) - MF_DONTENCOREMAP = 1<<30, - // free: 1<<31 + MF_DONTENCOREMAP = 1<<28, + // free: to and including 1<<31 } mobjflag_t; typedef enum @@ -177,25 +172,26 @@ typedef enum MF2_EXPLOSION = 1<<7, // Thrown ring has explosive properties MF2_SCATTER = 1<<8, // Thrown ring has scatter properties MF2_BEYONDTHEGRAVE = 1<<9, // Source of this missile has died and has since respawned. - MF2_PUSHED = 1<<10, // Mobj was already pushed this tic - MF2_SLIDEPUSH = 1<<11, // MF_PUSHABLE that pushes continuously. - MF2_CLASSICPUSH = 1<<12, // Drops straight down when object has negative Z. - MF2_STANDONME = 1<<13, // While not pushable, stand on me anyway. - MF2_INFLOAT = 1<<14, // Floating to a height for a move, don't auto float to target's height. - MF2_DEBRIS = 1<<15, // Splash ring from explosion ring - MF2_NIGHTSPULL = 1<<16, // Attracted from a paraloop - MF2_JUSTATTACKED = 1<<17, // can be pushed by other moving mobjs - MF2_FIRING = 1<<18, // turret fire - MF2_SUPERFIRE = 1<<19, // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it. - // free: 1<<20 - MF2_STRONGBOX = 1<<21, // Flag used for "strong" random monitors. - MF2_OBJECTFLIP = 1<<22, // Flag for objects that always have flipped gravity. - MF2_SKULLFLY = 1<<23, // Special handling: skull in flight. - MF2_FRET = 1<<24, // Flashing from a previous hit - MF2_BOSSNOTRAP = 1<<25, // No Egg Trap after boss - MF2_BOSSFLEE = 1<<26, // Boss is fleeing! - MF2_BOSSDEAD = 1<<27, // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.) - MF2_AMBUSH = 1<<28, // Alternate behaviour typically set by MTF_AMBUSH + MF2_SLIDEPUSH = 1<<10, // MF_PUSHABLE that pushes continuously. + MF2_CLASSICPUSH = 1<<11, // Drops straight down when object has negative momz. + MF2_INVERTAIMABLE = 1<<12, // Flips whether it's targetable by A_LookForEnemies (enemies no, decoys yes) + MF2_INFLOAT = 1<<13, // Floating to a height for a move, don't auto float to target's height. + MF2_DEBRIS = 1<<14, // Splash ring from explosion ring + MF2_NIGHTSPULL = 1<<15, // Attracted from a paraloop + MF2_JUSTATTACKED = 1<<16, // can be pushed by other moving mobjs + MF2_FIRING = 1<<17, // turret fire + MF2_SUPERFIRE = 1<<18, // Firing something with Super Sonic-stopping properties. Or, if mobj has MF_MISSILE, this is the actual fire from it. + // free: 1<<19 + MF2_STRONGBOX = 1<<20, // Flag used for "strong" random monitors. + MF2_OBJECTFLIP = 1<<21, // Flag for objects that always have flipped gravity. + MF2_SKULLFLY = 1<<22, // Special handling: skull in flight. + MF2_FRET = 1<<23, // Flashing from a previous hit + MF2_BOSSNOTRAP = 1<<24, // No Egg Trap after boss + MF2_BOSSFLEE = 1<<25, // Boss is fleeing! + MF2_BOSSDEAD = 1<<26, // Boss is dead! (Not necessarily fleeing, if a fleeing point doesn't exist.) + MF2_AMBUSH = 1<<27, // Alternate behaviour typically set by MTF_AMBUSH + MF2_LINKDRAW = 1<<28, // Draw vissprite of mobj immediately before/after tracer's vissprite (dependent on dispoffset and position) + MF2_SHIELD = 1<<29, // Thinker calls P_AddShield/P_ShieldLook (must be partnered with MF_SCENERY to use) // free: to and including 1<<31 } mobjflag2_t; @@ -235,12 +231,19 @@ typedef enum MFE_VERTICALFLIP = 1<<5, // Goo water MFE_GOOWATER = 1<<6, - // SRB2Kart: The mobj just hit & bounced off a wall, this is cleared on next frame - MFE_JUSTBOUNCEDWALL = 1<<7, + // The mobj is touching a lava block + MFE_TOUCHLAVA = 1<<7, + // Mobj was already pushed this tic + MFE_PUSHED = 1<<8, // Mobj was already sprung this tic - MFE_SPRUNG = 1<<8, + MFE_SPRUNG = 1<<9, // Platform movement - MFE_APPLYPMOMZ = 1<<9, + MFE_APPLYPMOMZ = 1<<10, + // Compute and trigger on mobj angle relative to tracer + // See Linedef Exec 457 (Track mobj angle to point) + MFE_TRACERANGLE = 1<<11, + // SRB2Kart: The mobj just hit & bounced off a wall, this is cleared on next frame + MFE_JUSTBOUNCEDWALL = 1<<12, // free: to and including 1<<15 } mobjeflag_t; @@ -265,6 +268,8 @@ typedef enum MFD_TRANS70 = 0x0070, MFD_TRANS80 = 0x0080, MFD_TRANS90 = 0x0090, + MFD_TRANSADD = 0x00A0, + MFD_TRANSSUB = 0x00B0, MFD_TRANSMASK = 0x00F0, // Brightness override flags MFD_FULLBRIGHT = 0x0100, @@ -307,9 +312,11 @@ typedef struct mobj_s struct mobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr // More drawing info: to determine current sprite. - angle_t angle; // orientation + angle_t angle, pitch, roll; // orientation + angle_t rollangle; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h + UINT8 sprite2; // player sprites UINT16 anim_duration; // for FF_ANIMATE states struct msecnode_s *touching_sectorlist; // a linked list of sectors where this object appears @@ -319,6 +326,10 @@ typedef struct mobj_s // The closest interval over all contacted sectors (or things). fixed_t floorz; // Nearest floor below. fixed_t ceilingz; // Nearest ceiling above. + struct ffloor_s *floorrover; // FOF referred by floorz + struct ffloor_s *ceilingrover; // FOF referred by ceilingz + fixed_t floordrop; + fixed_t ceilingdrop; // For movement checking. fixed_t radius; @@ -338,7 +349,7 @@ typedef struct mobj_s void *skin; // overrides 'sprite' when non-NULL (for player bodies to 'remember' the skin) // Player and mobj sprites in multiplayer modes are modified // using an internal color lookup table for re-indexing. - UINT8 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation). + UINT16 color; // This replaces MF_TRANSLATION. Use 0 for default (no translation). // Interaction info, by BLOCKMAP. // Links in blocks (if needed). @@ -352,7 +363,7 @@ typedef struct mobj_s // One last pointer for kart item lists struct mobj_s *itnext; - INT32 health; // for player this is rings + 1 + INT32 health; // for player this is rings + 1 -- no it isn't, not any more!! // Movement direction, movement generation (zig-zagging). angle_t movedir; // dirtype_t 0-7; also used by Deton for up/down angle @@ -396,14 +407,13 @@ typedef struct mobj_s INT32 cusval; INT32 cvmem; -#ifdef ESLOPE struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?) #ifdef HWRENDER struct pslope_s *modeltilt; // Slope used for model tilting. Also is not synched, this is totally visual. -#endif #endif boolean colorized; // Whether the mobj uses the rainbow colormap + boolean mirrored; // The object's rotations will be mirrored left to right, e.g., see frame AL from the right and AR from the left fixed_t shadowscale; // If this object casts a shadow, and the size relative to radius boolean whiteshadow; // Use white shadow, set to true by default for fullbright objects @@ -436,9 +446,11 @@ typedef struct precipmobj_s struct precipmobj_s **sprev; // killough 8/11/98: change to ptr-to-ptr // More drawing info: to determine current sprite. - angle_t angle; // orientation + angle_t angle, pitch, roll; // orientation + angle_t rollangle; spritenum_t sprite; // used to find patch_t and flip value UINT32 frame; // frame number, plus bits see p_pspr.h + UINT8 sprite2; // player sprites UINT16 anim_duration; // for FF_ANIMATE states struct mprecipsecnode_s *touching_sectorlist; // a linked list of sectors where this object appears @@ -448,6 +460,8 @@ typedef struct precipmobj_s // The closest interval over all contacted sectors (or things). fixed_t floorz; // Nearest floor below. fixed_t ceilingz; // Nearest ceiling above. + struct ffloor_s *floorrover; // FOF referred by floorz + struct ffloor_s *ceilingrover; // FOF referred by ceilingz // For movement checking. fixed_t radius; // Fixed at 2*FRACUNIT @@ -493,8 +507,12 @@ void P_MovePlayerToSpawn(INT32 playernum, mapthing_t *mthing); void P_MovePlayerToStarpost(INT32 playernum); void P_AfterPlayerSpawn(INT32 playernum); -void P_SpawnMapThing(mapthing_t *mthing); -void P_SpawnHoopsAndRings(mapthing_t *mthing); +fixed_t P_GetMobjSpawnHeight(const mobjtype_t mobjtype, const fixed_t x, const fixed_t y, const fixed_t dz, const fixed_t offset, const boolean flip, const fixed_t scale); +fixed_t P_GetMapThingSpawnHeight(const mobjtype_t mobjtype, const mapthing_t* mthing, const fixed_t x, const fixed_t y); + +mobj_t *P_SpawnMapThing(mapthing_t *mthing); +void P_SpawnHoop(mapthing_t *mthing); +void P_SpawnItemPattern(mapthing_t *mthing, boolean bonustime); void P_SpawnHoopOfSomething(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, angle_t rotangle); void P_SpawnPrecipitation(void); void P_SpawnParaloop(fixed_t x, fixed_t y, fixed_t z, fixed_t radius, INT32 number, mobjtype_t type, statenum_t nstate, angle_t rotangle, boolean spawncenter); @@ -506,11 +524,22 @@ void P_NullPrecipThinker(precipmobj_t *mobj); void P_RemovePrecipMobj(precipmobj_t *mobj); void P_SetScale(mobj_t *mobj, fixed_t newscale); void P_XYMovement(mobj_t *mo); +void P_RingXYMovement(mobj_t *mo); +void P_SceneryXYMovement(mobj_t *mo); +boolean P_ZMovement(mobj_t *mo); +void P_RingZMovement(mobj_t *mo); +boolean P_SceneryZMovement(mobj_t *mo); +void P_PlayerZMovement(mobj_t *mo); void P_EmeraldManager(void); +extern INT32 modulothing; + #define MAXHUNTEMERALDS 64 extern mapthing_t *huntemeralds[MAXHUNTEMERALDS]; extern INT32 numhuntemeralds; extern boolean runemeraldmanager; +extern UINT16 emeraldspawndelay; extern INT32 numstarposts; +extern UINT16 bossdisabled; +extern boolean stoppedclock; #endif diff --git a/src/p_polyobj.c b/src/p_polyobj.c index 12708a44b..6733fca79 100644 --- a/src/p_polyobj.c +++ b/src/p_polyobj.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2018 by Sonic Team Junior. +// Copyright (C) 2006-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,8 +28,6 @@ #include "r_state.h" #include "r_defs.h" -#ifdef POLYOBJECTS - /* Theory behind Polyobjects: @@ -142,21 +140,6 @@ FUNCINLINE static ATTRINLINE void Polyobj_vecSub2(vertex_t *dst, vertex_t *v1, v dst->y = v1->y - v2->y; } -// Add the polyobject's thinker to the thinker list -// Unlike P_AddThinker, this adds it to the front of the list instead of the back, so that carrying physics can work right. -Red -FUNCINLINE static ATTRINLINE void PolyObj_AddThinker(thinker_t *th) -{ - thinkercap.next->prev = th; - th->next = thinkercap.next; - th->prev = &thinkercap; - thinkercap.next = th; -} - -// -// P_PointInsidePolyobj -// -// Returns TRUE if the XY point is inside the polyobject -// boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y) { size_t i; @@ -170,11 +153,6 @@ boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y) return true; } -// -// P_MobjTouchingPolyobj -// -// Returns TRUE if the mobj is touching the edge of a polyobject -// boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo) { fixed_t mbbox[4]; @@ -194,11 +172,6 @@ boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo) return false; } -// -// P_MobjInsidePolyobj -// -// Returns TRUE if the mobj is inside the polyobject -// boolean P_MobjInsidePolyobj(polyobj_t *po, mobj_t *mo) { fixed_t mbbox[4]; @@ -218,11 +191,6 @@ boolean P_MobjInsidePolyobj(polyobj_t *po, mobj_t *mo) return true; } -// -// P_BBoxInsidePolyobj -// -// Returns TRUE if the bbox is inside the polyobject -// boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox) { size_t i; @@ -236,40 +204,53 @@ boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox) return true; } -// -// Polyobj_GetInfo -// -// Finds the 'polyobject settings' linedef that shares the same tag -// as the polyobj linedef to get the settings for it. -// -void Polyobj_GetInfo(INT16 tag, INT32 *polyID, INT32 *mirrorID, UINT16 *exparg) +// Gets the polyobject's settings from its first line +// args[0] of the first line should be the polyobject's id +static void Polyobj_GetInfo(polyobj_t *po, line_t *line) { - INT32 i = P_FindSpecialLineFromTag(POLYINFO_SPECIALNUM, tag, -1); + po->parent = line->args[1]; + if (po->parent == po->id) // do not allow a self-reference + po->parent = -1; - if (i == -1) - I_Error("Polyobject (tag: %d) needs line %d for information.\n", tag, POLYINFO_SPECIALNUM); + po->translucency = max(min(line->args[2], NUMEFFECTMAPS), 0); - if (polyID) - *polyID = lines[i].frontsector->floorheight>>FRACBITS; + po->flags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES|POF_RENDERPLANES; - if (mirrorID) - *mirrorID = lines[i].frontsector->special; + if (line->args[3] & TMPF_NOINSIDES) + po->flags |= POF_ONESIDE; - if (exparg) - *exparg = (UINT16)lines[i].frontsector->lightlevel; + if (line->args[3] & TMPF_INTANGIBLE) + po->flags &= ~POF_SOLID; + + if (line->args[3] & TMPF_PUSHABLESTOP) + po->flags |= POF_PUSHABLESTOP; + + if (line->args[3] & TMPF_INVISIBLEPLANES) + po->flags &= ~POF_RENDERPLANES; + + /*if (line->args[3] & TMPF_DONTCLIPPLANES) + po->flags &= ~POF_CLIPPLANES;*/ + + if (line->args[3] & TMPF_SPLAT) + po->flags |= POF_SPLAT; + + if (line->args[3] & TMPF_EXECUTOR) // Has a linedef executor + po->flags |= POF_LDEXEC; + + // TODO: support customized damage somehow? + if (line->args[3] & TMPF_CRUSH) + po->damage = 3; + + po->triggertag = line->args[4]; } // Reallocating array maintenance -// -// Polyobj_addVertex -// // Adds a vertex to a polyobject's reallocating vertex arrays, provided // that such a vertex isn't already in the array. Each vertex must only // be translated once during polyobject movement. Keeping track of them // this way results in much more clear and efficient code than what // Hexen used. -// static void Polyobj_addVertex(polyobj_t *po, vertex_t *v) { size_t i; @@ -305,14 +286,10 @@ static void Polyobj_addVertex(polyobj_t *po, vertex_t *v) po->numVertices++; } -// -// Polyobj_addLine -// // Adds a linedef to a polyobject's reallocating linedefs array, provided // that such a linedef isn't already in the array. Each linedef must only // be adjusted once during polyobject movement. Keeping track of them // this way provides the same benefits as for vertices. -// static void Polyobj_addLine(polyobj_t *po, line_t *l) { size_t i; @@ -337,14 +314,10 @@ static void Polyobj_addLine(polyobj_t *po, line_t *l) po->lines[po->numLines++] = l; } -// -// Polyobj_addSeg -// // Adds a single seg to a polyobject's reallocating seg pointer array. // Most polyobjects will have between 4 and 16 segs, so the array size // begins much smaller than usual. Calls Polyobj_addVertex and Polyobj_addLine // to add those respective structures for this seg, as well. -// static void Polyobj_addSeg(polyobj_t *po, seg_t *seg) { if (po->segCount >= po->numSegsAlloc) @@ -370,14 +343,10 @@ static void Polyobj_addSeg(polyobj_t *po, seg_t *seg) // Seg-finding functions -// -// Polyobj_findSegs -// // This method adds segs to a polyobject by following segs from vertex to // vertex. The process stops when the original starting point is reached // or if a particular search ends unexpectedly (ie, the polyobject is not // closed). -// static void Polyobj_findSegs(polyobj_t *po, seg_t *seg) { fixed_t startx, starty; @@ -391,23 +360,29 @@ static void Polyobj_findSegs(polyobj_t *po, seg_t *seg) // Find backfacings for (s = 0; s < numsegs; s++) { - if (segs[s].linedef == seg->linedef - && segs[s].side == 1) + size_t r; + + if (segs[s].glseg) + continue; + + if (segs[s].linedef != seg->linedef) + continue; + + if (segs[s].side != 1) + continue; + + for (r = 0; r < po->segCount; r++) { - size_t r; - for (r = 0; r < po->segCount; r++) - { - if (po->segs[r] == &segs[s]) - break; - } - - if (r != po->segCount) - continue; - - segs[s].dontrenderme = true; - - Polyobj_addSeg(po, &segs[s]); + if (po->segs[r] == &segs[s]) + break; } + + if (r != po->segCount) + continue; + + segs[s].dontrenderme = true; + + Polyobj_addSeg(po, &segs[s]); } } @@ -427,51 +402,60 @@ newseg: // seg's ending vertex. for (i = 0; i < numsegs; ++i) { + size_t q; + + if (segs[i].glseg) + continue; if (segs[i].side != 0) // needs to be frontfacing continue; - if (segs[i].v1->x == seg->v2->x && segs[i].v1->y == seg->v2->y) + if (segs[i].v1->x != seg->v2->x) + continue; + if (segs[i].v1->y != seg->v2->y) + continue; + + // Make sure you didn't already add this seg... + for (q = 0; q < po->segCount; q++) { - // Make sure you didn't already add this seg... - size_t q; - for (q = 0; q < po->segCount; q++) - { - if (po->segs[q] == &segs[i]) - break; - } - - if (q != po->segCount) - continue; - - // add the new seg and recurse - Polyobj_addSeg(po, &segs[i]); - seg = &segs[i]; - - if (!(po->flags & POF_ONESIDE)) - { - // Find backfacings - for (q = 0; q < numsegs; q++) - { - if (segs[q].linedef == segs[i].linedef - && segs[q].side == 1) - { - size_t r; - for (r=0; r < po->segCount; r++) - { - if (po->segs[r] == &segs[q]) - break; - } - - if (r != po->segCount) - continue; - - segs[q].dontrenderme = true; - Polyobj_addSeg(po, &segs[q]); - } - } - } - - goto newseg; + if (po->segs[q] == &segs[i]) + break; } + + if (q != po->segCount) + continue; + + // add the new seg and recurse + Polyobj_addSeg(po, &segs[i]); + seg = &segs[i]; + + if (!(po->flags & POF_ONESIDE)) + { + // Find backfacings + for (q = 0; q < numsegs; q++) + { + size_t r; + + if (segs[q].glseg) + continue; + if (segs[q].linedef != segs[i].linedef) + continue; + if (segs[q].side != 1) + continue; + + for (r = 0; r < po->segCount; r++) + { + if (po->segs[r] == &segs[q]) + break; + } + + if (r != po->segCount) + continue; + + segs[q].dontrenderme = true; + Polyobj_addSeg(po, &segs[q]); + } + } + + goto newseg; } // error: if we reach here, the seg search never found another seg to @@ -480,90 +464,8 @@ newseg: CONS_Debug(DBG_POLYOBJ, "Polyobject %d is not closed\n", po->id); } -// structure used to store segs during explicit search process -typedef struct segitem_s -{ - seg_t *seg; - INT32 num; -} segitem_t; - -// -// Polyobj_segCompare -// -// Callback for qsort that compares two segitems. -// -static int Polyobj_segCompare(const void *s1, const void *s2) -{ - const segitem_t *si1 = s1; - const segitem_t *si2 = s2; - - return si2->num - si1->num; -} - -// -// Polyobj_findExplicit -// -// Searches for segs to put into a polyobject in an explicitly provided order. -// -static void Polyobj_findExplicit(polyobj_t *po) -{ - // temporary dynamic seg array - segitem_t *segitems = NULL; - size_t numSegItems = 0; - size_t numSegItemsAlloc = 0; - - size_t i; - - // first loop: save off all segs with polyobject's id number - for (i = 0; i < numsegs; ++i) - { - INT32 polyID, parentID; - - if (segs[i].linedef->special != POLYOBJ_EXPLICIT_LINE) - continue; - - Polyobj_GetInfo(segs[i].linedef->tag, &polyID, &parentID, NULL); - - if (polyID == po->id && parentID > 0) - { - if (numSegItems >= numSegItemsAlloc) - { - numSegItemsAlloc = numSegItemsAlloc ? numSegItemsAlloc*2 : 4; - segitems = Z_Realloc(segitems, numSegItemsAlloc*sizeof(segitem_t), PU_STATIC, NULL); - } - segitems[numSegItems].seg = &segs[i]; - segitems[numSegItems].num = parentID; - ++numSegItems; - } - } - - // make sure array isn't empty - if (numSegItems == 0) - { - po->isBad = true; - CONS_Debug(DBG_POLYOBJ, "Polyobject %d is empty\n", po->id); - return; - } - - // sort the array if necessary - if (numSegItems >= 2) - qsort(segitems, numSegItems, sizeof(segitem_t), Polyobj_segCompare); - - // second loop: put the sorted segs into the polyobject - for (i = 0; i < numSegItems; ++i) - Polyobj_addSeg(po, segitems[i].seg); - - // free the temporary array - Z_Free(segitems); -} - // Setup functions -// -// Polyobj_spawnPolyObj -// -// Sets up a Polyobject. -// static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id) { size_t i; @@ -578,22 +480,20 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id) po->id = id; - // TODO: support customized damage somehow? - if (spawnSpot->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM) - po->damage = 3; - // set to default thrust; may be modified by attached thinkers // TODO: support customized thrust? po->thrust = FRACUNIT; po->spawnflags = po->flags = 0; - // 1. Search segs for "line start" special with tag matching this - // polyobject's id number. If found, iterate through segs which - // share common vertices and record them into the polyobject. + // Search segs for "line start" special with tag matching this + // polyobject's id number. If found, iterate through segs which + // share common vertices and record them into the polyobject. for (i = 0; i < numsegs; ++i) { seg_t *seg = &segs[i]; - INT32 polyID, parentID; + + if (seg->glseg) + continue; if (seg->side != 0) // needs to be frontfacing continue; @@ -601,42 +501,17 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id) if (seg->linedef->special != POLYOBJ_START_LINE) continue; - Polyobj_GetInfo(seg->linedef->tag, &polyID, &parentID, NULL); + if (seg->linedef->args[0] != po->id) + continue; - // is it a START line with this polyobject's id? - if (polyID == po->id) - { - po->flags = POF_SOLID|POF_TESTHEIGHT|POF_RENDERSIDES; + Polyobj_GetInfo(po, seg->linedef); // apply extra settings if they exist! - if (seg->linedef->flags & ML_EFFECT1) - po->flags |= POF_ONESIDE; + // save original flags and translucency to reference later for netgames! + po->spawnflags = po->flags; + po->spawntrans = po->translucency; - if (seg->linedef->flags & ML_EFFECT2) - po->flags &= ~POF_SOLID; - - if (seg->linedef->flags & ML_EFFECT3) - po->flags |= POF_PUSHABLESTOP; - - if (seg->linedef->flags & ML_EFFECT4) - po->flags |= POF_RENDERPLANES; - - // TODO: Use a different linedef flag for this if we really need it!! - // This clashes with texture tiling, also done by Effect 5 flag - /*if (seg->linedef->flags & ML_EFFECT5) - po->flags &= ~POF_CLIPPLANES;*/ - - if (seg->linedef->flags & ML_NOCLIMB) // Has a linedef executor - po->flags |= POF_LDEXEC; - - po->spawnflags = po->flags; // save original flags to reference later for netgames! - - Polyobj_findSegs(po, seg); - po->parent = parentID; - if (po->parent == po->id) // do not allow a self-reference - po->parent = -1; - // TODO: sound sequence is in args[2] - break; - } + Polyobj_findSegs(po, seg); + break; } CONS_Debug(DBG_POLYOBJ, "PO ID: %d; Num verts: %s\n", po->id, sizeu1(po->numVertices)); @@ -645,27 +520,14 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id) if (po->isBad) return; - // 2. If no such line existed in the first step, look for a seg with the - // "explicit" special with tag matching this polyobject's id number. If - // found, continue to search for all such lines, storing them in a - // temporary list of segs which is then copied into the polyobject in - // sorted order. + // make sure array isn't empty if (po->segCount == 0) { - UINT16 parent; - Polyobj_findExplicit(po); - // if an error occurred above, quit processing this object - if (po->isBad) - return; - - Polyobj_GetInfo(po->segs[0]->linedef->tag, NULL, NULL, &parent); - po->parent = parent; - if (po->parent == po->id) // do not allow a self-reference - po->parent = -1; - // TODO: sound sequence is in args[3] + po->isBad = true; + CONS_Debug(DBG_POLYOBJ, "Polyobject %d is empty\n", po->id); + return; } - // set the polyobject's spawn spot po->spawnSpot.x = spawnSpot->x; po->spawnSpot.y = spawnSpot->y; @@ -687,21 +549,17 @@ static void Polyobj_spawnPolyObj(INT32 num, mobj_t *spawnSpot, INT32 id) static void Polyobj_attachToSubsec(polyobj_t *po); -// -// Polyobj_moveToSpawnSpot -// // Translates the polyobject's vertices with respect to the difference between // the anchor and spawn spots. Updates linedef bounding boxes as well. -// static void Polyobj_moveToSpawnSpot(mapthing_t *anchor) { polyobj_t *po; vertex_t dist, sspot; size_t i; - if (!(po = Polyobj_GetForNum(anchor->angle))) + if (!(po = Polyobj_GetForNum(anchor->tag))) { - CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->angle); + CONS_Debug(DBG_POLYOBJ, "Bad polyobject %d for anchor point\n", anchor->tag); return; } @@ -739,11 +597,7 @@ static void Polyobj_moveToSpawnSpot(mapthing_t *anchor) Polyobj_attachToSubsec(po); } -// -// Polyobj_attachToSubsec -// // Attaches a polyobject to its appropriate subsector. -// static void Polyobj_attachToSubsec(polyobj_t *po) { subsector_t *ss; @@ -778,11 +632,7 @@ static void Polyobj_attachToSubsec(polyobj_t *po) po->attached = true; } -// -// Polyobj_removeFromSubsec -// // Removes a polyobject from the subsector to which it is attached. -// static void Polyobj_removeFromSubsec(polyobj_t *po) { if (po->attached) @@ -794,11 +644,7 @@ static void Polyobj_removeFromSubsec(polyobj_t *po) // Blockmap Functions -// -// Polyobj_getLink -// // Retrieves a polymaplink object from the free list or creates a new one. -// static polymaplink_t *Polyobj_getLink(void) { polymaplink_t *l; @@ -817,11 +663,7 @@ static polymaplink_t *Polyobj_getLink(void) return l; } -// -// Polyobj_putLink -// // Puts a polymaplink object into the free list. -// static void Polyobj_putLink(polymaplink_t *l) { memset(l, 0, sizeof(*l)); @@ -829,14 +671,10 @@ static void Polyobj_putLink(polymaplink_t *l) bmap_freelist = l; } -// -// Polyobj_linkToBlockmap -// // Inserts a polyobject into the polyobject blockmap. Unlike, mobj_t's, // polyobjects need to be linked into every blockmap cell which their // bounding box intersects. This ensures the accurate level of clipping // which is present with linedefs but absent from most mobj interactions. -// static void Polyobj_linkToBlockmap(polyobj_t *po) { fixed_t *blockbox = po->blockbox; @@ -881,12 +719,8 @@ static void Polyobj_linkToBlockmap(polyobj_t *po) po->linked = true; } -// -// Polyobj_removeFromBlockmap -// // Unlinks a polyobject from all blockmap cells it intersects and returns // its polymaplink objects to the free list. -// static void Polyobj_removeFromBlockmap(polyobj_t *po) { polymaplink_t *rover; @@ -925,13 +759,9 @@ static void Polyobj_removeFromBlockmap(polyobj_t *po) // Movement functions -// -// Polyobj_untouched -// // A version of Lee's routine from p_maputl.c that accepts an mobj pointer // argument instead of using tmthing. Returns true if the line isn't contacted // and false otherwise. -// static inline boolean Polyobj_untouched(line_t *ld, mobj_t *mo) { fixed_t x, y, ptmbbox[4]; @@ -944,13 +774,9 @@ static inline boolean Polyobj_untouched(line_t *ld, mobj_t *mo) P_BoxOnLineSide(ptmbbox, ld) != -1; } -// -// Polyobj_pushThing -// // Inflicts thrust and possibly damage on a thing which has been found to be // blocking the motion of a polyobject. The default thrust amount is only one // unit, but the motion of the polyobject can be used to change this. -// static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo) { angle_t lineangle; @@ -980,32 +806,43 @@ static void Polyobj_pushThing(polyobj_t *po, line_t *line, mobj_t *mo) P_CheckPosition(mo, mo->x + momx, mo->y + momy); mo->floorz = tmfloorz; mo->ceilingz = tmceilingz; + mo->floorrover = tmfloorrover; + mo->ceilingrover = tmceilingrover; } } -// -// Polyobj_slideThing -// // Moves an object resting on top of a polyobject by (x, y). Template function to make alteration easier. -// static void Polyobj_slideThing(mobj_t *mo, fixed_t dx, fixed_t dy) { - if (mo->player) { // Do something similar to conveyor movement. -Red - mo->player->cmomx += dx; - mo->player->cmomy += dy; + if (mo->player) { // Finally this doesn't suck eggs -fickle + fixed_t cdx, cdy; - dx = FixedMul(dx, CARRYFACTOR); - dy = FixedMul(dy, CARRYFACTOR); + cdx = FixedMul(dx, FRACUNIT-CARRYFACTOR); + cdy = FixedMul(dy, FRACUNIT-CARRYFACTOR); - mo->player->cmomx -= dx; - mo->player->cmomy -= dy; + if (mo->player->onconveyor == 1) + { + mo->momx += cdx; + mo->momy += cdy; - if (mo->player->pflags & PF_SPINNING && (mo->player->rmomx || mo->player->rmomy) && !(mo->player->pflags & PF_STARTDASH)) { -#define SPINMULT 5184 // Consider this a substitute for properly calculating FRACUNIT-friction. I'm tired. -Red - dx = FixedMul(dx, SPINMULT); - dy = FixedMul(dy, SPINMULT); -#undef SPINMULT + // Multiple slides in the same tic, somehow + mo->player->cmomx += cdx; + mo->player->cmomy += cdy; } + else + { + if (mo->player->onconveyor == 3) + { + mo->momx += cdx - mo->player->cmomx; + mo->momy += cdy - mo->player->cmomy; + } + + mo->player->cmomx = cdx; + mo->player->cmomy = cdy; + } + + dx = FixedMul(dx, FRACUNIT - mo->friction); + dy = FixedMul(dy, FRACUNIT - mo->friction); mo->momx += dx; mo->momy += dy; @@ -1015,11 +852,7 @@ static void Polyobj_slideThing(mobj_t *mo, fixed_t dx, fixed_t dy) P_TryMove(mo, mo->x+dx, mo->y+dy, true); } -// -// Polyobj_carryThings -// // Causes objects resting on top of the polyobject to 'ride' with its movement. -// static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy) { static INT32 pomovecount = 0; @@ -1071,12 +904,8 @@ static void Polyobj_carryThings(polyobj_t *po, fixed_t dx, fixed_t dy) } } -// -// Polyobj_clipThings -// // Checks for things that are in the way of a polyobject line move. // Returns true if something was hit. -// static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) { INT32 hitflags = 0; @@ -1138,12 +967,9 @@ static INT32 Polyobj_clipThings(polyobj_t *po, line_t *line) return hitflags; } -// -// Polyobj_moveXY -// + // Moves a polyobject on the x-y plane. -// -static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y) +boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs) { size_t i; vertex_t vec; @@ -1164,9 +990,12 @@ static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y) for (i = 0; i < po->numLines; ++i) Polyobj_bboxAdd(po->lines[i]->bbox, &vec); - // check for blocking things (yes, it needs to be done separately) - for (i = 0; i < po->numLines; ++i) - hitflags |= Polyobj_clipThings(po, po->lines[i]); + if (checkmobjs) + { + // check for blocking things (yes, it needs to be done separately) + for (i = 0; i < po->numLines; ++i) + hitflags |= Polyobj_clipThings(po, po->lines[i]); + } if (hitflags & 2) { @@ -1184,7 +1013,8 @@ static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y) po->spawnSpot.x += vec.x; po->spawnSpot.y += vec.y; - Polyobj_carryThings(po, x, y); + if (checkmobjs) + Polyobj_carryThings(po, x, y); Polyobj_removeFromBlockmap(po); // unlink it from the blockmap Polyobj_removeFromSubsec(po); // unlink it from its subsector Polyobj_linkToBlockmap(po); // relink to blockmap @@ -1194,15 +1024,11 @@ static boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y) return !(hitflags & 2); } -// -// Polyobj_rotatePoint -// // Rotates a point and then translates it relative to point c. // The formula for this can be found here: // http://www.inversereality.org/tutorials/graphics%20programming/2dtransformations.html // It is, of course, just a vector-matrix multiplication. -// -static inline void Polyobj_rotatePoint(vertex_t *v, const vertex_t *c, angle_t ang) +static inline void Polyobj_rotatePoint(vertex_t *v, const vector2_t *c, angle_t ang) { vertex_t tmp = *v; @@ -1213,12 +1039,8 @@ static inline void Polyobj_rotatePoint(vertex_t *v, const vertex_t *c, angle_t a v->y += c->y; } -// -// Polyobj_rotateLine -// // Taken from P_LoadLineDefs; simply updates the linedef's dx, dy, slopetype, // and bounding box to be consistent with its vertices. -// static void Polyobj_rotateLine(line_t *ld) { vertex_t *v1, *v2; @@ -1232,7 +1054,7 @@ static void Polyobj_rotateLine(line_t *ld) // determine slopetype ld->slopetype = !ld->dx ? ST_VERTICAL : !ld->dy ? ST_HORIZONTAL : - FixedDiv(ld->dy, ld->dx) > 0 ? ST_POSITIVE : ST_NEGATIVE; + ((ld->dy > 0) == (ld->dx > 0)) ? ST_POSITIVE : ST_NEGATIVE; // update bounding box if (v1->x < v2->x) @@ -1258,16 +1080,13 @@ static void Polyobj_rotateLine(line_t *ld) } } -// -// Polyobj_rotateThings -// // Causes objects resting on top of the rotating polyobject to 'ride' with its movement. -// -static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta, UINT8 turnthings) +static void Polyobj_rotateThings(polyobj_t *po, vector2_t origin, angle_t delta, UINT8 turnthings) { static INT32 pomovecount = 10000; INT32 x, y; - angle_t deltafine = delta >> ANGLETOFINESHIFT; + angle_t deltafine = (((po->angle + delta) >> ANGLETOFINESHIFT) - (po->angle >> ANGLETOFINESHIFT)) & FINEMASK; + // This fineshift trickery replaces the old delta>>ANGLETOFINESHIFT; doing it this way avoids loss of precision causing objects to slide off -fickle pomovecount++; @@ -1319,30 +1138,15 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta, oldxoff = mo->x-origin.x; oldyoff = mo->y-origin.y; - if (mo->player) // Hack to fix players sliding off of spinning polys -Red - { - fixed_t temp; + newxoff = FixedMul(oldxoff, c)-FixedMul(oldyoff, s) - oldxoff; + newyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s) - oldyoff; - temp = FixedMul(oldxoff, c)-FixedMul(oldyoff, s); - oldyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s); - oldxoff = temp; - } - - newxoff = FixedMul(oldxoff, c)-FixedMul(oldyoff, s); - newyoff = FixedMul(oldyoff, c)+FixedMul(oldxoff, s); - - Polyobj_slideThing(mo, newxoff-oldxoff, newyoff-oldyoff); + Polyobj_slideThing(mo, newxoff, newyoff); if (turnthings == 2 || (turnthings == 1 && !mo->player)) { mo->angle += delta; - if (mo->player == &players[consoleplayer]) - localangle[0] += delta; - else if (mo->player == &players[displayplayers[1]]) - localangle[1] += delta; - else if (mo->player == &players[displayplayers[2]]) - localangle[2] += delta; - else if (mo->player == &players[displayplayers[3]]) - localangle[3] += delta; + if (mo->player) + P_SetPlayerAngle(mo->player, mo->player->angleturn + delta); } } } @@ -1350,16 +1154,12 @@ static void Polyobj_rotateThings(polyobj_t *po, vertex_t origin, angle_t delta, } } -// -// Polyobj_rotate -// // Rotates a polyobject around its start point. -// -static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings) +boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs) { size_t i; angle_t angle; - vertex_t origin; + vector2_t origin; INT32 hitflags = 0; // don't move bad polyobjects @@ -1387,11 +1187,14 @@ static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings) for (i = 0; i < po->numLines; ++i) Polyobj_rotateLine(po->lines[i]); - // check for blocking things - for (i = 0; i < po->numLines; ++i) - hitflags |= Polyobj_clipThings(po, po->lines[i]); + if (checkmobjs) + { + // check for blocking things + for (i = 0; i < po->numLines; ++i) + hitflags |= Polyobj_clipThings(po, po->lines[i]); - Polyobj_rotateThings(po, origin, delta, turnthings); + Polyobj_rotateThings(po, origin, delta, turnthings); + } if (hitflags & 2) { @@ -1428,12 +1231,8 @@ static boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings) // Global Functions // -// -// Polyobj_GetForNum -// // Retrieves a polyobject by its numeric id using hashing. // Returns NULL if no such polyobject exists. -// polyobj_t *Polyobj_GetForNum(INT32 id) { INT32 curidx = PolyObjects[id % numPolyObjects].first; @@ -1444,12 +1243,9 @@ polyobj_t *Polyobj_GetForNum(INT32 id) return curidx == numPolyObjects ? NULL : &PolyObjects[curidx]; } -// -// Polyobj_GetParent -// + // Retrieves the parenting polyobject if one exists. Returns NULL // otherwise. -// #if 0 //unused function static polyobj_t *Polyobj_GetParent(polyobj_t *po) { @@ -1457,12 +1253,8 @@ static polyobj_t *Polyobj_GetParent(polyobj_t *po) } #endif -// -// Polyobj_GetChild -// // Iteratively retrieves the children POs of a parent, // sorta like P_FindSectorSpecialFromTag. -// static polyobj_t *Polyobj_GetChild(polyobj_t *po, INT32 *start) { for (; *start < numPolyObjects; (*start)++) @@ -1481,12 +1273,8 @@ typedef struct mobjqitem_s mobj_t *mo; } mobjqitem_t; -// -// Polyobj_InitLevel -// // Called at the beginning of each map after all other line and thing // processing is finished. -// void Polyobj_InitLevel(void) { thinker_t *th; @@ -1494,6 +1282,7 @@ void Polyobj_InitLevel(void) mqueue_t anchorqueue; mobjqitem_t *qitem; INT32 i, numAnchors = 0; + mobj_t *mo; M_QueueInit(&spawnqueue); M_QueueInit(&anchorqueue); @@ -1507,31 +1296,30 @@ void Polyobj_InitLevel(void) // run down the thinker list, count the number of spawn points, and save // the mobj_t pointers on a queue for use below. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)th; + + if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM) { - mobj_t *mo = (mobj_t *)th; + ++numPolyObjects; - if (mo->info->doomednum == POLYOBJ_SPAWN_DOOMEDNUM || - mo->info->doomednum == POLYOBJ_SPAWNCRUSH_DOOMEDNUM) - { - ++numPolyObjects; + qitem = malloc(sizeof(mobjqitem_t)); + memset(qitem, 0, sizeof(mobjqitem_t)); + qitem->mo = mo; + M_QueueInsert(&(qitem->mqitem), &spawnqueue); + } + else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM) + { + ++numAnchors; - qitem = malloc(sizeof(mobjqitem_t)); - memset(qitem, 0, sizeof(mobjqitem_t)); - qitem->mo = mo; - M_QueueInsert(&(qitem->mqitem), &spawnqueue); - } - else if (mo->info->doomednum == POLYOBJ_ANCHOR_DOOMEDNUM) - { - ++numAnchors; - - qitem = malloc(sizeof(mobjqitem_t)); - memset(qitem, 0, sizeof(mobjqitem_t)); - qitem->mo = mo; - M_QueueInsert(&(qitem->mqitem), &anchorqueue); - } + qitem = malloc(sizeof(mobjqitem_t)); + memset(qitem, 0, sizeof(mobjqitem_t)); + qitem->mo = mo; + M_QueueInsert(&(qitem->mqitem), &anchorqueue); } } @@ -1550,7 +1338,7 @@ void Polyobj_InitLevel(void) { qitem = (mobjqitem_t *)M_QueueIterator(&spawnqueue); - Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->angle); + Polyobj_spawnPolyObj(i, qitem->mo, qitem->mo->spawnpoint->tag); } // move polyobjects to spawn points @@ -1604,34 +1392,31 @@ void Polyobj_InitLevel(void) M_QueueFree(&anchorqueue); } -// -// Polyobj_MoveOnLoad -// // Called when a savegame is being loaded. Rotates and translates an // existing polyobject to its position when the game was saved. // +// Monster Iestyn 05/04/19: Please do not interact with mobjs! You +// can cause I_Error crashes that way, and all the important mobjs are +// going to be deleted afterwards anyway. +// void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y) { fixed_t dx, dy; // first, rotate to the saved angle - Polyobj_rotate(po, angle, false); + Polyobj_rotate(po, angle, false, false); // determine component distances to translate dx = x - po->spawnSpot.x; dy = y - po->spawnSpot.y; // translate - Polyobj_moveXY(po, dx, dy); + Polyobj_moveXY(po, dx, dy, false); } // Thinker Functions -// -// T_PolyObjRotate -// // Thinker function for PolyObject rotation. -// void T_PolyObjRotate(polyrotate_t *th) { polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); @@ -1642,7 +1427,7 @@ void T_PolyObjRotate(polyrotate_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotate: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -1662,7 +1447,7 @@ void T_PolyObjRotate(polyrotate_t *th) // rotate by 'speed' angle per frame // if distance == -1, this polyobject rotates perpetually - if (Polyobj_rotate(po, th->speed, th->turnobjs) && th->distance != -1) + if (Polyobj_rotate(po, th->speed, th->turnobjs, true) && th->distance != -1) { INT32 avel = abs(th->speed); @@ -1692,11 +1477,7 @@ void T_PolyObjRotate(polyrotate_t *th) } } -// -// Polyobj_componentSpeed -// // Calculates the speed components from the desired resultant velocity. -// FUNCINLINE static ATTRINLINE void Polyobj_componentSpeed(INT32 resVel, INT32 angle, fixed_t *xVel, fixed_t *yVel) { @@ -1727,7 +1508,7 @@ void T_PolyObjMove(polymove_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjMove: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -1746,7 +1527,7 @@ void T_PolyObjMove(polymove_t *th) } // move the polyobject one step along its movement angle - if (Polyobj_moveXY(po, th->momx, th->momy)) + if (Polyobj_moveXY(po, th->momx, th->momy, true)) { INT32 avel = abs(th->speed); @@ -1777,22 +1558,39 @@ void T_PolyObjMove(polymove_t *th) } } -// -// T_PolyObjWaypoint -// -// Kinda like 'Zoom Tubes for PolyObjects' -// +static void T_MovePolyObj(polyobj_t *po, fixed_t distx, fixed_t disty, fixed_t distz) +{ + polyobj_t *child; + INT32 start; + + Polyobj_moveXY(po, distx, disty, true); + // TODO: use T_MovePlane + po->lines[0]->backsector->floorheight += distz; + po->lines[0]->backsector->ceilingheight += distz; + // Sal: Remember to check your sectors! + // Monster Iestyn: we only need to bother with the back sector, now that P_CheckSector automatically checks the blockmap + // updating objects in the front one too just added teleporting to ground bugs + P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); + // Apply action to mirroring polyobjects as well + start = 0; + while ((child = Polyobj_GetChild(po, &start))) + { + if (child->isBad) + continue; + + Polyobj_moveXY(child, distx, disty, true); + // TODO: use T_MovePlane + child->lines[0]->backsector->floorheight += distz; + child->lines[0]->backsector->ceilingheight += distz; + P_CheckSector(child->lines[0]->backsector, (boolean)(child->damage)); + } +} + void T_PolyObjWaypoint(polywaypoint_t *th) { - mobj_t *mo2; mobj_t *target = NULL; - mobj_t *waypoint = NULL; - thinker_t *wp; - fixed_t adjustx, adjusty, adjustz; - fixed_t momx, momy, momz, dist; - INT32 start; polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); - polyobj_t *oldpo = po; + fixed_t speed = th->speed; if (!po) #ifdef RANGECHECK @@ -1800,33 +1598,16 @@ void T_PolyObjWaypoint(polywaypoint_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjWaypoint: thinker with invalid id %d removed.", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif // check for displacement due to override and reattach when possible - if (po->thinker == NULL) + if (!po->thinker) po->thinker = &th->thinker; - // Find out target first. - // We redo this each tic to make savegame compatibility easier. - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) - { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == th->sequence && mo2->health == th->pointnum) - { - target = mo2; - break; - } - } + target = tubewaypoints[th->sequence][th->pointnum]; if (!target) { @@ -1834,234 +1615,93 @@ void T_PolyObjWaypoint(polywaypoint_t *th) return; } - // Compensate for position offset - adjustx = po->centerPt.x + th->diffx; - adjusty = po->centerPt.y + th->diffy; - adjustz = po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2 + th->diffz; - - dist = P_AproxDistance(P_AproxDistance(target->x - adjustx, target->y - adjusty), target->z - adjustz); - - if (dist < 1) - dist = 1; - - momx = FixedMul(FixedDiv(target->x - adjustx, dist), (th->speed)); - momy = FixedMul(FixedDiv(target->y - adjusty, dist), (th->speed)); - momz = FixedMul(FixedDiv(target->z - adjustz, dist), (th->speed)); - - // Calculate the distance between the polyobject and the waypoint - // 'dist' already equals this. - - // Will the polyobject be FURTHER away if the momx/momy/momz is added to - // its current coordinates, or closer? (shift down to fracunits to avoid approximation errors) - if (dist>>FRACBITS <= P_AproxDistance(P_AproxDistance(target->x - adjustx - momx, target->y - adjusty - momy), target->z - adjustz - momz)>>FRACBITS) + // Move along the waypoint sequence until speed for the current tic is exhausted + while (speed > 0) { - // If further away, set XYZ of polyobject to waypoint location - fixed_t amtx, amty, amtz; - fixed_t diffz; - amtx = (target->x - th->diffx) - po->centerPt.x; - amty = (target->y - th->diffy) - po->centerPt.y; - Polyobj_moveXY(po, amtx, amty); - // TODO: use T_MovePlane - amtz = (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2; - diffz = po->lines[0]->backsector->floorheight - (target->z - amtz); - po->lines[0]->backsector->floorheight = target->z - amtz; - po->lines[0]->backsector->ceilingheight = target->z + amtz; - // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); - // Apply action to mirroring polyobjects as well - start = 0; - while ((po = Polyobj_GetChild(oldpo, &start))) + mobj_t *waypoint = NULL; + fixed_t pox, poy, poz; + fixed_t distx, disty, distz, dist; + + // Current position of polyobject + pox = po->centerPt.x; + poy = po->centerPt.y; + poz = (po->lines[0]->backsector->floorheight + po->lines[0]->backsector->ceilingheight)/2; + + // Calculate the distance between the polyobject and the waypoint + distx = target->x - pox; + disty = target->y - poy; + distz = target->z - poz; + dist = P_AproxDistance(P_AproxDistance(distx, disty), distz); + + if (dist < 1) + dist = 1; + + // Will the polyobject overshoot its target? + if (speed < dist) { - if (po->isBad) - continue; + // No. Move towards waypoint + fixed_t momx, momy, momz; - Polyobj_moveXY(po, amtx, amty); - // TODO: use T_MovePlane - po->lines[0]->backsector->floorheight += diffz; // move up/down by same amount as the parent did - po->lines[0]->backsector->ceilingheight += diffz; - // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); - } - - po = oldpo; - - if (!th->stophere) - { - CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n"); - - // Find next waypoint - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) - { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == th->sequence) - { - if (th->direction == -1) - { - if (mo2->health == target->health - 1) - { - waypoint = mo2; - break; - } - } - else - { - if (mo2->health == target->health + 1) - { - waypoint = mo2; - break; - } - } - } - } - - if (!waypoint && th->wrap) // If specified, wrap waypoints - { - if (!th->continuous) - { - th->wrap = 0; - th->stophere = true; - } - - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) - { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == th->sequence) - { - if (th->direction == -1) - { - if (waypoint == NULL) - waypoint = mo2; - else if (mo2->health > waypoint->health) - waypoint = mo2; - } - else - { - if (mo2->health == 0) - { - waypoint = mo2; - break; - } - } - } - } - } - else if (!waypoint && th->comeback) // Come back to the start - { - th->direction = -th->direction; - - if (!th->continuous) - th->comeback = false; - - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) - { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == th->sequence) - { - if (th->direction == -1) - { - if (mo2->health == target->health - 1) - { - waypoint = mo2; - break; - } - } - else - { - if (mo2->health == target->health + 1) - { - waypoint = mo2; - break; - } - } - } - } - } - } - - if (waypoint) - { - CONS_Debug(DBG_POLYOBJ, "Found waypoint (sequence %d, number %d).\n", waypoint->threshold, waypoint->health); - - target = waypoint; - th->pointnum = target->health; - - // calculate MOMX/MOMY/MOMZ for next waypoint - // change slope - dist = P_AproxDistance(P_AproxDistance(target->x - adjustx, target->y - adjusty), target->z - adjustz); - - if (dist < 1) - dist = 1; - - momx = FixedMul(FixedDiv(target->x - adjustx, dist), (th->speed)); - momy = FixedMul(FixedDiv(target->y - adjusty, dist), (th->speed)); - momz = FixedMul(FixedDiv(target->z - adjustz, dist), (th->speed)); + momx = FixedMul(FixedDiv(target->x - pox, dist), speed); + momy = FixedMul(FixedDiv(target->y - poy, dist), speed); + momz = FixedMul(FixedDiv(target->z - poz, dist), speed); + T_MovePolyObj(po, momx, momy, momz); + return; } else { - momx = momy = momz = 0; + // Yes. Teleport to waypoint and look for the next one + T_MovePolyObj(po, distx, disty, distz); if (!th->stophere) - CONS_Debug(DBG_POLYOBJ, "Next waypoint not found!\n"); + { + CONS_Debug(DBG_POLYOBJ, "Looking for next waypoint...\n"); + waypoint = (th->direction == -1) ? P_GetPreviousTubeWaypoint(target, false) : P_GetNextTubeWaypoint(target, false); - if (po->thinker == &th->thinker) - po->thinker = NULL; + if (!waypoint && th->returnbehavior == PWR_WRAP) // If specified, wrap waypoints + { + if (!th->continuous) + { + th->returnbehavior = PWR_STOP; + th->stophere = true; + } - P_RemoveThinker(&th->thinker); - return; + waypoint = (th->direction == -1) ? P_GetLastTubeWaypoint(th->sequence) : P_GetFirstTubeWaypoint(th->sequence); + } + else if (!waypoint && th->returnbehavior == PWR_COMEBACK) // Come back to the start + { + th->direction = -th->direction; + + if (!th->continuous) + th->returnbehavior = PWR_STOP; + + waypoint = (th->direction == -1) ? P_GetPreviousTubeWaypoint(target, false) : P_GetNextTubeWaypoint(target, false); + } + } + + if (waypoint) + { + CONS_Debug(DBG_POLYOBJ, "Found waypoint (sequence %d, number %d).\n", waypoint->threshold, waypoint->health); + + target = waypoint; + th->pointnum = target->health; + + // Calculate remaining speed + speed -= dist; + } + else + { + if (!th->stophere) + CONS_Debug(DBG_POLYOBJ, "Next waypoint not found!\n"); + + if (po->thinker == &th->thinker) + po->thinker = NULL; + + P_RemoveThinker(&th->thinker); + return; + } } } - else - { - // momx/momy/momz already equals the right speed - } - - // Move the polyobject - Polyobj_moveXY(po, momx, momy); - // TODO: use T_MovePlane - po->lines[0]->backsector->floorheight += momz; - po->lines[0]->backsector->ceilingheight += momz; - // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); // frontsector is NEEDED for crushing - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); // backsector may not be necessary, but just in case - - // Apply action to mirroring polyobjects as well - start = 0; - while ((po = Polyobj_GetChild(oldpo, &start))) - { - if (po->isBad) - continue; - - Polyobj_moveXY(po, momx, momy); - // TODO: use T_MovePlane - po->lines[0]->backsector->floorheight += momz; - po->lines[0]->backsector->ceilingheight += momz; - // Sal: Remember to check your sectors! - P_CheckSector(po->lines[0]->frontsector, (boolean)(po->damage)); - P_CheckSector(po->lines[0]->backsector, (boolean)(po->damage)); - } } void T_PolyDoorSlide(polyslidedoor_t *th) @@ -2074,7 +1714,7 @@ void T_PolyDoorSlide(polyslidedoor_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSlide: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2103,7 +1743,7 @@ void T_PolyDoorSlide(polyslidedoor_t *th) } // move the polyobject one step along its movement angle - if (Polyobj_moveXY(po, th->momx, th->momy)) + if (Polyobj_moveXY(po, th->momx, th->momy, true)) { INT32 avel = abs(th->speed); @@ -2179,7 +1819,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSwing: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2209,7 +1849,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th) // rotate by 'speed' angle per frame // if distance == -1, this polyobject rotates perpetually - if (Polyobj_rotate(po, th->speed, false) && th->distance != -1) + if (Polyobj_rotate(po, th->speed, false, true) && th->distance != -1) { INT32 avel = abs(th->speed); @@ -2265,7 +1905,7 @@ void T_PolyDoorSwing(polyswingdoor_t *th) } } -// T_PolyObjDisplace: shift a polyobject based on a control sector's heights. -Red +// Shift a polyobject based on a control sector's heights. void T_PolyObjDisplace(polydisplace_t *th) { polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); @@ -2274,11 +1914,11 @@ void T_PolyObjDisplace(polydisplace_t *th) if (!po) #ifdef RANGECHECK - I_Error("T_PolyDoorSwing: thinker has invalid id %d\n", th->polyObjNum); + I_Error("T_PolyObjDisplace: thinker has invalid id %d\n", th->polyObjNum); #else { - CONS_Debug(DBG_POLYOBJ, "T_PolyDoorSwing: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + CONS_Debug(DBG_POLYOBJ, "T_PolyObjDisplace: thinker with invalid id %d removed.\n", th->polyObjNum); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2301,7 +1941,46 @@ void T_PolyObjDisplace(polydisplace_t *th) dx = FixedMul(th->dx, delta); dy = FixedMul(th->dy, delta); - if (Polyobj_moveXY(po, dx, dy)) + if (Polyobj_moveXY(po, dx, dy, true)) + th->oldHeights = newheights; +} + +// Rotate a polyobject based on a control sector's heights. +void T_PolyObjRotDisplace(polyrotdisplace_t *th) +{ + polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); + fixed_t newheights, delta; + fixed_t rotangle; + + if (!po) +#ifdef RANGECHECK + I_Error("T_PolyObjRotDisplace: thinker has invalid id %d\n", th->polyObjNum); +#else + { + CONS_Debug(DBG_POLYOBJ, "T_PolyObjRotDisplace: thinker with invalid id %d removed.\n", th->polyObjNum); + P_RemoveThinker(&th->thinker); + return; + } +#endif + + // check for displacement due to override and reattach when possible + if (po->thinker == NULL) + { + po->thinker = &th->thinker; + + // reset polyobject's thrust + po->thrust = FRACUNIT; + } + + newheights = th->controlSector->floorheight+th->controlSector->ceilingheight; + delta = newheights-th->oldHeights; + + if (!delta) + return; + + rotangle = FixedMul(th->rotscale, delta); + + if (Polyobj_rotate(po, FixedAngle(rotangle), th->turnobjs, true)) th->oldHeights = newheights; } @@ -2312,7 +1991,7 @@ static inline INT32 Polyobj_AngSpeed(INT32 speed) // Linedef Handlers -INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata) +boolean EV_DoPolyObjRotate(polyrotdata_t *prdata) { polyobj_t *po; polyobj_t *oldpo; @@ -2322,21 +2001,21 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata) if (!(po = Polyobj_GetForNum(prdata->polyObjNum))) { CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", prdata->polyObjNum); - return 0; + return false; } // don't allow line actions to affect bad polyobjects if (po->isBad) - return 0; + return false; // check for override if this polyobj already has a thinker if (po->thinker && !prdata->overRide) - return 0; + return false; // create a new thinker th = Z_Malloc(sizeof(polyrotate_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotate; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -2374,10 +2053,10 @@ INT32 EV_DoPolyObjRotate(polyrotdata_t *prdata) } // action was successful - return 1; + return true; } -INT32 EV_DoPolyObjMove(polymovedata_t *pmdata) +boolean EV_DoPolyObjMove(polymovedata_t *pmdata) { polyobj_t *po; polyobj_t *oldpo; @@ -2387,21 +2066,21 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata) if (!(po = Polyobj_GetForNum(pmdata->polyObjNum))) { CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjMove: bad polyobj %d\n", pmdata->polyObjNum); - return 0; + return false; } // don't allow line actions to affect bad polyobjects if (po->isBad) - return 0; + return false; // check for override if this polyobj already has a thinker if (po->thinker && !pmdata->overRide) - return 0; + return false; // create a new thinker th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjMove; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -2433,169 +2112,67 @@ INT32 EV_DoPolyObjMove(polymovedata_t *pmdata) } // action was successful - return 1; + return true; } -INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) +boolean EV_DoPolyObjWaypoint(polywaypointdata_t *pwdata) { polyobj_t *po; polywaypoint_t *th; - mobj_t *mo2; mobj_t *first = NULL; - mobj_t *last = NULL; - mobj_t *target = NULL; - thinker_t *wp; if (!(po = Polyobj_GetForNum(pwdata->polyObjNum))) { CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: bad polyobj %d\n", pwdata->polyObjNum); - return 0; + return false; } // don't allow line actions to affect bad polyobjects if (po->isBad) - return 0; + return false; if (po->thinker) // Don't crowd out another thinker. - return 0; + return false; // create a new thinker th = Z_Malloc(sizeof(polywaypoint_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjWaypoint; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields th->polyObjNum = pwdata->polyObjNum; th->speed = pwdata->speed; - th->sequence = pwdata->sequence; // Used to specify sequence # - if (pwdata->reverse) - th->direction = -1; - else - th->direction = 1; + th->sequence = pwdata->sequence; + th->direction = (pwdata->flags & PWF_REVERSE) ? -1 : 1; - th->comeback = pwdata->comeback; - th->continuous = pwdata->continuous; - th->wrap = pwdata->wrap; + th->returnbehavior = pwdata->returnbehavior; + if (pwdata->flags & PWF_LOOP) + th->continuous = true; th->stophere = false; // Find the first waypoint we need to use - for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) - { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == th->sequence) - { - if (th->direction == -1) // highest waypoint # - { - if (mo2->health == 0) - last = mo2; - else - { - if (first == NULL) - first = mo2; - else if (mo2->health > first->health) - first = mo2; - } - } - else // waypoint 0 - { - if (mo2->health == 0) - first = mo2; - else - { - if (last == NULL) - last = mo2; - else if (mo2->health > last->health) - last = mo2; - } - } - } - } + first = (th->direction == -1) ? P_GetLastTubeWaypoint(th->sequence) : P_GetFirstTubeWaypoint(th->sequence); if (!first) { CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: Missing starting waypoint!\n"); po->thinker = NULL; P_RemoveThinker(&th->thinker); - return 0; + return false; } - // Hotfix to not crash on single-waypoint sequences -Red - if (!last) - last = first; - - // Set diffx, diffy, diffz - // Put these at 0 for now...might not be needed after all. - th->diffx = 0;//first->x - po->centerPt.x; - th->diffy = 0;//first->y - po->centerPt.y; - th->diffz = 0;//first->z - (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2); - - if (last->x == po->centerPt.x - && last->y == po->centerPt.y - && last->z == (po->lines[0]->backsector->floorheight + (po->lines[0]->backsector->ceilingheight - po->lines[0]->backsector->floorheight)/2)) + // Sanity check: If all waypoints are in the same location, + // don't allow the movement to be continuous so we don't get stuck in an infinite loop. + if (th->continuous && P_IsDegeneratedTubeWaypointSequence(th->sequence)) { - // Already at the destination point... - if (!th->wrap) - { - po->thinker = NULL; - P_RemoveThinker(&th->thinker); - } + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: All waypoints are in the same location!\n"); + th->continuous = false; } - // Find the actual target movement waypoint - target = first; - /*for (wp = thinkercap.next; wp != &thinkercap; wp = wp->next) - { - if (wp->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; + th->pointnum = first->health; - mo2 = (mobj_t *)wp; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == th->sequence) - { - if (th->direction == -1) // highest waypoint # - { - if (mo2->health == first->health - 1) - { - target = mo2; - break; - } - } - else // waypoint 0 - { - if (mo2->health == first->health + 1) - { - target = mo2; - break; - } - } - } - }*/ - - if (!target) - { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjWaypoint: Missing target waypoint!\n"); - po->thinker = NULL; - P_RemoveThinker(&th->thinker); - return 0; - } - - // Set pointnum - th->pointnum = target->health; - - // We don't deal with the mirror crap here, we'll - // handle that in the T_Thinker function. - return 1; + return true; } static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata) @@ -2608,7 +2185,7 @@ static void Polyobj_doSlideDoor(polyobj_t *po, polydoordata_t *doordata) // allocate and add a new slide door thinker th = Z_Malloc(sizeof(polyslidedoor_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSlide; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); // point the polyobject to this thinker po->thinker = &th->thinker; @@ -2656,7 +2233,7 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata) // allocate and add a new swing door thinker th = Z_Malloc(sizeof(polyswingdoor_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyDoorSwing; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); // point the polyobject to this thinker po->thinker = &th->thinker; @@ -2687,20 +2264,20 @@ static void Polyobj_doSwingDoor(polyobj_t *po, polydoordata_t *doordata) Polyobj_doSwingDoor(po, doordata); } -INT32 EV_DoPolyDoor(polydoordata_t *doordata) +boolean EV_DoPolyDoor(polydoordata_t *doordata) { polyobj_t *po; if (!(po = Polyobj_GetForNum(doordata->polyObjNum))) { CONS_Debug(DBG_POLYOBJ, "EV_DoPolyDoor: bad polyobj %d\n", doordata->polyObjNum); - return 0; + return false; } // don't allow line actions to affect bad polyobjects; // polyobject doors don't allow action overrides if (po->isBad || po->thinker) - return 0; + return false; switch (doordata->doorType) { @@ -2712,13 +2289,13 @@ INT32 EV_DoPolyDoor(polydoordata_t *doordata) break; default: CONS_Debug(DBG_POLYOBJ, "EV_DoPolyDoor: unknown door type %d", doordata->doorType); - return 0; + return false; } - return 1; + return true; } -INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata) +boolean EV_DoPolyObjDisplace(polydisplacedata_t *prdata) { polyobj_t *po; polyobj_t *oldpo; @@ -2728,17 +2305,17 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata) if (!(po = Polyobj_GetForNum(prdata->polyObjNum))) { CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", prdata->polyObjNum); - return 0; + return false; } // don't allow line actions to affect bad polyobjects if (po->isBad) - return 0; + return false; // create a new thinker th = Z_Malloc(sizeof(polydisplace_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjDisplace; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields @@ -2761,7 +2338,53 @@ INT32 EV_DoPolyObjDisplace(polydisplacedata_t *prdata) } // action was successful - return 1; + return true; +} + +boolean EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *prdata) +{ + polyobj_t *po; + polyobj_t *oldpo; + polyrotdisplace_t *th; + INT32 start; + + if (!(po = Polyobj_GetForNum(prdata->polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjRotate: bad polyobj %d\n", prdata->polyObjNum); + return false; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return false; + + // create a new thinker + th = Z_Malloc(sizeof(polyrotdisplace_t), PU_LEVSPEC, NULL); + th->thinker.function.acp1 = (actionf_p1)T_PolyObjRotDisplace; + P_AddThinker(THINK_POLYOBJ, &th->thinker); + po->thinker = &th->thinker; + + // set fields + th->polyObjNum = prdata->polyObjNum; + + th->controlSector = prdata->controlSector; + th->oldHeights = th->controlSector->floorheight+th->controlSector->ceilingheight; + + th->rotscale = prdata->rotscale; + th->turnobjs = prdata->turnobjs; + + oldpo = po; + + // apply action to mirroring polyobjects as well + start = 0; + while ((po = Polyobj_GetChild(oldpo, &start))) + { + prdata->polyObjNum = po->id; // change id to match child polyobject's + EV_DoPolyObjRotDisplace(prdata); + } + + // action was successful + return true; } void T_PolyObjFlag(polymove_t *th) @@ -2775,7 +2398,7 @@ void T_PolyObjFlag(polymove_t *th) #else { CONS_Debug(DBG_POLYOBJ, "T_PolyObjFlag: thinker with invalid id %d removed.\n", th->polyObjNum); - P_RemoveThinkerDelayed(&th->thinker); + P_RemoveThinker(&th->thinker); return; } #endif @@ -2810,7 +2433,7 @@ void T_PolyObjFlag(polymove_t *th) Polyobj_attachToSubsec(po); // relink to subsector } -INT32 EV_DoPolyObjFlag(line_t *pfdata) +boolean EV_DoPolyObjFlag(polyflagdata_t *pfdata) { polyobj_t *po; polyobj_t *oldpo; @@ -2818,36 +2441,36 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata) size_t i; INT32 start; - if (!(po = Polyobj_GetForNum(pfdata->tag))) + if (!(po = Polyobj_GetForNum(pfdata->polyObjNum))) { - CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->tag); - return 0; + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: bad polyobj %d\n", pfdata->polyObjNum); + return false; } // don't allow line actions to affect bad polyobjects, // polyobject doors don't allow action overrides if (po->isBad || po->thinker) - return 0; + return false; // Must have even # of vertices if (po->numVertices & 1) { CONS_Debug(DBG_POLYOBJ, "EV_DoPolyFlag: Polyobject has odd # of vertices!\n"); - return 0; + return false; } // create a new thinker th = Z_Malloc(sizeof(polymove_t), PU_LEVSPEC, NULL); th->thinker.function.acp1 = (actionf_p1)T_PolyObjFlag; - PolyObj_AddThinker(&th->thinker); + P_AddThinker(THINK_POLYOBJ, &th->thinker); po->thinker = &th->thinker; // set fields - th->polyObjNum = pfdata->tag; + th->polyObjNum = pfdata->polyObjNum; th->distance = 0; - th->speed = P_AproxDistance(pfdata->dx, pfdata->dy)>>FRACBITS; - th->angle = R_PointToAngle2(pfdata->v1->x, pfdata->v1->y, pfdata->v2->x, pfdata->v2->y)>>ANGLETOFINESHIFT; - th->momx = sides[pfdata->sidenum[0]].textureoffset>>FRACBITS; + th->speed = pfdata->speed; + th->angle = pfdata->angle; + th->momx = pfdata->momx; // save current positions for (i = 0; i < po->numVertices; ++i) @@ -2859,14 +2482,171 @@ INT32 EV_DoPolyObjFlag(line_t *pfdata) start = 0; while ((po = Polyobj_GetChild(oldpo, &start))) { - pfdata->tag = po->id; + pfdata->polyObjNum = po->id; EV_DoPolyObjFlag(pfdata); } // action was successful - return 1; + return true; } -#endif // ifdef POLYOBJECTS +void T_PolyObjFade(polyfade_t *th) +{ + boolean stillfading = false; + polyobj_t *po = Polyobj_GetForNum(th->polyObjNum); + + if (!po) +#ifdef RANGECHECK + I_Error("T_PolyObjFade: thinker has invalid id %d\n", th->polyObjNum); +#else + { + CONS_Debug(DBG_POLYOBJ, "T_PolyObjFade: thinker with invalid id %d removed.\n", th->polyObjNum); + P_RemoveThinker(&th->thinker); + return; + } +#endif + + // check for displacement due to override and reattach when possible + if (po->thinker == NULL) + po->thinker = &th->thinker; + + stillfading = th->ticbased ? !(--(th->timer) <= 0) + : !((th->timer -= th->duration) <= 0); + + if (th->timer <= 0) + { + po->translucency = max(min(th->destvalue, NUMTRANSMAPS), 0); + + // remove thinker + if (po->thinker == &th->thinker) + po->thinker = NULL; + P_RemoveThinker(&th->thinker); + } + else + { + INT16 delta = abs(th->destvalue - th->sourcevalue); + INT32 duration = th->ticbased ? th->duration + : abs(FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->destvalue) + - FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->sourcevalue)); // speed-based internal counter duration: delta in 256 scale + fixed_t factor = min(FixedDiv(duration - th->timer, duration), 1*FRACUNIT); + if (th->destvalue < th->sourcevalue) + po->translucency = max(min(po->translucency, th->sourcevalue - (INT16)FixedMul(delta, factor)), th->destvalue); + else if (th->destvalue > th->sourcevalue) + po->translucency = min(max(po->translucency, th->sourcevalue + (INT16)FixedMul(delta, factor)), th->destvalue); + } + + if (!stillfading) + { + // set render flags + if (po->translucency >= NUMTRANSMAPS) // invisible + po->flags &= ~POF_RENDERALL; + else + po->flags |= (po->spawnflags & POF_RENDERALL); + + // set collision + if (th->docollision) + { + if (th->destvalue > th->sourcevalue) // faded out + { + po->flags &= ~POF_SOLID; + po->flags |= POF_NOSPECIALS; + } + else + { + po->flags |= (po->spawnflags & POF_SOLID); + if (!(po->spawnflags & POF_NOSPECIALS)) + po->flags &= ~POF_NOSPECIALS; + } + } + } + else + { + if (po->translucency >= NUMTRANSMAPS) + // HACK: OpenGL renders fully opaque when >= NUMTRANSMAPS + po->translucency = tr_trans90; + + po->flags |= (po->spawnflags & POF_RENDERALL); + + // set collision + if (th->docollision) + { + if (th->doghostfade) + { + po->flags &= ~POF_SOLID; + po->flags |= POF_NOSPECIALS; + } + else + { + po->flags |= (po->spawnflags & POF_SOLID); + if (!(po->spawnflags & POF_NOSPECIALS)) + po->flags &= ~POF_NOSPECIALS; + } + } + } +} + +boolean EV_DoPolyObjFade(polyfadedata_t *pfdata) +{ + polyobj_t *po; + polyobj_t *oldpo; + polyfade_t *th; + INT32 start; + + if (!(po = Polyobj_GetForNum(pfdata->polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "EV_DoPolyObjFade: bad polyobj %d\n", pfdata->polyObjNum); + return false; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return false; + + // already equal, nothing to do + if (po->translucency == pfdata->destvalue) + return true; + + if (po->thinker && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade) + P_RemoveThinker(po->thinker); + + // create a new thinker + th = Z_Malloc(sizeof(polyfade_t), PU_LEVSPEC, NULL); + th->thinker.function.acp1 = (actionf_p1)T_PolyObjFade; + P_AddThinker(THINK_POLYOBJ, &th->thinker); + po->thinker = &th->thinker; + + // set fields + th->polyObjNum = pfdata->polyObjNum; + th->sourcevalue = po->translucency; + th->destvalue = pfdata->destvalue; + th->docollision = pfdata->docollision; + th->doghostfade = pfdata->doghostfade; + + if (pfdata->ticbased) + { + th->ticbased = true; + th->timer = th->duration = abs(pfdata->speed); // pfdata->speed is duration + } + else + { + th->ticbased = false; + th->timer = abs(FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->destvalue) + - FixedMul(FixedDiv(256, NUMTRANSMAPS), NUMTRANSMAPS - th->sourcevalue)); // delta converted to 256 scale, use as internal counter + th->duration = abs(pfdata->speed); // use th->duration as speed decrement + } + + oldpo = po; + + // apply action to mirroring polyobjects as well + start = 0; + while ((po = Polyobj_GetChild(oldpo, &start))) + { + pfdata->polyObjNum = po->id; + EV_DoPolyObjFade(pfdata); + } + + // action was successful + return true; +} // EOF diff --git a/src/p_polyobj.h b/src/p_polyobj.h index 60e996cae..8c2946965 100644 --- a/src/p_polyobj.h +++ b/src/p_polyobj.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by James Haley -// Copyright (C) 2006-2018 by Sonic Team Junior. +// Copyright (C) 2006-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,8 +18,6 @@ #include "p_mobj.h" #include "r_defs.h" -// haleyjd: temporary define -#ifdef POLYOBJECTS // // Defines // @@ -28,11 +26,8 @@ #define POLYOBJ_ANCHOR_DOOMEDNUM 760 #define POLYOBJ_SPAWN_DOOMEDNUM 761 -#define POLYOBJ_SPAWNCRUSH_DOOMEDNUM 762 #define POLYOBJ_START_LINE 20 -#define POLYOBJ_EXPLICIT_LINE 21 -#define POLYINFO_SPECIALNUM 22 typedef enum { @@ -41,7 +36,7 @@ typedef enum POF_SOLID = 0x3, ///< Clips things. POF_TESTHEIGHT = 0x4, ///< Test line collision with heights POF_RENDERSIDES = 0x8, ///< Renders the sides. - POF_RENDERTOP = 0x10, ///< Renders the top.. + POF_RENDERTOP = 0x10, ///< Renders the top. POF_RENDERBOTTOM = 0x20, ///< Renders the bottom. POF_RENDERPLANES = 0x30, ///< Renders top and bottom. POF_RENDERALL = 0x38, ///< Renders everything. @@ -52,8 +47,21 @@ typedef enum POF_LDEXEC = 0x400, ///< This PO triggers a linedef executor. POF_ONESIDE = 0x800, ///< Only use the first side of the linedef. POF_NOSPECIALS = 0x1000, ///< Don't apply sector specials. + POF_SPLAT = 0x2000, ///< Use splat flat renderer (treat cyan pixels as invisible). } polyobjflags_e; +typedef enum +{ + TMPF_NOINSIDES = 1, + TMPF_INTANGIBLE = 1<<1, + TMPF_PUSHABLESTOP = 1<<2, + TMPF_INVISIBLEPLANES = 1<<3, + TMPF_EXECUTOR = 1<<4, + TMPF_CRUSH = 1<<5, + TMPF_SPLAT = 1<<6, + //TMPF_DONTCLIPPLANES = 1<<7, +} textmappolyobjectflags_t; + // // Polyobject Structure // @@ -99,11 +107,13 @@ typedef struct polyobj_s UINT8 isBad; // a bad polyobject: should not be rendered/manipulated INT32 translucency; // index to translucency tables + INT16 triggertag; // Tag of linedef executor to trigger on touch struct visplane_s *visplane; // polyobject's visplane, for ease of putting into the list later // these are saved for netgames, so do not let Lua touch these! INT32 spawnflags; // Flags the polyobject originally spawned with + INT32 spawntrans; // Translucency the polyobject originally spawned with } polyobj_t; // @@ -142,24 +152,26 @@ typedef struct polymove_s UINT32 angle; // angle along which to move } polymove_t; +// PolyObject waypoint movement return behavior +typedef enum +{ + PWR_STOP, // Stop after reaching last waypoint + PWR_WRAP, // Wrap back to first waypoint + PWR_COMEBACK, // Repeat sequence in reverse +} polywaypointreturn_e; + typedef struct polywaypoint_s { thinker_t thinker; // must be first - INT32 polyObjNum; // numeric id of polyobject - INT32 speed; // resultant velocity - INT32 sequence; // waypoint sequence # - INT32 pointnum; // waypoint # - INT32 direction; // 1 for normal, -1 for backwards - UINT8 comeback; // reverses and comes back when the end is reached - UINT8 wrap; // Wrap around waypoints - UINT8 continuous; // continuously move - used with COMEBACK or WRAP - UINT8 stophere; // Will stop after it reaches the next waypoint - - // Difference between location of PO and location of waypoint (offset) - fixed_t diffx; - fixed_t diffy; - fixed_t diffz; + INT32 polyObjNum; // numeric id of polyobject + INT32 speed; // resultant velocity + INT32 sequence; // waypoint sequence # + INT32 pointnum; // waypoint # + INT32 direction; // 1 for normal, -1 for backwards + UINT8 returnbehavior; // behavior after reaching the last waypoint + UINT8 continuous; // continuously move - used with PWR_WRAP or PWR_COMEBACK + UINT8 stophere; // Will stop after it reaches the next waypoint } polywaypoint_t; typedef struct polyslidedoor_s @@ -206,6 +218,31 @@ typedef struct polydisplace_s fixed_t oldHeights; } polydisplace_t; +typedef struct polyrotdisplace_s +{ + thinker_t thinker; // must be first + + INT32 polyObjNum; + struct sector_s *controlSector; + fixed_t rotscale; + UINT8 turnobjs; + fixed_t oldHeights; +} polyrotdisplace_t; + +typedef struct polyfade_s +{ + thinker_t thinker; // must be first + + INT32 polyObjNum; + INT32 sourcevalue; + INT32 destvalue; + boolean docollision; + boolean doghostfade; + boolean ticbased; + INT32 duration; + INT32 timer; +} polyfade_t; + // // Line Activation Data Structures // @@ -229,15 +266,19 @@ typedef struct polymovedata_s UINT8 overRide; // if true, will override any action on the object } polymovedata_t; +typedef enum +{ + PWF_REVERSE = 1, // Move through waypoints in reverse order + PWF_LOOP = 1<<1, // Loop movement (used with PWR_WRAP or PWR_COMEBACK) +} polywaypointflags_e; + typedef struct polywaypointdata_s { - INT32 polyObjNum; // numeric id of polyobject to affect - INT32 sequence; // waypoint sequence # - fixed_t speed; // linear speed - UINT8 reverse; // if true, will go in reverse waypoint order - UINT8 comeback; // reverses and comes back when the end is reached - UINT8 wrap; // Wrap around waypoints - UINT8 continuous; // continuously move - used with COMEBACK or WRAP + INT32 polyObjNum; // numeric id of polyobject to affect + INT32 sequence; // waypoint sequence # + fixed_t speed; // linear speed + UINT8 returnbehavior; // behavior after reaching the last waypoint + UINT8 flags; // PWF_ flags } polywaypointdata_t; // polyobject door types @@ -265,10 +306,38 @@ typedef struct polydisplacedata_s fixed_t dy; } polydisplacedata_t; +typedef struct polyrotdisplacedata_s +{ + INT32 polyObjNum; + struct sector_s *controlSector; + fixed_t rotscale; + UINT8 turnobjs; +} polyrotdisplacedata_t; + +typedef struct polyflagdata_s +{ + INT32 polyObjNum; + INT32 speed; + UINT32 angle; + fixed_t momx; +} polyflagdata_t; + +typedef struct polyfadedata_s +{ + INT32 polyObjNum; + INT32 destvalue; + boolean docollision; + boolean doghostfade; + boolean ticbased; + INT32 speed; +} polyfadedata_t; + // // Functions // +boolean Polyobj_moveXY(polyobj_t *po, fixed_t x, fixed_t y, boolean checkmobjs); +boolean Polyobj_rotate(polyobj_t *po, angle_t delta, UINT8 turnthings, boolean checkmobjs); polyobj_t *Polyobj_GetForNum(INT32 id); void Polyobj_InitLevel(void); void Polyobj_MoveOnLoad(polyobj_t *po, angle_t angle, fixed_t x, fixed_t y); @@ -276,7 +345,6 @@ boolean P_PointInsidePolyobj(polyobj_t *po, fixed_t x, fixed_t y); boolean P_MobjTouchingPolyobj(polyobj_t *po, mobj_t *mo); boolean P_MobjInsidePolyobj(polyobj_t *po, mobj_t *mo); boolean P_BBoxInsidePolyobj(polyobj_t *po, fixed_t *bbox); -void Polyobj_GetInfo(INT16 tag, INT32 *polyID, INT32 *parentID, UINT16 *exparg); // thinkers (needed in p_saveg.c) void T_PolyObjRotate(polyrotate_t *); @@ -285,14 +353,18 @@ void T_PolyObjWaypoint (polywaypoint_t *); void T_PolyDoorSlide(polyslidedoor_t *); void T_PolyDoorSwing(polyswingdoor_t *); void T_PolyObjDisplace (polydisplace_t *); +void T_PolyObjRotDisplace (polyrotdisplace_t *); void T_PolyObjFlag (polymove_t *); +void T_PolyObjFade (polyfade_t *); -INT32 EV_DoPolyDoor(polydoordata_t *); -INT32 EV_DoPolyObjMove(polymovedata_t *); -INT32 EV_DoPolyObjWaypoint(polywaypointdata_t *); -INT32 EV_DoPolyObjRotate(polyrotdata_t *); -INT32 EV_DoPolyObjDisplace(polydisplacedata_t *); -INT32 EV_DoPolyObjFlag(struct line_s *); +boolean EV_DoPolyDoor(polydoordata_t *); +boolean EV_DoPolyObjMove(polymovedata_t *); +boolean EV_DoPolyObjWaypoint(polywaypointdata_t *); +boolean EV_DoPolyObjRotate(polyrotdata_t *); +boolean EV_DoPolyObjDisplace(polydisplacedata_t *); +boolean EV_DoPolyObjRotDisplace(polyrotdisplacedata_t *); +boolean EV_DoPolyObjFlag(polyflagdata_t *); +boolean EV_DoPolyObjFade(polyfadedata_t *); // @@ -303,8 +375,6 @@ extern polyobj_t *PolyObjects; extern INT32 numPolyObjects; extern polymaplink_t **polyblocklinks; // polyobject blockmap -#endif // ifdef POLYOBJECTS - #endif // EOF diff --git a/src/p_pspr.h b/src/p_pspr.h index b42692462..aa49f0306 100644 --- a/src/p_pspr.h +++ b/src/p_pspr.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -35,9 +35,16 @@ #pragma interface #endif -/// \brief Frame flags: only the frame number (frames from 0 to 63, but a bit of headroom for 2.2 compat) +/// \brief Frame flags: only the frame number - 0 to 256 (Frames from 0 to 63, Sprite2 number uses 0 to 127 plus FF_SPR2SUPER) #define FF_FRAMEMASK 0xff +/// \brief Frame flags - SPR2: Super sprite2 +#define FF_SPR2SUPER 0x80 +/// \brief Frame flags - SPR2: A change of state at the end of Sprite2 animation +#define FF_SPR2ENDSTATE 0x1000 +/// \brief Frame flags - SPR2: 50% of starting in middle of Sprite2 animation +#define FF_SPR2MIDSTART 0x2000 + /// \brief Frame flags: 0 = no trans(opaque), 1-15 = transl. table #define FF_TRANSMASK 0xf0000 /// \brief shift for FF_TRANSMASK @@ -52,6 +59,8 @@ #define FF_TRANS70 (tr_trans70<lives; - if (pllives < 3) // Bump up to 3 lives if the player - pllives = 3; // has less than that. - - WRITEUINT8(save_p, player->skincolor); - WRITEUINT8(save_p, player->skin); + INT16 skininfo = player->skin; + SINT8 pllives = player->lives; + if (pllives < startinglivesbalance[numgameovers]) // Bump up to 3 lives if the player + pllives = startinglivesbalance[numgameovers]; // has less than that. + WRITEUINT16(save_p, skininfo); + WRITEUINT8(save_p, numgameovers); + WRITESINT8(save_p, pllives); WRITEUINT32(save_p, player->score); - WRITEINT32(save_p, pllives); WRITEINT32(save_p, player->continues); } -// -// P_UnArchivePlayer -// static inline void P_UnArchivePlayer(void) { - savedata.skincolor = READUINT8(save_p); - savedata.skin = READUINT8(save_p); + INT16 skininfo = READUINT16(save_p); + savedata.skin = skininfo; - savedata.score = READINT32(save_p); - savedata.lives = READINT32(save_p); + savedata.numgameovers = READUINT8(save_p); + savedata.lives = READSINT8(save_p); + savedata.score = READUINT32(save_p); savedata.continues = READINT32(save_p); } -// -// P_NetArchivePlayers -// static void P_NetArchivePlayers(void) { INT32 i, j; @@ -115,14 +104,13 @@ static void P_NetArchivePlayers(void) // no longer send ticcmds, player name, skin, or color + WRITEANGLE(save_p, players[i].angleturn); WRITEANGLE(save_p, players[i].aiming); + WRITEANGLE(save_p, players[i].drawangle); + WRITEANGLE(save_p, players[i].viewrollangle); WRITEANGLE(save_p, players[i].awayviewaiming); WRITEINT32(save_p, players[i].awayviewtics); - WRITEINT32(save_p, players[i].health); - - WRITESINT8(save_p, players[i].pity); - WRITEINT32(save_p, players[i].currentweapon); - WRITEINT32(save_p, players[i].ringweapons); + WRITEINT16(save_p, players[i].rings); for (j = 0; j < NUMPOWERS; j++) WRITEUINT16(save_p, players[i].powers[j]); @@ -137,14 +125,12 @@ static void P_NetArchivePlayers(void) WRITEUINT32(save_p, players[i].score); WRITEFIXED(save_p, players[i].dashspeed); - WRITEINT32(save_p, players[i].dashtime); WRITESINT8(save_p, players[i].lives); WRITEUINT8(save_p, players[i].lostlife); WRITESINT8(save_p, players[i].continues); WRITESINT8(save_p, players[i].xtralife); WRITEUINT8(save_p, players[i].gotcontinue); WRITEFIXED(save_p, players[i].speed); - WRITEUINT8(save_p, players[i].jumping); WRITEUINT8(save_p, players[i].secondjump); WRITEUINT8(save_p, players[i].fly1); WRITEUINT8(save_p, players[i].scoreadd); @@ -153,6 +139,7 @@ static void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].deadtimer); WRITEUINT32(save_p, players[i].exiting); WRITEUINT8(save_p, players[i].homing); + WRITEUINT32(save_p, players[i].dashmode); WRITEUINT32(save_p, players[i].skidtime); //////////////////////////// @@ -194,30 +181,34 @@ static void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].drillmeter); WRITEUINT8(save_p, players[i].drilldelay); WRITEUINT8(save_p, players[i].bonustime); + WRITEFIXED(save_p, players[i].oldscale); WRITEUINT8(save_p, players[i].mare); - + WRITEUINT8(save_p, players[i].marelap); + WRITEUINT8(save_p, players[i].marebonuslap); WRITEUINT32(save_p, players[i].marebegunat); WRITEUINT32(save_p, players[i].startedtime); WRITEUINT32(save_p, players[i].finishedtime); + WRITEUINT32(save_p, players[i].lapbegunat); + WRITEUINT32(save_p, players[i].lapstartedtime); + WRITEINT16(save_p, players[i].finishedspheres); WRITEINT16(save_p, players[i].finishedrings); WRITEUINT32(save_p, players[i].marescore); WRITEUINT32(save_p, players[i].lastmarescore); + WRITEUINT32(save_p, players[i].totalmarescore); WRITEUINT8(save_p, players[i].lastmare); + WRITEUINT8(save_p, players[i].lastmarelap); + WRITEUINT8(save_p, players[i].lastmarebonuslap); + WRITEUINT8(save_p, players[i].totalmarelap); + WRITEUINT8(save_p, players[i].totalmarebonuslap); WRITEINT32(save_p, players[i].maxlink); WRITEUINT8(save_p, players[i].texttimer); WRITEUINT8(save_p, players[i].textvar); - if (players[i].capsule) - flags |= CAPSULE; - if (players[i].awayviewmobj) flags |= AWAYVIEW; - if (players[i].axis1) - flags |= FIRSTAXIS; - - if (players[i].axis2) - flags |= SECONDAXIS; + if (players[i].followmobj) + flags |= FOLLOWITEM; if (players[i].follower) flags |= FOLLOWER; @@ -232,47 +223,35 @@ static void P_NetArchivePlayers(void) WRITEINT32(save_p, players[i].onconveyor); WRITEUINT32(save_p, players[i].jointime); + WRITEUINT32(save_p, players[i].quittime); WRITEUINT8(save_p, players[i].splitscreenindex); WRITEUINT16(save_p, flags); - if (flags & CAPSULE) - WRITEUINT32(save_p, players[i].capsule->mobjnum); - - if (flags & FIRSTAXIS) - WRITEUINT32(save_p, players[i].axis1->mobjnum); - - if (flags & SECONDAXIS) - WRITEUINT32(save_p, players[i].axis2->mobjnum); - if (flags & AWAYVIEW) WRITEUINT32(save_p, players[i].awayviewmobj->mobjnum); + if (flags & FOLLOWITEM) + WRITEUINT32(save_p, players[i].followmobj->mobjnum); + + WRITEUINT32(save_p, (UINT32)players[i].followitem); + WRITEUINT32(save_p, players[i].charflags); + // SRB2kart WRITEUINT8(save_p, players[i].kartspeed); WRITEUINT8(save_p, players[i].kartweight); WRITEUINT8(save_p, players[i].followerskin); WRITEUINT8(save_p, players[i].followerready); // booleans are really just numbers eh?? - WRITEUINT8(save_p, players[i].followercolor); + WRITEUINT16(save_p, players[i].followercolor); if (flags & FOLLOWER) WRITEUINT32(save_p, players[i].follower->mobjnum); - - // - for (j = 0; j < NUMKARTSTUFF; j++) WRITEINT32(save_p, players[i].kartstuff[j]); - for (j = 0; j < MAXPREDICTTICS; j++) - { - WRITEINT16(save_p, players[i].lturn_max[j]); - WRITEINT16(save_p, players[i].rturn_max[j]); - } - - WRITEANGLE(save_p, players[i].frameangle); WRITEUINT32(save_p, players[i].distancetofinish); WRITEUINT32(save_p, K_GetWaypointHeapIndex(players[i].nextwaypoint)); WRITEUINT32(save_p, players[i].airtime); @@ -300,9 +279,6 @@ static void P_NetArchivePlayers(void) } } -// -// P_NetUnArchivePlayers -// static void P_NetUnArchivePlayers(void) { INT32 i, j; @@ -323,14 +299,13 @@ static void P_NetUnArchivePlayers(void) // sending player names, skin and color should not be necessary at all! // (that data is handled in the server config now) + players[i].angleturn = READANGLE(save_p); players[i].aiming = READANGLE(save_p); + players[i].drawangle = READANGLE(save_p); + players[i].viewrollangle = READANGLE(save_p); players[i].awayviewaiming = READANGLE(save_p); players[i].awayviewtics = READINT32(save_p); - players[i].health = READINT32(save_p); - - players[i].pity = READSINT8(save_p); - players[i].currentweapon = READINT32(save_p); - players[i].ringweapons = READINT32(save_p); + players[i].rings = READINT16(save_p); for (j = 0; j < NUMPOWERS; j++) players[i].powers[j] = READUINT16(save_p); @@ -345,14 +320,12 @@ static void P_NetUnArchivePlayers(void) players[i].score = READUINT32(save_p); players[i].dashspeed = READFIXED(save_p); // dashing speed - players[i].dashtime = READINT32(save_p); // dashing speed players[i].lives = READSINT8(save_p); players[i].lostlife = (boolean)READUINT8(save_p); players[i].continues = READSINT8(save_p); // continues that player has acquired players[i].xtralife = READSINT8(save_p); // Ring Extra Life counter players[i].gotcontinue = READUINT8(save_p); // got continue from stage players[i].speed = READFIXED(save_p); // Player's speed (distance formula of MOMX and MOMY values) - players[i].jumping = READUINT8(save_p); // Jump counter players[i].secondjump = READUINT8(save_p); players[i].fly1 = READUINT8(save_p); // Tails flying players[i].scoreadd = READUINT8(save_p); // Used for multiple enemy attack bonus @@ -361,6 +334,7 @@ static void P_NetUnArchivePlayers(void) players[i].deadtimer = READINT32(save_p); // End game if game over lasts too long players[i].exiting = READUINT32(save_p); // Exitlevel timer players[i].homing = READUINT8(save_p); // Are you homing? + players[i].dashmode = READUINT32(save_p); // counter for dashmode ability players[i].skidtime = READUINT32(save_p); // Skid timer //////////////////////////// @@ -402,15 +376,25 @@ static void P_NetUnArchivePlayers(void) players[i].drillmeter = READINT32(save_p); players[i].drilldelay = READUINT8(save_p); players[i].bonustime = (boolean)READUINT8(save_p); + players[i].oldscale = READFIXED(save_p); players[i].mare = READUINT8(save_p); - + players[i].marelap = READUINT8(save_p); + players[i].marebonuslap = READUINT8(save_p); players[i].marebegunat = READUINT32(save_p); players[i].startedtime = READUINT32(save_p); players[i].finishedtime = READUINT32(save_p); + players[i].lapbegunat = READUINT32(save_p); + players[i].lapstartedtime = READUINT32(save_p); + players[i].finishedspheres = READINT16(save_p); players[i].finishedrings = READINT16(save_p); players[i].marescore = READUINT32(save_p); players[i].lastmarescore = READUINT32(save_p); + players[i].totalmarescore = READUINT32(save_p); players[i].lastmare = READUINT8(save_p); + players[i].lastmarelap = READUINT8(save_p); + players[i].lastmarebonuslap = READUINT8(save_p); + players[i].totalmarelap = READUINT8(save_p); + players[i].totalmarebonuslap = READUINT8(save_p); players[i].maxlink = READINT32(save_p); players[i].texttimer = READUINT8(save_p); players[i].textvar = READUINT8(save_p); @@ -425,49 +409,36 @@ static void P_NetUnArchivePlayers(void) players[i].onconveyor = READINT32(save_p); players[i].jointime = READUINT32(save_p); + players[i].quittime = READUINT32(save_p); players[i].splitscreenindex = READUINT8(save_p); flags = READUINT16(save_p); - if (flags & CAPSULE) - players[i].capsule = (mobj_t *)(size_t)READUINT32(save_p); - - if (flags & FIRSTAXIS) - players[i].axis1 = (mobj_t *)(size_t)READUINT32(save_p); - - if (flags & SECONDAXIS) - players[i].axis2 = (mobj_t *)(size_t)READUINT32(save_p); - if (flags & AWAYVIEW) players[i].awayviewmobj = (mobj_t *)(size_t)READUINT32(save_p); - players[i].viewheight = 32<next = 0; + net_colormaps->prev = 0; + num_net_colormaps = i+1; + return i; + } + + for (exc = net_colormaps; exc; exc_prev = exc, exc = exc->next) + { + if (R_CheckEqualColormaps(exc, extra_colormap, true, true, true)) + return i; + i++; + } + + exc_prev->next = R_CopyColormap(extra_colormap, false); + extra_colormap->prev = exc_prev; + extra_colormap->next = 0; + + num_net_colormaps = i+1; + return i; +} + +static extracolormap_t *GetNetColormapFromList(UINT32 index) +{ + // For loading, we have to be tricky: + // We load the sectors BEFORE knowing the colormap values + // So if an index doesn't exist, fill our list with dummy colormaps + // until we get the index we want + // Then when we load the color data, we set up the dummy colormaps + + extracolormap_t *exc, *last_exc = NULL; + UINT32 i = 0; + + if (!net_colormaps) // initialize our list + net_colormaps = R_CreateDefaultColormap(false); + + for (exc = net_colormaps; exc; last_exc = exc, exc = exc->next) + { + if (i++ == index) + return exc; + } + + + // LET'S HOPE that index is a sane value, because we create up to [index] + // entries in net_colormaps. At this point, we don't know + // what the total colormap count is + if (index >= numsectors*3 + num_ffloors) + // if every sector had a unique colormap change AND a fade color thinker which has two colormap entries + // AND every ffloor had a fade FOF thinker with one colormap entry + I_Error("Colormap %d from server is too high for sectors %d", index, (UINT32)numsectors); + + // our index doesn't exist, so just make the entry + for (; i <= index; i++) + { + exc = R_CreateDefaultColormap(false); + if (last_exc) + last_exc->next = exc; + exc->prev = last_exc; + exc->next = NULL; + last_exc = exc; + } + return exc; +} + +static void ClearNetColormaps(void) +{ + // We're actually Z_Freeing each entry here, + // so don't call this in P_NetUnArchiveColormaps (where entries will be used in-game) + extracolormap_t *exc, *exc_next; + + for (exc = net_colormaps; exc; exc = exc_next) + { + exc_next = exc->next; + Z_Free(exc); + } + num_net_colormaps = 0; + num_ffloors = 0; + net_colormaps = NULL; +} + +static void P_NetArchiveColormaps(void) +{ + // We save and then we clean up our colormap mess + extracolormap_t *exc, *exc_next; + UINT32 i = 0; + WRITEUINT32(save_p, num_net_colormaps); // save for safety + + for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) + { + // We must save num_net_colormaps worth of data + // So fill non-existent entries with default. + if (!exc) + exc = R_CreateDefaultColormap(false); + + WRITEUINT8(save_p, exc->fadestart); + WRITEUINT8(save_p, exc->fadeend); + WRITEUINT8(save_p, exc->flags); + + WRITEINT32(save_p, exc->rgba); + WRITEINT32(save_p, exc->fadergba); + +#ifdef EXTRACOLORMAPLUMPS + WRITESTRINGN(save_p, exc->lumpname, 9); +#endif + + exc_next = exc->next; + Z_Free(exc); // don't need anymore + } + + num_net_colormaps = 0; + num_ffloors = 0; + net_colormaps = NULL; +} + +static void P_NetUnArchiveColormaps(void) +{ + // When we reach this point, we already populated our list with + // dummy colormaps. Now that we are loading the color data, + // set up the dummies. + extracolormap_t *exc, *existing_exc, *exc_next = NULL; + UINT32 i = 0; + + num_net_colormaps = READUINT32(save_p); + + for (exc = net_colormaps; i < num_net_colormaps; i++, exc = exc_next) + { + UINT8 fadestart, fadeend, flags; + INT32 rgba, fadergba; +#ifdef EXTRACOLORMAPLUMPS + char lumpname[9]; +#endif + + fadestart = READUINT8(save_p); + fadeend = READUINT8(save_p); + flags = READUINT8(save_p); + + rgba = READINT32(save_p); + fadergba = READINT32(save_p); + +#ifdef EXTRACOLORMAPLUMPS + READSTRINGN(save_p, lumpname, 9); + + if (lumpname[0]) + { + if (!exc) + // no point making a new entry since nothing points to it, + // but we needed to read the data so now continue + continue; + + exc_next = exc->next; // this gets overwritten during our operations here, so get it now + existing_exc = R_ColormapForName(lumpname); + *exc = *existing_exc; + R_AddColormapToList(exc); // see HACK note below on why we're adding duplicates + continue; + } +#endif + + if (!exc) + // no point making a new entry since nothing points to it, + // but we needed to read the data so now continue + continue; + + exc_next = exc->next; // this gets overwritten during our operations here, so get it now + + exc->fadestart = fadestart; + exc->fadeend = fadeend; + exc->flags = flags; + + exc->rgba = rgba; + exc->fadergba = fadergba; + +#ifdef EXTRACOLORMAPLUMPS + exc->lump = LUMPERROR; + exc->lumpname[0] = 0; +#endif + + existing_exc = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags); + + if (existing_exc) + exc->colormap = existing_exc->colormap; + else + // CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + // R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba), + // R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba)); + exc->colormap = R_CreateLightTable(exc); + + // HACK: If this dummy is a duplicate, we're going to add it + // to the extra_colormaps list anyway. I think this is faster + // than going through every loaded sector and correcting their + // colormap address to the pre-existing one, PER net_colormap entry + R_AddColormapToList(exc); + + if (i < num_net_colormaps-1 && !exc_next) + exc_next = R_CreateDefaultColormap(false); + } + + // if we still have a valid net_colormap after iterating up to num_net_colormaps, + // some sector had a colormap index higher than num_net_colormaps. We done goofed or $$$ was corrupted. + // In any case, add them to the colormap list too so that at least the sectors' colormap + // addresses are valid and accounted properly + if (exc_next) + { + existing_exc = R_GetDefaultColormap(); + for (exc = exc_next; exc; exc = exc->next) + { + exc->colormap = existing_exc->colormap; // all our dummies are default values + R_AddColormapToList(exc); + } + } + + // Don't need these anymore + num_net_colormaps = 0; + num_ffloors = 0; + net_colormaps = NULL; +} + +static void P_NetArchiveTubeWaypoints(void) +{ + INT32 i, j; + + for (i = 0; i < NUMTUBEWAYPOINTSEQUENCES; i++) + { + WRITEUINT16(save_p, numtubewaypoints[i]); + for (j = 0; j < numtubewaypoints[i]; j++) + WRITEUINT32(save_p, tubewaypoints[i][j] ? tubewaypoints[i][j]->mobjnum : 0); + } +} + +static void P_NetUnArchiveTubeWaypoints(void) +{ + INT32 i, j; + UINT32 mobjnum; + + for (i = 0; i < NUMTUBEWAYPOINTSEQUENCES; i++) + { + numtubewaypoints[i] = READUINT16(save_p); + for (j = 0; j < numtubewaypoints[i]; j++) + { + mobjnum = READUINT32(save_p); + tubewaypoints[i][j] = (mobjnum == 0) ? NULL : P_FindNewPosition(mobjnum); + } + } +} + +/// +/// World Archiving +/// + #define SD_FLOORHT 0x01 #define SD_CEILHT 0x02 #define SD_FLOORPIC 0x04 @@ -509,10 +747,15 @@ static void P_NetUnArchivePlayers(void) #define SD_FYOFFS 0x02 #define SD_CXOFFS 0x04 #define SD_CYOFFS 0x08 -#define SD_TAG 0x10 -#define SD_FLOORANG 0x20 -#define SD_CEILANG 0x40 -#define SD_TAGLIST 0x80 +#define SD_FLOORANG 0x10 +#define SD_CEILANG 0x20 +#define SD_TAG 0x40 +#define SD_DIFF3 0x80 + +// diff3 flags +#define SD_TAGLIST 0x01 +#define SD_COLORMAP 0x02 +#define SD_CRUMBLESTATE 0x04 #define LD_FLAG 0x01 #define LD_SPECIAL 0x02 @@ -524,286 +767,247 @@ static void P_NetUnArchivePlayers(void) #define LD_DIFF2 0x80 // diff2 flags -#define LD_S2TEXOFF 0x01 -#define LD_S2TOPTEX 0x02 -#define LD_S2BOTTEX 0x04 -#define LD_S2MIDTEX 0x08 +#define LD_S2TEXOFF 0x01 +#define LD_S2TOPTEX 0x02 +#define LD_S2BOTTEX 0x04 +#define LD_S2MIDTEX 0x08 +#define LD_ARGS 0x10 +#define LD_STRINGARGS 0x20 +#define LD_EXECUTORDELAY 0x40 -// -// P_NetArchiveWorld -// -static void P_NetArchiveWorld(void) +static boolean P_AreArgsEqual(const line_t *li, const line_t *spawnli) +{ + UINT8 i; + for (i = 0; i < NUMLINEARGS; i++) + if (li->args[i] != spawnli->args[i]) + return false; + + return true; +} + +static boolean P_AreStringArgsEqual(const line_t *li, const line_t *spawnli) +{ + UINT8 i; + for (i = 0; i < NUMLINESTRINGARGS; i++) + { + if (!li->stringargs[i]) + return !spawnli->stringargs[i]; + + if (strcmp(li->stringargs[i], spawnli->stringargs[i])) + return false; + } + + return true; +} + +#define FD_FLAGS 0x01 +#define FD_ALPHA 0x02 + +// Check if any of the sector's FOFs differ from how they spawned +static boolean CheckFFloorDiff(const sector_t *ss) +{ + ffloor_t *rover; + + for (rover = ss->ffloors; rover; rover = rover->next) + { + if (rover->flags != rover->spawnflags + || rover->alpha != rover->spawnalpha) + { + return true; // we found an FOF that changed! + // don't bother checking for more, we do that later + } + } + return false; +} + +// Special case: save the stats of all modified ffloors along with their ffloor "number"s +// we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed +static void ArchiveFFloors(const sector_t *ss) +{ + size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc + ffloor_t *rover; + UINT8 fflr_diff; + for (rover = ss->ffloors; rover; rover = rover->next) + { + fflr_diff = 0; // reset diff flags + if (rover->flags != rover->spawnflags) + fflr_diff |= FD_FLAGS; + if (rover->alpha != rover->spawnalpha) + fflr_diff |= FD_ALPHA; + + if (fflr_diff) + { + WRITEUINT16(save_p, j); // save ffloor "number" + WRITEUINT8(save_p, fflr_diff); + if (fflr_diff & FD_FLAGS) + WRITEUINT32(save_p, rover->flags); + if (fflr_diff & FD_ALPHA) + WRITEINT16(save_p, rover->alpha); + } + j++; + } + WRITEUINT16(save_p, 0xffff); +} + +static void UnArchiveFFloors(const sector_t *ss) +{ + UINT16 j = 0; // number of current ffloor in loop + UINT16 fflr_i; // saved ffloor "number" of next modified ffloor + UINT16 fflr_diff; // saved ffloor diff + ffloor_t *rover; + + rover = ss->ffloors; + if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... + I_Error("Sector does not have any ffloors!"); + + fflr_i = READUINT16(save_p); // get first modified ffloor's number ready + for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? + { + if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already + break; + // should NEVER need to be checked + //if (rover == NULL) + //break; + if (j != fflr_i) // this ffloor was not modified + { + j++; + rover = rover->next; + continue; + } + + fflr_diff = READUINT8(save_p); + + if (fflr_diff & FD_FLAGS) + rover->flags = READUINT32(save_p); + if (fflr_diff & FD_ALPHA) + rover->alpha = READINT16(save_p); + + fflr_i = READUINT16(save_p); // get next ffloor "number" ready + + j++; + rover = rover->next; + } +} + +static void ArchiveSectors(void) { size_t i; - INT32 statsec = 0, statline = 0; - const line_t *li = lines; - const side_t *si; - UINT8 *put; - - // reload the map just to see difference - mapsector_t *ms; - mapsidedef_t *msd; - maplinedef_t *mld; const sector_t *ss = sectors; - UINT8 diff, diff2; + const sector_t *spawnss = spawnsectors; + UINT8 diff, diff2, diff3; - WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); - put = save_p; - - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can get the data from the relevant lumps - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); -#define retrieve_mapdata(d, f)\ - d = Z_Malloc((f)->size, PU_CACHE, NULL); \ - M_Memcpy(d, wadData + (f)->filepos, (f)->size) - retrieve_mapdata(ms, fileinfo + ML_SECTORS); - retrieve_mapdata(mld, fileinfo + ML_LINEDEFS); - retrieve_mapdata(msd, fileinfo + ML_SIDEDEFS); -#undef retrieve_mapdata - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD + for (i = 0; i < numsectors; i++, ss++, spawnss++) { - ms = W_CacheLumpNum(lastloadedmaplumpnum+ML_SECTORS, PU_CACHE); - mld = W_CacheLumpNum(lastloadedmaplumpnum+ML_LINEDEFS, PU_CACHE); - msd = W_CacheLumpNum(lastloadedmaplumpnum+ML_SIDEDEFS, PU_CACHE); - } - - for (i = 0; i < numsectors; i++, ss++, ms++) - { - diff = diff2 = 0; - if (ss->floorheight != SHORT(ms->floorheight)<floorheight != spawnss->floorheight) diff |= SD_FLOORHT; - if (ss->ceilingheight != SHORT(ms->ceilingheight)<ceilingheight != spawnss->ceilingheight) diff |= SD_CEILHT; // // flats // - if (ss->floorpic != P_CheckLevelFlat(ms->floorpic)) + if (ss->floorpic != spawnss->floorpic) diff |= SD_FLOORPIC; - if (ss->ceilingpic != P_CheckLevelFlat(ms->ceilingpic)) + if (ss->ceilingpic != spawnss->ceilingpic) diff |= SD_CEILPIC; - if (ss->lightlevel != SHORT(ms->lightlevel)) + if (ss->lightlevel != spawnss->lightlevel) diff |= SD_LIGHT; - if (ss->special != SHORT(ms->special)) + if (ss->special != spawnss->special) diff |= SD_SPECIAL; - if (ss->floor_xoffs != ss->spawn_flr_xoffs) + if (ss->floor_xoffs != spawnss->floor_xoffs) diff2 |= SD_FXOFFS; - if (ss->floor_yoffs != ss->spawn_flr_yoffs) + if (ss->floor_yoffs != spawnss->floor_yoffs) diff2 |= SD_FYOFFS; - if (ss->ceiling_xoffs != ss->spawn_ceil_xoffs) + if (ss->ceiling_xoffs != spawnss->ceiling_xoffs) diff2 |= SD_CXOFFS; - if (ss->ceiling_yoffs != ss->spawn_ceil_yoffs) + if (ss->ceiling_yoffs != spawnss->ceiling_yoffs) diff2 |= SD_CYOFFS; - if (ss->floorpic_angle != ss->spawn_flrpic_angle) + if (ss->floorpic_angle != spawnss->floorpic_angle) diff2 |= SD_FLOORANG; - if (ss->ceilingpic_angle != ss->spawn_flrpic_angle) + if (ss->ceilingpic_angle != spawnss->ceilingpic_angle) diff2 |= SD_CEILANG; - if (ss->tag != SHORT(ms->tag)) + if (ss->tag != spawnss->tag) diff2 |= SD_TAG; - if (ss->nexttag != ss->spawn_nexttag || ss->firsttag != ss->spawn_firsttag) - diff2 |= SD_TAGLIST; + if (ss->nexttag != spawnss->nexttag || ss->firsttag != spawnss->firsttag) + diff3 |= SD_TAGLIST; - // Check if any of the sector's FOFs differ from how they spawned - if (ss->ffloors) - { - ffloor_t *rover; - for (rover = ss->ffloors; rover; rover = rover->next) - { - if (rover->flags != rover->spawnflags - || rover->alpha != rover->spawnalpha) - { - diff |= SD_FFLOORS; // we found an FOF that changed! - break; // don't bother checking for more, we do that later - } - } - } + if (ss->extra_colormap != spawnss->extra_colormap) + diff3 |= SD_COLORMAP; + if (ss->crumblestate) + diff3 |= SD_CRUMBLESTATE; + + if (ss->ffloors && CheckFFloorDiff(ss)) + diff |= SD_FFLOORS; + + if (diff3) + diff2 |= SD_DIFF3; if (diff2) diff |= SD_DIFF2; if (diff) { - statsec++; - - WRITEUINT16(put, i); - WRITEUINT8(put, diff); + WRITEUINT16(save_p, i); + WRITEUINT8(save_p, diff); if (diff & SD_DIFF2) - WRITEUINT8(put, diff2); + WRITEUINT8(save_p, diff2); + if (diff2 & SD_DIFF3) + WRITEUINT8(save_p, diff3); if (diff & SD_FLOORHT) - WRITEFIXED(put, ss->floorheight); + WRITEFIXED(save_p, ss->floorheight); if (diff & SD_CEILHT) - WRITEFIXED(put, ss->ceilingheight); + WRITEFIXED(save_p, ss->ceilingheight); if (diff & SD_FLOORPIC) - WRITEMEM(put, levelflats[ss->floorpic].name, 8); + WRITEMEM(save_p, levelflats[ss->floorpic].name, 8); if (diff & SD_CEILPIC) - WRITEMEM(put, levelflats[ss->ceilingpic].name, 8); + WRITEMEM(save_p, levelflats[ss->ceilingpic].name, 8); if (diff & SD_LIGHT) - WRITEINT16(put, ss->lightlevel); + WRITEINT16(save_p, ss->lightlevel); if (diff & SD_SPECIAL) - WRITEINT16(put, ss->special); + WRITEINT16(save_p, ss->special); if (diff2 & SD_FXOFFS) - WRITEFIXED(put, ss->floor_xoffs); + WRITEFIXED(save_p, ss->floor_xoffs); if (diff2 & SD_FYOFFS) - WRITEFIXED(put, ss->floor_yoffs); + WRITEFIXED(save_p, ss->floor_yoffs); if (diff2 & SD_CXOFFS) - WRITEFIXED(put, ss->ceiling_xoffs); + WRITEFIXED(save_p, ss->ceiling_xoffs); if (diff2 & SD_CYOFFS) - WRITEFIXED(put, ss->ceiling_yoffs); - if (diff2 & SD_TAG) // save only the tag - WRITEINT16(put, ss->tag); + WRITEFIXED(save_p, ss->ceiling_yoffs); if (diff2 & SD_FLOORANG) - WRITEANGLE(put, ss->floorpic_angle); + WRITEANGLE(save_p, ss->floorpic_angle); if (diff2 & SD_CEILANG) - WRITEANGLE(put, ss->ceilingpic_angle); - if (diff2 & SD_TAGLIST) // save both firsttag and nexttag + WRITEANGLE(save_p, ss->ceilingpic_angle); + if (diff2 & SD_TAG) // save only the tag + WRITEINT16(save_p, ss->tag); + if (diff3 & SD_TAGLIST) // save both firsttag and nexttag { // either of these could be changed even if tag isn't - WRITEINT32(put, ss->firsttag); - WRITEINT32(put, ss->nexttag); + WRITEINT32(save_p, ss->firsttag); + WRITEINT32(save_p, ss->nexttag); } - // Special case: save the stats of all modified ffloors along with their ffloor "number"s - // we don't bother with ffloors that haven't changed, that would just add to savegame even more than is really needed + if (diff3 & SD_COLORMAP) + WRITEUINT32(save_p, CheckAddNetColormapToList(ss->extra_colormap)); + // returns existing index if already added, or appends to net_colormaps and returns new index + if (diff3 & SD_CRUMBLESTATE) + WRITEINT32(save_p, ss->crumblestate); if (diff & SD_FFLOORS) - { - size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc - ffloor_t *rover; - UINT8 fflr_diff; - for (rover = ss->ffloors; rover; rover = rover->next) - { - fflr_diff = 0; // reset diff flags - if (rover->flags != rover->spawnflags) - fflr_diff |= 1; - if (rover->alpha != rover->spawnalpha) - fflr_diff |= 2; - - if (fflr_diff) - { - WRITEUINT16(put, j); // save ffloor "number" - WRITEUINT8(put, fflr_diff); - if (fflr_diff & 1) - WRITEUINT32(put, rover->flags); - if (fflr_diff & 2) - WRITEINT16(put, rover->alpha); - } - j++; - } - WRITEUINT16(put, 0xffff); - } + ArchiveFFloors(ss); } } - WRITEUINT16(put, 0xffff); - - // do lines - for (i = 0; i < numlines; i++, mld++, li++) - { - diff = diff2 = 0; - - if (li->special != SHORT(mld->special)) - diff |= LD_SPECIAL; - - if (SHORT(mld->special) == 321 || SHORT(mld->special) == 322) // only reason li->callcount would be non-zero is if either of these are involved - diff |= LD_CLLCOUNT; - - if (li->sidenum[0] != 0xffff) - { - si = &sides[li->sidenum[0]]; - if (si->textureoffset != SHORT(msd[li->sidenum[0]].textureoffset)<sidenum[0]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[0]].toptexture)) - diff |= LD_S1TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[0]].bottomtexture)) - diff |= LD_S1BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[0]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[0]].midtexture)) - diff |= LD_S1MIDTEX; - } - if (li->sidenum[1] != 0xffff) - { - si = &sides[li->sidenum[1]]; - if (si->textureoffset != SHORT(msd[li->sidenum[1]].textureoffset)<sidenum[1]].toptexture) != -1 - && si->toptexture != R_TextureNumForName(msd[li->sidenum[1]].toptexture)) - diff2 |= LD_S2TOPTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].bottomtexture) != -1 - && si->bottomtexture != R_TextureNumForName(msd[li->sidenum[1]].bottomtexture)) - diff2 |= LD_S2BOTTEX; - if (R_CheckTextureNumForName(msd[li->sidenum[1]].midtexture) != -1 - && si->midtexture != R_TextureNumForName(msd[li->sidenum[1]].midtexture)) - diff2 |= LD_S2MIDTEX; - if (diff2) - diff |= LD_DIFF2; - } - - if (diff) - { - statline++; - WRITEINT16(put, i); - WRITEUINT8(put, diff); - if (diff & LD_DIFF2) - WRITEUINT8(put, diff2); - if (diff & LD_FLAG) - WRITEINT16(put, li->flags); - if (diff & LD_SPECIAL) - WRITEINT16(put, li->special); - if (diff & LD_CLLCOUNT) - WRITEINT16(put, li->callcount); - - si = &sides[li->sidenum[0]]; - if (diff & LD_S1TEXOFF) - WRITEFIXED(put, si->textureoffset); - if (diff & LD_S1TOPTEX) - WRITEINT32(put, si->toptexture); - if (diff & LD_S1BOTTEX) - WRITEINT32(put, si->bottomtexture); - if (diff & LD_S1MIDTEX) - WRITEINT32(put, si->midtexture); - - si = &sides[li->sidenum[1]]; - if (diff2 & LD_S2TEXOFF) - WRITEFIXED(put, si->textureoffset); - if (diff2 & LD_S2TOPTEX) - WRITEINT32(put, si->toptexture); - if (diff2 & LD_S2BOTTEX) - WRITEINT32(put, si->bottomtexture); - if (diff2 & LD_S2MIDTEX) - WRITEINT32(put, si->midtexture); - } - } - WRITEUINT16(put, 0xffff); - R_ClearTextureNumCache(false); - - save_p = put; + WRITEUINT16(save_p, 0xffff); } -// -// P_NetUnArchiveWorld -// -static void P_NetUnArchiveWorld(void) +static void UnArchiveSectors(void) { UINT16 i; - line_t *li; - side_t *si; - UINT8 *get; - UINT8 diff, diff2; - - if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) - I_Error("Bad $$$.sav at archive block World"); - - get = save_p; - + UINT8 diff, diff2, diff3; for (;;) { - i = READUINT16(get); + i = READUINT16(save_p); if (i == 0xffff) break; @@ -811,137 +1015,303 @@ static void P_NetUnArchiveWorld(void) if (i > numsectors) I_Error("Invalid sector number %u from server (expected end at %s)", i, sizeu1(numsectors)); - diff = READUINT8(get); + diff = READUINT8(save_p); if (diff & SD_DIFF2) - diff2 = READUINT8(get); + diff2 = READUINT8(save_p); else diff2 = 0; + if (diff2 & SD_DIFF3) + diff3 = READUINT8(save_p); + else + diff3 = 0; if (diff & SD_FLOORHT) - sectors[i].floorheight = READFIXED(get); + sectors[i].floorheight = READFIXED(save_p); if (diff & SD_CEILHT) - sectors[i].ceilingheight = READFIXED(get); + sectors[i].ceilingheight = READFIXED(save_p); if (diff & SD_FLOORPIC) { - sectors[i].floorpic = P_AddLevelFlatRuntime((char *)get); - get += 8; + sectors[i].floorpic = P_AddLevelFlatRuntime((char *)save_p); + save_p += 8; } if (diff & SD_CEILPIC) { - sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)get); - get += 8; + sectors[i].ceilingpic = P_AddLevelFlatRuntime((char *)save_p); + save_p += 8; } if (diff & SD_LIGHT) - sectors[i].lightlevel = READINT16(get); + sectors[i].lightlevel = READINT16(save_p); if (diff & SD_SPECIAL) - sectors[i].special = READINT16(get); + sectors[i].special = READINT16(save_p); if (diff2 & SD_FXOFFS) - sectors[i].floor_xoffs = READFIXED(get); + sectors[i].floor_xoffs = READFIXED(save_p); if (diff2 & SD_FYOFFS) - sectors[i].floor_yoffs = READFIXED(get); + sectors[i].floor_yoffs = READFIXED(save_p); if (diff2 & SD_CXOFFS) - sectors[i].ceiling_xoffs = READFIXED(get); + sectors[i].ceiling_xoffs = READFIXED(save_p); if (diff2 & SD_CYOFFS) - sectors[i].ceiling_yoffs = READFIXED(get); - if (diff2 & SD_TAG) - sectors[i].tag = READINT16(get); // DON'T use P_ChangeSectorTag - if (diff2 & SD_TAGLIST) - { - sectors[i].firsttag = READINT32(get); - sectors[i].nexttag = READINT32(get); - } + sectors[i].ceiling_yoffs = READFIXED(save_p); if (diff2 & SD_FLOORANG) - sectors[i].floorpic_angle = READANGLE(get); + sectors[i].floorpic_angle = READANGLE(save_p); if (diff2 & SD_CEILANG) - sectors[i].ceilingpic_angle = READANGLE(get); + sectors[i].ceilingpic_angle = READANGLE(save_p); + if (diff2 & SD_TAG) + sectors[i].tag = READINT16(save_p); // DON'T use P_ChangeSectorTag + if (diff3 & SD_TAGLIST) + { + sectors[i].firsttag = READINT32(save_p); + sectors[i].nexttag = READINT32(save_p); + } + + if (diff3 & SD_COLORMAP) + sectors[i].extra_colormap = GetNetColormapFromList(READUINT32(save_p)); + if (diff3 & SD_CRUMBLESTATE) + sectors[i].crumblestate = READINT32(save_p); if (diff & SD_FFLOORS) + UnArchiveFFloors(§ors[i]); + } +} + +static void ArchiveLines(void) +{ + size_t i; + const line_t *li = lines; + const line_t *spawnli = spawnlines; + const side_t *si; + const side_t *spawnsi; + UINT8 diff, diff2; // no diff3 + + for (i = 0; i < numlines; i++, spawnli++, li++) + { + diff = diff2 = 0; + + if (li->special != spawnli->special) + diff |= LD_SPECIAL; + + if (spawnli->special == 321 || spawnli->special == 322) // only reason li->callcount would be non-zero is if either of these are involved + diff |= LD_CLLCOUNT; + + if (!P_AreArgsEqual(li, spawnli)) + diff2 |= LD_ARGS; + + if (!P_AreStringArgsEqual(li, spawnli)) + diff2 |= LD_STRINGARGS; + + if (li->executordelay != spawnli->executordelay) + diff2 |= LD_EXECUTORDELAY; + + if (li->sidenum[0] != 0xffff) { - UINT16 j = 0; // number of current ffloor in loop - UINT16 fflr_i; // saved ffloor "number" of next modified ffloor - UINT16 fflr_diff; // saved ffloor diff - ffloor_t *rover; + si = &sides[li->sidenum[0]]; + spawnsi = &spawnsides[li->sidenum[0]]; + if (si->textureoffset != spawnsi->textureoffset) + diff |= LD_S1TEXOFF; + //SoM: 4/1/2000: Some textures are colormaps. Don't worry about invalid textures. + if (si->toptexture != spawnsi->toptexture) + diff |= LD_S1TOPTEX; + if (si->bottomtexture != spawnsi->bottomtexture) + diff |= LD_S1BOTTEX; + if (si->midtexture != spawnsi->midtexture) + diff |= LD_S1MIDTEX; + } + if (li->sidenum[1] != 0xffff) + { + si = &sides[li->sidenum[1]]; + spawnsi = &spawnsides[li->sidenum[1]]; + if (si->textureoffset != spawnsi->textureoffset) + diff2 |= LD_S2TEXOFF; + if (si->toptexture != spawnsi->toptexture) + diff2 |= LD_S2TOPTEX; + if (si->bottomtexture != spawnsi->bottomtexture) + diff2 |= LD_S2BOTTEX; + if (si->midtexture != spawnsi->midtexture) + diff2 |= LD_S2MIDTEX; + } - rover = sectors[i].ffloors; - if (!rover) // it is assumed sectors[i].ffloors actually exists, but just in case... - I_Error("Sector does not have any ffloors!"); + if (diff2) + diff |= LD_DIFF2; - fflr_i = READUINT16(get); // get first modified ffloor's number ready - for (;;) // for some reason the usual for (rover = x; ...) thing doesn't work here? + if (diff) + { + WRITEINT16(save_p, i); + WRITEUINT8(save_p, diff); + if (diff & LD_DIFF2) + WRITEUINT8(save_p, diff2); + if (diff & LD_FLAG) + WRITEINT16(save_p, li->flags); + if (diff & LD_SPECIAL) + WRITEINT16(save_p, li->special); + if (diff & LD_CLLCOUNT) + WRITEINT16(save_p, li->callcount); + + si = &sides[li->sidenum[0]]; + if (diff & LD_S1TEXOFF) + WRITEFIXED(save_p, si->textureoffset); + if (diff & LD_S1TOPTEX) + WRITEINT32(save_p, si->toptexture); + if (diff & LD_S1BOTTEX) + WRITEINT32(save_p, si->bottomtexture); + if (diff & LD_S1MIDTEX) + WRITEINT32(save_p, si->midtexture); + + si = &sides[li->sidenum[1]]; + if (diff2 & LD_S2TEXOFF) + WRITEFIXED(save_p, si->textureoffset); + if (diff2 & LD_S2TOPTEX) + WRITEINT32(save_p, si->toptexture); + if (diff2 & LD_S2BOTTEX) + WRITEINT32(save_p, si->bottomtexture); + if (diff2 & LD_S2MIDTEX) + WRITEINT32(save_p, si->midtexture); + if (diff2 & LD_ARGS) { - if (fflr_i == 0xffff) // end of modified ffloors list, let's stop already - break; - // should NEVER need to be checked - //if (rover == NULL) - //break; - if (j != fflr_i) // this ffloor was not modified - { - j++; - rover = rover->next; - continue; - } - - fflr_diff = READUINT8(get); - - if (fflr_diff & 1) - rover->flags = READUINT32(get); - if (fflr_diff & 2) - rover->alpha = READINT16(get); - - fflr_i = READUINT16(get); // get next ffloor "number" ready - - j++; - rover = rover->next; + UINT8 j; + for (j = 0; j < NUMLINEARGS; j++) + WRITEINT32(save_p, li->args[j]); } + if (diff2 & LD_STRINGARGS) + { + UINT8 j; + for (j = 0; j < NUMLINESTRINGARGS; j++) + { + size_t len, k; + + if (!li->stringargs[j]) + { + WRITEINT32(save_p, 0); + continue; + } + + len = strlen(li->stringargs[j]); + WRITEINT32(save_p, len); + for (k = 0; k < len; k++) + WRITECHAR(save_p, li->stringargs[j][k]); + } + } + if (diff2 & LD_EXECUTORDELAY) + WRITEINT32(save_p, li->executordelay); } } + WRITEUINT16(save_p, 0xffff); +} + +static void UnArchiveLines(void) +{ + UINT16 i; + line_t *li; + side_t *si; + UINT8 diff, diff2; // no diff3 for (;;) { - i = READUINT16(get); + i = READUINT16(save_p); if (i == 0xffff) break; if (i > numlines) I_Error("Invalid line number %u from server", i); - diff = READUINT8(get); + diff = READUINT8(save_p); li = &lines[i]; if (diff & LD_DIFF2) - diff2 = READUINT8(get); + diff2 = READUINT8(save_p); else diff2 = 0; + if (diff & LD_FLAG) - li->flags = READINT16(get); + li->flags = READINT16(save_p); if (diff & LD_SPECIAL) - li->special = READINT16(get); + li->special = READINT16(save_p); if (diff & LD_CLLCOUNT) - li->callcount = READINT16(get); + li->callcount = READINT16(save_p); si = &sides[li->sidenum[0]]; if (diff & LD_S1TEXOFF) - si->textureoffset = READFIXED(get); + si->textureoffset = READFIXED(save_p); if (diff & LD_S1TOPTEX) - si->toptexture = READINT32(get); + si->toptexture = READINT32(save_p); if (diff & LD_S1BOTTEX) - si->bottomtexture = READINT32(get); + si->bottomtexture = READINT32(save_p); if (diff & LD_S1MIDTEX) - si->midtexture = READINT32(get); + si->midtexture = READINT32(save_p); si = &sides[li->sidenum[1]]; if (diff2 & LD_S2TEXOFF) - si->textureoffset = READFIXED(get); + si->textureoffset = READFIXED(save_p); if (diff2 & LD_S2TOPTEX) - si->toptexture = READINT32(get); + si->toptexture = READINT32(save_p); if (diff2 & LD_S2BOTTEX) - si->bottomtexture = READINT32(get); + si->bottomtexture = READINT32(save_p); if (diff2 & LD_S2MIDTEX) - si->midtexture = READINT32(get); + si->midtexture = READINT32(save_p); + if (diff2 & LD_ARGS) + { + UINT8 j; + for (j = 0; j < NUMLINEARGS; j++) + li->args[j] = READINT32(save_p); + } + if (diff2 & LD_STRINGARGS) + { + UINT8 j; + for (j = 0; j < NUMLINESTRINGARGS; j++) + { + size_t len = READINT32(save_p); + size_t k; + + if (!len) + { + Z_Free(li->stringargs[j]); + li->stringargs[j] = NULL; + continue; + } + + li->stringargs[j] = Z_Realloc(li->stringargs[j], len + 1, PU_LEVEL, NULL); + for (k = 0; k < len; k++) + li->stringargs[j][k] = READCHAR(save_p); + li->stringargs[j][len] = '\0'; + } + } + if (diff2 & LD_EXECUTORDELAY) + li->executordelay = READINT32(save_p); + + } +} + +static void P_NetArchiveWorld(void) +{ + // initialize colormap vars because paranoia + ClearNetColormaps(); + + WRITEUINT32(save_p, ARCHIVEBLOCK_WORLD); + + ArchiveSectors(); + ArchiveLines(); + R_ClearTextureNumCache(false); +} + +static void P_NetUnArchiveWorld(void) +{ + UINT16 i; + + if (READUINT32(save_p) != ARCHIVEBLOCK_WORLD) + I_Error("Bad $$$.sav at archive block World"); + + // initialize colormap vars because paranoia + ClearNetColormaps(); + + // count the level's ffloors so that colormap loading can have an upper limit + for (i = 0; i < numsectors; i++) + { + ffloor_t *rover; + for (rover = sectors[i].ffloors; rover; rover = rover->next) + num_ffloors++; } - save_p = get; + UnArchiveSectors(); + UnArchiveLines(); } // @@ -986,24 +1356,26 @@ typedef enum typedef enum { - MD2_CUSVAL = 1, - MD2_CVMEM = 1<<1, - MD2_SKIN = 1<<2, - MD2_COLOR = 1<<3, - MD2_SCALESPEED = 1<<4, - MD2_EXTVAL1 = 1<<5, - MD2_EXTVAL2 = 1<<6, - MD2_HNEXT = 1<<7, - MD2_HPREV = 1<<8, - MD2_COLORIZED = 1<<9, - MD2_WAYPOINTCAP = 1<<10, - MD2_KITEMCAP = 1<<11, - MD2_ITNEXT = 1<<12, -#ifdef ESLOPE - MD2_SLOPE = 1<<13, -#endif - MD2_SHADOWSCALE = 1<<14, - MD2_DRAWFLAGS = 1<<15, + MD2_CUSVAL = 1, + MD2_CVMEM = 1<<1, + MD2_SKIN = 1<<2, + MD2_COLOR = 1<<3, + MD2_SCALESPEED = 1<<4, + MD2_EXTVAL1 = 1<<5, + MD2_EXTVAL2 = 1<<6, + MD2_HNEXT = 1<<7, + MD2_HPREV = 1<<8, + MD2_FLOORROVER = 1<<9, + MD2_CEILINGROVER = 1<<10, + MD2_SLOPE = 1<<11, + MD2_COLORIZED = 1<<12, + MD2_MIRRORED = 1<<13, + MD2_ROLLANGLE = 1<<14, + MD2_SHADOWSCALE = 1<<15, + MD2_DRAWFLAGS = 1<<16, + MD2_WAYPOINTCAP = 1<<17, + MD2_KITEMCAP = 1<<18, + MD2_ITNEXT = 1<<19, } mobj_diff2_t; typedef enum @@ -1023,9 +1395,7 @@ typedef enum tc_startcrumble, tc_marioblock, tc_marioblockchecker, - tc_spikesector, tc_floatsector, - tc_bridgethinker, tc_crushceiling, tc_scroll, tc_friction, @@ -1037,7 +1407,11 @@ typedef enum tc_noenemies, tc_eachtime, tc_disappear, -#ifdef POLYOBJECTS + tc_fade, + tc_fadecolormap, + tc_planedisplace, + tc_dynslopeline, + tc_dynslopevert, tc_polyrotate, // haleyjd 03/26/06: polyobjects tc_polymove, tc_polywaypoint, @@ -1045,7 +1419,8 @@ typedef enum tc_polyswingdoor, tc_polyflag, tc_polydisplace, -#endif + tc_polyrotdisplace, + tc_polyfade, tc_end } specials_e; @@ -1073,11 +1448,12 @@ static inline UINT32 SavePlayer(const player_t *player) return 0xFFFFFFFF; } -// -// SaveMobjThinker -// -// Saves a mobj_t thinker -// +static UINT32 SaveSlope(const pslope_t *slope) +{ + if (slope) return (UINT32)(slope->id); + return 0xFFFFFFFF; +} + static void SaveMobjThinker(const thinker_t *th, const UINT8 type) { const mobj_t *mobj = (const mobj_t *)th; @@ -1103,7 +1479,9 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if ((mobj->x != mobj->spawnpoint->x << FRACBITS) || (mobj->y != mobj->spawnpoint->y << FRACBITS) || - (mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT))) + (mobj->angle != FixedAngle(mobj->spawnpoint->angle*FRACUNIT)) || + (mobj->pitch != FixedAngle(mobj->spawnpoint->pitch*FRACUNIT)) || + (mobj->roll != FixedAngle(mobj->spawnpoint->roll*FRACUNIT)) ) diff |= MD_POS; if (mobj->info->doomednum != mobj->spawnpoint->type) @@ -1135,6 +1513,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff |= MD_TICS; if (mobj->sprite != mobj->state->sprite) diff |= MD_SPRITE; + if (mobj->sprite == SPR_PLAY && mobj->sprite2 != (mobj->state->frame&FF_FRAMEMASK)) + diff |= MD_SPRITE; if (mobj->frame != mobj->state->frame) diff |= MD_FRAME; if (mobj->anim_duration != (UINT16)mobj->state->var2) @@ -1158,7 +1538,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff |= MD_TRACER; if (mobj->friction != ORIG_FRICTION) diff |= MD_FRICTION; - if (mobj->movefactor != FRACUNIT) //if (mobj->movefactor != ORIG_FRICTION_FACTOR) + if (mobj->movefactor != FRACUNIT) diff |= MD_MOVEFACTOR; if (mobj->fuse) diff |= MD_FUSE; @@ -1194,22 +1574,28 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) diff2 |= MD2_HNEXT; if (mobj->hprev) diff2 |= MD2_HPREV; - if (mobj->itnext) - diff2 |= MD2_ITNEXT; -#ifdef ESLOPE if (mobj->standingslope) diff2 |= MD2_SLOPE; -#endif + if (mobj->colorized) + diff2 |= MD2_COLORIZED; + if (mobj->floorrover) + diff2 |= MD2_FLOORROVER; + if (mobj->ceilingrover) + diff2 |= MD2_CEILINGROVER; + if (mobj->mirrored) + diff2 |= MD2_MIRRORED; + if (mobj->rollangle) + diff2 |= MD2_ROLLANGLE; if (mobj->shadowscale) diff2 |= MD2_SHADOWSCALE; if (mobj->drawflags) diff2 |= MD2_DRAWFLAGS; - if (mobj->colorized) - diff2 |= MD2_COLORIZED; if (mobj == waypointcap) diff2 |= MD2_WAYPOINTCAP; if (mobj == kitemcap) diff2 |= MD2_KITEMCAP; + if (mobj->itnext) + diff2 |= MD2_ITNEXT; if (diff2 != 0) diff |= MD_MORE; @@ -1229,6 +1615,18 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->floorz); WRITEFIXED(save_p, mobj->ceilingz); + if (diff2 & MD2_FLOORROVER) + { + WRITEUINT32(save_p, SaveSector(mobj->floorrover->target)); + WRITEUINT16(save_p, P_GetFFloorID(mobj->floorrover)); + } + + if (diff2 & MD2_CEILINGROVER) + { + WRITEUINT32(save_p, SaveSector(mobj->ceilingrover->target)); + WRITEUINT16(save_p, P_GetFFloorID(mobj->ceilingrover)); + } + if (diff & MD_SPAWNPOINT) { size_t z; @@ -1247,6 +1645,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, mobj->x); WRITEFIXED(save_p, mobj->y); WRITEANGLE(save_p, mobj->angle); + WRITEANGLE(save_p, mobj->pitch); + WRITEANGLE(save_p, mobj->roll); } if (diff & MD_MOM) { @@ -1270,8 +1670,11 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT16(save_p, mobj->state-states); if (diff & MD_TICS) WRITEINT32(save_p, mobj->tics); - if (diff & MD_SPRITE) + if (diff & MD_SPRITE) { WRITEUINT16(save_p, mobj->sprite); + if (mobj->sprite == SPR_PLAY) + WRITEUINT8(save_p, mobj->sprite2); + } if (diff & MD_FRAME) { WRITEUINT32(save_p, mobj->frame); @@ -1316,7 +1719,7 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) if (diff2 & MD2_SKIN) WRITEUINT8(save_p, (UINT8)((skin_t *)mobj->skin - skins)); if (diff2 & MD2_COLOR) - WRITEUINT8(save_p, mobj->color); + WRITEUINT16(save_p, mobj->color); if (diff2 & MD2_EXTVAL1) WRITEINT32(save_p, mobj->extravalue1); if (diff2 & MD2_EXTVAL2) @@ -1327,14 +1730,19 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, mobj->hprev->mobjnum); if (diff2 & MD2_ITNEXT) WRITEUINT32(save_p, mobj->itnext->mobjnum); -#ifdef ESLOPE if (diff2 & MD2_SLOPE) WRITEUINT16(save_p, mobj->standingslope->id); -#endif if (diff2 & MD2_COLORIZED) WRITEUINT8(save_p, mobj->colorized); + if (diff2 & MD2_MIRRORED) + WRITEUINT8(save_p, mobj->mirrored); + if (diff2 & MD2_ROLLANGLE) + WRITEANGLE(save_p, mobj->rollangle); if (diff2 & MD2_SHADOWSCALE) + { WRITEFIXED(save_p, mobj->shadowscale); + WRITEUINT8(save_p, mobj->whiteshadow); + } if (diff2 & MD2_DRAWFLAGS) { UINT16 df = mobj->drawflags; @@ -1350,30 +1758,111 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type) WRITEUINT32(save_p, mobj->mobjnum); } -// -// SaveSpecialLevelThinker -// -// Saves a levelspecthink_t thinker -// -static void SaveSpecialLevelThinker(const thinker_t *th, const UINT8 type) +static void SaveNoEnemiesThinker(const thinker_t *th, const UINT8 type) { - const levelspecthink_t *ht = (const void *)th; - size_t i; + const noenemies_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); +} + +static void SaveBounceCheeseThinker(const thinker_t *th, const UINT8 type) +{ + const bouncecheese_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEFIXED(save_p, ht->speed); + WRITEFIXED(save_p, ht->distance); + WRITEFIXED(save_p, ht->floorwasheight); + WRITEFIXED(save_p, ht->ceilingwasheight); + WRITECHAR(save_p, ht->low); +} + +static void SaveContinuousFallThinker(const thinker_t *th, const UINT8 type) +{ + const continuousfall_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEFIXED(save_p, ht->speed); + WRITEINT32(save_p, ht->direction); + WRITEFIXED(save_p, ht->floorstartheight); + WRITEFIXED(save_p, ht->ceilingstartheight); + WRITEFIXED(save_p, ht->destheight); +} + +static void SaveMarioBlockThinker(const thinker_t *th, const UINT8 type) +{ + const mariothink_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEFIXED(save_p, ht->speed); + WRITEINT32(save_p, ht->direction); + WRITEFIXED(save_p, ht->floorstartheight); + WRITEFIXED(save_p, ht->ceilingstartheight); + WRITEINT16(save_p, ht->tag); +} + +static void SaveMarioCheckThinker(const thinker_t *th, const UINT8 type) +{ + const mariocheck_t *ht = (const void *)th; WRITEUINT8(save_p, type); - for (i = 0; i < 16; i++) - { - WRITEFIXED(save_p, ht->vars[i]); //var[16] - WRITEFIXED(save_p, ht->var2s[i]); //var[16] - } WRITEUINT32(save_p, SaveLine(ht->sourceline)); WRITEUINT32(save_p, SaveSector(ht->sector)); } -// -// SaveCeilingThinker -// -// Saves a ceiling_t thinker -// +static void SaveThwompThinker(const thinker_t *th, const UINT8 type) +{ + const thwomp_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEFIXED(save_p, ht->crushspeed); + WRITEFIXED(save_p, ht->retractspeed); + WRITEINT32(save_p, ht->direction); + WRITEFIXED(save_p, ht->floorstartheight); + WRITEFIXED(save_p, ht->ceilingstartheight); + WRITEINT32(save_p, ht->delay); + WRITEINT16(save_p, ht->tag); + WRITEUINT16(save_p, ht->sound); +} + +static void SaveFloatThinker(const thinker_t *th, const UINT8 type) +{ + const floatthink_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEINT16(save_p, ht->tag); +} + +static void SaveEachTimeThinker(const thinker_t *th, const UINT8 type) +{ + const eachtime_t *ht = (const void *)th; + size_t i; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + for (i = 0; i < MAXPLAYERS; i++) + { + WRITECHAR(save_p, ht->playersInArea[i]); + WRITECHAR(save_p, ht->playersOnArea[i]); + } + WRITECHAR(save_p, ht->triggerOnExit); +} + +static void SaveRaiseThinker(const thinker_t *th, const UINT8 type) +{ + const raise_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEINT16(save_p, ht->tag); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEFIXED(save_p, ht->ceilingbottom); + WRITEFIXED(save_p, ht->ceilingtop); + WRITEFIXED(save_p, ht->basespeed); + WRITEFIXED(save_p, ht->extraspeed); + WRITEUINT8(save_p, ht->shaketimer); + WRITEUINT8(save_p, ht->flags); +} + static void SaveCeilingThinker(const thinker_t *th, const UINT8 type) { const ceiling_t *ht = (const void *)th; @@ -1395,11 +1884,6 @@ static void SaveCeilingThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->sourceline); } -// -// SaveFloormoveThinker -// -// Saves a floormove_t thinker -// static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) { const floormove_t *ht = (const void *)th; @@ -1416,11 +1900,6 @@ static void SaveFloormoveThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->delaytimer); } -// -// SaveLightflashThinker -// -// Saves a lightflash_t thinker -// static void SaveLightflashThinker(const thinker_t *th, const UINT8 type) { const lightflash_t *ht = (const void *)th; @@ -1430,11 +1909,6 @@ static void SaveLightflashThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->minlight); } -// -// SaveStrobeThinker -// -// Saves a strobe_t thinker -// static void SaveStrobeThinker(const thinker_t *th, const UINT8 type) { const strobe_t *ht = (const void *)th; @@ -1447,11 +1921,6 @@ static void SaveStrobeThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->brighttime); } -// -// SaveGlowThinker -// -// Saves a glow_t thinker -// static void SaveGlowThinker(const thinker_t *th, const UINT8 type) { const glow_t *ht = (const void *)th; @@ -1462,11 +1931,7 @@ static void SaveGlowThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->direction); WRITEINT32(save_p, ht->speed); } -// -// SaveFireflickerThinker -// -// Saves a fireflicker_t thinker -// + static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type) { const fireflicker_t *ht = (const void *)th; @@ -1477,11 +1942,7 @@ static inline void SaveFireflickerThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->maxlight); WRITEINT32(save_p, ht->minlight); } -// -// SaveElevatorThinker -// -// Saves a elevator_t thinker -// + static void SaveElevatorThinker(const thinker_t *th, const UINT8 type) { const elevator_t *ht = (const void *)th; @@ -1501,15 +1962,26 @@ static void SaveElevatorThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->delaytimer); WRITEFIXED(save_p, ht->floorwasheight); WRITEFIXED(save_p, ht->ceilingwasheight); - WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy WRITEUINT32(save_p, SaveLine(ht->sourceline)); } -// -// SaveScrollThinker -// -// Saves a scroll_t thinker -// +static void SaveCrumbleThinker(const thinker_t *th, const UINT8 type) +{ + const crumble_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEUINT32(save_p, SaveSector(ht->actionsector)); + WRITEUINT32(save_p, SavePlayer(ht->player)); // was dummy + WRITEINT32(save_p, ht->direction); + WRITEINT32(save_p, ht->origalpha); + WRITEINT32(save_p, ht->timer); + WRITEFIXED(save_p, ht->speed); + WRITEFIXED(save_p, ht->floorwasheight); + WRITEFIXED(save_p, ht->ceilingwasheight); + WRITEUINT8(save_p, ht->flags); +} + static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type) { const scroll_t *ht = (const void *)th; @@ -1526,11 +1998,6 @@ static inline void SaveScrollThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, ht->type); } -// -// SaveFrictionThinker -// -// Saves a friction_t thinker -// static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type) { const friction_t *ht = (const void *)th; @@ -1542,11 +2009,6 @@ static inline void SaveFrictionThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, ht->roverfriction); } -// -// SavePusherThinker -// -// Saves a pusher_t thinker -// static inline void SavePusherThinker(const thinker_t *th, const UINT8 type) { const pusher_t *ht = (const void *)th; @@ -1566,39 +2028,27 @@ static inline void SavePusherThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->slider); } -// -// SaveLaserThinker -// -// Saves a laserthink_t thinker -// static void SaveLaserThinker(const thinker_t *th, const UINT8 type) { const laserthink_t *ht = (const void *)th; WRITEUINT8(save_p, type); - WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEUINT32(save_p, SaveSector(ht->sec)); + WRITEINT16(save_p, ht->tag); WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEUINT8(save_p, ht->nobosses); } -// -// SaveLightlevelThinker -// -// Saves a lightlevel_t thinker -// static void SaveLightlevelThinker(const thinker_t *th, const UINT8 type) { const lightlevel_t *ht = (const void *)th; WRITEUINT8(save_p, type); WRITEUINT32(save_p, SaveSector(ht->sector)); - WRITEINT32(save_p, ht->destlevel); - WRITEINT32(save_p, ht->speed); + WRITEINT16(save_p, ht->sourcelevel); + WRITEINT16(save_p, ht->destlevel); + WRITEFIXED(save_p, ht->fixedcurlevel); + WRITEFIXED(save_p, ht->fixedpertic); + WRITEINT32(save_p, ht->timer); } -// -// SaveExecutorThinker -// -// Saves a executor_t thinker -// static void SaveExecutorThinker(const thinker_t *th, const UINT8 type) { const executor_t *ht = (const void *)th; @@ -1609,11 +2059,6 @@ static void SaveExecutorThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->timer); } -// -// SaveDisappearThinker -// -// Saves a disappear_t thinker -// static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) { const disappear_t *ht = (const void *)th; @@ -1627,13 +2072,66 @@ static void SaveDisappearThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->exists); } -#ifdef POLYOBJECTS +static void SaveFadeThinker(const thinker_t *th, const UINT8 type) +{ + const fade_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); + WRITEUINT32(save_p, ht->sectornum); + WRITEUINT32(save_p, ht->ffloornum); + WRITEINT32(save_p, ht->alpha); + WRITEINT16(save_p, ht->sourcevalue); + WRITEINT16(save_p, ht->destvalue); + WRITEINT16(save_p, ht->destlightlevel); + WRITEINT16(save_p, ht->speed); + WRITEUINT8(save_p, (UINT8)ht->ticbased); + WRITEINT32(save_p, ht->timer); + WRITEUINT8(save_p, ht->doexists); + WRITEUINT8(save_p, ht->dotranslucent); + WRITEUINT8(save_p, ht->dolighting); + WRITEUINT8(save_p, ht->docolormap); + WRITEUINT8(save_p, ht->docollision); + WRITEUINT8(save_p, ht->doghostfade); + WRITEUINT8(save_p, ht->exactalpha); +} + +static void SaveFadeColormapThinker(const thinker_t *th, const UINT8 type) +{ + const fadecolormap_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEUINT32(save_p, SaveSector(ht->sector)); + WRITEUINT32(save_p, CheckAddNetColormapToList(ht->source_exc)); + WRITEUINT32(save_p, CheckAddNetColormapToList(ht->dest_exc)); + WRITEUINT8(save_p, (UINT8)ht->ticbased); + WRITEINT32(save_p, ht->duration); + WRITEINT32(save_p, ht->timer); +} + +static void SavePlaneDisplaceThinker(const thinker_t *th, const UINT8 type) +{ + const planedisplace_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEINT32(save_p, ht->affectee); + WRITEINT32(save_p, ht->control); + WRITEFIXED(save_p, ht->last_height); + WRITEFIXED(save_p, ht->speed); + WRITEUINT8(save_p, ht->type); +} + +static inline void SaveDynamicSlopeThinker(const thinker_t *th, const UINT8 type) +{ + const dynplanethink_t* ht = (const void*)th; + + WRITEUINT8(save_p, type); + WRITEUINT8(save_p, ht->type); + WRITEUINT32(save_p, SaveSlope(ht->slope)); + WRITEUINT32(save_p, SaveLine(ht->sourceline)); + WRITEFIXED(save_p, ht->extent); + + WRITEMEM(save_p, ht->tags, sizeof(ht->tags)); + WRITEMEM(save_p, ht->vex, sizeof(ht->vex)); +} -// -// SavePolyrotateThinker -// -// Saves a polyrotate_t thinker -// static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type) { const polyrotate_t *ht = (const void *)th; @@ -1641,13 +2139,9 @@ static inline void SavePolyrotatetThinker(const thinker_t *th, const UINT8 type) WRITEINT32(save_p, ht->polyObjNum); WRITEINT32(save_p, ht->speed); WRITEINT32(save_p, ht->distance); + WRITEUINT8(save_p, ht->turnobjs); } -// -// SavePolymoveThinker -// -// Saves a polymovet_t thinker -// static void SavePolymoveThinker(const thinker_t *th, const UINT8 type) { const polymove_t *ht = (const void *)th; @@ -1660,11 +2154,6 @@ static void SavePolymoveThinker(const thinker_t *th, const UINT8 type) WRITEANGLE(save_p, ht->angle); } -// -// SavePolywaypointThinker -// -// Saves a polywaypoint_t thinker -// static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) { const polywaypoint_t *ht = (const void *)th; @@ -1674,20 +2163,11 @@ static void SavePolywaypointThinker(const thinker_t *th, UINT8 type) WRITEINT32(save_p, ht->sequence); WRITEINT32(save_p, ht->pointnum); WRITEINT32(save_p, ht->direction); - WRITEUINT8(save_p, ht->comeback); - WRITEUINT8(save_p, ht->wrap); + WRITEUINT8(save_p, ht->returnbehavior); WRITEUINT8(save_p, ht->continuous); WRITEUINT8(save_p, ht->stophere); - WRITEFIXED(save_p, ht->diffx); - WRITEFIXED(save_p, ht->diffy); - WRITEFIXED(save_p, ht->diffz); } -// -// SavePolyslidedoorThinker -// -// Saves a polyslidedoor_t thinker -// static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type) { const polyslidedoor_t *ht = (const void *)th; @@ -1707,11 +2187,6 @@ static void SavePolyslidedoorThinker(const thinker_t *th, const UINT8 type) WRITEUINT8(save_p, ht->closing); } -// -// SavePolyswingdoorThinker -// -// Saves a polyswingdoor_t thinker -// static void SavePolyswingdoorThinker(const thinker_t *th, const UINT8 type) { const polyswingdoor_t *ht = (const void *)th; @@ -1737,232 +2212,266 @@ static void SavePolydisplaceThinker(const thinker_t *th, const UINT8 type) WRITEFIXED(save_p, ht->oldHeights); } -#endif -/* -// -// SaveWhatThinker -// -// Saves a what_t thinker -// -static inline void SaveWhatThinker(const thinker_t *th, const UINT8 type) +static void SavePolyrotdisplaceThinker(const thinker_t *th, const UINT8 type) { - const what_t *ht = (const void *)th; + const polyrotdisplace_t *ht = (const void *)th; WRITEUINT8(save_p, type); + WRITEINT32(save_p, ht->polyObjNum); + WRITEUINT32(save_p, SaveSector(ht->controlSector)); + WRITEFIXED(save_p, ht->rotscale); + WRITEUINT8(save_p, ht->turnobjs); + WRITEFIXED(save_p, ht->oldHeights); +} + +static void SavePolyfadeThinker(const thinker_t *th, const UINT8 type) +{ + const polyfade_t *ht = (const void *)th; + WRITEUINT8(save_p, type); + WRITEINT32(save_p, ht->polyObjNum); + WRITEINT32(save_p, ht->sourcevalue); + WRITEINT32(save_p, ht->destvalue); + WRITEUINT8(save_p, (UINT8)ht->docollision); + WRITEUINT8(save_p, (UINT8)ht->doghostfade); + WRITEUINT8(save_p, (UINT8)ht->ticbased); + WRITEINT32(save_p, ht->duration); + WRITEINT32(save_p, ht->timer); } -*/ -// -// P_NetArchiveThinkers -// -// static void P_NetArchiveThinkers(void) { const thinker_t *th; - UINT32 numsaved = 0; + UINT32 i; WRITEUINT32(save_p, ARCHIVEBLOCK_THINKERS); - // save off the current thinkers - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (i = 0; i < NUM_THINKERLISTS; i++) { - if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed - || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) - numsaved++; + UINT32 numsaved = 0; + // save off the current thinkers + for (th = thlist[i].next; th != &thlist[i]; th = th->next) + { + if (!(th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed + || th->function.acp1 == (actionf_p1)P_NullPrecipThinker)) + numsaved++; - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - SaveMobjThinker(th, tc_mobj); - continue; - } + if (th->function.acp1 == (actionf_p1)P_MobjThinker) + { + SaveMobjThinker(th, tc_mobj); + continue; + } + #ifdef PARANOIA + else if (th->function.acp1 == (actionf_p1)P_NullPrecipThinker); + #endif + else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) + { + SaveCeilingThinker(th, tc_ceiling); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_CrushCeiling) + { + SaveCeilingThinker(th, tc_crushceiling); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_MoveFloor) + { + SaveFloormoveThinker(th, tc_floor); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_LightningFlash) + { + SaveLightflashThinker(th, tc_flash); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_StrobeFlash) + { + SaveStrobeThinker(th, tc_strobe); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Glow) + { + SaveGlowThinker(th, tc_glow); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_FireFlicker) + { + SaveFireflickerThinker(th, tc_fireflicker); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_MoveElevator) + { + SaveElevatorThinker(th, tc_elevator); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling) + { + SaveContinuousFallThinker(th, tc_continuousfalling); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_ThwompSector) + { + SaveThwompThinker(th, tc_thwomp); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) + { + SaveNoEnemiesThinker(th, tc_noenemies); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) + { + SaveEachTimeThinker(th, tc_eachtime); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_RaiseSector) + { + SaveRaiseThinker(th, tc_raisesector); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_CameraScanner) + { + SaveElevatorThinker(th, tc_camerascanner); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Scroll) + { + SaveScrollThinker(th, tc_scroll); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Friction) + { + SaveFrictionThinker(th, tc_friction); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Pusher) + { + SavePusherThinker(th, tc_pusher); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_BounceCheese) + { + SaveBounceCheeseThinker(th, tc_bouncecheese); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_StartCrumble) + { + SaveCrumbleThinker(th, tc_startcrumble); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_MarioBlock) + { + SaveMarioBlockThinker(th, tc_marioblock); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) + { + SaveMarioCheckThinker(th, tc_marioblockchecker); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_FloatSector) + { + SaveFloatThinker(th, tc_floatsector); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_LaserFlash) + { + SaveLaserThinker(th, tc_laserflash); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_LightFade) + { + SaveLightlevelThinker(th, tc_lightfade); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay) + { + SaveExecutorThinker(th, tc_executor); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Disappear) + { + SaveDisappearThinker(th, tc_disappear); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_Fade) + { + SaveFadeThinker(th, tc_fade); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_FadeColormap) + { + SaveFadeColormapThinker(th, tc_fadecolormap); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PlaneDisplace) + { + SavePlaneDisplaceThinker(th, tc_planedisplace); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) + { + SavePolyrotatetThinker(th, tc_polyrotate); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjMove) + { + SavePolymoveThinker(th, tc_polymove); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint) + { + SavePolywaypointThinker(th, tc_polywaypoint); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide) + { + SavePolyslidedoorThinker(th, tc_polyslidedoor); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing) + { + SavePolyswingdoorThinker(th, tc_polyswingdoor); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag) + { + SavePolymoveThinker(th, tc_polyflag); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace) + { + SavePolydisplaceThinker(th, tc_polydisplace); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjRotDisplace) + { + SavePolyrotdisplaceThinker(th, tc_polyrotdisplace); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_PolyObjFade) + { + SavePolyfadeThinker(th, tc_polyfade); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeLine) + { + SaveDynamicSlopeThinker(th, tc_dynslopeline); + continue; + } + else if (th->function.acp1 == (actionf_p1)T_DynamicSlopeVert) + { + SaveDynamicSlopeThinker(th, tc_dynslopevert); + continue; + } #ifdef PARANOIA - else if (th->function.acp1 == (actionf_p1)P_NullPrecipThinker); + else if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) // wait garbage collection + I_Error("unknown thinker type %p", th->function.acp1); #endif - else if (th->function.acp1 == (actionf_p1)T_MoveCeiling) - { - SaveCeilingThinker(th, tc_ceiling); - continue; } - else if (th->function.acp1 == (actionf_p1)T_CrushCeiling) - { - SaveCeilingThinker(th, tc_crushceiling); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_MoveFloor) - { - SaveFloormoveThinker(th, tc_floor); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_LightningFlash) - { - SaveLightflashThinker(th, tc_flash); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_StrobeFlash) - { - SaveStrobeThinker(th, tc_strobe); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Glow) - { - SaveGlowThinker(th, tc_glow); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_FireFlicker) - { - SaveFireflickerThinker(th, tc_fireflicker); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_MoveElevator) - { - SaveElevatorThinker(th, tc_elevator); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_ContinuousFalling) - { - SaveSpecialLevelThinker(th, tc_continuousfalling); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_ThwompSector) - { - SaveSpecialLevelThinker(th, tc_thwomp); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_NoEnemiesSector) - { - SaveSpecialLevelThinker(th, tc_noenemies); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_EachTimeThinker) - { - SaveSpecialLevelThinker(th, tc_eachtime); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_RaiseSector) - { - SaveSpecialLevelThinker(th, tc_raisesector); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_CameraScanner) - { - SaveElevatorThinker(th, tc_camerascanner); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Scroll) - { - SaveScrollThinker(th, tc_scroll); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Friction) - { - SaveFrictionThinker(th, tc_friction); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Pusher) - { - SavePusherThinker(th, tc_pusher); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_BounceCheese) - { - SaveSpecialLevelThinker(th, tc_bouncecheese); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_StartCrumble) - { - SaveElevatorThinker(th, tc_startcrumble); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_MarioBlock) - { - SaveSpecialLevelThinker(th, tc_marioblock); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_MarioBlockChecker) - { - SaveSpecialLevelThinker(th, tc_marioblockchecker); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_SpikeSector) - { - SaveSpecialLevelThinker(th, tc_spikesector); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_FloatSector) - { - SaveSpecialLevelThinker(th, tc_floatsector); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_BridgeThinker) - { - SaveSpecialLevelThinker(th, tc_bridgethinker); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_LaserFlash) - { - SaveLaserThinker(th, tc_laserflash); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_LightFade) - { - SaveLightlevelThinker(th, tc_lightfade); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_ExecutorDelay) - { - SaveExecutorThinker(th, tc_executor); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_Disappear) - { - SaveDisappearThinker(th, tc_disappear); - continue; - } -#ifdef POLYOBJECTS - else if (th->function.acp1 == (actionf_p1)T_PolyObjRotate) - { - SavePolyrotatetThinker(th, tc_polyrotate); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjMove) - { - SavePolymoveThinker(th, tc_polymove); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjWaypoint) - { - SavePolywaypointThinker(th, tc_polywaypoint); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyDoorSlide) - { - SavePolyslidedoorThinker(th, tc_polyslidedoor); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyDoorSwing) - { - SavePolyswingdoorThinker(th, tc_polyswingdoor); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjFlag) - { - SavePolymoveThinker(th, tc_polyflag); - continue; - } - else if (th->function.acp1 == (actionf_p1)T_PolyObjDisplace) - { - SavePolydisplaceThinker(th, tc_polydisplace); - continue; - } -#endif -#ifdef PARANOIA - else if (th->function.acv != P_RemoveThinkerDelayed) // wait garbage collection - I_Error("unknown thinker type %p", th->function.acp1); -#endif + + CONS_Debug(DBG_NETPLAY, "%u thinkers saved in list %d\n", numsaved, i); + + WRITEUINT8(save_p, tc_end); } - - CONS_Debug(DBG_NETPLAY, "%u thinkers saved\n", numsaved); - - WRITEUINT8(save_p, tc_end); } static void P_NetArchiveWaypoints(void) @@ -2017,14 +2526,16 @@ mobj_t *P_FindNewPosition(UINT32 oldposition) thinker_t *th; mobj_t *mobj; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; mobj = (mobj_t *)th; - if (mobj->mobjnum == oldposition) - return mobj; + if (mobj->mobjnum != oldposition) + continue; + + return mobj; } CONS_Debug(DBG_GAMELOGIC, "mobj not found\n"); return NULL; @@ -2054,12 +2565,19 @@ static inline player_t *LoadPlayer(UINT32 player) return &players[player]; } -// -// LoadMobjThinker -// -// Loads a mobj_t from a save game -// -static void LoadMobjThinker(actionf_p1 thinker) +static inline pslope_t *LoadSlope(UINT32 slopeid) +{ + pslope_t *p = slopelist; + if (slopeid > slopecount) return NULL; + do + { + if (p->id == slopeid) + return p; + } while ((p = p->next)); + return NULL; +} + +static thinker_t* LoadMobjThinker(actionf_p1 thinker) { thinker_t *next; mobj_t *mobj; @@ -2067,6 +2585,7 @@ static void LoadMobjThinker(actionf_p1 thinker) UINT16 diff2; INT32 i; fixed_t z, floorz, ceilingz; + ffloor_t *floorrover = NULL, *ceilingrover = NULL; diff = READUINT32(save_p); if (diff & MD_MORE) @@ -2080,14 +2599,28 @@ static void LoadMobjThinker(actionf_p1 thinker) floorz = READFIXED(save_p); ceilingz = READFIXED(save_p); + if (diff2 & MD2_FLOORROVER) + { + sector_t *sec = LoadSector(READUINT32(save_p)); + UINT16 id = READUINT16(save_p); + floorrover = P_GetFFloorByID(sec, id); + } + + if (diff2 & MD2_CEILINGROVER) + { + sector_t *sec = LoadSector(READUINT32(save_p)); + UINT16 id = READUINT16(save_p); + ceilingrover = P_GetFFloorByID(sec, id); + } + if (diff & MD_SPAWNPOINT) { UINT16 spawnpointnum = READUINT16(save_p); if (mapthings[spawnpointnum].type == 1705 || mapthings[spawnpointnum].type == 1713) // NiGHTS Hoop special case { - P_SpawnHoopsAndRings(&mapthings[spawnpointnum]); - return; + P_SpawnHoop(&mapthings[spawnpointnum]); + return NULL; } mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL); @@ -2104,6 +2637,8 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->z = z; mobj->floorz = floorz; mobj->ceilingz = ceilingz; + mobj->floorrover = floorrover; + mobj->ceilingrover = ceilingrover; if (diff & MD_TYPE) mobj->type = READUINT32(save_p); @@ -2128,12 +2663,16 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->x = READFIXED(save_p); mobj->y = READFIXED(save_p); mobj->angle = READANGLE(save_p); + mobj->pitch = READANGLE(save_p); + mobj->roll = READANGLE(save_p); } else { mobj->x = mobj->spawnpoint->x << FRACBITS; mobj->y = mobj->spawnpoint->y << FRACBITS; mobj->angle = FixedAngle(mobj->spawnpoint->angle*FRACUNIT); + mobj->pitch = FixedAngle(mobj->spawnpoint->pitch*FRACUNIT); + mobj->roll = FixedAngle(mobj->spawnpoint->roll*FRACUNIT); } if (diff & MD_MOM) { @@ -2173,10 +2712,16 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->tics = READINT32(save_p); else mobj->tics = mobj->state->tics; - if (diff & MD_SPRITE) + if (diff & MD_SPRITE) { mobj->sprite = READUINT16(save_p); - else + if (mobj->sprite == SPR_PLAY) + mobj->sprite2 = READUINT8(save_p); + } + else { mobj->sprite = mobj->state->sprite; + if (mobj->sprite == SPR_PLAY) + mobj->sprite2 = mobj->state->frame&FF_FRAMEMASK; + } if (diff & MD_FRAME) { mobj->frame = READUINT32(save_p); @@ -2194,15 +2739,6 @@ static void LoadMobjThinker(actionf_p1 thinker) i = READUINT8(save_p); mobj->player = &players[i]; mobj->player->mo = mobj; - // added for angle prediction - if (consoleplayer == i) - localangle[0] = mobj->angle; - if (displayplayers[1] == i) - localangle[1] = mobj->angle; - if (displayplayers[2] == i) - localangle[2] = mobj->angle; - if (displayplayers[3] == i) - localangle[3] = mobj->angle; } if (diff & MD_MOVEDIR) mobj->movedir = READANGLE(save_p); @@ -2225,7 +2761,7 @@ static void LoadMobjThinker(actionf_p1 thinker) if (diff & MD_MOVEFACTOR) mobj->movefactor = READFIXED(save_p); else - mobj->movefactor = FRACUNIT; //mobj->movefactor = ORIG_FRICTION_FACTOR; + mobj->movefactor = FRACUNIT; if (diff & MD_FUSE) mobj->fuse = READINT32(save_p); if (diff & MD_WATERTOP) @@ -2251,7 +2787,7 @@ static void LoadMobjThinker(actionf_p1 thinker) if (diff2 & MD2_SKIN) mobj->skin = &skins[READUINT8(save_p)]; if (diff2 & MD2_COLOR) - mobj->color = READUINT8(save_p); + mobj->color = READUINT16(save_p); if (diff2 & MD2_EXTVAL1) mobj->extravalue1 = READINT32(save_p); if (diff2 & MD2_EXTVAL2) @@ -2262,7 +2798,6 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p); if (diff2 & MD2_ITNEXT) mobj->itnext = (mobj_t *)(size_t)READUINT32(save_p); -#ifdef ESLOPE if (diff2 & MD2_SLOPE) { mobj->standingslope = P_SlopeById(READUINT16(save_p)); @@ -2270,11 +2805,17 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->modeltilt = mobj->standingslope; #endif } -#endif if (diff2 & MD2_COLORIZED) mobj->colorized = READUINT8(save_p); + if (diff2 & MD2_MIRRORED) + mobj->mirrored = READUINT8(save_p); + if (diff2 & MD2_ROLLANGLE) + mobj->rollangle = READANGLE(save_p); if (diff2 & MD2_SHADOWSCALE) + { mobj->shadowscale = READFIXED(save_p); + mobj->whiteshadow = READUINT8(save_p); + } if (diff2 & MD2_DRAWFLAGS) mobj->drawflags = READUINT16(save_p); @@ -2302,8 +2843,6 @@ static void LoadMobjThinker(actionf_p1 thinker) mobj->player->viewz = mobj->player->mo->z + mobj->player->viewheight; } - P_AddThinker(&mobj->thinker); - if (diff2 & MD2_WAYPOINTCAP) P_SetTarget(&waypointcap, mobj); @@ -2311,49 +2850,150 @@ static void LoadMobjThinker(actionf_p1 thinker) P_SetTarget(&kitemcap, mobj); mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function + + return &mobj->thinker; } -// -// LoadSpecialLevelThinker -// -// Loads a levelspecthink_t from a save game -// -// floorOrCeiling: -// 0 - Don't set -// 1 - Floor Only -// 2 - Ceiling Only -// 3 - Both -// -static void LoadSpecialLevelThinker(actionf_p1 thinker, UINT8 floorOrCeiling) +static thinker_t* LoadNoEnemiesThinker(actionf_p1 thinker) { - levelspecthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - size_t i; + noenemies_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + return &ht->thinker; +} + +static thinker_t* LoadBounceCheeseThinker(actionf_p1 thinker) +{ + bouncecheese_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; - for (i = 0; i < 16; i++) - { - ht->vars[i] = READFIXED(save_p); //var[16] - ht->var2s[i] = READFIXED(save_p); //var[16] - } ht->sourceline = LoadLine(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p)); + ht->speed = READFIXED(save_p); + ht->distance = READFIXED(save_p); + ht->floorwasheight = READFIXED(save_p); + ht->ceilingwasheight = READFIXED(save_p); + ht->low = READCHAR(save_p); + + if (ht->sector) + ht->sector->ceilingdata = ht; + + return &ht->thinker; +} + +static thinker_t* LoadContinuousFallThinker(actionf_p1 thinker) +{ + continuousfall_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sector = LoadSector(READUINT32(save_p)); + ht->speed = READFIXED(save_p); + ht->direction = READINT32(save_p); + ht->floorstartheight = READFIXED(save_p); + ht->ceilingstartheight = READFIXED(save_p); + ht->destheight = READFIXED(save_p); if (ht->sector) { - if (floorOrCeiling & 2) - ht->sector->ceilingdata = ht; - if (floorOrCeiling & 1) - ht->sector->floordata = ht; + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; } - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadCeilingThinker -// -// Loads a ceiling_t from a save game -// -static void LoadCeilingThinker(actionf_p1 thinker) +static thinker_t* LoadMarioBlockThinker(actionf_p1 thinker) +{ + mariothink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sector = LoadSector(READUINT32(save_p)); + ht->speed = READFIXED(save_p); + ht->direction = READINT32(save_p); + ht->floorstartheight = READFIXED(save_p); + ht->ceilingstartheight = READFIXED(save_p); + ht->tag = READINT16(save_p); + + if (ht->sector) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + + return &ht->thinker; +} + +static thinker_t* LoadMarioCheckThinker(actionf_p1 thinker) +{ + mariocheck_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sector = LoadSector(READUINT32(save_p)); + return &ht->thinker; +} + +static thinker_t* LoadThwompThinker(actionf_p1 thinker) +{ + thwomp_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sector = LoadSector(READUINT32(save_p)); + ht->crushspeed = READFIXED(save_p); + ht->retractspeed = READFIXED(save_p); + ht->direction = READINT32(save_p); + ht->floorstartheight = READFIXED(save_p); + ht->ceilingstartheight = READFIXED(save_p); + ht->delay = READINT32(save_p); + ht->tag = READINT16(save_p); + ht->sound = READUINT16(save_p); + + if (ht->sector) + { + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; + } + + return &ht->thinker; +} + +static thinker_t* LoadFloatThinker(actionf_p1 thinker) +{ + floatthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sector = LoadSector(READUINT32(save_p)); + ht->tag = READINT16(save_p); + return &ht->thinker; +} + +static thinker_t* LoadEachTimeThinker(actionf_p1 thinker) +{ + size_t i; + eachtime_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + for (i = 0; i < MAXPLAYERS; i++) + { + ht->playersInArea[i] = READCHAR(save_p); + ht->playersOnArea[i] = READCHAR(save_p); + } + ht->triggerOnExit = READCHAR(save_p); + return &ht->thinker; +} + +static thinker_t* LoadRaiseThinker(actionf_p1 thinker) +{ + raise_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->tag = READINT16(save_p); + ht->sector = LoadSector(READUINT32(save_p)); + ht->ceilingbottom = READFIXED(save_p); + ht->ceilingtop = READFIXED(save_p); + ht->basespeed = READFIXED(save_p); + ht->extraspeed = READFIXED(save_p); + ht->shaketimer = READUINT8(save_p); + ht->flags = READUINT8(save_p); + return &ht->thinker; +} + +static thinker_t* LoadCeilingThinker(actionf_p1 thinker) { ceiling_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2374,15 +3014,10 @@ static void LoadCeilingThinker(actionf_p1 thinker) ht->sourceline = READFIXED(save_p); if (ht->sector) ht->sector->ceilingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadFloormoveThinker -// -// Loads a floormove_t from a save game -// -static void LoadFloormoveThinker(actionf_p1 thinker) +static thinker_t* LoadFloormoveThinker(actionf_p1 thinker) { floormove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2398,15 +3033,10 @@ static void LoadFloormoveThinker(actionf_p1 thinker) ht->delaytimer = READFIXED(save_p); if (ht->sector) ht->sector->floordata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadLightflashThinker -// -// Loads a lightflash_t from a save game -// -static void LoadLightflashThinker(actionf_p1 thinker) +static thinker_t* LoadLightflashThinker(actionf_p1 thinker) { lightflash_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2415,15 +3045,10 @@ static void LoadLightflashThinker(actionf_p1 thinker) ht->minlight = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadStrobeThinker -// -// Loads a strobe_t from a save game -// -static void LoadStrobeThinker(actionf_p1 thinker) +static thinker_t* LoadStrobeThinker(actionf_p1 thinker) { strobe_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2435,15 +3060,10 @@ static void LoadStrobeThinker(actionf_p1 thinker) ht->brighttime = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadGlowThinker -// -// Loads a glow_t from a save game -// -static void LoadGlowThinker(actionf_p1 thinker) +static thinker_t* LoadGlowThinker(actionf_p1 thinker) { glow_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2454,14 +3074,10 @@ static void LoadGlowThinker(actionf_p1 thinker) ht->speed = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadFireflickerThinker -// -// Loads a fireflicker_t from a save game -// -static void LoadFireflickerThinker(actionf_p1 thinker) + +static thinker_t* LoadFireflickerThinker(actionf_p1 thinker) { fireflicker_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2472,14 +3088,10 @@ static void LoadFireflickerThinker(actionf_p1 thinker) ht->minlight = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadElevatorThinker -// -// Loads a elevator_t from a save game -// -static void LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling) + +static thinker_t* LoadElevatorThinker(actionf_p1 thinker, boolean setplanedata) { elevator_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2498,26 +3110,40 @@ static void LoadElevatorThinker(actionf_p1 thinker, UINT8 floorOrCeiling) ht->delaytimer = READFIXED(save_p); ht->floorwasheight = READFIXED(save_p); ht->ceilingwasheight = READFIXED(save_p); - ht->player = LoadPlayer(READUINT32(save_p)); // was dummy ht->sourceline = LoadLine(READUINT32(save_p)); - if (ht->sector) + if (ht->sector && setplanedata) { - if (floorOrCeiling & 2) - ht->sector->ceilingdata = ht; - if (floorOrCeiling & 1) - ht->sector->floordata = ht; + ht->sector->ceilingdata = ht; + ht->sector->floordata = ht; } - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadScrollThinker -// -// Loads a scroll_t from a save game -// -static void LoadScrollThinker(actionf_p1 thinker) +static thinker_t* LoadCrumbleThinker(actionf_p1 thinker) +{ + crumble_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->sector = LoadSector(READUINT32(save_p)); + ht->actionsector = LoadSector(READUINT32(save_p)); + ht->player = LoadPlayer(READUINT32(save_p)); + ht->direction = READINT32(save_p); + ht->origalpha = READINT32(save_p); + ht->timer = READINT32(save_p); + ht->speed = READFIXED(save_p); + ht->floorwasheight = READFIXED(save_p); + ht->ceilingwasheight = READFIXED(save_p); + ht->flags = READUINT8(save_p); + + if (ht->sector) + ht->sector->floordata = ht; + + return &ht->thinker; +} + +static thinker_t* LoadScrollThinker(actionf_p1 thinker) { scroll_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2531,15 +3157,10 @@ static void LoadScrollThinker(actionf_p1 thinker) ht->accel = READINT32(save_p); ht->exclusive = READINT32(save_p); ht->type = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadFrictionThinker -// -// Loads a friction_t from a save game -// -static inline void LoadFrictionThinker(actionf_p1 thinker) +static inline thinker_t* LoadFrictionThinker(actionf_p1 thinker) { friction_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2548,15 +3169,10 @@ static inline void LoadFrictionThinker(actionf_p1 thinker) ht->affectee = READINT32(save_p); ht->referrer = READINT32(save_p); ht->roverfriction = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadPusherThinker -// -// Loads a pusher_t from a save game -// -static void LoadPusherThinker(actionf_p1 thinker) +static thinker_t* LoadPusherThinker(actionf_p1 thinker) { pusher_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2574,52 +3190,35 @@ static void LoadPusherThinker(actionf_p1 thinker) ht->exclusive = READINT32(save_p); ht->slider = READINT32(save_p); ht->source = P_GetPushThing(ht->affectee); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadLaserThinker -// -// Loads a laserthink_t from a save game -// -static inline void LoadLaserThinker(actionf_p1 thinker) +static inline thinker_t* LoadLaserThinker(actionf_p1 thinker) { laserthink_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); - ffloor_t *rover = NULL; ht->thinker.function.acp1 = thinker; - ht->sector = LoadSector(READUINT32(save_p)); - ht->sec = LoadSector(READUINT32(save_p)); + ht->tag = READINT16(save_p); ht->sourceline = LoadLine(READUINT32(save_p)); - for (rover = ht->sector->ffloors; rover; rover = rover->next) - if (rover->secnum == (size_t)(ht->sec - sectors) - && rover->master == ht->sourceline) - ht->ffloor = rover; - P_AddThinker(&ht->thinker); + ht->nobosses = READUINT8(save_p); + return &ht->thinker; } -// -// LoadLightlevelThinker -// -// Loads a lightlevel_t from a save game -// -static inline void LoadLightlevelThinker(actionf_p1 thinker) +static inline thinker_t* LoadLightlevelThinker(actionf_p1 thinker) { lightlevel_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->sector = LoadSector(READUINT32(save_p)); - ht->destlevel = READINT32(save_p); - ht->speed = READINT32(save_p); + ht->sourcelevel = READINT16(save_p); + ht->destlevel = READINT16(save_p); + ht->fixedcurlevel = READFIXED(save_p); + ht->fixedpertic = READFIXED(save_p); + ht->timer = READINT32(save_p); if (ht->sector) ht->sector->lightingdata = ht; - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadExecutorThinker -// -// Loads a executor_t from a save game -// -static inline void LoadExecutorThinker(actionf_p1 thinker) +static inline thinker_t* LoadExecutorThinker(actionf_p1 thinker) { executor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2627,15 +3226,10 @@ static inline void LoadExecutorThinker(actionf_p1 thinker) ht->caller = LoadMobj(READUINT32(save_p)); ht->sector = LoadSector(READUINT32(save_p)); ht->timer = READINT32(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadDisappearThinker -// -// Loads a disappear_t thinker -// -static inline void LoadDisappearThinker(actionf_p1 thinker) +static inline thinker_t* LoadDisappearThinker(actionf_p1 thinker) { disappear_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2646,32 +3240,105 @@ static inline void LoadDisappearThinker(actionf_p1 thinker) ht->affectee = READINT32(save_p); ht->sourceline = READINT32(save_p); ht->exists = READINT32(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -#ifdef POLYOBJECTS +static inline thinker_t* LoadFadeThinker(actionf_p1 thinker) +{ + sector_t *ss; + fade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); + ht->sectornum = READUINT32(save_p); + ht->ffloornum = READUINT32(save_p); + ht->alpha = READINT32(save_p); + ht->sourcevalue = READINT16(save_p); + ht->destvalue = READINT16(save_p); + ht->destlightlevel = READINT16(save_p); + ht->speed = READINT16(save_p); + ht->ticbased = (boolean)READUINT8(save_p); + ht->timer = READINT32(save_p); + ht->doexists = READUINT8(save_p); + ht->dotranslucent = READUINT8(save_p); + ht->dolighting = READUINT8(save_p); + ht->docolormap = READUINT8(save_p); + ht->docollision = READUINT8(save_p); + ht->doghostfade = READUINT8(save_p); + ht->exactalpha = READUINT8(save_p); -// -// LoadPolyrotateThinker -// -// Loads a polyrotate_t thinker -// -static inline void LoadPolyrotatetThinker(actionf_p1 thinker) + ss = LoadSector(ht->sectornum); + if (ss) + { + size_t j = 0; // ss->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc + ffloor_t *rover; + for (rover = ss->ffloors; rover; rover = rover->next) + { + if (j == ht->ffloornum) + { + ht->rover = rover; + rover->fadingdata = ht; + break; + } + j++; + } + } + return &ht->thinker; +} + +static inline thinker_t* LoadFadeColormapThinker(actionf_p1 thinker) +{ + fadecolormap_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->sector = LoadSector(READUINT32(save_p)); + ht->source_exc = GetNetColormapFromList(READUINT32(save_p)); + ht->dest_exc = GetNetColormapFromList(READUINT32(save_p)); + ht->ticbased = (boolean)READUINT8(save_p); + ht->duration = READINT32(save_p); + ht->timer = READINT32(save_p); + if (ht->sector) + ht->sector->fadecolormapdata = ht; + return &ht->thinker; +} + +static inline thinker_t* LoadPlaneDisplaceThinker(actionf_p1 thinker) +{ + planedisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + + ht->affectee = READINT32(save_p); + ht->control = READINT32(save_p); + ht->last_height = READFIXED(save_p); + ht->speed = READFIXED(save_p); + ht->type = READUINT8(save_p); + return &ht->thinker; +} + +static inline thinker_t* LoadDynamicSlopeThinker(actionf_p1 thinker) +{ + dynplanethink_t* ht = Z_Malloc(sizeof(*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + + ht->type = READUINT8(save_p); + ht->slope = LoadSlope(READUINT32(save_p)); + ht->sourceline = LoadLine(READUINT32(save_p)); + ht->extent = READFIXED(save_p); + READMEM(save_p, ht->tags, sizeof(ht->tags)); + READMEM(save_p, ht->vex, sizeof(ht->vex)); + return &ht->thinker; +} + +static inline thinker_t* LoadPolyrotatetThinker(actionf_p1 thinker) { polyrotate_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; ht->polyObjNum = READINT32(save_p); ht->speed = READINT32(save_p); ht->distance = READINT32(save_p); - P_AddThinker(&ht->thinker); + ht->turnobjs = READUINT8(save_p); + return &ht->thinker; } -// -// LoadPolymoveThinker -// -// Loads a polymovet_t thinker -// -static void LoadPolymoveThinker(actionf_p1 thinker) +static thinker_t* LoadPolymoveThinker(actionf_p1 thinker) { polymove_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2681,15 +3348,10 @@ static void LoadPolymoveThinker(actionf_p1 thinker) ht->momy = READFIXED(save_p); ht->distance = READINT32(save_p); ht->angle = READANGLE(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadPolywaypointThinker -// -// Loads a polywaypoint_t thinker -// -static inline void LoadPolywaypointThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolywaypointThinker(actionf_p1 thinker) { polywaypoint_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2698,22 +3360,13 @@ static inline void LoadPolywaypointThinker(actionf_p1 thinker) ht->sequence = READINT32(save_p); ht->pointnum = READINT32(save_p); ht->direction = READINT32(save_p); - ht->comeback = READUINT8(save_p); - ht->wrap = READUINT8(save_p); + ht->returnbehavior = READUINT8(save_p); ht->continuous = READUINT8(save_p); ht->stophere = READUINT8(save_p); - ht->diffx = READFIXED(save_p); - ht->diffy = READFIXED(save_p); - ht->diffz = READFIXED(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadPolyslidedoorThinker -// -// loads a polyslidedoor_t thinker -// -static inline void LoadPolyslidedoorThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyslidedoorThinker(actionf_p1 thinker) { polyslidedoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2730,15 +3383,10 @@ static inline void LoadPolyslidedoorThinker(actionf_p1 thinker) ht->momx = READFIXED(save_p); ht->momy = READFIXED(save_p); ht->closing = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadPolyswingdoorThinker -// -// Loads a polyswingdoor_t thinker -// -static inline void LoadPolyswingdoorThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyswingdoorThinker(actionf_p1 thinker) { polyswingdoor_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2750,15 +3398,10 @@ static inline void LoadPolyswingdoorThinker(actionf_p1 thinker) ht->initDistance = READINT32(save_p); ht->distance = READINT32(save_p); ht->closing = READUINT8(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -// -// LoadPolydisplaceThinker -// -// Loads a polydisplace_t thinker -// -static inline void LoadPolydisplaceThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolydisplaceThinker(actionf_p1 thinker) { polydisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; @@ -2767,26 +3410,36 @@ static inline void LoadPolydisplaceThinker(actionf_p1 thinker) ht->dx = READFIXED(save_p); ht->dy = READFIXED(save_p); ht->oldHeights = READFIXED(save_p); - P_AddThinker(&ht->thinker); + return &ht->thinker; } -#endif -/* -// -// LoadWhatThinker -// -// load a what_t thinker -// -static inline void LoadWhatThinker(actionf_p1 thinker) +static inline thinker_t* LoadPolyrotdisplaceThinker(actionf_p1 thinker) { - what_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + polyrotdisplace_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); ht->thinker.function.acp1 = thinker; + ht->polyObjNum = READINT32(save_p); + ht->controlSector = LoadSector(READUINT32(save_p)); + ht->rotscale = READFIXED(save_p); + ht->turnobjs = READUINT8(save_p); + ht->oldHeights = READFIXED(save_p); + return &ht->thinker; +} + +static thinker_t* LoadPolyfadeThinker(actionf_p1 thinker) +{ + polyfade_t *ht = Z_Malloc(sizeof (*ht), PU_LEVSPEC, NULL); + ht->thinker.function.acp1 = thinker; + ht->polyObjNum = READINT32(save_p); + ht->sourcevalue = READINT32(save_p); + ht->destvalue = READINT32(save_p); + ht->docollision = (boolean)READUINT8(save_p); + ht->doghostfade = (boolean)READUINT8(save_p); + ht->ticbased = (boolean)READUINT8(save_p); + ht->duration = READINT32(save_p); + ht->timer = READINT32(save_p); + return &ht->thinker; } -*/ -// -// P_NetUnArchiveThinkers -// static void P_NetUnArchiveThinkers(void) { thinker_t *currentthinker; @@ -2800,15 +3453,18 @@ static void P_NetUnArchiveThinkers(void) I_Error("Bad $$$.sav at archive block Thinkers"); // remove all the current thinkers - currentthinker = thinkercap.next; - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = next) + for (i = 0; i < NUM_THINKERLISTS; i++) { - next = currentthinker->next; + currentthinker = thlist[i].next; + for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = next) + { + next = currentthinker->next; - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) - P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it - else - Z_Free(currentthinker); + if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) + P_RemoveSavegameMobj((mobj_t *)currentthinker); // item isn't saved, don't remove it + else + Z_Free(currentthinker); + } } // we don't want the removed mobjs to come back @@ -2818,187 +3474,209 @@ static void P_NetUnArchiveThinkers(void) // clear sector thinker pointers so they don't point to non-existant thinkers for all of eternity for (i = 0; i < numsectors; i++) { - sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = NULL; + sectors[i].floordata = sectors[i].ceilingdata = sectors[i].lightingdata = sectors[i].fadecolormapdata = NULL; } // read in saved thinkers - for (;;) + for (i = 0; i < NUM_THINKERLISTS; i++) { - tclass = READUINT8(save_p); - - if (tclass == tc_end) - break; // leave the saved thinker reading loop - numloaded++; - - switch (tclass) + for (;;) { - case tc_mobj: - LoadMobjThinker((actionf_p1)P_MobjThinker); - break; + thinker_t* th = NULL; + tclass = READUINT8(save_p); - case tc_ceiling: - LoadCeilingThinker((actionf_p1)T_MoveCeiling); - break; + if (tclass == tc_end) + break; // leave the saved thinker reading loop + numloaded++; - case tc_crushceiling: - LoadCeilingThinker((actionf_p1)T_CrushCeiling); - break; + switch (tclass) + { + case tc_mobj: + th = LoadMobjThinker((actionf_p1)P_MobjThinker); + break; - case tc_floor: - LoadFloormoveThinker((actionf_p1)T_MoveFloor); - break; + case tc_ceiling: + th = LoadCeilingThinker((actionf_p1)T_MoveCeiling); + break; - case tc_flash: - LoadLightflashThinker((actionf_p1)T_LightningFlash); - break; + case tc_crushceiling: + th = LoadCeilingThinker((actionf_p1)T_CrushCeiling); + break; - case tc_strobe: - LoadStrobeThinker((actionf_p1)T_StrobeFlash); - break; + case tc_floor: + th = LoadFloormoveThinker((actionf_p1)T_MoveFloor); + break; - case tc_glow: - LoadGlowThinker((actionf_p1)T_Glow); - break; + case tc_flash: + th = LoadLightflashThinker((actionf_p1)T_LightningFlash); + break; - case tc_fireflicker: - LoadFireflickerThinker((actionf_p1)T_FireFlicker); - break; + case tc_strobe: + th = LoadStrobeThinker((actionf_p1)T_StrobeFlash); + break; - case tc_elevator: - LoadElevatorThinker((actionf_p1)T_MoveElevator, 3); - break; + case tc_glow: + th = LoadGlowThinker((actionf_p1)T_Glow); + break; - case tc_continuousfalling: - LoadSpecialLevelThinker((actionf_p1)T_ContinuousFalling, 3); - break; + case tc_fireflicker: + th = LoadFireflickerThinker((actionf_p1)T_FireFlicker); + break; - case tc_thwomp: - LoadSpecialLevelThinker((actionf_p1)T_ThwompSector, 3); - break; + case tc_elevator: + th = LoadElevatorThinker((actionf_p1)T_MoveElevator, true); + break; - case tc_noenemies: - LoadSpecialLevelThinker((actionf_p1)T_NoEnemiesSector, 0); - break; + case tc_continuousfalling: + th = LoadContinuousFallThinker((actionf_p1)T_ContinuousFalling); + break; - case tc_eachtime: - LoadSpecialLevelThinker((actionf_p1)T_EachTimeThinker, 0); - break; + case tc_thwomp: + th = LoadThwompThinker((actionf_p1)T_ThwompSector); + break; - case tc_raisesector: - LoadSpecialLevelThinker((actionf_p1)T_RaiseSector, 0); - break; + case tc_noenemies: + th = LoadNoEnemiesThinker((actionf_p1)T_NoEnemiesSector); + break; - /// \todo rewrite all the code that uses an elevator_t but isn't an elevator - /// \note working on it! - case tc_camerascanner: - LoadElevatorThinker((actionf_p1)T_CameraScanner, 0); - break; + case tc_eachtime: + th = LoadEachTimeThinker((actionf_p1)T_EachTimeThinker); + break; - case tc_bouncecheese: - LoadSpecialLevelThinker((actionf_p1)T_BounceCheese, 2); - break; + case tc_raisesector: + th = LoadRaiseThinker((actionf_p1)T_RaiseSector); + break; - case tc_startcrumble: - LoadElevatorThinker((actionf_p1)T_StartCrumble, 1); - break; + case tc_camerascanner: + th = LoadElevatorThinker((actionf_p1)T_CameraScanner, false); + break; - case tc_marioblock: - LoadSpecialLevelThinker((actionf_p1)T_MarioBlock, 3); - break; + case tc_bouncecheese: + th = LoadBounceCheeseThinker((actionf_p1)T_BounceCheese); + break; - case tc_marioblockchecker: - LoadSpecialLevelThinker((actionf_p1)T_MarioBlockChecker, 0); - break; + case tc_startcrumble: + th = LoadCrumbleThinker((actionf_p1)T_StartCrumble); + break; - case tc_spikesector: - LoadSpecialLevelThinker((actionf_p1)T_SpikeSector, 0); - break; + case tc_marioblock: + th = LoadMarioBlockThinker((actionf_p1)T_MarioBlock); + break; - case tc_floatsector: - LoadSpecialLevelThinker((actionf_p1)T_FloatSector, 0); - break; + case tc_marioblockchecker: + th = LoadMarioCheckThinker((actionf_p1)T_MarioBlockChecker); + break; - case tc_bridgethinker: - LoadSpecialLevelThinker((actionf_p1)T_BridgeThinker, 3); - break; + case tc_floatsector: + th = LoadFloatThinker((actionf_p1)T_FloatSector); + break; - case tc_laserflash: - LoadLaserThinker((actionf_p1)T_LaserFlash); - break; + case tc_laserflash: + th = LoadLaserThinker((actionf_p1)T_LaserFlash); + break; - case tc_lightfade: - LoadLightlevelThinker((actionf_p1)T_LightFade); - break; + case tc_lightfade: + th = LoadLightlevelThinker((actionf_p1)T_LightFade); + break; - case tc_executor: - LoadExecutorThinker((actionf_p1)T_ExecutorDelay); - restoreNum = true; - break; + case tc_executor: + th = LoadExecutorThinker((actionf_p1)T_ExecutorDelay); + restoreNum = true; + break; - case tc_disappear: - LoadDisappearThinker((actionf_p1)T_Disappear); - break; -#ifdef POLYOBJECTS - case tc_polyrotate: - LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); - break; + case tc_disappear: + th = LoadDisappearThinker((actionf_p1)T_Disappear); + break; - case tc_polymove: - LoadPolymoveThinker((actionf_p1)T_PolyObjMove); - break; + case tc_fade: + th = LoadFadeThinker((actionf_p1)T_Fade); + break; - case tc_polywaypoint: - LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); - break; + case tc_fadecolormap: + th = LoadFadeColormapThinker((actionf_p1)T_FadeColormap); + break; - case tc_polyslidedoor: - LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide); - break; + case tc_planedisplace: + th = LoadPlaneDisplaceThinker((actionf_p1)T_PlaneDisplace); + break; + case tc_polyrotate: + th = LoadPolyrotatetThinker((actionf_p1)T_PolyObjRotate); + break; - case tc_polyswingdoor: - LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing); - break; + case tc_polymove: + th = LoadPolymoveThinker((actionf_p1)T_PolyObjMove); + break; - case tc_polyflag: - LoadPolymoveThinker((actionf_p1)T_PolyObjFlag); - break; + case tc_polywaypoint: + th = LoadPolywaypointThinker((actionf_p1)T_PolyObjWaypoint); + break; - case tc_polydisplace: - LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); - break; -#endif - case tc_scroll: - LoadScrollThinker((actionf_p1)T_Scroll); - break; + case tc_polyslidedoor: + th = LoadPolyslidedoorThinker((actionf_p1)T_PolyDoorSlide); + break; - case tc_friction: - LoadFrictionThinker((actionf_p1)T_Friction); - break; + case tc_polyswingdoor: + th = LoadPolyswingdoorThinker((actionf_p1)T_PolyDoorSwing); + break; - case tc_pusher: - LoadPusherThinker((actionf_p1)T_Pusher); - break; + case tc_polyflag: + th = LoadPolymoveThinker((actionf_p1)T_PolyObjFlag); + break; - default: - I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass); + case tc_polydisplace: + th = LoadPolydisplaceThinker((actionf_p1)T_PolyObjDisplace); + break; + + case tc_polyrotdisplace: + th = LoadPolyrotdisplaceThinker((actionf_p1)T_PolyObjRotDisplace); + break; + + case tc_polyfade: + th = LoadPolyfadeThinker((actionf_p1)T_PolyObjFade); + break; + + case tc_dynslopeline: + th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeLine); + break; + + case tc_dynslopevert: + th = LoadDynamicSlopeThinker((actionf_p1)T_DynamicSlopeVert); + break; + + case tc_scroll: + th = LoadScrollThinker((actionf_p1)T_Scroll); + break; + + case tc_friction: + th = LoadFrictionThinker((actionf_p1)T_Friction); + break; + + case tc_pusher: + th = LoadPusherThinker((actionf_p1)T_Pusher); + break; + + default: + I_Error("P_UnarchiveSpecials: Unknown tclass %d in savegame", tclass); + } + if (th) + P_AddThinker(i, th); } - } - CONS_Debug(DBG_NETPLAY, "%u thinkers loaded\n", numloaded); + CONS_Debug(DBG_NETPLAY, "%u thinkers loaded in list %d\n", numloaded, i); + } if (restoreNum) { executor_t *delay = NULL; UINT32 mobjnum; - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; - currentthinker = currentthinker->next) + for (currentthinker = thlist[THINK_MAIN].next; currentthinker != &thlist[THINK_MAIN]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)T_ExecutorDelay) - { - delay = (void *)currentthinker; - if ((mobjnum = (UINT32)(size_t)delay->caller)) - delay->caller = P_FindNewPosition(mobjnum); - } + if (currentthinker->function.acp1 != (actionf_p1)T_ExecutorDelay) + continue; + delay = (void *)currentthinker; + if (!(mobjnum = (UINT32)(size_t)delay->caller)) + continue; + delay->caller = P_FindNewPosition(mobjnum); } } } @@ -3007,7 +3685,6 @@ static void P_NetUnArchiveThinkers(void) // // haleyjd 03/26/06: PolyObject saving code // -#ifdef POLYOBJECTS #define PD_FLAGS 0x01 #define PD_TRANS 0x02 @@ -3022,7 +3699,7 @@ static inline void P_ArchivePolyObj(polyobj_t *po) if (po->flags != po->spawnflags) diff |= PD_FLAGS; - if (po->translucency != 0) + if (po->translucency != po->spawntrans) diff |= PD_TRANS; WRITEUINT8(save_p, diff); @@ -3096,24 +3773,21 @@ static inline void P_UnArchivePolyObjects(void) for (i = 0; i < numSavedPolys; ++i) P_UnArchivePolyObj(&PolyObjects[i]); } -#endif -// -// P_FinishMobjs -// + static inline void P_FinishMobjs(void) { thinker_t *currentthinker; mobj_t *mobj; // put info field there real value - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; + for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) - { - mobj = (mobj_t *)currentthinker; - mobj->info = &mobjinfo[mobj->type]; - } + if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mobj = (mobj_t *)currentthinker; + mobj->info = &mobjinfo[mobj->type]; } } @@ -3124,115 +3798,97 @@ static void P_RelinkPointers(void) UINT32 temp; // use info field (value = oldposition) to relink mobjs - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; + for (currentthinker = thlist[THINK_MOBJ].next; currentthinker != &thlist[THINK_MOBJ]; currentthinker = currentthinker->next) { - if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker) + if (currentthinker->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mobj = (mobj_t *)currentthinker; + + if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) + continue; + + if (mobj->tracer) { - mobj = (mobj_t *)currentthinker; - - if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) - continue; - - if (mobj->tracer) + temp = (UINT32)(size_t)mobj->tracer; + mobj->tracer = NULL; + if (!P_SetTarget(&mobj->tracer, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "tracer not found on %d\n", mobj->type); + } + if (mobj->target) + { + temp = (UINT32)(size_t)mobj->target; + mobj->target = NULL; + if (!P_SetTarget(&mobj->target, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "target not found on %d\n", mobj->type); + } + if (mobj->hnext) + { + temp = (UINT32)(size_t)mobj->hnext; + mobj->hnext = NULL; + if (!(mobj->hnext = P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "hnext not found on %d\n", mobj->type); + } + if (mobj->hprev) + { + temp = (UINT32)(size_t)mobj->hprev; + mobj->hprev = NULL; + if (!(mobj->hprev = P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type); + } + if (mobj->itnext) + { + temp = (UINT32)(size_t)mobj->itnext; + mobj->itnext = NULL; + if (!(mobj->itnext = P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type); + } + if (mobj->player) + { + if ( mobj->player->awayviewmobj) { - temp = (UINT32)(size_t)mobj->tracer; - mobj->tracer = NULL; - if (!P_SetTarget(&mobj->tracer, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "tracer not found on %d\n", mobj->type); + temp = (UINT32)(size_t)mobj->player->awayviewmobj; + mobj->player->awayviewmobj = NULL; + if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type); } - if (mobj->target) + if (mobj->player->followmobj) { - temp = (UINT32)(size_t)mobj->target; - mobj->target = NULL; - if (!P_SetTarget(&mobj->target, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "target not found on %d\n", mobj->type); + temp = (UINT32)(size_t)mobj->player->followmobj; + mobj->player->followmobj = NULL; + if (!P_SetTarget(&mobj->player->followmobj, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "followmobj not found on %d\n", mobj->type); } - if (mobj->hnext) + if (mobj->player->follower) { - temp = (UINT32)(size_t)mobj->hnext; - mobj->hnext = NULL; - if (!(mobj->hnext = P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "hnext not found on %d\n", mobj->type); + temp = (UINT32)(size_t)mobj->player->follower; + mobj->player->follower = NULL; + if (!P_SetTarget(&mobj->player->follower, P_FindNewPosition(temp))) + CONS_Debug(DBG_GAMELOGIC, "follower not found on %d\n", mobj->type); } - if (mobj->hprev) + if (mobj->player->nextwaypoint) { - temp = (UINT32)(size_t)mobj->hprev; - mobj->hprev = NULL; - if (!(mobj->hprev = P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type); + temp = (UINT32)(size_t)mobj->player->nextwaypoint; + mobj->player->nextwaypoint = K_GetWaypointFromIndex(temp); + if (mobj->player->nextwaypoint == NULL) + { + CONS_Debug(DBG_GAMELOGIC, "nextwaypoint not found on %d\n", mobj->type); + } } - if (mobj->itnext) + if (mobj->player->respawn.wp) { - temp = (UINT32)(size_t)mobj->itnext; - mobj->itnext = NULL; - if (!(mobj->itnext = P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type); - } - - if (mobj->player) - { - if (mobj->player->capsule) + temp = (UINT32)(size_t)mobj->player->respawn.wp; + mobj->player->respawn.wp = K_GetWaypointFromIndex(temp); + if (mobj->player->respawn.wp == NULL) { - temp = (UINT32)(size_t)mobj->player->capsule; - mobj->player->capsule = NULL; - if (!P_SetTarget(&mobj->player->capsule, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "capsule not found on %d\n", mobj->type); - } - if (mobj->player->axis1) - { - temp = (UINT32)(size_t)mobj->player->axis1; - mobj->player->axis1 = NULL; - if (!P_SetTarget(&mobj->player->axis1, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "axis1 not found on %d\n", mobj->type); - } - if (mobj->player->axis2) - { - temp = (UINT32)(size_t)mobj->player->axis2; - mobj->player->axis2 = NULL; - if (!P_SetTarget(&mobj->player->axis2, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "axis2 not found on %d\n", mobj->type); - } - if (mobj->player->awayviewmobj) - { - temp = (UINT32)(size_t)mobj->player->awayviewmobj; - mobj->player->awayviewmobj = NULL; - if (!P_SetTarget(&mobj->player->awayviewmobj, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "awayviewmobj not found on %d\n", mobj->type); - } - if (mobj->player->follower) - { - temp = (UINT32)(size_t)mobj->player->follower; - mobj->player->follower = NULL; - if (!P_SetTarget(&mobj->player->follower, P_FindNewPosition(temp))) - CONS_Debug(DBG_GAMELOGIC, "follower not found on %d\n", mobj->type); - } - if (mobj->player->nextwaypoint) - { - temp = (UINT32)(size_t)mobj->player->nextwaypoint; - mobj->player->nextwaypoint = K_GetWaypointFromIndex(temp); - if (mobj->player->nextwaypoint == NULL) - { - CONS_Debug(DBG_GAMELOGIC, "nextwaypoint not found on %d\n", mobj->type); - } - } - if (mobj->player->respawn.wp) - { - temp = (UINT32)(size_t)mobj->player->respawn.wp; - mobj->player->respawn.wp = K_GetWaypointFromIndex(temp); - if (mobj->player->respawn.wp == NULL) - { - CONS_Debug(DBG_GAMELOGIC, "respawn.wp not found on %d\n", mobj->type); - } + CONS_Debug(DBG_GAMELOGIC, "respawn.wp not found on %d\n", mobj->type); } } } } } -// -// P_NetArchiveSpecials -// static inline void P_NetArchiveSpecials(void) { size_t i, z; @@ -3273,9 +3929,6 @@ static inline void P_NetArchiveSpecials(void) WRITEUINT8(save_p, 0x00); } -// -// P_NetUnArchiveSpecials -// static void P_NetUnArchiveSpecials(void) { char skytex[9]; @@ -3318,15 +3971,15 @@ static void P_NetUnArchiveSpecials(void) // ======================================================================= // Misc // ======================================================================= -static inline void P_ArchiveMisc(void) +static inline void P_ArchiveMisc(INT16 mapnum) { + //lastmapsaved = mapnum; + lastmaploaded = mapnum; + if (gamecomplete) - WRITEINT16(save_p, gamemap | 8192); - else - WRITEINT16(save_p, gamemap); - - lastmapsaved = gamemap; + mapnum |= 8192; + WRITEINT16(save_p, mapnum); WRITEUINT16(save_p, emeralds+357); WRITESTRINGN(save_p, timeattackfolder, sizeof(timeattackfolder)); } @@ -3340,25 +3993,23 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) if (mapoverride != 0) { gamemap = mapoverride; - gamecomplete = true; + gamecomplete = 1; } else - gamecomplete = false; + gamecomplete = 0; // gamemap changed; we assume that its map header is always valid, // so make it so if(!mapheaderinfo[gamemap-1]) P_AllocMapHeader(gamemap-1); - lastmapsaved = gamemap; + //lastmapsaved = gamemap; + lastmaploaded = gamemap; tokenlist = 0; token = 0; savedata.emeralds = READUINT16(save_p)-357; - if (savedata.emeralds & (1<<10)) - savedata.botcolor = 0xFF; - savedata.emeralds &= 0xff; READSTRINGN(save_p, testname, sizeof(testname)); @@ -3376,7 +4027,6 @@ static inline void P_UnArchiveSPGame(INT16 mapoverride) static void P_NetArchiveMisc(void) { - UINT32 pig = 0; INT32 i; WRITEUINT32(save_p, ARCHIVEBLOCK_MISC); @@ -3387,9 +4037,12 @@ static void P_NetArchiveMisc(void) else WRITEINT16(save_p, gamestate); - for (i = 0; i < MAXPLAYERS; i++) - pig |= (playeringame[i] != 0)< NUM_LUABANKS) + return false; + for (i = 0; i < banksinuse; i++) + luabanks[i] = READINT32(save_p); + if (READUINT8(save_p) != 0x1d) + return false; + } + case 0x1d: + break; + default: + return false; + } + + return true; +} + +void P_SaveGame(INT16 mapnum) +{ + P_ArchiveMisc(mapnum); + P_ArchivePlayer(); + P_ArchiveLuabanksAndConsistency(); +} + void P_SaveNetGame(void) { thinker_t *th; mobj_t *mobj; INT32 i = 1; // don't start from 0, it'd be confused with a blank pointer otherwise - CV_SaveNetVars(&save_p, false); + CV_SaveNetVars(&save_p); P_NetArchiveMisc(); // Assign the mobjnumber for pointer tracking if (gamestate == GS_LEVEL) { - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 == (actionf_p1)P_MobjThinker) - { - mobj = (mobj_t *)th; - if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) - continue; - mobj->mobjnum = i++; - } + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mobj = (mobj_t *)th; + if (mobj->type == MT_HOOP || mobj->type == MT_HOOPCOLLIDE || mobj->type == MT_HOOPCENTER) + continue; + mobj->mobjnum = i++; } } @@ -3653,18 +4358,16 @@ void P_SaveNetGame(void) if (gamestate == GS_LEVEL) { P_NetArchiveWorld(); -#ifdef POLYOBJECTS P_ArchivePolyObjects(); -#endif P_NetArchiveThinkers(); P_NetArchiveSpecials(); + P_NetArchiveColormaps(); + P_NetArchiveTubeWaypoints(); P_NetArchiveWaypoints(); } -#ifdef HAVE_BLUA - LUA_Archive(); -#endif + LUA_Archive(&save_p); - WRITEUINT8(save_p, 0x1d); // consistency marker + P_ArchiveLuabanksAndConsistency(); } boolean P_LoadGame(INT16 mapoverride) @@ -3678,8 +4381,7 @@ boolean P_LoadGame(INT16 mapoverride) P_UnArchiveSPGame(mapoverride); P_UnArchivePlayer(); - // Savegame end marker - if (READUINT8(save_p) != 0x1d) + if (!P_UnArchiveLuabanksAndConsistency()) return false; // Only do this after confirming savegame is ok @@ -3698,18 +4400,16 @@ boolean P_LoadNetGame(void) if (gamestate == GS_LEVEL) { P_NetUnArchiveWorld(); -#ifdef POLYOBJECTS P_UnArchivePolyObjects(); -#endif P_NetUnArchiveThinkers(); P_NetUnArchiveSpecials(); + P_NetUnArchiveColormaps(); + P_NetUnArchiveTubeWaypoints(); P_NetUnArchiveWaypoints(); P_RelinkPointers(); P_FinishMobjs(); } -#ifdef HAVE_BLUA - LUA_UnArchive(); -#endif + LUA_UnArchive(&save_p); // This is stupid and hacky, but maybe it'll work! P_SetRandSeed(P_GetInitSeed()); @@ -3720,5 +4420,5 @@ boolean P_LoadNetGame(void) // precipitation when loading a netgame save. Instead, precip has to be spawned here. // This is done in P_NetUnArchiveSpecials now. - return READUINT8(save_p) == 0x1d; + return P_UnArchiveLuabanksAndConsistency(); } diff --git a/src/p_saveg.h b/src/p_saveg.h index 0992f1185..d235e71a1 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -21,7 +21,7 @@ // Persistent storage/archiving. // These are the load / save game routines. -void P_SaveGame(void); +void P_SaveGame(INT16 mapnum); void P_SaveNetGame(void); boolean P_LoadGame(INT16 mapoverride); boolean P_LoadNetGame(void); @@ -30,14 +30,12 @@ mobj_t *P_FindNewPosition(UINT32 oldposition); typedef struct { - UINT8 skincolor; UINT8 skin; - UINT8 botskin; - UINT8 botcolor; INT32 score; INT32 lives; INT32 continues; UINT16 emeralds; + UINT8 numgameovers; } savedata_t; extern savedata_t savedata; diff --git a/src/p_setup.c b/src/p_setup.c index 73a25fe51..50f39c5fa 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -21,13 +21,14 @@ #include "p_spec.h" #include "p_saveg.h" -#include "i_sound.h" // for I_PlayCD().. #include "i_video.h" // for I_FinishUpdate().. #include "r_sky.h" #include "i_system.h" #include "r_data.h" -#include "r_things.h" +#include "r_things.h" // for R_AddSpriteDefs +#include "r_textures.h" +#include "r_picformats.h" #include "r_sky.h" #include "r_draw.h" @@ -56,8 +57,9 @@ #include "filesrch.h" // refreshdirmenu -// wipes -#include "f_finale.h" +#include "lua_hud.h" // level title + +#include "f_finale.h" // wipes #include "md5.h" // map MD5 @@ -65,22 +67,19 @@ #include "lua_script.h" #include "lua_hook.h" -#if !defined (UNDER_CE) -#include -#endif - -#if defined (_WIN32) || defined (_WIN32_WCE) +#ifdef _WIN32 #include #include #endif #ifdef HWRENDER #include "hardware/hw_main.h" #include "hardware/hw_light.h" +#include "hardware/hw_model.h" #endif -#ifdef ESLOPE #include "p_slopes.h" -#endif + +#include "fastcmp.h" // textmap parsing // SRB2Kart #include "k_kart.h" @@ -90,6 +89,11 @@ #include "k_bot.h" #include "k_grandprix.h" +// Replay names have time +#if !defined (UNDER_CE) +#include +#endif + // // Map MD5, calculated on level load. // Sent to clients in PT_SERVERINFO. @@ -101,6 +105,7 @@ unsigned char mapmd5[16]; // Store VERTEXES, LINEDEFS, SIDEDEFS, etc. // +boolean udmf; size_t numvertexes, numsegs, numsectors, numsubsectors, numnodes, numlines, numsides, nummapthings; vertex_t *vertexes; seg_t *segs; @@ -110,7 +115,12 @@ node_t *nodes; line_t *lines; side_t *sides; mapthing_t *mapthings; +sector_t *spawnsectors; +line_t *spawnlines; +side_t *spawnsides; INT32 numstarposts; +UINT16 bossdisabled; +boolean stoppedclock; boolean levelloading; UINT8 levelfadecol; @@ -148,6 +158,134 @@ mapthing_t *playerstarts[MAXPLAYERS]; mapthing_t *bluectfstarts[MAXPLAYERS]; mapthing_t *redctfstarts[MAXPLAYERS]; +// Maintain *ZOOM TUBE* waypoints +// Renamed because SRB2Kart owns real waypoints. +mobj_t *tubewaypoints[NUMTUBEWAYPOINTSEQUENCES][TUBEWAYPOINTSEQUENCESIZE]; +UINT16 numtubewaypoints[NUMTUBEWAYPOINTSEQUENCES]; + +void P_AddTubeWaypoint(UINT8 sequence, UINT8 id, mobj_t *waypoint) +{ + tubewaypoints[sequence][id] = waypoint; + if (id >= numtubewaypoints[sequence]) + numtubewaypoints[sequence] = id + 1; +} + +static void P_ResetTubeWaypoints(void) +{ + UINT16 sequence, id; + for (sequence = 0; sequence < NUMTUBEWAYPOINTSEQUENCES; sequence++) + { + for (id = 0; id < numtubewaypoints[sequence]; id++) + tubewaypoints[sequence][id] = NULL; + + numtubewaypoints[sequence] = 0; + } +} + +mobj_t *P_GetFirstTubeWaypoint(UINT8 sequence) +{ + return tubewaypoints[sequence][0]; +} + +mobj_t *P_GetLastTubeWaypoint(UINT8 sequence) +{ + return tubewaypoints[sequence][numtubewaypoints[sequence] - 1]; +} + +mobj_t *P_GetPreviousTubeWaypoint(mobj_t *current, boolean wrap) +{ + UINT8 sequence = current->threshold; + UINT8 id = current->health; + + if (id == 0) + { + if (!wrap) + return NULL; + + id = numtubewaypoints[sequence] - 1; + } + else + id--; + + return tubewaypoints[sequence][id]; +} + +mobj_t *P_GetNextTubeWaypoint(mobj_t *current, boolean wrap) +{ + UINT8 sequence = current->threshold; + UINT8 id = current->health; + + if (id == numtubewaypoints[sequence] - 1) + { + if (!wrap) + return NULL; + + id = 0; + } + else + id++; + + return tubewaypoints[sequence][id]; +} + +mobj_t *P_GetClosestTubeWaypoint(UINT8 sequence, mobj_t *mo) +{ + UINT8 wp; + mobj_t *mo2, *result = NULL; + fixed_t bestdist = 0; + fixed_t curdist; + + for (wp = 0; wp < numtubewaypoints[sequence]; wp++) + { + mo2 = tubewaypoints[sequence][wp]; + + if (!mo2) + continue; + + curdist = P_AproxDistance(P_AproxDistance(mo->x - mo2->x, mo->y - mo2->y), mo->z - mo2->z); + + if (result && curdist > bestdist) + continue; + + result = mo2; + bestdist = curdist; + } + + return result; +} + +// Return true if all waypoints are in the same location +boolean P_IsDegeneratedTubeWaypointSequence(UINT8 sequence) +{ + mobj_t *first, *waypoint; + UINT8 wp; + + if (numtubewaypoints[sequence] <= 1) + return true; + + first = tubewaypoints[sequence][0]; + + for (wp = 1; wp < numtubewaypoints[sequence]; wp++) + { + waypoint = tubewaypoints[sequence][wp]; + + if (!waypoint) + continue; + + if (waypoint->x != first->x) + return false; + + if (waypoint->y != first->y) + return false; + + if (waypoint->z != first->z) + return false; + } + + return true; +} + + /** Logs an error about a map being corrupt, then terminate. * This allows reporting highly technical errors for usefulness, without * confusing a novice map designer who simply needs to run ZenNode. @@ -175,6 +313,33 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg) I_Error("Invalid or corrupt map.\nLook in log file or text console for technical details."); } +/** Sets a header's flickies to be equivalent to the original Freed Animals + * + * \param i The header to set flickies for + */ +void P_SetDemoFlickies(INT16 i) +{ + mapheaderinfo[i]->numFlickies = 5; + mapheaderinfo[i]->flickies = Z_Realloc(mapheaderinfo[i]->flickies, 5*sizeof(mobjtype_t), PU_STATIC, NULL); + mapheaderinfo[i]->flickies[0] = MT_FLICKY_02/*MT_BUNNY*/; + mapheaderinfo[i]->flickies[1] = MT_FLICKY_01/*MT_BIRD*/; + mapheaderinfo[i]->flickies[2] = MT_FLICKY_12/*MT_MOUSE*/; + mapheaderinfo[i]->flickies[3] = MT_FLICKY_11/*MT_COW*/; + mapheaderinfo[i]->flickies[4] = MT_FLICKY_03/*MT_CHICKEN*/; +} + +/** Clears a header's flickies + * + * \param i The header to clear flickies for + */ +void P_DeleteFlickies(INT16 i) +{ + if (mapheaderinfo[i]->flickies) + Z_Free(mapheaderinfo[i]->flickies); + mapheaderinfo[i]->flickies = NULL; + mapheaderinfo[i]->numFlickies = 0; +} + #define NUMLAPS_DEFAULT 3 /** Clears the data from a single map header. @@ -185,88 +350,72 @@ FUNCNORETURN static ATTRNORETURN void CorruptMapError(const char *msg) static void P_ClearSingleMapHeaderInfo(INT16 i) { const INT16 num = (INT16)(i-1); - INT32 exists = (mapheaderinfo[num]->menuflags & LF2_EXISTSHACK); - DEH_WriteUndoline("LEVELNAME", mapheaderinfo[num]->lvlttl, UNDO_NONE); + boolean exists = (mapheaderinfo[gamemap-1]->alreadyExists == true); + mapheaderinfo[num]->lvlttl[0] = '\0'; - DEH_WriteUndoline("SUBTITLE", mapheaderinfo[num]->subttl, UNDO_NONE); + mapheaderinfo[num]->selectheading[0] = '\0'; mapheaderinfo[num]->subttl[0] = '\0'; - DEH_WriteUndoline("ZONETITLE", mapheaderinfo[num]->zonttl, UNDO_NONE); // SRB2kart mapheaderinfo[num]->zonttl[0] = '\0'; - DEH_WriteUndoline("ACT", mapheaderinfo[num]->actnum, UNDO_NONE); // SRB2kart - mapheaderinfo[num]->actnum[0] = '\0'; - DEH_WriteUndoline("TYPEOFLEVEL", va("%d", mapheaderinfo[num]->typeoflevel), UNDO_NONE); + mapheaderinfo[num]->ltzzpatch[0] = '\0'; + mapheaderinfo[num]->ltzztext[0] = '\0'; + mapheaderinfo[num]->ltactdiamond[0] = '\0'; + mapheaderinfo[num]->actnum = 0; mapheaderinfo[num]->typeoflevel = 0; - DEH_WriteUndoline("NEXTLEVEL", va("%d", mapheaderinfo[num]->nextlevel), UNDO_NONE); mapheaderinfo[num]->nextlevel = (INT16)(i + 1); - DEH_WriteUndoline("MUSIC", mapheaderinfo[num]->musname, UNDO_NONE); + mapheaderinfo[num]->marathonnext = 0; + mapheaderinfo[num]->startrings = 0; + mapheaderinfo[num]->sstimer = 90; + mapheaderinfo[num]->ssspheres = 1; + mapheaderinfo[num]->gravity = DEFAULT_GRAVITY; + mapheaderinfo[num]->keywords[0] = '\0'; snprintf(mapheaderinfo[num]->musname, 7, "%sM", G_BuildMapName(i)); mapheaderinfo[num]->musname[6] = 0; - DEH_WriteUndoline("MUSICTRACK", va("%d", mapheaderinfo[num]->mustrack), UNDO_NONE); mapheaderinfo[num]->mustrack = 0; - DEH_WriteUndoline("MUSICPOS", va("%d", mapheaderinfo[num]->muspos), UNDO_NONE); mapheaderinfo[num]->muspos = 0; - DEH_WriteUndoline("MUSICINTERFADEOUT", va("%d", mapheaderinfo[num]->musinterfadeout), UNDO_NONE); mapheaderinfo[num]->musinterfadeout = 0; - DEH_WriteUndoline("MUSICINTER", mapheaderinfo[num]->musintername, UNDO_NONE); - mapheaderinfo[num]->musintername[0] = '\0'; - DEH_WriteUndoline("FORCECHARACTER", va("%d", mapheaderinfo[num]->forcecharacter), UNDO_NONE); + mapheaderinfo[num]->musintername[0] = 0; + mapheaderinfo[num]->muspostbossname[0] = 0; + mapheaderinfo[num]->muspostbosstrack = 0; + mapheaderinfo[num]->muspostbosspos = 0; + mapheaderinfo[num]->muspostbossfadein = 0; + mapheaderinfo[num]->musforcereset = -1; mapheaderinfo[num]->forcecharacter[0] = '\0'; - DEH_WriteUndoline("WEATHER", va("%d", mapheaderinfo[num]->weather), UNDO_NONE); mapheaderinfo[num]->weather = 0; - DEH_WriteUndoline("SKYTEXTURE", va("%d", mapheaderinfo[num]->skytexture), UNDO_NONE); - snprintf(mapheaderinfo[num]->skytexture, 9, "SKY1"); - mapheaderinfo[num]->skytexture[8] = 0; - DEH_WriteUndoline("SKYBOXSCALEX", va("%d", mapheaderinfo[num]->skybox_scalex), UNDO_NONE); + snprintf(mapheaderinfo[num]->skytexture, 5, "SKY1"); + mapheaderinfo[num]->skytexture[4] = 0; mapheaderinfo[num]->skybox_scalex = 16; - DEH_WriteUndoline("SKYBOXSCALEY", va("%d", mapheaderinfo[num]->skybox_scaley), UNDO_NONE); mapheaderinfo[num]->skybox_scaley = 16; - DEH_WriteUndoline("SKYBOXSCALEZ", va("%d", mapheaderinfo[num]->skybox_scalez), UNDO_NONE); mapheaderinfo[num]->skybox_scalez = 16; - DEH_WriteUndoline("INTERSCREEN", mapheaderinfo[num]->interscreen, UNDO_NONE); mapheaderinfo[num]->interscreen[0] = '#'; - DEH_WriteUndoline("RUNSOC", mapheaderinfo[num]->runsoc, UNDO_NONE); mapheaderinfo[num]->runsoc[0] = '#'; - DEH_WriteUndoline("SCRIPTNAME", mapheaderinfo[num]->scriptname, UNDO_NONE); mapheaderinfo[num]->scriptname[0] = '#'; - DEH_WriteUndoline("PRECUTSCENENUM", va("%d", mapheaderinfo[num]->precutscenenum), UNDO_NONE); mapheaderinfo[num]->precutscenenum = 0; - DEH_WriteUndoline("CUTSCENENUM", va("%d", mapheaderinfo[num]->cutscenenum), UNDO_NONE); mapheaderinfo[num]->cutscenenum = 0; - DEH_WriteUndoline("COUNTDOWN", va("%d", mapheaderinfo[num]->countdown), UNDO_NONE); mapheaderinfo[num]->countdown = 0; - DEH_WriteUndoline("PALLETE", va("%u", mapheaderinfo[num]->palette), UNDO_NONE); mapheaderinfo[num]->palette = UINT16_MAX; - DEH_WriteUndoline("ENCOREPAL", va("%u", mapheaderinfo[num]->encorepal), UNDO_NONE); mapheaderinfo[num]->encorepal = UINT16_MAX; - DEH_WriteUndoline("NUMLAPS", va("%u", mapheaderinfo[num]->numlaps), UNDO_NONE); mapheaderinfo[num]->numlaps = NUMLAPS_DEFAULT; - DEH_WriteUndoline("UNLOCKABLE", va("%s", mapheaderinfo[num]->unlockrequired), UNDO_NONE); mapheaderinfo[num]->unlockrequired = -1; - DEH_WriteUndoline("LEVELSELECT", va("%d", mapheaderinfo[num]->levelselect), UNDO_NONE); mapheaderinfo[num]->levelselect = 0; - DEH_WriteUndoline("BONUSTYPE", va("%d", mapheaderinfo[num]->bonustype), UNDO_NONE); mapheaderinfo[num]->bonustype = 0; - DEH_WriteUndoline("SAVEOVERRIDE", va("%d", mapheaderinfo[num]->saveoverride), UNDO_NONE); - mapheaderinfo[num]->saveoverride = SAVE_DEFAULT; - DEH_WriteUndoline("LEVELFLAGS", va("%d", mapheaderinfo[num]->levelflags), UNDO_NONE); + mapheaderinfo[num]->maxbonuslives = -1; mapheaderinfo[num]->levelflags = 0; - DEH_WriteUndoline("MENUFLAGS", va("%d", mapheaderinfo[num]->menuflags), UNDO_NONE); - mapheaderinfo[num]->menuflags = exists; // see p_setup.c - prevents replacing maps in addons with easier versions - // TODO grades support for delfile (pfft yeah right) - P_DeleteGrades(num); - // SRB2Kart - //DEH_WriteUndoline("AUTOMAP", va("%d", mapheaderinfo[num]->automap), UNDO_NONE); - //mapheaderinfo[num]->automap = false; - DEH_WriteUndoline("MOBJSCALE", va("%d", mapheaderinfo[num]->mobj_scale), UNDO_NONE); + mapheaderinfo[num]->menuflags = 0; mapheaderinfo[num]->mobj_scale = FRACUNIT; - DEH_WriteUndoline("DEFAULTWAYPOINTRADIUS", va("%d", mapheaderinfo[num]->default_waypoint_radius), UNDO_NONE); mapheaderinfo[num]->default_waypoint_radius = 0; - // an even further impossibility, delfile custom opts support +#if 1 // equivalent to "FlickyList = DEMO" + P_SetDemoFlickies(num); +#else // equivalent to "FlickyList = NONE" + P_DeleteFlickies(num); +#endif + P_DeleteGrades(num); + + // see p_setup.c - prevents replacing maps in addons with different versions + mapheaderinfo[num]->alreadyExists = exists; + mapheaderinfo[num]->customopts = NULL; mapheaderinfo[num]->numCustomOptions = 0; - - DEH_WriteUndoline(va("# uload for map %d", i), NULL, UNDO_DONE); } /** Allocates a new map-header structure. @@ -278,6 +427,7 @@ void P_AllocMapHeader(INT16 i) if (!mapheaderinfo[i]) { mapheaderinfo[i] = Z_Malloc(sizeof(mapheader_t), PU_STATIC, NULL); + mapheaderinfo[i]->flickies = NULL; mapheaderinfo[i]->grades = NULL; } P_ClearSingleMapHeaderInfo(i + 1); @@ -380,41 +530,1565 @@ UINT32 P_GetScoreForGrade(INT16 map, UINT8 mare, UINT8 grade) return mapheaderinfo[map-1]->grades[mare].grade[grade-1]; } -/** Loads the vertexes for a level. - * - * \param lump VERTEXES lump number. - * \sa ML_VERTEXES - */ +// +// levelflats +// +#define MAXLEVELFLATS 256 -static inline void P_LoadRawVertexes(UINT8 *data, size_t i) +size_t numlevelflats; +levelflat_t *levelflats; +levelflat_t *foundflats; + +//SoM: Other files want this info. +size_t P_PrecacheLevelFlats(void) { - mapvertex_t *ml; - vertex_t *li; + lumpnum_t lump; + size_t i; - numvertexes = i / sizeof (mapvertex_t); - - if (numvertexes <= 0) - I_Error("Level has no vertices"); // instead of crashing - - // Allocate zone memory for buffer. - vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); - - ml = (mapvertex_t *)data; - li = vertexes; - - // Copy and convert vertex coordinates, internal representation as fixed. - for (i = 0; i < numvertexes; i++, li++, ml++) + //SoM: 4/18/2000: New flat code to make use of levelflats. + flatmemory = 0; + for (i = 0; i < numlevelflats; i++) { - li->x = SHORT(ml->x)<y = SHORT(ml->y)<= MAXLEVELFLATS) + I_Error("Too many flats in level\n"); + + levelflat += numlevelflats; + } + + // Store the name. + strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); + strupr(levelflat->name); + + /* If we can't find a flat, try looking for a texture! */ + if (( flatnum = R_GetFlatNumForName(levelflat->name) ) == LUMPERROR) + { + if (( texturenum = R_CheckTextureNumForName(levelflat->name) ) == -1) + { + // check for REDWALL + if (( texturenum = R_CheckTextureNumForName("REDWALL") ) != -1) + goto texturefound; + // check for REDFLR + else if (( flatnum = R_GetFlatNumForName("REDFLR") ) != LUMPERROR) + goto flatfound; + // nevermind + levelflat->type = LEVELFLAT_NONE; + } + else + { +texturefound: + levelflat->type = LEVELFLAT_TEXTURE; + levelflat->u.texture. num = texturenum; + levelflat->u.texture.lastnum = texturenum; + /* start out unanimated */ + levelflat->u.texture.basenum = -1; + } + } + else + { +flatfound: + /* This could be a flat, patch, or PNG. */ + flatpatch = W_CacheLumpNum(flatnum, PU_CACHE); + lumplength = W_LumpLength(flatnum); + if (Picture_CheckIfPatch(flatpatch, lumplength)) + levelflat->type = LEVELFLAT_PATCH; + else + { +#ifndef NO_PNG_LUMPS + /* + Only need eight bytes for PNG headers. + FIXME: Put this elsewhere. + */ + W_ReadLumpHeader(flatnum, buffer, 8, 0); + if (Picture_IsLumpPNG(buffer, lumplength)) + levelflat->type = LEVELFLAT_PNG; + else +#endif/*NO_PNG_LUMPS*/ + levelflat->type = LEVELFLAT_FLAT;/* phew */ + } + if (flatpatch) + Z_Free(flatpatch); + + levelflat->u.flat. lumpnum = flatnum; + levelflat->u.flat.baselumpnum = LUMPERROR; + } + +#ifndef ZDEBUG + CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); +#endif + + return ( numlevelflats++ ); +} + +// Auxiliary function. Find a flat in the active wad files, +// allocate an id for it, and set the levelflat (to speedup search) +INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) +{ + return Ploadflat(levelflat, flatname, false); +} + +// help function for Lua and $$$.sav reading +// same as P_AddLevelFlat, except this is not setup so we must realloc levelflats to fit in the new flat +// no longer a static func in lua_maplib.c because p_saveg.c also needs it +// +INT32 P_AddLevelFlatRuntime(const char *flatname) +{ + return Ploadflat(levelflats, flatname, true); +} + +// help function for $$$.sav checking +// this simply returns the flat # for the name given +// +INT32 P_CheckLevelFlat(const char *flatname) +{ + size_t i; + levelflat_t *levelflat = levelflats; + + // + // scan through the already found flats + // + for (i = 0; i < numlevelflats; i++, levelflat++) + if (strnicmp(levelflat->name,flatname,8)==0) + break; + + if (i == numlevelflats) + return 0; // ??? flat was not found, this should not happen! + + // level flat id + return (INT32)i; +} + +// +// P_ReloadRings +// Used by NiGHTS, clears all ring/sphere/hoop/etc items and respawns them +// +void P_ReloadRings(void) +{ + mobj_t *mo; + thinker_t *th; + size_t i, numHoops = 0; + // Okay, if you have more than 4000 hoops in your map, + // you're insane. + mapthing_t *hoopsToRespawn[4096]; + mapthing_t *mt = mapthings; + + // scan the thinkers to find rings/spheres/hoops to unset + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo = (mobj_t *)th; + + if (mo->type == MT_HOOPCENTER) + { + // Hoops give me a headache + if (mo->threshold == 4242) // Dead hoop + { + hoopsToRespawn[numHoops++] = mo->spawnpoint; + P_RemoveMobj(mo); + } + continue; + } + if (mo->type != MT_RING) + continue; + + // Don't auto-disintegrate things being pulled to us + if (mo->flags2 & MF2_NIGHTSPULL) + continue; + + P_RemoveMobj(mo); + } + + // Reiterate through mapthings + for (i = 0; i < nummapthings; i++, mt++) + { + // Notice an omission? We handle hoops differently. + if (mt->type == mobjinfo[MT_RING].doomednum) + { + mt->mobj = NULL; + P_SpawnMapThing(mt); + } + else if (mt->type >= 600 && mt->type <= 609) // Item patterns + { + mt->mobj = NULL; + P_SpawnItemPattern(mt, true); + } + } + for (i = 0; i < numHoops; i++) + { + P_SpawnHoop(hoopsToRespawn[i]); } } -static inline void P_LoadVertexes(lumpnum_t lumpnum) +#ifdef SCANTHINGS +void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum) { - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawVertexes(data, W_LumpLength(lumpnum)); + size_t i, n; + UINT8 *data, *datastart; + UINT16 type, maprings; + INT16 tol; + UINT32 flags; + + tol = mapheaderinfo[mapnum-1]->typeoflevel; + flags = mapheaderinfo[mapnum-1]->levelflags; + + n = W_LumpLengthPwad(wadnum, lumpnum) / (5 * sizeof (INT16)); + //CONS_Printf("%u map things found!\n", n); + + maprings = 0; + data = datastart = W_CacheLumpNumPwad(wadnum, lumpnum, PU_STATIC); + for (i = 0; i < n; i++) + { + data += 3 * sizeof (INT16); // skip x y position, angle + type = READUINT16(data) & 4095; + data += sizeof (INT16); // skip options + + if (mt->type == mobjinfo[MT_RANDOMITEM].doomednum) + { + nummapboxes++; + } + else if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum) + { + maptargets++; + } + else if (mt->type == mobjinfo[MT_RING].doomednum) + { + maprings++; + } + else + { + switch (type) + { + case 603: // 10 diagonal rings + maprings += 10; + break; + case 600: // 5 vertical rings + case 601: // 5 vertical rings + case 602: // 5 diagonal rings + maprings += 5; + break; + case 604: // 8 circle rings + maprings += 8; + break; + case 605: // 16 circle rings + maprings += 16; + break; + } + } + } + Z_Free(datastart); + + if (maprings) + CONS_Printf("%s has %u rings\n", G_BuildMapName(mapnum), maprings); +} +#endif + +static void P_SpawnMapThings(boolean spawnemblems) +{ + size_t i; + mapthing_t *mt; + + // Spawn axis points first so they are at the front of the list for fast searching. + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { + switch (mt->type) + { + case 1700: // MT_AXIS + case 1701: // MT_AXISTRANSFER + case 1702: // MT_AXISTRANSFERLINE + mt->mobj = NULL; + P_SpawnMapThing(mt); + break; + default: + break; + } + } + + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { + if (mt->type == 1700 // MT_AXIS + || mt->type == 1701 // MT_AXISTRANSFER + || mt->type == 1702) // MT_AXISTRANSFERLINE + continue; // These were already spawned + + if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum) + continue; // This will spawn later + + if (!spawnemblems && mt->type == mobjinfo[MT_EMBLEM].doomednum) + continue; + + mt->mobj = NULL; + + if (mt->type >= 600 && mt->type <= 609) // item patterns + P_SpawnItemPattern(mt, false); + else if (mt->type == 1705 || mt->type == 1713) // hoops + P_SpawnHoop(mt); + else // Everything else + P_SpawnMapThing(mt); + } +} + +// Experimental groovy write function! +void P_WriteThings(lumpnum_t lumpnum) +{ + size_t i, length; + mapthing_t *mt; + UINT8 *data; + UINT8 *savebuffer, *savebuf_p; + INT16 temp; + + data = W_CacheLumpNum(lumpnum, PU_LEVEL); + + savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t)); + + if (!savebuf_p) + { + CONS_Alert(CONS_ERROR, M_GetText("No more free memory for thing writing!\n")); + return; + } + + mt = mapthings; + for (i = 0; i < nummapthings; i++, mt++) + { + WRITEINT16(savebuf_p, mt->x); + WRITEINT16(savebuf_p, mt->y); + + WRITEINT16(savebuf_p, mt->angle); + + temp = (INT16)(mt->type + ((INT16)mt->extrainfo << 12)); + WRITEINT16(savebuf_p, temp); + WRITEUINT16(savebuf_p, mt->options); + } + Z_Free(data); + + length = savebuf_p - savebuffer; + + FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length); + free(savebuffer); + savebuf_p = NULL; + + CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap); +} + +// +// MAP LOADING FUNCTIONS +// + +static void P_LoadVertices(UINT8 *data) +{ + mapvertex_t *mv = (mapvertex_t *)data; + vertex_t *v = vertexes; + size_t i; + + // Copy and convert vertex coordinates, internal representation as fixed. + for (i = 0; i < numvertexes; i++, v++, mv++) + { + v->x = SHORT(mv->x)<y = SHORT(mv->y)<floorzset = v->ceilingzset = false; + v->floorz = v->ceilingz = 0; + } +} + +static void P_InitializeSector(sector_t *ss) +{ + ss->nexttag = ss->firsttag = -1; + + memset(&ss->soundorg, 0, sizeof(ss->soundorg)); + + ss->validcount = 0; + + ss->thinglist = NULL; + + ss->floordata = NULL; + ss->ceilingdata = NULL; + ss->lightingdata = NULL; + ss->fadecolormapdata = NULL; + + ss->heightsec = -1; + ss->camsec = -1; + + ss->floorlightsec = ss->ceilinglightsec = -1; + ss->crumblestate = CRUMBLE_NONE; + + ss->touching_thinglist = NULL; + + ss->linecount = 0; + ss->lines = NULL; + + ss->ffloors = NULL; + ss->attached = NULL; + ss->attachedsolid = NULL; + ss->numattached = 0; + ss->maxattached = 1; + ss->lightlist = NULL; + ss->numlights = 0; + ss->moved = true; + + ss->extra_colormap = NULL; + + ss->gravity = NULL; + ss->verticalflip = false; + ss->flags = SF_FLIPSPECIAL_FLOOR; + + ss->cullheight = NULL; + + ss->floorspeed = ss->ceilspeed = 0; + + ss->preciplist = NULL; + ss->touching_preciplist = NULL; + + ss->f_slope = NULL; + ss->c_slope = NULL; + ss->hasslope = false; + + ss->spawn_lightlevel = ss->lightlevel; + + ss->spawn_extra_colormap = NULL; +} + +static void P_LoadSectors(UINT8 *data) +{ + mapsector_t *ms = (mapsector_t *)data; + sector_t *ss = sectors; + size_t i; + + // For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss. + for (i = 0; i < numsectors; i++, ss++, ms++) + { + ss->floorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = P_AddLevelFlat(ms->floorpic, foundflats); + ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); + + ss->lightlevel = SHORT(ms->lightlevel); + ss->special = SHORT(ms->special); + ss->tag = SHORT(ms->tag); + + ss->floor_xoffs = ss->floor_yoffs = 0; + ss->ceiling_xoffs = ss->ceiling_yoffs = 0; + + ss->floorpic_angle = ss->ceilingpic_angle = 0; + + ss->colormap_protected = false; + + P_InitializeSector(ss); + } +} + +static void P_InitializeLinedef(line_t *ld) +{ + vertex_t *v1 = ld->v1; + vertex_t *v2 = ld->v2; + UINT8 j; + + ld->dx = v2->x - v1->x; + ld->dy = v2->y - v1->y; + + ld->bbox[BOXLEFT] = min(v1->x, v2->x); + ld->bbox[BOXRIGHT] = max(v1->x, v2->x); + ld->bbox[BOXBOTTOM] = min(v1->y, v2->y); + ld->bbox[BOXTOP] = max(v1->y, v2->y); + + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else if ((ld->dy > 0) == (ld->dx > 0)) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + + ld->frontsector = ld->backsector = NULL; + + ld->validcount = 0; +#ifdef WALLSPLATS + ld->splats = NULL; +#endif + ld->firsttag = ld->nexttag = -1; + ld->polyobj = NULL; + + ld->text = NULL; + ld->callcount = 0; + + // cph 2006/09/30 - fix sidedef errors right away. + // cph 2002/07/20 - these errors are fatal if not fixed, so apply them + for (j = 0; j < 2; j++) + if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) + { + ld->sidenum[j] = 0xffff; + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has out-of-range sidedef number\n", sizeu1((size_t)(ld - lines))); + } + + // killough 11/98: fix common wad errors (missing sidedefs): + if (ld->sidenum[0] == 0xffff) + { + ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side + // cph - print a warning about the bug + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s missing first sidedef\n", sizeu1((size_t)(ld - lines))); + } + + if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) + { + ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side + // cph - print a warning about the bug + CONS_Debug(DBG_SETUP, "P_InitializeLinedef: Linedef %s has two-sided flag set, but no second sidedef\n", sizeu1((size_t)(ld - lines))); + } + + if (ld->sidenum[0] != 0xffff) + { + sides[ld->sidenum[0]].special = ld->special; + sides[ld->sidenum[0]].line = ld; + } + if (ld->sidenum[1] != 0xffff) + { + sides[ld->sidenum[1]].special = ld->special; + sides[ld->sidenum[1]].line = ld; + } +} + +static void P_SetLinedefV1(size_t i, UINT16 vertex_num) +{ + if (vertex_num >= numvertexes) + { + CONS_Debug(DBG_SETUP, "P_SetLinedefV1: linedef %s has out-of-range v1 num %u\n", sizeu1(i), vertex_num); + vertex_num = 0; + } + lines[i].v1 = &vertexes[vertex_num]; +} + +static void P_SetLinedefV2(size_t i, UINT16 vertex_num) +{ + if (vertex_num >= numvertexes) + { + CONS_Debug(DBG_SETUP, "P_SetLinedefV2: linedef %s has out-of-range v2 num %u\n", sizeu1(i), vertex_num); + vertex_num = 0; + } + lines[i].v2 = &vertexes[vertex_num]; +} + +static void P_LoadLinedefs(UINT8 *data) +{ + maplinedef_t *mld = (maplinedef_t *)data; + line_t *ld = lines; + size_t i; + + for (i = 0; i < numlines; i++, mld++, ld++) + { + ld->flags = SHORT(mld->flags); + ld->special = SHORT(mld->special); + ld->tag = SHORT(mld->tag); + memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); + memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); + ld->alpha = FRACUNIT; + ld->executordelay = 0; + P_SetLinedefV1(i, SHORT(mld->v1)); + P_SetLinedefV2(i, SHORT(mld->v2)); + + ld->sidenum[0] = SHORT(mld->sidenum[0]); + ld->sidenum[1] = SHORT(mld->sidenum[1]); + + P_InitializeLinedef(ld); + } +} + +static void P_SetSidedefSector(size_t i, UINT16 sector_num) +{ + // cph 2006/09/30 - catch out-of-range sector numbers; use sector 0 instead + if (sector_num >= numsectors) + { + CONS_Debug(DBG_SETUP, "P_SetSidedefSector: sidedef %s has out-of-range sector num %u\n", sizeu1(i), sector_num); + sector_num = 0; + } + sides[i].sector = §ors[sector_num]; +} + +static void P_InitializeSidedef(side_t *sd) +{ + if (!sd->line) + { + CONS_Debug(DBG_SETUP, "P_LoadSidedefs: Sidedef %s is not used by any linedef\n", sizeu1((size_t)(sd - sides))); + sd->line = &lines[0]; + sd->special = sd->line->special; + } + + sd->text = NULL; + sd->colormap_data = NULL; +} + +static void P_LoadSidedefs(UINT8 *data) +{ + mapsidedef_t *msd = (mapsidedef_t*)data; + side_t *sd = sides; + size_t i; + + for (i = 0; i < numsides; i++, sd++, msd++) + { + INT16 textureoffset = SHORT(msd->textureoffset); + boolean isfrontside; + + P_InitializeSidedef(sd); + + isfrontside = sd->line->sidenum[0] == i; + + // Repeat count for midtexture + if (((sd->line->flags & (ML_TWOSIDED|ML_EFFECT5)) == (ML_TWOSIDED|ML_EFFECT5)) + && !(sd->special >= 300 && sd->special < 500)) // exempt linedef exec specials + { + sd->repeatcnt = (INT16)(((UINT16)textureoffset) >> 12); + sd->textureoffset = (((UINT16)textureoffset) & 2047) << FRACBITS; + } + else + { + sd->repeatcnt = 0; + sd->textureoffset = textureoffset << FRACBITS; + } + sd->rowoffset = SHORT(msd->rowoffset)<sector)); + + // Special info stored in texture fields! + switch (sd->special) + { + case 606: //SoM: 4/4/2000: Just colormap transfer + case 447: // Change colormap of tagged sectors! -- Monster Iestyn 14/06/18 + case 455: // Fade colormaps! mazmazz 9/12/2018 (:flag_us:) + // SoM: R_CreateColormap will only create a colormap in software mode... + // Perhaps we should just call it instead of doing the calculations here. + if (!udmf) + { + sd->colormap_data = R_CreateColormapFromLinedef(msd->toptexture, msd->midtexture, msd->bottomtexture); + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + } + break; + + case 413: // Change music + { + char process[8+1]; + + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') + { + M_Memcpy(process,msd->bottomtexture,8); + process[8] = '\0'; + sd->bottomtexture = get_number(process); + } + + if (!(msd->midtexture[0] == '-' && msd->midtexture[1] == '\0') || msd->midtexture[1] != '\0') + { + M_Memcpy(process,msd->midtexture,8); + process[8] = '\0'; + sd->midtexture = get_number(process); + } + + sd->text = Z_Malloc(7, PU_LEVEL, NULL); + if (isfrontside && !(msd->toptexture[0] == '-' && msd->toptexture[1] == '\0')) + { + M_Memcpy(process,msd->toptexture,8); + process[8] = '\0'; + + // If they type in O_ or D_ and their music name, just shrug, + // then copy the rest instead. + if ((process[0] == 'O' || process[0] == 'D') && process[7]) + M_Memcpy(sd->text, process+2, 6); + else // Assume it's a proper music name. + M_Memcpy(sd->text, process, 6); + sd->text[6] = 0; + } + else + sd->text[0] = 0; + break; + } + + case 4: // Speed pad parameters + case 414: // Play SFX + { + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + if (msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') + { + char process[8+1]; + M_Memcpy(process,msd->toptexture,8); + process[8] = '\0'; + sd->toptexture = get_number(process); + } + break; + } + + case 9: // Mace parameters + case 14: // Bustable block parameters + case 15: // Fan particle spawner parameters + case 334: // Trigger linedef executor: Object dye - Continuous + case 335: // Trigger linedef executor: Object dye - Each time + case 336: // Trigger linedef executor: Object dye - Once + case 425: // Calls P_SetMobjState on calling mobj + case 434: // Custom Power + case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors + case 461: // Spawns an object on the map based on texture offsets + case 463: // Colorizes an object + { + char process[8*3+1]; + memset(process,0,8*3+1); + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + if (msd->toptexture[0] == '-' && msd->toptexture[1] == '\0') + break; + else + M_Memcpy(process,msd->toptexture,8); + if (msd->midtexture[0] != '-' || msd->midtexture[1] != '\0') + M_Memcpy(process+strlen(process), msd->midtexture, 8); + if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') + M_Memcpy(process+strlen(process), msd->bottomtexture, 8); + sd->toptexture = get_number(process); + break; + } + + case 331: // Trigger linedef executor: Skin - Continuous + case 332: // Trigger linedef executor: Skin - Each time + case 333: // Trigger linedef executor: Skin - Once + case 443: // Calls a named Lua function + case 459: // Control text prompt (named tag) + { + char process[8*3+1]; + memset(process,0,8*3+1); + sd->toptexture = sd->midtexture = sd->bottomtexture = 0; + if (msd->toptexture[0] == '-' && msd->toptexture[1] == '\0') + break; + else + M_Memcpy(process,msd->toptexture,8); + if (msd->midtexture[0] != '-' || msd->midtexture[1] != '\0') + M_Memcpy(process+strlen(process), msd->midtexture, 8); + if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') + M_Memcpy(process+strlen(process), msd->bottomtexture, 8); + sd->text = Z_Malloc(strlen(process)+1, PU_LEVEL, NULL); + M_Memcpy(sd->text, process, strlen(process)+1); + break; + } + + case 259: // Custom FOF + if (!isfrontside) + { + if ((msd->toptexture[0] >= '0' && msd->toptexture[0] <= '9') + || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F')) + sd->toptexture = axtoi(msd->toptexture); + else + I_Error("Custom FOF (tag %d) needs a value in the linedef's back side upper texture field.", sd->line->tag); + + sd->midtexture = R_TextureNumForName(msd->midtexture); + sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); + break; + } + // FALLTHRU + default: // normal cases + if (msd->toptexture[0] == '#') + { + char *col = msd->toptexture; + sd->toptexture = sd->bottomtexture = + ((col[1]-'0')*100 + (col[2]-'0')*10 + col[3]-'0') + 1; + sd->midtexture = R_TextureNumForName(msd->midtexture); + } + else + { + sd->midtexture = R_TextureNumForName(msd->midtexture); + sd->toptexture = R_TextureNumForName(msd->toptexture); + sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); + } + break; + } + } +} + +static void P_LoadThings(UINT8 *data) +{ + mapthing_t *mt; + size_t i; + + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { + mt->x = READINT16(data); + mt->y = READINT16(data); + + mt->angle = READINT16(data); + mt->type = READUINT16(data); + mt->options = READUINT16(data); + mt->extrainfo = (UINT8)(mt->type >> 12); + mt->scale = mapobjectscale; + mt->tag = 0; + memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); + memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); + mt->pitch = mt->roll = 0; + + mt->type &= 4095; + + if (mt->type == 1705 || (mt->type == 750 && mt->extrainfo)) + mt->z = mt->options; // NiGHTS Hoops use the full flags bits to set the height. + else + mt->z = mt->options >> ZSHIFT; + + mt->mobj = NULL; + } +} + +// Stores positions for relevant map data spread through a TEXTMAP. +UINT32 mapthingsPos[UINT16_MAX]; +UINT32 linesPos[UINT16_MAX]; +UINT32 sidesPos[UINT16_MAX]; +UINT32 vertexesPos[UINT16_MAX]; +UINT32 sectorsPos[UINT16_MAX]; + +// Determine total amount of map data in TEXTMAP. +static boolean TextmapCount(UINT8 *data, size_t size) +{ + char *tkn = M_GetToken((char *)data); + UINT8 brackets = 0; + + nummapthings = 0; + numlines = 0; + numsides = 0; + numvertexes = 0; + numsectors = 0; + + // Look for namespace at the beginning. + if (!fastcmp(tkn, "namespace")) + { + Z_Free(tkn); + CONS_Alert(CONS_ERROR, "No namespace at beginning of lump!\n"); + return false; + } + Z_Free(tkn); + + // Check if namespace is valid. + tkn = M_GetToken(NULL); + if (!fastcmp(tkn, "srb2")) + CONS_Alert(CONS_WARNING, "Invalid namespace '%s', only 'srb2' is supported.\n", tkn); + Z_Free(tkn); + + tkn = M_GetToken(NULL); + while (tkn && M_GetTokenPos() < size) + { + // Avoid anything inside bracketed stuff, only look for external keywords. + if (brackets) + { + if (fastcmp(tkn, "}")) + brackets--; + } + else if (fastcmp(tkn, "{")) + brackets++; + // Check for valid fields. + else if (fastcmp(tkn, "thing")) + mapthingsPos[nummapthings++] = M_GetTokenPos(); + else if (fastcmp(tkn, "linedef")) + linesPos[numlines++] = M_GetTokenPos(); + else if (fastcmp(tkn, "sidedef")) + sidesPos[numsides++] = M_GetTokenPos(); + else if (fastcmp(tkn, "vertex")) + vertexesPos[numvertexes++] = M_GetTokenPos(); + else if (fastcmp(tkn, "sector")) + sectorsPos[numsectors++] = M_GetTokenPos(); + else + CONS_Alert(CONS_NOTICE, "Unknown field '%s'.\n", tkn); + + Z_Free(tkn); + tkn = M_GetToken(NULL); + } + + Z_Free(tkn); + + if (brackets) + { + CONS_Alert(CONS_ERROR, "Unclosed brackets detected in textmap lump.\n"); + return false; + } + + return true; +} + +static void ParseTextmapVertexParameter(UINT32 i, char *param, char *val) +{ + if (fastcmp(param, "x")) + vertexes[i].x = FLOAT_TO_FIXED(atof(val)); + else if (fastcmp(param, "y")) + vertexes[i].y = FLOAT_TO_FIXED(atof(val)); + else if (fastcmp(param, "zfloor")) + { + vertexes[i].floorz = FLOAT_TO_FIXED(atof(val)); + vertexes[i].floorzset = true; + } + else if (fastcmp(param, "zceiling")) + { + vertexes[i].ceilingz = FLOAT_TO_FIXED(atof(val)); + vertexes[i].ceilingzset = true; + } +} + +typedef struct textmap_colormap_s { + boolean used; + INT32 lightcolor; + UINT8 lightalpha; + INT32 fadecolor; + UINT8 fadealpha; + UINT8 fadestart; + UINT8 fadeend; + UINT8 flags; +} textmap_colormap_t; + +textmap_colormap_t textmap_colormap = { false, 0, 25, 0, 25, 0, 31, 0 }; + +static void ParseTextmapSectorParameter(UINT32 i, char *param, char *val) +{ + if (fastcmp(param, "heightfloor")) + sectors[i].floorheight = atol(val) << FRACBITS; + else if (fastcmp(param, "heightceiling")) + sectors[i].ceilingheight = atol(val) << FRACBITS; + if (fastcmp(param, "texturefloor")) + sectors[i].floorpic = P_AddLevelFlat(val, foundflats); + else if (fastcmp(param, "textureceiling")) + sectors[i].ceilingpic = P_AddLevelFlat(val, foundflats); + else if (fastcmp(param, "lightlevel")) + sectors[i].lightlevel = atol(val); + else if (fastcmp(param, "special")) + sectors[i].special = atol(val); + else if (fastcmp(param, "id")) + sectors[i].tag = atol(val); + else if (fastcmp(param, "xpanningfloor")) + sectors[i].floor_xoffs = FLOAT_TO_FIXED(atof(val)); + else if (fastcmp(param, "ypanningfloor")) + sectors[i].floor_yoffs = FLOAT_TO_FIXED(atof(val)); + else if (fastcmp(param, "xpanningceiling")) + sectors[i].ceiling_xoffs = FLOAT_TO_FIXED(atof(val)); + else if (fastcmp(param, "ypanningceiling")) + sectors[i].ceiling_yoffs = FLOAT_TO_FIXED(atof(val)); + else if (fastcmp(param, "rotationfloor")) + sectors[i].floorpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); + else if (fastcmp(param, "rotationceiling")) + sectors[i].ceilingpic_angle = FixedAngle(FLOAT_TO_FIXED(atof(val))); + else if (fastcmp(param, "lightcolor")) + { + textmap_colormap.used = true; + textmap_colormap.lightcolor = atol(val); + } + else if (fastcmp(param, "lightalpha")) + { + textmap_colormap.used = true; + textmap_colormap.lightalpha = atol(val); + } + else if (fastcmp(param, "fadecolor")) + { + textmap_colormap.used = true; + textmap_colormap.fadecolor = atol(val); + } + else if (fastcmp(param, "fadealpha")) + { + textmap_colormap.used = true; + textmap_colormap.fadealpha = atol(val); + } + else if (fastcmp(param, "fadestart")) + { + textmap_colormap.used = true; + textmap_colormap.fadestart = atol(val); + } + else if (fastcmp(param, "fadeend")) + { + textmap_colormap.used = true; + textmap_colormap.fadeend = atol(val); + } + else if (fastcmp(param, "colormapfog") && fastcmp("true", val)) + { + textmap_colormap.used = true; + textmap_colormap.flags |= CMF_FOG; + } + else if (fastcmp(param, "colormapfadesprites") && fastcmp("true", val)) + { + textmap_colormap.used = true; + textmap_colormap.flags |= CMF_FADEFULLBRIGHTSPRITES; + } + else if (fastcmp(param, "colormapprotected") && fastcmp("true", val)) + sectors[i].colormap_protected = true; +} + +static void ParseTextmapSidedefParameter(UINT32 i, char *param, char *val) +{ + if (fastcmp(param, "offsetx")) + sides[i].textureoffset = atol(val)< 3) + { + size_t argnum = atol(param + 3); + if (argnum >= NUMLINEARGS) + return; + lines[i].args[argnum] = atol(val); + } + else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9) + { + size_t argnum = param[9] - '0'; + if (argnum >= NUMLINESTRINGARGS) + return; + lines[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[argnum], val, strlen(val) + 1); + } + else if (fastcmp(param, "sidefront")) + lines[i].sidenum[0] = atol(val); + else if (fastcmp(param, "sideback")) + lines[i].sidenum[1] = atol(val); + else if (fastcmp(param, "alpha")) + lines[i].alpha = FLOAT_TO_FIXED(atof(val)); + else if (fastcmp(param, "executordelay")) + lines[i].executordelay = atol(val); + + // Flags + else if (fastcmp(param, "blocking") && fastcmp("true", val)) + lines[i].flags |= ML_IMPASSABLE; + else if (fastcmp(param, "blockplayers") && fastcmp("true", val)) + lines[i].flags |= ML_BLOCKPLAYERS; + else if (fastcmp(param, "twosided") && fastcmp("true", val)) + lines[i].flags |= ML_TWOSIDED; + else if (fastcmp(param, "dontpegtop") && fastcmp("true", val)) + lines[i].flags |= ML_DONTPEGTOP; + else if (fastcmp(param, "dontpegbottom") && fastcmp("true", val)) + lines[i].flags |= ML_DONTPEGBOTTOM; + else if (fastcmp(param, "skewtd") && fastcmp("true", val)) + lines[i].flags |= ML_EFFECT1; + else if (fastcmp(param, "noclimb") && fastcmp("true", val)) + lines[i].flags |= ML_NOCLIMB; + else if (fastcmp(param, "noskew") && fastcmp("true", val)) + lines[i].flags |= ML_EFFECT2; + else if (fastcmp(param, "midpeg") && fastcmp("true", val)) + lines[i].flags |= ML_EFFECT3; + else if (fastcmp(param, "midsolid") && fastcmp("true", val)) + lines[i].flags |= ML_EFFECT4; + else if (fastcmp(param, "wrapmidtex") && fastcmp("true", val)) + lines[i].flags |= ML_EFFECT5; + else if (fastcmp(param, "effect6") && fastcmp("true", val)) + lines[i].flags |= ML_EFFECT6; + else if (fastcmp(param, "nonet") && fastcmp("true", val)) + lines[i].flags |= ML_NONET; + else if (fastcmp(param, "netonly") && fastcmp("true", val)) + lines[i].flags |= ML_NETONLY; + else if (fastcmp(param, "notbouncy") && fastcmp("true", val)) + lines[i].flags |= ML_NOTBOUNCY; + else if (fastcmp(param, "transfer") && fastcmp("true", val)) + lines[i].flags |= ML_TFERLINE; +} + +static void ParseTextmapThingParameter(UINT32 i, char *param, char *val) +{ + if (fastcmp(param, "id")) + mapthings[i].tag = atol(val); + if (fastcmp(param, "x")) + mapthings[i].x = atol(val); + else if (fastcmp(param, "y")) + mapthings[i].y = atol(val); + else if (fastcmp(param, "height")) + mapthings[i].z = atol(val); + else if (fastcmp(param, "angle")) + mapthings[i].angle = atol(val); + else if (fastcmp(param, "pitch")) + mapthings[i].pitch = atol(val); + else if (fastcmp(param, "roll")) + mapthings[i].roll = atol(val); + else if (fastcmp(param, "type")) + mapthings[i].type = atol(val); + else if (fastcmp(param, "scale") || fastcmp(param, "scalex") || fastcmp(param, "scaley")) + mapthings[i].scale = FLOAT_TO_FIXED(atof(val)); + // Flags + else if (fastcmp(param, "extra") && fastcmp("true", val)) + mapthings[i].options |= MTF_EXTRA; + else if (fastcmp(param, "flip") && fastcmp("true", val)) + mapthings[i].options |= MTF_OBJECTFLIP; + else if (fastcmp(param, "objectspecial") && fastcmp("true", val)) + mapthings[i].options |= MTF_OBJECTSPECIAL; + else if (fastcmp(param, "ambush") && fastcmp("true", val)) + mapthings[i].options |= MTF_AMBUSH; + + else if (fastncmp(param, "arg", 3) && strlen(param) > 3) + { + size_t argnum = atol(param + 3); + if (argnum >= NUMMAPTHINGARGS) + return; + mapthings[i].args[argnum] = atol(val); + } + else if (fastncmp(param, "stringarg", 9) && strlen(param) > 9) + { + size_t argnum = param[9] - '0'; + if (argnum >= NUMMAPTHINGSTRINGARGS) + return; + mapthings[i].stringargs[argnum] = Z_Malloc(strlen(val) + 1, PU_LEVEL, NULL); + M_Memcpy(mapthings[i].stringargs[argnum], val, strlen(val) + 1); + } +} + +/** From a given position table, run a specified parser function through a {}-encapsuled text. + * + * \param Position of the data to parse, in the textmap. + * \param Structure number (mapthings, sectors, ...). + * \param Parser function pointer. + */ +static void TextmapParse(UINT32 dataPos, size_t num, void (*parser)(UINT32, char *, char *)) +{ + char *param, *val; + + M_SetTokenPos(dataPos); + param = M_GetToken(NULL); + if (!fastcmp(param, "{")) + { + Z_Free(param); + CONS_Alert(CONS_WARNING, "Invalid UDMF data capsule!\n"); + return; + } + Z_Free(param); + + while (true) + { + param = M_GetToken(NULL); + if (fastcmp(param, "}")) + { + Z_Free(param); + break; + } + val = M_GetToken(NULL); + parser(num, param, val); + Z_Free(param); + Z_Free(val); + } +} + +/** Provides a fix to the flat alignment coordinate transform from standard Textmaps. + */ +static void TextmapFixFlatOffsets(sector_t *sec) +{ + if (sec->floorpic_angle) + { + fixed_t pc = FINECOSINE(sec->floorpic_angle>>ANGLETOFINESHIFT); + fixed_t ps = FINESINE (sec->floorpic_angle>>ANGLETOFINESHIFT); + fixed_t xoffs = sec->floor_xoffs; + fixed_t yoffs = sec->floor_yoffs; + sec->floor_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->floor_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + } + + if (sec->ceilingpic_angle) + { + fixed_t pc = FINECOSINE(sec->ceilingpic_angle>>ANGLETOFINESHIFT); + fixed_t ps = FINESINE (sec->ceilingpic_angle>>ANGLETOFINESHIFT); + fixed_t xoffs = sec->ceiling_xoffs; + fixed_t yoffs = sec->ceiling_yoffs; + sec->ceiling_xoffs = (FixedMul(xoffs, pc) % MAXFLATSIZE) - (FixedMul(yoffs, ps) % MAXFLATSIZE); + sec->ceiling_yoffs = (FixedMul(xoffs, ps) % MAXFLATSIZE) + (FixedMul(yoffs, pc) % MAXFLATSIZE); + } +} + +static INT32 P_ColorToRGBA(INT32 color, UINT8 alpha) +{ + UINT8 r = (color >> 16) & 0xFF; + UINT8 g = (color >> 8) & 0xFF; + UINT8 b = color & 0xFF; + return R_PutRgbaRGBA(r, g, b, alpha); +} + +/** Loads the textmap data, after obtaining the elements count and allocating their respective space. + */ +static void P_LoadTextmap(void) +{ + UINT32 i; + + vertex_t *vt; + sector_t *sc; + line_t *ld; + side_t *sd; + mapthing_t *mt; + + CONS_Alert(CONS_NOTICE, "UDMF support is still a work-in-progress; its specs and features are prone to change until it is fully implemented.\n"); + + /// Given the UDMF specs, some fields are given a default value. + /// If an element's field has a default value set, it is omitted + /// from the textmap, and therefore we have to account for it by + /// preemptively setting that value beforehand. + + for (i = 0, vt = vertexes; i < numvertexes; i++, vt++) + { + // Defaults. + vt->x = vt->y = INT32_MAX; + vt->floorzset = vt->ceilingzset = false; + vt->floorz = vt->ceilingz = 0; + + TextmapParse(vertexesPos[i], i, ParseTextmapVertexParameter); + + if (vt->x == INT32_MAX) + I_Error("P_LoadTextmap: vertex %s has no x value set!\n", sizeu1(i)); + if (vt->y == INT32_MAX) + I_Error("P_LoadTextmap: vertex %s has no y value set!\n", sizeu1(i)); + } + + for (i = 0, sc = sectors; i < numsectors; i++, sc++) + { + // Defaults. + sc->floorheight = 0; + sc->ceilingheight = 0; + + sc->floorpic = 0; + sc->ceilingpic = 0; + + sc->lightlevel = 255; + + sc->special = 0; + sc->tag = 0; + + sc->floor_xoffs = sc->floor_yoffs = 0; + sc->ceiling_xoffs = sc->ceiling_yoffs = 0; + + sc->floorpic_angle = sc->ceilingpic_angle = 0; + + sc->colormap_protected = false; + + textmap_colormap.used = false; + textmap_colormap.lightcolor = 0; + textmap_colormap.lightalpha = 25; + textmap_colormap.fadecolor = 0; + textmap_colormap.fadealpha = 25; + textmap_colormap.fadestart = 0; + textmap_colormap.fadeend = 31; + textmap_colormap.flags = 0; + TextmapParse(sectorsPos[i], i, ParseTextmapSectorParameter); + P_InitializeSector(sc); + if (textmap_colormap.used) + { + INT32 rgba = P_ColorToRGBA(textmap_colormap.lightcolor, textmap_colormap.lightalpha); + INT32 fadergba = P_ColorToRGBA(textmap_colormap.fadecolor, textmap_colormap.fadealpha); + sc->extra_colormap = sc->spawn_extra_colormap = R_CreateColormap(rgba, fadergba, textmap_colormap.fadestart, textmap_colormap.fadeend, textmap_colormap.flags); + } + TextmapFixFlatOffsets(sc); + } + + for (i = 0, ld = lines; i < numlines; i++, ld++) + { + // Defaults. + ld->v1 = ld->v2 = NULL; + ld->flags = 0; + ld->special = 0; + ld->tag = 0; + memset(ld->args, 0, NUMLINEARGS*sizeof(*ld->args)); + memset(ld->stringargs, 0x00, NUMLINESTRINGARGS*sizeof(*ld->stringargs)); + ld->alpha = FRACUNIT; + ld->executordelay = 0; + ld->sidenum[0] = 0xffff; + ld->sidenum[1] = 0xffff; + + TextmapParse(linesPos[i], i, ParseTextmapLinedefParameter); + + if (!ld->v1) + I_Error("P_LoadTextmap: linedef %s has no v1 value set!\n", sizeu1(i)); + if (!ld->v2) + I_Error("P_LoadTextmap: linedef %s has no v2 value set!\n", sizeu1(i)); + if (ld->sidenum[0] == 0xffff) + I_Error("P_LoadTextmap: linedef %s has no sidefront value set!\n", sizeu1(i)); + + P_InitializeLinedef(ld); + } + + for (i = 0, sd = sides; i < numsides; i++, sd++) + { + // Defaults. + sd->textureoffset = 0; + sd->rowoffset = 0; + sd->toptexture = R_TextureNumForName("-"); + sd->midtexture = R_TextureNumForName("-"); + sd->bottomtexture = R_TextureNumForName("-"); + sd->sector = NULL; + sd->repeatcnt = 0; + + TextmapParse(sidesPos[i], i, ParseTextmapSidedefParameter); + + if (!sd->sector) + I_Error("P_LoadTextmap: sidedef %s has no sector value set!\n", sizeu1(i)); + + P_InitializeSidedef(sd); + } + + for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) + { + // Defaults. + mt->x = mt->y = 0; + mt->angle = mt->pitch = mt->roll = 0; + mt->type = 0; + mt->options = 0; + mt->z = 0; + mt->extrainfo = 0; + mt->scale = mapobjectscale; + mt->tag = 0; + memset(mt->args, 0, NUMMAPTHINGARGS*sizeof(*mt->args)); + memset(mt->stringargs, 0x00, NUMMAPTHINGSTRINGARGS*sizeof(*mt->stringargs)); + mt->mobj = NULL; + + TextmapParse(mapthingsPos[i], i, ParseTextmapThingParameter); + } +} + +static void P_ProcessLinedefsAfterSidedefs(void) +{ + size_t i = numlines; + register line_t *ld = lines; + for (; i--; ld++) + { + ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here + ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; + + switch (ld->special) + { + // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. + case 331: // Trigger linedef executor: Skin - Continuous + case 332: // Trigger linedef executor: Skin - Each time + case 333: // Trigger linedef executor: Skin - Once + case 443: // Calls a named Lua function + if (sides[ld->sidenum[0]].text) + { + size_t len = strlen(sides[ld->sidenum[0]].text) + 1; + if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) + len += strlen(sides[ld->sidenum[1]].text); + ld->text = Z_Malloc(len, PU_LEVEL, NULL); + M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text) + 1); + if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) + M_Memcpy(ld->text + strlen(ld->text) + 1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text) + 1); + } + break; + case 447: // Change colormap + case 455: // Fade colormap + if (udmf) + break; + if (ld->flags & ML_DONTPEGBOTTOM) // alternate alpha (by texture offsets) + { + extracolormap_t *exc = R_CopyColormap(sides[ld->sidenum[0]].colormap_data, false); + INT16 alpha = max(min(sides[ld->sidenum[0]].textureoffset >> FRACBITS, 25), -25); + INT16 fadealpha = max(min(sides[ld->sidenum[0]].rowoffset >> FRACBITS, 25), -25); + + // If alpha is negative, set "subtract alpha" flag and store absolute value + if (alpha < 0) + { + alpha *= -1; + ld->args[2] |= TMCF_SUBLIGHTA; + } + if (fadealpha < 0) + { + fadealpha *= -1; + ld->args[2] |= TMCF_SUBFADEA; + } + + exc->rgba = R_GetRgbaRGB(exc->rgba) + R_PutRgbaA(alpha); + exc->fadergba = R_GetRgbaRGB(exc->fadergba) + R_PutRgbaA(fadealpha); + + if (!(sides[ld->sidenum[0]].colormap_data = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + sides[ld->sidenum[0]].colormap_data = exc; + } + else + Z_Free(exc); + } + break; + } + } +} + +static boolean P_LoadMapData(const virtres_t *virt) +{ + virtlump_t *virtvertexes = NULL, *virtsectors = NULL, *virtsidedefs = NULL, *virtlinedefs = NULL, *virtthings = NULL; + + // Count map data. + if (udmf) // Count how many entries for each type we got in textmap. + { + virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); + if (!TextmapCount(textmap->data, textmap->size)) + return false; + } + else + { + virtthings = vres_Find(virt, "THINGS"); + virtvertexes = vres_Find(virt, "VERTEXES"); + virtsectors = vres_Find(virt, "SECTORS"); + virtsidedefs = vres_Find(virt, "SIDEDEFS"); + virtlinedefs = vres_Find(virt, "LINEDEFS"); + + if (!virtthings) + I_Error("THINGS lump not found"); + if (!virtvertexes) + I_Error("VERTEXES lump not found"); + if (!virtsectors) + I_Error("SECTORS lump not found"); + if (!virtsidedefs) + I_Error("SIDEDEFS lump not found"); + if (!virtlinedefs) + I_Error("LINEDEFS lump not found"); + + // Traditional doom map format just assumes the number of elements from the lump sizes. + numvertexes = virtvertexes->size / sizeof (mapvertex_t); + numsectors = virtsectors->size / sizeof (mapsector_t); + numsides = virtsidedefs->size / sizeof (mapsidedef_t); + numlines = virtlinedefs->size / sizeof (maplinedef_t); + nummapthings = virtthings->size / (5 * sizeof (INT16)); + } + + if (numvertexes <= 0) + I_Error("Level has no vertices"); + if (numsectors <= 0) + I_Error("Level has no sectors"); + if (numsides <= 0) + I_Error("Level has no sidedefs"); + if (numlines <= 0) + I_Error("Level has no linedefs"); + + vertexes = Z_Calloc(numvertexes * sizeof (*vertexes), PU_LEVEL, NULL); + sectors = Z_Calloc(numsectors * sizeof (*sectors), PU_LEVEL, NULL); + sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); + lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); + mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); + + // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. + //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty + foundflats = calloc(MAXLEVELFLATS, sizeof (*foundflats)); + if (foundflats == NULL) + I_Error("Ran out of memory while loading sectors\n"); + + numlevelflats = 0; + + // Load map data. + if (udmf) + P_LoadTextmap(); + else + { + P_LoadVertices(virtvertexes->data); + P_LoadSectors(virtsectors->data); + P_LoadLinedefs(virtlinedefs->data); + P_LoadSidedefs(virtsidedefs->data); + P_LoadThings(virtthings->data); + } + + P_ProcessLinedefsAfterSidedefs(); + + R_ClearTextureNumCache(true); + + // set the sky flat num + skyflatnum = P_AddLevelFlat(SKYFLATNAME, foundflats); + + // copy table for global usage + levelflats = M_Memcpy(Z_Calloc(numlevelflats * sizeof (*levelflats), PU_LEVEL, NULL), foundflats, numlevelflats * sizeof (levelflat_t)); + free(foundflats); + + // search for animated flats and set up + P_SetupLevelFlatAnims(); + + return true; +} + +static void P_InitializeSubsector(subsector_t *ss) +{ + ss->sector = NULL; +#ifdef FLOORSPLATS + ss->splats = NULL; +#endif + ss->validcount = 0; +} + +static inline void P_LoadSubsectors(UINT8 *data) +{ + mapsubsector_t *ms = (mapsubsector_t*)data; + subsector_t *ss = subsectors; + size_t i; + + for (i = 0; i < numsubsectors; i++, ss++, ms++) + { + ss->numlines = SHORT(ms->numsegs); + ss->firstline = SHORT(ms->firstseg); + P_InitializeSubsector(ss); + } +} + +static void P_LoadNodes(UINT8 *data) +{ + UINT8 j, k; + mapnode_t *mn = (mapnode_t*)data; + node_t *no = nodes; + size_t i; + + for (i = 0; i < numnodes; i++, no++, mn++) + { + no->x = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<children[j] = SHORT(mn->children[j]); + for (k = 0; k < 4; k++) + no->bbox[j][k] = SHORT(mn->bbox[j][k])<linedef) { - li->v1 = &vertexes[SHORT(ml->v1)]; - li->v2 = &vertexes[SHORT(ml->v2)]; + UINT16 side = seg->linedef->sidenum[seg->side]; + + if (side == 0xffff) + I_Error("P_InitializeSeg: Seg %s refers to side %d of linedef %s, which doesn't exist!\n", sizeu1((size_t)(seg - segs)), seg->side, sizeu1((size_t)(seg->linedef - lines))); + + seg->sidedef = &sides[side]; + + seg->frontsector = seg->sidedef->sector; + seg->backsector = (seg->linedef->flags & ML_TWOSIDED) ? sides[seg->linedef->sidenum[seg->side ^ 1]].sector : NULL; + } - li->length = P_SegLength(li); #ifdef HWRENDER - if (rendermode == render_opengl) - li->flength = P_SegLengthFloat(li); - li->pv1 = li->pv2 = NULL; + seg->pv1 = seg->pv2 = NULL; + + //Hurdler: 04/12/2000: for now, only used in hardware mode + seg->lightmaps = NULL; // list of static lightmap for this seg #endif - li->angle = (SHORT(ml->angle))<offset = (SHORT(ml->offset))<linedef); - ldef = &lines[linedef]; - li->linedef = ldef; - li->side = side = SHORT(ml->side); - li->sidedef = &sides[ldef->sidenum[side]]; - li->frontsector = sides[ldef->sidenum[side]].sector; - if (ldef-> flags & ML_TWOSIDED) - li->backsector = sides[ldef->sidenum[side^1]].sector; + seg->numlights = 0; + seg->rlights = NULL; + seg->polyseg = NULL; + seg->dontrenderme = false; + + P_UpdateSegLightOffset(seg); +} + +static void P_LoadSegs(UINT8 *data) +{ + mapseg_t *ms = (mapseg_t*)data; + seg_t *seg = segs; + size_t i; + + for (i = 0; i < numsegs; i++, seg++, ms++) + { + seg->v1 = &vertexes[SHORT(ms->v1)]; + seg->v2 = &vertexes[SHORT(ms->v2)]; + + seg->side = SHORT(ms->side); + + seg->offset = (SHORT(ms->offset)) << FRACBITS; + + seg->angle = (SHORT(ms->angle)) << FRACBITS; + + seg->linedef = &lines[SHORT(ms->linedef)]; + + seg->length = P_SegLength(seg); +#ifdef HWRENDER + seg->flength = (rendermode == render_opengl) ? P_SegLengthFloat(seg) : 0; +#endif + + seg->glseg = false; + P_InitializeSeg(seg); + } +} + +typedef enum { + NT_DOOM, + NT_XNOD, + NT_ZNOD, + NT_XGLN, + NT_ZGLN, + NT_XGL2, + NT_ZGL2, + NT_XGL3, + NT_ZGL3, + NT_UNSUPPORTED, + NUMNODETYPES +} nodetype_t; + +// Find out the BSP format. +static nodetype_t P_GetNodetype(const virtres_t *virt, UINT8 **nodedata) +{ + boolean supported[NUMNODETYPES] = {0}; + nodetype_t nodetype = NT_UNSUPPORTED; + char signature[4 + 1]; + + if (udmf) + { + *nodedata = vres_Find(virt, "ZNODES")->data; + supported[NT_XGLN] = supported[NT_XGL3] = true; + } + else + { + virtlump_t *virtsegs = vres_Find(virt, "SEGS"); + virtlump_t *virtssectors; + + if (virtsegs && virtsegs->size) + { + *nodedata = vres_Find(virt, "NODES")->data; + return NT_DOOM; // Traditional map format BSP tree. + } + + virtssectors = vres_Find(virt, "SSECTORS"); + + if (virtssectors && virtssectors->size) + { // Possibly GL nodes: NODES ignored, SSECTORS takes precedence as nodes lump, (It is confusing yeah) and has a signature. + *nodedata = virtssectors->data; + supported[NT_XGLN] = supported[NT_ZGLN] = supported[NT_XGL3] = true; + } else - li->backsector = 0; - - li->numlights = 0; - li->rlights = NULL; - - P_UpdateSegLightOffset(li); + { // Possibly ZDoom extended nodes: SSECTORS is empty, NODES has a signature. + *nodedata = vres_Find(virt, "NODES")->data; + supported[NT_XNOD] = supported[NT_ZNOD] = true; + } } + + M_Memcpy(signature, *nodedata, 4); + signature[4] = '\0'; + (*nodedata) += 4; + + if (!strcmp(signature, "XNOD")) + nodetype = NT_XNOD; + else if (!strcmp(signature, "ZNOD")) + nodetype = NT_ZNOD; + else if (!strcmp(signature, "XGLN")) + nodetype = NT_XGLN; + else if (!strcmp(signature, "ZGLN")) + nodetype = NT_ZGLN; + else if (!strcmp(signature, "XGL3")) + nodetype = NT_XGL3; + + return supported[nodetype] ? nodetype : NT_UNSUPPORTED; } -static void P_LoadSegs(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSegs(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - - -/** Loads the SSECTORS resource from a level. - * - * \param lump Lump number of the SSECTORS resource. - * \sa ::ML_SSECTORS - */ -static inline void P_LoadRawSubsectors(void *data, size_t i) -{ - mapsubsector_t *ms; - subsector_t *ss; - - numsubsectors = i / sizeof (mapsubsector_t); - if (numsubsectors <= 0) - I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); - ss = subsectors = Z_Calloc(numsubsectors * sizeof (*subsectors), PU_LEVEL, NULL); - - ms = (mapsubsector_t *)data; - - for (i = 0; i < numsubsectors; i++, ss++, ms++) - { - ss->sector = NULL; - ss->numlines = SHORT(ms->numsegs); - ss->firstline = SHORT(ms->firstseg); -#ifdef FLOORSPLATS - ss->splats = NULL; -#endif - ss->validcount = 0; - } -} - -static void P_LoadSubsectors(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSubsectors(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - -// -// P_LoadSectors -// - -// -// levelflats -// -#define MAXLEVELFLATS 256 - -size_t numlevelflats; -levelflat_t *levelflats; - -//SoM: Other files want this info. -size_t P_PrecacheLevelFlats(void) -{ - lumpnum_t lump; - size_t i, flatmemory = 0; - - //SoM: 4/18/2000: New flat code to make use of levelflats. - for (i = 0; i < numlevelflats; i++) - { - lump = levelflats[i].lumpnum; - if (devparm) - flatmemory += W_LumpLength(lump); - R_GetFlat(lump); - } - return flatmemory; -} - -// help function for P_LoadSectors, find a flat in the active wad files, -// allocate an id for it, and set the levelflat (to speedup search) -// -INT32 P_AddLevelFlat(const char *flatname, levelflat_t *levelflat) +// Extended node formats feature additional vertices; useful for OpenGL, but totally useless in gamelogic. +static boolean P_LoadExtraVertices(UINT8 **data) { + UINT32 origvrtx = READUINT32((*data)); + UINT32 xtrvrtx = READUINT32((*data)); + line_t* ld = lines; + vertex_t *oldpos = vertexes; + ssize_t offset; size_t i; - // - // first scan through the already found flats - // - for (i = 0; i < numlevelflats; i++, levelflat++) - if (strnicmp(levelflat->name,flatname,8)==0) - break; - - // that flat was already found in the level, return the id - if (i == numlevelflats) + if (numvertexes != origvrtx) // If native vertex count doesn't match node original vertex count, bail out (broken data?). { - // store the name - strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); - strupr(levelflat->name); - - // store the flat lump number - levelflat->lumpnum = R_GetFlatNumForName(flatname); - -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); -#endif - - numlevelflats++; - - if (numlevelflats >= MAXLEVELFLATS) - I_Error("Too many flats in level\n"); + CONS_Alert(CONS_WARNING, "Vertex count in map data and nodes differ!\n"); + return false; } - // level flat id - return (INT32)i; -} + if (!xtrvrtx) + return true; -// help function for Lua and $$$.sav reading -// same as P_AddLevelFlat, except this is not setup so we must realloc levelflats to fit in the new flat -// no longer a static func in lua_maplib.c because p_saveg.c also needs it -// -INT32 P_AddLevelFlatRuntime(const char *flatname) -{ - size_t i; - levelflat_t *levelflat = levelflats; + // If extra vertexes were generated, reallocate the vertex array and fix the pointers. + numvertexes += xtrvrtx; + vertexes = Z_Realloc(vertexes, numvertexes*sizeof(*vertexes), PU_LEVEL, NULL); + offset = (size_t)(vertexes - oldpos); - // - // first scan through the already found flats - // - for (i = 0; i < numlevelflats; i++, levelflat++) - if (strnicmp(levelflat->name,flatname,8)==0) - break; - - // that flat was already found in the level, return the id - if (i == numlevelflats) + for (i = 0, ld = lines; i < numlines; i++, ld++) { - // allocate new flat memory - levelflats = Z_Realloc(levelflats, (numlevelflats + 1) * sizeof(*levelflats), PU_LEVEL, NULL); - levelflat = levelflats+i; - - // store the name - strlcpy(levelflat->name, flatname, sizeof (levelflat->name)); - strupr(levelflat->name); - - // store the flat lump number - levelflat->lumpnum = R_GetFlatNumForName(flatname); - -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "flat #%03d: %s\n", atoi(sizeu1(numlevelflats)), levelflat->name); -#endif - - numlevelflats++; + ld->v1 += offset; + ld->v2 += offset; } - // level flat id - return (INT32)i; -} - -// help function for $$$.sav checking -// this simply returns the flat # for the name given -// -INT32 P_CheckLevelFlat(const char *flatname) -{ - size_t i; - levelflat_t *levelflat = levelflats; - - // - // scan through the already found flats - // - for (i = 0; i < numlevelflats; i++, levelflat++) - if (strnicmp(levelflat->name,flatname,8)==0) - break; - - if (i == numlevelflats) - return 0; // ??? flat was not found, this should not happen! - - // level flat id - return (INT32)i; -} - -// Sets up the ingame sectors structures. -// Lumpnum is the lumpnum of a SECTORS lump. -static void P_LoadRawSectors(UINT8 *data, size_t i) -{ - mapsector_t *ms; - sector_t *ss; - levelflat_t *foundflats; - - // We count how many sectors we got. - numsectors = i / sizeof (mapsector_t); - if (numsectors <= 0) - I_Error("Level has no sectors"); - - // Allocate as much memory as we need into the global sectors table. - sectors = Z_Calloc(numsectors*sizeof (*sectors), PU_LEVEL, NULL); - - // Allocate a big chunk of memory as big as our MAXLEVELFLATS limit. - //Fab : FIXME: allocate for whatever number of flats - 512 different flats per level should be plenty - foundflats = calloc(MAXLEVELFLATS, sizeof (*foundflats)); - if (foundflats == NULL) - I_Error("Ran out of memory while loading sectors\n"); - - numlevelflats = 0; - - // For each counted sector, copy the sector raw data from our cache pointer ms, to the global table pointer ss. - ms = (mapsector_t *)data; - ss = sectors; - for (i = 0; i < numsectors; i++, ss++, ms++) + // Read extra vertex data. + for (i = origvrtx; i < numvertexes; i++) { - ss->floorheight = SHORT(ms->floorheight)<ceilingheight = SHORT(ms->ceilingheight)<floorpic = P_AddLevelFlat(ms->floorpic, foundflats); - ss->ceilingpic = P_AddLevelFlat(ms->ceilingpic, foundflats); - - ss->lightlevel = SHORT(ms->lightlevel); - ss->special = SHORT(ms->special); - ss->tag = SHORT(ms->tag); - ss->nexttag = ss->firsttag = -1; - ss->spawn_nexttag = ss->spawn_firsttag = -1; - - memset(&ss->soundorg, 0, sizeof(ss->soundorg)); - ss->validcount = 0; - - ss->thinglist = NULL; - ss->touching_thinglist = NULL; - ss->preciplist = NULL; - ss->touching_preciplist = NULL; - - ss->floordata = NULL; - ss->ceilingdata = NULL; - ss->lightingdata = NULL; - - ss->linecount = 0; - ss->lines = NULL; - - ss->heightsec = -1; - ss->camsec = -1; - ss->floorlightsec = -1; - ss->ceilinglightsec = -1; - ss->crumblestate = 0; - ss->ffloors = NULL; - ss->lightlist = NULL; - ss->numlights = 0; - ss->attached = NULL; - ss->attachedsolid = NULL; - ss->numattached = 0; - ss->maxattached = 1; - ss->moved = true; - - ss->extra_colormap = NULL; - - ss->floor_xoffs = ss->ceiling_xoffs = ss->floor_yoffs = ss->ceiling_yoffs = 0; - ss->spawn_flr_xoffs = ss->spawn_ceil_xoffs = ss->spawn_flr_yoffs = ss->spawn_ceil_yoffs = 0; - ss->floorpic_angle = ss->ceilingpic_angle = 0; - ss->spawn_flrpic_angle = ss->spawn_ceilpic_angle = 0; - ss->bottommap = ss->midmap = ss->topmap = -1; - ss->gravity = NULL; - ss->cullheight = NULL; - ss->verticalflip = false; - ss->flags = 0; - ss->flags |= SF_FLIPSPECIAL_FLOOR; - - ss->floorspeed = 0; - ss->ceilspeed = 0; - -#ifdef HWRENDER // ----- for special tricks with HW renderer ----- - ss->pseudoSector = false; - ss->virtualFloor = false; - ss->virtualCeiling = false; - ss->sectorLines = NULL; - ss->stackList = NULL; - ss->lineoutLength = -1.0l; -#endif // ----- end special tricks ----- + vertexes[i].x = READFIXED((*data)); + vertexes[i].y = READFIXED((*data)); } - // set the sky flat num - skyflatnum = P_AddLevelFlat(SKYFLATNAME, foundflats); - - // copy table for global usage - levelflats = M_Memcpy(Z_Calloc(numlevelflats * sizeof (*levelflats), PU_LEVEL, NULL), foundflats, numlevelflats * sizeof (levelflat_t)); - free(foundflats); - - // search for animated flats and set up - P_SetupLevelFlatAnims(); + return true; } -static void P_LoadSectors(lumpnum_t lumpnum) +static boolean P_LoadExtendedSubsectorsAndSegs(UINT8 **data, nodetype_t nodetype) { - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSectors(data, W_LumpLength(lumpnum)); - Z_Free(data); -} + size_t i, k; + INT16 m; + seg_t *seg; -// -// P_LoadNodes -// -static void P_LoadRawNodes(UINT8 *data, size_t i) -{ - UINT8 j, k; - mapnode_t *mn; - node_t *no; + // Subsectors + numsubsectors = READUINT32((*data)); + subsectors = Z_Calloc(numsubsectors*sizeof(*subsectors), PU_LEVEL, NULL); - numnodes = i / sizeof (mapnode_t); - if (numnodes <= 0) - I_Error("Level has no nodes"); - nodes = Z_Calloc(numnodes * sizeof (*nodes), PU_LEVEL, NULL); + for (i = 0; i < numsubsectors; i++) + subsectors[i].numlines = READUINT32((*data)); - mn = (mapnode_t *)data; - no = nodes; + // Segs + numsegs = READUINT32((*data)); + segs = Z_Calloc(numsegs*sizeof(*segs), PU_LEVEL, NULL); - for (i = 0; i < numnodes; i++, no++, mn++) + for (i = 0, k = 0; i < numsubsectors; i++) { - no->x = SHORT(mn->x)<y = SHORT(mn->y)<dx = SHORT(mn->dx)<dy = SHORT(mn->dy)<= numvertexes) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid vertex %d!\n", sizeu1(k), m, vertexnum); + + segs[k - 1 + ((m == 0) ? subsectors[i].numlines : 0)].v2 = segs[k].v1 = &vertexes[vertexnum]; + + READUINT32((*data)); // partner, can be ignored by software renderer + + linenum = (nodetype == NT_XGL3) ? READUINT32((*data)) : READUINT16((*data)); + if (linenum != 0xFFFF && linenum >= numlines) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum); + segs[k].glseg = (linenum == 0xFFFF); + segs[k].linedef = (linenum == 0xFFFF) ? NULL : &lines[linenum]; + segs[k].side = READUINT8((*data)); + } + break; + + case NT_XNOD: + for (m = 0; m < subsectors[i].numlines; m++, k++) + { + UINT32 v1num = READUINT32((*data)); + UINT32 v2num = READUINT32((*data)); + UINT16 linenum = READUINT16((*data)); + + if (v1num >= numvertexes) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid v1 %d!\n", sizeu1(k), m, v1num); + if (v2num >= numvertexes) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid v2 %d!\n", sizeu1(k), m, v2num); + if (linenum >= numlines) + I_Error("P_LoadExtendedSubsectorsAndSegs: Seg %s in subsector %d has invalid linedef %d!\n", sizeu1(k), m, linenum); + + segs[k].v1 = &vertexes[v1num]; + segs[k].v2 = &vertexes[v2num]; + segs[k].linedef = &lines[linenum]; + segs[k].side = READUINT8((*data)); + segs[k].glseg = false; + } + break; + + default: + return false; + } + } + + for (i = 0, seg = segs; i < numsegs; i++, seg++) + { + vertex_t *v1 = seg->v1; + vertex_t *v2 = seg->v2; + P_InitializeSeg(seg); + seg->angle = R_PointToAngle2(v1->x, v1->y, v2->x, v2->y); + if (seg->linedef) + segs[i].offset = FixedHypot(v1->x - seg->linedef->v1->x, v1->y - seg->linedef->v1->y); + } + + return true; +} + +// Auxiliary function: Shrink node ID from 32-bit to 16-bit. +static UINT16 ShrinkNodeID(UINT32 x) { + UINT16 mask = (x >> 16) & 0xC000; + UINT16 result = x; + return result | mask; +} + +static void P_LoadExtendedNodes(UINT8 **data, nodetype_t nodetype) +{ + node_t *mn; + size_t i, j, k; + boolean xgl3 = (nodetype == NT_XGL3); + + numnodes = READINT32((*data)); + nodes = Z_Calloc(numnodes*sizeof(*nodes), PU_LEVEL, NULL); + + for (i = 0, mn = nodes; i < numnodes; i++, mn++) + { + // Splitter + mn->x = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); + mn->y = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); + mn->dx = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); + mn->dy = xgl3 ? READINT32((*data)) : (READINT16((*data)) << FRACBITS); + + // Bounding boxes for (j = 0; j < 2; j++) - { - no->children[j] = SHORT(mn->children[j]); for (k = 0; k < 4; k++) - no->bbox[j][k] = SHORT(mn->bbox[j][k])<bbox[j][k] = READINT16((*data)) << FRACBITS; + + //Children + mn->children[0] = ShrinkNodeID(READUINT32((*data))); /// \todo Use UINT32 for node children in a future, instead? + mn->children[1] = ShrinkNodeID(READUINT32((*data))); } } -static void P_LoadNodes(lumpnum_t lumpnum) +static void P_LoadMapBSP(const virtres_t *virt) { - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawNodes(data, W_LumpLength(lumpnum)); - Z_Free(data); -} + UINT8 *nodedata = NULL; + nodetype_t nodetype = P_GetNodetype(virt, &nodedata); -// -// P_ReloadRings -// Used by NiGHTS, clears all ring/wing/etc items and respawns them -// -void P_ReloadRings(void) -{ - mobj_t *mo; - thinker_t *th; - size_t i, numHoops = 0; - // Okay, if you have more than 4000 hoops in your map, - // you're insane. - mapthing_t *hoopsToRespawn[4096]; - mapthing_t *mt = mapthings; - - // scan the thinkers to find rings/wings/hoops to unset - for (th = thinkercap.next; th != &thinkercap; th = th->next) + switch (nodetype) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo = (mobj_t *)th; - - if (mo->type == MT_HOOPCENTER) - { - // Hoops give me a headache - if (mo->threshold == 4242) // Dead hoop - { - hoopsToRespawn[numHoops++] = mo->spawnpoint; - P_RemoveMobj(mo); - } - continue; - } - if (!(mo->type == MT_RING || mo->type == MT_NIGHTSWING || mo->type == MT_COIN - || mo->type == MT_BLUEBALL)) - continue; - - // Don't auto-disintegrate things being pulled to us - if (mo->flags2 & MF2_NIGHTSPULL) - continue; - - P_RemoveMobj(mo); - } - - // Reiterate through mapthings - for (i = 0; i < nummapthings; i++, mt++) + case NT_DOOM: { - // Notice an omission? We handle hoops differently. - if (mt->type == 300 || mt->type == 308 || mt->type == 309 - || mt->type == 1706 || (mt->type >= 600 && mt->type <= 609) - || mt->type == 1800) - { - mt->mobj = NULL; + virtlump_t *virtssectors = vres_Find(virt, "SSECTORS"); + virtlump_t* virtnodes = vres_Find(virt, "NODES"); + virtlump_t *virtsegs = vres_Find(virt, "SEGS"); - // Z for objects Tails 05-26-2002 - mt->z = (INT16)(R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS) - ->sector->floorheight>>FRACBITS); + numsubsectors = virtssectors->size / sizeof(mapsubsector_t); + numnodes = virtnodes->size / sizeof(mapnode_t); + numsegs = virtsegs->size / sizeof(mapseg_t); - P_SpawnHoopsAndRings (mt); - } + if (numsubsectors <= 0) + I_Error("Level has no subsectors (did you forget to run it through a nodesbuilder?)"); + if (numnodes <= 0) + I_Error("Level has no nodes"); + if (numsegs <= 0) + I_Error("Level has no segs"); + + subsectors = Z_Calloc(numsubsectors * sizeof(*subsectors), PU_LEVEL, NULL); + nodes = Z_Calloc(numnodes * sizeof(*nodes), PU_LEVEL, NULL); + segs = Z_Calloc(numsegs * sizeof(*segs), PU_LEVEL, NULL); + + P_LoadSubsectors(virtssectors->data); + P_LoadNodes(virtnodes->data); + P_LoadSegs(virtsegs->data); + break; } - for (i = 0; i < numHoops; i++) - { - P_SpawnHoopsAndRings(hoopsToRespawn[i]); - } -} - -#ifdef SCANTHINGS -void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum) -{ - size_t i, n; - UINT8 *data, *datastart; - UINT16 type, maprings; - INT16 tol; - UINT32 flags; - - tol = mapheaderinfo[mapnum-1]->typeoflevel; - if (!(tol & TOL_SP)) + case NT_XNOD: + case NT_XGLN: + case NT_XGL3: + if (!P_LoadExtraVertices(&nodedata)) + return; + if (!P_LoadExtendedSubsectorsAndSegs(&nodedata, nodetype)) + return; + P_LoadExtendedNodes(&nodedata, nodetype); + break; + default: + CONS_Alert(CONS_WARNING, "Unsupported BSP format detected.\n"); return; - flags = mapheaderinfo[mapnum-1]->levelflags; - - n = W_LumpLengthPwad(wadnum, lumpnum) / (5 * sizeof (INT16)); - //CONS_Printf("%u map things found!\n", n); - - maprings = 0; - data = datastart = W_CacheLumpNumPwad(wadnum, lumpnum, PU_STATIC); - for (i = 0; i < n; i++) - { - data += 3 * sizeof (INT16); // skip x y position, angle - type = READUINT16(data) & 4095; - data += sizeof (INT16); // skip options - - switch (type) - { - case 300: // MT_RING - case 1800: // MT_COIN - case 308: // red team ring - case 309: // blue team ring - maprings++; - break; - case 400: // MT_SUPERRINGBOX - case 414: // red ring box - case 415: // blue ring box - case 603: // 10 diagonal rings - maprings += 10; - break; - case 600: // 5 vertical rings - case 601: // 5 vertical rings - case 602: // 5 diagonal rings - maprings += 5; - break; - case 604: // 8 circle rings - case 609: // 16 circle rings & wings - maprings += 8; - break; - case 605: // 16 circle rings - maprings += 16; - break; - case 608: // 8 circle rings & wings - maprings += 4; - break; - } - } - Z_Free(datastart); - - if (maprings) - CONS_Printf("%s has %u rings\n", G_BuildMapName(mapnum), maprings); -} -#endif - -// -// P_LoadThings -// - -static void P_PrepareRawThings(UINT8 *data, size_t i) -{ - mapthing_t *mt; - - nummapthings = i / (5 * sizeof (INT16)); - mapthings = Z_Calloc(nummapthings * sizeof (*mapthings), PU_LEVEL, NULL); - - // Spawn axis points first so they are - // at the front of the list for fast searching. - mt = mapthings; - for (i = 0; i < nummapthings; i++, mt++) - { - mt->x = READINT16(data); - mt->y = READINT16(data); - mt->angle = READINT16(data); - mt->type = READUINT16(data); - mt->options = READUINT16(data); - mt->extrainfo = (UINT8)(mt->type >> 12); - - mt->type &= 4095; - - switch (mt->type) - { - case 1700: // MT_AXIS - case 1701: // MT_AXISTRANSFER - case 1702: // MT_AXISTRANSFERLINE - mt->mobj = NULL; - P_SpawnMapThing(mt); - break; - default: - break; - } } + return; } -static void P_PrepareThings(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_PrepareRawThings(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - -static void P_LoadThings(void) +// Split from P_LoadBlockMap for convenience +// -- Monster Iestyn 08/01/18 +static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count) { size_t i; - mapthing_t *mt; + blockmaplump = Z_Calloc(sizeof (*blockmaplump) * count, PU_LEVEL, NULL); - // Loading the things lump itself into memory is now handled in P_PrepareThings, above + // killough 3/1/98: Expand wad blockmap into larger internal one, + // by treating all offsets except -1 as unsigned and zero-extending + // them. This potentially doubles the size of blockmaps allowed, + // because Doom originally considered the offsets as always signed. - mt = mapthings; - numhuntemeralds = 0; - for (i = 0; i < nummapthings; i++, mt++) + blockmaplump[0] = SHORT(wadblockmaplump[0]); + blockmaplump[1] = SHORT(wadblockmaplump[1]); + blockmaplump[2] = (INT32)(SHORT(wadblockmaplump[2])) & 0xffff; + blockmaplump[3] = (INT32)(SHORT(wadblockmaplump[3])) & 0xffff; + + for (i = 4; i < count; i++) { - sector_t *mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector; - - // Z for objects - mt->z = (INT16)( -#ifdef ESLOPE - mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : -#endif - mtsector->floorheight)>>FRACBITS; - - if (mt->type == 1700 // MT_AXIS - || mt->type == 1701 // MT_AXISTRANSFER - || mt->type == 1702) // MT_AXISTRANSFERLINE - continue; // These were already spawned - - if (mt->type == mobjinfo[MT_RANDOMITEM].doomednum) - nummapboxes++; - - if (mt->type == mobjinfo[MT_BATTLECAPSULE].doomednum) - { - maptargets++; - continue; // These should not be spawned *yet* - } - - mt->mobj = NULL; - P_SpawnMapThing(mt); - } - - // random emeralds for hunt - if (numhuntemeralds) - { - INT32 emer1, emer2, emer3; - INT32 timeout = 0; // keeps from getting stuck - - emer1 = emer2 = emer3 = 0; - - //increment spawn numbers because zero is valid. - emer1 = (P_RandomKey(numhuntemeralds)) + 1; - while (timeout++ < 100) - { - emer2 = (P_RandomKey(numhuntemeralds)) + 1; - - if (emer2 != emer1) - break; - } - - timeout = 0; - while (timeout++ < 100) - { - emer3 = (P_RandomKey(numhuntemeralds)) + 1; - - if (emer3 != emer2 && emer3 != emer1) - break; - } - - //decrement spawn values to the actual number because zero is valid. - if (emer1) - P_SpawnMobj(huntemeralds[emer1 - 1]->x<y<z<x<y<z<x<y<z<type == 300 || mt->type == 308 || mt->type == 309 - || mt->type == 1706 || (mt->type >= 600 && mt->type <= 609) - || mt->type == 1705 || mt->type == 1713 || mt->type == 1800) - { - sector_t *mtsector = R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector; - - mt->mobj = NULL; - - // Z for objects - mt->z = (INT16)( -#ifdef ESLOPE - mtsector->f_slope ? P_GetZAt(mtsector->f_slope, mt->x << FRACBITS, mt->y << FRACBITS) : -#endif - mtsector->floorheight)>>FRACBITS; - - P_SpawnHoopsAndRings (mt); - } + INT16 t = SHORT(wadblockmaplump[i]); // killough 3/1/98 + blockmaplump[i] = t == -1 ? (INT32)-1 : (INT32) t & 0xffff; } } -static inline void P_SpawnEmblems(void) +// This needs to be a separate function +// because making both the WAD and PK3 loading code use +// the same functions is trickier than it looks for blockmap +// -- Monster Iestyn 09/01/18 +static boolean P_LoadBlockMap(UINT8 *data, size_t count) { - INT32 i, color; - mobj_t *emblemmobj; + if (!count || count >= 0x20000) + return false; - for (i = 0; i < numemblems; i++) - { - if (emblemlocations[i].level != gamemap || emblemlocations[i].type > ET_SKIN) - continue; + //CONS_Printf("Reading blockmap lump for pk3...\n"); - emblemmobj = P_SpawnMobj(emblemlocations[i].x<= 'A' && emblemlocations[i].sprite <= 'Z'); - P_SetMobjStateNF(emblemmobj, emblemmobj->info->spawnstate + (emblemlocations[i].sprite - 'A')); + bmaporgx = blockmaplump[0]<health = i+1; - color = M_GetEmblemColor(&emblemlocations[i]); + // clear out mobj chains + count = sizeof (*blocklinks)* bmapwidth*bmapheight; + blocklinks = Z_Calloc(count, PU_LEVEL, NULL); + blockmap = blockmaplump+4; - emblemmobj->color = (UINT8)color; - - if (emblemlocations[i].collected - || (emblemlocations[i].type == ET_SKIN && emblemlocations[i].var != players[0].skin)) - { - P_UnsetThingPosition(emblemmobj); - emblemmobj->flags |= MF_NOCLIP; - emblemmobj->flags &= ~MF_SPECIAL; - emblemmobj->flags |= MF_NOBLOCKMAP; - emblemmobj->drawflags |= (tr_trans50 << MFD_TRANSSHIFT); - P_SetThingPosition(emblemmobj); - } - } + // haleyjd 2/22/06: setup polyobject blockmap + count = sizeof(*polyblocklinks) * bmapwidth * bmapheight; + polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); + return true; } -static void P_SpawnSecretItems(boolean loademblems) -{ - // Now let's spawn those funky emblem things! Tails 12-08-2002 - if (netgame || multiplayer || majormods) // No cheating!! - return; - - if (loademblems) - P_SpawnEmblems(); -} - -// Experimental groovy write function! -void P_WriteThings(lumpnum_t lumpnum) -{ - size_t i, length; - mapthing_t *mt; - UINT8 *data; - UINT8 *savebuffer, *savebuf_p; - INT16 temp; - - data = W_CacheLumpNum(lumpnum, PU_LEVEL); - - savebuf_p = savebuffer = (UINT8 *)malloc(nummapthings * sizeof (mapthing_t)); - - if (!savebuf_p) - { - CONS_Alert(CONS_ERROR, M_GetText("No more free memory for thing writing!\n")); - return; - } - - mt = mapthings; - for (i = 0; i < nummapthings; i++, mt++) - { - WRITEINT16(savebuf_p, mt->x); - WRITEINT16(savebuf_p, mt->y); - - WRITEINT16(savebuf_p, mt->angle); - - temp = (INT16)(mt->type + ((INT16)mt->extrainfo << 12)); - WRITEINT16(savebuf_p, temp); - WRITEUINT16(savebuf_p, mt->options); - } - - Z_Free(data); - - length = savebuf_p - savebuffer; - - FIL_WriteFile(va("newthings%d.lmp", gamemap), savebuffer, length); - free(savebuffer); - savebuf_p = NULL; - - CONS_Printf(M_GetText("newthings%d.lmp saved.\n"), gamemap); -} - -static void P_LoadRawLineDefs(UINT8 *data, size_t i) -{ - maplinedef_t *mld; - line_t *ld; - vertex_t *v1, *v2; - - numlines = i / sizeof (maplinedef_t); - if (numlines <= 0) - I_Error("Level has no linedefs"); - lines = Z_Calloc(numlines * sizeof (*lines), PU_LEVEL, NULL); - - mld = (maplinedef_t *)data; - ld = lines; - for (i = 0; i < numlines; i++, mld++, ld++) - { - ld->flags = SHORT(mld->flags); - ld->special = SHORT(mld->special); - ld->tag = SHORT(mld->tag); - v1 = ld->v1 = &vertexes[SHORT(mld->v1)]; - v2 = ld->v2 = &vertexes[SHORT(mld->v2)]; - ld->dx = v2->x - v1->x; - ld->dy = v2->y - v1->y; - -#ifdef WALLSPLATS - ld->splats = NULL; -#endif - - if (!ld->dx) - ld->slopetype = ST_VERTICAL; - else if (!ld->dy) - ld->slopetype = ST_HORIZONTAL; - else if ((ld->dy > 0) == (ld->dx > 0)) - ld->slopetype = ST_POSITIVE; - else - ld->slopetype = ST_NEGATIVE; - - if (v1->x < v2->x) - { - ld->bbox[BOXLEFT] = v1->x; - ld->bbox[BOXRIGHT] = v2->x; - } - else - { - ld->bbox[BOXLEFT] = v2->x; - ld->bbox[BOXRIGHT] = v1->x; - } - - if (v1->y < v2->y) - { - ld->bbox[BOXBOTTOM] = v1->y; - ld->bbox[BOXTOP] = v2->y; - } - else - { - ld->bbox[BOXBOTTOM] = v2->y; - ld->bbox[BOXTOP] = v1->y; - } - - ld->sidenum[0] = SHORT(mld->sidenum[0]); - ld->sidenum[1] = SHORT(mld->sidenum[1]); - - { - // cph 2006/09/30 - fix sidedef errors right away. - // cph 2002/07/20 - these errors are fatal if not fixed, so apply them - UINT8 j; - - for (j=0; j < 2; j++) - { - if (ld->sidenum[j] != 0xffff && ld->sidenum[j] >= (UINT16)numsides) - { - ld->sidenum[j] = 0xffff; - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has out-of-range sidedef number\n", sizeu1(numlines-i-1)); - } - } - } - - ld->frontsector = ld->backsector = NULL; - ld->validcount = 0; - ld->firsttag = ld->nexttag = -1; - ld->callcount = 0; - // killough 11/98: fix common wad errors (missing sidedefs): - - if (ld->sidenum[0] == 0xffff) - { - ld->sidenum[0] = 0; // Substitute dummy sidedef for missing right side - // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s missing first sidedef\n", sizeu1(numlines-i-1)); - } - - if ((ld->sidenum[1] == 0xffff) && (ld->flags & ML_TWOSIDED)) - { - ld->flags &= ~ML_TWOSIDED; // Clear 2s flag for missing left side - // cph - print a warning about the bug - CONS_Debug(DBG_SETUP, "P_LoadRawLineDefs: linedef %s has two-sided flag set, but no second sidedef\n", sizeu1(numlines-i-1)); - } - - if (ld->sidenum[0] != 0xffff && ld->special) - sides[ld->sidenum[0]].special = ld->special; - if (ld->sidenum[1] != 0xffff && ld->special) - sides[ld->sidenum[1]].special = ld->special; - -#ifdef POLYOBJECTS - ld->polyobj = NULL; -#endif - } -} - -static void P_LoadLineDefs(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawLineDefs(data, W_LumpLength(lumpnum)); - Z_Free(data); -} - -static void P_LoadLineDefs2(void) -{ - size_t i = numlines; - register line_t *ld = lines; - for (;i--;ld++) - { - ld->frontsector = sides[ld->sidenum[0]].sector; //e6y: Can't be -1 here - ld->backsector = ld->sidenum[1] != 0xffff ? sides[ld->sidenum[1]].sector : 0; - - // Repeat count for midtexture - if ((ld->flags & ML_EFFECT5) && (ld->sidenum[1] != 0xffff)) - { - sides[ld->sidenum[0]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) >> 12); - sides[ld->sidenum[0]].textureoffset = (((unsigned)sides[ld->sidenum[0]].textureoffset >> FRACBITS) & 2047) << FRACBITS; - sides[ld->sidenum[1]].repeatcnt = (INT16)(((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) >> 12); - sides[ld->sidenum[1]].textureoffset = (((unsigned)sides[ld->sidenum[1]].textureoffset >> FRACBITS) & 2047) << FRACBITS; - } - - // Compile linedef 'text' from both sidedefs 'text' for appropriate specials. - switch(ld->special) - { - case 443: // Calls a named Lua function - if (sides[ld->sidenum[0]].text) - { - size_t len = strlen(sides[ld->sidenum[0]].text)+1; - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - len += strlen(sides[ld->sidenum[1]].text); - ld->text = Z_Malloc(len, PU_LEVEL, NULL); - M_Memcpy(ld->text, sides[ld->sidenum[0]].text, strlen(sides[ld->sidenum[0]].text)+1); - if (ld->sidenum[1] != 0xffff && sides[ld->sidenum[1]].text) - M_Memcpy(ld->text+strlen(ld->text)+1, sides[ld->sidenum[1]].text, strlen(sides[ld->sidenum[1]].text)+1); - } - break; - } - } - - // Optimize sidedefs - if (M_CheckParm("-compress")) - { - side_t *newsides; - size_t numnewsides = 0; - size_t z; - - for (i = 0; i < numsides; i++) - { - size_t j, k; - if (sides[i].sector == NULL) - continue; - - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == i) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == i) - ld->sidenum[1] = (UINT16)numnewsides; - } - - for (j = i+1; j < numsides; j++) - { - if (sides[j].sector == NULL) - continue; - - if (!memcmp(&sides[i], &sides[j], sizeof(side_t))) - { - // Find the linedefs that belong to this one - for (k = numlines, ld = lines; k--; ld++) - { - if (ld->sidenum[0] == j) - ld->sidenum[0] = (UINT16)numnewsides; - - if (ld->sidenum[1] == j) - ld->sidenum[1] = (UINT16)numnewsides; - } - sides[j].sector = NULL; // Flag for deletion - } - } - numnewsides++; - } - - // We're loading crap into this block anyhow, so no point in zeroing it out. - newsides = Z_Malloc(numnewsides * sizeof(*newsides), PU_LEVEL, NULL); - - // Copy the sides to their new block of memory. - for (i = 0, z = 0; i < numsides; i++) - { - if (sides[i].sector != NULL) - M_Memcpy(&newsides[z++], &sides[i], sizeof(side_t)); - } - - CONS_Debug(DBG_SETUP, "Old sides is %s, new sides is %s\n", sizeu1(numsides), sizeu1(numnewsides)); - - Z_Free(sides); - sides = newsides; - numsides = numnewsides; - } -} - - - -static inline void P_LoadRawSideDefs(size_t i) -{ - numsides = i / sizeof (mapsidedef_t); - if (numsides <= 0) - I_Error("Level has no sidedefs"); - sides = Z_Calloc(numsides * sizeof (*sides), PU_LEVEL, NULL); -} - -static inline void P_LoadSideDefs(lumpnum_t lumpnum) -{ - P_LoadRawSideDefs(W_LumpLength(lumpnum)); -} - -static void P_LoadRawSideDefs2(void *data) -{ - UINT16 i; - INT32 num; - size_t j; - RGBA_t color; - - for (i = 0; i < numsides; i++) - { - register mapsidedef_t *msd = (mapsidedef_t *)data + i; - register side_t *sd = sides + i; - register sector_t *sec; - - sd->textureoffset = SHORT(msd->textureoffset)<rowoffset = SHORT(msd->rowoffset)<sector); - - if (sector_num >= numsectors) - { - CONS_Debug(DBG_SETUP, "P_LoadRawSideDefs2: sidedef %u has out-of-range sector num %u\n", i, sector_num); - sector_num = 0; - } - sd->sector = sec = §ors[sector_num]; - } - - // refined to allow colormaps to work as wall textures if invalid as colormaps - // but valid as textures. - - sd->sector = sec = §ors[SHORT(msd->sector)]; - - // Colormaps! - switch (sd->special) - { - case 63: // variable colormap via 242 linedef - case 606: //SoM: 4/4/2000: Just colormap transfer - // SoM: R_CreateColormap will only create a colormap in software mode... - // Perhaps we should just call it instead of doing the calculations here. - if (rendermode == render_soft || rendermode == render_none) - { - if (msd->toptexture[0] == '#' || msd->bottomtexture[0] == '#') - { - sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, - msd->bottomtexture); - sd->toptexture = sd->bottomtexture = 0; - } - else - { - if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) - sd->toptexture = 0; - else - sd->toptexture = num; - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) - sd->midtexture = 0; - else - sd->midtexture = num; - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) - sd->bottomtexture = 0; - else - sd->bottomtexture = num; - } - break; - } -#ifdef HWRENDER - else - { - // for now, full support of toptexture only - if ((msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) - || (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6])) - { - char *col; - - sec->midmap = R_CreateColormap(msd->toptexture, msd->midtexture, - msd->bottomtexture); - sd->toptexture = sd->bottomtexture = 0; -#define HEX2INT(x) (x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) -#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) - sec->extra_colormap = &extra_colormaps[sec->midmap]; - - if (msd->toptexture[0] == '#' && msd->toptexture[1] && msd->toptexture[2] && msd->toptexture[3] && msd->toptexture[4] && msd->toptexture[5] && msd->toptexture[6]) - { - col = msd->toptexture; - - // encore mode colormaps! - // do it like software by aproximating a color to a palette index, and then convert it to its encore variant and then back to a color code. - // do this for both the start and fade colormaps. - - color.s.red = (HEX2INT(col[1]) << 4) + HEX2INT(col[2]); - color.s.green = (HEX2INT(col[3]) << 4) + HEX2INT(col[4]); - color.s.blue = (HEX2INT(col[5]) << 4) + HEX2INT(col[6]); - -#ifdef GLENCORE - if (encoremap) - { - j = encoremap[NearestColor(color.s.red, color.s.green, color.s.blue)]; - //CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", j, encoremap[j]); -- moved encoremap upwards for optimisation - color = pLocalPalette[j]; // note: this sets alpha to 255, we will reset it below - } -#endif - color.s.alpha = 0; // reset/init the alpha, so the addition below will work correctly - sec->extra_colormap->rgba = color.rgba; - - // alpha - if (msd->toptexture[7]) - sec->extra_colormap->rgba += (ALPHA2INT(col[7]) << 24); - else - sec->extra_colormap->rgba += (25 << 24); - - /*nearest = NearestColor( - (HEX2INT(col[1]) << 4) + (HEX2INT(col[2]) << 0), - (HEX2INT(col[3]) << 4) + (HEX2INT(col[4]) << 0), - (HEX2INT(col[5]) << 4) + (HEX2INT(col[6]) << 0) - ); - - sec->extra_colormap->rgba = - pLocalPalette[nearest].s.red + - (pLocalPalette[nearest].s.green << 8) + - (pLocalPalette[nearest].s.blue << 16);*/ - } - else - sec->extra_colormap->rgba = 0; - - if (msd->bottomtexture[0] == '#' && msd->bottomtexture[1] && msd->bottomtexture[2] && msd->bottomtexture[3] && msd->bottomtexture[4] && msd->bottomtexture[5] && msd->bottomtexture[6]) - { - col = msd->bottomtexture; - - // do the exact same thing as above here. - - color.s.red = (HEX2INT(col[1]) << 4) + HEX2INT(col[2]); - color.s.green = (HEX2INT(col[3]) << 4) + HEX2INT(col[4]); - color.s.blue = (HEX2INT(col[5]) << 4) + HEX2INT(col[6]); - -#ifdef GLENCORE - if (encoremap) - { - j = encoremap[NearestColor(color.s.red, color.s.green, color.s.blue)]; - //CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", j, encoremap[j]); -- moved encoremap upwards for optimisation - color = pLocalPalette[j]; // note: this sets alpha to 255, we will reset it below - } -#endif - color.s.alpha = 0; // reset/init the alpha, so the addition below will work correctly - sec->extra_colormap->fadergba = color.rgba; - - // alpha - if (msd->bottomtexture[7]) - sec->extra_colormap->fadergba += (ALPHA2INT(col[7]) << 24); - else - sec->extra_colormap->fadergba += (25 << 24); - } - else - sec->extra_colormap->fadergba = 0x19000000; // default alpha, (25 << 24) -#undef ALPHA2INT -#undef HEX2INT - } - else - { - if ((num = R_CheckTextureNumForName(msd->toptexture)) == -1) - sd->toptexture = 0; - else - sd->toptexture = num; - - if ((num = R_CheckTextureNumForName(msd->midtexture)) == -1) - sd->midtexture = 0; - else - sd->midtexture = num; - - if ((num = R_CheckTextureNumForName(msd->bottomtexture)) == -1) - sd->bottomtexture = 0; - else - sd->bottomtexture = num; - } - break; - } -#endif - - case 413: // Change music - { - char process[8+1]; - - sd->toptexture = sd->midtexture = sd->bottomtexture = 0; - if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') - { - M_Memcpy(process,msd->bottomtexture,8); - process[8] = '\0'; - sd->bottomtexture = get_number(process); - } - - if (!(msd->midtexture[0] == '-' && msd->midtexture[1] == '\0') || msd->midtexture[1] != '\0') - { - M_Memcpy(process,msd->midtexture,8); - process[8] = '\0'; - sd->midtexture = get_number(process); - } - - // always process if back sidedef, because we need that - symbol - sd->text = Z_Malloc(7, PU_LEVEL, NULL); - if (i == 1 || msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') - { - M_Memcpy(process,msd->toptexture,8); - process[8] = '\0'; - - // If they type in O_ or D_ and their music name, just shrug, - // then copy the rest instead. - if ((process[0] == 'O' || process[0] == 'D') && process[7]) - M_Memcpy(sd->text, process+2, 6); - else // Assume it's a proper music name. - M_Memcpy(sd->text, process, 6); - sd->text[6] = 0; - } - else - sd->text[0] = 0; - break; - } - - case 4: // Speed pad parameters - case 414: // Play SFX - { - sd->toptexture = sd->midtexture = sd->bottomtexture = 0; - if (msd->toptexture[0] != '-' || msd->toptexture[1] != '\0') - { - char process[8+1]; - M_Memcpy(process,msd->toptexture,8); - process[8] = '\0'; - sd->toptexture = get_number(process); - } - break; - } - - case 9: // Mace parameters - case 14: // Bustable block parameters - case 15: // Fan particle spawner parameters - case 425: // Calls P_SetMobjState on calling mobj - case 434: // Custom Power - case 442: // Calls P_SetMobjState on mobjs of a given type in the tagged sectors - { - char process[8*3+1]; - memset(process,0,8*3+1); - sd->toptexture = sd->midtexture = sd->bottomtexture = 0; - if (msd->toptexture[0] == '-' && msd->toptexture[1] == '\0') - break; - else - M_Memcpy(process,msd->toptexture,8); - if (msd->midtexture[0] != '-' || msd->midtexture[1] != '\0') - M_Memcpy(process+strlen(process), msd->midtexture, 8); - if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') - M_Memcpy(process+strlen(process), msd->bottomtexture, 8); - sd->toptexture = get_number(process); - break; - } - - case 443: // Calls a named Lua function - { - char process[8*3+1]; - memset(process,0,8*3+1); - sd->toptexture = sd->midtexture = sd->bottomtexture = 0; - if (msd->toptexture[0] == '-' && msd->toptexture[1] == '\0') - break; - else - M_Memcpy(process,msd->toptexture,8); - if (msd->midtexture[0] != '-' || msd->midtexture[1] != '\0') - M_Memcpy(process+strlen(process), msd->midtexture, 8); - if (msd->bottomtexture[0] != '-' || msd->bottomtexture[1] != '\0') - M_Memcpy(process+strlen(process), msd->bottomtexture, 8); - sd->text = Z_Malloc(strlen(process)+1, PU_LEVEL, NULL); - M_Memcpy(sd->text, process, strlen(process)+1); - break; - } - - default: // normal cases - if (msd->toptexture[0] == '#') - { - char *col = msd->toptexture; - sd->toptexture = sd->bottomtexture = - ((col[1]-'0')*100 + (col[2]-'0')*10 + col[3]-'0') + 1; - sd->midtexture = R_TextureNumForName(msd->midtexture); - } - else - { - sd->midtexture = R_TextureNumForName(msd->midtexture); - sd->toptexture = R_TextureNumForName(msd->toptexture); - sd->bottomtexture = R_TextureNumForName(msd->bottomtexture); - } - break; - } - } - R_ClearTextureNumCache(true); -} - - -// Delay loading texture names until after loaded linedefs. -static void P_LoadSideDefs2(lumpnum_t lumpnum) -{ - UINT8 *data = W_CacheLumpNum(lumpnum, PU_STATIC); - P_LoadRawSideDefs2(data); - Z_Free(data); -} - - static boolean LineInBlock(fixed_t cx1, fixed_t cy1, fixed_t cx2, fixed_t cy2, fixed_t bx1, fixed_t by1) { fixed_t bbox[4]; @@ -1991,164 +2784,49 @@ static void P_CreateBlockMap(void) blocklinks = Z_Calloc(count, PU_LEVEL, NULL); blockmap = blockmaplump + 4; -#ifdef POLYOBJECTS // haleyjd 2/22/06: setup polyobject blockmap count = sizeof(*polyblocklinks) * bmapwidth * bmapheight; polyblocklinks = Z_Calloc(count, PU_LEVEL, NULL); -#endif } } -// Split from P_LoadBlockMap for convenience -// -- Monster Iestyn 08/01/18 -static void P_ReadBlockMapLump(INT16 *wadblockmaplump, size_t count) -{ - size_t i; - blockmaplump = Z_Calloc(sizeof (*blockmaplump) * count, PU_LEVEL, NULL); - - // killough 3/1/98: Expand wad blockmap into larger internal one, - // by treating all offsets except -1 as unsigned and zero-extending - // them. This potentially doubles the size of blockmaps allowed, - // because Doom originally considered the offsets as always signed. - - blockmaplump[0] = SHORT(wadblockmaplump[0]); - blockmaplump[1] = SHORT(wadblockmaplump[1]); - blockmaplump[2] = (INT32)(SHORT(wadblockmaplump[2])) & 0xffff; - blockmaplump[3] = (INT32)(SHORT(wadblockmaplump[3])) & 0xffff; - - for (i = 4; i < count; i++) - { - INT16 t = SHORT(wadblockmaplump[i]); // killough 3/1/98 - blockmaplump[i] = t == -1 ? (INT32)-1 : (INT32) t & 0xffff; - } -} - -// -// P_LoadBlockMap -// -// Levels might not have a blockmap, so if one does not exist -// this should return false. -static boolean P_LoadBlockMap(lumpnum_t lumpnum) -{ -#if 0 - (void)lumpnum; - return false; -#else - size_t count; - const char *lumpname = W_CheckNameForNum(lumpnum); - - // Check if the lump exists, and if it's named "BLOCKMAP" - if (!lumpname || memcmp(lumpname, "BLOCKMAP", 8) != 0) - { - return false; - } - - count = W_LumpLength(lumpnum); - - if (!count || count >= 0x20000) - return false; - - { - INT16 *wadblockmaplump = malloc(count); //INT16 *wadblockmaplump = W_CacheLumpNum (lump, PU_LEVEL); - if (!wadblockmaplump) - return false; - W_ReadLump(lumpnum, wadblockmaplump); - count /= 2; - P_ReadBlockMapLump(wadblockmaplump, count); - free(wadblockmaplump); - } - - bmaporgx = blockmaplump[0]<= 0x20000) - return false; +static void P_LoadMapLUT(const virtres_t *virt) +{ + virtlump_t* virtblockmap = vres_Find(virt, "BLOCKMAP"); + virtlump_t* virtreject = vres_Find(virt, "REJECT"); - //CONS_Printf("Reading blockmap lump for pk3...\n"); + // Lookup tables + if (virtreject) + P_LoadReject(virtreject->data, virtreject->size); + else + rejectmatrix = NULL; - // no need to malloc anything, assume the data is uncompressed for now - count /= 2; - P_ReadBlockMapLump((INT16 *)data, count); - - bmaporgx = blockmaplump[0]<data, virtblockmap->size))) + P_CreateBlockMap(); } // -// P_GroupLines +// P_LinkMapData // Builds sector line lists and subsector sector numbers. // Finds block bounding boxes for sectors. // -static void P_GroupLines(void) +static void P_LinkMapData(void) { size_t i, j; line_t *li; @@ -2162,20 +2840,20 @@ static void P_GroupLines(void) for (i = 0; i < numsubsectors; i++, ss++) { if (ss->firstline >= numsegs) - CorruptMapError(va("P_GroupLines: ss->firstline invalid " + CorruptMapError(va("P_LinkMapData: ss->firstline invalid " "(subsector %s, firstline refers to %d of %s)", sizeu1(i), ss->firstline, sizeu2(numsegs))); seg = &segs[ss->firstline]; sidei = (size_t)(seg->sidedef - sides); if (!seg->sidedef) - CorruptMapError(va("P_GroupLines: seg->sidedef is NULL " + CorruptMapError(va("P_LinkMapData: seg->sidedef is NULL " "(subsector %s, firstline is %d)", sizeu1(i), ss->firstline)); if (seg->sidedef - sides < 0 || seg->sidedef - sides > (UINT16)numsides) - CorruptMapError(va("P_GroupLines: seg->sidedef refers to sidedef %s of %s " + CorruptMapError(va("P_LinkMapData: seg->sidedef refers to sidedef %s of %s " "(subsector %s, firstline is %d)", sizeu1(sidei), sizeu2(numsides), sizeu3(i), ss->firstline)); if (!seg->sidedef->sector) - CorruptMapError(va("P_GroupLines: seg->sidedef->sector is NULL " + CorruptMapError(va("P_LinkMapData: seg->sidedef->sector is NULL " "(subsector %s, firstline is %d, sidedef is %s)", sizeu1(i), ss->firstline, sizeu1(sidei))); ss->sector = seg->sidedef->sector; @@ -2196,7 +2874,7 @@ static void P_GroupLines(void) if (sector->linecount == 0) // no lines found? { sector->lines = NULL; - CONS_Debug(DBG_SETUP, "P_GroupLines: sector %s has no lines\n", sizeu1(i)); + CONS_Debug(DBG_SETUP, "P_LinkMapData: sector %s has no lines\n", sizeu1(i)); } else { @@ -2239,95 +2917,386 @@ static void P_GroupLines(void) } } -// -// P_LoadReject -// -// Detect if the REJECT lump is valid, -// if not, rejectmatrix will be NULL -static void P_LoadReject(lumpnum_t lumpnum) -{ - size_t count; - const char *lumpname = W_CheckNameForNum(lumpnum); - - // Check if the lump exists, and if it's named "REJECT" - if (!lumpname || memcmp(lumpname, "REJECT\0\0", 8) != 0) - { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadReject: No valid REJECT lump found\n"); - return; - } - - count = W_LumpLength(lumpnum); - - if (!count) // zero length, someone probably used ZDBSP - { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadReject: REJECT lump has size 0, will not be loaded\n"); - } - else - rejectmatrix = W_CacheLumpNum(lumpnum, PU_LEVEL); -} - -// PK3 version -// -- Monster Iestyn 09/01/18 -static void P_LoadRawReject(UINT8 *data, size_t count, const char *lumpname) -{ - // Check if the lump is named "REJECT" - if (!lumpname || memcmp(lumpname, "REJECT\0\0", 8) != 0) - { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadRawReject: No valid REJECT lump found\n"); - return; - } - - if (!count) // zero length, someone probably used ZDBSP - { - rejectmatrix = NULL; - CONS_Debug(DBG_SETUP, "P_LoadRawReject: REJECT lump has size 0, will not be loaded\n"); - } - else - { - rejectmatrix = Z_Malloc(count, PU_LEVEL, NULL); // allocate memory for the reject matrix - M_Memcpy(rejectmatrix, data, count); // copy the data into it - } -} - -#if 0 -static char *levellumps[] = -{ - "label", // ML_LABEL, A separator, name, MAPxx - "THINGS", // ML_THINGS, Enemies, items.. - "LINEDEFS", // ML_LINEDEFS, Linedefs, from editing - "SIDEDEFS", // ML_SIDEDEFS, Sidedefs, from editing - "VERTEXES", // ML_VERTEXES, Vertices, edited and BSP splits generated - "SEGS", // ML_SEGS, Linesegs, from linedefs split by BSP - "SSECTORS", // ML_SSECTORS, Subsectors, list of linesegs - "NODES", // ML_NODES, BSP nodes - "SECTORS", // ML_SECTORS, Sectors, from editing - "REJECT", // ML_REJECT, LUT, sector-sector visibility -}; - -/** Checks a lump and returns whether it is a valid start-of-level marker. +/** Hashes the sector tags across the sectors and linedefs. * - * \param lumpnum Lump number to check. - * \return True if the lump is a valid level marker, false if not. + * \sa P_FindSectorFromTag, P_ChangeSectorTag + * \author Lee Killough */ -static inline boolean P_CheckLevel(lumpnum_t lumpnum) +static inline void P_InitTagLists(void) +{ + register size_t i; + + for (i = numsectors - 1; i != (size_t)-1; i--) + { + size_t j = (unsigned)sectors[i].tag % numsectors; + sectors[i].nexttag = sectors[j].firsttag; + sectors[j].firsttag = (INT32)i; + } + + for (i = numlines - 1; i != (size_t)-1; i--) + { + size_t j = (unsigned)lines[i].tag % numlines; + lines[i].nexttag = lines[j].firsttag; + lines[j].firsttag = (INT32)i; + } +} + +//For maps in binary format, converts setup of specials to UDMF format. +static void P_ConvertBinaryMap(void) { - UINT16 file, lump; size_t i; - for (i = ML_THINGS; i <= ML_REJECT; i++) + for (i = 0; i < numlines; i++) { - file = WADFILENUM(lumpnum); - lump = LUMPNUM(lumpnum+1); - if (file > numwadfiles || lump < LUMPNUM(lumpnum) || lump > wadfiles[file]->numlumps || - memcmp(wadfiles[file]->lumpinfo[lump].name, levellumps[i], 8) != 0) - return false; + switch (lines[i].special) + { + case 20: //PolyObject first line + { + INT32 paramline = P_FindSpecialLineFromTag(22, lines[i].tag, -1); + + //PolyObject ID + lines[i].args[0] = lines[i].tag; + + //Default: Invisible planes + lines[i].args[3] |= TMPF_INVISIBLEPLANES; + + //Linedef executor tag + lines[i].args[4] = 32000 + lines[i].args[0]; + + if (paramline == -1) + break; // no extra settings to apply, let's leave it + + //Parent ID + lines[i].args[1] = lines[paramline].frontsector->special; + //Translucency + lines[i].args[2] = (lines[paramline].flags & ML_DONTPEGTOP) + ? (sides[lines[paramline].sidenum[0]].textureoffset >> FRACBITS) + : ((lines[paramline].frontsector->floorheight >> FRACBITS) / 100); + + //Flags + if (lines[paramline].flags & ML_EFFECT1) + lines[i].args[3] |= TMPF_NOINSIDES; + if (lines[paramline].flags & ML_EFFECT2) + lines[i].args[3] |= TMPF_INTANGIBLE; + if (lines[paramline].flags & ML_EFFECT3) + lines[i].args[3] |= TMPF_PUSHABLESTOP; + if (lines[paramline].flags & ML_EFFECT4) + lines[i].args[3] &= ~TMPF_INVISIBLEPLANES; + /*if (lines[paramline].flags & ML_EFFECT5) + lines[i].args[3] |= TMPF_DONTCLIPPLANES;*/ + if (lines[paramline].flags & ML_EFFECT6) + lines[i].args[3] |= TMPF_SPLAT; + if (lines[paramline].flags & ML_NOCLIMB) + lines[i].args[3] |= TMPF_EXECUTOR; + + break; + } + case 443: //Call Lua function + if (lines[i].text) + { + lines[i].stringargs[0] = Z_Malloc(strlen(lines[i].text) + 1, PU_LEVEL, NULL); + M_Memcpy(lines[i].stringargs[0], lines[i].text, strlen(lines[i].text) + 1); + } + else + CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(i)); + break; + case 447: //Change colormap + lines[i].args[0] = lines[i].tag; + if (lines[i].flags & ML_EFFECT3) + lines[i].args[2] |= TMCF_RELATIVE; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[2] |= TMCF_SUBLIGHTR|TMCF_SUBFADER; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[2] |= TMCF_SUBLIGHTG|TMCF_SUBFADEG; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[2] |= TMCF_SUBLIGHTB|TMCF_SUBFADEB; + break; + case 455: //Fade colormap + { + INT32 speed = (INT32)((((lines[i].flags & ML_DONTPEGBOTTOM) || !sides[lines[i].sidenum[0]].rowoffset) && lines[i].sidenum[1] != 0xFFFF) ? + abs(sides[lines[i].sidenum[1]].rowoffset >> FRACBITS) + : abs(sides[lines[i].sidenum[0]].rowoffset >> FRACBITS)); + + lines[i].args[0] = lines[i].tag; + if (lines[i].flags & ML_EFFECT4) + lines[i].args[2] = speed; + else + lines[i].args[2] = (256 + speed - 1)/speed; + if (lines[i].flags & ML_EFFECT3) + lines[i].args[3] |= TMCF_RELATIVE; + if (lines[i].flags & ML_EFFECT1) + lines[i].args[3] |= TMCF_SUBLIGHTR|TMCF_SUBFADER; + if (lines[i].flags & ML_NOCLIMB) + lines[i].args[3] |= TMCF_SUBLIGHTG|TMCF_SUBFADEG; + if (lines[i].flags & ML_EFFECT2) + lines[i].args[3] |= TMCF_SUBLIGHTB|TMCF_SUBFADEB; + if (lines[i].flags & ML_NOTBOUNCY) + lines[i].args[3] |= TMCF_FROMBLACK; + if (lines[i].flags & ML_EFFECT5) + lines[i].args[3] |= TMCF_OVERRIDE; + break; + } + case 456: //Stop fading colormap + lines[i].args[0] = lines[i].tag; + break; + case 606: //Colormap + lines[i].args[0] = lines[i].tag; + break; + case 700: //Slope front sector floor + case 701: //Slope front sector ceiling + case 702: //Slope front sector floor and ceiling + case 703: //Slope front sector floor and back sector ceiling + case 710: //Slope back sector floor + case 711: //Slope back sector ceiling + case 712: //Slope back sector floor and ceiling + case 713: //Slope back sector floor and front sector ceiling + { + boolean frontfloor = (lines[i].special == 700 || lines[i].special == 702 || lines[i].special == 703); + boolean backfloor = (lines[i].special == 710 || lines[i].special == 712 || lines[i].special == 713); + boolean frontceil = (lines[i].special == 701 || lines[i].special == 702 || lines[i].special == 713); + boolean backceil = (lines[i].special == 711 || lines[i].special == 712 || lines[i].special == 703); + + lines[i].args[0] = backfloor ? TMS_BACK : (frontfloor ? TMS_FRONT : TMS_NONE); + lines[i].args[1] = backceil ? TMS_BACK : (frontceil ? TMS_FRONT : TMS_NONE); + + if (lines[i].flags & ML_NETONLY) + lines[i].args[2] |= TMSL_NOPHYSICS; + if (lines[i].flags & ML_NONET) + lines[i].args[2] |= TMSL_DYNAMIC; + + lines[i].special = 700; + break; + } + case 704: //Slope front sector floor by 3 tagged vertices + case 705: //Slope front sector ceiling by 3 tagged vertices + case 714: //Slope back sector floor by 3 tagged vertices + case 715: //Slope back sector ceiling by 3 tagged vertices + { + if (lines[i].special == 704) + lines[i].args[0] = TMSP_FRONTFLOOR; + else if (lines[i].special == 705) + lines[i].args[0] = TMSP_FRONTCEILING; + else if (lines[i].special == 714) + lines[i].args[0] = TMSP_BACKFLOOR; + else if (lines[i].special == 715) + lines[i].args[0] = TMSP_BACKCEILING; + + lines[i].args[1] = lines[i].tag; + + if (lines[i].flags & ML_EFFECT6) + { + UINT8 side = lines[i].special >= 714; + + if (side == 1 && lines[i].sidenum[1] == 0xffff) + CONS_Debug(DBG_GAMELOGIC, "P_ConvertBinaryMap: Line special %d (line #%s) missing 2nd side!\n", lines[i].special, sizeu1(i)); + else + { + lines[i].args[2] = sides[lines[i].sidenum[side]].textureoffset >> FRACBITS; + lines[i].args[3] = sides[lines[i].sidenum[side]].rowoffset >> FRACBITS; + } + } + else + { + lines[i].args[2] = lines[i].args[1]; + lines[i].args[3] = lines[i].args[1]; + } + + if (lines[i].flags & ML_NETONLY) + lines[i].args[4] |= TMSL_NOPHYSICS; + if (lines[i].flags & ML_NONET) + lines[i].args[4] |= TMSL_DYNAMIC; + + lines[i].special = 704; + break; + } + case 720: //Copy front side floor slope + case 721: //Copy front side ceiling slope + case 722: //Copy front side floor and ceiling slope + if (lines[i].special != 721) + lines[i].args[0] = lines[i].tag; + if (lines[i].special != 720) + lines[i].args[1] = lines[i].tag; + lines[i].special = 720; + break; + case 900: //Translucent wall (10%) + case 901: //Translucent wall (20%) + case 902: //Translucent wall (30%) + case 903: //Translucent wall (40%) + case 904: //Translucent wall (50%) + case 905: //Translucent wall (60%) + case 906: //Translucent wall (70%) + case 907: //Translucent wall (80%) + case 908: //Translucent wall (90%) + lines[i].alpha = ((909 - lines[i].special) << FRACBITS)/10; + break; + default: + break; + } + + //Linedef executor delay + if (lines[i].special >= 400 && lines[i].special < 500) + { + //Dummy value to indicate that this executor is delayed. + //The real value is taken from the back sector at runtime. + if (lines[i].flags & ML_DONTPEGTOP) + lines[i].executordelay = 1; + } + } + + for (i = 0; i < nummapthings; i++) + { + switch (mapthings[i].type) + { + case 750: + case 760: + case 761: + mapthings[i].tag = mapthings[i].angle; + break; + case 762: + { + INT32 firstline = P_FindSpecialLineFromTag(20, mapthings[i].angle, -1); + if (firstline != -1) + lines[firstline].args[3] |= TMPF_CRUSH; + mapthings[i].tag = mapthings[i].angle; + mapthings[i].type = 761; + break; + } + case 780: + mapthings[i].tag = mapthings[i].extrainfo; + break; + case 2001: // MT_WAYPOINT + { + INT32 firstline = P_FindSpecialLineFromTag(2000, mapthings[i].angle, -1); + + mapthings[i].tag = mapthings[i].angle; + mapthings[i].args[0] = mapthings[i].z; + mapthings[i].args[2] = mapthings[i].extrainfo; + mapthings[i].z = 0; + + if (firstline != -1) + { + fixed_t lineradius = sides[lines[firstline].sidenum[0]].textureoffset; + fixed_t linez = sides[lines[firstline].sidenum[0]].rowoffset; + + if (lineradius > 0) + mapthings[i].args[1] = lineradius / FRACUNIT; + + mapthings[i].z = linez / FRACUNIT; + } + break; + } + case 2004: // MT_BOTHINT + mapthings[i].args[0] = mapthings[i].angle; + mapthings[i].args[1] = mapthings[i].extrainfo; + break; + case 2333: // MT_BATTLECAPSULE + mapthings[i].args[0] = mapthings[i].extrainfo; + mapthings[i].args[1] = mapthings[i].angle; + break; + default: + break; + } } - return true; // all right } + +/** Compute MD5 message digest for bytes read from memory source + * + * The resulting message digest number will be written into the 16 bytes + * beginning at RESBLOCK. + * + * \param filename path of file + * \param resblock resulting MD5 checksum + * \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found + */ +static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock) +{ +#ifdef NOMD5 + (void)buffer; + (void)len; + memset(resblock, 0x00, 16); + return 1; +#else + tic_t t = I_GetTime(); + CONS_Debug(DBG_SETUP, "Making MD5\n"); + if (md5_buffer(buffer, len, resblock) == NULL) + return 1; + CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE); + return 0; #endif +} + +static void P_MakeMapMD5(virtres_t *virt, void *dest) +{ + unsigned char resmd5[16]; + + if (udmf) + { + virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); + P_MakeBufferMD5((char*)textmap->data, textmap->size, resmd5); + } + else + { + unsigned char linemd5[16]; + unsigned char sectormd5[16]; + unsigned char thingmd5[16]; + unsigned char sidedefmd5[16]; + UINT8 i; + + // Create a hash for the current map + // get the actual lumps! + virtlump_t* virtlines = vres_Find(virt, "LINEDEFS"); + virtlump_t* virtsectors = vres_Find(virt, "SECTORS"); + virtlump_t* virtmthings = vres_Find(virt, "THINGS"); + virtlump_t* virtsides = vres_Find(virt, "SIDEDEFS"); + + P_MakeBufferMD5((char*)virtlines->data, virtlines->size, linemd5); + P_MakeBufferMD5((char*)virtsectors->data, virtsectors->size, sectormd5); + P_MakeBufferMD5((char*)virtmthings->data, virtmthings->size, thingmd5); + P_MakeBufferMD5((char*)virtsides->data, virtsides->size, sidedefmd5); + + for (i = 0; i < 16; i++) + resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF; + } + + M_Memcpy(dest, &resmd5, 16); +} + +static boolean P_LoadMapFromFile(void) +{ + virtres_t *virt = vres_GetMap(lastloadedmaplumpnum); + virtlump_t *textmap = vres_Find(virt, "TEXTMAP"); + udmf = textmap != NULL; + + if (!P_LoadMapData(virt)) + return false; + P_LoadMapBSP(virt); + P_LoadMapLUT(virt); + + P_LinkMapData(); + + P_InitTagLists(); // Create xref tables for tags + + if (!udmf) + P_ConvertBinaryMap(); + + // Copy relevant map data for NetArchive purposes. + spawnsectors = Z_Calloc(numsectors * sizeof(*sectors), PU_LEVEL, NULL); + spawnlines = Z_Calloc(numlines * sizeof(*lines), PU_LEVEL, NULL); + spawnsides = Z_Calloc(numsides * sizeof(*sides), PU_LEVEL, NULL); + + memcpy(spawnsectors, sectors, numsectors * sizeof(*sectors)); + memcpy(spawnlines, lines, numlines * sizeof(*lines)); + memcpy(spawnsides, sides, numsides * sizeof(*sides)); + + P_MakeMapMD5(virt, &mapmd5); + + vres_Free(virt); + return true; +} + +// +// LEVEL INITIALIZATION FUNCTIONS +// /** Sets up a sky texture to use for the level. * The sky texture is used instead of F_SKY1. @@ -2361,7 +3330,7 @@ lumpnum_t lastloadedmaplumpnum; // for comparative savegame // // Some player initialization for map start. // -static void P_LevelInitStuff(void) +static void P_InitLevelSettings(void) { INT32 i; UINT8 p = 0; @@ -2369,10 +3338,13 @@ static void P_LevelInitStuff(void) leveltime = 0; memset(localaiming, 0, sizeof(localaiming)); + modulothing = 0; // special stage tokens, emeralds, and ring total tokenbits = 0; runemeraldmanager = false; + emeraldspawndelay = 60*TICRATE; + nummaprings = 0; nummapboxes = numgotboxes = 0; maptargets = numtargets = 0; @@ -2383,7 +3355,9 @@ static void P_LevelInitStuff(void) // map time limit if (mapheaderinfo[gamemap-1]->countdown) + { countdowntimer = mapheaderinfo[gamemap-1]->countdown * TICRATE; + } else countdowntimer = 0; countdowntimeup = false; @@ -2395,10 +3369,10 @@ static void P_LevelInitStuff(void) // circuit, race and competition stuff circuitmap = false; numstarposts = 0; - totalrings = timeinmap = 0; + ssspheres = timeinmap = 0; // special stage - stagefailed = false; + stagefailed = true; // assume failed unless proven otherwise - P_GiveEmerald or emerald touchspecial // Reset temporary record data //memset(&ntemprecords, 0, sizeof(nightsdata_t)); @@ -2428,36 +3402,25 @@ static void P_LevelInitStuff(void) players[i].gotcontinue = false; players[i].deadtimer = players[i].numboxes = players[i].laps = 0; - players[i].health = 1; players[i].aiming = 0; - players[i].pflags &= ~PF_TIMEOVER; + players[i].pflags &= ~PF_GAMETYPEOVER; + } - players[i].losstime = 0; - players[i].timeshit = 0; + racecountdown = exitcountdown = exitfadestarted = 0; - players[i].marescore = players[i].lastmarescore = players[i].maxlink = 0; - players[i].startedtime = players[i].finishedtime = players[i].finishedrings = 0; - players[i].lastmare = players[i].marebegunat = 0; + for (i = 0; i < MAXPLAYERS; i++) + { + G_PlayerReborn(i, true); - // Don't show anything - players[i].textvar = players[i].texttimer = 0; + // obliteration station... + players[i].numboxes = players[i].totalring =\ + players[i].laps = players[i].marescore = players[i].lastmarescore =\ + players[i].mare = players[i].exiting = 0; - players[i].linkcount = players[i].linktimer = 0; - players[i].flyangle = players[i].anotherflyangle = 0; - players[i].nightstime = players[i].mare = 0; - P_SetTarget(&players[i].capsule, NULL); players[i].drillmeter = 40*20; - players[i].exiting = 0; - P_ResetPlayer(&players[i]); - - players[i].mo = NULL; - - // we must unset axis details too - players[i].axis1 = players[i].axis2 = NULL; - - // and this stupid flag as a result - players[i].pflags &= ~PF_TRANSFERTOCLOSEST; + // hit these too + players[i].pflags &= ~(PF_GAMETYPEOVER); // Wipe follower from existence to avoid crashes players[i].follower = NULL; @@ -2489,7 +3452,7 @@ static void P_LevelInitStuff(void) // SRB2Kart: map load variables if (grandprixinfo.gp == true) { - if (G_BattleGametype()) + if (gametype == GT_BATTLE) { gamespeed = KARTSPEED_EASY; } @@ -2510,7 +3473,7 @@ static void P_LevelInitStuff(void) } else { - if (G_BattleGametype()) + if ((gametyperules & GTR_BUMPERS)) gamespeed = KARTSPEED_EASY; else { @@ -2530,101 +3493,37 @@ static void P_LevelInitStuff(void) speedscramble = encorescramble = -1; } -// -// P_LoadThingsOnly -// -// "Reloads" a level, but only reloads all of the mobjs. -// -void P_LoadThingsOnly(void) +// Respawns all the mapthings and mobjs in the map from the already loaded map data. +void P_RespawnThings(void) { // Search through all the thinkers. - mobj_t *mo; thinker_t *think; + INT32 i, viewid = -1, centerid = -1; // for skyboxes - for (think = thinkercap.next; think != &thinkercap; think = think->next) + // check if these are any of the normal viewpoint/centerpoint mobjs in the level or not + if (skyboxmo[0] || skyboxmo[1]) + for (i = 0; i < 16; i++) + { + if (skyboxmo[0] && skyboxmo[0] == skyboxviewpnts[i]) + viewid = i; // save id just in case + if (skyboxmo[1] && skyboxmo[1] == skyboxcenterpnts[i]) + centerid = i; // save id just in case + } + + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - - mo = (mobj_t *)think; - - if (mo) - P_RemoveMobj(mo); + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + P_RemoveMobj((mobj_t *)think); } - P_LevelInitStuff(); + P_InitLevelSettings(); - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can use the things lump - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - fileinfo += ML_THINGS; // we only need the THINGS lump - P_PrepareRawThings(wadData + fileinfo->filepos, fileinfo->size); - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD - P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); - P_LoadThings(); + P_SpawnMapThings(true); - P_SpawnSecretItems(true); -} - -/** Compute MD5 message digest for bytes read from memory source - * - * The resulting message digest number will be written into the 16 bytes - * beginning at RESBLOCK. - * - * \param filename path of file - * \param resblock resulting MD5 checksum - * \return 0 if MD5 checksum was made, and is at resblock, 1 if error was found - */ -static INT32 P_MakeBufferMD5(const char *buffer, size_t len, void *resblock) -{ -#ifdef NOMD5 - (void)buffer; - (void)len; - memset(resblock, 0x00, 16); - return 1; -#else - tic_t t = I_GetTime(); - CONS_Debug(DBG_SETUP, "Making MD5\n"); - if (md5_buffer(buffer, len, resblock) == NULL) - return 1; - CONS_Debug(DBG_SETUP, "MD5 calc took %f seconds\n", (float)(I_GetTime() - t)/NEWTICRATE); - return 0; -#endif -} - -static void P_MakeMapMD5(lumpnum_t maplumpnum, void *dest) -{ - unsigned char linemd5[16]; - unsigned char sectormd5[16]; - unsigned char thingmd5[16]; - unsigned char sidedefmd5[16]; - unsigned char resmd5[16]; - UINT8 i; - - // Create a hash for the current map - // get the actual lumps! - UINT8 *datalines = W_CacheLumpNum(maplumpnum + ML_LINEDEFS, PU_CACHE); - UINT8 *datasectors = W_CacheLumpNum(maplumpnum + ML_SECTORS, PU_CACHE); - UINT8 *datathings = W_CacheLumpNum(maplumpnum + ML_THINGS, PU_CACHE); - UINT8 *datasides = W_CacheLumpNum(maplumpnum + ML_SIDEDEFS, PU_CACHE); - - P_MakeBufferMD5((char*)datalines, W_LumpLength(maplumpnum + ML_LINEDEFS), linemd5); - P_MakeBufferMD5((char*)datasectors, W_LumpLength(maplumpnum + ML_SECTORS), sectormd5); - P_MakeBufferMD5((char*)datathings, W_LumpLength(maplumpnum + ML_THINGS), thingmd5); - P_MakeBufferMD5((char*)datasides, W_LumpLength(maplumpnum + ML_SIDEDEFS), sidedefmd5); - - Z_Free(datalines); - Z_Free(datasectors); - Z_Free(datathings); - Z_Free(datasides); - - for (i = 0; i < 16; i++) - resmd5[i] = (linemd5[i] + sectormd5[i] + thingmd5[i] + sidedefmd5[i]) & 0xFF; - - M_Memcpy(dest, &resmd5, 16); + // restore skybox viewpoint/centerpoint if necessary, set them to defaults if we can't do that + skyboxmo[0] = skyboxviewpnts[(viewid >= 0) ? viewid : 0]; + skyboxmo[1] = skyboxcenterpnts[(centerid >= 0) ? centerid : 0]; } static void P_RunLevelScript(const char *scriptname) @@ -2657,64 +3556,61 @@ static void P_RunLevelScript(const char *scriptname) static void P_ForceCharacter(const char *forcecharskin) { + UINT8 i; + if (netgame) { char skincmd[33]; - if (splitscreen) + + for (i = 0; i <= splitscreen; i++) { - sprintf(skincmd, "skin2 %s\n", forcecharskin); - CV_Set(&cv_skin2, forcecharskin); - if (splitscreen > 1) - { - sprintf(skincmd, "skin3 %s\n", forcecharskin); - CV_Set(&cv_skin3, forcecharskin); - if (splitscreen > 2) - { - sprintf(skincmd, "skin4 %s\n", forcecharskin); - CV_Set(&cv_skin4, forcecharskin); - } - } + const char *num = ""; + + if (i > 0) + num = va("%d", i+1); + + sprintf(skincmd, "skin%s %s\n", num, forcecharskin); + CV_Set(&cv_skin[i], forcecharskin); } - sprintf(skincmd, "skin %s\n", forcecharskin); COM_BufAddText(skincmd); } else { - if (splitscreen) + for (i = 0; i <= splitscreen; i++) { - SetPlayerSkin(g_localplayers[1], forcecharskin); - if ((unsigned)cv_playercolor2.value != skins[players[g_localplayers[1]].skin].prefcolor && !modeattacking) - { - CV_StealthSetValue(&cv_playercolor2, skins[players[g_localplayers[1]].skin].prefcolor); - players[g_localplayers[1]].skincolor = skins[players[g_localplayers[1]].skin].prefcolor; - } + SetPlayerSkin(g_localplayers[i], forcecharskin); - if (splitscreen > 1) + // normal player colors in single player + if ((unsigned)cv_playercolor[i].value != skins[players[g_localplayers[i]].skin].prefcolor && !modeattacking) { - SetPlayerSkin(g_localplayers[2], forcecharskin); - if ((unsigned)cv_playercolor3.value != skins[players[g_localplayers[2]].skin].prefcolor && !modeattacking) - { - CV_StealthSetValue(&cv_playercolor3, skins[players[g_localplayers[2]].skin].prefcolor); - players[g_localplayers[2]].skincolor = skins[players[g_localplayers[2]].skin].prefcolor; - } - - if (splitscreen > 2) - { - SetPlayerSkin(g_localplayers[3], forcecharskin); - if ((unsigned)cv_playercolor4.value != skins[players[g_localplayers[3]].skin].prefcolor && !modeattacking) - { - CV_StealthSetValue(&cv_playercolor4, skins[players[g_localplayers[3]].skin].prefcolor); - players[g_localplayers[3]].skincolor = skins[players[g_localplayers[3]].skin].prefcolor; - } - } + CV_StealthSetValue(&cv_playercolor[i], skins[players[g_localplayers[i]].skin].prefcolor); + players[g_localplayers[i]].skincolor = skins[players[g_localplayers[i]].skin].prefcolor; } } - - SetPlayerSkin(consoleplayer, forcecharskin); } } +static void P_ResetSpawnpoints(void) +{ + UINT8 i; + + numdmstarts = numredctfstarts = numbluectfstarts = 0; + + // reset the player starts + for (i = 0; i < MAXPLAYERS; i++) + playerstarts[i] = bluectfstarts[i] = redctfstarts[i] = NULL; + + for (i = 0; i < MAX_DM_STARTS; i++) + deathmatchstarts[i] = NULL; + + for (i = 0; i < 2; i++) + skyboxmo[i] = NULL; + + for (i = 0; i < 16; i++) + skyboxviewpnts[i] = skyboxcenterpnts[i] = NULL; +} + static void P_LoadRecordGhosts(void) { // see also m_menu.c's Nextmap_OnChange @@ -2788,47 +3684,6 @@ static void P_LoadRecordGhosts(void) free(gpath); } -/*static void P_LoadNightsGhosts(void) -{ - const size_t glen = strlen(srb2home)+1+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; - char *gpath = malloc(glen); - - if (!gpath) - return; - - sprintf(gpath,"%s"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - - // Best Score ghost - if (cv_ghost_bestscore.value && FIL_FileExists(va("%s-score-best.lmp", gpath))) - G_AddGhost(va("%s-score-best.lmp", gpath)); - - // Best Time ghost - if (cv_ghost_besttime.value && FIL_FileExists(va("%s-time-best.lmp", gpath))) - G_AddGhost(va("%s-time-best.lmp", gpath)); - - // Last ghost - if (cv_ghost_last.value && FIL_FileExists(va("%s-last.lmp", gpath))) - G_AddGhost(va("%s-last.lmp", gpath)); - - // Guest ghost - if (cv_ghost_guest.value && FIL_FileExists(va("%s-guest.lmp", gpath))) - G_AddGhost(va("%s-guest.lmp", gpath)); - - // Staff Attack ghosts - if (cv_ghost_staff.value) - { - lumpnum_t l; - UINT8 i = 1; - while (i <= 99 && (l = W_CheckNumForName(va("%sS%02u",G_BuildMapName(gamemap),i))) != LUMPERROR) - { - G_AddGhost(va("%sS%02u",G_BuildMapName(gamemap),i)); - i++; - } - } - - free(gpath); -}*/ - static void P_SetupCamera(UINT8 pnum, camera_t *cam) { if (players[pnum].mo && (server || addedtogame)) @@ -2843,80 +3698,119 @@ static void P_SetupCamera(UINT8 pnum, camera_t *cam) { mapthing_t *thing; - switch (gametype) - { - case GT_MATCH: - case GT_TAG: + if (gametyperules & GTR_BATTLESTARTS) thing = deathmatchstarts[0]; - break; - - default: + else thing = playerstarts[0]; - break; + + if (thing) + { + cam->x = thing->x; + cam->y = thing->y; + cam->z = thing->z; + cam->angle = FixedAngle((fixed_t)thing->angle << FRACBITS); + cam->subsector = R_PointInSubsector(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18) } - - if (!thing) - return; // we can't do jack shit - - cam->x = thing->x; - cam->y = thing->y; - cam->z = thing->z; - cam->angle = FixedAngle((fixed_t)thing->angle << FRACBITS); - cam->subsector = R_PointInSubsector(cam->x, cam->y); // make sure camera has a subsector set -- Monster Iestyn (12/11/18) } } -static boolean P_CanSave(void) +static void P_InitCamera(void) { -#if 0 - // Saving is completely ignored under these conditions: - if ((cursaveslot < 0) // Playing without saving - || (modifiedgame && !savemoddata) // Game is modified - || (netgame || multiplayer) // Not in single-player - || (demo.playback || demo.recording || metalrecording) // Currently in demo - || (players[consoleplayer].lives <= 0) // Completely dead - || (modeattacking || ultimatemode || G_IsSpecialStage(gamemap))) // Specialized instances - return false; + if (!dedicated) + { + UINT8 i; - if (mapheaderinfo[gamemap-1]->saveoverride == SAVE_ALWAYS) - return true; // Saving should ALWAYS happen! - else if (mapheaderinfo[gamemap-1]->saveoverride == SAVE_NEVER) - return false; // Saving should NEVER happen! + for (i = 0; i <= splitscreen; i++) + { + P_SetupCamera(i, &camera[i]); + displayplayers[i] = g_localplayers[i]; // Start with your OWN view, please! + } + } +} - // Default condition: In a non-hidden map, at the beginning of a zone or on a completed save-file, and not on save reload. - return (!(mapheaderinfo[gamemap-1]->menuflags & LF2_HIDEINMENU) - && (mapheaderinfo[gamemap-1]->actnum < 2 || gamecomplete) - && (gamemap != lastmapsaved)); -#else - return false; // SRB2Kart: no SP, no saving. -#endif +static void P_InitPlayers(void) +{ + UINT8 i; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + + players[i].mo = NULL; + + if (!(gametyperules & GTR_CIRCUIT)) + { + G_DoReborn(i); + } + else // gametype is race + { + G_SpawnPlayer(i); + } + } +} + +static void P_InitGametype(void) +{ + P_InitPlayers(); + + if (modeattacking && !demo.playback) + P_LoadRecordGhosts(); + + if ((gametyperules & GTR_CIRCUIT) && server) + { + if ((netgame || multiplayer) && cv_basenumlaps.value + && (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) + || (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))) + { + CV_StealthSetValue(&cv_numlaps, cv_basenumlaps.value); + } + else + { + CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps); + } + } + + // Start recording replay in multiplayer with a temp filename + //@TODO I'd like to fix dedis crashing when recording replays for the future too... + if (!demo.playback && multiplayer && !dedicated) + { + static char buf[256]; + char *path; + sprintf(buf, "media"PATHSEP"replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap)); + + path = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online", srb2home); + M_MkdirEach(path, M_PathParts(path) - 4, 0755); + + G_RecordDemo(buf); + } } /** Loads a level from a lump or external wad. * - * \param skipprecip If true, don't spawn precipitation. + * \param fromnetsave If true, skip some stuff because we're loading a netgame snapshot. * \todo Clean up, refactor, split up; get rid of the bloat. */ -boolean P_SetupLevel(boolean skipprecip) +boolean P_LoadLevel(boolean fromnetsave) { // use gamemap to get map number. // 99% of the things already did, so. // Map header should always be in place at this point - INT32 i, loadprecip = 1; - INT32 loademblems = 1; - INT32 fromnetsave = 0; - boolean loadedbm = false; + INT32 i, ranspecialwipe = 0; sector_t *ss; - boolean chase; - levelloading = true; // This is needed. Don't touch. maptol = mapheaderinfo[gamemap-1]->typeoflevel; + gametyperules = gametypedefaultrules[gametype]; CON_Drawer(); // let the user know what we are going to do I_FinishUpdate(); // page flip or blit buffer + // Reset the palette + if (rendermode != render_none) + V_SetPaletteLump("PLAYPAL"); + // Initialize sector node list. P_Initsecnode(); @@ -2935,7 +3829,7 @@ boolean P_SetupLevel(boolean skipprecip) if (cv_runscripts.value && mapheaderinfo[gamemap-1]->scriptname[0] != '#') P_RunLevelScript(mapheaderinfo[gamemap-1]->scriptname); - P_LevelInitStuff(); + P_InitLevelSettings(); for (i = 0; i <= r_splitscreen; i++) postimgtype[i] = postimg_none; @@ -2943,30 +3837,6 @@ boolean P_SetupLevel(boolean skipprecip) if (mapheaderinfo[gamemap-1]->forcecharacter[0] != '\0') P_ForceCharacter(mapheaderinfo[gamemap-1]->forcecharacter); - // chasecam on in chaos, race, coop - // chasecam off in match, tag, capture the flag - chase = true; // srb2kart: always on - - if (!dedicated) - { - // Salt: CV_ClearChangedFlags() messes with your settings :( - /*if (!cv_cam_speed.changed) - CV_Set(&cv_cam_speed, cv_cam_speed.defaultvalue);*/ - - if (!cv_chasecam.changed) - CV_SetValue(&cv_chasecam, chase); - - // same for second player - if (!cv_chasecam2.changed) - CV_SetValue(&cv_chasecam2, chase); - - if (!cv_chasecam3.changed) - CV_SetValue(&cv_chasecam3, chase); - - if (!cv_chasecam4.changed) - CV_SetValue(&cv_chasecam4, chase); - } - // Initial height of PointOfView // will be set by player think. players[consoleplayer].viewz = 1; @@ -2987,6 +3857,7 @@ boolean P_SetupLevel(boolean skipprecip) V_EncoreInvertScreen(); F_WipeEndScreen(); + S_StartSound(NULL, sfx_ruby1); F_RunWipe(wipedefs[wipe_encore_toinvert], false, NULL, false, false); // Hold on invert for extra effect. @@ -3034,13 +3905,52 @@ boolean P_SetupLevel(boolean skipprecip) } } + // Special stage & record attack retry fade to white + // This is handled BEFORE sounds are stopped. + if (G_GetModeAttackRetryFlag()) + { + if (modeattacking && !demo.playback) + { + ranspecialwipe = 2; + //wipestyleflags |= (WSF_FADEOUT|WSF_TOWHITE); + } + G_ClearModeAttackRetryFlag(); + } + /* + else if (rendermode != render_none && G_IsSpecialStage(gamemap)) + { + P_RunSpecialStageWipe(); + ranspecialwipe = 1; + } + */ + // Make sure all sounds are stopped before Z_FreeTags. S_StopSounds(); S_ClearSfx(); - // As oddly named as this is, this handles music only. - // We should be fine starting it here. - S_Start(); + // Fade out music here. Deduct 2 tics so the fade volume actually reaches 0. + // But don't halt the music! S_Start will take care of that. This dodges a MIDI crash bug. + if (!titlemapinaction) + S_FadeMusic(0, FixedMul( + FixedDiv((F_GetWipeLength(wipedefs[wipe_level_toblack])-2)*NEWTICRATERATIO, NEWTICRATE), MUSICRATE)); + + // Reset the palette now all fades have been done + if (rendermode != render_none) + V_SetPaletteLump(GetPalette()); // Set the level palette + + if (!titlemapinaction) + { + if (ranspecialwipe == 2) + { + pausedelay = -3; // preticker plus one + S_StartSound(NULL, sfx_s3k73); + } + + // As oddly named as this is, this handles music only. + // We should be fine starting it here. + // Don't do this during titlemap, because the menu code handles music by itself. + S_Start(); + } levelfadecol = (encoremode ? 0 : 31); @@ -3058,29 +3968,13 @@ boolean P_SetupLevel(boolean skipprecip) F_RunWipe(wipedefs[wipe_level_toblack], false, ((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), false, false); } + if (!titlemapinaction) + wipegamestate = GS_LEVEL; - // Reset the palette now all fades have been done - if (rendermode != render_none) - V_SetPaletteLump(GetPalette()); // Set the level palette + // Close text prompt before freeing the old level + F_EndTextPrompt(false, true); - // Print "SPEEDING OFF TO [ZONE] [ACT 1]..." - /*if (rendermode != render_none) - { - // Don't include these in the fade! - char tx[64]; - V_DrawSmallString(1, 191, V_ALLOWLOWERCASE, M_GetText("Speeding off to...")); - snprintf(tx, 63, "%s%s%s", - mapheaderinfo[gamemap-1]->lvlttl, - (strlen(mapheaderinfo[gamemap-1]->zonttl) > 0) ? va(" %s",mapheaderinfo[gamemap-1]->zonttl) : // SRB2kart - ((mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE) ? "" : " ZONE"), - (strlen(mapheaderinfo[gamemap-1]->actnum) > 0) ? va(", Act %s",mapheaderinfo[gamemap-1]->actnum) : ""); - V_DrawSmallString(1, 195, V_ALLOWLOWERCASE, tx); - I_UpdateNoVsync(); - }*/ - -#ifdef HAVE_BLUA LUA_InvalidateLevel(); -#endif for (ss = sectors; sectors+numsectors != ss; ss++) { @@ -3101,20 +3995,20 @@ boolean P_SetupLevel(boolean skipprecip) P_InitThinkers(); P_InitCachedActions(); - /// \note for not spawning precipitation, etc. when loading netgame snapshots - if (skipprecip) + if (!fromnetsave && savedata.lives > 0) { - fromnetsave = 1; - loadprecip = 0; - loademblems = 0; + numgameovers = savedata.numgameovers; + players[consoleplayer].continues = savedata.continues; + players[consoleplayer].lives = savedata.lives; + players[consoleplayer].score = savedata.score; + emeralds = savedata.emeralds; + savedata.lives = 0; } // internal game map maplumpname = G_BuildMapName(gamemap); - //lastloadedmaplumpnum = LUMPERROR; lastloadedmaplumpnum = W_CheckNumForName(maplumpname); - - if (lastloadedmaplumpnum == INT16_MAX) + if (lastloadedmaplumpnum == LUMPERROR) I_Error("Map %s not found.\n", maplumpname); R_ReInitColormaps(mapheaderinfo[gamemap-1]->palette, @@ -3124,138 +4018,65 @@ boolean P_SetupLevel(boolean skipprecip) // SRB2 determines the sky texture to be used depending on the map header. P_SetupLevelSky(mapheaderinfo[gamemap-1]->skytexture, true); - P_MakeMapMD5(lastloadedmaplumpnum, &mapmd5); + P_ResetSpawnpoints(); - // HACK ALERT: Cache the WAD, get the map data into the tables, free memory. - // As it is implemented right now, we're assuming an uncompressed WAD. - // (As in, a normal PWAD, not ZWAD or anything. The lump itself can be compressed.) - // We're not accounting for extra lumps and scrambled lump positions. Any additional data will cause an error. - if (W_IsLumpWad(lastloadedmaplumpnum)) - { - // Remember that we're assuming that the WAD will have a specific set of lumps in a specific order. - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - //filelump_t *fileinfo = wadData + ((wadinfo_t *)wadData)->infotableofs; - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - UINT32 numlumps = ((wadinfo_t *)wadData)->numlumps; + P_ResetTubeWaypoints(); - if (numlumps < ML_REJECT) // at least 9 lumps should be in the wad for a map to be loaded - { - I_Error("Bad WAD file for map %s!\n", maplumpname); - } + P_MapStart(); - if (numlumps > ML_BLOCKMAP) // enough room for a BLOCKMAP lump at least - { - loadedbm = P_LoadRawBlockMap( - wadData + (fileinfo + ML_BLOCKMAP)->filepos, - (fileinfo + ML_BLOCKMAP)->size, - (fileinfo + ML_BLOCKMAP)->name); - } - P_LoadRawVertexes(wadData + (fileinfo + ML_VERTEXES)->filepos, (fileinfo + ML_VERTEXES)->size); - P_LoadRawSectors(wadData + (fileinfo + ML_SECTORS)->filepos, (fileinfo + ML_SECTORS)->size); - P_LoadRawSideDefs((fileinfo + ML_SIDEDEFS)->size); - P_LoadRawLineDefs(wadData + (fileinfo + ML_LINEDEFS)->filepos, (fileinfo + ML_LINEDEFS)->size); - P_LoadRawSideDefs2(wadData + (fileinfo + ML_SIDEDEFS)->filepos); - P_LoadRawSubsectors(wadData + (fileinfo + ML_SSECTORS)->filepos, (fileinfo + ML_SSECTORS)->size); - P_LoadRawNodes(wadData + (fileinfo + ML_NODES)->filepos, (fileinfo + ML_NODES)->size); - P_LoadRawSegs(wadData + (fileinfo + ML_SEGS)->filepos, (fileinfo + ML_SEGS)->size); - if (numlumps > ML_REJECT) // enough room for a REJECT lump at least - { - P_LoadRawReject( - wadData + (fileinfo + ML_REJECT)->filepos, - (fileinfo + ML_REJECT)->size, - (fileinfo + ML_REJECT)->name); - } - - // Important: take care of the ordering of the next functions. - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 - P_LoadLineDefs2(); - P_GroupLines(); - numdmstarts = numredctfstarts = numbluectfstarts = 0; - - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = NULL; - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; - P_MapStart(); - - P_PrepareRawThings(wadData + (fileinfo + ML_THINGS)->filepos, (fileinfo + ML_THINGS)->size); - Z_Free(wadData); - } - else - { - // Important: take care of the ordering of the next functions. - loadedbm = P_LoadBlockMap(lastloadedmaplumpnum + ML_BLOCKMAP); - P_LoadVertexes(lastloadedmaplumpnum + ML_VERTEXES); - P_LoadSectors(lastloadedmaplumpnum + ML_SECTORS); - P_LoadSideDefs(lastloadedmaplumpnum + ML_SIDEDEFS); - P_LoadLineDefs(lastloadedmaplumpnum + ML_LINEDEFS); - P_LoadSideDefs2(lastloadedmaplumpnum + ML_SIDEDEFS); - P_LoadSubsectors(lastloadedmaplumpnum + ML_SSECTORS); - P_LoadNodes(lastloadedmaplumpnum + ML_NODES); - P_LoadSegs(lastloadedmaplumpnum + ML_SEGS); - P_LoadReject(lastloadedmaplumpnum + ML_REJECT); - - // Important: take care of the ordering of the next functions. - if (!loadedbm) - P_CreateBlockMap(); // Graue 02-29-2004 - - P_LoadLineDefs2(); - P_GroupLines(); - numdmstarts = numredctfstarts = numbluectfstarts = 0; - - // reset the player starts - for (i = 0; i < MAXPLAYERS; i++) - playerstarts[i] = NULL; - for (i = 0; i < 2; i++) - skyboxmo[i] = NULL; - P_MapStart(); - P_PrepareThings(lastloadedmaplumpnum + ML_THINGS); - } - - // init gravity, tag lists, - // anything that P_ResetDynamicSlopes/P_LoadThings needs to know + // init anything that P_SpawnSlopes/P_LoadThings needs to know P_InitSpecials(); -#ifdef ESLOPE - P_ResetDynamicSlopes(); -#endif + if (!P_LoadMapFromFile()) + return false; - P_LoadThings(); + // set up world state + // jart: needs to be done here so anchored slopes know the attached list + P_SpawnSpecials(fromnetsave); - P_SpawnSecretItems(loademblems); + P_SpawnSlopes(fromnetsave); + + P_SpawnSpecialsAfterSlopes(); + + P_SpawnMapThings(!fromnetsave); + skyboxmo[0] = skyboxviewpnts[0]; + skyboxmo[1] = skyboxcenterpnts[0]; for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++) if (!playerstarts[numcoopstarts]) break; - // set up world state - P_SpawnSpecials(fromnetsave); + P_SpawnSpecialsThatRequireObjects(); - K_AdjustWaypointsParameters(); + if (!udmf) + { + // Backwards compatibility for non-UDMF maps + K_AdjustWaypointsParameters(); + } - if (loadprecip) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame) + if (!fromnetsave) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame) P_SpawnPrecipitation(); - // The waypoint data that's in PU_LEVEL needs to be reset back to 0/NULL now since PU_LEVEL was cleared K_ClearWaypoints(); // Load the waypoints please! - if (G_RaceGametype()) + if (gametyperules & GTR_CIRCUIT) { if (K_SetupWaypointList() == false) { CONS_Alert(CONS_ERROR, "Waypoints were not able to be setup! Player positions will not work correctly.\n"); } } + #ifdef HWRENDER // not win32 only 19990829 by Kin - if (rendermode != render_soft && rendermode != render_none) - { - // Correct missing sidedefs & deep water trick - HWR_CorrectSWTricks(); - HWR_CreatePlanePolygons((INT32)numnodes - 1); - } + // Lactozilla: Free extrasubsectors regardless of renderer. + // Maybe we're not in OpenGL anymore. + if (extrasubsectors) + free(extrasubsectors); + extrasubsectors = NULL; + // stuff like HWR_CreatePlanePolygons is called there + if (rendermode == render_opengl) + HWR_SetupLevel(); #endif // oh god I hope this helps @@ -3263,125 +4084,10 @@ boolean P_SetupLevel(boolean skipprecip) // none of this needs to be done because it's not the beginning of the map when // a netgame save is being loaded, and could actively be harmful by messing with // the client's view of the data.) - if (fromnetsave) - goto netgameskip; - // ========== + if (!fromnetsave) + P_InitGametype(); - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - players[i].pflags &= ~PF_NIGHTSMODE; - - // Start players with pity shields if possible - players[i].pity = -1; - - if (!G_RaceGametype()) - { - players[i].mo = NULL; - G_DoReborn(i); - } - else // gametype is GT_COOP or GT_RACE - { - players[i].mo = NULL; - G_SpawnPlayer(i, (players[i].starpostnum != 0)); - } - } - - if (modeattacking && !demo.playback) - P_LoadRecordGhosts(); - - if (G_RaceGametype() && server) - CV_StealthSetValue(&cv_numlaps, - ((netgame || multiplayer) && cv_basenumlaps.value - && (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) - || (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))) - ? cv_basenumlaps.value - : mapheaderinfo[gamemap - 1]->numlaps); - - // Start recording replay in multiplayer with a temp filename - //@TODO I'd like to fix dedis crashing when recording replays for the future too... - if (!demo.playback && multiplayer && !dedicated) { - static char buf[256]; - char *path; - sprintf(buf, "media"PATHSEP"replay"PATHSEP"online"PATHSEP"%d-%s", (int) (time(NULL)), G_BuildMapName(gamemap)); - - path = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"online", srb2home); - M_MkdirEach(path, M_PathParts(path) - 4, 0755); - - G_RecordDemo(buf); - } - - // =========== - // landing point for netgames. - netgameskip: - - if (!dedicated) - { - if (!demo.freecam) - for (i = 0; i <= r_splitscreen; i++) - P_SetupCamera(displayplayers[i], &camera[i]); - - // Salt: CV_ClearChangedFlags() messes with your settings :( - /*if (!cv_cam_height.changed) - CV_Set(&cv_cam_height, cv_cam_height.defaultvalue); - - if (!cv_cam_dist.changed) - CV_Set(&cv_cam_dist, cv_cam_dist.defaultvalue); - - if (!cv_cam2_height.changed) - CV_Set(&cv_cam2_height, cv_cam2_height.defaultvalue); - - if (!cv_cam2_dist.changed) - CV_Set(&cv_cam2_dist, cv_cam2_dist.defaultvalue);*/ - - // Though, I don't think anyone would care about cam_rotate being reset back to the only value that makes sense :P - if (!cv_cam_rotate.changed) - CV_Set(&cv_cam_rotate, cv_cam_rotate.defaultvalue); - - if (!cv_cam2_rotate.changed) - CV_Set(&cv_cam2_rotate, cv_cam2_rotate.defaultvalue); - - if (!cv_cam3_rotate.changed) - CV_Set(&cv_cam3_rotate, cv_cam3_rotate.defaultvalue); - - if (!cv_cam4_rotate.changed) - CV_Set(&cv_cam4_rotate, cv_cam4_rotate.defaultvalue); - - /*if (!cv_analog.changed) - CV_SetValue(&cv_analog, 0); - if (!cv_analog2.changed) - CV_SetValue(&cv_analog2, 0); - if (!cv_analog3.changed) - CV_SetValue(&cv_analog3, 0); - if (!cv_analog4.changed) - CV_SetValue(&cv_analog4, 0);*/ - - // Shouldn't be necessary with render parity? - /*if (rendermode != render_none) - CV_Set(&cv_fov, cv_fov.defaultvalue);*/ - - g_localplayers[0] = consoleplayer; // Start with your OWN view, please! - } - - /*if (cv_useranalog.value) - CV_SetValue(&cv_analog, true); - - if (splitscreen && cv_useranalog2.value) - CV_SetValue(&cv_analog2, true); - - if (splitscreen > 1 && cv_useranalog3.value) - CV_SetValue(&cv_analog3, true); - - if (splitscreen > 2 && cv_useranalog4.value) - CV_SetValue(&cv_analog4, true); - - if (twodlevel) - { - CV_SetValue(&cv_analog4, false); - CV_SetValue(&cv_analog3, false); - CV_SetValue(&cv_analog2, false); - CV_SetValue(&cv_analog, false); - }*/ + P_InitCamera(); wantedcalcdelay = wantedfrequency*2; indirectitemcooldown = 0; @@ -3397,16 +4103,54 @@ boolean P_SetupLevel(boolean skipprecip) // clear special respawning que iquehead = iquetail = 0; - // Fab : 19-07-98 : start cd music for this level (note: can be remapped) - I_PlayCD((UINT8)(gamemap), false); + P_MapEnd(); - // preload graphics -#ifdef HWRENDER // not win32 only 19990829 by Kin - if (rendermode != render_soft && rendermode != render_none) + // Remove the loading shit from the screen + if (rendermode != render_none && !titlemapinaction) + F_WipeColorFill(levelfadecol); + + if (precache || dedicated) + R_PrecacheLevel(); + + nextmapoverride = 0; + skipstats = 0; + + if (!(netgame || multiplayer || demo.playback) && !majormods) + mapvisited[gamemap-1] |= MV_VISITED; + else if (netgame || multiplayer) + mapvisited[gamemap-1] |= MV_MP; // you want to record that you've been there this session, but not permanently + + G_AddMapToBuffer(gamemap-1); + + levelloading = false; + + P_RunCachedActions(); + + // Took me 3 hours to figure out why my progression kept on getting overwritten with the titlemap... + if (!titlemapinaction) { - HWR_PrepLevelCache(numtextures); + if (!lastmaploaded) // Start a new game? + { + // I'd love to do this in the menu code instead of here, but everything's a mess and I can't guarantee saving proper player struct info before the first act's started. You could probably refactor it, but it'd be a lot of effort. Easier to just work off known good code. ~toast 22/06/2020 + if (!(ultimatemode || netgame || multiplayer || demo.playback || demo.recording || metalrecording || modeattacking || marathonmode) + && (!modifiedgame || savemoddata) && cursaveslot > 0) + G_SaveGame((UINT32)cursaveslot, gamemap); + // If you're looking for saving sp file progression (distinct from G_SaveGameOver), check G_DoCompleted. + } + lastmaploaded = gamemap; // HAS to be set after saving!! + } + + if (!fromnetsave) // uglier hack + { // to make a newly loaded level start on the second frame. + INT32 buf = gametic % TICQUEUE; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); + } + P_PreTicker(2); + LUAh_MapLoad(); } -#endif // NOW you can try to spawn in the Battle capsules, if there's not enough players for a match K_SpawnBattleCapsules(); @@ -3430,60 +4174,52 @@ boolean P_SetupLevel(boolean skipprecip) K_UpdateMatchRaceBots(); } - P_MapEnd(); + // No render mode, stop here. + if (rendermode == render_none) + return true; - // Remove the loading shit from the screen - if (rendermode != render_none) - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); + // Title card! + G_StartTitleCard(); - if (precache || dedicated) - R_PrecacheLevel(); + // Can the title card actually run, though? + if (!WipeStageTitle) + return true; + if (ranspecialwipe == 2) + return true; - nextmapoverride = 0; - skipstats = false; - - if (!(netgame || multiplayer) && !majormods) - mapvisited[gamemap-1] |= MV_VISITED; - - G_AddMapToBuffer(gamemap-1); - - levelloading = false; - - P_RunCachedActions(); - - if (P_CanSave()) - G_SaveGame((UINT32)cursaveslot); - - if (savedata.lives > 0) - { - players[consoleplayer].continues = savedata.continues; - players[consoleplayer].lives = savedata.lives; - players[consoleplayer].score = savedata.score; - emeralds = savedata.emeralds; - savedata.lives = 0; - } - - // assume the skybox is visible on level load. - skyVisible = true; - memset(skyVisiblePerPlayer, true, sizeof(skyVisiblePerPlayer)); - - if (loadprecip) // uglier hack - { // to make a newly loaded level start on the second frame. - INT32 buf = gametic % TICQUEUE; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - G_CopyTiccmd(&players[i].cmd, &netcmds[buf][i], 1); - } - P_PreTicker(2); -#ifdef HAVE_BLUA - LUAh_MapLoad(); -#endif - } + // If so... + G_PreLevelTitleCard(); return true; } +#ifdef HWRENDER +void HWR_SetupLevel(void) +{ + // Lactozilla (December 8, 2019) + // Level setup used to free EVERY mipmap from memory. + // Even mipmaps that aren't related to level textures. + // Presumably, the hardware render code used to store textures as level data. + // Meaning, they had memory allocated and marked with the PU_LEVEL tag. + // Level textures are only reloaded after R_LoadTextures, which is + // when the texture list is loaded. + + // Sal: Unfortunately, NOT freeing them causes the dreaded Color Bug. + HWR_FreeMipmapCache(); + +#ifdef ALAM_LIGHTING + // BP: reset light between levels (we draw preview frame lights on current frame) + HWR_ResetLights(); +#endif + + HWR_CreatePlanePolygons((INT32)numnodes - 1); + + // Build the sky dome + HWR_ClearSkyDome(); + HWR_BuildSkyDome(); +} +#endif + // // P_RunSOC // @@ -3506,6 +4242,72 @@ boolean P_RunSOC(const char *socfilename) return true; } +// Auxiliary function for PK3 loading - looks for sound replacements. +// NOTE: it does not really add any new sound entry or anything. +void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num) +{ + size_t j; + lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo + first; + for (; num > 0; num--, lumpinfo++) + { + // Let's check whether it's replacing an existing sound or it's a brand new one. + for (j = 1; j < NUMSFX; j++) + { + if (S_sfx[j].name && !strnicmp(S_sfx[j].name, lumpinfo->name + 2, 6)) + { + // the sound will be reloaded when needed, + // since sfx->data will be NULL + CONS_Debug(DBG_SETUP, "Sound %.8s replaced\n", lumpinfo->name); + + I_FreeSfx(&S_sfx[j]); + break; // there shouldn't be two sounds with the same name, so stop looking + } + } + } +} + +// Auxiliary function for PK3 loading - looks for music and music replacements. +// NOTE: does nothing but print debug messages. The code is handled somewhere else. +void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num) +{ + lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo + first; + char *name; + for (; num > 0; num--, lumpinfo++) + { + name = lumpinfo->name; + if (name[0] == 'O' && name[1] == '_') + { + CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name); + } + else if (name[0] == 'D' && name[1] == '_') + { + CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name); + } + } + return; +} + +// Auxiliary function - input a folder name and gives us the resource markers positions. +static lumpinfo_t* FindFolder(const char *folName, UINT16 *start, UINT16 *end, lumpinfo_t *lumpinfo, UINT16 *pnumlumps, size_t *pi) +{ + UINT16 numlumps = *pnumlumps; + size_t i = *pi; + if (!stricmp(lumpinfo->fullname, folName)) + { + lumpinfo++; + *start = ++i; + for (; i < numlumps; i++, lumpinfo++) + if (strnicmp(lumpinfo->fullname, folName, strlen(folName))) + break; + lumpinfo--; + *end = i-- - *start; + *pi = i; + *pnumlumps = numlumps; + return lumpinfo; + } + return lumpinfo; +} + // // Add a wadfile to the active wad files, // replace sounds, musics, patches, textures, sprites and maps @@ -3516,59 +4318,105 @@ boolean P_AddWadFile(const char *wadfilename) UINT16 numlumps, wadnum; char *name; lumpinfo_t *lumpinfo; - boolean texturechange = false; + + //boolean texturechange = false; ///\todo Useless; broken when back-frontporting PK3 changes? boolean mapsadded = false; boolean replacedcurrentmap = false; - if ((numlumps = W_InitFile(wadfilename)) == INT16_MAX) + // Vars to help us with the position start and amount of each resource type. + // Useful for PK3s since they use folders. + // WADs use markers for some resources, but others such as sounds are checked lump-by-lump anyway. +// UINT16 luaPos, luaNum = 0; +// UINT16 socPos, socNum = 0; + UINT16 sfxPos = 0, sfxNum = 0; + UINT16 musPos = 0, musNum = 0; +// UINT16 sprPos, sprNum = 0; + UINT16 texPos = 0, texNum = 0; +// UINT16 patPos, patNum = 0; +// UINT16 flaPos, flaNum = 0; +// UINT16 mapPos, mapNum = 0; + + // Init file. + if ((numlumps = W_InitFile(wadfilename, false, false)) == INT16_MAX) { refreshdirmenu |= REFRESHDIR_NOTLOADED; - CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), wadfilename); return false; } - else wadnum = (UINT16)(numwadfiles-1); + else + wadnum = (UINT16)(numwadfiles-1); - // - // search for sound replacements - // - lumpinfo = wadfiles[wadnum]->lumpinfo; - for (i = 0; i < numlumps; i++, lumpinfo++) + switch(wadfiles[wadnum]->type) { - name = lumpinfo->name; - if (name[0] == 'D') + case RET_PK3: + // Look for the lumps that act as resource delimitation markers. + lumpinfo = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < numlumps; i++, lumpinfo++) { - if (name[1] == 'S') for (j = 1; j < NUMSFX; j++) +// lumpinfo = FindFolder("Lua/", &luaPos, &luaNum, lumpinfo, &numlumps, &i); +// lumpinfo = FindFolder("SOC/", &socPos, &socNum, lumpinfo, &numlumps, &i); + lumpinfo = FindFolder("Sounds/", &sfxPos, &sfxNum, lumpinfo, &numlumps, &i); + lumpinfo = FindFolder("Music/", &musPos, &musNum, lumpinfo, &numlumps, &i); +// lumpinfo = FindFolder("Sprites/", &sprPos, &sprNum, lumpinfo, &numlumps, &i); + lumpinfo = FindFolder("Textures/", &texPos, &texNum, lumpinfo, &numlumps, &i); +// lumpinfo = FindFolder("Patches/", &patPos, &patNum, lumpinfo, &numlumps, &i); +// lumpinfo = FindFolder("Flats/", &flaPos, &flaNum, lumpinfo, &numlumps, &i); +// lumpinfo = FindFolder("Maps/", &mapPos, &mapNum, lumpinfo, &numlumps, &i); + } + + // Update the detected resources. + // Note: ALWAYS load Lua scripts first, SOCs right after, and the remaining resources afterwards. +// if (luaNum) // Lua scripts. +// P_LoadLuaScrRange(wadnum, luaPos, luaNum); +// if (socNum) // SOCs. +// P_LoadDehackRange(wadnum, socPos, socNum); + if (sfxNum) // Sounds. TODO: Function currently only updates already existing sounds, the rest is handled somewhere else. + P_LoadSoundsRange(wadnum, sfxPos, sfxNum); + if (musNum) // Music. TODO: Useless function right now. + P_LoadMusicsRange(wadnum, musPos, musNum); +// if (sprNum) // Sprites. +// R_LoadSpritsRange(wadnum, sprPos, sprNum); +// if (texNum) // Textures. TODO: R_LoadTextures() does the folder positioning once again. New function maybe? +// R_LoadTextures(); +// if (mapNum) // Maps. TODO: Actually implement the map WAD loading code, lulz. +// P_LoadWadMapRange(wadnum, mapPos, mapNum); + break; + default: + lumpinfo = wadfiles[wadnum]->lumpinfo; + for (i = 0; i < numlumps; i++, lumpinfo++) + { + name = lumpinfo->name; + if (name[0] == 'D') { - if (S_sfx[j].name && !strnicmp(S_sfx[j].name, name + 2, 6)) + if (name[1] == 'S') { - // the sound will be reloaded when needed, - // since sfx->data will be NULL - CONS_Debug(DBG_SETUP, "Sound %.8s replaced\n", name); + for (j = 1; j < NUMSFX; j++) + { + if (S_sfx[j].name && !strnicmp(S_sfx[j].name, name + 2, 6)) + { + // the sound will be reloaded when needed, + // since sfx->data will be NULL + CONS_Debug(DBG_SETUP, "Sound %.8s replaced\n", name); - I_FreeSfx(&S_sfx[j]); + I_FreeSfx(&S_sfx[j]); - sreplaces++; + sreplaces++; + break; // there shouldn't be two sounds with the same name, so stop looking + } + } + } + else if (name[1] == '_') + { + CONS_Debug(DBG_SETUP, "Music %.8s ignored\n", name); + mreplaces++; } } - else if (name[1] == '_') + else if (name[0] == 'O' && name[1] == '_') { - CONS_Debug(DBG_SETUP, "Music %.8s ignored\n", name); - mreplaces++; + CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name); + digmreplaces++; } } - else if (name[0] == 'O' && name[1] == '_') - { - CONS_Debug(DBG_SETUP, "Music %.8s replaced\n", name); - digmreplaces++; - } -#if 0 - // - // search for texturechange replacements - // - else if (!memcmp(name, "TEXTURE1", 8) || !memcmp(name, "TEXTURE2", 8) - || !memcmp(name, "PNAMES", 6)) -#endif - texturechange = true; + break; } if (!devparm && sreplaces) CONS_Printf(M_GetText("%s sounds replaced\n"), sizeu1(sreplaces)); @@ -3585,25 +4433,28 @@ boolean P_AddWadFile(const char *wadfilename) // Reload it all anyway, just in case they // added some textures but didn't insert a - // TEXTURE1/PNAMES/etc. list. - if (texturechange) // initialized in the sound check - R_LoadTextures(); // numtexture changes - else - R_FlushTextureCache(); // just reload it from file + // TEXTURES/etc. list. + R_LoadTextures(); // numtexture changes - // Reload ANIMATED / ANIMDEFS + // Reload ANIMDEFS P_InitPicAnims(); // Flush and reload HUD graphics ST_UnloadGraphics(); HU_LoadGraphics(); ST_LoadGraphics(); - ST_ReloadSkinFaceGraphics(); // // look for skins // R_AddSkins(wadnum); // faB: wadfile index in wadfiles[] + R_PatchSkins(wadnum); // toast: PATCH PATCH + ST_ReloadSkinFaceGraphics(); + + // + // edit music defs + // + S_LoadMusicDefs(wadnum); // // edit music defs @@ -3617,7 +4468,6 @@ boolean P_AddWadFile(const char *wadfilename) for (i = 0; i < numlumps; i++, lumpinfo++) { name = lumpinfo->name; - if (name[0] == 'M' && name[1] == 'A' && name[2] == 'P') // Ignore the headers { INT16 num; @@ -3628,9 +4478,12 @@ boolean P_AddWadFile(const char *wadfilename) // we want to record whether this map exists. if it doesn't have a header, we can assume it's not relephant if (num <= NUMMAPS && mapheaderinfo[num-1]) { - if (mapheaderinfo[num-1]->menuflags & LF2_EXISTSHACK) + if (mapheaderinfo[num - 1]->alreadyExists != false) + { G_SetGameModified(multiplayer, true); // oops, double-defined - no record attack privileges for you - mapheaderinfo[num-1]->menuflags |= LF2_EXISTSHACK; + } + + mapheaderinfo[num - 1]->alreadyExists = true; } //If you replaced the map you're on, end the level when done. @@ -3644,13 +4497,19 @@ boolean P_AddWadFile(const char *wadfilename) if (!mapsadded) CONS_Printf(M_GetText("No maps added\n")); + R_LoadSpriteInfoLumps(wadnum, numlumps); + +#ifdef HWRENDER + HWR_ReloadModels(); +#endif + // reload status bar (warning should have valid player!) if (gamestate == GS_LEVEL) ST_Start(); // Prevent savefile cheating - if (cursaveslot >= 0) - cursaveslot = -1; + if (cursaveslot > 0) + cursaveslot = 0; if (replacedcurrentmap && gamestate == GS_LEVEL && (netgame || multiplayer)) { @@ -3663,31 +4522,3 @@ boolean P_AddWadFile(const char *wadfilename) return true; } - -#ifdef DELFILE -boolean P_DelWadFile(void) -{ - sfxenum_t i; - const UINT16 wadnum = (UINT16)(numwadfiles - 1); - const lumpnum_t lumpnum = numwadfiles<<16; - //lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo; - R_DelSkins(wadnum); // only used by DELFILE - R_DelSpriteDefs(wadnum); // only used by DELFILE - for (i = 0; i < NUMSFX; i++) - { - if (S_sfx[i].lumpnum != LUMPERROR && S_sfx[i].lumpnum >= lumpnum) - { - S_StopSoundByNum(i); - S_RemoveSoundFx(i); - if (S_sfx[i].lumpnum != LUMPERROR) - { - I_FreeSfx(&S_sfx[i]); - S_sfx[i].lumpnum = LUMPERROR; - } - } - } - W_UnloadWadFile(wadnum); // only used by DELFILE - R_LoadTextures(); - return false; -} -#endif diff --git a/src/p_setup.h b/src/p_setup.h index c0b30ca6a..ac0f22caf 100644 --- a/src/p_setup.h +++ b/src/p_setup.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -30,19 +30,57 @@ extern boolean levelloading; extern UINT8 levelfadecol; extern lumpnum_t lastloadedmaplumpnum; // for comparative savegame + +/* for levelflat type */ +enum +{ + LEVELFLAT_NONE,/* HOM time my friend */ + LEVELFLAT_FLAT, + LEVELFLAT_PATCH, + LEVELFLAT_PNG, + LEVELFLAT_TEXTURE, +}; + // // MAP used flats lookup table // typedef struct { char name[9]; // resource name from wad - lumpnum_t lumpnum; // lump number of the flat + + UINT8 type; + union + { + struct + { + lumpnum_t lumpnum; // lump number of the flat + // for flat animation + lumpnum_t baselumpnum; + } + flat; + struct + { + INT32 num; + INT32 lastnum; // texture number of the flat + // for flat animation + INT32 basenum; + } + texture; + } + u; + + UINT16 width, height; // for flat animation - lumpnum_t baselumpnum; INT32 animseq; // start pos. in the anim sequence INT32 numpics; INT32 speed; + + // for textures + UINT8 *picture; +#ifdef HWRENDER + void *mipmap; +#endif } levelflat_t; extern size_t numlevelflats; @@ -58,20 +96,26 @@ void P_SetupLevelSky(const char *skytexname, boolean global); #ifdef SCANTHINGS void P_ScanThings(INT16 mapnum, INT16 wadnum, INT16 lumpnum); #endif -void P_LoadThingsOnly(void); -boolean P_SetupLevel(boolean skipprecip); -boolean P_AddWadFile(const char *wadfilename); -#ifdef DELFILE -boolean P_DelWadFile(void); +void P_RespawnThings(void); +boolean P_LoadLevel(boolean fromnetsave); +#ifdef HWRENDER +void HWR_SetupLevel(void); #endif +boolean P_AddWadFile(const char *wadfilename); boolean P_RunSOC(const char *socfilename); +void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num); +void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num); void P_WriteThings(lumpnum_t lump); void P_UpdateSegLightOffset(seg_t *li); size_t P_PrecacheLevelFlats(void); void P_AllocMapHeader(INT16 i); +void P_SetDemoFlickies(INT16 i); +void P_DeleteFlickies(INT16 i); + // Needed for NiGHTS void P_ReloadRings(void); +void P_SwitchSpheresBonusMode(boolean bonustime); void P_DeleteGrades(INT16 i); void P_AddGradesForMare(INT16 i, UINT8 mare, char *gtext); UINT8 P_GetGrade(UINT32 pscore, INT16 map, UINT8 mare); diff --git a/src/p_sight.c b/src/p_sight.c index f230f40f6..a18f22d40 100644 --- a/src/p_sight.c +++ b/src/p_sight.c @@ -100,7 +100,6 @@ static fixed_t P_InterceptVector2(divline_t *v2, divline_t *v1) return frac; } -#ifdef POLYOBJECTS static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los) { size_t i; @@ -169,7 +168,6 @@ static boolean P_CrossSubsecPolyObj(polyobj_t *po, register los_t *los) return true; } -#endif // // P_CrossSubsector @@ -180,9 +178,7 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) { seg_t *seg; INT32 count; -#ifdef POLYOBJECTS polyobj_t *po; // haleyjd 02/23/06 -#endif #ifdef RANGECHECK if (num >= numsubsectors) @@ -192,7 +188,6 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) // haleyjd 02/23/06: this assignment should be after the above check seg = segs + subsectors[num].firstline; -#ifdef POLYOBJECTS // haleyjd 02/23/06: check polyobject lines if ((po = subsectors[num].polyList)) { @@ -207,7 +202,6 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) po = (polyobj_t *)(po->link.next); } } -#endif for (count = subsectors[num].numlines; --count >= 0; seg++) // check lines { @@ -218,14 +212,10 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) const vertex_t *v1,*v2; fixed_t frac; fixed_t frontf, backf, frontc, backc; -#ifdef ESLOPE fixed_t fracx, fracy; -#endif - /* SRB2Kart doesn't have this? if (seg->glseg) continue; - */ // already checked other side? if (line->validcount == validcount) @@ -265,21 +255,14 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) front = seg->frontsector; back = seg->backsector; -#ifdef ESLOPE // calculate position at intercept fracx = los->strace.x + FixedMul(los->strace.dx, frac); fracy = los->strace.y + FixedMul(los->strace.dy, frac); // calculate sector heights - frontf = (front->f_slope) ? P_GetZAt(front->f_slope, fracx, fracy) : front->floorheight; - frontc = (front->c_slope) ? P_GetZAt(front->c_slope, fracx, fracy) : front->ceilingheight; - backf = (back->f_slope) ? P_GetZAt(back->f_slope, fracx, fracy) : back->floorheight; - backc = (back->c_slope) ? P_GetZAt(back->c_slope, fracx, fracy) : back->ceilingheight; -#else - frontf = front->floorheight; - frontc = front->ceilingheight; - backf = back->floorheight; - backc = back->ceilingheight; -#endif + frontf = P_GetSectorFloorZAt (front, fracx, fracy); + frontc = P_GetSectorCeilingZAt(front, fracx, fracy); + backf = P_GetSectorFloorZAt (back , fracx, fracy); + backc = P_GetSectorCeilingZAt(back , fracx, fracy); // crosses a two sided line // no wall to block sight with? if (frontf == backf && frontc == backc @@ -329,15 +312,11 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) continue; } -#ifdef ESLOPE - topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight; - bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight; -#else - topz = *rover->topheight; - bottomz = *rover->bottomheight; -#endif - topslope = FixedDiv(topz - los->sightzstart , frac); - bottomslope = FixedDiv(bottomz - los->sightzstart , frac); + topz = P_GetFFloorTopZAt (rover, fracx, fracy); + bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy); + topslope = FixedDiv( topz - los->sightzstart, frac); + bottomslope = FixedDiv(bottomz - los->sightzstart, frac); + if (topslope >= los->topslope && bottomslope <= los->bottomslope) return false; // view completely blocked } @@ -350,15 +329,11 @@ static boolean P_CrossSubsector(size_t num, register los_t *los) continue; } -#ifdef ESLOPE - topz = (*rover->t_slope) ? P_GetZAt(*rover->t_slope, fracx, fracy) : *rover->topheight; - bottomz = (*rover->b_slope) ? P_GetZAt(*rover->b_slope, fracx, fracy) : *rover->bottomheight; -#else - topz = *rover->topheight; - bottomz = *rover->bottomheight; -#endif - topslope = FixedDiv(topz - los->sightzstart , frac); - bottomslope = FixedDiv(bottomz - los->sightzstart , frac); + topz = P_GetFFloorTopZAt (rover, fracx, fracy); + bottomz = P_GetFFloorBottomZAt(rover, fracx, fracy); + topslope = FixedDiv( topz - los->sightzstart, frac); + bottomslope = FixedDiv(bottomz - los->sightzstart, frac); + if (topslope >= los->topslope && bottomslope <= los->bottomslope) return false; // view completely blocked } @@ -434,15 +409,10 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) // killough 11/98: shortcut for melee situations // same subsector? obviously visible -#ifndef POLYOBJECTS - if (t1->subsector == t2->subsector) - return true; -#else // haleyjd 02/23/06: can't do this if there are polyobjects in the subsec if (!t1->subsector->polyList && t1->subsector == t2->subsector) return true; -#endif // An unobstructed LOS is possible. // Now look from eyes of t1 to any part of t2. @@ -489,26 +459,10 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) continue; } -#ifdef ESLOPE - if (*rover->t_slope) - { - topz1 = P_GetZAt(*rover->t_slope, t1->x, t1->y); - topz2 = P_GetZAt(*rover->t_slope, t2->x, t2->y); - } - else - topz1 = topz2 = *rover->topheight; - - if (*rover->b_slope) - { - bottomz1 = P_GetZAt(*rover->b_slope, t1->x, t1->y); - bottomz2 = P_GetZAt(*rover->b_slope, t2->x, t2->y); - } - else - bottomz1 = bottomz2 = *rover->bottomheight; -#else - topz1 = topz2 = *rover->topheight; - bottomz1 = bottomz2 = *rover->bottomheight; -#endif + topz1 = P_GetFFloorTopZAt (rover, t1->x, t1->y); + topz2 = P_GetFFloorTopZAt (rover, t2->x, t2->y); + bottomz1 = P_GetFFloorBottomZAt(rover, t1->x, t1->y); + bottomz2 = P_GetFFloorBottomZAt(rover, t2->x, t2->y); // Check for blocking floors here. if ((los.sightzstart < bottomz1 && t2->z >= topz2) @@ -521,7 +475,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) if (rover->flags & FF_SOLID) continue; // shortcut since neither mobj can be inside the 3dfloor - if (!(rover->flags & FF_INVERTPLANES)) + if (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)) { if (los.sightzstart >= topz1 && t2->z + t2->height < topz2) return false; // blocked by upper outside plane @@ -530,7 +484,7 @@ boolean P_CheckSight(mobj_t *t1, mobj_t *t2) return false; // blocked by lower outside plane } - if (rover->flags & FF_INVERTPLANES || rover->flags & FF_BOTHPLANES) + if (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES) { if (los.sightzstart < topz1 && t2->z >= topz2) return false; // blocked by upper inside plane diff --git a/src/p_slopes.c b/src/p_slopes.c index 6c44d2d9e..d903afb71 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2004 by Stephen McGranahan -// Copyright (C) 2015-2018 by Sonic Team Junior. +// Copyright (C) 2015-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -24,77 +24,106 @@ #include "w_wad.h" #include "k_kart.h" // K_PlayerEBrake -#ifdef ESLOPE +pslope_t *slopelist = NULL; +UINT16 slopecount = 0; -static pslope_t *slopelist = NULL; -static UINT16 slopecount = 0; +static void P_BuildSlopeAnchorList (void); +static void P_SetupAnchoredSlopes (void); // Calculate line normal void P_CalculateSlopeNormal(pslope_t *slope) { slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT); - slope->normal.x = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), -slope->d.x); - slope->normal.y = -FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), -slope->d.y); + slope->normal.x = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x); + slope->normal.y = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y); } -// With a vertex slope that has its vertices set, configure relevant slope info -static void P_ReconfigureVertexSlope(pslope_t *slope) +// Calculate slope's high & low z +static void P_CalculateLineSlopeHighLow(pslope_t *slope, line_t *line, boolean ceiling, boolean back) +{ + // To find the real highz/lowz of a slope, you need to check all the vertexes + // in the slope's sector with P_GetZAt to get the REAL lowz & highz + // Although these slopes are set by floorheights the ANGLE is what a slope is, + // so technically any slope can extend on forever (they are just bound by sectors) + // *You can use sourceline as a reference to see if two slopes really are the same + + size_t l; + + sector_t *checksector = back ? line->backsector : line->frontsector; + + // Default points for high and low + fixed_t highest = INT32_MIN; + fixed_t lowest = INT32_MAX; + + // Now check to see what the REAL high and low points of the slope inside the sector + // TODO: Is this really needed outside of FOFs? -Red + + for (l = 0; l < checksector->linecount; l++) + { + pslope_t *checkslope = ceiling ? checksector->c_slope : checksector->f_slope; + fixed_t height = P_GetSlopeZAt(checkslope, checksector->lines[l]->v1->x, checksector->lines[l]->v1->y); + + if (height > highest) + highest = height; + + if (height < lowest) + lowest = height; + } + + // Sets extra clipping data for the slope + slope->highz = highest; + slope->lowz = lowest; +} + +/// Setup slope via 3 vertexes. +void P_ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const vector3_t v2, const vector3_t v3) { vector3_t vec1, vec2; - // Set slope normal - vec1.x = (slope->vertices[1]->x - slope->vertices[0]->x) << FRACBITS; - vec1.y = (slope->vertices[1]->y - slope->vertices[0]->y) << FRACBITS; - vec1.z = (slope->vertices[1]->z - slope->vertices[0]->z) << FRACBITS; + // Set origin. + FV3_Copy(&slope->o, &v1); - vec2.x = (slope->vertices[2]->x - slope->vertices[0]->x) << FRACBITS; - vec2.y = (slope->vertices[2]->y - slope->vertices[0]->y) << FRACBITS; - vec2.z = (slope->vertices[2]->z - slope->vertices[0]->z) << FRACBITS; + // Get slope's normal. + FV3_SubEx(&v2, &v1, &vec1); + FV3_SubEx(&v3, &v1, &vec2); - // ugggggggh fixed-point maaaaaaath - slope->extent = max( - max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)), - max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z)) - ) >> (FRACBITS+5); - - if (slope->extent == 0) + // Set some defaults for a non-sloped "slope" + if (vec1.z == 0 && vec2.z == 0) { - // Prevent divide by zero - slope->extent = 1; - } - - vec1.x /= slope->extent; - vec1.y /= slope->extent; - vec1.z /= slope->extent; - vec2.x /= slope->extent; - vec2.y /= slope->extent; - vec2.z /= slope->extent; - - FV3_Cross(&vec1, &vec2, &slope->normal); - - slope->extent = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z); - if (slope->normal.z < 0) - slope->extent = -slope->extent; - - slope->normal.x = FixedDiv(slope->normal.x, slope->extent); - slope->normal.y = FixedDiv(slope->normal.y, slope->extent); - slope->normal.z = FixedDiv(slope->normal.z, slope->extent); - - // Set origin - slope->o.x = slope->vertices[0]->x << FRACBITS; - slope->o.y = slope->vertices[0]->y << FRACBITS; - slope->o.z = slope->vertices[0]->z << FRACBITS; - - if (slope->normal.x == 0 && slope->normal.y == 0) { // Set some defaults for a non-sloped "slope" slope->zangle = slope->xydirection = 0; slope->zdelta = slope->d.x = slope->d.y = 0; - } else { + slope->normal.x = slope->normal.y = 0; + slope->normal.z = FRACUNIT; + } + else + { + /// \note Using fixed point for vectorial products easily leads to overflows so we work around by downscaling them. + fixed_t m = max( + max(max(abs(vec1.x), abs(vec1.y)), abs(vec1.z)), + max(max(abs(vec2.x), abs(vec2.y)), abs(vec2.z)) + ) >> 5; // shifting right by 5 is good enough. + + FV3_Cross( + FV3_Divide(&vec1, m), + FV3_Divide(&vec2, m), + &slope->normal + ); + + // NOTE: FV3_Magnitude() doesn't work properly in some cases, and chaining FixedHypot() seems to give worse results. + m = R_PointToDist2(0, 0, R_PointToDist2(0, 0, slope->normal.x, slope->normal.y), slope->normal.z); + + // Invert normal if it's facing down. + if (slope->normal.z < 0) + m = -m; + + FV3_Divide(&slope->normal, m); + // Get direction vector - slope->extent = R_PointToDist2(0, 0, slope->normal.x, slope->normal.y); - slope->d.x = -FixedDiv(slope->normal.x, slope->extent); - slope->d.y = -FixedDiv(slope->normal.y, slope->extent); + m = FixedHypot(slope->normal.x, slope->normal.y); + slope->d.x = -FixedDiv(slope->normal.x, m); + slope->d.y = -FixedDiv(slope->normal.y, m); // Z delta - slope->zdelta = FixedDiv(slope->extent, slope->normal.z); + slope->zdelta = FixedDiv(m, slope->normal.z); // Get angles slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180; @@ -102,88 +131,95 @@ static void P_ReconfigureVertexSlope(pslope_t *slope) } } -// Recalculate dynamic slopes -void P_RunDynamicSlopes(void) { - pslope_t *slope; +/// Recalculate dynamic slopes. +void T_DynamicSlopeLine (dynplanethink_t* th) +{ + pslope_t* slope = th->slope; + line_t* srcline = th->sourceline; - for (slope = slopelist; slope; slope = slope->next) { - fixed_t zdelta; + fixed_t zdelta; - if (slope->flags & SL_NODYNAMIC) - continue; + switch(th->type) { + case DP_FRONTFLOOR: + zdelta = srcline->backsector->floorheight - srcline->frontsector->floorheight; + slope->o.z = srcline->frontsector->floorheight; + break; - switch(slope->refpos) { - case 1: // front floor - zdelta = slope->sourceline->backsector->floorheight - slope->sourceline->frontsector->floorheight; - slope->o.z = slope->sourceline->frontsector->floorheight; - break; - case 2: // front ceiling - zdelta = slope->sourceline->backsector->ceilingheight - slope->sourceline->frontsector->ceilingheight; - slope->o.z = slope->sourceline->frontsector->ceilingheight; - break; - case 3: // back floor - zdelta = slope->sourceline->frontsector->floorheight - slope->sourceline->backsector->floorheight; - slope->o.z = slope->sourceline->backsector->floorheight; - break; - case 4: // back ceiling - zdelta = slope->sourceline->frontsector->ceilingheight - slope->sourceline->backsector->ceilingheight; - slope->o.z = slope->sourceline->backsector->ceilingheight; - break; - case 5: // vertices - { - mapthing_t *mt; - size_t i; - INT32 l; - line_t *line; + case DP_FRONTCEIL: + zdelta = srcline->backsector->ceilingheight - srcline->frontsector->ceilingheight; + slope->o.z = srcline->frontsector->ceilingheight; + break; - for (i = 0; i < 3; i++) { - mt = slope->vertices[i]; - l = P_FindSpecialLineFromTag(799, mt->angle, -1); - if (l != -1) { - line = &lines[l]; - mt->z = line->frontsector->floorheight >> FRACBITS; - } - } + case DP_BACKFLOOR: + zdelta = srcline->frontsector->floorheight - srcline->backsector->floorheight; + slope->o.z = srcline->backsector->floorheight; + break; - P_ReconfigureVertexSlope(slope); - } - continue; // TODO + case DP_BACKCEIL: + zdelta = srcline->frontsector->ceilingheight - srcline->backsector->ceilingheight; + slope->o.z = srcline->backsector->ceilingheight; + break; - default: - I_Error("P_RunDynamicSlopes: slope has invalid type!"); - } + default: + return; + } - if (slope->zdelta != FixedDiv(zdelta, slope->extent)) { - slope->zdelta = FixedDiv(zdelta, slope->extent); - slope->zangle = R_PointToAngle2(0, 0, slope->extent, -zdelta); - P_CalculateSlopeNormal(slope); - } + if (slope->zdelta != FixedDiv(zdelta, th->extent)) { + slope->zdelta = FixedDiv(zdelta, th->extent); + slope->zangle = R_PointToAngle2(0, 0, th->extent, -zdelta); + P_CalculateSlopeNormal(slope); } } -// -// P_MakeSlope -// -// Alocates and fill the contents of a slope structure. -// -static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d, - const fixed_t zdelta, UINT8 flags) +/// Mapthing-defined +void T_DynamicSlopeVert (dynplanethink_t* th) { - pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL); - memset(ret, 0, sizeof(*ret)); + pslope_t* slope = th->slope; - ret->o.x = o->x; - ret->o.y = o->y; - ret->o.z = o->z; + size_t i; + INT32 l; - ret->d.x = d->x; - ret->d.y = d->y; + for (i = 0; i < 3; i++) { + l = P_FindSpecialLineFromTag(799, th->tags[i], -1); + if (l != -1) { + th->vex[i].z = lines[l].frontsector->floorheight; + } + else + th->vex[i].z = 0; + } - ret->zdelta = zdelta; + P_ReconfigureViaVertexes(slope, th->vex[0], th->vex[1], th->vex[2]); +} +static inline void P_AddDynSlopeThinker (pslope_t* slope, dynplanetype_t type, line_t* sourceline, fixed_t extent, const INT16 tags[3], const vector3_t vx[3]) +{ + dynplanethink_t* th = Z_Calloc(sizeof (*th), PU_LEVSPEC, NULL); + switch (type) + { + case DP_VERTEX: + th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeVert; + memcpy(th->tags, tags, sizeof(th->tags)); + memcpy(th->vex, vx, sizeof(th->vex)); + break; + default: + th->thinker.function.acp1 = (actionf_p1)T_DynamicSlopeLine; + th->sourceline = sourceline; + th->extent = extent; + } + + th->slope = slope; + th->type = type; + + P_AddThinker(THINK_DYNSLOPE, &th->thinker); +} + + +/// Create a new slope and add it to the slope list. +static inline pslope_t* Slope_Add (const UINT8 flags) +{ + pslope_t *ret = Z_Calloc(sizeof(pslope_t), PU_LEVEL, NULL); ret->flags = flags; - // Add to the slope list ret->next = slopelist; slopelist = ret; @@ -193,13 +229,24 @@ static pslope_t *P_MakeSlope(const vector3_t *o, const vector2_t *d, return ret; } -// -// P_GetExtent -// -// Returns the distance to the first line within the sector that -// is intersected by a line parallel to the plane normal with the point (ox, oy) -// -static fixed_t P_GetExtent(sector_t *sector, line_t *line) +/// Alocates and fill the contents of a slope structure. +static pslope_t *MakeViaVectors(const vector3_t *o, const vector2_t *d, + const fixed_t zdelta, UINT8 flags) +{ + pslope_t *ret = Slope_Add(flags); + + FV3_Copy(&ret->o, o); + FV2_Copy(&ret->d, d); + + ret->zdelta = zdelta; + + ret->flags = flags; + + return ret; +} + +/// Get furthest perpendicular distance from all vertexes in a sector for a given line. +static fixed_t GetExtent(sector_t *sector, line_t *line) { // ZDoom code reference: v3float_t = vertex_t fixed_t fardist = -FRACUNIT; @@ -232,47 +279,37 @@ static fixed_t P_GetExtent(sector_t *sector, line_t *line) return fardist; } - -// -// P_SpawnSlope_Line -// -// Creates one or more slopes based on the given line type and front/back -// sectors. -// -void P_SpawnSlope_Line(int linenum) +/// Creates one or more slopes based on the given line type and front/back sectors. +static void line_SpawnViaLine(const int linenum, const boolean spawnthinker) { // With dynamic slopes, it's fine to just leave this function as normal, // because checking to see if a slope had changed will waste more memory than // if the slope was just updated when called line_t *line = lines + linenum; - INT16 special = line->special; pslope_t *fslope = NULL, *cslope = NULL; vector3_t origin, point; vector2_t direction; fixed_t nx, ny, dz, extent; - boolean frontfloor = (special == 700 || special == 702 || special == 703); - boolean backfloor = (special == 710 || special == 712 || special == 713); - boolean frontceil = (special == 701 || special == 702 || special == 713); - boolean backceil = (special == 711 || special == 712 || special == 703); - + boolean frontfloor = line->args[0] == TMS_FRONT; + boolean backfloor = line->args[0] == TMS_BACK; + boolean frontceil = line->args[1] == TMS_FRONT; + boolean backceil = line->args[1] == TMS_BACK; UINT8 flags = 0; // Slope flags - if (line->flags & ML_NOSONIC) + if (line->args[2] & TMSL_NOPHYSICS) flags |= SL_NOPHYSICS; - if (!(line->flags & ML_NOTAILS)) - flags |= SL_NODYNAMIC; - if (line->flags & ML_NOKNUX) - flags |= SL_ANCHORVERTEX; + if (line->args[2] & TMSL_DYNAMIC) + flags |= SL_DYNAMIC; if(!frontfloor && !backfloor && !frontceil && !backceil) { - CONS_Printf("P_SpawnSlope_Line called with non-slope line special.\n"); + CONS_Printf("line_SpawnViaLine: Slope special with nothing to do.\n"); return; } if(!line->frontsector || !line->backsector) { - CONS_Debug(DBG_SETUP, "P_SpawnSlope_Line used on a line without two sides. (line number %i)\n", linenum); + CONS_Debug(DBG_SETUP, "line_SpawnViaLine: Slope special used on a line without two sides. (line number %i)\n", linenum); return; } @@ -282,6 +319,7 @@ void P_SpawnSlope_Line(int linenum) ny = -FixedDiv(line->dx, len); } + // Set origin to line's center. origin.x = line->v1->x + (line->v2->x - line->v1->x)/2; origin.y = line->v1->y + (line->v2->y - line->v1->y)/2; @@ -294,11 +332,11 @@ void P_SpawnSlope_Line(int linenum) direction.x = nx; direction.y = ny; - extent = P_GetExtent(line->frontsector, line); + extent = GetExtent(line->frontsector, line); if(extent < 0) { - CONS_Printf("P_SpawnSlope_Line failed to get frontsector extent on line number %i\n", linenum); + CONS_Printf("line_SpawnViaLine failed to get frontsector extent on line number %i\n", linenum); return; } @@ -312,104 +350,47 @@ void P_SpawnSlope_Line(int linenum) if(frontfloor) { - fixed_t highest, lowest; - size_t l; point.z = line->frontsector->floorheight; // Startz dz = FixedDiv(origin.z - point.z, extent); // Destinationz // In P_SpawnSlopeLine the origin is the centerpoint of the sourcelinedef fslope = line->frontsector->f_slope = - P_MakeSlope(&point, &direction, dz, flags); - - // Set up some shit - fslope->extent = extent; - fslope->refpos = 1; + MakeViaVectors(&point, &direction, dz, flags); // Now remember that f_slope IS a vector // fslope->o = origin 3D point 1 of the vector // fslope->d = destination 3D point 2 of the vector // fslope->normal is a 3D line perpendicular to the 3D vector - // Sync the linedata of the line that started this slope - // TODO: Anything special for control sector based slopes later? - fslope->sourceline = line; - - // To find the real highz/lowz of a slope, you need to check all the vertexes - // in the slope's sector with P_GetZAt to get the REAL lowz & highz - // Although these slopes are set by floorheights the ANGLE is what a slope is, - // so technically any slope can extend on forever (they are just bound by sectors) - // *You can use sourceline as a reference to see if two slopes really are the same - - // Default points for high and low - highest = point.z > origin.z ? point.z : origin.z; - lowest = point.z < origin.z ? point.z : origin.z; - - // Now check to see what the REAL high and low points of the slope inside the sector - // TODO: Is this really needed outside of FOFs? -Red - - for (l = 0; l < line->frontsector->linecount; l++) - { - fixed_t height = P_GetZAt(line->frontsector->f_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y); - - if (height > highest) - highest = height; - - if (height < lowest) - lowest = height; - } - - // Sets extra clipping data for the frontsector's slope - fslope->highz = highest; - fslope->lowz = lowest; + P_CalculateLineSlopeHighLow(fslope, line, false, false); fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(fslope); + + if (spawnthinker && (flags & SL_DYNAMIC)) + P_AddDynSlopeThinker(fslope, DP_FRONTFLOOR, line, extent, NULL, NULL); } if(frontceil) { - fixed_t highest, lowest; - size_t l; origin.z = line->backsector->ceilingheight; point.z = line->frontsector->ceilingheight; dz = FixedDiv(origin.z - point.z, extent); cslope = line->frontsector->c_slope = - P_MakeSlope(&point, &direction, dz, flags); + MakeViaVectors(&point, &direction, dz, flags); - // Set up some shit - cslope->extent = extent; - cslope->refpos = 2; - - // Sync the linedata of the line that started this slope - // TODO: Anything special for control sector based slopes later? - cslope->sourceline = line; - - // Remember the way the slope is formed - highest = point.z > origin.z ? point.z : origin.z; - lowest = point.z < origin.z ? point.z : origin.z; - - for (l = 0; l < line->frontsector->linecount; l++) - { - fixed_t height = P_GetZAt(line->frontsector->c_slope, line->frontsector->lines[l]->v1->x, line->frontsector->lines[l]->v1->y); - - if (height > highest) - highest = height; - - if (height < lowest) - lowest = height; - } - - // This line special sets extra clipping data for the frontsector's slope - cslope->highz = highest; - cslope->lowz = lowest; + P_CalculateLineSlopeHighLow(cslope, line, true, false); cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(cslope); + + if (spawnthinker && (flags & SL_DYNAMIC)) + P_AddDynSlopeThinker(cslope, DP_FRONTCEIL, line, extent, NULL, NULL); } } if(backfloor || backceil) @@ -421,11 +402,11 @@ void P_SpawnSlope_Line(int linenum) direction.x = -nx; direction.y = -ny; - extent = P_GetExtent(line->backsector, line); + extent = GetExtent(line->backsector, line); if(extent < 0) { - CONS_Printf("P_SpawnSlope_Line failed to get backsector extent on line number %i\n", linenum); + CONS_Printf("line_SpawnViaLine failed to get backsector extent on line number %i\n", linenum); return; } @@ -437,88 +418,40 @@ void P_SpawnSlope_Line(int linenum) if(backfloor) { - fixed_t highest, lowest; - size_t l; point.z = line->backsector->floorheight; dz = FixedDiv(origin.z - point.z, extent); fslope = line->backsector->f_slope = - P_MakeSlope(&point, &direction, dz, flags); + MakeViaVectors(&point, &direction, dz, flags); - // Set up some shit - fslope->extent = extent; - fslope->refpos = 3; - - // Sync the linedata of the line that started this slope - // TODO: Anything special for control sector based slopes later? - fslope->sourceline = line; - - // Remember the way the slope is formed - highest = point.z > origin.z ? point.z : origin.z; - lowest = point.z < origin.z ? point.z : origin.z; - - for (l = 0; l < line->backsector->linecount; l++) - { - fixed_t height = P_GetZAt(line->backsector->f_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y); - - if (height > highest) - highest = height; - - if (height < lowest) - lowest = height; - } - - // This line special sets extra clipping data for the frontsector's slope - fslope->highz = highest; - fslope->lowz = lowest; + P_CalculateLineSlopeHighLow(fslope, line, false, true); fslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); fslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(fslope); + + if (spawnthinker && (flags & SL_DYNAMIC)) + P_AddDynSlopeThinker(fslope, DP_BACKFLOOR, line, extent, NULL, NULL); } if(backceil) { - fixed_t highest, lowest; - size_t l; origin.z = line->frontsector->ceilingheight; point.z = line->backsector->ceilingheight; dz = FixedDiv(origin.z - point.z, extent); cslope = line->backsector->c_slope = - P_MakeSlope(&point, &direction, dz, flags); + MakeViaVectors(&point, &direction, dz, flags); - // Set up some shit - cslope->extent = extent; - cslope->refpos = 4; - - // Sync the linedata of the line that started this slope - // TODO: Anything special for control sector based slopes later? - cslope->sourceline = line; - - // Remember the way the slope is formed - highest = point.z > origin.z ? point.z : origin.z; - lowest = point.z < origin.z ? point.z : origin.z; - - for (l = 0; l < line->backsector->linecount; l++) - { - fixed_t height = P_GetZAt(line->backsector->c_slope, line->backsector->lines[l]->v1->x, line->backsector->lines[l]->v1->y); - - if (height > highest) - highest = height; - - if (height < lowest) - lowest = height; - } - - // This line special sets extra clipping data for the backsector's slope - cslope->highz = highest; - cslope->lowz = lowest; + P_CalculateLineSlopeHighLow(cslope, line, true, true); cslope->zangle = R_PointToAngle2(0, origin.z, extent, point.z); cslope->xydirection = R_PointToAngle2(origin.x, origin.y, point.x, point.y); P_CalculateSlopeNormal(cslope); + + if (spawnthinker && (flags & SL_DYNAMIC)) + P_AddDynSlopeThinker(cslope, DP_BACKCEIL, line, extent, NULL, NULL); } } @@ -526,64 +459,181 @@ void P_SpawnSlope_Line(int linenum) return; } -// -// P_NewVertexSlope -// -// Creates a new slope from three vertices with the specified IDs -// -static pslope_t *P_NewVertexSlope(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags) +/// Creates a new slope from three mapthings with the specified IDs +static pslope_t *MakeViaMapthings(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flags, const boolean spawnthinker) { size_t i; - mapthing_t *mt = mapthings; + mapthing_t* mt = mapthings; + mapthing_t* vertices[3] = {0}; + INT16 tags[3] = {tag1, tag2, tag3}; - pslope_t *ret = Z_Malloc(sizeof(pslope_t), PU_LEVEL, NULL); - memset(ret, 0, sizeof(*ret)); - - // Start by setting flags - ret->flags = flags; - - // Now set up the vertex list - ret->vertices = Z_Malloc(3*sizeof(mapthing_t), PU_LEVEL, NULL); - memset(ret->vertices, 0, 3*sizeof(mapthing_t)); + vector3_t vx[3]; + pslope_t* ret = Slope_Add(flags); // And... look for the vertices in question. for (i = 0; i < nummapthings; i++, mt++) { if (mt->type != 750) // Haha, I'm hijacking the old Chaos Spawn thingtype for something! continue; - if (!ret->vertices[0] && mt->angle == tag1) - ret->vertices[0] = mt; - else if (!ret->vertices[1] && mt->angle == tag2) - ret->vertices[1] = mt; - else if (!ret->vertices[2] && mt->angle == tag3) - ret->vertices[2] = mt; + if (!vertices[0] && mt->tag == tag1) + vertices[0] = mt; + else if (!vertices[1] && mt->tag == tag2) + vertices[1] = mt; + else if (!vertices[2] && mt->tag == tag3) + vertices[2] = mt; } // Now set heights for each vertex, because they haven't been set yet for (i = 0; i < 3; i++) { - mt = ret->vertices[i]; + mt = vertices[i]; if (!mt) // If a vertex wasn't found, it's game over. There's nothing you can do to recover (except maybe try and kill the slope instead - TODO?) - I_Error("P_NewVertexSlope: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1); - if (mt->extrainfo) - mt->z = mt->options; - else - mt->z = (R_PointInSubsector(mt->x << FRACBITS, mt->y << FRACBITS)->sector->floorheight >> FRACBITS) + (mt->options >> ZSHIFT); + I_Error("MakeViaMapthings: Slope vertex %s (for linedef tag %d) not found!", sizeu1(i), tag1); + vx[i].x = mt->x << FRACBITS; + vx[i].y = mt->y << FRACBITS; + vx[i].z = mt->z << FRACBITS; + if (!mt->extrainfo) + vx[i].z += R_PointInSubsector(vx[i].x, vx[i].y)->sector->floorheight; } - P_ReconfigureVertexSlope(ret); - ret->refpos = 5; + P_ReconfigureViaVertexes(ret, vx[0], vx[1], vx[2]); - // Add to the slope list - ret->next = slopelist; - slopelist = ret; - - slopecount++; - ret->id = slopecount; + if (spawnthinker && (flags & SL_DYNAMIC)) + P_AddDynSlopeThinker(ret, DP_VERTEX, NULL, 0, tags, vx); return ret; } +/// Create vertex based slopes using tagged mapthings. +static void line_SpawnViaMapthingVertexes(const int linenum, const boolean spawnthinker) +{ + line_t *line = lines + linenum; + side_t *side; + pslope_t **slopetoset; + UINT16 tag1 = line->args[1]; + UINT16 tag2 = line->args[2]; + UINT16 tag3 = line->args[3]; + UINT8 flags = 0; // Slope flags + if (line->args[4] & TMSL_NOPHYSICS) + flags |= SL_NOPHYSICS; + if (line->args[4] & TMSL_DYNAMIC) + flags |= SL_DYNAMIC; + switch(line->args[0]) + { + case TMSP_FRONTFLOOR: + slopetoset = &line->frontsector->f_slope; + side = &sides[line->sidenum[0]]; + break; + case TMSP_FRONTCEILING: + slopetoset = &line->frontsector->c_slope; + side = &sides[line->sidenum[0]]; + break; + case TMSP_BACKFLOOR: + slopetoset = &line->backsector->f_slope; + side = &sides[line->sidenum[1]]; + break; + case TMSP_BACKCEILING: + slopetoset = &line->backsector->c_slope; + side = &sides[line->sidenum[1]]; + default: + return; + } + + *slopetoset = MakeViaMapthings(tag1, tag2, tag3, flags, spawnthinker); + + side->sector->hasslope = true; +} + +/// Spawn textmap vertex slopes. +static void SpawnVertexSlopes(void) +{ + line_t *l1, *l2; + sector_t* sc; + vertex_t *v1, *v2, *v3; + size_t i; + for (i = 0, sc = sectors; i < numsectors; i++, sc++) + { + // The vertex slopes only work for 3-vertex sectors (and thus 3-sided sectors). + if (sc->linecount != 3) + continue; + + l1 = sc->lines[0]; + l2 = sc->lines[1]; + + // Determine the vertexes. + v1 = l1->v1; + v2 = l1->v2; + if ((l2->v1 != v1) && (l2->v1 != v2)) + v3 = l2->v1; + else + v3 = l2->v2; + + if (v1->floorzset || v2->floorzset || v3->floorzset) + { + vector3_t vtx[3] = { + {v1->x, v1->y, v1->floorzset ? v1->floorz : sc->floorheight}, + {v2->x, v2->y, v2->floorzset ? v2->floorz : sc->floorheight}, + {v3->x, v3->y, v3->floorzset ? v3->floorz : sc->floorheight}}; + pslope_t *slop = Slope_Add(0); + sc->f_slope = slop; + sc->hasslope = true; + P_ReconfigureViaVertexes(slop, vtx[0], vtx[1], vtx[2]); + } + + if (v1->ceilingzset || v2->ceilingzset || v3->ceilingzset) + { + vector3_t vtx[3] = { + {v1->x, v1->y, v1->ceilingzset ? v1->ceilingz : sc->ceilingheight}, + {v2->x, v2->y, v2->ceilingzset ? v2->ceilingz : sc->ceilingheight}, + {v3->x, v3->y, v3->ceilingzset ? v3->ceilingz : sc->ceilingheight}}; + pslope_t *slop = Slope_Add(0); + sc->c_slope = slop; + sc->hasslope = true; + P_ReconfigureViaVertexes(slop, vtx[0], vtx[1], vtx[2]); + } + } +} + +static boolean P_SetSlopeFromTag(sector_t *sec, INT32 tag, boolean ceiling) +{ + INT32 i; + pslope_t **secslope = ceiling ? &sec->c_slope : &sec->f_slope; + + if (!tag || *secslope) + return false; + + for (i = -1; (i = P_FindSectorFromTag(tag, i)) >= 0;) + { + pslope_t *srcslope = ceiling ? sectors[i].c_slope : sectors[i].f_slope; + if (srcslope) + { + *secslope = srcslope; + return true; + } + } + return false; +} + +static boolean P_CopySlope(pslope_t **toslope, pslope_t *fromslope) +{ + if (*toslope || !fromslope) + return true; + + *toslope = fromslope; + return true; +} + +static void P_UpdateHasSlope(sector_t *sec) +{ + size_t i; + + sec->hasslope = true; + + // if this is an FOF control sector, make sure any target sectors also are marked as having slopes + if (sec->numattached) + for (i = 0; i < sec->numattached; i++) + sectors[sec->attached[i]].hasslope = true; +} // // P_CopySectorSlope @@ -592,23 +642,34 @@ static pslope_t *P_NewVertexSlope(INT16 tag1, INT16 tag2, INT16 tag3, UINT8 flag // void P_CopySectorSlope(line_t *line) { - sector_t *fsec = line->frontsector; - int i, special = line->special; + sector_t *fsec = line->frontsector; + sector_t *bsec = line->backsector; + boolean setfront = false; + boolean setback = false; - // Check for copy linedefs - for(i = -1; (i = P_FindSectorFromLineTag(line, i)) >= 0;) - { - sector_t *srcsec = sectors + i; + setfront |= P_SetSlopeFromTag(fsec, line->args[0], false); + setfront |= P_SetSlopeFromTag(fsec, line->args[1], true); + if (bsec) + { + setback |= P_SetSlopeFromTag(bsec, line->args[2], false); + setback |= P_SetSlopeFromTag(bsec, line->args[3], true); - if((special - 719) & 1 && !fsec->f_slope && srcsec->f_slope) - fsec->f_slope = srcsec->f_slope; //P_CopySlope(srcsec->f_slope); - if((special - 719) & 2 && !fsec->c_slope && srcsec->c_slope) - fsec->c_slope = srcsec->c_slope; //P_CopySlope(srcsec->c_slope); - } + if (line->args[4] & TMSC_FRONTTOBACKFLOOR) + setback |= P_CopySlope(&bsec->f_slope, fsec->f_slope); + if (line->args[4] & TMSC_BACKTOFRONTFLOOR) + setfront |= P_CopySlope(&fsec->f_slope, bsec->f_slope); + if (line->args[4] & TMSC_FRONTTOBACKCEILING) + setback |= P_CopySlope(&bsec->c_slope, fsec->c_slope); + if (line->args[4] & TMSC_BACKTOFRONTCEILING) + setfront |= P_CopySlope(&fsec->c_slope, bsec->c_slope); + } - fsec->hasslope = true; + if (setfront) + P_UpdateHasSlope(fsec); + if (setback) + P_UpdateHasSlope(bsec); - line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef + line->special = 0; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef } // @@ -623,109 +684,27 @@ pslope_t *P_SlopeById(UINT16 id) return ret; } -// Reset the dynamic slopes pointer, and read all of the fancy schmancy slopes -void P_ResetDynamicSlopes(void) { +/// Initializes and reads the slopes from the map data. +void P_SpawnSlopes(const boolean fromsave) { size_t i; -#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning - boolean warned = false; -#endif slopelist = NULL; slopecount = 0; + /// Generates vertex slopes. + SpawnVertexSlopes(); + /// Generates line special-defined slopes. for (i = 0; i < numlines; i++) { switch (lines[i].special) { -#ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning -#define WARNME if (!warned) {warned = true; CONS_Alert(CONS_WARNING, "This level uses old slope specials.\nA conversion will be needed before 2.2's release.\n");} - case 386: - case 387: - case 388: - lines[i].special += 700-386; - WARNME - P_SpawnSlope_Line(i); - break; - - case 389: - case 390: - case 391: - case 392: - lines[i].special += 710-389; - WARNME - P_SpawnSlope_Line(i); - break; - - case 393: - lines[i].special = 703; - WARNME - P_SpawnSlope_Line(i); - break; - - case 394: - case 395: - case 396: - lines[i].special += 720-394; - WARNME - break; - -#endif - case 700: - case 701: - case 702: - case 703: - case 710: - case 711: - case 712: - case 713: - P_SpawnSlope_Line(i); + line_SpawnViaLine(i, !fromsave); break; case 704: - case 705: - case 714: - case 715: - { - pslope_t **slopetoset; - size_t which = lines[i].special; - - UINT8 flags = SL_VERTEXSLOPE; - if (lines[i].flags & ML_NOSONIC) - flags |= SL_NOPHYSICS; - if (!(lines[i].flags & ML_NOTAILS)) - flags |= SL_NODYNAMIC; - - if (which == 704) - { - slopetoset = &lines[i].frontsector->f_slope; - which = 0; - } - else if (which == 705) - { - slopetoset = &lines[i].frontsector->c_slope; - which = 0; - } - else if (which == 714) - { - slopetoset = &lines[i].backsector->f_slope; - which = 1; - } - else // 715 - { - slopetoset = &lines[i].backsector->c_slope; - which = 1; - } - - if (lines[i].flags & ML_NOKNUX) - *slopetoset = P_NewVertexSlope(lines[i].tag, sides[lines[i].sidenum[which]].textureoffset >> FRACBITS, - sides[lines[i].sidenum[which]].rowoffset >> FRACBITS, flags); - else - *slopetoset = P_NewVertexSlope(lines[i].tag, lines[i].tag, lines[i].tag, flags); - - sides[lines[i].sidenum[which]].sector->hasslope = true; - } + line_SpawnViaMapthingVertexes(i, !fromsave); break; default: @@ -733,14 +712,20 @@ void P_ResetDynamicSlopes(void) { } } + // jart + + /// Build list of slope anchors--faster searching. + P_BuildSlopeAnchorList(); + + /// Setup anchor based slopes. + P_SetupAnchoredSlopes(); + /// Copies slopes from tagged sectors via line specials. /// \note Doesn't actually copy, but instead they share the same pointers. for (i = 0; i < numlines; i++) switch (lines[i].special) { case 720: - case 721: - case 722: P_CopySectorSlope(&lines[i]); default: break; @@ -752,17 +737,49 @@ void P_ResetDynamicSlopes(void) { // Various utilities related to slopes // -// -// P_GetZAt -// // Returns the height of the sloped plane at (x, y) as a fixed_t -// -fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y) +fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y) { - fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) + - FixedMul(y - slope->o.y, slope->d.y); + fixed_t dist = FixedMul(x - slope->o.x, slope->d.x) + + FixedMul(y - slope->o.y, slope->d.y); - return slope->o.z + FixedMul(dist, slope->zdelta); + return slope->o.z + FixedMul(dist, slope->zdelta); +} + +// Like P_GetSlopeZAt but falls back to z if slope is NULL +fixed_t P_GetZAt(const pslope_t *slope, fixed_t x, fixed_t y, fixed_t z) +{ + return slope ? P_GetSlopeZAt(slope, x, y) : z; +} + +// Returns the height of the sector floor at (x, y) +fixed_t P_GetSectorFloorZAt(const sector_t *sector, fixed_t x, fixed_t y) +{ + return sector->f_slope ? P_GetSlopeZAt(sector->f_slope, x, y) : sector->floorheight; +} + +// Returns the height of the sector ceiling at (x, y) +fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y) +{ + return sector->c_slope ? P_GetSlopeZAt(sector->c_slope, x, y) : sector->ceilingheight; +} + +// Returns the height of the FOF top at (x, y) +fixed_t P_GetFFloorTopZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y) +{ + return *ffloor->t_slope ? P_GetSlopeZAt(*ffloor->t_slope, x, y) : *ffloor->topheight; +} + +// Returns the height of the FOF bottom at (x, y) +fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y) +{ + return *ffloor->b_slope ? P_GetSlopeZAt(*ffloor->b_slope, x, y) : *ffloor->bottomheight; +} + +// Returns the height of the light list at (x, y) +fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y) +{ + return light->slope ? P_GetSlopeZAt(light->slope, x, y) : light->height; } // @@ -804,7 +821,9 @@ void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope) // Handles slope ejection for objects void P_SlopeLaunch(mobj_t *mo) { - if (!(mo->standingslope->flags & SL_NOPHYSICS)) // If there's physics, time for launching. + if (!(mo->standingslope->flags & SL_NOPHYSICS) // If there's physics, time for launching. + && (mo->standingslope->normal.x != 0 + || mo->standingslope->normal.y != 0)) { // Double the pre-rotation Z, then halve the post-rotation Z. This reduces the // vertical launch given from slopes while increasing the horizontal launch @@ -832,20 +851,57 @@ void P_SlopeLaunch(mobj_t *mo) //CONS_Printf("Launched off of slope.\n"); mo->standingslope = NULL; + + if (mo->player) + mo->player->powers[pw_justlaunched] = 1; +} + +// +// P_GetWallTransferMomZ +// +// It would be nice to have a single function that does everything necessary for slope-to-wall transfer. +// However, it needs to be seperated out in P_XYMovement to take into account momentum before and after hitting the wall. +// This just performs the necessary calculations for getting the base vertical momentum; the horizontal is already reasonably calculated by P_SlideMove. +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope) +{ + vector3_t slopemom, axis; + angle_t ang; + + if (mo->standingslope->flags & SL_NOPHYSICS) + return 0; + + // If there's physics, time for launching. + // Doesn't kill the vertical momentum as much as P_SlopeLaunch does. + ang = slope->zangle + ANG15*((slope->zangle > 0) ? 1 : -1); + if (ang > ANGLE_90 && ang < ANGLE_180) + ang = ((slope->zangle > 0) ? ANGLE_90 : InvAngle(ANGLE_90)); // hard cap of directly upwards + + slopemom.x = mo->momx; + slopemom.y = mo->momy; + slopemom.z = 3*(mo->momz/2); + + axis.x = -slope->d.y; + axis.y = slope->d.x; + axis.z = 0; + + FV3_Rotate(&slopemom, &axis, ang >> ANGLETOFINESHIFT); + + return 2*(slopemom.z/3); } // Function to help handle landing on slopes void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) { vector3_t mom; // Ditto. - - if (slope->flags & SL_NOPHYSICS) { // No physics, no need to make anything complicated. - if (P_MobjFlip(thing)*(thing->momz) < 0) { // falling, land on slope - thing->momz = -P_MobjFlip(thing); + if (slope->flags & SL_NOPHYSICS || (slope->normal.x == 0 && slope->normal.y == 0)) { // No physics, no need to make anything complicated. + if (P_MobjFlip(thing)*(thing->momz) < 0) // falling, land on slope + { thing->standingslope = slope; #ifdef HWRENDER thing->modeltilt = thing->standingslope; #endif + if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) + thing->momz = -P_MobjFlip(thing); } return; } @@ -859,12 +915,12 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope) if (P_MobjFlip(thing)*mom.z < 0) { // falling, land on slope thing->momx = mom.x; thing->momy = mom.y; - thing->momz = -P_MobjFlip(thing); - thing->standingslope = slope; #ifdef HWRENDER thing->modeltilt = thing->standingslope; #endif + if (!thing->player || !(thing->player->pflags & PF_BOUNCING)) + thing->momz = -P_MobjFlip(thing); } } @@ -889,15 +945,15 @@ void P_ButteredSlope(mobj_t *mo) return; // Changed in kart to only not apply physics on very slight slopes (I think about 4 degree angles) - if (abs(mo->standingslope->zdelta) < FRACUNIT/21 && !(mo->player->pflags & PF_SPINNING)) - return; // Don't slide on non-steep slopes unless spinning + if (abs(mo->standingslope->zdelta) < FRACUNIT/21) + return; // Don't slide on non-steep slopes // This only means you can be stopped on slopes that aren't steeper than 45 degrees if (abs(mo->standingslope->zdelta) < FRACUNIT/2 && !(mo->player->rmomx || mo->player->rmomy)) return; // Allow the player to stand still on slopes below a certain steepness } - thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 4 / 5 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); + thrust = FINESINE(mo->standingslope->zangle>>ANGLETOFINESHIFT) * 5 / 4 * (mo->eflags & MFE_VERTICALFLIP ? 1 : -1); if (mo->player) { fixed_t mult = FRACUNIT; @@ -907,7 +963,7 @@ void P_ButteredSlope(mobj_t *mo) if (P_MobjFlip(mo) * mo->standingslope->zdelta < 0) angle ^= ANGLE_180; - mult = FRACUNIT + (FRACUNIT + FINECOSINE(angle>>ANGLETOFINESHIFT))*3/2; + mult = FRACUNIT + (FRACUNIT + FINECOSINE(angle>>ANGLETOFINESHIFT))*4/3; } thrust = FixedMul(thrust, mult); @@ -922,5 +978,5 @@ void P_ButteredSlope(mobj_t *mo) P_Thrust(mo, mo->standingslope->xydirection, thrust); } -// EOF -#endif // #ifdef ESLOPE +// jart +#include "slope_anchors.c" diff --git a/src/p_slopes.h b/src/p_slopes.h index 708a9107d..ef8cb5886 100644 --- a/src/p_slopes.h +++ b/src/p_slopes.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2004 by Stephen McGranahan -// Copyright (C) 2015-2018 by Sonic Team Junior. +// Copyright (C) 2015-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -13,14 +13,45 @@ #ifndef P_SLOPES_H__ #define P_SLOPES_H__ -#ifdef ESLOPE +#include "m_fixed.h" // Vectors + +extern pslope_t *slopelist; +extern UINT16 slopecount; + +typedef enum +{ + TMSP_FRONTFLOOR, + TMSP_FRONTCEILING, + TMSP_BACKFLOOR, + TMSP_BACKCEILING, +} textmapslopeplane_t; + +typedef enum +{ + TMSC_FRONTTOBACKFLOOR = 1, + TMSC_BACKTOFRONTFLOOR = 1<<1, + TMSC_FRONTTOBACKCEILING = 1<<2, + TMSC_BACKTOFRONTCEILING = 1<<3, +} textmapslopecopy_t; + +typedef enum +{ + TMS_NONE, + TMS_FRONT, + TMS_BACK, +} textmapside_t; + +typedef enum +{ + TMSL_NOPHYSICS = 1, + TMSL_DYNAMIC = 2, +} textmapslopeflags_t; + +void P_LinkSlopeThinkers (void); + void P_CalculateSlopeNormal(pslope_t *slope); -void P_ResetDynamicSlopes(void); -void P_RunDynamicSlopes(void); -// P_SpawnSlope_Line -// Creates one or more slopes based on the given line type and front/back -// sectors. -void P_SpawnSlope_Line(int linenum); +void P_ReconfigureViaVertexes(pslope_t *slope, const vector3_t v1, const vector3_t v2, const vector3_t v3); +void P_SpawnSlopes(const boolean fromsave); // // P_CopySectorSlope @@ -32,16 +63,57 @@ void P_CopySectorSlope(line_t *line); pslope_t *P_SlopeById(UINT16 id); // Returns the height of the sloped plane at (x, y) as a fixed_t -fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y); +fixed_t P_GetSlopeZAt(const pslope_t *slope, fixed_t x, fixed_t y); + +// Like P_GetSlopeZAt but falls back to z if slope is NULL +fixed_t P_GetZAt(const pslope_t *slope, fixed_t x, fixed_t y, fixed_t z); + +// Returns the height of the sector at (x, y) +fixed_t P_GetSectorFloorZAt (const sector_t *sector, fixed_t x, fixed_t y); +fixed_t P_GetSectorCeilingZAt(const sector_t *sector, fixed_t x, fixed_t y); + +// Returns the height of the FOF at (x, y) +fixed_t P_GetFFloorTopZAt (const ffloor_t *ffloor, fixed_t x, fixed_t y); +fixed_t P_GetFFloorBottomZAt(const ffloor_t *ffloor, fixed_t x, fixed_t y); + +// Returns the height of the light list at (x, y) +fixed_t P_GetLightZAt(const lightlist_t *light, fixed_t x, fixed_t y); // Lots of physics-based bullshit void P_QuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_ReverseQuantizeMomentumToSlope(vector3_t *momentum, pslope_t *slope); void P_SlopeLaunch(mobj_t *mo); +fixed_t P_GetWallTransferMomZ(mobj_t *mo, pslope_t *slope); void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope); void P_ButteredSlope(mobj_t *mo); -#endif -// EOF -#endif // #ifdef ESLOPE +/// Dynamic plane type enum for the thinker. Will have a different functionality depending on this. +typedef enum { + DP_FRONTFLOOR, + DP_FRONTCEIL, + DP_BACKFLOOR, + DP_BACKCEIL, + DP_VERTEX +} dynplanetype_t; + +/// Permit slopes to be dynamically altered through a thinker. +typedef struct +{ + thinker_t thinker; + + pslope_t* slope; + dynplanetype_t type; + + // Used by line slopes. + line_t* sourceline; + fixed_t extent; + + // Used by mapthing vertex slopes. + INT16 tags[3]; + vector3_t vex[3]; +} dynplanethink_t; + +void T_DynamicSlopeLine (dynplanethink_t* th); +void T_DynamicSlopeVert (dynplanethink_t* th); +#endif // #ifndef P_SLOPES_H__ diff --git a/src/p_spec.c b/src/p_spec.c index d54737bc1..81f1526d4 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -20,6 +20,7 @@ #include "p_local.h" #include "p_setup.h" // levelflats for flat animation #include "r_data.h" +#include "r_textures.h" #include "m_random.h" #include "p_mobj.h" #include "i_system.h" @@ -31,11 +32,15 @@ #include "p_polyobj.h" #include "p_slopes.h" #include "hu_stuff.h" +#include "v_video.h" // V_ALLOWLOWERCASE #include "m_misc.h" #include "m_cond.h" //unlock triggers #include "lua_hook.h" // LUAh_LinedefExecute +#include "f_finale.h" // control text prompt +#include "r_skins.h" // skins -#include "k_kart.h" // SRB2kart +// SRB2kart +#include "k_kart.h" #include "console.h" // CON_LogMessage #include "k_respawn.h" @@ -44,13 +49,11 @@ #endif // Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog -#ifdef _WIN32_WCE -#define AVOID_ERRNO -#else #include -#endif -mobj_t *skyboxmo[2]; +mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint +mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs +mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs // Amount (dx, dy) vector linedef is shifted right to get scroll amount #define SCROLL_SHIFT 5 @@ -76,7 +79,7 @@ typedef struct #endif /** Animated texture definition. - * Used for ::harddefs and for loading an ANIMATED lump from a wad. + * Used for loading an ANIMDEFS lump from a wad. * * Animations are defined by the first and last frame (i.e., flat or texture). * The animation sequence uses all flats between the start and end entry, in @@ -102,19 +105,30 @@ typedef struct thinker_t **thinkers; } thinkerlist_t; -static void P_SearchForDisableLinedefs(void); static void P_SpawnScrollers(void); static void P_SpawnFriction(void); static void P_SpawnPushers(void); static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t *source, INT32 affectee, INT32 referrer, INT32 exclusive, INT32 slider); //SoM: 3/9/2000 static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t offset, INT32 line, INT32 sourceline); +static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize); +#define P_RemoveFakeFloorFader(l) P_ResetFakeFloorFader(l, NULL, false); +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha); +static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, + INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha); +static void P_ResetColormapFader(sector_t *sector); +static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, + boolean ticbased, INT32 duration); static void P_AddBlockThinker(sector_t *sec, line_t *sourceline); -static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline); +static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline); //static void P_AddBridgeThinker(line_t *sourceline, sector_t *sec); static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinkerlist_t *secthinkers); static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec); static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 referrer); -static void P_AddSpikeThinker(sector_t *sec, INT32 referrer); +static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse); //SoM: 3/7/2000: New sturcture without limits. @@ -122,104 +136,6 @@ static anim_t *lastanim; static anim_t *anims = NULL; /// \todo free leak static size_t maxanims; -// -// P_InitPicAnims -// -/** Hardcoded animation sequences. - * Used if no ANIMATED lump is found in a loaded wad. - */ -static animdef_t harddefs[] = -{ - // flat animations. - {false, "LITEY3", "LITEY1", 4}, - {false, "FWATER16", "FWATER1", 4}, - {false, "BWATER16", "BWATER01", 4}, - {false, "LWATER16", "LWATER1", 4}, - {false, "WATER7", "WATER0", 4}, - {false, "LAVA4", "LAVA1", 8}, - {false, "DLAVA4", "DLAVA1", 8}, - {false, "RLAVA8", "RLAVA1", 8}, - {false, "LITER3", "LITER1", 8}, - {false, "SURF08", "SURF01", 4}, - - {false, "CHEMG16", "CHEMG01", 4}, // THZ Chemical gunk - {false, "GOOP16", "GOOP01", 4}, // Green chemical gunk - {false, "OIL16", "OIL01", 4}, // Oil - {false, "THZBOXF4", "THZBOXF1", 2}, // Moved up with the flats - {false, "ALTBOXF4", "ALTBOXF1", 2}, - - {false, "LITEB3", "LITEB1", 4}, - {false, "LITEN3", "LITEN1", 4}, - {false, "ACZRFL1H", "ACZRFL1A", 4}, - {false, "ACZRFL2H", "ACZRFL2A", 4}, - {false, "EGRIDF3", "EGRIDF1", 4}, - {false, "ERZFAN4", "ERZFAN1", 1}, - {false, "ERZFANR4", "ERZFANR1", 1}, - {false, "DISCO4", "DISCO1", 15}, - - // animated textures - {true, "GFALL4", "GFALL1", 2}, // Short waterfall - {true, "CFALL4", "CFALL1", 2}, // Long waterfall - {true, "TFALL4", "TFALL1", 2}, // THZ Chemical fall - {true, "AFALL4", "AFALL1", 2}, // Green Chemical fall - {true, "QFALL4", "QFALL1", 2}, // Quicksand fall - {true, "Q2FALL4", "Q2FALL1", 2}, - {true, "Q3FALL4", "Q3FALL1", 2}, - {true, "Q4FALL4", "Q4FALL1", 2}, - {true, "Q5FALL4", "Q5FALL1", 2}, - {true, "Q6FALL4", "Q6FALL1", 2}, - {true, "Q7FALL4", "Q7FALL1", 2}, - {true, "LFALL4", "LFALL1", 2}, - {true, "MFALL4", "MFALL1", 2}, - {true, "OFALL4", "OFALL1", 2}, - {true, "DLAVA4", "DLAVA1", 8}, - {true, "ERZLASA2", "ERZLASA1", 1}, - {true, "ERZLASB4", "ERZLASB1", 1}, - {true, "ERZLASC4", "ERZLASC1", 1}, - {true, "THZBOX04", "THZBOX01", 2}, - {true, "ALTBOX04", "ALTBOX01", 2}, - {true, "SFALL4", "SFALL1", 4}, // Lava fall - {true, "RVZFALL8", "RVZFALL1", 4}, - {true, "BFALL4", "BFALL1", 2}, // HPZ waterfall - {true, "GREYW3", "GREYW1", 4}, - {true, "BLUEW3", "BLUEW1", 4}, - {true, "COMP6", "COMP4", 4}, - {true, "RED3", "RED1", 4}, - {true, "YEL3", "YEL1", 4}, - {true, "ACWRFL1D", "ACWRFL1A", 1}, - {true, "ACWRFL2D", "ACWRFL2A", 1}, - {true, "ACWRFL3D", "ACWRFL3A", 1}, - {true, "ACWRFL4D", "ACWRFL4A", 1}, - {true, "ACWRP1D", "ACWRP1A", 1}, - {true, "ACWRP2D", "ACWRP2A", 1}, - {true, "ACZRP1D", "ACZRP1A", 1}, - {true, "ACZRP2D", "ACZRP2A", 1}, - {true, "OILFALL4", "OILFALL1", 2}, - {true, "SOLFALL4", "SOLFALL1", 2}, - {true, "DOWN1C", "DOWN1A", 4}, - {true, "DOWN2C", "DOWN2A", 4}, - {true, "DOWN3D", "DOWN3A", 4}, - {true, "DOWN4C", "DOWN4A", 4}, - {true, "DOWN5C", "DOWN5A", 4}, - {true, "UP1C", "UP1A", 4}, - {true, "UP2C", "UP2A", 4}, - {true, "UP3D", "UP3A", 4}, - {true, "UP4C", "UP4A", 4}, - {true, "UP5C", "UP5A", 4}, - {true, "EGRID3", "EGRID1", 4}, - {true, "ERFANW4", "ERFANW1", 1}, - {true, "ERFANX4", "ERFANX1", 1}, - {true, "DISCOD4", "DISCOD1", 15}, - {true, "DANCE4", "DANCE1", 8}, - {true, "SKY135", "SKY132", 2}, - {true, "APPLMS4", "APPLMS1", 2}, - {true, "APBOXW3", "APBOXW1", 2}, - {true, "ERZLAZC4", "ERZLAZC1", 4}, - - // End of line - { -1, "", "", 0}, -}; - // Animating line specials // Init animated textures @@ -227,13 +143,20 @@ static animdef_t harddefs[] = static animdef_t *animdefs = NULL; +// Increase the size of animdefs to make room for a new animation definition +static void GrowAnimDefs(void) +{ + maxanims++; + animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); +} + // A prototype; here instead of p_spec.h, so they're "private" void P_ParseANIMDEFSLump(INT32 wadNum, UINT16 lumpnum); void P_ParseAnimationDefintion(SINT8 istexture); /** Sets up texture and flat animations. * - * Converts an ::animdef_t array loaded from ::harddefs or a lump into + * Converts an ::animdef_t array loaded from a lump into * ::anim_t format. * * Issues an error if any animation cycles are invalid. @@ -245,73 +168,38 @@ void P_InitPicAnims(void) { // Init animation INT32 w; // WAD - UINT8 *animatedLump; - UINT8 *currentPos; size_t i; I_Assert(animdefs == NULL); - if (W_CheckNumForName("ANIMATED") != LUMPERROR || W_CheckNumForName("ANIMDEFS") != LUMPERROR) + maxanims = 0; + + for (w = numwadfiles-1; w >= 0; w--) { - for (w = numwadfiles-1, maxanims = 0; w >= 0; w--) + UINT16 animdefsLumpNum; + + // Find ANIMDEFS lump in the WAD + animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); + + while (animdefsLumpNum != INT16_MAX) { - UINT16 animatedLumpNum; - UINT16 animdefsLumpNum; - - // Find ANIMATED lump in the WAD - animatedLumpNum = W_CheckNumForNamePwad("ANIMATED", w, 0); - if (animatedLumpNum != INT16_MAX) - { - animatedLump = (UINT8 *)W_CacheLumpNumPwad(w, animatedLumpNum, PU_STATIC); - - // Get the number of animations in the file - i = maxanims; - for (currentPos = animatedLump; *currentPos != UINT8_MAX; maxanims++, currentPos+=23); - - // Resize animdefs (or if it hasn't been created, create it) - animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); - // Sanity check it - if (!animdefs) - I_Error("Not enough free memory for ANIMATED data"); - - // Populate the new array - for (currentPos = animatedLump; *currentPos != UINT8_MAX; i++, currentPos+=23) - { - M_Memcpy(&(animdefs[i].istexture), currentPos, 1); // istexture, 1 byte - M_Memcpy(animdefs[i].endname, (currentPos + 1), 9); // endname, 9 bytes - M_Memcpy(animdefs[i].startname, (currentPos + 10), 9); // startname, 9 bytes - M_Memcpy(&(animdefs[i].speed), (currentPos + 19), 4); // speed, 4 bytes - } - - Z_Free(animatedLump); - } - - // Find ANIMDEFS lump in the WAD - animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", w, 0); - while (animdefsLumpNum != INT16_MAX) - { - P_ParseANIMDEFSLump(w, animdefsLumpNum); - animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); - } + P_ParseANIMDEFSLump(w, animdefsLumpNum); + animdefsLumpNum = W_CheckNumForNamePwad("ANIMDEFS", (UINT16)w, animdefsLumpNum + 1); } - // Define the last one - animdefs[maxanims].istexture = -1; - strncpy(animdefs[maxanims].endname, "", 9); - strncpy(animdefs[maxanims].startname, "", 9); - animdefs[maxanims].speed = 0; - } - else - { - animdefs = harddefs; - for (maxanims = 0; animdefs[maxanims].istexture != -1; maxanims++); } + // Define the last one + animdefs[maxanims].istexture = -1; + strncpy(animdefs[maxanims].endname, "", 9); + strncpy(animdefs[maxanims].startname, "", 9); + animdefs[maxanims].speed = 0; + if (anims) free(anims); anims = (anim_t *)malloc(sizeof (*anims)*(maxanims + 1)); if (!anims) - I_Error("Not enough free memory for ANIMATED data"); + I_Error("Not enough free memory for ANIMDEFS data"); lastanim = anims; for (i = 0; animdefs[i].istexture != -1; i++) @@ -329,8 +217,8 @@ void P_InitPicAnims(void) if ((W_CheckNumForName(animdefs[i].startname)) == LUMPERROR) continue; - lastanim->picnum = R_FlatNumForName(animdefs[i].endname); - lastanim->basepic = R_FlatNumForName(animdefs[i].startname); + lastanim->picnum = R_GetFlatNumForName(animdefs[i].endname); + lastanim->basepic = R_GetFlatNumForName(animdefs[i].startname); } lastanim->istexture = animdefs[i].istexture; @@ -343,10 +231,7 @@ void P_InitPicAnims(void) animdefs[i].startname, animdefs[i].endname); } - if (animdefs == harddefs) - lastanim->speed = animdefs[i].speed; - else - lastanim->speed = LONG(animdefs[i].speed); + lastanim->speed = LONG(animdefs[i].speed); lastanim++; } lastanim->istexture = -1; @@ -354,8 +239,7 @@ void P_InitPicAnims(void) // Clear animdefs now that we're done with it. // We'll only be using anims from now on. - if (animdefs != harddefs) - Z_Free(animdefs); + Z_Free(animdefs); animdefs = NULL; } @@ -460,7 +344,8 @@ void P_ParseAnimationDefintion(SINT8 istexture) // Search for existing animdef for (i = 0; i < maxanims; i++) - if (stricmp(animdefsToken, animdefs[i].startname) == 0) + if (animdefs[i].istexture == istexture // Check if it's the same type! + && stricmp(animdefsToken, animdefs[i].startname) == 0) { //CONS_Alert(CONS_NOTICE, "Duplicate animation: %s\n", animdefsToken); @@ -474,8 +359,7 @@ void P_ParseAnimationDefintion(SINT8 istexture) if (i == maxanims) { // Increase the size to make room for the new animation definition - maxanims++; - animdefs = (animdef_t *)Z_Realloc(animdefs, sizeof(animdef_t)*(maxanims + 1), PU_STATIC, NULL); + GrowAnimDefs(); strncpy(animdefs[i].startname, animdefsToken, 9); } @@ -561,8 +445,17 @@ void P_ParseAnimationDefintion(SINT8 istexture) } animdefs[i].speed = animSpeed; Z_Free(animdefsToken); -} +#ifdef WALLFLATS + // hehe... uhh..... + if (!istexture) + { + GrowAnimDefs(); + M_Memcpy(&animdefs[maxanims-1], &animdefs[i], sizeof(animdef_t)); + animdefs[maxanims-1].istexture = 1; + } +#endif +} /** Checks for flats in levelflats that are part of a flat animation sequence * and sets them up for animation. @@ -591,10 +484,23 @@ static inline void P_FindAnimatedFlat(INT32 animnum) for (i = 0; i < numlevelflats; i++, foundflats++) { // is that levelflat from the flat anim sequence ? - if (foundflats->lumpnum >= startflatnum && foundflats->lumpnum <= endflatnum) + if ((anims[animnum].istexture) && (foundflats->type == LEVELFLAT_TEXTURE) + && ((UINT16)foundflats->u.texture.num >= startflatnum && (UINT16)foundflats->u.texture.num <= endflatnum)) { - foundflats->baselumpnum = startflatnum; - foundflats->animseq = foundflats->lumpnum - startflatnum; + foundflats->u.texture.basenum = startflatnum; + foundflats->animseq = foundflats->u.texture.num - startflatnum; + foundflats->numpics = endflatnum - startflatnum + 1; + foundflats->speed = anims[animnum].speed; + + CONS_Debug(DBG_SETUP, "animflat: #%03d name:%.8s animseq:%d numpics:%d speed:%d\n", + atoi(sizeu1(i)), foundflats->name, foundflats->animseq, + foundflats->numpics,foundflats->speed); + } + else if ((!anims[animnum].istexture) && (foundflats->type == LEVELFLAT_FLAT) + && (foundflats->u.flat.lumpnum >= startflatnum && foundflats->u.flat.lumpnum <= endflatnum)) + { + foundflats->u.flat.baselumpnum = startflatnum; + foundflats->animseq = foundflats->u.flat.lumpnum - startflatnum; foundflats->numpics = endflatnum - startflatnum + 1; foundflats->speed = anims[animnum].speed; @@ -615,10 +521,7 @@ void P_SetupLevelFlatAnims(void) // the original game flat anim sequences for (i = 0; anims[i].istexture != -1; i++) - { - if (!anims[i].istexture) - P_FindAnimatedFlat(i); - } + P_FindAnimatedFlat(i); } // @@ -1093,42 +996,12 @@ static sector_t *P_FindModelCeilingSector(fixed_t ceildestheight, INT32 secnum) } #endif -/** Searches the tag lists for the next sector tagged to a line. - * - * \param line Tagged line used as a reference. - * \param start -1 to start at the beginning, or the result of a previous call - * to keep searching. - * \return Number of the next tagged sector found. - * \sa P_FindSectorFromTag, P_FindLineFromLineTag - */ -INT32 P_FindSectorFromLineTag(line_t *line, INT32 start) -{ - if (line->tag == -1) - { - start++; - - if (start >= (INT32)numsectors) - return -1; - - return start; - } - else - { - start = start >= 0 ? sectors[start].nexttag : - sectors[(unsigned)line->tag % numsectors].firsttag; - while (start >= 0 && sectors[start].tag != line->tag) - start = sectors[start].nexttag; - return start; - } -} - /** Searches the tag lists for the next sector with a given tag. * * \param tag Tag number to look for. * \param start -1 to start anew, or the result of a previous call to keep * searching. * \return Number of the next tagged sector found. - * \sa P_FindSectorFromLineTag */ INT32 P_FindSectorFromTag(INT16 tag, INT32 start) { @@ -1151,42 +1024,12 @@ INT32 P_FindSectorFromTag(INT16 tag, INT32 start) } } -/** Searches the tag lists for the next line tagged to a line. - * - * \param line Tagged line used as a reference. - * \param start -1 to start anew, or the result of a previous call to keep - * searching. - * \return Number of the next tagged line found. - * \sa P_FindSectorFromLineTag - */ -static INT32 P_FindLineFromLineTag(const line_t *line, INT32 start) -{ - if (line->tag == -1) - { - start++; - - if (start >= (INT32)numlines) - return -1; - - return start; - } - else - { - start = start >= 0 ? lines[start].nexttag : - lines[(unsigned)line->tag % numlines].firsttag; - while (start >= 0 && lines[start].tag != line->tag) - start = lines[start].nexttag; - return start; - } -} -#if 0 /** Searches the tag lists for the next line with a given tag and special. * * \param tag Tag number. * \param start -1 to start anew, or the result of a previous call to keep * searching. * \return Number of next suitable line found. - * \sa P_FindLineFromLineTag * \author Graue */ static INT32 P_FindLineFromTag(INT32 tag, INT32 start) @@ -1195,7 +1038,7 @@ static INT32 P_FindLineFromTag(INT32 tag, INT32 start) { start++; - if (start >= numlines) + if (start >= (INT32)numlines) return -1; return start; @@ -1209,10 +1052,7 @@ static INT32 P_FindLineFromTag(INT32 tag, INT32 start) return start; } } -#endif -// -// P_FindSpecialLineFromTag -// + INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start) { if (tag == -1) @@ -1242,14 +1082,7 @@ INT32 P_FindSpecialLineFromTag(INT16 special, INT16 tag, INT32 start) } } -// haleyjd: temporary define -#ifdef POLYOBJECTS - -// -// PolyDoor -// // Parses arguments for parameterized polyobject door types -// static boolean PolyDoor(line_t *line) { polydoordata_t pdd; @@ -1286,11 +1119,7 @@ static boolean PolyDoor(line_t *line) return EV_DoPolyDoor(&pdd); } -// -// PolyMove -// // Parses arguments for parameterized polyobject move specials -// static boolean PolyMove(line_t *line) { polymovedata_t pmd; @@ -1305,12 +1134,8 @@ static boolean PolyMove(line_t *line) return EV_DoPolyObjMove(&pmd); } -// -// PolyInvisible -// // Makes a polyobject invisible and intangible // If NOCLIMB is ticked, the polyobject will still be tangible, just not visible. -// static void PolyInvisible(line_t *line) { INT32 polyObjNum = line->tag; @@ -1333,12 +1158,8 @@ static void PolyInvisible(line_t *line) po->flags &= ~POF_RENDERALL; } -// -// PolyVisible -// // Makes a polyobject visible and tangible // If NOCLIMB is ticked, the polyobject will not be tangible, just visible. -// static void PolyVisible(line_t *line) { INT32 polyObjNum = line->tag; @@ -1358,19 +1179,17 @@ static void PolyVisible(line_t *line) po->flags |= POF_SOLID; po->flags &= ~POF_NOSPECIALS; - po->flags |= POF_RENDERALL; + po->flags |= (po->spawnflags & POF_RENDERALL); } -// -// PolyTranslucency -// + // Sets the translucency of a polyobject // Frontsector floor / 100 = translevel -// static void PolyTranslucency(line_t *line) { INT32 polyObjNum = line->tag; polyobj_t *po; + INT32 value; if (!(po = Polyobj_GetForNum(polyObjNum))) { @@ -1382,14 +1201,82 @@ static void PolyTranslucency(line_t *line) if (po->isBad) return; - po->translucency = (line->frontsector->floorheight >> FRACBITS) / 100; + // If Front X Offset is specified, use that. Else, use floorheight. + value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS; + + // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. + if (!(line->flags & ML_DONTPEGBOTTOM)) + value /= 100; + + if (line->flags & ML_EFFECT3) // relative calc + po->translucency += value; + else + po->translucency = value; + + po->translucency = max(min(po->translucency, NUMEFFECTMAPS), 0); +} + +// Makes a polyobject translucency fade and applies tangibility +static boolean PolyFade(line_t *line) +{ + INT32 polyObjNum = line->tag; + polyobj_t *po; + polyfadedata_t pfd; + INT32 value; + + if (!(po = Polyobj_GetForNum(polyObjNum))) + { + CONS_Debug(DBG_POLYOBJ, "PolyFade: bad polyobj %d\n", polyObjNum); + return 0; + } + + // don't allow line actions to affect bad polyobjects + if (po->isBad) + return 0; + + // Prevent continuous execs from interfering on an existing fade + if (!(line->flags & ML_EFFECT5) + && po->thinker + && po->thinker->function.acp1 == (actionf_p1)T_PolyObjFade) + { + CONS_Debug(DBG_POLYOBJ, "Line type 492 Executor: Fade PolyObject thinker already exists\n"); + return 0; + } + + pfd.polyObjNum = polyObjNum; + + // If Front X Offset is specified, use that. Else, use floorheight. + value = (sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : line->frontsector->floorheight) >> FRACBITS; + + // If DONTPEGBOTTOM, specify raw translucency value. Else, take it out of 1000. + if (!(line->flags & ML_DONTPEGBOTTOM)) + value /= 100; + + if (line->flags & ML_EFFECT3) // relative calc + pfd.destvalue = po->translucency + value; + else + pfd.destvalue = value; + + pfd.destvalue = max(min(pfd.destvalue, NUMTRANSMAPS), 0); + + // already equal, nothing to do + if (po->translucency == pfd.destvalue) + return 1; + + pfd.docollision = !(line->flags & ML_NOTBOUNCY); // do not handle collision flags + pfd.doghostfade = (line->flags & ML_EFFECT1); // do ghost fade (no collision flags during fade) + pfd.ticbased = (line->flags & ML_EFFECT4); // Speed = Tic Duration + + // allow Back Y Offset to be consistent with other fade specials + pfd.speed = (line->sidenum[1] != 0xFFFF && !sides[line->sidenum[0]].rowoffset) ? + abs(sides[line->sidenum[1]].rowoffset>>FRACBITS) + : abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); + + + return EV_DoPolyObjFade(&pfd); } -// -// PolyWaypoint -// // Parses arguments for parameterized polyobject waypoint movement -// static boolean PolyWaypoint(line_t *line) { polywaypointdata_t pwd; @@ -1397,19 +1284,26 @@ static boolean PolyWaypoint(line_t *line) pwd.polyObjNum = line->tag; pwd.speed = sides[line->sidenum[0]].textureoffset / 8; pwd.sequence = sides[line->sidenum[0]].rowoffset >> FRACBITS; // Sequence # - pwd.reverse = (line->flags & ML_EFFECT1) == ML_EFFECT1; // Reverse? - pwd.comeback = (line->flags & ML_EFFECT2) == ML_EFFECT2; // Return when reaching end? - pwd.wrap = (line->flags & ML_EFFECT3) == ML_EFFECT3; // Wrap around waypoints - pwd.continuous = (line->flags & ML_EFFECT4) == ML_EFFECT4; // Continuously move - used with COMEBACK or WRAP + + // Behavior after reaching the last waypoint? + if (line->flags & ML_EFFECT3) + pwd.returnbehavior = PWR_WRAP; // Wrap back to first waypoint + else if (line->flags & ML_EFFECT2) + pwd.returnbehavior = PWR_COMEBACK; // Go through sequence in reverse + else + pwd.returnbehavior = PWR_STOP; // Stop + + // Flags + pwd.flags = 0; + if (line->flags & ML_EFFECT1) + pwd.flags |= PWF_REVERSE; + if (line->flags & ML_EFFECT4) + pwd.flags |= PWF_LOOP; return EV_DoPolyObjWaypoint(&pwd); } -// -// PolyRotate -// // Parses arguments for parameterized polyobject rotate specials -// static boolean PolyRotate(line_t *line) { polyrotdata_t prd; @@ -1434,11 +1328,20 @@ static boolean PolyRotate(line_t *line) return EV_DoPolyObjRotate(&prd); } -// -// PolyDisplace -// +// Parses arguments for polyobject flag waving special +static boolean PolyFlag(line_t *line) +{ + polyflagdata_t pfd; + + pfd.polyObjNum = line->tag; + pfd.speed = P_AproxDistance(line->dx, line->dy) >> FRACBITS; + pfd.angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y) >> ANGLETOFINESHIFT; + pfd.momx = sides[line->sidenum[0]].textureoffset >> FRACBITS; + + return EV_DoPolyObjFlag(&pfd); +} + // Parses arguments for parameterized polyobject move-by-sector-heights specials -// static boolean PolyDisplace(line_t *line) { polydisplacedata_t pdd; @@ -1452,7 +1355,31 @@ static boolean PolyDisplace(line_t *line) return EV_DoPolyObjDisplace(&pdd); } -#endif // ifdef POLYOBJECTS +// Parses arguments for parameterized polyobject rotate-by-sector-heights specials +static boolean PolyRotDisplace(line_t *line) +{ + polyrotdisplacedata_t pdd; + fixed_t anginter, distinter; + + pdd.polyObjNum = line->tag; + pdd.controlSector = line->frontsector; + + // Rotate 'anginter' interval for each 'distinter' interval from the control sector. + // Use default values if not provided as fallback. + anginter = sides[line->sidenum[0]].rowoffset ? sides[line->sidenum[0]].rowoffset : 90*FRACUNIT; + distinter = sides[line->sidenum[0]].textureoffset ? sides[line->sidenum[0]].textureoffset : 128*FRACUNIT; + pdd.rotscale = FixedDiv(anginter, distinter); + + // Same behavior as other rotators when carrying things. + if (line->flags & ML_NOCLIMB) + pdd.turnobjs = 0; + else if (line->flags & ML_EFFECT4) + pdd.turnobjs = 2; + else + pdd.turnobjs = 1; + + return EV_DoPolyObjRotDisplace(&pdd); +} /** Changes a sector's tag. * Used by the linedef executor tag changer and by crumblers. @@ -1515,32 +1442,6 @@ void P_ChangeSectorTag(UINT32 sector, INT16 newtag) } } -/** Hashes the sector tags across the sectors and linedefs. - * - * \sa P_FindSectorFromTag, P_ChangeSectorTag - * \author Lee Killough - */ -static inline void P_InitTagLists(void) -{ - register size_t i; - - for (i = numsectors - 1; i != (size_t)-1; i--) - { - size_t j = (unsigned)sectors[i].tag % numsectors; - sectors[i].nexttag = sectors[j].firsttag; - sectors[j].firsttag = (INT32)i; - sectors[i].spawn_nexttag = sectors[i].nexttag; - sectors[j].spawn_firsttag = sectors[j].firsttag; - } - - for (i = numlines - 1; i != (size_t)-1; i--) - { - size_t j = (unsigned)lines[i].tag % numlines; - lines[i].nexttag = lines[j].firsttag; - lines[j].firsttag = (INT32)i; - } -} - /** Finds minimum light from an adjacent sector. * * \param sector Sector to start in. @@ -1584,18 +1485,26 @@ void T_ExecutorDelay(executor_t *e) static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector) { executor_t *e; + INT32 delay; - if (!line->backsector) - I_Error("P_AddExecutorDelay: Line has no backsector!\n"); + if (udmf) + delay = line->executordelay; + else + { + if (!line->backsector) + I_Error("P_AddExecutorDelay: Line has no backsector!\n"); + + delay = (line->backsector->ceilingheight >> FRACBITS) + (line->backsector->floorheight >> FRACBITS); + } e = Z_Calloc(sizeof (*e), PU_LEVSPEC, NULL); e->thinker.function.acp1 = (actionf_p1)T_ExecutorDelay; e->line = line; e->sector = sector; - e->timer = (line->backsector->ceilingheight>>FRACBITS)+(line->backsector->floorheight>>FRACBITS); + e->timer = delay; P_SetTarget(&e->caller, mobj); // Use P_SetTarget to make sure the mobj doesn't get freed while we're delaying. - P_AddThinker(&e->thinker); + P_AddThinker(THINK_MAIN, &e->thinker); } /** Used by P_LinedefExecute to check a trigger linedef's conditions @@ -1633,10 +1542,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!playeringame[i] || players[i].spectator) continue; - if (!players[i].mo || players[i].mo->health < 1) + if (!players[i].mo || players[i].rings <= 0) continue; - rings += players[i].mo->health-1; + rings += players[i].rings; } } else @@ -1644,7 +1553,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (!(actor && actor->player)) return false; // no player to count rings from here, sorry - rings = actor->health-1; + rings = actor->player->rings; } if (triggerline->flags & ML_NOCLIMB) @@ -1678,7 +1587,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller while (node) { mo = node->m_thing; - if (mo->flags & MF_PUSHABLE) + if ((mo->flags & MF_PUSHABLE) || ((mo->info->flags & MF_PUSHABLE) && mo->fuse)) numpush++; node = node->m_thinglist_next; } @@ -1725,12 +1634,6 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller switch (specialtype) { - /*case 305: // continuous - case 306: // each time - case 307: // once - if (!(actor && actor->player && actor->player->charability == dist/10)) - return false; - break;*/ case 309: // continuous case 310: // each time // Only red team members can activate this. @@ -1784,6 +1687,23 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller return false; } break; + case 331: // continuous + case 332: // each time + case 333: // once + if (!(actor && actor->player && ((stricmp(triggerline->text, skins[actor->player->skin].name) == 0) ^ ((triggerline->flags & ML_NOCLIMB) == ML_NOCLIMB)))) + return false; + break; + case 334: // object dye - continuous + case 335: // object dye - each time + case 336: // object dye - once + { + INT32 triggercolor = (INT32)sides[triggerline->sidenum[0]].toptexture; + UINT16 color = (actor->player ? actor->player->powers[pw_dye] : actor->color); + boolean invert = (triggerline->flags & ML_NOCLIMB ? true : false); + + if (invert ^ (triggercolor != color)) + return false; + } default: break; } @@ -1802,7 +1722,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (ctlsector->lines[i]->special >= 400 && ctlsector->lines[i]->special < 500) { - if (ctlsector->lines[i]->flags & ML_DONTPEGTOP) + if (ctlsector->lines[i]->executordelay) P_AddExecutorDelay(ctlsector->lines[i], actor, caller); else P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); @@ -1890,7 +1810,7 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller if (ctlsector->lines[i]->special >= 400 && ctlsector->lines[i]->special < 500) { - if (ctlsector->lines[i]->flags & ML_DONTPEGTOP) + if (ctlsector->lines[i]->executordelay) P_AddExecutorDelay(ctlsector->lines[i], actor, caller); else P_ProcessLineSpecial(ctlsector->lines[i], actor, caller); @@ -1904,17 +1824,19 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller else // These special types work only once if (specialtype == 302 // Once - || specialtype == 304 // Ring count - Once - || specialtype == 307 // Character ability - Once - || specialtype == 308 // Race only - Once - || specialtype == 315 // No of pushables - Once - || specialtype == 318 // Unlockable trigger - Once - || specialtype == 320 // Unlockable - Once - || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time - || specialtype == 323 // Record attack only - Once - || specialtype == 328 // Encore Load - || specialtype == 399 // Level Load - || specialtype == 2002 // SRB2Kart Race Lap + || specialtype == 304 // Ring count - Once + || specialtype == 307 // Character ability - Once + || specialtype == 308 // Race only - Once + || specialtype == 313 // No More Enemies - Once + || specialtype == 315 // No of pushables - Once + || specialtype == 318 // Unlockable trigger - Once + || specialtype == 320 // Unlockable - Once + || specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time + || specialtype == 333 // Skin - Once + || specialtype == 336 // Dye - Once + || specialtype == 399 // Level Load + || specialtype == 328 // SRB2Kart Encore Load + || specialtype == 2002 // SRB2Kart Race Lap ) triggerline->special = 0; // Clear it out @@ -1958,7 +1880,9 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller) || lines[masterline].special == 306 // Character ability - Each time || lines[masterline].special == 310 // CTF Red team - Each time || lines[masterline].special == 312 // CTF Blue team - Each time - || lines[masterline].special == 322) // Trigger on X calls - Each Time + || lines[masterline].special == 322 // Trigger on X calls - Each Time + || lines[masterline].special == 332 // Skin - Each time + || lines[masterline].special == 335)// Dye - Each time continue; if (lines[masterline].special < 300 @@ -2001,7 +1925,7 @@ void P_SwitchWeather(UINT8 newWeather) thinker_t *think; precipmobj_t *precipmobj; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker @@ -2018,7 +1942,7 @@ void P_SwitchWeather(UINT8 newWeather) precipmobj_t *precipmobj; statenum_t st; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_PRECIP].next; think != &thlist[THINK_PRECIP]; think = think->next) { if (think->function.acp1 != (actionf_p1)P_NullPrecipThinker) continue; // not a precipmobj thinker @@ -2222,7 +2146,7 @@ static void K_HandleLapDecrement(player_t *player) void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) { // only used for the players currently - if (!(thing && thing->player && !thing->player->spectator && !(thing->player->pflags & PF_TIMEOVER))) + if (!(thing && thing->player && !thing->player->spectator && !(thing->player->pflags & PF_GAMETYPEOVER))) return; { player_t *player = thing->player; @@ -2230,7 +2154,7 @@ void P_CrossSpecialLine(line_t *line, INT32 side, mobj_t *thing) { case 2001: // Finish Line { - if (G_RaceGametype() && !(player->exiting) && !(player->pflags & PF_HITFINISHLINE)) + if ((gametyperules & GTR_CIRCUIT) && !(player->exiting) && !(player->pflags & PF_HITFINISHLINE)) { if (((line->flags & (ML_NOCLIMB)) && (side == 0)) || (!(line->flags & (ML_NOCLIMB)) && (side == 1))) // crossed from behind to infront @@ -2318,7 +2242,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) newceilinglightsec = line->frontsector->ceilinglightsec; // act on all sectors with the same tag as the triggering linedef - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { if (sectors[secnum].lightingdata) { @@ -2373,7 +2297,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 409: // Change tagged sectors' tag // (formerly "Change calling sectors' tag", but behavior was changed) { - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) P_ChangeSectorTag(secnum,(INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS)); break; } @@ -2383,7 +2307,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 411: // Stop floor/ceiling movement in tagged sector(s) - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { if (sectors[secnum].floordata) { @@ -2450,7 +2374,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } else { - if ((secnum = P_FindSectorFromLineTag(line, -1)) < 0) + if ((secnum = P_FindSectorFromTag(line->tag, -1)) < 0) return; dest = P_GetObjectTypeInSectorNum(MT_TELEPORTMAN, secnum); @@ -2471,7 +2395,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 413: // Change music // console player only unless NOCLIMB is set - if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player))) + if ((line->flags & ML_NOCLIMB) || (mo && mo->player && P_IsLocalPlayer(mo->player)) || titlemapinaction) { boolean musicsame = (!sides[line->sidenum[0]].text[0] || !strnicmp(sides[line->sidenum[0]].text, S_MusicName(), 7)); UINT16 tracknum = (UINT16)max(sides[line->sidenum[0]].bottomtexture, 0); @@ -2521,7 +2445,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) mapmusflags = tracknum & MUSIC_TRACKMASK; if (!(line->flags & ML_BLOCKPLAYERS)) mapmusflags |= MUSIC_RELOADRESET; - if (line->flags & ML_BOUNCY) + if (line->flags & ML_NOTBOUNCY) mapmusflags |= MUSIC_FORCERESET; mapmusposition = position; @@ -2549,7 +2473,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { INT32 sfxnum; - sfxnum = sides[line->sidenum[0]].toptexture; //P_AproxDistance(line->dx, line->dy)>>FRACBITS; + sfxnum = sides[line->sidenum[0]].toptexture; if (sfxnum == sfx_None) return; // Do nothing! @@ -2558,70 +2482,90 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) CONS_Debug(DBG_GAMELOGIC, "Line type 414 Executor: sfx number %d is invalid!\n", sfxnum); return; } + if (line->tag != 0) // Do special stuff only if a non-zero linedef tag is set { + // Play sounds from tagged sectors' origins. if (line->flags & ML_EFFECT5) // Repeat Midtexture { // Additionally play the sound from tagged sectors' soundorgs sector_t *sec; - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { sec = §ors[secnum]; S_StartSound(&sec->soundorg, sfxnum); } } - else if (mo) // A mobj must have triggered the executor + + // Play the sound without origin for anyone, as long as they're inside tagged areas. + else { - // Only trigger if mobj is touching the tag + UINT8 i = 0; + mobj_t* camobj; ffloor_t *rover; boolean foundit = false; - for(rover = mo->subsector->sector->ffloors; rover; rover = rover->next) + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - if (rover->master->frontsector->tag != line->tag) + camobj = players[displayplayers[i]].mo; + + if (!camobj) continue; - if (mo->z > P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector)) - continue; + if (foundit || (camobj->subsector->sector->tag == line->tag)) + { + foundit = true; + break; + } - if (mo->z + mo->height < P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)) - continue; + // Only trigger if mobj is touching the tag + for(rover = camobj->subsector->sector->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag != line->tag) + continue; - foundit = true; + if (camobj->z > P_GetSpecialTopZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) + continue; + + if (camobj->z + camobj->height < P_GetSpecialBottomZ(camobj, sectors + rover->secnum, camobj->subsector->sector)) + continue; + + foundit = true; + break; + } } - if (mo->subsector->sector->tag == line->tag) - foundit = true; - - if (!foundit) - return; + if (foundit) + S_StartSound(NULL, sfxnum); } } - - if (line->flags & ML_NOCLIMB) + else { - // play the sound from nowhere, but only if display player triggered it - if (mo && mo->player && P_IsDisplayPlayer(mo->player)) + if (line->flags & ML_NOCLIMB) + { + // play the sound from nowhere, but only if display player triggered it + if (mo && mo->player && P_IsDisplayPlayer(mo->player)) + S_StartSound(NULL, sfxnum); + } + else if (line->flags & ML_EFFECT4) + { + // play the sound from nowhere S_StartSound(NULL, sfxnum); - } - else if (line->flags & ML_EFFECT4) - { - // play the sound from nowhere - S_StartSound(NULL, sfxnum); - } - else if (line->flags & ML_BLOCKPLAYERS) - { - // play the sound from calling sector's soundorg - if (callsec) - S_StartSound(&callsec->soundorg, sfxnum); + } + else if (line->flags & ML_BLOCKPLAYERS) + { + // play the sound from calling sector's soundorg + if (callsec) + S_StartSound(&callsec->soundorg, sfxnum); + else if (mo) + S_StartSound(&mo->subsector->sector->soundorg, sfxnum); + } else if (mo) - S_StartSound(&mo->subsector->sector->soundorg, sfxnum); - } - else if (mo) - { - // play the sound from mobj that triggered it - S_StartSound(mo, sfxnum); + { + // play the sound from mobj that triggered it + S_StartSound(mo, sfxnum); + } } } break; @@ -2664,7 +2608,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 416: // Spawn adjustable fire flicker - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2698,7 +2642,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 417: // Spawn adjustable glowing light - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2732,7 +2676,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 418: // Spawn adjustable strobe flash (unsynchronized) - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2766,7 +2710,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 419: // Spawn adjustable strobe flash (synchronized) - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { if (line->flags & ML_NOCLIMB && line->backsector) { @@ -2800,11 +2744,21 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 420: // Fade light levels in tagged sectors to new value - P_FadeLight(line->tag, line->frontsector->lightlevel, P_AproxDistance(line->dx, line->dy)>>FRACBITS); + P_FadeLight(line->tag, + (line->flags & ML_DONTPEGBOTTOM) ? max(sides[line->sidenum[0]].textureoffset>>FRACBITS, 0) : line->frontsector->lightlevel, + // failsafe: if user specifies Back Y Offset and NOT Front Y Offset, use the Back Offset + // to be consistent with other light and fade specials + (line->flags & ML_DONTPEGBOTTOM) ? + ((line->sidenum[1] != 0xFFFF && !(sides[line->sidenum[0]].rowoffset>>FRACBITS)) ? + max(min(sides[line->sidenum[1]].rowoffset>>FRACBITS, 255), 0) + : max(min(sides[line->sidenum[0]].rowoffset>>FRACBITS, 255), 0)) + : abs(P_AproxDistance(line->dx, line->dy))>>FRACBITS, + (line->flags & ML_EFFECT4), + (line->flags & ML_EFFECT5)); break; case 421: // Stop lighting effect in tagged sectors - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) if (sectors[secnum].lightingdata) { P_RemoveThinker(&((elevator_t *)sectors[secnum].lightingdata)->thinker); @@ -2816,35 +2770,48 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) { mobj_t *altview; - if (!mo || !mo->player) // only players have views + if ((!mo || !mo->player) && !titlemapinaction) // only players have views, and title screens return; - if ((secnum = P_FindSectorFromLineTag(line, -1)) < 0) + if ((secnum = P_FindSectorFromTag(line->tag, -1)) < 0) return; altview = P_GetObjectTypeInSectorNum(MT_ALTVIEWMAN, secnum); if (!altview) return; - P_SetTarget(&mo->player->awayviewmobj, altview); - mo->player->awayviewtics = P_AproxDistance(line->dx, line->dy)>>FRACBITS; + // If titlemap, set the camera ref for title's thinker + // This is not revoked until overwritten; awayviewtics is ignored + if (titlemapinaction) + titlemapcameraref = altview; + else + { + P_SetTarget(&mo->player->awayviewmobj, altview); + mo->player->awayviewtics = P_AproxDistance(line->dx, line->dy)>>FRACBITS; + } + if (line->flags & ML_NOCLIMB) // lets you specify a vertical angle { INT32 aim; aim = sides[line->sidenum[0]].textureoffset>>FRACBITS; - while (aim < 0) - aim += 360; - while (aim >= 360) - aim -= 360; + aim = (aim + 360) % 360; aim *= (ANGLE_90>>8); aim /= 90; aim <<= 8; - mo->player->awayviewaiming = (angle_t)aim; + if (titlemapinaction) + titlemapcameraref->cusval = (angle_t)aim; + else + mo->player->awayviewaiming = (angle_t)aim; } else - mo->player->awayviewaiming = 0; // straight ahead + { + // straight ahead + if (!titlemapinaction) + mo->player->awayviewaiming = 0; + // don't do cusval cause that's annoying + } } break; @@ -2889,7 +2856,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) mo->player->rmomx = mo->player->rmomy = 1; mo->player->cmomx = mo->player->cmomy = 0; P_ResetPlayer(mo->player); - P_SetPlayerMobjState(mo, S_KART_STILL1); + P_SetPlayerMobjState(mo, S_KART_STILL); } break; @@ -2915,7 +2882,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 432: // Enable 2D Mode (Disable if noclimb) - if (mo->player) + if (mo && mo->player) { if (line->flags & ML_NOCLIMB) mo->flags2 &= ~MF2_TWOD; @@ -2932,7 +2899,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; case 434: // Custom Power - if (mo->player) + if (mo && mo->player) { mobj_t *dummy = P_SpawnMobj(mo->x, mo->y, mo->z, MT_NULL); @@ -2957,7 +2924,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) scroll_t *scroller; thinker_t *th; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { if (th->function.acp1 != (actionf_p1)T_Scroll) continue; @@ -2979,6 +2946,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible in ffloor_t *rover; // FOF that we are going to crumble + boolean foundrover = false; // for debug, "Can't find a FOF" message for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) { @@ -2993,22 +2961,24 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (rover = sec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector->tag == foftag) - break; + { + foundrover = true; + + EV_CrumbleChain(sec, rover); + } } - if (!rover) + if (!foundrover) { CONS_Debug(DBG_GAMELOGIC, "Line type 436 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } - - EV_CrumbleChain(sec, rover); } } break; case 437: // Disable Player Controls - if (mo->player) + if (mo && mo->player) { UINT16 fractime = (UINT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); if (fractime < 1) @@ -3076,10 +3046,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) unlocktriggers |= 1 << trigid; // Unlocked something? - if (M_UpdateUnlockablesAndExtraEmblems(false)) + if (M_UpdateUnlockablesAndExtraEmblems()) { - S_StartSound(NULL, sfx_ncitem); - G_SaveGameData(false); // only save if unlocked something + S_StartSound(NULL, sfx_s3k68); + G_SaveGameData(); // only save if unlocked something } } } @@ -3098,7 +3068,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) if (line->sidenum[1] != 0xffff) state = (statenum_t)sides[line->sidenum[1]].toptexture; - while ((secnum = P_FindSectorFromLineTag(line, secnum)) >= 0) + while ((secnum = P_FindSectorFromTag(line->tag, secnum)) >= 0) { boolean tryagain; sec = sectors + secnum; @@ -3127,14 +3097,10 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) } case 443: // Calls a named Lua function -#ifdef HAVE_BLUA - if (line->text) + if (line->stringargs[0]) LUAh_LinedefExecute(line, mo, callsec); else - CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in the front texture fields)\n", sizeu1(line-lines)); -#else - CONS_Alert(CONS_ERROR, "The map is trying to run a Lua script, but this exe was not compiled with Lua support!\n"); -#endif + CONS_Alert(CONS_WARNING, "Linedef %s is missing the hook name of the Lua function to call! (This should be given in arg0str)\n", sizeu1(line-lines)); break; case 444: // Earthquake camera @@ -3159,6 +3125,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); sector_t *sec; // Sector that the FOF is visible (or not visible) in ffloor_t *rover; // FOF to vanish/un-vanish + boolean foundrover = false; // for debug, "Can't find a FOF" message ffloortype_e oldflags; // store FOF's old flags for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) @@ -3174,30 +3141,214 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) for (rover = sec->ffloors; rover; rover = rover->next) { if (rover->master->frontsector->tag == foftag) - break; + { + foundrover = true; + + oldflags = rover->flags; + + // Abracadabra! + if (line->flags & ML_NOCLIMB) + rover->flags |= FF_EXISTS; + else + rover->flags &= ~FF_EXISTS; + + // if flags changed, reset sector's light list + if (rover->flags != oldflags) + { + sec->moved = true; + P_RecalcPrecipInSector(sec); + } + } } - if (!rover) + if (!foundrover) { CONS_Debug(DBG_GAMELOGIC, "Line type 445 Executor: Can't find a FOF control sector with tag %d\n", foftag); return; } - - oldflags = rover->flags; - - // Abracadabra! - if (line->flags & ML_NOCLIMB) - rover->flags |= FF_EXISTS; - else - rover->flags &= ~FF_EXISTS; - - // if flags changed, reset sector's light list - if (rover->flags != oldflags) - sec->moved = true; } } break; + case 446: // Make block fall remotely (acts like FF_CRUMBLE) + { + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to make fall down + boolean foundrover = false; // for debug, "Can't find a FOF" message + player_t *player = NULL; // player that caused FOF to fall + boolean respawn = true; // should the fallen FOF respawn? + + if (mo) // NULL check + player = mo->player; + + if (line->flags & ML_NOCLIMB) // don't respawn! + respawn = false; + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + { + foundrover = true; + + if (line->flags & ML_BLOCKPLAYERS) // FOF flags determine respawn ability instead? + respawn = !(rover->flags & FF_NORETURN) ^ !!(line->flags & ML_NOCLIMB); // no climb inverts + + EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, respawn); + } + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 446 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + } + break; + + case 447: // Change colormap of tagged sectors! + // Basically this special applies a colormap to the tagged sectors, just like 606 (the colormap linedef) + // Except it is activated by linedef executor, not level load + // This could even override existing colormaps I believe + // -- Monster Iestyn 14/06/18 + { + extracolormap_t *source; + if (!udmf) + source = sides[line->sidenum[0]].colormap_data; + else + { + if (!line->args[1]) + source = line->frontsector->extra_colormap; + else + { + INT32 sourcesec = P_FindSectorFromTag(line->args[1], -1); + if (sourcesec == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 447 Executor: Can't find sector with source colormap (tag %d)!\n", line->args[1]); + return; + } + source = sectors[sourcesec].extra_colormap; + } + } + + for (secnum = -1; (secnum = P_FindSectorFromTag(line->args[0], secnum)) >= 0;) + { + if (sectors[secnum].colormap_protected) + continue; + + P_ResetColormapFader(§ors[secnum]); + + if (line->args[2] & TMCF_RELATIVE) + { + extracolormap_t *target = (!udmf && (line->flags & ML_TFERLINE) && line->sidenum[1] != 0xFFFF) ? + sides[line->sidenum[1]].colormap_data : sectors[secnum].extra_colormap; // use back colormap instead of target sector + + extracolormap_t *exc = R_AddColormaps( + target, + source, + line->args[2] & TMCF_SUBLIGHTR, + line->args[2] & TMCF_SUBLIGHTG, + line->args[2] & TMCF_SUBLIGHTB, + line->args[2] & TMCF_SUBLIGHTA, + line->args[2] & TMCF_SUBFADER, + line->args[2] & TMCF_SUBFADEG, + line->args[2] & TMCF_SUBFADEB, + line->args[2] & TMCF_SUBFADEA, + line->args[2] & TMCF_SUBFADESTART, + line->args[2] & TMCF_SUBFADEEND, + line->args[2] & TMCF_IGNOREFLAGS, + false); + + if (!(sectors[secnum].extra_colormap = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + sectors[secnum].extra_colormap = exc; + } + else + Z_Free(exc); + } + else + sectors[secnum].extra_colormap = source; + } + break; + } + case 448: // Change skybox viewpoint/centerpoint + if ((mo && mo->player && P_IsLocalPlayer(mo->player)) || (line->flags & ML_NOCLIMB)) + { + INT32 viewid = sides[line->sidenum[0]].textureoffset>>FRACBITS; + INT32 centerid = sides[line->sidenum[0]].rowoffset>>FRACBITS; + + if ((line->flags & (ML_EFFECT4|ML_BLOCKPLAYERS)) == ML_EFFECT4) // Solid Midtexture is on but Block Enemies is off? + { + CONS_Alert(CONS_WARNING, + M_GetText("Skybox switch linedef (tag %d) doesn't have anything to do.\nConsider changing the linedef's flag configuration or removing it entirely.\n"), + line->tag); + } + else + { + // set viewpoint mobj + if (!(line->flags & ML_EFFECT4)) // Solid Midtexture turns off viewpoint setting + { + if (viewid >= 0 && viewid < 16) + skyboxmo[0] = skyboxviewpnts[viewid]; + else + skyboxmo[0] = NULL; + } + + // set centerpoint mobj + if (line->flags & ML_BLOCKPLAYERS) // Block Enemies turns ON centerpoint setting + { + if (centerid >= 0 && centerid < 16) + skyboxmo[1] = skyboxcenterpnts[centerid]; + else + skyboxmo[1] = NULL; + } + } + + CONS_Debug(DBG_GAMELOGIC, "Line type 448 Executor: viewid = %d, centerid = %d, viewpoint? = %s, centerpoint? = %s\n", + viewid, + centerid, + ((line->flags & ML_EFFECT4) ? "no" : "yes"), + ((line->flags & ML_BLOCKPLAYERS) ? "yes" : "no")); + } + break; + + case 449: // Enable bosses with parameter + { + INT32 bossid = sides[line->sidenum[0]].textureoffset>>FRACBITS; + if (bossid & ~15) // if any bits other than first 16 are set + { + CONS_Alert(CONS_WARNING, + M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), + line->tag); + break; + } + if (line->flags & ML_NOCLIMB) + { + bossdisabled |= (1<tag, mo, NULL); break; @@ -3217,7 +3368,500 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) break; } -#ifdef POLYOBJECTS + case 452: // Set FOF alpha + { + INT16 destvalue = line->sidenum[1] != 0xffff ? + (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(P_AproxDistance(line->dx, line->dy)>>FRACBITS); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + { + foundrover = true; + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + // for relative alpha calc + if (!(line->flags & ML_NOCLIMB) && // do translucent + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + P_RemoveFakeFloorFader(rover); + P_FadeFakeFloor(rover, + rover->alpha, + max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, // tic-based logic + false, // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // handle FF_TRANSLUCENT + false, // do not handle lighting + false, // do not handle colormap + false, // do not handle collision + false, // do not do ghost fade (no collision during fade) + true); // use exact alpha values (for opengl) + } + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 452 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + break; + } + + case 453: // Fade FOF + { + INT16 destvalue = line->sidenum[1] != 0xffff ? + (INT16)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : (INT16)(line->dx>>FRACBITS); + INT16 speed = line->sidenum[1] != 0xffff ? + (INT16)(abs(sides[line->sidenum[1]].rowoffset>>FRACBITS)) : (INT16)(abs(line->dy)>>FRACBITS); + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message + size_t j = 0; // sec->ffloors is saved as ffloor #0, ss->ffloors->next is #1, etc + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + { + foundrover = true; + + // Prevent continuous execs from interfering on an existing fade + if (!(line->flags & ML_EFFECT5) + && rover->fadingdata) + //&& ((fade_t*)rover->fadingdata)->timer > (ticbased ? 2 : speed*2)) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Fade FOF thinker already exists, timer: %d\n", ((fade_t*)rover->fadingdata)->timer); + continue; + } + + if (speed > 0) + P_AddFakeFloorFader(rover, secnum, j, + destvalue, + speed, + (line->flags & ML_EFFECT4), // tic-based logic + (line->flags & ML_EFFECT3), // Relative destvalue + !(line->flags & ML_BLOCKPLAYERS), // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) + !(line->flags & ML_NOTBOUNCY), // do not handle collision + (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) + (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) + else + { + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + // for relative alpha calc + if (!(line->flags & ML_NOCLIMB) && // do translucent + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + P_RemoveFakeFloorFader(rover); + P_FadeFakeFloor(rover, + rover->alpha, + max(1, min(256, (line->flags & ML_EFFECT3) ? rover->alpha + destvalue : destvalue)), + 0, // set alpha immediately + false, NULL, // tic-based logic + !(line->flags & ML_BLOCKPLAYERS), // do not handle FF_EXISTS + !(line->flags & ML_NOCLIMB), // do not handle FF_TRANSLUCENT + !(line->flags & ML_EFFECT2), // do not handle lighting + !(line->flags & ML_EFFECT2), // do not handle colormap (ran out of flags) + !(line->flags & ML_NOTBOUNCY), // do not handle collision + (line->flags & ML_EFFECT1), // do ghost fade (no collision during fade) + (line->flags & ML_TFERLINE)); // use exact alpha values (for opengl) + } + } + j++; + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 453 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + break; + } + + case 454: // Stop fading FOF + { + INT16 sectag = (INT16)(sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT16 foftag = (INT16)(sides[line->sidenum[0]].rowoffset>>FRACBITS); + sector_t *sec; // Sector that the FOF is visible in + ffloor_t *rover; // FOF that we are going to operate + boolean foundrover = false; // for debug, "Can't find a FOF" message + + for (secnum = -1; (secnum = P_FindSectorFromTag(sectag, secnum)) >= 0 ;) + { + sec = sectors + secnum; + + if (!sec->ffloors) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Target sector #%d has no FOFs.\n", secnum); + return; + } + + for (rover = sec->ffloors; rover; rover = rover->next) + { + if (rover->master->frontsector->tag == foftag) + { + foundrover = true; + + P_ResetFakeFloorFader(rover, NULL, + !(line->flags & ML_BLOCKPLAYERS)); // do not finalize collision flags + } + } + + if (!foundrover) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 454 Executor: Can't find a FOF control sector with tag %d\n", foftag); + return; + } + } + break; + } + + case 455: // Fade colormap + { + extracolormap_t *dest; + if (!udmf) + dest = sides[line->sidenum[0]].colormap_data; + else + { + if (!line->args[1]) + dest = line->frontsector->extra_colormap; + else + { + INT32 destsec = P_FindSectorFromTag(line->args[1], -1); + if (destsec == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Can't find sector with destination colormap (tag %d)!\n", line->args[1]); + return; + } + dest = sectors[destsec].extra_colormap; + } + } + + for (secnum = -1; (secnum = P_FindSectorFromTag(line->args[0], secnum)) >= 0;) + { + extracolormap_t *source_exc, *dest_exc, *exc; + + if (sectors[secnum].colormap_protected) + continue; + + // Don't interrupt ongoing fade + if (!(line->args[3] & TMCF_OVERRIDE) + && sectors[secnum].fadecolormapdata) + //&& ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer > (ticbased ? 2 : speed*2)) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 455 Executor: Fade color thinker already exists, timer: %d\n", ((fadecolormap_t*)sectors[secnum].fadecolormapdata)->timer); + continue; + } + + if (!udmf && (line->flags & ML_TFERLINE)) // use back colormap instead of target sector + sectors[secnum].extra_colormap = (line->sidenum[1] != 0xFFFF) ? + sides[line->sidenum[1]].colormap_data : NULL; + + exc = sectors[secnum].extra_colormap; + + if (!(line->args[3] & TMCF_FROMBLACK) // Override fade from default rgba + && !R_CheckDefaultColormap(dest, true, false, false) + && R_CheckDefaultColormap(exc, true, false, false)) + { + exc = R_CopyColormap(exc, false); + exc->rgba = R_GetRgbaRGB(dest->rgba) + R_PutRgbaA(R_GetRgbaA(exc->rgba)); + //exc->fadergba = R_GetRgbaRGB(dest->rgba) + R_PutRgbaA(R_GetRgbaA(exc->fadergba)); + + if (!(source_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + source_exc = exc; + } + else + Z_Free(exc); + + sectors[secnum].extra_colormap = source_exc; + } + else + source_exc = exc ? exc : R_GetDefaultColormap(); + + if (line->args[3] & TMCF_RELATIVE) + { + exc = R_AddColormaps( + source_exc, + dest, + line->args[3] & TMCF_SUBLIGHTR, + line->args[3] & TMCF_SUBLIGHTG, + line->args[3] & TMCF_SUBLIGHTB, + line->args[3] & TMCF_SUBLIGHTA, + line->args[3] & TMCF_SUBFADER, + line->args[3] & TMCF_SUBFADEG, + line->args[3] & TMCF_SUBFADEB, + line->args[3] & TMCF_SUBFADEA, + line->args[3] & TMCF_SUBFADESTART, + line->args[3] & TMCF_SUBFADEEND, + line->args[3] & TMCF_IGNOREFLAGS, + false); + } + else + exc = R_CopyColormap(dest, false); + + if (!(dest_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + dest_exc = exc; + } + else + Z_Free(exc); + + Add_ColormapFader(§ors[secnum], source_exc, dest_exc, true, // tic-based timing + line->args[2]); + } + break; + } + case 456: // Stop fade colormap + for (secnum = -1; (secnum = P_FindSectorFromTag(line->args[0], secnum)) >= 0 ;) + P_ResetColormapFader(§ors[secnum]); + break; + + case 457: // Track mobj angle to point + if (mo) + { + INT32 failureangle = FixedAngle((min(max(abs(sides[line->sidenum[0]].textureoffset>>FRACBITS), 0), 360))*FRACUNIT); + INT32 failuredelay = abs(sides[line->sidenum[0]].rowoffset>>FRACBITS); + INT32 failureexectag = line->sidenum[1] != 0xffff ? + (INT32)(sides[line->sidenum[1]].textureoffset>>FRACBITS) : 0; + boolean persist = (line->flags & ML_EFFECT2); + mobj_t *anchormo; + + if ((secnum = P_FindSectorFromTag(line->tag, -1)) < 0) + return; + + anchormo = P_GetObjectTypeInSectorNum(MT_ANGLEMAN, secnum); + if (!anchormo) + return; + + mo->eflags |= MFE_TRACERANGLE; + P_SetTarget(&mo->tracer, anchormo); + mo->lastlook = persist; // don't disable behavior after first failure + mo->extravalue1 = failureangle; // angle to exceed for failure state + mo->extravalue2 = failureexectag; // exec tag for failure state (angle is not within range) + mo->cusval = mo->cvmem = failuredelay; // cusval = tics to allow failure before line trigger; cvmem = decrement timer + } + break; + + case 458: // Stop tracking mobj angle to point + if (mo && (mo->eflags & MFE_TRACERANGLE)) + { + mo->eflags &= ~MFE_TRACERANGLE; + P_SetTarget(&mo->tracer, NULL); + mo->lastlook = mo->cvmem = mo->cusval = mo->extravalue1 = mo->extravalue2 = 0; + } + break; + + case 459: // Control Text Prompt + // console player only unless NOCLIMB is set + if (mo && mo->player && P_IsLocalPlayer(mo->player)) + { + INT32 promptnum = max(0, (sides[line->sidenum[0]].textureoffset>>FRACBITS)-1); + INT32 pagenum = max(0, (sides[line->sidenum[0]].rowoffset>>FRACBITS)-1); + INT32 postexectag = abs((line->sidenum[1] != 0xFFFF) ? sides[line->sidenum[1]].textureoffset>>FRACBITS : line->tag); + + boolean closetextprompt = (line->flags & ML_BLOCKPLAYERS); + //boolean allplayers = (line->flags & ML_NOCLIMB); + boolean runpostexec = (line->flags & ML_EFFECT1); + boolean blockcontrols = !(line->flags & ML_EFFECT2); + boolean freezerealtime = !(line->flags & ML_EFFECT3); + //boolean freezethinkers = (line->flags & ML_EFFECT4); + boolean callbynamedtag = (line->flags & ML_TFERLINE); + + if (closetextprompt) + F_EndTextPrompt(false, false); + else + { + if (callbynamedtag && sides[line->sidenum[0]].text && sides[line->sidenum[0]].text[0]) + F_GetPromptPageByNamedTag(sides[line->sidenum[0]].text, &promptnum, &pagenum); + F_StartTextPrompt(promptnum, pagenum, mo, runpostexec ? postexectag : 0, blockcontrols, freezerealtime); + } + } + break; + + case 460: // Award rings + { + INT16 rings = (sides[line->sidenum[0]].textureoffset>>FRACBITS); + INT32 delay = (sides[line->sidenum[0]].rowoffset>>FRACBITS); + if (mo && mo->player) + { + if (delay <= 0 || !(leveltime % delay)) + P_GivePlayerRings(mo->player, rings); + } + } + break; + + case 461: // Spawns an object on the map based on texture offsets + { + const mobjtype_t type = (mobjtype_t)(sides[line->sidenum[0]].toptexture); + mobj_t *mobj; + + fixed_t x, y, z; + x = sides[line->sidenum[0]].textureoffset; + y = sides[line->sidenum[0]].rowoffset; + z = line->frontsector->floorheight; + + if (line->flags & ML_NOCLIMB) // If noclimb is set, spawn randomly within a range + { + if (line->sidenum[1] != 0xffff) // Make sure the linedef has a back side + { + x = P_RandomRange(sides[line->sidenum[0]].textureoffset>>FRACBITS, sides[line->sidenum[1]].textureoffset>>FRACBITS)<sidenum[0]].rowoffset>>FRACBITS, sides[line->sidenum[1]].rowoffset>>FRACBITS)<frontsector->floorheight>>FRACBITS, line->frontsector->ceilingheight>>FRACBITS)<special); + break; + } + } + + mobj = P_SpawnMobj(x, y, z, type); + if (mobj) + { + if (line->flags & ML_EFFECT1) + mobj->angle = R_PointToAngle2(line->v1->x, line->v1->y, line->v2->x, line->v2->y); + CONS_Debug(DBG_GAMELOGIC, "Linedef Type %d - Spawn Object: %d spawned at (%d, %d, %d)\n", line->special, mobj->type, mobj->x>>FRACBITS, mobj->y>>FRACBITS, mobj->z>>FRACBITS); //TODO: Convert mobj->type to a string somehow. + } + else + CONS_Alert(CONS_ERROR,"Linedef Type %d - Spawn Object: Object did not spawn!\n", line->special); + } + break; + + case 462: // Stop clock (and end level in record attack) + stoppedclock = true; + CONS_Debug(DBG_GAMELOGIC, "Clock stopped!\n"); + if (modeattacking) + { + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + P_DoPlayerExit(&players[i]); + } + } + break; + + case 463: // Dye object + { + INT32 color = sides[line->sidenum[0]].toptexture; + + if (mo) + { + if (color < 0 || color >= numskincolors) + return; + + var1 = 0; + var2 = color; + A_Dye(mo); + } + } + break; + + case 464: // Trigger Egg Capsule + { + thinker_t *th; + mobj_t *mo2; + + // Find the center of the Eggtrap and release all the pretty animals! + // The chimps are my friends.. heeheeheheehehee..... - LouisJM + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mo2 = (mobj_t *)th; + + if (mo2->type != MT_EGGTRAP) + continue; + + if (!mo2->spawnpoint) + continue; + + if (mo2->spawnpoint->angle != line->tag) + continue; + + P_KillMobj(mo2, NULL, mo, DMG_NORMAL); + } + + if (!(line->flags & ML_NOCLIMB)) + { + INT32 i; + + // Mark all players with the time to exit thingy! + for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; + P_DoPlayerExit(&players[i]); + } + } + } + break; + + case 465: // Set linedef executor delay + { + INT32 linenum; + + if (!udmf) + break; + + for (linenum = -1; (linenum = P_FindLineFromTag(line->args[0], linenum)) >= 0 ;) + { + if (line->args[2]) + lines[linenum].executordelay += line->args[1]; + else + lines[linenum].executordelay = line->args[1]; + } + } + break; + case 480: // Polyobj_DoorSlide case 481: // Polyobj_DoorSwing PolyDoor(line); @@ -3244,14 +3888,16 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) case 491: PolyTranslucency(line); break; -#endif + case 492: + PolyFade(line); + break; default: break; } } -static void P_SetupSignObject(mobj_t *sign, mobj_t *pmo) +static void P_SetupSignObject(mobj_t *sign, mobj_t *pmo, boolean error) { mobj_t *cur = sign, *prev = NULL; @@ -3280,7 +3926,7 @@ static void P_SetupSignObject(mobj_t *sign, mobj_t *pmo) cur->hnext = P_SpawnMobj(sign->x, sign->y, sign->z, MT_SIGN_PIECE); P_SetTarget(&cur->hnext->target, sign); cur->hnext->skin = pmo->skin; - P_SetMobjState(cur->hnext, S_PLAY_SIGN); + P_SetMobjState(cur->hnext, (error == true) ? S_SIGN_ERROR : S_KART_SIGN); cur->hnext->extravalue1 = 7; cur->hnext->extravalue2 = 0; @@ -3346,8 +3992,7 @@ void P_SetupSignExit(player_t *player) if (thing->state != &states[thing->info->spawnstate]) continue; - P_SetupSignObject(thing, player->mo); - + P_SetupSignObject(thing, player->mo, false); ++numfound; } @@ -3356,10 +4001,10 @@ void P_SetupSignExit(player_t *player) // didn't find any signposts in the exit sector. // spin all signposts in the level then. - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; thing = (mobj_t *)think; if (thing->type != MT_SIGN) @@ -3368,7 +4013,7 @@ void P_SetupSignExit(player_t *player) if (thing->state != &states[thing->info->spawnstate]) continue; - P_SetupSignObject(thing, player->mo); + P_SetupSignObject(thing, player->mo, false); ++numfound; } @@ -3380,7 +4025,7 @@ void P_SetupSignExit(player_t *player) { thing = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->floorz, MT_SIGN); thing->angle = player->mo->angle; - P_SetupSignObject(thing, player->mo); + P_SetupSignObject(thing, player->mo, true); // Use :youfuckedup: sign face } } @@ -3393,23 +4038,18 @@ boolean P_IsFlagAtBase(mobjtype_t flag) { thinker_t *think; mobj_t *mo; - INT32 specialnum = 0; + INT32 specialnum = (flag == MT_REDFLAG) ? 3 : 4; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; mo = (mobj_t *)think; if (mo->type != flag) continue; - if (mo->type == MT_REDFLAG) - specialnum = 3; - else if (mo->type == MT_BLUEFLAG) - specialnum = 4; - if (GETSECSPECIAL(mo->subsector->sector->special, 4) == specialnum) return true; else if (mo->subsector->sector->ffloors) // Check the 3D floors @@ -3424,9 +4064,11 @@ boolean P_IsFlagAtBase(mobjtype_t flag) if (GETSECSPECIAL(rover->master->frontsector->special, 4) != specialnum) continue; - if (mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) - && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector)) - return true; + if (!(mo->z <= P_GetSpecialTopZ(mo, sectors + rover->secnum, mo->subsector->sector) + && mo->z >= P_GetSpecialBottomZ(mo, sectors + rover->secnum, mo->subsector->sector))) + continue; + + return true; } } } @@ -3499,26 +4141,17 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number, b if (((rover->flags & FF_BLOCKPLAYER) && mo->player) || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) + && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) + || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight)); + + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) + && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) + || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != topheight) - continue; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(mo->eflags & MFE_VERTICALFLIP) - || mo->z + mo->height != bottomheight) - continue; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottomheight) - || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == topheight))) - continue; - } + + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -3531,7 +4164,6 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number, b return rover->master->frontsector; } -#ifdef POLYOBJECTS // Allow sector specials to be applied to polyobjects! if (mo->subsector->polyList) { @@ -3620,7 +4252,6 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number, b return polysec; } } -#endif for (node = mo->touching_sectorlist; node; node = node->m_sectorlist_next) { @@ -3672,25 +4303,17 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number, b if (((rover->flags & FF_BLOCKPLAYER) && mo->player) || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) + && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) + || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight)); + + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) + && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) + || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != topheight) - continue; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(mo->eflags & MFE_VERTICALFLIP) || mo->z + mo->height != bottomheight) - continue; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottomheight) - || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == topheight))) - continue; - } + + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -3741,26 +4364,11 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar // Check the 3D floor's type... if (rover->flags & FF_BLOCKPLAYER) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == top)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottom)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != top) - return false; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(mo->eflags & MFE_VERTICALFLIP) - || mo->z + mo->height != bottom) - return false; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottom) - || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == top))) - return false; - } + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -3782,10 +4390,10 @@ static boolean P_ThingIsOnThe3DFloor(mobj_t *mo, sector_t *sector, sector_t *tar // static boolean P_MobjReadyToTrigger(mobj_t *mo, sector_t *sec) { - if (mo->eflags & MFE_VERTICALFLIP) - return (mo->z+mo->height == P_GetSpecialTopZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_CEILING); - else - return (mo->z == P_GetSpecialBottomZ(mo, sec, sec) && sec->flags & SF_FLIPSPECIAL_FLOOR); + boolean floorallowed = ((sec->flags & SF_FLIPSPECIAL_FLOOR) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == P_GetSpecialBottomZ(mo, sec, sec))); + boolean ceilingallowed = ((sec->flags & SF_FLIPSPECIAL_CEILING) && ((sec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == P_GetSpecialTopZ(mo, sec, sec))); + // Thing must be on top of the floor to be affected... + return (floorallowed || ceilingallowed); } /** Applies a sector special to a player. @@ -3815,7 +4423,7 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // Ignore dead players. // If this strange phenomenon could be potentially used in levels, // TODO: modify this to accommodate for it. - if (player->playerstate == PST_DEAD) + if (player->playerstate != PST_LIVE) return; // Conveyor stuff @@ -3829,58 +4437,33 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers { case 1: // Damage (Generic) if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - P_DamageMobj(player->mo, NULL, NULL, 1); + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL); break; case 2: // Damage (Water) // SRB2kart - These three damage types are now offroad sectors case 3: // Damage (Fire) case 4: // Damage (Electrical) break; case 5: // Spikes - // Don't do anything. In Soviet Russia, spikes find you. + if (roversector || P_MobjReadyToTrigger(player->mo, sector)) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_NORMAL); break; case 6: // Death Pit (Camera Mod) case 7: // Death Pit (No Camera Mod) if (roversector || P_MobjReadyToTrigger(player->mo, sector)) - K_DoIngameRespawn(player); + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_DEATHPIT); break; case 8: // Instant Kill - K_DoIngameRespawn(player); + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_INSTAKILL); break; case 9: // Ring Drainer (Floor Touch) case 10: // Ring Drainer (No Floor Touch) - if (leveltime % (TICRATE/2) == 0 && player->kartstuff[k_rings] > 0) + if (leveltime % (TICRATE/2) == 0 && player->rings > 0) { - player->kartstuff[k_rings]--; + player->rings--; S_StartSound(player->mo, sfx_itemup); } break; - case 11: // Special Stage Damage - Kind of like a mini-P_DamageMobj() - if (player->powers[pw_invulnerability] || player->powers[pw_flashing] || player->powers[pw_super] || player->exiting) - break; - - if (!(player->powers[pw_shield] || player->mo->health > 1)) // Don't do anything if no shield or rings anyway - break; - - if (player->powers[pw_shield]) - { - P_RemoveShield(player); - S_StartSound(player->mo, sfx_shldls); // Ba-Dum! Shield loss. - } - else if (player->mo->health > 1) - { - P_PlayRinglossSound(player->mo); - if (player->mo->health > 10) - player->mo->health -= 10; - else - player->mo->health = 1; - player->health = player->mo->health; - } - - P_DoPlayerPain(player, NULL, NULL); // this does basically everything that was here before - - if (gametype == GT_CTF && player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) - P_PlayerFlagBurst(player, false); - break; + case 11: // Unused case 12: // Wall Sector (Don't step-up/down) case 13: // Ramp Sector (Increase step-up/down) case 14: // Non-Ramp Sector (Don't step-down) @@ -3899,59 +4482,53 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers case 3: // Linedef executor requires all players present /// \todo check continues for proper splitscreen support? for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && (gametype != GT_COOP || players[i].lives > 0)) + { + if (!playeringame[i]) + continue; + if (!players[i].mo) + continue; + if (players[i].spectator) + continue; + if (players[i].bot) + continue; + if (roversector) { - if (roversector) + if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) { - if (players[i].mo->subsector->sector == roversector) - ; - else if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) + msecnode_t *node; + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) { - boolean insector = false; - msecnode_t *node; - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector == roversector) - { - insector = true; - break; - } - } - if (!insector) - goto DoneSection2; + if (P_ThingIsOnThe3DFloor(players[i].mo, sector, node->m_sector)) + break; } - else + if (!node) goto DoneSection2; - - if (!P_ThingIsOnThe3DFloor(players[i].mo, sector, roversector)) + } + else if (players[i].mo->subsector && !P_ThingIsOnThe3DFloor(players[i].mo, sector, players[i].mo->subsector->sector)) // this function handles basically everything for us lmao + goto DoneSection2; + } + else + { + if (players[i].mo->subsector->sector == sector) + ; + else if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) + { + msecnode_t *node; + for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) + { + if (node->m_sector == sector) + break; + } + if (!node) goto DoneSection2; } else - { - if (players[i].mo->subsector->sector == sector) - ; - else if (sector->flags & SF_TRIGGERSPECIAL_TOUCH) - { - boolean insector = false; - msecnode_t *node; - for (node = players[i].mo->touching_sectorlist; node; node = node->m_sectorlist_next) - { - if (node->m_sector == sector) - { - insector = true; - break; - } - } - if (!insector) - goto DoneSection2; - } - else - goto DoneSection2; + goto DoneSection2; - if (special == 3 && !P_MobjReadyToTrigger(players[i].mo, sector)) - goto DoneSection2; - } + if (special == 3 && !P_MobjReadyToTrigger(players[i].mo, sector)) + goto DoneSection2; } + } /* FALLTHRU */ case 4: // Linedef executor that doesn't require touching floor case 5: // Linedef executor @@ -3972,14 +4549,14 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // Find the center of the Eggtrap and release all the pretty animals! // The chimps are my friends.. heeheeheheehehee..... - LouisJM - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; - mo2 = (mobj_t *)th; - if (mo2->type == MT_EGGTRAP) - P_KillMobj(mo2, NULL, player->mo); + if (mo2->type != MT_EGGTRAP) + continue; + P_KillMobj(mo2, NULL, player->mo, DMG_NORMAL); } // clear the special so you can't push the button twice. @@ -3998,7 +4575,11 @@ void P_ProcessSpecialSector(player_t *player, sector_t *sector, sector_t *rovers // Mark all players with the time to exit thingy! for (i = 0; i < MAXPLAYERS; i++) + { + if (!playeringame[i]) + continue; P_DoPlayerExit(&players[i]); + } break; } case 10: // Special Stage Time/Rings @@ -4057,8 +4638,7 @@ DoneSection2: case 4: // Conveyor Belt break; - case 5: // Speed pad w/o spin - case 6: // Speed pad w/ spin + case 5: // Speed pad if (player->kartstuff[k_floorboost] != 0) { player->kartstuff[k_floorboost] = 2; @@ -4073,6 +4653,12 @@ DoneSection2: fixed_t linespeed = P_AproxDistance(lines[i].v2->x-lines[i].v1->x, lines[i].v2->y-lines[i].v1->y); fixed_t playerspeed = P_AproxDistance(player->mo->momx, player->mo->momy); + if (linespeed == 0) + { + CONS_Debug(DBG_GAMELOGIC, "ERROR: Speed pad (tag %d) at zero speed.\n", sector->tag); + break; + } + // SRB2Kart: Scale the speed you get from them! // This is scaled differently from other horizontal speed boosts from stuff like springs, because of how this is used for some ramp jumps. if (player->mo->scale > mapobjectscale) @@ -4094,15 +4680,16 @@ DoneSection2: } break; - case 7: // Bustable block sprite parameter - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: + case 6: // Unused + case 7: // Unused + case 8: // Unused + case 9: // Unused + case 10: // Unused + case 11: // Unused + case 12: // Unused + case 13: // Unused + case 14: // Unused + case 15: // Unused break; } @@ -4118,14 +4705,11 @@ DoneSection2: if (!post) break; - P_TouchSpecialThing(post, player->mo, false); + P_TouchStarPost(post, player, false); break; } case 2: // Special stage GOAL sector / Exit Sector / CTF Flag Return - if (!useNightsSS && G_IsSpecialStage(gamemap) && sstimer > 6) - sstimer = 6; // Just let P_Ticker take care of the rest. - // Exit (for FOF exits; others are handled in P_PlayerThink in p_user.c) { INT32 lineindex; @@ -4138,84 +4722,18 @@ DoneSection2: // FOF custom exits not to work. lineindex = P_FindSpecialLineFromTag(2, sector->tag, -1); - if (gametype == GT_COOP && lineindex != -1) // Custom exit! + if (lineindex != -1) // Custom exit! { - // Special goodies with the block monsters flag depending on emeralds collected - if ((lines[lineindex].flags & ML_BLOCKPLAYERS) && ALL7EMERALDS(emeralds)) - nextmapoverride = (INT16)(lines[lineindex].frontsector->ceilingheight>>FRACBITS); - else - nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS); + nextmapoverride = (INT16)(lines[lineindex].frontsector->floorheight>>FRACBITS); if (lines[lineindex].flags & ML_NOCLIMB) - skipstats = true; + skipstats = 1; } } break; - case 3: // Red Team's Base - if (gametype == GT_CTF && P_IsObjectOnGround(player->mo)) - { - if (player->ctfteam == 1 && (player->gotflag & GF_BLUEFLAG)) - { - mobj_t *mo; - - // Make sure the red team still has their own - // flag at their base so they can score. - if (!P_IsFlagAtBase(MT_REDFLAG)) - break; - - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho(va(M_GetText("%s\\captured the blue flag.\\\\\\\\"), player_names[player-players])); - - if (splitscreen || players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_flgcap); - else if (players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_lose); - - mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z,MT_BLUEFLAG); - player->gotflag &= ~GF_BLUEFLAG; - mo->flags &= ~MF_SPECIAL; - mo->fuse = TICRATE; - mo->spawnpoint = bflagpoint; - mo->flags2 |= MF2_JUSTATTACKED; - redscore += 1; - P_AddPlayerScore(player, 5); - } - } - break; - - case 4: // Blue Team's Base - if (gametype == GT_CTF && P_IsObjectOnGround(player->mo)) - { - if (player->ctfteam == 2 && (player->gotflag & GF_REDFLAG)) - { - mobj_t *mo; - - // Make sure the blue team still has their own - // flag at their base so they can score. - if (!P_IsFlagAtBase(MT_BLUEFLAG)) - break; - - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho(va(M_GetText("%s\\captured the red flag.\\\\\\\\"), player_names[player-players])); - - if (splitscreen || players[consoleplayer].ctfteam == 2) - S_StartSound(NULL, sfx_flgcap); - else if (players[consoleplayer].ctfteam == 1) - S_StartSound(NULL, sfx_lose); - - mo = P_SpawnMobj(player->mo->x,player->mo->y,player->mo->z,MT_REDFLAG); - player->gotflag &= ~GF_REDFLAG; - mo->flags &= ~MF_SPECIAL; - mo->fuse = TICRATE; - mo->spawnpoint = rflagpoint; - mo->flags2 |= MF2_JUSTATTACKED; - bluescore += 1; - P_AddPlayerScore(player, 5); - } - } + case 3: // Red Team's goal + case 4: // Blue Team's goal break; case 5: // Fan sector @@ -4225,8 +4743,6 @@ DoneSection2: player->mo->momz = mobjinfo[MT_FAN].mass; P_ResetPlayer(player); - //if (player->panim != PA_FALL) // SRB2kart - // P_SetPlayerMobjState(player->mo, S_PLAY_FALL1); break; case 6: // SRB2kart 190117 - Sneaker Panel @@ -4248,12 +4764,13 @@ DoneSection2: INT32 sequence; fixed_t speed; INT32 lineindex; - thinker_t *th; mobj_t *waypoint = NULL; - mobj_t *mo2; angle_t an; - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) + break; + + if (player->powers[pw_ignorelatch] & (1<<15)) break; // Find line #3 tagged to this sector @@ -4266,26 +4783,17 @@ DoneSection2: } // Grab speed and sequence values - speed = abs(lines[lineindex].dx)/8; - sequence = abs(lines[lineindex].dy)>>FRACBITS; + speed = abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - // scan the thinkers - // to find the first waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (speed == 0) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence - && mo2->health == 0) - { - waypoint = mo2; - break; - } + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + break; } + waypoint = P_GetFirstTubeWaypoint(sequence); + if (!waypoint) { CONS_Debug(DBG_GAMELOGIC, "ERROR: FIRST WAYPOINT IN SEQUENCE %d NOT FOUND.\n", sequence); @@ -4302,20 +4810,10 @@ DoneSection2: break; // behind back P_SetTarget(&player->mo->tracer, waypoint); + player->powers[pw_carry] = CR_ZOOMTUBE; player->speed = speed; - player->pflags &= ~PF_SPINNING; // SRB2kart 200117 - player->pflags &= ~PF_JUMPED; - player->pflags &= ~PF_GLIDING; - player->climbing = 0; - if (!(player->mo->state >= &states[S_KART_FAST1] && player->mo->state <= &states[S_KART_FAST2])) - P_SetPlayerMobjState(player->mo, S_KART_FAST1); - - //if (!(player->mo->state >= &states[S_PLAY_ATK1] && player->mo->state <= &states[S_PLAY_ATK4])) // SRB2kart - //{ - // P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - // S_StartSound(player->mo, sfx_spin); - //} + player->pflags &= ~(PF_SLIDING); } break; @@ -4324,12 +4822,13 @@ DoneSection2: INT32 sequence; fixed_t speed; INT32 lineindex; - thinker_t *th; mobj_t *waypoint = NULL; - mobj_t *mo2; angle_t an; - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) + if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT && player->powers[pw_carry] == CR_ZOOMTUBE) + break; + + if (player->powers[pw_ignorelatch] & (1<<15)) break; // Find line #3 tagged to this sector @@ -4342,27 +4841,17 @@ DoneSection2: } // Grab speed and sequence values - speed = -(abs(lines[lineindex].dx)/8); // Negative means reverse - sequence = abs(lines[lineindex].dy)>>FRACBITS; + speed = -abs(sides[lines[lineindex].sidenum[0]].textureoffset)/8; // Negative means reverse + sequence = abs(sides[lines[lineindex].sidenum[0]].rowoffset)>>FRACBITS; - // scan the thinkers - // to find the last waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) + if (speed == 0) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_TUBEWAYPOINT && mo2->threshold == sequence) - { - if (!waypoint) - waypoint = mo2; - else if (mo2->health > waypoint->health) - waypoint = mo2; - } + CONS_Debug(DBG_GAMELOGIC, "ERROR: Waypoint sequence %d at zero speed.\n", sequence); + break; } + waypoint = P_GetLastTubeWaypoint(sequence); + if (!waypoint) { CONS_Debug(DBG_GAMELOGIC, "ERROR: LAST WAYPOINT IN SEQUENCE %d NOT FOUND.\n", sequence); @@ -4379,280 +4868,13 @@ DoneSection2: break; // behind back P_SetTarget(&player->mo->tracer, waypoint); + player->powers[pw_carry] = CR_ZOOMTUBE; player->speed = speed; - player->pflags &= ~PF_SPINNING; // SRB2kart 200117 - player->pflags &= ~PF_JUMPED; - - if (!(player->mo->state >= &states[S_KART_FAST1] && player->mo->state <= &states[S_KART_FAST2])) - P_SetPlayerMobjState(player->mo, S_KART_FAST1); - - //if (!(player->mo->state >= &states[S_PLAY_ATK1] && player->mo->state <= &states[S_PLAY_ATK4])) // SRB2kart - //{ - // P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - // S_StartSound(player->mo, sfx_spin); - //} } break; - case 10: // Finish Line (Unused) - // SRB2Kart 20190616 - Is now a linedef type that activates by crossing over it - break; - - case 11: // Rope hang - { - INT32 sequence; - fixed_t speed; - INT32 lineindex; - thinker_t *th; - mobj_t *waypointmid = NULL; - mobj_t *waypointhigh = NULL; - mobj_t *waypointlow = NULL; - mobj_t *mo2; - mobj_t *closest = NULL; - line_t junk; - vertex_t v1, v2, resulthigh, resultlow; - mobj_t *highest = NULL; - - if (player->mo->tracer && player->mo->tracer->type == MT_TUBEWAYPOINT) - break; - - if (player->mo->momz > 0) - break; - - if (player->cmd.buttons & BT_BRAKE) - break; - - if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate]) - break; - - if (player->exiting) - break; - - //initialize resulthigh and resultlow with 0 - memset(&resultlow, 0x00, sizeof(resultlow)); - memset(&resulthigh, 0x00, sizeof(resulthigh)); - - // Find line #11 tagged to this sector - lineindex = P_FindSpecialLineFromTag(11, sector->tag, -1); - - if (lineindex == -1) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: Sector special %d missing line special #11.\n", sector->special); - break; - } - - // Grab speed and sequence values - speed = abs(lines[lineindex].dx)/8; - sequence = abs(lines[lineindex].dy)>>FRACBITS; - - // Find the closest waypoint - // Find the preceding waypoint - // Find the proceeding waypoint - // Determine the closest spot on the line between the three waypoints - // Put player at that location. - - // scan the thinkers - // to find the first waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (!highest) - highest = mo2; - else if (mo2->health > highest->health) // Find the highest waypoint # in case we wrap - highest = mo2; - - if (closest && P_AproxDistance(P_AproxDistance(player->mo->x-mo2->x, player->mo->y-mo2->y), - player->mo->z-mo2->z) > P_AproxDistance(P_AproxDistance(player->mo->x-closest->x, - player->mo->y-closest->y), player->mo->z-closest->z)) - continue; - - // Found a target - closest = mo2; - } - - waypointmid = closest; - - closest = NULL; - - if (waypointmid == NULL) - { - CONS_Debug(DBG_GAMELOGIC, "ERROR: WAYPOINT(S) IN SEQUENCE %d NOT FOUND.\n", sequence); - break; - } - - // Find waypoint before this one (waypointlow) - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (waypointmid->health == 0) - { - if (mo2->health != highest->health) - continue; - } - else if (mo2->health != waypointmid->health - 1) - continue; - - // Found a target - waypointlow = mo2; - break; - } - - // Find waypoint after this one (waypointhigh) - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold != sequence) - continue; - - if (waypointmid->health == highest->health) - { - if (mo2->health != 0) - continue; - } - else if (mo2->health != waypointmid->health + 1) - continue; - - // Found a target - waypointhigh = mo2; - break; - } - - CONS_Debug(DBG_GAMELOGIC, "WaypointMid: %d; WaypointLow: %d; WaypointHigh: %d\n", - waypointmid->health, waypointlow ? waypointlow->health : -1, waypointhigh ? waypointhigh->health : -1); - - // Now we have three waypoints... the closest one we're near, and the one that comes before, and after. - // Next, we need to find the closest point on the line between each set, and determine which one we're - // closest to. - - // Waypointmid and Waypointlow: - if (waypointlow) - { - v1.x = waypointmid->x; - v1.y = waypointmid->y; - v1.z = waypointmid->z; - v2.x = waypointlow->x; - v2.y = waypointlow->y; - v2.z = waypointlow->z; - junk.v1 = &v1; - junk.v2 = &v2; - junk.dx = v2.x - v1.x; - junk.dy = v2.y - v1.y; - - P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resultlow); - } - - // Waypointmid and Waypointhigh: - if (waypointhigh) - { - v1.x = waypointmid->x; - v1.y = waypointmid->y; - v1.z = waypointmid->z; - v2.x = waypointhigh->x; - v2.y = waypointhigh->y; - v2.z = waypointhigh->z; - junk.v1 = &v1; - junk.v2 = &v2; - junk.dx = v2.x - v1.x; - junk.dy = v2.y - v1.y; - - P_ClosestPointOnLine3D(player->mo->x, player->mo->y, player->mo->z, &junk, &resulthigh); - } - - // 3D support now available. Disregard the previous notice here. -Red - - P_UnsetThingPosition(player->mo); - P_ResetPlayer(player); - player->mo->momx = player->mo->momy = player->mo->momz = 0; - - if (lines[lineindex].flags & ML_EFFECT1) // Don't wrap - { - highest->flags |= MF_SLIDEME; - } - - // Changing the conditions on these ifs to fix issues with snapping to the wrong spot -Red - if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == 0) - { - closest = waypointhigh; - player->mo->x = resulthigh.x; - player->mo->y = resulthigh.y; - player->mo->z = resulthigh.z - P_GetPlayerHeight(player); - } - else if ((lines[lineindex].flags & ML_EFFECT1) && waypointmid->health == highest->health) - { - closest = waypointmid; - player->mo->x = resultlow.x; - player->mo->y = resultlow.y; - player->mo->z = resultlow.z - P_GetPlayerHeight(player); - } - else - { - if (P_AproxDistance(P_AproxDistance(player->mo->x-resultlow.x, player->mo->y-resultlow.y), - player->mo->z-resultlow.z) < P_AproxDistance(P_AproxDistance(player->mo->x-resulthigh.x, - player->mo->y-resulthigh.y), player->mo->z-resulthigh.z)) - { - // Line between Mid and Low is closer - closest = waypointmid; - player->mo->x = resultlow.x; - player->mo->y = resultlow.y; - player->mo->z = resultlow.z - P_GetPlayerHeight(player); - } - else - { - // Line between Mid and High is closer - closest = waypointhigh; - player->mo->x = resulthigh.x; - player->mo->y = resulthigh.y; - player->mo->z = resulthigh.z - P_GetPlayerHeight(player); - } - } - - P_SetTarget(&player->mo->tracer, closest); - - // Option for static ropes. - if (lines[lineindex].flags & ML_NOCLIMB) - player->speed = 0; - else - player->speed = speed; - - player->pflags |= PF_ROPEHANG; - - S_StartSound(player->mo, sfx_s3k4a); - - player->pflags &= ~PF_JUMPED; - player->pflags &= ~PF_GLIDING; - player->pflags &= ~PF_SLIDING; - player->climbing = 0; - P_SetThingPosition(player->mo); - //P_SetPlayerMobjState(player->mo, S_PLAY_CARRY); // SRB2kart - } - break; + case 10: // Unused + case 11: // Unused case 12: // Camera noclip case 13: // Unused case 14: // Unused @@ -4694,26 +4916,11 @@ sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) if (((rover->flags & FF_BLOCKPLAYER) && mo->player) || ((rover->flags & FF_BLOCKOTHERS) && !mo->player)) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(mo->eflags & MFE_VERTICALFLIP)) && (mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (mo->eflags & MFE_VERTICALFLIP)) && (mo->z + mo->height == bottomheight)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((mo->eflags & MFE_VERTICALFLIP) || mo->z != topheight) - continue; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(mo->eflags & MFE_VERTICALFLIP) - || mo->z + mo->height != bottomheight) - continue; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((mo->eflags & MFE_VERTICALFLIP && mo->z + mo->height == bottomheight) - || (!(mo->eflags & MFE_VERTICALFLIP) && mo->z == topheight))) - continue; - } + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -4756,26 +4963,11 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) // Check the 3D floor's type... if (rover->flags & FF_BLOCKPLAYER) { + boolean floorallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == topheight)); + boolean ceilingallowed = ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) && ((rover->master->frontsector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == bottomheight)); // Thing must be on top of the floor to be affected... - if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING)) - { - if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != topheight) - continue; - } - else if ((rover->master->frontsector->flags & SF_FLIPSPECIAL_CEILING) - && !(rover->master->frontsector->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP) - || player->mo->z + player->mo->height != bottomheight) - continue; - } - else if (rover->master->frontsector->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == bottomheight) - || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == topheight))) - continue; - } + if (!(floorallowed || ceilingallowed)) + continue; } else { @@ -4832,38 +5024,16 @@ static void P_PlayerOnSpecial3DFloor(player_t *player, sector_t *sector) } if (!(po->flags & POF_TESTHEIGHT)) // Don't do height checking - { - } + ; else if (po->flags & POF_SOLID) { + boolean floorallowed = ((polysec->flags & SF_FLIPSPECIAL_FLOOR) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == polysec->ceilingheight)); + boolean ceilingallowed = ((polysec->flags & SF_FLIPSPECIAL_CEILING) && ((polysec->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == polysec->floorheight)); // Thing must be on top of the floor to be affected... - if ((polysec->flags & SF_FLIPSPECIAL_FLOOR) - && !(polysec->flags & SF_FLIPSPECIAL_CEILING)) + if (!(floorallowed || ceilingallowed)) { - if ((player->mo->eflags & MFE_VERTICALFLIP) || player->mo->z != polysec->ceilingheight) - { - po = (polyobj_t *)(po->link.next); - continue; - } - } - else if ((polysec->flags & SF_FLIPSPECIAL_CEILING) - && !(polysec->flags & SF_FLIPSPECIAL_FLOOR)) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP) - || player->mo->z + player->mo->height != polysec->floorheight) - { - po = (polyobj_t *)(po->link.next); - continue; - } - } - else if (polysec->flags & SF_FLIPSPECIAL_BOTH) - { - if (!((player->mo->eflags & MFE_VERTICALFLIP && player->mo->z + player->mo->height == polysec->floorheight) - || (!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z == polysec->ceilingheight))) - { - po = (polyobj_t *)(po->link.next); - continue; - } + po = (polyobj_t *)(po->link.next); + continue; } } else @@ -4934,16 +5104,8 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) // Check Section 4 switch(GETSECSPECIAL(sector->special, 4)) { - case 2: // Level Exit / GOAL Sector / Flag Return - if (!useNightsSS && G_IsSpecialStage(gamemap)) - { - // Special stage GOAL sector - // requires touching floor. - break; - } - /* FALLTHRU */ - case 1: // Starpost activator + case 2: // Level Exit / GOAL Sector / Flag Return case 5: // Fan sector case 6: // Super Sonic Transform case 8: // Zoom Tube Start @@ -4962,17 +5124,13 @@ static void P_RunSpecialSectorCheck(player_t *player, sector_t *sector) f_affectpoint = P_GetSpecialBottomZ(player->mo, sector, sector); c_affectpoint = P_GetSpecialTopZ(player->mo, sector, sector); - // Only go further if on the ground - if ((sector->flags & SF_FLIPSPECIAL_FLOOR) && !(sector->flags & SF_FLIPSPECIAL_CEILING) && player->mo->z != f_affectpoint) - return; - - if ((sector->flags & SF_FLIPSPECIAL_CEILING) && !(sector->flags & SF_FLIPSPECIAL_FLOOR) && player->mo->z + player->mo->height != c_affectpoint) - return; - - if ((sector->flags & SF_FLIPSPECIAL_BOTH) - && player->mo->z != f_affectpoint - && player->mo->z + player->mo->height != c_affectpoint) - return; + { + boolean floorallowed = ((sector->flags & SF_FLIPSPECIAL_FLOOR) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || !(player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z == f_affectpoint)); + boolean ceilingallowed = ((sector->flags & SF_FLIPSPECIAL_CEILING) && ((sector->flags & SF_TRIGGERSPECIAL_HEADBUMP) || (player->mo->eflags & MFE_VERTICALFLIP)) && (player->mo->z + player->mo->height == c_affectpoint)); + // Thing must be on top of the floor to be affected... + if (!(floorallowed || ceilingallowed)) + return; + } P_ProcessSpecialSector(player, sector, NULL); } @@ -5040,11 +5198,6 @@ void P_UpdateSpecials(void) // POINT LIMIT P_CheckPointLimit(); -#ifdef ESLOPE - // Dynamic slopeness - P_RunDynamicSlopes(); -#endif - // ANIMATE TEXTURES for (anim = anims; anim < lastanim; anim++) { @@ -5065,13 +5218,52 @@ void P_UpdateSpecials(void) { if (foundflats->speed) // it is an animated flat { + // update the levelflat texture number + if ((foundflats->type == LEVELFLAT_TEXTURE) && (foundflats->u.texture.basenum != -1)) + foundflats->u.texture.num = foundflats->u.texture.basenum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); // update the levelflat lump number - foundflats->lumpnum = foundflats->baselumpnum + - ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); + else if ((foundflats->type == LEVELFLAT_FLAT) && (foundflats->u.flat.baselumpnum != LUMPERROR)) + foundflats->u.flat.lumpnum = foundflats->u.flat.baselumpnum + ((leveltime/foundflats->speed + foundflats->animseq) % foundflats->numpics); } } } +// +// Floor over floors (FOFs), 3Dfloors, 3Dblocks, fake floors (ffloors), rovers, or whatever you want to call them +// + +/** Gets the ID number for a 3Dfloor in its target sector. + * + * \param fflr The 3Dfloor we want an ID for. + * \return ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. UINT16_MAX is given if invalid. + * \sa P_GetFFloorByID + */ +UINT16 P_GetFFloorID(ffloor_t *fflr) +{ + ffloor_t *rover; + sector_t *sec; + UINT16 i = 0; + + if (!fflr) + return UINT16_MAX; + + sec = fflr->target; + + if (!sec->ffloors) + return UINT16_MAX; + for (rover = sec->ffloors; rover; rover = rover->next, i++) + if (rover == fflr) + return i; + return UINT16_MAX; +} + +/** Gets a 3Dfloor by control sector. + * + * \param sec Target sector. + * \param sec2 Control sector. + * \return Pointer to found 3Dfloor, or NULL. + * \sa P_GetFFloorByID + */ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) { ffloor_t *rover; @@ -5084,29 +5276,49 @@ static inline ffloor_t *P_GetFFloorBySec(sector_t *sec, sector_t *sec2) return NULL; } +/** Gets a 3Dfloor by ID number. + * + * \param sec Target sector. + * \param id ID of 3Dfloor in target sector. Note that the first FOF's ID is 0. + * \return Pointer to found 3Dfloor, or NULL. + * \sa P_GetFFloorBySec, P_GetFFloorID + */ +ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id) +{ + ffloor_t *rover; + UINT16 i = 0; + + if (!sec->ffloors) + return NULL; + for (rover = sec->ffloors; rover; rover = rover->next) + if (i++ == id) + return rover; + return NULL; +} + /** Adds a newly formed 3Dfloor structure to a sector's ffloors list. * * \param sec Target sector. - * \param ffloor Newly formed 3Dfloor structure. + * \param fflr Newly formed 3Dfloor structure. * \sa P_AddFakeFloor */ -static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *ffloor) +static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *fflr) { ffloor_t *rover; if (!sec->ffloors) { - sec->ffloors = ffloor; - ffloor->next = 0; - ffloor->prev = 0; + sec->ffloors = fflr; + fflr->next = 0; + fflr->prev = 0; return; } for (rover = sec->ffloors; rover->next; rover = rover->next); - rover->next = ffloor; - ffloor->prev = rover; - ffloor->next = 0; + rover->next = fflr; + fflr->prev = rover; + fflr->next = 0; } /** Adds a 3Dfloor. @@ -5121,18 +5333,17 @@ static inline void P_AddFFloorToList(sector_t *sec, ffloor_t *ffloor) */ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, ffloortype_e flags, thinkerlist_t *secthinkers) { - ffloor_t *ffloor; + ffloor_t *fflr; thinker_t *th; friction_t *f; pusher_t *p; - levelspecthink_t *lst; size_t sec2num; size_t i; if (sec == sec2) return NULL; //Don't need a fake floor on a control sector. - if ((ffloor = (P_GetFFloorBySec(sec, sec2)))) - return ffloor; // If this ffloor already exists, return it + if ((fflr = (P_GetFFloorBySec(sec, sec2)))) + return fflr; // If this ffloor already exists, return it if (sec2->ceilingheight < sec2->floorheight) { @@ -5143,8 +5354,6 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f sec2->floorheight = tempceiling; } - sec2->tagline = master; - if (sec2->numattached == 0) { sec2->attached = Z_Malloc(sizeof (*sec2->attached) * sec2->maxattached, PU_STATIC, NULL); @@ -5171,28 +5380,30 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f } // Add the floor - ffloor = Z_Calloc(sizeof (*ffloor), PU_LEVEL, NULL); - ffloor->secnum = sec2 - sectors; - ffloor->target = sec; - ffloor->bottomheight = &sec2->floorheight; - ffloor->bottompic = &sec2->floorpic; - ffloor->bottomxoffs = &sec2->floor_xoffs; - ffloor->bottomyoffs = &sec2->floor_yoffs; - ffloor->bottomangle = &sec2->floorpic_angle; + fflr = Z_Calloc(sizeof (*fflr), PU_LEVEL, NULL); + fflr->secnum = sec2 - sectors; + fflr->target = sec; + fflr->bottomheight = &sec2->floorheight; + fflr->bottompic = &sec2->floorpic; + fflr->bottomxoffs = &sec2->floor_xoffs; + fflr->bottomyoffs = &sec2->floor_yoffs; + fflr->bottomangle = &sec2->floorpic_angle; // Add the ceiling - ffloor->topheight = &sec2->ceilingheight; - ffloor->toppic = &sec2->ceilingpic; - ffloor->toplightlevel = &sec2->lightlevel; - ffloor->topxoffs = &sec2->ceiling_xoffs; - ffloor->topyoffs = &sec2->ceiling_yoffs; - ffloor->topangle = &sec2->ceilingpic_angle; + fflr->topheight = &sec2->ceilingheight; + fflr->toppic = &sec2->ceilingpic; + fflr->toplightlevel = &sec2->lightlevel; + fflr->topxoffs = &sec2->ceiling_xoffs; + fflr->topyoffs = &sec2->ceiling_yoffs; + fflr->topangle = &sec2->ceilingpic_angle; -#ifdef ESLOPE // Add slopes - ffloor->t_slope = &sec2->c_slope; - ffloor->b_slope = &sec2->f_slope; -#endif + fflr->t_slope = &sec2->c_slope; + fflr->b_slope = &sec2->f_slope; + // mark the target sector as having slopes, if the FOF has any of its own + // (this fixes FOF slopes glitching initially at level load in software mode) + if (sec2->hasslope) + sec->hasslope = true; if ((flags & FF_SOLID) && (master->flags & ML_EFFECT1)) // Block player only flags &= ~FF_BLOCKOTHERS; @@ -5200,10 +5411,10 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if ((flags & FF_SOLID) && (master->flags & ML_EFFECT2)) // Block all BUT player flags &= ~FF_BLOCKPLAYER; - ffloor->spawnflags = ffloor->flags = flags; - ffloor->master = master; - ffloor->norender = INFTICS; - + fflr->spawnflags = fflr->flags = flags; + fflr->master = master; + fflr->norender = INFTICS; + fflr->fadingdata = NULL; // Scan the thinkers to check for special conditions applying to this FOF. // If we have thinkers sorted by sector, just check the relevant ones; @@ -5213,7 +5424,7 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f // Just initialise both of these to placate the compiler. i = 0; - th = thinkercap.next; + th = thlist[THINK_MAIN].next; for(;;) { @@ -5223,19 +5434,11 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f th = secthinkers[sec2num].thinkers[i]; else break; } - else if (th == &thinkercap) + else if (th == &thlist[THINK_MAIN]) break; - // Should this FOF have spikeness? - if (th->function.acp1 == (actionf_p1)T_SpikeSector) - { - lst = (levelspecthink_t *)th; - - if (lst->sector == sec2) - P_AddSpikeThinker(sec, (INT32)sec2num); - } // Should this FOF have friction? - else if(th->function.acp1 == (actionf_p1)T_Friction) + if(th->function.acp1 == (actionf_p1)T_Friction) { f = (friction_t *)th; @@ -5259,14 +5462,14 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if (flags & FF_TRANSLUCENT) { if (sides[master->sidenum[0]].toptexture > 0) - ffloor->alpha = sides[master->sidenum[0]].toptexture; // for future reference, "#0" is 1, and "#255" is 256. Be warned + fflr->alpha = sides[master->sidenum[0]].toptexture; // for future reference, "#0" is 1, and "#255" is 256. Be warned else - ffloor->alpha = 0x80; + fflr->alpha = 0x80; } else - ffloor->alpha = 0xff; + fflr->alpha = 0xff; - ffloor->spawnalpha = ffloor->alpha; // save for netgames + fflr->spawnalpha = fflr->alpha; // save for netgames if (flags & FF_QUICKSAND) CheckForQuicksand = true; @@ -5276,12 +5479,13 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f if ((flags & FF_MARIO)) { - P_AddBlockThinker(sec2, master); + if (!(flags & FF_SHATTERBOTTOM)) // Don't change the textures of a brick block, just a question block + P_AddBlockThinker(sec2, master); CheckForMarioBlocks = true; } if ((flags & FF_CRUMBLE)) - sec2->crumblestate = 1; + sec2->crumblestate = CRUMBLE_WAIT; if ((flags & FF_FLOATBOB)) { @@ -5289,33 +5493,9 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f CheckForFloatBob = true; } - P_AddFFloorToList(sec, ffloor); + P_AddFFloorToList(sec, fflr); - return ffloor; -} - -static fixed_t -Floor_height (sector_t *s, fixed_t x, fixed_t y) -{ -#ifdef ESLOPE - return s->f_slope ? P_GetZAt(s->f_slope, x, y) : s->floorheight; -#else - (void)x; - (void)y; - return s->floorheight; -#endif -} - -static fixed_t -Ceiling_height (sector_t *s, fixed_t x, fixed_t y) -{ -#ifdef ESLOPE - return s->c_slope ? P_GetZAt(s->c_slope, x, y) : s->ceilingheight; -#else - (void)x; - (void)y; - return s->ceilingheight; -#endif + return fflr; } static void @@ -5348,12 +5528,12 @@ P_RaiseTaggedThingsToFakeFloor ( if (( mo->flags2 & MF2_OBJECTFLIP )) { offset = ( mo->ceilingz - mo->info->height ) - mo->z; - mo->z = ( Floor_height(control, mo->x, mo->y) - mo->info->height ) - offset; + mo->z = ( P_GetZAt(control->f_slope, mo->x, mo->y, control->floorheight) - mo->info->height ) - offset; } else { offset = mo->z - mo->floorz; - mo->z = Ceiling_height(control, mo->x, mo->y) + offset; + mo->z = P_GetZAt(control->c_slope, mo->x, mo->y, control->ceilingheight) + offset; } } } @@ -5364,28 +5544,6 @@ P_RaiseTaggedThingsToFakeFloor ( // SPECIAL SPAWNING // -/** Adds a spike thinker. - * Sector type Section1:5 will result in this effect. - * - * \param sec Sector in which to add the thinker. - * \param referrer If != sec, then we're dealing with a FOF - * \sa P_SpawnSpecials, T_SpikeSector - * \author SSNTails - */ -static void P_AddSpikeThinker(sector_t *sec, INT32 referrer) -{ - levelspecthink_t *spikes; - - // create and initialize new thinker - spikes = Z_Calloc(sizeof (*spikes), PU_LEVSPEC, NULL); - P_AddThinker(&spikes->thinker); - - spikes->thinker.function.acp1 = (actionf_p1)T_SpikeSector; - - spikes->sector = sec; - spikes->vars[0] = referrer; -} - /** Adds a float thinker. * Float thinkers cause solid 3Dfloors to float on water. * @@ -5394,53 +5552,49 @@ static void P_AddSpikeThinker(sector_t *sec, INT32 referrer) * \sa P_SpawnSpecials, T_FloatSector * \author SSNTails */ -static void P_AddFloatThinker(sector_t *sec, INT32 tag, line_t *sourceline) +static void P_AddFloatThinker(sector_t *sec, UINT16 tag, line_t *sourceline) { - levelspecthink_t *floater; + floatthink_t *floater; // create and initialize new thinker floater = Z_Calloc(sizeof (*floater), PU_LEVSPEC, NULL); - P_AddThinker(&floater->thinker); + P_AddThinker(THINK_MAIN, &floater->thinker); floater->thinker.function.acp1 = (actionf_p1)T_FloatSector; floater->sector = sec; - floater->vars[0] = tag; + floater->tag = (INT16)tag; floater->sourceline = sourceline; } -/** Adds a bridge thinker. - * Bridge thinkers cause a group of FOFs to behave like - * a bridge made up of pieces, that bows under weight. +/** + * Adds a plane displacement thinker. + * Whenever the "control" sector moves, + * the "affectee" sector's floor or ceiling plane moves too! * - * \param sec Control sector. - * \sa P_SpawnSpecials, T_BridgeThinker - * \author SSNTails + * \param speed Rate of movement relative to control sector + * \param control Control sector. + * \param affectee Target sector. + * \param reverse Reverse direction? + * \sa P_SpawnSpecials, T_PlaneDisplace + * \author Monster Iestyn */ -/* -static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec) +static void P_AddPlaneDisplaceThinker(INT32 type, fixed_t speed, INT32 control, INT32 affectee, UINT8 reverse) { - levelspecthink_t *bridge; + planedisplace_t *displace; - // create an initialize new thinker - bridge = Z_Calloc(sizeof (*bridge), PU_LEVSPEC, NULL); - P_AddThinker(&bridge->thinker); + // create and initialize new displacement thinker + displace = Z_Calloc(sizeof (*displace), PU_LEVSPEC, NULL); + P_AddThinker(THINK_MAIN, &displace->thinker); - bridge->thinker.function.acp1 = (actionf_p1)T_BridgeThinker; - - bridge->sector = sec; - bridge->vars[0] = sourceline->frontsector->floorheight; - bridge->vars[1] = sourceline->frontsector->ceilingheight; - bridge->vars[2] = P_AproxDistance(sourceline->dx, sourceline->dy); // Speed - bridge->vars[2] = FixedDiv(bridge->vars[2], 16*FRACUNIT); - bridge->vars[3] = bridge->vars[2]; - - // Start tag and end tag are TARGET SECTORS, not CONTROL SECTORS - // Control sector tags should be End_Tag + (End_Tag - Start_Tag) - bridge->vars[4] = sourceline->tag; // Start tag - bridge->vars[5] = (sides[sourceline->sidenum[0]].textureoffset>>FRACBITS); // End tag + displace->thinker.function.acp1 = (actionf_p1)T_PlaneDisplace; + displace->affectee = affectee; + displace->control = control; + displace->last_height = sectors[control].floorheight; + displace->speed = speed; + displace->type = type; + displace->reverse = reverse; } -*/ /** Adds a Mario block thinker, which changes the block's texture between blank * and ? depending on whether it has contents. @@ -5454,11 +5608,11 @@ static inline void P_AddBridgeThinker(line_t *sourceline, sector_t *sec) */ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline) { - levelspecthink_t *block; + mariocheck_t *block; // create and initialize new elevator thinker block = Z_Calloc(sizeof (*block), PU_LEVSPEC, NULL); - P_AddThinker(&block->thinker); + P_AddThinker(THINK_MAIN, &block->thinker); block->thinker.function.acp1 = (actionf_p1)T_MarioBlockChecker; block->sourceline = sourceline; @@ -5474,111 +5628,68 @@ static void P_AddBlockThinker(sector_t *sec, line_t *sourceline) * to the lowest nearby height if not * there already. * - * Replaces the old "AirBob". - * * \param sec Control sector. - * \param actionsector Target sector. - * \param sourceline Control linedef. * \sa P_SpawnSpecials, T_RaiseSector * \author SSNTails */ -static void P_AddRaiseThinker(sector_t *sec, line_t *sourceline) +static void P_AddRaiseThinker(sector_t *sec, INT16 tag, fixed_t speed, fixed_t ceilingtop, fixed_t ceilingbottom, boolean lower, boolean spindash) { - levelspecthink_t *raise; + raise_t *raise; raise = Z_Calloc(sizeof (*raise), PU_LEVSPEC, NULL); - P_AddThinker(&raise->thinker); + P_AddThinker(THINK_MAIN, &raise->thinker); raise->thinker.function.acp1 = (actionf_p1)T_RaiseSector; - if (sourceline->flags & ML_BLOCKPLAYERS) - raise->vars[0] = 1; - else - raise->vars[0] = 0; - - // set up the fields + raise->tag = tag; raise->sector = sec; - // Require a spindash to activate - if (sourceline->flags & ML_NOCLIMB) - raise->vars[1] = 1; - else - raise->vars[1] = 0; + raise->ceilingtop = ceilingtop; + raise->ceilingbottom = ceilingbottom; - raise->vars[2] = P_AproxDistance(sourceline->dx, sourceline->dy); - raise->vars[2] = FixedDiv(raise->vars[2], 4*FRACUNIT); - raise->vars[3] = raise->vars[2]; + raise->basespeed = speed; - raise->vars[5] = P_FindHighestCeilingSurrounding(sec); - raise->vars[4] = raise->vars[5] - - (sec->ceilingheight - sec->floorheight); - - raise->vars[7] = P_FindLowestCeilingSurrounding(sec); - raise->vars[6] = raise->vars[7] - - (sec->ceilingheight - sec->floorheight); - - raise->sourceline = sourceline; + if (lower) + raise->flags |= RF_REVERSE; + if (spindash) + raise->flags |= RF_SPINDASH; } -// Function to maintain backwards compatibility -static void P_AddOldAirbob(sector_t *sec, line_t *sourceline, boolean noadjust) +static void P_AddAirbob(sector_t *sec, INT16 tag, fixed_t dist, boolean raise, boolean spindash, boolean dynamic) { - levelspecthink_t *airbob; + raise_t *airbob; airbob = Z_Calloc(sizeof (*airbob), PU_LEVSPEC, NULL); - P_AddThinker(&airbob->thinker); + P_AddThinker(THINK_MAIN, &airbob->thinker); airbob->thinker.function.acp1 = (actionf_p1)T_RaiseSector; - // set up the fields + airbob->tag = tag; airbob->sector = sec; - // Require a spindash to activate - if (sourceline->flags & ML_NOCLIMB) - airbob->vars[1] = 1; - else - airbob->vars[1] = 0; + airbob->ceilingtop = sec->ceilingheight; + airbob->ceilingbottom = sec->ceilingheight - dist; - airbob->vars[2] = FRACUNIT; + airbob->basespeed = FRACUNIT; - if (noadjust) - airbob->vars[7] = airbob->sector->ceilingheight-16*FRACUNIT; - else - airbob->vars[7] = airbob->sector->ceilingheight - P_AproxDistance(sourceline->dx, sourceline->dy); - airbob->vars[6] = airbob->vars[7] - - (sec->ceilingheight - sec->floorheight); - - airbob->vars[3] = airbob->vars[2]; - - if (sourceline->flags & ML_BLOCKPLAYERS) - airbob->vars[0] = 1; - else - airbob->vars[0] = 0; - - airbob->vars[5] = sec->ceilingheight; - airbob->vars[4] = airbob->vars[5] - - (sec->ceilingheight - sec->floorheight); - - airbob->sourceline = sourceline; + if (!raise) + airbob->flags |= RF_REVERSE; + if (spindash) + airbob->flags |= RF_SPINDASH; + if (dynamic) + airbob->flags |= RF_DYNAMIC; } /** Adds a thwomp thinker. * Even thwomps need to think! * * \param sec Control sector. - * \param actionsector Target sector. - * \param sourceline Control linedef. * \sa P_SpawnSpecials, T_ThwompSector * \author SSNTails */ -static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, line_t *sourceline) +static inline void P_AddThwompThinker(sector_t *sec, INT16 tag, line_t *sourceline, fixed_t crushspeed, fixed_t retractspeed, UINT16 sound) { -#define speed vars[1] -#define direction vars[2] -#define distance vars[3] -#define floorwasheight vars[4] -#define ceilingwasheight vars[5] - levelspecthink_t *thwomp; + thwomp_t *thwomp; // You *probably* already have a thwomp in this sector. If you've combined it with something // else that uses the floordata/ceilingdata, you must be weird. @@ -5587,70 +5698,67 @@ static inline void P_AddThwompThinker(sector_t *sec, sector_t *actionsector, lin // create and initialize new elevator thinker thwomp = Z_Calloc(sizeof (*thwomp), PU_LEVSPEC, NULL); - P_AddThinker(&thwomp->thinker); + P_AddThinker(THINK_MAIN, &thwomp->thinker); thwomp->thinker.function.acp1 = (actionf_p1)T_ThwompSector; // set up the fields according to the type of elevator action - thwomp->sector = sec; - thwomp->vars[0] = actionsector->tag; - thwomp->floorwasheight = thwomp->sector->floorheight; - thwomp->ceilingwasheight = thwomp->sector->ceilingheight; - thwomp->direction = 0; - thwomp->distance = 1; thwomp->sourceline = sourceline; - thwomp->sector->floordata = thwomp; - thwomp->sector->ceilingdata = thwomp; - return; -#undef speed -#undef direction -#undef distance -#undef floorwasheight -#undef ceilingwasheight + thwomp->sector = sec; + thwomp->crushspeed = crushspeed; + thwomp->retractspeed = retractspeed; + thwomp->direction = 0; + thwomp->floorstartheight = sec->floorheight; + thwomp->ceilingstartheight = sec->ceilingheight; + thwomp->delay = 1; + thwomp->tag = tag; + thwomp->sound = sound; + + sec->floordata = thwomp; + sec->ceilingdata = thwomp; + // Start with 'resting' texture + sides[sourceline->sidenum[0]].midtexture = sides[sourceline->sidenum[0]].bottomtexture; } /** Adds a thinker which checks if any MF_ENEMY objects with health are in the defined area. * If not, a linedef executor is run once. * - * \param sec Control sector. * \param sourceline Control linedef. * \sa P_SpawnSpecials, T_NoEnemiesSector * \author SSNTails */ -static inline void P_AddNoEnemiesThinker(sector_t *sec, line_t *sourceline) +static inline void P_AddNoEnemiesThinker(line_t *sourceline) { - levelspecthink_t *nobaddies; + noenemies_t *nobaddies; // create and initialize new thinker nobaddies = Z_Calloc(sizeof (*nobaddies), PU_LEVSPEC, NULL); - P_AddThinker(&nobaddies->thinker); + P_AddThinker(THINK_MAIN, &nobaddies->thinker); nobaddies->thinker.function.acp1 = (actionf_p1)T_NoEnemiesSector; - nobaddies->sector = sec; nobaddies->sourceline = sourceline; } /** Adds a thinker for Each-Time linedef executors. A linedef executor is run * only when a player enters the area and doesn't run again until they re-enter. * - * \param sec Control sector that contains the lines of executors we will want to run. * \param sourceline Control linedef. * \sa P_SpawnSpecials, T_EachTimeThinker * \author SSNTails */ -static inline void P_AddEachTimeThinker(sector_t *sec, line_t *sourceline) +static void P_AddEachTimeThinker(line_t *sourceline) { - levelspecthink_t *eachtime; + eachtime_t *eachtime; // create and initialize new thinker eachtime = Z_Calloc(sizeof (*eachtime), PU_LEVSPEC, NULL); - P_AddThinker(&eachtime->thinker); + P_AddThinker(THINK_MAIN, &eachtime->thinker); eachtime->thinker.function.acp1 = (actionf_p1)T_EachTimeThinker; - eachtime->sector = sec; eachtime->sourceline = sourceline; + eachtime->triggerOnExit = !!(sourceline->flags & ML_NOTBOUNCY); } /** Adds a camera scanner. @@ -5665,9 +5773,11 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto { elevator_t *elevator; // Why not? LOL + CONS_Alert(CONS_WARNING, M_GetText("Detected a camera scanner effect (linedef type 5). This effect is deprecated and will be removed in the future!\n")); + // create and initialize new elevator thinker elevator = Z_Calloc(sizeof (*elevator), PU_LEVSPEC, NULL); - P_AddThinker(&elevator->thinker); + P_AddThinker(THINK_MAIN, &elevator->thinker); elevator->thinker.function.acp1 = (actionf_p1)T_CameraScanner; elevator->type = elevateBounce; @@ -5678,96 +5788,85 @@ static inline void P_AddCameraScanner(sector_t *sourcesec, sector_t *actionsecto elevator->distance = FixedInt(AngleFixed(angle)); } -static const ffloortype_e laserflags = FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA; - /** Flashes a laser block. * * \param flash Thinker structure for this laser. - * \sa EV_AddLaserThinker + * \sa P_AddLaserThinker * \author SSNTails */ void T_LaserFlash(laserthink_t *flash) { msecnode_t *node; mobj_t *thing; - sector_t *sourcesec; - ffloor_t *ffloor = flash->ffloor; - sector_t *sector = flash->sector; + INT32 s; + ffloor_t *fflr; + sector_t *sector; + sector_t *sourcesec = flash->sourceline->frontsector; fixed_t top, bottom; - if (!ffloor || !(ffloor->flags & FF_EXISTS)) - return; - - if (leveltime & 1) - ffloor->flags |= FF_RENDERALL; - else - ffloor->flags &= ~FF_RENDERALL; - - sourcesec = ffloor->master->frontsector; // Less to type! - -#ifdef ESLOPE - top = (*ffloor->t_slope) ? P_GetZAt(*ffloor->t_slope, sector->soundorg.x, sector->soundorg.y) - : *ffloor->topheight; - bottom = (*ffloor->b_slope) ? P_GetZAt(*ffloor->b_slope, sector->soundorg.x, sector->soundorg.y) - : *ffloor->bottomheight; - sector->soundorg.z = (top + bottom)/2; -#else - sector->soundorg.z = (*ffloor->topheight + *ffloor->bottomheight)/2; -#endif - S_StartSound(§or->soundorg, sfx_laser); - - // Seek out objects to DESTROY! MUAHAHHAHAHAA!!!*cough* - for (node = sector->touching_thinglist; node && node->m_thing; node = node->m_thinglist_next) + for (s = -1; (s = P_FindSectorFromTag(flash->tag, s)) >= 0 ;) { - thing = node->m_thing; + sector = §ors[s]; + for (fflr = sector->ffloors; fflr; fflr = fflr->next) + { + if (fflr->master != flash->sourceline) + continue; - if ((ffloor->master->flags & ML_EFFECT1) - && thing->flags & MF_BOSS) - continue; // Don't hurt bosses + if (!(fflr->flags & FF_EXISTS)) + break; - // Don't endlessly kill egg guard shields (or anything else for that matter) - if (thing->health <= 0) - continue; + if (leveltime & 2) + //fflr->flags |= FF_RENDERALL; + fflr->alpha = 0xB0; + else + //fflr->flags &= ~FF_RENDERALL; + fflr->alpha = 0x90; - top = P_GetSpecialTopZ(thing, sourcesec, sector); - bottom = P_GetSpecialBottomZ(thing, sourcesec, sector); + top = P_GetFFloorTopZAt (fflr, sector->soundorg.x, sector->soundorg.y); + bottom = P_GetFFloorBottomZAt(fflr, sector->soundorg.x, sector->soundorg.y); + sector->soundorg.z = (top + bottom)/2; + S_StartSound(§or->soundorg, sfx_laser); - if (thing->z >= top - || thing->z + thing->height <= bottom) - continue; + // Seek out objects to DESTROY! MUAHAHHAHAHAA!!!*cough* + for (node = sector->touching_thinglist; node && node->m_thing; node = node->m_thinglist_next) + { + thing = node->m_thing; - if (thing->flags & MF_SHOOTABLE) - P_DamageMobj(thing, NULL, NULL, 1); - else if (thing->type == MT_EGGSHIELD) - P_KillMobj(thing, NULL, NULL); + if (flash->nobosses && thing->flags & MF_BOSS) + continue; // Don't hurt bosses + + // Don't endlessly kill egg guard shields (or anything else for that matter) + if (thing->health <= 0) + continue; + + top = P_GetSpecialTopZ(thing, sourcesec, sector); + bottom = P_GetSpecialBottomZ(thing, sourcesec, sector); + + if (thing->z >= top + || thing->z + thing->height <= bottom) + continue; + + if (thing->flags & MF_SHOOTABLE) + P_DamageMobj(thing, NULL, NULL, 1, DMG_NORMAL); + else if (thing->type == MT_EGGSHIELD) + P_KillMobj(thing, NULL, NULL, DMG_NORMAL); + } + + break; + } } } -/** Adds a laser thinker to a 3Dfloor. - * - * \param ffloor 3Dfloor to turn into a laser block. - * \param sector Target sector. - * \param secthkiners Lists of thinkers sorted by sector. May be NULL. - * \sa T_LaserFlash - * \author SSNTails - */ -static inline void EV_AddLaserThinker(sector_t *sec, sector_t *sec2, line_t *line, thinkerlist_t *secthinkers) +static inline void P_AddLaserThinker(INT16 tag, line_t *line, boolean nobosses) { - laserthink_t *flash; - ffloor_t *ffloor = P_AddFakeFloor(sec, sec2, line, laserflags, secthinkers); + laserthink_t *flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); - if (!ffloor) - return; - - flash = Z_Calloc(sizeof (*flash), PU_LEVSPEC, NULL); - - P_AddThinker(&flash->thinker); + P_AddThinker(THINK_MAIN, &flash->thinker); flash->thinker.function.acp1 = (actionf_p1)T_LaserFlash; - flash->ffloor = ffloor; - flash->sector = sec; // For finding mobjs - flash->sec = sec2; + flash->tag = tag; flash->sourceline = line; + flash->nobosses = nobosses; } // @@ -5788,10 +5887,10 @@ static void P_RunLevelLoadExecutors(void) } /** Before things are loaded, initialises certain stuff in case they're needed - * by P_ResetDynamicSlopes or P_LoadThings. This was split off from + * by P_SpawnSlopes or P_LoadThings. This was split off from * P_SpawnSpecials, in case you couldn't tell. * - * \sa P_SpawnSpecials, P_InitTagLists + * \sa P_SpawnSpecials * \author Monster Iestyn */ void P_InitSpecials(void) @@ -5800,18 +5899,53 @@ void P_InitSpecials(void) mapobjectscale = mapheaderinfo[gamemap-1]->mobj_scale; // Set the default gravity. Custom gravity overrides this setting. - gravity = (FRACUNIT*8)/10; + gravity = mapheaderinfo[gamemap-1]->gravity; // Defaults in case levels don't have them set. - sstimer = 90*TICRATE + 6; - totalrings = 1; + sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6; + ssspheres = mapheaderinfo[gamemap-1]->ssspheres; CheckForBustableBlocks = CheckForBouncySector = CheckForQuicksand = CheckForMarioBlocks = CheckForFloatBob = CheckForReverseGravity = false; // Set weather curWeather = globalweather = mapheaderinfo[gamemap-1]->weather; +} - P_InitTagLists(); // Create xref tables for tags +static void P_ApplyFlatAlignment(line_t *master, sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs) +{ + if (!(master->flags & ML_NETONLY)) // Modify floor flat alignment unless ML_NETONLY flag is set + { + sector->floorpic_angle = flatangle; + sector->floor_xoffs += xoffs; + sector->floor_yoffs += yoffs; + } + + if (!(master->flags & ML_NONET)) // Modify ceiling flat alignment unless ML_NONET flag is set + { + sector->ceilingpic_angle = flatangle; + sector->ceiling_xoffs += xoffs; + sector->ceiling_yoffs += yoffs; + } +} + +static boolean P_IsLineDisabled (const line_t * line) +{ + if (line->special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment in netgames... + { + if (netgame || multiplayer) + { + if (line->flags & ML_NONET) + { + return true; + } + } + else if (line->flags & ML_NETONLY) + { + return true; + } + } + + return false; } /** After the map has loaded, scans for specials that spawn 3Dfloors and @@ -5823,18 +5957,21 @@ void P_InitSpecials(void) * as they'll just be erased by UnArchiveThinkers. * \sa P_SpawnPrecipitation, P_SpawnFriction, P_SpawnPushers, P_SpawnScrollers */ -void P_SpawnSpecials(INT32 fromnetsave) +void P_SpawnSpecials(boolean fromnetsave) { sector_t *sector; size_t i; INT32 j; thinkerlist_t *secthinkers; thinker_t *th; - // This used to be used, and *should* be used in the future, // but currently isn't. (void)fromnetsave; + // yep, we do this here - "bossdisabled" is considered an apparatus of specials. + bossdisabled = 0; + stoppedclock = false; + // Init special SECTORs. sector = sectors; for (i = 0; i < numsectors; i++, sector++) @@ -5846,9 +5983,11 @@ void P_SpawnSpecials(INT32 fromnetsave) switch(GETSECSPECIAL(sector->special, 1)) { case 5: // Spikes - P_AddSpikeThinker(sector, (INT32)(sector-sectors)); + //Terrible hack to replace an even worse hack: + //Spike damage automatically sets SF_TRIGGERSPECIAL_TOUCH. + //Yes, this also affects other specials on the same sector. Sorry. + sector->flags |= SF_TRIGGERSPECIAL_TOUCH; break; - case 15: // Bouncy sector CheckForBouncySector = true; break; @@ -5859,7 +5998,7 @@ void P_SpawnSpecials(INT32 fromnetsave) { case 10: // Time for special stage sstimer = (sector->floorheight>>FRACBITS) * TICRATE + 6; // Time to finish - totalrings = sector->ceilingheight>>FRACBITS; // Ring count for special stage + ssspheres = sector->ceilingheight>>FRACBITS; // Ring count for special stage break; case 11: // Custom global gravity! @@ -5883,8 +6022,6 @@ void P_SpawnSpecials(INT32 fromnetsave) } } - P_SearchForDisableLinedefs(); // Disable linedefs are now allowed to disable *any* line - P_SpawnScrollers(); // Add generalized scrollers P_SpawnFriction(); // Friction model using linedefs P_SpawnPushers(); // Pusher model using linedefs @@ -5894,11 +6031,9 @@ void P_SpawnSpecials(INT32 fromnetsave) secthinkers = Z_Calloc(numsectors * sizeof(thinkerlist_t), PU_STATIC, NULL); // Firstly, find out how many there are in each sector - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { - if (th->function.acp1 == (actionf_p1)T_SpikeSector) - secthinkers[((levelspecthink_t *)th)->sector - sectors].count++; - else if (th->function.acp1 == (actionf_p1)T_Friction) + if (th->function.acp1 == (actionf_p1)T_Friction) secthinkers[((friction_t *)th)->affectee].count++; else if (th->function.acp1 == (actionf_p1)T_Pusher) secthinkers[((pusher_t *)th)->affectee].count++; @@ -5914,13 +6049,11 @@ void P_SpawnSpecials(INT32 fromnetsave) } // Finally, populate the lists. - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MAIN].next; th != &thlist[THINK_MAIN]; th = th->next) { size_t secnum = (size_t)-1; - if (th->function.acp1 == (actionf_p1)T_SpikeSector) - secnum = ((levelspecthink_t *)th)->sector - sectors; - else if (th->function.acp1 == (actionf_p1)T_Friction) + if (th->function.acp1 == (actionf_p1)T_Friction) secnum = ((friction_t *)th)->affectee; else if (th->function.acp1 == (actionf_p1)T_Pusher) secnum = ((pusher_t *)th)->affectee; @@ -5932,28 +6065,9 @@ void P_SpawnSpecials(INT32 fromnetsave) // Init line EFFECTs for (i = 0; i < numlines; i++) { - if (lines[i].special != 7) // This is a hack. I can at least hope nobody wants to prevent flat alignment with arbitrary skin setups... + if (P_IsLineDisabled(&lines[i])) { - // set line specials to 0 here too, same reason as above - if (netgame || multiplayer) - { - // future: nonet flag? - } - else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) - { - lines[i].special = 0; - continue; - } - /*else -- commented out because irrelevant to kart. keeping here because we can use these flags for something else now - { - if ((players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) - || (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) - || (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX))) - { - lines[i].special = 0; - continue; - } - }*/ + continue; } switch (lines[i].special) @@ -5964,7 +6078,7 @@ void P_SpawnSpecials(INT32 fromnetsave) case 1: // Definable gravity per sector sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) { sectors[s].gravity = §ors[sec].floorheight; // This allows it to change in realtime! @@ -5988,23 +6102,18 @@ void P_SpawnSpecials(INT32 fromnetsave) case 5: // Change camera info sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) P_AddCameraScanner(§ors[sec], §ors[s], R_PointToAngle2(lines[i].v2->x, lines[i].v2->y, lines[i].v1->x, lines[i].v1->y)); break; -#ifdef PARANOIA - case 6: // Disable tags if level not cleared - I_Error("Failed to catch a disable linedef"); - break; -#endif case 7: // Flat alignment - redone by toast - if ((lines[i].flags & (ML_NOSONIC|ML_NOTAILS)) != (ML_NOSONIC|ML_NOTAILS)) // If you can do something... + if ((lines[i].flags & (ML_NETONLY|ML_NONET)) != (ML_NETONLY|ML_NONET)) // If you can do something... { angle_t flatangle = InvAngle(R_PointToAngle2(lines[i].v1->x, lines[i].v1->y, lines[i].v2->x, lines[i].v2->y)); fixed_t xoffs; fixed_t yoffs; - if (lines[i].flags & ML_NOKNUX) // Set offset through x and y texture offsets if NOKNUX flag is set + if (lines[i].flags & ML_EFFECT6) // Set offset through x and y texture offsets if ML_EFFECT6 flag is set { xoffs = sides[lines[i].sidenum[0]].textureoffset; yoffs = sides[lines[i].sidenum[0]].rowoffset; @@ -6015,27 +6124,13 @@ void P_SpawnSpecials(INT32 fromnetsave) yoffs = lines[i].v1->y; } - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + //If no tag is given, apply to front sector + if (lines[i].tag == 0) + P_ApplyFlatAlignment(lines + i, lines[i].frontsector, flatangle, xoffs, yoffs); + else { - if (!(lines[i].flags & ML_NOSONIC)) // Modify floor flat alignment unless NOSONIC flag is set - { - sectors[s].spawn_flrpic_angle = sectors[s].floorpic_angle = flatangle; - sectors[s].floor_xoffs += xoffs; - sectors[s].floor_yoffs += yoffs; - // saved for netgames - sectors[s].spawn_flr_xoffs = sectors[s].floor_xoffs; - sectors[s].spawn_flr_yoffs = sectors[s].floor_yoffs; - } - - if (!(lines[i].flags & ML_NOTAILS)) // Modify ceiling flat alignment unless NOTAILS flag is set - { - sectors[s].spawn_ceilpic_angle = sectors[s].ceilingpic_angle = flatangle; - sectors[s].ceiling_xoffs += xoffs; - sectors[s].ceiling_yoffs += yoffs; - // saved for netgames - sectors[s].spawn_ceil_xoffs = sectors[s].ceiling_xoffs; - sectors[s].spawn_ceil_yoffs = sectors[s].ceiling_yoffs; - } + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0;) + P_ApplyFlatAlignment(lines + i, sectors + s, flatangle, xoffs, yoffs); } } else // Otherwise, print a helpful warning. Can I do no less? @@ -6045,7 +6140,7 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 8: // Sector Parameters - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) { if (lines[i].flags & ML_NOCLIMB) { @@ -6057,6 +6152,11 @@ void P_SpawnSpecials(INT32 fromnetsave) if (lines[i].flags & ML_EFFECT3) sectors[s].flags |= SF_TRIGGERSPECIAL_TOUCH; + if (lines[i].flags & ML_EFFECT2) + sectors[s].flags |= SF_TRIGGERSPECIAL_HEADBUMP; + + if (lines[i].flags & ML_EFFECT1) + sectors[s].flags |= SF_INVERTPRECIP; if (lines[i].frontsector && GETSECSPECIAL(lines[i].frontsector->special, 4) == 12) sectors[s].camsec = sides[*lines[i].sidenum].sector-sectors; @@ -6068,7 +6168,7 @@ void P_SpawnSpecials(INT32 fromnetsave) case 10: // Vertical culling plane for sprites and FOFs sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) sectors[s].cullheight = &lines[i]; // This allows it to change in realtime! break; @@ -6129,18 +6229,18 @@ void P_SpawnSpecials(INT32 fromnetsave) case 63: // support for drawn heights coming from different sector sec = sides[*lines[i].sidenum].sector-sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) sectors[s].heightsec = (INT32)sec; break; case 64: // Appearing/Disappearing FOF option if (lines[i].flags & ML_BLOCKPLAYERS) { // Find FOFs by control sector tag - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) for (j = 0; (unsigned)j < sectors[s].linecount; j++) if (sectors[s].lines[j]->special >= 100 && sectors[s].lines[j]->special < 300) Add_MasterDisappearer(abs(lines[i].dx>>FRACBITS), abs(lines[i].dy>>FRACBITS), abs(sides[lines[i].sidenum[0]].sector->floorheight>>FRACBITS), (INT32)(sectors[s].lines[j]-lines), (INT32)i); } else // Find FOFs by effect sector tag - for (s = -1; (s = P_FindLineFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindLineFromTag(lines[i].tag, s)) >= 0 ;) { if ((size_t)s == i) continue; @@ -6149,11 +6249,17 @@ void P_SpawnSpecials(INT32 fromnetsave) } break; - case 65: // Bridge Thinker - /* - // Disable this until it's working right! - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - P_AddBridgeThinker(&lines[i], §ors[s]);*/ + case 66: // Displace floor by front sector + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) + P_AddPlaneDisplaceThinker(pd_floor, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); + break; + case 67: // Displace ceiling by front sector + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) + P_AddPlaneDisplaceThinker(pd_ceiling, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); + break; + case 68: // Displace both floor AND ceiling by front sector + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) + P_AddPlaneDisplaceThinker(pd_both, P_AproxDistance(lines[i].dx, lines[i].dy)>>8, sides[lines[i].sidenum[0]].sector-sectors, s, !!(lines[i].flags & ML_NOCLIMB)); break; case 100: // FOF (solid, opaque, shadows) @@ -6170,11 +6276,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_NOCLIMB) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -6281,11 +6384,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_EFFECT2) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -6299,11 +6399,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_EFFECT2) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -6327,11 +6424,8 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_EFFECT2) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); @@ -6345,29 +6439,32 @@ void P_SpawnSpecials(INT32 fromnetsave) // Draw the 'insides' of the block too if (lines[i].flags & ML_EFFECT2) { - ffloorflags |= FF_CUTLEVEL; - ffloorflags |= FF_BOTHPLANES; - ffloorflags |= FF_ALLSIDES; - ffloorflags &= ~FF_EXTRA; - ffloorflags &= ~FF_CUTEXTRA; + ffloorflags |= FF_CUTLEVEL|FF_BOTHPLANES|FF_ALLSIDES; + ffloorflags &= ~(FF_EXTRA|FF_CUTEXTRA); } P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 146: // Intangible floor/ceiling with solid sides (fences/hoops maybe?) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_ALLSIDES|FF_INTANGABLEFLATS, secthinkers); + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERSIDES|FF_ALLSIDES|FF_INTANGIBLEFLATS, secthinkers); break; case 150: // Air bobbing platform case 151: // Adjustable air bobbing platform + { + fixed_t dist = (lines[i].special == 150) ? 16*FRACUNIT : P_AproxDistance(lines[i].dx, lines[i].dy); P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - lines[i].flags |= ML_BLOCKPLAYERS; - P_AddOldAirbob(lines[i].frontsector, lines + i, (lines[i].special != 151)); + P_AddAirbob(lines[i].frontsector, lines[i].tag, dist, false, !!(lines[i].flags & ML_NOCLIMB), false); break; + } case 152: // Adjustable air bobbing platform in reverse P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddOldAirbob(lines[i].frontsector, lines + i, true); + P_AddAirbob(lines[i].frontsector, lines[i].tag, P_AproxDistance(lines[i].dx, lines[i].dy), true, !!(lines[i].flags & ML_NOCLIMB), false); + break; + case 153: // Dynamic Sinking Platform + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); + P_AddAirbob(lines[i].frontsector, lines[i].tag, P_AproxDistance(lines[i].dx, lines[i].dy), false, !!(lines[i].flags & ML_NOCLIMB), true); break; case 160: // Float/bob platform @@ -6417,15 +6514,13 @@ void P_SpawnSpecials(INT32 fromnetsave) case 176: // Air bobbing platform that will crumble and bob on the water when it falls and hits P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_FLOATBOB|FF_CRUMBLE, secthinkers); - lines[i].flags |= ML_BLOCKPLAYERS; - P_AddOldAirbob(lines[i].frontsector, lines + i, true); + P_AddAirbob(lines[i].frontsector, lines[i].tag, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false); break; case 177: // Air bobbing platform that will crumble and bob on // the water when it falls and hits, then never return P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_FLOATBOB|FF_CRUMBLE|FF_NORETURN, secthinkers); - lines[i].flags |= ML_BLOCKPLAYERS; - P_AddOldAirbob(lines[i].frontsector, lines + i, true); + P_AddAirbob(lines[i].frontsector, lines[i].tag, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false); break; case 178: // Crumbling platform that will float when it hits water @@ -6438,49 +6533,36 @@ void P_SpawnSpecials(INT32 fromnetsave) case 180: // Air bobbing platform that will crumble P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_CRUMBLE, secthinkers); - lines[i].flags |= ML_BLOCKPLAYERS; - P_AddOldAirbob(lines[i].frontsector, lines + i, true); + P_AddAirbob(lines[i].frontsector, lines[i].tag, 16*FRACUNIT, false, !!(lines[i].flags & ML_NOCLIMB), false); break; case 190: // Rising Platform FOF (solid, opaque, shadows) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); - break; - case 191: // Rising Platform FOF (solid, opaque, no shadows) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_CUTLEVEL, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); - break; - case 192: // Rising Platform TL block: FOF (solid, translucent) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_NOSHADE|FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); - break; - case 193: // Rising Platform FOF (solid, invisible) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_NOSHADE, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); - break; - case 194: // Rising Platform 'Platform' - You can jump up through it - // If line has no-climb set, don't give it shadows, otherwise do - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_NOSHADE; - - P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); - break; - case 195: // Rising Platform Translucent "platform" - // If line has no-climb set, don't give it shadows, otherwise do - ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_PLATFORM|FF_TRANSLUCENT|FF_BOTHPLANES|FF_ALLSIDES|FF_EXTRA|FF_CUTEXTRA; - if (lines[i].flags & ML_NOCLIMB) - ffloorflags |= FF_NOSHADE; + { + fixed_t speed = FixedDiv(P_AproxDistance(lines[i].dx, lines[i].dy), 4*FRACUNIT); + fixed_t ceilingtop = P_FindHighestCeilingSurrounding(lines[i].frontsector); + fixed_t ceilingbottom = P_FindLowestCeilingSurrounding(lines[i].frontsector); + ffloorflags = FF_EXISTS|FF_SOLID; + if (lines[i].special != 193) + ffloorflags |= FF_RENDERALL; + if (lines[i].special <= 191) + ffloorflags |= FF_CUTLEVEL; + if (lines[i].special == 192 || lines[i].special == 195) + ffloorflags |= FF_TRANSLUCENT|FF_EXTRA|FF_CUTEXTRA; + if (lines[i].special >= 194) + ffloorflags |= FF_PLATFORM|FF_BOTHPLANES|FF_ALLSIDES; + if (lines[i].special != 190 && (lines[i].special <= 193 || lines[i].flags & ML_NOCLIMB)) + ffloorflags |= FF_NOSHADE; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); - P_AddRaiseThinker(lines[i].frontsector, &lines[i]); + + P_AddRaiseThinker(lines[i].frontsector, lines[i].tag, speed, ceilingtop, ceilingbottom, !!(lines[i].flags & ML_BLOCKPLAYERS), !!(lines[i].flags & ML_NOCLIMB)); break; + } case 200: // Double light effect P_AddFakeFloorsByLine(i, FF_EXISTS|FF_CUTSPRITES|FF_DOUBLESHADOW, secthinkers); @@ -6491,12 +6573,11 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 202: // Fog - ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_BOTHPLANES|FF_INVERTPLANES|FF_ALLSIDES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES; + ffloorflags = FF_EXISTS|FF_RENDERALL|FF_FOG|FF_INVERTPLANES|FF_INVERTSIDES|FF_CUTEXTRA|FF_EXTRA|FF_DOUBLESHADOW|FF_CUTSPRITES; sec = sides[*lines[i].sidenum].sector - sectors; - // SoM: Because it's fog, check for an extra colormap and set - // the fog flag... + // SoM: Because it's fog, check for an extra colormap and set the fog flag... if (sectors[sec].extra_colormap) - sectors[sec].extra_colormap->fog = 1; + sectors[sec].extra_colormap->flags = CMF_FOG; P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; @@ -6527,35 +6608,43 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 250: // Mario Block - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO, secthinkers); + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL|FF_MARIO; + if (lines[i].flags & ML_NOCLIMB) + ffloorflags |= FF_SHATTERBOTTOM; + if (lines[i].flags & ML_EFFECT1) + ffloorflags &= ~(FF_SOLID|FF_RENDERALL|FF_CUTLEVEL); + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 251: // A THWOMP! - sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - { - P_AddThwompThinker(§ors[sec], §ors[s], &lines[i]); - P_AddFakeFloor(§ors[s], §ors[sec], lines + i, - FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); - } + { + fixed_t crushspeed = (lines[i].flags & ML_EFFECT5) ? lines[i].dy >> 3 : 10*FRACUNIT; + fixed_t retractspeed = (lines[i].flags & ML_EFFECT5) ? lines[i].dx >> 3 : 2*FRACUNIT; + UINT16 sound = (lines[i].flags & ML_EFFECT4) ? sides[lines[i].sidenum[0]].textureoffset >> FRACBITS : sfx_thwomp; + P_AddThwompThinker(lines[i].frontsector, lines[i].tag, &lines[i], crushspeed, retractspeed, sound); + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_CUTLEVEL, secthinkers); break; + } case 252: // Shatter block (breaks when touched) + ffloorflags = FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER; if (lines[i].flags & ML_NOCLIMB) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_SHATTERBOTTOM, secthinkers); - else - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER, secthinkers); + ffloorflags |= FF_BLOCKPLAYER|FF_SHATTERBOTTOM; + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 253: // Translucent shatter block (see 76) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_TRANSLUCENT, secthinkers); + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_BLOCKOTHERS|FF_RENDERALL|FF_BUSTUP|FF_SHATTER|FF_TRANSLUCENT, secthinkers); break; case 254: // Bustable block + ffloorflags = FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP; if (lines[i].flags & ML_NOCLIMB) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP|FF_ONLYKNUX, secthinkers); - else - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_SOLID|FF_RENDERALL|FF_BUSTUP, secthinkers); + ffloorflags |= FF_STRONGBUST; + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 255: // Spin bust block (breaks when jumped or spun downwards onto) @@ -6567,60 +6656,26 @@ void P_SpawnSpecials(INT32 fromnetsave) break; case 257: // Quicksand + ffloorflags = FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES; if (lines[i].flags & ML_EFFECT5) - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES|FF_RIPPLE, secthinkers); - else - P_AddFakeFloorsByLine(i, FF_EXISTS|FF_QUICKSAND|FF_RENDERALL|FF_ALLSIDES|FF_CUTSPRITES, secthinkers); + ffloorflags |= FF_RIPPLE; + + P_AddFakeFloorsByLine(i, ffloorflags, secthinkers); break; case 258: // Laser block - sec = sides[*lines[i].sidenum].sector - sectors; - - // No longer totally disrupts netgames - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - EV_AddLaserThinker(§ors[s], §ors[sec], lines + i, secthinkers); + P_AddLaserThinker(lines[i].tag, lines + i, !!(lines[i].flags & ML_EFFECT1)); + P_AddFakeFloorsByLine(i, FF_EXISTS|FF_RENDERALL|FF_NOSHADE|FF_EXTRA|FF_CUTEXTRA|FF_TRANSLUCENT, secthinkers); break; - case 259: // Make-Your-Own FOF! + case 259: // Custom FOF if (lines[i].sidenum[1] != 0xffff) { - UINT8 *data; - UINT16 b; - - if (W_IsLumpWad(lastloadedmaplumpnum)) // welp it's a map wad in a pk3 - { // HACK: Open wad file rather quickly so we can get the data from the sidedefs lump - UINT8 *wadData = W_CacheLumpNum(lastloadedmaplumpnum, PU_STATIC); - filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); - fileinfo += ML_SIDEDEFS; // we only need the SIDEDEFS lump - data = Z_Malloc(fileinfo->size, PU_STATIC, NULL); - M_Memcpy(data, wadData + fileinfo->filepos, fileinfo->size); // copy data - Z_Free(wadData); // we're done with this now - } - else // phew it's just a WAD - data = W_CacheLumpNum(lastloadedmaplumpnum + ML_SIDEDEFS,PU_STATIC); - - for (b = 0; b < (INT16)numsides; b++) - { - register mapsidedef_t *msd = (mapsidedef_t *)data + b; - - if (b == lines[i].sidenum[1]) - { - if ((msd->toptexture[0] >= '0' && msd->toptexture[0] <= '9') - || (msd->toptexture[0] >= 'A' && msd->toptexture[0] <= 'F')) - { - ffloortype_e FOF_Flags = axtoi(msd->toptexture); - - P_AddFakeFloorsByLine(i, FOF_Flags, secthinkers); - break; - } - else - I_Error("Make-Your-Own-FOF (tag %d) needs a value in the linedef's second side upper texture field.", lines[i].tag); - } - } - Z_Free(data); + ffloortype_e fofflags = sides[lines[i].sidenum[1]].toptexture; + P_AddFakeFloorsByLine(i, fofflags, secthinkers); } else - I_Error("Make-Your-Own FOF (tag %d) found without a 2nd linedef side!", lines[i].tag); + I_Error("Custom FOF (tag %d) found without a linedef back side!", lines[i].tag); break; case 300: // Linedef executor (combines with sector special 974/975) and commands @@ -6628,20 +6683,15 @@ void P_SpawnSpecials(INT32 fromnetsave) case 303: case 304: - // Charability linedef executors - case 305: - case 307: - break; - case 308: // Race-only linedef executor. Triggers once. - if (!G_RaceGametype()) + if (!(gametyperules & GTR_CIRCUIT)) lines[i].special = 0; break; // Linedef executor triggers for CTF teams. case 309: case 311: - if (gametype != GT_CTF) + if (!(gametyperules & GTR_TEAMS)) lines[i].special = 0; break; @@ -6650,14 +6700,14 @@ void P_SpawnSpecials(INT32 fromnetsave) case 301: case 310: case 312: - sec = sides[*lines[i].sidenum].sector - sectors; - P_AddEachTimeThinker(§ors[sec], &lines[i]); + case 332: + case 335: + P_AddEachTimeThinker(&lines[i]); break; // No More Enemies Linedef Exec case 313: - sec = sides[*lines[i].sidenum].sector - sectors; - P_AddNoEnemiesThinker(§ors[sec], &lines[i]); + P_AddNoEnemiesThinker(&lines[i]); break; // Pushable linedef executors (count # of pushables) @@ -6681,10 +6731,17 @@ void P_SpawnSpecials(INT32 fromnetsave) else lines[i].callcount = sides[lines[i].sidenum[0]].textureoffset>>FRACBITS; if (lines[i].special == 322) // Each time - { - sec = sides[*lines[i].sidenum].sector - sectors; - P_AddEachTimeThinker(§ors[sec], &lines[i]); - } + P_AddEachTimeThinker(&lines[i]); + break; + + // Skin trigger executors + case 331: + case 333: + break; + + // Object dye executors + case 334: + case 336: break; // Record attack only linedef exec case 323: @@ -6736,12 +6793,33 @@ void P_SpawnSpecials(INT32 fromnetsave) case 431: break; + case 449: // Enable bosses with parameter + { + INT32 bossid = sides[*lines[i].sidenum].textureoffset>>FRACBITS; + if (bossid & ~15) // if any bits other than first 16 are set + { + CONS_Alert(CONS_WARNING, + M_GetText("Boss enable linedef (tag %d) has an invalid texture x offset.\nConsider changing it or removing it entirely.\n"), + lines[i].tag); + break; + } + if (!(lines[i].flags & ML_NOCLIMB)) + { + bossdisabled |= (1<= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) sectors[s].floorlightsec = (INT32)sec; break; case 601: // ceiling lighting independently sec = sides[*lines[i].sidenum].sector-sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) sectors[s].ceilinglightsec = (INT32)sec; break; case 602: // Adjustable pulsating light sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) P_SpawnAdjustableGlowingLight(§ors[sec], §ors[s], P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); break; case 603: // Adjustable flickering light sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) P_SpawnAdjustableFireFlicker(§ors[sec], §ors[s], P_AproxDistance(lines[i].dx, lines[i].dy)>>FRACBITS); break; case 604: // Adjustable Blinking Light (unsynchronized) sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, false); break; case 605: // Adjustable Blinking Light (synchronized) sec = sides[*lines[i].sidenum].sector - sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[i].tag, s)) >= 0 ;) P_SpawnAdjustableStrobeFlash(§ors[sec], §ors[s], abs(lines[i].dx)>>FRACBITS, abs(lines[i].dy)>>FRACBITS, true); break; case 606: // HACK! Copy colormaps. Just plain colormaps. - for (s = -1; (s = P_FindSectorFromLineTag(lines + i, s)) >= 0 ;) - sectors[s].midmap = lines[i].frontsector->midmap; + for (s = -1; (s = P_FindSectorFromTag(lines[i].args[0], s)) >= 0;) + { + extracolormap_t *exc; + + if (sectors[s].colormap_protected) + continue; + + if (!udmf) + exc = sides[lines[i].sidenum[0]].colormap_data; + else + { + if (!lines[i].args[1]) + exc = lines[i].frontsector->extra_colormap; + else + { + INT32 sourcesec = P_FindSectorFromTag(lines[i].args[1], -1); + if (sourcesec == -1) + { + CONS_Debug(DBG_GAMELOGIC, "Line type 606: Can't find sector with source colormap (tag %d)!\n", lines[i].args[1]); + return; + } + exc = sectors[sourcesec].extra_colormap; + } + } + sectors[s].extra_colormap = sectors[s].spawn_extra_colormap = exc; + } break; // SRB2Kart case 2000: // Waypoint Parameters break; case 2001: // Finish Line - if (G_RaceGametype()) + if ((gametyperules & GTR_CIRCUIT)) circuitmap = true; break; case 2002: // Linedef Trigger: Race Lap break; + default: break; } } - /* some things have to be done after FOF spawn */ + // Allocate each list + for (i = 0; i < numsectors; i++) + if(secthinkers[i].thinkers) + Z_Free(secthinkers[i].thinkers); + + Z_Free(secthinkers); +} + +/** Fuck polyobjects + */ +void P_SpawnSpecialsThatRequireObjects(void) +{ + size_t i; + + // haleyjd 02/20/06: spawn polyobjects + Polyobj_InitLevel(); + + for (i = 0; i < numlines; i++) + { + switch (lines[i].special) + { + case 30: // Polyobj_Flag + PolyFlag(&lines[i]); + break; + + case 31: // Polyobj_Displace + PolyDisplace(&lines[i]); + break; + + case 32: // Polyobj_RotDisplace + PolyRotDisplace(&lines[i]); + break; + } + } + + P_RunLevelLoadExecutors(); +} + +/** Fuck ML_NONET + */ +void P_SpawnSpecialsAfterSlopes(void) +{ + size_t i; for (i = 0; i < numlines; ++i) { + if (P_IsLineDisabled(&lines[i])) + { + /* remove the special so it can't even be found during the level */ + lines[i].special = 0; + } + switch (lines[i].special) { case 80: // Raise tagged things by type to this FOF @@ -6843,34 +6994,6 @@ void P_SpawnSpecials(INT32 fromnetsave) break; } } - - // Allocate each list - for (i = 0; i < numsectors; i++) - if(secthinkers[i].thinkers) - Z_Free(secthinkers[i].thinkers); - - Z_Free(secthinkers); - -#ifdef POLYOBJECTS - // haleyjd 02/20/06: spawn polyobjects - Polyobj_InitLevel(); - - for (i = 0; i < numlines; i++) - { - switch (lines[i].special) - { - case 30: // Polyobj_Flag - EV_DoPolyObjFlag(&lines[i]); - break; - - case 31: // Polyobj_Displace - PolyDisplace(&lines[i]); - break; - } - } -#endif - - P_RunLevelLoadExecutors(); } /** Adds 3Dfloors as appropriate based on a common control linedef. @@ -6886,7 +7009,7 @@ static void P_AddFakeFloorsByLine(size_t line, ffloortype_e ffloorflags, thinker INT32 s; size_t sec = sides[*lines[line].sidenum].sector-sectors; - for (s = -1; (s = P_FindSectorFromLineTag(lines+line, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[line].tag, s)) >= 0 ;) P_AddFakeFloor(§ors[s], §ors[sec], lines+line, ffloorflags, secthinkers); } @@ -6918,9 +7041,7 @@ static void P_DoScrollMove(mobj_t *thing, fixed_t dx, fixed_t dy, INT32 exclusiv } } - if (thing->player && (thing->player->pflags & PF_SPINNING) && (thing->player->rmomx || thing->player->rmomy) && !(thing->player->pflags & PF_STARTDASH)) - fuckaj = FixedDiv(549*ORIG_FRICTION,500*FRACUNIT); - else if (thing->friction != ORIG_FRICTION) + if (thing->friction != ORIG_FRICTION) fuckaj = thing->friction; if (fuckaj) { @@ -6936,7 +7057,7 @@ static void P_DoScrollMove(mobj_t *thing, fixed_t dx, fixed_t dy, INT32 exclusiv thing->momy += dy; if (exclusive) - thing->flags2 |= MF2_PUSHED; + thing->eflags |= MFE_PUSHED; } /** Processes an active scroller. @@ -7054,7 +7175,7 @@ void T_Scroll(scroll_t *s) { thing = node->m_thing; - if (thing->flags2 & MF2_PUSHED) // Already pushed this tic by an exclusive pusher. + if (thing->eflags & MFE_PUSHED) // Already pushed this tic by an exclusive pusher. continue; height = P_GetSpecialBottomZ(thing, sec, psec); @@ -7076,7 +7197,7 @@ void T_Scroll(scroll_t *s) { thing = node->m_thing; - if (thing->flags2 & MF2_PUSHED) + if (thing->eflags & MFE_PUSHED) continue; height = P_GetSpecialBottomZ(thing, sec, sec); @@ -7130,7 +7251,7 @@ void T_Scroll(scroll_t *s) { thing = node->m_thing; - if (thing->flags2 & MF2_PUSHED) + if (thing->eflags & MFE_PUSHED) continue; height = P_GetSpecialTopZ(thing, sec, psec); @@ -7152,7 +7273,7 @@ void T_Scroll(scroll_t *s) { thing = node->m_thing; - if (thing->flags2 & MF2_PUSHED) + if (thing->eflags & MFE_PUSHED) continue; height = P_GetSpecialTopZ(thing, sec, sec); @@ -7194,32 +7315,7 @@ static void Add_Scroller(INT32 type, fixed_t dx, fixed_t dy, INT32 control, INT3 if ((s->control = control) != -1) s->last_height = sectors[control].floorheight + sectors[control].ceilingheight; s->affectee = affectee; - P_AddThinker(&s->thinker); -} - -/** Adds a wall scroller. - * Scroll amount is rotated with respect to wall's linedef first, so that - * scrolling towards the wall in a perpendicular direction is translated into - * vertical motion, while scrolling along the wall in a parallel direction is - * translated into horizontal motion. - * - * \param dx x speed of scrolling or its acceleration. - * \param dy y speed of scrolling or its acceleration. - * \param l Line whose front side will scroll. - * \param control Sector whose heights control this scroller's effect - * remotely, or -1 if there is no control sector. - * \param accel Nonzero for an accelerative effect. - * \sa Add_Scroller, P_SpawnScrollers - */ -static void Add_WallScroller(fixed_t dx, fixed_t dy, const line_t *l, INT32 control, INT32 accel) -{ - fixed_t x = abs(l->dx), y = abs(l->dy), d; - if (y > x) - d = x, x = y, y = d; - d = FixedDiv(x, FINESINE((tantoangle[FixedDiv(y, x) >> DBITS] + ANGLE_90) >> ANGLETOFINESHIFT)); - x = -FixedDiv(FixedMul(dy, l->dy) + FixedMul(dx, l->dx), d); - y = -FixedDiv(FixedMul(dx, l->dy) - FixedMul(dy, l->dx), d); - Add_Scroller(sc_side, x, y, control, *l->sidenum, accel, 0); + P_AddThinker(THINK_MAIN, &s->thinker); } /** Initializes the scrollers. @@ -7293,7 +7389,7 @@ static void P_SpawnScrollers(void) { case 513: // scroll effect ceiling case 533: // scroll and carry objects on ceiling - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Scroller(sc_ceiling, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); if (special != 533) break; @@ -7302,13 +7398,13 @@ static void P_SpawnScrollers(void) case 523: // carry objects on ceiling dx = FixedMul(dx, CARRYFACTOR); dy = FixedMul(dy, CARRYFACTOR); - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Scroller(sc_carry_ceiling, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); break; case 510: // scroll effect floor case 530: // scroll and carry objects on floor - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Scroller(sc_floor, -dx, dy, control, s, accel, l->flags & ML_NOCLIMB); if (special != 530) break; @@ -7317,16 +7413,29 @@ static void P_SpawnScrollers(void) case 520: // carry objects on floor dx = FixedMul(dx, CARRYFACTOR); dy = FixedMul(dy, CARRYFACTOR); - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Scroller(sc_carry, dx, dy, control, s, accel, l->flags & ML_NOCLIMB); break; // scroll wall according to linedef // (same direction and speed as scrolling floors) case 502: - for (s = -1; (s = P_FindLineFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindLineFromTag(l->tag, s)) >= 0 ;) if (s != (INT32)i) - Add_WallScroller(dx, dy, lines+s, control, accel); + { + if (l->flags & ML_EFFECT2) // use texture offsets instead + { + dx = sides[l->sidenum[0]].textureoffset; + dy = sides[l->sidenum[0]].rowoffset; + } + if (l->flags & ML_EFFECT3) + { + if (lines[s].sidenum[1] != 0xffff) + Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[1], accel, 0); + } + else + Add_Scroller(sc_side, dx, dy, control, lines[s].sidenum[0], accel, 0); + } break; case 505: @@ -7340,11 +7449,29 @@ static void P_SpawnScrollers(void) if (s != 0xffff) Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[0], accel, 0); else - CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing 2nd side!\n", sizeu1(i)); + CONS_Debug(DBG_GAMELOGIC, "Line special 506 (line #%s) missing back side!\n", sizeu1(i)); break; - case 507: // scroll front and backside of tagged lines - for (s = -1; (s = P_FindLineFromLineTag(l, s)) >= 0 ;) + case 507: + s = lines[i].sidenum[0]; + + if (lines[i].sidenum[1] != 0xffff) + Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, lines[i].sidenum[1], accel, 0); + else + CONS_Debug(DBG_GAMELOGIC, "Line special 507 (line #%s) missing back side!\n", sizeu1(i)); + break; + + case 508: + s = lines[i].sidenum[1]; + + if (s != 0xffff) + Add_Scroller(sc_side, -sides[s].textureoffset, sides[s].rowoffset, -1, s, accel, 0); + else + CONS_Debug(DBG_GAMELOGIC, "Line special 508 (line #%s) missing back side!\n", sizeu1(i)); + break; + + case 509: // scroll front and backside of tagged lines + for (s = -1; (s = P_FindLineFromTag(l->tag, s)) >= 0 ;) { if (s != (INT32)i) { @@ -7385,7 +7512,7 @@ static void Add_MasterDisappearer(tic_t appeartime, tic_t disappeartime, tic_t o d->exists = true; d->timer = 1; - P_AddThinker(&d->thinker); + P_AddThinker(THINK_MAIN, &d->thinker); } /** Makes a FOF appear/disappear @@ -7406,7 +7533,7 @@ void T_Disappear(disappear_t *d) ffloor_t *rover; register INT32 s; - for (s = -1; (s = P_FindSectorFromLineTag(&lines[d->affectee], s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(lines[d->affectee].tag, s)) >= 0 ;) { for (rover = sectors[s].ffloors; rover; rover = rover->next) { @@ -7421,17 +7548,13 @@ void T_Disappear(disappear_t *d) if (!(lines[d->sourceline].flags & ML_NOCLIMB)) { -#ifdef ESLOPE - if (*rover->t_slope) - sectors[s].soundorg.z = P_GetZAt(*rover->t_slope, sectors[s].soundorg.x, sectors[s].soundorg.y); - else -#endif - sectors[s].soundorg.z = *rover->topheight; + sectors[s].soundorg.z = P_GetFFloorTopZAt(rover, sectors[s].soundorg.x, sectors[s].soundorg.y); S_StartSound(§ors[s].soundorg, sfx_appear); } } } sectors[s].moved = true; + P_RecalcPrecipInSector(§ors[s]); } if (d->exists) @@ -7447,6 +7570,591 @@ void T_Disappear(disappear_t *d) } } +/** Removes fadingdata from FOF control sector + * + * \param line line to search for target faders + * \param data pointer to set new fadingdata to. Can be NULL to erase. + */ +static void P_ResetFakeFloorFader(ffloor_t *rover, fade_t *data, boolean finalize) +{ + fade_t *fadingdata = (fade_t *)rover->fadingdata; + // find any existing thinkers and remove them, then replace with new data + if (fadingdata != data) + { + if (fadingdata) + { + if (finalize) + P_FadeFakeFloor(rover, + fadingdata->sourcevalue, + fadingdata->alpha >= fadingdata->destvalue ? + fadingdata->alpha - 1 : // trigger fade-out finish + fadingdata->alpha + 1, // trigger fade-in finish + 0, + fadingdata->ticbased, + &fadingdata->timer, + fadingdata->doexists, + fadingdata->dotranslucent, + fadingdata->dolighting, + fadingdata->docolormap, + fadingdata->docollision, + fadingdata->doghostfade, + fadingdata->exactalpha); + rover->alpha = fadingdata->alpha; + + if (fadingdata->dolighting) + P_RemoveLighting(§ors[rover->secnum]); + + if (fadingdata->docolormap) + P_ResetColormapFader(§ors[rover->secnum]); + + P_RemoveThinker(&fadingdata->thinker); + } + + rover->fadingdata = data; + } +} + +static boolean P_FadeFakeFloor(ffloor_t *rover, INT16 sourcevalue, INT16 destvalue, INT16 speed, boolean ticbased, INT32 *timer, + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha) +{ + boolean stillfading = false; + INT32 alpha; + fade_t *fadingdata = (fade_t *)rover->fadingdata; + (void)docolormap; // *shrug* maybe we can use this in the future. For now, let's be consistent with our other function params + + if (rover->master->special == 258) // Laser block + return false; + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + if (dotranslucent && + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->flags & FF_FOG) && // do not include fog + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + if (fadingdata) + alpha = fadingdata->alpha; + else + alpha = rover->alpha; + + // routines specific to fade in and fade out + if (!ticbased && alpha == destvalue) + return stillfading; + else if (alpha > destvalue) // fade out + { + // finish fading out + if (speed < 1 || (!ticbased && alpha - speed <= destvalue + speed) || + (ticbased && (--(*timer) <= 0 || alpha <= destvalue))) + { + alpha = destvalue; + + if (docollision) + { + if (rover->spawnflags & FF_SOLID) + rover->flags &= ~FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags &= ~FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags &= ~FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags &= ~FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags &= ~FF_MARIO; + } + } + else // continue fading out + { + if (!ticbased) + alpha -= speed; + else + { + INT16 delta = abs(destvalue - sourcevalue); + fixed_t factor = min(FixedDiv(speed - (*timer), speed), 1*FRACUNIT); + alpha = max(min(alpha, sourcevalue - (INT16)FixedMul(delta, factor)), destvalue); + } + stillfading = true; + } + } + else // fade in + { + // finish fading in + if (speed < 1 || (!ticbased && alpha + speed >= destvalue - speed) || + (ticbased && (--(*timer) <= 0 || alpha >= destvalue))) + { + alpha = destvalue; + + if (docollision) + { + if (rover->spawnflags & FF_SOLID) + rover->flags |= FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags |= FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags |= FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags |= FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags |= FF_MARIO; + } + } + else // continue fading in + { + if (!ticbased) + alpha += speed; + else + { + INT16 delta = abs(destvalue - sourcevalue); + fixed_t factor = min(FixedDiv(speed - (*timer), speed), 1*FRACUNIT); + alpha = min(max(alpha, sourcevalue + (INT16)FixedMul(delta, factor)), destvalue); + } + stillfading = true; + } + } + + // routines common to both fade in and fade out + if (!stillfading) + { + if (doexists && !(rover->spawnflags & FF_BUSTUP)) + { + if (alpha <= 1) + rover->flags &= ~FF_EXISTS; + else + rover->flags |= FF_EXISTS; + + // Re-render lighting at end of fade + if (dolighting && !(rover->spawnflags & FF_NOSHADE) && !(rover->flags & FF_EXISTS)) + rover->target->moved = true; + } + + if (dotranslucent && !(rover->flags & FF_FOG)) + { + if (alpha >= 256) + { + if (!(rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags |= FF_CUTSOLIDS; + rover->target->moved = true; + } + + rover->flags &= ~FF_TRANSLUCENT; + } + else + { + rover->flags |= FF_TRANSLUCENT; + + if ((rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags &= ~FF_CUTSOLIDS; + rover->target->moved = true; + } + } + + if ((rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES)) + { + if (rover->alpha > 1) + rover->flags |= FF_RENDERALL; + else + rover->flags &= ~FF_RENDERALL; + } + } + } + else + { + if (doexists && !(rover->spawnflags & FF_BUSTUP)) + { + // Re-render lighting if we haven't yet set FF_EXISTS (beginning of fade) + if (dolighting && !(rover->spawnflags & FF_NOSHADE) && !(rover->flags & FF_EXISTS)) + rover->target->moved = true; + + rover->flags |= FF_EXISTS; + } + + if (dotranslucent && !(rover->flags & FF_FOG)) + { + rover->flags |= FF_TRANSLUCENT; + + if ((rover->flags & FF_CUTSOLIDS) && + (rover->spawnflags & FF_CUTSOLIDS)) + { + rover->flags &= ~FF_CUTSOLIDS; + rover->target->moved = true; + } + + if ((rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES)) + rover->flags |= FF_RENDERALL; + } + + if (docollision) + { + if (doghostfade) // remove collision flags during fade + { + if (rover->spawnflags & FF_SOLID) + rover->flags &= ~FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags &= ~FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags &= ~FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags &= ~FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags &= ~FF_MARIO; + } + else // keep collision during fade + { + if (rover->spawnflags & FF_SOLID) + rover->flags |= FF_SOLID; + if (rover->spawnflags & FF_SWIMMABLE) + rover->flags |= FF_SWIMMABLE; + if (rover->spawnflags & FF_QUICKSAND) + rover->flags |= FF_QUICKSAND; + if (rover->spawnflags & FF_BUSTUP) + rover->flags |= FF_BUSTUP; + if (rover->spawnflags & FF_MARIO) + rover->flags |= FF_MARIO; + } + } + } + + if (!(rover->flags & FF_FOG)) // don't set FOG alpha + { + if (!stillfading || exactalpha) + rover->alpha = alpha; + else // clamp fadingdata->alpha to software's alpha levels + { + if (alpha < 12) + rover->alpha = destvalue < 12 ? destvalue : 1; // Don't even draw it + else if (alpha < 38) + rover->alpha = destvalue >= 12 && destvalue < 38 ? destvalue : 25; + else if (alpha < 64) + rover->alpha = destvalue >=38 && destvalue < 64 ? destvalue : 51; + else if (alpha < 89) + rover->alpha = destvalue >= 64 && destvalue < 89 ? destvalue : 76; + else if (alpha < 115) + rover->alpha = destvalue >= 89 && destvalue < 115 ? destvalue : 102; + else if (alpha < 140) + rover->alpha = destvalue >= 115 && destvalue < 140 ? destvalue : 128; + else if (alpha < 166) + rover->alpha = destvalue >= 140 && destvalue < 166 ? destvalue : 154; + else if (alpha < 192) + rover->alpha = destvalue >= 166 && destvalue < 192 ? destvalue : 179; + else if (alpha < 217) + rover->alpha = destvalue >= 192 && destvalue < 217 ? destvalue : 204; + else if (alpha < 243) + rover->alpha = destvalue >= 217 && destvalue < 243 ? destvalue : 230; + else // Opaque + rover->alpha = destvalue >= 243 ? destvalue : 256; + } + } + + if (fadingdata) + fadingdata->alpha = alpha; + + return stillfading; +} + +/** Adds fake floor fader thinker. + * + * \param destvalue transparency value to fade to + * \param speed speed to fade by + * \param ticbased tic-based logic, speed = duration + * \param relative Destvalue is relative to rover->alpha + * \param doexists handle FF_EXISTS + * \param dotranslucent handle FF_TRANSLUCENT + * \param dolighting fade FOF light + * \param docollision handle interactive flags + * \param doghostfade no interactive flags during fading + * \param exactalpha use exact alpha values (opengl) + */ +static void P_AddFakeFloorFader(ffloor_t *rover, size_t sectornum, size_t ffloornum, + INT16 destvalue, INT16 speed, boolean ticbased, boolean relative, + boolean doexists, boolean dotranslucent, boolean dolighting, boolean docolormap, + boolean docollision, boolean doghostfade, boolean exactalpha) +{ + fade_t *d; + + // If fading an invisible FOF whose render flags we did not yet set, + // initialize its alpha to 1 + if (dotranslucent && + (rover->spawnflags & FF_NOSHADE) && // do not include light blocks, which don't set FF_NOSHADE + !(rover->spawnflags & FF_RENDERSIDES) && + !(rover->spawnflags & FF_RENDERPLANES) && + !(rover->flags & FF_RENDERALL)) + rover->alpha = 1; + + // already equal, nothing to do + if (rover->alpha == max(1, min(256, relative ? rover->alpha + destvalue : destvalue))) + return; + + d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + + d->thinker.function.acp1 = (actionf_p1)T_Fade; + d->rover = rover; + d->sectornum = (UINT32)sectornum; + d->ffloornum = (UINT32)ffloornum; + + d->alpha = d->sourcevalue = rover->alpha; + d->destvalue = max(1, min(256, relative ? rover->alpha + destvalue : destvalue)); // rover->alpha is 1-256 + + if (ticbased) + { + d->ticbased = true; + d->timer = d->speed = abs(speed); // use d->speed as total duration + } + else + { + d->ticbased = false; + d->speed = max(1, speed); // minimum speed 1/tic // if speed < 1, alpha is set immediately in thinker + d->timer = -1; + } + + d->doexists = doexists; + d->dotranslucent = dotranslucent; + d->dolighting = dolighting; + d->docolormap = docolormap; + d->docollision = docollision; + d->doghostfade = doghostfade; + d->exactalpha = exactalpha; + + // find any existing thinkers and remove them, then replace with new data + P_ResetFakeFloorFader(rover, d, false); + + // Set a separate thinker for shadow fading + if (dolighting && !(rover->flags & FF_NOSHADE)) + { + UINT16 lightdelta = abs(sectors[rover->secnum].spawn_lightlevel - rover->target->lightlevel); + fixed_t alphapercent = min(FixedDiv(d->destvalue, rover->spawnalpha), 1*FRACUNIT); // don't make darker than spawn_lightlevel + fixed_t adjustedlightdelta = FixedMul(lightdelta, alphapercent); + + if (rover->target->lightlevel >= sectors[rover->secnum].spawn_lightlevel) // fading out, get lighter + d->destlightlevel = rover->target->lightlevel - adjustedlightdelta; + else // fading in, get darker + d->destlightlevel = rover->target->lightlevel + adjustedlightdelta; + + P_FadeLightBySector(§ors[rover->secnum], + d->destlightlevel, + ticbased ? d->timer : + FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT, + true); + } + else + d->destlightlevel = -1; + + // Set a separate thinker for colormap fading + if (docolormap && !(rover->flags & FF_NOSHADE) && sectors[rover->secnum].spawn_extra_colormap && !sectors[rover->secnum].colormap_protected) + { + extracolormap_t *dest_exc, + *source_exc = sectors[rover->secnum].extra_colormap ? sectors[rover->secnum].extra_colormap : R_GetDefaultColormap(); + + INT32 colordelta = R_GetRgbaA(sectors[rover->secnum].spawn_extra_colormap->rgba); // alpha is from 0 + fixed_t alphapercent = min(FixedDiv(d->destvalue, rover->spawnalpha), 1*FRACUNIT); // don't make darker than spawn_lightlevel + fixed_t adjustedcolordelta = FixedMul(colordelta, alphapercent); + INT32 coloralpha; + + coloralpha = adjustedcolordelta; + + dest_exc = R_CopyColormap(sectors[rover->secnum].spawn_extra_colormap, false); + dest_exc->rgba = R_GetRgbaRGB(dest_exc->rgba) + R_PutRgbaA(coloralpha); + + if (!(d->dest_exc = R_GetColormapFromList(dest_exc))) + { + dest_exc->colormap = R_CreateLightTable(dest_exc); + R_AddColormapToList(dest_exc); + d->dest_exc = dest_exc; + } + else + Z_Free(dest_exc); + + // If fading from 0, set source_exc rgb same to dest_exc + if (!R_CheckDefaultColormap(d->dest_exc, true, false, false) + && R_CheckDefaultColormap(source_exc, true, false, false)) + { + extracolormap_t *exc = R_CopyColormap(source_exc, false); + exc->rgba = R_GetRgbaRGB(d->dest_exc->rgba) + R_PutRgbaA(R_GetRgbaA(source_exc->rgba)); + exc->fadergba = R_GetRgbaRGB(d->dest_exc->rgba) + R_PutRgbaA(R_GetRgbaA(source_exc->fadergba)); + + if (!(source_exc = R_GetColormapFromList(exc))) + { + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + source_exc = exc; + } + else + Z_Free(exc); + } + + Add_ColormapFader(§ors[rover->secnum], source_exc, d->dest_exc, true, + ticbased ? d->timer : + FixedFloor(FixedDiv(abs(d->destvalue - d->alpha), d->speed))/FRACUNIT); + } + + P_AddThinker(THINK_MAIN, &d->thinker); +} + +/** Makes a FOF fade + * + * \param d Fade thinker. + * \sa P_AddFakeFloorFader + */ +void T_Fade(fade_t *d) +{ + if (d->rover && !P_FadeFakeFloor(d->rover, d->sourcevalue, d->destvalue, d->speed, d->ticbased, &d->timer, + d->doexists, d->dotranslucent, d->dolighting, d->docolormap, d->docollision, d->doghostfade, d->exactalpha)) + { + // Finalize lighting, copypasta from P_AddFakeFloorFader + if (d->dolighting && !(d->rover->flags & FF_NOSHADE) && d->destlightlevel > -1) + sectors[d->rover->secnum].lightlevel = d->destlightlevel; + + // Finalize colormap + if (d->docolormap && !(d->rover->flags & FF_NOSHADE) && sectors[d->rover->secnum].spawn_extra_colormap) + sectors[d->rover->secnum].extra_colormap = d->dest_exc; + + P_RemoveFakeFloorFader(d->rover); + } +} + +static void P_ResetColormapFader(sector_t *sector) +{ + if (sector->fadecolormapdata) + { + // The thinker is the first member in all the action structs, + // so just let the thinker get freed, and that will free the whole + // structure. + P_RemoveThinker(&((elevator_t *)sector->fadecolormapdata)->thinker); + sector->fadecolormapdata = NULL; + } +} + +static void Add_ColormapFader(sector_t *sector, extracolormap_t *source_exc, extracolormap_t *dest_exc, + boolean ticbased, INT32 duration) +{ + fadecolormap_t *d; + + P_ResetColormapFader(sector); + + // nothing to do, set immediately + if (!duration || R_CheckEqualColormaps(source_exc, dest_exc, true, true, true)) + { + sector->extra_colormap = dest_exc; + return; + } + + d = Z_Malloc(sizeof *d, PU_LEVSPEC, NULL); + d->thinker.function.acp1 = (actionf_p1)T_FadeColormap; + d->sector = sector; + d->source_exc = source_exc; + d->dest_exc = dest_exc; + + if (ticbased) + { + d->ticbased = true; + d->duration = d->timer = duration; + } + else + { + d->ticbased = false; + d->timer = 256; + d->duration = duration; // use as speed + } + + sector->fadecolormapdata = d; + P_AddThinker(THINK_MAIN, &d->thinker); +} + +void T_FadeColormap(fadecolormap_t *d) +{ + if ((d->ticbased && --d->timer <= 0) + || (!d->ticbased && (d->timer -= d->duration) <= 0)) // d->duration used as speed decrement + { + d->sector->extra_colormap = d->dest_exc; + P_ResetColormapFader(d->sector); + } + else + { + extracolormap_t *exc; + INT32 duration = d->ticbased ? d->duration : 256; + fixed_t factor = min(FixedDiv(duration - d->timer, duration), 1*FRACUNIT); + INT16 cr, cg, cb, ca, fadestart, fadeend, flags; + INT32 rgba, fadergba; + + // NULL failsafes (or intentionally set to signify default) + if (!d->sector->extra_colormap) + d->sector->extra_colormap = R_GetDefaultColormap(); + + if (!d->source_exc) + d->source_exc = R_GetDefaultColormap(); + + if (!d->dest_exc) + d->dest_exc = R_GetDefaultColormap(); + + // For each var (rgba + fadergba + params = 11 vars), we apply + // percentage fading: currentval = sourceval + (delta * percent of duration elapsed) + // delta is negative when fading out (destval is lower) + // max/min are used to ensure progressive calcs don't go backwards and to cap values to dest. + +#define APPLYFADE(dest, src, cur) (\ +(dest-src < 0) ? \ + max(\ + min(cur,\ + src + (INT16)FixedMul(dest-src, factor)),\ + dest)\ +: (dest-src > 0) ? \ + min(\ + max(cur,\ + src + (INT16)FixedMul(dest-src, factor)),\ + dest)\ +: \ + dest\ +) + + cr = APPLYFADE(R_GetRgbaR(d->dest_exc->rgba), R_GetRgbaR(d->source_exc->rgba), R_GetRgbaR(d->sector->extra_colormap->rgba)); + cg = APPLYFADE(R_GetRgbaG(d->dest_exc->rgba), R_GetRgbaG(d->source_exc->rgba), R_GetRgbaG(d->sector->extra_colormap->rgba)); + cb = APPLYFADE(R_GetRgbaB(d->dest_exc->rgba), R_GetRgbaB(d->source_exc->rgba), R_GetRgbaB(d->sector->extra_colormap->rgba)); + ca = APPLYFADE(R_GetRgbaA(d->dest_exc->rgba), R_GetRgbaA(d->source_exc->rgba), R_GetRgbaA(d->sector->extra_colormap->rgba)); + + rgba = R_PutRgbaRGBA(cr, cg, cb, ca); + + cr = APPLYFADE(R_GetRgbaR(d->dest_exc->fadergba), R_GetRgbaR(d->source_exc->fadergba), R_GetRgbaR(d->sector->extra_colormap->fadergba)); + cg = APPLYFADE(R_GetRgbaG(d->dest_exc->fadergba), R_GetRgbaG(d->source_exc->fadergba), R_GetRgbaG(d->sector->extra_colormap->fadergba)); + cb = APPLYFADE(R_GetRgbaB(d->dest_exc->fadergba), R_GetRgbaB(d->source_exc->fadergba), R_GetRgbaB(d->sector->extra_colormap->fadergba)); + ca = APPLYFADE(R_GetRgbaA(d->dest_exc->fadergba), R_GetRgbaA(d->source_exc->fadergba), R_GetRgbaA(d->sector->extra_colormap->fadergba)); + + fadergba = R_PutRgbaRGBA(cr, cg, cb, ca); + + fadestart = APPLYFADE(d->dest_exc->fadestart, d->source_exc->fadestart, d->sector->extra_colormap->fadestart); + fadeend = APPLYFADE(d->dest_exc->fadeend, d->source_exc->fadeend, d->sector->extra_colormap->fadeend); + flags = abs(factor) > FRACUNIT/2 ? d->dest_exc->flags : d->source_exc->flags; // set new flags halfway through fade + +#undef APPLYFADE + + ////////////////// + // setup new colormap + ////////////////// + + if (!(d->sector->extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags))) + { + exc = R_CreateDefaultColormap(false); + exc->fadestart = fadestart; + exc->fadeend = fadeend; + exc->flags = flags; + exc->rgba = rgba; + exc->fadergba = fadergba; + exc->colormap = R_CreateLightTable(exc); + R_AddColormapToList(exc); + d->sector->extra_colormap = exc; + } + } +} + /* SoM: 3/8/2000: Friction functions start. Add_Friction, @@ -7457,7 +8165,6 @@ void T_Disappear(disappear_t *d) /** Adds friction thinker. * * \param friction Friction value, 0xe800 is normal. - * \param movefactor Inertia factor. * \param affectee Target sector. * \param roverfriction FOF or not * \sa T_Friction, P_SpawnFriction @@ -7479,7 +8186,7 @@ static void Add_Friction(INT32 friction, INT32 movefactor, INT32 affectee, INT32 else f->roverfriction = false; - P_AddThinker(&f->thinker); + P_AddThinker(THINK_MAIN, &f->thinker); } /** Applies friction to all things in a sector. @@ -7495,22 +8202,10 @@ void T_Friction(friction_t *f) sec = sectors + f->affectee; - // Get FOF control sector (was "Make sure the sector type hasn't changed") + // Get FOF control sector if (f->roverfriction) - //{ referrer = sectors + f->referrer; - /* if (!(GETSECSPECIAL(referrer->special, 3) == 1 - || GETSECSPECIAL(referrer->special, 3) == 3)) - return; - } - else - { - if (!(GETSECSPECIAL(sec->special, 3) == 1 - || GETSECSPECIAL(sec->special, 3) == 3)) - return; - }*/ - // Assign the friction value to players on the floor, non-floating, // and clipped. Normally the object's friction value is kept at // ORIG_FRICTION and this thinker changes it for icy or muddy floors. @@ -7565,20 +8260,18 @@ static void P_SpawnFriction(void) size_t i; line_t *l = lines; register INT32 s; - fixed_t strength; // frontside texture offset controls magnitude //fixed_t length; // line length controls magnitude + fixed_t strength; // frontside texture offset controls magnitude fixed_t friction; // friction value to be applied during movement INT32 movefactor; // applied to each player move to simulate inertia for (i = 0; i < numlines; i++, l++) if (l->special == 540) { - //length = P_AproxDistance(l->dx, l->dy)>>FRACBITS; - //friction = (0x1EB8*length)/0x80 + 0xD000; strength = sides[l->sidenum[0]].textureoffset>>FRACBITS; if (strength > 0) // sludge strength = strength*2; // otherwise, the maximum sludginess value is +967... - // The following check might seem odd. At the time of movement, + // The following might seem odd. At the time of movement, // the move distance is multiplied by 'friction/0x10000', so a // higher friction value actually means 'less friction'. friction = ORIG_FRICTION - (0x1EB8*strength)/0x80; // ORIG_FRICTION is 0xE800 @@ -7588,19 +8281,13 @@ static void P_SpawnFriction(void) if (friction < 0) friction = 0; - //if (friction > ORIG_FRICTION) // ice - // movefactor = ((0x10092 - friction)*(0x70))/0x158; movefactor = FixedDiv(ORIG_FRICTION, friction); if (movefactor < FRACUNIT) movefactor = 19*movefactor - 18*FRACUNIT; else - movefactor = FRACUNIT; //movefactor = ((friction - 0xDB34)*(0xA))/0x80; + movefactor = FRACUNIT; - // killough 8/28/98: prevent odd situations - if (movefactor < 32) - movefactor = 32; - - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Friction(friction, movefactor, s, -1); } } @@ -7665,7 +8352,7 @@ static void Add_Pusher(pushertype_e type, fixed_t x_mag, fixed_t y_mag, mobj_t * p->z = p->source->z; } p->affectee = affectee; - P_AddThinker(&p->thinker); + P_AddThinker(THINK_MAIN, &p->thinker); } @@ -7683,14 +8370,11 @@ static pusher_t *tmpusher; // pusher structure for blockmap searches */ static inline boolean PIT_PushThing(mobj_t *thing) { - if (thing->flags2 & MF2_PUSHED) - return false; - - if (thing->player && thing->player->pflags & PF_ROPEHANG) + if (thing->eflags & MFE_PUSHED) return false; // Allow this to affect pushable objects at some point? - if (thing->player && (!(thing->flags & (MF_NOGRAVITY | MF_NOCLIP)) || thing->player->pflags & PF_NIGHTSMODE)) + if (thing->player && !(thing->flags & (MF_NOGRAVITY | MF_NOCLIP))) { INT32 dist; INT32 speed; @@ -7721,75 +8405,14 @@ static inline boolean PIT_PushThing(mobj_t *thing) // Written with bits and pieces of P_HomingAttack if ((speed > 0) && (P_CheckSight(thing, tmpusher->source))) { - if (!(thing->player->pflags & PF_NIGHTSMODE)) + // only push wrt Z if health & 1 (mapthing has ambush flag) + if (tmpusher->source->health & 1) { - // only push wrt Z if health & 1 (mapthing has ambush flag) - if (tmpusher->source->health & 1) - { - fixed_t tmpmomx, tmpmomy, tmpmomz; - - tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); - tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); - tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); - if (tmpusher->source->type == MT_PUSH) // away! - { - tmpmomx *= -1; - tmpmomy *= -1; - tmpmomz *= -1; - } - - thing->momx += tmpmomx; - thing->momy += tmpmomy; - thing->momz += tmpmomz; - - if (thing->player) - { - thing->player->cmomx += tmpmomx; - thing->player->cmomy += tmpmomy; - thing->player->cmomx = FixedMul(thing->player->cmomx, ORIG_FRICTION); - thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION); - } - } - else - { - angle_t pushangle; - - pushangle = R_PointToAngle2(thing->x, thing->y, sx, sy); - if (tmpusher->source->type == MT_PUSH) - pushangle += ANGLE_180; // away - pushangle >>= ANGLETOFINESHIFT; - thing->momx += FixedMul(speed, FINECOSINE(pushangle)); - thing->momy += FixedMul(speed, FINESINE(pushangle)); - - if (thing->player) - { - thing->player->cmomx += FixedMul(speed, FINECOSINE(pushangle)); - thing->player->cmomy += FixedMul(speed, FINESINE(pushangle)); - thing->player->cmomx = FixedMul(thing->player->cmomx, ORIG_FRICTION); - thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION); - } - } - } - else - { - //NiGHTS-specific handling. - //By default, pushes and pulls only affect the Z-axis. - //By having the ambush flag, it affects the X-axis. - //By having the object special flag, it affects the Y-axis. fixed_t tmpmomx, tmpmomy, tmpmomz; - if (tmpusher->source->health & 1) - tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); - else - tmpmomx = 0; - - if (tmpusher->source->health & 2) - tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); - else - tmpmomy = 0; - + tmpmomx = FixedMul(FixedDiv(sx - thing->x, dist), speed); + tmpmomy = FixedMul(FixedDiv(sy - thing->y, dist), speed); tmpmomz = FixedMul(FixedDiv(sz - thing->z, dist), speed); - if (tmpusher->source->type == MT_PUSH) // away! { tmpmomx *= -1; @@ -7809,11 +8432,30 @@ static inline boolean PIT_PushThing(mobj_t *thing) thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION); } } + else + { + angle_t pushangle; + + pushangle = R_PointToAngle2(thing->x, thing->y, sx, sy); + if (tmpusher->source->type == MT_PUSH) + pushangle += ANGLE_180; // away + pushangle >>= ANGLETOFINESHIFT; + thing->momx += FixedMul(speed, FINECOSINE(pushangle)); + thing->momy += FixedMul(speed, FINESINE(pushangle)); + + if (thing->player) + { + thing->player->cmomx += FixedMul(speed, FINECOSINE(pushangle)); + thing->player->cmomy += FixedMul(speed, FINESINE(pushangle)); + thing->player->cmomx = FixedMul(thing->player->cmomx, ORIG_FRICTION); + thing->player->cmomy = FixedMul(thing->player->cmomy, ORIG_FRICTION); + } + } } } if (tmpusher->exclusive) - thing->flags2 |= MF2_PUSHED; + thing->eflags |= MFE_PUSHED; return true; } @@ -7848,14 +8490,12 @@ void T_Pusher(pusher_t *p) { referrer = §ors[p->referrer]; - //if (!(GETSECSPECIAL(referrer->special, 3) == 2 - // || GETSECSPECIAL(referrer->special, 3) == 3)) if (GETSECSPECIAL(referrer->special, 3) != 2) return; } - //else if (!(GETSECSPECIAL(sec->special, 3) == 2 - // || GETSECSPECIAL(sec->special, 3) == 3)) else if (GETSECSPECIAL(sec->special, 3) != 2) + return; + // For constant pushers (wind/current) there are 3 situations: // // 1) Affected Thing is above the floor. @@ -7908,7 +8548,8 @@ void T_Pusher(pusher_t *p) || thing->type == MT_EXTRALARGEBUBBLE)) continue; - if (!(thing->flags & MF_PUSHABLE) && !(thing->type == MT_PLAYER + if (!((thing->flags & MF_PUSHABLE) || ((thing->info->flags & MF_PUSHABLE) && thing->fuse)) + && !(thing->type == MT_PLAYER || thing->type == MT_SMALLBUBBLE || thing->type == MT_MEDIUMBUBBLE || thing->type == MT_EXTRALARGEBUBBLE @@ -7916,10 +8557,7 @@ void T_Pusher(pusher_t *p) || thing->type == MT_BIGTUMBLEWEED)) continue; - if (thing->flags2 & MF2_PUSHED) - continue; - - if (thing->player && thing->player->pflags & PF_ROPEHANG) + if (thing->eflags & MFE_PUSHED) continue; if (thing->player && (thing->state == &states[thing->info->painstate]) @@ -8054,58 +8692,28 @@ void T_Pusher(pusher_t *p) { if (p->slider && thing->player) { - boolean jumped = (thing->player->pflags & PF_JUMPED); + pflags_t jumped = (thing->player->pflags & (PF_JUMPED|PF_NOJUMPDAMAGE)); P_ResetPlayer (thing->player); if (jumped) - thing->player->pflags |= PF_JUMPED; + thing->player->pflags |= jumped; thing->player->pflags |= PF_SLIDING; thing->angle = R_PointToAngle2 (0, 0, xspeed<<(FRACBITS-PUSH_FACTOR), yspeed<<(FRACBITS-PUSH_FACTOR)); if (!demo.playback) { - if (thing->player == &players[consoleplayer]) - { - if (thing->angle - localangle[0] > ANGLE_180) - localangle[0] -= (localangle[0] - thing->angle) / 8; - else - localangle[0] += (thing->angle - localangle[0]) / 8; - } - else if (thing->player == &players[displayplayers[1]]) - { - if (thing->angle - localangle[1] > ANGLE_180) - localangle[1] -= (localangle[1] - thing->angle) / 8; - else - localangle[1] += (thing->angle - localangle[1]) / 8; - } - else if (thing->player == &players[displayplayers[2]]) - { - if (thing->angle - localangle[2] > ANGLE_180) - localangle[2] -= (localangle[2] - thing->angle) / 8; - else - localangle[2] += (thing->angle - localangle[2]) / 8; - } - else if (thing->player == &players[displayplayers[3]]) - { - if (thing->angle - localangle[3] > ANGLE_180) - localangle[3] -= (localangle[3] - thing->angle) / 8; - else - localangle[3] += (thing->angle - localangle[3]) / 8; - } - /*if (thing->player == &players[consoleplayer]) - localangle[0] = thing->angle; - else if (thing->player == &players[displayplayers[1]]) - localangle[1] = thing->angle; - else if (thing->player == &players[displayplayers[2]]) - localangle[2] = thing->angle; - else if (thing->player == &players[displayplayers[3]]) - localangle[3] = thing->angle;*/ + angle_t angle = thing->player->angleturn; + if (thing->angle - angle > ANGLE_180) + P_SetPlayerAngle(thing->player, angle - (angle - thing->angle) / 8); + else + P_SetPlayerAngle(thing->player, angle + (thing->angle - angle) / 8); + //P_SetPlayerAngle(thing->player, thing->angle); } } if (p->exclusive) - thing->flags2 |= MF2_PUSHED; + thing->eflags |= MFE_PUSHED; } } } @@ -8156,15 +8764,15 @@ static void P_SpawnPushers(void) switch (l->special) { case 541: // wind - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Pusher(p_wind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 544: // current - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Pusher(p_current, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 547: // push/pull - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) { thing = P_GetPushThing(s); if (thing) // No MT_P* means no effect @@ -8172,61 +8780,24 @@ static void P_SpawnPushers(void) } break; case 545: // current up - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Pusher(p_upcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 546: // current down - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Pusher(p_downcurrent, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 542: // wind up - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Pusher(p_upwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; case 543: // wind down - for (s = -1; (s = P_FindSectorFromLineTag(l, s)) >= 0 ;) + for (s = -1; (s = P_FindSectorFromTag(l->tag, s)) >= 0 ;) Add_Pusher(p_downwind, l->dx, l->dy, NULL, s, -1, l->flags & ML_NOCLIMB, l->flags & ML_EFFECT4); break; } } -static void P_SearchForDisableLinedefs(void) -{ - size_t i; - INT32 j; - - // Look for disable linedefs - for (i = 0; i < numlines; i++) - { - if (lines[i].special == 6) - { - // Remove special - // Do *not* remove tag. That would mess with the tag lists - // that P_InitTagLists literally just created! - lines[i].special = 0; - - // Ability flags can disable disable linedefs now, lol - if (netgame || multiplayer) - { - // future: nonet flag? - } - else if ((lines[i].flags & ML_NETONLY) == ML_NETONLY) - continue; // Net-only never triggers in single player - // commented out because irrelevant to kart. keeping here because we can use these flags for something else now - /*else if (players[consoleplayer].charability == CA_THOK && (lines[i].flags & ML_NOSONIC)) - continue; - else if (players[consoleplayer].charability == CA_FLY && (lines[i].flags & ML_NOTAILS)) - continue; - else if (players[consoleplayer].charability == CA_GLIDEANDCLIMB && (lines[i].flags & ML_NOKNUX)) - continue;*/ - - // Disable any linedef specials with our tag. - for (j = -1; (j = P_FindLineFromLineTag(&lines[i], j)) >= 0;) - lines[j].special = 0; - } - } -} - // Rudimentary function to start a earthquake. // epicenter and radius are not yet used. void P_StartQuake(fixed_t intensity, tic_t time) diff --git a/src/p_spec.h b/src/p_spec.h index 6c918ef11..f2a245bb7 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -17,7 +17,9 @@ #ifndef __P_SPEC__ #define __P_SPEC__ -extern mobj_t *skyboxmo[2]; +extern mobj_t *skyboxmo[2]; // current skybox mobjs: 0 = viewpoint, 1 = centerpoint +extern mobj_t *skyboxviewpnts[16]; // array of MT_SKYBOX viewpoint mobjs +extern mobj_t *skyboxcenterpnts[16]; // array of MT_SKYBOX centerpoint mobjs // Something that should've been done long ago??? // We won't be using epicenter or radius anytime soon so I don't think it's worth it yet. @@ -29,6 +31,9 @@ void P_StartQuake(fixed_t intensity, tic_t time); // #define GETSECSPECIAL(i,j) ((i >> ((j-1)*4))&15) +// This must be updated whenever we up the max flat size - quicker to assume rather than figuring out the sqrt of the specific flat's filesize. +#define MAXFLATSIZE (2048<reactiontime = TICRATE/2; // don't move for about half a second // absolute angle position - if (thing == players[consoleplayer].mo) - localangle[0] = angle; - else if (r_splitscreen) - { - for (i = 1; i <= r_splitscreen; i++) - { - if (thing == players[displayplayers[i]].mo) - { - localangle[i] = angle; - break; - } - } - } + P_SetPlayerAngle(thing->player, angle); // move chasecam at new player location for (i = 0; i <= r_splitscreen; i++) @@ -100,8 +89,10 @@ void P_MixUp(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, thing->player->respawn.pointz = starpostz; thing->player->starpostnum = starpostnum; + thing->player->drawangle = drawangle; + P_ResetPlayer(thing->player); - P_SetPlayerMobjState(thing, S_KART_STILL1); // SRB2kart - was S_PLAY_STND + P_SetPlayerMobjState(thing, S_KART_STILL); // SRB2kart - was S_PLAY_STND P_FlashPal(thing->player, PAL_MIXUP, 10); } @@ -132,12 +123,10 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle if (!P_TeleportMove(thing, x, y, z)) return false; - thing->angle = angle; - if (!dontstopmove) thing->momx = thing->momy = thing->momz = 0; else // Change speed to match direction - P_InstaThrust(thing, thing->angle, P_AproxDistance(thing->momx, thing->momy)); + P_InstaThrust(thing, angle, FixedHypot(thing->momx, thing->momy)); if (thing->player) { @@ -146,52 +135,43 @@ boolean P_Teleport(mobj_t *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle else thing->player->viewz = thing->z + thing->player->viewheight; - if (!dontstopmove) - thing->reactiontime = TICRATE/2; // don't move for about half a second - - // absolute angle position - if (thing == players[consoleplayer].mo) - localangle[0] = angle; - else if (r_splitscreen) - { - for (i = 1; i <= r_splitscreen; i++) - { - if (thing == players[displayplayers[i]].mo) - { - localangle[i] = angle; - break; - } - } - } - - // move chasecam at new player location - for (i = 0; i <= r_splitscreen; i++) - { - if (thing->player == &players[displayplayers[i]] && camera[i].chase) - P_ResetCamera(thing->player, &camera[i]); - } - // don't run in place after a teleport if (!dontstopmove) { - INT32 p; - // Search for any players you might be carrying, so you can get them off before they end up being taken with you! - for (p = 0; p < MAXPLAYERS; p++) - if (playeringame[p] && players[p].mo && players[p].pflags & PF_CARRIED && players[p].mo->tracer == thing) - { - players[p].pflags &= ~PF_CARRIED; - break; - } thing->player->cmomx = thing->player->cmomy = 0; thing->player->rmomx = thing->player->rmomy = 0; thing->player->speed = 0; P_ResetPlayer(thing->player); - P_SetPlayerMobjState(thing, S_KART_STILL1); // SRB2kart - was S_PLAY_STND + P_SetPlayerMobjState(thing, S_KART_STILL); // SRB2kart - was S_PLAY_STND + + thing->reactiontime = TICRATE/2; // don't move for about half a second + thing->player->drawangle = angle; + } + else + thing->player->drawangle += (angle - thing->angle); + + // absolute angle position + P_SetPlayerAngle(thing->player, angle); + + for (i = 0; i <= r_splitscreen; i++) + { + if (thing == players[displayplayers[i]].mo) + { + if (camera[i].chase) + { + // move chasecam at new player location + P_ResetCamera(thing->player, &camera[i]); + } + + break; + } } if (flash) P_FlashPal(thing->player, PAL_MIXUP, 10); } + thing->angle = angle; + return true; } diff --git a/src/p_tick.c b/src/p_tick.c index 0c7f5b1dc..79e71c655 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -22,13 +22,17 @@ #include "m_random.h" #include "lua_script.h" #include "lua_hook.h" -#include "k_kart.h" -#include "k_battle.h" -#include "k_waypoint.h" +#include "m_perfstats.h" +#include "i_system.h" // I_GetTimeMicros // Object place #include "m_cheat.h" +// SRB2Kart +#include "k_kart.h" +#include "k_battle.h" +#include "k_waypoint.h" + tic_t leveltime; // @@ -39,8 +43,8 @@ tic_t leveltime; // but the first element must be thinker_t. // -// Both the head and tail of the thinker list. -thinker_t thinkercap; +// The entries will behave like both the head and tail of the lists. +thinker_t thlist[NUM_THINKERLISTS]; void Command_Numthinkers_f(void) { @@ -48,6 +52,9 @@ void Command_Numthinkers_f(void) INT32 count = 0; actionf_p1 action; thinker_t *think; + thinklistnum_t start = 0; + thinklistnum_t end = NUM_THINKERLISTS - 1; + thinklistnum_t i; if (gamestate != GS_LEVEL) { @@ -72,18 +79,22 @@ void Command_Numthinkers_f(void) switch (num) { case 1: + start = end = THINK_MOBJ; action = (actionf_p1)P_MobjThinker; CONS_Printf(M_GetText("Number of %s: "), "P_MobjThinker"); break; case 2: + start = end = THINK_PRECIP; action = (actionf_p1)P_NullPrecipThinker; CONS_Printf(M_GetText("Number of %s: "), "P_NullPrecipThinker"); break; case 3: + start = end = THINK_MAIN; action = (actionf_p1)T_Friction; CONS_Printf(M_GetText("Number of %s: "), "T_Friction"); break; case 4: + start = end = THINK_MAIN; action = (actionf_p1)T_Pusher; CONS_Printf(M_GetText("Number of %s: "), "T_Pusher"); break; @@ -96,12 +107,15 @@ void Command_Numthinkers_f(void) return; } - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (i = start; i <= end; i++) { - if (think->function.acp1 != action) - continue; + for (think = thlist[i].next; think != &thlist[i]; think = think->next) + { + if (think->function.acp1 != action) + continue; - count++; + count++; + } } CONS_Printf("%d\n", count); @@ -133,9 +147,9 @@ void Command_CountMobjs_f(void) count = 0; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; if (((mobj_t *)th)->type == i) @@ -153,9 +167,9 @@ void Command_CountMobjs_f(void) { count = 0; - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; if (((mobj_t *)th)->type == i) @@ -172,21 +186,24 @@ void Command_CountMobjs_f(void) // void P_InitThinkers(void) { - thinkercap.prev = thinkercap.next = &thinkercap; + UINT8 i; waypointcap = NULL; kitemcap = NULL; + for (i = 0; i < NUM_THINKERLISTS; i++) + thlist[i].prev = thlist[i].next = &thlist[i]; } -// -// P_AddThinker // Adds a new thinker at the end of the list. -// -void P_AddThinker(thinker_t *thinker) +void P_AddThinker(const thinklistnum_t n, thinker_t *thinker) { - thinkercap.prev->next = thinker; - thinker->next = &thinkercap; - thinker->prev = thinkercap.prev; - thinkercap.prev = thinker; +#ifdef PARANOIA + I_Assert(n < NUM_THINKERLISTS); +#endif + + thlist[n].prev->next = thinker; + thinker->next = &thlist[n]; + thinker->prev = thlist[n].prev; + thlist[n].prev = thinker; thinker->references = 0; // killough 11/98: init reference counter to 0 } @@ -209,22 +226,33 @@ static thinker_t *currentthinker; // remove it, and set currentthinker to one node preceeding it, so // that the next step in P_RunThinkers() will get its successor. // -void P_RemoveThinkerDelayed(void *pthinker) +void P_RemoveThinkerDelayed(thinker_t *thinker) { - thinker_t *thinker = pthinker; - if (!thinker->references) + thinker_t *next; +#ifdef PARANOIA +#define BEENAROUNDBIT (0x40000000) // has to be sufficiently high that it's unlikely to happen in regular gameplay. If you change this, pay attention to the bit pattern of INT32_MIN. + if (thinker->references & ~BEENAROUNDBIT) { - { - /* Remove from main thinker list */ - thinker_t *next = thinker->next; - /* Note that currentthinker is guaranteed to point to us, - * and since we're freeing our memory, we had better change that. So - * point it to thinker->prev, so the iterator will correctly move on to - * thinker->prev->next = thinker->next */ - (next->prev = currentthinker = thinker->prev)->next = next; - } - Z_Free(thinker); + if (thinker->references & BEENAROUNDBIT) // Usually gets cleared up in one frame; what's going on here, then? + CONS_Printf("Number of potentially faulty references: %d\n", (thinker->references & ~BEENAROUNDBIT)); + thinker->references |= BEENAROUNDBIT; + return; } +#undef BEENAROUNDBIT +#else + if (thinker->references) + return; +#endif + + /* Remove from main thinker list */ + next = thinker->next; + /* Note that currentthinker is guaranteed to point to us, + * and since we're freeing our memory, we had better change that. So + * point it to thinker->prev, so the iterator will correctly move on to + * thinker->prev->next = thinker->next */ + (next->prev = currentthinker = thinker->prev)->next = next; + + Z_Free(thinker); } // @@ -241,10 +269,8 @@ void P_RemoveThinkerDelayed(void *pthinker) // void P_RemoveThinker(thinker_t *thinker) { -#ifdef HAVE_BLUA LUA_InvalidateUserdata(thinker); -#endif - thinker->function.acp1 = P_RemoveThinkerDelayed; + thinker->function.acp1 = (actionf_p1)P_RemoveThinkerDelayed; } /* @@ -292,11 +318,20 @@ if ((*mop = targ) != NULL) // Set new target and if non-NULL, increase its count // static inline void P_RunThinkers(void) { - for (currentthinker = thinkercap.next; currentthinker != &thinkercap; currentthinker = currentthinker->next) + size_t i; + for (i = 0; i < NUM_THINKERLISTS; i++) { - if (currentthinker->function.acp1) + ps_thlist_times[i] = I_GetTimeMicros(); + for (currentthinker = thlist[i].next; currentthinker != &thlist[i]; currentthinker = currentthinker->next) + { +#ifdef PARANOIA + I_Assert(currentthinker->function.acp1 != NULL); +#endif currentthinker->function.acp1(currentthinker); + } + ps_thlist_times[i] = I_GetTimeMicros() - ps_thlist_times[i]; } + } // @@ -304,7 +339,7 @@ static inline void P_RunThinkers(void) // // Determine if the teams are unbalanced, and if so, move a player to the other team. // -/*static void P_DoAutobalanceTeams(void) +static void P_DoAutobalanceTeams(void) { changeteam_union NetPacket; UINT16 usvalue; @@ -320,7 +355,7 @@ static inline void P_RunThinkers(void) // Only do it if we have enough room in the net buffer to send it. // Otherwise, come back next time and try again. - if (sizeof(usvalue) > GetFreeXCmdSize()) + if (sizeof(usvalue) > GetFreeXCmdSize(0)) return; //We have to store the players in an array with the rest of their team. @@ -355,7 +390,7 @@ static inline void P_RunThinkers(void) totalred = red + redflagcarrier; totalblue = blue + blueflagcarrier; - if ((abs(totalred - totalblue) > cv_autobalance.value)) + if ((abs(totalred - totalblue) > max(1, (totalred + totalblue) / 8))) { if (totalred > totalblue) { @@ -368,8 +403,7 @@ static inline void P_RunThinkers(void) usvalue = SHORT(NetPacket.value.l|NetPacket.value.b); SendNetXCmd(XD_TEAMCHANGE, &usvalue, sizeof(usvalue)); } - - if (totalblue > totalred) + else //if (totalblue > totalred) { i = M_RandomKey(blue); NetPacket.packet.newteam = 1; @@ -397,7 +431,7 @@ void P_DoTeamscrambling(void) // Only do it if we have enough room in the net buffer to send it. // Otherwise, come back next time and try again. - if (sizeof(usvalue) > GetFreeXCmdSize()) + if (sizeof(usvalue) > GetFreeXCmdSize(0)) return; if (scramblecount < scrambletotal) @@ -419,125 +453,7 @@ void P_DoTeamscrambling(void) CV_SetValue(&cv_teamscramble, 0); } -static inline void P_DoSpecialStageStuff(void) -{ - boolean inwater = false; - INT32 i; - - // Can't drown in a special stage - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - players[i].powers[pw_underwater] = players[i].powers[pw_spacetime] = 0; - } - - if (sstimer < 15*TICRATE+6 && sstimer > 7 && (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC)) - S_SpeedMusic(1.4f); - - if (sstimer < 7 && sstimer > 0) // The special stage time is up! - { - sstimer = 0; - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - players[i].exiting = raceexittime+1; - players[i].pflags &= ~PF_GLIDING; - } - - if (i == consoleplayer) - S_StartSound(NULL, sfx_lose); - } - - if (mapheaderinfo[gamemap-1]->levelflags & LF_SPEEDMUSIC) - S_SpeedMusic(1.0f); - - stagefailed = true; - } - - if (sstimer > 1) // As long as time isn't up... - { - UINT32 ssrings = 0; - // Count up the rings of all the players and see if - // they've collected the required amount. - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - ssrings += (players[i].mo->health-1); - - // If in water, deplete timer 6x as fast. - if ((players[i].mo->eflags & MFE_TOUCHWATER) - || (players[i].mo->eflags & MFE_UNDERWATER)) - inwater = true; - } - - if (ssrings >= totalrings && totalrings > 0) - { - // Halt all the players - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - { - players[i].mo->momx = players[i].mo->momy = 0; - players[i].exiting = raceexittime+1; - } - - sstimer = 0; - - P_GiveEmerald(true); - } - - // Decrement the timer - if (!objectplacing) - { - if (inwater) - sstimer -= 6; - else - sstimer--; - } - } -} - -static inline void P_DoTagStuff(void) -{ - INT32 i; - - // tell the netgame who the initial IT person is. - if (leveltime == TICRATE) - { - for (i = 0; i < MAXPLAYERS; i++) - { - if (players[i].pflags & PF_TAGIT) - { - CONS_Printf(M_GetText("%s is now IT!\n"), player_names[i]); // Tell everyone who is it! - break; - } - } - } - - //increment survivor scores - if (leveltime % TICRATE == 0 && leveltime > (hidetime * TICRATE)) - { - INT32 participants = 0; - - for (i=0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].spectator) - participants++; - } - - for (i=0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && !players[i].spectator && players[i].playerstate == PST_LIVE - && !(players[i].pflags & (PF_TAGIT|PF_TAGGED))) - //points given is the number of participating players divided by two. - P_AddPlayerScore(&players[i], participants/2); - } - } -} - -static inline void P_DoCTFStuff(void) +static inline void P_DoTeamStuff(void) { // Automatic team balance for CTF and team match if (leveltime % (TICRATE * 5) == 0) //only check once per five seconds for the sake of CPU conservation. @@ -556,7 +472,7 @@ static inline void P_DoCTFStuff(void) if (cv_teamscramble.value && server) P_DoTeamscrambling(); } -}*/ +} // // P_Ticker @@ -565,10 +481,21 @@ void P_Ticker(boolean run) { INT32 i; - //Increment jointime even if paused. + // Increment jointime and quittime even if paused for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i]) - ++players[i].jointime; + { + players[i].jointime++; + + if (players[i].quittime) + { + players[i].quittime++; + + if (server && players[i].quittime >= (tic_t)FixedMul(cv_rejointimeout.value, 60 * TICRATE) + && !(players[i].quittime % TICRATE)) + SendKick(i, KICK_MSG_PLAYER_QUIT); + } + } if (objectplacing) { @@ -578,6 +505,7 @@ void P_Ticker(boolean run) OP_ObjectplaceMovement(&players[0]); P_MoveChaseCamera(&players[0], &camera[0], false); P_MapEnd(); + S_SetStackAdjustmentStart(); return; } } @@ -592,10 +520,13 @@ void P_Ticker(boolean run) } else if (demo.freecam && democam.cam) // special case: allow freecam to MOVE during pause! P_DemoCameraMovement(democam.cam); - + S_SetStackAdjustmentStart(); return; } + if (!S_MusicPaused()) + S_AdjustMusicStackTics(); + for (i = 0; i <= r_splitscreen; i++) postimgtype[i] = postimg_none; @@ -618,6 +549,13 @@ void P_Ticker(boolean run) G_ReadDemoTiccmd(&players[i].cmd, i); } + ps_lua_mobjhooks = 0; + ps_checkposition_calls = 0; + + LUAh_PreThinkFrame(); + + ps_playerthink_time = I_GetTimeMicros(); + // First loop: Ensure all players' distance to the finish line are all accurate for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) @@ -632,40 +570,38 @@ void P_Ticker(boolean run) for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerThink(&players[i]); + + ps_playerthink_time = I_GetTimeMicros() - ps_playerthink_time; } // Keep track of how long they've been playing! if (!demo.playback) // Don't increment if a demo is playing. totalplaytime++; - /*if (!useNightsSS && G_IsSpecialStage(gamemap)) - P_DoSpecialStageStuff(); - - if (runemeraldmanager) - P_EmeraldManager(); // Power stone mode*/ - // formality so kitemcap gets updated properly each frame. P_RunKartItems(); if (run) { + ps_thinkertime = I_GetTimeMicros(); P_RunThinkers(); + ps_thinkertime = I_GetTimeMicros() - ps_thinkertime; // Run any "after all the other thinkers" stuff for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); - if (G_BattleGametype() && battleovertime.enabled) + if ((gametyperules & GTR_BUMPERS) && battleovertime.enabled) K_RunBattleOvertime(); -#ifdef HAVE_BLUA + ps_lua_thinkframe_time = I_GetTimeMicros(); LUAh_ThinkFrame(); -#endif + ps_lua_thinkframe_time = I_GetTimeMicros() - ps_lua_thinkframe_time; } // Run shield positioning - //P_RunShields(); + P_RunShields(); P_RunOverlays(); P_UpdateSpecials(); @@ -681,30 +617,11 @@ void P_Ticker(boolean run) if (!(modeattacking && !demo.playback) || leveltime >= starttime - TICRATE*4) timeinmap++; - /*if (G_TagGametype()) - P_DoTagStuff(); - if (G_GametypeHasTeams()) - P_DoCTFStuff();*/ + P_DoTeamStuff(); if (run) { - if (countdowntimer && --countdowntimer <= 0) - { - countdowntimer = 0; - countdowntimeup = true; - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || players[i].spectator) - continue; - - if (!players[i].mo) - continue; - - P_DamageMobj(players[i].mo, NULL, NULL, 10000); - } - } - if (racecountdown > 1) racecountdown--; @@ -716,7 +633,7 @@ void P_Ticker(boolean run) if (hyubgone > 0) hyubgone--; - if (G_BattleGametype()) + if ((gametyperules & GTR_BUMPERS)) { if (wantedcalcdelay && --wantedcalcdelay <= 0) K_CalculateBattleWanted(); @@ -747,7 +664,7 @@ void P_Ticker(boolean run) G_WriteAllGhostTics(); if (cv_recordmultiplayerdemos.value && (demo.savemode == DSM_NOTSAVING || demo.savemode == DSM_WILLAUTOSAVE)) - if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && InputDown(gc_lookback, 1)) + if (demo.savebutton && demo.savebutton + 3*TICRATE < leveltime && PlayerInputDown(1, gc_lookback)) demo.savemode = DSM_TITLEENTRY; } else if (demo.playback) // Use Ghost data for consistency checks. @@ -774,6 +691,7 @@ void P_Ticker(boolean run) { if (camera[i].chase) P_MoveChaseCamera(&players[displayplayers[i]], &camera[i], false); + LUAh_PostThinkFrame(); } P_MapEnd(); @@ -793,6 +711,9 @@ void P_PreTicker(INT32 frames) for (i = 0; i <= r_splitscreen; i++) postimgtype[i] = postimg_none; + if (marathonmode & MA_INGAME) + marathonmode |= MA_INIT; + for (framecnt = 0; framecnt < frames; ++framecnt) { P_MapStart(); @@ -808,6 +729,8 @@ void P_PreTicker(INT32 frames) K_KartUpdatePosition(&players[i]); // OK! Now that we got all of that sorted, players can think! + LUAh_PreThinkFrame(); + for (i = 0; i < MAXPLAYERS; i++) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) { @@ -816,8 +739,6 @@ void P_PreTicker(INT32 frames) // (and disrupt demo recording and other things !!) memcpy(&temptic, &players[i].cmd, sizeof(ticcmd_t)); memset(&players[i].cmd, 0, sizeof(ticcmd_t)); - // correct angle on spawn... - players[i].cmd.angleturn = temptic.angleturn; P_PlayerThink(&players[i]); @@ -831,20 +752,23 @@ void P_PreTicker(INT32 frames) if (playeringame[i] && players[i].mo && !P_MobjWasRemoved(players[i].mo)) P_PlayerAfterThink(&players[i]); - if (G_BattleGametype() && battleovertime.enabled) + if ((gametyperules & GTR_BUMPERS) && battleovertime.enabled) K_RunBattleOvertime(); -#ifdef HAVE_BLUA LUAh_ThinkFrame(); -#endif // Run shield positioning - //P_RunShields(); + P_RunShields(); P_RunOverlays(); P_UpdateSpecials(); P_RespawnSpecials(); + LUAh_PostThinkFrame(); + P_MapEnd(); } + + if (marathonmode & MA_INGAME) + marathonmode &= ~MA_INIT; } diff --git a/src/p_tick.h b/src/p_tick.h index 169c54c8e..1fb88f3f2 100644 --- a/src/p_tick.h +++ b/src/p_tick.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,7 +27,7 @@ void Command_CountMobjs_f(void); void P_Ticker(boolean run); void P_PreTicker(INT32 frames); void P_DoTeamscrambling(void); -void P_RemoveThinkerDelayed(void *pthinker); //killed +void P_RemoveThinkerDelayed(thinker_t *thinker); //killed mobj_t *P_SetTarget(mobj_t **mo, mobj_t *target); // killough 11/98 #endif diff --git a/src/p_user.c b/src/p_user.c index de50aaa0f..821ff850f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -22,7 +22,7 @@ #include "p_local.h" #include "r_main.h" #include "s_sound.h" -#include "r_things.h" +#include "r_skins.h" #include "d_think.h" #include "r_sky.h" #include "p_setup.h" @@ -42,10 +42,12 @@ #include "lua_hook.h" // Objectplace #include "m_cheat.h" +// Thok camera snap (ctrl-f "chalupa") +#include "g_input.h" + // SRB2kart #include "m_cond.h" // M_UpdateUnlockablesAndExtraEmblems #include "k_kart.h" -#include "k_color.h" // KartColor_Opposite #include "console.h" // CON_LogMessage #include "k_respawn.h" #include "k_bot.h" @@ -64,6 +66,29 @@ static void P_NukeAllPlayers(player_t *player); #endif +// +// Jingle stuff. +// + +jingle_t jingleinfo[NUMJINGLES] = { + // {musname, looping, reset, nest} + {"" , false}, // JT_NONE + {"" , false}, // JT_OTHER + {"" , false}, // JT_MASTER + {"_1up" , false}, + {"_shoes" , true}, + {"_inv" , false}, + {"_minv" , false}, + {"_drown" , false}, + {"_super" , true}, + {"_gover" , false}, + {"_ntime" , false}, // JT_NIGHTSTIMEOUT + {"_drown" , false} // JT_SSTIMEOUT + // {"_clear" , false}, + // {"_inter" , true}, + // {"_conti" , true} +}; + // // Movement. // @@ -81,21 +106,11 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move) { angle >>= ANGLETOFINESHIFT; - mo->momx += FixedMul(move, FINECOSINE(angle)); - - if (!(twodlevel || (mo->flags2 & MF2_TWOD))) - mo->momy += FixedMul(move, FINESINE(angle)); -} - -#if 0 -static inline void P_ThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move) -{ - angle >>= ANGLETOFINESHIFT; - mo->momx += FixedMul(move, FINECOSINE(angle)); mo->momy += FixedMul(move, FINESINE(angle)); } +#if 0 static inline void P_VectorInstaThrust(fixed_t xa, fixed_t xb, fixed_t xc, fixed_t ya, fixed_t yb, fixed_t yc, fixed_t za, fixed_t zb, fixed_t zc, fixed_t momentum, mobj_t *mo) { @@ -139,17 +154,7 @@ void P_InstaThrust(mobj_t *mo, angle_t angle, fixed_t move) angle >>= ANGLETOFINESHIFT; mo->momx = FixedMul(move, FINECOSINE(angle)); - - if (!(twodlevel || (mo->flags2 & MF2_TWOD))) - mo->momy = FixedMul(move,FINESINE(angle)); -} - -void P_InstaThrustEvenIn2D(mobj_t *mo, angle_t angle, fixed_t move) -{ - angle >>= ANGLETOFINESHIFT; - - mo->momx = FixedMul(move, FINECOSINE(angle)); - mo->momy = FixedMul(move, FINESINE(angle)); + mo->momy = FixedMul(move,FINESINE(angle)); } // Returns a location (hard to explain - go see how it is used) @@ -173,7 +178,7 @@ fixed_t P_ReturnThrustY(mobj_t *mo, angle_t angle, fixed_t move) boolean P_AutoPause(void) { // Don't pause even on menu-up or focus-lost in netgames or record attack - if (netgame || modeattacking || demo.title) + if (netgame || modeattacking || gamestate == GS_TITLESCREEN) return false; return ((menuactive && !demo.playback) || ( window_notinfocus && cv_pauseifunfocused.value )); @@ -185,10 +190,10 @@ boolean P_AutoPause(void) // void P_CalcHeight(player_t *player) { - //INT32 angle; - //fixed_t bob; - //fixed_t pviewheight; + fixed_t bob = 0; + fixed_t pviewheight; mobj_t *mo = player->mo; + fixed_t bobmul = FRACUNIT - FixedDiv(FixedHypot(player->rmomx, player->rmomy), K_GetKartSpeed(player, false)); // Regular movement bobbing. // Should not be calculated when not on ground (FIXTHIS?) @@ -196,11 +201,10 @@ void P_CalcHeight(player_t *player) // Note: a LUT allows for effects // like a ramp with low health. - /*player->bob = (FixedMul(player->rmomx,player->rmomx) - + FixedMul(player->rmomy,player->rmomy))>>2; + if (bobmul > FRACUNIT) bobmul = FRACUNIT; + if (bobmul < FRACUNIT/8) bobmul = FRACUNIT/8; - if (player->bob > FixedMul(MAXBOB, mo->scale)) - player->bob = FixedMul(MAXBOB, mo->scale);*/ + player->bob = FixedMul(cv_movebob.value, bobmul); if (!P_IsObjectOnGround(mo)) { @@ -219,13 +223,16 @@ void P_CalcHeight(player_t *player) return; } - //angle = (FINEANGLES/20*localgametic)&FINEMASK; - //bob = FixedMul(player->bob/2, FINESINE(angle)); + // First person move bobbing in Kart is more of a "move jitter", to match how a go-kart would feel :p + if (leveltime & 1) + { + bob = player->bob; + } // move viewheight - player->viewheight = FixedMul(32 << FRACBITS, mo->scale); // default eye view height + pviewheight = P_GetPlayerViewHeight(player); // default eye view height - /*if (player->playerstate == PST_LIVE) + if (player->playerstate == PST_LIVE) { player->viewheight += player->deltaviewheight; @@ -248,12 +255,12 @@ void P_CalcHeight(player_t *player) if (!player->deltaviewheight) player->deltaviewheight = 1; } - }*/ + } if (player->mo->eflags & MFE_VERTICALFLIP) - player->viewz = mo->z + mo->height - player->viewheight; //- bob + player->viewz = mo->z + mo->height - player->viewheight - bob; else - player->viewz = mo->z + player->viewheight; //+ bob + player->viewz = mo->z + player->viewheight + bob; if (player->viewz > mo->ceilingz-FixedMul(4*FRACUNIT, mo->scale)) player->viewz = mo->ceilingz-FixedMul(4*FRACUNIT, mo->scale); @@ -279,9 +286,7 @@ boolean P_PlayerMoving(INT32 pnum) return gamestate == GS_LEVEL && p->mo && p->mo->health > 0 && (abs(p->rmomx) >= FixedMul(FRACUNIT/2, p->mo->scale) || abs(p->rmomy) >= FixedMul(FRACUNIT/2, p->mo->scale) - || abs(p->mo->momz) >= FixedMul(FRACUNIT/2, p->mo->scale) - || p->climbing || p->powers[pw_tailsfly] - || (p->pflags & PF_JUMPED) || (p->pflags & PF_SPINNING)); + || abs(p->mo->momz) >= FixedMul(FRACUNIT/2, p->mo->scale)); } // P_GetNextEmerald @@ -290,22 +295,11 @@ boolean P_PlayerMoving(INT32 pnum) // UINT8 P_GetNextEmerald(void) { - if (!useNightsSS) // In order - { - if (!(emeralds & EMERALD1)) return 0; - if (!(emeralds & EMERALD2)) return 1; - if (!(emeralds & EMERALD3)) return 2; - if (!(emeralds & EMERALD4)) return 3; - if (!(emeralds & EMERALD5)) return 4; - if (!(emeralds & EMERALD6)) return 5; - return 6; - } - else // Depends on stage - { - if (gamemap < sstage_start || gamemap > sstage_end) - return 0; + if (gamemap >= sstage_start && gamemap <= sstage_end) return (UINT8)(gamemap - sstage_start); - } + if (gamemap >= smpstage_start || gamemap <= smpstage_end) + return (UINT8)(gamemap - smpstage_start); + return 0; } // @@ -316,23 +310,83 @@ UINT8 P_GetNextEmerald(void) // void P_GiveEmerald(boolean spawnObj) { - INT32 i; - UINT8 em; + UINT8 em = P_GetNextEmerald(); S_StartSound(NULL, sfx_cgot); // Got the emerald! - em = P_GetNextEmerald(); emeralds |= (1 << em); + stagefailed = false; if (spawnObj) { + // The Chaos Emerald begins to orbit us! + // Only visibly give it to ONE person! + UINT8 i, pnum = ((playeringame[consoleplayer]) && (!players[consoleplayer].spectator) && (players[consoleplayer].mo)) ? consoleplayer : 255; for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - P_SetMobjState(P_SpawnMobj(players[i].mo->x, players[i].mo->y, players[i].mo->z + players[i].mo->info->height, MT_GOTEMERALD), - mobjinfo[MT_GOTEMERALD].spawnstate + em); + { + mobj_t *emmo; + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + emmo = P_SpawnMobjFromMobj(players[i].mo, 0, 0, players[i].mo->height, MT_GOTEMERALD); + if (!emmo) + continue; + P_SetTarget(&emmo->target, players[i].mo); + P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); + + // Make sure we're not being carried before our tracer is changed + players[i].powers[pw_carry] = CR_NONE; + + P_SetTarget(&players[i].mo->tracer, emmo); + + if (pnum == 255) + { + pnum = i; + continue; + } + + if (i == pnum) + continue; + + emmo->flags2 |= MFD_DONTDRAW; + } } } +// +// P_GiveFinishFlags +// +// Give the player visual indicators +// that they've finished the map. +// +void P_GiveFinishFlags(player_t *player) +{ + angle_t angle = FixedAngle(player->mo->angle << FRACBITS); + UINT8 i; + + if (!player->mo) + return; + + if (!(netgame||multiplayer)) + return; + + for (i = 0; i < 3; i++) + { + angle_t fa = (angle >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t xoffs = FINECOSINE(fa); + fixed_t yoffs = FINESINE(fa); + mobj_t* flag = P_SpawnMobjFromMobj(player->mo, xoffs, yoffs, 0, MT_FINISHFLAG); + flag->angle = angle; + angle += FixedAngle(120*FRACUNIT); + + P_SetTarget(&flag->target, player->mo); + } +} + +#if 0 // // P_ResetScore // @@ -343,44 +397,7 @@ void P_ResetScore(player_t *player) player->scoreadd = 0; } - -// -// P_FindLowestMare -// -// Returns the lowest open mare available -// -/*UINT8 P_FindLowestMare(void) -{ - thinker_t *th; - mobj_t *mo2; - UINT8 mare = UINT8_MAX; - - if (G_RaceGametype()) - return 0; - - // scan the thinkers - // to find the egg capsule with the lowest mare - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_EGGCAPSULE && mo2->health > 0) - { - const UINT8 threshold = (UINT8)mo2->threshold; - if (mare == 255) - mare = threshold; - else if (threshold < mare) - mare = threshold; - } - } - - CONS_Debug(DBG_NIGHTS, "Lowest mare found: %d\n", mare); - - return mare; -}*/ +#endif // // P_FindLowestLap @@ -392,7 +409,7 @@ UINT8 P_FindLowestLap(void) INT32 i; UINT8 lowest = UINT8_MAX; - if (!G_RaceGametype()) + if (gametyperules & GTR_CIRCUIT) return 0; for (i = 0; i < MAXPLAYERS; i++) @@ -419,7 +436,7 @@ UINT8 P_FindHighestLap(void) INT32 i; UINT8 highest = 0; - if (!G_RaceGametype()) + if (!(gametyperules & GTR_CIRCUIT)) return 0; for (i = 0; i < MAXPLAYERS; i++) @@ -436,389 +453,6 @@ UINT8 P_FindHighestLap(void) return highest; } -// -// P_TransferToNextMare -// -// Transfers the player to the next Mare. -// (Finds the lowest mare # for capsules that have not been destroyed). -// Returns true if successful, false if there is no other mare. -// -/*boolean P_TransferToNextMare(player_t *player) -{ - thinker_t *th; - mobj_t *mo2; - mobj_t *closestaxis = NULL; - INT32 lowestaxisnum = -1; - UINT8 mare = P_FindLowestMare(); - fixed_t dist1, dist2 = 0; - - if (mare == 255) - return false; - - CONS_Debug(DBG_NIGHTS, "Mare is %d\n", mare); - - player->mare = mare; - - // scan the thinkers - // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_AXIS) - { - if (mo2->threshold == mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - lowestaxisnum = mo2->health; - dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; - } - else if (mo2->health < lowestaxisnum) - { - dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; - - if (dist1 < dist2) - { - closestaxis = mo2; - lowestaxisnum = mo2->health; - dist2 = dist1; - } - } - } - } - } - - if (closestaxis == NULL) - return false; - - P_SetTarget(&player->mo->target, closestaxis); - return true; -} - -// -// P_FindAxis -// -// Given a mare and axis number, returns -// the mobj for that axis point. -static mobj_t *P_FindAxis(INT32 mare, INT32 axisnum) -{ - thinker_t *th; - mobj_t *mo2; - - // scan the thinkers - // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - // Axis things are only at beginning of list. - if (!(mo2->flags2 & MF2_AXIS)) - return NULL; - - if (mo2->type == MT_AXIS) - { - if (mo2->health == axisnum && mo2->threshold == mare) - return mo2; - } - } - - return NULL; -} - -// -// P_FindAxisTransfer -// -// Given a mare and axis number, returns -// the mobj for that axis transfer point. -static mobj_t *P_FindAxisTransfer(INT32 mare, INT32 axisnum, mobjtype_t type) -{ - thinker_t *th; - mobj_t *mo2; - - // scan the thinkers - // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - // Axis things are only at beginning of list. - if (!(mo2->flags2 & MF2_AXIS)) - return NULL; - - if (mo2->type == type) - { - if (mo2->health == axisnum && mo2->threshold == mare) - return mo2; - } - } - - return NULL; -} - -// -// P_TransferToAxis -// -// Finds the CLOSEST axis with the number specified. -void P_TransferToAxis(player_t *player, INT32 axisnum) -{ - thinker_t *th; - mobj_t *mo2; - mobj_t *closestaxis; - INT32 mare = player->mare; - fixed_t dist1, dist2 = 0; - - CONS_Debug(DBG_NIGHTS, "Transferring to axis %d\nLeveltime: %u...\n", axisnum, leveltime); - - closestaxis = NULL; - - // scan the thinkers - // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_AXIS) - { - if (mo2->health == axisnum && mo2->threshold == mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - dist2 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; - } - else - { - dist1 = R_PointToDist2(player->mo->x, player->mo->y, mo2->x, mo2->y)-mo2->radius; - - if (dist1 < dist2) - { - closestaxis = mo2; - dist2 = dist1; - } - } - } - } - } - - if (!closestaxis) - { - CONS_Debug(DBG_NIGHTS, "ERROR: Specified axis point to transfer to not found!\n%d\n", axisnum); - } - else - { - CONS_Debug(DBG_NIGHTS, "Transferred to axis %d, mare %d\n", closestaxis->health, closestaxis->threshold); - } - - P_SetTarget(&player->mo->target, closestaxis); -} - -// -// P_DeNightserizePlayer -// -// Whoops! Ran out of NiGHTS time! -// -static void P_DeNightserizePlayer(player_t *player) -{ - thinker_t *th; - mobj_t *mo2; - - player->pflags &= ~PF_NIGHTSMODE; - - //if (player->mo->tracer) - //P_RemoveMobj(player->mo->tracer); - - player->powers[pw_underwater] = 0; - player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_THOKKED|PF_SPINNING|PF_DRILLING|PF_TRANSFERTOCLOSEST); - player->secondjump = 0; - player->jumping = 0; - player->homing = 0; - player->climbing = 0; - player->mo->fuse = 0; - player->speed = 0; - P_SetTarget(&player->mo->target, NULL); - P_SetTarget(&player->axis1, P_SetTarget(&player->axis2, NULL)); - - player->mo->flags &= ~MF_NOGRAVITY; - - player->mo->drawflags &= ~MFD_DONTDRAW; - - // Restore aiming angle - if (player == &players[consoleplayer]) - localaiming[0] = 0; - else if (player == &players[displayplayers[1]]) - localaiming[1] = 0; - else if (player == &players[displayplayers[2]]) - localaiming[2] = 0; - else if (player == &players[displayplayers[3]]) - localaiming[3] = 0; - - if (player->mo->tracer) - P_RemoveMobj(player->mo->tracer); - //P_SetPlayerMobjState(player->mo, S_PLAY_FALL1); // SRB2kart - player->pflags |= PF_NIGHTSFALL; - - // If in a special stage, add some preliminary exit time. - if (G_IsSpecialStage(gamemap)) - { - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) - players[i].nightstime = 1; // force everyone else to fall too. - player->exiting = raceexittime+2; - stagefailed = true; // NIGHT OVER - } - - // Check to see if the player should be killed. - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - if (!(mo2->type == MT_NIGHTSDRONE)) - continue; - - if (mo2->flags2 & MF2_AMBUSH) - P_DamageMobj(player->mo, NULL, NULL, 10000); - - break; - } - - // Restore from drowning music - P_RestoreMusic(player); -} -// -// P_NightserizePlayer -// -// NiGHTS Time! -void P_NightserizePlayer(player_t *player, INT32 nighttime) -{ - INT32 oldmare; - - if (!(player->pflags & PF_NIGHTSMODE)) - { - P_SetTarget(&player->mo->tracer, P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_NIGHTSCHAR)); - player->mo->tracer->destscale = player->mo->scale; - P_SetScale(player->mo->tracer, player->mo->scale); - player->mo->tracer->eflags = (player->mo->tracer->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); - player->mo->height = player->mo->tracer->height; - } - - player->pflags &= ~(PF_USEDOWN|PF_JUMPDOWN|PF_ATTACKDOWN|PF_STARTDASH|PF_GLIDING|PF_JUMPED|PF_THOKKED|PF_SPINNING|PF_DRILLING); - player->homing = 0; - player->mo->fuse = 0; - player->speed = 0; - player->climbing = 0; - player->secondjump = 0; - - player->powers[pw_shield] = SH_NONE; - - player->mo->flags |= MF_NOGRAVITY; - - player->mo->drawflags |= MFD_DONTDRAW; - - player->nightstime = player->startedtime = nighttime*TICRATE; - player->bonustime = false; - - P_RestoreMusic(player); - P_SetMobjState(player->mo->tracer, S_SUPERTRANS1); - - if (G_RaceGametype()) - { - if (player->drillmeter < 48*20) - player->drillmeter = 48*20; - } - else - { - if (player->drillmeter < 40*20) - player->drillmeter = 40*20; - } - - oldmare = player->mare; - - if (P_TransferToNextMare(player) == false) - { - INT32 i; - INT32 total_rings = 0; - - P_SetTarget(&player->mo->target, NULL); - - if (G_IsSpecialStage(gamemap)) - { - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - total_rings += players[i].health-1; - } - - for (i = 0; i < MAXPLAYERS; i++) - { - if (!playeringame[i] || !players[i].mo || players[i].spectator) - continue; - - players[i].texttimer = (3 * TICRATE) - 10; - players[i].textvar = 4; // Score and grades - players[i].lastmare = players[i].mare; - if (G_IsSpecialStage(gamemap)) - { - players[i].finishedrings = (INT16)total_rings; - P_AddPlayerScore(player, total_rings * 50); - } - else - { - players[i].finishedrings = (INT16)(players[i].health - 1); - P_AddPlayerScore(&players[i], (players[i].health - 1) * 50); - } - - // transfer scores anyway - - players[i].mo->health = players[i].health = 1; - P_DoPlayerExit(&players[i]); - } - } - else if (oldmare != player->mare) - { - /// \todo Handle multi-mare special stages. - // Ring bonus - P_AddPlayerScore(player, (player->health - 1) * 50); - - player->lastmare = (UINT8)oldmare; - player->texttimer = 4*TICRATE; - player->textvar = 4; // Score and grades - player->finishedrings = (INT16)(player->health - 1); - - // Starting a new mare, transfer scores - player->marebegunat = leveltime; - - player->mo->health = player->health = 1; - } - else - { - player->textvar = 5; // Nothing, just tells it to go to the GET n RINGS/SPHERES text in a bit - player->texttimer = 40; - - // Don't show before title card - // Not consistency safe, but this only affects drawing - if (timeinmap + 40 < 110) - player->texttimer = (UINT8)(110 - timeinmap); - } - - player->pflags |= PF_NIGHTSMODE; -}*/ - // // P_PlayerInPain // @@ -827,113 +461,31 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime) // boolean P_PlayerInPain(player_t *player) { - // no silly, sliding isn't pain - if (!(player->pflags & PF_SLIDING) && player->mo->state == &states[player->mo->info->painstate] && player->powers[pw_flashing]) + if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_squishedtimer] || player->respawn.state != RESPAWNST_NONE) return true; + if (gametyperules & GTR_KARMA) + { + if (player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) + return true; + } + return false; } -// -// P_DoPlayerPain -// -// Player was hit, -// put them in pain. -// -void P_DoPlayerPain(player_t *player, mobj_t *source, mobj_t *inflictor) -{ - angle_t ang; - fixed_t fallbackspeed; - - if (inflictor && (inflictor->type != MT_PLAYER && inflictor->type != MT_ORBINAUT && inflictor->type != MT_ORBINAUT_SHIELD - && inflictor->type != MT_JAWZ && inflictor->type != MT_JAWZ_DUD && inflictor->type != MT_JAWZ_SHIELD - && inflictor->type != MT_SMK_THWOMP)) - { - if (player->mo->eflags & MFE_VERTICALFLIP) - player->mo->z--; - else - player->mo->z++; - - if (player->mo->eflags & MFE_UNDERWATER) - P_SetObjectMomZ(player->mo, FixedDiv(10511*FRACUNIT,2600*FRACUNIT), false); - else - P_SetObjectMomZ(player->mo, FixedDiv(69*FRACUNIT,10*FRACUNIT), false); - } - - if (inflictor) - { - ang = R_PointToAngle2(inflictor->x, inflictor->y, player->mo->x, player->mo->y); // SRB2kart - //ang = R_PointToAngle2(inflictor->x-inflictor->momx, inflictor->y - inflictor->momy, player->mo->x - player->mo->momx, player->mo->y - player->mo->momy); - - // explosion and rail rings send you farther back, making it more difficult - // to recover - if ((inflictor->flags2 & MF2_SCATTER) && source) - { - fixed_t dist = P_AproxDistance(P_AproxDistance(source->x-player->mo->x, source->y-player->mo->y), source->z-player->mo->z); - - dist = FixedMul(128*FRACUNIT, inflictor->scale) - dist/4; - - if (dist < FixedMul(4*FRACUNIT, inflictor->scale)) - dist = FixedMul(4*FRACUNIT, inflictor->scale); - - fallbackspeed = dist; - } - else if (inflictor->flags2 & MF2_EXPLOSION) - { - if (inflictor->flags2 & MF2_RAILRING) - fallbackspeed = FixedMul(38*FRACUNIT, inflictor->scale); // 7x - else - fallbackspeed = FixedMul(30*FRACUNIT, inflictor->scale); // 5x - } - else if (inflictor->flags2 & MF2_RAILRING) - fallbackspeed = FixedMul(45*FRACUNIT, inflictor->scale); // 4x - else - fallbackspeed = FixedMul(4*FRACUNIT, inflictor->scale); // the usual amount of force - } - else - { - ang = R_PointToAngle2(player->mo->momx, player->mo->momy, 0, 0); - fallbackspeed = FixedMul(4*FRACUNIT, player->mo->scale); - } - - P_InstaThrust(player->mo, ang, fallbackspeed); - - if (player->pflags & PF_ROPEHANG) - P_SetTarget(&player->mo->tracer, NULL); - - // Point penalty for hitting a hazard during tag. - // Discourages players from intentionally hurting themselves to avoid being tagged. - /*if (gametype == GT_TAG && (!(player->pflags & PF_TAGGED) && !(player->pflags & PF_TAGIT))) - { - if (player->score >= 50) - player->score -= 50; - else - player->score = 0; - }*/ - - P_ResetPlayer(player); - P_SetPlayerMobjState(player->mo, player->mo->info->painstate); - player->powers[pw_flashing] = K_GetKartFlashing(player); - - if (player->timeshit != UINT8_MAX) - ++player->timeshit; -} - // // P_ResetPlayer // // Useful when you want to kill everything the player is doing. void P_ResetPlayer(player_t *player) { - player->pflags &= ~(PF_ROPEHANG|PF_ITEMHANG|PF_MACESPIN|PF_SPINNING|PF_JUMPED|PF_GLIDING|PF_THOKKED|PF_CARRIED); - player->jumping = 0; - player->secondjump = 0; - player->glidetime = 0; - player->homing = 0; - player->climbing = 0; - player->powers[pw_tailsfly] = 0; + //player->pflags &= ~(PF_); + + player->powers[pw_carry] = CR_NONE; player->onconveyor = 0; - player->skidtime = 0; + + //player->kartstuff[k_drift] = player->kartstuff[k_driftcharge] = 0; + player->trickpanel = 0; } // @@ -942,20 +494,22 @@ void P_ResetPlayer(player_t *player) // Gives rings to the player, and does any special things required. // Call this function when you want to increment the player's health. // + void P_GivePlayerRings(player_t *player, INT32 num_rings) { if (!player->mo) return; - if (G_BattleGametype()) // No rings in Battle Mode + if ((gametyperules & GTR_BUMPERS)) // No rings in Battle Mode return; - player->kartstuff[k_rings] += num_rings; + player->rings += num_rings; + //player->totalring += num_rings; // Used for GP lives later - if (player->kartstuff[k_rings] > 20) - player->kartstuff[k_rings] = 20; // Caps at 20 rings, sorry! - else if (player->kartstuff[k_rings] < -20) - player->kartstuff[k_rings] = -20; // Chaotix ring debt! + if (player->rings > 20) + player->rings = 20; // Caps at 20 rings, sorry! + else if (player->rings < -20) + player->rings = -20; // Chaotix ring debt! } // @@ -974,56 +528,12 @@ void P_GivePlayerLives(player_t *player, INT32 numlives) player->lives = 1; } -// -// P_DoSuperTransformation -// -// Transform into Super Sonic! -void P_DoSuperTransformation(player_t *player, boolean giverings) -{ - return; // SRB2kart - this is not a thing we need - player->powers[pw_super] = 1; - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC) && P_IsLocalPlayer(player)) - { - S_StopMusic(); - S_ChangeMusicInternal("supers", true); - } - - S_StartSound(NULL, sfx_supert); //let all players hear it -mattw_cfi - - // Transformation animation - //P_SetPlayerMobjState(player->mo, S_PLAY_SUPERTRANS1); - - player->mo->momx = player->mo->momy = player->mo->momz = 0; - - if (giverings) - { - player->mo->health = 51; - player->health = player->mo->health; - } - - // Just in case. - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC)) - { - player->powers[pw_extralife] = 0; - player->powers[pw_invulnerability] = 0; - player->powers[pw_sneakers] = 0; - } - - if (gametype != GT_COOP) - { - HU_SetCEchoFlags(0); - HU_SetCEchoDuration(5); - HU_DoCEcho(va("%s\\is now super.\\\\\\\\", player_names[player-players])); - } - - P_PlayerFlagBurst(player, false); -} // Adds to the player's score void P_AddPlayerScore(player_t *player, UINT32 amount) { //UINT32 oldscore; - if (!(G_BattleGametype())) + if (!((gametyperules & GTR_BUMPERS))) return; if (player->exiting) // srb2kart @@ -1036,22 +546,6 @@ void P_AddPlayerScore(player_t *player, UINT32 amount) player->marescore += amount; else player->marescore = MAXSCORE; - - // check for extra lives every 50000 pts - /*if (!ultimatemode && !modeattacking && player->score > oldscore && player->score % 50000 < amount && (gametype == GT_COMPETITION || gametype == GT_COOP)) - { - P_GivePlayerLives(player, (player->score/50000) - (oldscore/50000)); - P_PlayLivesJingle(player); - }*/ - - // In team match, all awarded points are incremented to the team's running score. - if (gametype == GT_TEAMMATCH) - { - if (player->ctfteam == 1) - redscore += amount; - else if (player->ctfteam == 2) - bluescore += amount; - } } // @@ -1064,22 +558,126 @@ void P_PlayLivesJingle(player_t *player) if (use1upSound) S_StartSound(NULL, sfx_oneup); - else if (mariomode) - S_StartSound(NULL, sfx_marioa); else { + P_PlayJingle(player, JT_1UP); if (player) player->powers[pw_extralife] = extralifetics + 1; - S_StopMusic(); // otherwise it won't restart if this is done twice in a row - S_ChangeMusicInternal("xtlife", false); + strlcpy(S_sfx[sfx_None].caption, "One-up", 7); + S_StartCaption(sfx_None, -1, extralifetics+1); } } +void P_PlayJingle(player_t *player, jingletype_t jingletype) +{ + const char *musname = jingleinfo[jingletype].musname; + UINT16 musflags = 0; + boolean looping = jingleinfo[jingletype].looping; + + char newmusic[7]; + strncpy(newmusic, musname, 7); +#ifdef HAVE_LUA_MUSICPLUS + if(LUAh_MusicJingle(jingletype, newmusic, &musflags, &looping)) + return; +#endif + newmusic[6] = 0; + + P_PlayJingleMusic(player, newmusic, musflags, looping, jingletype); +} + +// +// P_PlayJingleMusic +// +void P_PlayJingleMusic(player_t *player, const char *musname, UINT16 musflags, boolean looping, UINT16 status) +{ + // If gamestate != GS_LEVEL, always play the jingle (1-up intermission) + if (gamestate == GS_LEVEL && player && !P_IsLocalPlayer(player)) + return; + + S_RetainMusic(musname, musflags, looping, 0, status); + S_StopMusic(); + S_ChangeMusicInternal(musname, looping); +} + +boolean P_EvaluateMusicStatus(UINT16 status, const char *musname) +{ + // \todo lua hook + int i; + boolean result = false; + + for (i = 0; i < MAXPLAYERS; i++) + { + if (!P_IsLocalPlayer(&players[i])) + continue; + + switch(status) + { + case JT_1UP: // Extra life + result = (players[i].powers[pw_extralife] > 1); + break; + + case JT_SHOES: // Speed shoes + if (players[i].powers[pw_sneakers] > 1 && !players[i].powers[pw_super]) + { + //strlcpy(S_sfx[sfx_None].caption, "Speed shoes", 12); + //S_StartCaption(sfx_None, -1, players[i].powers[pw_sneakers]); + result = true; + } + else + result = false; + break; + + case JT_INV: // Invincibility + case JT_MINV: // Mario Invincibility + if (players[i].powers[pw_invulnerability] > 1) + { + //strlcpy(S_sfx[sfx_None].caption, "Invincibility", 14); + //S_StartCaption(sfx_None, -1, players[i].powers[pw_invulnerability]); + result = true; + } + else + result = false; + break; + + case JT_DROWN: // Drowning + result = (players[i].powers[pw_underwater] && players[i].powers[pw_underwater] <= 11*TICRATE + 1); + break; + + case JT_SUPER: // Super Sonic + result = (players[i].powers[pw_super]); + break; + + case JT_GOVER: // Game Over + result = (players[i].lives <= 0); + break; + + case JT_NIGHTSTIMEOUT: // NiGHTS Time Out (10 seconds) + case JT_SSTIMEOUT: + result = (players[i].nightstime && players[i].nightstime <= 10*TICRATE); + break; + + case JT_OTHER: // Other state + result = LUAh_ShouldJingleContinue(&players[i], musname); + break; + + case JT_NONE: // Null state + case JT_MASTER: // Main level music + default: + result = true; + } + + if (result) + break; + } + + return result; +} + void P_PlayRinglossSound(mobj_t *source) { if (source->player && K_GetShieldFromItem(source->player->kartstuff[k_itemtype]) != KSHIELD_NONE) S_StartSound(source, sfx_s1a3); // Shield hit (no ring loss) - else if (source->player && source->player->kartstuff[k_rings] <= 0) + else if (source->player && source->player->rings <= 0) S_StartSound(source, sfx_s1a6); // Ring debt (lessened ring loss) else S_StartSound(source, sfx_s1c6); // Normal ring loss sound @@ -1118,19 +716,19 @@ boolean P_EndingMusic(player_t *player) // Check for if this is valid or not if (r_splitscreen) { - if (!((players[displayplayers[0]].exiting || (players[displayplayers[0]].pflags & PF_TIMEOVER)) - || (players[displayplayers[1]].exiting || (players[displayplayers[1]].pflags & PF_TIMEOVER)) - || ((r_splitscreen < 2) && (players[displayplayers[2]].exiting || (players[displayplayers[2]].pflags & PF_TIMEOVER))) - || ((r_splitscreen < 3) && (players[displayplayers[3]].exiting || (players[displayplayers[3]].pflags & PF_TIMEOVER))))) + if (!((players[displayplayers[0]].exiting || (players[displayplayers[0]].pflags & PF_GAMETYPEOVER)) + || (players[displayplayers[1]].exiting || (players[displayplayers[1]].pflags & PF_GAMETYPEOVER)) + || ((r_splitscreen < 2) && (players[displayplayers[2]].exiting || (players[displayplayers[2]].pflags & PF_GAMETYPEOVER))) + || ((r_splitscreen < 3) && (players[displayplayers[3]].exiting || (players[displayplayers[3]].pflags & PF_GAMETYPEOVER))))) return false; bestlocalplayer = &players[displayplayers[0]]; - bestlocalpos = ((players[displayplayers[0]].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[displayplayers[0]].kartstuff[k_position]); + bestlocalpos = ((players[displayplayers[0]].pflags & PF_GAMETYPEOVER) ? MAXPLAYERS+1 : players[displayplayers[0]].kartstuff[k_position]); #define setbests(p) \ - if (((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]) < bestlocalpos) \ + if (((players[p].pflags & PF_GAMETYPEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]) < bestlocalpos) \ { \ bestlocalplayer = &players[p]; \ - bestlocalpos = ((players[p].pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]); \ + bestlocalpos = ((players[p].pflags & PF_GAMETYPEOVER) ? MAXPLAYERS+1 : players[p].kartstuff[k_position]); \ } setbests(displayplayers[1]); if (r_splitscreen > 1) @@ -1141,14 +739,14 @@ boolean P_EndingMusic(player_t *player) } else { - if (!(player->exiting || (player->pflags & PF_TIMEOVER))) + if (!(player->exiting || (player->pflags & PF_GAMETYPEOVER))) return false; bestlocalplayer = player; - bestlocalpos = ((player->pflags & PF_TIMEOVER) ? MAXPLAYERS+1 : player->kartstuff[k_position]); + bestlocalpos = ((player->pflags & PF_GAMETYPEOVER) ? MAXPLAYERS+1 : player->kartstuff[k_position]); } - if (G_RaceGametype() && bestlocalpos == MAXPLAYERS+1) + if ((gametyperules & GTR_CIRCUIT) && bestlocalpos == MAXPLAYERS+1) sprintf(buffer, "k*fail"); // F-Zero death results theme else { @@ -1162,9 +760,9 @@ boolean P_EndingMusic(player_t *player) S_SpeedMusic(1.0f); - if (G_RaceGametype()) + if ((gametyperules & GTR_CIRCUIT)) buffer[1] = 'r'; - else if (G_BattleGametype()) + else if ((gametyperules & GTR_BUMPERS)) { buffer[1] = 'b'; looping = false; @@ -1189,6 +787,8 @@ void P_RestoreMusic(player_t *player) S_SpeedMusic(1.0f); + // TO-DO: Use jingle system for Kart's stuff + // Event - HERE COMES A NEW CHALLENGER if (mapreset) { @@ -1255,7 +855,7 @@ void P_RestoreMusic(player_t *player) #if 0 // Event - Final Lap // Still works for GME, but disabled for consistency - if (G_RaceGametype() && player->laps >= (UINT8)(cv_numlaps.value)) + if ((gametyperules & GTR_CIRCUIT) && player->laps >= (UINT8)(cv_numlaps.value)) S_SpeedMusic(1.2f); #endif if (mapmusresume && cv_resume.value) @@ -1297,7 +897,7 @@ boolean P_IsObjectInGoop(mobj_t *mo) // boolean P_IsObjectOnGround(mobj_t *mo) { - if (P_IsObjectInGoop(mo)) + if (P_IsObjectInGoop(mo) && !(mo->player && mo->player->pflags & PF_BOUNCING)) { /* // It's a crazy hack that checking if you're on the ground @@ -1466,28 +1066,6 @@ void P_SetObjectMomZ(mobj_t *mo, fixed_t value, boolean relative) mo->momz = value; } -// -// P_GetPlayerHeight -// -// Returns the height -// of the player. -// -fixed_t P_GetPlayerHeight(player_t *player) -{ - return FixedMul(player->mo->info->height, player->mo->scale); -} - -// -// P_GetPlayerSpinHeight -// -// Returns the 'spin height' -// of the player. -// -fixed_t P_GetPlayerSpinHeight(player_t *player) -{ - return FixedMul(FixedMul(player->mo->info->height, player->mo->scale),2*FRACUNIT/3); -} - // // P_IsLocalPlayer // @@ -1498,23 +1076,10 @@ boolean P_IsLocalPlayer(player_t *player) { UINT8 i; - if (r_splitscreen > splitscreen) + for (i = 0; i <= r_splitscreen; i++) // DON'T skip P1 { - for (i = 0; i <= r_splitscreen; ++i) - { - if (player == &players[displayplayers[i]]) - return true; - } - } - else if (player == &players[consoleplayer]) - return true; - else if (splitscreen) - { - for (i = 1; i <= splitscreen; i++) // Skip P1 - { - if (player == &players[displayplayers[i]]) - return true; - } + if (player == &players[g_localplayers[i]]) + return true; } return false; @@ -1557,33 +1122,49 @@ void P_SpawnShieldOrb(player_t *player) I_Error("P_SpawnShieldOrb: player->mo is NULL!\n"); #endif + // SRB2Kart + // TODO: Make our shields use this system + + if (LUAh_ShieldSpawn(player)) + return; + if (player->powers[pw_shield] & SH_FORCE) - orbtype = MT_BLUEORB; + orbtype = MT_FORCE_ORB; else switch (player->powers[pw_shield] & SH_NOSTACK) { - case SH_JUMP: - orbtype = MT_WHITEORB; + case SH_WHIRLWIND: + orbtype = MT_WHIRLWIND_ORB; break; case SH_ATTRACT: - orbtype = MT_YELLOWORB; + orbtype = MT_ATTRACT_ORB; break; case SH_ELEMENTAL: - orbtype = MT_GREENORB; + orbtype = MT_ELEMENTAL_ORB; break; - case SH_BOMB: - orbtype = MT_BLACKORB; + case SH_ARMAGEDDON: + orbtype = MT_ARMAGEDDON_ORB; break; case SH_PITY: - orbtype = MT_PITYORB; + case SH_PINK: // PITY IN PINK + orbtype = MT_PITY_ORB; + break; + case SH_FLAMEAURA: + orbtype = MT_FLAMEAURA_ORB; + break; + case SH_BUBBLEWRAP: + orbtype = MT_BUBBLEWRAP_ORB; + break; + case SH_THUNDERCOIN: + orbtype = MT_THUNDERCOIN_ORB; break; default: return; } // blaze through the thinkers to see if an orb already exists! - for (th = thinkercap.next; th != &thinkercap; th = th->next) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) continue; shieldobj = (mobj_t *)th; @@ -1593,14 +1174,23 @@ void P_SpawnShieldOrb(player_t *player) } shieldobj = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, orbtype); + shieldobj->flags2 |= MF2_SHIELD; P_SetTarget(&shieldobj->target, player->mo); - shieldobj->color = (UINT8)shieldobj->info->painchance; + if ((player->powers[pw_shield] & SH_NOSTACK) == SH_PINK) + { + shieldobj->color = SKINCOLOR_PINK; + shieldobj->colorized = true; + } + else + shieldobj->color = (UINT16)shieldobj->info->painchance; + shieldobj->threshold = (player->powers[pw_shield] & SH_FORCE) ? SH_FORCE : (player->powers[pw_shield] & SH_NOSTACK); if (shieldobj->info->seestate) { ov = P_SpawnMobj(shieldobj->x, shieldobj->y, shieldobj->z, MT_OVERLAY); P_SetTarget(&ov->target, shieldobj); P_SetMobjState(ov, shieldobj->info->seestate); + P_SetTarget(&shieldobj->tracer, ov); } if (shieldobj->info->meleestate) { @@ -1617,7 +1207,7 @@ void P_SpawnShieldOrb(player_t *player) if (player->powers[pw_shield] & SH_FORCE) { //Copy and pasted from P_ShieldLook in p_mobj.c - shieldobj->movecount = (player->powers[pw_shield] & 0xFF); + shieldobj->movecount = (player->powers[pw_shield] & SH_FORCEHP); if (shieldobj->movecount < 1) { if (shieldobj->info->painstate) @@ -1628,6 +1218,56 @@ void P_SpawnShieldOrb(player_t *player) } } +// +// P_SwitchShield +// +// Handles the possibility of switching between +// the non-stack layer of shields thoroughly, +// then adds the desired one. +// +void P_SwitchShield(player_t *player, UINT16 shieldtype) +{ + boolean donthavealready; + + donthavealready = (shieldtype & SH_FORCE) + ? (!(player->powers[pw_shield] & SH_FORCE) || (player->powers[pw_shield] & SH_FORCEHP) < (shieldtype & ~SH_FORCE)) + : ((player->powers[pw_shield] & SH_NOSTACK) != shieldtype); + + if (donthavealready) + { + boolean stopshieldability = (shieldtype & SH_FORCE) + ? (!(player->powers[pw_shield] & SH_FORCE)) + : true; + + // Just in case. + if (stopshieldability && player->pflags & PF_SHIELDABILITY) + { + player->pflags &= ~(PF_SPINNING|PF_SHIELDABILITY); // They'll still have PF_THOKKED... + player->homing = 0; + } + + player->powers[pw_shield] = shieldtype|(player->powers[pw_shield] & SH_STACK); + P_SpawnShieldOrb(player); + + if (shieldtype & SH_PROTECTWATER) + { + if (player->powers[pw_underwater] && player->powers[pw_underwater] <= 12*TICRATE + 1) + { + player->powers[pw_underwater] = 0; + P_RestoreMusic(player); + } + else + player->powers[pw_underwater] = 0; + + if (player->powers[pw_spacetime] > 1) + { + player->powers[pw_spacetime] = 0; + P_RestoreMusic(player); + } + } + } +} + // // P_SpawnGhostMobj // @@ -1635,9 +1275,7 @@ void P_SpawnShieldOrb(player_t *player) // mobj_t *P_SpawnGhostMobj(mobj_t *mobj) { - mobj_t *ghost; - - ghost = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_GHOST); + mobj_t *ghost = P_SpawnMobj(mobj->x, mobj->y, mobj->z, MT_GHOST); P_SetScale(ghost, mobj->scale); ghost->destscale = mobj->scale; @@ -1651,12 +1289,9 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) ghost->color = mobj->color; ghost->colorized = mobj->colorized; // Kart: they should also be colorized if their origin is - if (mobj->player) - ghost->angle = mobj->player->frameangle; - else - ghost->angle = mobj->angle; - + ghost->angle = (mobj->player ? mobj->player->drawangle : mobj->angle); ghost->sprite = mobj->sprite; + ghost->sprite2 = mobj->sprite2; ghost->frame = mobj->frame; ghost->tics = -1; ghost->drawflags |= tr_trans50 << MFD_TRANSSHIFT; @@ -1677,6 +1312,14 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj) if (!(mobj->flags & MF_DONTENCOREMAP)) ghost->flags &= ~MF_DONTENCOREMAP; + if (mobj->player && mobj->player->followmobj) + { + mobj_t *ghost2 = P_SpawnGhostMobj(mobj->player->followmobj); + P_SetTarget(&ghost2->tracer, ghost); + P_SetTarget(&ghost->tracer, ghost2); + ghost2->flags2 |= (mobj->player->followmobj->flags2 & MF2_LINKDRAW); + } + return ghost; } @@ -1700,7 +1343,7 @@ void P_DoPlayerExit(player_t *player) K_PlayerLoseLife(player); } - if (G_RaceGametype()) // If in Race Mode, allow + if ((gametyperules & GTR_CIRCUIT)) // If in Race Mode, allow { player->exiting = raceexittime+2; K_KartUpdatePosition(player); @@ -1731,7 +1374,7 @@ void P_DoPlayerExit(player_t *player) if (P_CheckRacers()) player->exiting = raceexittime+1; } - else if (G_BattleGametype()) // Battle Mode exiting + else if ((gametyperules & GTR_BUMPERS)) // Battle Mode exiting { player->exiting = battleexittime+1; P_EndingMusic(player); @@ -1779,45 +1422,24 @@ void P_DoPlayerExit(player_t *player) demo.savebutton = leveltime; } -#define SPACESPECIAL 12 -boolean P_InSpaceSector(mobj_t *mo) // Returns true if you are in space +// +// P_PlayerHitFloor +// +// Handles player hitting floor surface. +// Returns whether to clip momz. +boolean P_PlayerHitFloor(player_t *player, boolean dorollstuff) { - sector_t *sector = mo->subsector->sector; - fixed_t topheight, bottomheight; + boolean clipmomz; - if (GETSECSPECIAL(sector->special, 1) == SPACESPECIAL) - return true; + (void)dorollstuff; - if (sector->ffloors) - { - ffloor_t *rover; + I_Assert(player->mo != NULL); - for (rover = sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) - continue; + clipmomz = !(P_CheckDeathPitCollide(player->mo)); - if (GETSECSPECIAL(rover->master->frontsector->special, 1) != SPACESPECIAL) - continue; -#ifdef ESLOPE - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : *rover->bottomheight; -#else - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; -#endif + // SRB2Kart: removed lots of really vanilla-specific code here - if (mo->z + (mo->height/2) > topheight) - continue; - - if (mo->z + (mo->height/2) < bottomheight) - continue; - - return true; - } - } - - return false; // No vacuum here, Captain! + return clipmomz; } boolean P_InQuicksand(mobj_t *mo) // Returns true if you are in quicksand @@ -1839,13 +1461,8 @@ boolean P_InQuicksand(mobj_t *mo) // Returns true if you are in quicksand if (!(rover->flags & FF_QUICKSAND)) continue; -#ifdef ESLOPE - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, mo->x, mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, mo->x, mo->y) : *rover->bottomheight; -#else - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; -#endif + topheight = P_GetFFloorTopZAt (rover, mo->x, mo->y); + bottomheight = P_GetFFloorBottomZAt(rover, mo->x, mo->y); if (mo->z + flipoffset > topheight) continue; @@ -1872,6 +1489,8 @@ static void P_CheckBustableBlocks(player_t *player) oldx = player->mo->x; oldy = player->mo->y; + // SRB2Kart TODO: make shatter blocks the default behavior, we don't need the hundreds of other types + P_UnsetThingPosition(player->mo); player->mo->x += player->mo->momx; player->mo->y += player->mo->momy; @@ -1891,26 +1510,16 @@ static void P_CheckBustableBlocks(player_t *player) { if (!(rover->flags & FF_EXISTS)) continue; - if ((rover->flags & FF_BUSTUP)/* && !rover->master->frontsector->crumblestate*/) + if ((rover->flags & FF_BUSTUP)/* && rover->master->frontsector->crumblestate == CRUMBLE_NONE*/) { - // If it's an FF_SPINBUST, you have to either be jumping, or coming down - // onto the top from a spin. - if (rover->flags & FF_SPINBUST && ((!(player->pflags & PF_JUMPED) && !(player->pflags & PF_SPINNING)) || (player->pflags & PF_STARTDASH))) + // If it's an FF_SHATTER, you can break it just by touching it. + if (rover->flags & FF_SHATTER) + goto bust; + + if (rover->flags & FF_STRONGBUST) continue; - // if it's not an FF_SHATTER, you must be spinning (and not jumping) - // or have Knuckles's abilities (or Super Sonic) - // ...or are drilling in NiGHTS (or Metal Sonic) - if (!(rover->flags & FF_SHATTER) && !(rover->flags & FF_SPINBUST) - && !((player->pflags & PF_SPINNING) && !(player->pflags & PF_JUMPED)) - && (/*player->charability != CA_GLIDEANDCLIMB &&*/ !player->powers[pw_super]) - && !(player->pflags & PF_DRILLING) && !metalrecording) - continue; - - // Only Knuckles can break this rock... - /*if (!(rover->flags & FF_SHATTER) && (rover->flags & FF_ONLYKNUX) && !(player->charability == CA_GLIDEANDCLIMB)) - continue;*/ - + bust: topheight = P_GetFOFTopZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); bottomheight = P_GetFOFBottomZ(player->mo, node->m_sector, rover, player->mo->x, player->mo->y, NULL); @@ -1960,7 +1569,7 @@ static void P_CheckBustableBlocks(player_t *player) //if (metalrecording) // G_RecordBustup(rover); - EV_CrumbleChain(node->m_sector, rover); + EV_CrumbleChain(NULL, rover); // node->m_sector // Run a linedef executor?? if (rover->master->flags & ML_EFFECT5) @@ -1972,6 +1581,7 @@ static void P_CheckBustableBlocks(player_t *player) } } bustupdone: + P_UnsetThingPosition(player->mo); player->mo->x = oldx; player->mo->y = oldy; @@ -1984,9 +1594,7 @@ static void P_CheckBouncySectors(player_t *player) fixed_t oldx; fixed_t oldy; fixed_t oldz; -#ifdef ESLOPE vector3_t momentum; -#endif oldx = player->mo->x; oldy = player->mo->y; @@ -2041,7 +1649,6 @@ static void P_CheckBouncySectors(player_t *player) { fixed_t newmom; -#ifdef ESLOPE pslope_t *slope; if (abs(oldz - topheight) < abs(oldz + player->mo->height - bottomheight)) { // Hit top slope = *rover->t_slope; @@ -2057,16 +1664,13 @@ static void P_CheckBouncySectors(player_t *player) P_ReverseQuantizeMomentumToSlope(&momentum, slope); newmom = momentum.z = -FixedMul(momentum.z,linedist)/2; -#else - newmom = -FixedMul(player->mo->momz,linedist); -#endif if (abs(newmom) < (linedist*2)) { goto bouncydone; } - if (!(rover->master->flags & ML_BOUNCY)) + if (!(rover->master->flags & ML_NOTBOUNCY)) { if (newmom > 0) { @@ -2077,12 +1681,11 @@ static void P_CheckBouncySectors(player_t *player) newmom = -8*FRACUNIT; } - if (newmom > P_GetPlayerHeight(player)/2) - newmom = P_GetPlayerHeight(player)/2; - else if (newmom < -P_GetPlayerHeight(player)/2) - newmom = -P_GetPlayerHeight(player)/2; + if (newmom > player->mo->height/2) + newmom = player->mo->height/2; + else if (newmom < -player->mo->height/2) + newmom = -player->mo->height/2; -#ifdef ESLOPE momentum.z = newmom*2; if (slope) @@ -2091,34 +1694,11 @@ static void P_CheckBouncySectors(player_t *player) player->mo->momx = momentum.x; player->mo->momy = momentum.y; player->mo->momz = momentum.z/2; -#else - player->mo->momz = newmom; -#endif - - if (player->pflags & PF_SPINNING) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= PF_JUMPED; - player->pflags |= PF_THOKKED; - } } else { player->mo->momx = -FixedMul(player->mo->momx,linedist); player->mo->momy = -FixedMul(player->mo->momy,linedist); - - if (player->pflags & PF_SPINNING) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= PF_JUMPED; - player->pflags |= PF_THOKKED; - } - } - - if ((player->pflags & PF_SPINNING) && player->speed < FixedMul(1<mo->scale) && player->mo->momz) - { - player->pflags &= ~PF_SPINNING; - player->pflags |= PF_JUMPED; } goto bouncydone; @@ -2150,13 +1730,8 @@ static void P_CheckQuicksand(player_t *player) if (!(rover->flags & FF_QUICKSAND)) continue; -#ifdef ESLOPE - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; -#else - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; -#endif + topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); + bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); if (topheight >= player->mo->z && bottomheight < player->mo->z + player->mo->height) { @@ -2172,6 +1747,9 @@ static void P_CheckQuicksand(player_t *player) if (player->mo->z + player->mo->height >= ceilingheight) player->mo->z = ceilingheight - player->mo->height; + + if (player->mo->momz <= 0) + P_PlayerHitFloor(player, false); } else { @@ -2181,6 +1759,9 @@ static void P_CheckQuicksand(player_t *player) if (player->mo->z <= floorheight) player->mo->z = floorheight; + + if (player->mo->momz >= 0) + P_PlayerHitFloor(player, false); } friction = abs(rover->master->v1->y - rover->master->v2->y)>>6; @@ -2191,142 +1772,6 @@ static void P_CheckQuicksand(player_t *player) } } -// -// P_CheckSneakerAndLivesTimer -// -// Restores music from sneaker and life fanfares -// -/* // SRB2kart - Can't drown. -static void P_CheckSneakerAndLivesTimer(player_t *player) -{ - if ((player->powers[pw_underwater] <= 11*TICRATE + 1) - && (player->powers[pw_underwater] > 1)) - return; // don't restore music if drowning music is playing - - if (player->powers[pw_extralife] == 1) // Extra Life! - P_RestoreMusic(player); - - //if (player->powers[pw_sneakers] == 1) // SRB2kart - // P_RestoreMusic(player); -} -*/ - -// -// P_CheckUnderwaterAndSpaceTimer -// -// Restores music from underwater and space warnings, and handles number generation -// -/* // SRB2kart - Can't drown. -static void P_CheckUnderwaterAndSpaceTimer(player_t *player) -{ - fixed_t height; - mobj_t *numbermobj = NULL; - - if (player->mo->eflags & MFE_VERTICALFLIP) - height = player->mo->z - FixedMul(8*FRACUNIT - mobjinfo[MT_DROWNNUMBERS].height, player->mo->scale); - else - height = player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, player->mo->scale); - - if (player->powers[pw_underwater] == 11*TICRATE + 1 || player->powers[pw_spacetime] == 11*TICRATE + 1) - { - numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS); - P_SetMobjState(numbermobj, numbermobj->info->spawnstate+5); - } - else if (player->powers[pw_underwater] == 9*TICRATE + 1 || player->powers[pw_spacetime] == 9*TICRATE + 1) - { - numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS); - P_SetMobjState(numbermobj, numbermobj->info->spawnstate+4); - } - else if (player->powers[pw_underwater] == 7*TICRATE + 1 || player->powers[pw_spacetime] == 7*TICRATE + 1) - { - numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS); - P_SetMobjState(numbermobj, numbermobj->info->spawnstate+3); - } - else if (player->powers[pw_underwater] == 5*TICRATE + 1 || player->powers[pw_spacetime] == 5*TICRATE + 1) - { - numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS); - P_SetMobjState(numbermobj, numbermobj->info->spawnstate+2); - } - else if (player->powers[pw_underwater] == 3*TICRATE + 1 || player->powers[pw_spacetime] == 3*TICRATE + 1) - { - numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS); - P_SetMobjState(numbermobj, numbermobj->info->spawnstate+1); - } - else if (player->powers[pw_underwater] == 1*TICRATE + 1 || player->powers[pw_spacetime] == 1*TICRATE + 1) - { - numbermobj = P_SpawnMobj(player->mo->x, player->mo->y, height, MT_DROWNNUMBERS); - //P_SetMobjState(numbermobj, numbermobj->info->spawnstate+0); - } - // Underwater timer runs out - else if (player->powers[pw_underwater] == 1) - { - mobj_t *killer; - - if ((netgame || multiplayer) && P_IsLocalPlayer(player)) - S_ChangeMusic(mapmusname, mapmusflags, true); - - killer = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_NULL); - killer->threshold = 42; // Special flag that it was drowning which killed you. - P_DamageMobj(player->mo, killer, killer, 10000); - } - else if (player->powers[pw_spacetime] == 1) - { - if ((netgame || multiplayer) && P_IsLocalPlayer(player)) - S_ChangeMusic(mapmusname, mapmusflags, true); - - P_DamageMobj(player->mo, NULL, NULL, 10000); - } - - if (numbermobj) - { - P_SetTarget(&numbermobj->target, player->mo); - numbermobj->threshold = 40; - S_StartSound(player->mo, sfx_dwnind); - numbermobj->destscale = player->mo->scale; - P_SetScale(numbermobj, player->mo->scale); - } - - if (!(player->mo->eflags & MFE_UNDERWATER) && player->powers[pw_underwater]) - { - if (player->powers[pw_underwater] <= 12*TICRATE + 1) - P_RestoreMusic(player); - - player->powers[pw_underwater] = 0; - } - - if (player->powers[pw_spacetime] > 1 && !P_InSpaceSector(player->mo)) - { - P_RestoreMusic(player); - player->powers[pw_spacetime] = 0; - } - - // Underwater audio cues - if (P_IsLocalPlayer(player)) - { - if (player->powers[pw_underwater] == 11*TICRATE + 1 - && player == &players[consoleplayer]) - { - S_StopMusic(); - S_ChangeMusicInternal("drown", false); - } - - if (player->powers[pw_underwater] == 25*TICRATE + 1) - S_StartSound(NULL, sfx_wtrdng); - else if (player->powers[pw_underwater] == 20*TICRATE + 1) - S_StartSound(NULL, sfx_wtrdng); - else if (player->powers[pw_underwater] == 15*TICRATE + 1) - S_StartSound(NULL, sfx_wtrdng); - } - - if (player->exiting) - { - if (player->powers[pw_underwater] > 1) - player->powers[pw_underwater] = 0; - - player->powers[pw_spacetime] = 0; - } -}*/ - // // P_CheckInvincibilityTimer // @@ -2337,44 +1782,18 @@ static void P_CheckInvincibilityTimer(player_t *player) if (!player->powers[pw_invulnerability] && !player->kartstuff[k_invincibilitytimer]) return; - //if (mariomode && !player->powers[pw_super]) // SRB2kart - player->mo->color = (UINT8)(1 + (leveltime % (MAXSKINCOLORS-1))); - /*if (leveltime % (TICRATE/7) == 0) - { - mobj_t *sparkle = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_IVSP); - sparkle->destscale = player->mo->scale; - P_SetScale(sparkle, player->mo->scale); - }*/ + player->mo->color = (UINT16)(SKINCOLOR_PINK + (leveltime % (numskincolors - SKINCOLOR_PINK))); // Resume normal music stuff. if (player->powers[pw_invulnerability] == 1 || player->kartstuff[k_invincibilitytimer] == 1) { if (!player->powers[pw_super]) { - //if (mariomode) - { - //if (player->powers[pw_shield] & SH_FIREFLOWER) - //{ - // player->mo->color = SKINCOLOR_WHITE; - // G_GhostAddColor((INT32) (player - players), GHC_FIREFLOWER); - //} - //else - { - player->mo->color = player->skincolor; - G_GhostAddColor((INT32) (player - players), GHC_NORMAL); - } - } - - // If you had a shield, restore its visual significance - P_SpawnShieldOrb(player); + player->mo->color = player->skincolor; + G_GhostAddColor((INT32) (player - players), GHC_NORMAL); } - /*if ((player->powers[pw_underwater] <= 11*TICRATE + 1) - && (player->powers[pw_underwater] > 1)) - return; // don't restore music if drowning music is playing - - if (!player->powers[pw_super] || (mapheaderinfo[gamemap-1]->levelflags & LF_NOSSMUSIC))*/ - P_RestoreMusic(player); + P_RestoreMusic(player); } } @@ -2385,1660 +1804,67 @@ static void P_CheckInvincibilityTimer(player_t *player) // static void P_DoBubbleBreath(player_t *player) { - fixed_t zh; + fixed_t x = player->mo->x; + fixed_t y = player->mo->y; + fixed_t z = player->mo->z; mobj_t *bubble = NULL; - if (player->mo->eflags & MFE_VERTICALFLIP) - zh = player->mo->z + player->mo->height - FixedDiv(player->mo->height,5*(FRACUNIT/4)); - else - zh = player->mo->z + FixedDiv(player->mo->height,5*(FRACUNIT/4)); - - if (!(player->mo->eflags & MFE_UNDERWATER) || ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL && !(player->pflags & PF_NIGHTSMODE)) || player->spectator) + if (!(player->mo->eflags & MFE_UNDERWATER) || (player->powers[pw_shield] & SH_PROTECTWATER) || player->spectator) return; - if (P_RandomChance(FRACUNIT/16)) - bubble = P_SpawnMobj(player->mo->x, player->mo->y, zh, MT_SMALLBUBBLE); - else if (P_RandomChance(3*FRACUNIT/256)) - bubble = P_SpawnMobj(player->mo->x, player->mo->y, zh, MT_MEDIUMBUBBLE); + if (player->charflags & SF_MACHINE) + { + if (player->powers[pw_underwater] && P_RandomChance((128-(player->powers[pw_underwater]/4))*FRACUNIT/256)) + { + fixed_t r = player->mo->radius>>FRACBITS; + x += (P_RandomRange(r, -r)<mo->height>>FRACBITS)<mo->eflags & MFE_VERTICALFLIP) + z += player->mo->height - FixedDiv(player->mo->height,5*(FRACUNIT/4)); + else + z += FixedDiv(player->mo->height,5*(FRACUNIT/4)); + + if (P_RandomChance(FRACUNIT/16)) + bubble = P_SpawnMobj(x, y, z, MT_SMALLBUBBLE); + else if (P_RandomChance(3*FRACUNIT/256)) + bubble = P_SpawnMobj(x, y, z, MT_MEDIUMBUBBLE); + } + if (bubble) { bubble->threshold = 42; bubble->destscale = player->mo->scale; P_SetScale(bubble, bubble->destscale); } - - if (player->pflags & PF_NIGHTSMODE) // NiGHTS Super doesn't spawn flight bubbles - return; - - // Tails stirs up the water while flying in it - /*if (player->powers[pw_tailsfly] && (leveltime & 1) && player->charability != CA_SWIM) - { - fixed_t radius = (3*player->mo->radius)>>1; - angle_t fa = ((leveltime%45)*FINEANGLES/8) & FINEMASK; - fixed_t stirwaterx = FixedMul(FINECOSINE(fa),radius); - fixed_t stirwatery = FixedMul(FINESINE(fa),radius); - fixed_t stirwaterz; - - if (player->mo->eflags & MFE_VERTICALFLIP) - stirwaterz = player->mo->z + player->mo->height - FixedDiv(player->mo->height,3*FRACUNIT/2); - else - stirwaterz = player->mo->z + FixedDiv(player->mo->height,3*FRACUNIT/2); - - bubble = P_SpawnMobj( - player->mo->x + stirwaterx, - player->mo->y + stirwatery, - stirwaterz, MT_SMALLBUBBLE); - bubble->destscale = player->mo->scale; - P_SetScale(bubble,bubble->destscale); - - bubble = P_SpawnMobj( - player->mo->x - stirwaterx, - player->mo->y - stirwatery, - stirwaterz, MT_SMALLBUBBLE); - bubble->destscale = player->mo->scale; - P_SetScale(bubble,bubble->destscale); - }*/ } -// -// P_DoPlayerHeadSigns -// -// Spawns "IT" and "GOT FLAG" signs for Tag and CTF respectively -// -static void P_DoPlayerHeadSigns(player_t *player) -{ - if (G_TagGametype()) - { - // If you're "IT", show a big "IT" over your head for others to see. - if (player->pflags & PF_TAGIT) - { - if (!P_IsDisplayPlayer(player)) // Don't display it on your own view. - { - if (!(player->mo->eflags & MFE_VERTICALFLIP)) - P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height, MT_TAG); - else - P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z - mobjinfo[MT_TAG].height, MT_TAG)->eflags |= MFE_VERTICALFLIP; - } - } - } - else if (gametype == GT_CTF) - { - if (player->gotflag & (GF_REDFLAG|GF_BLUEFLAG)) // If you have the flag (duh). - { - // Spawn a got-flag message over the head of the player that - // has it (but not on your own screen if you have the flag). - if (splitscreen || player != &players[consoleplayer]) - { - if (player->gotflag & GF_REDFLAG) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP)) - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, MT_GOTFLAG); - else - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+player->mo->height-P_GetPlayerHeight(player)-mobjinfo[MT_GOTFLAG].height-FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, MT_GOTFLAG)->eflags |= MFE_VERTICALFLIP; - } - if (player->gotflag & GF_BLUEFLAG) - { - if (!(player->mo->eflags & MFE_VERTICALFLIP)) - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+P_GetPlayerHeight(player)+FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, MT_GOTFLAG2); - else - P_SpawnMobj(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, - player->mo->z+player->mo->height-P_GetPlayerHeight(player)-mobjinfo[MT_GOTFLAG2].height-FixedMul(16*FRACUNIT, player->mo->scale)+player->mo->momz, MT_GOTFLAG2)->eflags |= MFE_VERTICALFLIP; - } - } - } - } -} - -// -// P_DoClimbing -// -// Handles player climbing -// -/* -static void P_DoClimbing(player_t *player) // SRB2kart - unused -{ - return; // SRB2kart - don't need - ticcmd_t *cmd = &player->cmd; - fixed_t platx; - fixed_t platy; - subsector_t *glidesector; - //boolean climb = true; // SRB2kart - unused - - platx = P_ReturnThrustX(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); - platy = P_ReturnThrustY(player->mo, player->mo->angle, player->mo->radius + FixedMul(8*FRACUNIT, player->mo->scale)); - - glidesector = R_IsPointInSubsector(player->mo->x + platx, player->mo->y + platy); - - if (!glidesector || glidesector->sector != player->mo->subsector->sector) - { - boolean floorclimb = false; - //boolean thrust = false; // SRB2kart - unused - //boolean boostup = false; // SRB2kart - unused - //boolean skyclimber = false; // SRB2kart - unused - fixed_t floorheight, ceilingheight; // ESLOPE - - if (!glidesector) - floorclimb = true; - else - { -#ifdef ESLOPE - floorheight = glidesector->sector->f_slope ? P_GetZAt(glidesector->sector->f_slope, player->mo->x, player->mo->y) - : glidesector->sector->floorheight; - ceilingheight = glidesector->sector->c_slope ? P_GetZAt(glidesector->sector->c_slope, player->mo->x, player->mo->y) - : glidesector->sector->ceilingheight; -#else - floorheight = glidesector->sector->floorheight; - ceilingheight = glidesector->sector->ceilingheight; -#endif - - if (glidesector->sector->ffloors) - { - ffloor_t *rover; - fixed_t topheight, bottomheight; // ESLOPE - - for (rover = glidesector->sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) - continue; - - floorclimb = true; - -#ifdef ESLOPE - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; -#else - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; -#endif - - // Only supports rovers that are moving like an 'elevator', not just the top or bottom. - if (rover->master->frontsector->floorspeed && rover->master->frontsector->ceilspeed == 42) - { - if ((!(player->mo->eflags & MFE_VERTICALFLIP) && (bottomheight < player->mo->z+player->mo->height) - && (topheight >= player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale))) - || ((player->mo->eflags & MFE_VERTICALFLIP) && (topheight > player->mo->z) - && (bottomheight <= player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale)))) - { - if (cmd->forwardmove != 0) - player->mo->momz += rover->master->frontsector->floorspeed; - else - { - player->mo->momz = rover->master->frontsector->floorspeed; - climb = false; - } - } - } - - // Gravity is flipped, so the comments are, too. - if (player->mo->eflags & MFE_VERTICALFLIP) - { - // Trying to climb down past the bottom of the FOF - if ((topheight >= player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) >= topheight)) - { - fixed_t bottomheight2; - ffloor_t *roverbelow; - boolean foundfof = false; - floorclimb = true; - boostup = false; - - // Is there a FOF directly below this one that we can move onto? - for (roverbelow = glidesector->sector->ffloors; roverbelow; roverbelow = roverbelow->next) - { - if (!(roverbelow->flags & FF_EXISTS) || !(roverbelow->flags & FF_BLOCKPLAYER) || (roverbelow->flags & FF_BUSTUP)) - continue; - - if (roverbelow == rover) - continue; - -#ifdef ESLOPE - bottomheight2 = *roverbelow->b_slope ? P_GetZAt(*roverbelow->b_slope, player->mo->x, player->mo->y) : *roverbelow->bottomheight; -#else - bottomheight2 = *roverbelow->bottomheight; -#endif - - if (bottomheight2 < topheight + FixedMul(16*FRACUNIT, player->mo->scale)) - foundfof = true; - } - - if (!foundfof) - player->mo->momz = 0; - } - - // Below the FOF - if (topheight <= player->mo->z) - { - floorclimb = false; - boostup = false; - thrust = false; - } - - // Above the FOF - if (bottomheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale)) - { - floorclimb = false; - thrust = true; - boostup = true; - } - } - else - { - // Trying to climb down past the bottom of a FOF - if ((bottomheight <= player->mo->z) && ((player->mo->z + player->mo->momz) <= bottomheight)) - { - fixed_t topheight2; - ffloor_t *roverbelow; - boolean foundfof = false; - floorclimb = true; - boostup = false; - - // Is there a FOF directly below this one that we can move onto? - for (roverbelow = glidesector->sector->ffloors; roverbelow; roverbelow = roverbelow->next) - { - if (!(roverbelow->flags & FF_EXISTS) || !(roverbelow->flags & FF_BLOCKPLAYER) || (roverbelow->flags & FF_BUSTUP)) - continue; - - if (roverbelow == rover) - continue; - -#ifdef ESLOPE - topheight2 = *roverbelow->t_slope ? P_GetZAt(*roverbelow->t_slope, player->mo->x, player->mo->y) : *roverbelow->topheight; -#else - topheight2 = *roverbelow->topheight; -#endif - - if (topheight2 > bottomheight - FixedMul(16*FRACUNIT, player->mo->scale)) - foundfof = true; - } - - if (!foundfof) - player->mo->momz = 0; - } - - // Below the FOF - if (bottomheight >= player->mo->z + player->mo->height) - { - floorclimb = false; - boostup = false; - thrust = false; - } - - // Above the FOF - if (topheight < player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale)) - { - floorclimb = false; - thrust = true; - boostup = true; - } - } - - if (floorclimb) - { - if (rover->flags & FF_CRUMBLE && !(netgame && player->spectator)) - EV_StartCrumble(rover->master->frontsector, rover, (rover->flags & FF_FLOATBOB), player, rover->alpha, !(rover->flags & FF_NORETURN)); - break; - } - } - } - - // Gravity is flipped, so are comments. - if (player->mo->eflags & MFE_VERTICALFLIP) - { - // Trying to climb down past the upper texture area - if ((floorheight >= player->mo->z + player->mo->height) && ((player->mo->z + player->mo->height + player->mo->momz) >= floorheight)) - { - boolean foundfof = false; - floorclimb = true; - - // Is there a FOF directly below that we can move onto? - if (glidesector->sector->ffloors) - { - fixed_t bottomheight; - ffloor_t *rover; - for (rover = glidesector->sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) - continue; - -#ifdef ESLOPE - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; -#else - bottomheight = *rover->bottomheight; -#endif - - if (bottomheight < floorheight + FixedMul(16*FRACUNIT, player->mo->scale)) - { - foundfof = true; - break; - } - } - } - - if (!foundfof) - player->mo->momz = 0; - } - - // Reached the top of the lower texture area - if (!floorclimb && ceilingheight > player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale) - && (glidesector->sector->ceilingpic == skyflatnum || floorheight < (player->mo->z - FixedMul(8*FRACUNIT, player->mo->scale)))) - { - thrust = true; - boostup = true; - // Play climb-up animation here - } - } - else - { - // Trying to climb down past the upper texture area - if ((ceilingheight <= player->mo->z) && ((player->mo->z + player->mo->momz) <= ceilingheight)) - { - boolean foundfof = false; - floorclimb = true; - - // Is there a FOF directly below that we can move onto? - if (glidesector->sector->ffloors) - { - fixed_t topheight; - ffloor_t *rover; - for (rover = glidesector->sector->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_BLOCKPLAYER) || (rover->flags & FF_BUSTUP)) - continue; - -#ifdef ESLOPE - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; -#else - topheight = *rover->topheight; -#endif - - if (topheight > ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale)) - { - foundfof = true; - break; - } - } - } - - if (!foundfof) - player->mo->momz = 0; - } - - // Allow climbing from a FOF or lower texture onto the upper texture and vice versa. - if (player->mo->z > ceilingheight - FixedMul(16*FRACUNIT, player->mo->scale)) - { - floorclimb = true; - thrust = false; - boostup = false; - } - - // Reached the top of the lower texture area - if (!floorclimb && floorheight < player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale) - && (glidesector->sector->ceilingpic == skyflatnum || ceilingheight > (player->mo->z + player->mo->height + FixedMul(8*FRACUNIT, player->mo->scale)))) - { - thrust = true; - boostup = true; - // Play climb-up animation here - } - } - - // Trying to climb on the sky - if ((ceilingheight < player->mo->z) && glidesector->sector->ceilingpic == skyflatnum) - { - skyclimber = true; - } - - // Climbing on the lower texture area? - if ((!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + FixedMul(16*FRACUNIT, player->mo->scale) < floorheight) - || ((player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + player->mo->height <= floorheight)) - { - floorclimb = true; - - if (glidesector->sector->floorspeed) - { - if (cmd->forwardmove != 0) - player->mo->momz += glidesector->sector->floorspeed; - else - { - player->mo->momz = glidesector->sector->floorspeed; - climb = false; - } - } - } - // Climbing on the upper texture area? - else if ((!(player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z >= ceilingheight) - || ((player->mo->eflags & MFE_VERTICALFLIP) && player->mo->z + player->mo->height - FixedMul(16*FRACUNIT, player->mo->scale) > ceilingheight)) - { - floorclimb = true; - - if (glidesector->sector->ceilspeed) - { - if (cmd->forwardmove != 0) - player->mo->momz += glidesector->sector->ceilspeed; - else - { - player->mo->momz = glidesector->sector->ceilspeed; - climb = false; - } - } - } - } - - if (player->lastsidehit != -1 && player->lastlinehit != -1) - { - thinker_t *think; - scroll_t *scroller; - angle_t sideangle; - fixed_t dx, dy; - - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function.acp1 != (actionf_p1)T_Scroll) - continue; - - scroller = (scroll_t *)think; - - if (scroller->type != sc_side) - continue; - - if (scroller->affectee != player->lastsidehit) - continue; - - if (scroller->accel) - { - dx = scroller->vdx; - dy = scroller->vdy; - } - else - { - dx = scroller->dx; - dy = scroller->dy; - } - - if (cmd->forwardmove != 0) - { - player->mo->momz += dy; - climb = true; - } - else - { - player->mo->momz = dy; - climb = false; - } - - sideangle = R_PointToAngle2(lines[player->lastlinehit].v2->x,lines[player->lastlinehit].v2->y,lines[player->lastlinehit].v1->x,lines[player->lastlinehit].v1->y); - - if (cmd->sidemove != 0) - { - P_Thrust(player->mo, sideangle, dx); - climb = true; - } - else - { - P_InstaThrust(player->mo, sideangle, dx); - climb = false; - } - } - } - - if (cmd->sidemove != 0 || cmd->forwardmove != 0) - climb = true; - else - climb = false; - - if (player->climbing && climb && (player->mo->momx || player->mo->momy || player->mo->momz) - && !(player->mo->state >= &states[S_PLAY_CLIMB2] && player->mo->state <= &states[S_PLAY_CLIMB5])) - P_SetPlayerMobjState(player->mo, S_PLAY_CLIMB2); - else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && player->mo->state != &states[S_PLAY_CLIMB1]) - P_SetPlayerMobjState(player->mo, S_PLAY_CLIMB1); - - if (!floorclimb) - { - if (boostup) - P_SetObjectMomZ(player->mo, 2*FRACUNIT, true); - if (thrust) - P_InstaThrust(player->mo, player->mo->angle, FixedMul(4*FRACUNIT, player->mo->scale)); // Lil' boost up. - - player->climbing = 0; - player->pflags |= PF_JUMPED; - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } - - if (skyclimber) - { - player->climbing = 0; - player->pflags |= PF_JUMPED; - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } - } - else - { - player->climbing = 0; - player->pflags |= PF_JUMPED; - //P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } - - if (cmd->sidemove != 0 || cmd->forwardmove != 0) - climb = true; - else - climb = false; - - if (player->climbing && climb && (player->mo->momx || player->mo->momy || player->mo->momz) - && !(player->mo->state >= &states[S_PLAY_CLIMB2] && player->mo->state <= &states[S_PLAY_CLIMB5])) - P_SetPlayerMobjState(player->mo, S_PLAY_CLIMB2); - else if ((!(player->mo->momx || player->mo->momy || player->mo->momz) || !climb) && player->mo->state != &states[S_PLAY_CLIMB1]) - P_SetPlayerMobjState(player->mo, S_PLAY_CLIMB1); - - if (cmd->buttons & BT_BRAKE && !(player->pflags & PF_JUMPSTASIS)) - { - player->climbing = 0; - player->pflags |= PF_JUMPED; - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - P_SetObjectMomZ(player->mo, 4*FRACUNIT, false); - P_InstaThrust(player->mo, player->mo->angle, FixedMul(-4*FRACUNIT, player->mo->scale)); - } - - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; - - if (player->climbing == 0) - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - - - if (player->climbing && P_IsObjectOnGround(player->mo)) - { - P_ResetPlayer(player); - P_SetPlayerMobjState(player->mo, S_KART_STILL1); // SRB2kart - } -} - -// -// PIT_CheckSolidsTeeter -// AKA: PIT_HacksToStopPlayersTeeteringOnGargoyles -// - -static mobj_t *teeterer; // the player checking for teetering -static boolean solidteeter; // saves whether the player can teeter on this or not -static fixed_t highesttop; // highest floor found so far -// reserved for standing on multiple objects -static boolean couldteeter; -static fixed_t teeterxl, teeterxh; -static fixed_t teeteryl, teeteryh; - -static boolean PIT_CheckSolidsTeeter(mobj_t *thing) // SRB2kart - unused. -{ - fixed_t blockdist; - fixed_t tiptop = FixedMul(MAXSTEPMOVE, mapobjectscale); - fixed_t thingtop = thing->z + thing->height; - fixed_t teeterertop = teeterer->z + teeterer->height; - - if (!teeterer || !thing) - return true; - - if (!(thing->flags & MF_SOLID)) - return true; - - if (thing->flags & MF_NOCLIP) - return true; - - if (thing == teeterer) - return true; - - if (thing->player && cv_tailspickup.value && gametype != GT_HIDEANDSEEK) - return true; - - blockdist = teeterer->radius + thing->radius; - - if (abs(thing->x - teeterer->x) >= blockdist || abs(thing->y - teeterer->y) >= blockdist) - return true; // didn't hit it - - if (teeterer->eflags & MFE_VERTICALFLIP) - { - if (thingtop < teeterer->z) - return true; - if (thing->z > highesttop) - return true; - highesttop = thing->z; - if (thing->z > teeterertop + tiptop) - { - solidteeter = true; - return true; - } - } - else - { - if (thing->z > teeterertop) - return true; - if (thingtop < highesttop) - return true; - highesttop = thingtop; - if (thingtop < teeterer->z - tiptop) - { - solidteeter = true; - return true; - } - } - - // are you standing on this? - if ((teeterer->eflags & MFE_VERTICALFLIP && thing->z - FixedMul(FRACUNIT, teeterer->scale) == teeterertop) - || (!(teeterer->eflags & MFE_VERTICALFLIP) && thingtop + FixedMul(FRACUNIT, teeterer->scale) == teeterer->z)) - { - fixed_t teeterdist = thing->radius - FixedMul(5*FRACUNIT, teeterer->scale); - // how far are you from the edge? - if (abs(teeterer->x - thing->x) > teeterdist || abs(teeterer->y - thing->y) > teeterdist) - { - if (couldteeter) // player is standing on another object already, see if we can stand on both and not teeter! - { - if (thing->x - teeterdist < teeterxl) - teeterxl = thing->x - teeterdist; - if (thing->x + teeterdist > teeterxh) - teeterxh = thing->x + teeterdist; - if (thing->y - teeterdist < teeteryl) - teeteryl = thing->y - teeterdist; - if (thing->y + teeterdist > teeteryh) - teeteryh = thing->y + teeterdist; - - if (teeterer->x < teeterxl) - return true; - if (teeterer->x > teeterxh) - return true; - if (teeterer->y < teeteryl) - return true; - if (teeterer->y > teeteryh) - return true; - - solidteeter = false; // you can stop teetering now! - couldteeter = false; // just in case... - return false; - } - else - { - // too far! don't change teeter status though - // save teeter x/y limits to bring up later - teeterxl = thing->x - teeterdist; - teeterxh = thing->x + teeterdist; - teeteryl = thing->y - teeterdist; - teeteryh = thing->y + teeterdist; - } - couldteeter = true; - return true; - } - solidteeter = false; - couldteeter = false; - return false; // you're definitely not teetering, that's the end of the matter - } - solidteeter = false; - return true; // you're not teetering but it's not neccessarily over, YET -} -*/ - -// -// P_DoTeeter -// -// Handles player teetering -// -/* -static void P_DoTeeter(player_t *player) // SRB2kart - unused. -{ - return; // SRB2kart - don't need - boolean teeter = false; - boolean roverfloor; // solid 3d floors? - fixed_t floorheight, ceilingheight; - fixed_t topheight, bottomheight; // for 3d floor usage - const fixed_t tiptop = FixedMul(MAXSTEPMOVE, mapobjectscale); // Distance you have to be above the ground in order to teeter. - - if (player->mo->standingslope && player->mo->standingslope->zdelta >= (FRACUNIT/2)) // Always teeter if the slope is too steep. - teeter = true; - else // Let's do some checks... - { - UINT8 i; - sector_t *sec; - fixed_t highestceilingheight = INT32_MIN; - fixed_t lowestfloorheight = INT32_MAX; - - teeter = false; - roverfloor = false; - for (i = 0; i < 4; i++) - { - ffloor_t *rover; - -#define xsign ((i & 1) ? -1 : 1) // 0 -> 1 | 1 -> -1 | 2 -> 1 | 3 -> -1 -#define ysign ((i & 2) ? 1 : -1) // 0 -> 1 | 1 -> 1 | 2 -> -1 | 3 -> -1 - fixed_t checkx = player->mo->x + (xsign*FixedMul(5*FRACUNIT, player->mo->scale)); - fixed_t checky = player->mo->y + (ysign*FixedMul(5*FRACUNIT, player->mo->scale)); -#undef xsign -#undef ysign - - sec = R_PointInSubsector(checkx, checky)->sector; - - ceilingheight = sec->ceilingheight; - floorheight = sec->floorheight; -#ifdef ESLOPE - if (sec->c_slope) - ceilingheight = P_GetZAt(sec->c_slope, checkx, checky); - if (sec->f_slope) - floorheight = P_GetZAt(sec->f_slope, checkx, checky); -#endif - highestceilingheight = (ceilingheight > highestceilingheight) ? ceilingheight : highestceilingheight; - lowestfloorheight = (floorheight < lowestfloorheight) ? floorheight : lowestfloorheight; - - if (!(sec->ffloors)) - continue; // move on to the next subsector - - for (rover = sec->ffloors; rover; rover = rover->next) - { - if (!(rover->flags & FF_EXISTS)) continue; - -#ifdef ESLOPE - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; -#else - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; -#endif - - if (P_CheckSolidLava(player->mo, rover)) - ; - else if (!(rover->flags & FF_BLOCKPLAYER || rover->flags & FF_QUICKSAND)) - continue; // intangible 3d floor - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if (bottomheight > ceilingheight) // Above the ceiling - continue; - - if (bottomheight > player->mo->z + player->mo->height + tiptop - || (topheight < player->mo->z - && player->mo->z + player->mo->height < ceilingheight - tiptop)) - { - teeter = true; - roverfloor = true; - } - else - { - teeter = false; - roverfloor = true; - break; - } - } - else - { - if (topheight < floorheight) // Below the floor - continue; - - if (topheight < player->mo->z - tiptop - || (bottomheight > player->mo->z + player->mo->height - && player->mo->z > floorheight + tiptop)) - { - teeter = true; - roverfloor = true; - } - else - { - teeter = false; - roverfloor = true; - break; - } - } - } - break; // break out of loop now, we're done - } - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if (!teeter && !roverfloor && (highestceilingheight > player->mo->ceilingz + tiptop)) - teeter = true; - } - else - { - if (!teeter && !roverfloor && (lowestfloorheight < player->mo->floorz - tiptop)) - teeter = true; - } - } - - { - INT32 bx, by, xl, xh, yl, yh; - - yh = (unsigned)(player->mo->y + player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT; - yl = (unsigned)(player->mo->y - player->mo->radius - bmaporgy)>>MAPBLOCKSHIFT; - xh = (unsigned)(player->mo->x + player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT; - xl = (unsigned)(player->mo->x - player->mo->radius - bmaporgx)>>MAPBLOCKSHIFT; - - BMBOUNDFIX(xl, xh, yl, yh); - - // Polyobjects -#ifdef POLYOBJECTS - validcount++; - - for (by = yl; by <= yh; by++) - for (bx = xl; bx <= xh; bx++) - { - INT32 offset; - polymaplink_t *plink; // haleyjd 02/22/06 - - if (bx < 0 || by < 0 || bx >= bmapwidth || by >= bmapheight) - continue; - - offset = by*bmapwidth + bx; - - // haleyjd 02/22/06: consider polyobject lines - plink = polyblocklinks[offset]; - - while (plink) - { - polyobj_t *po = plink->po; - - if (po->validcount != validcount) // if polyobj hasn't been checked - { - sector_t *polysec; - fixed_t polytop, polybottom; - - po->validcount = validcount; - - if (!(po->flags & POF_SOLID)) - { - plink = (polymaplink_t *)(plink->link.next); - continue; - } - - if (!P_MobjInsidePolyobj(po, player->mo)) - { - plink = (polymaplink_t *)(plink->link.next); - continue; - } - - // We're inside it! Yess... - polysec = po->lines[0]->backsector; - - if (po->flags & POF_CLIPPLANES) - { - polytop = polysec->ceilingheight; - polybottom = polysec->floorheight; - } - else - { - polytop = INT32_MAX; - polybottom = INT32_MIN; - } - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if (polybottom > player->mo->ceilingz) // Above the ceiling - { - plink = (polymaplink_t *)(plink->link.next); - continue; - } - - if (polybottom > player->mo->z + player->mo->height + tiptop - || (polytop < player->mo->z - && player->mo->z + player->mo->height < player->mo->ceilingz - tiptop)) - teeter = true; - else - { - teeter = false; - break; - } - } - else - { - if (polytop < player->mo->floorz) // Below the floor - { - plink = (polymaplink_t *)(plink->link.next); - continue; - } - - if (polytop < player->mo->z - tiptop - || (polybottom > player->mo->z + player->mo->height - && player->mo->z > player->mo->floorz + tiptop)) - teeter = true; - else - { - teeter = false; - break; - } - } - } - plink = (polymaplink_t *)(plink->link.next); - } - } -#endif - if (teeter) // only bother with objects as a last resort if you were already teetering - { - mobj_t *oldtmthing = tmthing; - tmthing = teeterer = player->mo; - teeterxl = teeterxh = player->mo->x; - teeteryl = teeteryh = player->mo->y; - couldteeter = false; - solidteeter = teeter; - for (by = yl; by <= yh; by++) - for (bx = xl; bx <= xh; bx++) - { - highesttop = INT32_MIN; - if (!P_BlockThingsIterator(bx, by, PIT_CheckSolidsTeeter)) - goto teeterdone; // we've found something that stops us teetering at all, how about we stop already - } -teeterdone: - teeter = solidteeter; - tmthing = oldtmthing; // restore old tmthing, goodness knows what the game does with this before mobj thinkers - } - } - if (teeter) - { - if ((player->mo->state == &states[S_PLAY_STND] || player->mo->state == &states[S_PLAY_TAP1] || player->mo->state == &states[S_PLAY_TAP2] || player->mo->state == &states[S_PLAY_SUPERSTAND])) - P_SetPlayerMobjState(player->mo, S_PLAY_TEETER1); - } - else if ((player->mo->state == &states[S_PLAY_TEETER1] || player->mo->state == &states[S_PLAY_TEETER2] || player->mo->state == &states[S_PLAY_SUPERTEETER])) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); -} -*/ - -// -// P_SetWeaponDelay -// -// Sets weapon delay. Properly accounts for Knux's firing rate bonus. -// -/* -static void P_SetWeaponDelay(player_t *player, INT32 delay) // SRB2kart - unused. -{ - player->weapondelay = delay; - - if (player->skin == 2) // Knuckles - { - // Multiply before dividing. - // Loss of precision can make a surprisingly large difference. - player->weapondelay *= 2; - player->weapondelay /= 3; - } -} - -// -// P_DoFiring() -// -// Handles firing ring weapons and Mario fireballs. -// -static void P_DoFiring(player_t *player, ticcmd_t *cmd) // SRB2kart - unused. -{ - INT32 i; - - I_Assert(player != NULL); - I_Assert(!P_MobjWasRemoved(player->mo)); - - if (cmd->buttons & BT_ATTACK) - { - if (!(player->pflags & PF_ATTACKDOWN) && player->powers[pw_shield] & SH_FIREFLOWER && !player->climbing) - { - player->pflags |= PF_ATTACKDOWN; - P_SpawnPlayerMissile(player->mo, MT_FIREBALL, 0); - S_StartSound(player->mo, sfx_mario7); - } - else if (G_BattleGametype() && (!G_TagGametype() || player->pflags & PF_TAGIT) - && !player->weapondelay && !player->climbing - && !(player->pflags & PF_ATTACKDOWN)) - { - mobj_t *mo = NULL; - player->pflags |= PF_ATTACKDOWN; - - //if (cmd->buttons & BT_FIRENORMAL) // No powers, just a regular ring. - // goto firenormal; //code repetition sucks. - // Bounce ring - if (player->currentweapon == WEP_BOUNCE && player->powers[pw_bouncering]) - { - if (player->health <= 1) - return; - P_SetWeaponDelay(player, TICRATE/4); - - mo = P_SpawnPlayerMissile(player->mo, MT_THROWNBOUNCE, MF2_BOUNCERING); - - if (mo) - mo->fuse = 3*TICRATE; // Bounce Ring time - - player->powers[pw_bouncering]--; - player->mo->health--; - player->health--; - } - // Rail ring - else if (player->currentweapon == WEP_RAIL && player->powers[pw_railring]) - { - if (player->health <= 1) - return; - P_SetWeaponDelay(player, (3*TICRATE)/2); - - mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, MF2_RAILRING); - - // Rail has no unique thrown object, therefore its sound plays here. - S_StartSound(player->mo, sfx_rail1); - - player->powers[pw_railring]--; - player->mo->health--; - player->health--; - } - // Automatic - else if (player->currentweapon == WEP_AUTO && player->powers[pw_automaticring]) - { - if (player->health <= 1) - return; - player->pflags &= ~PF_ATTACKDOWN; - P_SetWeaponDelay(player, 2); - - mo = P_SpawnPlayerMissile(player->mo, MT_THROWNAUTOMATIC, MF2_AUTOMATIC); - - player->powers[pw_automaticring]--; - player->mo->health--; - player->health--; - } - // Explosion - else if (player->currentweapon == WEP_EXPLODE && player->powers[pw_explosionring]) - { - if (player->health <= 1) - return; - P_SetWeaponDelay(player, (3*TICRATE)/2); - - mo = P_SpawnPlayerMissile(player->mo, MT_THROWNEXPLOSION, MF2_EXPLOSION); - - player->powers[pw_explosionring]--; - player->mo->health--; - player->health--; - } - // Grenade - else if (player->currentweapon == WEP_GRENADE && player->powers[pw_grenadering]) - { - if (player->health <= 1) - return; - P_SetWeaponDelay(player, TICRATE/3); - - mo = P_SpawnPlayerMissile(player->mo, MT_THROWNGRENADE, MF2_EXPLOSION); - - if (mo) - { - //P_InstaThrust(mo, player->mo->angle, FixedMul(mo->info->speed, player->mo->scale)); - mo->fuse = mo->info->mass; - } - - player->powers[pw_grenadering]--; - player->mo->health--; - player->health--; - } - // Scatter - // Note: Ignores MF2_RAILRING - else if (player->currentweapon == WEP_SCATTER && player->powers[pw_scatterring]) - { - fixed_t oldz = player->mo->z; - angle_t shotangle = player->mo->angle; - angle_t oldaiming = player->aiming; - - if (player->health <= 1) - return; - P_SetWeaponDelay(player, (2*TICRATE)/3); - - // Center - mo = P_SpawnPlayerMissile(player->mo, MT_THROWNSCATTER, MF2_SCATTER); - if (mo) - shotangle = R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y); - - // Left - mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle-ANG2, true, MF2_SCATTER); - - // Right - mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle+ANG2, true, MF2_SCATTER); - - // Down - player->mo->z += FixedMul(12*FRACUNIT, player->mo->scale); - player->aiming += ANG1; - mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle, true, MF2_SCATTER); - - // Up - player->mo->z -= FixedMul(24*FRACUNIT, player->mo->scale); - player->aiming -= ANG2; - mo = P_SPMAngle(player->mo, MT_THROWNSCATTER, shotangle, true, MF2_SCATTER); - - player->mo->z = oldz; - player->aiming = oldaiming; - - player->powers[pw_scatterring]--; - player->mo->health--; - player->health--; - return; - } - // No powers, just a regular ring. - else - { -//firenormal: - // Infinity ring was selected. - // Mystic wants this ONLY to happen specifically if it's selected, - // and to not be able to get around it EITHER WAY with firenormal. - - // Infinity Ring - if (player->currentweapon == 0 - && player->powers[pw_infinityring]) - { - P_SetWeaponDelay(player, TICRATE/4); - - mo = P_SpawnPlayerMissile(player->mo, MT_THROWNINFINITY, 0); - - player->powers[pw_infinityring]--; - } - // Red Ring - else - { - if (player->health <= 1) - return; - P_SetWeaponDelay(player, TICRATE/4); - - mo = P_SpawnPlayerMissile(player->mo, MT_REDRING, 0); - - if (mo) - P_ColorTeamMissile(mo, player); - - player->mo->health--; - player->health--; - } - } - - if (mo) - { - if (mo->flags & MF_MISSILE && mo->flags2 & MF2_RAILRING) - { - const boolean nblockmap = !(mo->flags & MF_NOBLOCKMAP); - for (i = 0; i < 256; i++) - { - if (nblockmap) - { - P_UnsetThingPosition(mo); - mo->flags |= MF_NOBLOCKMAP; - P_SetThingPosition(mo); - } - - if (i&1) - P_SpawnMobj(mo->x, mo->y, mo->z, MT_SPARK); - - if (P_RailThinker(mo)) - break; // mobj was removed (missile hit a wall) or couldn't move - } - - // Other rail sound plays at contact point. - S_StartSound(mo, sfx_rail2); - } - } - } - return; - } - - // Not holding any firing buttons anymore. - // Release the grenade / whatever. - player->pflags &= ~PF_ATTACKDOWN; -} -*/ - -// -// P_DoSpinDash -// -// Player spindash handling -// -/* -static void P_DoSpinDash(player_t *player, ticcmd_t *cmd) // SRB2kart - unused. -{ - return; // SRB2kart - what's a spindash? - if (player->pflags & PF_STASIS) - return; - -#ifdef HAVE_BLUA - if (cmd->buttons & BT_BRAKE) - { - if (LUAh_SpinSpecial(player)) - return; - } -#endif - - // Spinning and Spindashing - if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SLIDING) && !player->exiting - && !P_PlayerInPain(player)) // subsequent revs - { - if ((cmd->buttons & BT_BRAKE) && player->speed < FixedMul(5<mo->scale) && !player->mo->momz && onground && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING) -#ifdef ESLOPE - && (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2) -#endif - ) - { - player->mo->momx = player->cmomx; - player->mo->momy = player->cmomy; - player->pflags |= PF_STARTDASH|PF_SPINNING; - player->dashspeed = FixedMul(FRACUNIT, player->mo->scale); - player->dashtime = 0; - //P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - player->pflags |= PF_USEDOWN; - } - else if ((cmd->buttons & BT_BRAKE) && (player->pflags & PF_STARTDASH)) - { - player->dashspeed += FixedMul(FRACUNIT, player->mo->scale); - - if (!(player->dashtime++ % 5)) - { - if (!player->spectator && player->dashspeed < FixedMul(player->maxdash, player->mo->scale)) - S_StartSound(player->mo, sfx_spndsh); // Make the rev sound! - - // Now spawn the color thok circle. - P_SpawnSpinMobj(player, player->revitem); - if (demo.recording) - G_GhostAddRev((INT32) (player - players)); - } - } - // If not moving up or down, and travelling faster than a speed of four while not holding - // down the spin button and not spinning. - // AKA Just go into a spin on the ground, you idiot. ;) - else if ((cmd->buttons & BT_BRAKE || ((twodlevel || (player->mo->flags2 & MF2_TWOD)) && cmd->forwardmove < -20)) - && !player->climbing && !player->mo->momz && onground && (player->speed > FixedMul(5<mo->scale) -#ifdef ESLOPE - || (player->mo->standingslope && (!(player->mo->standingslope->flags & SL_NOPHYSICS)) && abs(player->mo->standingslope->zdelta) >= FRACUNIT/2) -#endif - ) && !(player->pflags & PF_USEDOWN) && !(player->pflags & PF_SPINNING)) - { - player->pflags |= PF_SPINNING; - //P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - if (!player->spectator) - S_StartSound(player->mo, sfx_spin); - player->pflags |= PF_USEDOWN; - } - } - - // Rolling normally - if (onground && player->pflags & PF_SPINNING && !(player->pflags & PF_STARTDASH) - && player->speed < FixedMul(5*FRACUNIT,player->mo->scale) -#ifdef ESLOPE - && (!player->mo->standingslope || (player->mo->standingslope->flags & SL_NOPHYSICS) || abs(player->mo->standingslope->zdelta) < FRACUNIT/2) -#endif - ) - { - if (GETSECSPECIAL(player->mo->subsector->sector->special, 4) == 7 || (player->mo->ceilingz - player->mo->floorz < P_GetPlayerHeight(player))) - P_InstaThrust(player->mo, player->mo->angle, FixedMul(10*FRACUNIT, player->mo->scale)); - else - { - player->skidtime = 0; - player->pflags &= ~PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_KART_STILL1); - player->mo->momx = player->cmomx; - player->mo->momy = player->cmomy; - } - } - - // Catapult the player from a spindash rev! - if (onground && !(player->pflags & PF_USEDOWN) && player->dashspeed && (player->pflags & PF_STARTDASH) && (player->pflags & PF_SPINNING)) - { - if (player->powers[pw_ingoop]) - player->dashspeed = 0; - - player->pflags &= ~PF_STARTDASH; - if (!((gametype == GT_RACE || gametype == GT_COMPETITION) && leveltime < 4*TICRATE)) - { - P_InstaThrust(player->mo, player->mo->angle, player->dashspeed); // catapult forward ho!! - if (!player->spectator) - S_StartSound(player->mo, sfx_zoom); - } - player->dashspeed = 0; - } - - //if (onground && (player->pflags & PF_SPINNING) && !(player->panim == PA_ROLL)) - // P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); -} -*/ - -// -// P_DoJumpShield -// -// Jump Shield Activation -// -void P_DoJumpShield(player_t *player) -{ - if (player->pflags & PF_THOKKED) - return; - - player->pflags &= ~PF_JUMPED; - //P_DoJump(player, false); - player->pflags &= ~PF_JUMPED; - player->secondjump = 0; - player->jumping = 0; - player->pflags |= PF_THOKKED; - player->pflags &= ~PF_SPINNING; - //P_SetPlayerMobjState(player->mo, S_PLAY_FALL1); - S_StartSound(player->mo, sfx_wdjump); -} - -// -// P_Telekinesis -// -// Morph's fancy stuff-moving character ability -// +ve thrust pushes away, -ve thrust pulls in -// -void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range) -{ - thinker_t *th; - mobj_t *mo2; - fixed_t dist = 0; - angle_t an; - - if (player->powers[pw_super]) // increase range when super - range *= 2; - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2 == player->mo) - continue; - - if (!((mo2->flags & MF_SHOOTABLE && mo2->flags & MF_ENEMY) || mo2->type == MT_EGGGUARD || mo2->player)) - continue; - - dist = P_AproxDistance(P_AproxDistance(player->mo->x-mo2->x, player->mo->y-mo2->y), player->mo->z-mo2->z); - - if (range < dist) - continue; - - if (!P_CheckSight(player->mo, mo2)) - continue; // if your psychic powers can't "see" it don't bother - - an = R_PointToAngle2(player->mo->x, player->mo->y, mo2->x, mo2->y); - - if (mo2->health > 0) - { - P_Thrust(mo2, an, thrust); - - if (mo2->type == MT_GOLDBUZZ || mo2->type == MT_REDBUZZ) - mo2->tics += 8; - } - } - - //P_SpawnThokMobj(player); - player->pflags |= PF_THOKKED; -} - -// -// P_GetPlayerControlDirection -// -// Determines if the player is pressing in the direction they are moving -// -// 0 = no controls pressed/no movement -// 1 = pressing in the direction of movement -// 2 = pressing in the opposite direction of movement -// -/*INT32 P_GetPlayerControlDirection(player_t *player) -{ - ticcmd_t *cmd = &player->cmd; - angle_t controllerdirection, controlplayerdirection; - camera_t *thiscam; - angle_t dangle; - fixed_t tempx = 0, tempy = 0; - angle_t tempangle, origtempangle; - - if (splitscreen > 2 && player == &players[displayplayers[3]]) - thiscam = &camera[3]; - else if (splitscreen > 1 && player == &players[displayplayers[2]]) - thiscam = &camera[2]; - else if (splitscreen && player == &players[displayplayers[1]]) - thiscam = &camera[1]; - else - thiscam = &camera[0]; - - if (!cmd->forwardmove && !cmd->sidemove) - return 0; - - if (!player->mo->momx && !player->mo->momy) - return 0; - - if (twodlevel || player->mo->flags2 & MF2_TWOD) - { - if (!cmd->sidemove) - return 0; - if (!player->mo->momx) - return 0; - origtempangle = tempangle = 0; // relative to the axis rather than the player! - controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); - } - else - { - origtempangle = tempangle = player->mo->angle; - controlplayerdirection = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); - } - - // Calculate the angle at which the controls are pointing - // to figure out the proper mforward and mbackward. - tempangle >>= ANGLETOFINESHIFT; - if (!(twodlevel || player->mo->flags2 & MF2_TWOD)) // in 2d mode, sidemove is treated as the forwards/backwards direction - { - tempx += FixedMul(cmd->forwardmove*FRACUNIT,FINECOSINE(tempangle)); - tempy += FixedMul(cmd->forwardmove*FRACUNIT,FINESINE(tempangle)); - - tempangle = origtempangle-ANGLE_90; - tempangle >>= ANGLETOFINESHIFT; - } - tempx += FixedMul(cmd->sidemove*FRACUNIT,FINECOSINE(tempangle)); - tempy += FixedMul(cmd->sidemove*FRACUNIT,FINESINE(tempangle)); - - controllerdirection = R_PointToAngle2(0, 0, tempx, tempy); - - dangle = controllerdirection - controlplayerdirection; - - if (dangle > ANGLE_180) //flip to keep to one side - dangle = InvAngle(dangle); - - if (dangle > ANGLE_90) - return 2; // Controls pointing backwards from player - else - return 1; // Controls pointing in player's general direction -} - -// Control scheme for 2d levels. -static void P_2dMovement(player_t *player) -{ - ticcmd_t *cmd; - INT32 topspeed, acceleration, thrustfactor; - fixed_t movepushforward = 0; - angle_t movepushangle = 0; - fixed_t normalspd = FixedMul(player->normalspeed, player->mo->scale); - - cmd = &player->cmd; - - if (player->exiting || player->pflags & PF_STASIS) - { - cmd->forwardmove = cmd->sidemove = 0; - if (player->pflags & PF_GLIDING) - { - if (!player->skidtime) - player->pflags &= ~PF_GLIDING; - else if (player->exiting) - { - player->pflags &= ~PF_GLIDING; - P_SetPlayerMobjState(player->mo, S_KART_SLOW1); // SRB2kart - was S_PLAY_RUN1 - player->skidtime = 0; - } - } - if (player->pflags & PF_SPINNING && !player->exiting) - { - player->pflags &= ~PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_KART_STILL1); // SRB2kart - was S_PLAY_STND - } - } - - // cmomx/cmomy stands for the conveyor belt speed. - if (player->onconveyor == 2) // Wind/Current - { - //if (player->mo->z > player->mo->watertop || player->mo->z + player->mo->height < player->mo->waterbottom) - if (!(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - player->cmomx = player->cmomy = 0; - } - else if (player->onconveyor == 4 && !P_IsObjectOnGround(player->mo)) // Actual conveyor belt - player->cmomx = player->cmomy = 0; - else if (player->onconveyor != 2 && player->onconveyor != 4 -#ifdef POLYOBJECTS - && player->onconveyor != 1 -#endif - ) - player->cmomx = player->cmomy = 0; - - player->rmomx = player->mo->momx - player->cmomx; - player->rmomy = player->mo->momy - player->cmomy; - - // Calculates player's speed based on absolute-value-of-a-number formula - player->speed = abs(player->rmomx); - - if (player->pflags & PF_GLIDING) - { - // Angle fix. - if (player->mo->angle < ANGLE_180 && player->mo->angle > ANGLE_90) - player->mo->angle = ANGLE_180; - else if (player->mo->angle < ANGLE_90 && player->mo->angle > 0) - player->mo->angle = 0; - - if (cmd->sidemove > 0 && player->mo->angle != 0 && player->mo->angle >= ANGLE_180) - player->mo->angle += 1280<sidemove < 0 && player->mo->angle != ANGLE_180 && (player->mo->angle > ANGLE_180 || player->mo->angle == 0)) - player->mo->angle -= 1280<sidemove == 0) - { - if (player->mo->angle >= ANGLE_270) - player->mo->angle += 1280<mo->angle < ANGLE_270 && player->mo->angle > ANGLE_180) - player->mo->angle -= 1280<sidemove && !(player->climbing) && !P_PlayerInPain(player)) - { - if (cmd->sidemove > 0) - player->mo->angle = 0; - else if (cmd->sidemove < 0) - player->mo->angle = ANGLE_180; - } - - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; - - if (player->pflags & PF_GLIDING) - movepushangle = player->mo->angle; - else - { - if (cmd->sidemove > 0) - movepushangle = 0; - else if (cmd->sidemove < 0) - movepushangle = ANGLE_180; - else - movepushangle = player->mo->angle; - } - - // Do not let the player control movement if not onground. - onground = P_IsObjectOnGround(player->mo); - - player->aiming = cmd->aiming<powers[pw_super] || player->powers[pw_sneakers]) - { - thrustfactor = player->thrustfactor*2; - acceleration = player->accelstart/2 + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration/2; - - if (player->powers[pw_tailsfly]) - topspeed = normalspd; - else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER) && !(player->pflags & PF_SLIDING)) - { - topspeed = normalspd; - acceleration = 2*acceleration/3; - } - else - topspeed = normalspd * 2; - } - else - { - thrustfactor = player->thrustfactor; - acceleration = player->accelstart + (FixedDiv(player->speed, player->mo->scale)>>FRACBITS) * player->acceleration; - - if (player->powers[pw_tailsfly]) - topspeed = normalspd/2; - else if (player->mo->eflags & (MFE_UNDERWATER|MFE_GOOWATER) && !(player->pflags & PF_SLIDING)) - { - topspeed = normalspd/2; - acceleration = 2*acceleration/3; - } - else - topspeed = normalspd; - } - -////////////////////////////////////// - if (player->climbing) - { - if (cmd->forwardmove != 0) - P_SetObjectMomZ(player->mo, FixedDiv(cmd->forwardmove*FRACUNIT,10*FRACUNIT), false); - - if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds])) - player->mo->momz *= 2; - - player->mo->momx = 0; - } - else if (cmd->sidemove != 0 && !(player->pflags & PF_GLIDING || player->exiting - || (P_PlayerInPain(player) && !onground))) - { - movepushforward = abs(cmd->sidemove) * (thrustfactor * acceleration); - - // allow very small movement while in air for gameplay - if (!onground) - movepushforward >>= 1; // Proper air movement - - // Allow a bit of movement while spinning - if (player->pflags & PF_SPINNING) - { - if (!(player->pflags & PF_STARTDASH)) - movepushforward = movepushforward/48; - else - movepushforward = 0; - } - - movepushforward = FixedMul(movepushforward, player->mo->scale); - if (player->rmomx < topspeed && cmd->sidemove > 0) // Sonic's Speed - P_Thrust(player->mo, movepushangle, movepushforward); - else if (player->rmomx > -topspeed && cmd->sidemove < 0) - P_Thrust(player->mo, movepushangle, movepushforward); - } -}*/ - //#define OLD_MOVEMENT_CODE 1 static void P_3dMovement(player_t *player) { - ticcmd_t *cmd; angle_t movepushangle; // Analog - //INT32 topspeed, acceleration, thrustfactor; fixed_t movepushforward = 0; angle_t dangle; // replaces old quadrants bits - //boolean dangleflip = false; // SRB2kart - toaster - //fixed_t normalspd = FixedMul(player->normalspeed, player->mo->scale); fixed_t oldMagnitude, newMagnitude; -#ifdef ESLOPE vector3_t totalthrust; totalthrust.x = totalthrust.y = 0; // I forget if this is needed totalthrust.z = FRACUNIT*P_MobjFlip(player->mo)/3; // A bit of extra push-back on slopes -#endif // ESLOPE + + if (player->kartstuff[k_sneakertimer] > 0) + { + totalthrust.z = -(totalthrust.z); + } // Get the old momentum; this will be needed at the end of the function! -SH oldMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0); - cmd = &player->cmd; - if (player->kartstuff[k_drift] != 0) movepushangle = player->mo->angle-(ANGLE_45/5)*player->kartstuff[k_drift]; else if (player->kartstuff[k_spinouttimer] || player->kartstuff[k_wipeoutslow]) // if spun out, use the boost angle @@ -4075,13 +1901,12 @@ static void P_3dMovement(player_t *player) if (dangle > ANGLE_180) //flip to keep to one side { dangle = InvAngle(dangle); - //dangleflip = true; } // anything else will leave both at 0, so no need to do anything else //{ SRB2kart 220217 - Toaster Code for misplaced thrust - /* +#if 0 if (!player->kartstuff[k_drift]) // Not Drifting { angle_t difference = dangle/2; @@ -4095,28 +1920,31 @@ static void P_3dMovement(player_t *player) P_InstaThrust(player->mo, player->mo->angle + difference, player->speed); } - */ +#endif //} // Do not let the player control movement if not onground. onground = P_IsObjectOnGround(player->mo); - player->aiming = cmd->aiming<mo->movefactor != FRACUNIT) // Friction-scaled acceleration... movepushforward = FixedMul(movepushforward, player->mo->movefactor); totalthrust.x += P_ReturnThrustX(player->mo, movepushangle, movepushforward); totalthrust.y += P_ReturnThrustY(player->mo, movepushangle, movepushforward); - } - else if (!(player->kartstuff[k_spinouttimer])) - { - K_MomentumToFacing(player); + + if (K_PlayerUsesBotMovement(player) == true) + { + K_MomentumToFacing(player); + } } if ((totalthrust.x || totalthrust.y) @@ -4136,11 +1964,6 @@ static void P_3dMovement(player_t *player) } } - if (K_PlayerUsesBotMovement(player)) - { - K_MomentumToFacing(player); - } - player->mo->momx += totalthrust.x; player->mo->momy += totalthrust.y; @@ -4215,6 +2038,39 @@ static void P_3dMovement(player_t *player) } } +// +// P_UpdatePlayerAngle +// +// Updates player angleturn with cmd->turning +// +static void P_UpdatePlayerAngle(player_t *player) +{ + angle_t angleChange = K_GetKartTurnValue(player, player->cmd.turning) << TICCMD_REDUCE; + UINT8 i; + + P_SetPlayerAngle(player, player->angleturn + angleChange); + player->mo->angle = player->angleturn; + + if (!cv_allowmlook.value || player->spectator == false) + { + player->aiming = 0; + } + else + { + player->aiming += (player->cmd.aiming << TICCMD_REDUCE); + player->aiming = G_ClipAimingPitch((INT32 *)&player->aiming); + } + + for (i = 0; i <= r_splitscreen; i++) + { + if (player == &players[displayplayers[i]]) + { + localaiming[i] = player->aiming; + break; + } + } +} + // // P_SpectatorMovement // @@ -4224,25 +2080,21 @@ static void P_SpectatorMovement(player_t *player) { ticcmd_t *cmd = &player->cmd; - player->mo->angle = (cmd->angleturn<<16 /* not FRACBITS */); + P_UpdatePlayerAngle(player); ticruned++; - if (!(cmd->angleturn & TICCMD_RECEIVED)) + if (!(cmd->flags & TICCMD_RECEIVED)) ticmiss++; - if (player->mo->z > player->mo->ceilingz - player->mo->height) - player->mo->z = player->mo->ceilingz - player->mo->height; - if (player->mo->z < player->mo->floorz) - player->mo->z = player->mo->floorz; - if (cmd->buttons & BT_ACCELERATE) player->mo->z += 32*mapobjectscale; else if (cmd->buttons & BT_BRAKE) player->mo->z -= 32*mapobjectscale; - // Aiming needed for SEENAMES, etc. - // We may not need to fire as a spectator, but this is still handy! - player->aiming = cmd->aiming<mo->z > player->mo->ceilingz - player->mo->height) + player->mo->z = player->mo->ceilingz - player->mo->height; + if (player->mo->z < player->mo->floorz) + player->mo->z = player->mo->floorz; player->mo->momx = player->mo->momy = player->mo->momz = 0; if (cmd->forwardmove != 0) @@ -4252,1367 +2104,11 @@ static void P_SpectatorMovement(player_t *player) // Quake-style flying spectators :D player->mo->momz += FixedMul(cmd->forwardmove*mapobjectscale, AIMINGTOSLOPE(player->aiming)); } - /*if (cmd->sidemove != 0) -- was disabled in practice anyways, since sidemove was suppressed - { - P_Thrust(player->mo, player->mo->angle-ANGLE_90, cmd->sidemove*mapobjectscale); - }*/ -} - -// -// P_ShootLine -// -// Fun and fancy -// graphical indicator -// for building/debugging -// NiGHTS levels! -/*static void P_ShootLine(mobj_t *source, mobj_t *dest, fixed_t height) -{ - mobj_t *mo; - INT32 i; - fixed_t temp; - INT32 speed, seesound; - - temp = dest->z; - dest->z = height; - - seesound = mobjinfo[MT_REDRING].seesound; - speed = mobjinfo[MT_REDRING].speed; - mobjinfo[MT_REDRING].seesound = sfx_None; - mobjinfo[MT_REDRING].speed = 20*FRACUNIT; - - mo = P_SpawnXYZMissile(source, dest, MT_REDRING, source->x, source->y, height); - - dest->z = temp; - if (mo) - { - mo->flags2 |= MF2_RAILRING; - mo->drawflags |= MFD_DONTDRAW; - mo->flags |= MF_NOCLIPHEIGHT; - mo->flags |= MF_NOCLIP; - mo->flags &= ~MF_MISSILE; - mo->fuse = 3; - } - - for (i = 0; i < 32; i++) - { - if (mo) - { - if (!(mo->flags & MF_NOBLOCKMAP)) - { - P_UnsetThingPosition(mo); - mo->flags |= MF_NOBLOCKMAP; - P_SetThingPosition(mo); - } - if (i&1) - P_SpawnMobj(mo->x, mo->y, mo->z, MT_SPARK); - - P_UnsetThingPosition(mo); - mo->x += mo->momx; - mo->y += mo->momy; - mo->z += mo->momz; - P_SetThingPosition(mo); - } - else - { - mobjinfo[MT_REDRING].seesound = seesound; - mobjinfo[MT_REDRING].speed = speed; - return; - } - } - mobjinfo[MT_REDRING].seesound = seesound; - mobjinfo[MT_REDRING].speed = speed; -} - -#define MAXDRILLSPEED 14000 -#define MAXNORMALSPEED 6250 //6000 - -static void P_NightsTransferPoints(player_t *player, fixed_t xspeed, fixed_t radius) -{ - if (player->pflags & PF_TRANSFERTOCLOSEST) - { - const angle_t fa = R_PointToAngle2(player->axis1->x, player->axis1->y, player->axis2->x, player->axis2->y); - P_InstaThrust(player->mo, fa, xspeed/10); - } - else - { - const angle_t fa = player->angle_pos>>ANGLETOFINESHIFT; - const angle_t faold = player->old_angle_pos>>ANGLETOFINESHIFT; - player->mo->momx = FixedMul(FINECOSINE(fa),radius) - FixedMul(FINECOSINE(faold),radius); - player->mo->momy = FixedMul(FINESINE(fa),radius) - FixedMul(FINESINE(faold),radius); - } - - if (player->exiting) - return; - - // You're welcome, Rob. (Now with slightly less horrendous hacking -Red - player->mo->tracer->flags &= ~MF_NOCLIP; - player->mo->tracer->z = player->mo->z; - if (!P_TryMove(player->mo->tracer, player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, true)) { - player->mo->tracer->flags |= MF_NOCLIP; - return; - } - player->mo->tracer->flags |= MF_NOCLIP; - { - const INT32 sequence = player->mo->target->threshold; - mobj_t *transfer1 = NULL; - mobj_t *transfer2 = NULL; - mobj_t *axis; - mobj_t *mo2; - thinker_t *th; - line_t transfer1line; - line_t transfer2line; - boolean transfer1last = false; - boolean transfer2last = false; - vertex_t vertices[4]; - fixed_t truexspeed = xspeed*(!(player->pflags & PF_TRANSFERTOCLOSEST) && player->mo->target->flags2 & MF2_AMBUSH ? -1 : 1); - - // Find next waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)th; - - // Axis things are only at beginning of list. - if (!(mo2->flags2 & MF2_AXIS)) - break; - - if ((mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE) - && mo2->threshold == sequence) - { - if (player->pflags & PF_TRANSFERTOCLOSEST) - { - if (mo2->health == player->axis1->health) - transfer1 = mo2; - else if (mo2->health == player->axis2->health) - transfer2 = mo2; - } - else - { - if (mo2->health == player->mo->target->health) - transfer1 = mo2; - else if (mo2->health == player->mo->target->health + 1) - transfer2 = mo2; - } - } - } - - // It might be possible that one wasn't found. - // Is it because we're at the end of the track? - // Look for a wrapper point. - if (!transfer1) - { - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)th; - - // Axis things are only at beginning of list. - if (!(mo2->flags2 & MF2_AXIS)) - break; - - if (mo2->threshold == sequence && (mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) - { - if (!transfer1) - { - transfer1 = mo2; - transfer1last = true; - } - else if (mo2->health > transfer1->health) - { - transfer1 = mo2; - transfer1last = true; - } - } - } - } - if (!transfer2) - { - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)th; - - // Axis things are only at beginning of list. - if (!(mo2->flags2 & MF2_AXIS)) - break; - - if (mo2->threshold == sequence && (mo2->type == MT_AXISTRANSFER || mo2->type == MT_AXISTRANSFERLINE)) - { - if (!transfer2) - { - transfer2 = mo2; - transfer2last = true; - } - else if (mo2->health > transfer2->health) - { - transfer2 = mo2; - transfer2last = true; - } - } - } - } - - if (!(transfer1 && transfer2)) // We can't continue... - I_Error("Mare does not form a complete circuit!\n"); - - transfer1line.v1 = &vertices[0]; - transfer1line.v2 = &vertices[1]; - transfer2line.v1 = &vertices[2]; - transfer2line.v2 = &vertices[3]; - - if (cv_debug && (leveltime % TICRATE == 0)) - { - CONS_Debug(DBG_NIGHTS, "Transfer1 : %d\n", transfer1->health); - CONS_Debug(DBG_NIGHTS, "Transfer2 : %d\n", transfer2->health); - } - //CONS_Debug(DBG_NIGHTS, "Xspeed : %d", truexspeed); - - //CONS_Debug(DBG_NIGHTS, "T1 is at %d, %d\n", transfer1->x>>FRACBITS, transfer1->y>>FRACBITS); - //CONS_Debug(DBG_NIGHTS, "T2 is at %d, %d\n", transfer2->x>>FRACBITS, transfer2->y>>FRACBITS); - //CONS_Debug(DBG_NIGHTS, "Distance from T1: %d\n", P_AproxDistance(transfer1->x - player->mo->x, transfer1->y - player->mo->y)>>FRACBITS); - //CONS_Debug(DBG_NIGHTS, "Distance from T2: %d\n", P_AproxDistance(transfer2->x - player->mo->x, transfer2->y - player->mo->y)>>FRACBITS); - - // Transfer1 is closer to the player than transfer2 - if (P_AproxDistance(transfer1->x - player->mo->x, transfer1->y - player->mo->y)>>FRACBITS - < P_AproxDistance(transfer2->x - player->mo->x, transfer2->y - player->mo->y)>>FRACBITS) - { - //CONS_Debug(DBG_NIGHTS, " must be < 0 to transfer\n"); - - if (transfer1->type == MT_AXISTRANSFERLINE) - { - if (transfer1last) - axis = P_FindAxis(transfer1->threshold, transfer1->health-2); - else if (player->pflags & PF_TRANSFERTOCLOSEST) - axis = P_FindAxis(transfer1->threshold, transfer1->health-1); - else - axis = P_FindAxis(transfer1->threshold, transfer1->health); - - if (!axis) - { - CONS_Debug(DBG_NIGHTS, "Unable to find an axis - error code #1\n"); - return; - } - - //CONS_Debug(DBG_NIGHTS, "Drawing a line from %d to ", axis->health); - - transfer1line.v1->x = axis->x; - transfer1line.v1->y = axis->y; - - transfer1line.v2->x = transfer1->x; - transfer1line.v2->y = transfer1->y; - - if (cv_debug & DBG_NIGHTS) - P_ShootLine(axis, transfer1, player->mo->z); - - //CONS_Debug(DBG_NIGHTS, "closest %d\n", transfer1->health); - - transfer1line.dx = transfer1line.v2->x - transfer1line.v1->x; - transfer1line.dy = transfer1line.v2->y - transfer1line.v1->y; - - if (P_PointOnLineSide(player->mo->x, player->mo->y, &transfer1line) - != P_PointOnLineSide(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, &transfer1line) - && truexspeed < 0) - { - if (cv_debug & DBG_NIGHTS) - { - HU_SetCEchoDuration(1); - HU_DoCEcho("transfer!"); - HU_SetCEchoDuration(5); - S_StartSound(NULL, sfx_strpst); - } - if (player->pflags & PF_TRANSFERTOCLOSEST) - { - player->pflags &= ~PF_TRANSFERTOCLOSEST; - P_TransferToAxis(player, transfer1->health - 1); - } - else - { - player->pflags |= PF_TRANSFERTOCLOSEST; - P_SetTarget(&player->axis2, transfer1); - P_SetTarget(&player->axis1, P_FindAxisTransfer(transfer1->threshold, transfer1->health-1, MT_AXISTRANSFERLINE));//P_FindAxis(transfer1->threshold, axis->health-2); - } - } - } - else - { - // Transfer1 - if (transfer1last) - axis = P_FindAxis(transfer1->threshold, 1); - else - axis = P_FindAxis(transfer1->threshold, transfer1->health); - - if (!axis) - { - CONS_Debug(DBG_NIGHTS, "Unable to find an axis - error code #2\n"); - return; - } - - //CONS_Debug(DBG_NIGHTS, "Drawing a line from %d to ", axis->health); - - transfer1line.v1->x = axis->x; - transfer1line.v1->y = axis->y; - - if (cv_debug & DBG_NIGHTS) - P_ShootLine(transfer1, P_FindAxis(transfer1->threshold, transfer1->health-1), player->mo->z); - - //axis = P_FindAxis(transfer1->threshold, transfer1->health-1); - - //CONS_Debug(DBG_NIGHTS, "%d\n", axis->health); - - transfer1line.v2->x = transfer1->x; - transfer1line.v2->y = transfer1->y; - - transfer1line.dx = transfer1line.v2->x - transfer1line.v1->x; - transfer1line.dy = transfer1line.v2->y - transfer1line.v1->y; - - if (P_PointOnLineSide(player->mo->x, player->mo->y, &transfer1line) - != P_PointOnLineSide(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, &transfer1line) - && truexspeed < 0) - { - if (cv_debug & DBG_NIGHTS) - { - HU_SetCEchoDuration(1); - HU_DoCEcho("transfer!"); - HU_SetCEchoDuration(5); - S_StartSound(NULL, sfx_strpst); - } - if (player->mo->target->health < transfer1->health) - { - // Find the next axis with a ->health - // +1 from the current axis. - if (transfer1last) - P_TransferToAxis(player, transfer1->health - 1); - else - P_TransferToAxis(player, transfer1->health); - } - else if (player->mo->target->health >= transfer1->health) - { - // Find the next axis with a ->health - // -1 from the current axis. - P_TransferToAxis(player, transfer1->health - 1); - } - } - } - } - else - { - //CONS_Debug(DBG_NIGHTS, " must be > 0 to transfer\n"); - if (transfer2->type == MT_AXISTRANSFERLINE) - { - if (transfer2last) - axis = P_FindAxis(transfer2->threshold, 1); - else if (player->pflags & PF_TRANSFERTOCLOSEST) - axis = P_FindAxis(transfer2->threshold, transfer2->health); - else - axis = P_FindAxis(transfer2->threshold, transfer2->health - 1); - - if (!axis) - axis = P_FindAxis(transfer2->threshold, 1); - - if (!axis) - { - CONS_Debug(DBG_NIGHTS, "Unable to find an axis - error code #3\n"); - return; - } - - //CONS_Debug(DBG_NIGHTS, "Drawing a line from %d to ", axis->health); - - transfer2line.v1->x = axis->x; - transfer2line.v1->y = axis->y; - - transfer2line.v2->x = transfer2->x; - transfer2line.v2->y = transfer2->y; - - //CONS_Debug(DBG_NIGHTS, "closest %d\n", transfer2->health); - - if (cv_debug & DBG_NIGHTS) - P_ShootLine(axis, transfer2, player->mo->z); - - transfer2line.dx = transfer2line.v2->x - transfer2line.v1->x; - transfer2line.dy = transfer2line.v2->y - transfer2line.v1->y; - - if (P_PointOnLineSide(player->mo->x, player->mo->y, &transfer2line) - != P_PointOnLineSide(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, &transfer2line) - && truexspeed > 0) - { - if (cv_debug & DBG_NIGHTS) - { - HU_SetCEchoDuration(1); - HU_DoCEcho("transfer!"); - HU_SetCEchoDuration(5); - S_StartSound(NULL, sfx_strpst); - } - if (player->pflags & PF_TRANSFERTOCLOSEST) - { - player->pflags &= ~PF_TRANSFERTOCLOSEST; - - if (!P_FindAxis(transfer2->threshold, transfer2->health)) - transfer2last = true; - - if (transfer2last) - P_TransferToAxis(player, 1); - else - P_TransferToAxis(player, transfer2->health); - } - else - { - player->pflags |= PF_TRANSFERTOCLOSEST; - P_SetTarget(&player->axis1, transfer2); - P_SetTarget(&player->axis2, P_FindAxisTransfer(transfer2->threshold, transfer2->health+1, MT_AXISTRANSFERLINE));//P_FindAxis(transfer2->threshold, axis->health + 2); - } - } - } - else - { - // Transfer2 - if (transfer2last) - axis = P_FindAxis(transfer2->threshold, 1); - else - axis = P_FindAxis(transfer2->threshold, transfer2->health); - - if (!axis) - axis = P_FindAxis(transfer2->threshold, 1); - - if (!axis) - { - CONS_Debug(DBG_NIGHTS, "Unable to find an axis - error code #4\n"); - return; - } - - //CONS_Debug(DBG_NIGHTS, "Drawing a line from %d to ", axis->health); - - transfer2line.v1->x = axis->x; - transfer2line.v1->y = axis->y; - - if (cv_debug & DBG_NIGHTS) - P_ShootLine(transfer2, P_FindAxis(transfer2->threshold, transfer2->health-1), player->mo->z); - - //axis = P_FindAxis(transfer2->threshold, transfer2->health-1); - - //CONS_Debug(DBG_NIGHTS, "%d\n", axis->health); - - transfer2line.v2->x = transfer2->x; - transfer2line.v2->y = transfer2->y; - - transfer2line.dx = transfer2line.v2->x - transfer2line.v1->x; - transfer2line.dy = transfer2line.v2->y - transfer2line.v1->y; - - if (P_PointOnLineSide(player->mo->x, player->mo->y, &transfer2line) - != P_PointOnLineSide(player->mo->x+player->mo->momx, player->mo->y+player->mo->momy, &transfer2line) - && truexspeed > 0) - { - if (cv_debug & DBG_NIGHTS) - { - HU_SetCEchoDuration(1); - HU_DoCEcho("transfer!"); - HU_SetCEchoDuration(5); - S_StartSound(NULL, sfx_strpst); - } - if (player->mo->target->health < transfer2->health) - { - if (!P_FindAxis(transfer2->threshold, transfer2->health)) - transfer2last = true; - - if (transfer2last) - P_TransferToAxis(player, 1); - else - P_TransferToAxis(player, transfer2->health); - } - else if (player->mo->target->health >= transfer2->health) - P_TransferToAxis(player, transfer2->health - 1); - } - } - } - } -} - -// -// P_DoNiGHTSCapsule -// -// Handles blowing up the Ideya (emerald) capsule for NiGHTS mode -// -static void P_DoNiGHTSCapsule(player_t *player) -{ - INT32 i; - - if ((player->pflags & PF_NIGHTSMODE) && (player->mo->tracer->state < &states[S_NIGHTSHURT1] - || player->mo->tracer->state > &states[S_NIGHTSHURT32])) - P_SetMobjState(player->mo->tracer, S_NIGHTSHURT1); - - if (abs(player->mo->x-player->capsule->x) <= 2*FRACUNIT) - { - P_UnsetThingPosition(player->mo); - player->mo->x = player->capsule->x; - P_SetThingPosition(player->mo); - player->mo->momx = 0; - } - - if (abs(player->mo->y-player->capsule->y) <= 2*FRACUNIT) - { - P_UnsetThingPosition(player->mo); - player->mo->y = player->capsule->y; - P_SetThingPosition(player->mo); - player->mo->momy = 0; - } - - if (abs(player->mo->z - (player->capsule->z+(player->capsule->height/3))) <= 2*FRACUNIT) - { - player->mo->z = player->capsule->z+(player->capsule->height/3); - player->mo->momz = 0; - } - - if (player->mo->x > player->capsule->x) - player->mo->momx = -2*FRACUNIT; - else if (player->mo->x < player->capsule->x) - player->mo->momx = 2*FRACUNIT; - - if (player->mo->y > player->capsule->y) - player->mo->momy = -2*FRACUNIT; - else if (player->mo->y < player->capsule->y) - player->mo->momy = 2*FRACUNIT; - - if (player->mo->z > player->capsule->z+(player->capsule->height/3)) - player->mo->momz = -2*FRACUNIT; - else if (player->mo->z < player->capsule->z+(player->capsule->height/3)) - player->mo->momz = 2*FRACUNIT; - - if (G_IsSpecialStage(gamemap)) - { // In special stages, share rings. Everyone gives up theirs to the capsule player always, because we can't have any individualism here! - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && (&players[i] != player) && players[i].mo->health > 1) - { - player->mo->health += players[i].mo->health-1; - player->health = player->mo->health; - players[i].mo->health = 1; - players[i].health = players[i].mo->health; - } - } - - // Time to blow it up! - if (player->mo->x == player->capsule->x - && player->mo->y == player->capsule->y - && player->mo->z == player->capsule->z+(player->capsule->height/3)) - { - if (player->mo->health > 1) - { - player->mo->health--; - player->health--; - player->capsule->health--; - player->capsule->extravalue1++; - - // Spawn a 'pop' for every 5 rings you deposit - if (!(player->capsule->extravalue1 % 5)) - S_StartSound(P_SpawnMobj(player->capsule->x + ((P_SignedRandom()/2)<capsule->y + ((P_SignedRandom()/2)<capsule->z + (player->capsule->height/2) + ((P_SignedRandom()/2)<capsule->health <= 0) - { - player->capsule->flags &= ~MF_NOGRAVITY; - player->capsule->momz = 5*FRACUNIT; - player->capsule->reactiontime = 0; - player->capsule->extravalue1 = -1; - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && !player->exiting && players[i].mare == player->mare) - { - players[i].bonustime = true; - players[i].texttimer = 4*TICRATE; - players[i].textvar = 1; // Time Bonus - players[i].finishedtime = players[i].nightstime; - if (!G_IsSpecialStage(gamemap)) - P_AddPlayerScore(&players[i], (players[i].finishedtime/TICRATE) * 100); - P_FlashPal(&players[i], PAL_WHITE, 8); - } - - if (G_IsSpecialStage(gamemap)) - { - // The Chaos Emerald begins to orbit us! - mobj_t *emmo; - UINT8 em = P_GetNextEmerald(); - tic_t lowest_time; - - if (player->mo->tracer) - { - // Only give it to ONE person, and THAT player has to get to the goal! - emmo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->info->height, MT_GOTEMERALD); - P_SetTarget(&emmo->target, player->mo); - P_SetMobjState(emmo, mobjinfo[MT_GOTEMERALD].meleestate + em); - P_SetTarget(&player->mo->tracer->target, emmo); - } - - // Okay, we're doing this down here because we're handling time weirdly for co-op special stages - // and because P_AddPlayerScore gives score to everyone in co-op special stages. - // Find the player with the lowest time remaining and award points based on that time instead. - lowest_time = player->finishedtime; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE) - if (players[i].finishedtime < lowest_time) - lowest_time = players[i].finishedtime; - P_AddPlayerScore(player, (lowest_time/TICRATE) * 100); - } - else - { - fixed_t z; - - z = player->capsule->z + player->capsule->height/2; - for (i = 0; i < 16; i++) - P_SpawnMobj(player->capsule->x, player->capsule->y, z, MT_BIRD); - } - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mare == player->mare) - P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead! - S_StartScreamSound(player->mo, sfx_ngdone); - } - } - else - { - S_StartScreamSound(player->mo, sfx_lose); - player->texttimer = 4*TICRATE; - player->textvar = 3; // Get more rings! - player->capsule->reactiontime = 0; - player->capsule->extravalue1 = -1; - } - } - else - player->capsule->extravalue1 = -1; -} - -// -// P_NiGHTSMovement -// -// Movement code for NiGHTS! -// -static void P_NiGHTSMovement(player_t *player) -{ - fixed_t drillamt = 0; - boolean still = false, moved = false, backwardaxis = false, firstdrill; - INT16 newangle = 0; - fixed_t xspeed, yspeed; - thinker_t *th; - mobj_t *mo2; - mobj_t *closestaxis = NULL; - fixed_t newx, newy, radius; - angle_t movingangle; - ticcmd_t *cmd = &player->cmd; - INT32 thrustfactor; - INT32 i; - statenum_t flystate = S_NIGHTSFLY1A; - - player->pflags &= ~PF_DRILLING; - - firstdrill = false; - - if (player->drillmeter > 96*20) - player->drillmeter = 96*20; - - if (player->drilldelay) - player->drilldelay--; - - if (!(cmd->buttons & BT_DRIFT)) - { - // Always have just a TINY bit of drill power. - if (player->drillmeter <= 0) - player->drillmeter = TICRATE/10; - } - - if (!player->mo->tracer) - { - P_DeNightserizePlayer(player); - return; - } - - if (G_IsSpecialStage(gamemap)) - { - boolean capsule = false; - // NiGHTS special stages have a pseudo-shared timer, so check if ANYONE is feeding the capsule. - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] - && (players[i].capsule && players[i].capsule->reactiontime)) - capsule = true; - if (!capsule - && !(player->mo->tracer->state >= &states[S_SUPERTRANS1] - && player->mo->tracer->state <= &states[S_SUPERTRANS9]) - && !player->exiting) - player->nightstime--; - } - else if (!G_RaceGametype() - && !(player->mo->tracer->state >= &states[S_SUPERTRANS1] && player->mo->tracer->state <= &states[S_SUPERTRANS9]) - && !(player->capsule && player->capsule->reactiontime) - && !player->exiting) - player->nightstime--; - - if (!player->nightstime) - { - P_DeNightserizePlayer(player); - S_StartScreamSound(player->mo, sfx_s3k66); -// S_StopSoundByNum(sfx_timeup); // Kill the "out of time" music, if it's playing. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH - P_RestoreMusic(player); // I have my doubts that this is the right place for this... - - return; - } - else if (P_IsLocalPlayer(player) && player->nightstime == 10*TICRATE) -// S_StartSound(NULL, sfx_timeup); // that creepy "out of time" music from NiGHTS. Dummied out, as some on the dev team thought it wasn't Sonic-y enough (Mystic, notably). Uncomment to restore. -SH - S_ChangeMusicInternal("drown",false); - - - if (player->mo->z < player->mo->floorz) - player->mo->z = player->mo->floorz; - - if (player->mo->z+player->mo->height > player->mo->ceilingz) - player->mo->z = player->mo->ceilingz - player->mo->height; - - newx = P_ReturnThrustX(player->mo, player->mo->angle, 3*FRACUNIT)+player->mo->x; - newy = P_ReturnThrustY(player->mo, player->mo->angle, 3*FRACUNIT)+player->mo->y; - - if (!player->mo->target) - { - fixed_t dist1, dist2 = 0; - - // scan the thinkers - // to find the closest axis point - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_AXIS) - { - if (mo2->threshold == player->mare) - { - if (closestaxis == NULL) - { - closestaxis = mo2; - dist2 = R_PointToDist2(newx, newy, mo2->x, mo2->y)-mo2->radius; - } - else - { - dist1 = R_PointToDist2(newx, newy, mo2->x, mo2->y)-mo2->radius; - - if (dist1 < dist2) - { - closestaxis = mo2; - dist2 = dist1; - } - } - } - } - } - - P_SetTarget(&player->mo->target, closestaxis); - } - - if (!player->mo->target) // Uh-oh! - { - CONS_Debug(DBG_NIGHTS, "No axis points found!\n"); - return; - } - - // The 'ambush' flag says you should rotate - // the other way around the axis. - if (player->mo->target->flags2 & MF2_AMBUSH) - backwardaxis = true; - - player->angle_pos = R_PointToAngle2(player->mo->target->x, player->mo->target->y, player->mo->x, player->mo->y); - - player->old_angle_pos = player->angle_pos; - - radius = player->mo->target->radius; - - player->mo->flags |= MF_NOGRAVITY; - player->mo->drawflags |= MFD_DONTDRAW; - P_SetScale(player->mo->tracer, player->mo->scale); - - if (player->mo->eflags & MFE_VERTICALFLIP) - cmd->forwardmove = (SINT8)(-cmd->forwardmove); - - if (!(player->pflags & PF_TRANSFERTOCLOSEST)) - { - fixed_t realdist = R_PointToDist2(player->mo->x, player->mo->y, player->mo->target->x, player->mo->target->y); - // teleport player to correct radius if neccessary - if (realdist>>FRACBITS != radius>>FRACBITS) - { - CONS_Debug(DBG_NIGHTS, "Aligning player with axis\n"); - P_UnsetThingPosition(player->mo); - if (realdist == 0) // other method won't work if we're exactly on the target lol - { - const angle_t fa = player->old_angle_pos>>ANGLETOFINESHIFT; - player->mo->x = player->mo->target->x + FixedMul(FINECOSINE(fa), radius); - player->mo->y = player->mo->target->y + FixedMul(FINESINE(fa), radius); - } - else - { - player->mo->x = player->mo->target->x + FixedMul(FixedDiv(player->mo->x - player->mo->target->x, realdist), radius); - player->mo->y = player->mo->target->y + FixedMul(FixedDiv(player->mo->y - player->mo->target->y, realdist), radius); - } - P_SetThingPosition(player->mo); - } - } - - // Currently reeling from being hit. - if (player->powers[pw_flashing] > (2*K_GetKartFlashing(player))/3) - { - { - const angle_t fa = (FixedAngle(player->flyangle*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - const fixed_t speed = FixedDiv(player->speed*FRACUNIT,50*FRACUNIT); - - xspeed = FixedMul(FINECOSINE(fa),speed); - yspeed = FixedMul(FINESINE(fa),speed); - } - - if (!(player->pflags & PF_TRANSFERTOCLOSEST)) - { - xspeed = FixedMul(xspeed, FixedDiv(1024*FRACUNIT, player->mo->target->radius)); - - if (backwardaxis) - xspeed *= -1; - - player->angle_pos += FixedAngleC(FixedDiv(xspeed,5*FRACUNIT),40*FRACUNIT); - } - - player->mo->momz = 0; - - P_NightsTransferPoints(player, xspeed, radius); - return; - } - - if (player->mo->tracer->state >= &states[S_SUPERTRANS1] - && player->mo->tracer->state <= &states[S_SUPERTRANS9]) - { - player->mo->momx = player->mo->momy = player->mo->momz = 0; - return; - } - - if (player->exiting > 0 && player->exiting < 2*TICRATE) - { - player->mo->momx = player->mo->momy = 0; - - if (!G_RaceGametype()) - P_SetObjectMomZ(player->mo, 30*FRACUNIT, false); - - player->mo->tracer->angle += ANGLE_11hh; - - if (!(player->mo->tracer->state >= &states[S_NIGHTSDRONE1] - && player->mo->tracer->state <= &states[S_NIGHTSDRONE2])) - P_SetMobjState(player->mo->tracer, S_NIGHTSDRONE1); - - player->mo->tracer->flags |= MF_NOCLIPHEIGHT; - player->mo->flags |= MF_NOCLIPHEIGHT; - return; - } - - // Spawn the little sparkles on each side of the player. - if (leveltime & 1) - { - mobj_t *firstmobj; - mobj_t *secondmobj; - fixed_t spawndist = FixedMul(16*FRACUNIT, player->mo->scale); - fixed_t z = player->mo->z + player->mo->height/2; - - if (player->mo->eflags & MFE_VERTICALFLIP) - z -= FixedMul(mobjinfo[MT_NIGHTSPARKLE].height, player->mo->scale); - - firstmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle+ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle+ANGLE_90, spawndist), z, MT_NIGHTSPARKLE); - secondmobj = P_SpawnMobj(player->mo->x + P_ReturnThrustX(player->mo, player->mo->angle-ANGLE_90, spawndist), player->mo->y + P_ReturnThrustY(player->mo, player->mo->angle-ANGLE_90, spawndist), z, MT_NIGHTSPARKLE); - - firstmobj->destscale = secondmobj->destscale = player->mo->scale; - P_SetTarget(&firstmobj->target, player->mo); - P_SetScale(firstmobj, player->mo->scale); - P_SetTarget(&secondmobj->target, player->mo); - P_SetScale(secondmobj, player->mo->scale); - - // Superloop turns sparkles red - if (player->powers[pw_nights_superloop]) - { - P_SetMobjState(firstmobj, mobjinfo[MT_NIGHTSPARKLE].seestate); - P_SetMobjState(secondmobj, mobjinfo[MT_NIGHTSPARKLE].seestate); - } - } - - // Paraloop helper is now separate from sparkles - // It also spawns every tic to avoid failed paraloops - { - mobj_t *helpermobj = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_NIGHTSLOOPHELPER); - helpermobj->fuse = player->mo->fuse = leveltime; - P_SetTarget(&helpermobj->target, player->mo); - P_SetScale(helpermobj, player->mo->scale); - } - - if (player->bumpertime) - { - player->jumping = 1; - player->pflags |= PF_DRILLING; - newangle = (INT16)player->flyangle; - } - else if (cmd->buttons & BT_DRIFT && player->drillmeter && player->drilldelay == 0) - { - if (!player->jumping) - firstdrill = true; - - player->jumping = 1; - player->pflags |= PF_DRILLING; - } - else - { - player->jumping = 0; - - if (cmd->sidemove != 0) - moved = true; - - if (player->drillmeter & 1) - player->drillmeter++; // I'll be nice and give them one. - } - - if (cmd->forwardmove != 0) - moved = true; - - if (!player->bumpertime) - { - if (moved) - { - if (player->pflags & PF_DRILLING) - drillamt += 100*FRACUNIT; - else - { - const fixed_t fforward = abs(cmd->forwardmove)*FRACUNIT; - const fixed_t fside = abs(cmd->sidemove)*FRACUNIT; - const fixed_t dist = FixedHypot(fforward, fside); - - drillamt += dist > 50*FRACUNIT ? 50*FRACUNIT : dist; - - // Accel up from 50 * 2.5 - drillamt = FixedMul(drillamt, 5*FRACUNIT/2); - } - if ((player->pflags & PF_DRILLING && player->speed < MAXDRILLSPEED) || player->speed < MAXNORMALSPEED) - player->speed += FixedInt(drillamt); - } - - if (player->pflags & PF_DRILLING) - { - if (player->speed < MAXDRILLSPEED) - player->speed += 150; - - if (--player->drillmeter == 0) - player->drilldelay = TICRATE*2; - } - - if (player->speed < 0) - player->speed = 0; - - if (!cmd->forwardmove) - { - if (cmd->sidemove > 0) - newangle = 0; - else if (cmd->sidemove < 0) - newangle = 180; - } - else if (!cmd->sidemove) - { - if (cmd->forwardmove > 0) - newangle = 90; - else if (cmd->forwardmove < 0) - newangle = 270; - } - else // AngleFixed(R_PointToAngle2()) results in slight inaccuracy! Don't use it unless movement is on both axises. - newangle = (INT16)FixedInt(AngleFixed(R_PointToAngle2(0,0, cmd->sidemove*FRACUNIT, cmd->forwardmove*FRACUNIT))); - - if (newangle < 0 && moved) - newangle = (INT16)(360+newangle); - } - - if (player->pflags & PF_DRILLING) - thrustfactor = 2; - else - { - thrustfactor = 8; - - // Decelerate while turning normally. - if (moved && player->flyangle != newangle && player->speed > 12000) - player->speed -= 60; - } - - for (i = 0; i < thrustfactor; i++) - { - if (moved && player->flyangle != newangle) - { - INT32 anglediff = (((newangle-player->flyangle)+360)%360); - INT32 angledif2 = (((player->flyangle-newangle)+360)%360); - - // player->flyangle is the one to move - // newangle is the "move to" - if (anglediff == 0 && angledif2 == 0) - break; - - if (anglediff>angledif2) - player->flyangle--; - else // if (anglediffflyangle++; - } - - // Buff out negatives, >360 angles... - player->flyangle = ((player->flyangle + 360) % 360); - } - - if (!(player->speed) - && cmd->forwardmove == 0) - still = true; - - // No more bumper braking - if (!player->bumpertime - && ((cmd->buttons & (BT_FORWARD|BT_BACKWARD)) == (BT_FORWARD|BT_BACKWARD) - || (cmd->buttons & BT_BRAKE))) - { - if (!(player->pflags & PF_SKIDDOWN)) - S_StartSound(player->mo, sfx_ngskid); - - // You can tap the button to only slow down a bit, - // or hold it to slow to a crawl as before, your choice. - if (player->speed > 8000) - player->speed -= 2000; - else if (player->speed > 1000) - player->speed -= (player->speed/4); - else { - player->speed -= 60; - if (player->speed < 0) - { - player->speed = 0; - still = true; - } - } - - player->pflags |= PF_SKIDDOWN; - } - else - player->pflags &= ~PF_SKIDDOWN; - - { - const angle_t fa = (FixedAngle(player->flyangle*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK; - const fixed_t speed = FixedDiv(player->speed*FRACUNIT,50*FRACUNIT); - xspeed = FixedMul(FINECOSINE(fa),speed); - yspeed = FixedMul(FINESINE(fa),speed); - } - - if (!(player->pflags & PF_TRANSFERTOCLOSEST)) - { - xspeed = FixedMul(xspeed, FixedDiv(1024*FRACUNIT, player->mo->target->radius)); - - if (backwardaxis) - xspeed *= -1; - - player->angle_pos += FixedAngleC(FixedDiv(xspeed,5*FRACUNIT),40*FRACUNIT); - } - - P_NightsTransferPoints(player, xspeed, radius); - - if (still) - player->mo->momz = -FRACUNIT; - else - player->mo->momz = yspeed/11; - - if (player->mo->momz > 20*FRACUNIT) - player->mo->momz = 20*FRACUNIT; - else if (player->mo->momz < -20*FRACUNIT) - player->mo->momz = -20*FRACUNIT; - - // You can create splashes as you fly across water. - if (((!(player->mo->eflags & MFE_VERTICALFLIP) - && player->mo->z + P_GetPlayerHeight(player) >= player->mo->watertop && player->mo->z <= player->mo->watertop) - || (player->mo->eflags & MFE_VERTICALFLIP - && player->mo->z + player->mo->height - P_GetPlayerHeight(player) <= player->mo->waterbottom && player->mo->z + player->mo->height >= player->mo->waterbottom)) - && player->speed > 9000 && leveltime % (TICRATE/7) == 0 && !player->spectator) - { - mobj_t *water = P_SpawnMobj(player->mo->x, player->mo->y, - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, player->mo->scale) : player->mo->watertop), MT_SPLISH); - if (player->mo->eflags & MFE_GOOWATER) - S_StartSound(water, sfx_ghit); - else - S_StartSound(water, sfx_wslap); - if (player->mo->eflags & MFE_VERTICALFLIP) - { - water->flags2 |= MF2_OBJECTFLIP; - water->eflags |= MFE_VERTICALFLIP; - } - water->destscale = player->mo->scale; - P_SetScale(water, player->mo->scale); - } - - if (player->mo->momx || player->mo->momy) - player->mo->angle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy); - - if (still) - { - player->anotherflyangle = 0; - movingangle = 0; - } - else - { - INT32 neg = 1; - - // Special cases to prevent the angle from being - // calculated incorrectly when wrapped. - if (backwardaxis && (player->old_angle_pos > ANG350 && player->angle_pos < ANG10)) - neg = -1; - else if (backwardaxis ^ (player->old_angle_pos < ANG10 && player->angle_pos > ANG350)) - neg = -1; - else if (player->angle_pos > player->old_angle_pos) - neg = -1; - - movingangle = R_PointToAngle2(0, 0, neg*R_PointToDist2(player->mo->momx, player->mo->momy, 0, 0), player->mo->momz); - player->anotherflyangle = (movingangle >> ANGLETOFINESHIFT) * 360/FINEANGLES; - } - - // NiGHTS flying state - // Yep, I just ripped out almost 1000 lines of code. - if ((player->anotherflyangle >= 12 && player->anotherflyangle <= 33) // +x +y - || (player->anotherflyangle >= 147 && player->anotherflyangle <= 168)) // -x +y - flystate = S_NIGHTSFLY2A; - else if ((player->anotherflyangle >= 34 && player->anotherflyangle <= 56) // +x +y - || (player->anotherflyangle >= 124 && player->anotherflyangle <= 146)) // -x +y - flystate = S_NIGHTSFLY3A; - else if ((player->anotherflyangle >= 57 && player->anotherflyangle <= 79) // +x +y - || (player->anotherflyangle >= 102 && player->anotherflyangle <= 123)) // -x +y - flystate = S_NIGHTSFLY4A; - else if (player->anotherflyangle >= 80 && player->anotherflyangle <= 101) - flystate = S_NIGHTSFLY5A; - else if ((player->anotherflyangle >= 192 && player->anotherflyangle <= 213) // -x -y - || (player->anotherflyangle >= 327 && player->anotherflyangle <= 348)) // +x -y - flystate = S_NIGHTSFLY6A; - else if ((player->anotherflyangle >= 214 && player->anotherflyangle <= 236) // -x -y - || (player->anotherflyangle >= 305 && player->anotherflyangle <= 326)) // +x -y - flystate = S_NIGHTSFLY7A; - else if ((player->anotherflyangle >= 237 && player->anotherflyangle <= 258) // -x -y - || (player->anotherflyangle >= 282 && player->anotherflyangle <= 304)) // +x -y - flystate = S_NIGHTSFLY8A; - else if (player->anotherflyangle >= 259 && player->anotherflyangle <= 281) - flystate = S_NIGHTSFLY9A; - else - flystate = S_NIGHTSFLY1A; - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if (flystate >= S_NIGHTSFLY2A && flystate <= S_NIGHTSFLY5A) - flystate += 24; // shift to S_NIGHTSFLY6A - else if (flystate >= S_NIGHTSFLY6A && flystate <= S_NIGHTSFLY9A) - flystate -= 24; // shift to S_NIGHTSFLY2A - } - - if (player->pflags & PF_DRILLING) - { - const statenum_t drillstate = flystate + 2; - - if (!(player->mo->tracer->state >= &states[drillstate] - && player->mo->tracer->state <= &states[drillstate+4])) - { - if (!(player->mo->tracer->state >= &states[S_NIGHTSFLY1A] - && player->mo->tracer->state <= &states[S_NIGHTSFLY9B])) - { - const INT32 framenum = player->mo->tracer->state->frame & 3; - - if (framenum == 3) // Drilld special case - P_SetMobjStateNF(player->mo->tracer, drillstate); - else - P_SetMobjStateNF(player->mo->tracer, drillstate+framenum+1); - } - else - P_SetMobjStateNF(player->mo->tracer, drillstate); - } - } - else - P_SetMobjStateNF(player->mo->tracer, leveltime & 1 ? flystate : flystate+1); - - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; - - if (still) - { - P_SetMobjStateNF(player->mo->tracer, S_NIGHTSDRONE1); - player->mo->tracer->angle = player->mo->angle; - } - - // Check for crushing in our new location - if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) - && !(player->mo->flags & MF_NOCLIP)) - { - // Flashing won't run out until you STOP being crushed. - if (player->powers[pw_flashing] == 1) - player->powers[pw_flashing] = 3; - else - P_DamageMobj(player->mo, NULL, NULL, 1); - } - - if (movingangle >= ANGLE_90 && movingangle <= ANGLE_180) - movingangle = movingangle - ANGLE_180; - else if (movingangle >= ANGLE_180 && movingangle <= ANGLE_270) - movingangle = movingangle - ANGLE_180; - else if (movingangle >= ANGLE_270) - movingangle = InvAngle(movingangle); - - if (player == &players[consoleplayer]) - localaiming[0] = movingangle; - else if (player == &players[displayplayers[1]]) - localaiming[1] = movingangle; - else if (player == &players[displayplayers[2]]) - localaiming[2] = movingangle; - else if (player == &players[displayplayers[3]]) - localaiming[3] = movingangle; - - player->mo->tracer->angle = player->mo->angle; - - if ((player->pflags & PF_DRILLING) && !player->bumpertime) - { - if (firstdrill) - { - S_StartSound(player->mo, sfx_drill1); - player->drilltimer = 32; - } - else if (--player->drilltimer <= 0) - { - player->drilltimer = 10; - S_StartSound(player->mo, sfx_drill2); - } - } - - if (objectplacing) - OP_NightsObjectplace(player); -}*/ - -// May be used in future for CTF -#if 0 -static void P_PlayerDropWeapon(player_t *player) -{ - mobj_t *mo = NULL; - - if (player->powers[pw_homingring]) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+(60*FRACUNIT), MT_HOMINGRING); - player->powers[pw_homingring] = 0; - } - else if (player->powers[pw_railring]) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+(60*FRACUNIT), MT_RAILRING); - player->powers[pw_railring] = 0; - } - else if (player->powers[pw_automaticring]) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+(60*FRACUNIT), MT_AUTOMATICRING); - player->powers[pw_automaticring] = 0; - } - else if (player->powers[pw_explosionring]) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+(60*FRACUNIT), MT_EXPLOSIONRING); - player->powers[pw_explosionring] = 0; - } - else if (player->powers[pw_scatterring]) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+(60*FRACUNIT), MT_SCATTERRING); - player->powers[pw_scatterring] = 0; - } - else if (player->powers[pw_grenadering]) - { - mo = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z+(60*FRACUNIT), MT_GRENADERING); - player->powers[pw_grenadering] = 0; - } - - if (mo) - { - player->mo->health--; - P_InstaThrust(mo, player->mo->angle-ANGLE_180, 8*FRACUNIT); - P_SetObjectMomZ(mo, 4*FRACUNIT, false); - mo->flags2 |= MF2_DONTRESPAWN; - mo->flags &= ~MF_NOGRAVITY; - mo->flags &= ~MF_NOCLIPHEIGHT; - mo->fuse = 12*TICRATE; - } -} -#endif - -void P_BlackOw(player_t *player) -{ - INT32 i; - S_StartSound (player->mo, sfx_bkpoof); // Sound the BANG! - - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && P_AproxDistance(player->mo->x - players[i].mo->x, - player->mo->y - players[i].mo->y) < 1536*FRACUNIT) - P_FlashPal(&players[i], PAL_NUKE, 10); - - P_NukeEnemies(player->mo, player->mo, 1536*FRACUNIT); // Search for all nearby enemies and nuke their pants off! - player->powers[pw_shield] = player->powers[pw_shield] & SH_STACK; -} - -void P_ElementalFireTrail(player_t *player) -{ - fixed_t newx; - fixed_t newy; - fixed_t ground; - mobj_t *flame; - angle_t travelangle; - INT32 i; - - I_Assert(player != NULL); - I_Assert(player->mo != NULL); - I_Assert(!P_MobjWasRemoved(player->mo)); - - if (player->mo->eflags & MFE_VERTICALFLIP) - ground = player->mo->ceilingz - FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale); - else - ground = player->mo->floorz; - - travelangle = R_PointToAngle2(0, 0, player->rmomx, player->rmomy); - - for (i = 0; i < 2; i++) - { - newx = player->mo->x + P_ReturnThrustX(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale)); - newy = player->mo->y + P_ReturnThrustY(player->mo, travelangle + ((i&1) ? -1 : 1)*ANGLE_135, FixedMul(24*FRACUNIT, player->mo->scale)); -#ifdef ESLOPE - if (player->mo->standingslope) - { - ground = P_GetZAt(player->mo->standingslope, newx, newy); - if (player->mo->eflags & MFE_VERTICALFLIP) - ground -= FixedMul(mobjinfo[MT_SPINFIRE].height, player->mo->scale); - } -#endif - flame = P_SpawnMobj(newx, newy, ground, MT_SPINFIRE); - P_SetTarget(&flame->target, player->mo); - flame->angle = travelangle; - flame->fuse = TICRATE*6; - flame->destscale = player->mo->scale; - P_SetScale(flame, player->mo->scale); - flame->eflags = (flame->eflags & ~MFE_VERTICALFLIP)|(player->mo->eflags & MFE_VERTICALFLIP); - - flame->momx = 8; - P_XYMovement(flame); - if (P_MobjWasRemoved(flame)) - continue; - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if (flame->z + flame->height < flame->ceilingz) - P_RemoveMobj(flame); - } - else if (flame->z > flame->floorz) - P_RemoveMobj(flame); - } } // // P_MovePlayer -static void P_MovePlayer(player_t *player) +void P_MovePlayer(player_t *player) { ticcmd_t *cmd; //INT32 i; @@ -5622,14 +2118,6 @@ static void P_MovePlayer(player_t *player) if (countdowntimeup) return; - /* // SRB2kart - junk - if (player->mo->state >= &states[S_PLAY_SUPERTRANS1] && player->mo->state <= &states[S_PLAY_SUPERTRANS9]) - { - player->mo->momx = player->mo->momy = player->mo->momz = 0; - return; - } - */ - cmd = &player->cmd; runspd = 14*player->mo->scale; //srb2kart @@ -5639,234 +2127,63 @@ static void P_MovePlayer(player_t *player) runspd = FixedMul(runspd, player->mo->movefactor); // Control relinquishing stuff! - if (player->powers[pw_ingoop]) - player->pflags |= PF_FULLSTASIS; - else if (player->pflags & PF_GLIDING && player->skidtime) - player->pflags |= PF_FULLSTASIS; - else if (player->powers[pw_nocontrol]) + if (player->powers[pw_nocontrol]) { player->pflags |= PF_STASIS; if (!(player->powers[pw_nocontrol] & (1<<15))) player->pflags |= PF_JUMPSTASIS; } + // note: don't unset stasis here - if (!player->spectator && G_TagGametype()) - { - // If we have stasis already here, it's because it's forced on us - // by a linedef executor or what have you - boolean forcestasis = false; - - //During hide time, taggers cannot move. - if (leveltime < hidetime * TICRATE) - { - if (player->pflags & PF_TAGIT) - forcestasis = true; - } - else if (gametype == GT_HIDEANDSEEK) - { - if (!(player->pflags & PF_TAGIT)) - { - forcestasis = true; - if (player->pflags & PF_TAGGED) // Already hit. - player->powers[pw_flashing] = 5; - } - } - - if (forcestasis) - { - player->pflags |= PF_FULLSTASIS; - // If you're in stasis in tag, you don't drown. - /*if (player->powers[pw_underwater] <= 12*TICRATE + 1) - P_RestoreMusic(player);*/ - player->powers[pw_underwater] = player->powers[pw_spacetime] = 0; - } - } - if (player->spectator) { + player->mo->eflags &= ~MFE_VERTICALFLIP; // deflip... P_SpectatorMovement(player); return; } - // Locate the capsule for this mare. - /*else if (maptol & TOL_NIGHTS) - { - if (!player->capsule && !player->bonustime) - { - thinker_t *th; - mobj_t *mo2; - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type == MT_EGGCAPSULE - && mo2->threshold == player->mare) - P_SetTarget(&player->capsule, mo2); - } - } - else if (player->capsule && player->capsule->reactiontime > 0 && player == &players[player->capsule->reactiontime-1]) - { - P_DoNiGHTSCapsule(player); - return; - } - - // Test revamped NiGHTS movement. - if (player->pflags & PF_NIGHTSMODE) - { - P_NiGHTSMovement(player); - // No more goto blockchecking, let's just do all that here =D - if (CheckForBustableBlocks) - P_CheckBustableBlocks(player); - if (CheckForBouncySector) - P_CheckBouncySectors(player); - if (CheckForQuicksand) - P_CheckQuicksand(player); - return; - } - - if (player->pflags & PF_NIGHTSFALL && P_IsObjectOnGround(player->mo)) - { - if (G_IsSpecialStage(gamemap)) - { - if (player == &players[displayplayers[0]]) // only play the sound for yourself landing - S_StartSound(NULL, sfx_s3k6a); - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i]) - players[i].exiting = raceexittime+1; - } - else if (player->health > 1) - P_DamageMobj(player->mo, NULL, NULL, 1); - player->pflags &= ~PF_NIGHTSFALL; - } - }*/ - ////////////////////// // MOVEMENT CODE // ////////////////////// - /*if (twodlevel || player->mo->flags2 & MF2_TWOD) // 2d-level, so special control applies. - P_2dMovement(player); - else*/ - { - INT16 angle_diff, max_left_turn, max_right_turn; - boolean add_delta = true; + P_UpdatePlayerAngle(player); - // Kart: store the current turn range for later use - player->lturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, KART_FULLTURN)+1; - player->rturn_max[leveltime%MAXPREDICTTICS] = K_GetKartTurnValue(player, -KART_FULLTURN)-1; + ticruned++; + if (!(cmd->flags & TICCMD_RECEIVED)) + ticmiss++; - if (leveltime >= introtime) - { - // KART: Don't directly apply angleturn! It may have been either A) forged by a malicious client, or B) not be a smooth turn due to a player dropping frames. - // Instead, turn the player only up to the amount they're supposed to turn accounting for latency. Allow exactly 1 extra turn unit to try to keep old replays synced. - angle_diff = cmd->angleturn - (player->mo->angle>>16); - max_left_turn = player->lturn_max[(leveltime + MAXPREDICTTICS - cmd->latency) % MAXPREDICTTICS]; - max_right_turn = player->rturn_max[(leveltime + MAXPREDICTTICS - cmd->latency) % MAXPREDICTTICS]; - - //CONS_Printf("----------------\nangle diff: %d - turning options: %d to %d - ", angle_diff, max_left_turn, max_right_turn); - - if (angle_diff > max_left_turn) - angle_diff = max_left_turn; - else if (angle_diff < max_right_turn) - angle_diff = max_right_turn; - else - { - // Try to keep normal turning as accurate to 1.0.1 as possible to reduce replay desyncs. - player->mo->angle = cmd->angleturn<<16; - add_delta = false; - } - //CONS_Printf("applied turn: %d\n", angle_diff); - - if (add_delta) { - player->mo->angle += angle_diff<<16; - player->mo->angle &= ~0xFFFF; // Try to keep the turning somewhat similar to how it was before? - //CONS_Printf("leftover turn (%s): %5d or %4d%%\n", - // player_names[player-players], - // (INT16) (cmd->angleturn - (player->mo->angle>>16)), - // (INT16) (cmd->angleturn - (player->mo->angle>>16)) * 100 / (angle_diff ? angle_diff : 1)); - } - } - - ticruned++; - if ((cmd->angleturn & TICCMD_RECEIVED) == 0) - ticmiss++; - - P_3dMovement(player); - } - - if (maptol & TOL_2D) - runspd = FixedMul(runspd, 2*FRACUNIT/3); - - //P_SkidStuff(player); - - ///////////////////////// - // MOVEMENT ANIMATIONS // - ///////////////////////// - - /* - if ((cmd->forwardmove != 0 || cmd->sidemove != 0) || (player->powers[pw_super] && player->mo->z > player->mo->floorz)) - { - // If the player is moving fast enough, - // break into a run! - if (player->speed >= runspd && player->panim == PA_WALK && !player->skidtime && (onground || player->powers[pw_super])) - P_SetPlayerMobjState (player->mo, S_KART_FAST1); // SRB2kart - was S_PLAY_SPD1 - - // Otherwise, just walk. - else if ((player->rmomx || player->rmomy) && player->panim == PA_IDLE) - P_SetPlayerMobjState (player->mo, S_KART_SLOW1); // SRB2kart - was S_PLAY_RUN1 - } - */ - - // If your running animation is playing, and you're - // going too slow, switch back to the walking frames. - //if (player->panim == PA_RUN && player->speed < runspd && player->kartstuff[k_spinouttimer] == 0) - //P_SetPlayerMobjState(player->mo, S_KART_SLOW1); // SRB2kart - was S_PLAY_RUN1 - - // If Springing, but travelling DOWNWARD, change back! - //if (player->mo->state == &states[S_PLAY_SPRING] && P_MobjFlip(player->mo)*player->mo->momz < 0) - // P_SetPlayerMobjState(player->mo, S_PLAY_FALL1); - // If Springing but on the ground, change back! - //else if (onground && (player->mo->state == &states[S_PLAY_SPRING] || player->panim == PA_FALL || player->mo->state == &states[S_PLAY_CARRY]) && !player->mo->momz) - // P_SetPlayerMobjState(player->mo, S_PLAY_STND); + P_3dMovement(player); // Kart frames if (player->kartstuff[k_squishedtimer] > 0) { - if (player->mo->state != &states[S_KART_SQUISH]) - P_SetPlayerMobjState(player->mo, S_KART_SQUISH); + P_SetPlayerMobjState(player->mo, S_KART_SQUISH); } else if (player->pflags & PF_SLIDING) { - if (player->mo->state != &states[S_KART_SPIN]) - P_SetPlayerMobjState(player->mo, S_KART_SPIN); - player->frameangle -= ANGLE_22h; + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); + player->drawangle -= ANGLE_22h; } else if (player->kartstuff[k_spinouttimer] > 0) { INT32 speed = max(1, min(8, player->kartstuff[k_spinouttimer]/8)); - if (player->mo->state != &states[S_KART_SPIN]) - P_SetPlayerMobjState(player->mo, S_KART_SPIN); + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); - if (speed == 1 && abs((signed)(player->mo->angle - player->frameangle)) < ANGLE_22h) - player->frameangle = player->mo->angle; // Face forward at the end of the animation + if (speed == 1 && abs((signed)(player->mo->angle - player->drawangle)) < ANGLE_22h) + player->drawangle = player->mo->angle; // Face forward at the end of the animation else - player->frameangle -= (ANGLE_11hh * speed); + player->drawangle -= (ANGLE_11hh * speed); } - else if (player->powers[pw_nocontrol] && player->pflags & PF_SKIDDOWN) + else if (player->pflags & PF_FAULT) { - if (player->mo->state != &states[S_KART_SPIN]) - P_SetPlayerMobjState(player->mo, S_KART_SPIN); + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); if (((player->powers[pw_nocontrol] + 5) % 20) < 10) - player->frameangle += ANGLE_11hh; + player->drawangle += ANGLE_11hh; else - player->frameangle -= ANGLE_11hh; + player->drawangle -= ANGLE_11hh; } else { @@ -5874,20 +2191,20 @@ static void P_MovePlayer(player_t *player) if (player->trickpanel == 2) { - player->frameangle += ANGLE_22h; + player->drawangle += ANGLE_22h; } else if (player->trickpanel == 3) { - player->frameangle -= ANGLE_22h; + player->drawangle -= ANGLE_22h; } else { - player->frameangle = player->mo->angle; + player->drawangle = player->mo->angle; if (player->kartstuff[k_drift] != 0) { INT32 a = (ANGLE_45 / 5) * player->kartstuff[k_drift]; - player->frameangle += a; + player->drawangle += a; } } } @@ -5910,120 +2227,10 @@ static void P_MovePlayer(player_t *player) K_MoveKartPlayer(player, onground); //} - ////////////////// //GAMEPLAY STUFF// ////////////////// - // Make sure you're not "jumping" on the ground - if (onground && player->pflags & PF_JUMPED && !(player->pflags & PF_GLIDING) - && P_MobjFlip(player->mo)*player->mo->momz < 0) - { - player->pflags &= ~PF_JUMPED; - player->jumping = 0; - player->secondjump = 0; - player->pflags &= ~PF_THOKKED; - P_SetPlayerMobjState(player->mo, S_KART_STILL1); // SRB2kart - was S_PLAY_STND - } - - if (/*!(player->charability == CA_GLIDEANDCLIMB) ||*/ player->gotflag) // If you can't glide, then why the heck would you be gliding? - { - /* // SRB2kart - ??? - if (player->pflags & PF_GLIDING || player->climbing) - { - if (onground) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN1); - else - { - player->pflags |= PF_JUMPED; - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } - } - */ - player->pflags &= ~PF_GLIDING; - player->glidetime = 0; - player->climbing = 0; - } - - // Glide MOMZ - // AKA my own gravity. =) - /* // SRB2kart - gliding is illegal, go to jail - if (player->pflags & PF_GLIDING) - { - fixed_t leeway; - fixed_t glidespeed = player->actionspd; - - if (player->powers[pw_super]) - glidespeed *= 2; - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if (player->mo->momz > FixedMul(2*FRACUNIT, player->mo->scale)) - player->mo->momz -= FixedMul(3*(FRACUNIT/4), player->mo->scale); - } - else - { - if (player->mo->momz < FixedMul(-2*FRACUNIT, player->mo->scale)) - player->mo->momz += FixedMul(3*(FRACUNIT/4), player->mo->scale); - } - - // Strafing while gliding. - leeway = FixedAngle(cmd->sidemove*(FRACUNIT/2)); - - if (player->skidtime) // ground gliding - { - fixed_t speed = FixedMul(glidespeed, FRACUNIT - (FRACUNIT>>2)); - if (player->mo->eflags & MFE_UNDERWATER) - speed >>= 1; - speed = FixedMul(speed - player->glidetime*FRACUNIT, player->mo->scale); - if (speed < 0) - speed = 0; - P_InstaThrust(player->mo, player->mo->angle-leeway, speed); - } - else if (player->mo->eflags & MFE_UNDERWATER) - P_InstaThrust(player->mo, player->mo->angle-leeway, FixedMul((glidespeed>>1) + player->glidetime*750, player->mo->scale)); - else - P_InstaThrust(player->mo, player->mo->angle-leeway, FixedMul(glidespeed + player->glidetime*1500, player->mo->scale)); - - player->glidetime++; - - if (!(player->pflags & PF_JUMPDOWN)) // If not holding the jump button - { - P_ResetPlayer(player); // down, stop gliding. - if (onground) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN1); - else if ((player->charability2 == CA2_MULTIABILITY) - || (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && player->charability == CA_GLIDEANDCLIMB)) - { - player->pflags |= PF_JUMPED; - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } - else - { - player->pflags |= PF_THOKKED; - player->mo->momx >>= 1; - player->mo->momy >>= 1; - P_SetPlayerMobjState(player->mo, S_PLAY_FALL1); - } - } - } - else if (player->climbing) // 'Deceleration' for climbing on walls. - { - if (player->mo->momz > 0) - { - player->mo->momz -= FixedMul(FRACUNIT/2, player->mo->scale); - if (player->mo->momz < 0) - player->mo->momz = 0; - } - else if (player->mo->momz < 0) - { - player->mo->momz += FixedMul(FRACUNIT/2, player->mo->scale); - if (player->mo->momz > 0) - player->mo->momz = 0; - } - } - */ - // If you're running fast enough, you can create splashes as you run in shallow water. #if 0 if (!player->climbing @@ -6032,10 +2239,13 @@ static void P_MovePlayer(player_t *player) && (player->speed > runspd || (player->pflags & PF_STARTDASH)) && leveltime % (TICRATE/7) == 0 && player->mo->momz == 0 && !(player->pflags & PF_SLIDING) && !player->spectator) { - mobj_t *water = P_SpawnMobj(player->mo->x, player->mo->y, - ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[MT_SPLISH].height, player->mo->scale) : player->mo->watertop), MT_SPLISH); + mobjtype_t splishtype = (player->mo->eflags & MFE_TOUCHLAVA) ? MT_LAVASPLISH : MT_SPLISH; + mobj_t *water = P_SpawnMobj(player->mo->x - P_ReturnThrustX(NULL, player->mo->angle, player->mo->radius), player->mo->y - P_ReturnThrustY(NULL, player->mo->angle, player->mo->radius), + ((player->mo->eflags & MFE_VERTICALFLIP) ? player->mo->waterbottom - FixedMul(mobjinfo[splishtype].height, player->mo->scale) : player->mo->watertop), splishtype); if (player->mo->eflags & MFE_GOOWATER) S_StartSound(water, sfx_ghit); + else if (player->mo->eflags & MFE_TOUCHLAVA) + S_StartSound(water, sfx_splash); else S_StartSound(water, sfx_wslap); if (player->mo->eflags & MFE_VERTICALFLIP) @@ -6131,100 +2341,6 @@ static void P_MovePlayer(player_t *player) S_StartSound(player->mo, sfx_floush); } - //////////////// - //TAILS FLYING// - //////////////// - - /* // SRB2kart - nah - if (!(player->charability == CA_FLY || player->charability == CA_SWIM)) // why are you flying when you cannot fly?! - { - if (player->powers[pw_tailsfly] - || (player->mo->state >= &states[S_PLAY_SPC1] && player->mo->state <= &states[S_PLAY_SPC4])) - { - if (onground) - P_SetPlayerMobjState(player->mo, S_PLAY_RUN1); - else - { - player->pflags |= PF_JUMPED; - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } - } - player->powers[pw_tailsfly] = 0; - } - - if (player->gotflag && player->powers[pw_tailsfly]) - player->powers[pw_tailsfly] = 1; - - // If not in a fly position, don't think you're flying! - if (player->panim != PA_ABILITY) - player->powers[pw_tailsfly] = 0; - - if (player->charability == CA_FLY || (player->charability == CA_SWIM && player->mo->eflags & MFE_UNDERWATER)) - { - // Fly counter for Tails. - if (player->powers[pw_tailsfly]) - { - const fixed_t actionspd = player->actionspd/100; - - if (player->charability2 == CA2_MULTIABILITY) - { - // Adventure-style flying by just holding the button down - if (cmd->buttons & BT_DRIFT && !(player->pflags & PF_STASIS) && !player->exiting) - P_SetObjectMomZ(player->mo, actionspd/4, true); - } - else - { - // Classic flying - if (player->fly1) - { - if (P_MobjFlip(player->mo)*player->mo->momz < FixedMul(5*actionspd, player->mo->scale)) - P_SetObjectMomZ(player->mo, actionspd/2, true); - - player->fly1--; - } - } - - // Tails Put-Put noise - if (player->charability == CA_FLY && player->bot != 1 && leveltime % 10 == 0 && !player->spectator) - S_StartSound(player->mo, sfx_putput); - - // Descend - if (cmd->buttons & BT_BRAKE && !(player->pflags & PF_STASIS) && !player->exiting) - if (P_MobjFlip(player->mo)*player->mo->momz > -FixedMul(5*actionspd, player->mo->scale)) - P_SetObjectMomZ(player->mo, -actionspd/2, true); - - } - else - { - // Tails-gets-tired Stuff - if (player->panim == PA_ABILITY) - P_SetPlayerMobjState(player->mo, S_PLAY_SPC4); - - if (player->charability == CA_FLY && (leveltime % 10 == 0) - && player->mo->state >= &states[S_PLAY_SPC1] - && player->mo->state <= &states[S_PLAY_SPC4] - && !player->spectator) - S_StartSound(player->mo, sfx_pudpud); - } - } - - // End your chain if you're on the ground or climbing a wall. - // But not if invincible! Allow for some crazy long chains with it. - // Also keep in mind the PF_JUMPED check. - // If we lacked this, stepping up while jumping up would reset score. - // (for instance, when climbing up off a wall.) - if ((onground || player->climbing) && !(player->pflags & PF_JUMPED) && player->powers[pw_invulnerability] <= 1) - P_ResetScore(player); - - // Show the "THOK!" graphic when spinning quickly across the ground. (even applies to non-spinners, in the case of zoom tubes) - if (player->pflags & PF_SPINNING && player->speed > FixedMul(15<mo->scale) && !(player->pflags & PF_JUMPED)) - { - P_SpawnSpinMobj(player, player->spinitem); - if (demo.recording) - G_GhostAddSpin((INT32) (player - players)); - } - */ - //////////////////////////// //SPINNING AND SPINDASHING// //////////////////////////// @@ -6242,219 +2358,17 @@ static void P_MovePlayer(player_t *player) K_DriftDustHandling(player->mo); - /* // SRB2kart - nadah - // If the player isn't on the ground, make sure they aren't in a "starting dash" position. - if (!onground) - { - player->pflags &= ~PF_STARTDASH; - player->dashspeed = 0; - } - - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL - && (player->pflags & PF_SPINNING) && player->speed > FixedMul(4<mo->scale) && onground && (leveltime & 1) - && !(player->mo->eflags & (MFE_UNDERWATER|MFE_TOUCHWATER))) - P_ElementalFireTrail(player); - - P_DoSpinDash(player, cmd); - */ - // jumping - //P_DoJumpStuff(player, cmd); - - /* - // If you're not spinning, you'd better not be spindashing! - if (!(player->pflags & PF_SPINNING)) - player->pflags &= ~PF_STARTDASH; - */ - - /////////////////////////// - //BOMB SHIELD ACTIVATION,// - //HOMING, AND OTHER COOL // - //STUFF! // - /////////////////////////// - - /* // SRB2kart - what's a shield? Never heard of it. Never happened. Nope. - if (cmd->buttons & BT_BRAKE) // Spin button effects - { - if (player->pflags & PF_JUMPED) // If the player is jumping - { - if (!(player->pflags & PF_USEDOWN)) // If the player is not holding down BT_BRAKE - { - // Jump shield activation - if (!P_PlayerInPain(player) // If the player is not in pain - && !player->climbing // If the player is not climbing - && !(player->pflags & (PF_GLIDING|PF_SLIDING|PF_THOKKED)) // If the player is not gliding or sliding and hasn't used their ability - && !onground) // If the player isn't on the ground - { - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_JUMP && !player->powers[pw_super]) - P_DoJumpShield(player); - else if (player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]) && player->charability == CA_FLY) - { - P_DoJumpShield(player); - player->mo->momz *= 2; - } - } - // Bomb shield activation - if ((player->powers[pw_shield] & SH_NOSTACK) == SH_BOMB) - { - // Don't let Super Sonic or invincibility use it - if (!(player->powers[pw_super] || player->powers[pw_invulnerability])) - P_BlackOw(player); - } - } - // Super Sonic move - if (player->skin == 0 && player->powers[pw_super] && player->speed > FixedMul(5<mo->scale) - && P_MobjFlip(player->mo)*player->mo->momz <= 0) - { - if (player->panim == PA_ROLL || player->mo->state == &states[S_PLAY_PAIN]) - P_SetPlayerMobjState(player->mo, S_PLAY_SUPERWALK1); - - player->mo->momz = 0; - player->pflags &= ~PF_SPINNING; - player->jumping = 0; // don't cut jump height after bouncing off something - } - } - } - - // HOMING option. - if (player->charability == CA_HOMINGTHOK) - { - // If you've got a target, chase after it! - if (player->homing && player->mo->tracer) - { - P_SpawnThokMobj(player); - P_HomingAttack(player->mo, player->mo->tracer); - - // But if you don't, then stop homing. - if (player->mo->tracer->health <= 0 || (player->mo->tracer->flags2 & MF2_FRET)) - { - if (player->mo->eflags & MFE_UNDERWATER) - P_SetObjectMomZ(player->mo, FixedDiv(457*FRACUNIT,72*FRACUNIT), false); - else - P_SetObjectMomZ(player->mo, 10*FRACUNIT, false); - - player->mo->momx = player->mo->momy = player->homing = 0; - - if (player->mo->tracer->flags2 & MF2_FRET) - P_InstaThrust(player->mo, player->mo->angle, -(player->speed>>3)); - - if (!(player->mo->tracer->flags & MF_BOSS)) - player->pflags &= ~PF_THOKKED; - } - } - - // If you're not jumping, then you obviously wouldn't be homing. - if (!(player->pflags & PF_JUMPED)) - player->homing = 0; - } - else - player->homing = 0; - - if (player->climbing == 1) - P_DoClimbing(player); - - if (player->climbing > 1) - { - P_InstaThrust(player->mo, player->mo->angle, FixedMul(4*FRACUNIT, player->mo->scale)); // Shove up against the wall - player->climbing--; - } - - if (!player->climbing) - { - player->lastsidehit = -1; - player->lastlinehit = -1; - } - - // Make sure you're not teetering when you shouldn't be. - if ((player->mo->state == &states[S_PLAY_TEETER1] || player->mo->state == &states[S_PLAY_TEETER2] || player->mo->state == &states[S_PLAY_SUPERTEETER]) - && (player->mo->momx || player->mo->momy || player->mo->momz)) - P_SetPlayerMobjState(player->mo, S_PLAY_STND); - - // Check for teeter! - if (!(player->mo->momz || player->mo->momx || player->mo->momy) && !(player->mo->eflags & MFE_GOOWATER) - && player->panim == PA_IDLE && !(player->pflags & (PF_CARRIED|PF_ITEMHANG|PF_ROPEHANG))) - P_DoTeeter(player); - - // Toss a flag - if (G_GametypeHasTeams() && (cmd->buttons & BT_SPECTATE) && !(player->powers[pw_super]) && !(player->tossdelay)) - { - if (!(player->gotflag & (GF_REDFLAG|GF_BLUEFLAG))) - P_PlayerEmeraldBurst(player, true); // Toss emeralds - else - P_PlayerFlagBurst(player, true); - } - - // check for fire - if (!player->exiting) - P_DoFiring(player, cmd); - - { - fixed_t oldheight = player->mo->height; - - // Less height while spinning. Good for spinning under things...? - if ((player->mo->state == &states[player->mo->info->painstate] || player->mo->state == &states[S_PLAY_SUPERHIT]) - || (player->charability2 == CA2_SPINDASH && (player->pflags & (PF_SPINNING|PF_JUMPED))) - || player->powers[pw_tailsfly] || player->pflags & PF_GLIDING - || (player->charability == CA_FLY && (player->mo->state >= &states[S_PLAY_SPC1] && player->mo->state <= &states[S_PLAY_SPC4]))) - player->mo->height = P_GetPlayerSpinHeight(player); - else - player->mo->height = P_GetPlayerHeight(player); - - if (player->mo->eflags & MFE_VERTICALFLIP && player->mo->height != oldheight) // adjust z height for reverse gravity, similar to how it's done for scaling - player->mo->z -= player->mo->height - oldheight; - } - */ - // Crush test... - if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) - && !(player->mo->flags & MF_NOCLIP)) + if ((player->mo->ceilingz - player->mo->floorz < player->mo->height) && !(player->mo->flags & MF_NOCLIP)) { - /* // SRB2kart - no, we're not making the playerspin - if ((player->charability2 == CA2_SPINDASH) && !(player->pflags & PF_SPINNING)) - { - player->pflags |= PF_SPINNING; - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } - else */if (player->mo->ceilingz - player->mo->floorz < player->mo->height) - { - if ((netgame || multiplayer) && player->spectator) - P_DamageMobj(player->mo, NULL, NULL, 42000); // Respawn crushed spectators - else - { - K_SquishPlayer(player, NULL, NULL); // SRB2kart - we don't kill when squished, we squish when squished. - /* - mobj_t *killer = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_NULL); - killer->threshold = 44; // Special flag that it was crushing which killed you. - P_DamageMobj(player->mo, killer, killer, 10000); - */ - } - - if (player->playerstate == PST_DEAD) - return; - } - } - -#ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none && cv_grfovchange.value) - { - fixed_t speed; - const fixed_t runnyspeed = 20*FRACUNIT; - - speed = R_PointToDist2(player->rmomx, player->rmomy, 0, 0); - - if (speed > K_GetKartSpeed(player, false)-(5<= runnyspeed) - player->fovadd = speed-runnyspeed; + if ((netgame || multiplayer) && player->spectator) + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_SPECTATOR); // Respawn crushed spectators else - player->fovadd = 0; + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_CRUSHED); - if (player->fovadd < 0) - player->fovadd = 0; + if (player->playerstate == PST_DEAD) + return; } - else - player->fovadd = 0; -#endif #ifdef FLOORSPLATS if (cv_shadow.value && rendermode == render_soft) @@ -6475,20 +2389,18 @@ static void P_MovePlayer(player_t *player) // Look for Quicksand! if (CheckForQuicksand) P_CheckQuicksand(player); + + if (P_IsObjectOnGround(player->mo)) + player->mo->pmomz = 0; } static void P_DoZoomTube(player_t *player) { - INT32 sequence; fixed_t speed; - thinker_t *th; - mobj_t *mo2; mobj_t *waypoint = NULL; fixed_t dist; boolean reverse; - //player->mo->height = P_GetPlayerSpinHeight(player); - if (player->speed > 0) reverse = false; else @@ -6498,8 +2410,6 @@ static void P_DoZoomTube(player_t *player) speed = abs(player->speed); - sequence = player->mo->tracer->threshold; - // change slope dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - player->mo->z); @@ -6531,26 +2441,7 @@ static void P_DoZoomTube(player_t *player) CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); // Find next waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == sequence) - { - if ((reverse && mo2->health == player->mo->tracer->health - 1) - || (!reverse && mo2->health == player->mo->tracer->health + 1)) - { - waypoint = mo2; - break; - } - } - } + waypoint = reverse ? P_GetPreviousTubeWaypoint(player->mo->tracer, false) : P_GetNextTubeWaypoint(player->mo->tracer, false); if (waypoint) { @@ -6573,6 +2464,7 @@ static void P_DoZoomTube(player_t *player) else { P_SetTarget(&player->mo->tracer, NULL); // Else, we just let them fly. + player->powers[pw_carry] = CR_NONE; CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, releasing from track...\n"); } @@ -6582,180 +2474,13 @@ static void P_DoZoomTube(player_t *player) if (player->mo->tracer) { player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, player->mo->tracer->x, player->mo->tracer->y); - - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; + P_SetPlayerAngle(player, player->mo->angle); } -#if 0 - if (player->mo->state != &states[S_KART_SPIN]) - P_SetPlayerMobjState(player->mo, S_KART_SPIN); - player->frameangle -= ANGLE_22h; -#endif + + P_SetPlayerMobjState(player->mo, S_KART_SPINOUT); + player->drawangle -= ANGLE_22h; } -// -// P_DoRopeHang -// -// Kinda like P_DoZoomTube -// but a little different. -// -/* -static void P_DoRopeHang(player_t *player) // SRB2kart - unused. -{ - INT32 sequence; - fixed_t speed; - thinker_t *th; - mobj_t *mo2; - mobj_t *waypoint = NULL; - fixed_t dist; - fixed_t playerz; - - player->mo->height = P_GetPlayerHeight(player); - - // Play the 'clink' sound only if the player is moving. - if (!(leveltime & 7) && player->speed) - S_StartSound(player->mo, sfx_s3k55); - - playerz = player->mo->z + player->mo->height; - - speed = abs(player->speed); - - sequence = player->mo->tracer->threshold; - - // change slope - dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - playerz); - - if (dist < 1) - dist = 1; - - player->mo->momx = FixedMul(FixedDiv(player->mo->tracer->x - player->mo->x, dist), (speed)); - player->mo->momy = FixedMul(FixedDiv(player->mo->tracer->y - player->mo->y, dist), (speed)); - player->mo->momz = FixedMul(FixedDiv(player->mo->tracer->z - playerz, dist), (speed)); - - if (player->cmd.buttons & BT_USE && !(player->pflags & PF_STASIS)) // Drop off of the rope - { - P_SetTarget(&player->mo->tracer, NULL); - - player->pflags |= PF_JUMPED; - player->pflags &= ~PF_ROPEHANG; - - if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED) - && !(player->panim == PA_ROLL) && player->charability2 == CA2_SPINDASH) - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - return; - } - - // If not allowed to move, we're done here. - if (!speed) - return; - - // Calculate the distance between the player and the waypoint - // 'dist' already equals this. - - // Will the player go past the waypoint? - if (speed > dist) - { - speed -= dist; - // If further away, set XYZ of player to waypoint location - P_UnsetThingPosition(player->mo); - player->mo->x = player->mo->tracer->x; - player->mo->y = player->mo->tracer->y; - player->mo->z = player->mo->tracer->z - player->mo->height; - playerz = player->mo->tracer->z; - P_SetThingPosition(player->mo); - - CONS_Debug(DBG_GAMELOGIC, "Looking for next waypoint...\n"); - - // Find next waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == sequence) - { - if (mo2->health == player->mo->tracer->health + 1) - { - waypoint = mo2; - break; - } - } - } - - if (!(player->mo->tracer->flags & MF_SLIDEME) && !waypoint) - { - CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found, wrapping to start...\n"); - - // Wrap around back to first waypoint - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) // Not a mobj thinker - continue; - - mo2 = (mobj_t *)th; - - if (mo2->type != MT_TUBEWAYPOINT) - continue; - - if (mo2->threshold == sequence) - { - if (mo2->health == 0) - { - waypoint = mo2; - break; - } - } - } - } - - if (waypoint) - { - CONS_Debug(DBG_GAMELOGIC, "Found waypoint (sequence %d, number %d).\n", waypoint->threshold, waypoint->health); - - P_SetTarget(&player->mo->tracer, waypoint); - - // calculate MOMX/MOMY/MOMZ for next waypoint - // change slope - dist = P_AproxDistance(P_AproxDistance(player->mo->tracer->x - player->mo->x, player->mo->tracer->y - player->mo->y), player->mo->tracer->z - playerz); - - if (dist < 1) - dist = 1; - - player->mo->momx = FixedMul(FixedDiv(player->mo->tracer->x - player->mo->x, dist), (speed)); - player->mo->momy = FixedMul(FixedDiv(player->mo->tracer->y - player->mo->y, dist), (speed)); - player->mo->momz = FixedMul(FixedDiv(player->mo->tracer->z - playerz, dist), (speed)); - } - else - { - if (player->mo->tracer->flags & MF_SLIDEME) - { - player->pflags |= PF_JUMPED; - player->pflags &= ~PF_ROPEHANG; - - if (!(player->pflags & PF_SLIDING) && (player->pflags & PF_JUMPED) - && !(player->panim == PA_ROLL) && player->charability2 == CA2_SPINDASH) - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1); - } - - P_SetTarget(&player->mo->tracer, NULL); - - CONS_Debug(DBG_GAMELOGIC, "Next waypoint not found!\n"); - } - } -} -*/ - #if 0 // // P_NukeAllPlayers @@ -6766,25 +2491,22 @@ static void P_DoRopeHang(player_t *player) // SRB2kart - unused. static void P_NukeAllPlayers(player_t *player) { mobj_t *mo; - thinker_t *think; + UINT8 i; - for (think = thinkercap.next; think != &thinkercap; think = think->next) + for (i = 0; i < MAXPLAYERS; i++) { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - - mo = (mobj_t *)think; - - if (!mo->player) + if (!playeringame[i]) + continue; + if (players[i].spectator) + continue; + if (!players[i].mo) + continue; + if (players[i].mo == player->mo) + continue; + if (players[i].mo->health <= 0) continue; - if (mo->health <= 0) // dead - continue; - - if (mo == player->mo) - continue; - - P_DamageMobj(mo, player->mo, player->mo, 1); + P_DamageMobj(players[i].mo, player->mo, player->mo, 1, DMG_NORMAL); } CONS_Printf(M_GetText("%s caused a world of pain.\n"), player_names[player-players]); @@ -6799,248 +2521,86 @@ static void P_NukeAllPlayers(player_t *player) // void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius) { - const fixed_t ns = 60 * mapobjectscale; mobj_t *mo; - angle_t fa; thinker_t *think; - INT32 i; radius = FixedMul(radius, mapobjectscale); - for (i = 0; i < 16; i++) + for (think = thlist[THINK_MOBJ].next; think != &thlist[THINK_MOBJ]; think = think->next) { - fa = (i*(FINEANGLES/16)); - mo = P_SpawnMobj(inflictor->x, inflictor->y, inflictor->z, MT_SUPERSPARK); - if (!P_MobjWasRemoved(mo)) - { - mo->momx = FixedMul(FINESINE(fa),ns); - mo->momy = FixedMul(FINECOSINE(fa),ns); - } - } - - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker + if (think->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; mo = (mobj_t *)think; - if (!(mo->flags & MF_SHOOTABLE) && !(mo->type == MT_EGGGUARD || mo->type == MT_MINUS - || mo->type == MT_SPB)) // Don't want to give SPB MF_SHOOTABLE, to ensure it's undamagable through other means + if (!(mo->flags & MF_SHOOTABLE) && (mo->type != MT_SPB)) // Don't want to give SPB MF_SHOOTABLE, to ensure it's undamagable through other means continue; if (mo->flags & MF_MONITOR) continue; // Monitors cannot be 'nuked'. - //if (!G_BattleGametype() && mo->type == MT_PLAYER) - // continue; // Don't hurt players in Co-Op! - if (abs(inflictor->x - mo->x) > radius || abs(inflictor->y - mo->y) > radius || abs(inflictor->z - mo->z) > radius) continue; // Workaround for possible integer overflow in the below -Red if (P_AproxDistance(P_AproxDistance(inflictor->x - mo->x, inflictor->y - mo->y), inflictor->z - mo->z) > radius) continue; - if (mo->type == MT_MINUS && !(mo->flags & (MF_SPECIAL|MF_SHOOTABLE))) - mo->flags |= MF_SPECIAL|MF_SHOOTABLE; - - if (mo->type == MT_EGGGUARD && mo->tracer) //nuke Egg Guard's shield! - P_KillMobj(mo->tracer, inflictor, source); - - if (mo->flags & MF_BOSS) //don't OHKO bosses! - P_DamageMobj(mo, inflictor, source, 1); - - //{ SRB2kart - if (mo->type == MT_ORBINAUT || mo->type == MT_JAWZ || mo->type == MT_JAWZ_DUD - || mo->type == MT_ORBINAUT_SHIELD || mo->type == MT_JAWZ_SHIELD - || mo->type == MT_BANANA || mo->type == MT_BANANA_SHIELD - || mo->type == MT_EGGMANITEM || mo->type == MT_EGGMANITEM_SHIELD - || mo->type == MT_BALLHOG || mo->type == MT_SPB) - { - if (mo->eflags & MFE_VERTICALFLIP) - mo->z -= mo->height; - else - mo->z += mo->height; - - S_StartSound(mo, mo->info->deathsound); - P_KillMobj(mo, inflictor, source); - - P_SetObjectMomZ(mo, 8*FRACUNIT, false); - P_InstaThrust(mo, R_PointToAngle2(inflictor->x, inflictor->y, mo->x, mo->y)+ANGLE_90, 16*FRACUNIT); - } - if (mo->type == MT_SPB) // If you destroy a SPB, you don't get the luxury of a cooldown. { spbplace = -1; indirectitemcooldown = 0; } - if (mo == inflictor) // Don't nuke yourself, dummy! - continue; - - if (mo->type == MT_PLAYER) // Players wipe out in Kart - K_SpinPlayer(mo->player, source, 0, inflictor, false); - //} + if (mo->flags & MF_BOSS || mo->type == MT_PLAYER) //don't OHKO bosses nor players! + P_DamageMobj(mo, inflictor, source, 1, DMG_NORMAL|DMG_CANTHURTSELF); else - P_DamageMobj(mo, inflictor, source, 1000); + P_DamageMobj(mo, inflictor, source, 1000, DMG_NORMAL|DMG_CANTHURTSELF); } } // -// P_LookForEnemies -// Looks for something you can hit - Used for homing attack -// Includes monitors and springs! +// P_ConsiderAllGone +// Shamelessly lifted from TD. Thanks, Sryder! // -boolean P_LookForEnemies(player_t *player) + +// SRB2Kart: Use for GP? +/* +static void P_ConsiderAllGone(void) { - mobj_t *mo; - thinker_t *think; - mobj_t *closestmo = NULL; - angle_t an; + INT32 i, lastdeadplayer = -1, deadtimercheck = INT32_MAX; - for (think = thinkercap.next; think != &thinkercap; think = think->next) - { - if (think->function.acp1 != (actionf_p1)P_MobjThinker) - continue; // not a mobj thinker - - mo = (mobj_t *)think; - if (!(mo->flags & (MF_ENEMY|MF_BOSS|MF_MONITOR|MF_SPRING))) - continue; // not a valid enemy - - if (mo->health <= 0) // dead - continue; - - if (mo == player->mo) - continue; - - if (mo->flags2 & MF2_FRET) - continue; - - if ((mo->flags & (MF_ENEMY|MF_BOSS)) && !(mo->flags & MF_SHOOTABLE)) // don't aim at something you can't shoot at anyway (see Egg Guard or Minus) - continue; - - if (mo->type == MT_DETON) // Don't be STUPID, Sonic! - continue; - - if (((mo->z > player->mo->z+FixedMul(MAXSTEPMOVE, mapobjectscale)) && !(player->mo->eflags & MFE_VERTICALFLIP)) - || ((mo->z+mo->height < player->mo->z+player->mo->height-FixedMul(MAXSTEPMOVE, mapobjectscale)) && (player->mo->eflags & MFE_VERTICALFLIP))) // Reverse gravity check - Flame. - continue; // Don't home upwards! - - if (P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y), - player->mo->z-mo->z) > FixedMul(RING_DIST, player->mo->scale)) - continue; // out of range - - if ((twodlevel || player->mo->flags2 & MF2_TWOD) - && abs(player->mo->y-mo->y) > player->mo->radius) - continue; // not in your 2d plane - - if (mo->type == MT_PLAYER) // Don't chase after other players! - continue; - - if (closestmo && P_AproxDistance(P_AproxDistance(player->mo->x-mo->x, player->mo->y-mo->y), - player->mo->z-mo->z) > P_AproxDistance(P_AproxDistance(player->mo->x-closestmo->x, - player->mo->y-closestmo->y), player->mo->z-closestmo->z)) - continue; - - an = R_PointToAngle2(player->mo->x, player->mo->y, mo->x, mo->y) - player->mo->angle; - - if (an > ANGLE_90 && an < ANGLE_270) - continue; // behind back - - if (!P_CheckSight(player->mo, mo)) - continue; // out of sight - - closestmo = mo; - } - - if (closestmo) - { - // Found a target monster - P_SetTarget(&player->mo->target, P_SetTarget(&player->mo->tracer, closestmo)); - player->mo->angle = R_PointToAngle2(player->mo->x, player->mo->y, closestmo->x, closestmo->y); - return true; - } - - return false; -} - -void P_HomingAttack(mobj_t *source, mobj_t *enemy) // Home in on your target -{ - fixed_t dist; - fixed_t ns = 0; - - if (!enemy) + if (countdown2) return; - if (!(enemy->health)) - return; - - // change angle - source->angle = R_PointToAngle2(source->x, source->y, enemy->x, enemy->y); - if (source->player) + for (i = 0; i < MAXPLAYERS; i++) { - if (source->player == &players[consoleplayer]) - localangle[0] = source->angle; - else if (source->player == &players[displayplayers[1]]) - localangle[1] = source->angle; - else if (source->player == &players[displayplayers[2]]) - localangle[2] = source->angle; - else if (source->player == &players[displayplayers[3]]) - localangle[3] = source->angle; - } - - // change slope - dist = P_AproxDistance(P_AproxDistance(enemy->x - source->x, enemy->y - source->y), - enemy->z - source->z); - - if (dist < 1) - dist = 1; - - if (source->type == MT_DETON && enemy->player) // For Deton Chase (Unused) - ns = FixedDiv(FixedMul(K_GetKartSpeed(enemy->player, false), enemy->scale), FixedDiv(20*FRACUNIT,17*FRACUNIT)); - else if (source->type != MT_PLAYER) - { - if (source->threshold == 32000) - ns = FixedMul(source->info->speed/2, source->scale); - else - ns = FixedMul(source->info->speed, source->scale); - } - else if (source->player) - ns = FixedDiv(FixedMul(K_GetKartSpeed(source->player, false), source->scale), 3*FRACUNIT/2); - - source->momx = FixedMul(FixedDiv(enemy->x - source->x, dist), ns); - source->momy = FixedMul(FixedDiv(enemy->y - source->y, dist), ns); - source->momz = FixedMul(FixedDiv(enemy->z - source->z, dist), ns); -} - -// Search for emeralds -void P_FindEmerald(void) -{ - thinker_t *th; - mobj_t *mo2; - - hunt1 = hunt2 = hunt3 = NULL; - - // scan the remaining thinkers - // to find all emeralds - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) + if (!playeringame[i]) continue; - mo2 = (mobj_t *)th; - if (mo2->type == MT_EMERHUNT) + if (players[i].playerstate != PST_DEAD && !players[i].spectator && players[i].mo && players[i].mo->health) + break; + + if (players[i].spectator) { - if (!hunt1) - hunt1 = mo2; - else if (!hunt2) - hunt2 = mo2; - else if (!hunt3) - hunt3 = mo2; + if (lastdeadplayer == -1) + lastdeadplayer = i; + } + else if (players[i].lives > 0) + { + lastdeadplayer = i; + if (players[i].deadtimer < deadtimercheck) + deadtimercheck = players[i].deadtimer; } } - return; + + if (i == MAXPLAYERS && lastdeadplayer != -1 && deadtimercheck > 2*TICRATE) // the last killed player will reset the level in G_DoReborn + { + //players[lastdeadplayer].spectator = true; + players[lastdeadplayer].outofcoop = true; + players[lastdeadplayer].playerstate = PST_REBORN; + } } +*/ // // P_DeathThink @@ -7049,8 +2609,7 @@ void P_FindEmerald(void) // static void P_DeathThink(player_t *player) { - //ticcmd_t *cmd = &player->cmd; - //player->deltaviewheight = 0; + player->deltaviewheight = 0; if (player->deadtimer < INT32_MAX) player->deadtimer++; @@ -7058,7 +2617,7 @@ static void P_DeathThink(player_t *player) if (player->bot) // don't allow bots to do any of the below, B_CheckRespawn does all they need for respawning already goto notrealplayer; - if ((player->pflags & PF_TIMEOVER) && G_RaceGametype()) + if ((player->pflags & PF_GAMETYPEOVER) && (gametyperules & GTR_CIRCUIT)) { player->karthud[khud_timeovercam]++; @@ -7073,13 +2632,13 @@ static void P_DeathThink(player_t *player) K_KartPlayerHUDUpdate(player); - if (player->lives > 0 && !(player->pflags & PF_TIMEOVER) && player->deadtimer > TICRATE) + if (player->lives > 0 && !(player->pflags & PF_GAMETYPEOVER) && player->deadtimer > TICRATE) { player->playerstate = PST_REBORN; } // Keep time rolling - if (!(exitcountdown && !racecountdown) && !(player->exiting || mapreset) && !(player->pflags & PF_TIMEOVER)) + if (!(exitcountdown && !racecountdown) && !(player->exiting || mapreset) && !(player->pflags & PF_GAMETYPEOVER) && !stoppedclock) { if (leveltime >= starttime) { @@ -7119,89 +2678,83 @@ camera_t camera[MAXSPLITSCREENPLAYERS]; // Four cameras, three for splitscreen static void CV_CamRotate_OnChange(void) { - if (cv_cam_rotate.value < 0) - CV_SetValue(&cv_cam_rotate, cv_cam_rotate.value + 360); - else if (cv_cam_rotate.value > 359) - CV_SetValue(&cv_cam_rotate, cv_cam_rotate.value % 360); + if (cv_cam_rotate[0].value < 0) + CV_SetValue(&cv_cam_rotate[0], cv_cam_rotate[0].value + 360); + else if (cv_cam_rotate[0].value > 359) + CV_SetValue(&cv_cam_rotate[0], cv_cam_rotate[0].value % 360); } static void CV_CamRotate2_OnChange(void) { - if (cv_cam2_rotate.value < 0) - CV_SetValue(&cv_cam2_rotate, cv_cam2_rotate.value + 360); - else if (cv_cam2_rotate.value > 359) - CV_SetValue(&cv_cam2_rotate, cv_cam2_rotate.value % 360); + if (cv_cam_rotate[1].value < 0) + CV_SetValue(&cv_cam_rotate[1], cv_cam_rotate[1].value + 360); + else if (cv_cam_rotate[1].value > 359) + CV_SetValue(&cv_cam_rotate[1], cv_cam_rotate[1].value % 360); } static void CV_CamRotate3_OnChange(void) { - if (cv_cam3_rotate.value < 0) - CV_SetValue(&cv_cam3_rotate, cv_cam3_rotate.value + 360); - else if (cv_cam3_rotate.value > 359) - CV_SetValue(&cv_cam3_rotate, cv_cam3_rotate.value % 360); + if (cv_cam_rotate[2].value < 0) + CV_SetValue(&cv_cam_rotate[2], cv_cam_rotate[2].value + 360); + else if (cv_cam_rotate[2].value > 359) + CV_SetValue(&cv_cam_rotate[2], cv_cam_rotate[2].value % 360); } static void CV_CamRotate4_OnChange(void) { - if (cv_cam4_rotate.value < 0) - CV_SetValue(&cv_cam4_rotate, cv_cam4_rotate.value + 360); - else if (cv_cam4_rotate.value > 359) - CV_SetValue(&cv_cam4_rotate, cv_cam4_rotate.value % 360); + if (cv_cam_rotate[3].value < 0) + CV_SetValue(&cv_cam_rotate[3], cv_cam_rotate[3].value + 360); + else if (cv_cam_rotate[3].value > 359) + CV_SetValue(&cv_cam_rotate[3], cv_cam_rotate[3].value % 360); } static CV_PossibleValue_t CV_CamSpeed[] = {{0, "MIN"}, {1*FRACUNIT, "MAX"}, {0, NULL}}; -static CV_PossibleValue_t rotation_cons_t[] = {{1, "MIN"}, {45, "MAX"}, {0, NULL}}; static CV_PossibleValue_t CV_CamRotate[] = {{-720, "MIN"}, {720, "MAX"}, {0, NULL}}; -consvar_t cv_cam_dist = {"cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam_height = {"cam_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam_still = {"cam_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam_speed = {"cam_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam_rotate = {"cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam_rotspeed = {"cam_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_dist[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("cam_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam3_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam4_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL) +}; -consvar_t cv_cam2_dist = {"cam2_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam2_height = {"cam2_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam2_still = {"cam2_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam2_speed = {"cam2_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam2_rotate = {"cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam2_rotspeed = {"cam2_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_height[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("cam_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam2_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam3_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL), + CVAR_INIT ("cam4_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL) +}; -consvar_t cv_cam3_dist = {"cam3_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam3_height = {"cam3_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam3_still = {"cam3_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam3_speed = {"cam3_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam3_rotate = {"cam3_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate3_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam3_rotspeed = {"cam3_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_still[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("cam_still", "Off", 0, CV_OnOff, NULL), + CVAR_INIT ("cam2_still", "Off", 0, CV_OnOff, NULL), + CVAR_INIT ("cam3_still", "Off", 0, CV_OnOff, NULL), + CVAR_INIT ("cam4_still", "Off", 0, CV_OnOff, NULL) +}; -consvar_t cv_cam4_dist = {"cam4_dist", "160", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam4_height = {"cam4_height", "50", CV_FLOAT|CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam4_still = {"cam4_still", "Off", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam4_speed = {"cam4_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam4_rotate = {"cam4_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate4_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cam4_rotspeed = {"cam4_rotspeed", "10", CV_SAVE, rotation_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_cam_speed[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("cam_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL), + CVAR_INIT ("cam2_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL), + CVAR_INIT ("cam3_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL), + CVAR_INIT ("cam4_speed", "0.4", CV_FLOAT|CV_SAVE, CV_CamSpeed, NULL) +}; -fixed_t t_cam_dist = -42; -fixed_t t_cam_height = -42; -fixed_t t_cam_rotate = -42; -fixed_t t_cam2_dist = -42; -fixed_t t_cam2_height = -42; -fixed_t t_cam2_rotate = -42; -fixed_t t_cam3_dist = -42; -fixed_t t_cam3_height = -42; -fixed_t t_cam3_rotate = -42; -fixed_t t_cam4_dist = -42; -fixed_t t_cam4_height = -42; -fixed_t t_cam4_rotate = -42; +consvar_t cv_cam_rotate[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("cam_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate_OnChange), + CVAR_INIT ("cam2_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate2_OnChange), + CVAR_INIT ("cam3_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate3_OnChange), + CVAR_INIT ("cam4_rotate", "0", CV_CALL|CV_NOINIT, CV_CamRotate, CV_CamRotate4_OnChange) +}; -#define MAXCAMERADIST 140*FRACUNIT // Max distance the camera can be in front of the player (2D mode) +fixed_t t_cam_dist[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; +fixed_t t_cam_height[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; +fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; // Heavily simplified version of G_BuildTicCmd that only takes the local first player's control input and converts it to readable ticcmd_t // we then throw that ticcmd garbage in the camera and make it move // redefine this -static fixed_t forwardmove = MAXPLMOVE<>16; -static fixed_t angleturn[3] = {KART_FULLTURN/2, KART_FULLTURN, KART_FULLTURN/4}; // + slow turn +static fixed_t angleturn[2] = {KART_FULLTURN, KART_FULLTURN/4}; // + slow turn static ticcmd_t cameracmd; @@ -7215,15 +2768,12 @@ void P_InitCameraCmd(void) static ticcmd_t *P_CameraCmd(camera_t *cam) { - INT32 laim, th, tspeed, forward, axis; //i - const INT32 speed = 1; + INT32 th, tspeed, forward, axis; //i // these ones used for multiple conditions boolean turnleft, turnright, mouseaiming; boolean invertmouse, lookaxis, usejoystick, kbl; - angle_t lang; INT32 player_invert; INT32 screen_invert; - ticcmd_t *cmd = &cameracmd; (void)cam; @@ -7231,25 +2781,20 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) if (!demo.playback) return cmd; // empty cmd, no. - lang = democam.localangle; - laim = democam.localaiming; th = democam.turnheld; kbl = democam.keyboardlook; G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver - cmd->angleturn = (INT16)(lang >> 16); - cmd->aiming = G_ClipAimingPitch(&laim); - mouseaiming = true; invertmouse = cv_invertmouse.value; - lookaxis = cv_lookaxis.value; + lookaxis = cv_lookaxis[0].value; usejoystick = true; - turnright = InputDown(gc_turnright, 1); - turnleft = InputDown(gc_turnleft, 1); + turnright = PlayerInputDown(1, gc_turnright); + turnleft = PlayerInputDown(1, gc_turnleft); - axis = JoyAxis(AXISTURN, 1); + axis = PlayerJoyAxis(1, AXISTURN); if (encoremode) { @@ -7274,37 +2819,39 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) th = 0; if (th < SLOWTURNTICS) - tspeed = 2; // slow turn + tspeed = 1; // slow turn else - tspeed = speed; + tspeed = 0; + + cmd->turning = 0; // let movement keys cancel each other out if (turnright && !(turnleft)) { - cmd->angleturn = (INT16)(cmd->angleturn - (angleturn[tspeed])); + cmd->turning = (INT16)(cmd->turning - (angleturn[tspeed])); } else if (turnleft && !(turnright)) { - cmd->angleturn = (INT16)(cmd->angleturn + (angleturn[tspeed])); + cmd->turning = (INT16)(cmd->turning + (angleturn[tspeed])); } - cmd->angleturn = (INT16)(cmd->angleturn - ((mousex*(encoremode ? -1 : 1)*8))); + cmd->turning = (INT16)(cmd->turning - ((mousex*(encoremode ? -1 : 1)*8))); - axis = JoyAxis(AXISMOVE, 1); - if (InputDown(gc_accelerate, 1) || (usejoystick && axis > 0)) + axis = PlayerJoyAxis(1, AXISMOVE); + if (PlayerInputDown(1, gc_accelerate) || (usejoystick && axis > 0)) cmd->buttons |= BT_ACCELERATE; - axis = JoyAxis(AXISBRAKE, 1); - if (InputDown(gc_brake, 1) || (usejoystick && axis > 0)) + axis = PlayerJoyAxis(1, AXISBRAKE); + if (PlayerInputDown(1, gc_brake) || (usejoystick && axis > 0)) cmd->buttons |= BT_BRAKE; - axis = JoyAxis(AXISAIM, 1); - if (InputDown(gc_aimforward, 1) || (usejoystick && axis < 0)) - forward += forwardmove; - if (InputDown(gc_aimbackward, 1) || (usejoystick && axis > 0)) - forward -= forwardmove; + axis = PlayerJoyAxis(1, AXISAIM); + if (PlayerInputDown(1, gc_aimforward) || (usejoystick && axis < 0)) + forward += MAXPLMOVE; + if (PlayerInputDown(1, gc_aimbackward) || (usejoystick && axis > 0)) + forward -= MAXPLMOVE; // fire with any button/key - axis = JoyAxis(AXISFIRE, 1); - if (InputDown(gc_fire, 1) || (usejoystick && axis > 0)) + axis = PlayerJoyAxis(1, AXISFIRE); + if (PlayerInputDown(1, gc_fire) || (usejoystick && axis > 0)) cmd->buttons |= BT_ATTACK; // spectator aiming shit, ahhhh... @@ -7315,29 +2862,27 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) kbl = false; // looking up/down - laim += (mlooky<<19)*player_invert*screen_invert; + cmd->aiming += (mlooky<<19)*player_invert*screen_invert; - axis = JoyAxis(AXISLOOK, 1); + axis = PlayerJoyAxis(1, AXISLOOK); // spring back if not using keyboard neither mouselookin' if (!kbl && !lookaxis && !mouseaiming) - laim = 0; + cmd->aiming = 0; - if (InputDown(gc_lookup, 1) || (axis < 0)) + if (PlayerInputDown(1, gc_lookup) || (axis < 0)) { - laim += KB_LOOKSPEED * screen_invert; + cmd->aiming += KB_LOOKSPEED * screen_invert; kbl = true; } - else if (InputDown(gc_lookdown, 1) || (axis > 0)) + else if (PlayerInputDown(1, gc_lookdown) || (axis > 0)) { - laim -= KB_LOOKSPEED * screen_invert; + cmd->aiming -= KB_LOOKSPEED * screen_invert; kbl = true; } - if (InputDown(gc_centerview, 1)) // No need to put a spectator limit on this one though :V - laim = 0; - - cmd->aiming = G_ClipAimingPitch(&laim); + if (PlayerInputDown(1, gc_centerview)) // No need to put a spectator limit on this one though :V + cmd->aiming = 0; mousex = mousey = mlooky = 0; @@ -7348,10 +2893,6 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) else if (cmd->forwardmove < -MAXPLMOVE) cmd->forwardmove = -MAXPLMOVE; - lang += (cmd->angleturn<<16); - - democam.localangle = lang; - democam.localaiming = laim; democam.turnheld = th; democam.keyboardlook = kbl; @@ -7373,11 +2914,16 @@ void P_DemoCameraMovement(camera_t *cam) // first off we need to get button input cmd = P_CameraCmd(cam); - cam->aiming = cmd->aiming<angle = cmd->angleturn<<16; + cam->aiming += cmd->aiming << TICCMD_REDUCE; + cam->angle += cmd->turning << TICCMD_REDUCE; + + democam.localangle += cmd->turning << TICCMD_REDUCE; + democam.localaiming += cmd->aiming << TICCMD_REDUCE; + + cam->aiming = G_ClipAimingPitch((INT32 *)&cam->aiming); + democam.localaiming = G_ClipAimingPitch((INT32 *)&democam.localaiming); // camera movement: - if (cmd->buttons & BT_ACCELERATE) cam->z += 32*mapobjectscale; else if (cmd->buttons & BT_BRAKE) @@ -7436,23 +2982,17 @@ void P_ResetCamera(player_t *player, camera_t *thiscam) x = player->mo->x - P_ReturnThrustX(player->mo, thiscam->angle, player->mo->radius); y = player->mo->y - P_ReturnThrustY(player->mo, thiscam->angle, player->mo->radius); if (player->mo->eflags & MFE_VERTICALFLIP) - z = player->mo->z + player->mo->height - (32<mo->z + player->mo->height - P_GetPlayerViewHeight(player) - 16*FRACUNIT; else - z = player->mo->z + (32<mo->z + P_GetPlayerViewHeight(player); // set bits for the camera thiscam->x = x; thiscam->y = y; thiscam->z = z; - if (!(thiscam == &camera[0] && (cv_cam_still.value || cv_analog.value)) - && !(thiscam == &camera[1] && (cv_cam2_still.value || cv_analog2.value)) - && !(thiscam == &camera[2] && (cv_cam3_still.value || cv_analog3.value)) - && !(thiscam == &camera[3] && (cv_cam4_still.value || cv_analog4.value))) - { - thiscam->angle = player->mo->angle; - thiscam->aiming = 0; - } + thiscam->angle = player->mo->angle; + thiscam->aiming = 0; thiscam->relativex = 0; thiscam->subsector = R_PointInSubsector(thiscam->x,thiscam->y); @@ -7498,15 +3038,32 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall return true; } + if (thiscam == &camera[1]) // Camera 2 + { + num = 1; + } + else if (thiscam == &camera[2]) // Camera 3 + { + num = 2; + } + else if (thiscam == &camera[3]) // Camera 4 + { + num = 3; + } + else // Camera 1 + { + num = 0; + } + mo = player->mo; #ifndef NOCLIPCAM - cameranoclip = ((player->pflags & (PF_NOCLIP|PF_NIGHTSMODE)) + cameranoclip = ((player->pflags & PF_NOCLIP) || (mo->flags & (MF_NOCLIP|MF_NOCLIPHEIGHT)) // Noclipping player camera noclips too!! || (leveltime < introtime)); // Kart intro cam #endif - if ((player->pflags & PF_TIMEOVER) && G_RaceGametype()) // 1 for momentum keep, 2 for turnaround + if ((player->pflags & PF_GAMETYPEOVER) && (gametyperules & GTR_CIRCUIT)) // 1 for momentum keep, 2 for turnaround timeover = (player->karthud[khud_timeovercam] > 2*TICRATE ? 2 : 1); else timeover = 0; @@ -7516,42 +3073,14 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (player->spectator) // force cam off for spectators return true; - if (!cv_chasecam.value && thiscam == &camera[0]) - return true; - - if (!cv_chasecam2.value && thiscam == &camera[1]) - return true; - - if (!cv_chasecam3.value && thiscam == &camera[2]) - return true; - - if (!cv_chasecam4.value && thiscam == &camera[3]) + if (!cv_chasecam[num].value && thiscam == &camera[num]) return true; } if (!thiscam->chase && !resetcalled) { - if (player == &players[consoleplayer]) - focusangle = localangle[0]; - else if (player == &players[displayplayers[1]]) - focusangle = localangle[1]; - else if (player == &players[displayplayers[2]]) - focusangle = localangle[2]; - else if (player == &players[displayplayers[3]]) - focusangle = localangle[3]; - else - focusangle = mo->angle; - - if (thiscam == &camera[0]) - camrotate = cv_cam_rotate.value; - else if (thiscam == &camera[1]) - camrotate = cv_cam2_rotate.value; - else if (thiscam == &camera[2]) - camrotate = cv_cam3_rotate.value; - else if (thiscam == &camera[3]) - camrotate = cv_cam4_rotate.value; - else - camrotate = 0; + focusangle = localangle[num]; + camrotate = cv_cam_rotate[num].value; if (leveltime < introtime) // Whoooshy camera! { @@ -7577,30 +3106,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall focusangle = mo->angle; focusaiming = 0; } - else if (player == &players[consoleplayer]) - { - focusangle = localangle[0]; - focusaiming = localaiming[0]; - } - else if (player == &players[g_localplayers[1]]) - { - focusangle = localangle[1]; - focusaiming = localaiming[1]; - } - else if (player == &players[g_localplayers[2]]) - { - focusangle = localangle[2]; - focusaiming = localaiming[2]; - } - else if (player == &players[g_localplayers[3]]) - { - focusangle = localangle[3]; - focusaiming = localaiming[3]; - } else { - focusangle = mo->angle; - focusaiming = player->aiming; + focusangle = localangle[num]; + focusaiming = localaiming[num]; } if (P_CameraThinker(player, thiscam, resetcalled)) @@ -7608,42 +3117,11 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall lookback = ( player->cmd.buttons & BT_LOOKBACK ); - if (thiscam == &camera[1]) // Camera 2 - { - num = 1; - camspeed = cv_cam2_speed.value; - camstill = cv_cam2_still.value; - camrotate = cv_cam2_rotate.value; - camdist = FixedMul(cv_cam2_dist.value, mapobjectscale); - camheight = FixedMul(cv_cam2_height.value, mapobjectscale); - } - else if (thiscam == &camera[2]) // Camera 3 - { - num = 2; - camspeed = cv_cam3_speed.value; - camstill = cv_cam3_still.value; - camrotate = cv_cam3_rotate.value; - camdist = FixedMul(cv_cam3_dist.value, mapobjectscale); - camheight = FixedMul(cv_cam3_height.value, mapobjectscale); - } - else if (thiscam == &camera[3]) // Camera 4 - { - num = 3; - camspeed = cv_cam4_speed.value; - camstill = cv_cam4_still.value; - camrotate = cv_cam4_rotate.value; - camdist = FixedMul(cv_cam4_dist.value, mapobjectscale); - camheight = FixedMul(cv_cam4_height.value, mapobjectscale); - } - else // Camera 1 - { - num = 0; - camspeed = cv_cam_speed.value; - camstill = cv_cam_still.value; - camrotate = cv_cam_rotate.value; - camdist = FixedMul(cv_cam_dist.value, mapobjectscale); - camheight = FixedMul(cv_cam_height.value, mapobjectscale); - } + camspeed = cv_cam_speed[num].value; + camstill = cv_cam_still[num].value; + camrotate = cv_cam_rotate[num].value; + camdist = FixedMul(cv_cam_dist[num].value, mapobjectscale); + camheight = FixedMul(cv_cam_height[num].value, mapobjectscale); if (timeover) { @@ -7707,10 +3185,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } if (!resetcalled && (leveltime >= introtime && timeover != 2) - && ((thiscam == &camera[0] && t_cam_rotate != -42) - || (thiscam == &camera[1] && t_cam2_rotate != -42) - || (thiscam == &camera[2] && t_cam3_rotate != -42) - || (thiscam == &camera[3] && t_cam4_rotate != -42))) + && (t_cam_rotate[num] != -42)) { angle = FixedAngle(camrotate*FRACUNIT); thiscam->angle = angle; @@ -7745,11 +3220,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } pitch = thiscam->pitch + (angle_t)FixedMul(pitch - thiscam->pitch, camspeed/4); - if (rendermode == render_opengl -#ifdef GL_SHADERS/* just so we can't possibly forget about it */ - && !cv_grshearing.value -#endif - ) + if (rendermode == render_opengl && !cv_glshearing.value) distxy = FixedMul(dist, FINECOSINE((pitch>>ANGLETOFINESHIFT) & FINEMASK)); else distxy = dist; @@ -7806,7 +3277,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall #ifndef NOCLIPCAM // Disable all z-clipping for noclip cam // move camera down to move under lower ceilings - newsubsec = R_IsPointInSubsector(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1)); + newsubsec = R_PointInSubsectorOrNull(((mo->x>>FRACBITS) + (thiscam->x>>FRACBITS))<<(FRACBITS-1), ((mo->y>>FRACBITS) + (thiscam->y>>FRACBITS))<<(FRACBITS-1)); if (!newsubsec) newsubsec = thiscam->subsector; @@ -7863,7 +3334,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } } -#ifdef POLYOBJECTS // Check polyobjects and see if floorz/ceilingz need to be altered { INT32 xl, xh, yl, yh, bx, by; @@ -7942,7 +3412,6 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall } } } -#endif // crushed camera if (myceilingz <= myfloorz + thiscam->height && !resetcalled && !cameranoclip) @@ -8046,21 +3515,21 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall if (mo->eflags & MFE_VERTICALFLIP) { - angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, mo->z + mo->height - P_GetPlayerHeight(player)); + angle = R_PointToAngle2(0, thiscam->z + thiscam->height, dist, mo->z + mo->height - player->mo->height); if (thiscam->pitch < ANGLE_180 && thiscam->pitch > angle) angle += (thiscam->pitch - angle)/2; } else { - angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + P_GetPlayerHeight(player)); + angle = R_PointToAngle2(0, thiscam->z, dist, mo->z + player->mo->height); if (thiscam->pitch >= ANGLE_180 && thiscam->pitch < angle) angle -= (angle - thiscam->pitch)/2; } - if (player->playerstate != PST_DEAD && !((player->pflags & PF_NIGHTSMODE) && player->exiting)) + if (player->playerstate != PST_DEAD) angle += (focusaiming < ANGLE_180 ? focusaiming/2 : InvAngle(InvAngle(focusaiming)/2)); // overcomplicated version of '((signed)focusaiming)/2;' - if (twodlevel || (mo->flags2 & MF2_TWOD) || (!camstill && !timeover)) // Keep the view still... + if (!camstill && !timeover) // Keep the view still... { G_ClipAimingPitch((INT32 *)&angle); @@ -8101,6 +3570,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall P_MoveChaseCamera(player, thiscam, false); return (x == thiscam->x && y == thiscam->y && z == thiscam->z && angle == thiscam->aiming); + } boolean P_SpectatorJoinGame(player_t *player) @@ -8142,6 +3612,9 @@ boolean P_SpectatorJoinGame(player_t *player) else changeto = (P_RandomFixed() & 1) + 1; + if (!LUAh_TeamSwitch(player, changeto, true, false, false)) + return false; + if (player->mo) { P_RemoveMobj(player->mo); @@ -8155,7 +3628,12 @@ boolean P_SpectatorJoinGame(player_t *player) //Reset away view if (P_IsLocalPlayer(player) && displayplayers[0] != consoleplayer) + { + // Call ViewpointSwitch hooks here. + // The viewpoint was forcibly changed. + LUAh_ViewpointSwitch(player, &players[consoleplayer], true); displayplayers[0] = consoleplayer; + } if (changeto == 1) CONS_Printf(M_GetText("%s switched to the %c%s%c.\n"), player_names[player-players], '\x85', M_GetText("Red team"), '\x80'); @@ -8187,6 +3665,7 @@ boolean P_SpectatorJoinGame(player_t *player) return false; } +// the below is first person only, if you're curious. check out P_CalcChasePostImg in p_mobj.c for chasecam static void P_CalcPostImg(player_t *player) { sector_t *sector = player->mo->subsector->sector; @@ -8231,13 +3710,8 @@ static void P_CalcPostImg(player_t *player) if (!(rover->flags & FF_EXISTS)) continue; -#ifdef ESLOPE - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; -#else - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; -#endif + topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); + bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); if (pviewheight >= topheight || pviewheight <= bottomheight) continue; @@ -8259,13 +3733,8 @@ static void P_CalcPostImg(player_t *player) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || rover->flags & FF_BLOCKPLAYER) continue; -#ifdef ESLOPE - topheight = *rover->t_slope ? P_GetZAt(*rover->t_slope, player->mo->x, player->mo->y) : *rover->topheight; - bottomheight = *rover->b_slope ? P_GetZAt(*rover->b_slope, player->mo->x, player->mo->y) : *rover->bottomheight; -#else - topheight = *rover->topheight; - bottomheight = *rover->bottomheight; -#endif + topheight = P_GetFFloorTopZAt (rover, player->mo->x, player->mo->y); + bottomheight = P_GetFFloorBottomZAt(rover, player->mo->x, player->mo->y); if (pviewheight >= topheight || pviewheight <= bottomheight) continue; @@ -8295,28 +3764,9 @@ static void P_CalcPostImg(player_t *player) *type = postimg_mirror; } -/*void P_DoPityCheck(player_t *player) -{ - // No pity outside of match or CTF. - if (player->spectator - || !(gametype == GT_MATCH || gametype == GT_TEAMMATCH || gametype == GT_CTF)) - return; - - // Apply pity shield if available. - if ((player->pity >= 3 || player->pity < 0) && player->powers[pw_shield] == SH_NONE) - { - if (player->pity > 0) - S_StartSound(player->mo, mobjinfo[MT_PITYSHIELDICO].seesound); - - player->pity = 0; - player->powers[pw_shield] = SH_PITY; - P_SpawnShieldOrb(player); - } -}*/ - void P_DoTimeOver(player_t *player) { - if (player->pflags & PF_TIMEOVER) + if (player->pflags & PF_GAMETYPEOVER) { // NO! Don't do this! return; @@ -8332,7 +3782,7 @@ void P_DoTimeOver(player_t *player) CON_LogMessage(va(M_GetText("%s ran out of time.\n"), player_names[player-players])); } - player->pflags |= PF_TIMEOVER; + player->pflags |= PF_GAMETYPEOVER; if (G_GametypeUsesLives()) { @@ -8342,7 +3792,7 @@ void P_DoTimeOver(player_t *player) if (player->mo) { S_StopSound(player->mo); - P_DamageMobj(player->mo, NULL, NULL, 10000); + P_DamageMobj(player->mo, NULL, NULL, 1, DMG_TIMEOVER); } P_EndingMusic(player); @@ -8351,6 +3801,98 @@ void P_DoTimeOver(player_t *player) exitcountdown = 5*TICRATE; } +// SRB2Kart: These are useful functions, but we aren't using them yet. +#if 0 + +// Get an axis of a certain ID number +static mobj_t *P_GetAxis(INT32 num) +{ + thinker_t *th; + mobj_t *mobj; + + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + { + if (th->function.acp1 == (actionf_p1)P_RemoveThinkerDelayed) + continue; + + mobj = (mobj_t *)th; + + // NiGHTS axes spawn before anything else. If this mobj doesn't have MF2_AXIS, it means we reached the axes' end. + if (!(mobj->flags2 & MF2_AXIS)) + break; + + // Skip if this axis isn't the one we want. + if (mobj->health != num) + continue; + + return mobj; + } + + CONS_Alert(CONS_WARNING, "P_GetAxis: Track segment %d is missing!\n", num); + return NULL; +} + +// Auxiliary function. For a given position and axis, it calculates the nearest "valid" snap-on position. +static void P_GetAxisPosition(fixed_t x, fixed_t y, mobj_t *amo, fixed_t *newx, fixed_t *newy, angle_t *targetangle, angle_t *grind) +{ + fixed_t ax = amo->x; + fixed_t ay = amo->y; + angle_t ang; + angle_t gr = 0; + + if (amo->type == MT_AXISTRANSFERLINE) + { + ang = amo->angle; + // Extra security for cardinal directions. + if (ang == ANGLE_90 || ang == ANGLE_270) // Vertical lines + x = ax; + else if (ang == 0 || ang == ANGLE_180) // Horizontal lines + y = ay; + else // Diagonal lines + { + fixed_t distance = R_PointToDist2(ax, ay, x, y); + angle_t fad = ((R_PointToAngle2(ax, ay, x, y) - ang) >> ANGLETOFINESHIFT) & FINEMASK; + fixed_t cosine = FINECOSINE(fad); + angle_t fa = (ang >> ANGLETOFINESHIFT) & FINEMASK; + distance = FixedMul(distance, cosine); + x = ax + FixedMul(distance, FINECOSINE(fa)); + y = ay + FixedMul(distance, FINESINE(fa)); + } + } + else // Keep minecart to circle + { + fixed_t rad = amo->radius; + fixed_t distfactor = FixedDiv(rad, R_PointToDist2(ax, ay, x, y)); + + gr = R_PointToAngle2(ax, ay, x, y); + ang = gr + ANGLE_90; + x = ax + FixedMul(x - ax, distfactor); + y = ay + FixedMul(y - ay, distfactor); + } + + *newx = x; + *newy = y; + *targetangle = ang; + *grind = gr; +} + +static void P_ParabolicMove(mobj_t *mo, fixed_t x, fixed_t y, fixed_t z, fixed_t g, fixed_t speed) +{ + fixed_t dx = x - mo->x; + fixed_t dy = y - mo->y; + fixed_t dz = z - mo->z; + fixed_t dh = P_AproxDistance(dx, dy); + fixed_t c = FixedDiv(dx, dh); + fixed_t s = FixedDiv(dy, dh); + fixed_t fixConst = FixedDiv(speed, g); + + mo->momx = FixedMul(c, speed); + mo->momy = FixedMul(s, speed); + mo->momz = FixedDiv(dh, 2*fixConst) + FixedDiv(dz, FixedDiv(dh, fixConst/2)); +} + +#endif + /* set follower state with our weird hacks the reason we do this is to avoid followers ever using actions (majormods, yikes!) without having to touch p_mobj.c. @@ -8395,7 +3937,7 @@ static void P_HandleFollower(player_t *player) angle_t an; fixed_t zoffs; fixed_t sx, sy, sz; - UINT8 color; + UINT16 color; fixed_t bubble; // bubble scale (0 if no bubble) mobj_t *bmobj; // temp bubble mobj @@ -8445,17 +3987,17 @@ static void P_HandleFollower(player_t *player) switch (player->followercolor) { - case MAXSKINCOLORS: // "Match" + case MAXSKINCOLORS: // "Match" color = player->skincolor; break; - case MAXSKINCOLORS+1: // "Opposite" - color = KartColor_Opposite[player->skincolor*2]; + case MAXSKINCOLORS+1: // "Opposite" + color = skincolors[player->skincolor].invcolor; break; default: color = player->followercolor; - if (!color || color > MAXSKINCOLORS+2) // Make sure this isn't garbage - color = player->skincolor; // "Match" as fallback. + if (!color || color > MAXSKINCOLORS+2) // Make sure this isn't garbage + color = player->skincolor; // "Match" as fallback. break; } @@ -8528,8 +4070,7 @@ static void P_HandleFollower(player_t *player) player->follower->drawflags = player->mo->drawflags; // Make the follower invisible if we no contest'd rather than removing it. No one will notice the diff seriously. - // Also make the follower invisible if we choose not to have it displayed because it isn't ours. (also quick hacky check for f12) - if (player->pflags & PF_TIMEOVER || (!cv_showfollowers.value && (!P_IsDisplayPlayer(player) || displayplayers[0] != consoleplayer) )) + if (player->pflags & PF_GAMETYPEOVER) player->follower->drawflags |= MFD_DONTDRAW; if (player->speed && (player->follower->momx || player->follower->momy)) @@ -8568,10 +4109,10 @@ static void P_HandleFollower(player_t *player) // handle follower animations. Could probably be better... // hurt or dead - if (player->kartstuff[k_spinouttimer] || player->mo->state == &states[S_KART_SPIN] || player->mo->health <= 0) + if (player->kartstuff[k_spinouttimer] || player->mo->state == &states[S_KART_SPINOUT] || player->mo->health <= 0) { player->follower->movecount = 0; // cancel hit confirm. - player->follower->angle = player->frameangle; // spin out + player->follower->angle = player->drawangle; // spin out if (player->follower->extravalue1 != 2) { player->follower->extravalue1 = 2; @@ -8647,7 +4188,7 @@ void P_PlayerThink(player_t *player) #endif // todo: Figure out what is actually causing these problems in the first place... - if ((player->health <= 0 || player->mo->health <= 0) && player->playerstate == PST_LIVE) //you should be DEAD! + if (player->mo->health <= 0 && player->playerstate == PST_LIVE) //you should be DEAD! { CONS_Debug(DBG_GAMELOGIC, "P_PlayerThink: Player %s in PST_LIVE with 0 health. (\"Zombie bug\")\n", sizeu1(playeri)); player->playerstate = PST_DEAD; @@ -8658,8 +4199,7 @@ void P_PlayerThink(player_t *player) { seenplayer = NULL; - if (cv_seenames.value && cv_allowseenames.value && - !(G_TagGametype() && (player->pflags & PF_TAGIT))) + if (cv_seenames.value && cv_allowseenames.value) { mobj_t *mo = P_SpawnNameFinder(player->mo, MT_NAMECHECK); @@ -8692,14 +4232,8 @@ void P_PlayerThink(player_t *player) if (player->flashcount) player->flashcount--; - // Re-fixed by Jimita (11-12-2018) - if (player->awayviewtics) - { + if (player->awayviewtics && player->awayviewtics != -1) player->awayviewtics--; - if (!player->awayviewtics) - player->awayviewtics = -1; - // The timer might've reached zero, but we'll run the remote view camera anyway by setting it to -1. - } // Track airtime if (P_IsObjectOnGround(player->mo)) @@ -8736,7 +4270,7 @@ void P_PlayerThink(player_t *player) if (!mapreset) { - if (G_RaceGametype()) + if (gametyperules & GTR_CIRCUIT) { INT32 i; @@ -8745,7 +4279,7 @@ void P_PlayerThink(player_t *player) { if (playeringame[i] && !players[i].spectator) { - if (!players[i].exiting && !(players[i].pflags & PF_TIMEOVER) && players[i].lives > 0) + if (!players[i].exiting && !(players[i].pflags & PF_GAMETYPEOVER) && players[i].lives > 0) break; } } @@ -8756,6 +4290,7 @@ void P_PlayerThink(player_t *player) #if 0 // If 10 seconds are left on the timer, // begin the drown music for countdown! + // SRB2Kart: despite how perfect this is, it's disabled FOR A REASON if (racecountdown == 11*TICRATE - 1) { if (P_IsLocalPlayer(player)) @@ -8765,7 +4300,7 @@ void P_PlayerThink(player_t *player) // If you've hit the countdown and you haven't made // it to the exit, you're a goner! - if (racecountdown == 1 && !player->spectator && !player->exiting && !(player->pflags & PF_TIMEOVER) && player->lives > 0) + if (racecountdown == 1 && !player->spectator && !player->exiting && !(player->pflags & PF_GAMETYPEOVER) && player->lives > 0) { P_DoTimeOver(player); @@ -8778,7 +4313,7 @@ void P_PlayerThink(player_t *player) // If it is set, start subtracting // Don't allow it to go back to 0 - if (player->exiting > 1 && (player->exiting < raceexittime+2 || !G_RaceGametype())) // SRB2kart - "&& player->exiting > 1" + if (player->exiting > 1 && (player->exiting < raceexittime+2 || !(gametyperules & GTR_CIRCUIT))) // SRB2kart - "&& player->exiting > 1" player->exiting--; if (player->exiting && exitcountdown) @@ -8797,15 +4332,20 @@ void P_PlayerThink(player_t *player) P_MobjCheckWater(player->mo); #ifndef SECTORSPECIALSAFTERTHINK -#ifdef POLYOBJECTS if (player->onconveyor != 1 || !P_IsObjectOnGround(player->mo)) -#endif - player->onconveyor = 0; + player->onconveyor = 0; // check special sectors : damage & secrets if (!player->spectator) P_PlayerInSpecialSector(player); + else if ( +#else + if (player->spectator && #endif + (gametyperules & GTR_LIVES)) + { + /*P_ConsiderAllGone()*/; + } if (player->playerstate == PST_DEAD) { @@ -8814,7 +4354,7 @@ void P_PlayerThink(player_t *player) else player->mo->drawflags &= ~(MFD_TRANSMASK|MFD_BRIGHTMASK); P_DeathThink(player); - + LUAh_PlayerThink(player); return; } @@ -8822,8 +4362,8 @@ void P_PlayerThink(player_t *player) if (player->spectator) { //player->score = 0; + player->rings = 0; player->mo->health = 1; - player->health = 1; } // SRB2kart 010217 @@ -8833,7 +4373,7 @@ void P_PlayerThink(player_t *player) } // Synchronizes the "real" amount of time spent in the level. - if (!player->exiting) + if (!(exitcountdown && !racecountdown) && !(player->exiting || mapreset) && !(player->pflags & PF_GAMETYPEOVER) && !stoppedclock) { if (leveltime >= starttime) { @@ -8862,37 +4402,6 @@ void P_PlayerThink(player_t *player) return; // player->mo was removed.*/ } - // Even if not NiGHTS, pull in nearby objects when walking around as John Q. Elliot. - if (!objectplacing && !((netgame || multiplayer) && player->spectator) - && maptol & TOL_NIGHTS && (!(player->pflags & PF_NIGHTSMODE) || player->powers[pw_nights_helper])) - { - thinker_t *th; - mobj_t *mo2; - fixed_t x = player->mo->x; - fixed_t y = player->mo->y; - fixed_t z = player->mo->z; - - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - - mo2 = (mobj_t *)th; - - if (!(mo2->type == MT_NIGHTSWING || mo2->type == MT_RING || mo2->type == MT_COIN - || mo2->type == MT_BLUEBALL)) - continue; - - if (P_AproxDistance(P_AproxDistance(mo2->x - x, mo2->y - y), mo2->z - z) > FixedMul(128*FRACUNIT, player->mo->scale)) - continue; - - // Yay! The thing's in reach! Pull it in! - mo2->flags |= MF_NOCLIP|MF_NOCLIPHEIGHT; - mo2->flags2 |= MF2_NIGHTSPULL; - P_SetTarget(&mo2->tracer, player->mo); - } - } - if (player->linktimer && !player->powers[pw_nights_linkfreeze]) { if (--player->linktimer <= 0) // Link timer @@ -8909,6 +4418,11 @@ void P_PlayerThink(player_t *player) // Allows some turning P_MovePlayer(player); } + else if (player->respawn.state == RESPAWNST_MOVE) + { + angle_t angleChange = player->cmd.turning << TICCMD_REDUCE; + P_SetPlayerAngle(player, player->angleturn + angleChange); + } } else if (player->mo->reactiontime) { @@ -8928,25 +4442,20 @@ void P_PlayerThink(player_t *player) P_MovePlayer(player); } - if (!player->mo) - return; // P_MovePlayer removed player->mo. + player->mo->movefactor = FRACUNIT; // We're not going to do any more with this, so let's change it back for the next frame. // Unset statis flags after moving. // In other words, if you manually set stasis via code, // it lasts for one tic. player->pflags &= ~PF_FULLSTASIS; -#ifdef POLYOBJECTS if (player->onconveyor == 1) - player->cmomy = player->cmomx = 0; -#endif + player->onconveyor = 3; + else if (player->onconveyor == 3) + player->cmomy = player->cmomx = 0; - //P_DoSuperStuff(player); - //P_CheckSneakerAndLivesTimer(player); P_DoBubbleBreath(player); // Spawn Sonic's bubbles - //P_CheckUnderwaterAndSpaceTimer(player); // Display the countdown drown numbers! P_CheckInvincibilityTimer(player); // Spawn Invincibility Sparkles - P_DoPlayerHeadSigns(player); // Spawn Tag/CTF signs over player's head #if 1 // "Blur" a bit when you have speed shoes and are going fast enough @@ -8957,9 +4466,17 @@ void P_PlayerThink(player_t *player) mobj_t *gmobj = P_SpawnGhostMobj(player->mo); gmobj->fuse = 2; + if (gmobj->tracer) + gmobj->tracer->fuse = 2; if (leveltime & 1) { - gmobj->drawflags |= tr_trans70 << MFD_TRANSSHIFT; + gmobj->frame &= ~FF_TRANSMASK; + gmobj->frame |= tr_trans70<tracer) + { + gmobj->tracer->frame &= ~FF_TRANSMASK; + gmobj->tracer->frame |= tr_trans70<pflags & PF_NIGHTSMODE)) - { - if (cmd->buttons & BT_BRAKE) - player->pflags |= PF_USEDOWN; - else - player->pflags &= ~PF_USEDOWN; - } - else if (player->mo->tracer) // match tracer's position with yours when NiGHTS - { - P_UnsetThingPosition(player->mo->tracer); - player->mo->tracer->x = player->mo->x; - player->mo->tracer->y = player->mo->y; - if (player->mo->eflags & MFE_VERTICALFLIP) - player->mo->tracer->z = player->mo->z + player->mo->height - player->mo->tracer->height; - else - player->mo->tracer->z = player->mo->z; - player->mo->tracer->floorz = player->mo->floorz; - player->mo->tracer->ceilingz = player->mo->ceilingz; - P_SetThingPosition(player->mo->tracer); - } + if (cmd->buttons & BT_BRAKE) + player->pflags |= PF_SPINDOWN; + else + player->pflags &= ~PF_SPINDOWN; + + // IF PLAYER NOT HERE THEN FLASH END IF + if (player->quittime && player->powers[pw_flashing] < K_GetKartFlashing(player) && !player->gotflag) + player->powers[pw_flashing] = K_GetKartFlashing(player); // Counters, time dependent power ups. // Time Bonus & Ring Bonus count settings // Strength counts up to diminish fade. - if (player->powers[pw_sneakers] && player->powers[pw_sneakers] < UINT16_MAX) - player->powers[pw_sneakers]--; - - if (player->powers[pw_invulnerability] && player->powers[pw_invulnerability] < UINT16_MAX) - player->powers[pw_invulnerability]--; - if (player->powers[pw_flashing] && player->powers[pw_flashing] < UINT16_MAX && - (player->spectator || player->powers[pw_flashing] < K_GetKartFlashing(player))) - player->powers[pw_flashing]--; - - if (player->powers[pw_tailsfly] && player->powers[pw_tailsfly] < UINT16_MAX /*&& player->charability != CA_SWIM*/ && !(player->powers[pw_super] && ALL7EMERALDS(player->powers[pw_emeralds]))) // tails fly counter - player->powers[pw_tailsfly]--; - - /* // SRB2kart - Can't drown. - if (player->powers[pw_underwater] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)) + (player->spectator || !P_PlayerInPain(player))) { - if (player->powers[pw_underwater] <= 12*TICRATE+1) - P_RestoreMusic(player); //incase they were about to drown - - player->powers[pw_underwater] = 0; + player->powers[pw_flashing]--; } - else if (player->powers[pw_underwater] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer - player->powers[pw_underwater]--; - - if (player->powers[pw_spacetime] && (player->pflags & PF_GODMODE || (player->powers[pw_shield] & SH_NOSTACK) == SH_ELEMENTAL)) - player->powers[pw_spacetime] = 0; - else if (player->powers[pw_spacetime] && !(maptol & TOL_NIGHTS) && !((netgame || multiplayer) && player->spectator)) // underwater timer - player->powers[pw_spacetime]--; - */ - - if (player->powers[pw_gravityboots] && player->powers[pw_gravityboots] < UINT16_MAX) - player->powers[pw_gravityboots]--; - - if (player->powers[pw_extralife] && player->powers[pw_extralife] < UINT16_MAX) - player->powers[pw_extralife]--; - - if (player->powers[pw_nights_linkfreeze] && player->powers[pw_nights_linkfreeze] < UINT16_MAX) - player->powers[pw_nights_linkfreeze]--; - - if (player->powers[pw_nights_superloop] && player->powers[pw_nights_superloop] < UINT16_MAX) - player->powers[pw_nights_superloop]--; - - if (player->powers[pw_nights_helper] && player->powers[pw_nights_helper] < UINT16_MAX) - player->powers[pw_nights_helper]--; if (player->powers[pw_nocontrol] & ((1<<15)-1) && player->powers[pw_nocontrol] < UINT16_MAX) { if (!(--player->powers[pw_nocontrol])) - player->pflags &= ~PF_SKIDDOWN; + player->pflags &= ~PF_FAULT; } else player->powers[pw_nocontrol] = 0; + if (player->powers[pw_ignorelatch] & ((1<<15)-1) && player->powers[pw_ignorelatch] < UINT16_MAX) + player->powers[pw_ignorelatch]--; + else + player->powers[pw_ignorelatch] = 0; + //pw_super acts as a timer now if (player->powers[pw_super]) player->powers[pw_super]++; - if (player->powers[pw_ingoop]) - { - if (player->mo->state == &states[S_KART_STILL1]) // SRB2kart - was S_PLAY_STND - player->mo->tics = 2; - - player->powers[pw_ingoop]--; - } - - if (player->bumpertime) - player->bumpertime--; - - if (player->skidtime) - player->skidtime--; - - if (player->weapondelay) - player->weapondelay--; - - if (player->tossdelay) - player->tossdelay--; - - if (player->homing) - player->homing--; - - if (player->texttimer) - { - --player->texttimer; - if (!player->texttimer && !player->exiting && player->textvar >= 4) - { - player->texttimer = 4*TICRATE; - player->textvar = 2; // GET n RINGS! - - if (player->capsule && player->capsule->health != player->capsule->spawnpoint->angle) - player->textvar++; // GET n MORE RINGS! - } - } - - if (player->losstime && !player->powers[pw_flashing]) - player->losstime--; - // Flash player after being hit. - if (!(//player->pflags & PF_NIGHTSMODE || - player->kartstuff[k_hyudorotimer] // SRB2kart - fixes Hyudoro not flashing when it should. + if (!(player->kartstuff[k_hyudorotimer] // SRB2kart - fixes Hyudoro not flashing when it should. || player->kartstuff[k_growshrinktimer] > 0 // Grow doesn't flash either. || (player->respawn.state != RESPAWNST_NONE) // Respawn timer (for drop dash effect) - || (player->pflags & PF_TIMEOVER) // NO CONTEST explosion - || (G_BattleGametype() && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) + || (player->pflags & PF_GAMETYPEOVER) // NO CONTEST explosion + || ((gametyperules & GTR_BUMPERS) && player->kartstuff[k_bumper] <= 0 && player->kartstuff[k_comebacktimer]) || leveltime < starttime)) // Level intro { if (player->powers[pw_flashing] > 0 && player->powers[pw_flashing] < K_GetKartFlashing(player) @@ -9113,53 +4544,12 @@ void P_PlayerThink(player_t *player) else player->mo->drawflags &= ~MFD_DONTDRAW; } - /*else if (player->mo->tracer) - { - if (player->powers[pw_flashing] & 1) - player->mo->tracer->drawflags |= MFD_DONTDRAW; - else - player->mo->tracer->drawflags &= ~MFD_DONTDRAW; - }*/ player->pflags &= ~PF_SLIDING; K_KartPlayerThink(player, cmd); // SRB2kart -/* -// Colormap verification - { - INT32 i,j; - sector_t *controlsec; - for (j=0; jtag) - break; - } - - if (i == numlines) - CONS_Debug(DBG_GAMELOGIC, "%d, %d\n", j, sectors[j].tag); - } - } - - I_Error("I'm done!\n"); - }*/ + LUAh_PlayerThink(player); } // @@ -9169,8 +4559,6 @@ void P_PlayerThink(player_t *player) // void P_PlayerAfterThink(player_t *player) { - ticcmd_t *cmd; - //INT32 oldweapon = player->currentweapon; // SRB2kart - unused camera_t *thiscam = NULL; // if not one of the displayed players, just don't bother UINT8 i; @@ -9182,13 +4570,9 @@ void P_PlayerAfterThink(player_t *player) } #endif - cmd = &player->cmd; - #ifdef SECTORSPECIALSAFTERTHINK -#ifdef POLYOBJECTS if (player->onconveyor != 1 || !P_IsObjectOnGround(player->mo)) -#endif - player->onconveyor = 0; + player->onconveyor = 0; // check special sectors : damage & secrets if (!player->spectator) @@ -9206,270 +4590,16 @@ void P_PlayerAfterThink(player_t *player) if (player->playerstate == PST_DEAD) { + if (player->followmobj) + { + P_RemoveMobj(player->followmobj); + P_SetTarget(&player->followmobj, NULL); + } return; } - if (player->pflags & PF_NIGHTSMODE) - { - player->powers[pw_gravityboots] = 0; - //player->mo->eflags &= ~MFE_VERTICALFLIP; - } - - /* SRB2kart - don't need no weapon rings - if (!(player->pflags & PF_WPNDOWN)) - { - if (cmd->buttons & BT_WEAPONNEXT) - { - player->currentweapon++; - player->currentweapon %= NUM_WEAPONS; - player->pflags |= PF_WPNDOWN; - } - - if (cmd->buttons & BT_WEAPONPREV) - { - player->currentweapon--; - if (player->currentweapon < 0) - player->currentweapon = NUM_WEAPONS - 1; - player->pflags |= PF_WPNDOWN; - - if (player->currentweapon == WEP_RAIL && (!(player->ringweapons & RW_RAIL) || !player->powers[pw_railring])) - player->currentweapon--; - if (player->currentweapon == WEP_EXPLODE && (!(player->ringweapons & RW_EXPLODE) || !player->powers[pw_explosionring])) - player->currentweapon--; - if (player->currentweapon == WEP_GRENADE && (!(player->ringweapons & RW_GRENADE) || !player->powers[pw_grenadering])) - player->currentweapon--; - if (player->currentweapon == WEP_SCATTER && (!(player->ringweapons & RW_SCATTER) || !player->powers[pw_scatterring])) - player->currentweapon--; - if (player->currentweapon == WEP_BOUNCE && (!(player->ringweapons & RW_BOUNCE) || !player->powers[pw_bouncering])) - player->currentweapon--; - if (player->currentweapon == WEP_AUTO && (!(player->ringweapons & RW_AUTO) || !player->powers[pw_automaticring])) - player->currentweapon = 0; - } - - if (cmd->buttons & BT_WEAPONMASK) - { - //Read the bits to determine individual weapon ring selection. - INT32 weapon = (cmd->buttons & BT_WEAPONMASK); - - switch (weapon) - { - case 1: //normal / infinity - player->currentweapon = 0; - player->pflags |= PF_WPNDOWN; - break; - case 2: //automatic - if ((player->ringweapons & RW_AUTO) && player->powers[pw_automaticring]) - { - player->currentweapon = WEP_AUTO; - player->pflags |= PF_WPNDOWN; - } - break; - case 3: //bounce - if ((player->ringweapons & RW_BOUNCE) && player->powers[pw_bouncering]) - { - player->currentweapon = WEP_BOUNCE; - player->pflags |= PF_WPNDOWN; - } - break; - case 4: //scatter - if ((player->ringweapons & RW_SCATTER) && player->powers[pw_scatterring]) - { - player->currentweapon = WEP_SCATTER; - player->pflags |= PF_WPNDOWN; - } - break; - case 5: //grenade - if ((player->ringweapons & RW_GRENADE) && player->powers[pw_grenadering]) - { - player->currentweapon = WEP_GRENADE; - player->pflags |= PF_WPNDOWN; - } - break; - case 6: //explosion - if ((player->ringweapons & RW_EXPLODE) && player->powers[pw_explosionring]) - { - player->currentweapon = WEP_EXPLODE; - player->pflags |= PF_WPNDOWN; - } - break; - case 7: //rail - if ((player->ringweapons & RW_RAIL) && player->powers[pw_railring]) - { - player->currentweapon = WEP_RAIL; - player->pflags |= PF_WPNDOWN; - } - break; - } - } - } - - if (!(cmd->buttons & (BT_WEAPONNEXT|BT_WEAPONPREV|BT_WEAPONMASK))) - player->pflags &= ~PF_WPNDOWN; - - // Weapon cycling if out of ammo for a certain weapon - if (player->currentweapon == WEP_AUTO && (!(player->ringweapons & RW_AUTO) || !player->powers[pw_automaticring])) - player->currentweapon++; - if (player->currentweapon == WEP_BOUNCE && (!(player->ringweapons & RW_BOUNCE) || !player->powers[pw_bouncering])) - player->currentweapon++; - if (player->currentweapon == WEP_SCATTER && (!(player->ringweapons & RW_SCATTER) || !player->powers[pw_scatterring])) - player->currentweapon++; - if (player->currentweapon == WEP_GRENADE && (!(player->ringweapons & RW_GRENADE) || !player->powers[pw_grenadering])) - player->currentweapon++; - if (player->currentweapon == WEP_EXPLODE && (!(player->ringweapons & RW_EXPLODE) || !player->powers[pw_explosionring])) - player->currentweapon++; - if (player->currentweapon == WEP_RAIL && (!(player->ringweapons & RW_RAIL) || !player->powers[pw_railring])) - player->currentweapon = 0; - - // If you're out of rings, but have Infinity Rings left, switch to that. - if (player->currentweapon != 0 && player->health <= 1 && player->powers[pw_infinityring]) - player->currentweapon = 0; - - if (P_IsLocalPlayer(player) && (player->pflags & PF_WPNDOWN) && player->currentweapon != oldweapon) - S_StartSound(NULL, sfx_wepchg); - */ - - /* // SRB2kart - if (player->pflags & PF_GLIDING) - { - if (player->panim != PA_ABILITY) - P_SetPlayerMobjState(player->mo, S_PLAY_ABL1); - } - else */ if (player->pflags & PF_SLIDING) P_SetPlayerMobjState(player->mo, player->mo->info->painstate); - /*else if (player->pflags & PF_JUMPED - && ((!player->powers[pw_super] && player->panim != PA_ROLL) - || player->mo->state == &states[player->mo->info->painstate]) - && player->charability2 == CA2_SPINDASH) - P_SetPlayerMobjState(player->mo, S_PLAY_ATK1);*/ - - /* // SRB2kart - fight! fight! fight! - if (player->pflags & PF_CARRIED && player->mo->tracer) - { - player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14*FRACUNIT,10*FRACUNIT)); - - // State check for the carrier - Flame - // You are an IDIOT, those aren't even the right frames! >_> - JTE - if (player->mo->tracer->player - && !(player->mo->tracer->state >= &states[S_PLAY_ABL1] - && player->mo->tracer->state <= &states[S_PLAY_SPC4])) - player->pflags &= ~PF_CARRIED; - - if (player->mo->eflags & MFE_VERTICALFLIP) - { - if ((player->mo->tracer->z + player->mo->tracer->height + player->mo->height + FixedMul(FRACUNIT, player->mo->scale)) <= player->mo->tracer->ceilingz - && (player->mo->tracer->eflags & MFE_VERTICALFLIP)) // Reverse gravity check for the carrier - Flame - player->mo->z = player->mo->tracer->z + player->mo->tracer->height + FixedMul(FRACUNIT, player->mo->scale); - else - player->pflags &= ~PF_CARRIED; - } - else - { - if ((player->mo->tracer->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale)) >= player->mo->tracer->floorz - && !(player->mo->tracer->eflags & MFE_VERTICALFLIP)) // Correct gravity check for the carrier - Flame - player->mo->z = player->mo->tracer->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale); - else - player->pflags &= ~PF_CARRIED; - } - - if (player->mo->tracer->health <= 0) - player->pflags &= ~PF_CARRIED; - else - { - P_TryMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, true); - player->mo->momx = player->mo->tracer->momx; - player->mo->momy = player->mo->tracer->momy; - player->mo->momz = player->mo->tracer->momz; - } - - if (gametype == GT_COOP) - { - player->mo->angle = player->mo->tracer->angle; - - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; - } - - if (P_AproxDistance(player->mo->x - player->mo->tracer->x, player->mo->y - player->mo->tracer->y) > player->mo->radius) - player->pflags &= ~PF_CARRIED; - - P_SetPlayerMobjState(player->mo, S_PLAY_CARRY); - - //if (player-players == consoleplayer && botingame) - //CV_SetValue(&cv_analog2, !(player->pflags & PF_CARRIED)); - } - else if (player->pflags & PF_ITEMHANG && player->mo->tracer) - { - // tracer is what you're hanging onto - P_UnsetThingPosition(player->mo); - player->mo->x = player->mo->tracer->x; - player->mo->y = player->mo->tracer->y; - if (player->mo->eflags & MFE_VERTICALFLIP) - player->mo->z = player->mo->tracer->z + player->mo->tracer->height - FixedDiv(player->mo->height, 3*FRACUNIT); - else - player->mo->z = player->mo->tracer->z - FixedDiv(player->mo->height, 3*FRACUNIT/2); - player->mo->momx = player->mo->momy = player->mo->momz = 0; - P_SetThingPosition(player->mo); - P_SetPlayerMobjState(player->mo, S_PLAY_CARRY); - - // Controllable missile - if (player->mo->tracer->type == MT_BLACKEGGMAN_MISSILE) - { - if (cmd->forwardmove > 0) - player->mo->tracer->momz += FixedMul(FRACUNIT/4, player->mo->tracer->scale); - else if (cmd->forwardmove < 0) - player->mo->tracer->momz -= FixedMul(FRACUNIT/4, player->mo->tracer->scale); - - player->mo->tracer->angle = player->mo->angle; - P_InstaThrust(player->mo->tracer, player->mo->tracer->angle, FixedMul(player->mo->tracer->info->speed, player->mo->tracer->scale)); - - if (player->mo->z <= player->mo->floorz - || player->mo->tracer->health <= 0) - { - player->pflags &= ~PF_ITEMHANG; - P_SetTarget(&player->mo->tracer, NULL); - } - } - } - else */if (player->pflags & PF_MACESPIN && player->mo->tracer && player->mo->tracer->target) - { - player->mo->height = P_GetPlayerSpinHeight(player); - // tracer is what you're hanging onto.... - player->mo->momx = (player->mo->tracer->x - player->mo->x)*2; - player->mo->momy = (player->mo->tracer->y - player->mo->y)*2; - player->mo->momz = (player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2) - player->mo->z)*2; - P_TeleportMove(player->mo, player->mo->tracer->x, player->mo->tracer->y, player->mo->tracer->z - (player->mo->height-player->mo->tracer->height/2)); - player->pflags |= PF_JUMPED; - player->secondjump = 0; - player->pflags &= ~PF_THOKKED; - - if (cmd->forwardmove > 0) - player->mo->tracer->target->lastlook += 2; - else if (cmd->forwardmove < 0 && player->mo->tracer->target->lastlook > player->mo->tracer->target->movecount) - player->mo->tracer->target->lastlook -= 2; - - if (!(player->mo->tracer->target->flags & MF_SLIDEME) // Noclimb on chain parameters gives this - && !(twodlevel || player->mo->flags2 & MF2_TWOD)) // why on earth would you want to turn them in 2D mode? - { - //player->mo->tracer->target->health += cmd->sidemove; - //player->mo->angle += cmd->sidemove< ANGLE_MAX - - if (player == &players[consoleplayer]) - localangle[0] = player->mo->angle; // Adjust the local control angle. - else if (player == &players[displayplayers[1]]) - localangle[1] = player->mo->angle; - else if (player == &players[displayplayers[2]]) - localangle[2] = player->mo->angle; - else if (player == &players[displayplayers[3]]) - localangle[3] = player->mo->angle; - } - } if (thiscam) { @@ -9481,8 +4611,9 @@ void P_PlayerAfterThink(player_t *player) else { // defaults to make sure 1st person cam doesn't do anything weird on startup - //player->deltaviewheight = 0; - player->viewheight = FixedMul(32 << FRACBITS, player->mo->scale); + player->deltaviewheight = 0; + player->viewheight = P_GetPlayerViewHeight(player); + if (player->mo->eflags & MFE_VERTICALFLIP) player->viewz = player->mo->z + player->mo->height - player->viewheight; else @@ -9490,9 +4621,6 @@ void P_PlayerAfterThink(player_t *player) } } - if (player->awayviewtics < 0) - player->awayviewtics = 0; - // spectator invisibility and nogravity. if ((netgame || multiplayer) && player->spectator) { @@ -9504,4 +4632,90 @@ void P_PlayerAfterThink(player_t *player) player->mo->pmomz = 0; K_KartPlayerAfterThink(player); + + if (player->powers[pw_dye]) + { + player->mo->colorized = true; + player->mo->color = player->powers[pw_dye]; + } + + if (player->followmobj && (player->spectator || player->mo->health <= 0 || player->followmobj->type != player->followitem)) + { + P_RemoveMobj(player->followmobj); + P_SetTarget(&player->followmobj, NULL); + } + + if (!player->spectator && player->mo->health && player->followitem) + { + if (!player->followmobj || P_MobjWasRemoved(player->followmobj)) + { + P_SetTarget(&player->followmobj, P_SpawnMobjFromMobj(player->mo, 0, 0, 0, player->followitem)); + P_SetTarget(&player->followmobj->tracer, player->mo); + switch (player->followmobj->type) + { + default: + player->followmobj->flags2 |= MF2_LINKDRAW; + break; + } + } + + if (player->followmobj) + { + if (LUAh_FollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) + {;} + else + { + switch (player->followmobj->type) + { + default: + var1 = 1; + var2 = 0; + A_CapeChase(player->followmobj); + break; + } + } + } + } +} + +void P_SetPlayerAngle(player_t *player, angle_t angle) +{ + P_ForceLocalAngle(player, angle); + player->angleturn = angle; +} + +angle_t P_GetLocalAngle(player_t *player) +{ + // this function is from vanilla srb2. can you tell? + // (hint: they have separate variables for all of this shit instead of arrays) + UINT8 i; + + for (i = 0; i <= r_splitscreen; i++) + { + if (player == &players[displayplayers[i]]) + return localangle[i]; + } + + return 0; +} + +void P_ForceLocalAngle(player_t *player, angle_t angle) +{ + UINT8 i; + + angle = angle & ~UINT16_MAX; + + for (i = 0; i <= r_splitscreen; i++) + { + if (player == &players[displayplayers[i]]) + { + localangle[i] = angle; + break; + } + } +} + +boolean P_PlayerFullbright(player_t *player) +{ + return (player->kartstuff[k_invincibilitytimer] > 0); } diff --git a/src/r_bsp.c b/src/r_bsp.c index 8ec4023c1..495b63d71 100644 --- a/src/r_bsp.c +++ b/src/r_bsp.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,6 +15,7 @@ #include "g_game.h" #include "r_local.h" #include "r_state.h" +#include "r_portal.h" // Add seg portals #include "r_splats.h" #include "p_local.h" // camera @@ -26,11 +27,11 @@ side_t *sidedef; line_t *linedef; sector_t *frontsector; sector_t *backsector; -boolean portalline; // is curline a portal seg? // very ugly realloc() of drawsegs at run-time, I upped it to 512 // instead of 256.. and someone managed to send me a level with // 896 drawsegs! So too bad here's a limit removal a-la-Boom +drawseg_t *curdrawsegs = NULL; /**< This is used to handle multiple lists for masked drawsegs. */ drawseg_t *drawsegs = NULL; drawseg_t *ds_p = NULL; @@ -232,6 +233,26 @@ void R_PortalClearClipSegs(INT32 start, INT32 end) newend = solidsegs + 2; } +// R_DoorClosed +// +// This function is used to fix the automap bug which +// showed lines behind closed doors simply because the door had a dropoff. +// +// It assumes that Doom has already ruled out a door being closed because +// of front-back closure (e.g. front floor is taller than back ceiling). +static INT32 R_DoorClosed(void) +{ + return + + // if door is closed because back is shut: + backsector->ceilingheight <= backsector->floorheight + + // preserve a kind of transparent door/lift special effect: + && (backsector->ceilingheight >= frontsector->ceilingheight || curline->sidedef->toptexture) + + && (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture); +} + // // If player's view height is underneath fake floor, lower the // drawn ceiling to be just under the floor height, and replace @@ -243,8 +264,6 @@ void R_PortalClearClipSegs(INT32 start, INT32 end) sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, INT32 *ceilinglightlevel, boolean back) { - INT32 mapnum = -1; - if (floorlightlevel) *floorlightlevel = sec->floorlightsec == -1 ? sec->lightlevel : sectors[sec->floorlightsec].lightlevel; @@ -253,10 +272,10 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, *ceilinglightlevel = sec->ceilinglightsec == -1 ? sec->lightlevel : sectors[sec->ceilinglightsec].lightlevel; - // If the sector has a midmap, it's probably from 280 type - if (sec->midmap != -1) - mapnum = sec->midmap; - else if (sec->heightsec != -1) + // if (sec->midmap != -1) + // mapnum = sec->midmap; + // In original colormap code, this block did not run if sec->midmap was set + if (!sec->extra_colormap && sec->heightsec != -1) { const sector_t *s = §ors[sec->heightsec]; mobj_t *viewmobj = viewplayer->mo; @@ -287,8 +306,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->floorheight = s->floorheight; tempsec->ceilingheight = s->ceilingheight; - mapnum = s->midmap; - if ((underwater && (tempsec-> floorheight = sec->floorheight, tempsec->ceilingheight = s->floorheight - 1, !back)) || viewz <= s->floorheight) { // head-below-floor hack @@ -314,7 +331,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->ceilingpic_angle = s->ceilingpic_angle; } - mapnum = s->bottommap; } tempsec->lightlevel = s->lightlevel; @@ -338,8 +354,6 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, tempsec->floor_yoffs = tempsec->ceiling_yoffs = s->ceiling_yoffs; tempsec->floorpic_angle = tempsec->ceilingpic_angle = s->ceilingpic_angle; - mapnum = s->topmap; - if (s->floorpic == skyflatnum) // SKYFIX? { tempsec->ceilingheight = tempsec->floorheight-1; @@ -370,26 +384,17 @@ sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, sec = tempsec; } - if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps) - sec->extra_colormap = &extra_colormaps[mapnum]; - else - sec->extra_colormap = NULL; - return sec; } boolean R_IsEmptyLine(seg_t *line, sector_t *front, sector_t *back) { return ( -#ifdef POLYOBJECTS !line->polyseg && -#endif back->ceilingpic == front->ceilingpic && back->floorpic == front->floorpic -#ifdef ESLOPE && back->f_slope == front->f_slope && back->c_slope == front->c_slope -#endif && back->lightlevel == front->lightlevel && !line->sidedef->midtexture // Check offsets too! @@ -417,6 +422,7 @@ static void R_AddLine(seg_t *line) INT32 x1, x2; angle_t angle1, angle2, span, tspan; static sector_t tempsec; + boolean bothceilingssky = false, bothfloorssky = false; portalline = false; @@ -440,34 +446,34 @@ static void R_AddLine(seg_t *line) angle1 -= viewangle; angle2 -= viewangle; - tspan = angle1 + clipangle; - if (tspan > doubleclipangle) + tspan = angle1 + clipangle[viewssnum]; + if (tspan > doubleclipangle[viewssnum]) { - tspan -= doubleclipangle; + tspan -= doubleclipangle[viewssnum]; // Totally off the left edge? if (tspan >= span) return; - angle1 = clipangle; + angle1 = clipangle[viewssnum]; } - tspan = clipangle - angle2; - if (tspan > doubleclipangle) + tspan = clipangle[viewssnum] - angle2; + if (tspan > doubleclipangle[viewssnum]) { - tspan -= doubleclipangle; + tspan -= doubleclipangle[viewssnum]; // Totally off the left edge? if (tspan >= span) return; - angle2 = -(signed)clipangle; + angle2 = -(signed)clipangle[viewssnum]; } // The seg is in the view range, but not necessarily visible. angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; - x1 = viewangletox[angle1]; - x2 = viewangletox[angle2]; + x1 = viewangletox[viewssnum][angle1]; + x2 = viewangletox[viewssnum][angle2]; // Does not cross a pixel? if (x1 >= x2) // killough 1/31/98 -- change == to >= for robustness @@ -486,7 +492,7 @@ static void R_AddLine(seg_t *line) line2 = P_FindSpecialLineFromTag(40, line->linedef->tag, line2); if (line2 >= 0) // found it! { - R_AddPortal(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering + Portal_Add2Lines(line->linedef-lines, line2, x1, x2); // Remember the lines for later rendering //return; // Don't fill in that space now! goto clipsolid; } @@ -503,25 +509,39 @@ static void R_AddLine(seg_t *line) doorclosed = 0; + if (backsector->ceilingpic == skyflatnum && frontsector->ceilingpic == skyflatnum) + bothceilingssky = true; + if (backsector->floorpic == skyflatnum && frontsector->floorpic == skyflatnum) + bothfloorssky = true; + + if (bothceilingssky && bothfloorssky) // everything's sky? let's save us a bit of time then + { + if (!line->polyseg && + !line->sidedef->midtexture + && ((!frontsector->ffloors && !backsector->ffloors) + || (frontsector->tag == backsector->tag))) + return; // line is empty, don't even bother + + goto clippass; // treat like wide open window instead + } + // Closed door. -#ifdef ESLOPE if (frontsector->f_slope || frontsector->c_slope || backsector->f_slope || backsector->c_slope) { fixed_t frontf1,frontf2, frontc1, frontc2; // front floor/ceiling ends fixed_t backf1, backf2, backc1, backc2; // back floor ceiling ends #define SLOPEPARAMS(slope, end1, end2, normalheight) \ - if (slope) { \ - end1 = P_GetZAt(slope, line->v1->x, line->v1->y); \ - end2 = P_GetZAt(slope, line->v2->x, line->v2->y); \ - } else \ - end1 = end2 = normalheight; + end1 = P_GetZAt(slope, line->v1->x, line->v1->y, normalheight); \ + end2 = P_GetZAt(slope, line->v2->x, line->v2->y, normalheight); - SLOPEPARAMS(frontsector->f_slope, frontf1, frontf2, frontsector->floorheight) + SLOPEPARAMS(frontsector->f_slope, frontf1, frontf2, frontsector-> floorheight) SLOPEPARAMS(frontsector->c_slope, frontc1, frontc2, frontsector->ceilingheight) - SLOPEPARAMS( backsector->f_slope, backf1, backf2, backsector->floorheight) - SLOPEPARAMS( backsector->c_slope, backc1, backc2, backsector->ceilingheight) + SLOPEPARAMS( backsector->f_slope, backf1, backf2, backsector-> floorheight) + SLOPEPARAMS( backsector->c_slope, backc1, backc2, backsector->ceilingheight) #undef SLOPEPARAMS - if (viewsector != backsector && viewsector != frontsector) + // if both ceilings are skies, consider it always "open" + // same for floors + if (!bothceilingssky && !bothfloorssky) { if ((backc1 <= frontf1 && backc2 <= frontf2) || (backf1 >= frontc1 && backf2 >= frontc2)) @@ -532,24 +552,25 @@ static void R_AddLine(seg_t *line) // Check for automap fix. Store in doorclosed for r_segs.c doorclosed = (backc1 <= backf1 && backc2 <= backf2 && ((backc1 >= frontc1 && backc2 >= frontc2) || curline->sidedef->toptexture) - && ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture) - && (backsector->ceilingpic != skyflatnum || frontsector->ceilingpic != skyflatnum)); + && ((backf1 <= frontf1 && backf2 >= frontf2) || curline->sidedef->bottomtexture)); if (doorclosed) goto clipsolid; } // Window. - if (backc1 != frontc1 || backc2 != frontc2 - || backf1 != frontf1 || backf2 != frontf2) - { - goto clippass; - } + if (!bothceilingssky) // ceilings are always the "same" when sky + if (backc1 != frontc1 || backc2 != frontc2) + goto clippass; + if (!bothfloorssky) // floors are always the "same" when sky + if (backf1 != frontf1 || backf2 != frontf2) + goto clippass; } else -#endif { - if (viewsector != backsector && viewsector != frontsector) + // if both ceilings are skies, consider it always "open" + // same for floors + if (!bothceilingssky && !bothfloorssky) { if (backsector->ceilingheight <= frontsector->floorheight || backsector->floorheight >= frontsector->ceilingheight) @@ -558,21 +579,18 @@ static void R_AddLine(seg_t *line) } // Check for automap fix. Store in doorclosed for r_segs.c - doorclosed = (backsector->ceilingheight <= backsector->floorheight - && (backsector->ceilingheight >= frontsector->ceilingheight || curline->sidedef->toptexture) - && (backsector->floorheight <= frontsector->floorheight || curline->sidedef->bottomtexture) - && (backsector->ceilingpic != skyflatnum || frontsector->ceilingpic != skyflatnum)); - + doorclosed = R_DoorClosed(); if (doorclosed) goto clipsolid; } // Window. - if (backsector->ceilingheight != frontsector->ceilingheight - || backsector->floorheight != frontsector->floorheight) - { - goto clippass; - } + if (!bothceilingssky) // ceilings are always the "same" when sky + if (backsector->ceilingheight != frontsector->ceilingheight) + goto clippass; + if (!bothfloorssky) // floors are always the "same" when sky + if (backsector->floorheight != frontsector->floorheight) + goto clippass; } // Reject empty lines used for triggers and special events. @@ -640,16 +658,16 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) angle2 = ANGLE_180; } - if ((signed)angle2 >= (signed)clipangle) return false; - if ((signed)angle1 <= -(signed)clipangle) return false; - if ((signed)angle1 >= (signed)clipangle) angle1 = clipangle; - if ((signed)angle2 <= -(signed)clipangle) angle2 = 0-clipangle; + if ((signed)angle2 >= (signed)clipangle[viewssnum]) return false; + if ((signed)angle1 <= -(signed)clipangle[viewssnum]) return false; + if ((signed)angle1 >= (signed)clipangle[viewssnum]) angle1 = clipangle[viewssnum]; + if ((signed)angle2 <= -(signed)clipangle[viewssnum]) angle2 = 0-clipangle[viewssnum]; // Find the first clippost that touches the source post (adjacent pixels are touching). angle1 = (angle1+ANGLE_90)>>ANGLETOFINESHIFT; angle2 = (angle2+ANGLE_90)>>ANGLETOFINESHIFT; - sx1 = viewangletox[angle1]; - sx2 = viewangletox[angle2]; + sx1 = viewangletox[viewssnum][angle1]; + sx2 = viewangletox[viewssnum][angle2]; // Does not cross a pixel. if (sx1 >= sx2) return false; @@ -664,8 +682,6 @@ static boolean R_CheckBBox(const fixed_t *bspcoord) return true; } -#ifdef POLYOBJECTS - size_t numpolys; // number of polyobjects in current subsector size_t num_po_ptrs; // number of polyobject pointers allocated polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers @@ -818,6 +834,9 @@ static void R_AddPolyObjects(subsector_t *sub) po = (polyobj_t *)(po->link.next); } + // for render stats + ps_numpolyobjects += numpolys; + // sort polyobjects R_SortPolyObjects(sub); @@ -829,7 +848,6 @@ static void R_AddPolyObjects(subsector_t *sub) R_AddLine(po_ptrs[i]->segs[j]); } } -#endif // // R_Subsector @@ -869,17 +887,8 @@ static void R_Subsector(size_t num) floorcolormap = ceilingcolormap = frontsector->extra_colormap; - floorcenterz = -#ifdef ESLOPE - frontsector->f_slope ? P_GetZAt(frontsector->f_slope, frontsector->soundorg.x, frontsector->soundorg.y) : -#endif - frontsector->floorheight; - - ceilingcenterz = -#ifdef ESLOPE - frontsector->c_slope ? P_GetZAt(frontsector->c_slope, frontsector->soundorg.x, frontsector->soundorg.y) : -#endif - frontsector->ceilingheight; + floorcenterz = P_GetSectorFloorZAt (frontsector, frontsector->soundorg.x, frontsector->soundorg.y); + ceilingcenterz = P_GetSectorCeilingZAt(frontsector, frontsector->soundorg.x, frontsector->soundorg.y); // Check and prep all 3D floors. Set the sector floor/ceiling light levels and colormaps. if (frontsector->ffloors) @@ -896,11 +905,11 @@ static void R_Subsector(size_t num) light = R_GetPlaneLight(frontsector, floorcenterz, false); if (frontsector->floorlightsec == -1) floorlightlevel = *frontsector->lightlist[light].lightlevel; - floorcolormap = frontsector->lightlist[light].extra_colormap; + floorcolormap = *frontsector->lightlist[light].extra_colormap; light = R_GetPlaneLight(frontsector, ceilingcenterz, false); if (frontsector->ceilinglightsec == -1) ceilinglightlevel = *frontsector->lightlist[light].lightlevel; - ceilingcolormap = frontsector->lightlist[light].extra_colormap; + ceilingcolormap = *frontsector->lightlist[light].extra_colormap; } sub->sector->extra_colormap = frontsector->extra_colormap; @@ -908,52 +917,31 @@ static void R_Subsector(size_t num) R_PlaneLightOverride(frontsector, false, &floorlightlevel); R_PlaneLightOverride(frontsector, true, &ceilinglightlevel); - if ((( -#ifdef ESLOPE - frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) : -#endif - frontsector->floorheight) < viewz || (frontsector->heightsec != -1 - && sectors[frontsector->heightsec].ceilingpic == skyflatnum))) + if (P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz + || frontsector->floorpic == skyflatnum + || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum)) { floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel, - frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL -#ifdef POLYOBJECTS_PLANES - , NULL -#endif -#ifdef ESLOPE - , frontsector->f_slope -#endif - , R_NoEncore(frontsector, false)); + frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL, NULL, frontsector->f_slope, + R_NoEncore(frontsector, false)); } else floorplane = NULL; - if ((( -#ifdef ESLOPE - frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) : -#endif - frontsector->ceilingheight) > viewz || frontsector->ceilingpic == skyflatnum - || (frontsector->heightsec != -1 - && sectors[frontsector->heightsec].floorpic == skyflatnum))) + if (P_GetSectorCeilingZAt(frontsector, viewx, viewy) > viewz + || frontsector->ceilingpic == skyflatnum + || (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum)) { - ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel, - frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, - ceilingcolormap, NULL -#ifdef POLYOBJECTS_PLANES - , NULL -#endif -#ifdef ESLOPE - , frontsector->c_slope -#endif - , R_NoEncore(frontsector, true)); + ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic, + ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle, + ceilingcolormap, NULL, NULL, frontsector->c_slope, + R_NoEncore(frontsector, true)); } else ceilingplane = NULL; numffloors = 0; -#ifdef ESLOPE ffloor[numffloors].slope = NULL; -#endif ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; if (frontsector->ffloors) @@ -978,43 +966,32 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; - heightcheck = -#ifdef ESLOPE - *rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : -#endif - *rover->bottomheight; + heightcheck = P_GetFFloorBottomZAt(rover, viewx, viewy); - planecenterz = -#ifdef ESLOPE - *rover->b_slope ? P_GetZAt(*rover->b_slope, frontsector->soundorg.x, frontsector->soundorg.y) : -#endif - *rover->bottomheight; + planecenterz = P_GetFFloorBottomZAt(rover, frontsector->soundorg.x, frontsector->soundorg.y); if (planecenterz <= ceilingcenterz && planecenterz >= floorcenterz - && ((viewz < heightcheck && !(rover->flags & FF_INVERTPLANES)) - || (viewz > heightcheck && (rover->flags & FF_BOTHPLANES)))) + && ((viewz < heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) + || (viewz > heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { + INT32 newlightlevel; + light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); - ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, - *frontsector->lightlist[light].lightlevel, *rover->bottomxoffs, - *rover->bottomyoffs, *rover->bottomangle, frontsector->lightlist[light].extra_colormap, rover -#ifdef POLYOBJECTS_PLANES - , NULL -#endif -#ifdef ESLOPE - , *rover->b_slope -#endif - , R_NoEncore(rover->master->frontsector, true)); + newlightlevel = *frontsector->lightlist[light].lightlevel; + R_PlaneLightOverride(rover->master->frontsector, true, &newlightlevel); + + ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic, + newlightlevel, *rover->bottomxoffs, + *rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope, + R_NoEncore(rover->master->frontsector, true)); -#ifdef ESLOPE ffloor[numffloors].slope = *rover->b_slope; // Tell the renderer this sector has slopes in it. if (ffloor[numffloors].slope) frontsector->hasslope = true; -#endif ffloor[numffloors].height = heightcheck; ffloor[numffloors].ffloor = rover; @@ -1025,42 +1002,31 @@ static void R_Subsector(size_t num) ffloor[numffloors].plane = NULL; ffloor[numffloors].polyobj = NULL; - heightcheck = -#ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : -#endif - *rover->topheight; + heightcheck = P_GetFFloorTopZAt(rover, viewx, viewy); - planecenterz = -#ifdef ESLOPE - *rover->t_slope ? P_GetZAt(*rover->t_slope, frontsector->soundorg.x, frontsector->soundorg.y) : -#endif - *rover->topheight; + planecenterz = P_GetFFloorTopZAt(rover, frontsector->soundorg.x, frontsector->soundorg.y); if (planecenterz >= floorcenterz && planecenterz <= ceilingcenterz - && ((viewz > heightcheck && !(rover->flags & FF_INVERTPLANES)) - || (viewz < heightcheck && (rover->flags & FF_BOTHPLANES)))) + && ((viewz > heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) + || (viewz < heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { + INT32 newlightlevel; + light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck); + newlightlevel = *frontsector->lightlist[light].lightlevel; + R_PlaneLightOverride(rover->master->frontsector, false, &newlightlevel); + ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic, *frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle, - frontsector->lightlist[light].extra_colormap, rover -#ifdef POLYOBJECTS_PLANES - , NULL -#endif -#ifdef ESLOPE - , *rover->t_slope -#endif - , R_NoEncore(rover->master->frontsector, false)); + *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope, + R_NoEncore(rover->master->frontsector, false)); -#ifdef ESLOPE ffloor[numffloors].slope = *rover->t_slope; // Tell the renderer this sector has slopes in it. if (ffloor[numffloors].slope) frontsector->hasslope = true; -#endif ffloor[numffloors].height = heightcheck; ffloor[numffloors].ffloor = rover; @@ -1069,7 +1035,6 @@ static void R_Subsector(size_t num) } } -#ifdef POLYOBJECTS_PLANES // Polyobjects have planes, too! if (sub->polyList) { @@ -1094,22 +1059,24 @@ static void R_Subsector(size_t num) && polysec->floorheight >= floorcenterz && (viewz < polysec->floorheight)) { + INT32 newlightlevel; + light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); + + newlightlevel = (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel); + R_PlaneLightOverride(polysec, false, &newlightlevel); + ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic, - polysec->lightlevel, polysec->floor_xoffs, polysec->floor_yoffs, - polysec->floorpic_angle-po->angle, - NULL, NULL, po -#ifdef ESLOPE - , NULL // will ffloors be slopable eventually? -#endif - , R_NoEncore(polysec, false)); + (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs, + polysec->floorpic_angle-po->angle, + (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, + NULL, // will ffloors be slopable eventually? + R_NoEncore(polysec, false)); ffloor[numffloors].height = polysec->floorheight; ffloor[numffloors].polyobj = po; -#ifdef ESLOPE ffloor[numffloors].slope = NULL; -#endif -// ffloor[numffloors].ffloor = rover; + //ffloor[numffloors].ffloor = rover; po->visplane = ffloor[numffloors].plane; numffloors++; } @@ -1123,22 +1090,23 @@ static void R_Subsector(size_t num) && polysec->ceilingheight <= ceilingcenterz && (viewz > polysec->ceilingheight)) { - light = R_GetPlaneLight(frontsector, polysec->ceilingheight, viewz < polysec->ceilingheight); + INT32 newlightlevel; + + light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight); + + newlightlevel = (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel); + R_PlaneLightOverride(polysec, true, &newlightlevel); + ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic, - polysec->lightlevel, polysec->ceiling_xoffs, polysec->ceiling_yoffs, - polysec->ceilingpic_angle-po->angle, - NULL, NULL, po -#ifdef ESLOPE - , NULL // will ffloors be slopable eventually? -#endif - , R_NoEncore(polysec, true)); + (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle, + (light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po, + NULL, // will ffloors be slopable eventually? + R_NoEncore(polysec, true)); ffloor[numffloors].polyobj = po; ffloor[numffloors].height = polysec->ceilingheight; -#ifdef ESLOPE ffloor[numffloors].slope = NULL; -#endif -// ffloor[numffloors].ffloor = rover; + //ffloor[numffloors].ffloor = rover; po->visplane = ffloor[numffloors].plane; numffloors++; } @@ -1146,7 +1114,6 @@ static void R_Subsector(size_t num) po = (polyobj_t *)(po->link.next); } } -#endif #ifdef FLOORSPLATS if (sub->splats) @@ -1169,19 +1136,15 @@ static void R_Subsector(size_t num) firstseg = NULL; -#ifdef POLYOBJECTS // haleyjd 02/19/06: draw polyobjects before static lines if (sub->polyList) R_AddPolyObjects(sub); -#endif while (count--) { // CONS_Debug(DBG_GAMELOGIC, "Adding normal line %d...(%d)\n", line->linedef-lines, leveltime); -#ifdef POLYOBJECTS - if (!line->polyseg) // ignore segs that belong to polyobjects -#endif - R_AddLine(line); + if (!line->glseg && !line->polyseg) // ignore segs that belong to polyobjects + R_AddLine(line); line++; curline = NULL; /* cph 2001/11/18 - must clear curline now we're done with it, so stuff doesn't try using it for other things */ } @@ -1197,13 +1160,11 @@ void R_Prep3DFloors(sector_t *sector) ffloor_t *rover; ffloor_t *best; fixed_t bestheight, maxheight; - INT32 count, i, mapnum; + INT32 count, i; sector_t *sec; -#ifdef ESLOPE pslope_t *bestslope = NULL; fixed_t heighttest; // I think it's better to check the Z height at the sector's center // than assume unsloped heights are accurate indicators of order in sloped sectors. -Red -#endif count = 1; for (rover = sector->ffloors; rover; rover = rover->next) @@ -1226,17 +1187,13 @@ void R_Prep3DFloors(sector_t *sector) else memset(sector->lightlist, 0, sizeof (lightlist_t) * count); -#ifdef ESLOPE - heighttest = sector->c_slope ? P_GetZAt(sector->c_slope, sector->soundorg.x, sector->soundorg.y) : sector->ceilingheight; + heighttest = P_GetSectorCeilingZAt(sector, sector->soundorg.x, sector->soundorg.y); sector->lightlist[0].height = heighttest + 1; sector->lightlist[0].slope = sector->c_slope; -#else - sector->lightlist[0].height = sector->ceilingheight + 1; -#endif sector->lightlist[0].lightlevel = §or->lightlevel; sector->lightlist[0].caster = NULL; - sector->lightlist[0].extra_colormap = sector->extra_colormap; + sector->lightlist[0].extra_colormap = §or->extra_colormap; sector->lightlist[0].flags = 0; maxheight = INT32_MAX; @@ -1251,8 +1208,7 @@ void R_Prep3DFloors(sector_t *sector) && !(rover->flags & FF_CUTLEVEL) && !(rover->flags & FF_CUTSPRITES))) continue; -#ifdef ESLOPE - heighttest = *rover->t_slope ? P_GetZAt(*rover->t_slope, sector->soundorg.x, sector->soundorg.y) : *rover->topheight; + heighttest = P_GetFFloorTopZAt(rover, sector->soundorg.x, sector->soundorg.y); if (heighttest > bestheight && heighttest < maxheight) { @@ -1262,7 +1218,7 @@ void R_Prep3DFloors(sector_t *sector) continue; } if (rover->flags & FF_DOUBLESHADOW) { - heighttest = *rover->b_slope ? P_GetZAt(*rover->b_slope, sector->soundorg.x, sector->soundorg.y) : *rover->bottomheight; + heighttest = P_GetFFloorBottomZAt(rover, sector->soundorg.x, sector->soundorg.y); if (heighttest > bestheight && heighttest < maxheight) @@ -1273,21 +1229,6 @@ void R_Prep3DFloors(sector_t *sector) continue; } } -#else - if (*rover->topheight > bestheight && *rover->topheight < maxheight) - { - best = rover; - bestheight = *rover->topheight; - continue; - } - if (rover->flags & FF_DOUBLESHADOW && *rover->bottomheight > bestheight - && *rover->bottomheight < maxheight) - { - best = rover; - bestheight = *rover->bottomheight; - continue; - } -#endif } if (!best) { @@ -1298,15 +1239,8 @@ void R_Prep3DFloors(sector_t *sector) sector->lightlist[i].height = maxheight = bestheight; sector->lightlist[i].caster = best; sector->lightlist[i].flags = best->flags; -#ifdef ESLOPE sector->lightlist[i].slope = bestslope; -#endif sec = §ors[best->secnum]; - mapnum = sec->midmap; - if (mapnum >= 0 && (size_t)mapnum < num_extra_colormaps) - sec->extra_colormap = &extra_colormaps[mapnum]; - else - sec->extra_colormap = NULL; if (best->flags & FF_NOSHADE) { @@ -1316,22 +1250,18 @@ void R_Prep3DFloors(sector_t *sector) else if (best->flags & FF_COLORMAPONLY) { sector->lightlist[i].lightlevel = sector->lightlist[i-1].lightlevel; - sector->lightlist[i].extra_colormap = sec->extra_colormap; + sector->lightlist[i].extra_colormap = &sec->extra_colormap; } else { sector->lightlist[i].lightlevel = best->toplightlevel; - sector->lightlist[i].extra_colormap = sec->extra_colormap; + sector->lightlist[i].extra_colormap = &sec->extra_colormap; } if (best->flags & FF_DOUBLESHADOW) { -#ifdef ESLOPE - heighttest = *best->b_slope ? P_GetZAt(*best->b_slope, sector->soundorg.x, sector->soundorg.y) : *best->bottomheight; + heighttest = P_GetFFloorBottomZAt(best, sector->soundorg.x, sector->soundorg.y); if (bestheight == heighttest) ///TODO: do this in a more efficient way -Red -#else - if (bestheight == *best->bottomheight) -#endif { sector->lightlist[i].lightlevel = sector->lightlist[best->lastlight].lightlevel; sector->lightlist[i].extra_colormap = @@ -1375,6 +1305,9 @@ void R_RenderBSPNode(INT32 bspnum) { node_t *bsp; INT32 side; + + ps_numbspcalls++; + while (!(bspnum & NF_SUBSECTOR)) // Found a subsector? { bsp = &nodes[bspnum]; diff --git a/src/r_bsp.h b/src/r_bsp.h index 1e4ca68fc..4e0ed1bbc 100644 --- a/src/r_bsp.h +++ b/src/r_bsp.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -29,6 +29,7 @@ extern boolean portalline; // is curline a portal seg? extern INT32 checkcoord[12][4]; +extern drawseg_t *curdrawsegs; extern drawseg_t *drawsegs; extern drawseg_t *ds_p; extern INT32 doorclosed; @@ -38,19 +39,16 @@ void R_ClearClipSegs(void); void R_PortalClearClipSegs(INT32 start, INT32 end); void R_ClearDrawSegs(void); void R_RenderBSPNode(INT32 bspnum); -void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2); // determines when a given sector shouldn't abide by the encoremap's palette. // no longer a static since this is used for encore in hw_main.c as well now: boolean R_NoEncore(sector_t *sector, boolean ceiling); -#ifdef POLYOBJECTS void R_SortPolyObjects(subsector_t *sub); extern size_t numpolys; // number of polyobjects in current subsector extern size_t num_po_ptrs; // number of polyobject pointers allocated extern polyobj_t **po_ptrs; // temp ptr array to sort polyobject pointers -#endif sector_t *R_FakeFlat(sector_t *sec, sector_t *tempsec, INT32 *floorlightlevel, INT32 *ceilinglightlevel, boolean back); diff --git a/src/r_data.c b/src/r_data.c index 8cb839ac4..fcc316362 100644 --- a/src/r_data.c +++ b/src/r_data.c @@ -2,14 +2,14 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. // See the 'LICENSE' file for more details. //----------------------------------------------------------------------------- /// \file r_data.c -/// \brief Preparation of data for rendering,generation of lookups, caching, retrieval by name +/// \brief Preparation of data for rendering, generation of lookups, caching, retrieval by name #include "doomdef.h" #include "g_game.h" @@ -19,70 +19,20 @@ #include "p_local.h" #include "m_misc.h" #include "r_data.h" +#include "r_textures.h" +#include "r_picformats.h" #include "w_wad.h" #include "z_zone.h" #include "p_setup.h" // levelflats #include "v_video.h" // pMasterPalette +#include "f_finale.h" // wipes +#include "byteptr.h" #include "dehacked.h" -#if defined (_WIN32) || defined (_WIN32_WCE) +#ifdef _WIN32 #include // alloca(sizeof) #endif -#if defined(_MSC_VER) -#pragma pack(1) -#endif - -// Not sure if this is necessary, but it was in w_wad.c, so I'm putting it here too -Shadow Hog -#ifdef _WIN32_WCE -#define AVOID_ERRNO -#else -#include -#endif - -// -// Texture definition. -// Each texture is composed of one or more patches, -// with patches being lumps stored in the WAD. -// The lumps are referenced by number, and patched -// into the rectangular texture space using origin -// and possibly other attributes. -// -typedef struct -{ - INT16 originx, originy; - INT16 patch, stepdir, colormap; -} ATTRPACK mappatch_t; - -// -// Texture definition. -// An SRB2 wall texture is a list of patches -// which are to be combined in a predefined order. -// -typedef struct -{ - char name[8]; - INT32 masked; - INT16 width; - INT16 height; - INT32 columndirectory; // FIXTHIS: OBSOLETE - INT16 patchcount; - mappatch_t patches[1]; -} ATTRPACK maptexture_t; - -#if defined(_MSC_VER) -#pragma pack() -#endif - - -// Store lists of lumps for F_START/F_END etc. -typedef struct -{ - UINT16 wadfile; - UINT16 firstlump; - size_t numlumps; -} lumplist_t; - // // Graphics. // SRB2 graphics for walls and sprites @@ -93,839 +43,173 @@ typedef struct size_t numspritelumps, max_spritelumps; -// textures -INT32 numtextures = 0; // total number of textures found, -// size of following tables - -texture_t **textures = NULL; -static UINT32 **texturecolumnofs; // column offset lookup table for each texture -static UINT8 **texturecache; // graphics data for each generated full-size texture - -// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -INT32 *texturewidthmask; - -fixed_t *textureheight; // needed for texture pegging - -INT32 *texturetranslation; - // needed for pre rendering sprcache_t *spritecachedinfo; lighttable_t *colormaps; UINT8 *encoremap; -#ifdef HASINVERT -UINT8 invertmap[256]; -#endif // for debugging/info purposes -static size_t flatmemory, spritememory, texturememory; +size_t flatmemory, spritememory, texturememory; // highcolor stuff INT16 color8to16[256]; // remap color index to highcolor rgb value INT16 *hicolormaps; // test a 32k colormap remaps high -> high -// Painfully simple texture id cacheing to make maps load faster. :3 -static struct { - char name[9]; - INT32 id; -} *tidcache = NULL; -static INT32 tidcachelen = 0; - -// -// MAPTEXTURE_T CACHING -// When a texture is first needed, it counts the number of composite columns -// required in the texture and allocates space for a column directory and -// any new columns. -// The directory will simply point inside other patches if there is only one -// patch in a given column, but any columns with multiple patches will have -// new column_ts generated. -// - -// -// R_DrawColumnInCache -// Clip and draw a column from a patch into a cached post. -// -static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, INT32 originy, INT32 cacheheight) +// Blends two pixels together, using the equation +// that matches the specified alpha style. +UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) { - INT32 count, position; - UINT8 *source; - INT32 topdelta, prevdelta = -1; - - while (patch->topdelta != 0xff) + RGBA_t output; + INT16 fullalpha = (alpha - (0xFF - foreground.s.alpha)); + if (style == AST_TRANSLUCENT) { - topdelta = patch->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - source = (UINT8 *)patch + 3; - count = patch->length; - position = originy + topdelta; - - if (position < 0) - { - count += position; - position = 0; - } - - if (position + count > cacheheight) - count = cacheheight - position; - - if (count > 0) - M_Memcpy(cache + position, source, count); - - patch = (column_t *)((UINT8 *)patch + patch->length + 4); - } -} - -// -// R_GenerateTexture -// -// Allocate space for full size texture, either single patch or 'composite' -// Build the full textures from patches. -// The texture caching system is a little more hungry of memory, but has -// been simplified for the sake of highcolor, dynamic ligthing, & speed. -// -// This is not optimised, but it's supposed to be executed only once -// per level, when enough memory is available. -// -static UINT8 *R_GenerateTexture(size_t texnum) -{ - UINT8 *block; - UINT8 *blocktex; - texture_t *texture; - texpatch_t *patch; - patch_t *realpatch; - int x, x1, x2, i; - size_t blocksize; - column_t *patchcol; - UINT8 *colofs; - - I_Assert(texnum <= (size_t)numtextures); - texture = textures[texnum]; - I_Assert(texture != NULL); - - // allocate texture column offset lookup - - // single-patch textures can have holes in them and may be used on - // 2sided lines so they need to be kept in 'packed' format - // BUT this is wrong for skies and walls with over 255 pixels, - // so check if there's holes and if not strip the posts. - if (texture->patchcount == 1) - { - boolean holey = false; - patch = texture->patches; - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); - - // Check the patch for holes. - if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) - holey = true; - colofs = (UINT8 *)realpatch->columnofs; - for (x = 0; x < texture->width && !holey; x++) - { - column_t *col = (column_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); - INT32 topdelta, prevdelta = -1, y = 0; - while (col->topdelta != 0xff) - { - topdelta = col->topdelta; - if (topdelta <= prevdelta) - topdelta += prevdelta; - prevdelta = topdelta; - if (topdelta > y) - break; - y = topdelta + col->length + 1; - col = (column_t *)((UINT8 *)col + col->length + 4); - } - if (y < texture->height) - holey = true; // this texture is HOLEy! D: - } - - // If the patch uses transparency, we have to save it this way. - if (holey) - { - texture->holes = true; - blocksize = W_LumpLengthPwad(patch->wad, patch->lump); - block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function - &texturecache[texnum]); - M_Memcpy(block, realpatch, blocksize); - texturememory += blocksize; - - // use the patch's column lookup - colofs = (block + 8); - texturecolumnofs[texnum] = (UINT32 *)colofs; - blocktex = block; - for (x = 0; x < texture->width; x++) - *(UINT32 *)&colofs[x<<2] = LONG(LONG(*(UINT32 *)&colofs[x<<2]) + 3); - goto done; - } - - // Otherwise, do multipatch format. - } - - // multi-patch textures (or 'composite') - texture->holes = false; - blocksize = (texture->width * 4) + (texture->width * texture->height); - texturememory += blocksize; - block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]); - - memset(block, 0xFF, blocksize+1); // TRANSPARENTPIXEL - - // columns lookup table - colofs = block; - texturecolumnofs[texnum] = (UINT32 *)colofs; - - // texture data after the lookup table - blocktex = block + (texture->width*4); - - // Composite the columns together. - for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) - { - realpatch = W_CacheLumpNumPwad(patch->wad, patch->lump, PU_CACHE); - x1 = patch->originx; - x2 = x1 + SHORT(realpatch->width); - - if (x1 < 0) - x = 0; - else - x = x1; - - if (x2 > texture->width) - x2 = texture->width; - - for (; x < x2; x++) - { - patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); - - // generate column ofset lookup - *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); - R_DrawColumnInCache(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch->originy, texture->height); - } - } - -done: - // Now that the texture has been built in column cache, it is purgable from zone memory. - Z_ChangeTag(block, PU_CACHE); - return blocktex; -} - -// -// R_GetTextureNum -// -// Returns the actual texture id that we should use. -// This can either be texnum, the current frame for texnum's anim (if animated), -// or 0 if not valid. -// -INT32 R_GetTextureNum(INT32 texnum) -{ - if (texnum < 0 || texnum >= numtextures) - return 0; - return texturetranslation[texnum]; -} - -// -// R_CheckTextureCache -// -// Use this if you need to make sure the texture is cached before R_GetColumn calls -// e.g.: midtextures and FOF walls -// -void R_CheckTextureCache(INT32 tex) -{ - if (!texturecache[tex]) - R_GenerateTexture(tex); -} - -// -// R_GetColumn -// -UINT8 *R_GetColumn(fixed_t tex, INT32 col) -{ - UINT8 *data; - - col &= texturewidthmask[tex]; - data = texturecache[tex]; - - if (!data) - data = R_GenerateTexture(tex); - - return data + LONG(texturecolumnofs[tex][col]); -} - -// convert flats to hicolor as they are requested -// -UINT8 *R_GetFlat(lumpnum_t flatlumpnum) -{ - return W_CacheLumpNum(flatlumpnum, PU_CACHE); -} - -// -// Empty the texture cache (used for load wad at runtime) -// -void R_FlushTextureCache(void) -{ - INT32 i; - - if (numtextures) - for (i = 0; i < numtextures; i++) - Z_Free(texturecache[i]); -} - -// Need these prototypes for later; defining them here instead of r_data.h so they're "private" -int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum); -void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); - -// -// R_LoadTextures -// Initializes the texture list with the textures from the world map. -// -#define TX_START "TX_START" -#define TX_END "TX_END" -void R_LoadTextures(void) -{ - INT32 i, k, w; - UINT16 j; - UINT16 texstart, texend, texturesLumpPos; - patch_t *patchlump; - texpatch_t *patch; - texture_t *texture; - - // Free previous memory before numtextures change. - if (numtextures) - { - for (i = 0; i < numtextures; i++) - { - Z_Free(textures[i]); - Z_Free(texturecache[i]); - } - Z_Free(texturetranslation); - Z_Free(textures); - } - - // Load patches and textures. - - // Get the number of textures to check. - // NOTE: Make SURE the system does not process - // the markers. - // This system will allocate memory for all duplicate/patched textures even if it never uses them, - // but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures. - for (w = 0, numtextures = 0; w < numwadfiles; w++) - { - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); - } + if (fullalpha <= 0) + output.rgba = background.rgba; else { - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - } + // don't go too high + if (fullalpha >= 0xFF) + fullalpha = 0xFF; + alpha = (UINT8)fullalpha; - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - while (texturesLumpPos != INT16_MAX) - { - numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); - } - - // Add all the textures between TX_START and TX_END - if (texstart != INT16_MAX && texend != INT16_MAX) - { - numtextures += (UINT32)(texend - texstart); - } - - // If no textures found by this point, bomb out - if (!numtextures && w == (numwadfiles - 1)) - { - I_Error("No textures detected in any WADs!\n"); - } - } - - // Allocate memory and initialize to 0 for all the textures we are initialising. - // There are actually 5 buffers allocated in one for convenience. - textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL); - - // Allocate texture column offset table. - texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); - // Allocate texture referencing cache. - texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); - // Allocate texture width mask table. - texturewidthmask = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); - // Allocate texture height mask table. - textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); - // Create translation table for global animation. - texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); - - for (i = 0; i < numtextures; i++) - texturetranslation[i] = i; - - for (i = 0, w = 0; w < numwadfiles; w++) - { - // Get the lump numbers for the markers in the WAD, if they exist. - if (wadfiles[w]->type == RET_PK3) - { - texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); - texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - while (texturesLumpPos != INT16_MAX) + // if the background pixel is empty, + // match software and don't blend anything + if (!background.s.alpha) { - R_ParseTEXTURESLump(w, texturesLumpPos, &i); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); - } - } - else - { - texstart = W_CheckNumForNamePwad(TX_START, (UINT16)w, 0) + 1; - texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); - texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); - if (texturesLumpPos != INT16_MAX) - R_ParseTEXTURESLump(w, texturesLumpPos, &i); - } - - if (texstart == INT16_MAX || texend == INT16_MAX) - continue; - - // Work through each lump between the markers in the WAD. - for (j = 0; j < (texend - texstart); i++, j++) - { - patchlump = W_CacheLumpNumPwad((UINT16)w, texstart + j, PU_CACHE); - - // Then, check the lump directly to see if it's a texture SOC, - // and if it is, load it using dehacked instead. - if (strstr((const char *)patchlump, "TEXTURE")) - { - CONS_Alert(CONS_WARNING, "%s is a Texture SOC.\n", W_CheckNameForNumPwad((UINT16)w,texstart+j)); - Z_Unlock(patchlump); - DEH_LoadDehackedLumpPwad((UINT16)w, texstart + j); - } - else - { - //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); - texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); - - // Set texture properties. - M_Memcpy(texture->name, W_CheckNameForNumPwad((UINT16)w, texstart + j), sizeof(texture->name)); - texture->width = SHORT(patchlump->width); - texture->height = SHORT(patchlump->height); - texture->patchcount = 1; - texture->holes = false; - - // Allocate information for the texture's patches. - patch = &texture->patches[0]; - - patch->originx = patch->originy = 0; - patch->wad = (UINT16)w; - patch->lump = texstart + j; - - Z_Unlock(patchlump); - - k = 1; - while (k << 1 <= texture->width) - k <<= 1; - - texturewidthmask[i] = k - 1; - textureheight[i] = texture->height << FRACBITS; - } - } - } -} - -static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) -{ - char *texturesToken; - size_t texturesTokenLength; - char *endPos; - char *patchName = NULL; - INT16 patchXPos; - INT16 patchYPos; - texpatch_t *resultPatch = NULL; - lumpnum_t patchLumpNum; - - // Patch identifier - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch name should be"); - } - texturesTokenLength = strlen(texturesToken); - if (texturesTokenLength>8) - { - I_Error("Error parsing TEXTURES lump: Patch name \"%s\" exceeds 8 characters",texturesToken); - } - else - { - if (patchName != NULL) - { - Z_Free(patchName); - } - patchName = (char *)Z_Malloc((texturesTokenLength+1)*sizeof(char),PU_STATIC,NULL); - M_Memcpy(patchName,texturesToken,texturesTokenLength*sizeof(char)); - patchName[texturesTokenLength] = '\0'; - } - - // Comma 1 - Z_Free(texturesToken); - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after \"%s\"'s patch name should be",patchName); - } - if (strcmp(texturesToken,",")!=0) - { - I_Error("Error parsing TEXTURES lump: Expected \",\" after %s's patch name, got \"%s\"",patchName,texturesToken); - } - - // XPos - Z_Free(texturesToken); - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s x coordinate should be",patchName); - } - endPos = NULL; -#ifndef AVOID_ERRNO - errno = 0; -#endif - patchXPos = strtol(texturesToken,&endPos,10); - (void)patchXPos; //unused for now - if (endPos == texturesToken // Empty string - || *endPos != '\0' // Not end of string -#ifndef AVOID_ERRNO - || errno == ERANGE // Number out-of-range -#endif - ) - { - I_Error("Error parsing TEXTURES lump: Expected an integer for patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken); - } - - // Comma 2 - Z_Free(texturesToken); - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after patch \"%s\"'s x coordinate should be",patchName); - } - if (strcmp(texturesToken,",")!=0) - { - I_Error("Error parsing TEXTURES lump: Expected \",\" after patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken); - } - - // YPos - Z_Free(texturesToken); - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s y coordinate should be",patchName); - } - endPos = NULL; -#ifndef AVOID_ERRNO - errno = 0; -#endif - patchYPos = strtol(texturesToken,&endPos,10); - (void)patchYPos; //unused for now - if (endPos == texturesToken // Empty string - || *endPos != '\0' // Not end of string -#ifndef AVOID_ERRNO - || errno == ERANGE // Number out-of-range -#endif - ) - { - I_Error("Error parsing TEXTURES lump: Expected an integer for patch \"%s\"'s y coordinate, got \"%s\"",patchName,texturesToken); - } - Z_Free(texturesToken); - - if (actuallyLoadPatch == true) - { - // Check lump exists - patchLumpNum = W_GetNumForName(patchName); - // If so, allocate memory for texpatch_t and fill 'er up - resultPatch = (texpatch_t *)Z_Malloc(sizeof(texpatch_t),PU_STATIC,NULL); - resultPatch->originx = patchXPos; - resultPatch->originy = patchYPos; - resultPatch->lump = patchLumpNum & 65535; - resultPatch->wad = patchLumpNum>>16; - // Clean up a little after ourselves - Z_Free(patchName); - // Then return it - return resultPatch; - } - else - { - Z_Free(patchName); - return NULL; - } -} - -static texture_t *R_ParseTexture(boolean actuallyLoadTexture) -{ - char *texturesToken; - size_t texturesTokenLength; - char *endPos; - INT32 newTextureWidth; - INT32 newTextureHeight; - texture_t *resultTexture = NULL; - texpatch_t *newPatch; - char newTextureName[9]; // no longer dynamically allocated - - // Texture name - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where texture name should be"); - } - texturesTokenLength = strlen(texturesToken); - if (texturesTokenLength>8) - { - I_Error("Error parsing TEXTURES lump: Texture name \"%s\" exceeds 8 characters",texturesToken); - } - else - { - memset(&newTextureName, 0, 9); - M_Memcpy(newTextureName, texturesToken, texturesTokenLength); - // ^^ we've confirmed that the token is <= 8 characters so it will never overflow a 9 byte char buffer - strupr(newTextureName); // Just do this now so we don't have to worry about it - } - Z_Free(texturesToken); - - // Comma 1 - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after texture \"%s\"'s name should be",newTextureName); - } - else if (strcmp(texturesToken,",")!=0) - { - I_Error("Error parsing TEXTURES lump: Expected \",\" after texture \"%s\"'s name, got \"%s\"",newTextureName,texturesToken); - } - Z_Free(texturesToken); - - // Width - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where texture \"%s\"'s width should be",newTextureName); - } - endPos = NULL; -#ifndef AVOID_ERRNO - errno = 0; -#endif - newTextureWidth = strtol(texturesToken,&endPos,10); - if (endPos == texturesToken // Empty string - || *endPos != '\0' // Not end of string -#ifndef AVOID_ERRNO - || errno == ERANGE // Number out-of-range -#endif - || newTextureWidth < 0) // Number is not positive - { - I_Error("Error parsing TEXTURES lump: Expected a positive integer for texture \"%s\"'s width, got \"%s\"",newTextureName,texturesToken); - } - Z_Free(texturesToken); - - // Comma 2 - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after texture \"%s\"'s width should be",newTextureName); - } - if (strcmp(texturesToken,",")!=0) - { - I_Error("Error parsing TEXTURES lump: Expected \",\" after texture \"%s\"'s width, got \"%s\"",newTextureName,texturesToken); - } - Z_Free(texturesToken); - - // Height - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where texture \"%s\"'s height should be",newTextureName); - } - endPos = NULL; -#ifndef AVOID_ERRNO - errno = 0; -#endif - newTextureHeight = strtol(texturesToken,&endPos,10); - if (endPos == texturesToken // Empty string - || *endPos != '\0' // Not end of string -#ifndef AVOID_ERRNO - || errno == ERANGE // Number out-of-range -#endif - || newTextureHeight < 0) // Number is not positive - { - I_Error("Error parsing TEXTURES lump: Expected a positive integer for texture \"%s\"'s height, got \"%s\"",newTextureName,texturesToken); - } - Z_Free(texturesToken); - - // Left Curly Brace - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where open curly brace for texture \"%s\" should be",newTextureName); - } - if (strcmp(texturesToken,"{")==0) - { - if (actuallyLoadTexture) - { - // Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily. - resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL); - M_Memcpy(resultTexture->name, newTextureName, 8); - resultTexture->width = newTextureWidth; - resultTexture->height = newTextureHeight; - } - Z_Free(texturesToken); - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch definition for texture \"%s\" should be",newTextureName); - } - while (strcmp(texturesToken,"}")!=0) - { - if (stricmp(texturesToken, "PATCH")==0) - { - Z_Free(texturesToken); - if (resultTexture) - { - // Get that new patch - newPatch = R_ParsePatch(true); - // Make room for the new patch - resultTexture = Z_Realloc(resultTexture, sizeof(texture_t) + (resultTexture->patchcount+1)*sizeof(texpatch_t), PU_STATIC, NULL); - // Populate the uninitialized values in the new patch entry of our array - M_Memcpy(&resultTexture->patches[resultTexture->patchcount], newPatch, sizeof(texpatch_t)); - // Account for the new number of patches in the texture - resultTexture->patchcount++; - // Then free up the memory assigned to R_ParsePatch, as it's unneeded now - Z_Free(newPatch); - } + // ...unless the foreground pixel ISN'T actually translucent. + if (alpha == 0xFF) + output.rgba = foreground.rgba; else - { - R_ParsePatch(false); - } + output.rgba = 0; } else { - I_Error("Error parsing TEXTURES lump: Expected \"PATCH\" in texture \"%s\", got \"%s\"",newTextureName,texturesToken); - } - - texturesToken = M_GetToken(NULL); - if (texturesToken == NULL) - { - I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch declaration or right curly brace for texture \"%s\" should be",newTextureName); + UINT8 beta = (0xFF - alpha); + output.s.red = ((background.s.red * beta) + (foreground.s.red * alpha)) / 0xFF; + output.s.green = ((background.s.green * beta) + (foreground.s.green * alpha)) / 0xFF; + output.s.blue = ((background.s.blue * beta) + (foreground.s.blue * alpha)) / 0xFF; + output.s.alpha = 0xFF; } } - if (resultTexture && resultTexture->patchcount == 0) - { - I_Error("Error parsing TEXTURES lump: Texture \"%s\" must have at least one patch",newTextureName); - } + return output.rgba; } +#define clamp(c) max(min(c, 0xFF), 0x00); else { - I_Error("Error parsing TEXTURES lump: Expected \"{\" for texture \"%s\", got \"%s\"",newTextureName,texturesToken); - } - Z_Free(texturesToken); + float falpha = ((float)alpha / 256.0f); + float fr = ((float)foreground.s.red * falpha); + float fg = ((float)foreground.s.green * falpha); + float fb = ((float)foreground.s.blue * falpha); + if (style == AST_ADD) + { + output.s.red = clamp((int)(background.s.red + fr)); + output.s.green = clamp((int)(background.s.green + fg)); + output.s.blue = clamp((int)(background.s.blue + fb)); + } + else if (style == AST_SUBTRACT) + { + output.s.red = clamp((int)(background.s.red - fr)); + output.s.green = clamp((int)(background.s.green - fg)); + output.s.blue = clamp((int)(background.s.blue - fb)); + } + else if (style == AST_REVERSESUBTRACT) + { + output.s.red = clamp((int)((-background.s.red) + fr)); + output.s.green = clamp((int)((-background.s.green) + fg)); + output.s.blue = clamp((int)((-background.s.blue) + fb)); + } + else if (style == AST_MODULATE) + { + fr = ((float)foreground.s.red / 256.0f); + fg = ((float)foreground.s.green / 256.0f); + fb = ((float)foreground.s.blue / 256.0f); + output.s.red = clamp((int)(background.s.red * fr)); + output.s.green = clamp((int)(background.s.green * fg)); + output.s.blue = clamp((int)(background.s.blue * fb)); + } + // just copy the pixel + else if (style == AST_COPY) + output.rgba = foreground.rgba; - if (actuallyLoadTexture) return resultTexture; - else return NULL; + output.s.alpha = 0xFF; + return output.rgba; + } +#undef clamp + return 0; } -// Parses the TEXTURES lump... but just to count the number of textures. -int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) +INT32 ASTTextureBlendingThreshold[2] = {255/11, (10*255/11)}; + +// Blends a pixel for a texture patch. +UINT32 ASTBlendTexturePixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha) { - char *texturesLump; - size_t texturesLumpLength; - char *texturesText; - UINT32 numTexturesInLump = 0; - char *texturesToken; - - // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll - // need to make a space of memory where I can ensure that it will terminate - // correctly. Start by loading the relevant data from the WAD. - texturesLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); - // If that didn't exist, we have nothing to do here. - if (texturesLump == NULL) return 0; - // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. - texturesLumpLength = W_LumpLengthPwad(wadNum, lumpNum); - texturesText = (char *)Z_Malloc((texturesLumpLength+1)*sizeof(char),PU_STATIC,NULL); - // Now move the contents of the lump into this new location. - memmove(texturesText,texturesLump,texturesLumpLength); - // Make damn well sure the last character in our new memory location is \0. - texturesText[texturesLumpLength] = '\0'; - // Finally, free up the memory from the first data load, because we really - // don't need it. - Z_Free(texturesLump); - - texturesToken = M_GetToken(texturesText); - while (texturesToken != NULL) + // Alpha style set to translucent? + if (style == AST_TRANSLUCENT) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + // Is the alpha small enough for translucency? + if (alpha <= ASTTextureBlendingThreshold[1]) { - numTexturesInLump++; - Z_Free(texturesToken); - R_ParseTexture(false); - } - else - { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); - } - texturesToken = M_GetToken(NULL); - } - Z_Free(texturesToken); - Z_Free((void *)texturesText); + // Is the patch way too translucent? Don't blend then. + if (alpha < ASTTextureBlendingThreshold[0]) + return background.rgba; - return numTexturesInLump; + return ASTBlendPixel(background, foreground, style, alpha); + } + else // just copy the pixel + return foreground.rgba; + } + else + return ASTBlendPixel(background, foreground, style, alpha); } -// Parses the TEXTURES lump... for real, this time. -void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) +// Blends two palette indexes for a texture patch, then +// finds the nearest palette index from the blended output. +UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT8 alpha) { - char *texturesLump; - size_t texturesLumpLength; - char *texturesText; - char *texturesToken; - texture_t *newTexture; - - I_Assert(texindex != NULL); - - // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll - // need to make a space of memory where I can ensure that it will terminate - // correctly. Start by loading the relevant data from the WAD. - texturesLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); - // If that didn't exist, we have nothing to do here. - if (texturesLump == NULL) return; - // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. - texturesLumpLength = W_LumpLengthPwad(wadNum, lumpNum); - texturesText = (char *)Z_Malloc((texturesLumpLength+1)*sizeof(char),PU_STATIC,NULL); - // Now move the contents of the lump into this new location. - memmove(texturesText,texturesLump,texturesLumpLength); - // Make damn well sure the last character in our new memory location is \0. - texturesText[texturesLumpLength] = '\0'; - // Finally, free up the memory from the first data load, because we really - // don't need it. - Z_Free(texturesLump); - - texturesToken = M_GetToken(texturesText); - while (texturesToken != NULL) + // Alpha style set to translucent? + if (style == AST_TRANSLUCENT) { - if (stricmp(texturesToken, "WALLTEXTURE")==0) + // Is the alpha small enough for translucency? + if (alpha <= ASTTextureBlendingThreshold[1]) { - Z_Free(texturesToken); - // Get the new texture - newTexture = R_ParseTexture(true); - // Store the new texture - textures[*texindex] = newTexture; - texturewidthmask[*texindex] = newTexture->width - 1; - textureheight[*texindex] = newTexture->height << FRACBITS; - // Increment i back in R_LoadTextures() - (*texindex)++; + UINT8 *mytransmap; + + // Is the patch way too translucent? Don't blend then. + if (alpha < ASTTextureBlendingThreshold[0]) + return background; + + // The equation's not exact but it works as intended. I'll call it a day for now. + mytransmap = transtables + ((8*(alpha) + 255/8)/(255 - 255/11) << FF_TRANSSHIFT); + if (background != 0xFF) + return *(mytransmap + (background<<8) + foreground); } - else - { - I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\", got \"%s\"",texturesToken); - } - texturesToken = M_GetToken(NULL); + else // just copy the pixel + return foreground; } - Z_Free(texturesToken); - Z_Free((void *)texturesText); + // just copy the pixel + else if (style == AST_COPY) + return foreground; + // use ASTBlendPixel for all other blend modes + // and find the nearest colour in the palette + else if (style != AST_TRANSLUCENT) + { + RGBA_t texel; + RGBA_t bg = V_GetMasterColor(background); + RGBA_t fg = V_GetMasterColor(foreground); + texel.rgba = ASTBlendPixel(bg, fg, style, alpha); + return NearestColor(texel.s.red, texel.s.green, texel.s.blue); + } + // fallback if all above fails, somehow + // return the background pixel + return background; } -/* -static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list, size_t listsize) // SRB2kart - unused. +#ifdef EXTRACOLORMAPLUMPS +static lumplist_t *colormaplumps = NULL; ///\todo free leak +static size_t numcolormaplumps = 0; + +static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list, size_t listsize) { size_t i; UINT16 lump; @@ -940,10 +224,6 @@ static inline lumpnum_t R_CheckNumForNameList(const char *name, lumplist_t *list } return LUMPERROR; } -*/ - -/*static lumplist_t *colormaplumps = NULL; ///\todo free leak -static size_t numcolormaplumps = 0; static void R_InitExtraColormaps(void) { @@ -976,62 +256,8 @@ static void R_InitExtraColormaps(void) numcolormaplumps++; } CONS_Printf(M_GetText("Number of Extra Colormaps: %s\n"), sizeu1(numcolormaplumps)); -}*/ - -// Search for flat name. -lumpnum_t R_GetFlatNumForName(const char *name) -{ - INT32 i; - lumpnum_t lump; - lumpnum_t start; - lumpnum_t end; - - // Scan wad files backwards so patched flats take preference. - for (i = numwadfiles - 1; i >= 0; i--) - { - switch (wadfiles[i]->type) - { - case RET_WAD: - if ((start = W_CheckNumForNamePwad("F_START", (UINT16)i, 0)) == INT16_MAX) - { - if ((start = W_CheckNumForNamePwad("FF_START", (UINT16)i, 0)) == INT16_MAX) - continue; - else if ((end = W_CheckNumForNamePwad("FF_END", (UINT16)i, start)) == INT16_MAX) - continue; - } - else - if ((end = W_CheckNumForNamePwad("F_END", (UINT16)i, start)) == INT16_MAX) - continue; - break; - case RET_PK3: - if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX) - continue; - if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX) - continue; - break; - default: - continue; - } - - // Now find lump with specified name in that range. - lump = W_CheckNumForNamePwad(name, (UINT16)i, start); - if (lump < end) - { - lump += (i<<16); // found it, in our constraints - break; - } - lump = LUMPERROR; - } - - if (lump == LUMPERROR) - { - if (strcmp(name, SKYFLATNAME)) - CONS_Debug(DBG_SETUP, "R_GetFlatNumForName: Could not find flat %.8s\n", name); - lump = W_CheckNumForName("REDFLR"); - } - - return lump; } +#endif // // R_InitSpriteLumps @@ -1055,20 +281,21 @@ static void R_InitSpriteLumps(void) // static void R_InitColormaps(void) { + size_t len; lumpnum_t lump; // Load in the light tables lump = W_GetNumForName("COLORMAP"); - //Z_MallocAlign(W_LumpLength (lump), PU_STATIC, NULL, 8); - colormaps = Z_MallocAlign((256 * 64), PU_STATIC, NULL, 8); + len = W_LumpLength(lump); + colormaps = Z_MallocAlign(len * 2, PU_STATIC, NULL, 8); // * 2 for encore W_ReadLump(lump, colormaps); // no need to init encoremap at this stage // Init Boom colormaps. R_ClearColormaps(); - //R_InitExtraColormaps(); -#ifdef HASINVERT - R_MakeInvertmap(); // this isn't the BEST place to do it the first time, but whatever + +#ifdef EXTRACOLORMAPLUMPS + R_InitExtraColormaps(); #endif } @@ -1076,15 +303,23 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) { char colormap[9] = "COLORMAP"; lumpnum_t lump; - + const lumpnum_t basecolormaplump = W_GetNumForName(colormap); if (num > 0 && num <= 10000) snprintf(colormap, 8, "CLM%04u", num-1); // Load in the light tables, now 64k aligned for smokie... lump = W_GetNumForName(colormap); if (lump == LUMPERROR) - lump = W_GetNumForName("COLORMAP"); - W_ReadLump(lump, colormaps); + lump = basecolormaplump; + else + { + if (W_LumpLength(lump) != W_LumpLength(basecolormaplump)) + { + CONS_Alert(CONS_WARNING, "%s lump size does not match COLORMAP, results may be unexpected.\n", colormap); + } + } + + W_ReadLumpHeader(lump, colormaps, W_LumpLength(basecolormaplump), 0U); // Encore mode. if (newencoremap != LUMPERROR) @@ -1114,8 +349,6 @@ void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap) R_ClearColormaps(); } -static lumpnum_t foundcolormaps[MAXCOLORMAPS]; - // // R_ClearColormaps // @@ -1123,52 +356,267 @@ static lumpnum_t foundcolormaps[MAXCOLORMAPS]; // void R_ClearColormaps(void) { - size_t i; - - num_extra_colormaps = 0; - - for (i = 0; i < MAXCOLORMAPS; i++) - foundcolormaps[i] = LUMPERROR; - - memset(extra_colormaps, 0, sizeof (extra_colormaps)); + // Purged by PU_LEVEL, just overwrite the pointer + extra_colormaps = R_CreateDefaultColormap(true); } -/*INT32 R_ColormapNumForName(char *name) +// +// R_CreateDefaultColormap() +// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself! +// +extracolormap_t *R_CreateDefaultColormap(boolean lighttable) { - lumpnum_t lump, i; + extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + exc->fadestart = 0; + exc->fadeend = 31; + exc->flags = 0; + exc->rgba = 0; + exc->fadergba = 0x19000000; + exc->colormap = lighttable ? R_CreateLightTable(exc) : NULL; +#ifdef EXTRACOLORMAPLUMPS + exc->lump = LUMPERROR; + exc->lumpname[0] = 0; +#endif + exc->next = exc->prev = NULL; + return exc; +} - if (num_extra_colormaps == MAXCOLORMAPS) - I_Error("R_ColormapNumForName: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); +// +// R_GetDefaultColormap() +// +extracolormap_t *R_GetDefaultColormap(void) +{ +#ifdef COLORMAPREVERSELIST + extracolormap_t *exc; +#endif + + if (!extra_colormaps) + return (extra_colormaps = R_CreateDefaultColormap(true)); + +#ifdef COLORMAPREVERSELIST + for (exc = extra_colormaps; exc->next; exc = exc->next); + return exc; +#else + return extra_colormaps; +#endif +} + +// +// R_CopyColormap() +// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself! +// +extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable) +{ + extracolormap_t *exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + + if (!extra_colormap) + extra_colormap = R_GetDefaultColormap(); + + *exc = *extra_colormap; + exc->next = exc->prev = NULL; + +#ifdef EXTRACOLORMAPLUMPS + strncpy(exc->lumpname, extra_colormap->lumpname, 9); + + if (exc->lump != LUMPERROR && lighttable) + { + // aligned on 8 bit for asm code + exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16); + W_ReadLump(lump, exc->colormap); + } + else +#endif + if (lighttable) + exc->colormap = R_CreateLightTable(exc); + else + exc->colormap = NULL; + + return exc; +} + +// +// R_AddColormapToList +// +// Sets prev/next chain for extra_colormaps var +// Copypasta from P_AddFFloorToList +// +void R_AddColormapToList(extracolormap_t *extra_colormap) +{ +#ifndef COLORMAPREVERSELIST + extracolormap_t *exc; +#endif + + if (!extra_colormaps) + { + extra_colormaps = extra_colormap; + extra_colormap->next = 0; + extra_colormap->prev = 0; + return; + } + +#ifdef COLORMAPREVERSELIST + extra_colormaps->prev = extra_colormap; + extra_colormap->next = extra_colormaps; + extra_colormaps = extra_colormap; + extra_colormap->prev = 0; +#else + for (exc = extra_colormaps; exc->next; exc = exc->next); + + exc->next = extra_colormap; + extra_colormap->prev = exc; + extra_colormap->next = 0; +#endif +} + +// +// R_CheckDefaultColormapByValues() +// +#ifdef EXTRACOLORMAPLUMPS +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags, lumpnum_t lump) +#else +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags) +#endif +{ + return ( + (!checkparams ? true : + (fadestart == 0 + && fadeend == 31 + && !flags) + ) + && (!checkrgba ? true : rgba == 0) + && (!checkfadergba ? true : fadergba == 0x19000000) +#ifdef EXTRACOLORMAPLUMPS + && lump == LUMPERROR + && extra_colormap->lumpname[0] == 0 +#endif + ); +} + +boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams) +{ + if (!extra_colormap) + return true; + +#ifdef EXTRACOLORMAPLUMPS + return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->flags, extra_colormap->lump); +#else + return R_CheckDefaultColormapByValues(checkrgba, checkfadergba, checkparams, extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->flags); +#endif +} + +boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams) +{ + // Treat NULL as default colormap + // We need this because what if one exc is a default colormap, and the other is NULL? They're really both equal. + if (!exc_a) + exc_a = R_GetDefaultColormap(); + if (!exc_b) + exc_b = R_GetDefaultColormap(); + + if (exc_a == exc_b) + return true; + + return ( + (!checkparams ? true : + (exc_a->fadestart == exc_b->fadestart + && exc_a->fadeend == exc_b->fadeend + && exc_a->flags == exc_b->flags) + ) + && (!checkrgba ? true : exc_a->rgba == exc_b->rgba) + && (!checkfadergba ? true : exc_a->fadergba == exc_b->fadergba) +#ifdef EXTRACOLORMAPLUMPS + && exc_a->lump == exc_b->lump + && !strncmp(exc_a->lumpname, exc_b->lumpname, 9) +#endif + ); +} + +// +// R_GetColormapFromListByValues() +// NOTE: Returns NULL if no match is found +// +#ifdef EXTRACOLORMAPLUMPS +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags, lumpnum_t lump) +#else +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags) +#endif +{ + extracolormap_t *exc; + UINT32 dbg_i = 0; + + for (exc = extra_colormaps; exc; exc = exc->next) + { + if (rgba == exc->rgba + && fadergba == exc->fadergba + && fadestart == exc->fadestart + && fadeend == exc->fadeend + && flags == exc->flags +#ifdef EXTRACOLORMAPLUMPS + && (lump != LUMPERROR && lump == exc->lump) +#endif + ) + { + CONS_Debug(DBG_RENDER, "Found Colormap %d: rgba(%d,%d,%d,%d) fadergba(%d,%d,%d,%d)\n", + dbg_i, R_GetRgbaR(rgba), R_GetRgbaG(rgba), R_GetRgbaB(rgba), R_GetRgbaA(rgba), + R_GetRgbaR(fadergba), R_GetRgbaG(fadergba), R_GetRgbaB(fadergba), R_GetRgbaA(fadergba)); + return exc; + } + dbg_i++; + } + return NULL; +} + +extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap) +{ +#ifdef EXTRACOLORMAPLUMPS + return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->flags, extra_colormap->lump); +#else + return R_GetColormapFromListByValues(extra_colormap->rgba, extra_colormap->fadergba, extra_colormap->fadestart, extra_colormap->fadeend, extra_colormap->flags); +#endif +} + +#ifdef EXTRACOLORMAPLUMPS +extracolormap_t *R_ColormapForName(char *name) +{ + lumpnum_t lump; + extracolormap_t *exc; lump = R_CheckNumForNameList(name, colormaplumps, numcolormaplumps); if (lump == LUMPERROR) - I_Error("R_ColormapNumForName: Cannot find colormap lump %.8s\n", name); + I_Error("R_ColormapForName: Cannot find colormap lump %.8s\n", name); - for (i = 0; i < num_extra_colormaps; i++) - if (lump == foundcolormaps[i]) - return i; + exc = R_GetColormapFromListByValues(0, 0x19000000, 0, 31, 0, lump); + if (exc) + return exc; - foundcolormaps[num_extra_colormaps] = lump; + exc = Z_Calloc(sizeof (*exc), PU_LEVEL, NULL); + + exc->lump = lump; + strncpy(exc->lumpname, name, 9); + exc->lumpname[8] = 0; // aligned on 8 bit for asm code - extra_colormaps[num_extra_colormaps].colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16); - W_ReadLump(lump, extra_colormaps[num_extra_colormaps].colormap); + exc->colormap = Z_MallocAlign(W_LumpLength(lump), PU_LEVEL, NULL, 16); + W_ReadLump(lump, exc->colormap); // We set all params of the colormap to normal because there // is no real way to tell how GL should handle a colormap lump anyway.. - extra_colormaps[num_extra_colormaps].maskcolor = 0xffff; - extra_colormaps[num_extra_colormaps].fadecolor = 0x0; - extra_colormaps[num_extra_colormaps].maskamt = 0x0; - extra_colormaps[num_extra_colormaps].fadestart = 0; - extra_colormaps[num_extra_colormaps].fadeend = 31; - extra_colormaps[num_extra_colormaps].fog = 0; + exc->fadestart = 0; + exc->fadeend = 31; + exc->flags = 0; + exc->rgba = 0; + exc->fadergba = 0x19000000; - num_extra_colormaps++; - return (INT32)num_extra_colormaps - 1; -}*/ + R_AddColormapToList(exc); + + return exc; +} +#endif // -// R_CreateColormap +// R_CreateColormapFromLinedef // // This is a more GL friendly way of doing colormaps: Specify colormap // data in a special linedef's texture areas and use that to generate @@ -1179,166 +627,62 @@ static double deltas[256][3], map[256][3]; static int RoundUp(double number); -#ifdef HASINVERT -void R_MakeInvertmap(void) -{ - size_t i; - - for (i = 0; i < 256; i++) - invertmap[i] = NearestColor(256 - pLocalPalette[i].s.red, 256 - pLocalPalette[i].s.green, 256 - pLocalPalette[i].s.blue); -} -#endif - -INT32 R_CreateColormap(char *p1, char *p2, char *p3) +lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap) { double cmaskr, cmaskg, cmaskb, cdestr, cdestg, cdestb; - double r, g, b, cbrightness, maskamt = 0, othermask = 0; - int mask, fog = 0; - size_t mapnum = num_extra_colormaps; + double maskamt = 0, othermask = 0; + + UINT8 cr = R_GetRgbaR(extra_colormap->rgba), + cg = R_GetRgbaG(extra_colormap->rgba), + cb = R_GetRgbaB(extra_colormap->rgba), + ca = R_GetRgbaA(extra_colormap->rgba), + cfr = R_GetRgbaR(extra_colormap->fadergba), + cfg = R_GetRgbaG(extra_colormap->fadergba), + cfb = R_GetRgbaB(extra_colormap->fadergba); +// cfa = R_GetRgbaA(extra_colormap->fadergba); // unused in software + + UINT8 fadestart = extra_colormap->fadestart, + fadedist = extra_colormap->fadeend - extra_colormap->fadestart; + + lighttable_t *lighttable = NULL; size_t i; - UINT32 cr, cg, cb, maskcolor, fadecolor; - UINT32 fadestart = 0, fadeend = 31, fadedist = 31; -#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) - if (p1[0] == '#') - { - cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); - cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); - cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); - - if (encoremap) - { - i = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; - //CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", i, encoremap[i]); -- moved encoremap upwards for optimisation - cr = pLocalPalette[i].s.red; - cg = pLocalPalette[i].s.green; - cb = pLocalPalette[i].s.blue; - } - - cmaskr = cr; - cmaskg = cg; - cmaskb = cb; - // Create a rough approximation of the color (a 16 bit color) - maskcolor = ((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11); - if (p1[7] >= 'a' && p1[7] <= 'z') - mask = (p1[7] - 'a'); - else if (p1[7] >= 'A' && p1[7] <= 'Z') - mask = (p1[7] - 'A'); - else - mask = 24; - - maskamt = (double)(mask/24.0l); - - othermask = 1 - maskamt; - maskamt /= 0xff; - cmaskr *= maskamt; - cmaskg *= maskamt; - cmaskb *= maskamt; - } - else - { - cmaskr = cmaskg = cmaskb = 0xff; - maskamt = 0; - maskcolor = ((0xff) >> 3) + (((0xff) >> 2) << 5) + (((0xff) >> 3) << 11); - } - -#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0) - if (p2[0] == '#') - { - // Get parameters like fadestart, fadeend, and the fogflag - fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); - fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); - if (fadestart > 30) - fadestart = 0; - if (fadeend > 31 || fadeend < 1) - fadeend = 31; - fadedist = fadeend - fadestart; - fog = NUMFROMCHAR(p2[1]); - } -#undef NUMFROMCHAR - - if (p3[0] == '#') - { - cr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); - cg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); - cb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); - - if (encoremap) - { - i = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; - cr = pLocalPalette[i].s.red; - cg = pLocalPalette[i].s.green; - cb = pLocalPalette[i].s.blue; - } - - cdestr = cr; - cdestg = cg; - cdestb = cb; - fadecolor = (((cb) >> 3) + (((cg) >> 2) << 5) + (((cr) >> 3) << 11)); - } - else - cdestr = cdestg = cdestb = fadecolor = 0; -#undef HEX2INT - - for (i = 0; i < num_extra_colormaps; i++) - { - if (foundcolormaps[i] != LUMPERROR) - continue; - if (maskcolor == extra_colormaps[i].maskcolor - && fadecolor == extra_colormaps[i].fadecolor - && fabs(maskamt - extra_colormaps[i].maskamt) < DBL_EPSILON - && fadestart == extra_colormaps[i].fadestart - && fadeend == extra_colormaps[i].fadeend - && fog == extra_colormaps[i].fog) - { - return (INT32)i; - } - } - - if (num_extra_colormaps == MAXCOLORMAPS) - I_Error("R_CreateColormap: Too many colormaps! the limit is %d\n", MAXCOLORMAPS); - - num_extra_colormaps++; - - if (rendermode == render_soft) - { - for (i = 0; i < 256; i++) - { - r = pMasterPalette[i].s.red; - g = pMasterPalette[i].s.green; - b = pMasterPalette[i].s.blue; - cbrightness = sqrt((r*r) + (g*g) + (b*b)); - - map[i][0] = (cbrightness * cmaskr) + (r * othermask); - if (map[i][0] > 255.0l) - map[i][0] = 255.0l; - deltas[i][0] = (map[i][0] - cdestr) / (double)fadedist; - - map[i][1] = (cbrightness * cmaskg) + (g * othermask); - if (map[i][1] > 255.0l) - map[i][1] = 255.0l; - deltas[i][1] = (map[i][1] - cdestg) / (double)fadedist; - - map[i][2] = (cbrightness * cmaskb) + (b * othermask); - if (map[i][2] > 255.0l) - map[i][2] = 255.0l; - deltas[i][2] = (map[i][2] - cdestb) / (double)fadedist; - } - } - - foundcolormaps[mapnum] = LUMPERROR; - - // aligned on 8 bit for asm code - extra_colormaps[mapnum].colormap = NULL; - extra_colormaps[mapnum].maskcolor = (UINT16)maskcolor; - extra_colormaps[mapnum].fadecolor = (UINT16)fadecolor; - extra_colormaps[mapnum].maskamt = maskamt; - extra_colormaps[mapnum].fadestart = (UINT16)fadestart; - extra_colormaps[mapnum].fadeend = (UINT16)fadeend; - extra_colormaps[mapnum].fog = fog; - - if (rendermode == render_soft) + ///////////////////// + // Calc the RGBA mask + ///////////////////// + cmaskr = cr; + cmaskg = cg; + cmaskb = cb; + + maskamt = (double)(ca/24.0l); + othermask = 1 - maskamt; + maskamt /= 0xff; + + cmaskr *= maskamt; + cmaskg *= maskamt; + cmaskb *= maskamt; + + ///////////////////// + // Calc the RGBA fade mask + ///////////////////// + cdestr = cfr; + cdestg = cfg; + cdestb = cfb; + + // fade alpha unused in software + // maskamt = (double)(cfa/24.0l); + // othermask = 1 - maskamt; + // maskamt /= 0xff; + + // cdestr *= maskamt; + // cdestg *= maskamt; + // cdestb *= maskamt; + + ///////////////////// + // This code creates the colormap array used by software renderer + ///////////////////// { + double r, g, b, cbrightness; int p; lighttable_t *colormap_p; @@ -1371,8 +715,9 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) } // Now allocate memory for the actual colormap array itself! - colormap_p = Z_MallocAlign((256 * (encoremap ? 64 : 32)) + 10, PU_LEVEL, NULL, 8); - extra_colormaps[mapnum].colormap = (UINT8 *)colormap_p; + // aligned on 8 bit for asm code + colormap_p = Z_MallocAlign((256 * 34) + 10, PU_LEVEL, NULL, 8); + lighttable = (UINT8 *)colormap_p; // Calculate the palette index for each palette index, for each light level // (as well as the two unused colormap lines we inherited from Doom) @@ -1408,7 +753,7 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) if (encoremap) { - lighttable_t *colormap_p2 = extra_colormaps[mapnum].colormap; + lighttable_t *colormap_p2 = lighttable; for (p = 0; p < 32; p++) { @@ -1422,7 +767,299 @@ INT32 R_CreateColormap(char *p1, char *p2, char *p3) } } - return (INT32)mapnum; + return lighttable; +} + +extracolormap_t *R_CreateColormapFromLinedef(char *p1, char *p2, char *p3) +{ + // default values + UINT8 cr = 0, cg = 0, cb = 0, ca = 0, cfr = 0, cfg = 0, cfb = 0, cfa = 25; + UINT32 fadestart = 0, fadeend = 31; + UINT8 flags = 0; + INT32 rgba = 0, fadergba = 0x19000000; + +#define HEX2INT(x) (UINT32)(x >= '0' && x <= '9' ? x - '0' : x >= 'a' && x <= 'f' ? x - 'a' + 10 : x >= 'A' && x <= 'F' ? x - 'A' + 10 : 0) +#define ALPHA2INT(x) (x >= 'a' && x <= 'z' ? x - 'a' : x >= 'A' && x <= 'Z' ? x - 'A' : x >= '0' && x <= '9' ? 25 : 0) + + // Get base colormap value + // First alpha-only, then full value + if (p1[0] >= 'a' && p1[0] <= 'z' && !p1[1]) + ca = (p1[0] - 'a'); + else if (p1[0] == '#' && p1[1] >= 'a' && p1[1] <= 'z' && !p1[2]) + ca = (p1[1] - 'a'); + else if (p1[0] >= 'A' && p1[0] <= 'Z' && !p1[1]) + ca = (p1[0] - 'A'); + else if (p1[0] == '#' && p1[1] >= 'A' && p1[1] <= 'Z' && !p1[2]) + ca = (p1[1] - 'A'); + else if (p1[0] == '#') + { + // For each subsequent value, the value before it must exist + // If we don't get every value, then set alpha to max + if (p1[1] && p1[2]) + { + cr = ((HEX2INT(p1[1]) * 16) + HEX2INT(p1[2])); + if (p1[3] && p1[4]) + { + cg = ((HEX2INT(p1[3]) * 16) + HEX2INT(p1[4])); + if (p1[5] && p1[6]) + { + cb = ((HEX2INT(p1[5]) * 16) + HEX2INT(p1[6])); + + if (p1[7] >= 'a' && p1[7] <= 'z') + ca = (p1[7] - 'a'); + else if (p1[7] >= 'A' && p1[7] <= 'Z') + ca = (p1[7] - 'A'); + else + ca = 25; + } + else + ca = 25; + } + else + ca = 25; + } + else + ca = 25; + } + +#define NUMFROMCHAR(c) (c >= '0' && c <= '9' ? c - '0' : 0) + + // Get parameters like fadestart, fadeend, and flags + if (p2[0] == '#') + { + if (p2[1]) + { + flags = NUMFROMCHAR(p2[1]); + if (p2[2] && p2[3]) + { + fadestart = NUMFROMCHAR(p2[3]) + (NUMFROMCHAR(p2[2]) * 10); + if (p2[4] && p2[5]) + fadeend = NUMFROMCHAR(p2[5]) + (NUMFROMCHAR(p2[4]) * 10); + } + } + + if (fadestart > 30) + fadestart = 0; + if (fadeend > 31 || fadeend < 1) + fadeend = 31; + } + +#undef NUMFROMCHAR + + // Get fade (dark) colormap value + // First alpha-only, then full value + if (p3[0] >= 'a' && p3[0] <= 'z' && !p3[1]) + cfa = (p3[0] - 'a'); + else if (p3[0] == '#' && p3[1] >= 'a' && p3[1] <= 'z' && !p3[2]) + cfa = (p3[1] - 'a'); + else if (p3[0] >= 'A' && p3[0] <= 'Z' && !p3[1]) + cfa = (p3[0] - 'A'); + else if (p3[0] == '#' && p3[1] >= 'A' && p3[1] <= 'Z' && !p3[2]) + cfa = (p3[1] - 'A'); + else if (p3[0] == '#') + { + // For each subsequent value, the value before it must exist + // If we don't get every value, then set alpha to max + if (p3[1] && p3[2]) + { + cfr = ((HEX2INT(p3[1]) * 16) + HEX2INT(p3[2])); + if (p3[3] && p3[4]) + { + cfg = ((HEX2INT(p3[3]) * 16) + HEX2INT(p3[4])); + if (p3[5] && p3[6]) + { + cfb = ((HEX2INT(p3[5]) * 16) + HEX2INT(p3[6])); + + if (p3[7] >= 'a' && p3[7] <= 'z') + cfa = (p3[7] - 'a'); + else if (p3[7] >= 'A' && p3[7] <= 'Z') + cfa = (p3[7] - 'A'); + else + cfa = 25; + } + else + cfa = 25; + } + else + cfa = 25; + } + else + cfa = 25; + } +#undef ALPHA2INT +#undef HEX2INT + +#ifdef GLENCORE + if (encoremap) + { + j = encoremap[NearestColor((UINT8)cr, (UINT8)cg, (UINT8)cb)]; + //CONS_Printf("R_CreateColormap: encoremap[%d] = %d\n", j, encoremap[j]); + cr = pLocalPalette[j].s.red; + cg = pLocalPalette[j].s.green; + cb = pLocalPalette[j].s.blue; + } +#endif + + // Pack rgba values into combined var + // OpenGL also uses this instead of lighttables for rendering + rgba = R_PutRgbaRGBA(cr, cg, cb, ca); + fadergba = R_PutRgbaRGBA(cfr, cfg, cfb, cfa); + + return R_CreateColormap(rgba, fadergba, fadestart, fadeend, flags); +} + +extracolormap_t *R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags) +{ + extracolormap_t *extra_colormap; + + // Did we just make a default colormap? +#ifdef EXTRACOLORMAPLUMPS + if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, flags, LUMPERROR)) + return NULL; +#else + if (R_CheckDefaultColormapByValues(true, true, true, rgba, fadergba, fadestart, fadeend, flags)) + return NULL; +#endif + + // Look for existing colormaps +#ifdef EXTRACOLORMAPLUMPS + extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags, LUMPERROR); +#else + extra_colormap = R_GetColormapFromListByValues(rgba, fadergba, fadestart, fadeend, flags); +#endif + if (extra_colormap) + return extra_colormap; + + CONS_Debug(DBG_RENDER, "Creating Colormap: rgba(%x) fadergba(%x)\n", rgba, fadergba); + + extra_colormap = Z_Calloc(sizeof(*extra_colormap), PU_LEVEL, NULL); + + extra_colormap->fadestart = (UINT16)fadestart; + extra_colormap->fadeend = (UINT16)fadeend; + extra_colormap->flags = flags; + + extra_colormap->rgba = rgba; + extra_colormap->fadergba = fadergba; + +#ifdef EXTRACOLORMAPLUMPS + extra_colormap->lump = LUMPERROR; + extra_colormap->lumpname[0] = 0; +#endif + + // Having lighttables for alpha-only entries is kind of pointless, + // but if there happens to be a matching rgba entry that is NOT alpha-only (but has same rgb values), + // then it needs this lighttable because we share matching entries. + extra_colormap->colormap = R_CreateLightTable(extra_colormap); + + R_AddColormapToList(extra_colormap); + + return extra_colormap; +} + +// +// R_AddColormaps() +// NOTE: The result colormap is not added to the extra_colormaps chain. You must do that yourself! +// +extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, + boolean subR, boolean subG, boolean subB, boolean subA, + boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean subFadeStart, boolean subFadeEnd, boolean ignoreFlags, + boolean lighttable) +{ + INT16 red, green, blue, alpha; + + // exc_augend is added (or subtracted) onto by exc_addend + // In Rennaisance times, the first number was considered the augend, the second number the addend + // But since the commutative property was discovered, today they're both called addends! + // So let's be Olde English for a hot second. + + exc_augend = R_CopyColormap(exc_augend, false); + if(!exc_addend) + exc_addend = R_GetDefaultColormap(); + + /////////////////// + // base rgba + /////////////////// + + red = max(min( + R_GetRgbaR(exc_augend->rgba) + + (subR ? -1 : 1) // subtract R + * R_GetRgbaR(exc_addend->rgba) + , 255), 0); + + green = max(min( + R_GetRgbaG(exc_augend->rgba) + + (subG ? -1 : 1) // subtract G + * R_GetRgbaG(exc_addend->rgba) + , 255), 0); + + blue = max(min( + R_GetRgbaB(exc_augend->rgba) + + (subB ? -1 : 1) // subtract B + * R_GetRgbaB(exc_addend->rgba) + , 255), 0); + + alpha = R_GetRgbaA(exc_addend->rgba); + alpha = max(min(R_GetRgbaA(exc_augend->rgba) + (subA ? -1 : 1) * alpha, 25), 0); + + exc_augend->rgba = R_PutRgbaRGBA(red, green, blue, alpha); + + /////////////////// + // fade/dark rgba + /////////////////// + + red = max(min( + R_GetRgbaR(exc_augend->fadergba) + + (subFadeR ? -1 : 1) // subtract R + * R_GetRgbaR(exc_addend->fadergba) + , 255), 0); + + green = max(min( + R_GetRgbaG(exc_augend->fadergba) + + (subFadeG ? -1 : 1) // subtract G + * R_GetRgbaG(exc_addend->fadergba) + , 255), 0); + + blue = max(min( + R_GetRgbaB(exc_augend->fadergba) + + (subFadeB ? -1 : 1) // subtract B + * R_GetRgbaB(exc_addend->fadergba) + , 255), 0); + + alpha = R_GetRgbaA(exc_addend->fadergba); + if (alpha == 25 && !R_GetRgbaRGB(exc_addend->fadergba)) + alpha = 0; // HACK: fadergba A defaults at 25, so don't add anything in this case + alpha = max(min(R_GetRgbaA(exc_augend->fadergba) + (subFadeA ? -1 : 1) * alpha, 25), 0); + + exc_augend->fadergba = R_PutRgbaRGBA(red, green, blue, alpha); + + /////////////////// + // parameters + /////////////////// + + exc_augend->fadestart = max(min( + exc_augend->fadestart + + (subFadeStart ? -1 : 1) // subtract fadestart + * exc_addend->fadestart + , 31), 0); + + exc_augend->fadeend = max(min( + exc_augend->fadeend + + (subFadeEnd ? -1 : 1) // subtract fadeend + * (exc_addend->fadeend == 31 && !exc_addend->fadestart ? 0 : exc_addend->fadeend) + // HACK: fadeend defaults to 31, so don't add anything in this case + , 31), 0); + + if (!ignoreFlags) // overwrite flags with new value + exc_augend->flags = exc_addend->flags; + + /////////////////// + // put it together + /////////////////// + + exc_augend->colormap = lighttable ? R_CreateLightTable(exc_augend) : NULL; + exc_augend->next = exc_augend->prev = NULL; + return exc_augend; } // Thanks to quake2 source! @@ -1469,20 +1106,18 @@ static int RoundUp(double number) return (int)number; } -const char *R_ColormapNameForNum(INT32 num) +#ifdef EXTRACOLORMAPLUMPS +const char *R_NameForColormap(extracolormap_t *extra_colormap) { - if (num == -1) + if (!extra_colormap) return "NONE"; - if (num < 0 || num > MAXCOLORMAPS) - I_Error("R_ColormapNameForNum: num %d is invalid!\n", num); - - if (foundcolormaps[num] == LUMPERROR) + if (extra_colormap->lump == LUMPERROR) return "INLEVEL"; - return W_CheckNameForNum(foundcolormaps[num]); + return extra_colormap->lumpname; } - +#endif // // build a table for quick conversion from 8bpp to 15bpp @@ -1546,74 +1181,6 @@ void R_InitData(void) R_InitColormaps(); } -void R_ClearTextureNumCache(boolean btell) -{ - if (tidcache) - Z_Free(tidcache); - tidcache = NULL; - if (btell) - CONS_Debug(DBG_SETUP, "Fun Fact: There are %d textures used in this map.\n", tidcachelen); - tidcachelen = 0; -} - -// -// R_CheckTextureNumForName -// -// Check whether texture is available. Filter out NoTexture indicator. -// -INT32 R_CheckTextureNumForName(const char *name) -{ - INT32 i; - - // "NoTexture" marker. - if (name[0] == '-') - return 0; - - for (i = 0; i < tidcachelen; i++) - if (!strncasecmp(tidcache[i].name, name, 8)) - return tidcache[i].id; - - // Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier - //for (i = 0; i < numtextures; i++) <- old - for (i = (numtextures - 1); i >= 0; i--) // <- new - if (!strncasecmp(textures[i]->name, name, 8)) - { - tidcachelen++; - Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache); - strncpy(tidcache[tidcachelen-1].name, name, 8); - tidcache[tidcachelen-1].name[8] = '\0'; -#ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name); -#endif - tidcache[tidcachelen-1].id = i; - return i; - } - - return -1; -} - -// -// R_TextureNumForName -// -// Calls R_CheckTextureNumForName, aborts with error message. -// -INT32 R_TextureNumForName(const char *name) -{ - const INT32 i = R_CheckTextureNumForName(name); - - if (i == -1) - { - static INT32 redwall = -2; - CONS_Debug(DBG_SETUP, "WARNING: R_TextureNumForName: %.8s not found\n", name); - if (redwall == -2) - redwall = R_CheckTextureNumForName("REDWALL"); - if (redwall != -1) - return redwall; - return 1; - } - return i; -} - // // R_PrecacheLevel // @@ -1681,8 +1248,8 @@ void R_PrecacheLevel(void) spritepresent = calloc(numsprites, sizeof (*spritepresent)); if (spritepresent == NULL) I_Error("%s: Out of memory looking up sprites", "R_PrecacheLevel"); - for (th = thinkercap.next; th != &thinkercap; th = th->next) - if (th->function.acp1 == (actionf_p1)P_MobjThinker) + for (th = thlist[THINK_MOBJ].next; th != &thlist[THINK_MOBJ]; th = th->next) + if (th->function.acp1 != (actionf_p1)P_RemoveThinkerDelayed) spritepresent[((mobj_t *)th)->sprite] = 1; spritememory = 0; @@ -1694,14 +1261,29 @@ void R_PrecacheLevel(void) for (j = 0; j < sprites[i].numframes; j++) { sf = &sprites[i].spriteframes[j]; - for (k = 0; k < 8; k++) +#define cacheang(a) {\ + lump = sf->lumppat[a];\ + if (devparm)\ + spritememory += W_LumpLength(lump);\ + W_CachePatchNum(lump, PU_PATCH);\ + } + // see R_InitSprites for more about lumppat,lumpid + switch (sf->rotate) { - // see R_InitSprites for more about lumppat,lumpid - lump = sf->lumppat[k]; - if (devparm) - spritememory += W_LumpLength(lump); - W_CachePatchNum(lump, PU_CACHE); + case SRF_SINGLE: + cacheang(0); + break; + case SRF_2D: + cacheang(2); + cacheang(6); + break; + default: + k = (sf->rotate & SRF_3DGE ? 16 : 8); + while (k--) + cacheang(k); + break; } +#undef cacheang } } free(spritepresent); diff --git a/src/r_data.h b/src/r_data.h index f9812d4e4..230f72a7c 100644 --- a/src/r_data.h +++ b/src/r_data.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -16,45 +16,28 @@ #include "r_defs.h" #include "r_state.h" +#include "p_setup.h" // levelflats #ifdef __GNUG__ #pragma interface #endif -// moved here for r_sky.c (texpatch_t is used) - -// A single patch from a texture definition, -// basically a rectangular area within -// the texture rectangle. +// Store lists of lumps for F_START/F_END etc. typedef struct { - // Block origin (always UL), which has already accounted for the internal origin of the patch. - INT16 originx, originy; - UINT16 wad, lump; -} texpatch_t; + UINT16 wadfile; + UINT16 firstlump; + size_t numlumps; +} lumplist_t; -// A maptexturedef_t describes a rectangular texture, -// which is composed of one or more mappatch_t structures -// that arrange graphic patches. -typedef struct -{ - // Keep name for switch changing, etc. - char name[8]; - INT16 width, height; - boolean holes; +// Possible alpha types for a patch. +enum patchalphastyle {AST_COPY, AST_TRANSLUCENT, AST_ADD, AST_SUBTRACT, AST_REVERSESUBTRACT, AST_MODULATE, AST_OVERLAY}; - // All the patches[patchcount] are drawn back to front into the cached texture. - INT16 patchcount; - texpatch_t patches[0]; -} texture_t; +UINT32 ASTBlendPixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); +UINT32 ASTBlendTexturePixel(RGBA_t background, RGBA_t foreground, int style, UINT8 alpha); +UINT8 ASTBlendPaletteIndexes(UINT8 background, UINT8 foreground, int style, UINT8 alpha); -// all loaded and prepared textures from the start of the game -extern texture_t **textures; - -// texture width is a power of 2, so it can easily repeat along sidedefs using a simple mask -extern INT32 *texturewidthmask; - -extern fixed_t *textureheight; // needed for texture pegging +extern INT32 ASTTextureBlendingThreshold[2]; extern INT16 color8to16[256]; // remap color index to highcolor extern INT16 *hicolormaps; // remap high colors to high colors.. @@ -62,46 +45,83 @@ extern INT16 *hicolormaps; // remap high colors to high colors.. extern CV_PossibleValue_t Color_cons_t[]; extern CV_PossibleValue_t Followercolor_cons_t[]; // follower colours table, not a duplicate because of the "Match" option. -// Load TEXTURE1/TEXTURE2/PNAMES definitions, create lookup tables -void R_LoadTextures(void); -void R_FlushTextureCache(void); - -INT32 R_GetTextureNum(INT32 texnum); -void R_CheckTextureCache(INT32 tex); - -// Retrieve column data for span blitting. -UINT8 *R_GetColumn(fixed_t tex, INT32 col); - -UINT8 *R_GetFlat(lumpnum_t flatnum); - // I/O, setting up the stuff. void R_InitData(void); void R_PrecacheLevel(void); -// Retrieval. -// Floor/ceiling opaque texture tiles, -// lookup by name. For animation? -lumpnum_t R_GetFlatNumForName(const char *name); -#define R_FlatNumForName(x) R_GetFlatNumForName(x) +extern size_t flatmemory, spritememory, texturememory; -// Called by P_Ticker for switches and animations, -// returns the texture number for the texture name. -void R_ClearTextureNumCache(boolean btell); -INT32 R_TextureNumForName(const char *name); -INT32 R_CheckTextureNumForName(const char *name); +// Extra Colormap lumps (C_START/C_END) are not used anywhere +// Uncomment to enable +//#define EXTRACOLORMAPLUMPS + +// Uncomment to make extra_colormaps order Newest -> Oldest +//#define COLORMAPREVERSELIST void R_ReInitColormaps(UINT16 num, lumpnum_t newencoremap); void R_ClearColormaps(void); -INT32 R_ColormapNumForName(char *name); -INT32 R_CreateColormap(char *p1, char *p2, char *p3); -#ifdef HASINVERT -void R_MakeInvertmap(void); +extracolormap_t *R_CreateDefaultColormap(boolean lighttable); +extracolormap_t *R_GetDefaultColormap(void); +extracolormap_t *R_CopyColormap(extracolormap_t *extra_colormap, boolean lighttable); +void R_AddColormapToList(extracolormap_t *extra_colormap); + +#ifdef EXTRACOLORMAPLUMPS +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags, lumpnum_t lump); +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags, lumpnum_t lump); +#else +boolean R_CheckDefaultColormapByValues(boolean checkrgba, boolean checkfadergba, boolean checkparams, + INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags); +extracolormap_t *R_GetColormapFromListByValues(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags); #endif -const char *R_ColormapNameForNum(INT32 num); +boolean R_CheckDefaultColormap(extracolormap_t *extra_colormap, boolean checkrgba, boolean checkfadergba, boolean checkparams); +boolean R_CheckEqualColormaps(extracolormap_t *exc_a, extracolormap_t *exc_b, boolean checkrgba, boolean checkfadergba, boolean checkparams); +extracolormap_t *R_GetColormapFromList(extracolormap_t *extra_colormap); + +typedef enum +{ + TMCF_RELATIVE = 1, + TMCF_SUBLIGHTR = 1<<1, + TMCF_SUBLIGHTG = 1<<2, + TMCF_SUBLIGHTB = 1<<3, + TMCF_SUBLIGHTA = 1<<4, + TMCF_SUBFADER = 1<<5, + TMCF_SUBFADEG = 1<<6, + TMCF_SUBFADEB = 1<<7, + TMCF_SUBFADEA = 1<<8, + TMCF_SUBFADESTART = 1<<9, + TMCF_SUBFADEEND = 1<<10, + TMCF_IGNOREFLAGS = 1<<11, + TMCF_FROMBLACK = 1<<12, + TMCF_OVERRIDE = 1<<13, +} textmapcolormapflags_t; + +lighttable_t *R_CreateLightTable(extracolormap_t *extra_colormap); +extracolormap_t * R_CreateColormapFromLinedef(char *p1, char *p2, char *p3); +extracolormap_t* R_CreateColormap(INT32 rgba, INT32 fadergba, UINT8 fadestart, UINT8 fadeend, UINT8 flags); +extracolormap_t *R_AddColormaps(extracolormap_t *exc_augend, extracolormap_t *exc_addend, + boolean subR, boolean subG, boolean subB, boolean subA, + boolean subFadeR, boolean subFadeG, boolean subFadeB, boolean subFadeA, + boolean subFadeStart, boolean subFadeEnd, boolean ignoreFlags, + boolean lighttable); +#ifdef EXTRACOLORMAPLUMPS +extracolormap_t *R_ColormapForName(char *name); +const char *R_NameForColormap(extracolormap_t *extra_colormap); +#endif + +#define R_GetRgbaR(rgba) (rgba & 0xFF) +#define R_GetRgbaG(rgba) ((rgba >> 8) & 0xFF) +#define R_GetRgbaB(rgba) ((rgba >> 16) & 0xFF) +#define R_GetRgbaA(rgba) ((rgba >> 24) & 0xFF) +#define R_GetRgbaRGB(rgba) (rgba & 0xFFFFFF) +#define R_PutRgbaR(r) (r) +#define R_PutRgbaG(g) (g << 8) +#define R_PutRgbaB(b) (b << 16) +#define R_PutRgbaA(a) (a << 24) +#define R_PutRgbaRGB(r, g, b) (R_PutRgbaR(r) + R_PutRgbaG(g) + R_PutRgbaB(b)) +#define R_PutRgbaRGBA(r, g, b, a) (R_PutRgbaRGB(r, g, b) + R_PutRgbaA(a)) UINT8 NearestPaletteColor(UINT8 r, UINT8 g, UINT8 b, RGBA_t *palette); #define NearestColor(r, g, b) NearestPaletteColor(r, g, b, NULL) -extern INT32 numtextures; - #endif diff --git a/src/r_defs.h b/src/r_defs.h index b186fecdf..8372a5ae5 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -24,7 +24,9 @@ #include "screen.h" // MAXVIDWIDTH, MAXVIDHEIGHT -#define POLYOBJECTS +#ifdef HWRENDER +#include "m_aatree.h" +#endif // // ClipWallSegment @@ -49,19 +51,29 @@ typedef struct // Could even use more than 32 levels. typedef UINT8 lighttable_t; -// ExtraColormap type. Use for extra_colormaps from now on. -typedef struct -{ - UINT16 maskcolor, fadecolor; - double maskamt; - UINT16 fadestart, fadeend; - INT32 fog; +#define CMF_FADEFULLBRIGHTSPRITES 1 +#define CMF_FOG 4 - // rgba is used in hw mode for colored sector lighting +// ExtraColormap type. Use for extra_colormaps from now on. +typedef struct extracolormap_s +{ + UINT8 fadestart, fadeend; + UINT8 flags; + + // store rgba values in combined bitwise + // also used in OpenGL instead lighttables INT32 rgba; // similar to maskcolor in sw mode INT32 fadergba; // The colour the colourmaps fade to lighttable_t *colormap; + +#ifdef EXTRACOLORMAPLUMPS + lumpnum_t lump; // for colormap lump matching, init to LUMPERROR + char lumpname[9]; // for netsyncing +#endif + + struct extracolormap_s *next; + struct extracolormap_s *prev; } extracolormap_t; // @@ -72,7 +84,9 @@ typedef struct */ typedef struct { - fixed_t x, y, z; + fixed_t x, y; + boolean floorzset, ceilingzset; + fixed_t floorz, ceilingz; } vertex_t; // Forward of linedefs, for sectors. @@ -91,9 +105,7 @@ typedef struct fixed_t z; ///< Z coordinate. } degenmobj_t; -#ifdef POLYOBJECTS #include "p_polyobj.h" -#endif // Store fake planes in a resizable array insted of just by // heightsec. Allows for multiple fake planes. @@ -114,11 +126,11 @@ typedef enum FF_CUTEXTRA = 0x100, ///< Cuts out hidden translucent pixels. FF_CUTLEVEL = 0x180, ///< Cuts out all hidden pixels. FF_CUTSPRITES = 0x200, ///< Final step in making 3D water. - FF_BOTHPLANES = 0x400, ///< Renders both planes all the time. + FF_BOTHPLANES = 0x400, ///< Render inside and outside planes. FF_EXTRA = 0x800, ///< Gets cut by ::FF_CUTEXTRA. FF_TRANSLUCENT = 0x1000, ///< See through! FF_FOG = 0x2000, ///< Fog "brush." - FF_INVERTPLANES = 0x4000, ///< Reverse the plane visibility rules. + FF_INVERTPLANES = 0x4000, ///< Only render inside planes. FF_ALLSIDES = 0x8000, ///< Render inside and outside sides. FF_INVERTSIDES = 0x10000, ///< Only render inside sides. FF_DOUBLESHADOW = 0x20000, ///< Make two lightlist entries to reset light? @@ -131,15 +143,18 @@ typedef enum FF_QUICKSAND = 0x1000000, ///< Quicksand! FF_PLATFORM = 0x2000000, ///< You can jump up through this to the top. FF_REVERSEPLATFORM = 0x4000000, ///< A fall-through floor in normal gravity, a platform in reverse gravity. - FF_INTANGABLEFLATS = 0x6000000, ///< Both flats are intangable, but the sides are still solid. - FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Thinks everyone's Knuckles. - FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Jump or fall onto it while curled in a ball. - FF_ONLYKNUX = 0x20000000, ///< Used with ::FF_BUSTUP. Only Knuckles can break this rock. + FF_INTANGIBLEFLATS = 0x6000000, ///< Both flats are intangible, but the sides are still solid. + FF_SHATTER = 0x8000000, ///< Used with ::FF_BUSTUP. Bustable on mere touch. + FF_SPINBUST = 0x10000000, ///< Used with ::FF_BUSTUP. Also bustable if you're in your spinning frames. + FF_STRONGBUST = 0x20000000, ///< Used with ::FF_BUSTUP. Only bustable by "strong" characters (Knuckles) and abilities (bouncing, twinspin, melee). FF_RIPPLE = 0x40000000, ///< Ripple the flats FF_COLORMAPONLY = 0x80000000, ///< Only copy the colormap, not the lightlevel FF_GOOWATER = FF_SHATTERBOTTOM, ///< Used with ::FF_SWIMMABLE. Makes thick bouncey goop. } ffloortype_e; +#define FFLOOR_ALPHA_SPECIAL_ADDITIVE (901) +#define FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE (902) + typedef struct ffloor_s { fixed_t *topheight; @@ -155,11 +170,9 @@ typedef struct ffloor_s fixed_t *bottomyoffs; angle_t *bottomangle; -#ifdef ESLOPE // Pointers to pointers. Yup. struct pslope_s **t_slope; struct pslope_s **b_slope; -#endif size_t secnum; ffloortype_e flags; @@ -177,6 +190,8 @@ typedef struct ffloor_s // these are saved for netgames, so do not let Lua touch these! ffloortype_e spawnflags; // flags the 3D floor spawned with INT32 spawnalpha; // alpha the 3D floor spawned with + + void *fadingdata; // fading FOF thinker } ffloor_t; @@ -187,12 +202,10 @@ typedef struct lightlist_s { fixed_t height; INT16 *lightlevel; - extracolormap_t *extra_colormap; + extracolormap_t **extra_colormap; // pointer-to-a-pointer, so we can react to colormap changes INT32 flags; ffloor_t *caster; -#ifdef ESLOPE struct pslope_s *slope; // FF_DOUBLESHADOW makes me have to store this pointer here. Bluh bluh. -#endif } lightlist_t; @@ -211,74 +224,58 @@ typedef struct r_lightlist_s INT32 lightnum; } r_lightlist_t; -// ----- for special tricks with HW renderer ----- - -// -// For creating a chain with the lines around a sector -// -typedef struct linechain_s -{ - struct line_s *line; - struct linechain_s *next; -} linechain_t; -// ----- end special tricks ----- - - - // Slopes -#ifdef ESLOPE typedef enum { - SL_NOPHYSICS = 1, // Don't do momentum adjustment with this slope - SL_NODYNAMIC = 1<<1, // Slope will never need to move during the level, so don't fuss with recalculating it - SL_ANCHORVERTEX = 1<<2, // Slope is using a Slope Vertex Thing to anchor its position - SL_VERTEXSLOPE = 1<<3, // Slope is built from three Slope Vertex Things + SL_NOPHYSICS = 1, /// This plane will have no physics applied besides the positioning. + SL_DYNAMIC = 1<<1, /// This plane slope will be assigned a thinker to make it dynamic. } slopeflags_t; typedef struct pslope_s { UINT16 id; // The number of the slope, mostly used for netgame syncing purposes + struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later - // --- Information used in clipping/projection --- - // Origin vector for the plane - vector3_t o; + // The plane's definition. + vector3_t o; /// Plane origin. + vector3_t normal; /// Plane normal. - // 2-Dimentional vector (x, y) normalized. Used to determine distance from - // the origin in 2d mapspace. (Basically a thrust of FRACUNIT in xydirection angle) - vector2_t d; - - // The rate at which z changes based on distance from the origin plane. - fixed_t zdelta; - - // The normal of the slope; will always point upward, and thus be inverted on ceilings. I think it's only needed for physics? -Red - vector3_t normal; - - // For comparing when a slope should be rendered - fixed_t lowz; - fixed_t highz; + vector2_t d; /// Precomputed normalized projection of the normal over XY. + fixed_t zdelta; /// Precomputed Z unit increase per XY unit. // This values only check and must be updated if the slope itself is modified - angle_t zangle; // Angle of the plane going up from the ground (not mesured in degrees) - angle_t xydirection; // The direction the slope is facing (north, west, south, etc.) - - struct line_s *sourceline; // The line that generated the slope - fixed_t extent; // Distance value used for recalculating zdelta - UINT8 refpos; // 1=front floor 2=front ceiling 3=back floor 4=back ceiling (used for dynamic sloping) + angle_t zangle; /// Precomputed angle of the plane going up from the ground (not measured in degrees). + angle_t xydirection;/// Precomputed angle of the normal's projection on the XY plane. UINT8 flags; // Slope options - mapthing_t **vertices; // List should be three long for slopes made by vertex things, or one long for slopes using one vertex thing to anchor - struct pslope_s *next; // Make a linked list of dynamic slopes, for easy reference later + // SRB2Kart: For P_VeryTopOfFOF & P_VeryBottomOfFOF + fixed_t lowz; + fixed_t highz; } pslope_t; -#endif typedef enum { - SF_FLIPSPECIAL_FLOOR = 1, - SF_FLIPSPECIAL_CEILING = 2, - SF_FLIPSPECIAL_BOTH = 3, - SF_TRIGGERSPECIAL_TOUCH = 4, + // flipspecial - planes with effect + SF_FLIPSPECIAL_FLOOR = 1, + SF_FLIPSPECIAL_CEILING = 1<<1, + SF_FLIPSPECIAL_BOTH = (SF_FLIPSPECIAL_FLOOR|SF_FLIPSPECIAL_CEILING), + // triggerspecial - conditions under which plane touch causes effect + SF_TRIGGERSPECIAL_TOUCH = 1<<2, + SF_TRIGGERSPECIAL_HEADBUMP = 1<<3, + // invertprecip - inverts presence of precipitation + SF_INVERTPRECIP = 1<<4, } sectorflags_t; + +typedef enum +{ + CRUMBLE_NONE, // No crumble thinker + CRUMBLE_WAIT, // Don't float on water because this is supposed to wait for a crumble + CRUMBLE_ACTIVATED, // Crumble thinker activated, but hasn't fallen yet + CRUMBLE_FALL, // Crumble thinker is falling + CRUMBLE_RESTORE, // Crumble thinker is about to restore to original position +} crumblestate_t; + // // The SECTORS record, at runtime. // Stores things/mobjs. @@ -308,6 +305,7 @@ typedef struct sector_s void *floordata; // floor move thinker void *ceilingdata; // ceiling move thinker void *lightingdata; // lighting change thinker + void *fadecolormapdata; // fade colormap thinker // floor and ceiling texture offsets fixed_t floor_xoffs, floor_yoffs; @@ -323,19 +321,12 @@ typedef struct sector_s INT32 floorlightsec, ceilinglightsec; INT32 crumblestate; // used for crumbling and bobbing - INT32 bottommap, midmap, topmap; // dynamic colormaps - // list of mobjs that are at least partially in the sector // thinglist is a subset of touching_thinglist struct msecnode_s *touching_thinglist; size_t linecount; struct line_s **lines; // [linecount] size - // Hack: store special line tagging to some sectors - // to efficiently help work around bugs by directly - // referencing the specific line that the problem happens in. - // (used in T_MovePlane mobj physics) - struct line_s *tagline; // Improved fake floor hack ffloor_t *ffloors; @@ -349,17 +340,7 @@ typedef struct sector_s // per-sector colormaps! extracolormap_t *extra_colormap; - -#ifdef HWRENDER // ----- for special tricks with HW renderer ----- - boolean pseudoSector; - boolean virtualFloor; - fixed_t virtualFloorheight; - boolean virtualCeiling; - fixed_t virtualCeilingheight; - linechain_t *sectorLines; - struct sector_s **stackList; - double lineoutLength; -#endif // ----- end special tricks ----- + boolean colormap_protected; // This points to the master's floorheight, so it can be changed in realtime! fixed_t *gravity; // per-sector gravity @@ -376,23 +357,16 @@ typedef struct sector_s precipmobj_t *preciplist; struct mprecipsecnode_s *touching_preciplist; -#ifdef ESLOPE // Eternity engine slope pslope_t *f_slope; // floor slope pslope_t *c_slope; // ceiling slope boolean hasslope; // The sector, or one of its visible FOFs, contains a slope -#endif - // these are saved for netgames, so do not let Lua touch these! - INT32 spawn_nexttag, spawn_firsttag; // the actual nexttag/firsttag values may differ if the sector's tag was changed + // for fade thinker + INT16 spawn_lightlevel; - // offsets sector spawned with (via linedef type 7) - fixed_t spawn_flr_xoffs, spawn_flr_yoffs; - fixed_t spawn_ceil_xoffs, spawn_ceil_yoffs; - - // flag angles sector spawned with (via linedef type 7) - angle_t spawn_flrpic_angle; - angle_t spawn_ceilpic_angle; + // colormap structure + extracolormap_t *spawn_extra_colormap; } sector_t; // @@ -408,6 +382,9 @@ typedef enum #define HORIZONSPECIAL 41 +#define NUMLINEARGS 6 +#define NUMLINESTRINGARGS 2 + typedef struct line_s { // Vertices, from v1 to v2. @@ -420,9 +397,13 @@ typedef struct line_s INT16 flags; INT16 special; INT16 tag; + INT32 args[NUMLINEARGS]; + char *stringargs[NUMLINESTRINGARGS]; // Visual appearance: sidedefs. UINT16 sidenum[2]; // sidenum[1] will be 0xffff if one-sided + fixed_t alpha; // translucency + INT32 executordelay; fixed_t bbox[4]; // bounding box for the extent of the linedef @@ -439,18 +420,12 @@ typedef struct line_s void *splats; // wallsplat_t list #endif INT32 firsttag, nexttag; // improves searches for tags. -#ifdef POLYOBJECTS polyobj_t *polyobj; // Belongs to a polyobject? -#endif - char *text; // a concatination of all front and back texture names, for linedef specials that require a string. + char *text; // a concatenation of all front and back texture names, for linedef specials that require a string. INT16 callcount; // no. of calls left before triggering, for the "X calls" linedef specials, defaults to 0 } line_t; -// -// The SideDef. -// - typedef struct { // add this to the calculated texture column @@ -463,13 +438,18 @@ typedef struct // We do not maintain names here. INT32 toptexture, bottomtexture, midtexture; - // Sector the SideDef is facing. + // Linedef the sidedef belongs to + line_t *line; + + // Sector the sidedef is facing. sector_t *sector; INT16 special; // the special of the linedef this side belongs to INT16 repeatcnt; // # of times to repeat midtexture - char *text; // a concatination of all top, bottom, and mid texture names, for linedef specials that require a string. + char *text; // a concatenation of all top, bottom, and mid texture names, for linedef specials that require a string. + + extracolormap_t *colormap_data; // storage for colormaps; not applied to sectors. } side_t; // @@ -483,9 +463,7 @@ typedef struct subsector_s sector_t *sector; INT16 numlines; UINT16 firstline; -#ifdef POLYOBJECTS struct polyobj_s *polyList; // haleyjd 02/19/06: list of polyobjects -#endif #if 1//#ifdef FLOORSPLATS void *splats; // floorsplat_t list #endif @@ -528,6 +506,31 @@ typedef struct mprecipsecnode_s boolean visited; // used in search algorithms } mprecipsecnode_t; +// for now, only used in hardware mode +// maybe later for software as well? +// that's why it's moved here +typedef struct light_s +{ + UINT16 type; // light,... (cfr #define in hwr_light.c) + + float light_xoffset; + float light_yoffset; // y offset to adjust corona's height + + UINT32 corona_color; // color of the light for static lighting + float corona_radius; // radius of the coronas + + UINT32 dynamic_color; // color of the light for dynamic lighting + float dynamic_radius; // radius of the light ball + float dynamic_sqrradius; // radius^2 of the light ball +} light_t; + +typedef struct lightmap_s +{ + float s[2], t[2]; + light_t *light; + struct lightmap_s *next; +} lightmap_t; + // // The lineseg. // @@ -556,15 +559,16 @@ typedef struct seg_s void *pv1; // polyvertex_t void *pv2; // polyvertex_t float flength; // length of the seg, used by hardware renderer + + lightmap_t *lightmaps; // for static lightmap #endif // Why slow things down by calculating lightlists for every thick side? size_t numlights; r_lightlist_t *rlights; -#ifdef POLYOBJECTS polyobj_t *polyseg; boolean dontrenderme; -#endif + boolean glseg; // Fake contrast calculated on level load SINT8 lightOffset; @@ -647,11 +651,9 @@ typedef struct drawseg_s UINT8 portalpass; // if > 0 and <= portalrender, do not affect sprite clipping -#ifdef ESLOPE fixed_t maskedtextureheight[MAXVIDWIDTH]; // For handling sloped midtextures vertex_t leftpos, rightpos; // Used for rendering FOF walls with slopes -#endif } drawseg_t; typedef enum @@ -670,7 +672,7 @@ typedef enum // Patches. // A patch holds one or more columns. // Patches are used for sprites and all masked pictures, and we compose -// textures from the TEXTURE1 list of patches. +// textures from the TEXTURES list of patches. // // WARNING: this structure is cloned in GLPatch_t typedef struct @@ -707,21 +709,50 @@ typedef struct #pragma pack() #endif +// rotsprite +#ifdef ROTSPRITE +typedef struct +{ + patch_t *patch[16][ROTANGLES]; + UINT16 cached; +} rotsprite_t; +#endif/*ROTSPRITE*/ + typedef enum { SRF_SINGLE = 0, // 0-angle for all rotations SRF_3D = 1, // Angles 1-8 - SRF_LEFT = 2, // Left side has single patch - SRF_RIGHT = 4, // Right side has single patch - SRF_2D = 6, // SRF_LEFT|SRF_RIGHT + SRF_3DGE = 2, // 3DGE, ZDoom and Doom Legacy all have 16-angle support. Why not us? + SRF_3DMASK = SRF_3D|SRF_3DGE, // 3 + SRF_LEFT = 4, // Left side uses single patch + SRF_RIGHT = 8, // Right side uses single patch + SRF_2D = SRF_LEFT|SRF_RIGHT, // 12 SRF_NONE = 0xff // Initial value } spriterotateflags_t; // SRF's up! +// Same as a patch_t, except just the header +// and the wadnum/lumpnum combination that points +// to wherever the patch is in memory. +struct patchinfo_s +{ + INT16 width; // bounding box size + INT16 height; + INT16 leftoffset; // pixels to the left of origin + INT16 topoffset; // pixels below the origin + + UINT16 wadnum; // the software patch lump num for when the patch + UINT16 lumpnum; // was flushed, and we need to re-create it + + // next patchinfo_t in memory + struct patchinfo_s *next; +}; +typedef struct patchinfo_s patchinfo_t; + // // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. // The base name is NNNNFx or NNNNFxFx, with x indicating the rotation, -// x = 0, 1-8, L/R +// x = 0, 1-8, 9+A-G, L/R // The sprite and frame specified by a thing_t is range checked at run time. // A sprite is a patch_t that is assumed to represent a three dimensional // object and may have multiple rotations predrawn. @@ -733,16 +764,21 @@ typedef enum // typedef struct { + // If false use 0 for any position. // Note: as eight entries are available, we might as well insert the same // name eight times. UINT8 rotate; // see spriterotateflags_t above - // Lump to use for view angles 0-7. - lumpnum_t lumppat[8]; // lump number 16 : 16 wad : lump - size_t lumpid[8]; // id in the spriteoffset, spritewidth, etc. tables + // Lump to use for view angles 0-7/15. + lumpnum_t lumppat[16]; // lump number 16 : 16 wad : lump + size_t lumpid[16]; // id in the spriteoffset, spritewidth, etc. tables - // Flip bits (1 = flip) to use for view angles 0-7. - UINT8 flip; + // Flip bits (1 = flip) to use for view angles 0-7/15. + UINT16 flip; + +#ifdef ROTSPRITE + rotsprite_t rotsprite; +#endif } spriteframe_t; // diff --git a/src/r_draw.c b/src/r_draw.c index c993810d5..3d806eaf0 100644 --- a/src/r_draw.c +++ b/src/r_draw.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -81,7 +81,7 @@ UINT8 *dc_source; // ----------------------- // translucency stuff here // ----------------------- -#define NUMTRANSTABLES 9 // how many translucency tables are used +#define NUMTRANSTABLES 11 // how many translucency tables are used UINT8 *transtables; // translucency tables @@ -108,15 +108,17 @@ INT32 dc_numlights = 0, dc_maxlights, dc_texheight; INT32 ds_y, ds_x1, ds_x2; lighttable_t *ds_colormap; fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; +UINT16 ds_flatwidth, ds_flatheight; +boolean ds_powersoftwo; UINT8 *ds_source; // start of a 64*64 tile image UINT8 *ds_transmap; // one of the translucency tables -#ifdef ESLOPE pslope_t *ds_slope; // Current slope being used -floatv3_t ds_su, ds_sv, ds_sz; // Vectors for... stuff? -float focallengthf, zeroheight; -#endif +floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff? +floatv3_t *ds_sup, *ds_svp, *ds_szp; +float focallengthf[MAXSPLITSCREENPLAYERS]; +float zeroheight; /** \brief Variable flat sizes */ @@ -137,14 +139,14 @@ UINT32 nflatxshift, nflatyshift, nflatshiftup, nflatmask; #define ALLWHITE_TT_CACHE_INDEX (MAXSKINS + 3) #define RAINBOW_TT_CACHE_INDEX (MAXSKINS + 4) #define BLINK_TT_CACHE_INDEX (MAXSKINS + 5) -#define TT_CACHE_SIZE (MAXSKINS + 6) +#define DASHMODE_TT_CACHE_INDEX (MAXSKINS + 6) +#define TT_CACHE_SIZE (MAXSKINS + 7) #define SKIN_RAMP_LENGTH 16 #define DEFAULT_STARTTRANSCOLOR 96 #define NUM_PALETTE_ENTRIES 256 static UINT8** translationtablecache[TT_CACHE_SIZE] = {NULL}; - -// SKINCOLOR DEFINITIONS HAVE BEEN MOVED TO K_KART.C +UINT8 skincolor_modified[MAXSKINCOLORS]; CV_PossibleValue_t Color_cons_t[MAXSKINCOLORS+1]; CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for "Match", "Opposite" & NULL @@ -155,10 +157,6 @@ CV_PossibleValue_t Followercolor_cons_t[MAXSKINCOLORS+3]; // +3 to account for " */ void R_InitTranslationTables(void) { -#ifdef _NDS - // Ugly temporary NDS hack. - transtables = (UINT8*)0x2000000; -#else // Load here the transparency lookup tables 'TINTTAB' // NOTE: the TINTTAB resource MUST BE aligned on 64k for the asm // optimised code (in other words, transtables pointer low word is 0) @@ -174,7 +172,8 @@ void R_InitTranslationTables(void) W_ReadLump(W_GetNumForName("TRANS70"), transtables+0x60000); W_ReadLump(W_GetNumForName("TRANS80"), transtables+0x70000); W_ReadLump(W_GetNumForName("TRANS90"), transtables+0x80000); -#endif + W_ReadLump(W_GetNumForName("TRANSADD"),transtables+0x90000); + W_ReadLump(W_GetNumForName("TRANSSUB"),transtables+0xA0000); } /** \brief Retrieves a translation colormap from the cache. @@ -185,29 +184,43 @@ void R_InitTranslationTables(void) \return Colormap. If not cached, caller should Z_Free. */ -UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags) +UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags) { UINT8* ret; INT32 skintableindex; + INT32 i; // Adjust if we want the default colormap - if (skinnum == TC_DEFAULT) skintableindex = DEFAULT_TT_CACHE_INDEX; - else if (skinnum == TC_BOSS) skintableindex = BOSS_TT_CACHE_INDEX; - else if (skinnum == TC_METALSONIC) skintableindex = METALSONIC_TT_CACHE_INDEX; - else if (skinnum == TC_ALLWHITE) skintableindex = ALLWHITE_TT_CACHE_INDEX; - else if (skinnum == TC_RAINBOW) skintableindex = RAINBOW_TT_CACHE_INDEX; - else if (skinnum == TC_BLINK) skintableindex = BLINK_TT_CACHE_INDEX; - else skintableindex = skinnum; + switch (skinnum) + { + case TC_DEFAULT: skintableindex = DEFAULT_TT_CACHE_INDEX; break; + case TC_BOSS: skintableindex = BOSS_TT_CACHE_INDEX; break; + case TC_METALSONIC: skintableindex = METALSONIC_TT_CACHE_INDEX; break; + case TC_ALLWHITE: skintableindex = ALLWHITE_TT_CACHE_INDEX; break; + case TC_RAINBOW: skintableindex = RAINBOW_TT_CACHE_INDEX; break; + case TC_BLINK: skintableindex = BLINK_TT_CACHE_INDEX; break; + case TC_DASHMODE: skintableindex = DASHMODE_TT_CACHE_INDEX; break; + default: skintableindex = skinnum; break; + } if (flags & GTC_CACHE) { // Allocate table for skin if necessary if (!translationtablecache[skintableindex]) - translationtablecache[skintableindex] = Z_Calloc(MAXTRANSLATIONS * sizeof(UINT8**), PU_STATIC, NULL); + translationtablecache[skintableindex] = Z_Calloc(MAXSKINCOLORS * sizeof(UINT8**), PU_STATIC, NULL); // Get colormap ret = translationtablecache[skintableindex][color]; + + // Rebuild the cache if necessary + if (skincolor_modified[color]) + { + for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++) + if (translationtablecache[i] && translationtablecache[i][color]) + K_GenerateKartColormap(translationtablecache[i][color], i>=MAXSKINS ? MAXSKINS-i-1 : i, color); + skincolor_modified[color] = false; + } } else ret = NULL; @@ -215,7 +228,7 @@ UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags) if (!ret) { ret = Z_MallocAlign(NUM_PALETTE_ENTRIES, (flags & GTC_CACHE) ? PU_LEVEL : PU_STATIC, NULL, 8); - K_GenerateKartColormap(ret, skinnum, color); //R_GenerateTranslationColormap(ret, skinnum, color); // SRB2kart + K_GenerateKartColormap(ret, skinnum, color); //R_GenerateTranslationColormap(ret, skinnum, color); // SRB2kart // Cache the colormap if desired if (flags & GTC_CACHE) @@ -239,21 +252,33 @@ void R_FlushTranslationColormapCache(void) for (i = 0; i < (INT32)(sizeof(translationtablecache) / sizeof(translationtablecache[0])); i++) if (translationtablecache[i]) - memset(translationtablecache[i], 0, MAXTRANSLATIONS * sizeof(UINT8**)); + memset(translationtablecache[i], 0, MAXSKINCOLORS * sizeof(UINT8**)); } -/* -UINT8 R_GetColorByName(const char *name) +UINT16 R_GetColorByName(const char *name) { - UINT8 color = (UINT8)atoi(name); - if (color > 0 && color < MAXSKINCOLORS) + UINT16 color = (UINT16)atoi(name); + if (color > 0 && color < numskincolors) return color; - for (color = 1; color < MAXSKINCOLORS; color++) - if (!stricmp(Color_Names[color], name)) + for (color = 1; color < numskincolors; color++) + if (!stricmp(skincolors[color].name, name)) return color; - return 0; + return SKINCOLOR_NONE; +} + +UINT16 R_GetSuperColorByName(const char *name) +{ + UINT16 i, color = SKINCOLOR_NONE; + char *realname = Z_Malloc(MAXCOLORNAME+1, PU_STATIC, NULL); + snprintf(realname, MAXCOLORNAME+1, "Super %s 1", name); + for (i = 1; i < numskincolors; i++) + if (!stricmp(skincolors[i].name, realname)) { + color = i; + break; + } + Z_Free(realname); + return color; } -*/ // ========================================================================== // COMMON DRAWER FOR 8 AND 16 BIT COLOR MODES @@ -478,6 +503,7 @@ void R_DrawViewBorder(void) // ========================================================================== #include "r_draw8.c" +#include "r_draw8_npo2.c" // ========================================================================== // INCLUDE 16bpp DRAWING CODE HERE diff --git a/src/r_draw.h b/src/r_draw.h index 900802cea..5f69a8d98 100644 --- a/src/r_draw.h +++ b/src/r_draw.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -59,18 +59,20 @@ extern INT32 dc_texheight; extern INT32 ds_y, ds_x1, ds_x2; extern lighttable_t *ds_colormap; extern fixed_t ds_xfrac, ds_yfrac, ds_xstep, ds_ystep; -extern UINT8 *ds_source; // start of a 64*64 tile image +extern UINT16 ds_flatwidth, ds_flatheight; +extern boolean ds_powersoftwo; +extern UINT8 *ds_source; extern UINT8 *ds_transmap; -#ifdef ESLOPE typedef struct { float x, y, z; } floatv3_t; extern pslope_t *ds_slope; // Current slope being used -extern floatv3_t ds_su, ds_sv, ds_sz; // Vectors for... stuff? -extern float focallengthf, zeroheight; -#endif +extern floatv3_t ds_su[MAXVIDHEIGHT], ds_sv[MAXVIDHEIGHT], ds_sz[MAXVIDHEIGHT]; // Vectors for... stuff? +extern floatv3_t *ds_sup, *ds_svp, *ds_szp; +extern float focallengthf[MAXSPLITSCREENPLAYERS]; +extern float zeroheight; // Variable flat sizes extern UINT32 nflatxshift; @@ -109,14 +111,19 @@ extern lumpnum_t viewborderlump[8]; #define TC_BOSS -2 #define TC_METALSONIC -3 // For Metal Sonic battle #define TC_ALLWHITE -4 // For Cy-Brak-demon -#define TC_RAINBOW -5 // For invincibility power -#define TC_BLINK -6 // For item blinking +#define TC_RAINBOW -5 // For single colour +#define TC_BLINK -6 // For item blinking, according to kart +#define TC_DASHMODE -7 // For Metal Sonic's dashmode // Initialize color translation tables, for player rendering etc. void R_InitTranslationTables(void); -UINT8* R_GetTranslationColormap(INT32 skinnum, skincolors_t color, UINT8 flags); +UINT8* R_GetTranslationColormap(INT32 skinnum, skincolornum_t color, UINT8 flags); void R_FlushTranslationColormapCache(void); -UINT8 R_GetColorByName(const char *name); +UINT16 R_GetColorByName(const char *name); +UINT16 R_GetSuperColorByName(const char *name); + +// Color ramp modification should force a recache +extern UINT8 skincolor_modified[]; // Custom player skin translation void R_InitViewBuffer(INT32 width, INT32 height); @@ -131,47 +138,68 @@ void R_FillBackScreen(void); void R_DrawViewBorder(void); #endif +#define TRANSPARENTPIXEL 255 + // ----------------- // 8bpp DRAWING CODE // ----------------- void R_DrawColumn_8(void); -#define R_DrawWallColumn_8 R_DrawColumn_8 void R_DrawShadeColumn_8(void); void R_DrawTranslucentColumn_8(void); +void R_DrawTranslatedColumn_8(void); +void R_DrawTranslatedTranslucentColumn_8(void); +void R_Draw2sMultiPatchColumn_8(void); +void R_Draw2sMultiPatchTranslucentColumn_8(void); +void R_DrawFogColumn_8(void); +void R_DrawColumnShadowed_8(void); + +void R_DrawSpan_8(void); +void R_DrawSplat_8(void); +void R_DrawTranslucentSpan_8(void); +void R_DrawTranslucentSplat_8(void); +void R_DrawTiltedSpan_8(void); +void R_DrawTiltedTranslucentSpan_8(void); +#ifndef NOWATER +void R_DrawTiltedTranslucentWaterSpan_8(void); +#endif +void R_DrawTiltedSplat_8(void); +void R_CalcTiltedLighting(fixed_t start, fixed_t end); +extern INT32 tiltlighting[MAXVIDWIDTH]; +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_8(void); +extern INT32 ds_bgofs; +extern INT32 ds_waterofs; +#endif +void R_DrawFogSpan_8(void); + +// Lactozilla: Non-powers-of-two +void R_DrawSpan_NPO2_8(void); +void R_DrawTranslucentSpan_NPO2_8(void); +void R_DrawSplat_NPO2_8(void); +void R_DrawTranslucentSplat_NPO2_8(void); +void R_DrawTiltedSpan_NPO2_8(void); +void R_DrawTiltedTranslucentSpan_NPO2_8(void); +#ifndef NOWATER +void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void); +#endif +void R_DrawTiltedSplat_NPO2_8(void); +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_NPO2_8(void); +#endif #ifdef USEASM void ASMCALL R_DrawColumn_8_ASM(void); -#define R_DrawWallColumn_8_ASM R_DrawColumn_8_ASM void ASMCALL R_DrawShadeColumn_8_ASM(void); void ASMCALL R_DrawTranslucentColumn_8_ASM(void); void ASMCALL R_Draw2sMultiPatchColumn_8_ASM(void); void ASMCALL R_DrawColumn_8_MMX(void); -#define R_DrawWallColumn_8_MMX R_DrawColumn_8_MMX void ASMCALL R_Draw2sMultiPatchColumn_8_MMX(void); void ASMCALL R_DrawSpan_8_MMX(void); #endif -void R_DrawTranslatedColumn_8(void); -void R_DrawTranslatedTranslucentColumn_8(void); -void R_DrawSpan_8(void); -#ifdef ESLOPE -void R_CalcTiltedLighting(fixed_t start, fixed_t end); -void R_DrawTiltedSpan_8(void); -void R_DrawTiltedTranslucentSpan_8(void); -void R_DrawTiltedSplat_8(void); -#endif -void R_DrawSplat_8(void); -void R_DrawTranslucentSplat_8(void); -void R_DrawTranslucentSpan_8(void); -void R_Draw2sMultiPatchColumn_8(void); -void R_Draw2sMultiPatchTranslucentColumn_8(void); -void R_DrawFogSpan_8(void); -void R_DrawFogColumn_8(void); -void R_DrawColumnShadowed_8(void); - // ------------------ // 16bpp DRAWING CODE // ------------------ diff --git a/src/r_draw16.c b/src/r_draw16.c index 918dd356c..8b1d29e8d 100644 --- a/src/r_draw16.c +++ b/src/r_draw16.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/r_draw8.c b/src/r_draw8.c index ef67dbaf7..2f7bb64b8 100644 --- a/src/r_draw8.c +++ b/src/r_draw8.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -105,8 +105,6 @@ void R_DrawColumn_8(void) } } -#define TRANSPARENTPIXEL 255 - void R_Draw2sMultiPatchColumn_8(void) { INT32 count; @@ -543,16 +541,19 @@ void R_DrawTranslatedColumn_8(void) */ void R_DrawSpan_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + size_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -561,13 +562,12 @@ void R_DrawSpan_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; if (dest+8 > deststop) return; @@ -577,35 +577,35 @@ void R_DrawSpan_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + dest[0] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; - dest[1] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + dest[1] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; - dest[2] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + dest[2] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; - dest[3] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + dest[3] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; - dest[4] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + dest[4] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; - dest[5] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + dest[5] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; - dest[6] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + dest[6] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; - dest[7] = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + dest[7] = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; @@ -614,16 +614,15 @@ void R_DrawSpan_8 (void) } while (count-- && dest <= deststop) { - *dest++ = colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]]; + *dest++ = colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]]; xposition += xstep; yposition += ystep; } } -#ifdef ESLOPE // R_CalcTiltedLighting // Exactly what it says on the tin. I wish I wasn't too lazy to explain things properly. -static INT32 tiltlighting[MAXVIDWIDTH]; +INT32 tiltlighting[MAXVIDWIDTH]; void R_CalcTiltedLighting(fixed_t start, fixed_t end) { // ZDoom uses a different lighting setup to us, and I couldn't figure out how to adapt their version @@ -644,6 +643,7 @@ void R_CalcTiltedLighting(fixed_t start, fixed_t end) } } +#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan[viewssnum])) /** \brief The R_DrawTiltedSpan_8 function Draw slopes! Holy sheit! @@ -665,22 +665,22 @@ void R_DrawTiltedSpan_8(void) double endz, endu, endv; UINT32 stepu, stepv; - iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end { - float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f; + float planelightfloat = PLANELIGHTFLOAT; float lightstart, lightend; - lightend = (iz + ds_sz.x*width) * planelightfloat; + lightend = (iz + ds_szp->x*width) * planelightfloat; lightstart = iz * planelightfloat; R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); } - uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); - vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; source = ds_source; @@ -699,9 +699,9 @@ void R_DrawTiltedSpan_8(void) *dest = colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]]; dest++; - iz += ds_sz.x; - uz += ds_su.x; - vz += ds_sv.x; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; } while (--width >= 0); #else #define SPANSIZE 16 @@ -711,9 +711,9 @@ void R_DrawTiltedSpan_8(void) startu = uz*startz; startv = vz*startz; - izstep = ds_sz.x * SPANSIZE; - uzstep = ds_su.x * SPANSIZE; - vzstep = ds_sv.x * SPANSIZE; + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; //x1 = 0; width++; @@ -755,9 +755,9 @@ void R_DrawTiltedSpan_8(void) else { double left = width; - iz += ds_sz.x * left; - uz += ds_su.x * left; - vz += ds_sv.x * left; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; endz = 1.f/iz; endu = uz*endz; @@ -801,22 +801,22 @@ void R_DrawTiltedTranslucentSpan_8(void) double endz, endu, endv; UINT32 stepu, stepv; - iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end { - float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f; + float planelightfloat = PLANELIGHTFLOAT; float lightstart, lightend; - lightend = (iz + ds_sz.x*width) * planelightfloat; + lightend = (iz + ds_szp->x*width) * planelightfloat; lightstart = iz * planelightfloat; R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); } - uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); - vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; source = ds_source; @@ -834,9 +834,9 @@ void R_DrawTiltedTranslucentSpan_8(void) colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dest); dest++; - iz += ds_sz.x; - uz += ds_su.x; - vz += ds_sv.x; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; } while (--width >= 0); #else #define SPANSIZE 16 @@ -846,9 +846,9 @@ void R_DrawTiltedTranslucentSpan_8(void) startu = uz*startz; startv = vz*startz; - izstep = ds_sz.x * SPANSIZE; - uzstep = ds_su.x * SPANSIZE; - vzstep = ds_sv.x * SPANSIZE; + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; //x1 = 0; width++; @@ -890,9 +890,9 @@ void R_DrawTiltedTranslucentSpan_8(void) else { double left = width; - iz += ds_sz.x * left; - uz += ds_su.x * left; - vz += ds_sv.x * left; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; endz = 1.f/iz; endu = uz*endz; @@ -916,6 +916,145 @@ void R_DrawTiltedTranslucentSpan_8(void) #endif } +#ifndef NOWATER +/** \brief The R_DrawTiltedTranslucentWaterSpan_8 function + Like DrawTiltedTranslucentSpan, but for water +*/ +void R_DrawTiltedTranslucentWaterSpan_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + UINT8 *dsrc; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds_szp->x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z) + viewx; + v = (INT64)(vz*z) + viewy; + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + dest++; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; + } while (--width >= 0); +#else +#define SPANSIZE 16 +#define INVSPAN 0.0625f + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + *dest = *(ds_transmap + (colormap[source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]] << 8) + *dsrc++); + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} +#endif // NOWATER + void R_DrawTiltedSplat_8(void) { // x1, x2 = ds_x1, ds_x2 @@ -935,22 +1074,22 @@ void R_DrawTiltedSplat_8(void) double endz, endu, endv; UINT32 stepu, stepv; - iz = ds_sz.z + ds_sz.y*(centery-ds_y) + ds_sz.x*(ds_x1-centerx); + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); // Lighting is simple. It's just linear interpolation from start to end { - float planelightfloat = BASEVIDWIDTH*BASEVIDWIDTH/vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f; + float planelightfloat = PLANELIGHTFLOAT; float lightstart, lightend; - lightend = (iz + ds_sz.x*width) * planelightfloat; + lightend = (iz + ds_szp->x*width) * planelightfloat; lightstart = iz * planelightfloat; R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); } - uz = ds_su.z + ds_su.y*(centery-ds_y) + ds_su.x*(ds_x1-centerx); - vz = ds_sv.z + ds_sv.y*(centery-ds_y) + ds_sv.x*(ds_x1-centerx); + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); dest = ylookup[ds_y] + columnofs[ds_x1]; source = ds_source; @@ -970,10 +1109,11 @@ void R_DrawTiltedSplat_8(void) val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; + dest++; - iz += ds_sz.x; - uz += ds_su.x; - vz += ds_sv.x; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; } while (--width >= 0); #else #define SPANSIZE 16 @@ -983,9 +1123,9 @@ void R_DrawTiltedSplat_8(void) startu = uz*startz; startv = vz*startz; - izstep = ds_sz.x * SPANSIZE; - uzstep = ds_su.x * SPANSIZE; - vzstep = ds_sv.x * SPANSIZE; + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; //x1 = 0; width++; @@ -1031,9 +1171,9 @@ void R_DrawTiltedSplat_8(void) else { double left = width; - iz += ds_sz.x * left; - uz += ds_su.x * left; - vz += ds_sv.x * left; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; endz = 1.f/iz; endu = uz*endz; @@ -1058,24 +1198,27 @@ void R_DrawTiltedSplat_8(void) } #endif } -#endif // ESLOPE /** \brief The R_DrawSplat_8 function Just like R_DrawSpan_8, but skips transparent pixels. */ void R_DrawSplat_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; + size_t count = (ds_x2 - ds_x1 + 1); UINT32 val; + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the // texture with two shifts, an OR and one AND. (see below) @@ -1083,13 +1226,12 @@ void R_DrawSplat_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; while (count >= 8) { @@ -1098,7 +1240,7 @@ void R_DrawSplat_8 (void) // need! // // 4194303 = (2048x2048)-1 (2048x2048 is maximum flat size) - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); val &= 4194303; val = source[val]; if (val != TRANSPARENTPIXEL) @@ -1106,7 +1248,7 @@ void R_DrawSplat_8 (void) xposition += xstep; yposition += ystep; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); val &= 4194303; val = source[val]; if (val != TRANSPARENTPIXEL) @@ -1114,7 +1256,7 @@ void R_DrawSplat_8 (void) xposition += xstep; yposition += ystep; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); val &= 4194303; val = source[val]; if (val != TRANSPARENTPIXEL) @@ -1122,7 +1264,7 @@ void R_DrawSplat_8 (void) xposition += xstep; yposition += ystep; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); val &= 4194303; val = source[val]; if (val != TRANSPARENTPIXEL) @@ -1130,7 +1272,7 @@ void R_DrawSplat_8 (void) xposition += xstep; yposition += ystep; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); val &= 4194303; val = source[val]; if (val != TRANSPARENTPIXEL) @@ -1138,7 +1280,7 @@ void R_DrawSplat_8 (void) xposition += xstep; yposition += ystep; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); val &= 4194303; val = source[val]; if (val != TRANSPARENTPIXEL) @@ -1146,7 +1288,7 @@ void R_DrawSplat_8 (void) xposition += xstep; yposition += ystep; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); val &= 4194303; val = source[val]; if (val != TRANSPARENTPIXEL) @@ -1154,7 +1296,7 @@ void R_DrawSplat_8 (void) xposition += xstep; yposition += ystep; - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); val &= 4194303; val = source[val]; if (val != TRANSPARENTPIXEL) @@ -1165,14 +1307,11 @@ void R_DrawSplat_8 (void) dest += 8; count -= 8; } - while (count--) + while (count-- && dest <= deststop) { - val = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift); - val &= 4194303; - val = source[val]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = colormap[val]; - dest++; xposition += xstep; yposition += ystep; @@ -1184,16 +1323,20 @@ void R_DrawSplat_8 (void) */ void R_DrawTranslucentSplat_8 (void) { - UINT32 xposition; - UINT32 yposition; - UINT32 xstep, ystep; + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; UINT8 *source; UINT8 *colormap; UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; - size_t count; - UINT8 val; + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest // can be used for the fraction part. This allows calculation of the memory address in the @@ -1202,62 +1345,61 @@ void R_DrawTranslucentSplat_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; - count = ds_x2 - ds_x1 + 1; while (count >= 8) { // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) dest[0] = *(ds_transmap + (colormap[val] << 8) + dest[0]); xposition += xstep; yposition += ystep; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) dest[1] = *(ds_transmap + (colormap[val] << 8) + dest[1]); xposition += xstep; yposition += ystep; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) dest[2] = *(ds_transmap + (colormap[val] << 8) + dest[2]); xposition += xstep; yposition += ystep; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) dest[3] = *(ds_transmap + (colormap[val] << 8) + dest[3]); xposition += xstep; yposition += ystep; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) dest[4] = *(ds_transmap + (colormap[val] << 8) + dest[4]); xposition += xstep; yposition += ystep; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) dest[5] = *(ds_transmap + (colormap[val] << 8) + dest[5]); xposition += xstep; yposition += ystep; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) dest[6] = *(ds_transmap + (colormap[val] << 8) + dest[6]); xposition += xstep; yposition += ystep; - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) dest[7] = *(ds_transmap + (colormap[val] << 8) + dest[7]); xposition += xstep; @@ -1266,12 +1408,11 @@ void R_DrawTranslucentSplat_8 (void) dest += 8; count -= 8; } - while (count--) + while (count-- && dest <= deststop) { - val = source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]; + val = source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]; if (val != TRANSPARENTPIXEL) *dest = *(ds_transmap + (colormap[val] << 8) + *dest); - dest++; xposition += xstep; yposition += ystep; @@ -1279,9 +1420,91 @@ void R_DrawTranslucentSplat_8 (void) } /** \brief The R_DrawTranslucentSpan_8 function - Draws the actual span with translucent. + Draws the actual span with translucency. */ void R_DrawTranslucentSpan_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + // SoM: we only need 6 bits for the integer part (0 thru 63) so the rest + // can be used for the fraction part. This allows calculation of the memory address in the + // texture with two shifts, an OR and one AND. (see below) + // for texture sizes > 64 the amount of precision we can allow will decrease, but only by one + // bit per power of two (obviously) + // Ok, because I was able to eliminate the variable spot below, this function is now FASTER + // than the original span renderer. Whodathunkit? + xposition <<= nflatshiftup; yposition <<= nflatshiftup; + xstep <<= nflatshiftup; ystep <<= nflatshiftup; + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + while (count >= 8) + { + // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't + // have the uber complicated math to calculate it now, so that was a memory write we didn't + // need! + dest[0] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[0]); + xposition += xstep; + yposition += ystep; + + dest[1] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[1]); + xposition += xstep; + yposition += ystep; + + dest[2] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[2]); + xposition += xstep; + yposition += ystep; + + dest[3] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[3]); + xposition += xstep; + yposition += ystep; + + dest[4] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[4]); + xposition += xstep; + yposition += ystep; + + dest[5] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[5]); + xposition += xstep; + yposition += ystep; + + dest[6] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[6]); + xposition += xstep; + yposition += ystep; + + dest[7] = *(ds_transmap + (colormap[source[(((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift)]] << 8) + dest[7]); + xposition += xstep; + yposition += ystep; + + dest += 8; + count -= 8; + } + while (count-- && dest <= deststop) + { + val = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift); + *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } +} + +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_8(void) { UINT32 xposition; UINT32 yposition; @@ -1290,6 +1513,7 @@ void R_DrawTranslucentSpan_8 (void) UINT8 *source; UINT8 *colormap; UINT8 *dest; + UINT8 *dsrc; size_t count; @@ -1300,12 +1524,13 @@ void R_DrawTranslucentSpan_8 (void) // bit per power of two (obviously) // Ok, because I was able to eliminate the variable spot below, this function is now FASTER // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = ds_yfrac << nflatshiftup; + xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + ds_waterofs) << nflatshiftup; xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; source = ds_source; colormap = ds_colormap; dest = ylookup[ds_y] + columnofs[ds_x1]; + dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; count = ds_x2 - ds_x1 + 1; while (count >= 8) @@ -1313,35 +1538,35 @@ void R_DrawTranslucentSpan_8 (void) // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't // have the uber complicated math to calculate it now, so that was a memory write we didn't // need! - dest[0] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[0]); + dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - dest[1] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[1]); + dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - dest[2] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[2]); + dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - dest[3] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[3]); + dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - dest[4] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[4]); + dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - dest[5] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[5]); + dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - dest[6] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[6]); + dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; - dest[7] = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + dest[7]); + dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; @@ -1350,12 +1575,12 @@ void R_DrawTranslucentSpan_8 (void) } while (count--) { - *dest = *(ds_transmap + (colormap[source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)]] << 8) + *dest); - dest++; + *dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; xposition += xstep; yposition += ystep; } } +#endif /** \brief The R_DrawFogSpan_8 function Draws the actual span with fogging. @@ -1483,7 +1708,7 @@ void R_DrawColumnShadowed_8(void) if (dc_yh > realyh) dc_yh = realyh; - basecolfunc(); // R_DrawColumn_8 for the appropriate architecture + (colfuncs[BASEDRAWFUNC])(); // R_DrawColumn_8 for the appropriate architecture if (solid) dc_yl = bheight; else @@ -1495,5 +1720,5 @@ void R_DrawColumnShadowed_8(void) } dc_yh = realyh; if (dc_yl <= realyh) - walldrawerfunc(); // R_DrawWallColumn_8 for the appropriate architecture + (colfuncs[BASEDRAWFUNC])(); // R_DrawWallColumn_8 for the appropriate architecture } diff --git a/src/r_draw8_npo2.c b/src/r_draw8_npo2.c new file mode 100644 index 000000000..82e4ddc13 --- /dev/null +++ b/src/r_draw8_npo2.c @@ -0,0 +1,1148 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_draw8_npo2.c +/// \brief 8bpp span drawer functions (for non-powers-of-two flat dimensions) +/// \note no includes because this is included as part of r_draw.c + +// ========================================================================== +// SPANS +// ========================================================================== + +/** \brief The R_DrawSpan_NPO2_8 function + Draws the actual span. +*/ +void R_DrawSpan_NPO2_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + fixed_t x, y; + fixed_t fixedwidth, fixedheight; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + size_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + if (dest+8 > deststop) + return; + + fixedwidth = ds_flatwidth << FRACBITS; + fixedheight = ds_flatheight << FRACBITS; + + // Fix xposition and yposition if they are out of bounds. + if (xposition < 0) + xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth); + else if (xposition >= fixedwidth) + xposition %= fixedwidth; + if (yposition < 0) + yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight); + else if (yposition >= fixedheight) + yposition %= fixedheight; + + while (count-- && dest <= deststop) + { + // The loops here keep the texture coordinates within the texture. + // They will rarely iterate multiple times, and are cheaper than a modulo operation, + // even if using libdivide. + if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop + while (xposition < 0) + xposition += fixedwidth; + else + while (xposition >= fixedwidth) + xposition -= fixedwidth; + if (ystep < 0) + while (yposition < 0) + yposition += fixedheight; + else + while (yposition >= fixedheight) + yposition -= fixedheight; + + x = (xposition >> FRACBITS); + y = (yposition >> FRACBITS); + + *dest++ = colormap[source[((y * ds_flatwidth) + x)]]; + xposition += xstep; + yposition += ystep; + } +} + +#define PLANELIGHTFLOAT (BASEVIDWIDTH * BASEVIDWIDTH / vid.width / (zeroheight - FIXED_TO_FLOAT(viewz)) / 21.0f * FIXED_TO_FLOAT(fovtan[viewssnum])) + +/** \brief The R_DrawTiltedSpan_NPO2_8 function + Draw slopes! Holy sheit! +*/ +void R_DrawTiltedSpan_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds_szp->x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z) + viewx; + v = (INT64)(vz*z) + viewy; + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + dest++; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; + } while (--width >= 0); +#else +#define SPANSIZE 16 +#define INVSPAN 0.0625f + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = colormap[source[((y * ds_flatwidth) + x)]]; + } + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + +/** \brief The R_DrawTiltedTranslucentSpan_NPO2_8 function + Like DrawTiltedSpan_NPO2, but translucent +*/ +void R_DrawTiltedTranslucentSpan_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds_szp->x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z) + viewx; + v = (INT64)(vz*z) + viewy; + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + dest++; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; + } while (--width >= 0); +#else +#define SPANSIZE 16 +#define INVSPAN 0.0625f + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dest); + } + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + +void R_DrawTiltedSplat_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + + UINT8 val; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds_szp->x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z) + viewx; + v = (INT64)(vz*z) + viewy; + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + + dest++; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; + } while (--width >= 0); +#else +#define SPANSIZE 16 +#define INVSPAN 0.0625f + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + val = source[((v >> nflatyshift) & nflatmask) | (u >> nflatxshift)]; + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + val = source[((y * ds_flatwidth) + x)]; + } + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} + +/** \brief The R_DrawSplat_NPO2_8 function + Just like R_DrawSpan_NPO2_8, but skips transparent pixels. +*/ +void R_DrawSplat_NPO2_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + fixed_t x, y; + fixed_t fixedwidth, fixedheight; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + fixedwidth = ds_flatwidth << FRACBITS; + fixedheight = ds_flatheight << FRACBITS; + + // Fix xposition and yposition if they are out of bounds. + if (xposition < 0) + xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth); + else if (xposition >= fixedwidth) + xposition %= fixedwidth; + if (yposition < 0) + yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight); + else if (yposition >= fixedheight) + yposition %= fixedheight; + + while (count-- && dest <= deststop) + { + // The loops here keep the texture coordinates within the texture. + // They will rarely iterate multiple times, and are cheaper than a modulo operation, + // even if using libdivide. + if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop + while (xposition < 0) + xposition += fixedwidth; + else + while (xposition >= fixedwidth) + xposition -= fixedwidth; + if (ystep < 0) + while (yposition < 0) + yposition += fixedheight; + else + while (yposition >= fixedheight) + yposition -= fixedheight; + + x = (xposition >> FRACBITS); + y = (yposition >> FRACBITS); + val = source[((y * ds_flatwidth) + x)]; + if (val != TRANSPARENTPIXEL) + *dest = colormap[val]; + dest++; + xposition += xstep; + yposition += ystep; + } +} + +/** \brief The R_DrawTranslucentSplat_NPO2_8 function + Just like R_DrawSplat_NPO2_8, but is translucent! +*/ +void R_DrawTranslucentSplat_NPO2_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + fixed_t x, y; + fixed_t fixedwidth, fixedheight; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + fixedwidth = ds_flatwidth << FRACBITS; + fixedheight = ds_flatheight << FRACBITS; + + // Fix xposition and yposition if they are out of bounds. + if (xposition < 0) + xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth); + else if (xposition >= fixedwidth) + xposition %= fixedwidth; + if (yposition < 0) + yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight); + else if (yposition >= fixedheight) + yposition %= fixedheight; + + while (count-- && dest <= deststop) + { + // The loops here keep the texture coordinates within the texture. + // They will rarely iterate multiple times, and are cheaper than a modulo operation, + // even if using libdivide. + if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop + while (xposition < 0) + xposition += fixedwidth; + else + while (xposition >= fixedwidth) + xposition -= fixedwidth; + if (ystep < 0) + while (yposition < 0) + yposition += fixedheight; + else + while (yposition >= fixedheight) + yposition -= fixedheight; + + x = (xposition >> FRACBITS); + y = (yposition >> FRACBITS); + val = source[((y * ds_flatwidth) + x)]; + if (val != TRANSPARENTPIXEL) + *dest = *(ds_transmap + (colormap[val] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } +} + +/** \brief The R_DrawTranslucentSpan_NPO2_8 function + Draws the actual span with translucency. +*/ +void R_DrawTranslucentSpan_NPO2_8 (void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + fixed_t x, y; + fixed_t fixedwidth, fixedheight; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + size_t count = (ds_x2 - ds_x1 + 1); + UINT32 val; + + xposition = ds_xfrac; yposition = ds_yfrac; + xstep = ds_xstep; ystep = ds_ystep; + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + + fixedwidth = ds_flatwidth << FRACBITS; + fixedheight = ds_flatheight << FRACBITS; + + // Fix xposition and yposition if they are out of bounds. + if (xposition < 0) + xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth); + else if (xposition >= fixedwidth) + xposition %= fixedwidth; + if (yposition < 0) + yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight); + else if (yposition >= fixedheight) + yposition %= fixedheight; + + while (count-- && dest <= deststop) + { + // The loops here keep the texture coordinates within the texture. + // They will rarely iterate multiple times, and are cheaper than a modulo operation, + // even if using libdivide. + if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop + while (xposition < 0) + xposition += fixedwidth; + else + while (xposition >= fixedwidth) + xposition -= fixedwidth; + if (ystep < 0) + while (yposition < 0) + yposition += fixedheight; + else + while (yposition >= fixedheight) + yposition -= fixedheight; + + x = (xposition >> FRACBITS); + y = (yposition >> FRACBITS); + val = ((y * ds_flatwidth) + x); + *dest = *(ds_transmap + (colormap[source[val]] << 8) + *dest); + dest++; + xposition += xstep; + yposition += ystep; + } +} + +#ifndef NOWATER +void R_DrawTranslucentWaterSpan_NPO2_8(void) +{ + fixed_t xposition; + fixed_t yposition; + fixed_t xstep, ystep; + fixed_t x, y; + fixed_t fixedwidth, fixedheight; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + UINT8 *dsrc; + const UINT8 *deststop = screens[0] + vid.rowbytes * vid.height; + + size_t count = (ds_x2 - ds_x1 + 1); + + xposition = ds_xfrac; yposition = (ds_yfrac + ds_waterofs); + xstep = ds_xstep; ystep = ds_ystep; + + source = ds_source; + colormap = ds_colormap; + dest = ylookup[ds_y] + columnofs[ds_x1]; + dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + + fixedwidth = ds_flatwidth << FRACBITS; + fixedheight = ds_flatheight << FRACBITS; + + // Fix xposition and yposition if they are out of bounds. + if (xposition < 0) + xposition = fixedwidth - ((UINT32)(fixedwidth - xposition) % fixedwidth); + else if (xposition >= fixedwidth) + xposition %= fixedwidth; + if (yposition < 0) + yposition = fixedheight - ((UINT32)(fixedheight - yposition) % fixedheight); + else if (yposition >= fixedheight) + yposition %= fixedheight; + + while (count-- && dest <= deststop) + { + // The loops here keep the texture coordinates within the texture. + // They will rarely iterate multiple times, and are cheaper than a modulo operation, + // even if using libdivide. + if (xstep < 0) // These if statements are hopefully hoisted by the compiler to above this loop + while (xposition < 0) + xposition += fixedwidth; + else + while (xposition >= fixedwidth) + xposition -= fixedwidth; + if (ystep < 0) + while (yposition < 0) + yposition += fixedheight; + else + while (yposition >= fixedheight) + yposition -= fixedheight; + + x = (xposition >> FRACBITS); + y = (yposition >> FRACBITS); + *dest++ = colormap[*(ds_transmap + (source[((y * ds_flatwidth) + x)] << 8) + *dsrc++)]; + xposition += xstep; + yposition += ystep; + } +} + +/** \brief The R_DrawTiltedTranslucentWaterSpan_NPO2_8 function + Like DrawTiltedTranslucentSpan_NPO2, but for water +*/ +void R_DrawTiltedTranslucentWaterSpan_NPO2_8(void) +{ + // x1, x2 = ds_x1, ds_x2 + int width = ds_x2 - ds_x1; + double iz, uz, vz; + UINT32 u, v; + int i; + + UINT8 *source; + UINT8 *colormap; + UINT8 *dest; + UINT8 *dsrc; + + double startz, startu, startv; + double izstep, uzstep, vzstep; + double endz, endu, endv; + UINT32 stepu, stepv; + + iz = ds_szp->z + ds_szp->y*(centery-ds_y) + ds_szp->x*(ds_x1-centerx); + + // Lighting is simple. It's just linear interpolation from start to end + { + float planelightfloat = PLANELIGHTFLOAT; + float lightstart, lightend; + + lightend = (iz + ds_szp->x*width) * planelightfloat; + lightstart = iz * planelightfloat; + + R_CalcTiltedLighting(FLOAT_TO_FIXED(lightstart), FLOAT_TO_FIXED(lightend)); + //CONS_Printf("tilted lighting %f to %f (foc %f)\n", lightstart, lightend, focallengthf); + } + + uz = ds_sup->z + ds_sup->y*(centery-ds_y) + ds_sup->x*(ds_x1-centerx); + vz = ds_svp->z + ds_svp->y*(centery-ds_y) + ds_svp->x*(ds_x1-centerx); + + dest = ylookup[ds_y] + columnofs[ds_x1]; + dsrc = screens[1] + (ds_y+ds_bgofs)*vid.width + ds_x1; + source = ds_source; + //colormap = ds_colormap; + +#if 0 // The "perfect" reference version of this routine. Pretty slow. + // Use it only to see how things are supposed to look. + i = 0; + do + { + double z = 1.f/iz; + u = (INT64)(uz*z) + viewx; + v = (INT64)(vz*z) + viewy; + + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); + } + dest++; + iz += ds_szp->x; + uz += ds_sup->x; + vz += ds_svp->x; + } while (--width >= 0); +#else +#define SPANSIZE 16 +#define INVSPAN 0.0625f + + startz = 1.f/iz; + startu = uz*startz; + startv = vz*startz; + + izstep = ds_szp->x * SPANSIZE; + uzstep = ds_sup->x * SPANSIZE; + vzstep = ds_svp->x * SPANSIZE; + //x1 = 0; + width++; + + while (width >= SPANSIZE) + { + iz += izstep; + uz += uzstep; + vz += vzstep; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + stepu = (INT64)((endu - startu) * INVSPAN); + stepv = (INT64)((endv - startv) * INVSPAN); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (i = SPANSIZE-1; i >= 0; i--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); + } + dest++; + u += stepu; + v += stepv; + } + startu = endu; + startv = endv; + width -= SPANSIZE; + } + if (width > 0) + { + if (width == 1) + { + u = (INT64)(startu); + v = (INT64)(startv); + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); + } + } + else + { + double left = width; + iz += ds_szp->x * left; + uz += ds_sup->x * left; + vz += ds_svp->x * left; + + endz = 1.f/iz; + endu = uz*endz; + endv = vz*endz; + left = 1.f/left; + stepu = (INT64)((endu - startu) * left); + stepv = (INT64)((endv - startv) * left); + u = (INT64)(startu) + viewx; + v = (INT64)(startv) + viewy; + + for (; width != 0; width--) + { + colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps); + // Lactozilla: Non-powers-of-two + { + fixed_t x = (((fixed_t)u-viewx) >> FRACBITS); + fixed_t y = (((fixed_t)v-viewy) >> FRACBITS); + + // Carefully align all of my Friends. + if (x < 0) + x = ds_flatwidth - ((UINT32)(ds_flatwidth - x) % ds_flatwidth); + if (y < 0) + y = ds_flatheight - ((UINT32)(ds_flatheight - y) % ds_flatheight); + + x %= ds_flatwidth; + y %= ds_flatheight; + + *dest = *(ds_transmap + (colormap[source[((y * ds_flatwidth) + x)]] << 8) + *dsrc++); + } + dest++; + u += stepu; + v += stepv; + } + } + } +#endif +} +#endif // NOWATER diff --git a/src/r_local.h b/src/r_local.h index 1d3187750..4ccb766cf 100644 --- a/src/r_local.h +++ b/src/r_local.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -31,6 +31,7 @@ #include "r_plane.h" #include "r_sky.h" #include "r_data.h" +#include "r_textures.h" #include "r_things.h" #include "r_draw.h" diff --git a/src/r_main.c b/src/r_main.c index 4cdfc470e..8e05b8d27 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,6 +19,7 @@ #include "r_local.h" #include "r_splats.h" // faB(21jan): testing #include "r_sky.h" +#include "hu_stuff.h" #include "st_stuff.h" #include "p_local.h" #include "keys.h" @@ -28,8 +29,12 @@ #include "d_main.h" #include "v_video.h" #include "p_spec.h" // skyboxmo +#include "p_setup.h" #include "z_zone.h" #include "m_random.h" // quake camera shake +#include "r_portal.h" +#include "r_main.h" +#include "i_system.h" // I_GetTimeMicros #include "doomstat.h" // MAXSPLITSCREENPLAYERS #ifdef HWRENDER @@ -55,9 +60,9 @@ size_t validcount = 1; INT32 centerx, centery; fixed_t centerxfrac, centeryfrac; -fixed_t projection; -fixed_t projectiony; // aspect ratio -fixed_t fovtan; // field of view +fixed_t projection[MAXSPLITSCREENPLAYERS]; +fixed_t projectiony[MAXSPLITSCREENPLAYERS]; // aspect ratio +fixed_t fovtan[MAXSPLITSCREENPLAYERS]; // field of view // just for profiling purposes size_t framecount; @@ -68,63 +73,53 @@ fixed_t viewx, viewy, viewz; angle_t viewangle, aimingangle; UINT8 viewssnum; fixed_t viewcos, viewsin; -boolean viewsky, skyVisible; -boolean skyVisiblePerPlayer[MAXSPLITSCREENPLAYERS]; // saved values of skyVisible for each splitscreen player sector_t *viewsector; player_t *viewplayer; +mobj_t *r_viewmobj; int r_splitscreen; -// PORTALS! -// You can thank and/or curse JTE for these. -UINT8 portalrender; -sector_t *portalcullsector; -typedef struct portal_pair -{ - INT32 line1; - INT32 line2; - UINT8 pass; - struct portal_pair *next; - - fixed_t viewx; - fixed_t viewy; - fixed_t viewz; - angle_t viewangle; - - INT32 start; - INT32 end; - INT16 *ceilingclip; - INT16 *floorclip; - fixed_t *frontscale; -} portal_pair; -portal_pair *portal_base, *portal_cap; -line_t *portalclipline; -INT32 portalclipstart, portalclipend; - // // precalculated math tables // -angle_t clipangle; -angle_t doubleclipangle; +angle_t clipangle[MAXSPLITSCREENPLAYERS]; +angle_t doubleclipangle[MAXSPLITSCREENPLAYERS]; // The viewangletox[viewangle + FINEANGLES/4] lookup // maps the visible view angles to screen X coordinates, // flattening the arc to a flat projection plane. // There will be many angles mapped to the same X. -INT32 viewangletox[FINEANGLES/2]; +INT32 viewangletox[MAXSPLITSCREENPLAYERS][FINEANGLES/2]; // The xtoviewangleangle[] table maps a screen pixel // to the lowest viewangle that maps back to x ranges // from clipangle to -clipangle. -angle_t xtoviewangle[MAXVIDWIDTH+1]; +angle_t xtoviewangle[MAXSPLITSCREENPLAYERS][MAXVIDWIDTH+1]; lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; lighttable_t *scalelightfixed[MAXLIGHTSCALE]; lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; // Hack to support extra boom colormaps. -size_t num_extra_colormaps; -extracolormap_t extra_colormaps[MAXCOLORMAPS]; +extracolormap_t *extra_colormaps = NULL; + +// Render stats +int ps_prevframetime = 0; +int ps_rendercalltime = 0; +int ps_uitime = 0; +int ps_swaptime = 0; + +int ps_bsptime = 0; + +int ps_sw_spritecliptime = 0; +int ps_sw_portaltime = 0; +int ps_sw_planetime = 0; +int ps_sw_maskedtime = 0; + +int ps_numbspcalls = 0; +int ps_numsprites = 0; +int ps_numdrawnodes = 0; +int ps_numpolyobjects = 0; static CV_PossibleValue_t drawdist_cons_t[] = { /*{256, "256"},*/ {512, "512"}, {768, "768"}, @@ -132,16 +127,12 @@ static CV_PossibleValue_t drawdist_cons_t[] = { {3072, "3072"}, {4096, "4096"}, {6144, "6144"}, {8192, "8192"}, {0, "Infinite"}, {0, NULL}}; -//static CV_PossibleValue_t precipdensity_cons_t[] = {{0, "None"}, {1, "Light"}, {2, "Moderate"}, {4, "Heavy"}, {6, "Thick"}, {8, "V.Thick"}, {0, NULL}}; - static CV_PossibleValue_t drawdist_precip_cons_t[] = { {256, "256"}, {512, "512"}, {768, "768"}, {1024, "1024"}, {1536, "1536"}, {2048, "2048"}, {0, "None"}, {0, NULL}}; -static CV_PossibleValue_t fov_cons_t[] = {{5*FRACUNIT, "MIN"}, {178*FRACUNIT, "MAX"}, {0, NULL}}; - -//static CV_PossibleValue_t precipdensity_cons_t[] = {{0, "None"}, {1, "Light"}, {2, "Moderate"}, {4, "Heavy"}, {6, "Thick"}, {8, "V.Thick"}, {0, NULL}}; +static CV_PossibleValue_t fov_cons_t[] = {{60*FRACUNIT, "MIN"}, {179*FRACUNIT, "MAX"}, {0, NULL}}; static CV_PossibleValue_t translucenthud_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; static CV_PossibleValue_t maxportals_cons_t[] = {{0, "MIN"}, {12, "MAX"}, {0, NULL}}; // lmao rendering 32 portals, you're a card static CV_PossibleValue_t homremoval_cons_t[] = {{0, "No"}, {1, "Yes"}, {2, "Flash"}, {0, NULL}}; @@ -156,32 +147,37 @@ void SendWeaponPref2(void); void SendWeaponPref3(void); void SendWeaponPref4(void); -consvar_t cv_tailspickup = {"tailspickup", "On", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chasecam = {"chasecam", "On", CV_CALL, CV_OnOff, ChaseCam_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chasecam2 = {"chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chasecam3 = {"chasecam3", "On", CV_CALL, CV_OnOff, ChaseCam3_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chasecam4 = {"chasecam4", "On", CV_CALL, CV_OnOff, ChaseCam4_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_tailspickup = CVAR_INIT ("tailspickup", "On", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL); +consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("chasecam", "On", CV_CALL, CV_OnOff, ChaseCam_OnChange), + CVAR_INIT ("chasecam2", "On", CV_CALL, CV_OnOff, ChaseCam2_OnChange), + CVAR_INIT ("chasecam3", "On", CV_CALL, CV_OnOff, ChaseCam3_OnChange), + CVAR_INIT ("chasecam4", "On", CV_CALL, CV_OnOff, ChaseCam4_OnChange) +}; -consvar_t cv_shadow = {"shadow", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_skybox = {"skybox", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_soniccd = {"soniccd", "Off", CV_NETVAR|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_allowmlook = {"allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_showhud = {"showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_translucenthud = {"translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_shadow = CVAR_INIT ("shadow", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_skybox = CVAR_INIT ("skybox", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_ffloorclip = CVAR_INIT ("ffloorclip", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_allowmlook = CVAR_INIT ("allowmlook", "Yes", CV_NETVAR, CV_YesNo, NULL); +consvar_t cv_showhud = CVAR_INIT ("showhud", "Yes", CV_CALL, CV_YesNo, R_SetViewSize); +consvar_t cv_translucenthud = CVAR_INIT ("translucenthud", "10", CV_SAVE, translucenthud_cons_t, NULL); -consvar_t cv_drawdist = {"drawdist", "8192", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_drawdist = CVAR_INIT ("drawdist", "8192", CV_SAVE, drawdist_cons_t, NULL); +consvar_t cv_drawdist_precip = CVAR_INIT ("drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL); -//consvar_t cv_drawdist_nights = {"drawdist_nights", "2048", CV_SAVE, drawdist_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_drawdist_precip = {"drawdist_precip", "1024", CV_SAVE, drawdist_precip_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -//consvar_t cv_precipdensity = {"precipdensity", "Moderate", CV_SAVE, precipdensity_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - -// cap fov, fov too high tears software apart. -consvar_t cv_fov = {"fov", "90", CV_FLOAT|CV_CALL|CV_SAVE, fov_cons_t, Fov_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_fov[MAXSPLITSCREENPLAYERS] = { + CVAR_INIT ("fov", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange), + CVAR_INIT ("fov2", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange), + CVAR_INIT ("fov3", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange), + CVAR_INIT ("fov4", "90", CV_FLOAT|CV_CALL, fov_cons_t, Fov_OnChange) +}; // Okay, whoever said homremoval causes a performance hit should be shot. -consvar_t cv_homremoval = {"homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_homremoval = CVAR_INIT ("homremoval", "Yes", CV_SAVE, homremoval_cons_t, NULL); -consvar_t cv_maxportals = {"maxportals", "2", CV_SAVE, maxportals_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_maxportals = CVAR_INIT ("maxportals", "2", CV_SAVE, maxportals_cons_t, NULL); + +consvar_t cv_renderstats = CVAR_INIT ("renderstats", "Off", 0, CV_OnOff, NULL); void SplitScreen_OnChange(void) { @@ -236,43 +232,27 @@ void SplitScreen_OnChange(void) } static void Fov_OnChange(void) { - // Shouldn't be needed with render parity? - //if ((netgame || multiplayer) && !cv_debug && cv_fov.value != 90*FRACUNIT) - // CV_Set(&cv_fov, cv_fov.defaultvalue); - R_SetViewSize(); } static void ChaseCam_OnChange(void) { - /*if (!cv_chasecam.value || !cv_useranalog.value) - CV_SetValue(&cv_analog, 0); - else - CV_SetValue(&cv_analog, 1);*/ + ; } static void ChaseCam2_OnChange(void) { - /*if (!cv_chasecam2.value || !cv_useranalog2.value) - CV_SetValue(&cv_analog2, 0); - else - CV_SetValue(&cv_analog2, 1);*/ + ; } static void ChaseCam3_OnChange(void) { - /*if (!cv_chasecam3.value || !cv_useranalog3.value) - CV_SetValue(&cv_analog3, 0); - else - CV_SetValue(&cv_analog3, 1);*/ + ; } static void ChaseCam4_OnChange(void) { - /*if (!cv_chasecam4.value || !cv_useranalog4.value) - CV_SetValue(&cv_analog4, 0); - else - CV_SetValue(&cv_analog4, 1);*/ + ; } // @@ -352,6 +332,24 @@ angle_t R_PointToAngle(fixed_t x, fixed_t y) 0; } +// This version uses 64-bit variables to avoid overflows with large values. +// Currently used only by OpenGL rendering. +angle_t R_PointToAngle64(INT64 x, INT64 y) +{ + return (y -= viewy, (x -= viewx) || y) ? + x >= 0 ? + y >= 0 ? + (x > y) ? tantoangle[SlopeDivEx(y,x)] : // octant 0 + ANGLE_90-tantoangle[SlopeDivEx(x,y)] : // octant 1 + x > (y = -y) ? 0-tantoangle[SlopeDivEx(y,x)] : // octant 8 + ANGLE_270+tantoangle[SlopeDivEx(x,y)] : // octant 7 + y >= 0 ? (x = -x) > y ? ANGLE_180-tantoangle[SlopeDivEx(y,x)] : // octant 3 + ANGLE_90 + tantoangle[SlopeDivEx(x,y)] : // octant 2 + (x = -x) > (y = -y) ? ANGLE_180+tantoangle[SlopeDivEx(y,x)] : // octant 4 + ANGLE_270-tantoangle[SlopeDivEx(x,y)] : // octant 5 + 0; +} + angle_t R_PointToAngle2(fixed_t pviewx, fixed_t pviewy, fixed_t x, fixed_t y) { return (y -= pviewy, (x -= pviewx) || y) ? @@ -439,7 +437,8 @@ fixed_t R_ScaleFromGlobalAngle(angle_t visangle) angle_t angleb = ANGLE_90 + (visangle-rw_normalangle); fixed_t den = FixedMul(rw_distance, FINESINE(anglea>>ANGLETOFINESHIFT)); // proff 11/06/98: Changed for high-res - fixed_t num = FixedMul(projectiony, FINESINE(angleb>>ANGLETOFINESHIFT)); + fixed_t num = FixedMul(projectiony[viewssnum], + FINESINE(angleb>>ANGLETOFINESHIFT)); if (den > num>>16) { @@ -497,7 +496,7 @@ boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixe // // R_InitTextureMapping // -static void R_InitTextureMapping(void) +static void R_InitTextureMapping(int s) { INT32 i; INT32 x; @@ -510,18 +509,16 @@ static void R_InitTextureMapping(void) // // Calc focallength // so FIELDOFVIEW angles covers SCREENWIDTH. - focallength = FixedDiv(projection, - FINETANGENT(FINEANGLES/4+/*cv_fov.value*/ FIELDOFVIEW/2)); + focallength = FixedDiv(projection[s], + FINETANGENT(FINEANGLES/4+FIELDOFVIEW/2)); -#ifdef ESLOPE - focallengthf = FIXED_TO_FLOAT(focallength); -#endif + focallengthf[s] = FIXED_TO_FLOAT(focallength); for (i = 0; i < FINEANGLES/2; i++) { - if (FINETANGENT(i) > fovtan*2) + if (FINETANGENT(i) > fovtan[s]*2) t = -1; - else if (FINETANGENT(i) < -fovtan*2) + else if (FINETANGENT(i) < -fovtan[s]*2) t = viewwidth+1; else { @@ -533,7 +530,7 @@ static void R_InitTextureMapping(void) else if (t > viewwidth+1) t = viewwidth+1; } - viewangletox[i] = t; + viewangletox[s][i] = t; } // Scan viewangletox[] to generate xtoviewangle[]: @@ -542,22 +539,22 @@ static void R_InitTextureMapping(void) for (x = 0; x <= viewwidth;x++) { i = 0; - while (viewangletox[i] > x) + while (viewangletox[s][i] > x) i++; - xtoviewangle[x] = (i<>= ANGLETOFINESHIFT; + rollangle = ((rollangle+2) & ~3) & FINEMASK; // Limit the distinct number of angles to reduce recalcs from angles changing a lot. + +#ifdef WOUGHMP_WOUGHMP + fisheye &= ~0x7FF; // Same +#endif + + if (r_splitscreen > 0) + { + height /= 2; + + if (r_splitscreen > 1) + { + width /= 2; + } + } + + halfwidth = width / 2; + halfheight = height / 2; + + if (rollangle == v->rollangle && +#ifdef WOUGHMP_WOUGHMP + fisheye == v->fisheye && +#endif + v->scrmapsize == width * height) + return; // No change + + v->rollangle = rollangle; +#ifdef WOUGHMP_WOUGHMP + v->fisheye = fisheye; +#endif + + if (v->rollangle == 0 +#ifdef WOUGHMP_WOUGHMP + && v->fisheye == 0 +#endif + ) + { + v->use = false; + v->x1 = 0; + if (v->zoomneeded != FRACUNIT) + R_SetViewSize(); + v->zoomneeded = FRACUNIT; + + return; + } + + if (v->scrmapsize != width * height) + { + if (v->scrmap) + free(v->scrmap); + v->scrmap = malloc(width * height * sizeof(INT32)); + v->scrmapsize = width * height; + } + + temp = FINECOSINE(rollangle); + rollcos = FIXED_TO_FLOAT(temp); + temp = FINESINE(rollangle); + rollsin = FIXED_TO_FLOAT(temp); + + // Calculate maximum zoom needed + x1 = (width * fabsf(rollcos) + height * fabsf(rollsin)) / width; + y1 = (height * fabsf(rollcos) + width * fabsf(rollsin)) / height; + +#ifdef WOUGHMP_WOUGHMP + if (fisheye) + { + float f = FIXED_TO_FLOAT(fisheye); + for (vx = 0; vx <= halfwidth; vx++) + fisheyemap[vx] = 1.0f / cos(atan(vx * f / halfwidth)); + + f = cos(atan(f)); + if (f < 1.0f) + { + x1 /= f; + y1 /= f; + } + } +#endif + + temp = max(x1, y1)*FRACUNIT; + if (temp < FRACUNIT) + temp = FRACUNIT; + else + temp |= 0x3FFF; // Limit how many times the viewport needs to be recalculated + + //CONS_Printf("Setting zoom to %f\n", FIXED_TO_FLOAT(temp)); + + if (temp != v->zoomneeded) + { + v->zoomneeded = temp; + R_SetViewSize(); + } + + zoomfactor = FIXED_TO_FLOAT(v->zoomneeded); + + realend = end = width * height - 1; + + if (r_splitscreen > 1) + { + realend = ( realend << 1 ) - width; + } + + pos = 0; + + // Pre-multiply rollcos and rollsin to use for positional stuff + rollcos /= zoomfactor; + rollsin /= zoomfactor; + + x1 = -(halfwidth * rollcos - halfheight * rollsin); + y1 = -(halfheight * rollcos + halfwidth * rollsin); + +#ifdef WOUGHMP_WOUGHMP + if (fisheye) + v->x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin)) * fisheyemap[halfwidth]); + else +#endif + v->x1 = (INT32)(halfwidth - (halfwidth * fabsf(rollcos) + halfheight * fabsf(rollsin))); + //CONS_Printf("saving %d cols\n", v->x1); + + // Set ceilingclip and floorclip + for (vx = 0; vx < width; vx++) + { + v->ceilingclip[vx] = height; + v->floorclip[vx] = -1; + } + x2 = x1; + y2 = y1; + for (vx = 0; vx < width; vx++) + { + INT16 xa, ya, xb, yb; + xa = x2+halfwidth; + ya = y2+halfheight-1; + xb = width-1-xa; + yb = height-1-ya; + + v->ceilingclip[xa] = min(v->ceilingclip[xa], ya); + v->floorclip[xa] = max(v->floorclip[xa], ya); + v->ceilingclip[xb] = min(v->ceilingclip[xb], yb); + v->floorclip[xb] = max(v->floorclip[xb], yb); + x2 += rollcos; + y2 += rollsin; + } + x2 = x1; + y2 = y1; + for (vy = 0; vy < height; vy++) + { + INT16 xa, ya, xb, yb; + xa = x2+halfwidth; + ya = y2+halfheight; + xb = width-1-xa; + yb = height-1-ya; + + v->ceilingclip[xa] = min(v->ceilingclip[xa], ya); + v->floorclip[xa] = max(v->floorclip[xa], ya); + v->ceilingclip[xb] = min(v->ceilingclip[xb], yb); + v->floorclip[xb] = max(v->floorclip[xb], yb); + x2 -= rollsin; + y2 += rollcos; + } + + //CONS_Printf("Top left corner is %f %f\n", x1, y1); + +#ifdef WOUGHMP_WOUGHMP + if (fisheye) + { + for (vy = 0; vy < halfheight; vy++) + { + x2 = x1; + y2 = y1; + x1 -= rollsin; + y1 += rollcos; + + for (vx = 0; vx < width; vx++) + { + usedx = halfwidth + x2*fisheyemap[(int) floorf(fabsf(y2*zoomfactor))]; + usedy = halfheight + y2*fisheyemap[(int) floorf(fabsf(x2*zoomfactor))]; + + usedpos = usedx + usedy*width; + + v->scrmap[pos] = usedpos; + v->scrmap[end-pos] = end-usedpos; + + x2 += rollcos; + y2 += rollsin; + pos++; + } + } + } + else + { +#endif + x1 += halfwidth; + y1 += halfheight; + + for (vy = 0; vy < halfheight; vy++) + { + x2 = x1; + y2 = y1; + x1 -= rollsin; + y1 += rollcos; + + for (vx = 0; vx < width; vx++) + { + usedx = x2; + usedy = y2; + + usedpos = usedx + usedy * vid.width; + + v->scrmap[pos] = usedpos; + v->scrmap[end-pos] = realend-usedpos; + + x2 += rollcos; + y2 += rollsin; + pos++; + } + } +#ifdef WOUGHMP_WOUGHMP + } +#endif + + v->use = true; +} + +void R_ApplyViewMorph(int s) +{ + UINT8 *tmpscr = screens[4]; + UINT8 *srcscr = screens[0]; + INT32 width = vid.width; + INT32 height = vid.height; + INT32 p; + INT32 end; + + if (!viewmorph[s].use) + return; + + if (r_splitscreen == 1) + { + height /= 2; + + if (s == 1) + { + srcscr += vid.width * height; + } + } + else if (r_splitscreen > 1) + { + width /= 2; + height /= 2; + + if (s % 2) + { + srcscr += width; + } + + if (s > 1) + { + srcscr += vid.width * height; + } + } + + end = width * height; + +#if 0 + if (cv_debug & DBG_VIEWMORPH) + { + UINT8 border = 32; + UINT8 grid = 160; + INT32 ws = vid.width / 4; + INT32 hs = vid.width * (vid.height / 4); + + memcpy(tmpscr, srcscr, vid.width*vid.height); + for (p = 0; p < vid.width; p++) + { + tmpscr[viewmorph.scrmap[p]] = border; + tmpscr[viewmorph.scrmap[p + hs]] = grid; + tmpscr[viewmorph.scrmap[p + hs*2]] = grid; + tmpscr[viewmorph.scrmap[p + hs*3]] = grid; + tmpscr[viewmorph.scrmap[end - 1 - p]] = border; + } + for (p = vid.width; p < end; p += vid.width) + { + tmpscr[viewmorph.scrmap[p]] = border; + tmpscr[viewmorph.scrmap[p + ws]] = grid; + tmpscr[viewmorph.scrmap[p + ws*2]] = grid; + tmpscr[viewmorph.scrmap[p + ws*3]] = grid; + tmpscr[viewmorph.scrmap[end - 1 - p]] = border; + } + } + else +#endif + { + for (p = 0; p < end; p++) + { + tmpscr[p] = srcscr[viewmorph[s].scrmap[p]]; + } + } + + VID_BlitLinearScreen(tmpscr, srcscr, + width*vid.bpp, height, width*vid.bpp, vid.width); +} + // // R_SetViewSize @@ -626,6 +983,7 @@ void R_ExecuteSetViewSize(void) INT32 level; INT32 startmapl; angle_t fov; + int s; setsizeneeded = false; @@ -654,17 +1012,33 @@ void R_ExecuteSetViewSize(void) centerxfrac = centerx<> ANGLETOFINESHIFT); - if (r_splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view - fovtan = 17*fovtan/10; + for (s = 0; s <= r_splitscreen; ++s) + { + fov = FixedAngle(cv_fov[s].value/2) + ANGLE_90; + fovtan[s] = FixedMul(FINETANGENT(fov >> ANGLETOFINESHIFT), viewmorph[s].zoomneeded); + if (r_splitscreen == 1) // Splitscreen FOV should be adjusted to maintain expected vertical view + fovtan[s] = 17*fovtan[s]/10; - projection = projectiony = FixedDiv(centerxfrac, fovtan); + projection[s] = projectiony[s] = FixedDiv(centerxfrac, fovtan[s]); + + R_InitTextureMapping(s); + + // planes + if (rendermode == render_soft) + { + // this is only used for planes rendering in software mode + j = viewheight*16; + for (i = 0; i < j; i++) + { + dy = ((i - viewheight*8)<numlines; i++) - //if (R_PointOnSegSide(x, y, &segs[ret->firstline + i])) -- breaks in ogl because polyvertex_t cast over vertex pointers - if (P_PointOnLineSide(x, y, segs[ret->firstline + i].linedef) != segs[ret->firstline + i].side) + for (i = 0, seg = &segs[ret->firstline]; i < ret->numlines; i++, seg++) + { + if (seg->glseg) + continue; + + //if (R_PointOnSegSide(x, y, seg)) -- breaks in ogl because polyvertex_t cast over vertex pointers + if (P_PointOnLineSide(x, y, seg->linedef) != seg->side) return 0; + } return ret; } @@ -792,37 +1159,146 @@ subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y) // R_SetupFrame // -static mobj_t *viewmobj; - // recalc necessary stuff for mouseaiming // slopes are already calculated for the full possible view (which is 4*viewheight). // 18/08/18: (No it's actually 16*viewheight, thanks Jimita for finding this out) -static void R_SetupFreelook(void) +static void R_SetupFreelook(player_t *player, boolean skybox) { INT32 dy = 0; +#ifndef HWRENDER + (void)player; + (void)skybox; +#endif + // clip it in the case we are looking a hardware 90 degrees full aiming // (lmps, network and use F12...) if (rendermode == render_soft #ifdef HWRENDER - || cv_grshearing.value + || (rendermode == render_opengl + && (cv_glshearing.value == 1 + || (cv_glshearing.value == 2 && R_IsViewpointThirdPerson(player, skybox)))) #endif - ) + ) + { G_SoftwareClipAimingPitch((INT32 *)&aimingangle); + } if (rendermode == render_soft) { - dy = (AIMINGTODY(aimingangle)/fovtan) * viewwidth/BASEVIDWIDTH; - yslope = &yslopetab[viewheight*8 - (viewheight/2 + dy)]; + dy = (AIMINGTODY(aimingangle)>>FRACBITS) * viewwidth/BASEVIDWIDTH; + yslope = &yslopetab[viewssnum][viewheight*8 - (viewheight/2 + dy)]; } + centery = (viewheight/2) + dy; centeryfrac = centery< r_splitscreen) + return; // shouldn't be possible, but just in case + + if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) + chasecam = true; // force chasecam on + else if (player->spectator) // no spectator chasecam + chasecam = false; // force chasecam off + + if (chasecam && !thiscam->chase) + { + P_ResetCamera(player, thiscam); + thiscam->chase = true; + } + else if (!chasecam) + thiscam->chase = false; + + if (player->awayviewtics) + { + // cut-away view stuff + r_viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN + I_Assert(r_viewmobj != NULL); + viewz = r_viewmobj->z + 20*FRACUNIT; + aimingangle = player->awayviewaiming; + viewangle = r_viewmobj->angle; + } + else if (!player->spectator && chasecam) + // use outside cam view + { + r_viewmobj = NULL; + viewz = thiscam->z + (thiscam->height>>1); + aimingangle = thiscam->aiming; + viewangle = thiscam->angle; + } + else + // use the player's eyes view + { + viewz = player->viewz; + + r_viewmobj = player->mo; + I_Assert(r_viewmobj != NULL); + + aimingangle = player->aiming; + viewangle = r_viewmobj->angle; + + if (!demo.playback && player->playerstate != PST_DEAD) + { + viewangle = localangle[i]; // WARNING: camera uses this + aimingangle = localaiming[i]; + } + } + viewz += quake.z; + + viewplayer = player; + + if (chasecam && !player->awayviewtics && !player->spectator) + { + viewx = thiscam->x; + viewy = thiscam->y; + viewx += quake.x; + viewy += quake.y; + + if (thiscam->subsector) + viewsector = thiscam->subsector->sector; + else + viewsector = R_PointInSubsector(viewx, viewy)->sector; + } + else + { + viewx = r_viewmobj->x; + viewy = r_viewmobj->y; + viewx += quake.x; + viewy += quake.y; + + if (r_viewmobj->subsector) + viewsector = r_viewmobj->subsector->sector; + else + viewsector = R_PointInSubsector(viewx, viewy)->sector; + } + + viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); + viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); + + R_SetupFreelook(player, false); +} + void R_SkyboxFrame(player_t *player) { camera_t *thiscam = &camera[0]; - UINT8 i; + UINT8 i = 0; if (r_splitscreen) { @@ -834,16 +1310,20 @@ void R_SkyboxFrame(player_t *player) break; } } + + if (i > r_splitscreen) + { + i = 0; + } } // cut-away view stuff - viewsky = true; - viewmobj = skyboxmo[0]; + r_viewmobj = skyboxmo[0]; #ifdef PARANOIA - if (!viewmobj) + if (!r_viewmobj) { const size_t playeri = (size_t)(player - players); - I_Error("R_SkyboxFrame: viewmobj null (player %s)", sizeu1(playeri)); + I_Error("R_SkyboxFrame: r_viewmobj null (player %s)", sizeu1(playeri)); } #endif if (player->awayviewtics) @@ -862,331 +1342,139 @@ void R_SkyboxFrame(player_t *player) viewangle = player->mo->angle; if (/*!demo.playback && */player->playerstate != PST_DEAD) { - if (player == &players[consoleplayer]) - { - viewangle = localangle[0]; // WARNING: camera uses this - aimingangle = localaiming[0]; - } - else if (splitscreen) - { - for (i = 1; i <= splitscreen; i++) - { - if (player == &players[g_localplayers[i]]) - { - viewangle = localangle[i]; - aimingangle = localaiming[i]; - break; - } - } - } + viewangle = localangle[i]; + aimingangle = localaiming[i]; } } - viewangle += viewmobj->angle; + viewangle += r_viewmobj->angle; viewplayer = player; - viewx = viewmobj->x; - viewy = viewmobj->y; - viewz = 0; - if (viewmobj->spawnpoint) - viewz = ((fixed_t)viewmobj->spawnpoint->angle)<x; + viewy = r_viewmobj->y; + viewz = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle! if (mapheaderinfo[gamemap-1]) { mapheader_t *mh = mapheaderinfo[gamemap-1]; - if (player->awayviewtics) - { - if (skyboxmo[1]) - { - fixed_t x = 0, y = 0; - if (mh->skybox_scalex > 0) - x = (player->awayviewmobj->x - skyboxmo[1]->x) / mh->skybox_scalex; - else if (mh->skybox_scalex < 0) - x = (player->awayviewmobj->x - skyboxmo[1]->x) * -mh->skybox_scalex; + vector3_t campos = {0,0,0}; // Position of player's actual view point - if (mh->skybox_scaley > 0) - y = (player->awayviewmobj->y - skyboxmo[1]->y) / mh->skybox_scaley; - else if (mh->skybox_scaley < 0) - y = (player->awayviewmobj->y - skyboxmo[1]->y) * -mh->skybox_scaley; - - if (viewmobj->angle == 0) - { - viewx += x; - viewy += y; - } - else if (viewmobj->angle == ANGLE_90) - { - viewx -= y; - viewy += x; - } - else if (viewmobj->angle == ANGLE_180) - { - viewx -= x; - viewy -= y; - } - else if (viewmobj->angle == ANGLE_270) - { - viewx += y; - viewy -= x; - } - else - { - angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT; - viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); - viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); - } - } - if (mh->skybox_scalez > 0) - viewz += (player->awayviewmobj->z + 20*FRACUNIT) / mh->skybox_scalez; - else if (mh->skybox_scalez < 0) - viewz += (player->awayviewmobj->z + 20*FRACUNIT) * -mh->skybox_scalez; + if (player->awayviewtics) { + campos.x = player->awayviewmobj->x; + campos.y = player->awayviewmobj->y; + campos.z = player->awayviewmobj->z + 20*FRACUNIT; + } else if (thiscam->chase) { + campos.x = thiscam->x; + campos.y = thiscam->y; + campos.z = thiscam->z + (thiscam->height>>1); + } else { + campos.x = player->mo->x; + campos.y = player->mo->y; + campos.z = player->viewz; } - else if (thiscam->chase) + + // Earthquake effects should be scaled in the skybox + // (if an axis isn't used, the skybox won't shake in that direction) + campos.x += quake.x; + campos.y += quake.y; + campos.z += quake.z; + + if (skyboxmo[1]) // Is there a viewpoint? { - if (skyboxmo[1]) + fixed_t x = 0, y = 0; + if (mh->skybox_scalex > 0) + x = (campos.x - skyboxmo[1]->x) / mh->skybox_scalex; + else if (mh->skybox_scalex < 0) + x = (campos.x - skyboxmo[1]->x) * -mh->skybox_scalex; + + if (mh->skybox_scaley > 0) + y = (campos.y - skyboxmo[1]->y) / mh->skybox_scaley; + else if (mh->skybox_scaley < 0) + y = (campos.y - skyboxmo[1]->y) * -mh->skybox_scaley; + + if (r_viewmobj->angle == 0) { - fixed_t x = 0, y = 0; - if (mh->skybox_scalex > 0) - x = (thiscam->x - skyboxmo[1]->x) / mh->skybox_scalex; - else if (mh->skybox_scalex < 0) - x = (thiscam->x - skyboxmo[1]->x) * -mh->skybox_scalex; - - if (mh->skybox_scaley > 0) - y = (thiscam->y - skyboxmo[1]->y) / mh->skybox_scaley; - else if (mh->skybox_scaley < 0) - y = (thiscam->y - skyboxmo[1]->y) * -mh->skybox_scaley; - - if (viewmobj->angle == 0) - { - viewx += x; - viewy += y; - } - else if (viewmobj->angle == ANGLE_90) - { - viewx -= y; - viewy += x; - } - else if (viewmobj->angle == ANGLE_180) - { - viewx -= x; - viewy -= y; - } - else if (viewmobj->angle == ANGLE_270) - { - viewx += y; - viewy -= x; - } - else - { - angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT; - viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); - viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); - } + viewx += x; + viewy += y; } - if (mh->skybox_scalez > 0) - viewz += (thiscam->z + (thiscam->height>>1)) / mh->skybox_scalez; - else if (mh->skybox_scalez < 0) - viewz += (thiscam->z + (thiscam->height>>1)) * -mh->skybox_scalez; - } - else - { - if (skyboxmo[1]) + else if (r_viewmobj->angle == ANGLE_90) { - fixed_t x = 0, y = 0; - if (mh->skybox_scalex > 0) - x = (player->mo->x - skyboxmo[1]->x) / mh->skybox_scalex; - else if (mh->skybox_scalex < 0) - x = (player->mo->x - skyboxmo[1]->x) * -mh->skybox_scalex; - if (mh->skybox_scaley > 0) - y = (player->mo->y - skyboxmo[1]->y) / mh->skybox_scaley; - else if (mh->skybox_scaley < 0) - y = (player->mo->y - skyboxmo[1]->y) * -mh->skybox_scaley; - - if (viewmobj->angle == 0) - { - viewx += x; - viewy += y; - } - else if (viewmobj->angle == ANGLE_90) - { - viewx -= y; - viewy += x; - } - else if (viewmobj->angle == ANGLE_180) - { - viewx -= x; - viewy -= y; - } - else if (viewmobj->angle == ANGLE_270) - { - viewx += y; - viewy -= x; - } - else - { - angle_t ang = viewmobj->angle>>ANGLETOFINESHIFT; - viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); - viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); - } + viewx -= y; + viewy += x; + } + else if (r_viewmobj->angle == ANGLE_180) + { + viewx -= x; + viewy -= y; + } + else if (r_viewmobj->angle == ANGLE_270) + { + viewx += y; + viewy -= x; + } + else + { + angle_t ang = r_viewmobj->angle>>ANGLETOFINESHIFT; + viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); + viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); } - if (mh->skybox_scalez > 0) - viewz += player->viewz / mh->skybox_scalez; - else if (mh->skybox_scalez < 0) - viewz += player->viewz * -mh->skybox_scalez; } + if (mh->skybox_scalez > 0) + viewz += campos.z / mh->skybox_scalez; + else if (mh->skybox_scalez < 0) + viewz += campos.z * -mh->skybox_scalez; } - if (viewmobj->subsector) - viewsector = viewmobj->subsector->sector; + if (r_viewmobj->subsector) + viewsector = r_viewmobj->subsector->sector; else viewsector = R_PointInSubsector(viewx, viewy)->sector; viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - R_SetupFreelook(); + R_SetupFreelook(player, true); } -void R_SetupFrame(player_t *player, boolean skybox) +boolean R_ViewpointHasChasecam(player_t *player) { - camera_t *thiscam; boolean chasecam = false; + UINT8 i; - if (r_splitscreen > 2 && player == &players[displayplayers[3]]) + for (i = 0; i <= splitscreen; i++) { - thiscam = &camera[3]; - chasecam = (cv_chasecam4.value != 0); - } - else if (r_splitscreen > 1 && player == &players[displayplayers[2]]) - { - thiscam = &camera[2]; - chasecam = (cv_chasecam3.value != 0); - } - else if (r_splitscreen && player == &players[displayplayers[1]]) - { - thiscam = &camera[1]; - chasecam = (cv_chasecam2.value != 0); - } - else - { - thiscam = &camera[0]; - chasecam = (cv_chasecam.value != 0); - } - - if (player->spectator) // no spectator chasecam - chasecam = false; // force chasecam off - else if (player->playerstate == PST_DEAD || player->exiting) - chasecam = true; // force chasecam on - - if (chasecam && !thiscam->chase) - { - P_ResetCamera(player, thiscam); - thiscam->chase = true; - } - else if (!chasecam) - thiscam->chase = false; - - viewsky = !skybox; - if (player->awayviewtics) - { - // cut-away view stuff - viewmobj = player->awayviewmobj; // should be a MT_ALTVIEWMAN - I_Assert(viewmobj != NULL); - viewz = viewmobj->z + 20*FRACUNIT; - aimingangle = player->awayviewaiming; - viewangle = viewmobj->angle; - } - else if (!player->spectator && chasecam) - // use outside cam view - { - viewmobj = NULL; - viewz = thiscam->z + (thiscam->height>>1); - aimingangle = thiscam->aiming; - viewangle = thiscam->angle; - } - else - // use the player's eyes view - { - viewz = player->viewz; - - viewmobj = player->mo; - I_Assert(viewmobj != NULL); - - aimingangle = player->aiming; - viewangle = viewmobj->angle; - - if (!demo.playback && player->playerstate != PST_DEAD) + if (player == &players[g_localplayers[i]]) { - if (player == &players[consoleplayer]) - { - viewangle = localangle[0]; // WARNING: camera uses this - aimingangle = localaiming[0]; - } - else if (splitscreen) - { - UINT8 i; - for (i = 1; i <= splitscreen; i++) - { - if (player == &players[g_localplayers[i]]) - { - viewangle = localangle[i]; - aimingangle = localaiming[i]; - break; - } - } - } + chasecam = (cv_chasecam[i].value != 0); + break; } } - viewz += quake.z; - viewplayer = player; + if (player->playerstate == PST_DEAD || gamestate == GS_TITLESCREEN || tutorialmode) + chasecam = true; // force chasecam on + else if (player->spectator) // no spectator chasecam + chasecam = false; // force chasecam off - if (chasecam && !player->awayviewtics && !player->spectator) - { - viewx = thiscam->x; - viewy = thiscam->y; - viewx += quake.x; - viewy += quake.y; - - if (thiscam->subsector && thiscam->subsector->sector) - viewsector = thiscam->subsector->sector; - else - viewsector = R_PointInSubsector(viewx, viewy)->sector; - } - else - { - viewx = viewmobj->x; - viewy = viewmobj->y; - viewx += quake.x; - viewy += quake.y; - - if (viewmobj->subsector && thiscam->subsector->sector) - viewsector = viewmobj->subsector->sector; - else - viewsector = R_PointInSubsector(viewx, viewy)->sector; - } - - viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); - viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - - R_SetupFreelook(); + return chasecam; } -#define ANGLED_PORTALS - -static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal) +boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox) { - vertex_t dest_c, start_c; -#ifdef ANGLED_PORTALS - // delta angle - angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0); -#endif + boolean chasecam = R_ViewpointHasChasecam(player); - //R_SetupFrame(player, false); + // cut-away view stuff + if (player->awayviewtics || skybox) + return chasecam; + // use outside cam view + else if (!player->spectator && chasecam) + return true; + + // use the player's eyes view + return false; +} + +static void R_PortalFrame(portal_t *portal) +{ viewx = portal->viewx; viewy = portal->viewy; viewz = portal->viewz; @@ -1195,96 +1483,39 @@ static void R_PortalFrame(line_t *start, line_t *dest, portal_pair *portal) viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - portalcullsector = dest->frontsector; - viewsector = dest->frontsector; - portalclipline = dest; portalclipstart = portal->start; portalclipend = portal->end; - // Offset the portal view by the linedef centers - - // looking glass center - start_c.x = (start->v1->x + start->v2->x) / 2; - start_c.y = (start->v1->y + start->v2->y) / 2; - - // other side center - dest_c.x = (dest->v1->x + dest->v2->x) / 2; - dest_c.y = (dest->v1->y + dest->v2->y) / 2; - - // Heights! - viewz += dest->frontsector->floorheight - start->frontsector->floorheight; - - // calculate the difference in position and rotation! -#ifdef ANGLED_PORTALS - if (dangle == 0) -#endif - { // the entrance goes straight opposite the exit, so we just need to mess with the offset. - viewx += dest_c.x - start_c.x; - viewy += dest_c.y - start_c.y; - return; - } - -#ifdef ANGLED_PORTALS - viewangle += dangle; - viewsin = FINESINE(viewangle>>ANGLETOFINESHIFT); - viewcos = FINECOSINE(viewangle>>ANGLETOFINESHIFT); - //CONS_Printf("dangle == %u\n", AngleFixed(dangle)>>FRACBITS); - - // ???? + if (portal->clipline != -1) { - fixed_t disttopoint; - angle_t angtopoint; - - disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy); - angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy); - angtopoint += dangle; - - viewx = dest_c.x+FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); - viewy = dest_c.y+FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); - } -#endif -} - -void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2) -{ - portal_pair *portal = Z_Malloc(sizeof(portal_pair), PU_LEVEL, NULL); - INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL); - INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1), PU_LEVEL, NULL); - fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1), PU_LEVEL, NULL); - - portal->line1 = line1; - portal->line2 = line2; - portal->pass = portalrender+1; - portal->next = NULL; - - R_PortalStoreClipValues(x1, x2, ceilingclipsave, floorclipsave, frontscalesave); - - portal->ceilingclip = ceilingclipsave; - portal->floorclip = floorclipsave; - portal->frontscale = frontscalesave; - - portal->start = x1; - portal->end = x2; - - portalline = true; // this tells R_StoreWallRange that curline is a portal seg - - portal->viewx = viewx; - portal->viewy = viewy; - portal->viewz = viewz; - portal->viewangle = viewangle; - - if (!portal_base) - { - portal_base = portal; - portal_cap = portal; + portalclipline = &lines[portal->clipline]; + portalcullsector = portalclipline->frontsector; + viewsector = portalclipline->frontsector; } else { - portal_cap->next = portal; - portal_cap = portal; + portalclipline = NULL; + portalcullsector = NULL; + viewsector = R_PointInSubsector(viewx, viewy)->sector; } } +static void Mask_Pre (maskcount_t* m) +{ + m->drawsegs[0] = ds_p - drawsegs; + m->vissprites[0] = visspritecount; + m->viewx = viewx; + m->viewy = viewy; + m->viewz = viewz; + m->viewsector = viewsector; +} + +static void Mask_Post (maskcount_t* m) +{ + m->drawsegs[1] = ds_p - drawsegs; + m->vissprites[1] = visspritecount; +} + // ================ // R_RenderView // ================ @@ -1295,11 +1526,12 @@ void R_AddPortal(INT32 line1, INT32 line2, INT32 x1, INT32 x2) // I mean, there is a win16lock() or something that lasts all the rendering, // so maybe we should release screen lock before each netupdate below..? -void R_RenderPlayerView(player_t *player) +void R_RenderPlayerView(void) { - portal_pair *portal; - const boolean skybox = (skyboxmo[0] && cv_skybox.value); - UINT8 i; + player_t * player = &players[displayplayers[viewssnum]]; + + UINT8 nummasks = 1; + maskcount_t* masks = malloc(sizeof(maskcount_t)); // if this is display player 1 if (cv_homremoval.value && player == &players[displayplayers[0]]) @@ -1309,85 +1541,56 @@ void R_RenderPlayerView(player_t *player) else //'development' HOM removal -- makes it blindingly obvious if HOM is spotted. V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 32+(timeinmap&15)); } - // Draw over the fourth screen so you don't have to stare at a HOM :V else if (r_splitscreen == 2 && player == &players[displayplayers[2]]) -#if 1 { - // V_DrawPatchFill, but for the fourth screen only - patch_t *pat = W_CachePatchName("SRB2BACK", PU_CACHE); - INT32 dupz = (vid.dupx < vid.dupy ? vid.dupx : vid.dupy); - INT32 x, y, pw = SHORT(pat->width) * dupz, ph = SHORT(pat->height) * dupz; - - for (x = vid.width>>1; x < vid.width; x += pw) - { - for (y = vid.height>>1; y < vid.height; y += ph) - V_DrawScaledPatch(x, y, V_NOSCALESTART, pat); - } - } -#else - V_DrawFill(viewwidth, viewheight, viewwidth, viewheight, 31|V_NOSCALESTART); -#endif - - // load previous saved value of skyVisible for the player - for (i = 0; i <= r_splitscreen; i++) - { - if (player == &players[displayplayers[i]]) - { - skyVisible = skyVisiblePerPlayer[i]; - break; - } + // Draw over the fourth screen so you don't have to stare at a HOM :V + V_DrawFill(viewwidth, viewheight, viewwidth, viewheight, 31|V_NOSCALESTART); } - portalrender = 0; - portal_base = portal_cap = NULL; - - if (skybox && skyVisible) - { - R_SkyboxFrame(player); - - R_ClearClipSegs(); - R_ClearDrawSegs(); - R_ClearPlanes(); - R_ClearSprites(); -#ifdef FLOORSPLATS - R_ClearVisibleFloorSplats(); -#endif - - R_RenderBSPNode((INT32)numnodes - 1); - R_ClipSprites(); - R_DrawPlanes(); -#ifdef FLOORSPLATS - R_DrawVisibleFloorSplats(); -#endif - R_DrawMasked(); - } - - R_SetupFrame(player, skybox); - skyVisible = false; + R_SetupFrame(player); framecount++; validcount++; // Clear buffers. - R_ClearClipSegs(); - R_ClearDrawSegs(); R_ClearPlanes(); + if (viewmorph[viewssnum].use) + { + portalclipstart = viewmorph[viewssnum].x1; + portalclipend = viewwidth-viewmorph[viewssnum].x1-1; + R_PortalClearClipSegs(portalclipstart, portalclipend); + memcpy(ceilingclip, viewmorph[viewssnum].ceilingclip, sizeof(INT16)*vid.width); + memcpy(floorclip, viewmorph[viewssnum].floorclip, sizeof(INT16)*vid.width); + } + else + { + portalclipstart = 0; + portalclipend = viewwidth; + R_ClearClipSegs(); + } + R_ClearDrawSegs(); R_ClearSprites(); #ifdef FLOORSPLATS R_ClearVisibleFloorSplats(); #endif + Portal_InitList(); // check for new console commands. NetUpdate(); // The head node is the last node output. + Mask_Pre(&masks[nummasks - 1]); + curdrawsegs = ds_p; //profile stuff --------------------------------------------------------- #ifdef TIMING mytotal = 0; ProfZeroTimer(); #endif + ps_numbspcalls = ps_numpolyobjects = ps_numdrawnodes = 0; + ps_bsptime = I_GetTimeMicros(); R_RenderBSPNode((INT32)numnodes - 1); - R_ClipSprites(); + ps_bsptime = I_GetTimeMicros() - ps_bsptime; + ps_numsprites = visspritecount; #ifdef TIMING RDMSR(0x10, &mycount); mytotal += mycount; // 64bit add @@ -1395,58 +1598,92 @@ void R_RenderPlayerView(player_t *player) CONS_Debug(DBG_RENDER, "RenderBSPNode: 0x%d %d\n", *((INT32 *)&mytotal + 1), (INT32)mytotal); #endif //profile stuff --------------------------------------------------------- + Mask_Post(&masks[nummasks - 1]); - // PORTAL RENDERING - for(portal = portal_base; portal; portal = portal_base) + ps_sw_spritecliptime = I_GetTimeMicros(); + R_ClipSprites(drawsegs, NULL); + ps_sw_spritecliptime = I_GetTimeMicros() - ps_sw_spritecliptime; + + + // Add skybox portals caused by sky visplanes. + if (cv_skybox.value && skyboxmo[0]) + Portal_AddSkyboxPortals(); + + // Portal rendering. Hijacks the BSP traversal. + ps_sw_portaltime = I_GetTimeMicros(); + if (portal_base) { - // render the portal - CONS_Debug(DBG_RENDER, "Rendering portal from line %d to %d\n", portal->line1, portal->line2); - portalrender = portal->pass; + portal_t *portal; - R_PortalFrame(&lines[portal->line1], &lines[portal->line2], portal); + for(portal = portal_base; portal; portal = portal_base) + { + portalrender = portal->pass; // Recursiveness depth. - R_PortalClearClipSegs(portal->start, portal->end); + R_ClearFFloorClips(); - R_PortalRestoreClipValues(portal->start, portal->end, portal->ceilingclip, portal->floorclip, portal->frontscale); + // Apply the viewpoint stored for the portal. + R_PortalFrame(portal); - validcount++; + // Hack in the clipsegs to delimit the starting + // clipping for sprites and possibly other similar + // future items. + R_PortalClearClipSegs(portal->start, portal->end); - R_RenderBSPNode((INT32)numnodes - 1); - R_ClipSprites(); - //R_DrawPlanes(); - //R_DrawMasked(); + // Hack in the top/bottom clip values for the window + // that were previously stored. + Portal_ClipApply(portal); - // okay done. free it. - portalcullsector = NULL; // Just in case... - portal_base = portal->next; - Z_Free(portal->ceilingclip); - Z_Free(portal->floorclip); - Z_Free(portal->frontscale); - Z_Free(portal); + validcount++; + + masks = realloc(masks, (++nummasks)*sizeof(maskcount_t)); + + Mask_Pre(&masks[nummasks - 1]); + curdrawsegs = ds_p; + + // Render the BSP from the new viewpoint, and clip + // any sprites with the new clipsegs and window. + R_RenderBSPNode((INT32)numnodes - 1); + Mask_Post(&masks[nummasks - 1]); + + R_ClipSprites(ds_p - (masks[nummasks - 1].drawsegs[1] - masks[nummasks - 1].drawsegs[0]), portal); + + Portal_Remove(portal); + } } - // END PORTAL RENDERING + ps_sw_portaltime = I_GetTimeMicros() - ps_sw_portaltime; + ps_sw_planetime = I_GetTimeMicros(); R_DrawPlanes(); #ifdef FLOORSPLATS R_DrawVisibleFloorSplats(); #endif + ps_sw_planetime = I_GetTimeMicros() - ps_sw_planetime; + // draw mid texture and sprite // And now 3D floors/sides! - R_DrawMasked(); + ps_sw_maskedtime = I_GetTimeMicros(); + R_DrawMasked(masks, nummasks); + ps_sw_maskedtime = I_GetTimeMicros() - ps_sw_maskedtime; - // Check for new console commands. - NetUpdate(); + free(masks); +} - // save value to skyVisiblePerPlayer - // this is so that P1 can't affect whether P2 can see a skybox or not, or vice versa - for (i = 0; i <= r_splitscreen; i++) - { - if (player == &players[displayplayers[i]]) - { - skyVisiblePerPlayer[i] = skyVisible; - break; - } - } +#ifdef HWRENDER +void R_InitHardwareMode(void) +{ + HWR_AddSessionCommands(); + HWR_Switch(); + HWR_LoadTextures(numtextures); + if (gamestate == GS_LEVEL || (gamestate == GS_TITLESCREEN && titlemapinaction)) + HWR_SetupLevel(); +} +#endif + +void R_ReloadHUDGraphics(void) +{ + ST_LoadGraphics(); + HU_LoadGraphics(); + ST_ReloadSkinFaceGraphics(); } // ========================================================================= @@ -1455,87 +1692,38 @@ void R_RenderPlayerView(player_t *player) void R_RegisterEngineStuff(void) { + UINT8 i; + CV_RegisterVar(&cv_gravity); CV_RegisterVar(&cv_tailspickup); - CV_RegisterVar(&cv_soniccd); CV_RegisterVar(&cv_allowmlook); CV_RegisterVar(&cv_homremoval); // Enough for dedicated server if (dedicated) return; - //CV_RegisterVar(&cv_precipdensity); CV_RegisterVar(&cv_drawdist); - //CV_RegisterVar(&cv_drawdist_nights); CV_RegisterVar(&cv_drawdist_precip); - CV_RegisterVar(&cv_fov); - CV_RegisterVar(&cv_chasecam); - CV_RegisterVar(&cv_chasecam2); - CV_RegisterVar(&cv_chasecam3); - CV_RegisterVar(&cv_chasecam4); CV_RegisterVar(&cv_shadow); CV_RegisterVar(&cv_skybox); + CV_RegisterVar(&cv_ffloorclip); - CV_RegisterVar(&cv_cam_dist); - CV_RegisterVar(&cv_cam_still); - CV_RegisterVar(&cv_cam_height); - CV_RegisterVar(&cv_cam_speed); - CV_RegisterVar(&cv_cam_rotate); - CV_RegisterVar(&cv_cam_rotspeed); - - CV_RegisterVar(&cv_cam2_dist); - CV_RegisterVar(&cv_cam2_still); - CV_RegisterVar(&cv_cam2_height); - CV_RegisterVar(&cv_cam2_speed); - CV_RegisterVar(&cv_cam2_rotate); - CV_RegisterVar(&cv_cam2_rotspeed); - - CV_RegisterVar(&cv_cam3_dist); - CV_RegisterVar(&cv_cam3_still); - CV_RegisterVar(&cv_cam3_height); - CV_RegisterVar(&cv_cam3_speed); - CV_RegisterVar(&cv_cam3_rotate); - CV_RegisterVar(&cv_cam3_rotspeed); - - CV_RegisterVar(&cv_cam4_dist); - CV_RegisterVar(&cv_cam4_still); - CV_RegisterVar(&cv_cam4_height); - CV_RegisterVar(&cv_cam4_speed); - CV_RegisterVar(&cv_cam4_rotate); - CV_RegisterVar(&cv_cam4_rotspeed); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + CV_RegisterVar(&cv_fov[i]); + CV_RegisterVar(&cv_chasecam[i]); + CV_RegisterVar(&cv_cam_dist[i]); + CV_RegisterVar(&cv_cam_still[i]); + CV_RegisterVar(&cv_cam_height[i]); + CV_RegisterVar(&cv_cam_speed[i]); + CV_RegisterVar(&cv_cam_rotate[i]); + } CV_RegisterVar(&cv_showhud); CV_RegisterVar(&cv_translucenthud); CV_RegisterVar(&cv_maxportals); - // Default viewheight is changeable, - // initialized to standard viewheight - //CV_RegisterVar(&cv_viewheight); - -#ifdef HWRENDER - // GL-specific Commands - CV_RegisterVar(&cv_grgammablue); - CV_RegisterVar(&cv_grgammagreen); - CV_RegisterVar(&cv_grgammared); - CV_RegisterVar(&cv_grfovchange); -#ifdef ALAM_LIGHTING - CV_RegisterVar(&cv_grstaticlighting); - CV_RegisterVar(&cv_grdynamiclighting); - CV_RegisterVar(&cv_grcoronas); - CV_RegisterVar(&cv_grcoronasize); -#endif - CV_RegisterVar(&cv_grmdls); - CV_RegisterVar(&cv_grfallbackplayermodel); - CV_RegisterVar(&cv_grspritebillboarding); - CV_RegisterVar(&cv_grfakecontrast); - CV_RegisterVar(&cv_grshearing); - CV_RegisterVar(&cv_grshaders); -#endif - -#ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) - HWR_AddCommands(); -#endif + CV_RegisterVar(&cv_movebob); } diff --git a/src/r_main.h b/src/r_main.h index 641fdb3e4..b4845af18 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -16,6 +16,7 @@ #include "d_player.h" #include "r_data.h" +#include "r_textures.h" // // POV related. @@ -24,8 +25,11 @@ extern fixed_t viewcos, viewsin; extern INT32 viewheight; extern INT32 centerx, centery; -extern fixed_t centerxfrac, centeryfrac; -extern fixed_t projection, projectiony; +extern fixed_t centerxfrac; +extern fixed_t centeryfrac; +extern fixed_t projection[MAXSPLITSCREENPLAYERS]; +extern fixed_t projectiony[MAXSPLITSCREENPLAYERS]; +extern fixed_t fovtan[MAXSPLITSCREENPLAYERS]; extern size_t validcount, linecount, loopcount, framecount; @@ -45,6 +49,8 @@ extern size_t validcount, linecount, loopcount, framecount; #define MAXLIGHTZ 128 #define LIGHTZSHIFT 20 +#define LIGHTRESOLUTIONFIX (640*fovtan[viewssnum]/vid.width) + extern lighttable_t *scalelight[LIGHTLEVELS][MAXLIGHTSCALE]; extern lighttable_t *scalelightfixed[MAXLIGHTSCALE]; extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; @@ -57,6 +63,7 @@ extern lighttable_t *zlight[LIGHTLEVELS][MAXLIGHTZ]; INT32 R_PointOnSide(fixed_t x, fixed_t y, node_t *node); INT32 R_PointOnSegSide(fixed_t x, fixed_t y, seg_t *line); angle_t R_PointToAngle(fixed_t x, fixed_t y); +angle_t R_PointToAngle64(INT64 x, INT64 y); angle_t R_PointToAngle2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); angle_t R_PointToAngleEx(INT32 x2, INT32 y2, INT32 x1, INT32 y1); fixed_t R_PointToDist(fixed_t x, fixed_t y); @@ -64,25 +71,54 @@ fixed_t R_PointToDist2(fixed_t px2, fixed_t py2, fixed_t px1, fixed_t py1); fixed_t R_ScaleFromGlobalAngle(angle_t visangle); subsector_t *R_PointInSubsector(fixed_t x, fixed_t y); -subsector_t *R_IsPointInSubsector(fixed_t x, fixed_t y); +subsector_t *R_PointInSubsectorOrNull(fixed_t x, fixed_t y); boolean R_DoCulling(line_t *cullheight, line_t *viewcullheight, fixed_t vz, fixed_t bottomh, fixed_t toph); +// Render stats + +extern int ps_prevframetime;// time when previous frame was rendered +extern int ps_rendercalltime; +extern int ps_uitime; +extern int ps_swaptime; + +extern int ps_bsptime; + +extern int ps_sw_spritecliptime; +extern int ps_sw_portaltime; +extern int ps_sw_planetime; +extern int ps_sw_maskedtime; + +extern int ps_numbspcalls; +extern int ps_numsprites; +extern int ps_numdrawnodes; +extern int ps_numpolyobjects; + // // REFRESH - the actual rendering functions. // extern consvar_t cv_showhud, cv_translucenthud; extern consvar_t cv_homremoval; -extern consvar_t cv_chasecam, cv_chasecam2, cv_chasecam3, cv_chasecam4; +extern consvar_t cv_chasecam[MAXSPLITSCREENPLAYERS]; +extern consvar_t cv_flipcam[MAXSPLITSCREENPLAYERS]; + extern consvar_t cv_shadow; -extern consvar_t /*cv_precipdensity,*/ cv_drawdist, /*cv_drawdist_nights,*/ cv_drawdist_precip; -extern consvar_t cv_fov; +extern consvar_t cv_ffloorclip; +extern consvar_t cv_drawdist, cv_drawdist_precip; +extern consvar_t cv_fov[MAXSPLITSCREENPLAYERS]; extern consvar_t cv_skybox; extern consvar_t cv_tailspickup; // Called by startup code. void R_Init(void); +#ifdef HWRENDER +void R_InitHardwareMode(void); +#endif +void R_ReloadHUDGraphics(void); + +void R_CheckViewMorph(int split); +void R_ApplyViewMorph(int split); // just sets setsizeneeded true extern boolean setsizeneeded; @@ -91,11 +127,14 @@ void R_SetViewSize(void); // do it (sometimes explicitly called) void R_ExecuteSetViewSize(void); +void R_SetupFrame(player_t *player); void R_SkyboxFrame(player_t *player); -void R_SetupFrame(player_t *player, boolean skybox); -// Called by G_Drawer. -void R_RenderPlayerView(player_t *player); +boolean R_ViewpointHasChasecam(player_t *player); +boolean R_IsViewpointThirdPerson(player_t *player, boolean skybox); + +// Called by D_Display. +void R_RenderPlayerView(void); // add commands related to engine, at game startup void R_RegisterEngineStuff(void); diff --git a/src/r_picformats.c b/src/r_picformats.c new file mode 100644 index 000000000..95fe23aeb --- /dev/null +++ b/src/r_picformats.c @@ -0,0 +1,1918 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 2005-2009 by Andrey "entryway" Budko. +// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_picformats.c +/// \brief Picture generation. + +#include "byteptr.h" +#include "dehacked.h" +#include "i_video.h" +#include "r_data.h" +#include "r_textures.h" +#include "r_draw.h" +#include "r_picformats.h" +#include "r_things.h" +#include "v_video.h" +#include "z_zone.h" +#include "w_wad.h" + +#ifdef HWRENDER +#include "hardware/hw_glob.h" +#endif + +#ifdef HAVE_PNG + +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include "png.h" +#ifndef PNG_READ_SUPPORTED +#undef HAVE_PNG +#endif +#endif + +static unsigned char imgbuf[1<<26]; + +#ifdef PICTURE_PNG_USELOOKUP +static colorlookup_t png_colorlookup; +#endif + +/** Converts a picture between two formats. + * + * \param informat Input picture format. + * \param picture Input picture data. + * \param outformat Output picture format. + * \param insize Input picture size. + * \param outsize Output picture size, as a pointer. + * \param inwidth Input picture width. + * \param inheight Input picture height. + * \param inleftoffset Input picture left offset, for patches. + * \param intopoffset Input picture top offset, for patches. + * \param flags Input picture flags. + * \return A pointer to the converted picture. + * \sa Picture_PatchConvert + * \sa Picture_FlatConvert + */ +void *Picture_Convert( + pictureformat_t informat, void *picture, pictureformat_t outformat, + size_t insize, size_t *outsize, + INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset, + pictureflags_t flags) +{ + if (informat == PICFMT_NONE) + I_Error("Picture_Convert: input format was PICFMT_NONE!"); + else if (outformat == PICFMT_NONE) + I_Error("Picture_Convert: output format was PICFMT_NONE!"); + else if (informat == outformat) + I_Error("Picture_Convert: input and output formats were the same!"); + + if (Picture_IsPatchFormat(outformat)) + return Picture_PatchConvert(informat, picture, outformat, insize, outsize, inwidth, inheight, inleftoffset, intopoffset, flags); + else if (Picture_IsFlatFormat(outformat)) + return Picture_FlatConvert(informat, picture, outformat, insize, outsize, inwidth, inheight, inleftoffset, intopoffset, flags); + else + I_Error("Picture_Convert: unsupported input format!"); + + return NULL; +} + +/** Converts a picture to a patch. + * + * \param informat Input picture format. + * \param picture Input picture data. + * \param outformat Output picture format. + * \param insize Input picture size. + * \param outsize Output picture size, as a pointer. + * \param inwidth Input picture width. + * \param inheight Input picture height. + * \param inleftoffset Input picture left offset, for patches. + * \param intopoffset Input picture top offset, for patches. + * \param flags Input picture flags. + * \return A pointer to the converted picture. + */ +void *Picture_PatchConvert( + pictureformat_t informat, void *picture, pictureformat_t outformat, + size_t insize, size_t *outsize, + INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset, + pictureflags_t flags) +{ + INT16 x, y; + UINT8 *img; + UINT8 *imgptr = imgbuf; + UINT8 *colpointers, *startofspan; + size_t size = 0; + patch_t *inpatch = NULL; + INT32 inbpp = Picture_FormatBPP(informat); + + (void)insize; // ignore + + if (informat == PICFMT_NONE) + I_Error("Picture_PatchConvert: input format was PICFMT_NONE!"); + else if (outformat == PICFMT_NONE) + I_Error("Picture_PatchConvert: output format was PICFMT_NONE!"); + else if (informat == outformat) + I_Error("Picture_PatchConvert: input and output formats were the same!"); + + if (inbpp == PICDEPTH_NONE) + I_Error("Picture_PatchConvert: unknown input bits per pixel?!"); + if (Picture_FormatBPP(outformat) == PICDEPTH_NONE) + I_Error("Picture_PatchConvert: unknown output bits per pixel?!"); + + // If it's a patch, you can just figure out + // the dimensions from the header. + if (Picture_IsPatchFormat(informat)) + { + inpatch = (patch_t *)picture; + inwidth = SHORT(inpatch->width); + inheight = SHORT(inpatch->height); + inleftoffset = SHORT(inpatch->leftoffset); + intopoffset = SHORT(inpatch->topoffset); + } + + // Write image size and offset + WRITEINT16(imgptr, inwidth); + WRITEINT16(imgptr, inheight); + WRITEINT16(imgptr, inleftoffset); + WRITEINT16(imgptr, intopoffset); + + // Leave placeholder to column pointers + colpointers = imgptr; + imgptr += inwidth*4; + + // Write columns + for (x = 0; x < inwidth; x++) + { + int lastStartY = 0; + int spanSize = 0; + startofspan = NULL; + + // Write column pointer + WRITEINT32(colpointers, imgptr - imgbuf); + + // Write pixels + for (y = 0; y < inheight; y++) + { + void *input = NULL; + boolean opaque = false; + + // Read pixel + if (Picture_IsPatchFormat(informat)) + input = Picture_GetPatchPixel(inpatch, informat, x, y, flags); + else if (Picture_IsFlatFormat(informat)) + { + size_t offs = ((y * inwidth) + x); + switch (informat) + { + case PICFMT_FLAT32: + input = (UINT32 *)picture + offs; + break; + case PICFMT_FLAT16: + input = (UINT16 *)picture + offs; + break; + case PICFMT_FLAT: + input = (UINT8 *)picture + offs; + break; + default: + I_Error("Picture_PatchConvert: unsupported flat input format!"); + break; + } + } + else + I_Error("Picture_PatchConvert: unsupported input format!"); + + // Determine opacity + if (input != NULL) + { + UINT8 alpha = 0xFF; + if (inbpp == PICDEPTH_32BPP) + { + RGBA_t px = *(RGBA_t *)input; + alpha = px.s.alpha; + } + else if (inbpp == PICDEPTH_16BPP) + { + UINT16 px = *(UINT16 *)input; + alpha = (px & 0xFF00) >> 8; + } + else if (inbpp == PICDEPTH_8BPP) + { + UINT8 px = *(UINT8 *)input; + if (px == TRANSPARENTPIXEL) + alpha = 0; + } + opaque = (alpha > 1); + } + + // End span if we have a transparent pixel + if (!opaque) + { + if (startofspan) + WRITEUINT8(imgptr, 0); + startofspan = NULL; + continue; + } + + // Start new column if we need to + if (!startofspan || spanSize == 255) + { + int writeY = y; + + // If we reached the span size limit, finish the previous span + if (startofspan) + WRITEUINT8(imgptr, 0); + + if (y > 254) + { + // Make sure we're aligned to 254 + if (lastStartY < 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + lastStartY = 254; + } + + // Write stopgap empty spans if needed + writeY = y - lastStartY; + + while (writeY > 254) + { + WRITEUINT8(imgptr, 254); + WRITEUINT8(imgptr, 0); + imgptr += 2; + writeY -= 254; + } + } + + startofspan = imgptr; + WRITEUINT8(imgptr, writeY); + imgptr += 2; + spanSize = 0; + + lastStartY = y; + } + + // Write the pixel + switch (outformat) + { + case PICFMT_PATCH32: + { + if (inbpp == PICDEPTH_32BPP) + { + RGBA_t out = *(RGBA_t *)input; + WRITEUINT32(imgptr, out.rgba); + } + else if (inbpp == PICDEPTH_16BPP) + { + RGBA_t out = pMasterPalette[*((UINT16 *)input) & 0xFF]; + WRITEUINT32(imgptr, out.rgba); + } + else // PICFMT_PATCH + { + RGBA_t out = pMasterPalette[*((UINT8 *)input) & 0xFF]; + WRITEUINT32(imgptr, out.rgba); + } + break; + } + case PICFMT_PATCH16: + if (inbpp == PICDEPTH_32BPP) + { + RGBA_t in = *(RGBA_t *)input; + UINT8 out = NearestColor(in.s.red, in.s.green, in.s.blue); + WRITEUINT16(imgptr, (0xFF00 | out)); + } + else if (inbpp == PICDEPTH_16BPP) + WRITEUINT16(imgptr, *(UINT16 *)input); + else // PICFMT_PATCH + WRITEUINT16(imgptr, (0xFF00 | (*(UINT8 *)input))); + break; + default: // PICFMT_PATCH + { + if (inbpp == PICDEPTH_32BPP) + { + RGBA_t in = *(RGBA_t *)input; + UINT8 out = NearestColor(in.s.red, in.s.green, in.s.blue); + WRITEUINT8(imgptr, out); + } + else if (inbpp == PICDEPTH_16BPP) + { + UINT16 out = *(UINT16 *)input; + WRITEUINT8(imgptr, (out & 0xFF)); + } + else // PICFMT_PATCH + WRITEUINT8(imgptr, *(UINT8 *)input); + break; + } + } + + spanSize++; + startofspan[1] = spanSize; + } + + if (startofspan) + WRITEUINT8(imgptr, 0); + + WRITEUINT8(imgptr, 0xFF); + } + + size = imgptr-imgbuf; + img = Z_Malloc(size, PU_STATIC, NULL); + memcpy(img, imgbuf, size); + + if (outsize != NULL) + *outsize = size; + return img; +} + +/** Converts a picture to a flat. + * + * \param informat Input picture format. + * \param picture Input picture data. + * \param outformat Output picture format. + * \param insize Input picture size. + * \param outsize Output picture size, as a pointer. + * \param inwidth Input picture width. + * \param inheight Input picture height. + * \param inleftoffset Input picture left offset, for patches. + * \param intopoffset Input picture top offset, for patches. + * \param flags Input picture flags. + * \return A pointer to the converted picture. + */ +void *Picture_FlatConvert( + pictureformat_t informat, void *picture, pictureformat_t outformat, + size_t insize, size_t *outsize, + INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset, + pictureflags_t flags) +{ + void *outflat; + patch_t *inpatch = NULL; + INT32 inbpp = Picture_FormatBPP(informat); + INT32 outbpp = Picture_FormatBPP(outformat); + INT32 x, y; + size_t size; + + (void)insize; // ignore + (void)inleftoffset; // ignore + (void)intopoffset; // ignore + + if (informat == PICFMT_NONE) + I_Error("Picture_FlatConvert: input format was PICFMT_NONE!"); + else if (outformat == PICFMT_NONE) + I_Error("Picture_FlatConvert: output format was PICFMT_NONE!"); + else if (informat == outformat) + I_Error("Picture_FlatConvert: input and output formats were the same!"); + + if (inbpp == PICDEPTH_NONE) + I_Error("Picture_FlatConvert: unknown input bits per pixel?!"); + if (outbpp == PICDEPTH_NONE) + I_Error("Picture_FlatConvert: unknown output bits per pixel?!"); + + // If it's a patch, you can just figure out + // the dimensions from the header. + if (Picture_IsPatchFormat(informat)) + { + inpatch = (patch_t *)picture; + inwidth = SHORT(inpatch->width); + inheight = SHORT(inpatch->height); + } + + size = (inwidth * inheight) * (outbpp / 8); + outflat = Z_Calloc(size, PU_STATIC, NULL); + if (outsize) + *outsize = size; + + // Set transparency + if (outbpp == PICDEPTH_8BPP) + memset(outflat, TRANSPARENTPIXEL, size); + + for (y = 0; y < inheight; y++) + for (x = 0; x < inwidth; x++) + { + void *input; + size_t offs = ((y * inwidth) + x); + + // Read pixel + if (Picture_IsPatchFormat(informat)) + input = Picture_GetPatchPixel(inpatch, informat, x, y, flags); + else if (Picture_IsFlatFormat(informat)) + input = (UINT8 *)picture + (offs * (inbpp / 8)); + else + I_Error("Picture_FlatConvert: unsupported input format!"); + + if (!input) + continue; + + switch (outformat) + { + case PICFMT_FLAT32: + { + UINT32 *f32 = (UINT32 *)outflat; + if (inbpp == PICDEPTH_32BPP) + { + RGBA_t out = *(RGBA_t *)input; + f32[offs] = out.rgba; + } + else if (inbpp == PICDEPTH_16BPP) + { + RGBA_t out = pMasterPalette[*((UINT16 *)input) & 0xFF]; + f32[offs] = out.rgba; + } + else // PICFMT_PATCH + { + RGBA_t out = pMasterPalette[*((UINT8 *)input) & 0xFF]; + f32[offs] = out.rgba; + } + break; + } + case PICFMT_FLAT16: + { + UINT16 *f16 = (UINT16 *)outflat; + if (inbpp == PICDEPTH_32BPP) + { + RGBA_t in = *(RGBA_t *)input; + UINT8 out = NearestColor(in.s.red, in.s.green, in.s.blue); + f16[offs] = (0xFF00 | out); + } + else if (inbpp == PICDEPTH_16BPP) + f16[offs] = *(UINT16 *)input; + else // PICFMT_PATCH + f16[offs] = (0xFF00 | *((UINT8 *)input)); + break; + } + case PICFMT_FLAT: + { + UINT8 *f8 = (UINT8 *)outflat; + if (inbpp == PICDEPTH_32BPP) + { + RGBA_t in = *(RGBA_t *)input; + UINT8 out = NearestColor(in.s.red, in.s.green, in.s.blue); + f8[offs] = out; + } + else if (inbpp == PICDEPTH_16BPP) + { + UINT16 out = *(UINT16 *)input; + f8[offs] = (out & 0xFF); + } + else // PICFMT_PATCH + f8[offs] = *(UINT8 *)input; + break; + } + default: + I_Error("Picture_FlatConvert: unsupported output format!"); + } + } + + return outflat; +} + +/** Returns a pixel from a patch. + * + * \param patch Input patch. + * \param informat Input picture format. + * \param x Pixel X position. + * \param y Pixel Y position. + * \param flags Input picture flags. + * \return A pointer to a pixel in the patch. Returns NULL if not opaque. + */ +void *Picture_GetPatchPixel( + patch_t *patch, pictureformat_t informat, + INT32 x, INT32 y, + pictureflags_t flags) +{ + fixed_t ofs; + column_t *column; + UINT8 *s8 = NULL; + UINT16 *s16 = NULL; + UINT32 *s32 = NULL; + + if (patch == NULL) + I_Error("Picture_GetPatchPixel: patch == NULL"); + + if (x >= 0 && x < SHORT(patch->width)) + { + INT32 topdelta, prevdelta = -1; + INT32 colofs = 0; + + if (flags & PICFLAGS_XFLIP) + colofs = LONG(patch->columnofs[(SHORT(patch->width)-1)-x]); + else + colofs = LONG(patch->columnofs[x]); + + // Column offsets are pointers so no casting required + column = (column_t *)((UINT8 *)patch + colofs); + + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + s8 = (UINT8 *)(column) + 3; + if (informat == PICFMT_PATCH32) + s32 = (UINT32 *)s8; + else if (informat == PICFMT_PATCH16) + s16 = (UINT16 *)s8; + for (ofs = 0; ofs < column->length; ofs++) + { + if ((topdelta + ofs) == y) + { + if (informat == PICFMT_PATCH32) + return &s32[ofs]; + else if (informat == PICFMT_PATCH16) + return &s16[ofs]; + else // PICFMT_PATCH + return &s8[ofs]; + } + } + if (informat == PICFMT_PATCH32) + column = (column_t *)((UINT32 *)column + column->length); + else if (informat == PICFMT_PATCH16) + column = (column_t *)((UINT16 *)column + column->length); + else + column = (column_t *)((UINT8 *)column + column->length); + column = (column_t *)((UINT8 *)column + 4); + } + } + + return NULL; +} + +/** Returns the amount of bits per pixel in the specified picture format. + * + * \param format Input picture format. + * \return The bits per pixel amount of the picture format. + */ +INT32 Picture_FormatBPP(pictureformat_t format) +{ + INT32 bpp = PICDEPTH_NONE; + switch (format) + { + case PICFMT_PATCH32: + case PICFMT_FLAT32: + case PICFMT_PNG: + bpp = PICDEPTH_32BPP; + break; + case PICFMT_PATCH16: + case PICFMT_FLAT16: + bpp = PICDEPTH_16BPP; + break; + case PICFMT_PATCH: + case PICFMT_FLAT: + bpp = PICDEPTH_8BPP; + break; + default: + break; + } + return bpp; +} + +/** Checks if the specified picture format is a patch. + * + * \param format Input picture format. + * \return True if the picture format is a patch, false if not. + */ +boolean Picture_IsPatchFormat(pictureformat_t format) +{ + return (format == PICFMT_PATCH || format == PICFMT_PATCH16 || format == PICFMT_PATCH32); +} + +/** Checks if the specified picture format is a flat. + * + * \param format Input picture format. + * \return True if the picture format is a flat, false if not. + */ +boolean Picture_IsFlatFormat(pictureformat_t format) +{ + return (format == PICFMT_FLAT || format == PICFMT_FLAT16 || format == PICFMT_FLAT32); +} + +/** Returns true if the lump is a valid patch. + * PICFMT_PATCH only, I think?? + * + * \param patch Input patch. + * \param picture Input patch size. + * \return True if the input patch is valid. + */ +boolean Picture_CheckIfPatch(patch_t *patch, size_t size) +{ + INT16 width, height; + boolean result; + + // minimum length of a valid Doom patch + if (size < 13) + return false; + + width = SHORT(patch->width); + height = SHORT(patch->height); + result = (height > 0 && height <= 16384 && width > 0 && width <= 16384); + + if (result) + { + // The dimensions seem like they might be valid for a patch, so + // check the column directory for extra security. All columns + // must begin after the column directory, and none of them must + // point past the end of the patch. + INT16 x; + + for (x = 0; x < width; x++) + { + UINT32 ofs = LONG(patch->columnofs[x]); + + // Need one byte for an empty column (but there's patches that don't know that!) + if (ofs < (UINT32)width * 4 + 8 || ofs >= (UINT32)size) + { + result = false; + break; + } + } + } + + return result; +} + +/** Converts a texture to a flat. + * + * \param trickytex The texture number. + * \return The converted flat. + */ +void *Picture_TextureToFlat(size_t trickytex) +{ + texture_t *texture; + size_t tex; + + UINT8 *converted; + size_t flatsize; + fixed_t col, ofs; + column_t *column; + UINT8 *desttop, *dest, *deststop; + UINT8 *source; + + if (trickytex >= (unsigned)numtextures) + I_Error("Picture_TextureToFlat: invalid texture number!"); + + // Check the texture cache + // If the texture's not there, it'll be generated right now + tex = trickytex; + texture = textures[tex]; + R_CheckTextureCache(tex); + + // Allocate the flat + flatsize = (texture->width * texture->height); + converted = Z_Malloc(flatsize, PU_STATIC, NULL); + memset(converted, TRANSPARENTPIXEL, flatsize); + + // Now we're gonna write to it + desttop = converted; + deststop = desttop + flatsize; + for (col = 0; col < texture->width; col++, desttop++) + { + // no post_t info + if (!texture->holes) + { + column = (column_t *)(R_GetColumn(tex, col)); + source = (UINT8 *)(column); + dest = desttop; + for (ofs = 0; dest < deststop && ofs < texture->height; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + } + else + { + INT32 topdelta, prevdelta = -1; + column = (column_t *)((UINT8 *)R_GetColumn(tex, col) - 3); + while (column->topdelta != 0xff) + { + topdelta = column->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + + dest = desttop + (topdelta * texture->width); + source = (UINT8 *)column + 3; + for (ofs = 0; dest < deststop && ofs < column->length; ofs++) + { + if (source[ofs] != TRANSPARENTPIXEL) + *dest = source[ofs]; + dest += texture->width; + } + column = (column_t *)((UINT8 *)column + column->length + 4); + } + } + } + + return converted; +} + +/** Returns true if the lump is a valid PNG. + * + * \param d The lump to be checked. + * \param s The lump size. + * \return True if the lump is a PNG image. + */ +boolean Picture_IsLumpPNG(const UINT8 *d, size_t s) +{ + if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ + return false; + // Check for PNG file signature using memcmp + // As it may be faster on CPUs with slow unaligned memory access + // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature + return (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0); +} + +#ifndef NO_PNG_LUMPS +#ifdef HAVE_PNG + +/*#if PNG_LIBPNG_VER_DLLNUM < 14 +typedef PNG_CONST png_byte *png_const_bytep; +#endif*/ +typedef struct +{ + const UINT8 *buffer; + UINT32 size; + UINT32 position; +} png_io_t; + +static void PNG_IOReader(png_structp png_ptr, png_bytep data, png_size_t length) +{ + png_io_t *f = png_get_io_ptr(png_ptr); + if (length > (f->size - f->position)) + png_error(png_ptr, "PNG_IOReader: buffer overrun"); + memcpy(data, f->buffer + f->position, length); + f->position += length; +} + +typedef struct +{ + char name[4]; + void *data; + size_t size; +} png_chunk_t; + +static png_byte *chunkname = NULL; +static png_chunk_t chunk; + +static int PNG_ChunkReader(png_structp png_ptr, png_unknown_chunkp chonk) +{ + (void)png_ptr; + if (!memcmp(chonk->name, chunkname, 4)) + { + memcpy(chunk.name, chonk->name, 4); + chunk.size = chonk->size; + chunk.data = Z_Malloc(chunk.size, PU_STATIC, NULL); + memcpy(chunk.data, chonk->data, chunk.size); + return 1; + } + return 0; +} + +static void PNG_error(png_structp PNG, png_const_charp pngtext) +{ + CONS_Debug(DBG_RENDER, "libpng error at %p: %s", PNG, pngtext); + //I_Error("libpng error at %p: %s", PNG, pngtext); +} + +static void PNG_warn(png_structp PNG, png_const_charp pngtext) +{ + CONS_Debug(DBG_RENDER, "libpng warning at %p: %s", PNG, pngtext); +} + +static png_byte grAb_chunk[5] = {'g', 'r', 'A', 'b', (png_byte)'\0'}; + +static png_bytep *PNG_Read( + const UINT8 *png, + INT32 *w, INT32 *h, INT16 *topoffset, INT16 *leftoffset, + boolean *use_palette, size_t size) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_uint_32 width, height; + int bit_depth, color_type; + png_uint_32 y; + + png_colorp palette; + int palette_size; + + png_bytep trans; + int trans_num; + png_color_16p trans_values; + +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + png_io_t png_io; + png_bytep *row_pointers; + png_voidp *user_chunk_ptr; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); + if (!png_ptr) + I_Error("PNG_Read: Couldn't initialize libpng!"); + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + I_Error("PNG_Read: libpng couldn't allocate memory!"); + } + +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) +#endif + { + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + I_Error("PNG_Read: libpng load error!"); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); +#endif + + png_io.buffer = png; + png_io.size = size; + png_io.position = 0; + png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + + memset(&chunk, 0x00, sizeof(png_chunk_t)); + chunkname = grAb_chunk; // I want to read a grAb chunk + + user_chunk_ptr = png_get_user_chunk_ptr(png_ptr); + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, PNG_ChunkReader); + png_set_keep_unknown_chunks(png_ptr, 2, chunkname, 1); + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_set_user_limits(png_ptr, 2048, 2048); +#endif + + png_read_info(png_ptr, png_info_ptr); + png_get_IHDR(png_ptr, png_info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); + + if (bit_depth == 16) + png_set_strip_16(png_ptr); + + palette = NULL; + *use_palette = false; + + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + else if (color_type == PNG_COLOR_TYPE_PALETTE) + { + boolean usepal = false; + + // Lactozilla: Check if the PNG has a palette, and if its color count + // matches the color count of SRB2's palette: 256 colors. + if (png_get_PLTE(png_ptr, png_info_ptr, &palette, &palette_size)) + { + if (palette_size == 256) + usepal = true; + } + + // If any of the tRNS colors have an alpha lower than 0xFF, and that + // color is present on the image, the palette flag is disabled. + png_get_tRNS(png_ptr, png_info_ptr, &trans, &trans_num, &trans_values); + + if (trans && trans_num == 256) + { + int i; + for (i = 0; i < trans_num; i++) + { + // libpng will transform this image into RGB even if + // the transparent index does not exist in the image, + // and there is no way around that. + if (trans[i] < 0xFF) + { + usepal = false; + break; + } + } + } + + if (usepal) + *use_palette = true; + else + png_set_palette_to_rgb(png_ptr); + } + + if (png_get_valid(png_ptr, png_info_ptr, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_ptr); + else if (color_type != PNG_COLOR_TYPE_RGB_ALPHA && color_type != PNG_COLOR_TYPE_GRAY_ALPHA) + { +#if PNG_LIBPNG_VER < 10207 + png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER); +#else + png_set_add_alpha(png_ptr, 0xFF, PNG_FILLER_AFTER); +#endif + } + + png_read_update_info(png_ptr, png_info_ptr); + + // Read the image + row_pointers = (png_bytep*)malloc(sizeof(png_bytep) * height); + for (y = 0; y < height; y++) + row_pointers[y] = (png_byte*)malloc(png_get_rowbytes(png_ptr, png_info_ptr)); + png_read_image(png_ptr, row_pointers); + + // Read grAB chunk + if ((topoffset || leftoffset) && (chunk.data != NULL)) + { + INT32 *offsets = (INT32 *)chunk.data; + // read left offset + if (leftoffset != NULL) + *leftoffset = (INT16)BIGENDIAN_LONG(*offsets); + offsets++; + // read top offset + if (topoffset != NULL) + *topoffset = (INT16)BIGENDIAN_LONG(*offsets); + } + + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + if (chunk.data) + Z_Free(chunk.data); + + *w = (INT32)width; + *h = (INT32)height; + + return row_pointers; +} + +/** Converts a PNG to a picture. + * + * \param png The PNG image. + * \param outformat The output picture's format. + * \param w The output picture's width, as a pointer. + * \param h The output picture's height, as a pointer. + * \param topoffset The output picture's top offset, for sprites, as a pointer. + * \param leftoffset The output picture's left offset, for sprites, as a pointer. + * \param insize The input picture's size. + * \param outsize A pointer to the output picture's size. + * \param flags Input picture flags. + * \return A pointer to the converted picture. + */ +void *Picture_PNGConvert( + const UINT8 *png, pictureformat_t outformat, + INT32 *w, INT32 *h, + INT16 *topoffset, INT16 *leftoffset, + size_t insize, size_t *outsize, + pictureflags_t flags) +{ + void *flat; + INT32 outbpp; + size_t flatsize; + png_uint_32 x, y; + png_bytep row; + boolean palette = false; + png_bytep *row_pointers = NULL; + png_uint_32 width, height; + + INT32 pngwidth, pngheight; + INT16 loffs = 0, toffs = 0; + + if (png == NULL) + I_Error("Picture_PNGConvert: picture was NULL!"); + + if (w == NULL) + w = &pngwidth; + if (h == NULL) + h = &pngheight; + if (topoffset == NULL) + topoffset = &toffs; + if (leftoffset == NULL) + leftoffset = &loffs; + + row_pointers = PNG_Read(png, w, h, topoffset, leftoffset, &palette, insize); + width = *w; + height = *h; + + if (row_pointers == NULL) + I_Error("Picture_PNGConvert: row_pointers was NULL!"); + + // Find the output format's bits per pixel amount + outbpp = Picture_FormatBPP(outformat); + + // Hack for patches because you'll want to preserve transparency. + if (Picture_IsPatchFormat(outformat)) + { + // Force a higher bit depth + if (outbpp == PICDEPTH_8BPP) + outbpp = PICDEPTH_16BPP; + } + + // Shouldn't happen. + if (outbpp == PICDEPTH_NONE) + I_Error("Picture_PNGConvert: unknown output bits per pixel?!"); + + // Figure out the size + flatsize = (width * height) * (outbpp / 8); + if (outsize) + *outsize = flatsize; + + // Convert the image + flat = Z_Calloc(flatsize, PU_STATIC, NULL); + + // Set transparency + if (outbpp == PICDEPTH_8BPP) + memset(flat, TRANSPARENTPIXEL, (width * height)); + +#ifdef PICTURE_PNG_USELOOKUP + if (outbpp != PICDEPTH_32BPP) + InitColorLUT(&png_colorlookup, pMasterPalette, false); +#endif + + if (outbpp == PICDEPTH_32BPP) + { + RGBA_t out; + UINT32 *outflat = (UINT32 *)flat; + + if (palette) + { + for (y = 0; y < height; y++) + { + row = row_pointers[y]; + for (x = 0; x < width; x++) + { + out = V_GetColor(row[x]); + outflat[((y * width) + x)] = out.rgba; + } + } + } + else + { + for (y = 0; y < height; y++) + { + row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_bytep px = &(row[x * 4]); + if ((UINT8)px[3]) + { + out.s.red = (UINT8)px[0]; + out.s.green = (UINT8)px[1]; + out.s.blue = (UINT8)px[2]; + out.s.alpha = (UINT8)px[3]; + outflat[((y * width) + x)] = out.rgba; + } + else + outflat[((y * width) + x)] = 0x00000000; + } + } + } + } + else if (outbpp == PICDEPTH_16BPP) + { + UINT16 *outflat = (UINT16 *)flat; + + if (palette) + { + for (y = 0; y < height; y++) + { + row = row_pointers[y]; + for (x = 0; x < width; x++) + outflat[((y * width) + x)] = (0xFF << 8) | row[x]; + } + } + else + { + for (y = 0; y < height; y++) + { + row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_bytep px = &(row[x * 4]); + UINT8 red = (UINT8)px[0]; + UINT8 green = (UINT8)px[1]; + UINT8 blue = (UINT8)px[2]; + UINT8 alpha = (UINT8)px[3]; + + if (alpha) + { +#ifdef PICTURE_PNG_USELOOKUP + UINT8 palidx = GetColorLUT(&png_colorlookup, red, green, blue); +#else + UINT8 palidx = NearestColor(red, green, blue); +#endif + outflat[((y * width) + x)] = (0xFF << 8) | palidx; + } + else + outflat[((y * width) + x)] = 0x0000; + } + } + } + } + else // 8bpp + { + UINT8 *outflat = (UINT8 *)flat; + + if (palette) + { + for (y = 0; y < height; y++) + { + row = row_pointers[y]; + for (x = 0; x < width; x++) + outflat[((y * width) + x)] = row[x]; + } + } + else + { + for (y = 0; y < height; y++) + { + row = row_pointers[y]; + for (x = 0; x < width; x++) + { + png_bytep px = &(row[x * 4]); + UINT8 red = (UINT8)px[0]; + UINT8 green = (UINT8)px[1]; + UINT8 blue = (UINT8)px[2]; + UINT8 alpha = (UINT8)px[3]; + + if (alpha) + { +#ifdef PICTURE_PNG_USELOOKUP + UINT8 palidx = GetColorLUT(&png_colorlookup, red, green, blue); +#else + UINT8 palidx = NearestColor(red, green, blue); +#endif + outflat[((y * width) + x)] = palidx; + } + } + } + } + } + + // Free the row pointers that we allocated for libpng. + for (y = 0; y < height; y++) + free(row_pointers[y]); + free(row_pointers); + + // But wait, there's more! + if (Picture_IsPatchFormat(outformat)) + { + void *converted; + pictureformat_t informat = PICFMT_NONE; + + // Figure out the format of the flat, from the bit depth of the output format + switch (outbpp) + { + case 32: + informat = PICFMT_FLAT32; + break; + case 16: + informat = PICFMT_FLAT16; + break; + default: + informat = PICFMT_FLAT; + break; + } + + // Now, convert it! + converted = Picture_PatchConvert(informat, flat, outformat, insize, outsize, (INT16)width, (INT16)height, *leftoffset, *topoffset, flags); + Z_Free(flat); + return converted; + } + + // Return the converted flat! + return flat; +} + +/** Returns the dimensions of a PNG image, but doesn't perform any conversions. + * + * \param png The PNG image. + * \param width A pointer to the input picture's width. + * \param height A pointer to the input picture's height. + * \param topoffset A pointer to the input picture's vertical offset. + * \param leftoffset A pointer to the input picture's horizontal offset. + * \param size The input picture's size. + * \return True if reading the file succeeded, false if it failed. + */ +boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size) +{ + png_structp png_ptr; + png_infop png_info_ptr; + png_uint_32 w, h; + int bit_depth, color_type; +#ifdef PNG_SETJMP_SUPPORTED +#ifdef USE_FAR_KEYWORD + jmp_buf jmpbuf; +#endif +#endif + + png_io_t png_io; + png_voidp *user_chunk_ptr; + + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, PNG_error, PNG_warn); + if (!png_ptr) + I_Error("Picture_PNGDimensions: Couldn't initialize libpng!"); + + png_info_ptr = png_create_info_struct(png_ptr); + if (!png_info_ptr) + { + png_destroy_read_struct(&png_ptr, NULL, NULL); + I_Error("Picture_PNGDimensions: libpng couldn't allocate memory!"); + } + +#ifdef USE_FAR_KEYWORD + if (setjmp(jmpbuf)) +#else + if (setjmp(png_jmpbuf(png_ptr))) +#endif + { + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + I_Error("Picture_PNGDimensions: libpng load error!"); + } +#ifdef USE_FAR_KEYWORD + png_memcpy(png_jmpbuf(png_ptr), jmpbuf, sizeof jmp_buf); +#endif + + png_io.buffer = png; + png_io.size = size; + png_io.position = 0; + png_set_read_fn(png_ptr, &png_io, PNG_IOReader); + + memset(&chunk, 0x00, sizeof(png_chunk_t)); + chunkname = grAb_chunk; // I want to read a grAb chunk + + user_chunk_ptr = png_get_user_chunk_ptr(png_ptr); + png_set_read_user_chunk_fn(png_ptr, user_chunk_ptr, PNG_ChunkReader); + png_set_keep_unknown_chunks(png_ptr, 2, chunkname, 1); + +#ifdef PNG_SET_USER_LIMITS_SUPPORTED + png_set_user_limits(png_ptr, 2048, 2048); +#endif + + png_read_info(png_ptr, png_info_ptr); + png_get_IHDR(png_ptr, png_info_ptr, &w, &h, &bit_depth, &color_type, NULL, NULL, NULL); + + // Read grAB chunk + if ((topoffset || leftoffset) && (chunk.data != NULL)) + { + INT32 *offsets = (INT32 *)chunk.data; + // read left offset + if (leftoffset != NULL) + *leftoffset = (INT16)BIGENDIAN_LONG(*offsets); + offsets++; + // read top offset + if (topoffset != NULL) + *topoffset = (INT16)BIGENDIAN_LONG(*offsets); + } + + png_destroy_read_struct(&png_ptr, &png_info_ptr, NULL); + if (chunk.data) + Z_Free(chunk.data); + + *width = (INT32)w; + *height = (INT32)h; + return true; +} +#endif +#endif + +// +// R_ParseSpriteInfoFrame +// +// Parse a SPRTINFO frame. +// +static void R_ParseSpriteInfoFrame(spriteinfo_t *info) +{ + char *sprinfoToken; + size_t sprinfoTokenLength; + char *frameChar = NULL; + UINT8 frameFrame = 0xFF; + INT16 frameXPivot = 0; + INT16 frameYPivot = 0; + rotaxis_t frameRotAxis = 0; + + // Sprite identifier + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite frame should be"); + } + sprinfoTokenLength = strlen(sprinfoToken); + if (sprinfoTokenLength != 1) + { + I_Error("Error parsing SPRTINFO lump: Invalid frame \"%s\"",sprinfoToken); + } + else + frameChar = sprinfoToken; + + frameFrame = R_Char2Frame(frameChar[0]); + Z_Free(sprinfoToken); + + // Left Curly Brace + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + I_Error("Error parsing SPRTINFO lump: Missing sprite info"); + else + { + if (strcmp(sprinfoToken,"{")==0) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info should be"); + } + while (strcmp(sprinfoToken,"}")!=0) + { + if (stricmp(sprinfoToken, "XPIVOT")==0) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + frameXPivot = atoi(sprinfoToken); + } + else if (stricmp(sprinfoToken, "YPIVOT")==0) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + frameYPivot = atoi(sprinfoToken); + } + else if (stricmp(sprinfoToken, "ROTAXIS")==0) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + if ((stricmp(sprinfoToken, "X")==0) || (stricmp(sprinfoToken, "XAXIS")==0) || (stricmp(sprinfoToken, "ROLL")==0)) + frameRotAxis = ROTAXIS_X; + else if ((stricmp(sprinfoToken, "Y")==0) || (stricmp(sprinfoToken, "YAXIS")==0) || (stricmp(sprinfoToken, "PITCH")==0)) + frameRotAxis = ROTAXIS_Y; + else if ((stricmp(sprinfoToken, "Z")==0) || (stricmp(sprinfoToken, "ZAXIS")==0) || (stricmp(sprinfoToken, "YAW")==0)) + frameRotAxis = ROTAXIS_Z; + } + Z_Free(sprinfoToken); + + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info or right curly brace should be"); + } + } + } + Z_Free(sprinfoToken); + } + + // set fields + info->pivot[frameFrame].x = frameXPivot; + info->pivot[frameFrame].y = frameYPivot; + info->pivot[frameFrame].rotaxis = frameRotAxis; +} + +// +// R_ParseSpriteInfo +// +// Parse a SPRTINFO lump. +// +static void R_ParseSpriteInfo(boolean spr2) +{ + spriteinfo_t *info; + char *sprinfoToken; + size_t sprinfoTokenLength; + char newSpriteName[5]; // no longer dynamically allocated + spritenum_t sprnum = NUMSPRITES; + playersprite_t spr2num = NUMPLAYERSPRITES; + INT32 i; + INT32 skinnumbers[MAXSKINS]; + INT32 foundskins = 0; + + // Sprite name + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite name should be"); + } + sprinfoTokenLength = strlen(sprinfoToken); + if (sprinfoTokenLength != 4) + { + I_Error("Error parsing SPRTINFO lump: Sprite name \"%s\" isn't 4 characters long",sprinfoToken); + } + else + { + memset(&newSpriteName, 0, 5); + M_Memcpy(newSpriteName, sprinfoToken, sprinfoTokenLength); + // ^^ we've confirmed that the token is == 4 characters so it will never overflow a 5 byte char buffer + strupr(newSpriteName); // Just do this now so we don't have to worry about it + } + Z_Free(sprinfoToken); + + if (!spr2) + { + for (i = 0; i <= NUMSPRITES; i++) + { + if (i == NUMSPRITES) + I_Error("Error parsing SPRTINFO lump: Unknown sprite name \"%s\"", newSpriteName); + if (!memcmp(newSpriteName,sprnames[i],4)) + { + sprnum = i; + break; + } + } + } + else + { + for (i = 0; i <= NUMPLAYERSPRITES; i++) + { + if (i == NUMPLAYERSPRITES) + I_Error("Error parsing SPRTINFO lump: Unknown sprite2 name \"%s\"", newSpriteName); + if (!memcmp(newSpriteName,spr2names[i],4)) + { + spr2num = i; + break; + } + } + } + + // allocate a spriteinfo + info = Z_Calloc(sizeof(spriteinfo_t), PU_STATIC, NULL); + info->available = true; + +#ifdef ROTSPRITE + if ((sprites != NULL) && (!spr2)) + R_FreeSingleRotSprite(&sprites[sprnum]); +#endif + + // Left Curly Brace + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where open curly brace for sprite \"%s\" should be",newSpriteName); + } + if (strcmp(sprinfoToken,"{")==0) + { + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where definition for sprite \"%s\" should be",newSpriteName); + } + while (strcmp(sprinfoToken,"}")!=0) + { + if (stricmp(sprinfoToken, "SKIN")==0) + { + INT32 skinnum; + char *skinName = NULL; + if (!spr2) + I_Error("Error parsing SPRTINFO lump: \"SKIN\" token found outside of a sprite2 definition"); + + Z_Free(sprinfoToken); + + // Skin name + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where skin frame should be"); + } + + // copy skin name yada yada + sprinfoTokenLength = strlen(sprinfoToken); + skinName = (char *)Z_Malloc((sprinfoTokenLength+1)*sizeof(char),PU_STATIC,NULL); + M_Memcpy(skinName,sprinfoToken,sprinfoTokenLength*sizeof(char)); + skinName[sprinfoTokenLength] = '\0'; + strlwr(skinName); + Z_Free(sprinfoToken); + + skinnum = R_SkinAvailable(skinName); + if (skinnum == -1) + I_Error("Error parsing SPRTINFO lump: Unknown skin \"%s\"", skinName); + + skinnumbers[foundskins] = skinnum; + foundskins++; + } + else if (stricmp(sprinfoToken, "FRAME")==0) + { + R_ParseSpriteInfoFrame(info); + Z_Free(sprinfoToken); + if (spr2) + { + if (!foundskins) + I_Error("Error parsing SPRTINFO lump: No skins specified in this sprite2 definition"); + for (i = 0; i < foundskins; i++) + { + size_t skinnum = skinnumbers[i]; + skin_t *skin = &skins[skinnum]; + spriteinfo_t *sprinfo = skin->sprinfo; +#ifdef ROTSPRITE + R_FreeSkinRotSprite(skinnum); +#endif + M_Memcpy(&sprinfo[spr2num], info, sizeof(spriteinfo_t)); + } + } + else + M_Memcpy(&spriteinfo[sprnum], info, sizeof(spriteinfo_t)); + } + else + { + I_Error("Error parsing SPRTINFO lump: Unknown keyword \"%s\" in sprite %s",sprinfoToken,newSpriteName); + } + + sprinfoToken = M_GetToken(NULL); + if (sprinfoToken == NULL) + { + I_Error("Error parsing SPRTINFO lump: Unexpected end of file where sprite info or right curly brace for sprite \"%s\" should be",newSpriteName); + } + } + } + else + { + I_Error("Error parsing SPRTINFO lump: Expected \"{\" for sprite \"%s\", got \"%s\"",newSpriteName,sprinfoToken); + } + Z_Free(sprinfoToken); + Z_Free(info); +} + +// +// R_ParseSPRTINFOLump +// +// Read a SPRTINFO lump. +// +void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum) +{ + char *sprinfoLump; + size_t sprinfoLumpLength; + char *sprinfoText; + char *sprinfoToken; + + // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll + // need to make a space of memory where I can ensure that it will terminate + // correctly. Start by loading the relevant data from the WAD. + sprinfoLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); + // If that didn't exist, we have nothing to do here. + if (sprinfoLump == NULL) return; + // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. + sprinfoLumpLength = W_LumpLengthPwad(wadNum, lumpNum); + sprinfoText = (char *)Z_Malloc((sprinfoLumpLength+1)*sizeof(char),PU_STATIC,NULL); + // Now move the contents of the lump into this new location. + memmove(sprinfoText,sprinfoLump,sprinfoLumpLength); + // Make damn well sure the last character in our new memory location is \0. + sprinfoText[sprinfoLumpLength] = '\0'; + // Finally, free up the memory from the first data load, because we really + // don't need it. + Z_Free(sprinfoLump); + + sprinfoToken = M_GetToken(sprinfoText); + while (sprinfoToken != NULL) + { + if (!stricmp(sprinfoToken, "SPRITE")) + R_ParseSpriteInfo(false); + else if (!stricmp(sprinfoToken, "SPRITE2")) + R_ParseSpriteInfo(true); + else + I_Error("Error parsing SPRTINFO lump: Unknown keyword \"%s\"", sprinfoToken); + Z_Free(sprinfoToken); + sprinfoToken = M_GetToken(NULL); + } + Z_Free((void *)sprinfoText); +} + +// +// R_LoadSpriteInfoLumps +// +// Load and read every SPRTINFO lump from the specified file. +// +void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps) +{ + lumpinfo_t *lumpinfo = wadfiles[wadnum]->lumpinfo; + UINT16 i; + char *name; + + for (i = 0; i < numlumps; i++, lumpinfo++) + { + name = lumpinfo->name; + // Load SPRTINFO and SPR_ lumps as SpriteInfo + if (!memcmp(name, "SPRTINFO", 8) || !memcmp(name, "SPR_", 4)) + R_ParseSPRTINFOLump(wadnum, i); + } +} + +#ifdef ROTSPRITE +// +// R_GetRollAngle +// +// Angles precalculated in R_InitSprites. +// +fixed_t rollcosang[ROTANGLES]; +fixed_t rollsinang[ROTANGLES]; +INT32 R_GetRollAngle(angle_t rollangle) +{ + INT32 ra = AngleFixed(rollangle)>>FRACBITS; +#if (ROTANGDIFF > 1) + ra += (ROTANGDIFF/2); +#endif + ra /= ROTANGDIFF; + ra %= ROTANGLES; + return ra; +} + +// +// R_CacheRotSprite +// +// Create a rotated sprite. +// +void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip) +{ + INT32 angle; + patch_t *patch; + patch_t *newpatch; + UINT16 *rawdst; + size_t size; + pictureflags_t bflip = (flip) ? PICFLAGS_XFLIP : 0; + +#define SPRITE_XCENTER (leftoffset) +#define SPRITE_YCENTER (height / 2) +#define ROTSPRITE_XCENTER (newwidth / 2) +#define ROTSPRITE_YCENTER (newheight / 2) + + if (!(sprframe->rotsprite.cached & (1<lumppat[rot]; +#ifndef NO_PNG_LUMPS + size_t lumplength; +#endif + + if (lump == LUMPERROR) + return; + + patch = (patch_t *)W_CacheLumpNum(lump, PU_STATIC); +#ifndef NO_PNG_LUMPS + lumplength = W_LumpLength(lump); + + if (Picture_IsLumpPNG((const UINT8 *)patch, lumplength)) + patch = (patch_t *)Picture_PNGConvert((const UINT8 *)patch, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); + else +#endif + // Because there's something wrong with SPR_DFLM, I guess + if (!Picture_CheckIfPatch(patch, lumplength)) + return; + + width = SHORT(patch->width); + height = SHORT(patch->height); + leftoffset = SHORT(patch->leftoffset); + + // rotation pivot + px = SPRITE_XCENTER; + py = SPRITE_YCENTER; + + // get correct sprite info for sprite + if (sprinfo == NULL) + sprinfo = &spriteinfo[sprnum]; + if (sprinfo->available) + { + px = sprinfo->pivot[frame].x; + py = sprinfo->pivot[frame].y; + } + if (bflip) + { + px = width - px; + leftoffset = width - leftoffset; + } + + // Don't cache angle = 0 + for (angle = 1; angle < ROTANGLES; angle++) + { + INT32 newwidth, newheight; + + ca = rollcosang[angle]; + sa = rollsinang[angle]; + + // Find the dimensions of the rotated patch. + { + INT32 w1 = abs(FixedMul(width << FRACBITS, ca) - FixedMul(height << FRACBITS, sa)); + INT32 w2 = abs(FixedMul(-(width << FRACBITS), ca) - FixedMul(height << FRACBITS, sa)); + INT32 h1 = abs(FixedMul(width << FRACBITS, sa) + FixedMul(height << FRACBITS, ca)); + INT32 h2 = abs(FixedMul(-(width << FRACBITS), sa) + FixedMul(height << FRACBITS, ca)); + w1 = FixedInt(FixedCeil(w1 + (FRACUNIT/2))); + w2 = FixedInt(FixedCeil(w2 + (FRACUNIT/2))); + h1 = FixedInt(FixedCeil(h1 + (FRACUNIT/2))); + h2 = FixedInt(FixedCeil(h2 + (FRACUNIT/2))); + newwidth = max(width, max(w1, w2)); + newheight = max(height, max(h1, h2)); + } + + // check boundaries + { + fixed_t top[2][2]; + fixed_t bottom[2][2]; + + top[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); + top[0][1] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); + top[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); + top[1][1] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); + + bottom[0][0] = FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); + bottom[0][1] = -FixedMul((-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); + bottom[1][0] = FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, ca) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, sa) + (px << FRACBITS); + bottom[1][1] = -FixedMul((newwidth-ROTSPRITE_XCENTER) << FRACBITS, sa) + FixedMul((newheight-ROTSPRITE_YCENTER) << FRACBITS, ca) + (py << FRACBITS); + + top[0][0] >>= FRACBITS; + top[0][1] >>= FRACBITS; + top[1][0] >>= FRACBITS; + top[1][1] >>= FRACBITS; + + bottom[0][0] >>= FRACBITS; + bottom[0][1] >>= FRACBITS; + bottom[1][0] >>= FRACBITS; + bottom[1][1] >>= FRACBITS; + +#define BOUNDARYWCHECK(b) (b[0] < 0 || b[0] >= width) +#define BOUNDARYHCHECK(b) (b[1] < 0 || b[1] >= height) +#define BOUNDARYADJUST(x) x *= 2 + // top left/right + if (BOUNDARYWCHECK(top[0]) || BOUNDARYWCHECK(top[1])) + BOUNDARYADJUST(newwidth); + // bottom left/right + else if (BOUNDARYWCHECK(bottom[0]) || BOUNDARYWCHECK(bottom[1])) + BOUNDARYADJUST(newwidth); + // top left/right + if (BOUNDARYHCHECK(top[0]) || BOUNDARYHCHECK(top[1])) + BOUNDARYADJUST(newheight); + // bottom left/right + else if (BOUNDARYHCHECK(bottom[0]) || BOUNDARYHCHECK(bottom[1])) + BOUNDARYADJUST(newheight); +#undef BOUNDARYWCHECK +#undef BOUNDARYHCHECK +#undef BOUNDARYADJUST + } + + // Draw the rotated sprite to a temporary buffer. + size = (newwidth * newheight); + if (!size) + size = (width * height); + rawdst = Z_Calloc(size * sizeof(UINT16), PU_STATIC, NULL); + + for (dy = 0; dy < newheight; dy++) + { + for (dx = 0; dx < newwidth; dx++) + { + INT32 x = (dx-ROTSPRITE_XCENTER) << FRACBITS; + INT32 y = (dy-ROTSPRITE_YCENTER) << FRACBITS; + INT32 sx = FixedMul(x, ca) + FixedMul(y, sa) + (px << FRACBITS); + INT32 sy = -FixedMul(x, sa) + FixedMul(y, ca) + (py << FRACBITS); + sx >>= FRACBITS; + sy >>= FRACBITS; + if (sx >= 0 && sy >= 0 && sx < width && sy < height) + { + void *input = Picture_GetPatchPixel(patch, PICFMT_PATCH, sx, sy, bflip); + if (input != NULL) + rawdst[(dy*newwidth)+dx] = (0xFF00 | (*(UINT8 *)input)); + } + } + } + + // make patch + newpatch = (patch_t *)Picture_Convert(PICFMT_FLAT16, rawdst, PICFMT_PATCH, 0, &size, newwidth, newheight, 0, 0, 0); + { + newpatch->leftoffset = (newpatch->width / 2) + (leftoffset - px); + newpatch->topoffset = (newpatch->height / 2) + (SHORT(patch->topoffset) - py); + } + + //BP: we cannot use special tric in hardware mode because feet in ground caused by z-buffer + if (rendermode != render_none) // not for psprite + newpatch->topoffset += FEETADJUST>>FRACBITS; + + // P_PrecacheLevel + if (devparm) spritememory += size; + + // convert everything to little-endian, for big-endian support + newpatch->width = SHORT(newpatch->width); + newpatch->height = SHORT(newpatch->height); + newpatch->leftoffset = SHORT(newpatch->leftoffset); + newpatch->topoffset = SHORT(newpatch->topoffset); + +#ifdef HWRENDER + if (rendermode == render_opengl) + { + GLPatch_t *grPatch = Z_Calloc(sizeof(GLPatch_t), PU_HWRPATCHINFO, NULL); + grPatch->mipmap = Z_Calloc(sizeof(GLMipmap_t), PU_HWRPATCHINFO, NULL); + grPatch->rawpatch = newpatch; + sprframe->rotsprite.patch[rot][angle] = (patch_t *)grPatch; + HWR_MakePatch(newpatch, grPatch, grPatch->mipmap, false); + } + else +#endif // HWRENDER + sprframe->rotsprite.patch[rot][angle] = newpatch; + + // free rotated image data + Z_Free(rawdst); + } + + // This rotation is cached now + sprframe->rotsprite.cached |= (1<numframes; frame++) + { + spriteframe_t *sprframe = &spritedef->spriteframes[frame]; + for (rot = 0; rot < 16; rot++) + { + if (sprframe->rotsprite.cached & (1<rotsprite.patch[rot][ang]; + if (rotsprite) + { +#ifdef HWRENDER + if (rendermode == render_opengl) + { + GLPatch_t *grPatch = (GLPatch_t *)rotsprite; + if (grPatch->rawpatch) + { + Z_Free(grPatch->rawpatch); + grPatch->rawpatch = NULL; + } + if (grPatch->mipmap) + { + if (grPatch->mipmap->data) + { + Z_Free(grPatch->mipmap->data); + grPatch->mipmap->data = NULL; + } + Z_Free(grPatch->mipmap); + grPatch->mipmap = NULL; + } + } +#endif + Z_Free(rotsprite); + } + } + sprframe->rotsprite.cached &= ~(1<sprites; + for (i = 0; i < NUMPLAYERSPRITES*2; i++) + { + R_FreeSingleRotSprite(skinsprites); + skinsprites++; + } +} + +// +// R_FreeAllRotSprite +// +// Free ALL sprite rotation data from memory. +// +void R_FreeAllRotSprite(void) +{ + INT32 i; + size_t s; + for (s = 0; s < numsprites; s++) + R_FreeSingleRotSprite(&sprites[s]); + for (i = 0; i < numskins; ++i) + R_FreeSkinRotSprite(i); +} +#endif diff --git a/src/r_picformats.h b/src/r_picformats.h new file mode 100644 index 000000000..3ee76a92f --- /dev/null +++ b/src/r_picformats.h @@ -0,0 +1,134 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 2018-2020 by Jaime "Lactozilla" Passos. +// Copyright (C) 2019-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_picformats.h +/// \brief Patch generation. + +#ifndef __R_PICFORMATS__ +#define __R_PICFORMATS__ + +#include "r_defs.h" +#include "doomdef.h" + +typedef enum +{ + PICFMT_NONE = 0, + + // Doom formats + PICFMT_PATCH, + PICFMT_FLAT, + + // PNG + PICFMT_PNG, + + // 16bpp + PICFMT_PATCH16, + PICFMT_FLAT16, + + // 32bpp + PICFMT_PATCH32, + PICFMT_FLAT32 +} pictureformat_t; + +typedef enum +{ + PICFLAGS_XFLIP = 1, + PICFLAGS_YFLIP = 1<<1 +} pictureflags_t; + +enum +{ + PICDEPTH_NONE = 0, + PICDEPTH_8BPP = 8, + PICDEPTH_16BPP = 16, + PICDEPTH_32BPP = 32 +}; + +void *Picture_Convert( + pictureformat_t informat, void *picture, pictureformat_t outformat, + size_t insize, size_t *outsize, + INT32 inwidth, INT32 inheight, INT32 inleftoffset, INT32 intopoffset, + pictureflags_t flags); + +void *Picture_PatchConvert( + pictureformat_t informat, void *picture, pictureformat_t outformat, + size_t insize, size_t *outsize, + INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset, + pictureflags_t flags); +void *Picture_FlatConvert( + pictureformat_t informat, void *picture, pictureformat_t outformat, + size_t insize, size_t *outsize, + INT16 inwidth, INT16 inheight, INT16 inleftoffset, INT16 intopoffset, + pictureflags_t flags); +void *Picture_GetPatchPixel( + patch_t *patch, pictureformat_t informat, + INT32 x, INT32 y, + pictureflags_t flags); + +void *Picture_TextureToFlat(size_t trickytex); + +INT32 Picture_FormatBPP(pictureformat_t format); +boolean Picture_IsPatchFormat(pictureformat_t format); +boolean Picture_IsFlatFormat(pictureformat_t format); +boolean Picture_CheckIfPatch(patch_t *patch, size_t size); + +// Structs +typedef enum +{ + ROTAXIS_X, // Roll (the default) + ROTAXIS_Y, // Pitch + ROTAXIS_Z // Yaw +} rotaxis_t; + +typedef struct +{ + INT32 x, y; + rotaxis_t rotaxis; +} spriteframepivot_t; + +typedef struct +{ + spriteframepivot_t pivot[64]; + boolean available; +} spriteinfo_t; + +// Portable Network Graphics +boolean Picture_IsLumpPNG(const UINT8 *d, size_t s); +#define Picture_ThrowPNGError(lumpname, wadfilename) I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .png - please convert to either Doom or Flat (raw) image format.", lumpname, wadfilename); // Fears Of LJ Sonic + +#ifndef NO_PNG_LUMPS +void *Picture_PNGConvert( + const UINT8 *png, pictureformat_t outformat, + INT32 *w, INT32 *h, + INT16 *topoffset, INT16 *leftoffset, + size_t insize, size_t *outsize, + pictureflags_t flags); +boolean Picture_PNGDimensions(UINT8 *png, INT32 *width, INT32 *height, INT16 *topoffset, INT16 *leftoffset, size_t size); +#endif + +#define PICTURE_PNG_USELOOKUP + +// SpriteInfo +extern spriteinfo_t spriteinfo[NUMSPRITES]; +void R_LoadSpriteInfoLumps(UINT16 wadnum, UINT16 numlumps); +void R_ParseSPRTINFOLump(UINT16 wadNum, UINT16 lumpNum); + +// Sprite rotation +#ifdef ROTSPRITE +INT32 R_GetRollAngle(angle_t rollangle); +void R_CacheRotSprite(spritenum_t sprnum, UINT8 frame, spriteinfo_t *sprinfo, spriteframe_t *sprframe, INT32 rot, UINT8 flip); +void R_FreeSingleRotSprite(spritedef_t *spritedef); +void R_FreeSkinRotSprite(size_t skinnum); +extern fixed_t rollcosang[ROTANGLES]; +extern fixed_t rollsinang[ROTANGLES]; +void R_FreeAllRotSprite(void); +#endif + +#endif // __R_PATCH__ diff --git a/src/r_plane.c b/src/r_plane.c index 3a6bf4982..7770d2d12 100644 --- a/src/r_plane.c +++ b/src/r_plane.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,10 +19,13 @@ #include "p_setup.h" // levelflats #include "p_slopes.h" #include "r_data.h" +#include "r_textures.h" #include "r_local.h" #include "r_state.h" #include "r_splats.h" // faB(21jan):testing #include "r_sky.h" +#include "r_portal.h" + #include "v_video.h" #include "w_wad.h" #include "z_zone.h" @@ -42,13 +45,9 @@ // Quincunx antialiasing of flats! //#define QUINCUNX -// good night sweet prince -//#define SHITPLANESPARENCY - //SoM: 3/23/2000: Use Boom visplane hashing. -#define MAXVISPLANES 512 -static visplane_t *visplanes[MAXVISPLANES]; +visplane_t *visplanes[MAXVISPLANES]; static visplane_t *freetail; static visplane_t **freehead = &freetail; @@ -61,7 +60,7 @@ INT32 numffloors; //SoM: 3/23/2000: Boom visplane hashing routine. #define visplane_hash(picnum,lightlevel,height) \ - ((unsigned)((picnum)*3+(lightlevel)+(height)*7) & (MAXVISPLANES-1)) + ((unsigned)((picnum)*3+(lightlevel)+(height)*7) & VISPLANEHASHMASK) //SoM: 3/23/2000: Use boom opening limit removal size_t maxopenings; @@ -94,7 +93,7 @@ static fixed_t planeheight; // (this is to calculate yslopes only when really needed) // (when mouselookin', yslope is moving into yslopetab) // Check R_SetupFrame, R_SetViewSize for more... -fixed_t yslopetab[MAXVIDHEIGHT*16]; +fixed_t yslopetab[MAXSPLITSCREENPLAYERS][MAXVIDHEIGHT*16]; fixed_t *yslope; fixed_t basexscale, baseyscale; @@ -115,49 +114,34 @@ void R_InitPlanes(void) // FIXME: unused } -// R_PortalStoreClipValues -// Saves clipping values for later. -Red -void R_PortalStoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale) -{ - INT32 i; - for (i = 0; i < end-start; i++) - { - *ceil = ceilingclip[start+i]; - ceil++; - *floor = floorclip[start+i]; - floor++; - *scale = frontscale[start+i]; - scale++; - } -} +// +// Water ripple effect!! +// Needs the height of the plane, and the vertical position of the span. +// Sets ripple_xfrac and ripple_yfrac, added to ds_xfrac and ds_yfrac, if the span is not tilted. +// -// R_PortalRestoreClipValues -// Inverse of the above. Restores the old value! -void R_PortalRestoreClipValues(INT32 start, INT32 end, INT16 *ceil, INT16 *floor, fixed_t *scale) -{ - INT32 i; - for (i = 0; i < end-start; i++) - { - ceilingclip[start+i] = *ceil; - ceil++; - floorclip[start+i] = *floor; - floor++; - frontscale[start+i] = *scale; - scale++; - } +#ifndef NOWATER +INT32 ds_bgofs; +INT32 ds_waterofs; - // HACKS FOLLOW - for (i = 0; i < start; i++) - { - floorclip[i] = -1; - ceilingclip[i] = (INT16)viewheight; - } - for (i = end; i < vid.width; i++) - { - floorclip[i] = -1; - ceilingclip[i] = (INT16)viewheight; - } +static INT32 wtofs=0; +static boolean itswater; +static fixed_t ripple_xfrac; +static fixed_t ripple_yfrac; + +static void R_PlaneRipple(visplane_t *plane, INT32 y, fixed_t plheight) +{ + fixed_t distance = FixedMul(plheight, yslope[y]); + const INT32 yay = (wtofs + (distance>>9) ) & 8191; + // ripples da water texture + angle_t angle = (plane->viewangle + plane->plangle)>>ANGLETOFINESHIFT; + ds_bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; + + angle = (angle + 2048) & 8191; // 90 degrees + ripple_xfrac = FixedMul(FINECOSINE(angle), (ds_bgofs< 64 the amount of precision we can allow will decrease, but only by one - // bit per power of two (obviously) - // Ok, because I was able to eliminate the variable spot below, this function is now FASTER - // than the original span renderer. Whodathunkit? - xposition = ds_xfrac << nflatshiftup; yposition = (ds_yfrac + waterofs) << nflatshiftup; - xstep = ds_xstep << nflatshiftup; ystep = ds_ystep << nflatshiftup; - - source = ds_source; - colormap = ds_colormap; - dest = ylookup[ds_y] + columnofs[ds_x1]; - dsrc = screens[1] + (ds_y+bgofs)*vid.width + ds_x1; - count = ds_x2 - ds_x1 + 1; - - while (count >= 8) - { - // SoM: Why didn't I see this earlier? the spot variable is a waste now because we don't - // have the uber complicated math to calculate it now, so that was a memory write we didn't - // need! - dest[0] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[1] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[2] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[3] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[4] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[5] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[6] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest[7] = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - - dest += 8; - count -= 8; - } - while (count--) - { - *dest++ = colormap[*(ds_transmap + (source[((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift)] << 8) + *dsrc++)]; - xposition += xstep; - yposition += ystep; - } -} -#endif - void R_MapPlane(INT32 y, INT32 x1, INT32 x2) { angle_t angle, planecos, planesin; @@ -302,19 +200,25 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) #ifndef NOWATER if (itswater) { - const INT32 yay = (wtofs + (distance>>9) ) & 8191; - // ripples da water texture - bgofs = FixedDiv(FINESINE(yay), (1<<12) + (distance>>11))>>FRACBITS; - angle = (currentplane->viewangle + currentplane->plangle + xtoviewangle[x1])>>ANGLETOFINESHIFT; + // Needed for ds_bgofs + R_PlaneRipple(currentplane, y, planeheight); - angle = (angle + 2048) & 8191; // 90 degrees - ds_xfrac += FixedMul(FINECOSINE(angle), (bgofs<slope) + { + ds_sup = &ds_su[y]; + ds_svp = &ds_sv[y]; + ds_szp = &ds_sz[y]; + } + else + { + ds_xfrac += ripple_xfrac; + ds_yfrac += ripple_yfrac; + } - if (y+bgofs>=viewheight) - bgofs = viewheight-y-1; - if (y+bgofs<0) - bgofs = -y; + if (y+ds_bgofs>=viewheight) + ds_bgofs = viewheight-y-1; + if (y+ds_bgofs<0) + ds_bgofs = -y; } #endif @@ -322,12 +226,11 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) if (pindex >= MAXLIGHTZ) pindex = MAXLIGHTZ - 1; -#ifdef ESLOPE if (currentplane->slope) ds_colormap = colormaps; else -#endif - ds_colormap = planezlight[pindex]; + ds_colormap = planezlight[pindex]; + if (encoremap && !currentplane->noencore) ds_colormap += (256*32); @@ -353,6 +256,23 @@ void R_MapPlane(INT32 y, INT32 x1, INT32 x2) #endif } +void R_ClearFFloorClips (void) +{ + INT32 i, p; + + // opening / clipping determination + for (i = 0; i < viewwidth; i++) + { + for (p = 0; p < MAXFFLOORS; p++) + { + ffloor[p].f_clip[i] = (INT16)viewheight; + ffloor[p].c_clip[i] = -1; + } + } + + numffloors = 0; +} + // // R_ClearPlanes // At begining of frame. @@ -375,8 +295,6 @@ void R_ClearPlanes(void) } } - numffloors = 0; - for (i = 0; i < MAXVISPLANES; i++) for (*freehead = visplanes[i], visplanes[i] = NULL; freehead && *freehead ;) @@ -423,21 +341,12 @@ static visplane_t *new_visplane(unsigned hash) // visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap, - ffloor_t *pfloor -#ifdef POLYOBJECTS_PLANES - , polyobj_t *polyobj -#endif -#ifdef ESLOPE - , pslope_t *slope -#endif - , boolean noencore) + ffloor_t *pfloor, polyobj_t *polyobj, pslope_t *slope, boolean noencore) { visplane_t *check; unsigned hash; -#ifdef ESLOPE - if (slope); else // Don't mess with this right now if a slope is involved -#endif + if (!slope) // Don't mess with this right now if a slope is involved { xoff += viewx; yoff -= viewy; @@ -452,7 +361,6 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, } } -#ifdef POLYOBJECTS_PLANES if (polyobj) { if (polyobj->angle != 0) @@ -467,7 +375,6 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, yoff += polyobj->centerPt.y; } } -#endif // This appears to fix the Nimbus Ruins sky bug. if (picnum == skyflatnum && pfloor) @@ -476,33 +383,31 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, lightlevel = 0; } - // New visplane algorithm uses hash table - hash = visplane_hash(picnum, lightlevel, height); - - for (check = visplanes[hash]; check; check = check->next) + if (!pfloor) { -#ifdef POLYOBJECTS_PLANES - if (check->polyobj && pfloor) - continue; - if (polyobj != check->polyobj) - continue; -#endif - if (height == check->height && picnum == check->picnum - && lightlevel == check->lightlevel - && xoff == check->xoffs && yoff == check->yoffs - && planecolormap == check->extra_colormap - && !pfloor && !check->ffloor - && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz - && check->viewangle == viewangle - && check->plangle == plangle -#ifdef ESLOPE - && check->slope == slope -#endif - && check->noencore == noencore) + hash = visplane_hash(picnum, lightlevel, height); + for (check = visplanes[hash]; check; check = check->next) { - return check; + if (polyobj != check->polyobj) + continue; + if (height == check->height && picnum == check->picnum + && lightlevel == check->lightlevel + && xoff == check->xoffs && yoff == check->yoffs + && planecolormap == check->extra_colormap + && check->viewx == viewx && check->viewy == viewy && check->viewz == viewz + && check->viewangle == viewangle + && check->plangle == plangle + && check->slope == slope + && check->noencore == noencore) + { + return check; + } } } + else + { + hash = MAXVISPLANES - 1; + } check = new_visplane(hash); @@ -520,12 +425,8 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, check->viewz = viewz; check->viewangle = viewangle; check->plangle = plangle; -#ifdef POLYOBJECTS_PLANES check->polyobj = polyobj; -#endif -#ifdef ESLOPE check->slope = slope; -#endif check->noencore = noencore; memset(check->top, 0xff, sizeof (check->top)); @@ -577,9 +478,17 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) } else /* Cannot use existing plane; create a new one */ { - unsigned hash = - visplane_hash(pl->picnum, pl->lightlevel, pl->height); - visplane_t *new_pl = new_visplane(hash); + visplane_t *new_pl; + if (pl->ffloor) + { + new_pl = new_visplane(MAXVISPLANES - 1); + } + else + { + unsigned hash = + visplane_hash(pl->picnum, pl->lightlevel, pl->height); + new_pl = new_visplane(hash); + } new_pl->height = pl->height; new_pl->picnum = pl->picnum; @@ -593,12 +502,8 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) new_pl->viewz = pl->viewz; new_pl->viewangle = pl->viewangle; new_pl->plangle = pl->plangle; -#ifdef POLYOBJECTS_PLANES new_pl->polyobj = pl->polyobj; -#endif -#ifdef ESLOPE new_pl->slope = pl->slope; -#endif new_pl->noencore = pl->noencore; pl = new_pl; pl->minx = start; @@ -620,15 +525,16 @@ visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop) // overlap. void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) { - INT32 unionl, unionh; +// INT32 unionl, unionh; // INT32 x; -#ifdef POLYOBJECTS_PLANES // Don't expand polyobject planes here - we do that on our own. if (pl->polyobj) return; -#endif + if (pl->minx > start) pl->minx = start; + if (pl->maxx < stop) pl->maxx = stop; +/* if (start < pl->minx) { unionl = start; @@ -646,15 +552,16 @@ void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop) { unionh = pl->maxx; } -/* for (x = start; x <= stop; x++) if (pl->top[x] != 0xffff || pl->bottom[x] != 0x0000) break; if (x <= stop) I_Error("R_ExpandPlane: planes in same subsector overlap?!\nminx: %d, maxx: %d, start: %d, stop: %d\n", pl->minx, pl->maxx, start, stop); -*/ + pl->minx = unionl, pl->maxx = unionh; +*/ + } // @@ -689,223 +596,338 @@ void R_MakeSpans(INT32 x, INT32 t1, INT32 b1, INT32 t2, INT32 b2) void R_DrawPlanes(void) { visplane_t *pl; - INT32 x; - INT32 angle; INT32 i; - spanfunc = basespanfunc; - wallcolfunc = walldrawerfunc; + // Note: are these two lines really needed? + // R_DrawSinglePlane and R_DrawSkyPlane do span/column drawer resets themselves anyway + spanfunc = spanfuncs[BASEDRAWFUNC]; for (i = 0; i < MAXVISPLANES; i++, pl++) { for (pl = visplanes[i]; pl; pl = pl->next) { - // sky flat - if (pl->picnum == skyflatnum) - { - if (!viewsky) - { - skyVisible = true; - continue; - } - - // use correct aspect ratio scale - dc_iscale = skyscale; - - // Sky is always drawn full bright, - // i.e. colormaps[0] is used. - // Because of this hack, sky is not affected - // by INVUL inverse mapping. - dc_colormap = colormaps; - if (encoremap) - dc_colormap += (256*32); - dc_texturemid = skytexturemid; - dc_texheight = textureheight[skytexture] - >>FRACBITS; - for (x = pl->minx; x <= pl->maxx; x++) - { - dc_yl = pl->top[x]; - dc_yh = pl->bottom[x]; - - if (dc_yl <= dc_yh) - { - angle = (pl->viewangle + xtoviewangle[x])>>ANGLETOSKYSHIFT; - dc_iscale = FixedMul(skyscale, FINECOSINE(xtoviewangle[x]>>ANGLETOFINESHIFT)); - dc_x = x; - dc_source = - R_GetColumn(texturetranslation[skytexture], - -angle); // Negative because skies were being drawn horizontally flipped - wallcolfunc(); - } - } - continue; - } - - if (pl->ffloor != NULL -#ifdef POLYOBJECTS_PLANES - || pl->polyobj != NULL -#endif - ) + if (pl->ffloor != NULL || pl->polyobj != NULL) continue; R_DrawSinglePlane(pl); } } #ifndef NOWATER - waterofs = (leveltime & 1)*16384; + ds_waterofs = (leveltime & 1)*16384; wtofs = leveltime * 140; #endif } +// R_DrawSkyPlane +// +// Draws the sky within the plane's top/bottom bounds +// Note: this uses column drawers instead of span drawers, since the sky is always a texture +// +static void R_DrawSkyPlane(visplane_t *pl) +{ + INT32 x; + INT32 angle; + + // Reset column drawer function (note: couldn't we just call walldrawerfunc directly?) + // (that is, unless we'll need to switch drawers in future for some reason) + colfunc = colfuncs[BASEDRAWFUNC]; + + // use correct aspect ratio scale + dc_iscale = skyscale[viewssnum]; + + // Sky is always drawn full bright, + // i.e. colormaps[0] is used. + // Because of this hack, sky is not affected + // by sector colormaps (INVUL inverse mapping is not implemented in SRB2 so is irrelevant). + dc_colormap = colormaps; + dc_texturemid = skytexturemid; + dc_texheight = textureheight[skytexture] + >>FRACBITS; + for (x = pl->minx; x <= pl->maxx; x++) + { + dc_yl = pl->top[x]; + dc_yh = pl->bottom[x]; + + if (dc_yl <= dc_yh) + { + angle = (pl->viewangle + xtoviewangle[viewssnum][x])>>ANGLETOSKYSHIFT; + dc_iscale = FixedMul(skyscale[viewssnum], FINECOSINE(xtoviewangle[viewssnum][x]>>ANGLETOFINESHIFT)); + dc_x = x; + dc_source = + R_GetColumn(texturetranslation[skytexture], + -angle); // get negative of angle for each column to display sky correct way round! --Monster Iestyn 27/01/18 + colfunc(); + } + } +} + +static void R_SlopeVectors(visplane_t *pl, INT32 i, float fudge) +{ + // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! + // I copied ZDoom's code and adapted it to SRB2... -Red + floatv3_t p, m, n; + float ang; + float vx, vy, vz; + // compiler complains when P_GetSlopeZAt is used in FLOAT_TO_FIXED directly + // use this as a temp var to store P_GetSlopeZAt's return value each time + fixed_t temp; + + vx = FIXED_TO_FLOAT(pl->viewx+xoffs); + vy = FIXED_TO_FLOAT(pl->viewy-yoffs); + vz = FIXED_TO_FLOAT(pl->viewz); + + temp = P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy); + zeroheight = FIXED_TO_FLOAT(temp); + + // p is the texture origin in view space + // Don't add in the offsets at this stage, because doing so can result in + // errors if the flat is rotated. + ang = ANG2RAD(ANGLE_270 - pl->viewangle); + p.x = vx * cos(ang) - vy * sin(ang); + p.z = vx * sin(ang) + vy * cos(ang); + temp = P_GetSlopeZAt(pl->slope, -xoffs, yoffs); + p.y = FIXED_TO_FLOAT(temp) - vz; + + // m is the v direction vector in view space + ang = ANG2RAD(ANGLE_180 - (pl->viewangle + pl->plangle)); + m.x = cos(ang); + m.z = sin(ang); + + // n is the u direction vector in view space + n.x = sin(ang); + n.z = -cos(ang); + + ang = ANG2RAD(pl->plangle); + temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->viewy + FLOAT_TO_FIXED(cos(ang))); + m.y = FIXED_TO_FLOAT(temp) - zeroheight; + temp = P_GetSlopeZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); + n.y = FIXED_TO_FLOAT(temp) - zeroheight; + + if (ds_powersoftwo) + { + m.x /= fudge; + m.y /= fudge; + m.z /= fudge; + + n.x *= fudge; + n.y *= fudge; + n.z *= fudge; + } + + // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. +#define CROSS(d, v1, v2) \ +d.x = (v1.y * v2.z) - (v1.z * v2.y);\ +d.y = (v1.z * v2.x) - (v1.x * v2.z);\ +d.z = (v1.x * v2.y) - (v1.y * v2.x) + CROSS(ds_su[i], p, m); + CROSS(ds_sv[i], p, n); + CROSS(ds_sz[i], m, n); +#undef CROSS + + ds_su[i].z *= focallengthf[viewssnum]; + ds_sv[i].z *= focallengthf[viewssnum]; + ds_sz[i].z *= focallengthf[viewssnum]; + + // Premultiply the texture vectors with the scale factors +#define SFMULT 65536.f + if (ds_powersoftwo) + { + ds_su[i].x *= (SFMULT * (1<minx <= pl->maxx)) return; + // sky flat + if (pl->picnum == skyflatnum) + { + R_DrawSkyPlane(pl); + return; + } + #ifndef NOWATER itswater = false; #endif - spanfunc = basespanfunc; - -#ifdef POLYOBJECTS_PLANES - if (pl->polyobj && pl->polyobj->translucency != 0) { - spanfunc = R_DrawTranslucentSpan_8; + spanfunc = spanfuncs[BASEDRAWFUNC]; + if (pl->polyobj) + { // Hacked up support for alpha value in software mode Tails 09-24-2002 (sidenote: ported to polys 10-15-2014, there was no time travel involved -Red) - if (pl->polyobj->translucency >= 10) + if (pl->polyobj->translucency >= NUMEFFECTMAPS) return; // Don't even draw it else if (pl->polyobj->translucency > 0) + { + spanfunctype = (pl->polyobj->flags & POF_SPLAT) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; ds_transmap = transtables + ((pl->polyobj->translucency-1)<polyobj->flags & POF_SPLAT) // Opaque, but allow transparent flat pixels + spanfunctype = SPANDRAWFUNC_SPLAT; -#ifdef SHITPLANESPARENCY - if (spanfunc == splatfunc || (pl->extra_colormap && pl->extra_colormap->fog)) -#else - if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2)) -#endif + if (pl->polyobj->translucency == 0 || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) light = (pl->lightlevel >> LIGHTSEGSHIFT); else light = LIGHTLEVELS-1; - - } else -#endif - if (pl->ffloor) + } + else { - // Don't draw planes that shouldn't be drawn. - for (rover = pl->ffloor->target->ffloors; rover; rover = rover->next) + if (pl->ffloor) { - if ((pl->ffloor->flags & FF_CUTEXTRA) && (rover->flags & FF_EXTRA)) + // Don't draw planes that shouldn't be drawn. + for (rover = pl->ffloor->target->ffloors; rover; rover = rover->next) { - if (pl->ffloor->flags & FF_EXTRA) + if ((pl->ffloor->flags & FF_CUTEXTRA) && (rover->flags & FF_EXTRA)) { - // The plane is from an extra 3D floor... Check the flags so - // there are no undesired cuts. - if (((pl->ffloor->flags & (FF_FOG|FF_SWIMMABLE)) == (rover->flags & (FF_FOG|FF_SWIMMABLE))) - && pl->height < *rover->topheight - && pl->height > *rover->bottomheight) - return; + if (pl->ffloor->flags & FF_EXTRA) + { + // The plane is from an extra 3D floor... Check the flags so + // there are no undesired cuts. + if (((pl->ffloor->flags & (FF_FOG|FF_SWIMMABLE)) == (rover->flags & (FF_FOG|FF_SWIMMABLE))) + && pl->height < *rover->topheight + && pl->height > *rover->bottomheight) + return; + } } } - } - if (pl->ffloor->flags & FF_TRANSLUCENT) - { - spanfunc = R_DrawTranslucentSpan_8; + if (pl->ffloor->flags & FF_TRANSLUCENT) + { + spanfunctype = (pl->ffloor->master->flags & ML_EFFECT6) ? SPANDRAWFUNC_TRANSSPLAT : SPANDRAWFUNC_TRANS; - // Hacked up support for alpha value in software mode Tails 09-24-2002 - if (pl->ffloor->alpha < 12) - return; // Don't even draw it - else if (pl->ffloor->alpha < 38) - ds_transmap = transtables + ((tr_trans90-1)<ffloor->alpha < 64) - ds_transmap = transtables + ((tr_trans80-1)<ffloor->alpha < 89) - ds_transmap = transtables + ((tr_trans70-1)<ffloor->alpha < 115) - ds_transmap = transtables + ((tr_trans60-1)<ffloor->alpha < 140) - ds_transmap = transtables + ((tr_trans50-1)<ffloor->alpha < 166) - ds_transmap = transtables + ((tr_trans40-1)<ffloor->alpha < 192) - ds_transmap = transtables + ((tr_trans30-1)<ffloor->alpha < 217) - ds_transmap = transtables + ((tr_trans20-1)<ffloor->alpha < 243) - ds_transmap = transtables + ((tr_trans10-1)<ffloor->alpha < 12) + return; // Don't even draw it + else if (pl->ffloor->alpha < 38) + ds_transmap = transtables + ((tr_trans90-1)<ffloor->alpha < 64) + ds_transmap = transtables + ((tr_trans80-1)<ffloor->alpha < 89) + ds_transmap = transtables + ((tr_trans70-1)<ffloor->alpha < 115) + ds_transmap = transtables + ((tr_trans60-1)<ffloor->alpha < 140) + ds_transmap = transtables + ((tr_trans50-1)<ffloor->alpha < 166) + ds_transmap = transtables + ((tr_trans40-1)<ffloor->alpha < 192) + ds_transmap = transtables + ((tr_trans30-1)<ffloor->alpha < 217) + ds_transmap = transtables + ((tr_trans20-1)<ffloor->alpha < 243) + ds_transmap = transtables + ((tr_trans10-1)<ffloor->alpha == FFLOOR_ALPHA_SPECIAL_ADDITIVE) + ds_transmap = transtables + ((tr_transadd-1)<ffloor->alpha == FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE) + ds_transmap = transtables + ((tr_transsub-1)<extra_colormap && pl->extra_colormap->fog)) -#else - if (!pl->extra_colormap || !(pl->extra_colormap->fog & 2)) -#endif + if ((spanfunctype == SPANDRAWFUNC_SPLAT) || (pl->extra_colormap && (pl->extra_colormap->flags & CMF_FOG))) + light = (pl->lightlevel >> LIGHTSEGSHIFT); + else + light = LIGHTLEVELS-1; + } + else if (pl->ffloor->flags & FF_FOG) + { + spanfunctype = SPANDRAWFUNC_FOG; light = (pl->lightlevel >> LIGHTSEGSHIFT); - else - light = LIGHTLEVELS-1; - } - else if (pl->ffloor->flags & FF_FOG) - { - spanfunc = R_DrawFogSpan_8; - light = (pl->lightlevel >> LIGHTSEGSHIFT); - } - else light = (pl->lightlevel >> LIGHTSEGSHIFT); + } + else light = (pl->lightlevel >> LIGHTSEGSHIFT); #ifndef NOWATER - if (pl->ffloor->flags & FF_RIPPLE -#ifdef ESLOPE - && !pl->slope -#endif - ) - { - INT32 top, bottom; - UINT8 *scr; - - itswater = true; - if (spanfunc == R_DrawTranslucentSpan_8) + if (pl->ffloor->flags & FF_RIPPLE) { - spanfunc = R_DrawTranslucentWaterSpan_8; + INT32 top, bottom; - // Copy the current scene, ugh - top = pl->high-8; - bottom = pl->low+8; + itswater = true; + if (spanfunctype == SPANDRAWFUNC_TRANS) + { + UINT8 i; - if (top < 0) - top = 0; - if (bottom > vid.height) - bottom = vid.height; + spanfunctype = SPANDRAWFUNC_WATER; - if (r_splitscreen > 2 && viewplayer == &players[displayplayers[3]]) // Only copy the part of the screen we need - scr = (screens[0] + (top+(viewheight))*vid.width + viewwidth); - else if ((r_splitscreen == 1 && viewplayer == &players[displayplayers[1]]) - || (r_splitscreen > 1 && viewplayer == &players[displayplayers[2]])) - scr = (screens[0] + (top+(viewheight))*vid.width); - else if (r_splitscreen > 1 && viewplayer == &players[displayplayers[1]]) - scr = (screens[0] + ((top)*vid.width) + viewwidth); - else - scr = (screens[0] + ((top)*vid.width)); + // Copy the current scene, ugh + top = pl->high-8; + bottom = pl->low+8; - VID_BlitLinearScreen(scr, screens[1]+((top)*vid.width), - vid.width, bottom-top, - vid.width, vid.width); + if (top < 0) + top = 0; + if (bottom > vid.height) + bottom = vid.height; + + // Only copy the part of the screen we need + for (i = 0; i <= r_splitscreen; i++) + { + if (viewplayer == &players[displayplayers[i]]) + { + INT32 scrx = 0; + INT32 scry = top; + INT32 offset; + + if (r_splitscreen == 1) + { + if (i & 1) + { + scry += viewheight; + } + } + else + { + if (i & 1) + { + scrx += viewwidth; + } + + if (i / 2) + { + scry += viewheight; + } + } + + offset = (scry*vid.width) + scrx; + + // No idea if this works + VID_BlitLinearScreen(screens[0] + offset, screens[1] + offset, + viewwidth, bottom-top, + vid.width, vid.width); + } + } + } } +#endif } -#endif + else + light = (pl->lightlevel >> LIGHTSEGSHIFT); } - else light = (pl->lightlevel >> LIGHTSEGSHIFT); -#ifdef ESLOPE - if (!pl->slope) // Don't mess with angle on slopes! We'll handle this ourselves later -#endif - if (viewangle != pl->viewangle+pl->plangle) + if (!pl->slope // Don't mess with angle on slopes! We'll handle this ourselves later + && viewangle != pl->viewangle+pl->plangle) { memset(cachedheight, 0, sizeof (cachedheight)); angle = (pl->viewangle+pl->plangle-ANGLE_90)>>ANGLETOFINESHIFT; @@ -914,213 +936,153 @@ void R_DrawSinglePlane(visplane_t *pl) viewangle = pl->viewangle+pl->plangle; } - currentplane = pl; - - ds_source = (UINT8 *) - W_CacheLumpNum(levelflats[pl->picnum].lumpnum, - PU_STATIC); // Stay here until Z_ChangeTag - - size = W_LumpLength(levelflats[pl->picnum].lumpnum); - - switch (size) - { - case 4194304: // 2048x2048 lump - nflatmask = 0x3FF800; - nflatxshift = 21; - nflatyshift = 10; - nflatshiftup = 5; - break; - case 1048576: // 1024x1024 lump - nflatmask = 0xFFC00; - nflatxshift = 22; - nflatyshift = 12; - nflatshiftup = 6; - break; - case 262144:// 512x512 lump' - nflatmask = 0x3FE00; - nflatxshift = 23; - nflatyshift = 14; - nflatshiftup = 7; - break; - case 65536: // 256x256 lump - nflatmask = 0xFF00; - nflatxshift = 24; - nflatyshift = 16; - nflatshiftup = 8; - break; - case 16384: // 128x128 lump - nflatmask = 0x3F80; - nflatxshift = 25; - nflatyshift = 18; - nflatshiftup = 9; - break; - case 1024: // 32x32 lump - nflatmask = 0x3E0; - nflatxshift = 27; - nflatyshift = 22; - nflatshiftup = 11; - break; - default: // 64x64 lump - nflatmask = 0xFC0; - nflatxshift = 26; - nflatyshift = 20; - nflatshiftup = 10; - break; - } - xoffs = pl->xoffs; yoffs = pl->yoffs; planeheight = abs(pl->height - pl->viewz); + currentplane = pl; + levelflat = &levelflats[pl->picnum]; + + /* :james: */ + type = levelflat->type; + switch (type) + { + case LEVELFLAT_NONE: + return; + case LEVELFLAT_FLAT: + ds_source = (UINT8 *)R_GetFlat(levelflat->u.flat.lumpnum); + R_CheckFlatLength(W_LumpLength(levelflat->u.flat.lumpnum)); + // Raw flats always have dimensions that are powers-of-two numbers. + ds_powersoftwo = true; + break; + default: + ds_source = (UINT8 *)R_GetLevelFlat(levelflat); + if (!ds_source) + return; + // Check if this texture or patch has power-of-two dimensions. + if (R_CheckPowersOfTwo()) + R_CheckFlatLength(ds_flatwidth * ds_flatheight); + } + if (light >= LIGHTLEVELS) light = LIGHTLEVELS-1; if (light < 0) light = 0; -#ifdef ESLOPE - if (pl->slope) { - // Potentially override other stuff for now cus we're mean. :< But draw a slope plane! - // I copied ZDoom's code and adapted it to SRB2... -fickle - floatv3_t p, m, n; - float ang; - float vx, vy, vz; - // compiler complains when P_GetZAt is used in FLOAT_TO_FIXED directly - // use this as a temp var to store P_GetZAt's return value each time - fixed_t temp; - // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -fickle - const float fudge = ((1<slope) + { + float fudgecanyon = 0; angle_t hack = (pl->plangle & (ANGLE_90-1)); - if (hack) + yoffs *= 1; + + if (ds_powersoftwo) { - /* - Essentially: We can't & the components along the regular axes when the plane is rotated. - This is because the distance on each regular axis in order to loop is different. - We rotate them, & the components, add them together, & them again, and then rotate them back. - These three seperate & operations are done per axis in order to prevent overflows. - toast 10/04/17 - --- - ...of coooourse, this still isn't perfect. but it looks... merely kind of grody, rather than - completely wrong? idk. i'm just backporting this to kart right now. if anyone else wants to - ever try dig around: it's drifting towards 0,0, and no, multiplying by fudge doesn't fix it. - toast 27/09/18 - */ + fixed_t temp; + // Okay, look, don't ask me why this works, but without this setup there's a disgusting-looking misalignment with the textures. -Red + fudgecanyon = ((1<>ANGLETOFINESHIFT); + const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); - const fixed_t cosinecomponent = FINECOSINE(hack>>ANGLETOFINESHIFT); - const fixed_t sinecomponent = FINESINE(hack>>ANGLETOFINESHIFT); + const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); - const fixed_t modmask = ((1 << (32-nflatshiftup)) - 1); + fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); + fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); - fixed_t ox = (FixedMul(pl->slope->o.x,cosinecomponent) & modmask) - (FixedMul(pl->slope->o.y,sinecomponent) & modmask); - fixed_t oy = (-FixedMul(pl->slope->o.x,sinecomponent) & modmask) - (FixedMul(pl->slope->o.y,cosinecomponent) & modmask); + temp = ox & modmask; + oy &= modmask; + ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction + oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); - temp = ox & modmask; - oy &= modmask; - ox = FixedMul(temp,cosinecomponent)+FixedMul(oy,-sinecomponent); // negative sine for opposite direction - oy = -FixedMul(temp,-sinecomponent)+FixedMul(oy,cosinecomponent); + temp = xoffs; + xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); + yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); - temp = xoffs; - xoffs = (FixedMul(temp,cosinecomponent) & modmask) + (FixedMul(yoffs,sinecomponent) & modmask); - yoffs = (-FixedMul(temp,sinecomponent) & modmask) + (FixedMul(yoffs,cosinecomponent) & modmask); + temp = xoffs & modmask; + yoffs &= modmask; + xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto + yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - temp = xoffs & modmask; - yoffs &= modmask; - xoffs = FixedMul(temp,cosinecomponent)+FixedMul(yoffs,-sinecomponent); // ditto - yoffs = -FixedMul(temp,-sinecomponent)+FixedMul(yoffs,cosinecomponent); - - xoffs -= (pl->slope->o.x - ox); - yoffs += (pl->slope->o.y + oy); - } - else - { - xoffs &= ((1 << (32-nflatshiftup))-1); - yoffs &= ((1 << (32-nflatshiftup))-1); - xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); - yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + xoffs -= (pl->slope->o.x - ox); + yoffs += (pl->slope->o.y + oy); + } + else + { + xoffs &= ((1 << (32-nflatshiftup))-1); + yoffs &= ((1 << (32-nflatshiftup))-1); + xoffs -= (pl->slope->o.x + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + yoffs += (pl->slope->o.y + (1 << (31-nflatshiftup))) & ~((1 << (32-nflatshiftup))-1); + } + xoffs = (fixed_t)(xoffs*fudgecanyon); + yoffs = (fixed_t)(yoffs/fudgecanyon); } - xoffs = (fixed_t)(xoffs*fudge); - yoffs = (fixed_t)(yoffs/fudge); + ds_sup = &ds_su[0]; + ds_svp = &ds_sv[0]; + ds_szp = &ds_sz[0]; - vx = FIXED_TO_FLOAT(pl->viewx+xoffs); - vy = FIXED_TO_FLOAT(pl->viewy-yoffs); - vz = FIXED_TO_FLOAT(pl->viewz); +#ifndef NOWATER + if (itswater) + { + INT32 i; + fixed_t plheight = abs(P_GetSlopeZAt(pl->slope, pl->viewx, pl->viewy) - pl->viewz); + fixed_t rxoffs = xoffs; + fixed_t ryoffs = yoffs; - temp = P_GetZAt(pl->slope, pl->viewx, pl->viewy); - zeroheight = FIXED_TO_FLOAT(temp); + R_PlaneBounds(pl); -#define ANG2RAD(angle) ((float)((angle)*M_PIl)/ANGLE_180) + for (i = pl->high; i < pl->low; i++) + { + R_PlaneRipple(pl, i, plheight); + xoffs = rxoffs + ripple_xfrac; + yoffs = ryoffs + ripple_yfrac; + R_SlopeVectors(pl, i, fudgecanyon); + } - // p is the texture origin in view space - // Don't add in the offsets at this stage, because doing so can result in - // errors if the flat is rotated. - ang = ANG2RAD(ANGLE_270 - pl->viewangle); - p.x = vx * cos(ang) - vy * sin(ang); - p.z = vx * sin(ang) + vy * cos(ang); - temp = P_GetZAt(pl->slope, -xoffs, yoffs); - p.y = FIXED_TO_FLOAT(temp) - vz; - - // m is the v direction vector in view space - ang = ANG2RAD(ANGLE_180 - (pl->viewangle + pl->plangle)); - m.x = cos(ang); - m.z = sin(ang); - - // n is the u direction vector in view space - n.x = sin(ang); - n.z = -cos(ang); - - ang = ANG2RAD(pl->plangle); - temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(sin(ang)), pl->viewy + FLOAT_TO_FIXED(cos(ang))); - m.y = FIXED_TO_FLOAT(temp) - zeroheight; - temp = P_GetZAt(pl->slope, pl->viewx + FLOAT_TO_FIXED(cos(ang)), pl->viewy - FLOAT_TO_FIXED(sin(ang))); - n.y = FIXED_TO_FLOAT(temp) - zeroheight; - - m.x /= fudge; - m.y /= fudge; - m.z /= fudge; - - n.x *= fudge; - n.y *= fudge; - n.z *= fudge; - - // Eh. I tried making this stuff fixed-point and it exploded on me. Here's a macro for the only floating-point vector function I recall using. -#define CROSS(d, v1, v2) \ - d.x = (v1.y * v2.z) - (v1.z * v2.y);\ - d.y = (v1.z * v2.x) - (v1.x * v2.z);\ - d.z = (v1.x * v2.y) - (v1.y * v2.x) - CROSS(ds_su, p, m); - CROSS(ds_sv, p, n); - CROSS(ds_sz, m, n); -#undef CROSS - - ds_su.z *= focallengthf; - ds_sv.z *= focallengthf; - ds_sz.z *= focallengthf; - - // Premultiply the texture vectors with the scale factors -#define SFMULT 65536.f*(1<top[pl->maxx+1] = 0xffff; @@ -1161,11 +1123,11 @@ a 'smoothing' of the texture while using the palette colors. */ #ifdef QUINCUNX - if (spanfunc == R_DrawSpan_8) + if (spanfunc == spanfuncs[BASEDRAWFUNC]) { INT32 i; ds_transmap = transtables + ((tr_trans50-1)<xoffs; @@ -1214,8 +1176,6 @@ using the palette colors. } } #endif - - Z_ChangeTag(ds_source, PU_CACHE); } void R_PlaneBounds(visplane_t *plane) diff --git a/src/r_plane.h b/src/r_plane.h index 8f5a6073d..57a7dabf6 100644 --- a/src/r_plane.h +++ b/src/r_plane.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -16,8 +16,14 @@ #include "screen.h" // needs MAXVIDWIDTH/MAXVIDHEIGHT #include "r_data.h" +#include "r_textures.h" #include "p_polyobj.h" +#define VISPLANEHASHBITS 9 +#define VISPLANEHASHMASK ((1<start; + INT32 end = portal->end; + INT16 *ceil = portal->ceilingclip; + INT16 *floor = portal->floorclip; + fixed_t *scale = portal->frontscale; + + INT32 i; + for (i = 0; i < end-start; i++) + { + *ceil = ceilingclip[start+i]; + ceil++; + *floor = floorclip[start+i]; + floor++; + *scale = frontscale[start+i]; + scale++; + } +} + +/** Apply the clipping window from a portal. + */ +void Portal_ClipApply (const portal_t* portal) +{ + INT32 i; + INT32 start = portal->start; + INT32 end = portal->end; + INT16 *ceil = portal->ceilingclip; + INT16 *floor = portal->floorclip; + fixed_t *scale = portal->frontscale; + + for (i = 0; i < end-start; i++) + { + ceilingclip[start+i] = *ceil; + ceil++; + floorclip[start+i] = *floor; + floor++; + frontscale[start+i] = *scale; + scale++; + } + + // HACKS FOLLOW + for (i = 0; i < start; i++) + { + floorclip[i] = -1; + ceilingclip[i] = (INT16)viewheight; + } + for (i = end; i < vid.width; i++) + { + floorclip[i] = -1; + ceilingclip[i] = (INT16)viewheight; + } +} + +static portal_t* Portal_Add (const INT16 x1, const INT16 x2) +{ + portal_t *portal = Z_Malloc(sizeof(portal_t), PU_LEVEL, NULL); + INT16 *ceilingclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); + INT16 *floorclipsave = Z_Malloc(sizeof(INT16)*(x2-x1 + 1), PU_LEVEL, NULL); + fixed_t *frontscalesave = Z_Malloc(sizeof(fixed_t)*(x2-x1 + 1), PU_LEVEL, NULL); + + // Linked list. + if (!portal_base) + { + portal_base = portal; + portal_cap = portal; + } + else + { + portal_cap->next = portal; + portal_cap = portal; + } + portal->next = NULL; + + // Store clipping values so they can be restored once the portal is rendered. + portal->ceilingclip = ceilingclipsave; + portal->floorclip = floorclipsave; + portal->frontscale = frontscalesave; + portal->start = x1; + portal->end = x2; + + // Increase recursion level. + portal->pass = portalrender+1; + + return portal; +} + +void Portal_Remove (portal_t* portal) +{ + portal_base = portal->next; + Z_Free(portal->ceilingclip); + Z_Free(portal->floorclip); + Z_Free(portal->frontscale); + Z_Free(portal); +} + +/** Creates a portal out of two lines and a determined screen range. + * + * line1 determines the entrance, and line2 the exit. + * x1 and x2 determine the screen's column bounds. + + * The view's offset from the entry line center is obtained, + * and then rotated&translated to the exit line's center. + * When the portal renders, it will create the illusion of + * the two lines being seamed together. + */ +void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2) +{ + portal_t* portal = Portal_Add(x1, x2); + + // Offset the portal view by the linedef centers + line_t* start = &lines[line1]; + line_t* dest = &lines[line2]; + + angle_t dangle = R_PointToAngle2(0,0,dest->dx,dest->dy) - R_PointToAngle2(start->dx,start->dy,0,0); + + fixed_t disttopoint; + angle_t angtopoint; + + vertex_t dest_c, start_c; + + // looking glass center + start_c.x = (start->v1->x + start->v2->x) / 2; + start_c.y = (start->v1->y + start->v2->y) / 2; + + // other side center + dest_c.x = (dest->v1->x + dest->v2->x) / 2; + dest_c.y = (dest->v1->y + dest->v2->y) / 2; + + disttopoint = R_PointToDist2(start_c.x, start_c.y, viewx, viewy); + angtopoint = R_PointToAngle2(start_c.x, start_c.y, viewx, viewy); + angtopoint += dangle; + + portal->viewx = dest_c.x + FixedMul(FINECOSINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); + portal->viewy = dest_c.y + FixedMul(FINESINE(angtopoint>>ANGLETOFINESHIFT), disttopoint); + portal->viewz = viewz + dest->frontsector->floorheight - start->frontsector->floorheight; + portal->viewangle = viewangle + dangle; + + portal->clipline = line2; + + Portal_ClipRange(portal); + + portalline = true; // this tells R_StoreWallRange that curline is a portal seg +} + +/** Store the clipping window for a portal using a visplane. + * + * Since visplanes top/bottom windows work in an identical way, + * it can just be copied almost directly. + */ +static void Portal_ClipVisplane (const visplane_t* plane, portal_t* portal) +{ + INT16 start = portal->start; + INT16 end = portal->end; + INT32 i; + + for (i = 0; i < end - start; i++) + { + // Invalid column. + if (plane->top[i + start] == 65535) + { + portal->ceilingclip[i] = -1; + portal->floorclip[i] = -1; + continue; + } + portal->ceilingclip[i] = plane->top[i + start] - 1; + portal->floorclip[i] = plane->bottom[i + start] + 1; + portal->frontscale[i] = INT32_MAX; + } +} + +extern INT32 viewwidth; + +static boolean TrimVisplaneBounds (const visplane_t* plane, INT16* start, INT16* end) +{ + *start = plane->minx; + *end = plane->maxx + 1; + + // Visplanes have 1-px pads on their sides (extra columns). + // Trim them, else it may render out of bounds. + if (*end > viewwidth) + *end = viewwidth; + + if (!(*start < *end)) + return true; + + + /** Trims a visplane's horizontal gap to match its render area. + * + * Visplanes' minx/maxx may sometimes exceed the area they're + * covering. This merely adjusts the boundaries to the next + * valid area. + */ + + while (plane->bottom[*start] == 0 && plane->top[*start] == 65535 && *start < *end) + { + (*start)++; + } + + + while (plane->bottom[*end - 1] == 0 && plane->top[*start] == 65535 && *end > *start) + { + (*end)--; + } + + return false; +} + +/** Creates a skybox portal out of a visplane. + * + * Applies the necessary offsets and rotation to give + * a depth illusion to the skybox. + */ +void Portal_AddSkybox (const visplane_t* plane) +{ + INT16 start, end; + mapheader_t *mh; + portal_t* portal; + + if (TrimVisplaneBounds(plane, &start, &end)) + return; + + portal = Portal_Add(start, end); + + Portal_ClipVisplane(plane, portal); + + portal->viewx = skyboxmo[0]->x; + portal->viewy = skyboxmo[0]->y; + portal->viewz = skyboxmo[0]->z; + portal->viewangle = viewangle + skyboxmo[0]->angle; + + mh = mapheaderinfo[gamemap-1]; + + // If a relative viewpoint exists, offset the viewpoint. + if (skyboxmo[1]) + { + fixed_t x = 0, y = 0; + angle_t ang = skyboxmo[0]->angle>>ANGLETOFINESHIFT; + + if (mh->skybox_scalex > 0) + x = (viewx - skyboxmo[1]->x) / mh->skybox_scalex; + else if (mh->skybox_scalex < 0) + x = (viewx - skyboxmo[1]->x) * -mh->skybox_scalex; + + if (mh->skybox_scaley > 0) + y = (viewy - skyboxmo[1]->y) / mh->skybox_scaley; + else if (mh->skybox_scaley < 0) + y = (viewy - skyboxmo[1]->y) * -mh->skybox_scaley; + + // Apply transform to account for the skybox viewport angle. + portal->viewx += FixedMul(x,FINECOSINE(ang)) - FixedMul(y, FINESINE(ang)); + portal->viewy += FixedMul(x, FINESINE(ang)) + FixedMul(y,FINECOSINE(ang)); + } + + if (mh->skybox_scalez > 0) + portal->viewz += viewz / mh->skybox_scalez; + else if (mh->skybox_scalez < 0) + portal->viewz += viewz * -mh->skybox_scalez; + + portal->clipline = -1; +} + +/** Creates portals for the currently existing sky visplanes. + * The visplanes are also removed and cleared from the list. + */ +void Portal_AddSkyboxPortals (void) +{ + visplane_t *pl; + INT32 i; + UINT16 count = 0; + + for (i = 0; i < MAXVISPLANES; i++, pl++) + { + for (pl = visplanes[i]; pl; pl = pl->next) + { + if (pl->picnum == skyflatnum) + { + Portal_AddSkybox(pl); + + pl->minx = 0; + pl->maxx = -1; + + count++; + } + } + } + + CONS_Debug(DBG_RENDER, "Skybox portals: %d\n", count); +} diff --git a/src/r_portal.h b/src/r_portal.h new file mode 100644 index 000000000..e665a26e6 --- /dev/null +++ b/src/r_portal.h @@ -0,0 +1,61 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_portal.h +/// \brief Software renderer portal struct, functions, linked list extern. + +#ifndef __R_PORTAL__ +#define __R_PORTAL__ + +#include "r_data.h" +#include "r_textures.h" +#include "r_plane.h" // visplanes + +/** Portal structure for the software renderer. + */ +typedef struct portal_s +{ + struct portal_s *next; + + // Viewport. + fixed_t viewx; + fixed_t viewy; + fixed_t viewz; + angle_t viewangle; + + UINT8 pass; /**< Keeps track of the portal's recursion depth. */ + INT32 clipline; /**< Optional clipline for line-based portals. */ + + // Clipping information. + INT32 start; /**< First horizontal pixel coordinate to draw at. */ + INT32 end; /**< Last horizontal pixel coordinate to draw at. */ + INT16 *ceilingclip; /**< Temporary screen top clipping array. */ + INT16 *floorclip; /**< Temporary screen bottom clipping array. */ + fixed_t *frontscale;/**< Temporary screen bottom clipping array. */ +} portal_t; + +extern portal_t* portal_base; +extern portal_t* portal_cap; +extern UINT8 portalrender; + +extern line_t *portalclipline; +extern sector_t *portalcullsector; +extern INT32 portalclipstart, portalclipend; + +void Portal_InitList (void); +void Portal_Remove (portal_t* portal); +void Portal_Add2Lines (const INT32 line1, const INT32 line2, const INT32 x1, const INT32 x2); +void Portal_AddSkybox (const visplane_t* plane); + +void Portal_ClipRange (portal_t* portal); +void Portal_ClipApply (const portal_t* portal); + +void Portal_AddSkyboxPortals (void); +#endif diff --git a/src/r_segs.c b/src/r_segs.c index 9078d5f98..8dcb61992 100644 --- a/src/r_segs.c +++ b/src/r_segs.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,6 +15,7 @@ #include "r_local.h" #include "r_sky.h" +#include "r_portal.h" #include "r_splats.h" #include "w_wad.h" @@ -51,20 +52,25 @@ static fixed_t rw_offset2; // for splats static fixed_t rw_scale, rw_scalestep; static fixed_t rw_midtexturemid, rw_toptexturemid, rw_bottomtexturemid; static INT32 worldtop, worldbottom, worldhigh, worldlow; -#ifdef ESLOPE static INT32 worldtopslope, worldbottomslope, worldhighslope, worldlowslope; // worldtop/bottom at end of slope static fixed_t rw_toptextureslide, rw_midtextureslide, rw_bottomtextureslide; // Defines how to adjust Y offsets along the wall for slopes static fixed_t rw_midtextureback, rw_midtexturebackslide; // Values for masked midtexture height calculation -#endif + +// Lactozilla: 3D floor clipping +static boolean rw_floormarked = false; +static boolean rw_ceilingmarked = false; + +static INT32 *rw_silhouette = NULL; +static fixed_t *rw_tsilheight = NULL; +static fixed_t *rw_bsilheight = NULL; + static fixed_t pixhigh, pixlow, pixhighstep, pixlowstep; static fixed_t topfrac, topstep; static fixed_t bottomfrac, bottomstep; static lighttable_t **walllights; static INT16 *maskedtexturecol; -#ifdef ESLOPE static fixed_t *maskedtextureheight = NULL; -#endif // ========================================================================== // R_Splats Wall Splats Drawer @@ -164,7 +170,7 @@ static void R_DrawWallSplats(void) mfloorclip = floorclip; mceilingclip = ceilingclip; - patch = W_CachePatchNum(splat->patch, PU_CACHE); + patch = W_CachePatchNum(splat->patch, PU_PATCH); dc_texturemid = splat->top + (SHORT(patch->height)<<(FRACBITS-1)) - viewz; if (splat->yoffset) @@ -176,14 +182,14 @@ static void R_DrawWallSplats(void) switch (splat->flags & SPLATDRAWMODE_MASK) { case SPLATDRAWMODE_OPAQUE: - colfunc = basecolfunc; + colfunc = colfuncs[BASEDRAWFUNC]; break; case SPLATDRAWMODE_TRANS: dc_transmap = transtables + ((tr_trans50 - 1)<>LIGHTSCALESHIFT; + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; dc_colormap = walllights[pindex]; @@ -206,7 +212,7 @@ static void R_DrawWallSplats(void) dc_iscale = 0xffffffffu / (unsigned)spryscale; // find column of patch, from perspective - angle = (rw_centerangle + xtoviewangle[dc_x])>>ANGLETOFINESHIFT; + angle = (rw_centerangle + xtoviewangle[viewssnum][dc_x])>>ANGLETOFINESHIFT; texturecolumn = rw_offset2 - splat->offset - FixedMul(FINETANGENT(angle), rw_distance); @@ -221,7 +227,7 @@ static void R_DrawWallSplats(void) } } // next splat - colfunc = basecolfunc; + colfunc = colfuncs[BASEDRAWFUNC]; } #endif //WALLSPLATS @@ -235,14 +241,13 @@ static void R_DrawWallSplats(void) // way we don't have to store extra post_t info with each column for // multi-patch textures. They are not normally needed as multi-patch // textures don't have holes in it. At least not for now. -static INT32 column2s_length; // column->length : for multi-patch on 2sided wall = texture->height static void R_Render2sidedMultiPatchColumn(column_t *column) { INT32 topscreen, bottomscreen; topscreen = sprtopscreen; // + spryscale*column->topdelta; topdelta is 0 for the wall - bottomscreen = topscreen + spryscale * column2s_length; + bottomscreen = topscreen + spryscale * lengthcol; dc_yl = (sprtopscreen+FRACUNIT-1)>>FRACBITS; dc_yh = (bottomscreen-1)>>FRACBITS; @@ -265,15 +270,34 @@ static void R_Render2sidedMultiPatchColumn(column_t *column) { dc_source = (UINT8 *)column + 3; - if (colfunc == wallcolfunc) - twosmultipatchfunc(); - else if (colfunc == fuzzcolfunc) - twosmultipatchtransfunc(); + if (colfunc == colfuncs[BASEDRAWFUNC]) + (colfuncs[COLDRAWFUNC_TWOSMULTIPATCH])(); + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) + (colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS])(); else colfunc(); } } +transnum_t R_GetLinedefTransTable(line_t *ldef) +{ + transnum_t transnum = NUMEFFECTMAPS; // Send back NUMEFFECTMAPS for none + fixed_t alpha = ldef->alpha; + if (alpha > 0 && alpha < FRACUNIT) + transnum = (20*(FRACUNIT - alpha - 1) + FRACUNIT) >> (FRACBITS+1); + else + { + switch (ldef->special) + { + case 910: transnum = tr_transadd; break; + case 911: transnum = tr_transsub; break; + default: transnum = NUMEFFECTMAPS; break; + } + } + + return transnum; +} + void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) { size_t pindex; @@ -287,58 +311,50 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) sector_t *front, *back; INT32 times, repeats; INT64 overflow_test; -#ifdef ESLOPE INT32 range; -#endif + transnum_t transtable = NUMEFFECTMAPS; // Calculate light table. // Use different light tables // for horizontal / vertical / diagonal. Diagonal? // OPTIMIZE: get rid of LIGHTSEGSHIFT globally curline = ds->curline; + frontsector = curline->frontsector; backsector = curline->backsector; texnum = R_GetTextureNum(curline->sidedef->midtexture); windowbottom = windowtop = sprbotscreen = INT32_MAX; - // hack translucent linedef types (900-909 for transtables 1-9) ldef = curline->linedef; - switch (ldef->special) + if (!ldef->alpha) + return; + + transtable = R_GetLinedefTransTable(ldef); + if (transtable != NUMEFFECTMAPS) { - case 900: - case 901: - case 902: - case 903: - case 904: - case 905: - case 906: - case 907: - case 908: - dc_transmap = transtables + ((ldef->special-900)<ceilingheight; - windowbottom = frontsector->floorheight; - break; - default: - colfunc = wallcolfunc; - break; + dc_transmap = transtables + ((transtable - 1) << FF_TRANSSHIFT); + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; + } + else if (ldef->special == 909) + { + colfunc = colfuncs[COLDRAWFUNC_FOG]; + windowtop = frontsector->ceilingheight; + windowbottom = frontsector->floorheight; + } + else + colfunc = colfuncs[BASEDRAWFUNC]; if (curline->polyseg && curline->polyseg->translucency > 0) { - if (curline->polyseg->translucency >= NUMTRANSMAPS) + if (curline->polyseg->translucency >= NUMEFFECTMAPS) return; dc_transmap = transtables + ((curline->polyseg->translucency-1)<x2-ds->x1, 1); -#endif rw_scalestep = ds->scalestep; spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; @@ -348,11 +364,19 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info in SRB2 if (textures[texnum]->holes) - colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawFlippedMaskedColumn; + lengthcol = textures[texnum]->height; + } + else + colfunc_2s = R_DrawMaskedColumn; // render the usual 2sided single-patch packed texture + } else { colfunc_2s = R_Render2sidedMultiPatchColumn; // render multipatch with no holes (no post_t info) - column2s_length = textures[texnum]->height; + lengthcol = textures[texnum]->height; } // Setup lighting based on the presence/lack-of 3D floors. @@ -368,43 +392,33 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) for (i = 0; i < dc_numlights; i++) { -#ifdef ESLOPE fixed_t leftheight, rightheight; -#endif light = &frontsector->lightlist[i]; rlight = &dc_lightlist[i]; -#ifdef ESLOPE - if (light->slope) { - leftheight = P_GetZAt(light->slope, ds->leftpos.x, ds->leftpos.y); - rightheight = P_GetZAt(light->slope, ds->rightpos.x, ds->rightpos.y); - } else - leftheight = rightheight = light->height; + leftheight = P_GetLightZAt(light, ds-> leftpos.x, ds-> leftpos.y); + rightheight = P_GetLightZAt(light, ds->rightpos.x, ds->rightpos.y); - leftheight -= viewz; + leftheight -= viewz; rightheight -= viewz; - rlight->height = (centeryfrac) - FixedMul(leftheight, ds->scale1); + rlight->height = (centeryfrac) - FixedMul(leftheight , ds->scale1); rlight->heightstep = (centeryfrac) - FixedMul(rightheight, ds->scale2); rlight->heightstep = (rlight->heightstep-rlight->height)/(range); //if (x1 > ds->x1) //rlight->height -= (x1 - ds->x1)*rlight->heightstep; -#else - rlight->height = (centeryfrac) - FixedMul((light->height - viewz), spryscale); - rlight->heightstep = -FixedMul(rw_scalestep, (light->height - viewz)); -#endif rlight->startheight = rlight->height; // keep starting value here to reset for each repeat rlight->lightlevel = *light->lightlevel; - rlight->extra_colormap = light->extra_colormap; + rlight->extra_colormap = *light->extra_colormap; rlight->flags = light->flags; - if (rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) + if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) + || (rlight->flags & FF_FOG) + || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == fuzzcolfunc) - lightnum = LIGHTLEVELS - 1; else - lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); + lightnum = LIGHTLEVELS - 1; - if (rlight->extra_colormap && rlight->extra_colormap->fog) + if (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)) ; else lightnum += curline->lightOffset; @@ -414,18 +428,14 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } else { - if (colfunc == fuzzcolfunc) - { - if (frontsector->extra_colormap && frontsector->extra_colormap->fog) - lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); - else - lightnum = LIGHTLEVELS - 1; - } - else + if ((colfunc != colfuncs[COLDRAWFUNC_FUZZY]) + || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); + else + lightnum = LIGHTLEVELS - 1; - if (colfunc == R_DrawFogColumn_8 - || (frontsector->extra_colormap && frontsector->extra_colormap->fog)) + if (colfunc == colfuncs[COLDRAWFUNC_FOG] + || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) ; else lightnum += curline->lightOffset; @@ -492,40 +502,17 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } } -#ifndef ESLOPE - if (curline->linedef->flags & ML_DONTPEGBOTTOM) - { - dc_texturemid = front->floorheight > back->floorheight - ? front->floorheight : back->floorheight; - dc_texturemid = dc_texturemid + textureheight[texnum] - viewz; - } - else - { - dc_texturemid = front->ceilingheight < back->ceilingheight - ? front->ceilingheight : back->ceilingheight; - dc_texturemid = dc_texturemid - viewz; - } - dc_texturemid += curline->sidedef->rowoffset; - - if (curline->linedef->flags & ML_DONTPEGBOTTOM) - dc_texturemid += (textureheight[texnum])*times; - else - dc_texturemid -= (textureheight[texnum])*times; -#endif - dc_texheight = textureheight[texnum]>>FRACBITS; // draw the columns for (dc_x = x1; dc_x <= x2; dc_x++) { -#ifdef ESLOPE dc_texturemid = ds->maskedtextureheight[dc_x]; if (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3)) dc_texturemid += (textureheight[texnum])*times + textureheight[texnum]; else dc_texturemid -= (textureheight[texnum])*times; -#endif // calculate lighting if (maskedtexturecol[dc_x] != INT16_MAX) { @@ -574,7 +561,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) else xwalllights = scalelight[rlight->lightnum]; - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; @@ -623,7 +610,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) } // calculate lighting - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; @@ -641,7 +628,6 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) // draw the texture col = (column_t *)((UINT8 *)R_GetColumn(texnum, maskedtexturecol[dc_x]) - 3); -//#ifdef POLYOBJECTS_PLANES #if 0 // Disabling this allows inside edges to render below the planes, for until the clipping is fixed to work right when POs are near the camera. -Red if (curline->dontrenderme && curline->polyseg && (curline->polyseg->flags & POF_RENDERPLANES)) { @@ -700,7 +686,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2) spryscale += rw_scalestep; } } - colfunc = wallcolfunc; + colfunc = colfuncs[BASEDRAWFUNC]; } // Loop through R_DrawMaskedColumn calls @@ -715,6 +701,27 @@ static void R_DrawRepeatMaskedColumn(column_t *col) } } +static void R_DrawRepeatFlippedMaskedColumn(column_t *col) +{ + do { + R_DrawFlippedMaskedColumn(col); + sprtopscreen += dc_texheight*spryscale; + } while (sprtopscreen < sprbotscreen); +} + +// Returns true if a fake floor is translucent. +static boolean R_IsFFloorTranslucent(visffloor_t *pfloor) +{ + if (pfloor->polyobj) + return (pfloor->polyobj->translucency > 0); + + // Polyobjects have no ffloors, and they're handled in the conditional above. + if (pfloor->ffloor != NULL) + return (pfloor->ffloor->flags & FF_TRANSLUCENT); + + return false; +} + // // R_RenderThickSideRange // Renders all the thick sides in the given range. @@ -732,14 +739,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) fixed_t offsetvalue = 0; lightlist_t *light; r_lightlist_t *rlight; -#ifdef ESLOPE INT32 range; -#endif -#ifndef ESLOPE - fixed_t lheight; -#endif line_t *newline = NULL; -#ifdef ESLOPE // Render FOF sides kinda like normal sides, with the frac and step and everything // NOTE: INT64 instead of fixed_t because overflow concerns INT64 top_frac, top_step, bottom_frac, bottom_step; @@ -749,7 +750,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) INT32 oldx = -1; fixed_t left_top, left_bottom; // needed here for slope skewing pslope_t *skewslope = NULL; -#endif void (*colfunc_2s) (column_t *); @@ -763,7 +763,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) frontsector = curline->frontsector == pfloor->target ? curline->backsector : curline->frontsector; texnum = R_GetTextureNum(sides[pfloor->master->sidenum[0]].midtexture); - colfunc = wallcolfunc; + colfunc = colfuncs[BASEDRAWFUNC]; if (pfloor->master->flags & ML_TFERLINE) { @@ -797,18 +797,20 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) dc_transmap = transtables + ((tr_trans20-1)<alpha < 243) dc_transmap = transtables + ((tr_trans10-1)<alpha == FFLOOR_ALPHA_SPECIAL_ADDITIVE) + dc_transmap = transtables + ((tr_transadd-1)<alpha == FFLOOR_ALPHA_SPECIAL_SUBTRACTIVE) + dc_transmap = transtables + ((tr_transsub-1)<flags & FF_FOG) - colfunc = R_DrawFogColumn_8; + colfunc = colfuncs[COLDRAWFUNC_FOG]; -#ifdef ESLOPE range = max(ds->x2-ds->x1, 1); -#endif //SoM: Moved these up here so they are available for my lightlist calculations rw_scalestep = ds->scalestep; spryscale = ds->scale1 + (x1 - ds->x1)*rw_scalestep; @@ -825,21 +827,15 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) for (i = p = 0; i < dc_numlights; i++) { -#ifdef ESLOPE fixed_t leftheight, rightheight; fixed_t pfloorleft, pfloorright; INT64 overflow_test; -#endif light = &frontsector->lightlist[i]; rlight = &dc_lightlist[p]; -#ifdef ESLOPE #define SLOPEPARAMS(slope, end1, end2, normalheight) \ - if (slope) { \ - end1 = P_GetZAt(slope, ds->leftpos.x, ds->leftpos.y); \ - end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y); \ - } else \ - end1 = end2 = normalheight; + end1 = P_GetZAt(slope, ds-> leftpos.x, ds-> leftpos.y, normalheight); \ + end2 = P_GetZAt(slope, ds->rightpos.x, ds->rightpos.y, normalheight); SLOPEPARAMS(light->slope, leftheight, rightheight, light->height) SLOPEPARAMS(*pfloor->b_slope, pfloorleft, pfloorright, *pfloor->bottomheight) @@ -852,8 +848,8 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (leftheight > pfloorleft && rightheight > pfloorright && i+1 < dc_numlights) { lightlist_t *nextlight = &frontsector->lightlist[i+1]; - if ((nextlight->slope ? P_GetZAt(nextlight->slope, ds->leftpos.x, ds->leftpos.y) : nextlight->height) > pfloorleft - && (nextlight->slope ? P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y) : nextlight->height) > pfloorright) + if (P_GetZAt(nextlight->slope, ds-> leftpos.x, ds-> leftpos.y, nextlight->height) > pfloorleft + && P_GetZAt(nextlight->slope, ds->rightpos.x, ds->rightpos.y, nextlight->height) > pfloorright) continue; } @@ -873,21 +869,9 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else if (overflow_test > (INT64)CLAMPMIN) rlight->heightstep = (fixed_t)overflow_test; else rlight->heightstep = CLAMPMIN; rlight->heightstep = (rlight->heightstep-rlight->height)/(range); -#else - if (light->height < *pfloor->bottomheight) - continue; - - if (light->height > *pfloor->topheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > *pfloor->topheight) - continue; - - lheight = light->height;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : light->height; - rlight->heightstep = -FixedMul (rw_scalestep, (lheight - viewz)); - rlight->height = (centeryfrac) - FixedMul((lheight - viewz), spryscale); -#endif rlight->flags = light->flags; if (light->flags & FF_CUTLEVEL) { -#ifdef ESLOPE SLOPEPARAMS(*light->caster->b_slope, leftheight, rightheight, *light->caster->bottomheight) #undef SLOPEPARAMS leftheight -= viewz; @@ -904,15 +888,10 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else if (overflow_test > (INT64)CLAMPMIN) rlight->botheightstep = (fixed_t)overflow_test; else rlight->botheightstep = CLAMPMIN; rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range); -#else - lheight = *light->caster->bottomheight;// > *pfloor->topheight ? *pfloor->topheight + FRACUNIT : *light->caster->bottomheight; - rlight->botheightstep = -FixedMul (rw_scalestep, (lheight - viewz)); - rlight->botheight = (centeryfrac) - FixedMul((lheight - viewz), spryscale); -#endif } rlight->lightlevel = *light->lightlevel; - rlight->extra_colormap = light->extra_colormap; + rlight->extra_colormap = *light->extra_colormap; // Check if the current light effects the colormap/lightlevel if (pfloor->flags & FF_FOG) @@ -920,7 +899,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else rlight->lightnum = (rlight->lightlevel >> LIGHTSEGSHIFT); - if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && rlight->extra_colormap->fog)) + if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))) ; else rlight->lightnum += curline->lightOffset; @@ -933,17 +912,17 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else { // Get correct light level! - if ((frontsector->extra_colormap && frontsector->extra_colormap->fog)) + if ((frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT); else if (pfloor->flags & FF_FOG) lightnum = (pfloor->master->frontsector->lightlevel >> LIGHTSEGSHIFT); - else if (colfunc == fuzzcolfunc) + else if (colfunc == colfuncs[COLDRAWFUNC_FUZZY]) lightnum = LIGHTLEVELS-1; else lightnum = R_FakeFlat(frontsector, &tempsec, &templight, &templight, false) ->lightlevel >> LIGHTSEGSHIFT; - if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && frontsector->extra_colormap->fog)) + if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG))) ; else lightnum += curline->lightOffset; @@ -962,17 +941,10 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) mceilingclip = ds->sprtopclip; dc_texheight = textureheight[texnum]>>FRACBITS; -#ifdef ESLOPE // calculate both left ends - if (*pfloor->t_slope) - left_top = P_GetZAt(*pfloor->t_slope, ds->leftpos.x, ds->leftpos.y) - viewz; - else - left_top = *pfloor->topheight - viewz; + left_top = P_GetFFloorTopZAt (pfloor, ds->leftpos.x, ds->leftpos.y) - viewz; + left_bottom = P_GetFFloorBottomZAt(pfloor, ds->leftpos.x, ds->leftpos.y) - viewz; - if (*pfloor->b_slope) - left_bottom = P_GetZAt(*pfloor->b_slope, ds->leftpos.x, ds->leftpos.y) - viewz; - else - left_bottom = *pfloor->bottomheight - viewz; skewslope = *pfloor->t_slope; // skew using top slope by default if (newline) { @@ -985,21 +957,18 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (slopeskew) dc_texturemid = left_top; else -#endif - dc_texturemid = *pfloor->topheight - viewz; + dc_texturemid = *pfloor->topheight - viewz; if (newline) { offsetvalue = sides[newline->sidenum[0]].rowoffset; if (newline->flags & ML_DONTPEGBOTTOM) { -#ifdef ESLOPE skewslope = *pfloor->b_slope; // skew using bottom slope if (slopeskew) dc_texturemid = left_bottom; else -#endif - offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; + offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; } } else @@ -1007,17 +976,14 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) offsetvalue = sides[pfloor->master->sidenum[0]].rowoffset; if (curline->linedef->flags & ML_DONTPEGBOTTOM) { -#ifdef ESLOPE skewslope = *pfloor->b_slope; // skew using bottom slope if (slopeskew) dc_texturemid = left_bottom; else -#endif - offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; + offsetvalue -= *pfloor->topheight - *pfloor->bottomheight; } } -#ifdef ESLOPE if (slopeskew) { angle_t lineangle = R_PointToAngle2(curline->v1->x, curline->v1->y, curline->v2->x, curline->v2->y); @@ -1025,7 +991,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) if (skewslope) ffloortextureslide = FixedMul(skewslope->zdelta, FINECOSINE((lineangle-skewslope->xydirection)>>ANGLETOFINESHIFT)); } -#endif dc_texturemid += offsetvalue; @@ -1035,28 +1000,28 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) //faB: handle case where multipatch texture is drawn on a 2sided wall, multi-patch textures // are not stored per-column with post info anymore in Doom Legacy if (textures[texnum]->holes) - colfunc_2s = R_DrawRepeatMaskedColumn; //render the usual 2sided single-patch packed texture + { + if (textures[texnum]->flip & 2) // vertically flipped? + { + colfunc_2s = R_DrawRepeatFlippedMaskedColumn; + lengthcol = textures[texnum]->height; + } + else + colfunc_2s = R_DrawRepeatMaskedColumn; // render the usual 2sided single-patch packed texture + } else { colfunc_2s = R_Render2sidedMultiPatchColumn; //render multipatch with no holes (no post_t info) - column2s_length = textures[texnum]->height; + lengthcol = textures[texnum]->height; } -#ifdef ESLOPE // Set heights according to plane, or slope, whichever { fixed_t right_top, right_bottom; // calculate right ends now - if (*pfloor->t_slope) - right_top = P_GetZAt(*pfloor->t_slope, ds->rightpos.x, ds->rightpos.y) - viewz; - else - right_top = *pfloor->topheight - viewz; - - if (*pfloor->b_slope) - right_bottom = P_GetZAt(*pfloor->b_slope, ds->rightpos.x, ds->rightpos.y) - viewz; - else - right_bottom = *pfloor->bottomheight - viewz; + right_top = P_GetFFloorTopZAt (pfloor, ds->rightpos.x, ds->rightpos.y) - viewz; + right_bottom = P_GetFFloorBottomZAt(pfloor, ds->rightpos.x, ds->rightpos.y) - viewz; // using INT64 to avoid 32bit overflow top_frac = (INT64)centeryfrac - (((INT64)left_top * ds->scale1) >> FRACBITS); @@ -1070,24 +1035,20 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) top_frac += top_step * (x1 - ds->x1); bottom_frac += bottom_step * (x1 - ds->x1); } -#endif // draw the columns for (dc_x = x1; dc_x <= x2; dc_x++) { if (maskedtexturecol[dc_x] != INT16_MAX) { -#ifdef ESLOPE if (ffloortextureslide) { // skew FOF walls if (oldx != -1) dc_texturemid += FixedMul(ffloortextureslide, (maskedtexturecol[oldx]-maskedtexturecol[dc_x])< (INT64)CLAMPMAX) sprtopscreen = windowtop = CLAMPMAX; else if (top_frac > (INT64)CLAMPMIN) sprtopscreen = windowtop = (fixed_t)top_frac; else sprtopscreen = windowtop = CLAMPMIN; @@ -1097,10 +1058,6 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) top_frac += top_step; bottom_frac += bottom_step; -#else - sprtopscreen = windowtop = (centeryfrac - FixedMul((dc_texturemid - offsetvalue), spryscale)); - sprbotscreen = windowbottom = FixedMul(*pfloor->topheight - *pfloor->bottomheight, spryscale) + sprtopscreen; -#endif // SoM: If column is out of range, why bother with it?? if (windowbottom < topbounds || windowtop > bottombounds) @@ -1150,7 +1107,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) else xwalllights = scalelight[lightnum]; - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE-1; @@ -1251,7 +1208,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) } // calculate lighting - pindex = FixedMul(spryscale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + pindex = FixedMul(spryscale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE - 1; @@ -1271,12 +1228,32 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor) spryscale += rw_scalestep; } } - colfunc = wallcolfunc; + colfunc = colfuncs[BASEDRAWFUNC]; #undef CLAMPMAX #undef CLAMPMIN } +// R_ExpandPlaneY +// +// A simple function to modify a visplane's top and bottom for a particular column +// Sort of like R_ExpandPlane in r_plane.c, except this is vertical expansion +static inline void R_ExpandPlaneY(visplane_t *pl, INT32 x, INT16 top, INT16 bottom) +{ + // Expand the plane, don't shrink it! + // note: top and bottom default to 0xFFFF and 0x0000 respectively, which is totally compatible with this + if (pl->top[x] > top) pl->top[x] = top; + if (pl->bottom[x] < bottom) pl->bottom[x] = bottom; +} + +// R_FFloorCanClip +// +// Returns true if a fake floor can clip a column away. +static boolean R_FFloorCanClip(visffloor_t *pfloor) +{ + return (cv_ffloorclip.value && !R_IsFFloorTranslucent(pfloor) && !pfloor->polyobj); +} + // // R_RenderSegLoop // Draws zero, one, or two textures (and possibly a masked @@ -1300,7 +1277,6 @@ UINT32 nombre = 100000; #endif //profile stuff --------------------------------------------------------- - static void R_RenderSegLoop (void) { angle_t angle; @@ -1310,9 +1286,7 @@ static void R_RenderSegLoop (void) INT32 mid; fixed_t texturecolumn = 0; -#ifdef ESLOPE fixed_t oldtexturecolumn = -1; -#endif INT32 top; INT32 bottom; INT32 i; @@ -1322,7 +1296,6 @@ static void R_RenderSegLoop (void) // mark floor / ceiling areas yl = (topfrac+HEIGHTUNIT-1)>>HEIGHTBITS; - // no space above wall? top = ceilingclip[rw_x]+1; // no space above wall? @@ -1331,16 +1304,19 @@ static void R_RenderSegLoop (void) if (markceiling) { +#if 0 bottom = yl-1; if (bottom >= floorclip[rw_x]) bottom = floorclip[rw_x]-1; - if (top <= bottom && ceilingplane) - { - ceilingplane->top[rw_x] = (INT16)top; - ceilingplane->bottom[rw_x] = (INT16)bottom; - } + if (top <= bottom) +#else + bottom = yl > floorclip[rw_x] ? floorclip[rw_x] : yl; + + if (top <= --bottom && ceilingplane) +#endif + R_ExpandPlaneY(ceilingplane, rw_x, top, bottom); } @@ -1354,34 +1330,27 @@ static void R_RenderSegLoop (void) if (markfloor) { top = yh < ceilingclip[rw_x] ? ceilingclip[rw_x] : yh; + if (++top <= bottom && floorplane) - { - floorplane->top[rw_x] = (INT16)top; - floorplane->bottom[rw_x] = (INT16)bottom; - } + R_ExpandPlaneY(floorplane, rw_x, top, bottom); } + rw_floormarked = false; + rw_ceilingmarked = false; + if (numffloors) { + INT16 fftop, ffbottom; + firstseg->frontscale[rw_x] = frontscale[rw_x]; top = ceilingclip[rw_x]+1; // PRBoom bottom = floorclip[rw_x]-1; // PRBoom for (i = 0; i < numffloors; i++) { -#ifdef POLYOBJECTS_PLANES if (ffloor[i].polyobj && (!curline->polyseg || ffloor[i].polyobj != curline->polyseg)) continue; - // FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red - if (curline->polyseg) { - if (ffloor[i].plane->minx > rw_x) - ffloor[i].plane->minx = rw_x; - else if (ffloor[i].plane->maxx < rw_x) - ffloor[i].plane->maxx = rw_x; - } -#endif - if (ffloor[i].height < viewz) { INT32 top_w = (ffloor[i].f_frac >> HEIGHTBITS) + 1; @@ -1393,17 +1362,41 @@ static void R_RenderSegLoop (void) if (bottom_w > bottom) bottom_w = bottom; -#ifdef POLYOBJECTS_PLANES // Polyobject-specific hack to fix plane leaking -Red - if (curline->polyseg && ffloor[i].polyobj && ffloor[i].polyobj == curline->polyseg && top_w >= bottom_w) { - ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF; - } else -#endif - - if (top_w <= bottom_w) + if (ffloor[i].polyobj && top_w >= bottom_w) { - ffloor[i].plane->top[rw_x] = (INT16)top_w; - ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w; + ffloor[i].plane->top[rw_x] = 0xFFFF; + ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 + } + else + { + if (top_w <= bottom_w) + { + fftop = (INT16)top_w; + ffbottom = (INT16)bottom_w; + + ffloor[i].plane->top[rw_x] = fftop; + ffloor[i].plane->bottom[rw_x] = ffbottom; + + // Lactozilla: Cull part of the column by the 3D floor if it can't be seen + // "bottom" is the top pixel of the floor column + if (ffbottom >= bottom-1 && R_FFloorCanClip(&ffloor[i])) + { + rw_floormarked = true; + floorclip[rw_x] = fftop; + if (yh > fftop) + yh = fftop; + + if (markfloor && floorplane) + floorplane->top[rw_x] = bottom; + + if (rw_silhouette) + { + (*rw_silhouette) |= SIL_BOTTOM; + (*rw_bsilheight) = INT32_MAX; + } + } + } } } else if (ffloor[i].height > viewz) @@ -1417,17 +1410,41 @@ static void R_RenderSegLoop (void) if (bottom_w > bottom) bottom_w = bottom; -#ifdef POLYOBJECTS_PLANES // Polyobject-specific hack to fix plane leaking -Red - if (curline->polyseg && ffloor[i].polyobj && ffloor[i].polyobj == curline->polyseg && top_w >= bottom_w) { - ffloor[i].plane->top[rw_x] = ffloor[i].plane->bottom[rw_x] = 0xFFFF; - } else -#endif - - if (top_w <= bottom_w) + if (ffloor[i].polyobj && top_w >= bottom_w) { - ffloor[i].plane->top[rw_x] = (INT16)top_w; - ffloor[i].plane->bottom[rw_x] = (INT16)bottom_w; + ffloor[i].plane->top[rw_x] = 0xFFFF; + ffloor[i].plane->bottom[rw_x] = 0x0000; // fix for sky plane drawing crashes - Monster Iestyn 25/05/18 + } + else + { + if (top_w <= bottom_w) + { + fftop = (INT16)top_w; + ffbottom = (INT16)bottom_w; + + ffloor[i].plane->top[rw_x] = fftop; + ffloor[i].plane->bottom[rw_x] = ffbottom; + + // Lactozilla: Cull part of the column by the 3D floor if it can't be seen + // "top" is the height of the ceiling column + if (fftop <= top+1 && R_FFloorCanClip(&ffloor[i])) + { + rw_ceilingmarked = true; + ceilingclip[rw_x] = ffbottom; + if (yl < ffbottom) + yl = ffbottom; + + if (markceiling && ceilingplane) + ceilingplane->bottom[rw_x] = top; + + if (rw_silhouette) + { + (*rw_silhouette) |= SIL_TOP; + (*rw_tsilheight) = INT32_MIN; + } + } + } } } } @@ -1435,10 +1452,9 @@ static void R_RenderSegLoop (void) //SoM: Calculate offsets for Thick fake floors. // calculate texture offset - angle = (rw_centerangle + xtoviewangle[rw_x])>>ANGLETOFINESHIFT; + angle = (rw_centerangle + xtoviewangle[viewssnum][rw_x])>>ANGLETOFINESHIFT; texturecolumn = rw_offset-FixedMul(FINETANGENT(angle),rw_distance); -#ifdef ESLOPE if (oldtexturecolumn != -1) { rw_bottomtexturemid += FixedMul(rw_bottomtextureslide, oldtexturecolumn-texturecolumn); rw_midtexturemid += FixedMul(rw_midtextureslide, oldtexturecolumn-texturecolumn); @@ -1446,7 +1462,6 @@ static void R_RenderSegLoop (void) rw_midtextureback += FixedMul(rw_midtexturebackslide, oldtexturecolumn-texturecolumn); } oldtexturecolumn = texturecolumn; -#endif texturecolumn >>= FRACBITS; @@ -1454,7 +1469,7 @@ static void R_RenderSegLoop (void) if (segtextured) { // calculate lighting - pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + pindex = FixedMul(rw_scale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE-1; @@ -1489,7 +1504,7 @@ static void R_RenderSegLoop (void) else xwalllights = scalelight[lightnum]; - pindex = FixedMul(rw_scale, FixedDiv(640, vid.width))>>LIGHTSCALESHIFT; + pindex = FixedMul(rw_scale, LIGHTRESOLUTIONFIX)>>LIGHTSCALESHIFT; if (pindex >= MAXLIGHTSCALE) pindex = MAXLIGHTSCALE-1; @@ -1499,7 +1514,7 @@ static void R_RenderSegLoop (void) else dc_lightlist[i].rcolormap = xwalllights[pindex]; - colfunc = R_DrawColumnShadowed_8; + colfunc = colfuncs[COLDRAWFUNC_SHADOWED]; } } @@ -1534,20 +1549,25 @@ static void R_RenderSegLoop (void) // dont draw anything more for this column, since // a midtexture blocks the view - ceilingclip[rw_x] = (INT16)viewheight; - floorclip[rw_x] = -1; + if (!rw_ceilingmarked) + ceilingclip[rw_x] = (INT16)viewheight; + if (!rw_floormarked) + floorclip[rw_x] = -1; } else { // note: don't use min/max macros, since casting from INT32 to INT16 is involved here - if (markceiling) + if (markceiling && (!rw_ceilingmarked)) ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; - if (markfloor) + if (markfloor && (!rw_floormarked)) floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; } } else { + INT16 topclip = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + INT16 bottomclip = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + // two sided line if (toptexture) { @@ -1561,7 +1581,10 @@ static void R_RenderSegLoop (void) if (mid >= yl) // back ceiling lower than front ceiling ? { if (yl >= viewheight) // entirely off bottom of screen - ceilingclip[rw_x] = (INT16)viewheight; + { + if (!rw_ceilingmarked) + ceilingclip[rw_x] = (INT16)viewheight; + } else if (mid >= 0) // safe to draw top texture { dc_yl = yl; @@ -1572,14 +1595,14 @@ static void R_RenderSegLoop (void) colfunc(); ceilingclip[rw_x] = (INT16)mid; } - else // entirely off top of screen + else if (!rw_ceilingmarked) // entirely off top of screen ceilingclip[rw_x] = -1; } - else - ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + else if (!rw_ceilingmarked) + ceilingclip[rw_x] = topclip; } - else if (markceiling) // no top wall - ceilingclip[rw_x] = (yl >= 0) ? ((yl > viewheight) ? (INT16)viewheight : (INT16)((INT16)yl - 1)) : -1; + else if (markceiling && (!rw_ceilingmarked)) // no top wall + ceilingclip[rw_x] = topclip; if (bottomtexture) { @@ -1594,7 +1617,10 @@ static void R_RenderSegLoop (void) if (mid <= yh) // back floor higher than front floor ? { if (yh < 0) // entirely off top of screen - floorclip[rw_x] = -1; + { + if (!rw_floormarked) + floorclip[rw_x] = -1; + } else if (mid < viewheight) // safe to draw bottom texture { dc_yl = mid; @@ -1606,14 +1632,14 @@ static void R_RenderSegLoop (void) colfunc(); floorclip[rw_x] = (INT16)mid; } - else // entirely off bottom of screen + else if (!rw_floormarked) // entirely off bottom of screen floorclip[rw_x] = (INT16)viewheight; } - else - floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + else if (!rw_floormarked) + floorclip[rw_x] = bottomclip; } - else if (markfloor) // no bottom wall - floorclip[rw_x] = (yh < viewheight) ? ((yh < -1) ? -1 : (INT16)((INT16)yh + 1)) : (INT16)viewheight; + else if (markfloor && (!rw_floormarked)) // no bottom wall + floorclip[rw_x] = bottomclip; } if (maskedtexture || numthicksides) @@ -1622,13 +1648,11 @@ static void R_RenderSegLoop (void) // for backdrawing of masked mid texture maskedtexturecol[rw_x] = (INT16)texturecolumn; -#ifdef ESLOPE if (maskedtextureheight != NULL) { maskedtextureheight[rw_x] = (!!(curline->linedef->flags & ML_DONTPEGBOTTOM) ^ !!(curline->linedef->flags & ML_EFFECT3) ? max(rw_midtexturemid, rw_midtextureback) : min(rw_midtexturemid, rw_midtextureback)); } -#endif } if (dc_numlights) @@ -1684,29 +1708,25 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t sineval; angle_t distangle, offsetangle; boolean longboi; -#ifndef ESLOPE - fixed_t vtop; -#endif INT32 lightnum; INT32 i, p; lightlist_t *light; r_lightlist_t *rlight; INT32 range; -#ifdef ESLOPE vertex_t segleft, segright; fixed_t ceilingfrontslide, floorfrontslide, ceilingbackslide, floorbackslide; -#endif static size_t maxdrawsegs = 0; -#ifdef ESLOPE maskedtextureheight = NULL; //initialize segleft and segright memset(&segleft, 0x00, sizeof(segleft)); memset(&segright, 0x00, sizeof(segright)); -#endif + + colfunc = colfuncs[BASEDRAWFUNC]; if (ds_p == drawsegs+maxdrawsegs) { + size_t curpos = curdrawsegs - drawsegs; size_t pos = ds_p - drawsegs; size_t newmax = maxdrawsegs ? maxdrawsegs*2 : 128; if (firstseg) @@ -1714,6 +1734,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) drawsegs = Z_Realloc(drawsegs, newmax*sizeof (*drawsegs), PU_STATIC, NULL); ds_p = drawsegs + pos; maxdrawsegs = newmax; + curdrawsegs = drawsegs + curpos; if (firstseg) firstseg = drawsegs + (size_t)firstseg; } @@ -1776,11 +1797,11 @@ void R_StoreWallRange(INT32 start, INT32 stop) } // end of code to remove limits on openings // calculate scale at both ends and step - ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[start]); + ds_p->scale1 = rw_scale = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[viewssnum][start]); if (stop > start) { - ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[stop]); + ds_p->scale2 = R_ScaleFromGlobalAngle(viewangle + xtoviewangle[viewssnum][stop]); range = stop-start; } else @@ -1809,14 +1830,13 @@ void R_StoreWallRange(INT32 start, INT32 stop) // calculate texture boundaries // and decide if floor / ceiling marks are needed -#ifdef ESLOPE // Figure out map coordinates of where start and end are mapping to on seg, so we can clip right for slope bullshit if (frontsector->hasslope || (backsector && backsector->hasslope)) // Commenting this out for FOFslop. -Red { angle_t temp; // left - temp = xtoviewangle[start]+viewangle; + temp = xtoviewangle[viewssnum][start]+viewangle; { // Both lines can be written in slope-intercept form, so figure out line intersection @@ -1838,7 +1858,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) } // right - temp = xtoviewangle[stop]+viewangle; + temp = xtoviewangle[viewssnum][stop]+viewangle; { // Both lines can be written in slope-intercept form, so figure out line intersection @@ -1860,29 +1880,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } - if (frontsector->c_slope) { - worldtop = P_GetZAt(frontsector->c_slope, segleft.x, segleft.y) - viewz; - worldtopslope = P_GetZAt(frontsector->c_slope, segright.x, segright.y) - viewz; - } else { - worldtopslope = -#else - { -#endif - worldtop = frontsector->ceilingheight - viewz; - } +#define SLOPEPARAMS(slope, end1, end2, normalheight) \ + end1 = P_GetZAt(slope, segleft.x, segleft.y, normalheight); \ + end2 = P_GetZAt(slope, segright.x, segright.y, normalheight); -#ifdef ESLOPE - if (frontsector->f_slope) { - worldbottom = P_GetZAt(frontsector->f_slope, segleft.x, segleft.y) - viewz; - worldbottomslope = P_GetZAt(frontsector->f_slope, segright.x, segright.y) - viewz; - } else { - worldbottomslope = -#else - { -#endif - worldbottom = frontsector->floorheight - viewz; - } + SLOPEPARAMS(frontsector->c_slope, worldtop, worldtopslope, frontsector->ceilingheight) + SLOPEPARAMS(frontsector->f_slope, worldbottom, worldbottomslope, frontsector->floorheight) + // subtract viewz from these to turn them into + // positions relative to the camera's z position + worldtop -= viewz; + worldtopslope -= viewz; + worldbottom -= viewz; + worldbottomslope -= viewz; midtexture = toptexture = bottomtexture = maskedtexture = 0; ds_p->maskedtexturecol = NULL; @@ -1899,23 +1909,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) { for (i = 0; i < numffloors; i++) { -#ifdef POLYOBJECTS_PLANES if (ffloor[i].polyobj && (!ds_p->curline->polyseg || ffloor[i].polyobj != ds_p->curline->polyseg)) continue; -#endif -#ifdef ESLOPE - if (ffloor[i].slope) { - ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft.x, segleft.y) - viewz; - ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y) - viewz; - } else - ffloor[i].f_pos_slope = -#endif - ffloor[i].f_pos = ffloor[i].height - viewz; + ffloor[i].f_pos = P_GetZAt(ffloor[i].slope, segleft .x, segleft .y, ffloor[i].height) - viewz; + ffloor[i].f_pos_slope = P_GetZAt(ffloor[i].slope, segright.x, segright.y, ffloor[i].height) - viewz; } } -#ifdef ESLOPE // Set up texture Y offset slides for sloped walls rw_toptextureslide = rw_midtextureslide = rw_bottomtextureslide = 0; ceilingfrontslide = floorfrontslide = ceilingbackslide = floorbackslide = 0; @@ -1935,7 +1936,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (backsector && backsector->c_slope) ceilingbackslide = FixedMul(backsector->c_slope->zdelta, FINECOSINE((lineangle-backsector->c_slope->xydirection)>>ANGLETOFINESHIFT)); } -#endif if (!backsector) { @@ -1945,33 +1945,22 @@ void R_StoreWallRange(INT32 start, INT32 stop) texheight = textureheight[midtexture]; // a single sided line is terminal, so it must mark ends markfloor = markceiling = true; -#ifdef ESLOPE if (linedef->flags & ML_EFFECT2) { if (linedef->flags & ML_DONTPEGBOTTOM) rw_midtexturemid = frontsector->floorheight + texheight - viewz; else rw_midtexturemid = frontsector->ceilingheight - viewz; } - else -#endif - if (linedef->flags & ML_DONTPEGBOTTOM) + else if (linedef->flags & ML_DONTPEGBOTTOM) { -#ifdef ESLOPE rw_midtexturemid = worldbottom + texheight; rw_midtextureslide = floorfrontslide; -#else - vtop = frontsector->floorheight + texheight; - // bottom of texture at bottom - rw_midtexturemid = vtop - viewz; -#endif } else { // top of texture at top rw_midtexturemid = worldtop; -#ifdef ESLOPE rw_midtextureslide = ceilingfrontslide; -#endif } rw_midtexturemid += sidedef->rowoffset; @@ -1984,143 +1973,117 @@ void R_StoreWallRange(INT32 start, INT32 stop) else { // two sided line + boolean bothceilingssky = false; // turned on if both back and front ceilings are sky + boolean bothfloorssky = false; // likewise, but for floors -#ifdef ESLOPE - if (backsector->c_slope) { - worldhigh = P_GetZAt(backsector->c_slope, segleft.x, segleft.y) - viewz; - worldhighslope = P_GetZAt(backsector->c_slope, segright.x, segright.y) - viewz; - } else { - worldhighslope = -#else - { -#endif - worldhigh = backsector->ceilingheight - viewz; - } - - -#ifdef ESLOPE - if (backsector->f_slope) { - worldlow = P_GetZAt(backsector->f_slope, segleft.x, segleft.y) - viewz; - worldlowslope = P_GetZAt(backsector->f_slope, segright.x, segright.y) - viewz; - } else { - worldlowslope = -#else - { -#endif - worldlow = backsector->floorheight - viewz; - } - + SLOPEPARAMS(backsector->c_slope, worldhigh, worldhighslope, backsector->ceilingheight) + SLOPEPARAMS(backsector->f_slope, worldlow, worldlowslope, backsector->floorheight) + worldhigh -= viewz; + worldhighslope -= viewz; + worldlow -= viewz; + worldlowslope -= viewz; // hack to allow height changes in outdoor areas + // This is what gets rid of the upper textures if there should be sky if (frontsector->ceilingpic == skyflatnum && backsector->ceilingpic == skyflatnum) { -#ifdef ESLOPE - worldtopslope = worldhighslope = -#endif - worldtop = worldhigh; + bothceilingssky = true; + } + + // likewise, but for floors and upper textures + if (frontsector->floorpic == skyflatnum + && backsector->floorpic == skyflatnum) + { + bothfloorssky = true; } ds_p->sprtopclip = ds_p->sprbottomclip = NULL; ds_p->silhouette = 0; - if ( -#ifdef ESLOPE - worldbottomslope > worldlowslope || -#endif - worldbottom > worldlow) + if (!bothfloorssky) { - ds_p->silhouette = SIL_BOTTOM; -#ifdef ESLOPE - if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz) + if (worldbottomslope > worldlowslope || worldbottom > worldlow) + { + ds_p->silhouette = SIL_BOTTOM; + if (P_GetSectorFloorZAt(backsector, viewx, viewy) > viewz) + ds_p->bsilheight = INT32_MAX; + else + ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight); + } + else if (P_GetSectorFloorZAt(backsector, viewx, viewy) > viewz) + { + ds_p->silhouette = SIL_BOTTOM; ds_p->bsilheight = INT32_MAX; - else - ds_p->bsilheight = (frontsector->f_slope ? INT32_MAX : frontsector->floorheight); -#else - ds_p->bsilheight = frontsector->floorheight; -#endif - } -#ifdef ESLOPE - else if ((backsector->f_slope ? P_GetZAt(backsector->f_slope, viewx, viewy) : backsector->floorheight) > viewz) -#else - else if (backsector->floorheight > viewz) -#endif - { - ds_p->silhouette = SIL_BOTTOM; - ds_p->bsilheight = INT32_MAX; - // ds_p->sprbottomclip = negonearray; + // ds_p->sprbottomclip = negonearray; + } } - if ( -#ifdef ESLOPE - worldtopslope < worldhighslope || -#endif - worldtop < worldhigh) + if (!bothceilingssky) { - ds_p->silhouette |= SIL_TOP; -#ifdef ESLOPE - if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz) + if (worldtopslope < worldhighslope || worldtop < worldhigh) + { + ds_p->silhouette |= SIL_TOP; + if (P_GetSectorCeilingZAt(backsector, viewx, viewy) < viewz) + ds_p->tsilheight = INT32_MIN; + else + ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight); + } + else if (P_GetSectorCeilingZAt(backsector, viewx, viewy) < viewz) + { + ds_p->silhouette |= SIL_TOP; ds_p->tsilheight = INT32_MIN; - else - ds_p->tsilheight = (frontsector->c_slope ? INT32_MIN : frontsector->ceilingheight); -#else - ds_p->tsilheight = frontsector->ceilingheight; -#endif - } -#ifdef ESLOPE - else if ((backsector->c_slope ? P_GetZAt(backsector->c_slope, viewx, viewy) : backsector->ceilingheight) < viewz) -#else - else if (backsector->ceilingheight < viewz) -#endif - { - ds_p->silhouette |= SIL_TOP; - ds_p->tsilheight = INT32_MIN; - // ds_p->sprtopclip = screenheightarray; + // ds_p->sprtopclip = screenheightarray; + } } - if (viewsector != frontsector && viewsector != backsector) + if (!bothceilingssky && !bothfloorssky) { -#ifdef ESLOPE if (worldhigh <= worldbottom && worldhighslope <= worldbottomslope) -#else - if (worldhigh <= worldbottom) -#endif { ds_p->sprbottomclip = negonearray; ds_p->bsilheight = INT32_MAX; ds_p->silhouette |= SIL_BOTTOM; } -#ifdef ESLOPE if (worldlow >= worldtop && worldlowslope >= worldtopslope) -#else - if (worldlow >= worldtop) -#endif { ds_p->sprtopclip = screenheightarray; ds_p->tsilheight = INT32_MIN; ds_p->silhouette |= SIL_TOP; } + } + + //SoM: 3/25/2000: This code fixes an automap bug that didn't check + // frontsector->ceiling and backsector->floor to see if a door was closed. + // Without the following code, sprites get displayed behind closed doors. + if (!bothceilingssky && !bothfloorssky) + { + if (doorclosed || (worldhigh <= worldbottom && worldhighslope <= worldbottomslope)) + { + ds_p->sprbottomclip = negonearray; + ds_p->bsilheight = INT32_MAX; + ds_p->silhouette |= SIL_BOTTOM; + } + + if (doorclosed || (worldlow >= worldtop && worldlowslope >= worldtopslope)) + { // killough 1/17/98, 2/8/98 + ds_p->sprtopclip = screenheightarray; + ds_p->tsilheight = INT32_MIN; + ds_p->silhouette |= SIL_TOP; + } //SoM: 3/25/2000: This code fixes an automap bug that didn't check // frontsector->ceiling and backsector->floor to see if a door was closed. // Without the following code, sprites get displayed behind closed doors. { -#ifdef ESLOPE if (doorclosed || (worldhigh <= worldbottom && worldhighslope <= worldbottomslope)) -#else - if (doorclosed || backsector->ceilingheight <= frontsector->floorheight) -#endif { ds_p->sprbottomclip = negonearray; ds_p->bsilheight = INT32_MAX; ds_p->silhouette |= SIL_BOTTOM; } -#ifdef ESLOPE if (doorclosed || (worldlow >= worldtop && worldlowslope >= worldtopslope)) -#else - if (doorclosed || backsector->floorheight >= frontsector->ceilingheight) -#endif { // killough 1/17/98, 2/8/98 ds_p->sprtopclip = screenheightarray; ds_p->tsilheight = INT32_MIN; @@ -2129,11 +2092,15 @@ void R_StoreWallRange(INT32 start, INT32 stop) } } - if (worldlow != worldbottom -#ifdef ESLOPE + if (bothfloorssky) + { + // see double ceiling skies comment + // this is the same but for upside down thok barriers where the floor is sky and the ceiling is normal + markfloor = false; + } + else if (worldlow != worldbottom || worldlowslope != worldbottomslope || backsector->f_slope != frontsector->f_slope -#endif || backsector->floorpic != frontsector->floorpic || backsector->lightlevel != frontsector->lightlevel //SoM: 3/22/2000: Check floor x and y offsets. @@ -2141,7 +2108,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) || backsector->floor_yoffs != frontsector->floor_yoffs || backsector->floorpic_angle != frontsector->floorpic_angle //SoM: 3/22/2000: Prevents bleeding. - || frontsector->heightsec != -1 + || (frontsector->heightsec != -1 && frontsector->floorpic != skyflatnum) || backsector->floorlightsec != frontsector->floorlightsec //SoM: 4/3/2000: Check for colormaps || frontsector->extra_colormap != backsector->extra_colormap @@ -2155,11 +2122,16 @@ void R_StoreWallRange(INT32 start, INT32 stop) markfloor = false; } - if (worldhigh != worldtop -#ifdef ESLOPE + if (bothceilingssky) + { + // double ceiling skies are special + // we don't want to lower the ceiling clipping, (no new plane is drawn anyway) + // so we can see the floor of thok barriers always regardless of sector properties + markceiling = false; + } + else if (worldhigh != worldtop || worldhighslope != worldtopslope || backsector->c_slope != frontsector->c_slope -#endif || backsector->ceilingpic != frontsector->ceilingpic || backsector->lightlevel != frontsector->lightlevel //SoM: 3/22/2000: Check floor x and y offsets. @@ -2181,19 +2153,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) markceiling = false; } - if (backsector->ceilingheight <= frontsector->floorheight || - backsector->floorheight >= frontsector->ceilingheight) + if (!bothceilingssky && !bothfloorssky) { - // closed door - markceiling = markfloor = true; + if ((worldhigh <= worldbottom && worldhighslope <= worldbottomslope) + || (worldlow >= worldtop && worldlowslope >= worldtopslope)) + { + // closed door + markceiling = markfloor = true; + } } // check TOP TEXTURE - if (worldhigh < worldtop -#ifdef ESLOPE - || worldhighslope < worldtopslope -#endif - ) + if (!bothceilingssky // never draw the top texture if on + && (worldhigh < worldtop || worldhighslope < worldtopslope)) { fixed_t texheight; // top texture @@ -2213,66 +2185,47 @@ void R_StoreWallRange(INT32 start, INT32 stop) toptexture = R_GetTextureNum(sidedef->toptexture); texheight = textureheight[toptexture]; } -#ifdef ESLOPE if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked if (linedef->flags & ML_DONTPEGTOP) rw_toptexturemid = frontsector->ceilingheight - viewz; else rw_toptexturemid = backsector->ceilingheight - viewz; - } else -#endif - if (linedef->flags & ML_DONTPEGTOP) + } + else if (linedef->flags & ML_DONTPEGTOP) { // top of texture at top rw_toptexturemid = worldtop; -#ifdef ESLOPE rw_toptextureslide = ceilingfrontslide; -#endif } else { -#ifdef ESLOPE rw_toptexturemid = worldhigh + texheight; rw_toptextureslide = ceilingbackslide; -#else - vtop = backsector->ceilingheight + texheight; - // bottom of texture - rw_toptexturemid = vtop - viewz; -#endif } } // check BOTTOM TEXTURE - if (worldlow > worldbottom -#ifdef ESLOPE - || worldlowslope > worldbottomslope -#endif - ) //seulement si VISIBLE!!! + if (!bothfloorssky // never draw the bottom texture if on + && (worldlow > worldbottom || worldlowslope > worldbottomslope)) // Only if VISIBLE!!! { // bottom texture bottomtexture = R_GetTextureNum(sidedef->bottomtexture); -#ifdef ESLOPE if (!(linedef->flags & ML_EFFECT1)) { // Ignore slopes for lower/upper textures unless flag is checked if (linedef->flags & ML_DONTPEGBOTTOM) rw_bottomtexturemid = frontsector->floorheight - viewz; else rw_bottomtexturemid = backsector->floorheight - viewz; - } else -#endif - if (linedef->flags & ML_DONTPEGBOTTOM) + } + else if (linedef->flags & ML_DONTPEGBOTTOM) { // bottom of texture at bottom // top of texture at top rw_bottomtexturemid = worldbottom; -#ifdef ESLOPE rw_bottomtextureslide = floorfrontslide; -#endif } else { // top of texture at top rw_bottomtexturemid = worldlow; -#ifdef ESLOPE rw_bottomtextureslide = floorbackslide; -#endif } } @@ -2285,12 +2238,10 @@ void R_StoreWallRange(INT32 start, INT32 stop) ffloor_t *rover; ffloor_t *r2; fixed_t lowcut, highcut; -#ifdef ESLOPE fixed_t lowcutslope, highcutslope; // Used for height comparisons and etc across FOFs and slopes fixed_t high1, highslope1, low1, lowslope1, high2, highslope2, low2, lowslope2; -#endif //markceiling = markfloor = true; maskedtexture = true; @@ -2300,10 +2251,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) lowcut = max(worldbottom, worldlow) + viewz; highcut = min(worldtop, worldhigh) + viewz; -#ifdef ESLOPE lowcutslope = max(worldbottomslope, worldlowslope) + viewz; highcutslope = min(worldtopslope, worldhighslope) + viewz; -#endif if (frontsector->ffloors && backsector->ffloors) { @@ -2312,30 +2261,17 @@ void R_StoreWallRange(INT32 start, INT32 stop) { if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS)) continue; - if (rover->flags & FF_INVERTSIDES) + if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES) continue; if (rover->norender == leveltime) continue; -#ifdef ESLOPE - if (*rover->t_slope) { - high1 = P_GetZAt(*rover->t_slope, segleft.x, segleft.y); - highslope1 = P_GetZAt(*rover->t_slope, segright.x, segright.y); - } else - high1 = highslope1 = *rover->topheight; - if (*rover->b_slope) { - low1 = P_GetZAt(*rover->b_slope, segleft.x, segleft.y); - lowslope1 = P_GetZAt(*rover->b_slope, segright.x, segright.y); - } else - low1 = lowslope1 = *rover->bottomheight; + SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; -#else - if (*rover->topheight < lowcut || *rover->bottomheight > highcut) - continue; -#endif for (r2 = frontsector->ffloors; r2; r2 = r2->next) { @@ -2359,28 +2295,13 @@ void R_StoreWallRange(INT32 start, INT32 stop) continue; } -#ifdef ESLOPE - if (*r2->t_slope) { - high2 = P_GetZAt(*r2->t_slope, segleft.x, segleft.y); - highslope2 = P_GetZAt(*r2->t_slope, segright.x, segright.y); - } else - high2 = highslope2 = *r2->topheight; - if (*r2->b_slope) { - low2 = P_GetZAt(*r2->b_slope, segleft.x, segleft.y); - lowslope2 = P_GetZAt(*r2->b_slope, segright.x, segright.y); - } else - low2 = lowslope2 = *r2->bottomheight; + SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight) + SLOPEPARAMS(*r2->b_slope, low2, lowslope2, *r2->bottomheight) if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope)) continue; if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2)) continue; -#else - if (*r2->topheight < lowcut || *r2->bottomheight > highcut) - continue; - if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight) - continue; -#endif break; } @@ -2395,30 +2316,17 @@ void R_StoreWallRange(INT32 start, INT32 stop) { if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS)) continue; - if (!(rover->flags & FF_ALLSIDES)) + if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) continue; if (rover->norender == leveltime) continue; -#ifdef ESLOPE - if (*rover->t_slope) { - high1 = P_GetZAt(*rover->t_slope, segleft.x, segleft.y); - highslope1 = P_GetZAt(*rover->t_slope, segright.x, segright.y); - } else - high1 = highslope1 = *rover->topheight; - if (*rover->b_slope) { - low1 = P_GetZAt(*rover->b_slope, segleft.x, segleft.y); - lowslope1 = P_GetZAt(*rover->b_slope, segright.x, segright.y); - } else - low1 = lowslope1 = *rover->bottomheight; + SLOPEPARAMS(*rover->t_slope, high1, highslope1, *rover->topheight) + SLOPEPARAMS(*rover->b_slope, low1, lowslope1, *rover->bottomheight) if ((high1 < lowcut && highslope1 < lowcutslope) || (low1 > highcut && lowslope1 > highcutslope)) continue; -#else - if (*rover->topheight < lowcut || *rover->bottomheight > highcut) - continue; -#endif for (r2 = backsector->ffloors; r2; r2 = r2->next) { @@ -2442,28 +2350,13 @@ void R_StoreWallRange(INT32 start, INT32 stop) continue; } -#ifdef ESLOPE - if (*r2->t_slope) { - high2 = P_GetZAt(*r2->t_slope, segleft.x, segleft.y); - highslope2 = P_GetZAt(*r2->t_slope, segright.x, segright.y); - } else - high2 = highslope2 = *r2->topheight; - if (*r2->b_slope) { - low2 = P_GetZAt(*r2->b_slope, segleft.x, segleft.y); - lowslope2 = P_GetZAt(*r2->b_slope, segright.x, segright.y); - } else - low2 = lowslope2 = *r2->bottomheight; - + SLOPEPARAMS(*r2->t_slope, high2, highslope2, *r2->topheight) + SLOPEPARAMS(*r2->b_slope, low2, lowslope2, *r2->bottomheight) +#undef SLOPEPARAMS if ((high2 < lowcut || highslope2 < lowcutslope) || (low2 > highcut || lowslope2 > highcutslope)) continue; if ((high1 > high2 || highslope1 > highslope2) || (low1 < low2 || lowslope1 < lowslope2)) continue; -#else - if (*r2->topheight < lowcut || *r2->bottomheight > highcut) - continue; - if (*rover->topheight > *r2->topheight || *rover->bottomheight < *r2->bottomheight) - continue; -#endif break; } @@ -2478,22 +2371,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) { for (rover = backsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next) { - if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || rover->flags & FF_INVERTSIDES) + if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS)) + continue; + if (!(rover->flags & FF_ALLSIDES) && rover->flags & FF_INVERTSIDES) continue; if (rover->norender == leveltime) continue; -#ifdef ESLOPE // Oy vey. - if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz - && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz) - ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz - && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz)) + if ( ((P_GetFFloorTopZAt (rover, segleft .x, segleft .y)) <= worldbottom + viewz + && (P_GetFFloorTopZAt (rover, segright.x, segright.y)) <= worldbottomslope + viewz) + ||((P_GetFFloorBottomZAt(rover, segleft .x, segleft .y)) >= worldtop + viewz + && (P_GetFFloorBottomZAt(rover, segright.x, segright.y)) >= worldtopslope + viewz)) continue; -#else - if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight) - continue; -#endif ds_p->thicksides[i] = rover; i++; @@ -2503,29 +2393,24 @@ void R_StoreWallRange(INT32 start, INT32 stop) { for (rover = frontsector->ffloors, i = 0; rover && i < MAXFFLOORS; rover = rover->next) { - if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS) || !(rover->flags & FF_ALLSIDES)) + if (!(rover->flags & FF_RENDERSIDES) || !(rover->flags & FF_EXISTS)) + continue; + if (!(rover->flags & FF_ALLSIDES || rover->flags & FF_INVERTSIDES)) continue; if (rover->norender == leveltime) continue; -#ifdef ESLOPE // Oy vey. - if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldbottom+viewz - && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldbottomslope+viewz) - ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldtop+viewz - && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldtopslope+viewz)) + if ( (P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= worldbottom + viewz + && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldbottomslope + viewz) + ||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldtop + viewz + && P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldtopslope + viewz)) continue; - if (( (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) <= worldlow+viewz - && (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) <= worldlowslope+viewz) - ||((*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) >= worldhigh+viewz - && (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) >= worldhighslope+viewz)) + if ( (P_GetFFloorTopZAt (rover, segleft .x, segleft .y) <= worldlow + viewz + && P_GetFFloorTopZAt (rover, segright.x, segright.y) <= worldlowslope + viewz) + ||(P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) >= worldhigh + viewz + && P_GetFFloorBottomZAt(rover, segright.x, segright.y) >= worldhighslope + viewz)) continue; -#else - if (*rover->topheight <= frontsector->floorheight || *rover->bottomheight >= frontsector->ceilingheight) - continue; - if (*rover->topheight <= backsector->floorheight || *rover->bottomheight >= backsector->ceilingheight) - continue; -#endif ds_p->thicksides[i] = rover; i++; @@ -2545,40 +2430,45 @@ void R_StoreWallRange(INT32 start, INT32 stop) else ds_p->maskedtexturecol = ds_p->thicksidecol; -#ifdef ESLOPE maskedtextureheight = ds_p->maskedtextureheight; // note to red, this == &(ds_p->maskedtextureheight[0]) -#ifdef POLYOBJECTS - if (curline->polyseg) { // use REAL front and back floors please, so midtexture rendering isn't mucked up + if (curline->polyseg) + { // use REAL front and back floors please, so midtexture rendering isn't mucked up rw_midtextureslide = rw_midtexturebackslide = 0; if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) rw_midtexturemid = rw_midtextureback = max(curline->frontsector->floorheight, curline->backsector->floorheight) - viewz; else rw_midtexturemid = rw_midtextureback = min(curline->frontsector->ceilingheight, curline->backsector->ceilingheight) - viewz; - } else -#endif - // Set midtexture starting height - if (linedef->flags & ML_EFFECT2) { // Ignore slopes when texturing - rw_midtextureslide = rw_midtexturebackslide = 0; - if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) - rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz; - else - rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; + } + else + { + // Set midtexture starting height + if (linedef->flags & ML_EFFECT2) + { // Ignore slopes when texturing + rw_midtextureslide = rw_midtexturebackslide = 0; + if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) + rw_midtexturemid = rw_midtextureback = max(frontsector->floorheight, backsector->floorheight) - viewz; + else + rw_midtexturemid = rw_midtextureback = min(frontsector->ceilingheight, backsector->ceilingheight) - viewz; - } else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) { - rw_midtexturemid = worldbottom; - rw_midtextureslide = floorfrontslide; - rw_midtextureback = worldlow; - rw_midtexturebackslide = floorbackslide; - } else { - rw_midtexturemid = worldtop; - rw_midtextureslide = ceilingfrontslide; - rw_midtextureback = worldhigh; - rw_midtexturebackslide = ceilingbackslide; + } + else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) + { + rw_midtexturemid = worldbottom; + rw_midtextureslide = floorfrontslide; + rw_midtextureback = worldlow; + rw_midtexturebackslide = floorbackslide; + } + else + { + rw_midtexturemid = worldtop; + rw_midtextureslide = ceilingfrontslide; + rw_midtextureback = worldhigh; + rw_midtexturebackslide = ceilingbackslide; + } } rw_midtexturemid += sidedef->rowoffset; rw_midtextureback += sidedef->rowoffset; -#endif maskedtexture = true; } @@ -2639,22 +2529,13 @@ void R_StoreWallRange(INT32 start, INT32 stop) // and doesn't need to be marked. if (frontsector->heightsec == -1) { - if (( -#ifdef ESLOPE - frontsector->f_slope ? P_GetZAt(frontsector->f_slope, viewx, viewy) : -#endif - frontsector->floorheight) >= viewz) + if (frontsector->floorpic != skyflatnum && P_GetSectorFloorZAt(frontsector, viewx, viewy) >= viewz) { // above view plane markfloor = false; } - if (( -#ifdef ESLOPE - frontsector->c_slope ? P_GetZAt(frontsector->c_slope, viewx, viewy) : -#endif - frontsector->ceilingheight) <= viewz && - frontsector->ceilingpic != skyflatnum) + if (frontsector->ceilingpic != skyflatnum && P_GetSectorCeilingZAt(frontsector, viewx, viewy) <= viewz) { // below view plane markceiling = false; @@ -2664,10 +2545,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) // calculate incremental stepping values for texture edges worldtop >>= 4; worldbottom >>= 4; -#ifdef ESLOPE worldtopslope >>= 4; worldbottomslope >>= 4; -#endif if (linedef->special == HORIZONSPECIAL) { // HORIZON LINES topstep = bottomstep = 0; @@ -2680,7 +2559,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) bottomstep = -FixedMul (rw_scalestep,worldbottom); bottomfrac = (centeryfrac>>4) - FixedMul (worldbottom, rw_scale); -#ifdef ESLOPE if (frontsector->c_slope) { fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldtopslope, ds_p->scale2); topstep = (topfracend-topfrac)/(range); @@ -2689,7 +2567,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldbottomslope, ds_p->scale2); bottomstep = (bottomfracend-bottomfrac)/(range); } -#endif } dc_numlights = 0; @@ -2705,87 +2582,61 @@ void R_StoreWallRange(INT32 start, INT32 stop) for (i = p = 0; i < dc_numlights; i++) { -#ifdef ESLOPE fixed_t leftheight, rightheight; -#endif light = &frontsector->lightlist[i]; rlight = &dc_lightlist[p]; -#ifdef ESLOPE - if (light->slope) { - leftheight = P_GetZAt(light->slope, segleft.x, segleft.y); - rightheight = P_GetZAt(light->slope, segright.x, segright.y); + leftheight = P_GetLightZAt(light, segleft.x, segleft.y); + rightheight = P_GetLightZAt(light, segright.x, segright.y); + if (light->slope) // Flag sector as having slopes frontsector->hasslope = true; - } else - leftheight = rightheight = light->height; leftheight -= viewz; rightheight -= viewz; leftheight >>= 4; rightheight >>= 4; -#endif if (i != 0) { -#ifdef ESLOPE if (leftheight < worldbottom && rightheight < worldbottomslope) continue; if (leftheight > worldtop && rightheight > worldtopslope && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight) continue; -#else - if (light->height < frontsector->floorheight) - continue; - - if (light->height > frontsector->ceilingheight && i+1 < dc_numlights && frontsector->lightlist[i+1].height > frontsector->ceilingheight) - continue; -#endif } -#ifdef ESLOPE rlight->height = (centeryfrac>>4) - FixedMul(leftheight, rw_scale); rlight->heightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2); rlight->heightstep = (rlight->heightstep-rlight->height)/(range); -#else - rlight->height = (centeryfrac>>4) - FixedMul((light->height - viewz) >> 4, rw_scale); - rlight->heightstep = -FixedMul (rw_scalestep, (light->height - viewz) >> 4); -#endif rlight->flags = light->flags; if (light->caster && light->caster->flags & FF_CUTSOLIDS) { -#ifdef ESLOPE - if (*light->caster->b_slope) { - leftheight = P_GetZAt(*light->caster->b_slope, segleft.x, segleft.y); - rightheight = P_GetZAt(*light->caster->b_slope, segright.x, segright.y); + leftheight = P_GetFFloorBottomZAt(light->caster, segleft.x, segleft.y); + rightheight = P_GetFFloorBottomZAt(light->caster, segright.x, segright.y); + if (*light->caster->b_slope) // Flag sector as having slopes frontsector->hasslope = true; - } else - leftheight = rightheight = *light->caster->bottomheight; - leftheight -= viewz; + leftheight -= viewz; rightheight -= viewz; - leftheight >>= 4; + leftheight >>= 4; rightheight >>= 4; rlight->botheight = (centeryfrac>>4) - FixedMul(leftheight, rw_scale); rlight->botheightstep = (centeryfrac>>4) - FixedMul(rightheight, ds_p->scale2); rlight->botheightstep = (rlight->botheightstep-rlight->botheight)/(range); -#else - rlight->botheight = (centeryfrac >> 4) - FixedMul((*light->caster->bottomheight - viewz) >> 4, rw_scale); - rlight->botheightstep = -FixedMul (rw_scalestep, (*light->caster->bottomheight - viewz) >> 4); -#endif } rlight->lightlevel = *light->lightlevel; - rlight->extra_colormap = light->extra_colormap; + rlight->extra_colormap = *light->extra_colormap; p++; } @@ -2797,9 +2648,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) for (i = 0; i < numffloors; i++) { ffloor[i].f_pos >>= 4; -#ifdef ESLOPE ffloor[i].f_pos_slope >>= 4; -#endif if (linedef->special == HORIZONSPECIAL) // Horizon lines extend FOFs in contact with them too. { ffloor[i].f_step = 0; @@ -2808,13 +2657,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) } else { -#ifdef ESLOPE ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale); ffloor[i].f_step = ((centeryfrac>>4) - FixedMul(ffloor[i].f_pos_slope, ds_p->scale2) - ffloor[i].f_frac)/(range); -#else - ffloor[i].f_step = FixedMul(-rw_scalestep, ffloor[i].f_pos); - ffloor[i].f_frac = (centeryfrac>>4) - FixedMul(ffloor[i].f_pos, rw_scale); -#endif } } } @@ -2823,42 +2667,34 @@ void R_StoreWallRange(INT32 start, INT32 stop) { worldhigh >>= 4; worldlow >>= 4; -#ifdef ESLOPE worldhighslope >>= 4; worldlowslope >>= 4; -#endif if (toptexture) { pixhigh = (centeryfrac>>4) - FixedMul (worldhigh, rw_scale); pixhighstep = -FixedMul (rw_scalestep,worldhigh); -#ifdef ESLOPE if (backsector->c_slope) { fixed_t topfracend = (centeryfrac>>4) - FixedMul (worldhighslope, ds_p->scale2); pixhighstep = (topfracend-pixhigh)/(range); } -#endif } if (bottomtexture) { pixlow = (centeryfrac>>4) - FixedMul (worldlow, rw_scale); pixlowstep = -FixedMul (rw_scalestep,worldlow); -#ifdef ESLOPE if (backsector->f_slope) { fixed_t bottomfracend = (centeryfrac>>4) - FixedMul (worldlowslope, ds_p->scale2); pixlowstep = (bottomfracend-pixlow)/(range); } -#endif } { ffloor_t * rover; -#ifdef ESLOPE fixed_t roverleft, roverright; fixed_t planevistest; -#endif i = 0; if (backsector->ffloors) @@ -2870,19 +2706,18 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (rover->norender == leveltime) continue; -#ifdef ESLOPE // Let the renderer know this sector is sloped. if (*rover->b_slope || *rover->t_slope) backsector->hasslope = true; - roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz; - roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz; - planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight); + roverleft = P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) - viewz; + roverright = P_GetFFloorBottomZAt(rover, segright.x, segright.y) - viewz; + planevistest = P_GetFFloorBottomZAt(rover, viewx, viewy); if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) + ((viewz < planevistest && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) || + (viewz > planevistest && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { //ffloor[i].slope = *rover->b_slope; ffloor[i].b_pos = roverleft; @@ -2898,14 +2733,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (i >= MAXFFLOORS) break; - roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz; - roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz; - planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight); + roverleft = P_GetFFloorTopZAt(rover, segleft .x, segleft .y) - viewz; + roverright = P_GetFFloorTopZAt(rover, segright.x, segright.y) - viewz; + planevistest = P_GetFFloorTopZAt(rover, viewx, viewy); if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) + ((viewz > planevistest && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) || + (viewz < planevistest && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { //ffloor[i].slope = *rover->t_slope; ffloor[i].b_pos = roverleft; @@ -2917,34 +2752,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); i++; } -#else - if (*rover->bottomheight <= backsector->ceilingheight && - *rover->bottomheight >= backsector->floorheight && - ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) || - (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES)))) - { - ffloor[i].b_pos = *rover->bottomheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } - - if (i >= MAXFFLOORS) - break; - - if (*rover->topheight >= backsector->floorheight && - *rover->topheight <= backsector->ceilingheight && - ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) || - (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES)))) - { - ffloor[i].b_pos = *rover->topheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } -#endif } } else if (frontsector && frontsector->ffloors) @@ -2956,20 +2763,18 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (rover->norender == leveltime) continue; - -#ifdef ESLOPE // Let the renderer know this sector is sloped. if (*rover->b_slope || *rover->t_slope) frontsector->hasslope = true; - roverleft = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segleft.x, segleft.y) : *rover->bottomheight) - viewz; - roverright = (*rover->b_slope ? P_GetZAt(*rover->b_slope, segright.x, segright.y) : *rover->bottomheight) - viewz; - planevistest = (*rover->b_slope ? P_GetZAt(*rover->b_slope, viewx, viewy) : *rover->bottomheight); + roverleft = P_GetFFloorBottomZAt(rover, segleft .x, segleft .y) - viewz; + roverright = P_GetFFloorBottomZAt(rover, segright.x, segright.y) - viewz; + planevistest = P_GetFFloorBottomZAt(rover, viewx, viewy); if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz < planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz > planevistest && (rover->flags & FF_BOTHPLANES)))) + ((viewz < planevistest && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) || + (viewz > planevistest && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { //ffloor[i].slope = *rover->b_slope; ffloor[i].b_pos = roverleft; @@ -2985,14 +2790,14 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (i >= MAXFFLOORS) break; - roverleft = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segleft.x, segleft.y) : *rover->topheight) - viewz; - roverright = (*rover->t_slope ? P_GetZAt(*rover->t_slope, segright.x, segright.y) : *rover->topheight) - viewz; - planevistest = (*rover->t_slope ? P_GetZAt(*rover->t_slope, viewx, viewy) : *rover->topheight); + roverleft = P_GetFFloorTopZAt(rover, segleft .x, segleft .y) - viewz; + roverright = P_GetFFloorTopZAt(rover, segright.x, segright.y) - viewz; + planevistest = P_GetFFloorTopZAt(rover, viewx, viewy); if ((roverleft>>4 <= worldhigh || roverright>>4 <= worldhighslope) && (roverleft>>4 >= worldlow || roverright>>4 >= worldlowslope) && - ((viewz > planevistest && !(rover->flags & FF_INVERTPLANES)) || - (viewz < planevistest && (rover->flags & FF_BOTHPLANES)))) + ((viewz > planevistest && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES))) || + (viewz < planevistest && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES)))) { //ffloor[i].slope = *rover->t_slope; ffloor[i].b_pos = roverleft; @@ -3004,35 +2809,8 @@ void R_StoreWallRange(INT32 start, INT32 stop) ffloor[i].b_step = (ffloor[i].b_step-ffloor[i].b_frac)/(range); i++; } -#else - if (*rover->bottomheight <= frontsector->ceilingheight && - *rover->bottomheight >= frontsector->floorheight && - ((viewz < *rover->bottomheight && !(rover->flags & FF_INVERTPLANES)) || - (viewz > *rover->bottomheight && (rover->flags & FF_BOTHPLANES)))) - { - ffloor[i].b_pos = *rover->bottomheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } - if (i >= MAXFFLOORS) - break; - if (*rover->topheight >= frontsector->floorheight && - *rover->topheight <= frontsector->ceilingheight && - ((viewz > *rover->topheight && !(rover->flags & FF_INVERTPLANES)) || - (viewz < *rover->topheight && (rover->flags & FF_BOTHPLANES)))) - { - ffloor[i].b_pos = *rover->topheight; - ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; - ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); - ffloor[i].b_frac = (centeryfrac >> 4) - FixedMul(ffloor[i].b_pos, rw_scale); - i++; - } -#endif } } -#ifdef POLYOBJECTS_PLANES if (curline->polyseg && frontsector && (curline->polyseg->flags & POF_RENDERPLANES)) { while (i < numffloors && ffloor[i].polyobj != curline->polyseg) i++; @@ -3046,9 +2824,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (ffloor[i].plane->maxx < ds_p->x2) ffloor[i].plane->maxx = ds_p->x2; -#ifdef ESLOPE ffloor[i].slope = NULL; -#endif ffloor[i].b_pos = backsector->floorheight; ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); @@ -3065,9 +2841,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) if (ffloor[i].plane->maxx < ds_p->x2) ffloor[i].plane->maxx = ds_p->x2; -#ifdef ESLOPE ffloor[i].slope = NULL; -#endif ffloor[i].b_pos = backsector->ceilingheight; ffloor[i].b_pos = (ffloor[i].b_pos - viewz) >> 4; ffloor[i].b_step = FixedMul(-rw_scalestep, ffloor[i].b_pos); @@ -3075,7 +2849,6 @@ void R_StoreWallRange(INT32 start, INT32 stop) i++; } } -#endif numbackffloors = i; } @@ -3129,8 +2902,26 @@ void R_StoreWallRange(INT32 start, INT32 stop) for (i = 0; i < numffloors; i++) R_ExpandPlane(ffloor[i].plane, rw_x, rw_stopx - 1); } + // FIXME hack to fix planes disappearing when a seg goes behind the camera. This NEEDS to be changed to be done properly. -Red + if (curline->polyseg) + { + for (i = 0; i < numffloors; i++) + { + if (!ffloor[i].polyobj || ffloor[i].polyobj != curline->polyseg) + continue; + if (ffloor[i].plane->minx > rw_x) + ffloor[i].plane->minx = rw_x; + + if (ffloor[i].plane->maxx < rw_stopx - 1) + ffloor[i].plane->maxx = rw_stopx - 1; + } + } } + rw_silhouette = &(ds_p->silhouette); + rw_tsilheight = &(ds_p->tsilheight); + rw_bsilheight = &(ds_p->bsilheight); + #ifdef WALLSPLATS if (linedef->splats && cv_splats.value) { @@ -3145,7 +2936,7 @@ void R_StoreWallRange(INT32 start, INT32 stop) else #endif R_RenderSegLoop(); - colfunc = wallcolfunc; + colfunc = colfuncs[BASEDRAWFUNC]; if (portalline) // if curline is a portal, set portalrender for drawseg ds_p->portalpass = portalrender+1; diff --git a/src/r_segs.h b/src/r_segs.h index 92d0100e2..6a79047e0 100644 --- a/src/r_segs.h +++ b/src/r_segs.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,6 +18,7 @@ #pragma interface #endif +transnum_t R_GetLinedefTransTable(line_t *line); void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2); void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pffloor); void R_StoreWallRange(INT32 start, INT32 stop); diff --git a/src/r_skins.c b/src/r_skins.c new file mode 100644 index 000000000..951eeaad6 --- /dev/null +++ b/src/r_skins.c @@ -0,0 +1,944 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_skins.c +/// \brief Loading skins + +#include "doomdef.h" +#include "console.h" +#include "g_game.h" +#include "r_local.h" +#include "st_stuff.h" +#include "w_wad.h" +#include "z_zone.h" +#include "m_misc.h" +#include "info.h" // spr2names +#include "i_video.h" // rendermode +#include "i_system.h" +#include "r_things.h" +#include "r_skins.h" +#include "p_local.h" +#include "dehacked.h" // get_number (for thok) +#include "m_cond.h" +#ifdef HWRENDER +#include "hardware/hw_md2.h" +#endif + +INT32 numskins = 0; +skin_t skins[MAXSKINS]; + +// FIXTHIS: don't work because it must be inistilised before the config load +//#define SKINVALUES +#ifdef SKINVALUES +CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; +#endif + +CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; + +// SRB2Kart followers +follower_t followers[MAXSKINS]; + +// +// P_GetSkinSprite2 +// For non-super players, tries each sprite2's immediate predecessor until it finds one with a number of frames or ends up at standing. +// For super players, does the same as above - but tries the super equivalent for each sprite2 before the non-super version. +// + +UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player) +{ + UINT8 super = 0, i = 0; + + (void)player; + + if (!skin) + return 0; + + if ((playersprite_t)(spr2 & ~FF_SPR2SUPER) >= free_spr2) + return 0; + + while (!skin->sprites[spr2].numframes + && spr2 != SPR2_STIL + && ++i < 32) // recursion limiter + { + if (spr2 & FF_SPR2SUPER) + { + super = FF_SPR2SUPER; + spr2 &= ~FF_SPR2SUPER; + continue; + } + + switch(spr2) + { + // Normal special cases. + // (none in kart) + + // Use the handy list, that's what it's there for! + default: + spr2 = spr2defaults[spr2]; + break; + } + + spr2 |= super; + } + + if (i >= 32) // probably an infinite loop... + return 0; + + return spr2; +} + +static void Sk_SetDefaultValue(skin_t *skin) +{ + INT32 i; + // + // set default skin values + // + memset(skin, 0, sizeof (skin_t)); + snprintf(skin->name, + sizeof skin->name, "skin %u", (UINT32)(skin-skins)); + skin->name[sizeof skin->name - 1] = '\0'; + skin->wadnum = INT16_MAX; + + skin->flags = 0; + + strcpy(skin->realname, "Someone"); + skin->starttranscolor = 96; + skin->prefcolor = SKINCOLOR_GREEN; + skin->supercolor = SKINCOLOR_SUPERGOLD1; + skin->prefoppositecolor = 0; // use tables + + skin->kartspeed = 5; + skin->kartweight = 5; + + skin->followitem = 0; + + skin->highresscale = FRACUNIT; + + for (i = 0; i < sfx_skinsoundslot0; i++) + if (S_sfx[i].skinsound != -1) + skin->soundsid[S_sfx[i].skinsound] = i; +} + +// +// Initialize the basic skins +// +void R_InitSkins(void) +{ +#ifdef SKINVALUES + INT32 i; + + for (i = 0; i <= MAXSKINS; i++) + { + skin_cons_t[i].value = 0; + skin_cons_t[i].strvalue = NULL; + } +#endif + + // no default skin! + numskins = 0; +} + +UINT32 R_GetSkinAvailabilities(void) +{ + UINT8 i; + UINT32 response = 0; + + for (i = 0; i < MAXUNLOCKABLES; i++) + { + if (unlockables[i].type == SECRET_SKIN && unlockables[i].unlocked) + { + UINT8 s = min(unlockables[i].variable, MAXSKINS); + response |= (1 << s); + } + } + + return response; +} + +// returns true if available in circumstances, otherwise nope +// warning don't use with an invalid skinnum other than -1 which always returns true +boolean R_SkinUsable(INT32 playernum, INT32 skinnum) +{ + boolean needsunlocked = false; + UINT8 i; + + if (skinnum == -1) + { + // Simplifies things elsewhere, since there's already plenty of checks for less-than-0... + return true; + } + + if (modeattacking) + { + // If you have someone else's run, you should be able to take a look + return true; + } + + if (Playing() && (R_SkinAvailable(mapheaderinfo[gamemap-1]->forcecharacter) == skinnum)) + { + // Being forced to play as this character by the level + return true; + } + + if (netgame && (cv_forceskin.value == skinnum)) + { + // Being forced to play as this character by the server + return true; + } + + if (metalrecording) + { + // Recording a Metal Sonic race + const INT32 metalskin = R_SkinAvailable("metalsonic"); + return (skinnum == metalskin); + } + + // Determine if this character is supposed to be unlockable or not + for (i = 0; i < MAXUNLOCKABLES; i++) + { + if (unlockables[i].type == SECRET_SKIN && unlockables[i].variable == skinnum) + { + // i is now the unlockable index, we can use this later + needsunlocked = true; + break; + } + } + + if (needsunlocked == true) + { + // You can use this character IF you have it unlocked. + if ((netgame || multiplayer) && playernum != -1) + { + // Use the netgame synchronized unlocks. + return (boolean)(!(players[playernum].availabilities & (1 << skinnum))); + } + else + { + // Use the unlockables table directly + return (boolean)(unlockables[i].unlocked); + } + } + else + { + // Didn't trip anything, so we can use this character. + return true; + } +} + +// returns true if the skin name is found (loaded from pwad) +// warning return -1 if not found +INT32 R_SkinAvailable(const char *name) +{ + INT32 i; + + for (i = 0; i < numskins; i++) + { + // search in the skin list + if (stricmp(skins[i].name,name)==0) + return i; + } + return -1; +} + +// network code calls this when a 'skin change' is received +void SetPlayerSkin(INT32 playernum, const char *skinname) +{ + INT32 i = R_SkinAvailable(skinname); + player_t *player = &players[playernum]; + + if ((i != -1) && R_SkinUsable(playernum, i)) + { + SetPlayerSkinByNum(playernum, i); + return; + } + + if (P_IsLocalPlayer(player)) + CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); + else if(server || IsPlayerAdmin(consoleplayer)) + CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); + + SetPlayerSkinByNum(playernum, 0); +} + +// Same as SetPlayerSkin, but uses the skin #. +// network code calls this when a 'skin change' is received +void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) +{ + player_t *player = &players[playernum]; + skin_t *skin = &skins[skinnum]; + UINT16 newcolor = 0; + //UINT8 i; + + if (skinnum >= 0 && skinnum < numskins && R_SkinUsable(playernum, skinnum)) // Make sure it exists! + { + player->skin = skinnum; + + player->charflags = (UINT32)skin->flags; + + player->followitem = skin->followitem; + + player->kartspeed = skin->kartspeed; + player->kartweight = skin->kartweight; + +#if 0 + if (!(cv_debug || devparm) && !(netgame || multiplayer || demo.playback)) + { + for (i = 0; i <= r_splitscreen; i++) + { + if (playernum == g_localplayers[i]) + { + CV_StealthSetValue(&cv_playercolor[i], skin->prefcolor); + } + } + + player->skincolor = newcolor = skin->prefcolor; + if (player->bot && botingame) + { + botskin = (UINT8)(skinnum + 1); + botcolor = skin->prefcolor; + } + } +#endif + + if (player->followmobj) + { + P_RemoveMobj(player->followmobj); + P_SetTarget(&player->followmobj, NULL); + } + + if (player->mo) + { + player->mo->skin = skin; + + if (newcolor) + { + player->mo->color = newcolor; + } + + P_SetScale(player->mo, player->mo->scale); + P_SetPlayerMobjState(player->mo, player->mo->state-states); // Prevent visual errors when switching between skins with differing number of frames + } + + // for replays: We have changed our skin mid-game; let the game know so it can do the same in the replay! + demo_extradata[playernum] |= DXD_SKIN; + + return; + } + + if (P_IsLocalPlayer(player)) + CONS_Alert(CONS_WARNING, M_GetText("Requested skin %d not found\n"), skinnum); + else if(server || IsPlayerAdmin(consoleplayer)) + CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); + + SetPlayerSkinByNum(playernum, 0); // not found, put in the default skin +} + +// +// Add skins from a pwad, each skin preceded by 'S_SKIN' marker +// + +// Does the same is in w_wad, but check only for +// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2.. +// for wad editors that don't like multiple resources of the same name) +// +static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +{ + UINT16 i; + const char *S_SKIN = "S_SKIN"; + lumpinfo_t *lump_p; + + // scan forward, start at + if (startlump < wadfiles[wadid]->numlumps) + { + lump_p = wadfiles[wadid]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name,S_SKIN,6)==0) + return i; + } + return INT16_MAX; // not found +} + +// turn _ into spaces and . into katana dot +#define SYMBOLCONVERT(name) for (value = name; *value; value++)\ + {\ + if (*value == '_') *value = ' ';\ + } + +// +// Patch skins from a pwad, each skin preceded by 'P_SKIN' marker +// + +// Does the same is in w_wad, but check only for +// the first 6 characters (this is so we can have P_SKIN1, P_SKIN2.. +// for wad editors that don't like multiple resources of the same name) +// +static UINT16 W_CheckForPatchSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) +{ + UINT16 i; + const char *P_SKIN = "P_SKIN"; + lumpinfo_t *lump_p; + + // scan forward, start at + if (startlump < wadfiles[wadid]->numlumps) + { + lump_p = wadfiles[wadid]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) + if (memcmp(lump_p->name,P_SKIN,6)==0) + return i; + } + return INT16_MAX; // not found +} + +static void R_LoadSkinSprites(UINT16 wadnum, UINT16 *lump, UINT16 *lastlump, skin_t *skin) +{ + UINT16 newlastlump; + UINT8 sprite2; + + *lump += 1; // start after S_SKIN + *lastlump = W_CheckNumForNamePwad("S_END",wadnum,*lump); // stop at S_END + + // old wadding practices die hard -- stop at S_SKIN (or P_SKIN) or S_START if they come before S_END. + newlastlump = W_FindNextEmptyInPwad(wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + newlastlump = W_CheckForSkinMarkerInPwad(wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + newlastlump = W_CheckForPatchSkinMarkerInPwad(wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + newlastlump = W_CheckNumForNamePwad("S_START",wadnum,*lump); + if (newlastlump < *lastlump) *lastlump = newlastlump; + + /*// ...and let's handle super, too + newlastlump = W_CheckNumForNamePwad("S_SUPER",wadnum,*lump); + if (newlastlump < *lastlump) + { + newlastlump++; + // load all sprite sets we are aware of... for super! + for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[FF_SPR2SUPER|sprite2], wadnum, newlastlump, *lastlump); + + newlastlump--; + *lastlump = newlastlump; // okay, make the normal sprite set loading end there + }*/ + + // load all sprite sets we are aware of... for normal stuff. + for (sprite2 = 0; sprite2 < free_spr2; sprite2++) + R_AddSingleSpriteDef(spr2names[sprite2], &skin->sprites[sprite2], wadnum, *lump, *lastlump); + + if (skin->sprites[0].numframes == 0) + I_Error("R_LoadSkinSprites: no frames found for sprite SPR2_%s\n", spr2names[0]); +} + +// returns whether found appropriate property +static boolean R_ProcessPatchableFields(skin_t *skin, char *stoken, char *value) +{ + // custom translation table + if (!stricmp(stoken, "startcolor")) + skin->starttranscolor = atoi(value); + +#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); + // character type identification + FULLPROCESS(flags) + FULLPROCESS(followitem) +#undef FULLPROCESS + +#define GETSKINCOLOR(field) else if (!stricmp(stoken, #field)) \ +{ \ + UINT16 color = R_GetColorByName(value); \ + skin->field = (color ? color : SKINCOLOR_GREEN); \ +} + GETSKINCOLOR(prefcolor) + GETSKINCOLOR(prefoppositecolor) +#undef GETSKINCOLOR + else if (!stricmp(stoken, "supercolor")) + { + UINT16 color = R_GetSuperColorByName(value); + skin->supercolor = (color ? color : SKINCOLOR_SUPERGOLD1); + } + +#define GETFLOAT(field) else if (!stricmp(stoken, #field)) skin->field = FLOAT_TO_FIXED(atof(value)); + GETFLOAT(highresscale) +#undef GETFLOAT + +#define GETKARTSTAT(field) \ + else if (!stricmp(stoken, #field)) \ + { \ + skin->field = atoi(value); \ + if (skin->field < 1) skin->field = 1; \ + if (skin->field > 9) skin->field = 9; \ + } + GETKARTSTAT(kartspeed) + GETKARTSTAT(kartweight) +#undef GETKARTSTAT + + +#define GETFLAG(field) else if (!stricmp(stoken, #field)) { \ + strupr(value); \ + if (atoi(value) || value[0] == 'T' || value[0] == 'Y') \ + skin->flags |= (SF_##field); \ + else \ + skin->flags &= ~(SF_##field); \ +} + // parameters for individual character flags + // these are uppercase so they can be concatenated with SF_ + // 1, true, yes are all valid values + GETFLAG(HIRES) + GETFLAG(MACHINE) +#undef GETFLAG + + else // let's check if it's a sound, otherwise error out + { + boolean found = false; + sfxenum_t i; + size_t stokenadjust; + + // Remove the prefix. (We need to affect an adjusting variable so that we can print error messages if it's not actually a sound.) + if ((stoken[0] == 'D' || stoken[0] == 'd') && (stoken[1] == 'S' || stoken[1] == 's')) // DS* + stokenadjust = 2; + else // sfx_* + stokenadjust = 4; + + // Remove the prefix. (We can affect this directly since we're not going to use it again.) + if ((value[0] == 'D' || value[0] == 'd') && (value[1] == 'S' || value[1] == 's')) // DS* + value += 2; + else // sfx_* + value += 4; + + // copy name of sounds that are remapped + // for this skin + for (i = 0; i < sfx_skinsoundslot0; i++) + { + if (!S_sfx[i].name) + continue; + if (S_sfx[i].skinsound != -1 + && !stricmp(S_sfx[i].name, + stoken + stokenadjust)) + { + skin->soundsid[S_sfx[i].skinsound] = + S_AddSoundFx(value, S_sfx[i].singularity, S_sfx[i].pitch, true); + found = true; + } + } + return found; + } + return true; +} + +// +// Find skin sprites, sounds & optional status bar face, & add them +// +void R_AddSkins(UINT16 wadnum) +{ + UINT16 lump, lastlump = 0; + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + skin_t *skin; + boolean realname; + + // + // search for all skin markers in pwad + // + + while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + { + // advance by default + lastlump = lump + 1; + + if (numskins >= MAXSKINS) + { + CONS_Debug(DBG_RENDER, "ignored skin (%d skins maximum)\n", MAXSKINS); + continue; // so we know how many skins couldn't be added + } + buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + // for strtok + buf2 = malloc(size+1); + if (!buf2) + I_Error("R_AddSkins: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + // set defaults + skin = &skins[numskins]; + Sk_SetDefaultValue(skin); + skin->wadnum = wadnum; + realname = false; + // parse + stoken = strtok (buf2, "\r\n= "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); // skip end of line + goto next_token; // find the real next token + } + + value = strtok(NULL, "\r\n= "); + + if (!value) + I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + + // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. + // Others can't go in there because we don't want them to be patchable. + if (!stricmp(stoken, "name")) + { + INT32 skinnum = R_SkinAvailable(value); + strlwr(value); + if (skinnum == -1) + STRBUFCPY(skin->name, value); + // the skin name must uniquely identify a single skin + // if the name is already used I make the name 'namex' + // using the default skin name's number set above + else + { + const size_t stringspace = + strlen(value) + sizeof (numskins) + 1; + char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL); + snprintf(value2, stringspace, + "%s%d", value, numskins); + value2[stringspace - 1] = '\0'; + if (R_SkinAvailable(value2) == -1) + // I'm lazy so if NEW name is already used I leave the 'skin x' + // default skin name set in Sk_SetDefaultValue + STRBUFCPY(skin->name, value2); + Z_Free(value2); + } + + // copy to hudname and fullname as a default. + if (!realname) + { + STRBUFCPY(skin->realname, skin->name); + SYMBOLCONVERT(skin->realname); + } + } + else if (!stricmp(stoken, "realname")) + { // Display name (eg. "Knuckles") + realname = true; + STRBUFCPY(skin->realname, value); + SYMBOLCONVERT(skin->realname) + } + else if (!stricmp(stoken, "rivals")) + { + size_t len = strlen(value); + size_t i; + char rivalname[SKINNAMESIZE] = ""; + UINT8 pos = 0; + UINT8 numrivals = 0; + + // Can't use strtok, because this function's already using it. + // Using it causes it to upset the saved pointer, + // corrupting the reading for the rest of the file. + + // So instead we get to crawl through the value, character by character, + // and write it down as we go, until we hit a comma or the end of the string. + // Yaaay. + + for (i = 0; i <= len; i++) + { + if (numrivals >= SKINRIVALS) + { + break; + } + + if (value[i] == ',' || i == len) + { + STRBUFCPY(skin->rivals[numrivals], rivalname); + strlwr(skin->rivals[numrivals]); + numrivals++; + + memset(rivalname, 0, sizeof (rivalname)); + pos = 0; + + continue; + } + + rivalname[pos] = value[i]; + pos++; + } + } + else if (!R_ProcessPatchableFields(skin, stoken, value)) + CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); + +next_token: + stoken = strtok(NULL, "\r\n= "); + } + free(buf2); + + // Add sprites + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + //ST_LoadFaceGraphics(numskins); -- nah let's do this elsewhere + + R_FlushTranslationColormapCache(); + + CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); + +#ifdef SKINVALUES + skin_cons_t[numskins].value = numskins; + skin_cons_t[numskins].strvalue = skin->name; +#endif + + // Update the forceskin possiblevalues + Forceskin_cons_t[numskins+1].value = numskins; + Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name; + +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_AddPlayerModel(numskins); +#endif + + numskins++; + } + return; +} + +// +// Patch skin sprites +// +void R_PatchSkins(UINT16 wadnum) +{ + UINT16 lump, lastlump = 0; + char *buf; + char *buf2; + char *stoken; + char *value; + size_t size; + skin_t *skin; + boolean noskincomplain, realname; + + // + // search for all skin patch markers in pwad + // + + while ((lump = W_CheckForPatchSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) + { + INT32 skinnum = 0; + + // advance by default + lastlump = lump + 1; + + buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); + size = W_LumpLengthPwad(wadnum, lump); + + // for strtok + buf2 = malloc(size+1); + if (!buf2) + I_Error("R_PatchSkins: No more free memory\n"); + M_Memcpy(buf2,buf,size); + buf2[size] = '\0'; + + skin = NULL; + noskincomplain = realname = false; + + /* + Parse. Has more phases than the parser in R_AddSkins because it needs to have the patching name first (no default skin name is acceptible for patching, unlike skin creation) + */ + + stoken = strtok(buf2, "\r\n= "); + while (stoken) + { + if ((stoken[0] == '/' && stoken[1] == '/') + || (stoken[0] == '#'))// skip comments + { + stoken = strtok(NULL, "\r\n"); // skip end of line + goto next_token; // find the real next token + } + + value = strtok(NULL, "\r\n= "); + + if (!value) + I_Error("R_PatchSkins: syntax error in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + + if (!skin) // Get the name! + { + if (!stricmp(stoken, "name")) + { + strlwr(value); + skinnum = R_SkinAvailable(value); + if (skinnum != -1) + skin = &skins[skinnum]; + else + { + CONS_Debug(DBG_SETUP, "R_PatchSkins: unknown skin name in P_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); + noskincomplain = true; + } + } + } + else // Get the properties! + { + // Some of these can't go in R_ProcessPatchableFields because they have side effects for future lines. + if (!stricmp(stoken, "realname")) + { // Display name (eg. "Knuckles") + realname = true; + STRBUFCPY(skin->realname, value); + SYMBOLCONVERT(skin->realname) + } + else if (!stricmp(stoken, "rivals")) + { + size_t len = strlen(value); + size_t i; + char rivalname[SKINNAMESIZE] = ""; + UINT8 pos = 0; + UINT8 numrivals = 0; + + // Can't use strtok, because this function's already using it. + // Using it causes it to upset the saved pointer, + // corrupting the reading for the rest of the file. + + // So instead we get to crawl through the value, character by character, + // and write it down as we go, until we hit a comma or the end of the string. + // Yaaay. + + for (i = 0; i <= len; i++) + { + if (numrivals >= SKINRIVALS) + { + break; + } + + if (value[i] == ',' || i == len) + { + STRBUFCPY(skin->rivals[numrivals], rivalname); + strlwr(skin->rivals[numrivals]); + numrivals++; + + memset(rivalname, 0, sizeof (rivalname)); + pos = 0; + + continue; + } + + rivalname[pos] = value[i]; + pos++; + } + } + else if (!R_ProcessPatchableFields(skin, stoken, value)) + CONS_Debug(DBG_SETUP, "R_PatchSkins: Unknown keyword '%s' in P_SKIN lump #%d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); + } + + if (!skin) + break; + +next_token: + stoken = strtok(NULL, "\r\n= "); + } + free(buf2); + + if (!skin) // Didn't include a name parameter? What a waste. + { + if (!noskincomplain) + CONS_Debug(DBG_SETUP, "R_PatchSkins: no skin name given in P_SKIN lump #%d (WAD %s)\n", lump, wadfiles[wadnum]->filename); + continue; + } + + // Patch sprites + R_LoadSkinSprites(wadnum, &lump, &lastlump, skin); + //ST_LoadFaceGraphics(skinnum); -- nah let's do this elsewhere + + R_FlushTranslationColormapCache(); + + CONS_Printf(M_GetText("Patched skin '%s'\n"), skin->name); + } + return; +} + +#undef SYMBOLCONVERT + +// SRB2Kart: Followers! +// TODO: put this stuff in its own file? + +// same thing as R_SkinAvailable, but for followers +INT32 R_FollowerAvailable(const char *name) +{ + INT32 i; + + for (i = 0; i < numfollowers; i++) + { + if (stricmp(followers[i].skinname,name)==0) + return i; + } + return -1; +} + +// same thing as SetPlayerSkin, but for followers +boolean SetPlayerFollower(INT32 playernum, const char *skinname) +{ + INT32 i; + player_t *player = &players[playernum]; + + for (i = 0; i < numfollowers; i++) + { + // search in the skin list + if (stricmp(followers[i].skinname, skinname) == 0) + { + SetFollower(playernum, i); + return true; + } + } + + if (P_IsLocalPlayer(player)) + CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found.\n"), skinname); + else if(server || IsPlayerAdmin(consoleplayer)) + CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) follower '%s' not found\n"), playernum, player_names[playernum], skinname); + + SetFollower(playernum, -1); // reminder that -1 is nothing + return false; +} + +// SetPlayerSkinByNum, for followers +void SetFollower(INT32 playernum, INT32 skinnum) +{ + player_t *player = &players[playernum]; + mobj_t *bub; + mobj_t *tmp; + + player->followerready = true; // we are ready to perform follower related actions in the player thinker, now. + + if (skinnum >= -1 && skinnum <= numfollowers) // Make sure it exists! + { + /* + We don't spawn the follower here since it'll be easier to handle all of it in the Player thinker itself. + However, we will despawn it right here if there's any to make it easy for the player thinker to replace it or delete it. + */ + + if (player->follower && skinnum != player->followerskin) // this is also called when we change colour so don't respawn the follower unless we changed skins + { + // Remove follower's possible hnext list (bubble) + bub = player->follower->hnext; + + while (bub && !P_MobjWasRemoved(bub)) + { + tmp = bub->hnext; + P_RemoveMobj(bub); + bub = tmp; + } + + P_RemoveMobj(player->follower); + P_SetTarget(&player->follower, NULL); + } + + player->followerskin = skinnum; + + // for replays: We have changed our follower mid-game; let the game know so it can do the same in the replay! + demo_extradata[playernum] |= DXD_FOLLOWER; + + return; + } + + if (P_IsLocalPlayer(player)) + CONS_Alert(CONS_WARNING, M_GetText("Follower %d not found\n"), skinnum); + else if(server || IsPlayerAdmin(consoleplayer)) + CONS_Alert(CONS_WARNING, "Player %d (%s) follower %d not found\n", playernum, player_names[playernum], skinnum); + + SetFollower(playernum, -1); // Not found, then set -1 (nothing) as our follower. +} diff --git a/src/r_skins.h b/src/r_skins.h new file mode 100644 index 000000000..614bd904f --- /dev/null +++ b/src/r_skins.h @@ -0,0 +1,139 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_skins.h +/// \brief Skins stuff + +#ifndef __R_SKINS__ +#define __R_SKINS__ + +#include "info.h" +#include "sounds.h" +#include "d_player.h" // skinflags +#include "r_picformats.h" // spriteinfo_t +#include "r_defs.h" // spritedef_t + +/// Defaults +#define SKINNAMESIZE 16 +#define SKINRIVALS 3 +// should be all lowercase!! S_SKIN processing does a strlwr +#define DEFAULTSKIN "eggman" +#define DEFAULTSKIN2 "tails" // secondary player +#define DEFAULTSKIN3 "sonic" // third player +#define DEFAULTSKIN4 "knuckles" // fourth player + +/// The skin_t struct +typedef struct +{ + char name[SKINNAMESIZE+1]; // INT16 descriptive name of the skin + UINT16 wadnum; + skinflags_t flags; + + char realname[SKINNAMESIZE+1]; // Display name for level completion. + + // SRB2kart + UINT8 kartspeed; + UINT8 kartweight; + // + + INT32 followitem; + + // Definable color translation table + UINT8 starttranscolor; + UINT16 prefcolor; + UINT16 supercolor; + UINT16 prefoppositecolor; // if 0 use tables instead + + fixed_t highresscale; // scale of highres, default is 0.5 + + char rivals[SKINRIVALS][SKINNAMESIZE+1]; // Your top 3 rivals for GP mode. Uses names so that you can reference skins that aren't added + + // specific sounds per skin + sfxenum_t soundsid[NUMSKINSOUNDS]; // sound # in S_sfx table + + // contains super versions too + spritedef_t sprites[NUMPLAYERSPRITES*2]; + spriteinfo_t sprinfo[NUMPLAYERSPRITES*2]; +} skin_t; + +enum facepatches { + FACE_RANK = 0, + FACE_WANTED, + FACE_MINIMAP, + NUMFACES +}; + +/// Externs +extern INT32 numskins; +extern skin_t skins[MAXSKINS]; + +extern CV_PossibleValue_t Forceskin_cons_t[]; + +/// Function prototypes +void R_InitSkins(void); + +void SetPlayerSkin(INT32 playernum,const char *skinname); +void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 +boolean R_SkinUsable(INT32 playernum, INT32 skinnum); +UINT32 R_GetSkinAvailabilities(void); +INT32 R_SkinAvailable(const char *name); +void R_PatchSkins(UINT16 wadnum); +void R_AddSkins(UINT16 wadnum); + +UINT8 P_GetSkinSprite2(skin_t *skin, UINT8 spr2, player_t *player); + +// SRB2Kart Followers + +// +// We'll define these here because they're really just a mobj that'll follow some rules behind a player +// +typedef struct follower_s +{ + char skinname[SKINNAMESIZE+1]; // Skin Name. This is what to refer to when asking the commands anything. + char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this. + + UINT16 defaultcolor; // default color for menus. + + fixed_t scale; // Scale relative to the player's. + fixed_t bubblescale; // Bubble scale relative to the player scale. If not set, no bubble will spawn (default) + + // some position shenanigans: + INT32 atangle; // angle the object will be at around the player. The object itself will always face the same direction as the player. + INT32 dist; // distance relative to the player. (In a circle) + INT32 height; // height of the follower, this is mostly important for Z flipping. + INT32 zoffs; // Z offset relative to the player's height. Cannot be negative. + + // movement options + + UINT32 horzlag; // Lag for X/Y displacement. Default is 2. Must be > 0 because we divide by this number. + UINT32 vertlag; // not Vert from Neptunia lagging, this is for Z displacement lag Default is 6. Must be > 0 because we divide by this number. + INT32 bobamp; // Bob amplitude. Default is 4. + INT32 bobspeed; // Arbitrary modifier for bobbing speed, default is TICRATE*2 (70). + + // from there on out, everything is STATES to allow customization + // these are only set once when the action is performed and are then free to animate however they want. + + INT32 idlestate; // state when the player is at a standstill + INT32 followstate; // state when the player is moving + INT32 hurtstate; // state when the player is being hurt + INT32 winstate; // state when the player has won + INT32 losestate; // state when the player has lost + INT32 hitconfirmstate; // state for hit confirm + UINT32 hitconfirmtime; // time to keep the above playing for +} follower_t; + +extern INT32 numfollowers; +extern follower_t followers[MAXSKINS]; // again, use the same rules as skins, no reason not to. + +INT32 R_FollowerAvailable(const char *name); +boolean SetPlayerFollower(INT32 playernum,const char *skinname); +void SetFollower(INT32 playernum,INT32 skinnum); + +#endif //__R_SKINS__ diff --git a/src/r_sky.c b/src/r_sky.c index 3904eba3a..5510c36da 100644 --- a/src/r_sky.c +++ b/src/r_sky.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -43,7 +43,7 @@ INT32 skytexturemid; /** \brief the scale of the sky */ -fixed_t skyscale; +fixed_t skyscale[MAXSPLITSCREENPLAYERS]; /** \brief used for keeping track of the current sky */ @@ -64,10 +64,6 @@ void R_SetupSkyDraw(void) // the horizon line in a 256x128 sky texture skytexturemid = (textures[skytexture]->height/2)< 1) - scr *= 2; - skyscale = FixedDiv(scr, vid.fdupx+difference); + int i; + for (i = 0; i <= r_splitscreen; ++i) + { + skyscale[i] = FixedDiv(fovtan[i], vid.fdupx+difference); + } } diff --git a/src/r_sky.h b/src/r_sky.h index a41b24463..123d66274 100644 --- a/src/r_sky.h +++ b/src/r_sky.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,7 +27,7 @@ #define ANGLETOSKYSHIFT 22 extern INT32 skytexture, skytexturemid; -extern fixed_t skyscale; +extern fixed_t skyscale[MAXSPLITSCREENPLAYERS]; extern INT32 skyflatnum; extern char levelskytexture[9]; diff --git a/src/r_splats.c b/src/r_splats.c index 9ab671274..dfec185a1 100644 --- a/src/r_splats.c +++ b/src/r_splats.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -147,7 +147,7 @@ void R_AddWallSplat(line_t *wallline, INT16 sectorside, const char *patchname, f splat->flags = flags; // bad.. but will be needed for drawing anyway.. - patch = W_CachePatchNum(splat->patch, PU_CACHE); + patch = W_CachePatchNum(splat->patch, PU_PATCH); // offset needed by draw code for texture mapping linelength = P_SegLength((seg_t *)wallline); @@ -512,7 +512,7 @@ static void R_RenderFloorSplat(floorsplat_t *pSplat, vertex_t *verts, UINT8 *pTe ds_x1 = x1; ds_x2 = x2; ds_transmap = transtables + ((tr_trans50-1)< // alloca(sizeof) +#endif + +#ifdef HWRENDER +#include "hardware/hw_main.h" // HWR_LoadTextures +#endif + +#include + +// +// TEXTURE_T CACHING +// When a texture is first needed, it counts the number of composite columns +// required in the texture and allocates space for a column directory and +// any new columns. +// The directory will simply point inside other patches if there is only one +// patch in a given column, but any columns with multiple patches will have +// new column_ts generated. +// + +INT32 numtextures = 0; // total number of textures found, +// size of following tables + +texture_t **textures = NULL; +UINT32 **texturecolumnofs; // column offset lookup table for each texture +UINT8 **texturecache; // graphics data for each generated full-size texture + +INT32 *texturewidth; +fixed_t *textureheight; // needed for texture pegging + +INT32 *texturetranslation; + +// Painfully simple texture id cacheing to make maps load faster. :3 +static struct { + char name[9]; + INT32 id; +} *tidcache = NULL; +static INT32 tidcachelen = 0; + +// +// MAPTEXTURE_T CACHING +// When a texture is first needed, it counts the number of composite columns +// required in the texture and allocates space for a column directory and +// any new columns. +// The directory will simply point inside other patches if there is only one +// patch in a given column, but any columns with multiple patches will have +// new column_ts generated. +// + +// +// R_DrawColumnInCache +// Clip and draw a column from a patch into a cached post. +// +static inline void R_DrawColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +{ + INT32 count, position; + UINT8 *source; + INT32 topdelta, prevdelta = -1; + INT32 originy = originPatch->originy; + + (void)patchheight; // This parameter is unused + + while (patch->topdelta != 0xff) + { + topdelta = patch->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (UINT8 *)patch + 3; + count = patch->length; + position = originy + topdelta; + + if (position < 0) + { + count += position; + source -= position; // start further down the column + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + if (count > 0) + M_Memcpy(cache + position, source, count); + + patch = (column_t *)((UINT8 *)patch + patch->length + 4); + } +} + +// +// R_DrawFlippedColumnInCache +// Similar to R_DrawColumnInCache; it draws the column inverted, however. +// +static inline void R_DrawFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +{ + INT32 count, position; + UINT8 *source, *dest; + INT32 topdelta, prevdelta = -1; + INT32 originy = originPatch->originy; + + while (patch->topdelta != 0xff) + { + topdelta = patch->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + topdelta = patchheight-patch->length-topdelta; + source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1) + count = patch->length; + position = originy + topdelta; + + if (position < 0) + { + count += position; + source += position; // start further UP the column + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + dest = cache + position; + if (count > 0) + { + for (; dest < cache + position + count; --source) + *dest++ = *source; + } + + patch = (column_t *)((UINT8 *)patch + patch->length + 4); + } +} + +// +// R_DrawBlendColumnInCache +// Draws a translucent column into the cache, applying a half-cooked equation to get a proper translucency value (Needs code in R_GenerateTexture()). +// +static inline void R_DrawBlendColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +{ + INT32 count, position; + UINT8 *source, *dest; + INT32 topdelta, prevdelta = -1; + INT32 originy = originPatch->originy; + + (void)patchheight; // This parameter is unused + + while (patch->topdelta != 0xff) + { + topdelta = patch->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + source = (UINT8 *)patch + 3; + count = patch->length; + position = originy + topdelta; + + if (position < 0) + { + count += position; + source -= position; // start further down the column + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + dest = cache + position; + if (count > 0) + { + for (; dest < cache + position + count; source++, dest++) + if (*source != 0xFF) + *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); + } + + patch = (column_t *)((UINT8 *)patch + patch->length + 4); + } +} + +// +// R_DrawBlendFlippedColumnInCache +// Similar to the one above except that the column is inverted. +// +static inline void R_DrawBlendFlippedColumnInCache(column_t *patch, UINT8 *cache, texpatch_t *originPatch, INT32 cacheheight, INT32 patchheight) +{ + INT32 count, position; + UINT8 *source, *dest; + INT32 topdelta, prevdelta = -1; + INT32 originy = originPatch->originy; + + while (patch->topdelta != 0xff) + { + topdelta = patch->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + topdelta = patchheight-patch->length-topdelta; + source = (UINT8 *)patch + 2 + patch->length; // patch + 3 + (patch->length-1) + count = patch->length; + position = originy + topdelta; + + if (position < 0) + { + count += position; + source += position; // start further UP the column + position = 0; + } + + if (position + count > cacheheight) + count = cacheheight - position; + + dest = cache + position; + if (count > 0) + { + for (; dest < cache + position + count; --source, dest++) + if (*source != 0xFF) + *dest = ASTBlendPaletteIndexes(*dest, *source, originPatch->style, originPatch->alpha); + } + + patch = (column_t *)((UINT8 *)patch + patch->length + 4); + } +} + +// +// R_GenerateTexture +// +// Allocate space for full size texture, either single patch or 'composite' +// Build the full textures from patches. +// The texture caching system is a little more hungry of memory, but has +// been simplified for the sake of highcolor (lol), dynamic ligthing, & speed. +// +// This is not optimised, but it's supposed to be executed only once +// per level, when enough memory is available. +// +UINT8 *R_GenerateTexture(size_t texnum) +{ + UINT8 *block; + UINT8 *blocktex; + texture_t *texture; + texpatch_t *patch; + patch_t *realpatch; + UINT8 *pdata; + int x, x1, x2, i, width, height; + size_t blocksize; + column_t *patchcol; + UINT8 *colofs; + + UINT16 wadnum; + lumpnum_t lumpnum; + size_t lumplength; + + I_Assert(texnum <= (size_t)numtextures); + texture = textures[texnum]; + I_Assert(texture != NULL); + + // allocate texture column offset lookup + + // single-patch textures can have holes in them and may be used on + // 2sided lines so they need to be kept in 'packed' format + // BUT this is wrong for skies and walls with over 255 pixels, + // so check if there's holes and if not strip the posts. + if (texture->patchcount == 1) + { + boolean holey = false; + patch = texture->patches; + + wadnum = patch->wad; + lumpnum = patch->lump; + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + realpatch = (patch_t *)pdata; + +#ifndef NO_PNG_LUMPS + if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) + goto multipatch; +#endif +#ifdef WALLFLATS + if (texture->type == TEXTURETYPE_FLAT) + goto multipatch; +#endif + + // Check the patch for holes. + if (texture->width > SHORT(realpatch->width) || texture->height > SHORT(realpatch->height)) + holey = true; + colofs = (UINT8 *)realpatch->columnofs; + for (x = 0; x < texture->width && !holey; x++) + { + column_t *col = (column_t *)((UINT8 *)realpatch + LONG(*(UINT32 *)&colofs[x<<2])); + INT32 topdelta, prevdelta = -1, y = 0; + while (col->topdelta != 0xff) + { + topdelta = col->topdelta; + if (topdelta <= prevdelta) + topdelta += prevdelta; + prevdelta = topdelta; + if (topdelta > y) + break; + y = topdelta + col->length + 1; + col = (column_t *)((UINT8 *)col + col->length + 4); + } + if (y < texture->height) + holey = true; // this texture is HOLEy! D: + } + + // If the patch uses transparency, we have to save it this way. + if (holey) + { + texture->holes = true; + texture->flip = patch->flip; + blocksize = lumplength; + block = Z_Calloc(blocksize, PU_STATIC, // will change tag at end of this function + &texturecache[texnum]); + M_Memcpy(block, realpatch, blocksize); + texturememory += blocksize; + + // use the patch's column lookup + colofs = (block + 8); + texturecolumnofs[texnum] = (UINT32 *)colofs; + blocktex = block; + if (patch->flip & 1) // flip the patch horizontally + { + UINT8 *realcolofs = (UINT8 *)realpatch->columnofs; + for (x = 0; x < texture->width; x++) + *(UINT32 *)&colofs[x<<2] = realcolofs[( texture->width-1-x )<<2]; // swap with the offset of the other side of the texture + } + // we can't as easily flip the patch vertically sadly though, + // we have wait until the texture itself is drawn to do that + for (x = 0; x < texture->width; x++) + *(UINT32 *)&colofs[x<<2] = LONG(LONG(*(UINT32 *)&colofs[x<<2]) + 3); + goto done; + } + + // Otherwise, do multipatch format. + } + + // multi-patch textures (or 'composite') + multipatch: + texture->holes = false; + texture->flip = 0; + blocksize = (texture->width * 4) + (texture->width * texture->height); + texturememory += blocksize; + block = Z_Malloc(blocksize+1, PU_STATIC, &texturecache[texnum]); + + memset(block, TRANSPARENTPIXEL, blocksize+1); // Transparency hack + + // columns lookup table + colofs = block; + texturecolumnofs[texnum] = (UINT32 *)colofs; + + // texture data after the lookup table + blocktex = block + (texture->width*4); + + // Composite the columns together. + for (i = 0, patch = texture->patches; i < texture->patchcount; i++, patch++) + { + boolean dealloc = true; + static void (*ColumnDrawerPointer)(column_t *, UINT8 *, texpatch_t *, INT32, INT32); // Column drawing function pointer. + if (patch->style != AST_COPY) + ColumnDrawerPointer = (patch->flip & 2) ? R_DrawBlendFlippedColumnInCache : R_DrawBlendColumnInCache; + else + ColumnDrawerPointer = (patch->flip & 2) ? R_DrawFlippedColumnInCache : R_DrawColumnInCache; + + wadnum = patch->wad; + lumpnum = patch->lump; + pdata = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + realpatch = (patch_t *)pdata; + dealloc = true; + +#ifndef NO_PNG_LUMPS + if (Picture_IsLumpPNG((UINT8 *)realpatch, lumplength)) + realpatch = (patch_t *)Picture_PNGConvert((UINT8 *)realpatch, PICFMT_PATCH, NULL, NULL, NULL, NULL, lumplength, NULL, 0); + else +#endif +#ifdef WALLFLATS + if (texture->type == TEXTURETYPE_FLAT) + realpatch = (patch_t *)Picture_Convert(PICFMT_FLAT, pdata, PICFMT_PATCH, 0, NULL, texture->width, texture->height, 0, 0, 0); + else +#endif + { + (void)lumplength; + dealloc = false; + } + + x1 = patch->originx; + width = SHORT(realpatch->width); + height = SHORT(realpatch->height); + x2 = x1 + width; + + if (x1 > texture->width || x2 < 0) + { + if (dealloc) + Z_Free(realpatch); + continue; // patch not located within texture's x bounds, ignore + } + + if (patch->originy > texture->height || (patch->originy + height) < 0) + { + if (dealloc) + Z_Free(realpatch); + continue; // patch not located within texture's y bounds, ignore + } + + // patch is actually inside the texture! + // now check if texture is partly off-screen and adjust accordingly + + // left edge + if (x1 < 0) + x = 0; + else + x = x1; + + // right edge + if (x2 > texture->width) + x2 = texture->width; + + for (; x < x2; x++) + { + if (patch->flip & 1) + patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[(x1+width-1)-x])); + else + patchcol = (column_t *)((UINT8 *)realpatch + LONG(realpatch->columnofs[x-x1])); + + // generate column ofset lookup + *(UINT32 *)&colofs[x<<2] = LONG((x * texture->height) + (texture->width*4)); + ColumnDrawerPointer(patchcol, block + LONG(*(UINT32 *)&colofs[x<<2]), patch, texture->height, height); + } + + if (dealloc) + Z_Free(realpatch); + } + +done: + // Now that the texture has been built in column cache, it is purgable from zone memory. + Z_ChangeTag(block, PU_CACHE); + return blocktex; +} + +// +// R_GenerateTextureAsFlat +// +// Generates a flat picture for a texture. +// +UINT8 *R_GenerateTextureAsFlat(size_t texnum) +{ + texture_t *texture = textures[texnum]; + UINT8 *converted = NULL; + size_t size = (texture->width * texture->height); + + // The flat picture for this texture was not generated yet. + if (!texture->flat) + { + // Well, let's do it now, then. + texture->flat = Z_Malloc(size, PU_STATIC, NULL); + + // Picture_TextureToFlat handles everything for us. + converted = (UINT8 *)Picture_TextureToFlat(texnum); + M_Memcpy(texture->flat, converted, size); + Z_Free(converted); + } + + return texture->flat; +} + +// +// R_GetTextureNum +// +// Returns the actual texture id that we should use. +// This can either be texnum, the current frame for texnum's anim (if animated), +// or 0 if not valid. +// +INT32 R_GetTextureNum(INT32 texnum) +{ + if (texnum < 0 || texnum >= numtextures) + return 0; + return texturetranslation[texnum]; +} + +// +// R_CheckTextureCache +// +// Use this if you need to make sure the texture is cached before R_GetColumn calls +// e.g.: midtextures and FOF walls +// +void R_CheckTextureCache(INT32 tex) +{ + if (!texturecache[tex]) + R_GenerateTexture(tex); +} + +// +// R_GetColumn +// +UINT8 *R_GetColumn(fixed_t tex, INT32 col) +{ + UINT8 *data; + INT32 width = texturewidth[tex]; + + if (width & (width - 1)) + col = (UINT32)col % width; + else + col &= (width - 1); + + data = texturecache[tex]; + if (!data) + data = R_GenerateTexture(tex); + + return data + LONG(texturecolumnofs[tex][col]); +} + +void *R_GetFlat(lumpnum_t flatlumpnum) +{ + return W_CacheLumpNum(flatlumpnum, PU_CACHE); +} + +// +// R_GetLevelFlat +// +// If needed, convert a texture or patch to a flat. +// +void *R_GetLevelFlat(levelflat_t *levelflat) +{ + boolean isleveltexture = (levelflat->type == LEVELFLAT_TEXTURE); + texture_t *texture = (isleveltexture ? textures[levelflat->u.texture.num] : NULL); + boolean texturechanged = (isleveltexture ? (levelflat->u.texture.num != levelflat->u.texture.lastnum) : false); + UINT8 *flatdata = NULL; + + // Check if the texture changed. + if (isleveltexture && (!texturechanged)) + { + if (texture->flat) + { + flatdata = texture->flat; + ds_flatwidth = texture->width; + ds_flatheight = texture->height; + texturechanged = false; + } + else + texturechanged = true; + } + + // If the texture changed, or the flat wasn't generated, convert. + if (levelflat->picture == NULL || texturechanged) + { + // Level texture + if (isleveltexture) + { + levelflat->picture = R_GenerateTextureAsFlat(levelflat->u.texture.num); + ds_flatwidth = levelflat->width = texture->width; + ds_flatheight = levelflat->height = texture->height; + } + else + { +#ifndef NO_PNG_LUMPS + if (levelflat->type == LEVELFLAT_PNG) + { + INT32 pngwidth, pngheight; + + levelflat->picture = Picture_PNGConvert(W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE), PICFMT_FLAT, &pngwidth, &pngheight, NULL, NULL, W_LumpLength(levelflat->u.flat.lumpnum), NULL, 0); + levelflat->width = (UINT16)pngwidth; + levelflat->height = (UINT16)pngheight; + + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; + } + else +#endif + if (levelflat->type == LEVELFLAT_PATCH) + { + UINT8 *converted; + size_t size; + patch_t *patch = W_CacheLumpNum(levelflat->u.flat.lumpnum, PU_CACHE); + + levelflat->width = ds_flatwidth = SHORT(patch->width); + levelflat->height = ds_flatheight = SHORT(patch->height); + + levelflat->picture = Z_Malloc(levelflat->width * levelflat->height, PU_LEVEL, NULL); + converted = Picture_FlatConvert(PICFMT_PATCH, patch, PICFMT_FLAT, 0, &size, levelflat->width, levelflat->height, patch->topoffset, patch->leftoffset, 0); + M_Memcpy(levelflat->picture, converted, size); + Z_Free(converted); + } + } + } + else + { + ds_flatwidth = levelflat->width; + ds_flatheight = levelflat->height; + } + + levelflat->u.texture.lastnum = levelflat->u.texture.num; + + if (flatdata == NULL) + flatdata = levelflat->picture; + return flatdata; +} + +// +// R_CheckPowersOfTwo +// +// Self-explanatory? +// +boolean R_CheckPowersOfTwo(void) +{ + boolean wpow2 = (!(ds_flatwidth & (ds_flatwidth - 1))); + boolean hpow2 = (!(ds_flatheight & (ds_flatheight - 1))); + + // Initially, the flat isn't powers-of-two-sized. + ds_powersoftwo = false; + + // But if the width and height are powers of two, + // and are EQUAL, then it's okay :] + if ((ds_flatwidth == ds_flatheight) && (wpow2 && hpow2)) + ds_powersoftwo = true; + + // Just return ds_powersoftwo. + return ds_powersoftwo; +} + +// +// R_CheckFlatLength +// +// Determine the flat's dimensions from its lump length. +// +void R_CheckFlatLength(size_t size) +{ + switch (size) + { + case 4194304: // 2048x2048 lump + nflatmask = 0x3FF800; + nflatxshift = 21; + nflatyshift = 10; + nflatshiftup = 5; + ds_flatwidth = ds_flatheight = 2048; + break; + case 1048576: // 1024x1024 lump + nflatmask = 0xFFC00; + nflatxshift = 22; + nflatyshift = 12; + nflatshiftup = 6; + ds_flatwidth = ds_flatheight = 1024; + break; + case 262144:// 512x512 lump + nflatmask = 0x3FE00; + nflatxshift = 23; + nflatyshift = 14; + nflatshiftup = 7; + ds_flatwidth = ds_flatheight = 512; + break; + case 65536: // 256x256 lump + nflatmask = 0xFF00; + nflatxshift = 24; + nflatyshift = 16; + nflatshiftup = 8; + ds_flatwidth = ds_flatheight = 256; + break; + case 16384: // 128x128 lump + nflatmask = 0x3F80; + nflatxshift = 25; + nflatyshift = 18; + nflatshiftup = 9; + ds_flatwidth = ds_flatheight = 128; + break; + case 1024: // 32x32 lump + nflatmask = 0x3E0; + nflatxshift = 27; + nflatyshift = 22; + nflatshiftup = 11; + ds_flatwidth = ds_flatheight = 32; + break; + default: // 64x64 lump + nflatmask = 0xFC0; + nflatxshift = 26; + nflatyshift = 20; + nflatshiftup = 10; + ds_flatwidth = ds_flatheight = 64; + break; + } +} + +// +// Empty the texture cache (used for load wad at runtime) +// +void R_FlushTextureCache(void) +{ + INT32 i; + + if (numtextures) + for (i = 0; i < numtextures; i++) + Z_Free(texturecache[i]); +} + +// Need these prototypes for later; defining them here instead of r_textures.h so they're "private" +int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum); +void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *index); + +#ifdef WALLFLATS +static INT32 +Rloadflats (INT32 i, INT32 w) +{ + UINT16 j; + UINT16 texstart, texend; + texture_t *texture; + texpatch_t *patch; + + // Yes + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForMarkerStartPwad("F_START", (UINT16)w, 0); + texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); + } + + if (!( texstart == INT16_MAX || texend == INT16_MAX )) + { + // Work through each lump between the markers in the WAD. + for (j = 0; j < (texend - texstart); j++) + { + UINT8 *flatlump; + UINT16 wadnum = (UINT16)w; + lumpnum_t lumpnum = texstart + j; + size_t lumplength; + size_t flatsize = 0; + + if (wadfiles[w]->type == RET_PK3) + { + if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder + continue; // If it is then SKIP IT + } + + flatlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); + lumplength = W_LumpLengthPwad(wadnum, lumpnum); + + switch (lumplength) + { + case 4194304: // 2048x2048 lump + flatsize = 2048; + break; + case 1048576: // 1024x1024 lump + flatsize = 1024; + break; + case 262144:// 512x512 lump + flatsize = 512; + break; + case 65536: // 256x256 lump + flatsize = 256; + break; + case 16384: // 128x128 lump + flatsize = 128; + break; + case 1024: // 32x32 lump + flatsize = 32; + break; + default: // 64x64 lump + flatsize = 64; + break; + } + + //CONS_Printf("\n\"%s\" is a flat, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),flatsize,flatsize); + texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); + + // Set texture properties. + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + +#ifndef NO_PNG_LUMPS + if (Picture_IsLumpPNG((UINT8 *)flatlump, lumplength)) + { + INT32 width, height; + Picture_PNGDimensions((UINT8 *)flatlump, &width, &height, NULL, NULL, lumplength); + texture->width = (INT16)width; + texture->height = (INT16)height; + } + else +#endif + texture->width = texture->height = flatsize; + + texture->type = TEXTURETYPE_FLAT; + texture->patchcount = 1; + texture->holes = false; + texture->flip = 0; + + // Allocate information for the texture's patches. + patch = &texture->patches[0]; + + patch->originx = patch->originy = 0; + patch->wad = (UINT16)w; + patch->lump = texstart + j; + patch->flip = 0; + + Z_Unlock(flatlump); + + texturewidth[i] = texture->width; + textureheight[i] = texture->height << FRACBITS; + i++; + } + } + + return i; +} +#endif/*WALLFLATS*/ + +#define TX_START "TX_START" +#define TX_END "TX_END" + +static INT32 +Rloadtextures (INT32 i, INT32 w) +{ + UINT16 j; + UINT16 texstart, texend, texturesLumpPos; + texture_t *texture; + patch_t *patchlump; + texpatch_t *patch; + + // Get the lump numbers for the markers in the WAD, if they exist. + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + while (texturesLumpPos != INT16_MAX) + { + R_ParseTEXTURESLump(w, texturesLumpPos, &i); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); + } + } + else + { + texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0); + texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + if (texturesLumpPos != INT16_MAX) + R_ParseTEXTURESLump(w, texturesLumpPos, &i); + } + + if (!( texstart == INT16_MAX || texend == INT16_MAX )) + { + // Work through each lump between the markers in the WAD. + for (j = 0; j < (texend - texstart); j++) + { + UINT16 wadnum = (UINT16)w; + lumpnum_t lumpnum = texstart + j; +#ifndef NO_PNG_LUMPS + size_t lumplength; +#endif + + if (wadfiles[w]->type == RET_PK3) + { + if (W_IsLumpFolder(wadnum, lumpnum)) // Check if lump is a folder + continue; // If it is then SKIP IT + } + + patchlump = W_CacheLumpNumPwad(wadnum, lumpnum, PU_CACHE); +#ifndef NO_PNG_LUMPS + lumplength = W_LumpLengthPwad(wadnum, lumpnum); +#endif + + //CONS_Printf("\n\"%s\" is a single patch, dimensions %d x %d",W_CheckNameForNumPwad((UINT16)w,texstart+j),patchlump->width, patchlump->height); + texture = textures[i] = Z_Calloc(sizeof(texture_t) + sizeof(texpatch_t), PU_STATIC, NULL); + + // Set texture properties. + M_Memcpy(texture->name, W_CheckNameForNumPwad(wadnum, lumpnum), sizeof(texture->name)); + +#ifndef NO_PNG_LUMPS + if (Picture_IsLumpPNG((UINT8 *)patchlump, lumplength)) + { + INT32 width, height; + Picture_PNGDimensions((UINT8 *)patchlump, &width, &height, NULL, NULL, lumplength); + texture->width = (INT16)width; + texture->height = (INT16)height; + } + else +#endif + { + texture->width = SHORT(patchlump->width); + texture->height = SHORT(patchlump->height); + } + + texture->type = TEXTURETYPE_SINGLEPATCH; + texture->patchcount = 1; + texture->holes = false; + texture->flip = 0; + + // Allocate information for the texture's patches. + patch = &texture->patches[0]; + + patch->originx = patch->originy = 0; + patch->wad = (UINT16)w; + patch->lump = texstart + j; + patch->flip = 0; + + Z_Unlock(patchlump); + + texturewidth[i] = texture->width; + textureheight[i] = texture->height << FRACBITS; + i++; + } + } + + return i; +} + +// +// R_LoadTextures +// Initializes the texture list with the textures from the world map. +// +void R_LoadTextures(void) +{ + INT32 i, w; + UINT16 j; + UINT16 texstart, texend, texturesLumpPos; + + // Free previous memory before numtextures change. + if (numtextures) + { + for (i = 0; i < numtextures; i++) + { + Z_Free(textures[i]); + Z_Free(texturecache[i]); + } + Z_Free(texturetranslation); + Z_Free(textures); + } + + // Load patches and textures. + + // Get the number of textures to check. + // NOTE: Make SURE the system does not process + // the markers. + // This system will allocate memory for all duplicate/patched textures even if it never uses them, + // but the alternative is to spend a ton of time checking and re-checking all previous entries just to skip any potentially patched textures. + for (w = 0, numtextures = 0; w < numwadfiles; w++) + { +#ifdef WALLFLATS + // Count flats + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("flats/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("flats/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForMarkerStartPwad("F_START", (UINT16)w, 0); + texend = W_CheckNumForNamePwad("F_END", (UINT16)w, texstart); + } + + if (!( texstart == INT16_MAX || texend == INT16_MAX )) + { + // PK3s have subfolders, so we can't just make a simple sum + if (wadfiles[w]->type == RET_PK3) + { + for (j = texstart; j < texend; j++) + { + if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it + numtextures++; + } + } + else // Add all the textures between F_START and F_END + { + numtextures += (UINT32)(texend - texstart); + } + } +#endif/*WALLFLATS*/ + + // Count the textures from TEXTURES lumps + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, 0); + while (texturesLumpPos != INT16_MAX) + { + numtextures += R_CountTexturesInTEXTURESLump((UINT16)w, (UINT16)texturesLumpPos); + texturesLumpPos = W_CheckNumForNamePwad("TEXTURES", (UINT16)w, texturesLumpPos + 1); + } + + // Count single-patch textures + if (wadfiles[w]->type == RET_PK3) + { + texstart = W_CheckNumForFolderStartPK3("textures/", (UINT16)w, 0); + texend = W_CheckNumForFolderEndPK3("textures/", (UINT16)w, texstart); + } + else + { + texstart = W_CheckNumForMarkerStartPwad(TX_START, (UINT16)w, 0); + texend = W_CheckNumForNamePwad(TX_END, (UINT16)w, 0); + } + + if (texstart == INT16_MAX || texend == INT16_MAX) + continue; + + // PK3s have subfolders, so we can't just make a simple sum + if (wadfiles[w]->type == RET_PK3) + { + for (j = texstart; j < texend; j++) + { + if (!W_IsLumpFolder((UINT16)w, j)) // Check if lump is a folder; if not, then count it + numtextures++; + } + } + else // Add all the textures between TX_START and TX_END + { + numtextures += (UINT32)(texend - texstart); + } + } + + // If no textures found by this point, bomb out + if (!numtextures) + I_Error("No textures detected in any WADs!\n"); + + // Allocate memory and initialize to 0 for all the textures we are initialising. + // There are actually 5 buffers allocated in one for convenience. + textures = Z_Calloc((numtextures * sizeof(void *)) * 5, PU_STATIC, NULL); + + // Allocate texture column offset table. + texturecolumnofs = (void *)((UINT8 *)textures + (numtextures * sizeof(void *))); + // Allocate texture referencing cache. + texturecache = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 2)); + // Allocate texture width table. + texturewidth = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 3)); + // Allocate texture height table. + textureheight = (void *)((UINT8 *)textures + ((numtextures * sizeof(void *)) * 4)); + // Create translation table for global animation. + texturetranslation = Z_Malloc((numtextures + 1) * sizeof(*texturetranslation), PU_STATIC, NULL); + + for (i = 0; i < numtextures; i++) + texturetranslation[i] = i; + + for (i = 0, w = 0; w < numwadfiles; w++) + { +#ifdef WALLFLATS + i = Rloadflats(i, w); +#endif + i = Rloadtextures(i, w); + } + +#ifdef HWRENDER + if (rendermode == render_opengl) + HWR_LoadTextures(numtextures); +#endif +} + +static texpatch_t *R_ParsePatch(boolean actuallyLoadPatch) +{ + char *texturesToken; + size_t texturesTokenLength; + char *endPos; + char *patchName = NULL; + INT16 patchXPos; + INT16 patchYPos; + UINT8 flip = 0; + UINT8 alpha = 255; + enum patchalphastyle style = AST_COPY; + texpatch_t *resultPatch = NULL; + lumpnum_t patchLumpNum; + + // Patch identifier + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch name should be"); + } + texturesTokenLength = strlen(texturesToken); + if (texturesTokenLength>8) + { + I_Error("Error parsing TEXTURES lump: Patch name \"%s\" exceeds 8 characters",texturesToken); + } + else + { + if (patchName != NULL) + { + Z_Free(patchName); + } + patchName = (char *)Z_Malloc((texturesTokenLength+1)*sizeof(char),PU_STATIC,NULL); + M_Memcpy(patchName,texturesToken,texturesTokenLength*sizeof(char)); + patchName[texturesTokenLength] = '\0'; + } + + // Comma 1 + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after \"%s\"'s patch name should be",patchName); + } + if (strcmp(texturesToken,",")!=0) + { + I_Error("Error parsing TEXTURES lump: Expected \",\" after %s's patch name, got \"%s\"",patchName,texturesToken); + } + + // XPos + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s x coordinate should be",patchName); + } + endPos = NULL; +#ifndef AVOID_ERRNO + errno = 0; +#endif + patchXPos = strtol(texturesToken,&endPos,10); + (void)patchXPos; //unused for now + if (endPos == texturesToken // Empty string + || *endPos != '\0' // Not end of string +#ifndef AVOID_ERRNO + || errno == ERANGE // Number out-of-range +#endif + ) + { + I_Error("Error parsing TEXTURES lump: Expected an integer for patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken); + } + + // Comma 2 + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after patch \"%s\"'s x coordinate should be",patchName); + } + if (strcmp(texturesToken,",")!=0) + { + I_Error("Error parsing TEXTURES lump: Expected \",\" after patch \"%s\"'s x coordinate, got \"%s\"",patchName,texturesToken); + } + + // YPos + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s y coordinate should be",patchName); + } + endPos = NULL; +#ifndef AVOID_ERRNO + errno = 0; +#endif + patchYPos = strtol(texturesToken,&endPos,10); + (void)patchYPos; //unused for now + if (endPos == texturesToken // Empty string + || *endPos != '\0' // Not end of string +#ifndef AVOID_ERRNO + || errno == ERANGE // Number out-of-range +#endif + ) + { + I_Error("Error parsing TEXTURES lump: Expected an integer for patch \"%s\"'s y coordinate, got \"%s\"",patchName,texturesToken); + } + Z_Free(texturesToken); + + // Patch parameters block (OPTIONAL) + // added by Monster Iestyn (22/10/16) + + // Left Curly Brace + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + ; // move on and ignore, R_ParseTextures will deal with this + else + { + if (strcmp(texturesToken,"{")==0) + { + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters should be",patchName); + } + while (strcmp(texturesToken,"}")!=0) + { + if (stricmp(texturesToken, "ALPHA")==0) + { + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + alpha = 255*strtof(texturesToken, NULL); + } + else if (stricmp(texturesToken, "STYLE")==0) + { + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (stricmp(texturesToken, "TRANSLUCENT")==0) + style = AST_TRANSLUCENT; + else if (stricmp(texturesToken, "ADD")==0) + style = AST_ADD; + else if (stricmp(texturesToken, "SUBTRACT")==0) + style = AST_SUBTRACT; + else if (stricmp(texturesToken, "REVERSESUBTRACT")==0) + style = AST_REVERSESUBTRACT; + else if (stricmp(texturesToken, "MODULATE")==0) + style = AST_MODULATE; + } + else if (stricmp(texturesToken, "FLIPX")==0) + flip |= 1; + else if (stricmp(texturesToken, "FLIPY")==0) + flip |= 2; + Z_Free(texturesToken); + + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch \"%s\"'s parameters or right curly brace should be",patchName); + } + } + } + else + { + // this is not what we wanted... + // undo last read so R_ParseTextures can re-get the token for its own purposes + M_UnGetToken(); + } + Z_Free(texturesToken); + } + + if (actuallyLoadPatch == true) + { + // Check lump exists + patchLumpNum = W_GetNumForName(patchName); + // If so, allocate memory for texpatch_t and fill 'er up + resultPatch = (texpatch_t *)Z_Malloc(sizeof(texpatch_t),PU_STATIC,NULL); + resultPatch->originx = patchXPos; + resultPatch->originy = patchYPos; + resultPatch->lump = patchLumpNum & 65535; + resultPatch->wad = patchLumpNum>>16; + resultPatch->flip = flip; + resultPatch->alpha = alpha; + resultPatch->style = style; + // Clean up a little after ourselves + Z_Free(patchName); + // Then return it + return resultPatch; + } + else + { + Z_Free(patchName); + return NULL; + } +} + +static texture_t *R_ParseTexture(boolean actuallyLoadTexture) +{ + char *texturesToken; + size_t texturesTokenLength; + char *endPos; + INT32 newTextureWidth; + INT32 newTextureHeight; + texture_t *resultTexture = NULL; + texpatch_t *newPatch; + char newTextureName[9]; // no longer dynamically allocated + + // Texture name + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where texture name should be"); + } + texturesTokenLength = strlen(texturesToken); + if (texturesTokenLength>8) + { + I_Error("Error parsing TEXTURES lump: Texture name \"%s\" exceeds 8 characters",texturesToken); + } + else + { + memset(&newTextureName, 0, 9); + M_Memcpy(newTextureName, texturesToken, texturesTokenLength); + // ^^ we've confirmed that the token is <= 8 characters so it will never overflow a 9 byte char buffer + strupr(newTextureName); // Just do this now so we don't have to worry about it + } + Z_Free(texturesToken); + + // Comma 1 + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after texture \"%s\"'s name should be",newTextureName); + } + else if (strcmp(texturesToken,",")!=0) + { + I_Error("Error parsing TEXTURES lump: Expected \",\" after texture \"%s\"'s name, got \"%s\"",newTextureName,texturesToken); + } + Z_Free(texturesToken); + + // Width + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where texture \"%s\"'s width should be",newTextureName); + } + endPos = NULL; +#ifndef AVOID_ERRNO + errno = 0; +#endif + newTextureWidth = strtol(texturesToken,&endPos,10); + if (endPos == texturesToken // Empty string + || *endPos != '\0' // Not end of string +#ifndef AVOID_ERRNO + || errno == ERANGE // Number out-of-range +#endif + || newTextureWidth < 0) // Number is not positive + { + I_Error("Error parsing TEXTURES lump: Expected a positive integer for texture \"%s\"'s width, got \"%s\"",newTextureName,texturesToken); + } + Z_Free(texturesToken); + + // Comma 2 + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where comma after texture \"%s\"'s width should be",newTextureName); + } + if (strcmp(texturesToken,",")!=0) + { + I_Error("Error parsing TEXTURES lump: Expected \",\" after texture \"%s\"'s width, got \"%s\"",newTextureName,texturesToken); + } + Z_Free(texturesToken); + + // Height + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where texture \"%s\"'s height should be",newTextureName); + } + endPos = NULL; +#ifndef AVOID_ERRNO + errno = 0; +#endif + newTextureHeight = strtol(texturesToken,&endPos,10); + if (endPos == texturesToken // Empty string + || *endPos != '\0' // Not end of string +#ifndef AVOID_ERRNO + || errno == ERANGE // Number out-of-range +#endif + || newTextureHeight < 0) // Number is not positive + { + I_Error("Error parsing TEXTURES lump: Expected a positive integer for texture \"%s\"'s height, got \"%s\"",newTextureName,texturesToken); + } + Z_Free(texturesToken); + + // Left Curly Brace + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where open curly brace for texture \"%s\" should be",newTextureName); + } + if (strcmp(texturesToken,"{")==0) + { + if (actuallyLoadTexture) + { + // Allocate memory for a zero-patch texture. Obviously, we'll be adding patches momentarily. + resultTexture = (texture_t *)Z_Calloc(sizeof(texture_t),PU_STATIC,NULL); + M_Memcpy(resultTexture->name, newTextureName, 8); + resultTexture->width = newTextureWidth; + resultTexture->height = newTextureHeight; + resultTexture->type = TEXTURETYPE_COMPOSITE; + } + Z_Free(texturesToken); + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch definition for texture \"%s\" should be",newTextureName); + } + while (strcmp(texturesToken,"}")!=0) + { + if (stricmp(texturesToken, "PATCH")==0) + { + Z_Free(texturesToken); + if (resultTexture) + { + // Get that new patch + newPatch = R_ParsePatch(true); + // Make room for the new patch + resultTexture = Z_Realloc(resultTexture, sizeof(texture_t) + (resultTexture->patchcount+1)*sizeof(texpatch_t), PU_STATIC, NULL); + // Populate the uninitialized values in the new patch entry of our array + M_Memcpy(&resultTexture->patches[resultTexture->patchcount], newPatch, sizeof(texpatch_t)); + // Account for the new number of patches in the texture + resultTexture->patchcount++; + // Then free up the memory assigned to R_ParsePatch, as it's unneeded now + Z_Free(newPatch); + } + else + { + R_ParsePatch(false); + } + } + else + { + I_Error("Error parsing TEXTURES lump: Expected \"PATCH\" in texture \"%s\", got \"%s\"",newTextureName,texturesToken); + } + + texturesToken = M_GetToken(NULL); + if (texturesToken == NULL) + { + I_Error("Error parsing TEXTURES lump: Unexpected end of file where patch declaration or right curly brace for texture \"%s\" should be",newTextureName); + } + } + if (resultTexture && resultTexture->patchcount == 0) + { + I_Error("Error parsing TEXTURES lump: Texture \"%s\" must have at least one patch",newTextureName); + } + } + else + { + I_Error("Error parsing TEXTURES lump: Expected \"{\" for texture \"%s\", got \"%s\"",newTextureName,texturesToken); + } + Z_Free(texturesToken); + + if (actuallyLoadTexture) return resultTexture; + else return NULL; +} + +// Parses the TEXTURES lump... but just to count the number of textures. +int R_CountTexturesInTEXTURESLump(UINT16 wadNum, UINT16 lumpNum) +{ + char *texturesLump; + size_t texturesLumpLength; + char *texturesText; + UINT32 numTexturesInLump = 0; + char *texturesToken; + + // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll + // need to make a space of memory where I can ensure that it will terminate + // correctly. Start by loading the relevant data from the WAD. + texturesLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); + // If that didn't exist, we have nothing to do here. + if (texturesLump == NULL) return 0; + // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. + texturesLumpLength = W_LumpLengthPwad(wadNum, lumpNum); + texturesText = (char *)Z_Malloc((texturesLumpLength+1)*sizeof(char),PU_STATIC,NULL); + // Now move the contents of the lump into this new location. + memmove(texturesText,texturesLump,texturesLumpLength); + // Make damn well sure the last character in our new memory location is \0. + texturesText[texturesLumpLength] = '\0'; + // Finally, free up the memory from the first data load, because we really + // don't need it. + Z_Free(texturesLump); + + texturesToken = M_GetToken(texturesText); + while (texturesToken != NULL) + { + if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) + { + numTexturesInLump++; + Z_Free(texturesToken); + R_ParseTexture(false); + } + else + { + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); + } + texturesToken = M_GetToken(NULL); + } + Z_Free(texturesToken); + Z_Free((void *)texturesText); + + return numTexturesInLump; +} + +// Parses the TEXTURES lump... for real, this time. +void R_ParseTEXTURESLump(UINT16 wadNum, UINT16 lumpNum, INT32 *texindex) +{ + char *texturesLump; + size_t texturesLumpLength; + char *texturesText; + char *texturesToken; + texture_t *newTexture; + + I_Assert(texindex != NULL); + + // Since lumps AREN'T \0-terminated like I'd assumed they should be, I'll + // need to make a space of memory where I can ensure that it will terminate + // correctly. Start by loading the relevant data from the WAD. + texturesLump = (char *)W_CacheLumpNumPwad(wadNum, lumpNum, PU_STATIC); + // If that didn't exist, we have nothing to do here. + if (texturesLump == NULL) return; + // If we're still here, then it DOES exist; figure out how long it is, and allot memory accordingly. + texturesLumpLength = W_LumpLengthPwad(wadNum, lumpNum); + texturesText = (char *)Z_Malloc((texturesLumpLength+1)*sizeof(char),PU_STATIC,NULL); + // Now move the contents of the lump into this new location. + memmove(texturesText,texturesLump,texturesLumpLength); + // Make damn well sure the last character in our new memory location is \0. + texturesText[texturesLumpLength] = '\0'; + // Finally, free up the memory from the first data load, because we really + // don't need it. + Z_Free(texturesLump); + + texturesToken = M_GetToken(texturesText); + while (texturesToken != NULL) + { + if (stricmp(texturesToken, "WALLTEXTURE") == 0 || stricmp(texturesToken, "TEXTURE") == 0) + { + Z_Free(texturesToken); + // Get the new texture + newTexture = R_ParseTexture(true); + // Store the new texture + textures[*texindex] = newTexture; + texturewidth[*texindex] = newTexture->width; + textureheight[*texindex] = newTexture->height << FRACBITS; + // Increment i back in R_LoadTextures() + (*texindex)++; + } + else + { + I_Error("Error parsing TEXTURES lump: Expected \"WALLTEXTURE\" or \"TEXTURE\", got \"%s\"",texturesToken); + } + texturesToken = M_GetToken(NULL); + } + Z_Free(texturesToken); + Z_Free((void *)texturesText); +} + +// Search for flat name. +lumpnum_t R_GetFlatNumForName(const char *name) +{ + INT32 i; + lumpnum_t lump; + lumpnum_t start; + lumpnum_t end; + + // Scan wad files backwards so patched flats take preference. + for (i = numwadfiles - 1; i >= 0; i--) + { + switch (wadfiles[i]->type) + { + case RET_WAD: + if ((start = W_CheckNumForMarkerStartPwad("F_START", (UINT16)i, 0)) == INT16_MAX) + { + if ((start = W_CheckNumForMarkerStartPwad("FF_START", (UINT16)i, 0)) == INT16_MAX) + continue; + else if ((end = W_CheckNumForNamePwad("FF_END", (UINT16)i, start)) == INT16_MAX) + continue; + } + else + if ((end = W_CheckNumForNamePwad("F_END", (UINT16)i, start)) == INT16_MAX) + continue; + break; + case RET_PK3: + if ((start = W_CheckNumForFolderStartPK3("Flats/", i, 0)) == INT16_MAX) + continue; + if ((end = W_CheckNumForFolderEndPK3("Flats/", i, start)) == INT16_MAX) + continue; + break; + default: + continue; + } + + // Now find lump with specified name in that range. + lump = W_CheckNumForNamePwad(name, (UINT16)i, start); + if (lump < end) + { + lump += (i<<16); // found it, in our constraints + break; + } + lump = LUMPERROR; + } + + return lump; +} + +void R_ClearTextureNumCache(boolean btell) +{ + if (tidcache) + Z_Free(tidcache); + tidcache = NULL; + if (btell) + CONS_Debug(DBG_SETUP, "Fun Fact: There are %d textures used in this map.\n", tidcachelen); + tidcachelen = 0; +} + +// +// R_CheckTextureNumForName +// +// Check whether texture is available. Filter out NoTexture indicator. +// +INT32 R_CheckTextureNumForName(const char *name) +{ + INT32 i; + + // "NoTexture" marker. + if (name[0] == '-') + return 0; + + for (i = 0; i < tidcachelen; i++) + if (!strncasecmp(tidcache[i].name, name, 8)) + return tidcache[i].id; + + // Need to parse the list backwards, so textures loaded more recently are used in lieu of ones loaded earlier + //for (i = 0; i < numtextures; i++) <- old + for (i = (numtextures - 1); i >= 0; i--) // <- new + if (!strncasecmp(textures[i]->name, name, 8)) + { + tidcachelen++; + Z_Realloc(tidcache, tidcachelen * sizeof(*tidcache), PU_STATIC, &tidcache); + strncpy(tidcache[tidcachelen-1].name, name, 8); + tidcache[tidcachelen-1].name[8] = '\0'; +#ifndef ZDEBUG + CONS_Debug(DBG_SETUP, "texture #%s: %s\n", sizeu1(tidcachelen), tidcache[tidcachelen-1].name); +#endif + tidcache[tidcachelen-1].id = i; + return i; + } + + return -1; +} + +// +// R_TextureNumForName +// +// Calls R_CheckTextureNumForName, aborts with error message. +// +INT32 R_TextureNumForName(const char *name) +{ + const INT32 i = R_CheckTextureNumForName(name); + + if (i == -1) + { + static INT32 redwall = -2; + CONS_Debug(DBG_SETUP, "WARNING: R_TextureNumForName: %.8s not found\n", name); + if (redwall == -2) + redwall = R_CheckTextureNumForName("REDWALL"); + if (redwall != -1) + return redwall; + return 1; + } + return i; +} diff --git a/src/r_textures.h b/src/r_textures.h new file mode 100644 index 000000000..74a94a9ed --- /dev/null +++ b/src/r_textures.h @@ -0,0 +1,103 @@ +// SONIC ROBO BLAST 2 +//----------------------------------------------------------------------------- +// Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 1999-2020 by Sonic Team Junior. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \file r_textures.h +/// \brief Texture generation. + +#ifndef __R_TEXTURES__ +#define __R_TEXTURES__ + +#include "r_defs.h" +#include "r_state.h" +#include "p_setup.h" // levelflats +#include "r_data.h" + +#ifdef __GNUG__ +#pragma interface +#endif + +// A single patch from a texture definition, +// basically a rectangular area within +// the texture rectangle. +typedef struct +{ + // Block origin (always UL), which has already accounted for the internal origin of the patch. + INT16 originx, originy; + UINT16 wad, lump; + UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both + UINT8 alpha; // Translucency value + enum patchalphastyle style; +} texpatch_t; + +// texture type +enum +{ + TEXTURETYPE_UNKNOWN, + TEXTURETYPE_SINGLEPATCH, + TEXTURETYPE_COMPOSITE, +#ifdef WALLFLATS + TEXTURETYPE_FLAT, +#endif +}; + +// A texture_t describes a rectangular texture, +// which is composed of one or more texpatch_t structures +// that arrange graphic patches. +typedef struct +{ + // Keep name for switch changing, etc. + char name[8]; + UINT8 type; // TEXTURETYPE_ + INT16 width, height; + boolean holes; + UINT8 flip; // 1 = flipx, 2 = flipy, 3 = both + void *flat; // The texture, as a flat. + + // All the patches[patchcount] are drawn back to front into the cached texture. + INT16 patchcount; + texpatch_t patches[0]; +} texture_t; + +// all loaded and prepared textures from the start of the game +extern texture_t **textures; + +extern INT32 *texturewidth; +extern fixed_t *textureheight; // needed for texture pegging + +extern UINT32 **texturecolumnofs; // column offset lookup table for each texture +extern UINT8 **texturecache; // graphics data for each generated full-size texture + +// Load TEXTURES definitions, create lookup tables +void R_LoadTextures(void); +void R_FlushTextureCache(void); + +// Texture generation +UINT8 *R_GenerateTexture(size_t texnum); +UINT8 *R_GenerateTextureAsFlat(size_t texnum); +INT32 R_GetTextureNum(INT32 texnum); +void R_CheckTextureCache(INT32 tex); +void R_ClearTextureNumCache(boolean btell); + +// Retrieve texture data. +void *R_GetLevelFlat(levelflat_t *levelflat); +UINT8 *R_GetColumn(fixed_t tex, INT32 col); +void *R_GetFlat(lumpnum_t flatnum); + +boolean R_CheckPowersOfTwo(void); +void R_CheckFlatLength(size_t size); + +// Returns the texture number for the texture name. +INT32 R_TextureNumForName(const char *name); +INT32 R_CheckTextureNumForName(const char *name); +lumpnum_t R_GetFlatNumForName(const char *name); + +extern INT32 numtextures; + +#endif diff --git a/src/r_things.c b/src/r_things.c index 43a689545..df1946ba6 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,30 +18,29 @@ #include "st_stuff.h" #include "w_wad.h" #include "z_zone.h" +#include "m_menu.h" // character select #include "m_misc.h" +#include "info.h" // spr2names #include "i_video.h" // rendermode +#include "i_system.h" #include "r_things.h" +#include "r_picformats.h" #include "r_plane.h" +#include "r_portal.h" #include "p_tick.h" #include "p_local.h" #include "p_slopes.h" -#include "dehacked.h" // get_number (for thok) #include "d_netfil.h" // blargh. for nameonly(). #include "m_cheat.h" // objectplace #include "k_color.h" // SRB2kart #include "p_local.h" // stplyr #ifdef HWRENDER #include "hardware/hw_md2.h" +#include "hardware/hw_glob.h" +#include "hardware/hw_light.h" +#include "hardware/hw_drv.h" #endif -#ifdef PC_DOS -#include // for snprintf -int snprintf(char *str, size_t n, const char *fmt, ...); -//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); -#endif - -CV_PossibleValue_t Forceskin_cons_t[MAXSKINS+2]; - #define MINZ (FRACUNIT*4) #define BASEYCENTER (BASEVIDHEIGHT/2) @@ -65,6 +64,8 @@ static lighttable_t **spritelights; INT16 negonearray[MAXVIDWIDTH]; INT16 screenheightarray[MAXVIDWIDTH]; +spriteinfo_t spriteinfo[NUMSPRITES]; + // // INITIALIZATION FUNCTIONS // @@ -95,34 +96,41 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch UINT8 rotation, UINT8 flipped) { - char cn = R_Frame2Char(frame); // for debugging + char cn = R_Frame2Char(frame), cr = R_Rotation2Char(rotation); // for debugging - INT32 r; + INT32 r, ang; lumpnum_t lumppat = wad; lumppat <<= 16; lumppat += lump; - if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) - I_Error("R_InstallSpriteLump: Bad frame characters in lump %s", W_CheckNameForNum(lumppat)); - if (maxframe ==(size_t)-1 || frame > maxframe) maxframe = frame; + // rotsprite +#ifdef ROTSPRITE + sprtemp[frame].rotsprite.cached = 0; + for (r = 0; r < 16; r++) + { + for (ang = 0; ang < ROTANGLES; ang++) + sprtemp[frame].rotsprite.patch[r][ang] = NULL; + } +#endif/*ROTSPRITE*/ + if (rotation == 0) { // the lump should be used for all rotations if (sprtemp[frame].rotate == SRF_SINGLE) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple rot = 0 lump\n", spritename, cn); - else if (sprtemp[frame].rotate != SRF_NONE) // Let's complain for both 1-8 and L/R rotations. + else if (sprtemp[frame].rotate != SRF_NONE) // Let's bundle 1-8/16 and L/R rotations into one debug message. CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has rotations and a rot = 0 lump\n", spritename, cn); sprtemp[frame].rotate = SRF_SINGLE; - for (r = 0; r < 8; r++) + for (r = 0; r < 16; r++) { sprtemp[frame].lumppat[r] = lumppat; sprtemp[frame].lumpid[r] = lumpid; } - sprtemp[frame].flip = flipped ? UINT8_MAX : 0; // 11111111 in binary + sprtemp[frame].flip = flipped ? 0xFFFF : 0; // 1111111111111111 in binary return; } @@ -131,52 +139,67 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch UINT8 rightfactor = ((rotation == ROT_R) ? 4 : 0); // the lump should be used for half of all rotations - if (sprtemp[frame].rotate == SRF_SINGLE) + if (sprtemp[frame].rotate == SRF_NONE) + sprtemp[frame].rotate = SRF_SINGLE; + else if (sprtemp[frame].rotate == SRF_SINGLE) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has L/R rotations and a rot = 0 lump\n", spritename, cn); else if (sprtemp[frame].rotate == SRF_3D) CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-8 rotations\n", spritename, cn); - // Let's not complain about multiple L/R rotations. It's not worth the effort. - - if (sprtemp[frame].rotate == SRF_NONE) - sprtemp[frame].rotate = SRF_SINGLE; + else if (sprtemp[frame].rotate == SRF_3DGE) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has both L/R and 1-G rotations\n", spritename, cn); + else if ((sprtemp[frame].rotate & SRF_LEFT) && (rotation == ROT_L)) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple L rotations\n", spritename, cn); + else if ((sprtemp[frame].rotate & SRF_RIGHT) && (rotation == ROT_R)) + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s frame %c has multiple R rotations\n", spritename, cn); sprtemp[frame].rotate |= ((rotation == ROT_R) ? SRF_RIGHT : SRF_LEFT); + if ((sprtemp[frame].rotate & SRF_2D) == SRF_2D) + sprtemp[frame].rotate &= ~SRF_3DMASK; // SRF_3D|SRF_2D being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen. - if (sprtemp[frame].rotate == (SRF_3D|SRF_2D)) - sprtemp[frame].rotate = SRF_2D; // SRF_3D|SRF_2D being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen. - - for (r = 0; r < 4; r++) // Thanks to R_PrecacheLevel, we can't leave sprtemp[*].lumppat[*] == LUMPERROR... so we load into the front/back angle too. + // load into every relevant angle, including the front one + for (r = 0; r < 4; r++) { sprtemp[frame].lumppat[r + rightfactor] = lumppat; sprtemp[frame].lumpid[r + rightfactor] = lumpid; + sprtemp[frame].lumppat[r + rightfactor + 8] = lumppat; + sprtemp[frame].lumpid[r + rightfactor + 8] = lumpid; + } if (flipped) - sprtemp[frame].flip |= (0x0F< 3) // Right side - sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_LEFT)); // Continue allowing L frame changeover - else // if (rotation <= 3) // Left side - sprtemp[frame].rotate = (SRF_3D | (sprtemp[frame].rotate & SRF_RIGHT)); // Continue allowing R frame changeover + { + // SRF_3D|SRF_3DGE being enabled at the same time doesn't HURT in the current sprite angle implementation, but it DOES mean more to check in some of the helper functions. Let's not allow this scenario to happen. + UINT8 threedrot = (rotation > 7) ? SRF_3DGE : (sprtemp[frame].rotate & SRF_3DMASK); + if (!threedrot) + threedrot = SRF_3D; + + if (rotation == 0 || rotation == 4) // Front or back... + sprtemp[frame].rotate = threedrot; // Prevent L and R changeover + else if ((rotation & 7) > 3) // Right side + sprtemp[frame].rotate = (threedrot | (sprtemp[frame].rotate & SRF_LEFT)); // Continue allowing L frame changeover + else // if ((rotation & 7) <= 3) // Left side + sprtemp[frame].rotate = (threedrot | (sprtemp[frame].rotate & SRF_RIGHT)); // Continue allowing R frame changeover + } if (sprtemp[frame].lumppat[rotation] != LUMPERROR) - CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, '1'+rotation); + CONS_Debug(DBG_SETUP, "R_InitSprites: Sprite %s: %c%c has two lumps mapped to it\n", spritename, cn, cr); // lumppat & lumpid are the same for original Doom, but different // when using sprites in pwad : the lumppat points the new graphics @@ -201,7 +224,7 @@ static void R_InstallSpriteLump(UINT16 wad, // graphics patch // // Returns true if the sprite was succesfully added // -static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump) +boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump) { UINT16 l; UINT8 frame; @@ -213,10 +236,15 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, memset(sprtemp,0xFF, sizeof (sprtemp)); maxframe = (size_t)-1; + spritename = sprname; + // are we 'patching' a sprite already loaded ? // if so, it might patch only certain frames, not all if (spritedef->numframes) // (then spriteframes is not null) { +#ifdef ROTSPRITE + R_FreeSingleRotSprite(spritedef); +#endif // copy the already defined sprite frames M_Memcpy(sprtemp, spritedef->spriteframes, spritedef->numframes * sizeof (spriteframe_t)); @@ -233,10 +261,16 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, { if (memcmp(lumpinfo[l].name,sprname,4)==0) { - frame = R_Char2Frame(lumpinfo[l].name[4]); - rotation = (UINT8)(lumpinfo[l].name[5] - '0'); + INT32 width, height; + INT16 topoffset, leftoffset; +#ifndef NO_PNG_LUMPS + boolean isPNG = false; +#endif - if (frame >= 64 || !(R_ValidSpriteAngle(rotation))) // Give an actual NAME error -_-... + frame = R_Char2Frame(lumpinfo[l].name[4]); + rotation = R_Char2Rotation(lumpinfo[l].name[5]); + + if (frame >= 64 || rotation == 255) // Give an actual NAME error -_-... { CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); continue; @@ -248,21 +282,45 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, // store sprite info in lookup tables //FIXME : numspritelumps do not duplicate sprite replacements - W_ReadLumpHeaderPwad(wadnum, l, &patch, sizeof (patch_t), 0); - spritecachedinfo[numspritelumps].width = SHORT(patch.width)<0 && SHORT(patch.topoffset)>FRACBITS),SHORT(patch.height))<= 64 || rotation == 255) // Give an actual NAME error -_-... + { + CONS_Alert(CONS_WARNING, M_GetText("Bad sprite name: %s\n"), W_CheckNameForNumPwad(wadnum,l)); + continue; + } R_InstallSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1); } @@ -330,20 +394,21 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, break; case SRF_2D: // both Left and Right rotations - // we test to see whether the left and right slots are present - if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR)) - I_Error("R_AddSingleSpriteDef: Sprite %s frame %c is missing rotations", - sprname, R_Frame2Char(frame)); + // we test to see whether the left and right slots are present + if ((sprtemp[frame].lumppat[2] == LUMPERROR) || (sprtemp[frame].lumppat[6] == LUMPERROR)) + I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (L-R mode)", + sprname, R_Frame2Char(frame)); break; default: - // must have all 8 frames - for (rotation = 0; rotation < 8; rotation++) + // must have all 8/16 frames + rotation = ((sprtemp[frame].rotate & SRF_3DGE) ? 16 : 8); + while (rotation--) // we test the patch lump, or the id lump whatever // if it was not loaded the two are LUMPERROR if (sprtemp[frame].lumppat[rotation] == LUMPERROR) - I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations", - sprname, R_Frame2Char(frame)); + I_Error("R_AddSingleSpriteDef: Sprite %.4s frame %c is missing rotations (1-%c mode)", + sprname, R_Frame2Char(frame), ((sprtemp[frame].rotate & SRF_3DGE) ? 'G' : '8')); break; } } @@ -352,6 +417,9 @@ static boolean R_AddSingleSpriteDef(const char *sprname, spritedef_t *spritedef, if (spritedef->numframes && // has been allocated spritedef->numframes < maxframe) // more frames are defined ? { +#ifdef ROTSPRITE + R_FreeSingleRotSprite(spritedef); +#endif Z_Free(spritedef->spriteframes); spritedef->spriteframes = NULL; } @@ -376,16 +444,14 @@ void R_AddSpriteDefs(UINT16 wadnum) UINT16 start, end; char wadname[MAX_WADPATH]; + // Find the sprites section in this resource file. switch (wadfiles[wadnum]->type) { case RET_WAD: - start = W_CheckNumForNamePwad("S_START", wadnum, 0); + start = W_CheckNumForMarkerStartPwad("S_START", wadnum, 0); if (start == INT16_MAX) - start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib. - if (start == INT16_MAX) - start = 0; //let say S_START is lump 0 - else - start++; // just after S_START + start = W_CheckNumForMarkerStartPwad("SS_START", wadnum, 0); //deutex compatib. + end = W_CheckNumForNamePwad("S_END",wadnum,start); if (end == INT16_MAX) end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib. @@ -398,31 +464,40 @@ void R_AddSpriteDefs(UINT16 wadnum) return; } - if (end == INT16_MAX) + if (start == INT16_MAX) + { + // ignore skin wads (we don't want skin sprites interfering with vanilla sprites) + if (W_CheckNumForNamePwad("S_SKIN", wadnum, 0) != UINT16_MAX) + return; + + start = 0; //let say S_START is lump 0 + } + + if (end == INT16_MAX || start >= end) { CONS_Debug(DBG_SETUP, "no sprites in pwad %d\n", wadnum); return; } + // // scan through lumps, for each sprite, find all the sprite frames // for (i = 0; i < numsprites; i++) { - spritename = sprnames[i]; - if (spritename[4] && wadnum >= (UINT16)spritename[4]) + if (sprnames[i][4] && wadnum >= (UINT16)sprnames[i][4]) continue; - if (R_AddSingleSpriteDef(spritename, &sprites[i], wadnum, start, end)) + if (R_AddSingleSpriteDef(sprnames[i], &sprites[i], wadnum, start, end)) { #ifdef HWRENDER if (rendermode == render_opengl) - HWR_AddSpriteMD2(i); + HWR_AddSpriteModel(i); #endif // if a new sprite was added (not just replaced) addsprites++; #ifndef ZDEBUG - CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", spritename, wadnum); + CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", sprnames[i], wadnum); #endif } } @@ -431,125 +506,13 @@ void R_AddSpriteDefs(UINT16 wadnum) CONS_Printf(M_GetText("%s added %d frames in %s sprites\n"), wadname, end-start, sizeu1(addsprites)); } -#ifdef DELFILE -static void R_RemoveSpriteLump(UINT16 wad, // graphics patch - UINT16 lump, - size_t lumpid, // identifier - UINT8 frame, - UINT8 rotation, - UINT8 flipped) -{ - (void)wad; /// \todo: how do I remove sprites? - (void)lump; - (void)lumpid; - (void)frame; - (void)rotation; - (void)flipped; -} - -static boolean R_DelSingleSpriteDef(const char *sprname, spritedef_t *spritedef, UINT16 wadnum, UINT16 startlump, UINT16 endlump) -{ - UINT16 l; - UINT8 frame; - UINT8 rotation; - lumpinfo_t *lumpinfo; - - maxframe = (size_t)-1; - - // scan the lumps, - // filling in the frames for whatever is found - lumpinfo = wadfiles[wadnum]->lumpinfo; - if (endlump > wadfiles[wadnum]->numlumps) - endlump = wadfiles[wadnum]->numlumps; - - for (l = startlump; l < endlump; l++) - { - if (memcmp(lumpinfo[l].name,sprname,4)==0) - { - frame = (UINT8)(lumpinfo[l].name[4] - 'A'); - rotation = (UINT8)(lumpinfo[l].name[5] - '0'); - - // skip NULL sprites from very old dmadds pwads - if (W_LumpLengthPwad(wadnum,l)<=8) - continue; - - //---------------------------------------------------- - - R_RemoveSpriteLump(wadnum, l, numspritelumps, frame, rotation, 0); - - if (lumpinfo[l].name[6]) - { - frame = (UINT8)(lumpinfo[l].name[6] - 'A'); - rotation = (UINT8)(lumpinfo[l].name[7] - '0'); - R_RemoveSpriteLump(wadnum, l, numspritelumps, frame, rotation, 1); - } - } - } - - if (maxframe == (size_t)-1) - return false; - - spritedef->numframes = 0; - Z_Free(spritedef->spriteframes); - spritedef->spriteframes = NULL; - return true; -} - -void R_DelSpriteDefs(UINT16 wadnum) -{ - size_t i, delsprites = 0; - UINT16 start, end; - - // find the sprites section in this pwad - // we need at least the S_END - // (not really, but for speedup) - - start = W_CheckNumForNamePwad("S_START", wadnum, 0); - if (start == INT16_MAX) - start = W_CheckNumForNamePwad("SS_START", wadnum, 0); //deutex compatib. - if (start == INT16_MAX) - start = 0; //let say S_START is lump 0 - else - start++; // just after S_START - - end = W_CheckNumForNamePwad("S_END",wadnum,start); - if (end == INT16_MAX) - end = W_CheckNumForNamePwad("SS_END",wadnum,start); //deutex compatib. - if (end == INT16_MAX) - { - CONS_Debug(DBG_SETUP, "no sprites in pwad %d\n", wadnum); - return; - //I_Error("R_DelSpriteDefs: S_END, or SS_END missing for sprites " - // "in pwad %d\n",wadnum); - } - - // - // scan through lumps, for each sprite, find all the sprite frames - // - for (i = 0; i < numsprites; i++) - { - spritename = sprnames[i]; - - if (R_DelSingleSpriteDef(spritename, &sprites[i], wadnum, start, end)) - { - // if a new sprite was removed (not just replaced) - delsprites++; - CONS_Debug(DBG_SETUP, "sprite %s set in pwad %d\n", spritename, wadnum); - } - } - - CONS_Printf(M_GetText("%s sprites removed from file %s\n"), sizeu1(delsprites), wadfiles[wadnum]->filename); -} -#endif - // // GAME FUNCTIONS // -static UINT32 visspritecount; +UINT32 visspritecount; static UINT32 clippedvissprites; static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL}; - // // R_InitSprites // Called at program start. @@ -557,11 +520,22 @@ static vissprite_t *visspritechunks[MAXVISSPRITES >> VISSPRITECHUNKBITS] = {NULL void R_InitSprites(void) { size_t i; +#ifdef ROTSPRITE + INT32 angle; + float fa; +#endif for (i = 0; i < MAXVIDWIDTH; i++) - { negonearray[i] = -1; + +#ifdef ROTSPRITE + for (angle = 1; angle < ROTANGLES; angle++) + { + fa = ANG2RAD(FixedAngle((ROTANGDIFF * angle)<numlumps); + } + ST_ReloadSkinFaceGraphics(); // // check if all sprites have frames @@ -690,10 +669,10 @@ void R_DrawMaskedColumn(column_t *column) dc_yl = mceilingclip[dc_x]+1; if (dc_yl < 0) dc_yl = 0; - if (dc_yh >= vid.height) + if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop dc_yh = vid.height - 1; - if (dc_yl <= dc_yh && dc_yl < vid.height && dc_yh > 0) + if (dc_yl <= dc_yh && dc_yh > 0) { dc_source = (UINT8 *)column + 3; dc_texturemid = basetexturemid - (topdelta<length + 4); } @@ -724,7 +694,9 @@ void R_DrawMaskedColumn(column_t *column) dc_texturemid = basetexturemid; } -static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) +INT32 lengthcol; // column->length : for flipped column function pointers and multi-patch on 2sided wall = texture->height + +void R_DrawFlippedMaskedColumn(column_t *column) { INT32 topscreen; INT32 bottomscreen; @@ -740,7 +712,7 @@ static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) if (topdelta <= prevdelta) topdelta += prevdelta; prevdelta = topdelta; - topdelta = texheight-column->length-topdelta; + topdelta = lengthcol-column->length-topdelta; topscreen = sprtopscreen + spryscale*topdelta; bottomscreen = sprbotscreen == INT32_MAX ? topscreen + spryscale*column->length : sprbotscreen + spryscale*column->length; @@ -762,10 +734,10 @@ static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) dc_yl = mceilingclip[dc_x]+1; if (dc_yl < 0) dc_yl = 0; - if (dc_yh >= vid.height) + if (dc_yh >= vid.height) // dc_yl must be < vid.height, so reduces number of checks in tight loop dc_yh = vid.height - 1; - if (dc_yl <= dc_yh && dc_yl < vid.height && dc_yh > 0) + if (dc_yl <= dc_yh && dc_yh > 0) { dc_source = ZZ_Alloc(column->length); for (s = (UINT8 *)column+2+column->length, d = dc_source; d < dc_source+column->length; --s) @@ -775,19 +747,10 @@ static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) // Still drawn by R_DrawColumn. if (ylookup[dc_yl]) colfunc(); - else if (colfunc == R_DrawColumn_8 -#ifdef USEASM - || colfunc == R_DrawColumn_8_ASM || colfunc == R_DrawColumn_8_MMX +#ifdef PARANOIA + else + I_Error("R_DrawMaskedColumn: Invalid ylookup for dc_yl %d", dc_yl); #endif - ) - { - static INT32 first = 1; - if (first) - { - CONS_Debug(DBG_RENDER, "WARNING: avoiding a crash in %s %d\n", __FILE__, __LINE__); - first = 0; - } - } Z_Free(dc_source); } column = (column_t *)((UINT8 *)column + column->length + 4); @@ -803,9 +766,11 @@ static void R_DrawFlippedMaskedColumn(column_t *column, INT32 texheight) static void R_DrawVisSprite(vissprite_t *vis) { column_t *column; + void (*localcolfunc)(column_t *); INT32 texturecolumn; + INT32 pwidth; fixed_t frac; - patch_t *patch = W_CacheLumpNum(vis->patch, PU_CACHE); + patch_t *patch = vis->patch; fixed_t this_scale = vis->mobj->scale; INT32 x1, x2; INT64 overflow_test; @@ -825,13 +790,13 @@ static void R_DrawVisSprite(vissprite_t *vis) if ((UINT64)overflow_test&0xFFFFFFFF80000000ULL) return; // ditto } - colfunc = basecolfunc; // hack: this isn't resetting properly somewhere. + colfunc = colfuncs[BASEDRAWFUNC]; // hack: this isn't resetting properly somewhere. dc_colormap = vis->colormap; - if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & MF_BOSS) && (vis->mobj->flags2 & MF2_FRET) && (leveltime & 1)) // Bosses "flash" + if (!(vis->cut & SC_PRECIP) && (vis->mobj->flags & (MF_ENEMY|MF_BOSS)) && (vis->mobj->flags2 & MF2_FRET) && !(vis->mobj->flags & MF_GRENADEBOUNCE) && (leveltime & 1)) // Bosses "flash" { // translate certain pixels to white - colfunc = transcolfunc; - if (vis->mobj->type == MT_CYBRAKDEMON) + colfunc = colfuncs[COLDRAWFUNC_TRANS]; + if (vis->mobj->type == MT_CYBRAKDEMON || vis->mobj->colorized) dc_translation = R_GetTranslationColormap(TC_ALLWHITE, 0, GTC_CACHE); else if (vis->mobj->type == MT_METALSONIC_BATTLE) dc_translation = R_GetTranslationColormap(TC_METALSONIC, 0, GTC_CACHE); @@ -840,42 +805,50 @@ static void R_DrawVisSprite(vissprite_t *vis) } else if (vis->mobj->color && vis->transmap) // Color mapping { - colfunc = transtransfunc; + colfunc = colfuncs[COLDRAWFUNC_TRANSTRANS]; dc_transmap = vis->transmap; - if (vis->mobj->colorized) + if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) + { dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - else if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> + } + else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // MT_GHOST LOOKS LIKE A PLAYER SO USE THE PLAYER TRANSLATION TABLES. >_> { size_t skinnum = (skin_t*)vis->mobj->skin-skins; dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); } else // Use the defaults + { dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + } } else if (vis->transmap) { - colfunc = fuzzcolfunc; + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } else if (vis->mobj->color) { // translate green skin to another color - colfunc = transcolfunc; + colfunc = colfuncs[COLDRAWFUNC_TRANS]; // New colormap stuff for skins Tails 06-07-2002 - if (vis->mobj->colorized) + if (!(vis->cut & SC_PRECIP) && vis->mobj->colorized) + { dc_translation = R_GetTranslationColormap(TC_RAINBOW, vis->mobj->color, GTC_CACHE); - else if (vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! + } + else if (!(vis->cut & SC_PRECIP) && vis->mobj->skin && vis->mobj->sprite == SPR_PLAY) // This thing is a player! { size_t skinnum = (skin_t*)vis->mobj->skin-skins; dc_translation = R_GetTranslationColormap((INT32)skinnum, vis->mobj->color, GTC_CACHE); } else // Use the defaults + { dc_translation = R_GetTranslationColormap(TC_DEFAULT, vis->mobj->color, GTC_CACHE); + } } else if (vis->mobj->sprite == SPR_PLAY) // Looks like a player, but doesn't have a color? Get rid of green sonic syndrome. { - colfunc = transcolfunc; + colfunc = colfuncs[COLDRAWFUNC_TRANS]; dc_translation = R_GetTranslationColormap(TC_DEFAULT, SKINCOLOR_BLUE, GTC_CACHE); } @@ -935,60 +908,56 @@ static void R_DrawVisSprite(vissprite_t *vis) if (vis->x2 >= vid.width) vis->x2 = vid.width-1; -#if 1 - // Something is occasionally setting 1px-wide sprites whose frac is exactly the width of the sprite, causing crashes due to - // accessing invalid column info. Until the cause is found, let's try to correct those manually... - while (frac + vis->xiscale*(vis->x2-vis->x1) > SHORT(patch->width)<x2 >= vis->x1) - vis->x2--; -#endif + localcolfunc = (vis->cut & SC_VFLIP) ? R_DrawFlippedMaskedColumn : R_DrawMaskedColumn; + lengthcol = SHORT(patch->height); // Split drawing loops for paper and non-paper to reduce conditional checks per sprite if (vis->scalestep) { + pwidth = SHORT(patch->width); + // Papersprite drawing loop for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, spryscale += vis->scalestep) { - angle_t angle = ((vis->centerangle + xtoviewangle[dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; + angle_t angle = ((vis->centerangle + xtoviewangle[viewssnum][dc_x]) >> ANGLETOFINESHIFT) & 0xFFF; texturecolumn = (vis->paperoffset - FixedMul(FINETANGENT(angle), vis->paperdistance)) / this_scale; - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + if (texturecolumn < 0 || texturecolumn >= pwidth) continue; if (vis->xiscale < 0) // Flipped sprite - texturecolumn = SHORT(patch->width) - 1 - texturecolumn; + texturecolumn = pwidth - 1 - texturecolumn; sprtopscreen = (centeryfrac - FixedMul(dc_texturemid, spryscale)); dc_iscale = (0xffffffffu / (unsigned)spryscale); column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); - if (vis->cut & SC_VFLIP) - R_DrawFlippedMaskedColumn(column, patch->height); - else - R_DrawMaskedColumn(column); + localcolfunc (column); } } else { +#ifdef RANGECHECK + pwidth = SHORT(patch->width); +#endif + // Non-paper drawing loop for (dc_x = vis->x1; dc_x <= vis->x2; dc_x++, frac += vis->xiscale, sprtopscreen += vis->shear.tan) { #ifdef RANGECHECK texturecolumn = frac>>FRACBITS; - if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width)) + if (texturecolumn < 0 || texturecolumn >= pwidth) I_Error("R_DrawSpriteRange: bad texturecolumn at %d from end", vis->x2 - dc_x); column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[texturecolumn])); #else column = (column_t *)((UINT8 *)patch + LONG(patch->columnofs[frac>>FRACBITS])); #endif - if (vis->cut & SC_VFLIP) - R_DrawFlippedMaskedColumn(column, patch->height); - else - R_DrawMaskedColumn(column); + localcolfunc (column); } } - colfunc = basecolfunc; + colfunc = colfuncs[BASEDRAWFUNC]; dc_hires = 0; vis->x1 = x1; @@ -1007,7 +976,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) INT64 overflow_test; //Fab : R_InitSprites now sets a wad lump number - patch = W_CacheLumpNum(vis->patch, PU_CACHE); + patch = vis->patch; if (!patch) return; @@ -1018,7 +987,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) if (vis->transmap) { - colfunc = fuzzcolfunc; + colfunc = colfuncs[COLDRAWFUNC_FUZZY]; dc_transmap = vis->transmap; //Fab : 29-04-98: translucency table } @@ -1056,12 +1025,12 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis) R_DrawMaskedColumn(column); } - colfunc = basecolfunc; + colfunc = colfuncs[BASEDRAWFUNC]; } // // R_SplitSprite -// runs through a sector's lightlist and +// runs through a sector's lightlist and Knuckles static void R_SplitSprite(vissprite_t *sprite) { INT32 i, lightnum, lindex; @@ -1073,15 +1042,12 @@ static void R_SplitSprite(vissprite_t *sprite) for (i = 1; i < sector->numlights; i++) { - fixed_t testheight = sector->lightlist[i].height; + fixed_t testheight; if (!(sector->lightlist[i].caster->flags & FF_CUTSPRITES)) continue; -#ifdef ESLOPE - if (sector->lightlist[i].slope) - testheight = P_GetZAt(sector->lightlist[i].slope, sprite->gx, sprite->gy); -#endif + testheight = P_GetLightZAt(§or->lightlist[i], sprite->gx, sprite->gy); if (testheight >= sprite->gzt) continue; @@ -1108,14 +1074,6 @@ static void R_SplitSprite(vissprite_t *sprite) sprite->sz = cutfrac; newsprite->szt = (INT16)(sprite->sz - 1); - if (testheight < sprite->pzt && testheight > sprite->pz) - sprite->pz = newsprite->pzt = testheight; - else - { - newsprite->pz = newsprite->gz; - newsprite->pzt = newsprite->gzt; - } - newsprite->szt -= 8; newsprite->cut |= SC_TOP; @@ -1130,12 +1088,12 @@ static void R_SplitSprite(vissprite_t *sprite) else spritelights = scalelight[lightnum]; - newsprite->extra_colormap = sector->lightlist[i].extra_colormap; + newsprite->extra_colormap = *sector->lightlist[i].extra_colormap; - if (!((newsprite->cut & SC_FULLBRIGHT) - && (!newsprite->extra_colormap || !(newsprite->extra_colormap->fog & 1)))) + if (!(newsprite->cut & SC_FULLBRIGHT) + || (newsprite->extra_colormap && (newsprite->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES))) { - lindex = FixedMul(sprite->xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); + lindex = FixedMul(sprite->xscale, LIGHTRESOLUTIONFIX)>>(LIGHTSCALESHIFT); if (lindex >= MAXLIGHTSCALE) lindex = MAXLIGHTSCALE-1; @@ -1174,12 +1132,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) if (sector->heightsec != -1) z = isflipped ? sectors[sector->heightsec].ceilingheight : sectors[sector->heightsec].floorheight; else - { - if (isflipped) - z = sector->c_slope ? P_GetZAt(sector->c_slope, thing->x, thing->y) : sector->ceilingheight; // P_GetSectorCeilingZAt - else - z = sector->f_slope ? P_GetZAt(sector->f_slope, thing->x, thing->y) : sector->floorheight; // P_GetSectorFloorZAt - } + z = isflipped ? P_GetSectorCeilingZAt(sector, thing->x, thing->y) : P_GetSectorFloorZAt(sector, thing->x, thing->y); if CHECKZ { @@ -1193,10 +1146,7 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_RENDERPLANES) || (rover->alpha < 90 && !(rover->flags & FF_SWIMMABLE))) continue; - if (isflipped) - z = *rover->b_slope ? P_GetZAt(*rover->b_slope, thing->x, thing->y) : *rover->bottomheight; // P_GetFFloorBottomZAt - else - z = *rover->t_slope ? P_GetZAt(*rover->t_slope, thing->x, thing->y) : *rover->topheight; // P_GetFFloorTopZAt + z = isflipped ? P_GetFFloorBottomZAt(rover, thing->x, thing->y) : P_GetFFloorTopZAt(rover, thing->x, thing->y); if CHECKZ { @@ -1214,7 +1164,6 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) } #if 0 // Unfortunately, this drops CEZ2 down to sub-17 FPS on my i7. -//#ifdef POLYOBJECTS // NOTE: this section was not updated to reflect reverse gravity support // Check polyobjects and see if groundz needs to be altered, for rings only because they don't update floorz if (thing->type == MT_RING) @@ -1276,9 +1225,37 @@ fixed_t R_GetShadowZ(mobj_t *thing, pslope_t **shadowslope) if (shadowslope != NULL) *shadowslope = groundslope; +#undef CHECKZ + return groundz; } +static void R_SetSpritePlaneHeights(vissprite_t *vis) +{ + ffloor_t *rover; + + fixed_t top; + fixed_t bot; + + vis->pt = vis->sector->floorheight; + vis->pb = vis->sector->ceilingheight; + + for (rover = vis->sector->ffloors; rover; rover = rover->next) + { + if (rover->flags & FF_EXISTS) + { + top = P_GetFFloorTopZAt (rover, vis->gx, vis->gy); + bot = P_GetFFloorBottomZAt (rover, vis->gx, vis->gy); + + if (top <= vis->gzt && top > vis->pt) + vis->pt = top; + + if (bot >= vis->gz && bot < vis->pb) + vis->pb = bot; + } + } +} + static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, fixed_t tx, fixed_t tz) { vissprite_t *shadow; @@ -1302,13 +1279,9 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, scalemul = FixedMul(FRACUNIT - floordiff/640, scale); - if (thing->whiteshadow) - patch = W_CachePatchName("LSHADOW", PU_CACHE); - else - patch = W_CachePatchName("DSHADOW", PU_CACHE); - - xscale = FixedDiv(projection, tz); - yscale = FixedDiv(projectiony, tz); + patch = W_CachePatchName((thing->whiteshadow == true ? "LSHADOW" : "DSHADOW"), PU_CACHE); + xscale = FixedDiv(projection[viewssnum], tz); + yscale = FixedDiv(projectiony[viewssnum], tz); shadowxscale = FixedMul(thing->radius*2, scalemul); shadowyscale = FixedMul(FixedMul(thing->radius*2, scalemul), FixedDiv(abs(groundz - viewz), tz)); shadowyscale = min(shadowyscale, shadowxscale) / SHORT(patch->height); @@ -1347,24 +1320,15 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, if (shadowyscale < FRACUNIT/SHORT(patch->height)) return; // fix some crashes? shadow = R_NewVisSprite(); - - if (thing->whiteshadow) - shadow->patch = W_CheckNumForName("LSHADOW"); - else - shadow->patch = W_CheckNumForName("DSHADOW"); - + shadow->patch = patch; shadow->heightsec = vis->heightsec; - shadow->thingheight = FRACUNIT; - shadow->pz = groundz + (isflipped ? -shadow->thingheight : 0); - shadow->pzt = shadow->pz + shadow->thingheight; - shadow->mobjflags = 0; shadow->sortscale = vis->sortscale; shadow->dispoffset = vis->dispoffset - 5; shadow->gx = thing->x; shadow->gy = thing->y; - shadow->gzt = (isflipped ? shadow->pzt : shadow->pz) + SHORT(patch->height) * shadowyscale / 2; + shadow->gzt = groundz + SHORT(patch->height) * shadowyscale / 2; shadow->gz = shadow->gzt - SHORT(patch->height) * shadowyscale; shadow->texturemid = FixedMul(thing->scale, FixedDiv(shadow->gzt - viewz, shadowyscale)); if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) @@ -1374,21 +1338,14 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, shadow->mobj = thing; // Easy access! Tails 06-07-2002 - shadow->x1 = x1 < 0 ? 0 : x1; - shadow->x2 = x2 >= viewwidth ? viewwidth-1 : x2; - - // PORTAL SEMI-CLIPPING - if (portalrender) - { - if (shadow->x1 < portalclipstart) - shadow->x1 = portalclipstart; - if (shadow->x2 >= portalclipend) - shadow->x2 = portalclipend-1; - } + shadow->x1 = x1 < portalclipstart ? portalclipstart : x1; + shadow->x2 = x2 >= portalclipend ? portalclipend-1 : x2; shadow->xscale = FixedMul(xscale, shadowxscale); //SoM: 4/17/2000 shadow->scale = FixedMul(yscale, shadowyscale); shadow->sector = vis->sector; + shadow->pt = vis->pt; + shadow->pb = vis->pb; shadow->szt = (INT16)((centeryfrac - FixedMul(shadow->gzt - viewz, yscale))>>FRACBITS); shadow->sz = (INT16)((centeryfrac - FixedMul(shadow->gz - viewz, yscale))>>FRACBITS); shadow->cut = SC_ISSCALED|SC_SHADOW; //check this @@ -1407,33 +1364,34 @@ static void R_ProjectDropShadow(mobj_t *thing, vissprite_t *vis, fixed_t scale, if (thing->subsector->sector->numlights) { INT32 lightnum; -#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights! light = thing->subsector->sector->numlights - 1; + // R_GetPlaneLight won't work on sloped lights! for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { - fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thing->x, thing->y) - : thing->subsector->sector->lightlist[lightnum].height; + fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thing->x, thing->y); if (h <= shadow->gzt) { light = lightnum - 1; break; } } -#else - light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false); -#endif + //light = R_GetPlaneLight(thing->subsector->sector, shadow->gzt, false); } if (thing->subsector->sector->numlights) - shadow->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap; + shadow->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap; else shadow->extra_colormap = thing->subsector->sector->extra_colormap; shadow->transmap = transtables + (trans<whiteshadow) + if (thing->whiteshadow == true) + { shadow->colormap = scalelight[LIGHTLEVELS - 1][0]; // full bright! + } else + { shadow->colormap = scalelight[0][0]; // full dark! + } objectsdrawn++; } @@ -1449,8 +1407,13 @@ static void R_ProjectSprite(mobj_t *thing) const fixed_t thingypos = thing->y + thing->spryoff; const fixed_t thingzpos = thing->z + thing->sprzoff; + mobj_t *oldthing = thing; + + //const fixed_t oldthingxpos = oldthing->x + oldthing->sprxoff; + //const fixed_t oldthingypos = oldthing->y + oldthing->spryoff; + const fixed_t oldthingzpos = oldthing->z + oldthing->sprzoff; + fixed_t tr_x, tr_y; - fixed_t gxt, gyt; fixed_t tx, tz; fixed_t xscale, yscale, sortscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! @@ -1458,19 +1421,26 @@ static void R_ProjectSprite(mobj_t *thing) spritedef_t *sprdef; spriteframe_t *sprframe; +#ifdef ROTSPRITE + spriteinfo_t *sprinfo; +#endif size_t lump; - size_t rot; - UINT8 flip; + size_t frame, rot; + UINT16 flip; boolean vflip = (!(thing->eflags & MFE_VERTICALFLIP) != !(thing->frame & FF_VERTICALFLIP)); + boolean mirrored = thing->mirrored; + boolean hflip = (!(thing->frame & FF_HORIZONTALFLIP) != !mirrored); INT32 lindex; vissprite_t *vis; - angle_t ang = 0; // gcc 4.6 and lower fix + spritecut_e cut = SC_NONE; + + angle_t ang = 0; // compiler complaints fixed_t iscale; - fixed_t scalestep; // toast '16 + fixed_t scalestep; fixed_t offset, offset2; fixed_t basetx; // drop shadows @@ -1478,36 +1448,41 @@ static void R_ProjectSprite(mobj_t *thing) boolean papersprite = !!(thing->frame & FF_PAPERSPRITE); fixed_t paperoffset = 0, paperdistance = 0; angle_t centerangle = 0; + INT32 dispoffset = thing->info->dispoffset; + //SoM: 3/17/2000 fixed_t gz, gzt; INT32 heightsec, phs; INT32 light = 0; fixed_t this_scale = thing->scale; + // rotsprite + fixed_t spr_width, spr_height; + fixed_t spr_offset, spr_topoffset; +#ifdef ROTSPRITE + patch_t *rotsprite = NULL; + INT32 rollangle = 0; +#endif + // transform the origin point tr_x = thingxpos - viewx; tr_y = thingypos - viewy; - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - - tz = gxt-gyt; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance // thing is behind view plane? if (!papersprite && (tz < FixedMul(MINZ, this_scale))) // papersprite clipping is handled later return; - gxt = -FixedMul(tr_x, viewsin); - gyt = FixedMul(tr_y, viewcos); - basetx = tx = -(gyt + gxt); + basetx = tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance // too far off the side? - if (!papersprite && abs(tx) > tz<<2) // papersprite clipping is handled later + if (!papersprite && abs(tx) > FixedMul(tz, fovtan[viewssnum])<<2) // papersprite clipping is handled later return; // aspect ratio stuff - xscale = FixedDiv(projection, tz); - sortscale = FixedDiv(projectiony, tz); + xscale = FixedDiv(projection[viewssnum], tz); + sortscale = FixedDiv(projectiony[viewssnum], tz); // decide which patch to use for sprite relative to player #ifdef RANGECHECK @@ -1515,34 +1490,50 @@ static void R_ProjectSprite(mobj_t *thing) I_Error("R_ProjectSprite: invalid sprite number %d ", thing->sprite); #endif - rot = thing->frame&FF_FRAMEMASK; + frame = thing->frame&FF_FRAMEMASK; //Fab : 02-08-98: 'skin' override spritedef currently used for skin if (thing->skin && thing->sprite == SPR_PLAY) { - sprdef = &((skin_t *)thing->skin)->spritedef; - if (rot >= sprdef->numframes) + sprdef = &((skin_t *)thing->skin)->sprites[thing->sprite2]; +#ifdef ROTSPRITE + sprinfo = &((skin_t *)thing->skin)->sprinfo[thing->sprite2]; +#endif + if (frame >= sprdef->numframes) { + CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid skins[\"%s\"].sprites[%sSPR2_%s] frame %s\n"), ((skin_t *)thing->skin)->name, ((thing->sprite2 & FF_SPR2SUPER) ? "FF_SPR2SUPER|": ""), spr2names[(thing->sprite2 & ~FF_SPR2SUPER)], sizeu5(frame)); + thing->sprite = states[S_UNKNOWN].sprite; + thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; +#ifdef ROTSPRITE + sprinfo = NULL; +#endif + frame = thing->frame&FF_FRAMEMASK; + } } else - sprdef = &sprites[thing->sprite]; - - if (rot >= sprdef->numframes) { - CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"), - sizeu1(rot), sizeu2(sprdef->numframes), sprnames[thing->sprite]); - thing->sprite = states[S_UNKNOWN].sprite; - thing->frame = states[S_UNKNOWN].frame; sprdef = &sprites[thing->sprite]; - rot = thing->frame&FF_FRAMEMASK; - if (!thing->skin) +#ifdef ROTSPRITE + sprinfo = NULL; +#endif + + if (frame >= sprdef->numframes) { - thing->state->sprite = thing->sprite; - thing->state->frame = thing->frame; + CONS_Alert(CONS_ERROR, M_GetText("R_ProjectSprite: invalid sprite frame %s/%s for %s\n"), + sizeu1(frame), sizeu2(sprdef->numframes), sprnames[thing->sprite]); + if (thing->sprite == thing->state->sprite && thing->frame == thing->state->frame) + { + thing->state->sprite = states[S_UNKNOWN].sprite; + thing->state->frame = states[S_UNKNOWN].frame; + } + thing->sprite = states[S_UNKNOWN].sprite; + thing->frame = states[S_UNKNOWN].frame; + sprdef = &sprites[thing->sprite]; + frame = thing->frame&FF_FRAMEMASK; } } - sprframe = &sprdef->spriteframes[rot]; + sprframe = &sprdef->spriteframes[frame]; #ifdef PARANOIA if (!sprframe) @@ -1551,10 +1542,9 @@ static void R_ProjectSprite(mobj_t *thing) if (sprframe->rotate != SRF_SINGLE || papersprite) { - if (thing->player) - ang = R_PointToAngle (thingxpos, thingypos) - thing->player->frameangle; - else - ang = R_PointToAngle (thingxpos, thingypos) - thing->angle; + ang = R_PointToAngle (thingxpos, thingypos) - (thing->player ? thing->player->drawangle : thing->angle); + if (mirrored) + ang = InvAngle(ang); } if (sprframe->rotate == SRF_SINGLE) @@ -1562,17 +1552,22 @@ static void R_ProjectSprite(mobj_t *thing) // use single rotation for all views rot = 0; //Fab: for vis->patch below lump = sprframe->lumpid[0]; //Fab: see note above - flip = sprframe->flip; // Will only be 0x00 or 0xFF + flip = sprframe->flip; // Will only be 0 or 0xFFFF } else { // choose a different rotation based on player view //ang = R_PointToAngle (thingxpos, thingypos) - thing->angle; - if ((ang < ANGLE_180) && (sprframe->rotate & SRF_RIGHT)) // See from right + if ((sprframe->rotate & SRF_RIGHT) && (ang < ANGLE_180)) // See from right rot = 6; // F7 slot - else if ((ang >= ANGLE_180) && (sprframe->rotate & SRF_LEFT)) // See from left + else if ((sprframe->rotate & SRF_LEFT) && (ang >= ANGLE_180)) // See from left rot = 2; // F3 slot + else if (sprframe->rotate & SRF_3DGE) // 16-angle mode + { + rot = (ang+ANGLE_180+ANGLE_11hh)>>28; + rot = ((rot & 1)<<3)|(rot>>1); + } else // Normal behaviour rot = (ang+ANGLE_202h)>>29; @@ -1586,13 +1581,39 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->skin && ((skin_t *)thing->skin)->flags & SF_HIRES) this_scale = FixedMul(this_scale, ((skin_t *)thing->skin)->highresscale); + spr_width = spritecachedinfo[lump].width; + spr_height = spritecachedinfo[lump].height; + spr_offset = spritecachedinfo[lump].offset; + spr_topoffset = spritecachedinfo[lump].topoffset; + +#ifdef ROTSPRITE + if (thing->rollangle) + { + rollangle = R_GetRollAngle(thing->rollangle); + if (!(sprframe->rotsprite.cached & (1<sprite, frame, sprinfo, sprframe, rot, flip); + rotsprite = sprframe->rotsprite.patch[rot][rollangle]; + if (rotsprite != NULL) + { + spr_width = SHORT(rotsprite->width) << FRACBITS; + spr_height = SHORT(rotsprite->height) << FRACBITS; + spr_offset = SHORT(rotsprite->leftoffset) << FRACBITS; + spr_topoffset = SHORT(rotsprite->topoffset) << FRACBITS; + // flip -> rotate, not rotate -> flip + flip = 0; + } + } +#endif + + flip = !flip != !hflip; + // calculate edges of the shape if (flip) - offset = spritecachedinfo[lump].offset - spritecachedinfo[lump].width; + offset = spr_offset - spr_width; else - offset = -spritecachedinfo[lump].offset; + offset = -spr_offset; offset = FixedMul(offset, this_scale); - offset2 = FixedMul(spritecachedinfo[lump].width, this_scale); + offset2 = FixedMul(spr_width, this_scale); if (papersprite) { @@ -1610,17 +1631,9 @@ static void R_ProjectSprite(mobj_t *thing) tr_x += FixedMul(offset, cosmul); tr_y += FixedMul(offset, sinmul); - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - tz = gxt-gyt; - yscale = FixedDiv(projectiony, tz); - //if (yscale < 64) return; // Fix some funky visuals + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - gxt = -FixedMul(tr_x, viewsin); - gyt = FixedMul(tr_y, viewcos); - tx = -(gyt + gxt); - xscale = FixedDiv(projection, tz); - x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // Get paperoffset (offset) and paperoffset (distance) paperoffset = -FixedMul(tr_x, cosmul) - FixedMul(tr_y, sinmul); @@ -1634,17 +1647,9 @@ static void R_ProjectSprite(mobj_t *thing) tr_x += FixedMul(offset2, cosmul); tr_y += FixedMul(offset2, sinmul); - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - tz2 = gxt-gyt; - yscale2 = FixedDiv(projectiony, tz2); - //if (yscale2 < 64) return; // ditto + tz2 = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); - gxt = -FixedMul(tr_x, viewsin); - gyt = FixedMul(tr_y, viewcos); - tx2 = -(gyt + gxt); - xscale2 = FixedDiv(projection, tz2); - x2 = ((centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS); + tx2 = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); if (max(tz, tz2) < FixedMul(MINZ, this_scale)) // non-papersprite clipping is handled earlier return; @@ -1655,24 +1660,31 @@ static void R_ProjectSprite(mobj_t *thing) fixed_t div = FixedDiv(tz2-tz, FixedMul(MINZ, this_scale)-tz); tx += FixedDiv(tx2-tx, div); tz = FixedMul(MINZ, this_scale); - yscale = FixedDiv(projectiony, tz); - xscale = FixedDiv(projection, tz); - x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; } else if (tz2 < FixedMul(MINZ, this_scale)) { fixed_t div = FixedDiv(tz-tz2, FixedMul(MINZ, this_scale)-tz2); tx2 += FixedDiv(tx-tx2, div); tz2 = FixedMul(MINZ, this_scale); - yscale2 = FixedDiv(projectiony, tz2); - xscale2 = FixedDiv(projection, tz2); - x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS; } + if (tx2 < -(FixedMul(tz2, fovtan[viewssnum])<<2) || tx > FixedMul(tz, fovtan[viewssnum])<<2) // too far off the side? + return; + + yscale = FixedDiv(projectiony[viewssnum], tz); + xscale = FixedDiv(projection[viewssnum], tz); + + x1 = (centerxfrac + FixedMul(tx,xscale))>>FRACBITS; + // off the right side? if (x1 > viewwidth) return; + yscale2 = FixedDiv(projectiony[viewssnum], tz2); + xscale2 = FixedDiv(projection[viewssnum], tz2); + + x2 = (centerxfrac + FixedMul(tx2,xscale2))>>FRACBITS; + // off the left side if (x2 < 0) return; @@ -1708,10 +1720,34 @@ static void R_ProjectSprite(mobj_t *thing) return; } - // PORTAL SPRITE CLIPPING - if (portalrender) + if ((thing->flags2 & MF2_LINKDRAW) && thing->tracer) // toast 16/09/16 (SYMMETRY) { - if (x2 < portalclipstart || x1 > portalclipend) + fixed_t linkscale; + + thing = thing->tracer; + + if (! R_ThingVisible(thing)) + return; + + tr_x = thingxpos - viewx; + tr_y = thingypos - viewy; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); + linkscale = FixedDiv(projectiony[viewssnum], tz); + + if (tz < FixedMul(MINZ, this_scale)) + return; + + if (sortscale < linkscale) + dispoffset *= -1; // if it's physically behind, make sure it's ordered behind (if dispoffset > 0) + + sortscale = linkscale; // now make sure it's linked + cut = SC_LINKDRAW; + } + + // PORTAL SPRITE CLIPPING + if (portalrender && portalclipline) + { + if (x2 < portalclipstart || x1 >= portalclipend) return; if (P_PointOnLineSide(thingxpos, thingypos, portalclipline) != 0) @@ -1724,13 +1760,13 @@ static void R_ProjectSprite(mobj_t *thing) // When vertical flipped, draw sprites from the top down, at least as far as offsets are concerned. // sprite height - sprite topoffset is the proper inverse of the vertical offset, of course. // remember gz and gzt should be seperated by sprite height, not thing height - thing height can be shorter than the sprite itself sometimes! - gz = thingzpos + thing->height - FixedMul(spritecachedinfo[lump].topoffset, this_scale); - gzt = gz + FixedMul(spritecachedinfo[lump].height, this_scale); + gz = oldthingzpos + oldthing->height - FixedMul(spr_topoffset, this_scale); + gzt = gz + FixedMul(spr_height, this_scale); } else { - gzt = thingzpos + FixedMul(spritecachedinfo[lump].topoffset, this_scale); - gz = gzt - FixedMul(spritecachedinfo[lump].height, this_scale); + gzt = oldthingzpos + FixedMul(spr_topoffset, this_scale); + gz = gzt - FixedMul(spr_height, this_scale); } if (thing->subsector->sector->cullheight) @@ -1742,20 +1778,17 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) { INT32 lightnum; -#ifdef ESLOPE // R_GetPlaneLight won't work on sloped lights! light = thing->subsector->sector->numlights - 1; + // R_GetPlaneLight won't work on sloped lights! for (lightnum = 1; lightnum < thing->subsector->sector->numlights; lightnum++) { - fixed_t h = thing->subsector->sector->lightlist[lightnum].slope ? P_GetZAt(thing->subsector->sector->lightlist[lightnum].slope, thingxpos, thingypos) - : thing->subsector->sector->lightlist[lightnum].height; + fixed_t h = P_GetLightZAt(&thing->subsector->sector->lightlist[lightnum], thingxpos, thingypos); if (h <= gzt) { light = lightnum - 1; break; } } -#else - light = R_GetPlaneLight(thing->subsector->sector, gzt, false); -#endif + //light = R_GetPlaneLight(thing->subsector->sector, gzt, false); lightnum = (*thing->subsector->sector->lightlist[light].lightlevel >> LIGHTSEGSHIFT); if (lightnum < 0) @@ -1790,14 +1823,11 @@ static void R_ProjectSprite(mobj_t *thing) vis->mobjflags = thing->flags; vis->scale = yscale; //<sortscale = sortscale; - vis->dispoffset = thing->info->dispoffset; // Monster Iestyn: 23/11/15 + vis->dispoffset = dispoffset; // Monster Iestyn: 23/11/15 vis->gx = thingxpos; vis->gy = thingypos; vis->gz = gz; vis->gzt = gzt; - vis->thingheight = thing->height; - vis->pz = thingzpos; - vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = scalestep; vis->paperoffset = paperoffset; @@ -1808,25 +1838,19 @@ static void R_ProjectSprite(mobj_t *thing) vis->mobj = thing; // Easy access! Tails 06-07-2002 - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; - - // PORTAL SEMI-CLIPPING - if (portalrender) - { - if (vis->x1 < portalclipstart) - vis->x1 = portalclipstart; - if (vis->x2 > portalclipend) - vis->x2 = portalclipend; - } + vis->x1 = x1 < portalclipstart ? portalclipstart : x1; + vis->x2 = x2 >= portalclipend ? portalclipend-1 : x2; vis->xscale = xscale; //SoM: 4/17/2000 vis->sector = thing->subsector->sector; vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, sortscale))>>FRACBITS); vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, sortscale))>>FRACBITS); - vis->cut = SC_NONE; + + R_SetSpritePlaneHeights(vis); + + vis->cut = cut; if (thing->subsector->sector->numlights) - vis->extra_colormap = thing->subsector->sector->lightlist[light].extra_colormap; + vis->extra_colormap = *thing->subsector->sector->lightlist[light].extra_colormap; else vis->extra_colormap = thing->subsector->sector->extra_colormap; @@ -1834,7 +1858,7 @@ static void R_ProjectSprite(mobj_t *thing) if (flip) { - vis->startfrac = spritecachedinfo[lump].width-1; + vis->startfrac = spr_width-1; vis->xiscale = -iscale; } else @@ -1851,7 +1875,12 @@ static void R_ProjectSprite(mobj_t *thing) //Fab: lumppat is the lump number of the patch to use, this is different // than lumpid for sprites-in-pwad : the graphics are patched - vis->patch = sprframe->lumppat[rot]; +#ifdef ROTSPRITE + if (rotsprite != NULL) + vis->patch = rotsprite; + else +#endif + vis->patch = W_CachePatchNum(sprframe->lumppat[rot], PU_CACHE); // // determine the colormap (lightlevel & special effects) @@ -1880,7 +1909,7 @@ static void R_ProjectSprite(mobj_t *thing) } if ((vis->cut & SC_FULLBRIGHT) - && (!vis->extra_colormap || !(vis->extra_colormap->fog & 1))) + && (!vis->extra_colormap || !(vis->extra_colormap->flags & CMF_FADEFULLBRIGHTSPRITES))) { // full bright: goggles vis->colormap = colormaps; @@ -1888,7 +1917,7 @@ static void R_ProjectSprite(mobj_t *thing) else { // diminished light - lindex = FixedMul(xscale, FixedDiv(640, vid.width))>>(LIGHTSCALESHIFT); + lindex = FixedMul(xscale, LIGHTRESOLUTIONFIX)>>(LIGHTSCALESHIFT); if (lindex >= MAXLIGHTSCALE) lindex = MAXLIGHTSCALE-1; @@ -1905,8 +1934,8 @@ static void R_ProjectSprite(mobj_t *thing) if (thing->subsector->sector->numlights) R_SplitSprite(vis); - if (thing->shadowscale && cv_shadow.value) - R_ProjectDropShadow(thing, vis, thing->shadowscale, basetx, tz); + if (oldthing->shadowscale && cv_shadow.value) + R_ProjectDropShadow(oldthing, vis, oldthing->shadowscale, basetx, tz); // Debug ++objectsdrawn; @@ -1915,7 +1944,6 @@ static void R_ProjectSprite(mobj_t *thing) static void R_ProjectPrecipitationSprite(precipmobj_t *thing) { fixed_t tr_x, tr_y; - fixed_t gxt, gyt; fixed_t tx, tz; fixed_t xscale, yscale; //added : 02-02-98 : aaargll..if I were a math-guy!!! @@ -1930,32 +1958,27 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) fixed_t iscale; //SoM: 3/17/2000 - fixed_t gz ,gzt; + fixed_t gz, gzt; // transform the origin point tr_x = thing->x - viewx; tr_y = thing->y - viewy; - gxt = FixedMul(tr_x, viewcos); - gyt = -FixedMul(tr_y, viewsin); - - tz = gxt - gyt; + tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance // thing is behind view plane? if (tz < MINZ) return; - gxt = -FixedMul(tr_x, viewsin); - gyt = FixedMul(tr_y, viewcos); - tx = -(gyt + gxt); + tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance // too far off the side? - if (abs(tx) > tz<<2) + if (abs(tx) > FixedMul(tz, fovtan[viewssnum])<<2) return; // aspect ratio stuff : - xscale = FixedDiv(projection, tz); - yscale = FixedDiv(projectiony, tz); + xscale = FixedDiv(projection[viewssnum], tz); + yscale = FixedDiv(projectiony[viewssnum], tz); // decide which patch to use for sprite relative to player #ifdef RANGECHECK @@ -1998,22 +2021,15 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) return; // PORTAL SPRITE CLIPPING - if (portalrender) + if (portalrender && portalclipline) { - if (x2 < portalclipstart || x1 > portalclipend) + if (x2 < portalclipstart || x1 >= portalclipend) return; if (P_PointOnLineSide(thing->x, thing->y, portalclipline) != 0) return; } - // okay, we can't return now except for vertical clipping... this is a hack, but weather isn't networked, so it should be ok - if (!(thing->precipflags & PCF_THUNK)) - { - P_PrecipThinker(thing); - thing->precipflags |= PCF_THUNK; - } - //SoM: 3/17/2000: Disregard sprites that are out of view.. gzt = thing->z + spritecachedinfo[lump].topoffset; gz = gzt - spritecachedinfo[lump].height; @@ -2021,7 +2037,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) if (thing->subsector->sector->cullheight) { if (R_DoCulling(thing->subsector->sector->cullheight, viewsector->cullheight, viewz, gz, gzt)) - return; + goto weatherthink; } // store information in a vissprite @@ -2032,32 +2048,22 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) vis->gy = thing->y; vis->gz = gz; vis->gzt = gzt; - vis->thingheight = 4*FRACUNIT; - vis->pz = thing->z; - vis->pzt = vis->pz + vis->thingheight; vis->texturemid = vis->gzt - viewz; vis->scalestep = 0; vis->paperdistance = 0; vis->shear.tan = 0; vis->shear.offset = 0; - vis->x1 = x1 < 0 ? 0 : x1; - vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2; - - // PORTAL SEMI-CLIPPING - if (portalrender) - { - if (vis->x1 < portalclipstart) - vis->x1 = portalclipstart; - if (vis->x2 > portalclipend) - vis->x2 = portalclipend; - } + vis->x1 = x1 < portalclipstart ? portalclipstart : x1; + vis->x2 = x2 >= portalclipend ? portalclipend-1 : x2; vis->xscale = xscale; //SoM: 4/17/2000 vis->sector = thing->subsector->sector; vis->szt = (INT16)((centeryfrac - FixedMul(vis->gzt - viewz, yscale))>>FRACBITS); vis->sz = (INT16)((centeryfrac - FixedMul(vis->gz - viewz, yscale))>>FRACBITS); + R_SetSpritePlaneHeights(vis); + iscale = FixedDiv(FRACUNIT, xscale); vis->startfrac = 0; @@ -2068,7 +2074,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) //Fab: lumppat is the lump number of the patch to use, this is different // than lumpid for sprites-in-pwad : the graphics are patched - vis->patch = sprframe->lumppat[0]; + vis->patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); // specific translucency // (no draw flags) @@ -2077,6 +2083,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) else vis->transmap = NULL; + vis->mobj = (mobj_t *)thing; vis->mobjflags = 0; vis->cut = SC_PRECIP; vis->extra_colormap = thing->subsector->sector->extra_colormap; @@ -2084,6 +2091,14 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing) // Fullbright vis->colormap = colormaps; + +weatherthink: + // okay... this is a hack, but weather isn't networked, so it should be ok + if (!(thing->precipflags & PCF_THUNK)) + { + P_PrecipThinker(thing); + thing->precipflags |= PCF_THUNK; + } } // R_AddSprites @@ -2094,7 +2109,7 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) mobj_t *thing; precipmobj_t *precipthing; // Tails 08-25-2002 INT32 lightnum; - fixed_t approx_dist, limit_dist; + fixed_t limit_dist; if (rendermode != render_soft) return; @@ -2125,59 +2140,20 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) // Handle all things in sector. // If a limit exists, handle things a tiny bit different. - if ((limit_dist = (fixed_t)(cv_drawdist.value) * mapobjectscale)) + limit_dist = (fixed_t)(cv_drawdist.value) * mapobjectscale; + for (thing = sec->thinglist; thing; thing = thing->snext) { - for (thing = sec->thinglist; thing; thing = thing->snext) - { - if (thing->sprite == SPR_NULL) - continue; - - if ((viewssnum == 0 && (thing->drawflags & MFD_DONTDRAWP1)) - || (viewssnum == 1 && (thing->drawflags & MFD_DONTDRAWP2)) - || (viewssnum == 2 && (thing->drawflags & MFD_DONTDRAWP3)) - || (viewssnum == 3 && (thing->drawflags & MFD_DONTDRAWP4))) - continue; - - approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); - - if (approx_dist > limit_dist) - continue; - + if (R_ThingVisibleWithinDist(thing, limit_dist)) R_ProjectSprite(thing); - } - } - else - { - // Draw everything in sector, no checks - for (thing = sec->thinglist; thing; thing = thing->snext) - { - if (thing->sprite == SPR_NULL) - continue; - - if ((viewssnum == 0 && (thing->drawflags & MFD_DONTDRAWP1)) - || (viewssnum == 1 && (thing->drawflags & MFD_DONTDRAWP2)) - || (viewssnum == 2 && (thing->drawflags & MFD_DONTDRAWP3)) - || (viewssnum == 3 && (thing->drawflags & MFD_DONTDRAWP4))) - continue; - - R_ProjectSprite(thing); - } } // no, no infinite draw distance for precipitation. this option at zero is supposed to turn it off - if ((limit_dist = (fixed_t)(cv_drawdist_precip.value) * mapobjectscale)) + if ((limit_dist = (fixed_t)cv_drawdist_precip.value * mapobjectscale)) { for (precipthing = sec->preciplist; precipthing; precipthing = precipthing->snext) { - if (precipthing->precipflags & PCF_INVISIBLE) - continue; - - approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y); - - if (approx_dist > limit_dist) - continue; - - R_ProjectPrecipitationSprite(precipthing); + if (R_PrecipThingVisible(precipthing, limit_dist)) + R_ProjectPrecipitationSprite(precipthing); } } } @@ -2185,50 +2161,121 @@ void R_AddSprites(sector_t *sec, INT32 lightlevel) // // R_SortVisSprites // -static vissprite_t vsprsortedhead; - -void R_SortVisSprites(void) +static void R_SortVisSprites(vissprite_t* vsprsortedhead, UINT32 start, UINT32 end) { - UINT32 i; + UINT32 i, linkedvissprites = 0; vissprite_t *ds, *dsprev, *dsnext, *dsfirst; vissprite_t *best = NULL; vissprite_t unsorted; fixed_t bestscale; INT32 bestdispoffset; - if (!visspritecount) - return; - unsorted.next = unsorted.prev = &unsorted; - dsfirst = R_GetVisSprite(0); + dsfirst = R_GetVisSprite(start); // The first's prev and last's next will be set to // nonsense, but are fixed in a moment - for (i = 0, dsnext = dsfirst, ds = NULL; i < visspritecount; i++) + for (i = start, dsnext = dsfirst, ds = NULL; i < end; i++) { dsprev = ds; ds = dsnext; - if (i < visspritecount - 1) dsnext = R_GetVisSprite(i + 1); + if (i < end - 1) dsnext = R_GetVisSprite(i + 1); ds->next = dsnext; ds->prev = dsprev; + ds->linkdraw = NULL; } // Fix first and last. ds still points to the last one after the loop dsfirst->prev = &unsorted; unsorted.next = dsfirst; if (ds) + { ds->next = &unsorted; + ds->linkdraw = NULL; + } unsorted.prev = ds; + // bundle linkdraw + for (ds = unsorted.prev; ds != &unsorted; ds = ds->prev) + { + if (!(ds->cut & SC_LINKDRAW)) + continue; + + if (ds->cut & SC_SHADOW) + continue; + + // reuse dsfirst... + for (dsfirst = unsorted.prev; dsfirst != &unsorted; dsfirst = dsfirst->prev) + { + // don't connect if it's also a link + if (dsfirst->cut & SC_LINKDRAW) + continue; + + // don't connect to your shadow! + if (dsfirst->cut & SC_SHADOW) + continue; + + // don't connect if it's not the tracer + if (dsfirst->mobj != ds->mobj) + continue; + + // don't connect if the tracer's top is cut off, but lower than the link's top + if ((dsfirst->cut & SC_TOP) + && dsfirst->szt > ds->szt) + continue; + + // don't connect if the tracer's bottom is cut off, but higher than the link's bottom + if ((dsfirst->cut & SC_BOTTOM) + && dsfirst->sz < ds->sz) + continue; + + break; + } + + // remove from chain + ds->next->prev = ds->prev; + ds->prev->next = ds->next; + linkedvissprites++; + + if (dsfirst != &unsorted) + { + if (!(ds->cut & SC_FULLBRIGHT)) + ds->colormap = dsfirst->colormap; + ds->extra_colormap = dsfirst->extra_colormap; + + // reusing dsnext... + dsnext = dsfirst->linkdraw; + + if (!dsnext || ds->dispoffset < dsnext->dispoffset) + { + ds->next = dsnext; + dsfirst->linkdraw = ds; + } + else + { + for (; dsnext->next != NULL; dsnext = dsnext->next) + if (ds->dispoffset < dsnext->next->dispoffset) + break; + ds->next = dsnext->next; + dsnext->next = ds; + } + } + } + // pull the vissprites out by scale - vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead; - for (i = 0; i < visspritecount; i++) + vsprsortedhead->next = vsprsortedhead->prev = vsprsortedhead; + for (i = start; i < end-linkedvissprites; i++) { bestscale = bestdispoffset = INT32_MAX; for (ds = unsorted.next; ds != &unsorted; ds = ds->next) { +#ifdef PARANOIA + if (ds->cut & SC_LINKDRAW) + I_Error("R_SortVisSprites: no link or discardal made for linkdraw!"); +#endif + if (ds->sortscale < bestscale) { bestscale = ds->sortscale; @@ -2244,10 +2291,10 @@ void R_SortVisSprites(void) } best->next->prev = best->prev; best->prev->next = best->next; - best->next = &vsprsortedhead; - best->prev = vsprsortedhead.prev; - vsprsortedhead.prev->next = best; - vsprsortedhead.prev = best; + best->next = vsprsortedhead; + best->prev = vsprsortedhead->prev; + vsprsortedhead->prev->next = best; + vsprsortedhead->prev = best; } } @@ -2257,33 +2304,32 @@ void R_SortVisSprites(void) static drawnode_t *R_CreateDrawNode(drawnode_t *link); static drawnode_t nodebankhead; -static drawnode_t nodehead; -static void R_CreateDrawNodes(void) +static void R_CreateDrawNodes(maskcount_t* mask, drawnode_t* head, boolean tempskip) { drawnode_t *entry; drawseg_t *ds; INT32 i, p, best, x1, x2; fixed_t bestdelta, delta; vissprite_t *rover; + static vissprite_t vsprsortedhead; drawnode_t *r2; visplane_t *plane; INT32 sintersect; fixed_t scale = 0; // Add the 3D floors, thicksides, and masked textures... - for (ds = ds_p; ds-- > drawsegs ;) + for (ds = drawsegs + mask->drawsegs[1]; ds-- > drawsegs + mask->drawsegs[0];) { if (ds->numthicksides) { for (i = 0; i < ds->numthicksides; i++) { - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->thickseg = ds; entry->ffloor = ds->thicksides[i]; } } -#ifdef POLYOBJECTS_PLANES // Check for a polyobject plane, but only if this is a front line if (ds->curline->polyseg && ds->curline->polyseg->visplane && !ds->curline->side) { plane = ds->curline->polyseg->visplane; @@ -2293,16 +2339,15 @@ static void R_CreateDrawNodes(void) ; else { // Put it in! - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->plane = plane; entry->seg = ds; } ds->curline->polyseg->visplane = NULL; } -#endif if (ds->maskedtexturecol) { - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->seg = ds; } if (ds->numffloorplanes) @@ -2333,7 +2378,7 @@ static void R_CreateDrawNodes(void) } if (best != -1) { - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->plane = ds->ffloorplanes[best]; entry->seg = ds; ds->ffloorplanes[best] = NULL; @@ -2344,7 +2389,9 @@ static void R_CreateDrawNodes(void) } } -#ifdef POLYOBJECTS_PLANES + if (tempskip) + return; + // find all the remaining polyobject planes and add them on the end of the list // probably this is a terrible idea if we wanted them to be sorted properly // but it works getting them in for now @@ -2360,17 +2407,18 @@ static void R_CreateDrawNodes(void) PolyObjects[i].visplane = NULL; continue; } - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->plane = plane; // note: no seg is set, for what should be obvious reasons PolyObjects[i].visplane = NULL; } -#endif - if (visspritecount == 0) + // No vissprites in this mask? + if (mask->vissprites[1] - mask->vissprites[0] == 0) return; - R_SortVisSprites(); + R_SortVisSprites(&vsprsortedhead, mask->vissprites[0], mask->vissprites[1]); + for (rover = vsprsortedhead.prev; rover != &vsprsortedhead; rover = rover->prev) { if (rover->szt > vid.height || rover->sz < 0) @@ -2378,7 +2426,7 @@ static void R_CreateDrawNodes(void) sintersect = (rover->x1 + rover->x2) / 2; - for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next) + for (r2 = head->next; r2 != head; r2 = r2->next) { if (r2->plane) { @@ -2388,28 +2436,19 @@ static void R_CreateDrawNodes(void) if (rover->szt > r2->plane->low || rover->sz < r2->plane->high) continue; -#ifdef ESLOPE // Effective height may be different for each comparison in the case of slopes - if (r2->plane->slope) { - planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy); - planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy); - } else -#endif - planeobjectz = planecameraz = r2->plane->height; + planeobjectz = P_GetZAt(r2->plane->slope, rover->gx, rover->gy, r2->plane->height); + planecameraz = P_GetZAt(r2->plane->slope, viewx, viewy, r2->plane->height); - if (rover->mobjflags & MF_NOCLIPHEIGHT) + // bird: if any part of the sprite peeks in front the plane + if (planecameraz < viewz) { - //Objects with NOCLIPHEIGHT can appear halfway in. - if (planecameraz < viewz && rover->pz+(rover->thingheight/2) >= planeobjectz) - continue; - if (planecameraz > viewz && rover->pzt-(rover->thingheight/2) <= planeobjectz) + if (rover->pt >= planeobjectz && rover->gzt >= planeobjectz) continue; } - else + else if (planecameraz > viewz) { - if (planecameraz < viewz && rover->pz >= planeobjectz) - continue; - if (planecameraz > viewz && rover->pzt <= planeobjectz) + if (rover->pb <= planeobjectz && rover->gz <= planeobjectz) continue; } @@ -2453,21 +2492,10 @@ static void R_CreateDrawNodes(void) if (scale <= rover->sortscale) continue; -#ifdef ESLOPE - if (*r2->ffloor->t_slope) { - topplaneobjectz = P_GetZAt(*r2->ffloor->t_slope, rover->gx, rover->gy); - topplanecameraz = P_GetZAt(*r2->ffloor->t_slope, viewx, viewy); - } else -#endif - topplaneobjectz = topplanecameraz = *r2->ffloor->topheight; - -#ifdef ESLOPE - if (*r2->ffloor->b_slope) { - botplaneobjectz = P_GetZAt(*r2->ffloor->b_slope, rover->gx, rover->gy); - botplanecameraz = P_GetZAt(*r2->ffloor->b_slope, viewx, viewy); - } else -#endif - botplaneobjectz = botplanecameraz = *r2->ffloor->bottomheight; + topplaneobjectz = P_GetFFloorTopZAt (r2->ffloor, rover->gx, rover->gy); + topplanecameraz = P_GetFFloorTopZAt (r2->ffloor, viewx, viewy); + botplaneobjectz = P_GetFFloorBottomZAt(r2->ffloor, rover->gx, rover->gy); + botplanecameraz = P_GetFFloorBottomZAt(r2->ffloor, viewx, viewy); if ((topplanecameraz > viewz && botplanecameraz < viewz) || (topplanecameraz < viewz && rover->gzt < topplaneobjectz) || @@ -2482,20 +2510,6 @@ static void R_CreateDrawNodes(void) } else if (r2->seg) { -#if 0 //#ifdef POLYOBJECTS_PLANES - if (r2->seg->curline->polyseg && rover->mobj && P_MobjInsidePolyobj(r2->seg->curline->polyseg, rover->mobj)) { - // Determine if we need to sort in front of the polyobj, based on the planes. This fixes the issue where - // polyobject planes render above the object standing on them. (A bit hacky... but it works.) -Red - mobj_t *mo = rover->mobj; - sector_t *po = r2->seg->curline->backsector; - - if (po->ceilingheight < viewz && mo->z+mo->height > po->ceilingheight) - continue; - - if (po->floorheight > viewz && mo->z < po->floorheight) - continue; - } -#endif if (rover->x1 > r2->seg->x2 || rover->x2 < r2->seg->x1) continue; @@ -2531,9 +2545,9 @@ static void R_CreateDrawNodes(void) } } } - if (r2 == &nodehead) + if (r2 == head) { - entry = R_CreateDrawNode(&nodehead); + entry = R_CreateDrawNode(head); entry->sprite = rover; } } @@ -2565,6 +2579,8 @@ static drawnode_t *R_CreateDrawNode(drawnode_t *link) node->thickseg = NULL; node->ffloor = NULL; node->sprite = NULL; + + ps_numdrawnodes++; return node; } @@ -2575,25 +2591,24 @@ static void R_DoneWithNode(drawnode_t *node) (node->prev = &nodebankhead)->next = node; } -static void R_ClearDrawNodes(void) +static void R_ClearDrawNodes(drawnode_t* head) { drawnode_t *rover; drawnode_t *next; - for (rover = nodehead.next; rover != &nodehead ;) + for (rover = head->next; rover != head;) { next = rover->next; R_DoneWithNode(rover); rover = next; } - nodehead.next = nodehead.prev = &nodehead; + head->next = head->prev = head; } void R_InitDrawNodes(void) { nodebankhead.next = nodebankhead.prev = &nodebankhead; - nodehead.next = nodehead.prev = &nodehead; } // @@ -2619,10 +2634,10 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr) // R_ClipSprites // Clips vissprites without drawing, so that portals can work. -Red -void R_ClipSprites(void) +void R_ClipSprites(drawseg_t* dsstart, portal_t* portal) { vissprite_t *spr; - for (;clippedvissprites < visspritecount; clippedvissprites++) + for (; clippedvissprites < visspritecount; clippedvissprites++) { drawseg_t *ds; INT32 x; @@ -2645,7 +2660,7 @@ void R_ClipSprites(void) // and buggy, by going past LEFT end of array: // for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code - for (ds = ds_p; ds-- > drawsegs ;) + for (ds = ds_p; ds-- > dsstart;) { // determine if the drawseg obscures the sprite if (ds->x1 > spr->x2 || @@ -2657,34 +2672,37 @@ void R_ClipSprites(void) continue; } - if (ds->portalpass > 0 && ds->portalpass <= portalrender) - continue; // is a portal + if (ds->portalpass != 66) + { + if (ds->portalpass > 0 && ds->portalpass <= portalrender) + continue; // is a portal + + if (ds->scale1 > ds->scale2) + { + lowscale = ds->scale2; + scale = ds->scale1; + } + else + { + lowscale = ds->scale1; + scale = ds->scale2; + } + + if (scale < spr->sortscale || + (lowscale < spr->sortscale && + !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) + { + // masked mid texture? + /*if (ds->maskedtexturecol) + R_RenderMaskedSegRange (ds, r1, r2);*/ + // seg is behind sprite + continue; + } + } r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1; r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2; - if (ds->scale1 > ds->scale2) - { - lowscale = ds->scale2; - scale = ds->scale1; - } - else - { - lowscale = ds->scale1; - scale = ds->scale2; - } - - if (scale < spr->sortscale || - (lowscale < spr->sortscale && - !R_PointOnSegSide (spr->gx, spr->gy, ds->curline))) - { - // masked mid texture? - /*if (ds->maskedtexturecol) - R_RenderMaskedSegRange (ds, r1, r2);*/ - // seg is behind sprite - continue; - } - // clip this piece of the sprite silhouette = ds->silhouette; @@ -2801,20 +2819,77 @@ void R_ClipSprites(void) //Fab : 26-04-98: was -1, now clips against console bottom spr->cliptop[x] = (INT16)con_clipviewtop; } + + if (portal) + { + for (x = spr->x1; x <= spr->x2; x++) + { + if (spr->clipbot[x] > portal->floorclip[x - portal->start]) + spr->clipbot[x] = portal->floorclip[x - portal->start]; + if (spr->cliptop[x] < portal->ceilingclip[x - portal->start]) + spr->cliptop[x] = portal->ceilingclip[x - portal->start]; + } + } } } +/* Check if thing may be drawn from our current view. */ +boolean R_ThingVisible (mobj_t *thing) +{ + if (thing->sprite == SPR_NULL) + return false; + + if (r_viewmobj && (thing == r_viewmobj || (r_viewmobj->player && r_viewmobj->player->followmobj == thing))) + return false; + + if ((viewssnum == 0 && (thing->drawflags & MFD_DONTDRAWP1)) + || (viewssnum == 1 && (thing->drawflags & MFD_DONTDRAWP2)) + || (viewssnum == 2 && (thing->drawflags & MFD_DONTDRAWP3)) + || (viewssnum == 3 && (thing->drawflags & MFD_DONTDRAWP4))) + return false; + + return true; +} + +boolean R_ThingVisibleWithinDist (mobj_t *thing, + fixed_t limit_dist) +{ + fixed_t approx_dist; + + if (! R_ThingVisible(thing)) + return false; + + approx_dist = P_AproxDistance(viewx-thing->x, viewy-thing->y); + + if (limit_dist && approx_dist > limit_dist) + return false; + + return true; +} + +/* Check if precipitation may be drawn from our current view. */ +boolean R_PrecipThingVisible (precipmobj_t *precipthing, + fixed_t limit_dist) +{ + fixed_t approx_dist; + + if (( precipthing->precipflags & PCF_INVISIBLE )) + return false; + + approx_dist = P_AproxDistance(viewx-precipthing->x, viewy-precipthing->y); + + return ( approx_dist <= limit_dist ); +} + // // R_DrawMasked // -void R_DrawMasked(void) +static void R_DrawMaskedList (drawnode_t* head) { drawnode_t *r2; drawnode_t *next; - R_CreateDrawNodes(); - - for (r2 = nodehead.next; r2 != &nodehead; r2 = r2->next) + for (r2 = head->next; r2 != head; r2 = r2->next) { if (r2->plane) { @@ -2845,638 +2920,61 @@ void R_DrawMasked(void) // Tails 08-18-2002 if (r2->sprite->cut & SC_PRECIP) R_DrawPrecipitationSprite(r2->sprite); - else + else if (!r2->sprite->linkdraw) R_DrawSprite(r2->sprite); + else // unbundle linkdraw + { + vissprite_t *ds = r2->sprite->linkdraw; + + for (; + (ds != NULL && r2->sprite->dispoffset > ds->dispoffset); + ds = ds->next) + R_DrawSprite(ds); + + R_DrawSprite(r2->sprite); + + for (; ds != NULL; ds = ds->next) + R_DrawSprite(ds); + } R_DoneWithNode(r2); r2 = next; } } - R_ClearDrawNodes(); } -// ========================================================================== -// -// SKINS CODE -// -// ========================================================================== - -// We can assume those are tied to skins somewhat, hence why they're defined here. -INT32 numskins = 0; -follower_t followers[MAXSKINS]; -// default followers are defined in SOC_FLWR in followers.kart / gfx.kart (depending on what exe this is, at this point) - - -skin_t skins[MAXSKINS]; -// FIXTHIS: don't work because it must be inistilised before the config load -//#define SKINVALUES -#ifdef SKINVALUES -CV_PossibleValue_t skin_cons_t[MAXSKINS+1]; -#endif - -static void Sk_SetDefaultValue(skin_t *skin) +void R_DrawMasked(maskcount_t* masks, UINT8 nummasks) { - INT32 i; - // - // set default skin values - // - memset(skin, 0, sizeof (skin_t)); - snprintf(skin->name, - sizeof skin->name, "skin %u", (UINT32)(skin-skins)); - skin->name[sizeof skin->name - 1] = '\0'; - skin->wadnum = INT16_MAX; - strcpy(skin->sprite, ""); + drawnode_t *heads; /**< Drawnode lists; as many as number of views/portals. */ + SINT8 i; - skin->flags = 0; + heads = calloc(nummasks, sizeof(drawnode_t)); - strcpy(skin->realname, "Someone"); - strcpy(skin->hudname, "???"); - strncpy(skin->facerank, "PLAYRANK", 9); - strncpy(skin->facewant, "PLAYWANT", 9); - strncpy(skin->facemmap, "PLAYMMAP", 9); - - for (i = 0; i < SKINRIVALS; i++) + for (i = 0; i < nummasks; i++) { - strcpy(skin->rivals[i], ""); + heads[i].next = heads[i].prev = &heads[i]; + + viewx = masks[i].viewx; + viewy = masks[i].viewy; + viewz = masks[i].viewz; + viewsector = masks[i].viewsector; + + R_CreateDrawNodes(&masks[i], &heads[i], false); } - skin->starttranscolor = 96; - skin->prefcolor = SKINCOLOR_GREEN; + //for (i = 0; i < nummasks; i++) + // CONS_Printf("Mask no.%d:\ndrawsegs: %d\n vissprites: %d\n\n", i, masks[i].drawsegs[1] - masks[i].drawsegs[0], masks[i].vissprites[1] - masks[i].vissprites[0]); - // SRB2kart - skin->kartspeed = 5; - skin->kartweight = 5; - // - - skin->highresscale = FRACUNIT>>1; - - for (i = 0; i < sfx_skinsoundslot0; i++) - if (S_sfx[i].skinsound != -1) - skin->soundsid[S_sfx[i].skinsound] = i; -} - -// returns true if the skin name is found (loaded from pwad) -// warning return -1 if not found -INT32 R_SkinAvailable(const char *name) -{ - INT32 i; - - for (i = 0; i < numskins; i++) + for (; nummasks > 0; nummasks--) { - if (stricmp(skins[i].name,name)==0) - return i; + viewx = masks[nummasks - 1].viewx; + viewy = masks[nummasks - 1].viewy; + viewz = masks[nummasks - 1].viewz; + viewsector = masks[nummasks - 1].viewsector; + + R_DrawMaskedList(&heads[nummasks - 1]); + R_ClearDrawNodes(&heads[nummasks - 1]); } - return -1; + + free(heads); } - -// same thing but for followers: -INT32 R_FollowerAvailable(const char *name) -{ - INT32 i; - - for (i = 0; i < numfollowers; i++) - { - if (stricmp(followers[i].skinname,name)==0) - return i; - } - return -1; -} - -// network code calls this when a 'skin change' is received -boolean SetPlayerSkin(INT32 playernum, const char *skinname) -{ - INT32 i; - player_t *player = &players[playernum]; - - for (i = 0; i < numskins; i++) - { - // search in the skin list - if (stricmp(skins[i].name, skinname) == 0) - { - SetPlayerSkinByNum(playernum, i); - return true; - } - } - - if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Skin '%s' not found.\n"), skinname); - else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) skin '%s' not found\n"), playernum, player_names[playernum], skinname); - - SetPlayerSkinByNum(playernum, 0); - return false; -} - -// Again, same thing but for followers; -boolean SetPlayerFollower(INT32 playernum, const char *skinname) -{ - INT32 i; - player_t *player = &players[playernum]; - - for (i = 0; i < numfollowers; i++) - { - // search in the skin list - if (stricmp(followers[i].skinname, skinname) == 0) - { - SetFollower(playernum, i); - return true; - } - } - - if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found.\n"), skinname); - else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, M_GetText("Player %d (%s) follower '%s' not found\n"), playernum, player_names[playernum], skinname); - - SetFollower(playernum, -1); // reminder that -1 is nothing - return false; -} - -// Same as SetPlayerSkin, but uses the skin #. -// network code calls this when a 'skin change' is received -void SetPlayerSkinByNum(INT32 playernum, INT32 skinnum) -{ - player_t *player = &players[playernum]; - skin_t *skin = &skins[skinnum]; - if (skinnum >= 0 && skinnum < numskins) // Make sure it exists! - { - player->skin = skinnum; - if (player->mo) - player->mo->skin = skin; - - player->charflags = (UINT32)skin->flags; - - // SRB2kart - player->kartspeed = skin->kartspeed; - player->kartweight = skin->kartweight; - - /*if (!(cv_debug || devparm) && !(netgame || multiplayer || demo.playback || modeattacking)) - { - if (playernum == consoleplayer) - CV_StealthSetValue(&cv_playercolor, skin->prefcolor); - else if (playernum == displayplayers[1]) - CV_StealthSetValue(&cv_playercolor2, skin->prefcolor); - else if (playernum == displayplayers[2]) - CV_StealthSetValue(&cv_playercolor3, skin->prefcolor); - else if (playernum == displayplayers[3]) - CV_StealthSetValue(&cv_playercolor4, skin->prefcolor); - player->skincolor = skin->prefcolor; - if (player->mo) - player->mo->color = player->skincolor; - }*/ - - if (player->mo) - P_SetScale(player->mo, player->mo->scale); - - // for replays: We have changed our skin mid-game; let the game know so it can do the same in the replay! - demo_extradata[playernum] |= DXD_SKIN; - - return; - } - - if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Skin %d not found\n"), skinnum); - else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, "Player %d (%s) skin %d not found\n", playernum, player_names[playernum], skinnum); - SetPlayerSkinByNum(playernum, 0); // not found put the sonic skin -} - -// you get the drill, now we do the same for followers: -void SetFollower(INT32 playernum, INT32 skinnum) -{ - player_t *player = &players[playernum]; - mobj_t *bub; - mobj_t *tmp; - - player->followerready = true; // we are ready to perform follower related actions in the player thinker, now. - if (skinnum >= -1 && skinnum <= numfollowers) // Make sure it exists! - { - /* - We don't spawn the follower here since it'll be easier to handle all of it in the Player thinker itself. - However, we will despawn it right here if there's any to make it easy for the player thinker to replace it or delete it. - */ - if (player->follower && skinnum != player->followerskin) // this is also called when we change colour so don't respawn the follower unless we changed skins - { - - // Remove follower's possible hnext list (bubble) - bub = player->follower->hnext; - - while (bub && !P_MobjWasRemoved(bub)) - { - tmp = bub->hnext; - P_RemoveMobj(bub); - bub = tmp; - } - - P_RemoveMobj(player->follower); - P_SetTarget(&player->follower, NULL); - } - - player->followerskin = skinnum; - //CONS_Printf("Updated player follower num\n"); - - // for replays: We have changed our follower mid-game; let the game know so it can do the same in the replay! - demo_extradata[playernum] |= DXD_FOLLOWER; - - return; - } - - if (P_IsLocalPlayer(player)) - CONS_Alert(CONS_WARNING, M_GetText("Follower %d not found\n"), skinnum); - else if(server || IsPlayerAdmin(consoleplayer)) - CONS_Alert(CONS_WARNING, "Player %d (%s) follower %d not found\n", playernum, player_names[playernum], skinnum); - SetFollower(playernum, -1); // Not found, then set -1 (nothing) as our follower. -} - -// -// Add skins from a pwad, each skin preceded by 'S_SKIN' marker -// - -// Does the same is in w_wad, but check only for -// the first 6 characters (this is so we can have S_SKIN1, S_SKIN2.. -// for wad editors that don't like multiple resources of the same name) -// -static UINT16 W_CheckForSkinMarkerInPwad(UINT16 wadid, UINT16 startlump) -{ - UINT16 i; - const char *S_SKIN = "S_SKIN"; - lumpinfo_t *lump_p; - - // scan forward, start at - if (startlump < wadfiles[wadid]->numlumps) - { - lump_p = wadfiles[wadid]->lumpinfo + startlump; - for (i = startlump; i < wadfiles[wadid]->numlumps; i++, lump_p++) - if (memcmp(lump_p->name,S_SKIN,6)==0) - return i; - } - return INT16_MAX; // not found -} - -// -// Find skin sprites, sounds & optional status bar face, & add them -// -void R_AddSkins(UINT16 wadnum) -{ - UINT16 lump, lastlump = 0; - char *buf; - char *buf2; - char *stoken; - char *value; - size_t size; - skin_t *skin; - boolean hudname, realname; - - // - // search for all skin markers in pwad - // - - while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) - { - // advance by default - lastlump = lump + 1; - - if (numskins >= MAXSKINS) - { - CONS_Debug(DBG_RENDER, "ignored skin (%d skins maximum)\n", MAXSKINS); - continue; // so we know how many skins couldn't be added - } - buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lump); - - // for strtok - buf2 = malloc(size+1); - if (!buf2) - I_Error("R_AddSkins: No more free memory\n"); - M_Memcpy(buf2,buf,size); - buf2[size] = '\0'; - - // set defaults - skin = &skins[numskins]; - Sk_SetDefaultValue(skin); - skin->wadnum = wadnum; - hudname = realname = false; - // parse - stoken = strtok (buf2, "\r\n= "); - while (stoken) - { - if ((stoken[0] == '/' && stoken[1] == '/') - || (stoken[0] == '#'))// skip comments - { - stoken = strtok(NULL, "\r\n"); // skip end of line - goto next_token; // find the real next token - } - - value = strtok(NULL, "\r\n= "); - - if (!value) - I_Error("R_AddSkins: syntax error in S_SKIN lump# %d(%s) in WAD %s\n", lump, W_CheckNameForNumPwad(wadnum,lump), wadfiles[wadnum]->filename); - - if (!stricmp(stoken, "name")) - { - // the skin name must uniquely identify a single skin - // I'm lazy so if name is already used I leave the 'skin x' - // default skin name set in Sk_SetDefaultValue - if (R_SkinAvailable(value) == -1) - { - STRBUFCPY(skin->name, value); - strlwr(skin->name); - } - // I'm not lazy, so if the name is already used I make the name 'namex' - // using the default skin name's number set above - else - { - const size_t stringspace = - strlen(value) + sizeof (numskins) + 1; - char *value2 = Z_Malloc(stringspace, PU_STATIC, NULL); - snprintf(value2, stringspace, - "%s%d", value, numskins); - value2[stringspace - 1] = '\0'; - if (R_SkinAvailable(value2) == -1) - { - STRBUFCPY(skin->name, - value2); - strlwr(skin->name); - } - Z_Free(value2); - } - - // copy to hudname and fullname as a default. - if (!realname) - { - STRBUFCPY(skin->realname, skin->name); - for (value = skin->realname; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - } - if (!hudname) - { - STRBUFCPY(skin->hudname, skin->name); - strupr(skin->hudname); - for (value = skin->hudname; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - } - } - else if (!stricmp(stoken, "realname")) - { // Display name (eg. "Knuckles") - realname = true; - STRBUFCPY(skin->realname, value); - for (value = skin->realname; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - if (!hudname) - STRBUFCPY(skin->hudname, skin->realname); - } - else if (!stricmp(stoken, "hudname")) - { // Life icon name (eg. "K.T.E") - hudname = true; - STRBUFCPY(skin->hudname, value); - for (value = skin->hudname; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - if (!realname) - STRBUFCPY(skin->realname, skin->hudname); - } - - else if (!stricmp(stoken, "sprite")) - { - strupr(value); - strncpy(skin->sprite, value, sizeof skin->sprite); - } - else if (!stricmp(stoken, "facerank")) - { - strupr(value); - strncpy(skin->facerank, value, sizeof skin->facerank); - } - else if (!stricmp(stoken, "facewant")) - { - strupr(value); - strncpy(skin->facewant, value, sizeof skin->facewant); - } - else if (!stricmp(stoken, "facemmap")) - { - strupr(value); - strncpy(skin->facemmap, value, sizeof skin->facemmap); - } - else if (!stricmp(stoken, "rivals")) - { - size_t len = strlen(value); - size_t i; - char rivalname[SKINNAMESIZE] = ""; - UINT8 pos = 0; - UINT8 numrivals = 0; - - // Can't use strtok, because this function's already using it. - // Using it causes it to upset the saved pointer, - // corrupting the reading for the rest of the file. - - // So instead we get to crawl through the value, character by character, - // and write it down as we go, until we hit a comma or the end of the string. - // Yaaay. - - for (i = 0; i <= len; i++) - { - if (numrivals >= SKINRIVALS) - { - break; - } - - if (value[i] == ',' || i == len) - { - STRBUFCPY(skin->rivals[numrivals], rivalname); - strlwr(skin->rivals[numrivals]); - numrivals++; - - memset(rivalname, 0, sizeof (rivalname)); - pos = 0; - - continue; - } - - rivalname[pos] = value[i]; - pos++; - } - } - -#define FULLPROCESS(field) else if (!stricmp(stoken, #field)) skin->field = get_number(value); - // character type identification - FULLPROCESS(flags) -#undef FULLPROCESS - -#define GETKARTSTAT(field) \ - else if (!stricmp(stoken, #field)) \ - { \ - skin->field = atoi(value); \ - if (skin->field < 1) skin->field = 1; \ - if (skin->field > 9) skin->field = 9; \ - } - GETKARTSTAT(kartspeed) - GETKARTSTAT(kartweight) -#undef GETKARTSTAT - - // custom translation table - else if (!stricmp(stoken, "startcolor")) - skin->starttranscolor = atoi(value); - - else if (!stricmp(stoken, "prefcolor")) - skin->prefcolor = K_GetKartColorByName(value); - else if (!stricmp(stoken, "highresscale")) - skin->highresscale = FLOAT_TO_FIXED(atof(value)); - else - { - INT32 found = false; - sfxenum_t i; - // copy name of sounds that are remapped - // for this skin - for (i = 0; i < sfx_skinsoundslot0; i++) - { - if (!S_sfx[i].name) - continue; - if (S_sfx[i].skinsound != -1 - && !stricmp(S_sfx[i].name, - stoken + 2)) - { - skin->soundsid[S_sfx[i].skinsound] = - S_AddSoundFx(value+2, S_sfx[i].singularity, S_sfx[i].pitch, true); - found = true; - } - } - if (!found) - CONS_Debug(DBG_SETUP, "R_AddSkins: Unknown keyword '%s' in S_SKIN lump# %d (WAD %s)\n", stoken, lump, wadfiles[wadnum]->filename); - } -next_token: - stoken = strtok(NULL, "\r\n= "); - } - free(buf2); - - lump++; // if no sprite defined use spirte just after this one - if (skin->sprite[0] == '\0') - { - const char *csprname = W_CheckNameForNumPwad(wadnum, lump); - - // skip to end of this skin's frames - lastlump = lump; - while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),csprname,4)==0) - lastlump++; - // allocate (or replace) sprite frames, and set spritedef - R_AddSingleSpriteDef(csprname, &skin->spritedef, wadnum, lump, lastlump); - } - else - { - // search in the normal sprite tables - size_t name; - boolean found = false; - const char *sprname = skin->sprite; - for (name = 0;sprnames[name][0] != '\0';name++) - if (strncmp(sprnames[name], sprname, 4) == 0) - { - found = true; - skin->spritedef = sprites[name]; - } - - // not found so make a new one - // go through the entire current wad looking for our sprite - // don't just mass add anything beginning with our four letters. - // "HOODFACE" is not a sprite name. - if (!found) - { - UINT16 localllump = 0, lstart = UINT16_MAX, lend = UINT16_MAX; - const char *lname; - - while ((lname = W_CheckNameForNumPwad(wadnum,localllump))) - { - // If this is a valid sprite... - if (!memcmp(lname,sprname,4) && lname[4] && lname[5] && lname[5] >= '0' && lname[5] <= '8') - { - if (lstart == UINT16_MAX) - lstart = localllump; - // If already set do nothing - } - else - { - if (lstart != UINT16_MAX) - { - lend = localllump; - break; - } - // If not already set do nothing - } - ++localllump; - } - - R_AddSingleSpriteDef(sprname, &skin->spritedef, wadnum, lstart, lend); - } - - // I don't particularly care about skipping to the end of the used frames. - // We could be using frames from ANYWHERE in the current WAD file, including - // right before us, which is a terrible idea. - // So just let the function in the while loop take care of it for us. - } - - R_FlushTranslationColormapCache(); - - CONS_Printf(M_GetText("Added skin '%s'\n"), skin->name); -#ifdef SKINVALUES - skin_cons_t[numskins].value = numskins; - skin_cons_t[numskins].strvalue = skin->name; -#endif - - // Update the forceskin possiblevalues - Forceskin_cons_t[numskins+1].value = numskins; - Forceskin_cons_t[numskins+1].strvalue = skins[numskins].name; - - // add face graphics - ST_LoadFaceGraphics(skin->facerank, skin->facewant, skin->facemmap, numskins); - -#ifdef HWRENDER - if (rendermode == render_opengl) - HWR_AddPlayerMD2(numskins); -#endif - - numskins++; - } - return; -} - -#ifdef DELFILE -void R_DelSkins(UINT16 wadnum) -{ - UINT16 lump, lastlump = 0; - while ((lump = W_CheckForSkinMarkerInPwad(wadnum, lastlump)) != INT16_MAX) - { - if (skins[numskins].wadnum != wadnum) - break; - numskins--; - ST_UnLoadFaceGraphics(numskins); // only used by DELFILE - if (skins[numskins].sprite[0] != '\0') - { - const char *csprname = W_CheckNameForNumPwad(wadnum, lump); - - // skip to end of this skin's frames - lastlump = lump; - while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),csprname,4)==0) - lastlump++; - // allocate (or replace) sprite frames, and set spritedef - R_DelSingleSpriteDef(csprname, &skins[numskins].spritedef, wadnum, lump, lastlump); - } - else - { - // search in the normal sprite tables - size_t name; - boolean found = false; - const char *sprname = skins[numskins].sprite; - for (name = 0;sprnames[name][0] != '\0';name++) - if (strcmp(sprnames[name], sprname) == 0) - { - found = true; - skins[numskins].spritedef = sprites[name]; - } - - // not found so make a new one - if (!found) - R_DelSingleSpriteDef(sprname, &skins[numskins].spritedef, wadnum, 0, INT16_MAX); - - while (W_CheckNameForNumPwad(wadnum,lastlump) && memcmp(W_CheckNameForNumPwad(wadnum, lastlump),sprname,4)==0) - lastlump++; - } - CONS_Printf(M_GetText("Removed skin '%s'\n"), skins[numskins].name); - } -} -#endif diff --git a/src/r_things.h b/src/r_things.h index 94bd37656..f95cd5c9e 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -14,25 +14,27 @@ #ifndef __R_THINGS__ #define __R_THINGS__ -#include "sounds.h" #include "r_plane.h" +#include "r_picformats.h" +#include "r_portal.h" +#include "r_defs.h" +#include "r_skins.h" -// "Left" and "Right" character symbols for additional rotation functionality -#define ROT_L ('L' - '0') -#define ROT_R ('R' - '0') +// -------------- +// SPRITE LOADING +// -------------- -// number of sprite lumps for spritewidth,offset,topoffset lookup tables -// Fab: this is a hack : should allocate the lookup tables per sprite -#define MAXVISSPRITES 2048 // added 2-2-98 was 128 +#define FEETADJUST (4< 0 because we divide by this number. - INT32 vertlag; // not Vert from Neptunia lagging, this is for Z displacement lag Default is 6. Must be > 0 because we divide by this number. - INT32 bobamp; // Bob amplitude. Default is 4. - INT32 bobspeed; // Arbitrary modifier for bobbing speed, default is TICRATE*2 (70). - - // from there on out, everything is STATES to allow customization - // these are only set once when the action is performed and are then free to animate however they want. - - INT32 idlestate; // state when the player is at a standstill - INT32 followstate; // state when the player is moving - INT32 hurtstate; // state when the player is being hurt - INT32 winstate; // state when the player has won - INT32 losestate; // state when the player has lost - INT32 hitconfirmstate; // state for hit confirm - INT32 hitconfirmtime; // time to keep the above playing for -} follower_t; - -// ----------- -// NOT SKINS STUFF ! -// ----------- typedef enum { // actual cuts @@ -154,7 +111,7 @@ typedef enum SC_BOTTOM = 1<<1, // other flags SC_PRECIP = 1<<2, - //SC_LINKDRAW = 1<<3, -- 2.2 compat + SC_LINKDRAW = 1<<3, SC_FULLBRIGHT = 1<<4, SC_SEMIBRIGHT = 1<<5, SC_VFLIP = 1<<6, @@ -173,17 +130,19 @@ typedef struct vissprite_s struct vissprite_s *prev; struct vissprite_s *next; + // Bonus linkdraw pointer. + struct vissprite_s *linkdraw; + mobj_t *mobj; // for easy access INT32 x1, x2; fixed_t gx, gy; // for line side calculation - fixed_t gz, gzt; // global bottom/top for silhouette clipping - fixed_t pz, pzt; // physical bottom/top for sorting with 3D floors + fixed_t gz, gzt; // global bottom/top for silhouette clipping and sorting with 3D floors fixed_t startfrac; // horizontal position of x1 - fixed_t scale, sortscale; // sortscale only differs from scale for flat sprites - fixed_t scalestep; // only for flat sprites, 0 otherwise + fixed_t scale, sortscale; // sortscale only differs from scale for paper sprites and MF2_LINKDRAW + fixed_t scalestep; // only for paper sprites, 0 otherwise fixed_t paperoffset, paperdistance; // for paper sprites, offset/dist relative to the angle fixed_t xiscale; // negative if flipped @@ -195,7 +154,7 @@ typedef struct vissprite_s } shear; fixed_t texturemid; - lumpnum_t patch; + patch_t *patch; lighttable_t *colormap; // for color translation and shadow draw // maxbright frames as well @@ -211,8 +170,8 @@ typedef struct vissprite_s fixed_t xscale; // Precalculated top and bottom screen coords for the sprite. - fixed_t thingheight; // The actual height of the thing (for 3D floors) sector_t *sector; // The sector containing the thing. + fixed_t pt, pb; // plane heights, also for sorting against 3D floors INT16 sz, szt; spritecut_e cut; @@ -222,6 +181,12 @@ typedef struct vissprite_s INT32 dispoffset; // copy of info->dispoffset, affects ordering but not drawing } vissprite_t; +extern UINT32 visspritecount; + +// ---------- +// DRAW NODES +// ---------- + // A drawnode is something that points to a 3D floor, 3D side, or masked // middle texture. This is used for sorting with sprites. typedef struct drawnode_s @@ -236,27 +201,11 @@ typedef struct drawnode_s struct drawnode_s *prev; } drawnode_t; -extern INT32 numskins; -extern skin_t skins[MAXSKINS]; -extern INT32 numfollowers; -extern follower_t followers[MAXSKINS]; // again, use the same rules as skins, no reason not to. - -boolean SetPlayerSkin(INT32 playernum,const char *skinname); -void SetPlayerSkinByNum(INT32 playernum,INT32 skinnum); // Tails 03-16-2002 -INT32 R_SkinAvailable(const char *name); -void R_AddSkins(UINT16 wadnum); - -INT32 R_FollowerAvailable(const char *name); -boolean SetPlayerFollower(INT32 playernum,const char *skinname); -void SetFollower(INT32 playernum,INT32 skinnum); - -#ifdef DELFILE -void R_DelSkins(UINT16 wadnum); -#endif - void R_InitDrawNodes(void); -char *GetPlayerFacePic(INT32 skinnum); +// ----------------------- +// SPRITE FRAME CHARACTERS +// ----------------------- // Functions to go from sprite character ID to frame number // for 2.1 compatibility this still uses the old 'A' + frame code @@ -285,7 +234,7 @@ FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn) if (cn == '+') return '\\' - 'A'; // PK3 can't use backslash, so use + instead return cn - 'A'; #else - if (cn >= 'A' && cn <= 'Z') return cn - 'A'; + if (cn >= 'A' && cn <= 'Z') return (cn - 'A'); if (cn >= '0' && cn <= '9') return (cn - '0') + 26; if (cn >= 'a' && cn <= 'z') return (cn - 'a') + 36; if (cn == '!') return 62; @@ -294,9 +243,26 @@ FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Frame(char cn) #endif } -FUNCMATH FUNCINLINE static ATTRINLINE boolean R_ValidSpriteAngle(UINT8 rotation) +// "Left" and "Right" character symbols for additional rotation functionality +#define ROT_L 17 +#define ROT_R 18 + +FUNCMATH FUNCINLINE static ATTRINLINE char R_Rotation2Char(UINT8 rot) { - return ((rotation <= 8) || (rotation == ROT_L) || (rotation == ROT_R)); + if (rot <= 9) return '0' + rot; + if (rot <= 16) return 'A' + (rot - 10); + if (rot == ROT_L) return 'L'; + if (rot == ROT_R) return 'R'; + return '\xFF'; +} + +FUNCMATH FUNCINLINE static ATTRINLINE UINT8 R_Char2Rotation(char cn) +{ + if (cn >= '0' && cn <= '9') return (cn - '0'); + if (cn >= 'A' && cn <= 'G') return (cn - 'A') + 10; + if (cn == 'L') return ROT_L; + if (cn == 'R') return ROT_R; + return 255; } #endif //__R_THINGS__ diff --git a/src/s_sound.c b/src/s_sound.c index 9b49784ec..a7d45e160 100644 --- a/src/s_sound.c +++ b/src/s_sound.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,23 +11,13 @@ /// \file s_sound.c /// \brief System-independent sound and music routines -#ifdef MUSSERV -#include -struct musmsg -{ - long msg_type; - char msg_text[12]; -}; -extern INT32 msg_id; -#endif - #include "doomdef.h" #include "doomstat.h" #include "command.h" #include "g_game.h" #include "m_argv.h" #include "r_main.h" // R_PointToAngle2() used to calc stereo sep. -#include "r_things.h" // for skins +#include "r_skins.h" // for skins #include "i_system.h" #include "i_sound.h" #include "s_sound.h" @@ -36,11 +26,10 @@ extern INT32 msg_id; #include "d_main.h" #include "r_sky.h" // skyflatnum #include "p_local.h" // camera info +#include "fastcmp.h" #include "m_misc.h" // for tunes command - -#ifdef HAVE_BLUA +#include "m_cond.h" // for conditionsets #include "lua_hook.h" // MusicChange hook -#endif #ifdef HW3SOUND // 3D Sound Interface @@ -49,86 +38,83 @@ extern INT32 msg_id; static INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *vol, INT32 *sep, INT32 *pitch, sfxinfo_t *sfxinfo); #endif -CV_PossibleValue_t soundvolume_cons_t[] = {{0, "MIN"}, {31, "MAX"}, {0, NULL}}; +CV_PossibleValue_t soundvolume_cons_t[] = {{0, "MIN"}, {MAX_VOLUME, "MAX"}, {0, NULL}}; static void SetChannelsNum(void); static void Command_Tunes_f(void); static void Command_RestartAudio_f(void); // Sound system toggles -#ifndef NO_MIDI -static void GameMIDIMusic_OnChange(void); -#endif static void GameSounds_OnChange(void); static void GameDigiMusic_OnChange(void); static void PlayMusicIfUnfocused_OnChange(void); static void PlaySoundIfUnfocused_OnChange(void); -// commands for music and sound servers -#ifdef MUSSERV -consvar_t musserver_cmd = {"musserver_cmd", "musserver", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t musserver_arg = {"musserver_arg", "-t 20 -f -u 0 -i music.dta", CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif -#ifdef SNDSERV -consvar_t sndserver_cmd = {"sndserver_cmd", "llsndserv", CV_SAVE, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t sndserver_arg = {"sndserver_arg", "-quiet", CV_SAVE, NULL, 0, NULL, NULL, 0, 0, NULL}; +#ifdef HAVE_OPENMPT +static void ModFilter_OnChange(void); #endif +static lumpnum_t S_GetMusicLumpNum(const char *mname); + +static boolean S_CheckQueue(void); + #if defined (_WINDOWS) && !defined (SURROUND) //&& defined (_X86_) #define SURROUND #endif -#if defined (_WIN32_WCE) || defined (DC) || defined(GP2X) -consvar_t cv_samplerate = {"samplerate", "11025", 0, CV_Unsigned, NULL, 11025, NULL, NULL, 0, 0, NULL}; //Alam: For easy hacking? -#elif defined(_PSP) || defined(_WINDOWS) -consvar_t cv_samplerate = {"samplerate", "44100", 0, CV_Unsigned, NULL, 44100, NULL, NULL, 0, 0, NULL}; //Alam: For easy hacking? -#elif defined(_WII) -consvar_t cv_samplerate = {"samplerate", "32000", 0, CV_Unsigned, NULL, 32000, NULL, NULL, 0, 0, NULL}; //Alam: For easy hacking? +#ifdef _WINDOWS +consvar_t cv_samplerate = CVAR_INIT ("samplerate", "44100", 0, CV_Unsigned, NULL); //Alam: For easy hacking? #else -consvar_t cv_samplerate = {"samplerate", "22050", 0, CV_Unsigned, NULL, 22050, NULL, NULL, 0, 0, NULL}; //Alam: For easy hacking? +consvar_t cv_samplerate = CVAR_INIT ("samplerate", "22050", 0, CV_Unsigned, NULL); //Alam: For easy hacking? #endif // stereo reverse -consvar_t stereoreverse = {"stereoreverse", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t stereoreverse = CVAR_INIT ("stereoreverse", "Off", CV_SAVE, CV_OnOff, NULL); // if true, all sounds are loaded at game startup -static consvar_t precachesound = {"precachesound", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +static consvar_t precachesound = CVAR_INIT ("precachesound", "Off", CV_SAVE, CV_OnOff, NULL); // actual general (maximum) sound & music volume, saved into the config -consvar_t cv_soundvolume = {"soundvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_digmusicvolume = {"digmusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -#ifndef NO_MIDI -consvar_t cv_midimusicvolume = {"midimusicvolume", "18", CV_SAVE, soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif -// number of channels available -#if defined (_WIN32_WCE) || defined (DC) || defined (PSP) || defined(GP2X) -consvar_t cv_numChannels = {"snd_channels", "8", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL}; -#else -consvar_t cv_numChannels = {"snd_channels", "64", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum, 0, NULL, NULL, 0, 0, NULL}; -#endif +consvar_t cv_soundvolume = CVAR_INIT ("soundvolume", "50", CV_SAVE, soundvolume_cons_t, NULL); +consvar_t cv_digmusicvolume = CVAR_INIT ("musicvolume", "50", CV_SAVE, soundvolume_cons_t, NULL); -consvar_t surround = {"surround", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -//consvar_t cv_resetmusic = {"resetmusic", "No", CV_SAVE|CV_NOSHOWHELP, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +// number of channels available +consvar_t cv_numChannels = CVAR_INIT ("snd_channels", "64", CV_SAVE|CV_CALL, CV_Unsigned, SetChannelsNum); + +consvar_t surround = CVAR_INIT ("surround", "Off", CV_SAVE, CV_OnOff, NULL); + +static void Captioning_OnChange(void) +{ + S_ResetCaptions(); + if (cv_closedcaptioning.value) + S_StartSound(NULL, sfx_menu1); +} + +consvar_t cv_closedcaptioning = CVAR_INIT ("closedcaptioning", "Off", CV_SAVE|CV_CALL, CV_OnOff, Captioning_OnChange); // Sound system toggles, saved into the config -consvar_t cv_gamedigimusic = {"digimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange, 0, NULL, NULL, 0, 0, NULL}; -#ifndef NO_MIDI -consvar_t cv_gamemidimusic = {"midimusic", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameMIDIMusic_OnChange, 0, NULL, NULL, 0, 0, NULL}; -#endif -consvar_t cv_gamesounds = {"sounds", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameSounds_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_playmusicifunfocused = {"playmusicifunfocused", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, PlayMusicIfUnfocused_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_playsoundifunfocused = {"playsoundsifunfocused", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, PlaySoundIfUnfocused_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_gamedigimusic = CVAR_INIT ("music", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameDigiMusic_OnChange); +consvar_t cv_gamesounds = CVAR_INIT ("sounds", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, GameSounds_OnChange); static CV_PossibleValue_t music_resync_threshold_cons_t[] = { {0, "MIN"}, {1000, "MAX"}, - - {0} + {0, NULL} }; -consvar_t cv_music_resync_threshold = {"music_resync_threshold", "100", CV_SAVE|CV_CALL, music_resync_threshold_cons_t, I_UpdateSongLagThreshold, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_music_resync_powerups_only = {"music_resync_powerups_only", "No", CV_SAVE|CV_CALL, CV_YesNo, I_UpdateSongLagConditions, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_music_resync_threshold = CVAR_INIT ("music_resync_threshold", "100", CV_SAVE|CV_CALL, music_resync_threshold_cons_t, I_UpdateSongLagThreshold); +consvar_t cv_music_resync_powerups_only = CVAR_INIT ("music_resync_powerups_only", "No", CV_SAVE|CV_CALL, CV_YesNo, I_UpdateSongLagConditions); + +// Window focus sound sytem toggles +consvar_t cv_playmusicifunfocused = CVAR_INIT ("playmusicifunfocused", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, PlayMusicIfUnfocused_OnChange); +consvar_t cv_playsoundifunfocused = CVAR_INIT ("playsoundsifunfocused", "No", CV_SAVE|CV_CALL|CV_NOINIT, CV_YesNo, PlaySoundIfUnfocused_OnChange); + +#ifdef HAVE_OPENMPT +openmpt_module *openmpt_mhandle = NULL; + +static CV_PossibleValue_t interpolationfilter_cons_t[] = {{0, "Default"}, {1, "None"}, {2, "Linear"}, {4, "Cubic"}, {8, "Windowed sinc"}, {0, NULL}}; +consvar_t cv_modfilter = CVAR_INIT ("modfilter", "0", CV_SAVE|CV_CALL, interpolationfilter_cons_t, ModFilter_OnChange); +#endif #define S_MAX_VOLUME 127 @@ -164,23 +150,24 @@ consvar_t cv_music_resync_powerups_only = {"music_resync_powerups_only", "No", C // percent attenuation from front to back #define S_IFRACVOL 30 -typedef struct -{ - // sound information (if null, channel avail.) - sfxinfo_t *sfxinfo; - - // origin of sound - const void *origin; - - // handle of the sound being played - INT32 handle; - -} channel_t; - // the set of channels available static channel_t *channels = NULL; static INT32 numofchannels = 0; +caption_t closedcaptions[NUMCAPTIONS]; + +void S_ResetCaptions(void) +{ + UINT8 i; + for (i = 0; i < NUMCAPTIONS; i++) + { + closedcaptions[i].c = NULL; + closedcaptions[i].s = NULL; + closedcaptions[i].t = 0; + closedcaptions[i].b = 0; + } +} + // // Internals. // @@ -273,53 +260,22 @@ void S_RegisterSoundStuff(void) CV_RegisterVar(&stereoreverse); CV_RegisterVar(&precachesound); -#ifdef SNDSERV - CV_RegisterVar(&sndserver_cmd); - CV_RegisterVar(&sndserver_arg); -#endif -#ifdef MUSSERV - CV_RegisterVar(&musserver_cmd); - CV_RegisterVar(&musserver_arg); -#endif CV_RegisterVar(&surround); CV_RegisterVar(&cv_samplerate); - //CV_RegisterVar(&cv_resetmusic); + CV_RegisterVar(&cv_playsoundifunfocused); + CV_RegisterVar(&cv_playmusicifunfocused); CV_RegisterVar(&cv_gamesounds); CV_RegisterVar(&cv_gamedigimusic); -#ifndef NO_MIDI - CV_RegisterVar(&cv_gamemidimusic); -#endif - - CV_RegisterVar(&cv_playmusicifunfocused); - CV_RegisterVar(&cv_playsoundifunfocused); CV_RegisterVar(&cv_music_resync_threshold); CV_RegisterVar(&cv_music_resync_powerups_only); +#ifdef HAVE_OPENMPT + CV_RegisterVar(&cv_modfilter); +#endif + COM_AddCommand("tunes", Command_Tunes_f); COM_AddCommand("restartaudio", Command_RestartAudio_f); - - -#if defined (macintosh) && !defined (HAVE_SDL) // mp3 playlist stuff - { - INT32 i; - for (i = 0; i < PLAYLIST_LENGTH; i++) - { - user_songs[i].name = malloc(7); - if (!user_songs[i].name) - I_Error("No more free memory for mp3 playlist"); - sprintf(user_songs[i].name, "song%d%d",i/10,i%10); - user_songs[i].defaultvalue = malloc(sizeof (char)); - if (user_songs[i].defaultvalue) - I_Error("No more free memory for blank mp3 playerlist"); - *user_songs[i].defaultvalue = 0; - user_songs[i].flags = CV_SAVE; - user_songs[i].PossibleValue = NULL; - CV_RegisterVar(&user_songs[i]); - } - CV_RegisterVar(&play_mode); - } -#endif } static void SetChannelsNum(void) @@ -353,6 +309,8 @@ static void SetChannelsNum(void) // Free all channels for use for (i = 0; i < numofchannels; i++) channels[i].sfxinfo = 0; + + S_ResetCaptions(); } @@ -378,6 +336,18 @@ lumpnum_t S_GetSfxLumpNum(sfxinfo_t *sfx) return W_GetNumForName("dsthok"); } +// +// Sound Status +// + +boolean S_SoundDisabled(void) +{ + return ( + sound_disabled || + ( window_notinfocus && ! cv_playsoundifunfocused.value ) + ); +} + // Stop all sounds, load level info, THEN start sounds. void S_StopSounds(void) { @@ -395,6 +365,8 @@ void S_StopSounds(void) for (cnum = 0; cnum < numofchannels; cnum++) if (channels[cnum].sfxinfo) S_StopChannel(cnum); + + S_ResetCaptions(); } void S_StopSoundByID(void *origin, sfxenum_t sfx_id) @@ -443,9 +415,97 @@ void S_StopSoundByNum(sfxenum_t sfxnum) } } +void S_StartCaption(sfxenum_t sfx_id, INT32 cnum, UINT16 lifespan) +{ + UINT8 i, set, moveup, start; + boolean same = false; + sfxinfo_t *sfx; + + if (!cv_closedcaptioning.value) // no captions at all + return; + + // check for bogus sound # + // I_Assert(sfx_id >= 0); -- allowing sfx_None; this shouldn't be allowed directly if S_StartCaption is ever exposed to Lua by itself + I_Assert(sfx_id < NUMSFX); + + sfx = &S_sfx[sfx_id]; + + if (sfx->caption[0] == '/') // no caption for this one + return; + + start = ((closedcaptions[0].s && (closedcaptions[0].s-S_sfx == sfx_None)) ? 1 : 0); + + if (sfx_id) + { + for (i = start; i < (set = NUMCAPTIONS-1); i++) + { + same = ((sfx == closedcaptions[i].s) || (closedcaptions[i].s && fastcmp(sfx->caption, closedcaptions[i].s->caption))); + if (same) + { + set = i; + break; + } + } + } + else + { + set = 0; + same = (closedcaptions[0].s == sfx); + } + + moveup = 255; + + if (!same) + { + for (i = start; i < set; i++) + { + if (!(closedcaptions[i].c || closedcaptions[i].s) || (sfx->priority >= closedcaptions[i].s->priority)) + { + set = i; + if (closedcaptions[i].s && (sfx->priority >= closedcaptions[i].s->priority)) + moveup = i; + break; + } + } + for (i = NUMCAPTIONS-1; i > set; i--) + { + if (sfx == closedcaptions[i].s) + { + closedcaptions[i].c = NULL; + closedcaptions[i].s = NULL; + closedcaptions[i].t = 0; + closedcaptions[i].b = 0; + } + } + } + + if (moveup != 255) + { + for (i = moveup; i < NUMCAPTIONS-1; i++) + { + if (!(closedcaptions[i].c || closedcaptions[i].s)) + break; + } + for (; i > set; i--) + { + closedcaptions[i].c = closedcaptions[i-1].c; + closedcaptions[i].s = closedcaptions[i-1].s; + closedcaptions[i].t = closedcaptions[i-1].t; + closedcaptions[i].b = closedcaptions[i-1].b; + } + } + + closedcaptions[set].c = ((cnum == -1) ? NULL : &channels[cnum]); + closedcaptions[set].s = sfx; + closedcaptions[set].t = lifespan; + closedcaptions[set].b = 2; // bob +} + void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) { + const INT32 initial_volume = volume; INT32 sep, pitch, priority, cnum; + const sfxenum_t actual_id = sfx_id; sfxinfo_t *sfx; const boolean reverse = (stereoreverse.value ^ encoremode); const mobj_t *origin = (const mobj_t *)origin_p; @@ -460,7 +520,7 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume) mobj_t *listenmobj3 = NULL; mobj_t *listenmobj4 = NULL; - if (sound_disabled || !sound_started) + if (S_SoundDisabled() || !sound_started) return; // Don't want a sound? Okay then... @@ -751,6 +811,9 @@ dontplay3: ) sep = (~sep) & 255; + // Handle closed caption input. + S_StartCaption(actual_id, cnum, MAXCAPTIONTICS); + // Assigns the handle to one of the channels in the // mix/output buffer. channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); @@ -800,68 +863,20 @@ dontplay4: ) sep = (~sep) & 255; + // Handle closed caption input. + S_StartCaption(actual_id, cnum, MAXCAPTIONTICS); + // Assigns the handle to one of the channels in the // mix/output buffer. + channels[cnum].volume = initial_volume; channels[cnum].handle = I_StartSound(sfx_id, volume, sep, pitch, priority, cnum); } void S_StartSound(const void *origin, sfxenum_t sfx_id) { - if (sound_disabled) + if (S_SoundDisabled()) return; - if (mariomode) // Sounds change in Mario mode! - { - switch (sfx_id) - { -// case sfx_altow1: -// case sfx_altow2: -// case sfx_altow3: -// case sfx_altow4: -// sfx_id = sfx_mario8; -// break; - case sfx_thok: - sfx_id = sfx_mario7; - break; - case sfx_pop: - sfx_id = sfx_mario5; - break; - case sfx_jump: - sfx_id = sfx_mario6; - break; - case sfx_shield: - sfx_id = sfx_mario3; - break; - case sfx_itemup: - sfx_id = sfx_mario4; - break; -// case sfx_tink: -// sfx_id = sfx_mario1; -// break; -// case sfx_cgot: -// sfx_id = sfx_mario9; -// break; -// case sfx_lose: -// sfx_id = sfx_mario2; -// break; - default: - break; - } - } - if (maptol & TOL_XMAS) // Some sounds change for xmas - { - switch (sfx_id) - { - case sfx_ideya: - case sfx_nbmper: - case sfx_ncitem: - case sfx_ngdone: - ++sfx_id; - default: - break; - } - } - // the volume is handled 8 bits #ifdef HW3SOUND if (hws_mode != HWS_DEFAULT_MODE) @@ -902,9 +917,6 @@ void S_StopSound(void *origin) // static INT32 actualsfxvolume; // check for change through console static INT32 actualdigmusicvolume; -#ifndef NO_MIDI -static INT32 actualmidimusicvolume; -#endif void S_UpdateSounds(void) { @@ -927,14 +939,10 @@ void S_UpdateSounds(void) memset(&listener4, 0, sizeof(listener_t)); // Update sound/music volumes, if changed manually at console - if (actualsfxvolume != cv_soundvolume.value) + if (actualsfxvolume != cv_soundvolume.value * USER_VOLUME_SCALE) S_SetSfxVolume (cv_soundvolume.value); - if (actualdigmusicvolume != cv_digmusicvolume.value) + if (actualdigmusicvolume != cv_digmusicvolume.value * USER_VOLUME_SCALE) S_SetDigMusicVolume (cv_digmusicvolume.value); -#ifndef NO_MIDI - if (actualmidimusicvolume != cv_midimusicvolume.value) - S_SetMIDIMusicVolume (cv_midimusicvolume.value); -#endif // We're done now, if we're not in a level. if (gamestate != GS_LEVEL) @@ -944,9 +952,7 @@ void S_UpdateSounds(void) I_UpdateMumble(NULL, listener); #endif - // Stop cutting FMOD out. WE'RE sick of it. - I_UpdateSound(); - return; + goto notinlevel; } if (dedicated || sound_disabled) @@ -999,8 +1005,7 @@ void S_UpdateSounds(void) if (hws_mode != HWS_DEFAULT_MODE) { HW3S_UpdateSources(); - I_UpdateSound(); - return; + goto notinlevel; } #endif @@ -1067,7 +1072,7 @@ void S_UpdateSounds(void) if (I_SoundIsPlaying(c->handle)) { // initialize parameters - volume = 255; // 8 bits internal volume precision + volume = c->volume; // 8 bits internal volume precision pitch = NORM_PITCH; sep = NORM_SEP; @@ -1164,22 +1169,46 @@ void S_UpdateSounds(void) } } +notinlevel: I_UpdateSound(); } +void S_UpdateClosedCaptions(void) +{ + UINT8 i; + boolean gamestopped = (paused || P_AutoPause()); + for (i = 0; i < NUMCAPTIONS; i++) // update captions + { + if (!closedcaptions[i].s) + continue; + + if (i == 0 && (closedcaptions[0].s-S_sfx == sfx_None) && gamestopped) + continue; + + if (!(--closedcaptions[i].t)) + { + closedcaptions[i].c = NULL; + closedcaptions[i].s = NULL; + } + else if (closedcaptions[i].c && !I_SoundIsPlaying(closedcaptions[i].c->handle)) + { + closedcaptions[i].c = NULL; + if (closedcaptions[i].t > CAPTIONFADETICS) + closedcaptions[i].t = CAPTIONFADETICS; + } + } +} + void S_SetSfxVolume(INT32 volume) { - if (volume < 0 || volume > 31) - CONS_Alert(CONS_WARNING, "sfxvolume should be between 0-31\n"); - - CV_SetValue(&cv_soundvolume, volume&0x1F); - actualsfxvolume = cv_soundvolume.value; // check for change of var + CV_SetValue(&cv_soundvolume, volume); + actualsfxvolume = cv_soundvolume.value * USER_VOLUME_SCALE; #ifdef HW3SOUND hws_mode == HWS_DEFAULT_MODE ? I_SetSfxVolume(volume&0x1F) : HW3S_SetSfxVolume(volume&0x1F); #else // now hardware volume - I_SetSfxVolume(volume&0x1F); + I_SetSfxVolume(volume); #endif } @@ -1194,7 +1223,6 @@ void S_ClearSfx(void) static void S_StopChannel(INT32 cnum) { - INT32 i; channel_t *c = &channels[cnum]; if (c->sfxinfo) @@ -1203,17 +1231,12 @@ static void S_StopChannel(INT32 cnum) if (I_SoundIsPlaying(c->handle)) I_StopSound(c->handle); - // check to see - // if other channels are playing the sound - for (i = 0; i < numofchannels; i++) - if (cnum != i && c->sfxinfo == channels[i].sfxinfo) - break; - // degrade usefulness of sound data c->sfxinfo->usefulness--; - c->sfxinfo = 0; } + + c->origin = NULL; } // @@ -1374,15 +1397,12 @@ INT32 S_AdjustSoundParams(const mobj_t *listener, const mobj_t *source, INT32 *v } // volume calculation - if (approx_dist < S_CLOSE_DIST) - { - // SfxVolume is now hardware volume - *vol = 255; // not snd_SfxVolume - } - else + /* not sure if it should be > (no =), but this matches the old behavior */ + if (approx_dist >= S_CLOSE_DIST) { // distance effect - *vol = (15 * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)) / S_ATTENUATOR; + INT32 n = (15 * ((S_CLIPPING_DIST - approx_dist)>>FRACBITS)); + *vol = FixedMul(*vol * FRACUNIT / 255, n) / S_ATTENUATOR; } if (r_splitscreen) @@ -1540,21 +1560,21 @@ void S_InitSfxChannels(INT32 sfxVolume) #ifdef MUSICSLOT_COMPATIBILITY const char *compat_special_music_slots[16] = { - "titles", // 1036 title screen - "read_m", // 1037 intro - "lclear", // 1038 level clear - "invinc", // 1039 invincibility - "shoes", // 1040 super sneakers - "minvnc", // 1041 Mario invincibility - "drown", // 1042 drowning - "gmover", // 1043 game over - "xtlife", // 1044 extra life - "contsc", // 1045 continue screen - "supers", // 1046 Super Sonic - "chrsel", // 1047 character select - "credit", // 1048 credits - "racent", // 1049 Race Results - "stjr", // 1050 Sonic Team Jr. Presents + "_title", // 1036 title screen + "_intro", // 1037 intro + "_clear", // 1038 level clear + "_inv", // 1039 invincibility + "_shoes", // 1040 super sneakers + "_minv", // 1041 Mario invincibility + "_drown", // 1042 drowning + "_gover", // 1043 game over + "_1up", // 1044 extra life + "_conti", // 1045 continue screen + "_super", // 1046 Super Sonic + "_chsel", // 1047 character select + "_creds", // 1048 credits + "_inter", // 1049 Race Results + "_stjr", // 1050 Sonic Team Jr. Presents "" }; #endif @@ -1572,166 +1592,225 @@ static boolean queue_looping; static UINT32 queue_position; static UINT32 queue_fadeinms; +static tic_t pause_starttic; + /// ------------------------ /// Music Definitions /// ------------------------ -musicdef_t *musicdefstart = NULL; // First music definition +musicdef_t *musicdefstart = NULL; struct cursongcredit cursongcredit; // Currently displayed song credit info +int musicdef_volume; -// -// search for music definition in wad -// -static UINT16 W_CheckForMusicDefInPwad(UINT16 wadid) -{ - UINT16 i; - lumpinfo_t *lump_p; +static boolean +MusicDefError +( + alerttype_t level, + const char * description, + const char * field, + lumpnum_t lumpnum, + int line +){ + const wadfile_t * wad = wadfiles[WADFILENUM (lumpnum)]; + const lumpinfo_t * lump = &wad->lumpinfo[LUMPNUM (lumpnum)]; - lump_p = wadfiles[wadid]->lumpinfo; - for (i = 0; i < wadfiles[wadid]->numlumps; i++, lump_p++) - if (memcmp(lump_p->name, "MUSICDEF", 8) == 0) - return i; + CONS_Alert(level, + va("%%s|%%s: %s (line %%d)\n", description), + wad->filename, + lump->fullname, + field, + line + ); - return INT16_MAX; // not found + return false; } -void S_LoadMusicDefs(UINT16 wadnum) -{ - UINT16 lump; - char *buf; - char *buf2; - char *stoken; +static boolean +ReadMusicDefFields +( + lumpnum_t lumpnum, + int line, + char * stoken, + musicdef_t ** defp +){ + musicdef_t *def; + char *value; - size_t size; - musicdef_t *def, *prev; - UINT16 line = 1; // for better error msgs + char *textline; - lump = W_CheckForMusicDefInPwad(wadnum); - if (lump == INT16_MAX) - return; - - buf = W_CacheLumpNumPwad(wadnum, lump, PU_CACHE); - size = W_LumpLengthPwad(wadnum, lump); - - // for strtok - buf2 = malloc(size+1); - if (!buf2) - I_Error("S_LoadMusicDefs: No more free memory\n"); - M_Memcpy(buf2,buf,size); - buf2[size] = '\0'; - - def = prev = NULL; - - stoken = strtok (buf2, "\r\n "); - // Find music def - while (stoken) + if (!stricmp(stoken, "lump")) { - /*if ((stoken[0] == '/' && stoken[1] == '/') - || (stoken[0] == '#')) // skip comments + value = strtok(NULL, " "); + if (!value) { - stoken = strtok(NULL, "\r\n"); // skip end of line - if (def) - stoken = strtok(NULL, "\r\n= "); - else - stoken = strtok(NULL, "\r\n "); - line++; - } - else*/ if (!stricmp(stoken, "lump")) - { - value = strtok(NULL, "\r\n "); - - if (!value) - { - CONS_Alert(CONS_WARNING, "MUSICDEF: Lump '%s' is missing name. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); - stoken = strtok(NULL, "\r\n"); // skip end of line - goto skip_lump; - } - - // No existing musicdefs - if (!musicdefstart) - { - musicdefstart = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); - STRBUFCPY(musicdefstart->name, value); - strlwr(musicdefstart->name); - def = musicdefstart; - //CONS_Printf("S_LoadMusicDefs: Initialized musicdef w/ song '%s'\n", def->name); - } - else - { - def = musicdefstart; - - // Search if this is a replacement - //CONS_Printf("S_LoadMusicDefs: Searching for song replacement...\n"); - while (def) - { - if (!stricmp(def->name, value)) - { - //CONS_Printf("S_LoadMusicDefs: Found song replacement '%s'\n", def->name); - break; - } - - prev = def; - def = def->next; - } - - // Nothing found, add to the end. - if (!def) - { - def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); - STRBUFCPY(def->name, value); - strlwr(def->name); - if (prev != NULL) - prev->next = def; - //CONS_Printf("S_LoadMusicDefs: Added song '%s'\n", def->name); - } - } - -skip_lump: - stoken = strtok(NULL, "\r\n "); - line++; + return MusicDefError(CONS_WARNING, + "Field '%'s is missing name.", + stoken, lumpnum, line); } else { - value = strtok(NULL, "\r\n= "); + musicdef_t **tail = &musicdefstart; - if (!value) + // Search if this is a replacement + while (*tail) { - CONS_Alert(CONS_WARNING, "MUSICDEF: Field '%s' is missing value. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); - stoken = strtok(NULL, "\r\n"); // skip end of line - goto skip_field; + if (!stricmp((*tail)->name, value)) + { + break; + } + + tail = &(*tail)->next; } + // Nothing found, add to the end. + if (!(*tail)) + { + def = Z_Calloc(sizeof (musicdef_t), PU_STATIC, NULL); + + STRBUFCPY(def->name, value); + strlwr(def->name); + def->volume = DEFAULT_MUSICDEF_VOLUME; + + (*tail) = def; + } + + (*defp) = (*tail); + } + } + else + { + value = strtok(NULL, ""); + + if (value) + { + // Find the equals sign. + value = strchr(value, '='); + } + + if (!value) + { + return MusicDefError(CONS_WARNING, + "Field '%s' is missing value.", + stoken, lumpnum, line); + } + else + { + def = (*defp); + if (!def) { - CONS_Alert(CONS_ERROR, "MUSICDEF: No music definition before field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); - free(buf2); - return; + return MusicDefError(CONS_ERROR, + "No music definition before field '%s'.", + stoken, lumpnum, line); } + // Skip the equals sign. + value++; + + // Now skip funny whitespace. + value += strspn(value, "\t "); + + textline = value; + + /* based ignored lumps */ if (!stricmp(stoken, "usage")) { #if 0 // Ignore for now - STRBUFCPY(def->usage, value); - for (value = def->usage; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - //CONS_Printf("S_LoadMusicDefs: Set usage to '%s'\n", def->usage); + STRBUFCPY(def->usage, textline); #endif } else if (!stricmp(stoken, "source")) { - STRBUFCPY(def->source, value); - for (value = def->source; *value; value++) - if (*value == '_') *value = ' '; // turn _ into spaces. - //CONS_Printf("S_LoadMusicDefs: Set source to '%s'\n", def->source); + STRBUFCPY(def->source, textline); + } else if (!stricmp(stoken, "volume")) { + def->volume = atoi(textline); } else { - CONS_Alert(CONS_WARNING, "MUSICDEF: Invalid field '%s'. (file %s, line %d)\n", stoken, wadfiles[wadnum]->filename, line); + MusicDefError(CONS_WARNING, + "Unknown field '%s'.", + stoken, lumpnum, line); } - -skip_field: - stoken = strtok(NULL, "\r\n= "); - line++; } } - free(buf2); - return; + return true; +} + +static void S_LoadMusicDefLump(lumpnum_t lumpnum) +{ + char *lump; + char *musdeftext; + size_t size; + + char *lf; + char *stoken; + + size_t nlf; + size_t ncr; + + musicdef_t *def = NULL; + int line = 1; // for better error msgs + + lump = W_CacheLumpNum(lumpnum, PU_CACHE); + size = W_LumpLength(lumpnum); + + // Null-terminated MUSICDEF lump. + musdeftext = malloc(size+1); + if (!musdeftext) + I_Error("S_LoadMusicDefs: No more free memory for the parser\n"); + M_Memcpy(musdeftext, lump, size); + musdeftext[size] = '\0'; + + // Find music def + stoken = musdeftext; + for (;;) + { + lf = strpbrk(stoken, "\r\n"); + if (lf) + { + if (*lf == '\n') + nlf = 1; + else + nlf = 0; + *lf++ = '\0';/* now we can delimit to here */ + } + + stoken = strtok(stoken, " "); + if (stoken) + { + if (! ReadMusicDefFields(lumpnum, line, stoken, &def)) + break; + } + + if (lf) + { + do + { + line += nlf; + ncr = strspn(lf, "\r");/* skip CR */ + lf += ncr; + nlf = strspn(lf, "\n"); + lf += nlf; + } + while (nlf || ncr) ; + + stoken = lf;/* now the next nonempty line */ + } + else + break;/* EOF */ + } + + free(musdeftext); +} + +void S_LoadMusicDefs(UINT16 wad) +{ + const lumpnum_t wadnum = wad << 16; + + UINT16 lump = 0; + + while (( lump = W_CheckNumForNamePwad("MUSICDEF", wad, lump) ) != INT16_MAX) + { + S_LoadMusicDefLump(wadnum | lump); + + lump++; + } } // @@ -1785,14 +1864,9 @@ boolean S_DigMusicDisabled(void) return digital_disabled; } -boolean S_MIDIMusicDisabled(void) -{ - return midi_disabled; // SRB2Kart: defined as "true" w/ NO_MIDI -} - boolean S_MusicDisabled(void) { - return (midi_disabled && digital_disabled); + return digital_disabled; } boolean S_MusicPlaying(void) @@ -1805,6 +1879,13 @@ boolean S_MusicPaused(void) return I_SongPaused(); } +boolean S_MusicNotInFocus(void) +{ + return ( + ( window_notinfocus && ! cv_playmusicifunfocused.value ) + ); +} + musictype_t S_MusicType(void) { return I_SongType(); @@ -1828,12 +1909,9 @@ boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping) return (boolean)mname[0]; } -boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi) +boolean S_MusicExists(const char *mname) { - return ( - (checkDigi ? W_CheckNumForName(va("O_%s", mname)) != LUMPERROR : false) - || (checkMIDI ? W_CheckNumForName(va("D_%s", mname)) != LUMPERROR : false) - ); + return W_CheckNumForName(va("O_%s", mname)) != LUMPERROR; } /// ------------------------ @@ -1874,10 +1952,307 @@ UINT32 S_GetMusicPosition(void) return I_GetSongPosition(); } +/// ------------------------ +/// Music Stacking (Jingles) +/// In this section: mazmazz doesn't know how to do dynamic arrays or struct pointers! +/// ------------------------ + +char music_stack_nextmusname[7]; +boolean music_stack_noposition = false; +UINT32 music_stack_fadeout = 0; +UINT32 music_stack_fadein = 0; +static musicstack_t *music_stacks = NULL; +static musicstack_t *last_music_stack = NULL; + +void S_SetStackAdjustmentStart(void) +{ + if (!pause_starttic) + pause_starttic = gametic; +} + +void S_AdjustMusicStackTics(void) +{ + if (pause_starttic) + { + musicstack_t *mst; + for (mst = music_stacks; mst; mst = mst->next) + mst->tic += gametic - pause_starttic; + pause_starttic = 0; + } +} + +static void S_ResetMusicStack(void) +{ + musicstack_t *mst, *mst_next; + for (mst = music_stacks; mst; mst = mst_next) + { + mst_next = mst->next; + Z_Free(mst); + } + music_stacks = last_music_stack = NULL; +} + +static void S_RemoveMusicStackEntry(musicstack_t *entry) +{ + musicstack_t *mst; + for (mst = music_stacks; mst; mst = mst->next) + { + if (mst == entry) + { + // Remove ourselves from the chain and link + // prev and next together + + if (mst->prev) + mst->prev->next = mst->next; + else + music_stacks = mst->next; + + if (mst->next) + mst->next->prev = mst->prev; + else + last_music_stack = mst->prev; + + break; + } + } + Z_Free(entry); +} + +static void S_RemoveMusicStackEntryByStatus(UINT16 status) +{ + musicstack_t *mst, *mst_next; + + if (!status) + return; + + for (mst = music_stacks; mst; mst = mst_next) + { + mst_next = mst->next; + if (mst->status == status) + S_RemoveMusicStackEntry(mst); + } +} + +static void S_AddMusicStackEntry(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status) +{ + musicstack_t *mst, *new_mst; + + // if the first entry is empty, force master onto it + if (!music_stacks) + { + music_stacks = Z_Calloc(sizeof (*mst), PU_MUSIC, NULL); + strncpy(music_stacks->musname, (status == JT_MASTER ? mname : (S_CheckQueue() ? queue_name : mapmusname)), 7); + music_stacks->musflags = (status == JT_MASTER ? mflags : (S_CheckQueue() ? queue_flags : mapmusflags)); + music_stacks->looping = (status == JT_MASTER ? looping : (S_CheckQueue() ? queue_looping : true)); + music_stacks->position = (status == JT_MASTER ? position : (S_CheckQueue() ? queue_position : S_GetMusicPosition())); + music_stacks->tic = gametic; + music_stacks->status = JT_MASTER; + music_stacks->mlumpnum = S_GetMusicLumpNum(music_stacks->musname); + music_stacks->noposition = S_CheckQueue(); + + if (status == JT_MASTER) + return; // we just added the user's entry here + } + + // look for an empty slot to park ourselves + for (mst = music_stacks; mst->next; mst = mst->next); + + // create our new entry + new_mst = Z_Calloc(sizeof (*new_mst), PU_MUSIC, NULL); + strncpy(new_mst->musname, mname, 7); + new_mst->musname[6] = 0; + new_mst->musflags = mflags; + new_mst->looping = looping; + new_mst->position = position; + new_mst->tic = gametic; + new_mst->status = status; + new_mst->mlumpnum = S_GetMusicLumpNum(new_mst->musname); + new_mst->noposition = false; + + mst->next = new_mst; + new_mst->prev = mst; + new_mst->next = NULL; + last_music_stack = new_mst; +} + +static musicstack_t *S_GetMusicStackEntry(UINT16 status, boolean fromfirst, INT16 startindex) +{ + musicstack_t *mst, *start_mst = NULL, *mst_next; + + // if the first entry is empty, force master onto it + // fixes a memory corruption bug + if (!music_stacks && status != JT_MASTER) + S_AddMusicStackEntry(mapmusname, mapmusflags, true, S_GetMusicPosition(), JT_MASTER); + + if (startindex >= 0) + { + INT16 i = 0; + for (mst = music_stacks; mst && i <= startindex; mst = mst->next, i++) + start_mst = mst; + } + else + start_mst = (fromfirst ? music_stacks : last_music_stack); + + for (mst = start_mst; mst; mst = mst_next) + { + mst_next = (fromfirst ? mst->next : mst->prev); + + if (!status || mst->status == status) + { + if (P_EvaluateMusicStatus(mst->status, mst->musname)) + { + if (!S_MusicExists(mst->musname)) // paranoia + S_RemoveMusicStackEntry(mst); // then continue + else + return mst; + } + else + S_RemoveMusicStackEntry(mst); // then continue + } + } + + return NULL; +} + +void S_RetainMusic(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status) +{ + musicstack_t *mst; + + if (!status) // we use this as a null indicator, don't push + { + CONS_Alert(CONS_ERROR, "Music stack entry must have a nonzero status.\n"); + return; + } + else if (status == JT_MASTER) // enforce only one JT_MASTER + { + for (mst = music_stacks; mst; mst = mst->next) + { + if (mst->status == JT_MASTER) + { + CONS_Alert(CONS_ERROR, "Music stack can only have one JT_MASTER entry.\n"); + return; + } + } + } + else // remove any existing status + S_RemoveMusicStackEntryByStatus(status); + + S_AddMusicStackEntry(mname, mflags, looping, position, status); +} + +boolean S_RecallMusic(UINT16 status, boolean fromfirst) +{ + UINT32 newpos = 0; + boolean mapmuschanged = false; + musicstack_t *result; + musicstack_t *entry = Z_Calloc(sizeof (*result), PU_MUSIC, NULL); + + if (status) + result = S_GetMusicStackEntry(status, fromfirst, -1); + else + result = S_GetMusicStackEntry(JT_NONE, false, -1); + + if (result && !S_MusicExists(result->musname)) + { + Z_Free(entry); + return false; // music doesn't exist, so don't do anything + } + + // make a copy of result, since we make modifications to our copy + if (result) + { + *entry = *result; + strncpy(entry->musname, result->musname, 7); + } + + // no result, just grab mapmusname + if (!result || !entry->musname[0] || ((status == JT_MASTER || (music_stacks ? !music_stacks->status : false)) && !entry->status)) + { + strncpy(entry->musname, mapmusname, 7); + entry->musflags = mapmusflags; + entry->looping = true; + entry->position = mapmusposition; + entry->tic = gametic; + entry->status = JT_MASTER; + entry->mlumpnum = S_GetMusicLumpNum(entry->musname); + entry->noposition = false; // don't set this until we do the mapmuschanged check, below. Else, this breaks some resumes. + } + + if (entry->status == JT_MASTER) + { + mapmuschanged = strnicmp(entry->musname, mapmusname, 7); + if (mapmuschanged) + { + strncpy(entry->musname, mapmusname, 7); + entry->musflags = mapmusflags; + entry->looping = true; + entry->position = mapmusposition; + entry->tic = gametic; + entry->status = JT_MASTER; + entry->mlumpnum = S_GetMusicLumpNum(entry->musname); + entry->noposition = true; + } + S_ResetMusicStack(); + } + else if (!entry->status) + { + Z_Free(entry); + return false; + } + + if (strncmp(entry->musname, S_MusicName(), 7)) // don't restart music if we're already playing it + { + if (music_stack_fadeout) + S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, music_stack_fadeout, 0); + else + { + S_ChangeMusicEx(entry->musname, entry->musflags, entry->looping, 0, 0, music_stack_fadein); + + if (!entry->noposition && !music_stack_noposition) // HACK: Global boolean to toggle position resuming, e.g., de-superize + { + UINT32 poslapse = 0; + + // To prevent the game from jumping past the end of the music, we need + // to check if we can get the song's length. Otherwise, if the lapsed resume time goes + // over a LOOPPOINT, mixer_sound.c will be unable to calculate the new resume position. + if (S_GetMusicLength()) + poslapse = (UINT32)((float)(gametic - entry->tic)/(float)TICRATE*(float)MUSICRATE); + + newpos = entry->position + poslapse; + } + + // If the newly recalled music lumpnum does not match the lumpnum that we stored in stack, + // then discard the new position. That way, we will not recall an invalid position + // when the music is replaced or digital/MIDI is toggled. + if (newpos > 0 && S_MusicPlaying() && S_GetMusicLumpNum(entry->musname) == entry->mlumpnum) + S_SetMusicPosition(newpos); + else + { + S_StopFadingMusic(); + S_SetInternalMusicVolume(100); + } + } + music_stack_noposition = false; + music_stack_fadeout = 0; + music_stack_fadein = JINGLEPOSTFADE; + } + + Z_Free(entry); + return true; +} + /// ------------------------ /// Music Playback /// ------------------------ +static lumpnum_t S_GetMusicLumpNum(const char *mname) +{ + if (S_MusicExists(mname)) + return W_GetNumForName(va("o_%s", mname)); + else + return LUMPERROR; +} + static boolean S_LoadMusic(const char *mname) { lumpnum_t mlumpnum; @@ -1886,45 +2261,17 @@ static boolean S_LoadMusic(const char *mname) if (S_MusicDisabled()) return false; - if (!S_DigMusicDisabled() && S_DigExists(mname)) - mlumpnum = W_GetNumForName(va("o_%s", mname)); - else if (!S_MIDIMusicDisabled() && S_MIDIExists(mname)) - mlumpnum = W_GetNumForName(va("d_%s", mname)); - else if (S_DigMusicDisabled() && S_DigExists(mname)) + mlumpnum = S_GetMusicLumpNum(mname); + + if (mlumpnum == LUMPERROR) { - CONS_Alert(CONS_NOTICE, "Digital music is disabled!\n"); - return false; - } - else if (S_MIDIMusicDisabled() && S_MIDIExists(mname)) - { -#ifdef NO_MIDI - CONS_Alert(CONS_ERROR, "A MIDI music lump %.6s was found,\nbut SRB2Kart does not support MIDI output.\nWe apologise for the inconvenience.\n", mname); -#else - CONS_Alert(CONS_NOTICE, "MIDI music is disabled!\n"); -#endif - return false; - } - else - { - CONS_Alert(CONS_ERROR, M_GetText("Music lump %.6s not found!\n"), mname); + CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded: lump not found!\n", mname); return false; } // load & register it mdata = W_CacheLumpNum(mlumpnum, PU_MUSIC); -#ifdef MUSSERV - if (msg_id != -1) - { - struct musmsg msg_buffer; - - msg_buffer.msg_type = 6; - memset(msg_buffer.msg_text, 0, sizeof (msg_buffer.msg_text)); - sprintf(msg_buffer.msg_text, "d_%s", mname); - msgsnd(msg_id, (struct msgbuf*)&msg_buffer, sizeof (msg_buffer.msg_text), IPC_NOWAIT); - } -#endif - if (I_LoadSong(mdata, W_LumpLength(mlumpnum))) { strncpy(music_name, mname, 7); @@ -1933,7 +2280,10 @@ static boolean S_LoadMusic(const char *mname) return true; } else + { + CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded: engine failure!\n", mname); return false; + } } static void S_UnloadMusic(void) @@ -1955,6 +2305,8 @@ static void S_UnloadMusic(void) static boolean S_PlayMusic(boolean looping, UINT32 fadeinms) { + //musicdef_t *def; + if (S_MusicDisabled()) return false; @@ -1963,14 +2315,28 @@ static boolean S_PlayMusic(boolean looping, UINT32 fadeinms) if ((!fadeinms && !I_PlaySong(looping)) || (fadeinms && !I_FadeInPlaySong(fadeinms, looping))) { + CONS_Alert(CONS_ERROR, "Music %.6s could not be played: engine failure!\n", music_name); S_UnloadMusic(); return false; } +#if 0 + /* set loop point from MUSICDEF */ + for (def = musicdefstart; def; def = def->next) + { + if (strcasecmp(def->name, music_name) == 0) + { + if (def->loop_ms) + S_SetMusicLoopPoint(def->loop_ms); + break; + } + } +#endif + S_InitMusicVolume(); // switch between digi and sequence volume - if (window_notinfocus && !cv_playmusicifunfocused.value) - I_PauseSong(); + if (S_MusicNotInFocus()) + S_PauseAudio(); return true; } @@ -1984,6 +2350,11 @@ static void S_QueueMusic(const char *mmusic, UINT16 mflags, boolean looping, UIN queue_fadeinms = fadeinms; } +static boolean S_CheckQueue(void) +{ + return queue_name[0]; +} + static void S_ClearQueue(void) { queue_name[0] = queue_flags = queue_looping = queue_position = queue_fadeinms = 0; @@ -1999,20 +2370,16 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 { char newmusic[7]; -#if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined(GP2X) - S_ClearSfx(); -#endif - if (S_MusicDisabled() || demo.rewinding // Don't mess with music while rewinding! || demo.title) // SRB2Kart: Demos don't interrupt title screen music return; strncpy(newmusic, mmusic, 7); -#ifdef HAVE_BLUA + if(LUAh_MusicChange(music_name, newmusic, &mflags, &looping, &position, &prefadems, &fadeinms)) return; -#endif + newmusic[6] = 0; // No Music (empty string) @@ -2025,7 +2392,8 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 return; } - if (prefadems && S_MusicPlaying()) // queue music change for after fade // allow even if the music is the same + if (prefadems) // queue music change for after fade // allow even if the music is the same + // && S_MusicPlaying() // Let the delay happen even if we're not playing music { CONS_Debug(DBG_DETAILED, "Now fading out song %s\n", music_name); S_QueueMusic(newmusic, mflags, looping, position, fadeinms); @@ -2039,20 +2407,27 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 S_StopMusic(); if (!S_LoadMusic(newmusic)) - { - CONS_Alert(CONS_ERROR, "Music %.6s could not be loaded!\n", newmusic); return; - } music_flags = mflags; music_looping = looping; - if (!S_PlayMusic(looping, fadeinms)) - { - CONS_Alert(CONS_ERROR, "Music %.6s could not be played!\n", newmusic); - return; + musicdef_volume = DEFAULT_MUSICDEF_VOLUME; + + { + musicdef_t *def; + for (def = musicdefstart; def; def = def->next) + { + if (strcasecmp(def->name, music_name) == 0) + { + musicdef_volume = def->volume; + } + } } + if (!S_PlayMusic(looping, fadeinms)) + return; + if (position) I_SetSongPosition(position); @@ -2070,8 +2445,7 @@ void S_ChangeMusicEx(const char *mmusic, UINT16 mflags, boolean looping, UINT32 } } -void -S_ChangeMusicSpecial (const char *mmusic) +void S_ChangeMusicSpecial (const char *mmusic) { if (cv_resetspecialmusic.value) S_ChangeMusic(mmusic, MUSIC_FORCERESET, true); @@ -2095,6 +2469,22 @@ void S_StopMusic(void) S_SpeedMusic(1.0f); I_StopSong(); S_UnloadMusic(); // for now, stopping also means you unload the song + + if (cv_closedcaptioning.value) + { + if (closedcaptions[0].s-S_sfx == sfx_None) + { + if (gamestate != wipegamestate) + { + closedcaptions[0].c = NULL; + closedcaptions[0].s = NULL; + closedcaptions[0].t = 0; + closedcaptions[0].b = 0; + } + else + closedcaptions[0].t = CAPTIONFADETICS; + } + } } // @@ -2105,21 +2495,18 @@ void S_PauseAudio(void) if (I_SongPlaying() && !I_SongPaused()) I_PauseSong(); - // pause cd music -#if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) - I_PauseCD(); -#else - I_StopCD(); -#endif + S_SetStackAdjustmentStart(); } void S_ResumeAudio(void) { + if (S_MusicNotInFocus()) + return; + if (I_SongPlaying() && I_SongPaused()) I_ResumeSong(); - // resume cd music - I_ResumeCD(); + S_AdjustMusicStackTics(); } void S_DisableSound(void) @@ -2140,50 +2527,14 @@ void S_EnableSound(void) } } -void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume) +void S_SetMusicVolume(INT32 digvolume) { if (digvolume < 0) digvolume = cv_digmusicvolume.value; -#ifdef NO_MIDI - (void)seqvolume; -#else - if (seqvolume < 0) - seqvolume = cv_midimusicvolume.value; -#endif - - if (digvolume < 0 || digvolume > 31) - CONS_Alert(CONS_WARNING, "digmusicvolume should be between 0-31\n"); - CV_SetValue(&cv_digmusicvolume, digvolume&31); - actualdigmusicvolume = cv_digmusicvolume.value; //check for change of var - -#ifndef NO_MIDI - if (seqvolume < 0 || seqvolume > 31) - CONS_Alert(CONS_WARNING, "midimusicvolume should be between 0-31\n"); - CV_SetValue(&cv_midimusicvolume, seqvolume&31); - actualmidimusicvolume = cv_midimusicvolume.value; //check for change of var -#endif - -#ifdef DJGPPDOS - digvolume = 31; -#ifndef NO_MIDI - seqvolume = 31; -#endif -#endif - - switch(I_SongType()) - { -#ifndef NO_MIDI - case MU_MID: - //case MU_MOD: - //case MU_GME: - I_SetMusicVolume(seqvolume&31); - break; -#endif - default: - I_SetMusicVolume(digvolume&31); - break; - } + CV_SetValue(&cv_digmusicvolume, digvolume); + actualdigmusicvolume = cv_digmusicvolume.value * USER_VOLUME_SCALE; + I_SetMusicVolume(digvolume); } void @@ -2250,8 +2601,10 @@ boolean S_FadeOutStopMusic(UINT32 ms) // Kills playing sounds at start of level, // determines music if any, changes music. // -void S_Start(void) +void S_StartEx(boolean reset) { + (void)reset; + if (mapmusflags & MUSIC_RELOADRESET) { strncpy(mapmusname, mapheaderinfo[gamemap-1]->musname, 7); @@ -2261,13 +2614,17 @@ void S_Start(void) mapmusresume = 0; } - //if (cv_resetmusic.value) // Starting ambience should always be restarted - S_StopMusic(); + S_StopMusic(); // Starting ambience should always be restarted, if playing. if (leveltime < (starttime + (TICRATE/2))) // SRB2Kart S_ChangeMusicEx((encoremode ? "estart" : "kstart"), 0, false, mapmusposition, 0, 0); else S_ChangeMusicEx(mapmusname, mapmusflags, true, mapmusposition, 0, 0); + + S_ResetMusicStack(); + music_stack_noposition = false; + music_stack_fadeout = 0; + music_stack_fadein = JINGLEPOSTFADE; } static void Command_Tunes_f(void) @@ -2360,11 +2717,7 @@ static void Command_RestartAudio_f(void) // These must be called or no sound and music until manually set. I_SetSfxVolume(cv_soundvolume.value); -#ifdef NO_MIDI - S_SetMusicVolume(cv_digmusicvolume.value, -1); -#else - S_SetMusicVolume(cv_digmusicvolume.value, cv_midimusicvolume.value); -#endif + S_SetMusicVolume(cv_digmusicvolume.value); S_StartSound(NULL, sfx_strpst); @@ -2381,11 +2734,16 @@ void GameSounds_OnChange(void) if (sound_disabled) { - if (!( cv_playsoundifunfocused.value && window_notinfocus )) - S_EnableSound(); + sound_disabled = false; + I_StartupSound(); // will return early if initialised + S_InitSfxChannels(cv_soundvolume.value); + S_StartSound(NULL, sfx_strpst); } else - S_DisableSound(); + { + sound_disabled = true; + S_StopSounds(); + } } void GameDigiMusic_OnChange(void) @@ -2398,81 +2756,25 @@ void GameDigiMusic_OnChange(void) if (digital_disabled) { digital_disabled = false; + I_StartupSound(); // will return early if initialised I_InitMusic(); - S_StopMusic(); + if (Playing()) + { P_RestoreMusic(&players[consoleplayer]); - else - S_ChangeMusicInternal("titles", looptitle); + } + else if (S_MusicExists("_title")) + { + S_ChangeMusicInternal("_title", looptitle); + } } else { digital_disabled = true; - if (S_MusicType() != MU_MID) - { - if (midi_disabled) - S_StopMusic(); - else - { - char mmusic[7]; - UINT16 mflags; - boolean looping; - - if (S_MusicInfo(mmusic, &mflags, &looping) && S_MIDIExists(mmusic)) - { - S_StopMusic(); - S_ChangeMusic(mmusic, mflags, looping); - } - else - S_StopMusic(); - } - } + S_StopMusic(); } } -#ifndef NO_MIDI -void GameMIDIMusic_OnChange(void) -{ - if (M_CheckParm("-nomusic") || M_CheckParm("-noaudio")) - return; - else if (M_CheckParm("-nomidimusic")) - return; - - if (midi_disabled) - { - midi_disabled = false; - I_InitMusic(); - if (Playing()) - P_RestoreMusic(&players[consoleplayer]); - else - S_ChangeMusicInternal("titles", looptitle); - } - else - { - midi_disabled = true; - if (S_MusicType() == MU_MID) - { - if (digital_disabled) - S_StopMusic(); - else - { - char mmusic[7]; - UINT16 mflags; - boolean looping; - - if (S_MusicInfo(mmusic, &mflags, &looping) && S_DigExists(mmusic)) - { - S_StopMusic(); - S_ChangeMusic(mmusic, mflags, looping); - } - else - S_StopMusic(); - } - } - } -} -#endif - static void PlayMusicIfUnfocused_OnChange(void) { if (window_notinfocus) @@ -2497,3 +2799,11 @@ static void PlaySoundIfUnfocused_OnChange(void) S_EnableSound(); } } + +#ifdef HAVE_OPENMPT +void ModFilter_OnChange(void) +{ + if (openmpt_mhandle) + openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value); +} +#endif diff --git a/src/s_sound.h b/src/s_sound.h index c433aa974..80a53fb3e 100644 --- a/src/s_sound.h +++ b/src/s_sound.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -20,18 +20,28 @@ #include "command.h" #include "tables.h" // angle_t +#ifdef HAVE_OPENMPT +#include "libopenmpt/libopenmpt.h" +extern openmpt_module *openmpt_mhandle; +#endif + // mask used to indicate sound origin is player item pickup #define PICKUP_SOUND 0x8000 +// +#define SOUND_VOLUME_RANGE 256 +#define MAX_SOUND_VOLUME 255 + +#define DEFAULT_MUSICDEF_VOLUME ( 100 / VOLUME_DIVIDER ) + extern consvar_t stereoreverse; -extern consvar_t cv_soundvolume, cv_digmusicvolume;//, cv_midimusicvolume; -extern consvar_t cv_numChannels; +extern consvar_t cv_soundvolume, cv_closedcaptioning, cv_digmusicvolume; + extern consvar_t surround; -//extern consvar_t cv_resetmusic; +extern consvar_t cv_numChannels; + extern consvar_t cv_gamedigimusic; -#ifndef NO_MIDI -extern consvar_t cv_gamemidimusic; -#endif + extern consvar_t cv_gamesounds; extern consvar_t cv_playmusicifunfocused; extern consvar_t cv_playsoundifunfocused; @@ -39,27 +49,11 @@ extern consvar_t cv_playsoundifunfocused; extern consvar_t cv_music_resync_threshold; extern consvar_t cv_music_resync_powerups_only; -#ifdef SNDSERV -extern consvar_t sndserver_cmd, sndserver_arg; -#endif -#ifdef MUSSERV -extern consvar_t musserver_cmd, musserver_arg; +#ifdef HAVE_OPENMPT +extern consvar_t cv_modfilter; #endif extern CV_PossibleValue_t soundvolume_cons_t[]; -//part of i_cdmus.c -extern consvar_t cd_volume, cdUpdate; - -#if defined (macintosh) && !defined (HAVE_SDL) -typedef enum -{ - music_normal, - playlist_random, - playlist_normal -} playmode_t; - -extern consvar_t play_mode; -#endif typedef enum { @@ -77,6 +71,37 @@ typedef struct { angle_t angle; } listener_t; +typedef struct +{ + // sound information (if null, channel avail.) + sfxinfo_t *sfxinfo; + + // origin of sound + const void *origin; + + // initial volume of sound, which is applied after distance and direction + INT32 volume; + + // handle of the sound being played + INT32 handle; + +} channel_t; + +typedef struct { + channel_t *c; + sfxinfo_t *s; + UINT16 t; + UINT8 b; +} caption_t; + +#define NUMCAPTIONS 8 +#define MAXCAPTIONTICS (2*TICRATE) +#define CAPTIONFADETICS 20 + +extern caption_t closedcaptions[NUMCAPTIONS]; +void S_StartCaption(sfxenum_t sfx_id, INT32 cnum, UINT16 lifespan); +void S_ResetCaptions(void); + // register sound vars and commands at game startup void S_RegisterSoundStuff(void); @@ -92,13 +117,20 @@ void S_InitSfxChannels(INT32 sfxVolume); // void S_StopSounds(void); void S_ClearSfx(void); -void S_Start(void); +void S_StartEx(boolean reset); +#define S_Start() S_StartEx(false) // // Basically a W_GetNumForName that adds "ds" at the beginning of the string. Returns a lumpnum. // lumpnum_t S_GetSfxLumpNum(sfxinfo_t *sfx); +// +// Sound Status +// + +boolean S_SoundDisabled(void); + // // Start sound for thing at using from sounds.h // @@ -115,16 +147,16 @@ void S_StopSound(void *origin); // boolean S_DigMusicDisabled(void); -boolean S_MIDIMusicDisabled(void); boolean S_MusicDisabled(void); boolean S_MusicPlaying(void); boolean S_MusicPaused(void); +boolean S_MusicNotInFocus(void); musictype_t S_MusicType(void); const char *S_MusicName(void); + +boolean S_MusicExists(const char *mname); boolean S_MusicInfo(char *mname, UINT16 *mflags, boolean *looping); -boolean S_MusicExists(const char *mname, boolean checkMIDI, boolean checkDigi); -#define S_DigExists(a) S_MusicExists(a, false, true) -#define S_MIDIExists(a) S_MusicExists(a, true, false) + // // Music Effects @@ -139,6 +171,7 @@ typedef struct musicdef_s char name[7]; //char usage[256]; char source[256]; + int volume; struct musicdef_s *next; } musicdef_t; @@ -151,6 +184,7 @@ extern struct cursongcredit } cursongcredit; extern musicdef_t *musicdefstart; +extern int musicdef_volume; void S_LoadMusicDefs(UINT16 wadnum); void S_InitMusicDefs(void); @@ -175,6 +209,35 @@ boolean S_SetMusicPosition(UINT32 position); // Get Position of Music UINT32 S_GetMusicPosition(void); +// +// Music Stacking (Jingles) +// + +typedef struct musicstack_s +{ + char musname[7]; + UINT16 musflags; + boolean looping; + UINT32 position; + tic_t tic; + UINT16 status; + lumpnum_t mlumpnum; + boolean noposition; // force music stack resuming from zero (like music_stack_noposition) + + struct musicstack_s *prev; + struct musicstack_s *next; +} musicstack_t; + +extern char music_stack_nextmusname[7]; +extern boolean music_stack_noposition; +extern UINT32 music_stack_fadeout; +extern UINT32 music_stack_fadein; + +void S_SetStackAdjustmentStart(void); +void S_AdjustMusicStackTics(void); +void S_RetainMusic(const char *mname, UINT16 mflags, boolean looping, UINT32 position, UINT16 status); +boolean S_RecallMusic(UINT16 status, boolean fromfirst); + // // Music Playback // @@ -228,14 +291,14 @@ boolean S_FadeOutStopMusic(UINT32 ms); // Updates music & sounds // void S_UpdateSounds(void); +void S_UpdateClosedCaptions(void); FUNCMATH fixed_t S_CalculateSoundDistance(fixed_t px1, fixed_t py1, fixed_t pz1, fixed_t px2, fixed_t py2, fixed_t pz2); void S_SetSfxVolume(INT32 volume); -void S_SetMusicVolume(INT32 digvolume, INT32 seqvolume); -#define S_SetDigMusicVolume(a) S_SetMusicVolume(a,-1) -#define S_SetMIDIMusicVolume(a) S_SetMusicVolume(-1,a) -#define S_InitMusicVolume() S_SetMusicVolume(-1,-1) +void S_SetMusicVolume(INT32 digvolume); +#define S_SetDigMusicVolume S_SetMusicVolume +#define S_InitMusicVolume() S_SetMusicVolume(-1) INT32 S_OriginPlaying(void *origin); INT32 S_IdPlaying(sfxenum_t id); diff --git a/src/screen.c b/src/screen.c index 651c9f481..6e5eda3cc 100644 --- a/src/screen.c +++ b/src/screen.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -28,6 +28,10 @@ #include "d_main.h" #include "d_clisrv.h" #include "f_finale.h" +#include "i_sound.h" // closed captions +#include "s_sound.h" // ditto +#include "g_game.h" // ditto +#include "p_local.h" // P_AutoPause() #if defined (USEASM) && !defined (NORUSEASM)//&& (!defined (_MSC_VER) || (_MSC_VER <= 1200)) @@ -37,47 +41,45 @@ // -------------------------------------------- // assembly or c drawer routines for 8bpp/16bpp // -------------------------------------------- -void (*wallcolfunc)(void); // new wall column drawer to draw posts >128 high -void (*colfunc)(void); // standard column, up to 128 high posts +void (*colfunc)(void); +void (*colfuncs[COLDRAWFUNC_MAX])(void); -void (*basecolfunc)(void); -void (*fuzzcolfunc)(void); // standard fuzzy effect column drawer -void (*transcolfunc)(void); // translation column drawer -void (*shadecolfunc)(void); // smokie test.. -void (*spanfunc)(void); // span drawer, use a 64x64 tile -void (*splatfunc)(void); // span drawer w/ transparency -void (*basespanfunc)(void); // default span func for color mode -void (*transtransfunc)(void); // translucent translated column drawer -void (*twosmultipatchfunc)(void); // for cols with transparent pixels -void (*twosmultipatchtransfunc)(void); // for cols with transparent pixels AND translucency +void (*spanfunc)(void); +void (*spanfuncs[SPANDRAWFUNC_MAX])(void); +void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); // ------------------ // global video state // ------------------ viddef_t vid; INT32 setmodeneeded; //video mode change needed if > 0 (the mode number to set + 1) +UINT8 setrenderneeded = 0; static CV_PossibleValue_t scr_depth_cons_t[] = {{8, "8 bits"}, {16, "16 bits"}, {24, "24 bits"}, {32, "32 bits"}, {0, NULL}}; static CV_PossibleValue_t shittyscreen_cons_t[] = {{0, "Okay"}, {1, "Shitty"}, {2, "Extra Shitty"}, {0, NULL}}; //added : 03-02-98: default screen mode, as loaded/saved in config -#ifdef WII -consvar_t cv_scr_width = {"scr_width", "640", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_scr_height = {"scr_height", "480", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -#else -consvar_t cv_scr_width = {"scr_width", "1280", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_scr_height = {"scr_height", "800", CV_SAVE, CV_Unsigned, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_scr_depth = {"scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_scr_width = CVAR_INIT ("scr_width", "640", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_scr_height = CVAR_INIT ("scr_height", "400", CV_SAVE, CV_Unsigned, NULL); +consvar_t cv_scr_depth = CVAR_INIT ("scr_depth", "16 bits", CV_SAVE, scr_depth_cons_t, NULL); +consvar_t cv_renderview = CVAR_INIT ("renderview", "On", 0, CV_OnOff, NULL); +consvar_t cv_vhseffect = CVAR_INIT ("vhspause", "On", CV_SAVE, CV_OnOff, NULL); +consvar_t cv_shittyscreen = CVAR_INIT ("televisionsignal", "Okay", CV_NOSHOWHELP, shittyscreen_cons_t, NULL); + +static void SCR_ActuallyChangeRenderer(void); +static CV_PossibleValue_t cv_renderer_t[] = { + {1, "Software"}, +#ifdef HWRENDER + {2, "OpenGL"}, #endif -consvar_t cv_renderview = {"renderview", "On", 0, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_vhseffect = {"vhspause", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_shittyscreen = {"televisionsignal", "Okay", CV_NOSHOWHELP, shittyscreen_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; + {0, NULL} +}; +consvar_t cv_renderer = CVAR_INIT ("renderer", "Software", CV_SAVE|CV_NOLUA|CV_CALL, cv_renderer_t, SCR_ChangeRenderer); -static void SCR_ChangeFullscreen (void); +static void SCR_ChangeFullscreen(void); -consvar_t cv_fullscreen = {"fullscreen", "Yes", CV_SAVE|CV_CALL, CV_YesNo, SCR_ChangeFullscreen, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_fullscreen = CVAR_INIT ("fullscreen", "Yes", CV_SAVE|CV_CALL, CV_YesNo, SCR_ChangeFullscreen); // ========================================================================= // SCREEN VARIABLES @@ -100,54 +102,75 @@ boolean R_3DNow = false; boolean R_MMXExt = false; boolean R_SSE2 = false; - -void SCR_SetMode(void) +void SCR_SetDrawFuncs(void) { - if (dedicated) - return; - - if (!setmodeneeded || WipeInAction) - return; // should never happen and don't change it during a wipe, BAD! - - VID_SetMode(--setmodeneeded); - - V_SetPalette(0); - // // setup the right draw routines for either 8bpp or 16bpp // if (true)//vid.bpp == 1) //Always run in 8bpp. todo: remove all 16bpp code? { - spanfunc = basespanfunc = R_DrawSpan_8; - splatfunc = R_DrawSplat_8; - transcolfunc = R_DrawTranslatedColumn_8; - transtransfunc = R_DrawTranslatedTranslucentColumn_8; + colfuncs[BASEDRAWFUNC] = R_DrawColumn_8; + spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8; + + colfunc = colfuncs[BASEDRAWFUNC]; + spanfunc = spanfuncs[BASEDRAWFUNC]; + + colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8; + colfuncs[COLDRAWFUNC_TRANS] = R_DrawTranslatedColumn_8; + colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8; + colfuncs[COLDRAWFUNC_SHADOWED] = R_DrawColumnShadowed_8; + colfuncs[COLDRAWFUNC_TRANSTRANS] = R_DrawTranslatedTranslucentColumn_8; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCHTRANS] = R_Draw2sMultiPatchTranslucentColumn_8; + colfuncs[COLDRAWFUNC_FOG] = R_DrawFogColumn_8; + + spanfuncs[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_8; + spanfuncs[SPANDRAWFUNC_SPLAT] = R_DrawSplat_8; + spanfuncs[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_8; + spanfuncs[SPANDRAWFUNC_FOG] = R_DrawFogSpan_8; +#ifndef NOWATER + spanfuncs[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_8; +#endif + spanfuncs[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_8; + spanfuncs[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_8; +#ifndef NOWATER + spanfuncs[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_8; +#endif + spanfuncs[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_8; + + // Lactozilla: Non-powers-of-two + spanfuncs_npo2[BASEDRAWFUNC] = R_DrawSpan_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TRANS] = R_DrawTranslucentSpan_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_SPLAT] = R_DrawSplat_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TRANSSPLAT] = R_DrawTranslucentSplat_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_FOG] = NULL; // Not needed +#ifndef NOWATER + spanfuncs_npo2[SPANDRAWFUNC_WATER] = R_DrawTranslucentWaterSpan_NPO2_8; +#endif + spanfuncs_npo2[SPANDRAWFUNC_TILTED] = R_DrawTiltedSpan_NPO2_8; + spanfuncs_npo2[SPANDRAWFUNC_TILTEDTRANS] = R_DrawTiltedTranslucentSpan_NPO2_8; +#ifndef NOWATER + spanfuncs_npo2[SPANDRAWFUNC_TILTEDWATER] = R_DrawTiltedTranslucentWaterSpan_NPO2_8; +#endif + spanfuncs_npo2[SPANDRAWFUNC_TILTEDSPLAT] = R_DrawTiltedSplat_NPO2_8; - colfunc = basecolfunc = R_DrawColumn_8; - shadecolfunc = R_DrawShadeColumn_8; - fuzzcolfunc = R_DrawTranslucentColumn_8; - walldrawerfunc = R_DrawWallColumn_8; - twosmultipatchfunc = R_Draw2sMultiPatchColumn_8; - twosmultipatchtransfunc = R_Draw2sMultiPatchTranslucentColumn_8; #ifdef RUSEASM if (R_ASM) { if (R_MMX) { - colfunc = basecolfunc = R_DrawColumn_8_MMX; - //shadecolfunc = R_DrawShadeColumn_8_ASM; - //fuzzcolfunc = R_DrawTranslucentColumn_8_ASM; - walldrawerfunc = R_DrawWallColumn_8_MMX; - twosmultipatchfunc = R_Draw2sMultiPatchColumn_8_MMX; - spanfunc = basespanfunc = R_DrawSpan_8_MMX; + colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_MMX; + //colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; + //colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_MMX; + spanfuncs[BASEDRAWFUNC] = R_DrawSpan_8_MMX; } else { - colfunc = basecolfunc = R_DrawColumn_8_ASM; - //shadecolfunc = R_DrawShadeColumn_8_ASM; - //fuzzcolfunc = R_DrawTranslucentColumn_8_ASM; - walldrawerfunc = R_DrawWallColumn_8_ASM; - twosmultipatchfunc = R_Draw2sMultiPatchColumn_8_ASM; + colfuncs[BASEDRAWFUNC] = R_DrawColumn_8_ASM; + //colfuncs[COLDRAWFUNC_SHADE] = R_DrawShadeColumn_8_ASM; + //colfuncs[COLDRAWFUNC_FUZZY] = R_DrawTranslucentColumn_8_ASM; + colfuncs[COLDRAWFUNC_TWOSMULTIPATCH] = R_Draw2sMultiPatchColumn_8_ASM; } } #endif @@ -166,12 +189,41 @@ void SCR_SetMode(void) }*/ else I_Error("unknown bytes per pixel mode %d\n", vid.bpp); -/*#if !defined (DC) && !defined (WII) +/* if (SCR_IsAspectCorrect(vid.width, vid.height)) CONS_Alert(CONS_WARNING, M_GetText("Resolution is not aspect-correct!\nUse a multiple of %dx%d\n"), BASEVIDWIDTH, BASEVIDHEIGHT); -#endif*/ +*/ +} + +void SCR_SetMode(void) +{ + if (dedicated) + return; + + if (!(setmodeneeded || setrenderneeded) || WipeInAction) + return; // should never happen and don't change it during a wipe, BAD! + + // Lactozilla: Renderer switching + if (setrenderneeded) + { + Z_PreparePatchFlush(); + needpatchflush = true; + needpatchrecache = true; + VID_CheckRenderer(); + if (!setmodeneeded) + VID_SetMode(vid.modenum); + } + + if (setmodeneeded) + VID_SetMode(--setmodeneeded); + + V_SetPalette(0); + + SCR_SetDrawFuncs(); + // set the apprpriate drawer for the sky (tall or INT16) setmodeneeded = 0; + setrenderneeded = 0; } // do some initial settings for the game loading screen @@ -308,10 +360,13 @@ void SCR_Recalc(void) vid.fsmalldupy = vid.smalldupy*FRACUNIT; #endif - // toggle off automap because some screensize-dependent values will + // toggle off (then back on) the automap because some screensize-dependent values will // be calculated next time the automap is activated. if (automapactive) - AM_Stop(); + { + am_recalc = true; + AM_Start(); + } // set the screen[x] ptrs on the new vidbuffers V_Init(); @@ -359,6 +414,8 @@ void SCR_CheckDefaultMode(void) // see note above setmodeneeded = VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value) + 1; } + + SCR_ActuallyChangeRenderer(); } // sets the modenum as the new default video mode to be saved in the config file @@ -388,6 +445,66 @@ void SCR_ChangeFullscreen(void) #endif } +static int target_renderer = 0; + +void SCR_ActuallyChangeRenderer(void) +{ + setrenderneeded = target_renderer; + +#ifdef HWRENDER + // Well, it didn't even load anyway. + if ((vid_opengl_state == -1) && (setrenderneeded == render_opengl)) + { + if (M_CheckParm("-nogl")) + CONS_Alert(CONS_ERROR, "OpenGL rendering was disabled!\n"); + else + CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); + setrenderneeded = 0; + return; + } +#endif + + // setting the same renderer twice WILL crash your game, so let's not, please + if (rendermode == setrenderneeded) + setrenderneeded = 0; +} + +// Lactozilla: Renderer switching +void SCR_ChangeRenderer(void) +{ + setrenderneeded = 0; + + if (con_startup) + { + target_renderer = cv_renderer.value; +#ifdef HWRENDER + if (M_CheckParm("-opengl") && (vid_opengl_state == 1)) + target_renderer = rendermode = render_opengl; + else +#endif + if (M_CheckParm("-software")) + target_renderer = rendermode = render_soft; + // set cv_renderer back + SCR_ChangeRendererCVars(rendermode); + return; + } + + if (cv_renderer.value == 1) + target_renderer = render_soft; + else if (cv_renderer.value == 2) + target_renderer = render_opengl; + SCR_ActuallyChangeRenderer(); +} + +void SCR_ChangeRendererCVars(INT32 mode) +{ + // set cv_renderer back + if (mode == render_soft) + CV_StealthSetValue(&cv_renderer, 1); + else if (mode == render_opengl) + CV_StealthSetValue(&cv_renderer, 2); +} + boolean SCR_IsAspectCorrect(INT32 width, INT32 height) { return @@ -421,11 +538,6 @@ void SCR_DisplayTicRate(void) if (totaltics <= TICRATE/2) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_RASPBERRY, GTC_CACHE); else if (totaltics == TICRATE) ticcntcolor = R_GetTranslationColormap(TC_RAINBOW, SKINCOLOR_MINT, GTC_CACHE); - /*V_DrawString(vid.width-(24*vid.dupx), vid.height-(16*vid.dupy), - V_YELLOWMAP|V_NOSCALESTART, "FPS"); - V_DrawString(vid.width-(40*vid.dupx), vid.height-( 8*vid.dupy), - ticcntcolor|V_NOSCALESTART, va("%02d/%02u", totaltics, TICRATE));*/ - // draw "FPS" V_DrawFixedPatch(306<origin) + dot = '\x1E'; + else + dot = ' '; + + V_DrawRightAlignedString(BASEVIDWIDTH - 20, y, flags, + va("%c [%s]", dot, (closedcaptions[i].s->caption[0] ? closedcaptions[i].s->caption : closedcaptions[i].s->name))); + } +} + +void SCR_DisplayMarathonInfo(void) +{ + INT32 flags = V_SNAPTOBOTTOM; + static tic_t entertic, oldentertics = 0, antisplice[2] = {48,0}; + const char *str; +#if 0 // eh, this probably isn't going to be a problem + if (((signed)marathontime) < 0) + { + flags |= V_REDMAP; + str = "No waiting out the clock to submit a bogus time."; + } + else +#endif + { + entertic = I_GetTime(); + if (gamecomplete) + flags |= V_YELLOWMAP; + else if (marathonmode & MA_INGAME) + ; // see also G_Ticker + else if (marathonmode & MA_INIT) + marathonmode &= ~MA_INIT; + else + marathontime += entertic - oldentertics; + + // Create a sequence of primes such that their LCM is nice and big. +#define PRIMEV1 13 +#define PRIMEV2 17 // I can't believe it! I'm on TV! + antisplice[0] += (entertic - oldentertics)*PRIMEV2; + antisplice[0] %= PRIMEV1*((vid.width/vid.dupx)+1); + antisplice[1] += (entertic - oldentertics)*PRIMEV1; + antisplice[1] %= PRIMEV1*((vid.width/vid.dupx)+1); + str = va("%i:%02i:%02i.%02i", + G_TicsToHours(marathontime), + G_TicsToMinutes(marathontime, false), + G_TicsToSeconds(marathontime), + G_TicsToCentiseconds(marathontime)); + oldentertics = entertic; + } + V_DrawFill((antisplice[0]/PRIMEV1)-1, BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTOLEFT); + V_DrawFill((antisplice[0]/PRIMEV1), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTOLEFT|31); + V_DrawFill(BASEVIDWIDTH-((antisplice[1]/PRIMEV1)-1), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTORIGHT); + V_DrawFill(BASEVIDWIDTH-((antisplice[1]/PRIMEV1)), BASEVIDHEIGHT-8, 1, 8, V_SNAPTOBOTTOM|V_SNAPTORIGHT|31); +#undef PRIMEV1 +#undef PRIMEV2 + V_DrawPromptBack(-8, cons_backcolor.value); + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-8, flags, str); +} diff --git a/src/screen.h b/src/screen.h index 2e4d29b95..32f5db9f1 100644 --- a/src/screen.h +++ b/src/screen.h @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,20 +15,16 @@ #include "command.h" -#if (defined (_WIN32) || defined (_WIN32_WCE)) && !defined (__CYGWIN__) && !defined (_XBOX) -#if defined (_WIN32_WCE) && defined (__GNUC__) -#include -#else +#if defined (_WIN32) && !defined (__CYGWIN__) #define RPC_NO_WINDOWS_H #include -#endif #define DNWH HWND #else #define DNWH void * // unused in DOS version #endif // quickhack for V_Init()... to be cleaned up -#if defined (DC) || defined (_WIN32_WCE) || defined (PSP) || defined (NOPOSTPROCESSING) +#ifdef NOPOSTPROCESSING #define NUMSCREENS 2 #else #define NUMSCREENS 5 @@ -43,19 +39,8 @@ // we try to re-allocate a minimum of buffers for stability of the memory, // so all the small-enough tables based on screen size, are allocated once // and for all at the maximum size. -#if defined (_WIN32_WCE) || defined (DC) || defined (_PSP) || defined (_NDS) -#define MAXVIDWIDTH 320 -#define MAXVIDHEIGHT 200 -#elif defined (GP2X) -#define MAXVIDWIDTH 320 //720 -#define MAXVIDHEIGHT 240 //576 -#elif defined (WII) // Wii, VGA/640x480 -#define MAXVIDWIDTH 640 -#define MAXVIDHEIGHT 480 -#else #define MAXVIDWIDTH 1920 // don't set this too high because actually #define MAXVIDHEIGHT 1200 // lots of tables are allocated with the MAX size. -#endif #define BASEVIDWIDTH 320 // NEVER CHANGE THIS! This is the original #define BASEVIDHEIGHT 200 // resolution of the graphics. @@ -110,7 +95,7 @@ typedef struct vmode_s INT32 windowed; // if true this is a windowed mode INT32 numpages; vesa_extra_t *pextradata; // vesa mode extra data -#if defined (_WIN32) && !defined (_XBOX) +#ifdef _WIN32 INT32 (WINAPI *setmode)(viddef_t *lvid, struct vmode_s *pcurrentmode); #else INT32 (*setmode)(viddef_t *lvid, struct vmode_s *pcurrentmode); @@ -125,18 +110,49 @@ extern vmode_t specialmodes[NUMSPECIALMODES]; // color mode dependent drawer function pointers // --------------------------------------------- -extern void (*wallcolfunc)(void); +#define BASEDRAWFUNC 0 + +enum +{ + COLDRAWFUNC_BASE = BASEDRAWFUNC, + COLDRAWFUNC_FUZZY, + COLDRAWFUNC_TRANS, + COLDRAWFUNC_SHADE, + COLDRAWFUNC_SHADOWED, + COLDRAWFUNC_TRANSTRANS, + COLDRAWFUNC_TWOSMULTIPATCH, + COLDRAWFUNC_TWOSMULTIPATCHTRANS, + COLDRAWFUNC_FOG, + + COLDRAWFUNC_MAX +}; + extern void (*colfunc)(void); -extern void (*basecolfunc)(void); -extern void (*fuzzcolfunc)(void); -extern void (*transcolfunc)(void); -extern void (*shadecolfunc)(void); +extern void (*colfuncs[COLDRAWFUNC_MAX])(void); + +enum +{ + SPANDRAWFUNC_BASE = BASEDRAWFUNC, + SPANDRAWFUNC_TRANS, + SPANDRAWFUNC_SPLAT, + SPANDRAWFUNC_TRANSSPLAT, + SPANDRAWFUNC_FOG, +#ifndef NOWATER + SPANDRAWFUNC_WATER, +#endif + SPANDRAWFUNC_TILTED, + SPANDRAWFUNC_TILTEDTRANS, + SPANDRAWFUNC_TILTEDSPLAT, +#ifndef NOWATER + SPANDRAWFUNC_TILTEDWATER, +#endif + + SPANDRAWFUNC_MAX +}; + extern void (*spanfunc)(void); -extern void (*basespanfunc)(void); -extern void (*splatfunc)(void); -extern void (*transtransfunc)(void); -extern void (*twosmultipatchfunc)(void); -extern void (*twosmultipatchtransfunc)(void); +extern void (*spanfuncs[SPANDRAWFUNC_MAX])(void); +extern void (*spanfuncs_npo2[SPANDRAWFUNC_MAX])(void); // ----- // CPUID @@ -155,18 +171,22 @@ extern boolean R_SSE2; extern viddef_t vid; extern INT32 setmodeneeded; // mode number to set if needed, or 0 +void SCR_ChangeRenderer(void); +void SCR_ChangeRendererCVars(INT32 mode); +extern UINT8 setrenderneeded; + extern INT32 scr_bpp; extern UINT8 *scr_borderpatch; // patch used to fill the view borders -extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_fullscreen, cv_vhseffect, cv_shittyscreen; +extern consvar_t cv_scr_width, cv_scr_height, cv_scr_depth, cv_renderview, cv_renderer, cv_fullscreen; +extern consvar_t cv_vhseffect, cv_shittyscreen; + // wait for page flipping to end or not extern consvar_t cv_vidwait; -// quick fix for tall/short skies, depending on bytesperpixel -extern void (*walldrawerfunc)(void); - // Change video mode, only at the start of a refresh. void SCR_SetMode(void); +void SCR_SetDrawFuncs(void); // Recalc screen size dependent stuff void SCR_Recalc(void); // Check parms once at startup @@ -180,6 +200,8 @@ FUNCMATH boolean SCR_IsAspectCorrect(INT32 width, INT32 height); // move out to main code for consistency void SCR_DisplayTicRate(void); +void SCR_ClosedCaptions(void); void SCR_DisplayLocalPing(void); +void SCR_DisplayMarathonInfo(void); #undef DNWH #endif //__SCREEN_H__ diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index 33c83b8b3..1ea8a2b15 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -1,6 +1,10 @@ # Declare SDL2 interface sources -set(SRB2_CONFIG_SDL2_USEMIXER ON CACHE BOOL "Use SDL2_mixer or regular sdl sound") +if(NOT ${SRB2_CONFIG_HAVE_MIXERX}) + set(SRB2_CONFIG_SDL2_USEMIXER ON CACHE BOOL "Use SDL2_mixer or regular sdl sound") +else() + set(SRB2_CONFIG_SDL2_USEMIXER OFF) +endif() if(${SRB2_CONFIG_SDL2_USEMIXER}) if(${SRB2_CONFIG_USE_INTERNAL_LIBRARIES}) @@ -22,6 +26,8 @@ if(${SRB2_CONFIG_SDL2_USEMIXER}) message(WARNING "You specified that SDL2_mixer is available, but it was not found. Falling back to sdl sound.") set(SRB2_SDL2_SOUNDIMPL sdl_sound.c) endif() +elseif(${MIXERX_FOUND}) + set(SRB2_SDL2_SOUNDIMPL mixer_sound.c) else() set(SRB2_SDL2_SOUNDIMPL sdl_sound.c) endif() @@ -30,7 +36,6 @@ set(SRB2_SDL2_SOURCES dosstr.c endtxt.c hwsym_sdl.c - i_cdmus.c i_main.c i_net.c i_system.c @@ -50,6 +55,10 @@ set(SRB2_SDL2_HEADERS sdlmain.h ) +if(${SRB2_CONFIG_HAVE_THREADS}) + set(SRB2_SDL2_SOURCES ${SRB2_SDL2_SOURCES} i_threads.c) +endif() + source_group("Interface Code" FILES ${SRB2_SDL2_SOURCES} ${SRB2_SDL2_HEADERS}) # Dependency @@ -70,6 +79,8 @@ if(${SDL2_FOUND}) set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_CORE_SOURCES} ${SRB2_CORE_HEADERS} + ${SRB2_DISCORDRPC_SOURCES} + ${SRB2_DISCORDRPC_HEADERS} ${SRB2_PNG_SOURCES} ${SRB2_PNG_HEADERS} ${SRB2_CORE_RENDER_SOURCES} @@ -86,9 +97,11 @@ if(${SDL2_FOUND}) ${SRB2_PNG_SOURCES} ${SRB2_PNG_HEADERS}) source_group("Renderer" FILES ${SRB2_CORE_RENDER_SOURCES}) source_group("Game" FILES ${SRB2_CORE_GAME_SOURCES}) + source_group("Discord Rich Presence" FILES ${SRB2_DISCORDRPC_SOURCES} ${SRB2_DISCORDRPC_HEADERS}) source_group("Assembly" FILES ${SRB2_ASM_SOURCES} ${SRB2_NASM_SOURCES}) source_group("LUA" FILES ${SRB2_LUA_SOURCES} ${SRB2_LUA_HEADERS}) source_group("LUA\\Interpreter" FILES ${SRB2_BLUA_SOURCES} ${SRB2_BLUA_HEADERS}) + if(${SRB2_CONFIG_HWRENDER}) set(SRB2_SDL2_TOTAL_SOURCES ${SRB2_SDL2_TOTAL_SOURCES} @@ -140,7 +153,13 @@ if(${SDL2_FOUND}) endif() add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32 ${SRB2_SDL2_TOTAL_SOURCES}) - set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME ${SRB2_SDL2_EXE_NAME}) + if(${CMAKE_SYSTEM} MATCHES Windows) + set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2win) + elseif(${CMAKE_SYSTEM} MATCHES Linux) + set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME lsdlsrb2) + else() + set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2) + endif() if(${CMAKE_SYSTEM} MATCHES Darwin) find_library(CORE_LIB CoreFoundation) @@ -149,10 +168,13 @@ if(${SDL2_FOUND}) SDL2 SDL2_mixer ${GME_LIBRARIES} + ${OPENMPT_LIBRARIES} + ${MIXERX_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${OPENGL_LIBRARIES} ${CURL_LIBRARIES} + ${DISCORDRPC_LIBRARIES} ) set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") else() @@ -160,10 +182,13 @@ if(${SDL2_FOUND}) ${SDL2_LIBRARIES} ${SDL2_MIXER_LIBRARIES} ${GME_LIBRARIES} + ${OPENMPT_LIBRARIES} + ${MIXERX_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${OPENGL_LIBRARIES} ${CURL_LIBRARIES} + ${DISCORDRPC_LIBRARIES} ) if(${CMAKE_SYSTEM} MATCHES Linux) @@ -240,28 +265,35 @@ if(${SDL2_FOUND}) ${SDL2_INCLUDE_DIRS} ${SDL2_MIXER_INCLUDE_DIRS} ${GME_INCLUDE_DIRS} + ${OPENMPT_INCLUDE_DIRS} + ${MIXERX_INCLUDE_DIRS} ${PNG_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIRS} ${CURL_INCLUDE_DIRS} + ${DISCORDRPC_INCLUDE_DIRS} ) - if(${SRB2_HAVE_MIXER}) + if((${SRB2_HAVE_MIXER}) OR (${SRB2_HAVE_MIXERX})) target_compile_definitions(SRB2SDL2 PRIVATE -DHAVE_MIXER -DSOUND=SOUND_MIXER) endif() target_compile_definitions(SRB2SDL2 PRIVATE - -DHAVE_SDL + -DDDIRECTFULLSCREEN -DHAVE_SDL ) - ## strip debug symbols into separate file when using gcc - if(CMAKE_COMPILER_IS_GNUCC) - if(${CMAKE_BUILD_TYPE} MATCHES Debug) + ## strip debug symbols into separate file when using gcc. + ## to be consistent with Makefile, don't generate for OS X. + if((CMAKE_COMPILER_IS_GNUCC) AND NOT (${CMAKE_SYSTEM} MATCHES Darwin)) + if((${CMAKE_BUILD_TYPE} MATCHES Debug) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo)) + if(${CMAKE_BUILD_TYPE} MATCHES Debug) + set(OBJCOPY_ONLY_KEEP_DEBUG "--only-keep-debug") + endif() message(STATUS "Will make separate debug symbols in *.debug") add_custom_command(TARGET SRB2SDL2 POST_BUILD - COMMAND ${OBJCOPY} --only-keep-debug $ $.debug + COMMAND ${OBJCOPY} ${OBJCOPY_ONLY_KEEP_DEBUG} $ $.debug COMMAND ${OBJCOPY} --strip-debug $ - COMMAND ${OBJCOPY} --add-gnu-debuglink=$.debug $ + COMMAND ${OBJCOPY} --add-gnu-debuglink=$.debug $ ) endif() endif() @@ -275,6 +307,15 @@ if(${SDL2_FOUND}) install(TARGETS SRB2SDL2 SRB2SDL2 RUNTIME DESTINATION . ) + if ((${CMAKE_BUILD_TYPE} MATCHES Debug) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo)) + set(SRB2_DEBUG_INSTALL OFF CACHE BOOL "Insert *.debug file into the install directory or package.") + if (${SRB2_DEBUG_INSTALL}) + install(FILES $.debug + DESTINATION . + OPTIONAL + ) + endif() + endif() endif() if(${CMAKE_SYSTEM} MATCHES Windows) @@ -287,12 +328,16 @@ if(${SDL2_FOUND}) HINTS ${CMAKE_SOURCE_DIR}/libs/dll-binaries/x86_64 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/x86_64-w64-mingw32/bin HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/x86_64-w64-mingw32/bin + HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86_64/mingw + HINTS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/x86_64-w64-mingw32/bin ) else() find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}" HINTS ${CMAKE_SOURCE_DIR}/libs/dll-binaries/i686 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/i686-w64-mingw32/bin HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/i686-w64-mingw32/bin + HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86/mingw + HINTS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/i686-w64-mingw32/bin ) endif() else() @@ -301,12 +346,16 @@ if(${SDL2_FOUND}) HINTS ${CMAKE_SOURCE_DIR}/libs/dll-binaries/x86_64 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/lib/x64 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/lib/x64 + HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86_64/mingw + HINTS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/x86_64-w64-mingw32/bin ) else() find_library(SRB2_SDL2_DLL_${dllname} "${defaultname}" HINTS ${CMAKE_SOURCE_DIR}/libs/dll-binaries/i686 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2/lib/x86 HINTS ${CMAKE_SOURCE_DIR}/libs/SDL2_mixer/lib/x86 + HINTS ${CMAKE_SOURCE_DIR}/libs/libopenmpt/bin/x86/mingw + HINTS ${CMAKE_SOURCE_DIR}/libs/SDLMixerX/i686-w64-mingw32/bin ) endif() endif() @@ -327,6 +376,19 @@ if(${SDL2_FOUND}) if(${SRB2_CONFIG_HAVE_GME}) getwinlib(libgme "libgme.dll") endif() + if(${SRB2_CONFIG_HAVE_OPENMPT}) + getwinlib(libopenmpt "libopenmpt.dll") + endif() + if(${SRB2_CONFIG_HAVE_MIXERX}) + getwinlib(SDL2_mixer_ext "SDL2_mixer_ext.dll") + getwinlib(libfluidsynth-2 "libfluidsynth-2.dll") + getwinlib(libgcc_s_sjlj-1 "libgcc_s_sjlj-1.dll") + getwinlib(libstdc++-6 "libstdc++-6.dll") + endif() + + if(${SRB2_CONFIG_HAVE_DISCORDRPC}) + getwinlib(discord-rpc "discord-rpc.dll") + endif() install(PROGRAMS ${win_extra_dll_list} diff --git a/src/sdl/IMG_xpm.c b/src/sdl/IMG_xpm.c index af76ec1dd..458131620 100644 --- a/src/sdl/IMG_xpm.c +++ b/src/sdl/IMG_xpm.c @@ -1,6 +1,6 @@ /* SDL_image: An example image loading library for use with SDL - Copyright (C) 1997-2018 Sam Lantinga + Copyright (C) 1997-2019 Sam Lantinga This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages @@ -34,7 +34,7 @@ * * Besides the standard API, also provides * - * SDL_Surface *IMG_ReadXPMFromArray(char **xpm) + * SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) * * that reads the image data from an XPM file included in the C source. * @@ -88,8 +88,8 @@ struct color_hash { struct hash_entry **table; struct hash_entry *entries; /* array of all entries */ struct hash_entry *next_free; - int size; - int maxnum; + size_t size; + size_t maxnum; }; static int hash_key(const char *key, int cpp, int size) @@ -103,14 +103,14 @@ static int hash_key(const char *key, int cpp, int size) return hash & (size - 1); } -static struct color_hash *create_colorhash(int maxnum) +static struct color_hash *create_colorhash(size_t maxnum) { - int bytes, s; + size_t bytes, s; struct color_hash *hash; /* we know how many entries we need, so we can allocate everything here */ - hash = (struct color_hash *)SDL_malloc(sizeof *hash); + hash = (struct color_hash *)SDL_calloc(1, sizeof(*hash)); if (!hash) return NULL; @@ -119,15 +119,29 @@ static struct color_hash *create_colorhash(int maxnum) ; hash->size = s; hash->maxnum = maxnum; + bytes = hash->size * sizeof(struct hash_entry **); - hash->entries = NULL; /* in case malloc fails */ - hash->table = (struct hash_entry **)SDL_malloc(bytes); + /* Check for overflow */ + if ((bytes / sizeof(struct hash_entry **)) != hash->size) { + IMG_SetError("memory allocation overflow"); + SDL_free(hash); + return NULL; + } + hash->table = (struct hash_entry **)SDL_calloc(1, bytes); if (!hash->table) { SDL_free(hash); return NULL; } - SDL_memset(hash->table, 0, bytes); - hash->entries = (struct hash_entry *)SDL_malloc(maxnum * sizeof(struct hash_entry)); + + bytes = maxnum * sizeof(struct hash_entry); + /* Check for overflow */ + if ((bytes / sizeof(struct hash_entry)) != maxnum) { + IMG_SetError("memory allocation overflow"); + SDL_free(hash->table); + SDL_free(hash); + return NULL; + } + hash->entries = (struct hash_entry *)SDL_calloc(1, bytes); if (!hash->entries) { SDL_free(hash->table); SDL_free(hash); @@ -138,7 +152,7 @@ static struct color_hash *create_colorhash(int maxnum) } static int add_colorhash(struct color_hash *hash, - char *key, int cpp, Uint32 color) + const char *key, int cpp, Uint32 color) { int index = hash_key(key, cpp, hash->size); struct hash_entry *e = hash->next_free++; @@ -995,10 +1009,11 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) { Sint64 start = 0; SDL_Surface *image = NULL; - int index; + size_t index; int x, y; - int w, h, ncolors, cpp; - int indexed; + int w, h, cpp; + long unsigned int ncolors; + size_t indexed; Uint8 *dst; struct color_hash *colors = NULL; SDL_Color *im_colors = NULL; @@ -1029,12 +1044,17 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) * Right now we don't use the hotspots but it should be handled * one day. */ - if (SDL_sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 + if (SDL_sscanf(line, "%d %d %lu %d", &w, &h, &ncolors, &cpp) != 4 || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) { error = "Invalid format description"; goto done; } + /* Check for allocation overflow */ + if ((size_t)(ncolors * cpp)/cpp != ncolors) { + error = "Invalid color specification"; + goto done; + } keystrings = (char *)SDL_malloc(ncolors * cpp); if (!keystrings) { error = "Out of memory"; @@ -1102,8 +1122,9 @@ static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) c->g = (Uint8)(rgb >> 8); c->b = (Uint8)(rgb); pixel = index; - } else + } else { pixel = rgb; + } add_colorhash(colors, nextkey, cpp, pixel); nextkey += cpp; if (rgb == 0xffffffff) @@ -1192,7 +1213,7 @@ SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) return(NULL); } -SDL_Surface *IMG_ReadXPMFromArray(char **xpm) +SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) { return NULL; } diff --git a/src/sdl/Makefile.cfg b/src/sdl/Makefile.cfg index b0c591ce2..45d0d6ba7 100644 --- a/src/sdl/Makefile.cfg +++ b/src/sdl/Makefile.cfg @@ -53,35 +53,18 @@ ifndef NOHW OBJS+=$(OBJDIR)/r_opengl.o $(OBJDIR)/ogl_sdl.o endif -ifndef NOHS -ifdef OPENAL - OBJS+=$(OBJDIR)/s_openal.o - OPTS+=-DSTATIC3DS - STATICHS=1 -else -ifdef FMOD - OBJS+=$(OBJDIR)/s_fmod.o - OPTS+=-DSTATIC3DS - STATICHS=1 -else -ifdef MINGW -ifdef DS3D - OBJS+=$(OBJDIR)/s_ds3d.o - OPTS+=-DSTATIC3DS - STATICHS=1 -endif -endif -endif -endif -endif - ifdef NOMIXER i_sound_o=$(OBJDIR)/sdl_sound.o else i_sound_o=$(OBJDIR)/mixer_sound.o OPTS+=-DHAVE_MIXER +ifdef HAVE_MIXERX + OPTS+=-DHAVE_MIXERX + SDL_LDFLAGS+=-lSDL2_mixer_ext +else SDL_LDFLAGS+=-lSDL2_mixer endif +endif ifndef NOTHREADS OPTS+=-DHAVE_THREADS diff --git a/src/sdl/Srb2SDL-vc10.vcxproj b/src/sdl/Srb2SDL-vc10.vcxproj index e9377b1c0..0c06f226d 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj +++ b/src/sdl/Srb2SDL-vc10.vcxproj @@ -94,6 +94,7 @@ + @@ -212,12 +213,14 @@ + + @@ -261,6 +264,7 @@ + @@ -281,11 +285,15 @@ + + + + @@ -335,6 +343,7 @@ + @@ -362,9 +371,11 @@ + + @@ -375,7 +386,6 @@ - @@ -396,6 +406,7 @@ + @@ -412,6 +423,7 @@ + @@ -440,11 +452,18 @@ true + + true + + + + + diff --git a/src/sdl/Srb2SDL-vc10.vcxproj.filters b/src/sdl/Srb2SDL-vc10.vcxproj.filters index f197a394b..a14e40427 100644 --- a/src/sdl/Srb2SDL-vc10.vcxproj.filters +++ b/src/sdl/Srb2SDL-vc10.vcxproj.filters @@ -180,6 +180,9 @@ F_Frame + + G_Game + G_Game @@ -216,6 +219,9 @@ Hw_Hardware + + Hw_Hardware + Hw_Hardware @@ -342,6 +348,9 @@ M_Misc + + M_Misc + M_Misc @@ -417,6 +426,9 @@ R_Rend + + R_Rend + R_Rend @@ -462,8 +474,22 @@ SDLApp +<<<<<<< HEAD D_Doom +======= + + Hw_Hardware + + + R_Rend + + + R_Rend + + + R_Rend +>>>>>>> srb2/next @@ -522,6 +548,9 @@ BLUA + + BLUA + BLUA @@ -591,6 +620,9 @@ F_Frame + + G_Game + G_Game @@ -618,6 +650,9 @@ Hw_Hardware + + Hw_Hardware + Hw_Hardware @@ -639,7 +674,11 @@ Hw_Hardware +<<<<<<< HEAD +======= + +>>>>>>> srb2/next Hw_Hardware @@ -648,9 +687,6 @@ Hw_Hardware - - Hw_Hardware - Hw_Hardware @@ -699,6 +735,9 @@ LUA + + LUA + LUA @@ -738,6 +777,9 @@ M_Misc + + M_Misc + M_Misc @@ -834,6 +876,9 @@ R_Rend + + R_Rend + R_Rend @@ -843,6 +888,9 @@ R_Rend + + R_Rend + R_Rend @@ -918,8 +966,23 @@ SDLApp +<<<<<<< HEAD D_Doom +======= + + Hw_Hardware + + + + R_Rend + + + R_Rend + + + R_Rend +>>>>>>> srb2/next diff --git a/src/sdl/Srb2SDL-vc9.vcproj b/src/sdl/Srb2SDL-vc9.vcproj index 7c5c523b8..b7094b49c 100644 --- a/src/sdl/Srb2SDL-vc9.vcproj +++ b/src/sdl/Srb2SDL-vc9.vcproj @@ -50,7 +50,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=""$(ProjectDir)..\..\libs\libpng-src";"$(ProjectDir)..\..\libs\zlib"" - PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" + PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -145,7 +145,7 @@ Name="VCCLCompilerTool" Optimization="0" AdditionalIncludeDirectories=""$(ProjectDir)..\..\libs\libpng-src";"$(ProjectDir)..\..\libs\zlib"" - PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" + PreprocessorDefinitions="_DEBUG;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" MinimalRebuild="true" BasicRuntimeChecks="3" RuntimeLibrary="1" @@ -248,7 +248,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" AdditionalIncludeDirectories=""$(ProjectDir)..\..\libs\libpng-src";"$(ProjectDir)..\..\libs\zlib"" - PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" + PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;USEASM;HAVE_PNG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" StringPooling="true" RuntimeLibrary="0" PrecompiledHeaderFile=".\..\..\objs\VC9\$(Platform)\$(Configuration)\SDL\Srb2SDL-vc9.pch" @@ -350,7 +350,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" AdditionalIncludeDirectories=""$(ProjectDir)..\..\libs\libpng-src";"$(ProjectDir)..\..\libs\zlib"" - PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" + PreprocessorDefinitions="NDEBUG;SDLMAIN;NO_STDIO_REDIRECT;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_PNG;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" StringPooling="true" RuntimeLibrary="0" PrecompiledHeaderFile=".\..\..\objs\VC9\$(Platform)\$(Configuration)\SDL\Srb2SDL-vc9.pch" @@ -2590,46 +2590,6 @@ RelativePath="..\hardware\hw_md2.h" > - - - - - - - - - - - - - - diff --git a/src/sdl/Srb2SDL.dsp b/src/sdl/Srb2SDL.dsp index ce35e2e23..9f6dd7b33 100644 --- a/src/sdl/Srb2SDL.dsp +++ b/src/sdl/Srb2SDL.dsp @@ -604,10 +604,6 @@ SOURCE=..\hardware\hw_md2.h # End Source File # Begin Source File -SOURCE=..\hardware\hw_trick.c -# End Source File -# Begin Source File - SOURCE=..\hardware\hws_data.h # End Source File # End Group diff --git a/src/sdl/Srb2SDL.props b/src/sdl/Srb2SDL.props index 75839a5b2..17b41bddc 100644 --- a/src/sdl/Srb2SDL.props +++ b/src/sdl/Srb2SDL.props @@ -6,7 +6,7 @@ - HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) + HAVE_ZLIB;HAVE_LIBGME;USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;HAVE_OPENMPT;SDLMAIN;%(PreprocessorDefinitions) USE_WGL_SWAP;DIRECTFULLSCREEN;HAVE_SDL;HWRENDER;HW3SOUND;HAVE_FILTER;HAVE_MIXER;SDLMAIN;%(PreprocessorDefinitions) diff --git a/src/sdl/hwsym_sdl.c b/src/sdl/hwsym_sdl.c index 2627c3fdb..e545bbb63 100644 --- a/src/sdl/hwsym_sdl.c +++ b/src/sdl/hwsym_sdl.c @@ -80,9 +80,12 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(Init); GETFUNC(Draw2DLine); GETFUNC(DrawPolygon); + GETFUNC(DrawIndexedTriangles); + GETFUNC(RenderSkyDome); GETFUNC(SetBlend); GETFUNC(ClearBuffer); GETFUNC(SetTexture); + GETFUNC(UpdateTexture); GETFUNC(ReadRect); GETFUNC(GClipRect); GETFUNC(ClearMipMapCache); @@ -100,19 +103,14 @@ void *hwSym(const char *funcName,void *handle) GETFUNC(MakeScreenTexture); GETFUNC(MakeScreenFinalTexture); GETFUNC(DrawScreenFinalTexture); - - GETFUNC(RenderSkyDome); - GETFUNC(LoadShaders); - GETFUNC(KillShaders); + GETFUNC(CompileShaders); + GETFUNC(CleanShaders); GETFUNC(SetShader); GETFUNC(UnSetShader); + GETFUNC(SetShaderInfo); GETFUNC(LoadCustomShader); - GETFUNC(InitCustomShaders); - - GETFUNC(StartBatching); - GETFUNC(RenderBatches); #else //HWRENDER if (0 == strcmp("FinishUpdate", funcName)) diff --git a/src/sdl/i_cdmus.c b/src/sdl/i_cdmus.c deleted file mode 100644 index 5d086e73a..000000000 --- a/src/sdl/i_cdmus.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "../command.h" -#include "../s_sound.h" -#include "../i_sound.h" - -// -// CD MUSIC I/O -// - -UINT8 cdaudio_started = 0; - -consvar_t cd_volume = {"cd_volume","31",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; - - -void I_InitCD(void){} - -void I_StopCD(void){} - -void I_PauseCD(void){} - -void I_ResumeCD(void){} - -void I_ShutdownCD(void){} - -void I_UpdateCD(void){} - -void I_PlayCD(UINT8 track, UINT8 looping) -{ - (void)track; - (void)looping; -} - -FUNCMATH boolean I_SetVolumeCD(int volume) -{ - (void)volume; - return false; -} diff --git a/src/sdl/i_main.c b/src/sdl/i_main.c index e36021aa0..5b205503e 100644 --- a/src/sdl/i_main.c +++ b/src/sdl/i_main.c @@ -27,7 +27,7 @@ #include #endif -#ifdef __unix__ +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) #include #endif @@ -65,6 +65,10 @@ char logfilename[1024]; #endif #endif +#if defined (_WIN32) +#include "exchndl.h" +#endif + #if defined (_WIN32) #include "../win32/win_dbg.h" typedef BOOL (WINAPI *p_IsDebuggerPresent)(VOID); @@ -103,6 +107,107 @@ static inline VOID MakeCodeWritable(VOID) } #endif +#ifdef LOGMESSAGES +static void InitLogging(void) +{ + const char *logdir = NULL; + time_t my_time; + struct tm * timeinfo; + const char *format; + const char *reldir; + int left; + boolean fileabs; +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + const char *link; +#endif + + logdir = D_Home(); + + my_time = time(NULL); + timeinfo = localtime(&my_time); + + if (M_CheckParm("-logfile") && M_IsNextParm()) + { + format = M_GetNextParm(); + fileabs = M_IsPathAbsolute(format); + } + else + { + format = "log-%Y-%m-%d_%H-%M-%S.txt"; + fileabs = false; + } + + if (fileabs) + { + strftime(logfilename, sizeof logfilename, format, timeinfo); + } + else + { + if (M_CheckParm("-logdir") && M_IsNextParm()) + reldir = M_GetNextParm(); + else + reldir = "logs"; + + if (M_IsPathAbsolute(reldir)) + { + left = snprintf(logfilename, sizeof logfilename, + "%s"PATHSEP, reldir); + } + else +#ifdef DEFAULTDIR + if (logdir) + { + left = snprintf(logfilename, sizeof logfilename, + "%s"PATHSEP DEFAULTDIR PATHSEP"%s"PATHSEP, logdir, reldir); + } + else +#endif/*DEFAULTDIR*/ + { + left = snprintf(logfilename, sizeof logfilename, + "."PATHSEP"%s"PATHSEP, reldir); + } + + strftime(&logfilename[left], sizeof logfilename - left, + format, timeinfo); + } + + M_MkdirEachUntil(logfilename, + M_PathParts(logdir) - 1, + M_PathParts(logfilename) - 1, 0755); + +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) + logstream = fopen(logfilename, "w"); +#ifdef DEFAULTDIR + if (logdir) + link = va("%s/"DEFAULTDIR"/latest-log.txt", logdir); + else +#endif/*DEFAULTDIR*/ + link = "latest-log.txt"; + unlink(link); + if (symlink(logfilename, link) == -1) + { + I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno)); + } +#else/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/ + logstream = fopen("latest-log.txt", "wt+"); +#endif/*defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)*/ +} +#endif + + +#ifdef _WIN32 +static void +ChDirToExe (void) +{ + CHAR path[MAX_PATH]; + if (GetModuleFileNameA(NULL, path, MAX_PATH) > 0) + { + strrchr(path, '\\')[0] = '\0'; + SetCurrentDirectoryA(path); + } +} +#endif + /** \brief The main function @@ -121,7 +226,6 @@ int SDL_main(int argc, char **argv) int main(int argc, char **argv) #endif { - const char *logdir = NULL; myargc = argc; myargv = argv; /// \todo pull out path to exe from this string @@ -133,91 +237,15 @@ int main(int argc, char **argv) #endif #endif +#ifdef _WIN32 + ChDirToExe(); +#endif + #ifdef LOGMESSAGES if (!M_CheckParm("-nolog")) - { - time_t my_time; - struct tm * timeinfo; - const char *format; - const char *reldir; - int left; - boolean fileabs; - const char *link; - - logdir = D_Home(); - - my_time = time(NULL); - timeinfo = localtime(&my_time); - - if (M_CheckParm("-logfile") && M_IsNextParm()) - { - format = M_GetNextParm(); - fileabs = M_IsPathAbsolute(format); - } - else - { - format = "log-%Y-%m-%d_%H-%M-%S.txt"; - fileabs = false; - } - - if (fileabs) - { - strftime(logfilename, sizeof logfilename, format, timeinfo); - } - else - { - if (M_CheckParm("-logdir") && M_IsNextParm()) - reldir = M_GetNextParm(); - else - reldir = "logs"; - - if (M_IsPathAbsolute(reldir)) - { - left = snprintf(logfilename, sizeof logfilename, - "%s"PATHSEP, reldir); - } - else -#ifdef DEFAULTDIR - if (logdir) - { - left = snprintf(logfilename, sizeof logfilename, - "%s"PATHSEP DEFAULTDIR PATHSEP"%s"PATHSEP, logdir, reldir); - } - else -#endif/*DEFAULTDIR*/ - { - left = snprintf(logfilename, sizeof logfilename, - "."PATHSEP"%s"PATHSEP, reldir); - } + InitLogging(); #endif/*LOGMESSAGES*/ - strftime(&logfilename[left], sizeof logfilename - left, - format, timeinfo); - } - - M_MkdirEachUntil(logfilename, - M_PathParts(logdir) - 1, - M_PathParts(logfilename) - 1, 0755); - -#ifdef __unix__ - logstream = fopen(logfilename, "w"); -#ifdef DEFAULTDIR - if (logdir) - link = va("%s/"DEFAULTDIR"/latest-log.txt", logdir); - else -#endif/*DEFAULTDIR*/ - link = "latest-log.txt"; - unlink(link); - if (symlink(logfilename, link) == -1) - { - I_OutputMsg("Error symlinking latest-log.txt: %s\n", strerror(errno)); - } -#else/*__unix__*/ - (void)link; - logstream = fopen("latest-log.txt", "wt+"); -#endif/*__unix__*/ - } - //I_OutputMsg("I_StartupSystem() ...\n"); I_StartupSystem(); #if defined (_WIN32) @@ -231,7 +259,7 @@ int main(int argc, char **argv) ) #endif { - LoadLibraryA("exchndl.dll"); + ExcHndlInit(); } } #ifndef __MINGW32__ @@ -259,4 +287,5 @@ int main(int argc, char **argv) // return to OS return 0; } + #endif diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index f03d88197..5b41985a8 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -5,7 +5,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2018 by Sonic Team Junior. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -54,6 +54,12 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #include #endif +#if defined (_WIN32) +DWORD TimeFunction(int requested_frequency); +#else +int TimeFunction(int requested_frequency); +#endif + #include #ifdef _WIN32 #include @@ -102,7 +108,7 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #endif #endif -#if (defined (__unix__) && !defined (_MSDOS)) || defined (UNIXCOMMON) +#if (defined (__unix__) && !defined (_MSDOS)) || (defined (UNIXCOMMON) && !defined(__APPLE__)) #include #include #define NEWSIGNALHANDLER @@ -146,11 +152,6 @@ typedef LPVOID (WINAPI *p_MapViewOfFile) (HANDLE, DWORD, DWORD, DWORD, SIZE_T); #define DEFAULTSEARCHPATH1 "/usr/local/games" #define DEFAULTSEARCHPATH2 "/usr/games" #define DEFAULTSEARCHPATH3 "/usr/local" -#elif defined (_WIN32) -#define DEFAULTWADLOCATION1 "c:\\games\\srb2kart" -#define DEFAULTWADLOCATION2 "\\games\\srb2kart" -#define DEFAULTSEARCHPATH1 "c:\\games" -#define DEFAULTSEARCHPATH2 "\\games" #endif /** \brief WAD file to look for @@ -180,6 +181,8 @@ static char returnWadPath[256]; #include "../m_argv.h" +#include "../m_menu.h" + #ifdef MAC_ALERT #include "macosx/mac_alert.h" #endif @@ -212,41 +215,11 @@ static void JoyReset(SDLJoyInfo_t *JoySet) /** \brief First joystick up and running */ -static INT32 joystick_started = 0; +static INT32 joystick_started[MAXSPLITSCREENPLAYERS] = {0,0,0,0}; /** \brief SDL info about joystick 1 */ -SDLJoyInfo_t JoyInfo; - - -/** \brief Second joystick up and running -*/ -static INT32 joystick2_started = 0; - -/** \brief SDL info about joystick 2 -*/ -SDLJoyInfo_t JoyInfo2; - -/** \brief Third joystick up and running -*/ -static INT32 joystick3_started = 0; - -/** \brief SDL info about joystick 3 -*/ -SDLJoyInfo_t JoyInfo3; - -/** \brief Fourth joystick up and running -*/ -static INT32 joystick4_started = 0; - -/** \brief SDL info about joystick 4 -*/ -SDLJoyInfo_t JoyInfo4; - -#ifdef HAVE_TERMIOS -static INT32 fdmouse2 = -1; -static INT32 mouse2_started = 0; -#endif +SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS]; SDL_bool consolevent = SDL_FALSE; SDL_bool framebuffer = SDL_FALSE; @@ -311,6 +284,7 @@ static void I_ReportSignal(int num, int coredumped) FUNCNORETURN static ATTRNORETURN void signal_handler(INT32 num) { D_QuitNetGame(); // Fix server freezes + CL_AbortDownloadResume(); I_ReportSignal(num, 0); I_ShutdownSystem(); signal(num, SIG_DFL); //default signal action @@ -568,14 +542,12 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co) case VK_TAB: event.data1 = KEY_NULL; break; - case VK_SHIFT: - event.data1 = KEY_LSHIFT; - break; case VK_RETURN: entering_con_command = false; - // Fall through. + /* FALLTHRU */ default: - event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char + //event.data1 = MapVirtualKey(evt.wVirtualKeyCode,2); // convert in to char + event.data1 = evt.uChar.AsciiChar; } if (co != INVALID_HANDLE_VALUE && GetFileType(co) == FILE_TYPE_CHAR && GetConsoleMode(co, &t)) { @@ -594,18 +566,6 @@ static void Impl_HandleKeyboardConsoleEvent(KEY_EVENT_RECORD evt, HANDLE co) } } } - else - { - event.type = ev_keyup; - switch (evt.wVirtualKeyCode) - { - case VK_SHIFT: - event.data1 = KEY_LSHIFT; - break; - default: - break; - } - } if (event.data1) D_PostEvent(&event); } @@ -721,7 +681,7 @@ static void I_RegisterSignals (void) void I_OutputMsg(const char *fmt, ...) { size_t len; - XBOXSTATIC char txt[8192]; + char txt[8192]; va_list argptr; va_start(argptr,fmt); @@ -862,26 +822,26 @@ INT32 I_GetKey (void) // void I_JoyScale(void) { - Joystick.bGamepadStyle = cv_joyscale.value==0; - JoyInfo.scale = Joystick.bGamepadStyle?1:cv_joyscale.value; + Joystick[0].bGamepadStyle = cv_joyscale[0].value==0; + JoyInfo[0].scale = Joystick[0].bGamepadStyle?1:cv_joyscale[0].value; } void I_JoyScale2(void) { - Joystick2.bGamepadStyle = cv_joyscale2.value==0; - JoyInfo2.scale = Joystick2.bGamepadStyle?1:cv_joyscale2.value; + Joystick[1].bGamepadStyle = cv_joyscale[1].value==0; + JoyInfo[1].scale = Joystick[1].bGamepadStyle?1:cv_joyscale[1].value; } void I_JoyScale3(void) { - Joystick3.bGamepadStyle = cv_joyscale3.value==0; - JoyInfo3.scale = Joystick3.bGamepadStyle?1:cv_joyscale3.value; + Joystick[2].bGamepadStyle = cv_joyscale[2].value==0; + JoyInfo[2].scale = Joystick[2].bGamepadStyle?1:cv_joyscale[2].value; } void I_JoyScale4(void) { - Joystick4.bGamepadStyle = cv_joyscale4.value==0; - JoyInfo4.scale = Joystick4.bGamepadStyle?1:cv_joyscale4.value; + Joystick[3].bGamepadStyle = cv_joyscale[3].value==0; + JoyInfo[3].scale = Joystick[3].bGamepadStyle?1:cv_joyscale[1].value; } // Cheat to get the device index for a joystick handle @@ -894,226 +854,96 @@ INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev) SDL_Joystick *test = SDL_JoystickOpen(i); if (test && test == dev) return i; - else if (JoyInfo.dev != test && JoyInfo2.dev != test && JoyInfo3.dev != test && JoyInfo4.dev != test) - SDL_JoystickClose(test); + else + { + UINT8 j; + + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + { + if (JoyInfo[j].dev == test) + break; + } + + if (j == MAXSPLITSCREENPLAYERS) + SDL_JoystickClose(test); + } } return -1; } -// Misleading function: updates device indices for all players BUT the one specified. -// Necessary for SDL_JOYDEVICEADDED events -void I_UpdateJoystickDeviceIndices(INT32 player) +void I_UpdateJoystickDeviceIndex(UINT8 player) { - if (player != 1) // This is a fucking mess. - { - ////////////////////////////// - // update joystick 1's device index - ////////////////////////////// + /////////////////////////////////////////////// + // update this joystick's device index (wow) // + /////////////////////////////////////////////// - if (JoyInfo.dev) - cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; - // is cv_usejoystick used? - else if (// don't check JoyInfo or cv_usejoystick; we're currently operating on those - atoi(cv_usejoystick.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick2.value - && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick3.value - && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick4.value) - cv_usejoystick.value = atoi(cv_usejoystick.string); - // is cv_usejoystick2 used? - else if ( // don't check JoyInfo or cv_usejoystick; we're currently operating on those - atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick2.value - && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick3.value - && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick4.value) - cv_usejoystick.value = atoi(cv_usejoystick2.string); - // is cv_usejoystick3 used? - else if (// don't check JoyInfo or cv_usejoystick; we're currently operating on those - atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick2.value - && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick3.value - && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick4.value) - cv_usejoystick.value = atoi(cv_usejoystick3.string); - // is cv_usejoystick4 used? - else if (// don't check JoyInfo or cv_usejoystick; we're currently operating on those - atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick2.value - && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick3.value - && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick4.value) - cv_usejoystick.value = atoi(cv_usejoystick4.string); - else // we tried... - cv_usejoystick.value = 0; + if (JoyInfo[player].dev) + { + cv_usejoystick[player].value = I_GetJoystickDeviceIndex(JoyInfo[player].dev) + 1; } - - if (player != 2) + else { - ////////////////////////////// - // update joystick 2's device index - ////////////////////////////// + UINT8 joystickID, compareJoystick; - if (JoyInfo2.dev) - cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; - // is cv_usejoystick2 used? - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick.value - // don't check JoyInfo2 or cv_usejoystick2; we're currently operating on those - && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick3.value - && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick4.value) - cv_usejoystick2.value = atoi(cv_usejoystick2.string); - // is cv_usejoystick used? - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick.value - // don't check JoyInfo2 or cv_usejoystick2; we're currently operating on those - && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick3.value - && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick4.value) - cv_usejoystick2.value = atoi(cv_usejoystick.string); - // is cv_usejoystick3 used? - else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick.value - // don't check JoyInfo2 or cv_usejoystick2; we're currently operating on those - && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick3.value - && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick4.value) - cv_usejoystick2.value = atoi(cv_usejoystick3.string); - // is cv_usejoystick4 used? - else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick.value - // don't check JoyInfo2 or cv_usejoystick2; we're currently operating on those - && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick3.value - && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick4.value) - cv_usejoystick2.value = atoi(cv_usejoystick4.string); - else // we tried... - cv_usejoystick2.value = 0; - } + for (joystickID = 0; joystickID < MAXSPLITSCREENPLAYERS; joystickID++) + { + // is this cv_usejoystick used? + const INT32 value = atoi(cv_usejoystick[joystickID].string); - if (player != 3) - { - ////////////////////////////// - // update joystick 3's device index - ////////////////////////////// + for (compareJoystick = 0; compareJoystick < MAXSPLITSCREENPLAYERS; compareJoystick++) + { + if (compareJoystick == player) + continue; - if (JoyInfo3.dev) - cv_usejoystick3.value = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; - // is cv_usejoystick3 used? - else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick.value - && atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick2.value - // don't check JoyInfo3 or cv_usejoystick3; we're currently operating on those - && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick4.value) - cv_usejoystick3.value = atoi(cv_usejoystick3.string); - // is cv_usejoystick used? - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick.value - && atoi(cv_usejoystick.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick2.value - // don't check JoyInfo3 or cv_usejoystick3; we're currently operating on those - && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick4.value) - cv_usejoystick3.value = atoi(cv_usejoystick.string); - // is cv_usejoystick2 used? - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick.value - && atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick2.value - // don't check JoyInfo3 or cv_usejoystick3; we're currently operating on those - && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick4.value) - cv_usejoystick3.value = atoi(cv_usejoystick2.string); - // is cv_usejoystick4 used? - else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick.value - && atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick2.value - // don't check JoyInfo3 or cv_usejoystick3; we're currently operating on those - && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick4.value) - cv_usejoystick3.value = atoi(cv_usejoystick4.string); - else // we tried... - cv_usejoystick3.value = 0; - } + if (value == JoyInfo[compareJoystick].oldjoy || value == cv_usejoystick[compareJoystick].value) + break; + } - if (player != 4) - { - ////////////////////////////// - // update joystick 4's device index - ////////////////////////////// + if (compareJoystick == MAXSPLITSCREENPLAYERS) + { + // We DID make it through the whole loop, so we can use this one! + cv_usejoystick[player].value = value; + break; + } + } - if (JoyInfo4.dev) - cv_usejoystick4.value = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; - // is cv_usejoystick4 used? - else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick.value - && atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick2.value - && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick4.string) != cv_usejoystick3.value) - // don't check JoyInfo4 or cv_usejoystick4; we're currently operating on those - cv_usejoystick4.value = atoi(cv_usejoystick4.string); - // is cv_usejoystick used? - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick.value - && atoi(cv_usejoystick.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick2.value - && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick.string) != cv_usejoystick3.value) - // don't check JoyInfo4 or cv_usejoystick4; we're currently operating on those - cv_usejoystick4.value = atoi(cv_usejoystick.string); - // is cv_usejoystick2 used? - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick.value - && atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick2.value - && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick2.string) != cv_usejoystick3.value) - // don't check JoyInfo4 or cv_usejoystick4; we're currently operating on those - cv_usejoystick4.value = atoi(cv_usejoystick2.string); - // is cv_usejoystick3 used? - else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick.value - && atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick2.value - && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick3.string) != cv_usejoystick3.value) - // don't check JoyInfo4 or cv_usejoystick4; we're currently operating on those - cv_usejoystick4.value = atoi(cv_usejoystick3.string); - else // we tried... - cv_usejoystick4.value = 0; + if (joystickID == MAXSPLITSCREENPLAYERS) + { + // We DID NOT make it through the whole loop, so we can't assign this joystick to anything. + // When you try your best, but you don't succeed... + cv_usejoystick[player].value = 0; + } } } -/** \brief Joystick 1 buttons states +// Misleading function: updates device indices for all players BUT the one specified. +// Necessary for SDL_JOYDEVICEADDED events +void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer) +{ + UINT8 player; + + for (player = 0; player < MAXSPLITSCREENPLAYERS; player++) + { + if (player == excludePlayer) + continue; + + I_UpdateJoystickDeviceIndex(player); + } +} + +/** \brief Joystick buttons states */ -static UINT64 lastjoybuttons = 0; +static UINT64 lastjoybuttons[MAXSPLITSCREENPLAYERS] = {0,0,0,0}; -/** \brief Joystick 1 hats state +/** \brief Joystick hats state */ -static UINT64 lastjoyhats = 0; - -/** \brief Shuts down joystick 1 - +static UINT64 lastjoyhats[MAXSPLITSCREENPLAYERS] = {0,0,0,0}; +/** \brief Shuts down joystick \return void - - */ -void I_ShutdownJoystick(void) +void I_ShutdownJoystick(UINT8 index) { INT32 i; event_t event; @@ -1121,7 +951,7 @@ void I_ShutdownJoystick(void) event.data2 = 0; event.data3 = 0; - lastjoybuttons = lastjoyhats = 0; + lastjoybuttons[index] = lastjoyhats[index] = 0; // emulate the up of all joystick buttons for (i=0;i= 0; i--) + for (i = JoyInfo[index].buttons - 1; i >= 0; i--) { joybuttons <<= 1; - if (SDL_JoystickGetButton(JoyInfo.dev,i)) + if (SDL_JoystickGetButton(JoyInfo[index].dev,i)) joybuttons |= 1; } - if (joybuttons != lastjoybuttons) + if (joybuttons != lastjoybuttons[index]) { INT64 j = 1; // keep only bits that changed since last time - INT64 newbuttons = joybuttons ^ lastjoybuttons; - lastjoybuttons = joybuttons; + INT64 newbuttons = joybuttons ^ lastjoybuttons[index]; + lastjoybuttons[index] = joybuttons; for (i = 0; i < JOYBUTTONS; i++, j <<= 1) { @@ -1197,9 +1027,9 @@ void I_GetJoystickEvents(void) } #endif - for (i = JoyInfo.hats - 1; i >= 0; i--) + for (i = JoyInfo[index].hats - 1; i >= 0; i--) { - Uint8 hat = SDL_JoystickGetHat(JoyInfo.dev, i); + Uint8 hat = SDL_JoystickGetHat(JoyInfo[index].dev, i); if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i); if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i); @@ -1207,11 +1037,11 @@ void I_GetJoystickEvents(void) if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i); } - if (joyhats != lastjoyhats) + if (joyhats != lastjoyhats[index]) { INT64 j = 1; // keep only bits that changed since last time - INT64 newhats = joyhats ^ lastjoyhats; - lastjoyhats = joyhats; + INT64 newhats = joyhats ^ lastjoyhats[index]; + lastjoyhats[index] = joyhats; for (i = 0; i < JOYHATS*4; i++, j <<= 1) { @@ -1234,11 +1064,11 @@ void I_GetJoystickEvents(void) for (i = JOYAXISSET - 1; i >= 0; i--) { event.data1 = i; - if (i*2 + 1 <= JoyInfo.axises) - axisx = SDL_JoystickGetAxis(JoyInfo.dev, i*2 + 0); + if (i*2 + 1 <= JoyInfo[index].axises) + axisx = SDL_JoystickGetAxis(JoyInfo[index].dev, i*2 + 0); else axisx = 0; - if (i*2 + 2 <= JoyInfo.axises) - axisy = SDL_JoystickGetAxis(JoyInfo.dev, i*2 + 1); + if (i*2 + 2 <= JoyInfo[index].axises) + axisy = SDL_JoystickGetAxis(JoyInfo[index].dev, i*2 + 1); else axisy = 0; @@ -1247,7 +1077,7 @@ void I_GetJoystickEvents(void) axisy = axisy/32; - if (Joystick.bGamepadStyle) + if (Joystick[index].bGamepadStyle) { // gamepad control type, on or off, live or die if (axisx < -(JOYAXISRANGE/2)) @@ -1264,8 +1094,8 @@ void I_GetJoystickEvents(void) else { - axisx = JoyInfo.scale?((axisx/JoyInfo.scale)*JoyInfo.scale):axisx; - axisy = JoyInfo.scale?((axisy/JoyInfo.scale)*JoyInfo.scale):axisy; + axisx = JoyInfo[index].scale?((axisx/JoyInfo[index].scale)*JoyInfo[index].scale):axisx; + axisy = JoyInfo[index].scale?((axisy/JoyInfo[index].scale)*JoyInfo[index].scale):axisy; #ifdef SDL_JDEADZONE if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0; @@ -1289,7 +1119,7 @@ void I_GetJoystickEvents(void) */ -static int joy_open(int joyindex) +static int joy_open(int playerIndex, int joyIndex) { SDL_Joystick *newdev = NULL; int num_joy = 0; @@ -1300,7 +1130,7 @@ static int joy_open(int joyindex) return -1; } - if (joyindex <= 0) + if (joyIndex <= 0) return -1; num_joy = SDL_NumJoysticks(); @@ -1311,7 +1141,7 @@ static int joy_open(int joyindex) return -1; } - newdev = SDL_JoystickOpen(joyindex-1); + newdev = SDL_JoystickOpen(joyIndex-1); // Handle the edge case where the device <-> joystick index assignment can change due to hotplugging // This indexing is SDL's responsibility and there's not much we can do about it. @@ -1323,871 +1153,65 @@ static int joy_open(int joyindex) // 4. Unplug Controller B -> Index 0 inactive, Index 1 closed // 5. Plug Controller B -> Index 0 opened // 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B - if (JoyInfo.dev) + if (JoyInfo[playerIndex].dev) { - if (JoyInfo.dev == newdev // same device, nothing to do - || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo.dev))) // we failed, but already have a working device - return JoyInfo.axises; + if (JoyInfo[playerIndex].dev == newdev // same device, nothing to do + || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo[playerIndex].dev))) // we failed, but already have a working device + { + return JoyInfo[playerIndex].axises; + } + // Else, we're changing devices, so send neutral joy events - CONS_Debug(DBG_GAMELOGIC, "Joystick1 device is changing; resetting events...\n"); - I_ShutdownJoystick(); + CONS_Debug(DBG_GAMELOGIC, "Joystick%d device is changing; resetting events...\n", playerIndex+1); + I_ShutdownJoystick(playerIndex); } - JoyInfo.dev = newdev; + JoyInfo[playerIndex].dev = newdev; - if (JoyInfo.dev == NULL) + if (JoyInfo[playerIndex].dev == NULL) { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: Couldn't open device - %s\n"), SDL_GetError()); + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: Couldn't open device - %s\n"), playerIndex+1, SDL_GetError()); return -1; } else { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick1: %s\n"), SDL_JoystickName(JoyInfo.dev)); - JoyInfo.axises = SDL_JoystickNumAxes(JoyInfo.dev); - if (JoyInfo.axises > JOYAXISSET*2) - JoyInfo.axises = JOYAXISSET*2; - /* if (joyaxes<2) + CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick%d: %s\n"), playerIndex+1, SDL_JoystickName(JoyInfo[playerIndex].dev)); + + JoyInfo[playerIndex].axises = SDL_JoystickNumAxes(JoyInfo[playerIndex].dev); + if (JoyInfo[playerIndex].axises > JOYAXISSET*2) + JoyInfo[playerIndex].axises = JOYAXISSET*2; + + /* + if (joyaxes<2) { I_OutputMsg("Not enought axes?\n"); return 0; - }*/ - - JoyInfo.buttons = SDL_JoystickNumButtons(JoyInfo.dev); - if (JoyInfo.buttons > JOYBUTTONS) - JoyInfo.buttons = JOYBUTTONS; - - JoyInfo.hats = SDL_JoystickNumHats(JoyInfo.dev); - if (JoyInfo.hats > JOYHATS) - JoyInfo.hats = JOYHATS; - - JoyInfo.balls = SDL_JoystickNumBalls(JoyInfo.dev); - - //Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo.dev), "pad"); - - return JoyInfo.axises; - } -} - -//Joystick2 - -/** \brief Joystick 2 buttons states -*/ -static UINT64 lastjoy2buttons = 0; - -/** \brief Joystick 2 hats state -*/ -static UINT64 lastjoy2hats = 0; - -/** \brief Shuts down joystick 2 - - - \return void -*/ -void I_ShutdownJoystick2(void) -{ - INT32 i; - event_t event; - event.type = ev_keyup; - event.data2 = 0; - event.data3 = 0; - - lastjoy2buttons = lastjoy2hats = 0; - - // emulate the up of all joystick buttons - for (i = 0; i < JOYBUTTONS; i++) - { - event.data1 = KEY_2JOY1 + i; - D_PostEvent(&event); - } - - // emulate the up of all joystick hats - for (i = 0; i < JOYHATS*4; i++) - { - event.data1 = KEY_2HAT1 + i; - D_PostEvent(&event); - } - - // reset joystick position - event.type = ev_joystick2; - for (i = 0; i < JOYAXISSET; i++) - { - event.data1 = i; - D_PostEvent(&event); - } - - joystick2_started = 0; - JoyReset(&JoyInfo2); - - // don't shut down the subsystem here, because hotplugging -} - -void I_GetJoystick2Events(void) -{ - static event_t event = {0,0,0,0}; - INT32 i = 0; - UINT64 joyhats = 0; -#if 0 - INT64 joybuttons = 0; - INT32 axisx, axisy; -#endif - - if (!joystick2_started) - return; - - if (!JoyInfo2.dev) //I_ShutdownJoystick2(); - return; - - -#if 0 - //faB: look for as much buttons as g_input code supports, - // we don't use the others - for (i = JoyInfo2.buttons - 1; i >= 0; i--) - { - joybuttons <<= 1; - if (SDL_JoystickGetButton(JoyInfo2.dev,i)) - joybuttons |= 1; - } - - if (joybuttons != lastjoy2buttons) - { - INT64 j = 1; // keep only bits that changed since last time - INT64 newbuttons = joybuttons ^ lastjoy2buttons; - lastjoy2buttons = joybuttons; - - for (i = 0; i < JOYBUTTONS; i++, j <<= 1) - { - if (newbuttons & j) // button changed state? - { - if (joybuttons & j) - event.type = ev_keydown; - else - event.type = ev_keyup; - event.data1 = KEY_2JOY1 + i; - D_PostEvent(&event); - } } - } -#endif + */ - for (i = JoyInfo2.hats - 1; i >= 0; i--) - { - Uint8 hat = SDL_JoystickGetHat(JoyInfo2.dev, i); + JoyInfo[playerIndex].buttons = SDL_JoystickNumButtons(JoyInfo[playerIndex].dev); + if (JoyInfo[playerIndex].buttons > JOYBUTTONS) + JoyInfo[playerIndex].buttons = JOYBUTTONS; - if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i); - if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i); - if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i); - if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i); - } + JoyInfo[playerIndex].hats = SDL_JoystickNumHats(JoyInfo[playerIndex].dev); + if (JoyInfo[playerIndex].hats > JOYHATS) + JoyInfo[playerIndex].hats = JOYHATS; - if (joyhats != lastjoy2hats) - { - INT64 j = 1; // keep only bits that changed since last time - INT64 newhats = joyhats ^ lastjoy2hats; - lastjoy2hats = joyhats; + JoyInfo[playerIndex].balls = SDL_JoystickNumBalls(JoyInfo[playerIndex].dev); - for (i = 0; i < JOYHATS*4; i++, j <<= 1) - { - if (newhats & j) // hat changed state? - { - if (joyhats & j) - event.type = ev_keydown; - else - event.type = ev_keyup; - event.data1 = KEY_2HAT1 + i; - D_PostEvent(&event); - } - } - } + //JoyInfo[playerIndex].bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo[playerIndex].dev), "pad"); -#if 0 - // send joystick axis positions - event.type = ev_joystick2; - - for (i = JOYAXISSET - 1; i >= 0; i--) - { - event.data1 = i; - if (i*2 + 1 <= JoyInfo2.axises) - axisx = SDL_JoystickGetAxis(JoyInfo2.dev, i*2 + 0); - else axisx = 0; - if (i*2 + 2 <= JoyInfo2.axises) - axisy = SDL_JoystickGetAxis(JoyInfo2.dev, i*2 + 1); - else axisy = 0; - - // -32768 to 32767 - axisx = axisx/32; - axisy = axisy/32; - - if (Joystick2.bGamepadStyle) - { - // gamepad control type, on or off, live or die - if (axisx < -(JOYAXISRANGE/2)) - event.data2 = -1; - else if (axisx > (JOYAXISRANGE/2)) - event.data2 = 1; - else - event.data2 = 0; - if (axisy < -(JOYAXISRANGE/2)) - event.data3 = -1; - else if (axisy > (JOYAXISRANGE/2)) - event.data3 = 1; - else - event.data3 = 0; - } - else - { - - axisx = JoyInfo2.scale?((axisx/JoyInfo2.scale)*JoyInfo2.scale):axisx; - axisy = JoyInfo2.scale?((axisy/JoyInfo2.scale)*JoyInfo2.scale):axisy; - -#ifdef SDL_JDEADZONE - if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0; - if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0; -#endif - - // analog control style , just send the raw data - event.data2 = axisx; // x axis - event.data3 = axisy; // y axis - } - D_PostEvent(&event); - } -#endif -} - -/** \brief Open joystick handle - - \param fname name of joystick - - \return axises - - -*/ -static int joy_open2(int joyindex) -{ - SDL_Joystick *newdev = NULL; - int num_joy = 0; - - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - CONS_Printf(M_GetText("Joystick subsystem not started\n")); - return -1; - } - - if (joyindex <= 0) - return -1; - - num_joy = SDL_NumJoysticks(); - - if (num_joy == 0) - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - return -1; - } - - newdev = SDL_JoystickOpen(joyindex-1); - - // Handle the edge case where the device <-> joystick index assignment can change due to hotplugging - // This indexing is SDL's responsibility and there's not much we can do about it. - // - // Example: - // 1. Plug Controller A -> Index 0 opened - // 2. Plug Controller B -> Index 1 opened - // 3. Unplug Controller A -> Index 0 closed, Index 1 active - // 4. Unplug Controller B -> Index 0 inactive, Index 1 closed - // 5. Plug Controller B -> Index 0 opened - // 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B - if (JoyInfo2.dev) - { - if (JoyInfo2.dev == newdev // same device, nothing to do - || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo2.dev))) // we failed, but already have a working device - return JoyInfo.axises; - // Else, we're changing devices, so send neutral joy events - CONS_Debug(DBG_GAMELOGIC, "Joystick2 device is changing; resetting events...\n"); - I_ShutdownJoystick2(); - } - - JoyInfo2.dev = newdev; - - if (JoyInfo2.dev == NULL) - { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: couldn't open device - %s\n"), SDL_GetError()); - return -1; - } - else - { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick2: %s\n"), SDL_JoystickName(JoyInfo2.dev)); - JoyInfo2.axises = SDL_JoystickNumAxes(JoyInfo2.dev); - if (JoyInfo2.axises > JOYAXISSET*2) - JoyInfo2.axises = JOYAXISSET*2; -/* if (joyaxes<2) - { - I_OutputMsg("Not enought axes?\n"); - return 0; - }*/ - - JoyInfo2.buttons = SDL_JoystickNumButtons(JoyInfo2.dev); - if (JoyInfo2.buttons > JOYBUTTONS) - JoyInfo2.buttons = JOYBUTTONS; - - JoyInfo2.hats = SDL_JoystickNumHats(JoyInfo2.dev); - if (JoyInfo2.hats > JOYHATS) - JoyInfo2.hats = JOYHATS; - - JoyInfo2.balls = SDL_JoystickNumBalls(JoyInfo2.dev); - - //Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo2.dev), "pad"); - - return JoyInfo2.axises; - } -} - -//Joystick3 - -/** \brief Joystick 3 buttons states -*/ -static UINT64 lastjoy3buttons = 0; - -/** \brief Joystick 3 hats state -*/ -static UINT64 lastjoy3hats = 0; - -/** \brief Shuts down joystick 3 - - -\return void -*/ -void I_ShutdownJoystick3(void) -{ - INT32 i; - event_t event; - event.type = ev_keyup; - event.data2 = 0; - event.data3 = 0; - - lastjoy3buttons = lastjoy3hats = 0; - - // emulate the up of all joystick buttons - for (i = 0; i < JOYBUTTONS; i++) - { - event.data1 = KEY_3JOY1 + i; - D_PostEvent(&event); - } - - // emulate the up of all joystick hats - for (i = 0; i < JOYHATS*4; i++) - { - event.data1 = KEY_3HAT1 + i; - D_PostEvent(&event); - } - - // reset joystick position - event.type = ev_joystick3; - for (i = 0; i < JOYAXISSET; i++) - { - event.data1 = i; - D_PostEvent(&event); - } - - joystick3_started = 0; - JoyReset(&JoyInfo3); - - // don't shutdown the subsystem here, because hotplugging -} - -void I_GetJoystick3Events(void) -{ - static event_t event = {0,0,0,0}; - INT32 i = 0; - UINT64 joyhats = 0; -#if 0 - INT64 joybuttons = 0; -#endif - INT32 axisx, axisy; - - if (!joystick3_started) - return; - - if (!JoyInfo3.dev) //I_ShutdownJoystick3(); - return; - - -#if 0 - //faB: look for as much buttons as g_input code supports, - // we don't use the others - for (i = JoyInfo3.buttons - 1; i >= 0; i--) - { - joybuttons <<= 1; - if (SDL_JoystickGetButton(JoyInfo3.dev,i)) - joybuttons |= 1; - } - - if (joybuttons != lastjoy3buttons) - { - INT64 j = 1; // keep only bits that changed since last time - INT64 newbuttons = joybuttons ^ lastjoy3buttons; - lastjoy3buttons = joybuttons; - - for (i = 0; i < JOYBUTTONS; i++, j <<= 1) - { - if (newbuttons & j) // button changed state? - { - if (joybuttons & j) - event.type = ev_keydown; - else - event.type = ev_keyup; - event.data1 = KEY_3JOY1 + i; - D_PostEvent(&event); - } - } - } -#endif - - for (i = JoyInfo3.hats - 1; i >= 0; i--) - { - Uint8 hat = SDL_JoystickGetHat(JoyInfo3.dev, i); - - if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i); - if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i); - if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i); - if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i); - } - - if (joyhats != lastjoy3hats) - { - INT64 j = 1; // keep only bits that changed since last time - INT64 newhats = joyhats ^ lastjoy3hats; - lastjoy3hats = joyhats; - - for (i = 0; i < JOYHATS*4; i++, j <<= 1) - { - if (newhats & j) // hat changed state? - { - if (joyhats & j) - event.type = ev_keydown; - else - event.type = ev_keyup; - event.data1 = KEY_3HAT1 + i; - D_PostEvent(&event); - } - } - } - - // send joystick axis positions - event.type = ev_joystick3; - - for (i = JOYAXISSET - 1; i >= 0; i--) - { - event.data1 = i; - if (i*2 + 1 <= JoyInfo3.axises) - axisx = SDL_JoystickGetAxis(JoyInfo3.dev, i*2 + 0); - else axisx = 0; - if (i*2 + 2 <= JoyInfo3.axises) - axisy = SDL_JoystickGetAxis(JoyInfo3.dev, i*2 + 1); - else axisy = 0; - - // -32768 to 32767 - axisx = axisx/32; - axisy = axisy/32; - - if (Joystick3.bGamepadStyle) - { - // gamepad control type, on or off, live or die - if (axisx < -(JOYAXISRANGE/2)) - event.data2 = -1; - else if (axisx > (JOYAXISRANGE/2)) - event.data2 = 1; - else - event.data2 = 0; - if (axisy < -(JOYAXISRANGE/2)) - event.data3 = -1; - else if (axisy > (JOYAXISRANGE/2)) - event.data3 = 1; - else - event.data3 = 0; - } - else - { - - axisx = JoyInfo3.scale?((axisx/JoyInfo3.scale)*JoyInfo3.scale):axisx; - axisy = JoyInfo3.scale?((axisy/JoyInfo3.scale)*JoyInfo3.scale):axisy; - -#ifdef SDL_JDEADZONE - if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0; - if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0; -#endif - - // analog control style , just send the raw data - event.data2 = axisx; // x axis - event.data3 = axisy; // y axis - } - D_PostEvent(&event); - } - -} - -/** \brief Open joystick handle - - \param fname name of joystick - - \return axises - - -*/ -static int joy_open3(int joyindex) -{ - SDL_Joystick *newdev = NULL; - int num_joy = 0; - - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - CONS_Printf(M_GetText("Joystick subsystem not started\n")); - return -1; - } - - if (joyindex <= 0) - return -1; - - num_joy = SDL_NumJoysticks(); - - if (num_joy == 0) - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - return -1; - } - - newdev = SDL_JoystickOpen(joyindex - 1); - - // Handle the edge case where the device <-> joystick index assignment can change due to hotplugging - // This indexing is SDL's responsibility and there's not much we can do about it. - // - // Example: - // 1. Plug Controller A -> Index 0 opened - // 2. Plug Controller B -> Index 1 opened - // 3. Unplug Controller A -> Index 0 closed, Index 1 active - // 4. Unplug Controller B -> Index 0 inactive, Index 1 closed - // 5. Plug Controller B -> Index 0 opened - // 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B - if (JoyInfo3.dev) - { - if (JoyInfo3.dev == newdev // same device, nothing to do - || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo3.dev))) // we failed, but already have a working device - return JoyInfo.axises; - // Else, we're changing devices, so send neutral joy events - CONS_Debug(DBG_GAMELOGIC, "Joystick3 device is changing; resetting events...\n"); - I_ShutdownJoystick3(); - } - - JoyInfo3.dev = newdev; - - if (JoyInfo3.dev == NULL) - { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick3: couldn't open device - %s\n"), SDL_GetError()); - return -1; - } - else - { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick3: %s\n"), SDL_JoystickName(JoyInfo3.dev)); - JoyInfo3.axises = SDL_JoystickNumAxes(JoyInfo3.dev); - if (JoyInfo3.axises > JOYAXISSET * 2) - JoyInfo3.axises = JOYAXISSET * 2; - /* if (joyaxes<2) - { - I_OutputMsg("Not enought axes?\n"); - return 0; - }*/ - - JoyInfo3.buttons = SDL_JoystickNumButtons(JoyInfo3.dev); - if (JoyInfo3.buttons > JOYBUTTONS) - JoyInfo3.buttons = JOYBUTTONS; - - JoyInfo3.hats = SDL_JoystickNumHats(JoyInfo3.dev); - if (JoyInfo3.hats > JOYHATS) - JoyInfo3.hats = JOYHATS; - - JoyInfo3.balls = SDL_JoystickNumBalls(JoyInfo3.dev); - - //Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo3.dev), "pad"); - - return JoyInfo3.axises; - } -} - -//Joystick4 - -/** \brief Joystick 4 buttons states -*/ -static UINT64 lastjoy4buttons = 0; - -/** \brief Joystick 4 hats state -*/ -static UINT64 lastjoy4hats = 0; - -/** \brief Shuts down joystick 4 - - -\return void -*/ -void I_ShutdownJoystick4(void) -{ - INT32 i; - event_t event; - event.type = ev_keyup; - event.data2 = 0; - event.data3 = 0; - - lastjoy4buttons = lastjoy4hats = 0; - - // emulate the up of all joystick buttons - for (i = 0; i < JOYBUTTONS; i++) - { - event.data1 = KEY_4JOY1 + i; - D_PostEvent(&event); - } - - // emulate the up of all joystick hats - for (i = 0; i < JOYHATS*4; i++) - { - event.data1 = KEY_4HAT1 + i; - D_PostEvent(&event); - } - - // reset joystick position - event.type = ev_joystick4; - for (i = 0; i < JOYAXISSET; i++) - { - event.data1 = i; - D_PostEvent(&event); - } - - joystick4_started = 0; - JoyReset(&JoyInfo4); - - // don't shutdown the subsystem here, because hotplugging -} - -void I_GetJoystick4Events(void) -{ - static event_t event = {0,0,0,0}; - INT32 i = 0; - UINT64 joyhats = 0; -#if 0 - INT64 joybuttons = 0; -#endif - INT32 axisx, axisy; - - if (!joystick4_started) - return; - - if (!JoyInfo4.dev) //I_ShutdownJoystick4(); - return; - - -#if 0 - //faB: look for as much buttons as g_input code supports, - // we don't use the others - for (i = JoyInfo4.buttons - 1; i >= 0; i--) - { - joybuttons <<= 1; - if (SDL_JoystickGetButton(JoyInfo4.dev,i)) - joybuttons |= 1; - } - - if (joybuttons != lastjoy4buttons) - { - INT64 j = 1; // keep only bits that changed since last time - INT64 newbuttons = joybuttons ^ lastjoy4buttons; - lastjoy4buttons = joybuttons; - - for (i = 0; i < JOYBUTTONS; i++, j <<= 1) - { - if (newbuttons & j) // button changed state? - { - if (joybuttons & j) - event.type = ev_keydown; - else - event.type = ev_keyup; - event.data1 = KEY_4JOY1 + i; - D_PostEvent(&event); - } - } - } -#endif - - for (i = JoyInfo4.hats - 1; i >= 0; i--) - { - Uint8 hat = SDL_JoystickGetHat(JoyInfo4.dev, i); - - if (hat & SDL_HAT_UP ) joyhats|=(UINT64)0x1<<(0 + 4*i); - if (hat & SDL_HAT_DOWN ) joyhats|=(UINT64)0x1<<(1 + 4*i); - if (hat & SDL_HAT_LEFT ) joyhats|=(UINT64)0x1<<(2 + 4*i); - if (hat & SDL_HAT_RIGHT) joyhats|=(UINT64)0x1<<(3 + 4*i); - } - - if (joyhats != lastjoy4hats) - { - INT64 j = 1; // keep only bits that changed since last time - INT64 newhats = joyhats ^ lastjoy4hats; - lastjoy4hats = joyhats; - - for (i = 0; i < JOYHATS*4; i++, j <<= 1) - { - if (newhats & j) // hat changed state? - { - if (joyhats & j) - event.type = ev_keydown; - else - event.type = ev_keyup; - event.data1 = KEY_4HAT1 + i; - D_PostEvent(&event); - } - } - } - - // send joystick axis positions - event.type = ev_joystick4; - - for (i = JOYAXISSET - 1; i >= 0; i--) - { - event.data1 = i; - if (i*2 + 1 <= JoyInfo4.axises) - axisx = SDL_JoystickGetAxis(JoyInfo4.dev, i*2 + 0); - else axisx = 0; - if (i*2 + 2 <= JoyInfo4.axises) - axisy = SDL_JoystickGetAxis(JoyInfo4.dev, i*2 + 1); - else axisy = 0; - - // -32768 to 32767 - axisx = axisx/32; - axisy = axisy/32; - - if (Joystick4.bGamepadStyle) - { - // gamepad control type, on or off, live or die - if (axisx < -(JOYAXISRANGE/2)) - event.data2 = -1; - else if (axisx > (JOYAXISRANGE/2)) - event.data2 = 1; - else - event.data2 = 0; - if (axisy < -(JOYAXISRANGE/2)) - event.data3 = -1; - else if (axisy > (JOYAXISRANGE/2)) - event.data3 = 1; - else - event.data3 = 0; - } - else - { - - axisx = JoyInfo4.scale?((axisx/JoyInfo4.scale)*JoyInfo4.scale):axisx; - axisy = JoyInfo4.scale?((axisy/JoyInfo4.scale)*JoyInfo4.scale):axisy; - -#ifdef SDL_JDEADZONE - if (-SDL_JDEADZONE <= axisx && axisx <= SDL_JDEADZONE) axisx = 0; - if (-SDL_JDEADZONE <= axisy && axisy <= SDL_JDEADZONE) axisy = 0; -#endif - - // analog control style , just send the raw data - event.data2 = axisx; // x axis - event.data3 = axisy; // y axis - } - D_PostEvent(&event); - } - -} - -/** \brief Open joystick handle - - \param fname name of joystick - - \return axises - - -*/ -static int joy_open4(int joyindex) -{ - SDL_Joystick *newdev = NULL; - int num_joy = 0; - - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - CONS_Printf(M_GetText("Joystick subsystem not started\n")); - return -1; - } - - if (joyindex <= 0) - return -1; - - num_joy = SDL_NumJoysticks(); - - if (num_joy == 0) - { - CONS_Printf("%s", M_GetText("Found no joysticks on this system\n")); - return -1; - } - - newdev = SDL_JoystickOpen(joyindex - 1); - - // Handle the edge case where the device <-> joystick index assignment can change due to hotplugging - // This indexing is SDL's responsibility and there's not much we can do about it. - // - // Example: - // 1. Plug Controller A -> Index 0 opened - // 2. Plug Controller B -> Index 1 opened - // 3. Unplug Controller A -> Index 0 closed, Index 1 active - // 4. Unplug Controller B -> Index 0 inactive, Index 1 closed - // 5. Plug Controller B -> Index 0 opened - // 6. Plug Controller A -> Index 0 REPLACED, opened as Controller A; Index 1 is now Controller B - if (JoyInfo4.dev) - { - if (JoyInfo4.dev == newdev // same device, nothing to do - || (newdev == NULL && SDL_JoystickGetAttached(JoyInfo4.dev))) // we failed, but already have a working device - return JoyInfo.axises; - // Else, we're changing devices, so send neutral joy events - CONS_Debug(DBG_GAMELOGIC, "Joystick4 device is changing; resetting events...\n"); - I_ShutdownJoystick4(); - } - - JoyInfo4.dev = newdev; - - if (JoyInfo4.dev == NULL) - { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick4: couldn't open device - %s\n"), SDL_GetError()); - return -1; - } - else - { - CONS_Debug(DBG_GAMELOGIC, M_GetText("Joystick4: %s\n"), SDL_JoystickName(JoyInfo4.dev)); - JoyInfo4.axises = SDL_JoystickNumAxes(JoyInfo4.dev); - if (JoyInfo4.axises > JOYAXISSET * 2) - JoyInfo4.axises = JOYAXISSET * 2; - /* if (joyaxes<2) - { - I_OutputMsg("Not enought axes?\n"); - return 0; - }*/ - - JoyInfo4.buttons = SDL_JoystickNumButtons(JoyInfo4.dev); - if (JoyInfo4.buttons > JOYBUTTONS) - JoyInfo4.buttons = JOYBUTTONS; - - JoyInfo4.hats = SDL_JoystickNumHats(JoyInfo4.dev); - if (JoyInfo4.hats > JOYHATS) - JoyInfo4.hats = JOYHATS; - - JoyInfo4.balls = SDL_JoystickNumBalls(JoyInfo4.dev); - - //Joystick.bGamepadStyle = !stricmp(SDL_JoystickName(JoyInfo4.dev), "pad"); - - return JoyInfo4.axises; + return JoyInfo[playerIndex].axises; } } // // I_InitJoystick // -void I_InitJoystick(void) +void I_InitJoystick(UINT8 index) { SDL_Joystick *newjoy = NULL; + UINT8 i; //I_ShutdownJoystick(); //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); @@ -2211,168 +1235,80 @@ void I_InitJoystick(void) } } - if (cv_usejoystick.value) - newjoy = SDL_JoystickOpen(cv_usejoystick.value-1); + if (cv_usejoystick[index].value) + newjoy = SDL_JoystickOpen(cv_usejoystick[index].value-1); - if (newjoy && (JoyInfo2.dev == newjoy || JoyInfo3.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device - cv_usejoystick.value = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; - else if (newjoy && joy_open(cv_usejoystick.value) != -1) + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (i == index) + continue; + + if (JoyInfo[i].dev == newjoy) + break; + } + + if (newjoy && i < MAXSPLITSCREENPLAYERS) // don't override an active device + { + cv_usejoystick[index].value = I_GetJoystickDeviceIndex(JoyInfo[index].dev) + 1; + } + else if (newjoy && joy_open(index, cv_usejoystick[index].value) != -1) { // SDL's device indexes are unstable, so cv_usejoystick may not match // the actual device index. So let's cheat a bit and find the device's current index. - JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; - joystick_started = 1; + JoyInfo[index].oldjoy = I_GetJoystickDeviceIndex(JoyInfo[index].dev) + 1; + joystick_started[index] = 1; } else { - if (JoyInfo.oldjoy) - I_ShutdownJoystick(); - cv_usejoystick.value = 0; - joystick_started = 0; + if (JoyInfo[index].oldjoy) + I_ShutdownJoystick(index); + cv_usejoystick[index].value = 0; + joystick_started[index] = 0; } - if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (JoyInfo[i].dev == newjoy) + break; + } + + if (i == MAXSPLITSCREENPLAYERS) + { + // Joystick didn't end up being used SDL_JoystickClose(newjoy); + } +} + +void I_InitJoystick1(void) +{ + I_InitJoystick(0); } void I_InitJoystick2(void) { - SDL_Joystick *newjoy = NULL; - - //I_ShutdownJoystick2(); - //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (M_CheckParm("-nojoy")) - return; - - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - CONS_Printf("I_InitJoystick2()...\n"); - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return; - } - } - - if (cv_usejoystick2.value) - newjoy = SDL_JoystickOpen(cv_usejoystick2.value-1); - - if (newjoy && (JoyInfo.dev == newjoy || JoyInfo3.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device - cv_usejoystick2.value = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; - else if (newjoy && joy_open2(cv_usejoystick2.value) != -1) - { - // SDL's device indexes are unstable, so cv_usejoystick may not match - // the actual device index. So let's cheat a bit and find the device's current index. - JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; - joystick2_started = 1; - } - else - { - if (JoyInfo2.oldjoy) - I_ShutdownJoystick2(); - cv_usejoystick2.value = 0; - joystick2_started = 0; - } - - if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) - SDL_JoystickClose(newjoy); + I_InitJoystick(1); } void I_InitJoystick3(void) { - SDL_Joystick *newjoy = NULL; - - //I_ShutdownJoystick3(); - //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (M_CheckParm("-nojoy")) - return; - - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - CONS_Printf("I_InitJoystick3()...\n"); - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return; - } - } - - if (cv_usejoystick3.value) - newjoy = SDL_JoystickOpen(cv_usejoystick3.value - 1); - - if (newjoy && (JoyInfo.dev == newjoy || JoyInfo2.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device - cv_usejoystick3.value = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; - else if (newjoy && joy_open3(cv_usejoystick3.value) != -1) - { - // SDL's device indexes are unstable, so cv_usejoystick may not match - // the actual device index. So let's cheat a bit and find the device's current index. - JoyInfo3.oldjoy = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; - joystick3_started = 1; - } - else - { - if (JoyInfo3.oldjoy) - I_ShutdownJoystick3(); - cv_usejoystick3.value = 0; - joystick3_started = 0; - } - - if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) - SDL_JoystickClose(newjoy); + I_InitJoystick(2); } void I_InitJoystick4(void) { - SDL_Joystick *newjoy = NULL; - - //I_ShutdownJoystick4(); - //SDL_SetHintWithPriority("SDL_XINPUT_ENABLED", "0", SDL_HINT_OVERRIDE); - if (M_CheckParm("-nojoy")) - return; - - if (SDL_WasInit(SDL_INIT_JOYSTICK) == 0) - { - CONS_Printf("I_InitJoystick4()...\n"); - if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) - { - CONS_Printf(M_GetText("Couldn't initialize joystick: %s\n"), SDL_GetError()); - return; - } - } - - if (cv_usejoystick4.value) - newjoy = SDL_JoystickOpen(cv_usejoystick4.value - 1); - - if (newjoy && (JoyInfo.dev == newjoy || JoyInfo2.dev == newjoy || JoyInfo4.dev == newjoy)) // don't override an active device - cv_usejoystick4.value = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; - else if (newjoy && joy_open4(cv_usejoystick4.value) != -1) - { - // SDL's device indexes are unstable, so cv_usejoystick may not match - // the actual device index. So let's cheat a bit and find the device's current index. - JoyInfo4.oldjoy = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; - joystick4_started = 1; - } - else - { - if (JoyInfo4.oldjoy) - I_ShutdownJoystick4(); - cv_usejoystick4.value = 0; - joystick4_started = 0; - } - - if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) - SDL_JoystickClose(newjoy); + I_InitJoystick(3); } static void I_ShutdownInput(void) { + UINT8 i; + // Yes, the name is misleading: these send neutral events to // clean up the unplugged joystick's input // Note these methods are internal to this file, not called elsewhere. - I_ShutdownJoystick(); - I_ShutdownJoystick2(); - I_ShutdownJoystick3(); - I_ShutdownJoystick4(); + + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + I_ShutdownJoystick(i); if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) { @@ -2390,7 +1326,7 @@ INT32 I_NumJoys(void) return numjoy; } -static char joyname[255]; // MAX_PATH; joystick name is straight from the driver +static char joyname[255]; // joystick name is straight from the driver const char *I_GetJoyName(INT32 joyindex) { @@ -2534,337 +1470,6 @@ void I_UpdateMumble(const mobj_t *mobj, const listener_t listener) #undef WINMUMBLE #endif // NOMUMBLE -#ifdef HAVE_TERMIOS - -void I_GetMouseEvents(void) -{ - static UINT8 mdata[5]; - static INT32 i = 0,om2b = 0; - INT32 di, j, mlp, button; - event_t event; - const INT32 mswap[8] = {0, 4, 1, 5, 2, 6, 3, 7}; - - if (!mouse2_started) return; - for (mlp = 0; mlp < 20; mlp++) - { - for (; i < 5; i++) - { - di = read(fdmouse2, mdata+i, 1); - if (di == -1) return; - } - if ((mdata[0] & 0xf8) != 0x80) - { - for (j = 1; j < 5; j++) - if ((mdata[j] & 0xf8) == 0x80) - for (i = 0; i < 5-j; i++) // shift - mdata[i] = mdata[i+j]; - if (i < 5) continue; - } - else - { - button = mswap[~mdata[0] & 0x07]; - for (j = 0; j < MOUSEBUTTONS; j++) - { - if (om2b & (1<> 4); - } - else if (bytenum == 3) - { - dx = (char)((combytes[0] & 3) << 6); - dy = (char)((combytes[0] & 12) << 4); - dx = (char)(dx + combytes[1]); - dy = (char)(dy + combytes[2]); - handlermouse2x+= dx; - handlermouse2y+= dy; - } - else if (bytenum == 4) // fourth UINT8 (logitech mouses) - { - if (buffer[i] & 32) - handlermouse2buttons |= 4; - else - handlermouse2buttons &= ~4; - } - } -} - -void I_GetMouseEvents(void) -{ - static UINT8 lastbuttons2 = 0; //mouse movement - event_t event; - - if (mouse2filehandle == INVALID_HANDLE_VALUE) - return; - - I_PoolMouse2(); - // post key event for buttons - if (handlermouse2buttons != lastbuttons2) - { - INT32 i, j = 1, k; - k = (handlermouse2buttons ^ lastbuttons2); // only changed bit to 1 - lastbuttons2 = (UINT8)handlermouse2buttons; - - for (i = 0; i < MOUSEBUTTONS; i++, j <<= 1) - if (k & j) - { - if (handlermouse2buttons & j) - event.type = ev_keydown; - else - event.type = ev_keyup; - event.data1 = KEY_2MOUSE1+i; - D_PostEvent(&event); - } - } - - if (handlermouse2x != 0 || handlermouse2y != 0) - { - event.type = ev_mouse2; - event.data1 = 0; -// event.data1 = buttons; // not needed - event.data2 = handlermouse2x << 1; - event.data3 = -handlermouse2y << 1; - handlermouse2x = 0; - handlermouse2y = 0; - - D_PostEvent(&event); - } -} -#else -void I_GetMouseEvents(void){}; -#endif - -// -// I_StartupMouse2 -// -void I_StartupMouse2(void) -{ -#ifdef HAVE_TERMIOS - struct termios m2tio; - size_t i; - INT32 dtr = -1, rts = -1;; - I_ShutdownMouse2(); - if (cv_usemouse2.value == 0) return; - if ((fdmouse2 = open(cv_mouse2port.string, O_RDONLY|O_NONBLOCK|O_NOCTTY)) == -1) - { - CONS_Printf(M_GetText("Error opening %s!\n"), cv_mouse2port.string); - return; - } - tcflush(fdmouse2, TCIOFLUSH); - m2tio.c_iflag = IGNBRK; - m2tio.c_oflag = 0; - m2tio.c_cflag = CREAD|CLOCAL|HUPCL|CS8|CSTOPB|B1200; - m2tio.c_lflag = 0; - m2tio.c_cc[VTIME] = 0; - m2tio.c_cc[VMIN] = 1; - tcsetattr(fdmouse2, TCSANOW, &m2tio); - for (i = 0; i < strlen(cv_mouse2opt.string); i++) - { - if (toupper(cv_mouse2opt.string[i]) == 'D') - { - if (cv_mouse2opt.string[i+1] == '-') - dtr = 0; - else - dtr = 1; - } - if (toupper(cv_mouse2opt.string[i]) == 'R') - { - if (cv_mouse2opt.string[i+1] == '-') - rts = 0; - else - rts = 1; - } - if (dtr != -1 || rts != -1) - { - INT32 c; - if (!ioctl(fdmouse2, TIOCMGET, &c)) - { - if (!dtr) - c &= ~TIOCM_DTR; - else if (dtr > 0) - c |= TIOCM_DTR; - } - if (!rts) - c &= ~TIOCM_RTS; - else if (rts > 0) - c |= TIOCM_RTS; - ioctl(fdmouse2, TIOCMSET, &c); - } - } - mouse2_started = 1; - I_AddExitFunc(I_ShutdownMouse2); -#elif defined (_WIN32) - DCB dcb; - - if (mouse2filehandle != INVALID_HANDLE_VALUE) - I_ShutdownMouse2(); - - if (cv_usemouse2.value == 0) - return; - - if (mouse2filehandle == INVALID_HANDLE_VALUE) - { - // COM file handle - mouse2filehandle = CreateFileA(cv_mouse2port.string, GENERIC_READ | GENERIC_WRITE, - 0, // exclusive access - NULL, // no security attrs - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (mouse2filehandle == INVALID_HANDLE_VALUE) - { - INT32 e = GetLastError(); - if (e == 5) - CONS_Alert(CONS_ERROR, M_GetText("Can't open %s: Access denied\n"), cv_mouse2port.string); - else - CONS_Alert(CONS_ERROR, M_GetText("Can't open %s: error %d\n"), cv_mouse2port.string, e); - return; - } - } - - // getevent when somthing happens - //SetCommMask(mouse2filehandle, EV_RXCHAR); - - // buffers - SetupComm(mouse2filehandle, MOUSECOMBUFFERSIZE, MOUSECOMBUFFERSIZE); - - // purge buffers - PurgeComm(mouse2filehandle, PURGE_TXABORT | PURGE_RXABORT - | PURGE_TXCLEAR | PURGE_RXCLEAR); - - // setup port to 1200 7N1 - dcb.DCBlength = sizeof (DCB); - - GetCommState(mouse2filehandle, &dcb); - - dcb.BaudRate = CBR_1200; - dcb.ByteSize = 7; - dcb.Parity = NOPARITY; - dcb.StopBits = ONESTOPBIT; - - dcb.fDtrControl = DTR_CONTROL_ENABLE; - dcb.fRtsControl = RTS_CONTROL_ENABLE; - - dcb.fBinary = TRUE; - dcb.fParity = TRUE; - - SetCommState(mouse2filehandle, &dcb); - I_AddExitFunc(I_ShutdownMouse2); -#endif -} - // // I_Tactile // @@ -2896,40 +1501,38 @@ void I_Tactile4(FFType pFFType, const JoyFF_t *FFEffect) (void)FFEffect; } +static ticcmd_t emptycmd[MAXSPLITSCREENPLAYERS]; + /** \brief empty ticcmd for player 1 */ -static ticcmd_t emptycmd; ticcmd_t *I_BaseTiccmd(void) { - return &emptycmd; + return &emptycmd[0]; } /** \brief empty ticcmd for player 2 */ -static ticcmd_t emptycmd2; ticcmd_t *I_BaseTiccmd2(void) { - return &emptycmd2; + return &emptycmd[1]; } /** \brief empty ticcmd for player 3 */ -static ticcmd_t emptycmd3; ticcmd_t *I_BaseTiccmd3(void) { - return &emptycmd3; + return &emptycmd[2]; } /** \brief empty ticcmd for player 4 */ -static ticcmd_t emptycmd4; ticcmd_t *I_BaseTiccmd4(void) { - return &emptycmd4; + return &emptycmd[3]; } #if defined (_WIN32) @@ -2944,9 +1547,11 @@ static p_timeGetTime pfntimeGetTime = NULL; // but lower precision on Windows NT // --------- -tic_t I_GetTime(void) +DWORD TimeFunction(int requested_frequency) { - tic_t newtics = 0; + DWORD newtics = 0; + // this var acts as a multiplier if sub-millisecond precision is asked but is not available + int excess_frequency = requested_frequency / 1000; if (!starttickcount) // high precision timer { @@ -2966,7 +1571,7 @@ tic_t I_GetTime(void) if (frequency.LowPart && QueryPerformanceCounter(&currtime)) { - newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * NEWTICRATE + newtics = (INT32)((currtime.QuadPart - basetime.QuadPart) * requested_frequency / frequency.QuadPart); } else if (pfntimeGetTime) @@ -2974,11 +1579,19 @@ tic_t I_GetTime(void) currtime.LowPart = pfntimeGetTime(); if (!basetime.LowPart) basetime.LowPart = currtime.LowPart; - newtics = ((currtime.LowPart - basetime.LowPart)/(1000/NEWTICRATE)); + if (requested_frequency > 1000) + newtics = currtime.LowPart - basetime.LowPart * excess_frequency; + else + newtics = (currtime.LowPart - basetime.LowPart)/(1000/requested_frequency); } } else - newtics = (GetTickCount() - starttickcount)/(1000/NEWTICRATE); + { + if (requested_frequency > 1000) + newtics = (GetTickCount() - starttickcount) * excess_frequency; + else + newtics = (GetTickCount() - starttickcount)/(1000/requested_frequency); + } return newtics; } @@ -3000,7 +1613,9 @@ static void I_ShutdownTimer(void) // I_GetTime // returns time in 1/TICRATE second tics // -tic_t I_GetTime (void) + +// millisecond precision only +int TimeFunction(int requested_frequency) { static Uint64 basetime = 0; Uint64 ticks = SDL_GetTicks(); @@ -3010,14 +1625,24 @@ tic_t I_GetTime (void) ticks -= basetime; - ticks = (ticks*TICRATE); + ticks = (ticks*requested_frequency); ticks = (ticks/1000); - return (tic_t)ticks; + return ticks; } #endif +tic_t I_GetTime(void) +{ + return TimeFunction(NEWTICRATE); +} + +int I_GetTimeMicros(void) +{ + return TimeFunction(1000000); +} + // //I_StartupTimer // @@ -3167,7 +1792,6 @@ void I_Quit(void) if (quiting) goto death; SDLforceUngrabMouse(); quiting = SDL_FALSE; - I_ShutdownConsole(); M_SaveConfig(NULL); //save game config, cvars.. #ifndef NONET D_SaveBan(); // save the ban list @@ -3177,19 +1801,20 @@ void I_Quit(void) if (Playing()) K_PlayerForfeit(consoleplayer, true); - G_SaveGameData(false); // Tails 12-08-2002 + G_SaveGameData(); // Tails 12-08-2002 //added:16-02-98: when recording a demo, should exit using 'q' key, // but sometimes we forget and use 'F10'.. so save here too. if (demo.recording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); D_QuitNetGame(); + CL_AbortDownloadResume(); + M_FreePlayerSetupColors(); I_ShutdownMusic(); I_ShutdownSound(); - I_ShutdownCD(); // use this for 1.28 19990220 by Kin I_ShutdownGraphics(); I_ShutdownInput(); @@ -3250,19 +1875,17 @@ void I_Error(const char *error, ...) if (errorcount == 3) I_ShutdownSound(); if (errorcount == 4) - I_ShutdownCD(); - if (errorcount == 5) I_ShutdownGraphics(); - if (errorcount == 6) + if (errorcount == 5) I_ShutdownInput(); - if (errorcount == 7) + if (errorcount == 6) I_ShutdownSystem(); - if (errorcount == 8) + if (errorcount == 7) SDL_Quit(); - if (errorcount == 9) + if (errorcount == 8) { M_SaveConfig(NULL); - G_SaveGameData(false); + G_SaveGameData(); } if (errorcount > 20) { @@ -3290,27 +1913,27 @@ void I_Error(const char *error, ...) I_OutputMsg("\nI_Error(): %s\n", buffer); // --- - I_ShutdownConsole(); - M_SaveConfig(NULL); // save game config, cvars.. #ifndef NONET D_SaveBan(); // save the ban list #endif - G_SaveGameData(false); // Tails 12-08-2002 + G_SaveGameData(); // Tails 12-08-2002 + + // Shutdown. Here might be other errors. /* Prevent segmentation fault if testers go to Record Attack... */ #ifndef TESTERS - // Shutdown. Here might be other errors. if (demo.recording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); #endif D_QuitNetGame(); + CL_AbortDownloadResume(); + M_FreePlayerSetupColors(); I_ShutdownMusic(); I_ShutdownSound(); - I_ShutdownCD(); // use this for 1.28 19990220 by Kin I_ShutdownGraphics(); I_ShutdownInput(); @@ -3383,7 +2006,7 @@ void I_RemoveExitFunc(void (*func)()) } } -#ifndef __unix__ +#if !(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)) static void Shittycopyerror(const char *name) { I_OutputMsg( @@ -3397,16 +2020,16 @@ static void Shittylogcopy(void) { char buf[8192]; FILE *fp; - size_t n; + size_t r; if (fseek(logstream, 0, SEEK_SET) == -1) { Shittycopyerror("fseek"); } else if (( fp = fopen(logfilename, "wt") )) { - while (( n = fread(buf, 1, sizeof buf, logstream) )) + while (( r = fread(buf, 1, sizeof buf, logstream) )) { - if (fwrite(buf, 1, n, fp) < n) + if (fwrite(buf, 1, r, fp) < r) { Shittycopyerror("fwrite"); break; @@ -3423,7 +2046,7 @@ static void Shittylogcopy(void) Shittycopyerror(logfilename); } } -#endif/*__unix__*/ +#endif/*!(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON))*/ // // Closes down everything. This includes restoring the initial @@ -3447,7 +2070,7 @@ void I_ShutdownSystem(void) if (logstream) { I_OutputMsg("I_ShutdownSystem(): end of logstream.\n"); -#ifndef __unix__ +#if !(defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON)) Shittylogcopy(); #endif fclose(logstream); @@ -3465,7 +2088,7 @@ void I_GetDiskFreeSpace(INT64 *freespace) return; #else // Both Linux and BSD have this, apparently. struct statfs stfs; - if (statfs(".", &stfs) == -1) + if (statfs(srb2home, &stfs) == -1) { *freespace = INT32_MAX; return; @@ -3484,7 +2107,7 @@ void I_GetDiskFreeSpace(INT64 *freespace) } if (pfnGetDiskFreeSpaceEx) { - if (pfnGetDiskFreeSpaceEx(NULL, &lfreespace, &usedbytes, NULL)) + if (pfnGetDiskFreeSpaceEx(srb2home, &lfreespace, &usedbytes, NULL)) *freespace = lfreespace.QuadPart; else *freespace = INT32_MAX; @@ -3540,7 +2163,7 @@ char *I_GetUserName(void) INT32 I_mkdir(const char *dirname, INT32 unixright) { //[segabor] -#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (__CYGWIN__) || defined (__OS2__) +#if defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) || defined (__CYGWIN__) return mkdir(dirname, unixright); #elif defined (_WIN32) UNREFERENCED_PARAMETER(unixright); /// \todo should implement ntright under nt... @@ -3590,10 +2213,10 @@ const char *I_ClipboardPaste(void) if (!SDL_HasClipboardText()) return NULL; + clipboard_contents = SDL_GetClipboardText(); - memcpy(clipboard_modified, clipboard_contents, 255); + strlcpy(clipboard_modified, clipboard_contents, 256); SDL_free(clipboard_contents); - clipboard_modified[255] = 0; while (*i) { @@ -3678,6 +2301,7 @@ static const char *searchWad(const char *searchDir) /** \brief go through all possible paths and look for main.kart \return path to main.kart if any + */ static const char *locateWad(void) { @@ -3698,6 +2322,18 @@ static const char *locateWad(void) #endif +#ifdef DEFAULTDIR + I_OutputMsg(",HOME/" DEFAULTDIR); + // examine user jart directory + if ((envstr = I_GetEnv("HOME")) != NULL) + { + sprintf(returnWadPath, "%s" PATHSEP DEFAULTDIR, envstr); + if (isWadPathOk(returnWadPath)) + return returnWadPath; + } +#endif + + #ifdef CMAKECONFIG #ifndef NDEBUG I_OutputMsg(","CMAKE_ASSETS_DIR); @@ -3897,16 +2533,6 @@ UINT32 I_GetFreeMem(UINT32 *total) if (total) *total = (UINT32)info.dwTotalPhys; return (UINT32)info.dwAvailPhys; -#elif defined (__OS2__) - UINT32 pr_arena; - - if (total) - DosQuerySysInfo( QSV_TOTPHYSMEM, QSV_TOTPHYSMEM, - (PVOID) total, sizeof (UINT32)); - DosQuerySysInfo( QSV_MAXPRMEM, QSV_MAXPRMEM, - (PVOID) &pr_arena, sizeof (UINT32)); - - return pr_arena; #elif defined (__linux__) /* Linux */ char buf[1024]; @@ -4044,4 +2670,5 @@ const CPUInfoFlags *I_CPUInfo(void) // note CPUAFFINITY code used to reside here void I_RegisterSysCommands(void) {} -#endif + +#endif // HAVE_SDL diff --git a/src/sdl/i_threads.c b/src/sdl/i_threads.c index 078f4e0f4..3b1c20b9a 100644 --- a/src/sdl/i_threads.c +++ b/src/sdl/i_threads.c @@ -1,4 +1,4 @@ -// SONIC ROBO BLAST 2 KART +// SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2020 by James R. // diff --git a/src/sdl/i_video.c b/src/sdl/i_video.c index 7630f705c..5a9db4963 100644 --- a/src/sdl/i_video.c +++ b/src/sdl/i_video.c @@ -4,7 +4,7 @@ // // Copyright (C) 1993-1996 by id Software, Inc. // Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 2014-2018 by Sonic Team Junior. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -20,6 +20,7 @@ /// \brief SRB2 graphics stuff for SDL #include +#include #include @@ -32,6 +33,7 @@ #include "SDL.h" #ifdef _MSC_VER +#include #pragma warning(default : 4214 4244) #endif @@ -41,7 +43,7 @@ #ifdef HAVE_IMAGE #include "SDL_image.h" -#elif 1 +#elif defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) // Windows doesn't need this, as SDL will do it for us. #define LOAD_XPM //I want XPM! #include "IMG_xpm.c" //Alam: I don't want to add SDL_Image.dll/so #define HAVE_IMAGE //I have SDL_Image, sortof @@ -67,10 +69,13 @@ #include "../i_sound.h" // midi pause/unpause #include "../i_joy.h" #include "../st_stuff.h" +#include "../hu_stuff.h" #include "../g_game.h" #include "../i_video.h" #include "../console.h" #include "../command.h" +#include "../r_main.h" +#include "../lua_hook.h" #include "sdlmain.h" #include "../i_system.h" #ifdef HWRENDER @@ -81,6 +86,10 @@ #include "ogl_sdl.h" #endif +#ifdef HAVE_DISCORDRPC +#include "../discord.h" +#endif + // maximum number of windowed modes (see windowedModes[][]) #define MAXWINMODES (18) @@ -92,15 +101,18 @@ static INT32 numVidModes = -1; */ static char vidModeName[33][32]; // allow 33 different modes -rendermode_t rendermode=render_soft; +rendermode_t rendermode = render_soft; +static rendermode_t chosenrendermode = render_soft; // set by command line arguments boolean highcolor = false; // synchronize page flipping with screen refresh -consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_stretch = {"stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, NULL); +static consvar_t cv_stretch = CVAR_INIT ("stretch", "Off", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL); +static consvar_t cv_alwaysgrabmouse = CVAR_INIT ("alwaysgrabmouse", "Off", CV_SAVE, CV_OnOff, NULL); UINT8 graphics_started = 0; // Is used in console.c and screen.c +INT32 vid_opengl_state = 0; // To disable fullscreen at startup; is set in VID_PrepareModeList boolean allow_fullscreen = false; @@ -172,7 +184,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen); //static void Impl_SetWindowName(const char *title); static void Impl_SetWindowIcon(void); -static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) +static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen, SDL_bool reposition) { static SDL_bool wasfullscreen = SDL_FALSE; Uint32 rmask; @@ -201,16 +213,18 @@ static void SDLSetMode(INT32 width, INT32 height, SDL_bool fullscreen) } // Reposition window only in windowed mode SDL_SetWindowSize(window, width, height); - SDL_SetWindowPosition(window, - SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)), - SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)) - ); + if (reposition) + { + SDL_SetWindowPosition(window, + SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)), + SDL_WINDOWPOS_CENTERED_DISPLAY(SDL_GetWindowDisplayIndex(window)) + ); + } } } else { Impl_CreateWindow(fullscreen); - Impl_SetWindowIcon(); wasfullscreen = fullscreen; SDL_SetWindowSize(window, width, height); if (fullscreen) @@ -354,6 +368,20 @@ static INT32 Impl_SDL_Scancode_To_Keycode(SDL_Scancode code) return 0; } +static boolean IgnoreMouse(void) +{ + if (cv_alwaysgrabmouse.value) + return false; + if (menuactive) + return !M_MouseNeeded(); + if (paused || con_destlines || chat_on) + return true; + if (gamestate != GS_LEVEL && gamestate != GS_INTERMISSION && + gamestate != GS_CONTINUING && gamestate != GS_CUTSCENE) + return true; + return false; +} + static void SDLdoGrabMouse(void) { SDL_ShowCursor(SDL_DISABLE); @@ -373,12 +401,15 @@ static void SDLdoUngrabMouse(void) void SDLforceUngrabMouse(void) { if (SDL_WasInit(SDL_INIT_VIDEO)==SDL_INIT_VIDEO && window != NULL) - { - SDL_ShowCursor(SDL_ENABLE); - SDL_SetWindowGrab(window, SDL_FALSE); - wrapmouseok = SDL_FALSE; - SDL_SetRelativeMouseMode(SDL_FALSE); - } + SDLdoUngrabMouse(); +} + +void I_UpdateMouseGrab(void) +{ + if (SDL_WasInit(SDL_INIT_VIDEO) == SDL_INIT_VIDEO && window != NULL + && SDL_GetMouseFocus() == window && SDL_GetKeyboardFocus() == window + && USE_MOUSEINPUT && !IgnoreMouse()) + SDLdoGrabMouse(); } static void VID_Command_NumModes_f (void) @@ -502,7 +533,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) INT32 raxis = axis/32; if (which == ev_joystick) { - if (Joystick.bGamepadStyle) + if (Joystick[0].bGamepadStyle) { // gamepad control type, on or off, live or die if (raxis < -(JOYAXISRANGE/2)) @@ -514,7 +545,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) } else { - raxis = JoyInfo.scale!=1?((raxis/JoyInfo.scale)*JoyInfo.scale):raxis; + raxis = JoyInfo[0].scale!=1?((raxis/JoyInfo[0].scale)*JoyInfo[0].scale):raxis; #ifdef SDL_JDEADZONE if (-SDL_JDEADZONE <= raxis && raxis <= SDL_JDEADZONE) @@ -524,7 +555,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) } else if (which == ev_joystick2) { - if (Joystick2.bGamepadStyle) + if (Joystick[1].bGamepadStyle) { // gamepad control type, on or off, live or die if (raxis < -(JOYAXISRANGE/2)) @@ -535,7 +566,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) } else { - raxis = JoyInfo2.scale!=1?((raxis/JoyInfo2.scale)*JoyInfo2.scale):raxis; + raxis = JoyInfo[1].scale!=1?((raxis/JoyInfo[1].scale)*JoyInfo[1].scale):raxis; #ifdef SDL_JDEADZONE if (-SDL_JDEADZONE <= raxis && raxis <= SDL_JDEADZONE) @@ -545,7 +576,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) } else if (which == ev_joystick3) { - if (Joystick3.bGamepadStyle) + if (Joystick[2].bGamepadStyle) { // gamepad control type, on or off, live or die if (raxis < -(JOYAXISRANGE/2)) @@ -556,7 +587,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) } else { - raxis = JoyInfo3.scale!=1?((raxis/JoyInfo3.scale)*JoyInfo3.scale):raxis; + raxis = JoyInfo[2].scale!=1?((raxis/JoyInfo[2].scale)*JoyInfo[2].scale):raxis; #ifdef SDL_JDEADZONE if (-SDL_JDEADZONE <= raxis && raxis <= SDL_JDEADZONE) @@ -566,7 +597,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) } else if (which == ev_joystick4) { - if (Joystick4.bGamepadStyle) + if (Joystick[3].bGamepadStyle) { // gamepad control type, on or off, live or die if (raxis < -(JOYAXISRANGE/2)) @@ -577,7 +608,7 @@ static INT32 SDLJoyAxis(const Sint16 axis, evtype_t which) } else { - raxis = JoyInfo4.scale!=1?((raxis/JoyInfo4.scale)*JoyInfo4.scale):raxis; + raxis = JoyInfo[3].scale!=1?((raxis/JoyInfo[3].scale)*JoyInfo[3].scale):raxis; #ifdef SDL_JDEADZONE if (-SDL_JDEADZONE <= raxis && raxis <= SDL_JDEADZONE) @@ -620,7 +651,7 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) window_notinfocus = false; if (!paused) - I_ResumeSong(); //resume it + S_ResumeAudio(); //resume it if (cv_gamesounds.value) S_EnableSound(); @@ -630,6 +661,9 @@ static void Impl_HandleWindowEvent(SDL_WindowEvent evt) if (cv_usemouse.value) I_StartupMouse(); } //else firsttimeonmouse = SDL_FALSE; + + if (USE_MOUSEINPUT && !IgnoreMouse()) + SDLdoGrabMouse(); } else if (!mousefocus && !kbfocus) { @@ -675,11 +709,14 @@ static void Impl_HandleKeyboardEvent(SDL_KeyboardEvent evt, Uint32 type) static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) { + static boolean firstmove = true; + if (USE_MOUSEINPUT) { - if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window)) + if ((SDL_GetMouseFocus() != window && SDL_GetKeyboardFocus() != window) || (IgnoreMouse() && !firstmove)) { SDLdoUngrabMouse(); + firstmove = false; return; } @@ -693,6 +730,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) mousemovey += -evt.yrel; SDL_SetWindowGrab(window, SDL_TRUE); } + firstmove = false; return; } @@ -700,6 +738,7 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) // of the screen then ignore it. if ((evt.x == realwidth/2) && (evt.y == realheight/2)) { + firstmove = false; return; } @@ -712,6 +751,8 @@ static void Impl_HandleMouseMotionEvent(SDL_MouseMotionEvent evt) SDLdoGrabMouse(); } } + + firstmove = false; } static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type) @@ -725,7 +766,7 @@ static void Impl_HandleMouseButtonEvent(SDL_MouseButtonEvent evt, Uint32 type) // this apparently makes a mouse button down event but not a mouse button up event, // resulting in whatever key was pressed down getting "stuck" if we don't ignore it. // -- Monster Iestyn (28/05/18) - if (SDL_GetMouseFocus() != window) + if (SDL_GetMouseFocus() != window || IgnoreMouse()) return; /// \todo inputEvent.button.which @@ -787,13 +828,12 @@ static void Impl_HandleMouseWheelEvent(SDL_MouseWheelEvent evt) static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt) { event_t event; - SDL_JoystickID joyid[4]; + SDL_JoystickID joyid[MAXSPLITSCREENPLAYERS]; + UINT8 i; // Determine the Joystick IDs for each current open joystick - joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev); - joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev); - joyid[2] = SDL_JoystickInstanceID(JoyInfo3.dev); - joyid[3] = SDL_JoystickInstanceID(JoyInfo4.dev); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + joyid[i] = SDL_JoystickInstanceID(JoyInfo[i].dev); evt.axis++; event.data1 = event.data2 = event.data3 = INT32_MAX; @@ -837,11 +877,12 @@ static void Impl_HandleJoystickAxisEvent(SDL_JoyAxisEvent evt) static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt) { event_t event; - SDL_JoystickID joyid[2]; + SDL_JoystickID joyid[MAXSPLITSCREENPLAYERS]; + UINT8 i; // Determine the Joystick IDs for each current open joystick - joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev); - joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + joyid[i] = SDL_JoystickInstanceID(JoyInfo[i].dev); if (evt.hat >= JOYHATS) return; // ignore hats with too high an index @@ -854,6 +895,14 @@ static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt) { event.data1 = KEY_2HAT1 + (evt.hat*4); } + else if (evt.which == joyid[2]) + { + event.data1 = KEY_3HAT1 + (evt.hat*4); + } + else if (evt.which == joyid[3]) + { + event.data1 = KEY_4HAT1 + (evt.hat*4); + } else return; // NOTE: UNFINISHED @@ -863,13 +912,12 @@ static void Impl_HandleJoystickHatEvent(SDL_JoyHatEvent evt) static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type) { event_t event; - SDL_JoystickID joyid[4]; + SDL_JoystickID joyid[MAXSPLITSCREENPLAYERS]; + UINT8 i; // Determine the Joystick IDs for each current open joystick - joyid[0] = SDL_JoystickInstanceID(JoyInfo.dev); - joyid[1] = SDL_JoystickInstanceID(JoyInfo2.dev); - joyid[2] = SDL_JoystickInstanceID(JoyInfo3.dev); - joyid[3] = SDL_JoystickInstanceID(JoyInfo4.dev); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + joyid[i] = SDL_JoystickInstanceID(JoyInfo[i].dev); if (evt.which == joyid[0]) { @@ -912,10 +960,13 @@ static void Impl_HandleJoystickButtonEvent(SDL_JoyButtonEvent evt, Uint32 type) void I_GetEvent(void) { SDL_Event evt; + // We only want the first motion event, // otherwise we'll end up catching the warp back to center. //int mouseMotionOnce = 0; + UINT8 i; + if (!graphics_started) { return; @@ -980,77 +1031,42 @@ void I_GetEvent(void) // * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! //////////////////////////////////////////////////////////// - ////////////////////////////// - // PLAYER 1 - ////////////////////////////// - - if (newjoy && (!JoyInfo.dev || !SDL_JoystickGetAttached(JoyInfo.dev)) - && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - cv_usejoystick.value = evt.jdevice.which + 1; - I_UpdateJoystickDeviceIndices(1); - } + if (newjoy && (!JoyInfo[i].dev || !SDL_JoystickGetAttached(JoyInfo[i].dev))) + { + UINT8 j; - ////////////////////////////// - // PLAYER 2 - ////////////////////////////// + for (j = 0; j < MAXSPLITSCREENPLAYERS; j++) + { + if (i == j) + continue; - else if (newjoy && (!JoyInfo2.dev || !SDL_JoystickGetAttached(JoyInfo2.dev)) - && JoyInfo.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device - { - cv_usejoystick2.value = evt.jdevice.which + 1; - I_UpdateJoystickDeviceIndices(2); - } + if (JoyInfo[j].dev == newjoy) + break; + } - ////////////////////////////// - // PLAYER 3 - ////////////////////////////// - - else if (newjoy && (!JoyInfo3.dev || !SDL_JoystickGetAttached(JoyInfo3.dev)) - && JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo4.dev != newjoy) // don't override a currently active device - { - cv_usejoystick3.value = evt.jdevice.which + 1; - I_UpdateJoystickDeviceIndices(3); - } - - ////////////////////////////// - // PLAYER 4 - ////////////////////////////// - - else if (newjoy && (!JoyInfo4.dev || !SDL_JoystickGetAttached(JoyInfo4.dev)) - && JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy) // don't override a currently active device - { - cv_usejoystick4.value = evt.jdevice.which + 1; - I_UpdateJoystickDeviceIndices(4); + if (j == MAXSPLITSCREENPLAYERS) + { + // ensures we aren't overriding a currently active device + cv_usejoystick[i].value = evt.jdevice.which + 1; + I_UpdateJoystickDeviceIndices(0); + } + } } //////////////////////////////////////////////////////////// // Was cv_usejoystick disabled in settings? //////////////////////////////////////////////////////////// - if (!strcmp(cv_usejoystick.string, "0") || !cv_usejoystick.value) - cv_usejoystick.value = 0; - else if (atoi(cv_usejoystick.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys - && cv_usejoystick.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick, cv_usejoystick.value); - - if (!strcmp(cv_usejoystick2.string, "0") || !cv_usejoystick2.value) - cv_usejoystick2.value = 0; - else if (atoi(cv_usejoystick2.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys - && cv_usejoystick2.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); - - if (!strcmp(cv_usejoystick3.string, "0") || !cv_usejoystick3.value) - cv_usejoystick3.value = 0; - else if (atoi(cv_usejoystick3.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys - && cv_usejoystick3.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick3, cv_usejoystick3.value); - - if (!strcmp(cv_usejoystick4.string, "0") || !cv_usejoystick4.value) - cv_usejoystick4.value = 0; - else if (atoi(cv_usejoystick4.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys - && cv_usejoystick4.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick4, cv_usejoystick4.value); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (!strcmp(cv_usejoystick[i].string, "0") || !cv_usejoystick[i].value) + cv_usejoystick[i].value = 0; + else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick[i].value) // update the cvar ONLY if a device exists + CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value); + } //////////////////////////////////////////////////////////// // Update all joysticks' init states @@ -1059,23 +1075,25 @@ void I_GetEvent(void) // if the device is already active, this should do nothing, effectively. //////////////////////////////////////////////////////////// - I_InitJoystick(); - I_InitJoystick2(); - I_InitJoystick3(); - I_InitJoystick4(); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + I_InitJoystick(i); //////////////////////////////////////////////////////////// - CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); - CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); - CONS_Debug(DBG_GAMELOGIC, "Joystick3 device index: %d\n", JoyInfo3.oldjoy); - CONS_Debug(DBG_GAMELOGIC, "Joystick4 device index: %d\n", JoyInfo4.oldjoy); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy); // update the menu if (currentMenu == &OP_JoystickSetDef) M_SetupJoystickMenu(0); - if (JoyInfo.dev != newjoy && JoyInfo2.dev != newjoy && JoyInfo3.dev != newjoy && JoyInfo4.dev != newjoy) + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (JoyInfo[i].dev == newjoy) + break; + } + + if (i == MAXSPLITSCREENPLAYERS) SDL_JoystickClose(newjoy); } break; @@ -1083,28 +1101,13 @@ void I_GetEvent(void) //////////////////////////////////////////////////////////// case SDL_JOYDEVICEREMOVED: - if (JoyInfo.dev && !SDL_JoystickGetAttached(JoyInfo.dev)) + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) { - CONS_Debug(DBG_GAMELOGIC, "Joystick1 removed, device index: %d\n", JoyInfo.oldjoy); - I_ShutdownJoystick(); - } - - if (JoyInfo2.dev && !SDL_JoystickGetAttached(JoyInfo2.dev)) - { - CONS_Debug(DBG_GAMELOGIC, "Joystick2 removed, device index: %d\n", JoyInfo2.oldjoy); - I_ShutdownJoystick2(); - } - - if (JoyInfo3.dev && !SDL_JoystickGetAttached(JoyInfo3.dev)) - { - CONS_Debug(DBG_GAMELOGIC, "Joystick3 removed, device index: %d\n", JoyInfo3.oldjoy); - I_ShutdownJoystick3(); - } - - if (JoyInfo4.dev && !SDL_JoystickGetAttached(JoyInfo4.dev)) - { - CONS_Debug(DBG_GAMELOGIC, "Joystick4 removed, device index: %d\n", JoyInfo4.oldjoy); - I_ShutdownJoystick4(); + if (JoyInfo[i].dev && !SDL_JoystickGetAttached(JoyInfo[i].dev)) + { + CONS_Debug(DBG_GAMELOGIC, "Joystick%d removed, device index: %d\n", i+1, JoyInfo[i].oldjoy); + I_ShutdownJoystick(i); + } } //////////////////////////////////////////////////////////// @@ -1113,132 +1116,41 @@ void I_GetEvent(void) // * BUT: If that default index is being occupied, use ANOTHER cv_usejoystick's default value! //////////////////////////////////////////////////////////// - if (JoyInfo.dev) - cv_usejoystick.value = JoyInfo.oldjoy = I_GetJoystickDeviceIndex(JoyInfo.dev) + 1; - else if (atoi(cv_usejoystick.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy) - cv_usejoystick.value = atoi(cv_usejoystick.string); - else if (atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy) - cv_usejoystick.value = atoi(cv_usejoystick2.string); - else if (atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy) - cv_usejoystick.value = atoi(cv_usejoystick3.string); - else if (atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy) - cv_usejoystick.value = atoi(cv_usejoystick4.string); - else // we tried... - cv_usejoystick.value = 0; - - if (JoyInfo2.dev) - cv_usejoystick2.value = JoyInfo2.oldjoy = I_GetJoystickDeviceIndex(JoyInfo2.dev) + 1; - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy) - cv_usejoystick2.value = atoi(cv_usejoystick.string); - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy) - cv_usejoystick2.value = atoi(cv_usejoystick2.string); - else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy) - cv_usejoystick2.value = atoi(cv_usejoystick3.string); - else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy - && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy) - cv_usejoystick2.value = atoi(cv_usejoystick4.string); - else // we tried... - cv_usejoystick2.value = 0; - - if (JoyInfo3.dev) - cv_usejoystick3.value = JoyInfo3.oldjoy = I_GetJoystickDeviceIndex(JoyInfo3.dev) + 1; - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick.string) != JoyInfo4.oldjoy) - cv_usejoystick3.value = atoi(cv_usejoystick.string); - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick2.string) != JoyInfo4.oldjoy) - cv_usejoystick3.value = atoi(cv_usejoystick2.string); - else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick3.string) != JoyInfo4.oldjoy) - cv_usejoystick3.value = atoi(cv_usejoystick3.string); - else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick4.string) != JoyInfo4.oldjoy) - cv_usejoystick3.value = atoi(cv_usejoystick4.string); - else // we tried... - cv_usejoystick3.value = 0; - - if (JoyInfo4.dev) - cv_usejoystick4.value = JoyInfo4.oldjoy = I_GetJoystickDeviceIndex(JoyInfo4.dev) + 1; - else if (atoi(cv_usejoystick.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick.string) != JoyInfo3.oldjoy) - cv_usejoystick4.value = atoi(cv_usejoystick.string); - else if (atoi(cv_usejoystick2.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick2.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick2.string) != JoyInfo3.oldjoy) - cv_usejoystick4.value = atoi(cv_usejoystick2.string); - else if (atoi(cv_usejoystick3.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick3.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick3.string) != JoyInfo3.oldjoy) - cv_usejoystick4.value = atoi(cv_usejoystick3.string); - else if (atoi(cv_usejoystick4.string) != JoyInfo.oldjoy - && atoi(cv_usejoystick4.string) != JoyInfo2.oldjoy - && atoi(cv_usejoystick4.string) != JoyInfo3.oldjoy) - cv_usejoystick4.value = atoi(cv_usejoystick4.string); - else // we tried... - cv_usejoystick4.value = 0; + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + I_UpdateJoystickDeviceIndex(i); + } //////////////////////////////////////////////////////////// // Was cv_usejoystick disabled in settings? //////////////////////////////////////////////////////////// - if (!strcmp(cv_usejoystick.string, "0")) - cv_usejoystick.value = 0; - else if (atoi(cv_usejoystick.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys - && cv_usejoystick.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick, cv_usejoystick.value); - - if (!strcmp(cv_usejoystick2.string, "0")) - cv_usejoystick2.value = 0; - else if (atoi(cv_usejoystick2.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys - && cv_usejoystick2.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick2, cv_usejoystick2.value); - - if (!strcmp(cv_usejoystick3.string, "0")) - cv_usejoystick3.value = 0; - else if (atoi(cv_usejoystick3.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys - && cv_usejoystick3.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick3, cv_usejoystick3.value); - - if (!strcmp(cv_usejoystick4.string, "0")) - cv_usejoystick4.value = 0; - else if (atoi(cv_usejoystick4.string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys - && cv_usejoystick4.value) // update the cvar ONLY if a device exists - CV_SetValue(&cv_usejoystick4, cv_usejoystick4.value); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + { + if (!strcmp(cv_usejoystick[i].string, "0")) + { + cv_usejoystick[i].value = 0; + } + else if (atoi(cv_usejoystick[i].string) <= I_NumJoys() // don't mess if we intentionally set higher than NumJoys + && cv_usejoystick[i].value) // update the cvar ONLY if a device exists + { + CV_SetValue(&cv_usejoystick[i], cv_usejoystick[i].value); + } + } //////////////////////////////////////////////////////////// - CONS_Debug(DBG_GAMELOGIC, "Joystick1 device index: %d\n", JoyInfo.oldjoy); - CONS_Debug(DBG_GAMELOGIC, "Joystick2 device index: %d\n", JoyInfo2.oldjoy); - CONS_Debug(DBG_GAMELOGIC, "Joystick3 device index: %d\n", JoyInfo3.oldjoy); - CONS_Debug(DBG_GAMELOGIC, "Joystick4 device index: %d\n", JoyInfo4.oldjoy); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + CONS_Debug(DBG_GAMELOGIC, "Joystick%d device index: %d\n", i+1, JoyInfo[i].oldjoy); // update the menu if (currentMenu == &OP_JoystickSetDef) M_SetupJoystickMenu(0); break; case SDL_QUIT: + if (Playing()) + LUAh_GameQuit(); I_Quit(); - M_QuitResponse('y'); break; } } @@ -1275,7 +1187,7 @@ void I_StartupMouse(void) } else firsttimeonmouse = SDL_FALSE; - if (cv_usemouse.value) + if (cv_usemouse.value && !IgnoreMouse()) SDLdoGrabMouse(); else SDLdoUngrabMouse(); @@ -1287,20 +1199,17 @@ void I_StartupMouse(void) void I_OsPolling(void) { SDL_Keymod mod; + UINT8 i; if (consolevent) I_GetConsoleEvents(); if (SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK) { SDL_JoystickUpdate(); - I_GetJoystickEvents(); - I_GetJoystick2Events(); - I_GetJoystick3Events(); - I_GetJoystick4Events(); + for (i = 0; i < MAXSPLITSCREENPLAYERS; i++) + I_GetJoystickEvents(i); } - I_GetMouseEvents(); - I_GetEvent(); mod = SDL_GetModState(); @@ -1413,6 +1322,18 @@ void I_FinishUpdate(void) } } + if (marathonmode) + SCR_DisplayMarathonInfo(); + + // draw captions if enabled + if (cv_closedcaptioning.value) + SCR_ClosedCaptions(); + +#ifdef HAVE_DISCORDRPC + if (discordRequestList != NULL) + ST_AskToJoinEnvelope(); +#endif + if (rendermode == render_soft && screens[0]) { SDL_Rect rect; @@ -1438,7 +1359,6 @@ void I_FinishUpdate(void) SDL_RenderCopy(renderer, texture, NULL, NULL); SDL_RenderPresent(renderer); } - #ifdef HWRENDER else if (rendermode == render_opengl) { @@ -1638,39 +1558,122 @@ void VID_PrepareModeList(void) #endif } -INT32 VID_SetMode(INT32 modeNum) +static SDL_bool Impl_CreateContext(void) { - SDLdoUngrabMouse(); - - vid.recalc = 1; - vid.bpp = 1; - - if (modeNum >= 0 && modeNum < MAXWINMODES) + // Renderer-specific stuff +#ifdef HWRENDER + if ((rendermode == render_opengl) && (vid_opengl_state != -1)) { - vid.width = windowedModes[modeNum][0]; - vid.height = windowedModes[modeNum][1]; - vid.modenum = modeNum; + if (!sdlglcontext) + sdlglcontext = SDL_GL_CreateContext(window); + if (sdlglcontext == NULL) + { + SDL_DestroyWindow(window); + I_Error("Failed to create a GL context: %s\n", SDL_GetError()); + } + SDL_GL_MakeCurrent(window, sdlglcontext); } else +#endif + if (rendermode == render_soft) { - // just set the desktop resolution as a fallback - SDL_DisplayMode mode; - SDL_GetWindowDisplayMode(window, &mode); - if (mode.w >= 2048) - { - vid.width = 1920; - vid.height = 1200; - } - else - { - vid.width = mode.w; - vid.height = mode.h; - } - vid.modenum = -1; - } - //Impl_SetWindowName("SRB2Kart "VERSIONSTRING); + int flags = 0; // Use this to set SDL_RENDERER_* flags now + if (usesdl2soft) + flags |= SDL_RENDERER_SOFTWARE; + else if (cv_vidwait.value) + flags |= SDL_RENDERER_PRESENTVSYNC; - SDLSetMode(vid.width, vid.height, USE_FULLSCREEN); + if (!renderer) + renderer = SDL_CreateRenderer(window, -1, flags); + if (renderer == NULL) + { + CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError()); + return SDL_FALSE; + } + SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); + } + return SDL_TRUE; +} + +void VID_CheckGLLoaded(rendermode_t oldrender) +{ + (void)oldrender; +#ifdef HWRENDER + if (vid_opengl_state == -1) // Well, it didn't work the first time anyway. + { + CONS_Alert(CONS_ERROR, "OpenGL never loaded\n"); + rendermode = oldrender; + if (chosenrendermode == render_opengl) // fallback to software + rendermode = render_soft; + if (setrenderneeded) + { + CV_StealthSetValue(&cv_renderer, oldrender); + setrenderneeded = 0; + } + } +#endif +} + +void VID_CheckRenderer(void) +{ + boolean rendererchanged = false; + boolean contextcreated = false; + rendermode_t oldrenderer = rendermode; + + if (dedicated) + return; + + if (setrenderneeded) + { + rendermode = setrenderneeded; + rendererchanged = true; + +#ifdef HWRENDER + if (rendermode == render_opengl) + { + VID_CheckGLLoaded(oldrenderer); + + // Initialise OpenGL before calling SDLSetMode!!! + // This is because SDLSetMode calls OglSdlSurface. + if (vid_opengl_state == 0) + { + VID_StartupOpenGL(); + // Loaded successfully! + if (vid_opengl_state == 1) + { + // Destroy the current window, if it exists. + if (window) + { + SDL_DestroyWindow(window); + window = NULL; + } + + // Destroy the current window rendering context, if that also exists. + if (renderer) + { + SDL_DestroyRenderer(renderer); + renderer = NULL; + } + + // Create a new window. + Impl_CreateWindow(USE_FULLSCREEN); + + // From there, the OpenGL context was already created. + contextcreated = true; + } + } + else if (vid_opengl_state == -1) + rendererchanged = false; + } +#endif + + if (!contextcreated) + Impl_CreateContext(); + + setrenderneeded = 0; + } + + SDLSetMode(vid.width, vid.height, USE_FULLSCREEN, (rendererchanged ? SDL_FALSE : SDL_TRUE)); Impl_VideoSetupBuffer(); if (rendermode == render_soft) @@ -1680,8 +1683,48 @@ INT32 VID_SetMode(INT32 modeNum) SDL_FreeSurface(bufSurface); bufSurface = NULL; } - } + if (rendererchanged) + { +#ifdef HWRENDER + if (vid_opengl_state == 1) // Only if OpenGL ever loaded! + HWR_FreeTextureCache(); +#endif + SCR_SetDrawFuncs(); + } + } +#ifdef HWRENDER + else if (rendermode == render_opengl) + { + if (rendererchanged) + { + R_InitHardwareMode(); + V_SetPalette(0); + } + } +#else + (void)oldrenderer; +#endif +} + +INT32 VID_SetMode(INT32 modeNum) +{ + SDLdoUngrabMouse(); + + vid.recalc = 1; + vid.bpp = 1; + + if (modeNum < 0) + modeNum = 0; + if (modeNum >= MAXWINMODES) + modeNum = MAXWINMODES-1; + + vid.width = windowedModes[modeNum][0]; + vid.height = windowedModes[modeNum][1]; + vid.modenum = modeNum; + + //Impl_SetWindowName("SRB2Kart "VERSIONSTRING); + VID_CheckRenderer(); return SDL_TRUE; } @@ -1702,7 +1745,7 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) flags |= SDL_WINDOW_BORDERLESS; #ifdef HWRENDER - if (rendermode == render_opengl) + if (vid_opengl_state == 1) flags |= SDL_WINDOW_OPENGL; #endif @@ -1710,44 +1753,16 @@ static SDL_bool Impl_CreateWindow(SDL_bool fullscreen) window = SDL_CreateWindow("SRB2Kart "VERSIONSTRING, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, realwidth, realheight, flags); + if (window == NULL) { CONS_Printf(M_GetText("Couldn't create window: %s\n"), SDL_GetError()); return SDL_FALSE; } - // Renderer-specific stuff -#ifdef HWRENDER - if (rendermode == render_opengl) - { - sdlglcontext = SDL_GL_CreateContext(window); - if (sdlglcontext == NULL) - { - SDL_DestroyWindow(window); - I_Error("Failed to create a GL context: %s\n", SDL_GetError()); - } - SDL_GL_MakeCurrent(window, sdlglcontext); - } - else -#endif - if (rendermode == render_soft) - { - flags = 0; // Use this to set SDL_RENDERER_* flags now - if (usesdl2soft) - flags |= SDL_RENDERER_SOFTWARE; - else if (cv_vidwait.value) - flags |= SDL_RENDERER_PRESENTVSYNC; + Impl_SetWindowIcon(); - renderer = SDL_CreateRenderer(window, -1, flags); - if (renderer == NULL) - { - CONS_Printf(M_GetText("Couldn't create rendering context: %s\n"), SDL_GetError()); - return SDL_FALSE; - } - SDL_RenderSetLogicalSize(renderer, BASEVIDWIDTH, BASEVIDHEIGHT); - } - - return SDL_TRUE; + return Impl_CreateContext(); } /* @@ -1763,12 +1778,8 @@ static void Impl_SetWindowName(const char *title) static void Impl_SetWindowIcon(void) { - if (window == NULL || icoSurface == NULL) - { - return; - } - //SDL2STUB(); // Monster Iestyn: why is this stubbed? - SDL_SetWindowIcon(window, icoSurface); + if (window && icoSurface) + SDL_SetWindowIcon(window, icoSurface); } static void Impl_VideoSetupSDLBuffer(void) @@ -1802,17 +1813,14 @@ static void Impl_VideoSetupSDLBuffer(void) static void Impl_VideoSetupBuffer(void) { // Set up game's software render buffer - //if (rendermode == render_soft) + vid.rowbytes = vid.width * vid.bpp; + vid.direct = NULL; + if (vid.buffer) + free(vid.buffer); + vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS); + if (!vid.buffer) { - vid.rowbytes = vid.width * vid.bpp; - vid.direct = NULL; - if (vid.buffer) - free(vid.buffer); - vid.buffer = calloc(vid.rowbytes*vid.height, NUMSCREENS); - if (!vid.buffer) - { - I_Error("%s", M_GetText("Not enough memory for video buffer\n")); - } + I_Error("%s", M_GetText("Not enough memory for video buffer\n")); } } @@ -1832,6 +1840,7 @@ void I_StartupGraphics(void) COM_AddCommand ("vid_mode", VID_Command_Mode_f); CV_RegisterVar (&cv_vidwait); CV_RegisterVar (&cv_stretch); + CV_RegisterVar (&cv_alwaysgrabmouse); disable_mouse = M_CheckParm("-nomouse"); disable_fullscreen = M_CheckParm("-win") ? 1 : 0; @@ -1856,63 +1865,30 @@ void I_StartupGraphics(void) )) framebuffer = SDL_TRUE; } - if (M_CheckParm("-software")) - rendermode = render_soft; + #ifdef HWRENDER - else if (M_CheckParm("-opengl")) - rendermode = render_opengl; + if (M_CheckParm("-opengl")) + chosenrendermode = rendermode = render_opengl; + else if (M_CheckParm("-software")) #endif + chosenrendermode = rendermode = render_soft; usesdl2soft = M_CheckParm("-softblit"); borderlesswindow = M_CheckParm("-borderless"); //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY>>1,SDL_DEFAULT_REPEAT_INTERVAL<<2); VID_Command_ModeList_f(); + #ifdef HWRENDER - if (rendermode == render_opengl) - { - HWD.pfnInit = hwSym("Init",NULL); - HWD.pfnFinishUpdate = NULL; - HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); - HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); - HWD.pfnSetBlend = hwSym("SetBlend",NULL); - HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); - HWD.pfnSetTexture = hwSym("SetTexture",NULL); - HWD.pfnReadRect = hwSym("ReadRect",NULL); - HWD.pfnGClipRect = hwSym("GClipRect",NULL); - HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); - HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); - HWD.pfnSetPalette = hwSym("SetPalette",NULL); - HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); - HWD.pfnDrawModel = hwSym("DrawModel",NULL); - HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); - HWD.pfnSetTransform = hwSym("SetTransform",NULL); - HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); - HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); - HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); - HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); - HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); - HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); - HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); - HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); - HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); + if (M_CheckParm("-nogl")) + vid_opengl_state = -1; // Don't startup OpenGL + else if (chosenrendermode == render_opengl) + VID_StartupOpenGL(); +#endif - HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); - - HWD.pfnLoadShaders = hwSym("LoadShaders",NULL); - HWD.pfnKillShaders = hwSym("KillShaders",NULL); - HWD.pfnSetShader = hwSym("SetShader",NULL); - HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); - - HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); - HWD.pfnInitCustomShaders = hwSym("InitCustomShaders",NULL); - - HWD.pfnStartBatching = hwSym("StartBatching",NULL); - HWD.pfnRenderBatches = hwSym("RenderBatches",NULL); - - if (!HWD.pfnInit()) // load the OpenGL library - rendermode = render_soft; - } + // Window icon +#ifdef HAVE_IMAGE + icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm); #endif // Fury: we do window initialization after GL setup to allow @@ -1933,11 +1909,6 @@ void I_StartupGraphics(void) #ifdef HAVE_TTF I_ShutdownTTF(); #endif - // Window icon -#ifdef HAVE_IMAGE - icoSurface = IMG_ReadXPMFromArray(SDL_icon_xpm); -#endif - Impl_SetWindowIcon(); VID_SetMode(VID_GetModeForSize(BASEVIDWIDTH, BASEVIDHEIGHT)); @@ -1962,16 +1933,67 @@ void I_StartupGraphics(void) SDL_RaiseWindow(window); if (mousegrabok && !disable_mouse) - { - SDL_ShowCursor(SDL_DISABLE); - SDL_SetRelativeMouseMode(SDL_TRUE); - wrapmouseok = SDL_TRUE; - SDL_SetWindowGrab(window, SDL_TRUE); - } + SDLdoGrabMouse(); graphics_started = true; } +void VID_StartupOpenGL(void) +{ +#ifdef HWRENDER + static boolean glstartup = false; + if (!glstartup) + { + CONS_Printf("VID_StartupOpenGL()...\n"); + HWD.pfnInit = hwSym("Init",NULL); + HWD.pfnFinishUpdate = NULL; + HWD.pfnDraw2DLine = hwSym("Draw2DLine",NULL); + HWD.pfnDrawPolygon = hwSym("DrawPolygon",NULL); + HWD.pfnDrawIndexedTriangles = hwSym("DrawIndexedTriangles",NULL); + HWD.pfnRenderSkyDome = hwSym("RenderSkyDome",NULL); + HWD.pfnSetBlend = hwSym("SetBlend",NULL); + HWD.pfnClearBuffer = hwSym("ClearBuffer",NULL); + HWD.pfnSetTexture = hwSym("SetTexture",NULL); + HWD.pfnUpdateTexture = hwSym("UpdateTexture",NULL); + HWD.pfnReadRect = hwSym("ReadRect",NULL); + HWD.pfnGClipRect = hwSym("GClipRect",NULL); + HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache",NULL); + HWD.pfnSetSpecialState = hwSym("SetSpecialState",NULL); + HWD.pfnSetPalette = hwSym("SetPalette",NULL); + HWD.pfnGetTextureUsed = hwSym("GetTextureUsed",NULL); + HWD.pfnDrawModel = hwSym("DrawModel",NULL); + HWD.pfnCreateModelVBOs = hwSym("CreateModelVBOs",NULL); + HWD.pfnSetTransform = hwSym("SetTransform",NULL); + HWD.pfnPostImgRedraw = hwSym("PostImgRedraw",NULL); + HWD.pfnFlushScreenTextures=hwSym("FlushScreenTextures",NULL); + HWD.pfnStartScreenWipe = hwSym("StartScreenWipe",NULL); + HWD.pfnEndScreenWipe = hwSym("EndScreenWipe",NULL); + HWD.pfnDoScreenWipe = hwSym("DoScreenWipe",NULL); + HWD.pfnDrawIntermissionBG=hwSym("DrawIntermissionBG",NULL); + HWD.pfnMakeScreenTexture= hwSym("MakeScreenTexture",NULL); + HWD.pfnMakeScreenFinalTexture=hwSym("MakeScreenFinalTexture",NULL); + HWD.pfnDrawScreenFinalTexture=hwSym("DrawScreenFinalTexture",NULL); + + HWD.pfnCompileShaders = hwSym("CompileShaders",NULL); + HWD.pfnCleanShaders = hwSym("CleanShaders",NULL); + HWD.pfnSetShader = hwSym("SetShader",NULL); + HWD.pfnUnSetShader = hwSym("UnSetShader",NULL); + + HWD.pfnSetShaderInfo = hwSym("SetShaderInfo",NULL); + HWD.pfnLoadCustomShader = hwSym("LoadCustomShader",NULL); + + vid_opengl_state = HWD.pfnInit() ? 1 : -1; // let load the OpenGL library + + if (vid_opengl_state == -1) + { + rendermode = render_soft; + setrenderneeded = 0; + } + glstartup = true; + } +#endif +} + void I_ShutdownGraphics(void) { const rendermode_t oldrendermode = rendermode; diff --git a/src/sdl/macosx/Srb2mac.pbproj/project.pbxproj b/src/sdl/macosx/Srb2mac.pbproj/project.pbxproj index ee0bf4697..909bb2ced 100644 --- a/src/sdl/macosx/Srb2mac.pbproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.pbproj/project.pbxproj @@ -1113,13 +1113,6 @@ path = ../../hardware/hw_md2.h; refType = 2; }; - 84177743085A106C000C01D8 = { - fileEncoding = 30; - isa = PBXFileReference; - name = hw_trick.c; - path = ../../hardware/hw_trick.c; - refType = 2; - }; 84177744085A106C000C01D8 = { fileEncoding = 30; isa = PBXFileReference; diff --git a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj index 00930bfb3..04f8ecc0a 100644 --- a/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj +++ b/src/sdl/macosx/Srb2mac.xcodeproj/project.pbxproj @@ -19,7 +19,6 @@ 1E44AE800B67CC2B00BAD059 /* hw_draw.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E44AE6C0B67CC2B00BAD059 /* hw_draw.c */; }; 1E44AE820B67CC2B00BAD059 /* hw_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E44AE6E0B67CC2B00BAD059 /* hw_main.c */; }; 1E44AE840B67CC2B00BAD059 /* hw_md2.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E44AE700B67CC2B00BAD059 /* hw_md2.c */; }; - 1E44AE860B67CC2B00BAD059 /* hw_trick.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E44AE720B67CC2B00BAD059 /* hw_trick.c */; }; 1E44AEA40B67CC8500BAD059 /* d_clisrv.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E44AE8D0B67CC8400BAD059 /* d_clisrv.c */; }; 1E44AEA70B67CC8500BAD059 /* d_main.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E44AE900B67CC8400BAD059 /* d_main.c */; }; 1E44AEA80B67CC8500BAD059 /* d_net.c in Sources */ = {isa = PBXBuildFile; fileRef = 1E44AE910B67CC8500BAD059 /* d_net.c */; }; @@ -191,7 +190,6 @@ 1E44AE6F0B67CC2B00BAD059 /* hw_main.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_main.h; path = ../../hardware/hw_main.h; sourceTree = SOURCE_ROOT; }; 1E44AE700B67CC2B00BAD059 /* hw_md2.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = hw_md2.c; path = ../../hardware/hw_md2.c; sourceTree = SOURCE_ROOT; }; 1E44AE710B67CC2B00BAD059 /* hw_md2.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hw_md2.h; path = ../../hardware/hw_md2.h; sourceTree = SOURCE_ROOT; }; - 1E44AE720B67CC2B00BAD059 /* hw_trick.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = hw_trick.c; path = ../../hardware/hw_trick.c; sourceTree = SOURCE_ROOT; }; 1E44AE730B67CC2B00BAD059 /* hws_data.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = hws_data.h; path = ../../hardware/hws_data.h; sourceTree = SOURCE_ROOT; }; 1E44AE8A0B67CC6000BAD059 /* asm_defs.inc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.pascal; name = asm_defs.inc; path = ../../asm_defs.inc; sourceTree = SOURCE_ROOT; }; 1E44AE8D0B67CC8400BAD059 /* d_clisrv.c */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.c; name = d_clisrv.c; path = ../../d_clisrv.c; sourceTree = SOURCE_ROOT; }; @@ -544,7 +542,6 @@ 1E44AE6F0B67CC2B00BAD059 /* hw_main.h */, 1E44AE700B67CC2B00BAD059 /* hw_md2.c */, 1E44AE710B67CC2B00BAD059 /* hw_md2.h */, - 1E44AE720B67CC2B00BAD059 /* hw_trick.c */, 1E44AE730B67CC2B00BAD059 /* hws_data.h */, ); name = Hw_Hardware; @@ -1078,7 +1075,6 @@ 1E44AE800B67CC2B00BAD059 /* hw_draw.c in Sources */, 1E44AE820B67CC2B00BAD059 /* hw_main.c in Sources */, 1E44AE840B67CC2B00BAD059 /* hw_md2.c in Sources */, - 1E44AE860B67CC2B00BAD059 /* hw_trick.c in Sources */, 1E44AEA40B67CC8500BAD059 /* d_clisrv.c in Sources */, 1E44AEA70B67CC8500BAD059 /* d_main.c in Sources */, 1E44AEA80B67CC8500BAD059 /* d_net.c in Sources */, @@ -1217,7 +1213,7 @@ C01FCF4B08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.24; + CURRENT_PROJECT_VERSION = 2.2.6; GCC_PREPROCESSOR_DEFINITIONS = ( "$(inherited)", NORMALSRB2, @@ -1229,7 +1225,7 @@ C01FCF4C08A954540054247B /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - CURRENT_PROJECT_VERSION = 2.1.24; + CURRENT_PROJECT_VERSION = 2.2.6; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -1270,7 +1266,6 @@ HAVE_SDL, HAVE_MIXER, HAVE_PNG, - HAVE_BLUA, LUA_USE_POSIX, COMPVERSION, HWRENDER, @@ -1393,7 +1388,6 @@ HAVE_SDL, HAVE_MIXER, HAVE_PNG, - HAVE_BLUA, LUA_USE_POSIX, COMPVERSION, HWRENDER, diff --git a/src/sdl/mixer_sound.c b/src/sdl/mixer_sound.c index 77fcc0914..6c669f415 100644 --- a/src/sdl/mixer_sound.c +++ b/src/sdl/mixer_sound.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2014-2018 by Sonic Team Junior. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -9,7 +9,28 @@ /// \file /// \brief SDL Mixer interface for sound +#ifdef HAVE_LIBGME +#ifdef HAVE_ZLIB +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include +#endif // HAVE_ZLIB +#endif // HAVE_LIBGME + #include "../doomdef.h" +#include "../doomstat.h" // menuactive #if defined(HAVE_SDL) && defined(HAVE_MIXER) && SOUND==SOUND_MIXER @@ -34,7 +55,11 @@ write netcode into the sound code, OKAY? #pragma warning(default : 4214 4244) #endif +#ifdef HAVE_MIXERX +#include "SDL_mixer_ext.h" +#else #include "SDL_mixer.h" +#endif /* This is the version number macro for the current SDL_mixer version: */ #ifndef SDL_MIXER_COMPILEDVERSION @@ -58,33 +83,28 @@ write netcode into the sound code, OKAY? #include "gme/gme.h" #define GME_TREBLE 5.0f #define GME_BASS 1.0f - -#ifdef HAVE_ZLIB -#ifndef _MSC_VER -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif -#endif - -#ifndef _LFS64_LARGEFILE -#define _LFS64_LARGEFILE -#endif - -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 0 -#endif - -#include "zlib.h" -#endif // HAVE_ZLIB #endif // HAVE_LIBGME +static UINT16 BUFFERSIZE = 2048; +static UINT16 SAMPLERATE = 44100; + +#ifdef HAVE_OPENMPT +#include "libopenmpt/libopenmpt.h" +#endif + +/// ------------------------ +/// Audio Declarations +/// ------------------------ + UINT8 sound_started = false; static UINT32 stutter_threshold_user; static UINT32 stutter_threshold; static Mix_Music *music; -static UINT8 music_volume, sfx_volume, internal_volume; +static int music_volume; +static int sfx_volume; +static int internal_volume; static float loop_point; static float song_length; // length in seconds static boolean songpaused; @@ -101,16 +121,25 @@ static UINT32 fading_timer; static UINT32 fading_duration; static INT32 fading_id; static void (*fading_callback)(void); +static boolean fading_nocleanup; #ifdef HAVE_LIBGME static Music_Emu *gme; -static INT32 current_track; +static UINT16 current_track; +#endif + +#ifdef HAVE_OPENMPT +static int mod_err = OPENMPT_ERROR_OK; +static const char *mod_err_str; +static UINT16 current_subsong; +static size_t probesize; +static int result; #endif static void var_cleanup(void) { - loop_point = song_length =\ - music_bytes = fading_source = fading_target =\ + song_length = loop_point = 0.0f; + music_bytes = fading_source = fading_target =\ fading_timer = fading_duration = 0; music_end_bytes = 0; music_stutter_bytes = 0; @@ -118,18 +147,48 @@ static void var_cleanup(void) songpaused = is_looping =\ is_fading = false; - fading_callback = NULL; + // HACK: See music_loop, where we want the fade timing to proceed after a non-looping + // song has stopped playing + if (!fading_nocleanup) + fading_callback = NULL; + else + fading_nocleanup = false; // use it once, set it back immediately internal_volume = 100; } +#if defined (HAVE_LIBGME) && defined (HAVE_ZLIB) +static const char* get_zlib_error(int zErr) +{ + switch (zErr) + { + case Z_ERRNO: + return "Z_ERRNO"; + case Z_STREAM_ERROR: + return "Z_STREAM_ERROR"; + case Z_DATA_ERROR: + return "Z_DATA_ERROR"; + case Z_MEM_ERROR: + return "Z_MEM_ERROR"; + case Z_BUF_ERROR: + return "Z_BUF_ERROR"; + case Z_VERSION_ERROR: + return "Z_VERSION_ERROR"; + default: + return "unknown error"; + } +} +#endif + /// ------------------------ /// Audio System /// ------------------------ void I_StartupSound(void) { - I_Assert(!sound_started); + //I_Assert(!sound_started); + if (sound_started) + return; #ifdef _WIN32 // Force DirectSound instead of WASAPI @@ -150,22 +209,29 @@ void I_StartupSound(void) return; } + fading_nocleanup = false; + var_cleanup(); music = NULL; music_volume = sfx_volume = 0; #if SDL_MIXER_VERSION_ATLEAST(1,2,11) - Mix_Init(MIX_INIT_FLAC|MIX_INIT_MOD|MIX_INIT_MP3|MIX_INIT_OGG); + Mix_Init(MIX_INIT_FLAC|MIX_INIT_MP3|MIX_INIT_OGG|MIX_INIT_MOD); #endif - if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 2048) < 0) + if (Mix_OpenAudio(SAMPLERATE, AUDIO_S16SYS, 2, BUFFERSIZE) < 0) { CONS_Alert(CONS_ERROR, "Error starting SDL_Mixer: %s\n", Mix_GetError()); // call to start audio failed -- we do not have it return; } +#ifdef HAVE_OPENMPT + CONS_Printf("libopenmpt version: %s\n", openmpt_get_string("library_version")); + CONS_Printf("libopenmpt build date: %s\n", openmpt_get_string("build")); +#endif + sound_started = true; songpaused = false; Mix_AllocateChannels(256); @@ -188,6 +254,10 @@ void I_ShutdownSound(void) if (gme) gme_delete(gme); #endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + openmpt_module_destroy(openmpt_mhandle); +#endif } void I_UpdateSound(void) @@ -198,6 +268,15 @@ void I_UpdateSound(void) /// SFX /// ------------------------ +static int +get_real_sfx_volume (int vol) +{ + const int scale = SOUND_VOLUME_RANGE / MIX_MAX_VOLUME; + const int divider = VOLUME_DIVIDER * scale; + const int volume = ( vol + 1 ) / divider * sfx_volume / 100; + return volume; +} + // this is as fast as I can possibly make it. // sorry. more asm needed. static Mix_Chunk *ds2chunk(void *stream) @@ -361,7 +440,7 @@ void *I_GetSfx(sfxinfo_t *sfx) zErr = inflate(&stream, Z_FINISH); if (zErr == Z_STREAM_END) { // Run GME on new data - if (!gme_open_data(inflatedData, inflatedLen, &emu, 44100)) + if (!gme_open_data(inflatedData, inflatedLen, &emu, SAMPLERATE)) { short *mem; UINT32 len; @@ -375,7 +454,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = malloc(len); + mem = Z_Malloc(len, PU_SOUND, 0); gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); @@ -384,58 +463,18 @@ void *I_GetSfx(sfxinfo_t *sfx) } } else - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg); - } + CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg); (void)inflateEnd(&stream); } else // Hold up, zlib's got a problem - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg); - } + CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg); Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up #else return NULL; // No zlib support #endif } // Try to read it as a GME sound - else if (!gme_open_data(lump, sfx->length, &emu, 44100)) + else if (!gme_open_data(lump, sfx->length, &emu, SAMPLERATE)) { short *mem; UINT32 len; @@ -448,7 +487,7 @@ void *I_GetSfx(sfxinfo_t *sfx) gme_track_info(emu, &info, 0); len = (info->play_length * 441 / 10) << 2; - mem = malloc(len); + mem = Z_Malloc(len, PU_SOUND, 0); gme_play(emu, len >> 1, mem); gme_free_info(info); gme_delete(emu); @@ -493,7 +532,8 @@ void I_FreeSfx(sfxinfo_t *sfx) INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) { - UINT8 volume = (((UINT16)vol + 1) * (UINT16)sfx_volume) / 62; // (256 * 31) / 62 == 127 + //UINT8 volume = (((UINT16)vol + 1) * (UINT16)sfx_volume) / 62; // (256 * 31) / 62 == 127 + UINT8 volume = get_real_sfx_volume(vol); INT32 handle = Mix_PlayChannel(channel, S_sfx[id].data, 0); Mix_Volume(handle, volume); Mix_SetPanning(handle, min((UINT16)(0xff-sep)<<1, 0xff), min((UINT16)(sep)<<1, 0xff)); @@ -514,13 +554,14 @@ boolean I_SoundIsPlaying(INT32 handle) void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch) { - UINT8 volume = (((UINT16)vol + 1) * (UINT16)sfx_volume) / 62; // (256 * 31) / 62 == 127 + //UINT8 volume = (((UINT16)vol + 1) * (UINT16)sfx_volume) / 62; // (256 * 31) / 62 == 127 + UINT8 volume = get_real_sfx_volume(vol); Mix_Volume(handle, volume); Mix_SetPanning(handle, min((UINT16)(0xff-sep)<<1, 0xff), min((UINT16)(sep)<<1, 0xff)); (void)pitch; } -void I_SetSfxVolume(UINT8 volume) +void I_SetSfxVolume(int volume) { sfx_volume = volume; } @@ -529,18 +570,13 @@ void I_SetSfxVolume(UINT8 volume) /// Music Utilities /// ------------------------ -static UINT32 get_real_volume(UINT8 volume) +static int attenuate(int scale) { -#ifdef _WIN32 - if (I_SongType() == MU_MID) - // HACK: Until we stop using native MIDI, - // disable volume changes - return ((UINT32)31*128/31); // volume = 31 - else -#endif - // convert volume to mixer's 128 scale - // then apply internal_volume as a percentage - return ((UINT32)volume*128/31) * (UINT32)internal_volume / 100; + // attenuate scale by all volumes as percentages + return scale + * musicdef_volume / 100 + * internal_volume / 100 + * music_volume / 100; } static UINT32 get_adjusted_position(UINT32 position) @@ -600,7 +636,7 @@ static void count_music_bytes(int chan, void *stream, int len, void *udata) (void)stream; (void)udata; - if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID) + if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD) return; music_bytes += len; @@ -615,10 +651,18 @@ static void music_loop(void) music_end_bytes = music_bytes; Mix_PlayMusic(music, 0); Mix_SetMusicPosition(loop_point); - music_bytes = loop_point*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + music_bytes = (UINT32)(loop_point*44100.0L*4); //assume 44.1khz, 4-byte length (see I_GetSongPosition) } else + { + // HACK: Let fade timing proceed beyond the end of a + // non-looping song. This is a specific case where the timing + // should persist after stopping a song, so I don't believe + // this should apply every time the user stops a song. + // This is auto-unset in var_cleanup, called by I_StopSong + fading_nocleanup = true; I_StopSong(); + } } static UINT32 music_fade(UINT32 interval, void *param) @@ -638,7 +682,7 @@ static UINT32 music_fade(UINT32 interval, void *param) else if ((fading_timer -= 10) <= 0) { internal_volume = fading_target; - Mix_VolumeMusic(get_real_volume(music_volume)); + Mix_VolumeMusic(attenuate(MIX_MAX_VOLUME)); I_StopFadingSong(); do_fading_callback(); return 0; @@ -651,7 +695,7 @@ static UINT32 music_fade(UINT32 interval, void *param) internal_volume = max(min(internal_volume, fading_source - FixedMul(delta, factor)), fading_target); else if (fading_target > fading_source) internal_volume = min(max(internal_volume, fading_source + FixedMul(delta, factor)), fading_target); - Mix_VolumeMusic(get_real_volume(music_volume)); + Mix_VolumeMusic(attenuate(MIX_MAX_VOLUME)); return interval; } } @@ -673,7 +717,27 @@ static void mix_gme(void *udata, Uint8 *stream, int len) // apply volume to stream for (i = 0, p = (short *)stream; i < len/2; i++, p++) - *p = ((INT32)*p) * (music_volume*internal_volume/100)*2 / 42; + *p = attenuate(*p); +} +#endif + +#ifdef HAVE_OPENMPT +static void mix_openmpt(void *udata, Uint8 *stream, int len) +{ + int i; + short *p; + + (void)udata; + + if (!openmpt_mhandle || songpaused) + return; + + // Play module into stream + openmpt_module_read_interleaved_stereo(openmpt_mhandle, SAMPLERATE, BUFFERSIZE, (short *)stream); + + // apply volume to stream + for (i = 0, p = (short *)stream; i < len/2; i++, p++) + *p = attenuate(*p); } #endif @@ -700,11 +764,22 @@ musictype_t I_SongType(void) if (gme) return MU_GME; else +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + return MU_MOD_EX; #endif if (!music) return MU_NONE; else if (Mix_GetMusicType(music) == MUS_MID) + { +#ifdef HAVE_MIXERX + if (Mix_GetMidiPlayer() != MIDI_Native) + return MU_MID_EX; + else +#endif return MU_MID; + } else if (Mix_GetMusicType(music) == MUS_MOD || Mix_GetMusicType(music) == MUS_MODPLUG) return MU_MOD; else if (Mix_GetMusicType(music) == MUS_MP3 || Mix_GetMusicType(music) == MUS_MP3_MAD) @@ -718,6 +793,9 @@ boolean I_SongPlaying(void) return ( #ifdef HAVE_LIBGME (I_SongType() == MU_GME && gme) || +#endif +#ifdef HAVE_OPENMPT + (I_SongType() == MU_MOD_EX && openmpt_mhandle) || #endif music != NULL ); @@ -744,8 +822,28 @@ boolean I_SetSongSpeed(float speed) SDL_UnlockAudio(); return true; } + else +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + { + if (speed > 4.0f) + speed = 4.0f; // Limit this to 4x to prevent crashing, stupid fix but... ~SteelT 27/9/19 +#if OPENMPT_API_VERSION_MAJOR < 1 && OPENMPT_API_VERSION_MINOR < 5 + { + // deprecated in 0.5.0 + char modspd[13]; + sprintf(modspd, "%g", speed); + openmpt_module_ctl_set(openmpt_mhandle, "play.tempo_factor", modspd); + } +#else + openmpt_module_ctl_set_floatingpoint(openmpt_mhandle, "play.tempo_factor", (double)speed); +#endif + return true; + } #else (void)speed; + return false; #endif return false; } @@ -786,11 +884,21 @@ UINT32 I_GetSongLength(void) return max(length, 0); } else +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + return (UINT32)(openmpt_module_get_duration_seconds(openmpt_mhandle) * 1000.); + else #endif if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID) return 0; else { +#ifdef HAVE_MIXERX + double xlength = Mix_GetMusicTotalTime(music); + if (xlength >= 0) + return (UINT32)(xlength*1000); +#endif // VERY IMPORTANT to set your LENGTHMS= in your song files, folks! // SDL mixer can't read music length itself. length = (UINT32)(song_length*1000); @@ -802,7 +910,7 @@ UINT32 I_GetSongLength(void) boolean I_SetSongLoopPoint(UINT32 looppoint) { - if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || I_SongType() == MU_MID || !is_looping) + if (!music || I_SongType() == MU_GME || I_SongType() == MU_MOD || !is_looping) return false; else { @@ -838,7 +946,7 @@ UINT32 I_GetSongLoopPoint(void) } else #endif - if (!music || I_SongType() == MU_MOD || I_SongType() == MU_MID) + if (!music || I_SongType() == MU_MOD) return 0; else return (UINT32)(loop_point * 1000); @@ -871,6 +979,16 @@ boolean I_SetSongPosition(UINT32 position) // return true; } else +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + { + // This isn't 100% correct because we don't account for loop points because we can't get them. + // But if you seek past end of song, OpenMPT seeks to 0. So adjust the position anyway. + openmpt_module_set_position_seconds(openmpt_mhandle, (double)(get_adjusted_position(position)/1000.0L)); // returns new position + return true; + } + else #endif if (!music || I_SongType() == MU_MID) return false; @@ -888,7 +1006,7 @@ boolean I_SetSongPosition(UINT32 position) Mix_RewindMusic(); // needed for mp3 if(Mix_SetMusicPosition((float)(position/1000.0L)) == 0) - music_bytes = position/1000.0L*44100.0L*4; //assume 44.1khz, 4-byte length (see I_GetSongPosition) + music_bytes = (UINT32)(position/1000.0L*44100.0L*4); //assume 44.1khz, 4-byte length (see I_GetSongPosition) else // NOTE: This block fires on incorrect song format, // NOT if position input is greater than song length. @@ -930,14 +1048,29 @@ UINT32 I_GetSongPosition(void) return max(position, 0); } else +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + // This will be incorrect if we adjust for length because we can't get loop points. + // So return unadjusted. See note in SetMusicPosition: we adjust for that. + return (UINT32)(openmpt_module_get_position_seconds(openmpt_mhandle)*1000.); + //return get_adjusted_position((UINT32)(openmpt_module_get_position_seconds(openmpt_mhandle)*1000.)); + else #endif if (!music || I_SongType() == MU_MID) return 0; else - return music_bytes/44100.0L*1000.0L/4; //assume 44.1khz + { +#ifdef HAVE_MIXERX + double xposition = Mix_GetMusicPosition(music); + if (xposition >= 0) + return (UINT32)(xposition*1000); +#endif + return (UINT32)(music_bytes/44100.0L*1000.0L/4); //assume 44.1khz // 4 = byte length for 16-bit samples (AUDIO_S16SYS), stereo (2-channel) // This is hardcoded in I_StartupSound. Other formats for factor: // 8M: 1 | 8S: 2 | 16M: 2 | 16S: 4 + } } void @@ -968,13 +1101,15 @@ boolean I_LoadSong(char *data, size_t len) const size_t key1len = strlen(key1); const size_t key2len = strlen(key2); const size_t key3len = strlen(key3); - char *p = data; SDL_RWops *rw; if (music #ifdef HAVE_LIBGME || gme +#endif +#ifdef HAVE_OPENMPT + || openmpt_mhandle #endif ) I_UnloadSong(); @@ -1005,81 +1140,63 @@ boolean I_LoadSong(char *data, size_t len) if (zErr == Z_OK) // We're good to go { zErr = inflate(&stream, Z_FINISH); - if (zErr == Z_STREAM_END) { + if (zErr == Z_STREAM_END) + { // Run GME on new data - if (!gme_open_data(inflatedData, inflatedLen, &gme, 44100)) + if (!gme_open_data(inflatedData, inflatedLen, &gme, SAMPLERATE)) { - gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - gme_start_track(gme, 0); - current_track = 0; - gme_set_equalizer(gme, &eq); - Mix_HookMusic(mix_gme, gme); Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around return true; } } else - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg); - } + CONS_Alert(CONS_ERROR, "Encountered %s when running inflate: %s\n", get_zlib_error(zErr), stream.msg); (void)inflateEnd(&stream); } else // Hold up, zlib's got a problem - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg); - } + CONS_Alert(CONS_ERROR, "Encountered %s when running inflateInit: %s\n", get_zlib_error(zErr), stream.msg); Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up + return false; #else - CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n"); - return true; + CONS_Alert(CONS_ERROR, "Cannot decompress VGZ; no zlib support\n"); + return false; #endif } - else if (!gme_open_data(data, len, &gme, 44100)) - { - gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - gme_set_equalizer(gme, &eq); + else if (!gme_open_data(data, len, &gme, SAMPLERATE)) return true; +#endif + +#ifdef HAVE_OPENMPT + /* + If the size of the data to be checked is bigger than the recommended size (> 2048 bytes) + Let's just set the probe size to the recommended size + Otherwise let's give it the full data size + */ + + if (len > openmpt_probe_file_header_get_recommended_size()) + probesize = openmpt_probe_file_header_get_recommended_size(); + else + probesize = len; + + result = openmpt_probe_file_header(OPENMPT_PROBE_FILE_HEADER_FLAGS_DEFAULT, data, probesize, len, NULL, NULL, NULL, NULL, NULL, NULL); + + if (result == OPENMPT_PROBE_FILE_HEADER_RESULT_SUCCESS) // We only cared if it succeeded, continue on if not. + { + openmpt_mhandle = openmpt_module_create_from_memory2(data, len, NULL, NULL, NULL, NULL, NULL, NULL, NULL); + if (!openmpt_mhandle) // Failed to create module handle? Show error and return! + { + mod_err = openmpt_module_error_get_last(openmpt_mhandle); + mod_err_str = openmpt_error_string(mod_err); + CONS_Alert(CONS_ERROR, "openmpt_module_create_from_memory2: %s\n", mod_err_str); + return false; + } + else + return true; // All good and we're ready for music playback! } #endif + // Let's see if Mixer is able to load this. rw = SDL_RWFromMem(data, len); - if (rw != NULL) { music = Mix_LoadMUS_RW(rw, 1); } @@ -1133,6 +1250,13 @@ void I_UnloadSong(void) gme_delete(gme); gme = NULL; } +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + { + openmpt_module_destroy(openmpt_mhandle); + openmpt_mhandle = NULL; + } #endif if (music) { @@ -1146,12 +1270,27 @@ boolean I_PlaySong(boolean looping) #ifdef HAVE_LIBGME if (gme) { + gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; + gme_set_equalizer(gme, &eq); gme_start_track(gme, 0); current_track = 0; Mix_HookMusic(mix_gme, gme); return true; } else +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + { + openmpt_module_select_subsong(openmpt_mhandle, 0); + openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value); + if (looping) + openmpt_module_set_repeat_count(openmpt_mhandle, -1); // Always repeat + current_subsong = 0; + Mix_HookMusic(mix_openmpt, openmpt_mhandle); + return true; + } + else #endif if (!music) return false; @@ -1159,12 +1298,12 @@ boolean I_PlaySong(boolean looping) if (fpclassify(song_length) == FP_ZERO && (I_SongType() == MU_OGG || I_SongType() == MU_MP3 || I_SongType() == MU_FLAC)) CONS_Debug(DBG_DETAILED, "This song is missing a LENGTHMS= tag! Required to make seeking work properly.\n"); - if (I_SongType() != MU_MOD && I_SongType() != MU_MID && Mix_PlayMusic(music, 0) == -1) + if (I_SongType() != MU_MOD && Mix_PlayMusic(music, 0) == -1) { CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); return false; } - else if ((I_SongType() == MU_MOD || I_SongType() == MU_MID) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever + else if ((I_SongType() == MU_MOD || I_SongType() == MU_MID || I_SongType() == MU_MID_EX) && Mix_PlayMusic(music, looping ? -1 : 0) == -1) // if MOD, loop forever { CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); return false; @@ -1174,10 +1313,10 @@ boolean I_PlaySong(boolean looping) I_SetMusicVolume(music_volume); - if (I_SongType() != MU_MOD && I_SongType() != MU_MID) + if (I_SongType() != MU_MOD && I_SongType() != MU_MID && I_SongType() != MU_MID_EX) Mix_HookMusicFinished(music_loop); // don't bother counting if MOD - if(I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + if(I_SongType() != MU_MOD && I_SongType() != MU_MID && I_SongType() != MU_MID_EX && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); return true; @@ -1185,7 +1324,10 @@ boolean I_PlaySong(boolean looping) void I_StopSong(void) { - I_StopFadingSong(); + // HACK: See music_loop on why we want fade timing to proceed + // after end of song + if (!fading_nocleanup) + I_StopFadingSong(); #ifdef HAVE_LIBGME if (gme) @@ -1193,6 +1335,13 @@ void I_StopSong(void) Mix_HookMusic(NULL, NULL); current_track = -1; } +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + { + Mix_HookMusic(NULL, NULL); + current_subsong = -1; + } #endif if (music) { @@ -1206,10 +1355,9 @@ void I_StopSong(void) void I_PauseSong(void) { - if(I_SongType() == MU_MID) // really, SDL Mixer? why can't you pause MIDI??? - return; + // really, SRB2? why do you support MIDI??? - if(I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID) + if(I_SongType() != MU_GME && I_SongType() != MU_MOD) Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes); Mix_PauseMusic(); @@ -1218,15 +1366,12 @@ void I_PauseSong(void) void I_ResumeSong(void) { - if (I_SongType() == MU_MID) - return; - - if (I_SongType() != MU_GME && I_SongType() != MU_MOD && I_SongType() != MU_MID) + if (I_SongType() != MU_GME && I_SongType() != MU_MOD) { while(Mix_UnregisterEffect(MIX_CHANNEL_POST, count_music_bytes) != 0) { } // HACK: fixes issue of multiple effect callbacks being registered - if(music && I_SongType() != MU_MOD && I_SongType() != MU_MID && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) + if(music && I_SongType() != MU_MOD && !Mix_RegisterEffect(MIX_CHANNEL_POST, count_music_bytes, NULL, NULL)) CONS_Alert(CONS_WARNING, "Error registering SDL music position counter: %s\n", Mix_GetError()); } @@ -1234,35 +1379,26 @@ void I_ResumeSong(void) songpaused = false; } -void I_SetMusicVolume(UINT8 volume) +void I_SetMusicVolume(int volume) { if (!I_SongPlaying()) return; -#ifdef _WIN32 - if (I_SongType() == MU_MID) - // HACK: Until we stop using native MIDI, - // disable volume changes - music_volume = 31; - else -#endif - music_volume = volume; + music_volume = volume; - Mix_VolumeMusic(get_real_volume(music_volume)); + Mix_VolumeMusic(attenuate(MIX_MAX_VOLUME)); } boolean I_SetSongTrack(int track) { #ifdef HAVE_LIBGME - if (current_track == track) - return false; - // If the specified track is within the number of tracks playing, then change it if (gme) { + if (current_track == track) + return false; SDL_LockAudio(); - if (track >= 0 - && track < gme_track_count(gme)) + if (track >= 0 && track < gme_track_count(gme)-1) { gme_err_t gme_e = gme_start_track(gme, track); if (gme_e != NULL) @@ -1278,6 +1414,24 @@ boolean I_SetSongTrack(int track) return false; } else +#endif +#ifdef HAVE_OPENMPT + if (openmpt_mhandle) + { + if (current_subsong == track) + return false; + SDL_LockAudio(); + if (track >= 0 && track < openmpt_module_get_num_subsongs(openmpt_mhandle)) + { + openmpt_module_select_subsong(openmpt_mhandle, track); + current_subsong = track; + SDL_UnlockAudio(); + return true; + } + SDL_UnlockAudio(); + + return false; + } #endif if (I_SongType() == MU_MOD) return !Mix_SetMusicPosition(track); @@ -1294,7 +1448,7 @@ void I_SetInternalMusicVolume(UINT8 volume) internal_volume = volume; if (!I_SongPlaying()) return; - Mix_VolumeMusic(get_real_volume(music_volume)); + Mix_VolumeMusic(attenuate(MIX_MAX_VOLUME)); } void I_StopFadingSong(void) @@ -1303,6 +1457,8 @@ void I_StopFadingSong(void) SDL_RemoveTimer(fading_id); is_fading = false; fading_source = fading_target = fading_timer = fading_duration = fading_id = 0; + // don't unset fading_nocleanup here just yet; fading_callback is cleaned up + // in var_cleanup() } boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms, void (*callback)(void)) diff --git a/src/sdl/ogl_sdl.c b/src/sdl/ogl_sdl.c index eb8e12cbc..3d2ac1855 100644 --- a/src/sdl/ogl_sdl.c +++ b/src/sdl/ogl_sdl.c @@ -2,6 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -137,7 +138,7 @@ boolean LoadGL(void) else { CONS_Alert(CONS_ERROR, "Could not load GLU Library\n"); - CONS_Printf("If you know what is the GLU library's name, use -GLUlib\n"); + CONS_Printf("If you know what is the GLU library's name, use -GLUlib\n");; } #endif return SetupGLfunc(); @@ -155,26 +156,11 @@ boolean OglSdlSurface(INT32 w, INT32 h) { INT32 cbpp = cv_scr_depth.value < 16 ? 16 : cv_scr_depth.value; static boolean first_init = false; - const char *gllogdir = NULL; oglflags = 0; if (!first_init) { - if (!gllogstream) - { - gllogdir = D_Home(); - -#ifdef DEBUG_TO_FILE -#ifdef DEFAULTDIR - if (gllogdir) - gllogstream = fopen(va("%s/"DEFAULTDIR"/ogllog.txt",gllogdir), "wt"); - else -#endif - gllogstream = fopen("./ogllog.txt", "wt"); -#endif - } - gl_version = pglGetString(GL_VERSION); gl_renderer = pglGetString(GL_RENDERER); gl_extensions = pglGetString(GL_EXTENSIONS); @@ -182,6 +168,18 @@ boolean OglSdlSurface(INT32 w, INT32 h) GL_DBG_Printf("OpenGL %s\n", gl_version); GL_DBG_Printf("GPU: %s\n", gl_renderer); GL_DBG_Printf("Extensions: %s\n", gl_extensions); + + if (strcmp((const char*)gl_renderer, "GDI Generic") == 0 && + strcmp((const char*)gl_version, "1.1.0") == 0) + { + // Oh no... Windows gave us the GDI Generic rasterizer, so something is wrong... + // The game will crash later on when unsupported OpenGL commands are encountered. + // Instead of a nondescript crash, show a more informative error message. + // Also set the renderer variable back to software so the next launch won't + // repeat this error. + CV_StealthSet(&cv_renderer, "Software"); + I_Error("OpenGL Error: Failed to access the GPU. There may be an issue with your graphics drivers."); + } } first_init = true; @@ -236,20 +234,15 @@ void OglSdlFinishUpdate(boolean waitvbl) HWR_DrawScreenFinalTexture(realwidth, realheight); } -EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette, RGBA_t *pgamma) +EXPORT void HWRAPI(OglSdlSetPalette) (RGBA_t *palette) { - INT32 i = -1; - UINT32 redgamma = pgamma->s.red, greengamma = pgamma->s.green, - bluegamma = pgamma->s.blue; - - for (i = 0; i < 256; i++) + size_t palsize = (sizeof(RGBA_t) * 256); + // on a palette change, you have to reload all of the textures + if (memcmp(&myPaletteData, palette, palsize)) { - myPaletteData[i].s.red = (UINT8)MIN((palette[i].s.red * redgamma) /127, 255); - myPaletteData[i].s.green = (UINT8)MIN((palette[i].s.green * greengamma)/127, 255); - myPaletteData[i].s.blue = (UINT8)MIN((palette[i].s.blue * bluegamma) /127, 255); - myPaletteData[i].s.alpha = palette[i].s.alpha; + memcpy(&myPaletteData, palette, palsize); + Flush(); } - Flush(); } #endif //HWRENDER diff --git a/src/sdl/ogl_sdl.h b/src/sdl/ogl_sdl.h index 2d6209f2b..748e30bae 100644 --- a/src/sdl/ogl_sdl.h +++ b/src/sdl/ogl_sdl.h @@ -2,6 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1998-2000 by DooM Legacy Team. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -30,5 +31,5 @@ extern Uint16 realwidth; extern Uint16 realheight; #ifdef _CREATE_DLL_ -EXPORT void HWRAPI( OglSdlSetPalette ) (RGBA_t *palette, RGBA_t *pgamma); +EXPORT void HWRAPI( OglSdlSetPalette ) (RGBA_t *palette); #endif diff --git a/src/sdl/sdl_sound.c b/src/sdl/sdl_sound.c index 4bb1b5676..d7a5cb384 100644 --- a/src/sdl/sdl_sound.c +++ b/src/sdl/sdl_sound.c @@ -2,6 +2,7 @@ //----------------------------------------------------------------------------- // // Copyright (C) 1993-1996 by id Software, Inc. +// Copyright (C) 2014-2020 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -32,7 +33,7 @@ #endif #ifdef HAVE_MIXER -#include "SDL_mixer.h" +#include /* This is the version number macro for the current SDL_mixer version: */ #ifndef SDL_MIXER_COMPILEDVERSION #define SDL_MIXER_COMPILEDVERSION \ @@ -195,7 +196,7 @@ static void Snd_LockAudio(void) //Alam: Lock audio data and uninstall audio call { if (Snd_Mutex) SDL_LockMutex(Snd_Mutex); else if (sound_disabled) return; - else if (midi_disabled && digital_disabled + else if (digital_disabled #ifdef HW3SOUND && hws_mode == HWS_DEFAULT_MODE #endif @@ -209,7 +210,7 @@ static void Snd_UnlockAudio(void) //Alam: Unlock audio data and reinstall audio { if (Snd_Mutex) SDL_UnlockMutex(Snd_Mutex); else if (sound_disabled) return; - else if (midi_disabled && digital_disabled + else if (digital_disabled #ifdef HW3SOUND && hws_mode == HWS_DEFAULT_MODE #endif @@ -1153,7 +1154,7 @@ void I_ShutdownSound(void) } #endif - if (midi_disabled && digital_disabled) + if (digital_disabled) SDL_CloseAudio(); CONS_Printf("%s", M_GetText("shut down\n")); sound_started = false; @@ -1173,9 +1174,6 @@ void I_StartupSound(void) const char *sdrv_name = NULL; #endif #ifndef HAVE_MIXER -#ifndef NO_MIDI - midi_disabled = -#endif digital_disabled = true; #endif @@ -1389,8 +1387,8 @@ UINT32 I_GetSongLength(void) boolean I_SetSongLoopPoint(UINT32 looppoint) { - (void)looppoint; - return false; + (void)looppoint; + return false; } UINT32 I_GetSongLoopPoint(void) @@ -1434,6 +1432,8 @@ static void I_ResumeGME(void) boolean I_LoadSong(char *data, size_t len) { + (void)data; + (void)len; return false; } @@ -1495,6 +1495,7 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms (void)target_volume; (void)source_volume; (void)ms; + (void)callback; return false; } @@ -1502,6 +1503,7 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) { (void)target_volume; (void)ms; + (void)callback; return false; } diff --git a/src/sdl/sdlmain.h b/src/sdl/sdlmain.h index 0bc771a71..39c099a2b 100644 --- a/src/sdl/sdlmain.h +++ b/src/sdl/sdlmain.h @@ -1,7 +1,7 @@ // Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // -// Copyright (C) 2006-2018 by Sonic Team Jr. +// Copyright (C) 2006-2020 by Sonic Team Junior. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -23,6 +23,7 @@ extern SDL_bool consolevent; extern SDL_bool framebuffer; #include "../m_fixed.h" +#include "../doomdef.h" // SDL2 stub macro #ifdef _MSC_VER @@ -57,40 +58,26 @@ typedef struct SDLJoyInfo_s } SDLJoyInfo_t; -/** \brief SDL info about joystick 1 +/** \brief SDL info about joysticks */ -extern SDLJoyInfo_t JoyInfo; +extern SDLJoyInfo_t JoyInfo[MAXSPLITSCREENPLAYERS]; /** \brief joystick axis deadzone */ #define SDL_JDEADZONE 153 #undef SDL_JDEADZONE -/** \brief SDL inof about joystick 2 -*/ -extern SDLJoyInfo_t JoyInfo2; - -/** \brief SDL inof about joystick 3 -*/ -extern SDLJoyInfo_t JoyInfo3; - -/** \brief SDL inof about joystick 4 -*/ -extern SDLJoyInfo_t JoyInfo4; - void I_GetConsoleEvents(void); // So we can call this from i_video event loop -void I_ShutdownJoystick(void); -void I_ShutdownJoystick2(void); -void I_ShutdownJoystick3(void); -void I_ShutdownJoystick4(void); +void I_ShutdownJoystick(UINT8 index); // Cheat to get the device index for a joystick handle INT32 I_GetJoystickDeviceIndex(SDL_Joystick *dev); // Quick thing to make SDL_JOYDEVICEADDED events less of an abomination -void I_UpdateJoystickDeviceIndices(INT32 player); +void I_UpdateJoystickDeviceIndex(UINT8 player); +void I_UpdateJoystickDeviceIndices(UINT8 excludePlayer); void I_GetConsoleEvents(void); diff --git a/src/sdl12/IMG_xpm.c b/src/sdl12/IMG_xpm.c deleted file mode 100644 index e08736d66..000000000 --- a/src/sdl12/IMG_xpm.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - SDL_image: An example image loading library for use with SDL - Copyright (C) 1999-2004 Sam Lantinga - - 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 - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Sam Lantinga - slouken@libsdl.org -*/ - -/* $Id: IMG_xpm.c,v 1.10 2004/01/04 22:04:38 slouken Exp $ */ - -/* - * XPM (X PixMap) image loader: - * - * Supports the XPMv3 format, EXCEPT: - * - hotspot coordinates are ignored - * - only colour ('c') colour symbols are used - * - rgb.txt is not used (for portability), so only RGB colours - * are recognized (#rrggbb etc) - only a few basic colour names are - * handled - * - * The result is an 8bpp indexed surface if possible, otherwise 32bpp. - * The colourkey is correctly set if transparency is used. - * - * Besides the standard API, also provides - * - * SDL_Surface *IMG_ReadXPMFromArray(char **xpm) - * - * that reads the image data from an XPM file included in the C source. - * - * TODO: include rgb.txt here. The full table (from solaris 2.6) only - * requires about 13K in binary form. - */ - -#include -#include -#include -#include - -//#include "SDL_image.h" - - -#ifdef LOAD_XPM - -/* See if an image is contained in a data source */ -#if 0 -int IMG_isXPM(SDL_RWops *src) -{ - char magic[9]; - - return (SDL_RWread(src, magic, sizeof (magic), 1) - && memcmp(magic, "/* XPM */", 9) == 0); -} -#endif - -/* Hash table to look up colors from pixel strings */ -#define STARTING_HASH_SIZE 256 - -struct hash_entry { - char *key; - Uint32 color; - struct hash_entry *next; -}; - -struct color_hash { - struct hash_entry **table; - struct hash_entry *entries; /* array of all entries */ - struct hash_entry *next_free; - size_t size; - int maxnum; -}; - -static int hash_key(const char *key, int cpp, size_t size) -{ - int hash; - - hash = 0; - while ( cpp-- > 0 ) { - hash = hash * 33 + *key++; - } - return (int)(hash & (size - 1)); -} - -static struct color_hash *create_colorhash(int maxnum) -{ - size_t bytes; - int s; - struct color_hash *hash; - - /* we know how many entries we need, so we can allocate - everything here */ - hash = malloc(sizeof *hash); - if (!hash) - return NULL; - - /* use power-of-2 sized hash table for decoding speed */ - for (s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) - ; - hash->size = s; - hash->maxnum = maxnum; - bytes = hash->size * sizeof (struct hash_entry **); - hash->entries = NULL; /* in case malloc fails */ - hash->table = malloc(bytes); - if (!hash->table) - return NULL; - memset(hash->table, 0, bytes); - hash->entries = malloc(maxnum * sizeof (struct hash_entry)); - if (!hash->entries) - { - free(hash->table); - return NULL; - } - hash->next_free = hash->entries; - return hash; -} - -static int add_colorhash(struct color_hash *hash, - char *key, int cpp, Uint32 color) -{ - const int indexkey = hash_key(key, cpp, hash->size); - struct hash_entry *e = hash->next_free++; - e->color = color; - e->key = key; - e->next = hash->table[indexkey]; - hash->table[indexkey] = e; - return 1; -} - -/* fast lookup that works if cpp == 1 */ -#define QUICK_COLORHASH(hash, key) ((hash)->table[*(const Uint8 *)(key)]->color) - -static Uint32 get_colorhash(struct color_hash *hash, const char *key, int cpp) -{ - struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)]; - while (entry) { - if (memcmp(key, entry->key, cpp) == 0) - return entry->color; - entry = entry->next; - } - return 0; /* garbage in - garbage out */ -} - -static void free_colorhash(struct color_hash *hash) -{ - if (hash && hash->table) { - free(hash->table); - free(hash->entries); - free(hash); - } -} - -/* portable case-insensitive string comparison */ -static int string_equal(const char *a, const char *b, size_t n) -{ - while (*a && *b && n) { - if (toupper((unsigned char)*a) != toupper((unsigned char)*b)) - return 0; - a++; - b++; - n--; - } - return *a == *b; -} - -#undef ARRAYSIZE -#define ARRAYSIZE(a) (int)(sizeof (a) / sizeof ((a)[0])) - -/* - * convert colour spec to RGB (in 0xrrggbb format). - * return 1 if successful. - */ -static int color_to_rgb(const char *spec, size_t speclen, Uint32 *rgb) -{ - /* poor man's rgb.txt */ - static struct { const char *name; Uint32 rgb; } known[] = { - {"none", 0xffffffff}, - {"black", 0x00000000}, - {"white", 0x00ffffff}, - {"red", 0x00ff0000}, - {"green", 0x0000ff00}, - {"blue", 0x000000ff} - }; - - if (spec[0] == '#') { - char buf[7]; - switch (speclen) { - case 4: - buf[0] = buf[1] = spec[1]; - buf[2] = buf[3] = spec[2]; - buf[4] = buf[5] = spec[3]; - break; - case 7: - memcpy(buf, spec + 1, 6); - break; - case 13: - buf[0] = spec[1]; - buf[1] = spec[2]; - buf[2] = spec[5]; - buf[3] = spec[6]; - buf[4] = spec[9]; - buf[5] = spec[10]; - break; - } - buf[6] = '\0'; - *rgb = (Uint32)strtol(buf, NULL, 16); - return 1; - } else { - int i; - for (i = 0; i < ARRAYSIZE(known); i++) - if (string_equal(known[i].name, spec, speclen)) { - *rgb = known[i].rgb; - return 1; - } - return 0; - } -} - -#ifndef MAX -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#endif - -static char *linebuf; -static int buflen; -static const char *error; - -/* - * Read next line from the source. - * If len > 0, it's assumed to be at least len chars (for efficiency). - * Return NULL and set error upon EOF or parse error. - */ -static const char *get_next_line(const char ***lines, SDL_RWops *src, int len) -{ - char *linebufnew; - if (lines) { - return *(*lines)++; - } else { - char c; - int n; - do { - if (SDL_RWread(src, &c, 1, 1) <= 0) { - error = "Premature end of data"; - return NULL; - } - } while (c != '"'); - if (len) { - len += 4; /* "\",\n\0" */ - if (len > buflen){ - buflen = len; - linebufnew = realloc(linebuf, buflen); - if(!linebufnew) { - free(linebuf); - error = "Out of memory"; - return NULL; - } - linebuf = linebufnew; - } - if (SDL_RWread(src, linebuf, len - 1, 1) <= 0) { - error = "Premature end of data"; - return NULL; - } - n = len - 2; - } else { - n = 0; - do { - if (n >= buflen - 1) { - if (buflen == 0) - buflen = 16; - buflen *= 2; - linebufnew = realloc(linebuf, buflen); - if(!linebufnew) { - free(linebuf); - error = "Out of memory"; - return NULL; - } - linebuf = linebufnew; - } - if (SDL_RWread(src, linebuf + n, 1, 1) <= 0) { - error = "Premature end of data"; - return NULL; - } - } while (linebuf[n++] != '"'); - n--; - } - linebuf[n] = '\0'; - return linebuf; - } -} - -#define SKIPSPACE(p) \ -do { \ - while (isspace((unsigned char)*(p))) \ - ++(p); \ -} while (0) - -#define SKIPNONSPACE(p) \ -do { \ - while (!isspace((unsigned char)*(p)) && *p) \ - ++(p); \ -} while (0) - -/* read XPM from either array or RWops */ -static SDL_Surface *load_xpm(const char **xpm, SDL_RWops *src) -{ - SDL_Surface *image = NULL; - int indexc; - int x, y; - int w, h, ncolors, cpp; - int indexed; - Uint8 *dst; - struct color_hash *colors = NULL; - SDL_Color *im_colors = NULL; - char *keystrings = NULL, *nextkey; - const char *line; - const char ***xpmlines = NULL; - int pixels_len; - - error = NULL; - linebuf = NULL; - buflen = 0; - - if (xpm) - xpmlines = &xpm; - - line = get_next_line(xpmlines, src, 0); - if (!line) - goto done; - /* - * The header string of an XPMv3 image has the format - * - * [ ] - * - * where the hotspot coords are intended for mouse cursors. - * Right now we don't use the hotspots but it should be handled - * one day. - */ - if (sscanf(line, "%d %d %d %d", &w, &h, &ncolors, &cpp) != 4 - || w <= 0 || h <= 0 || ncolors <= 0 || cpp <= 0) { - error = "Invalid format description"; - goto done; - } - - keystrings = malloc(ncolors * cpp); - if (!keystrings) { - error = "Out of memory"; - goto done; - } - nextkey = keystrings; - - /* Create the new surface */ - if (ncolors <= 256) { - indexed = 1; - image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, - 0, 0, 0, 0); - im_colors = image->format->palette->colors; - image->format->palette->ncolors = ncolors; - } else { - indexed = 0; - image = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, - 0xff0000, 0x00ff00, 0x0000ff, 0); - } - if (!image) { - /* Hmm, some SDL error (out of memory?) */ - goto done; - } - - /* Read the colors */ - colors = create_colorhash(ncolors); - if (!colors) { - error = "Out of memory"; - goto done; - } - for (indexc = 0; indexc < ncolors; ++indexc ) { - const char *p; - line = get_next_line(xpmlines, src, 0); - if (!line) - goto done; - - p = line + cpp + 1; - - /* parse a colour definition */ - for (;;) { - char nametype; - const char *colname; - Uint32 rgb, pixel; - - SKIPSPACE(p); - if (!*p) { - error = "colour parse error"; - goto done; - } - nametype = *p; - SKIPNONSPACE(p); - SKIPSPACE(p); - colname = p; - SKIPNONSPACE(p); - if (nametype == 's') - continue; /* skip symbolic colour names */ - - if (!color_to_rgb(colname, p - colname, &rgb)) - continue; - - memcpy(nextkey, line, cpp); - if (indexed) { - SDL_Color *c = im_colors + indexc; - c->r = (Uint8)(rgb >> 16); - c->g = (Uint8)(rgb >> 8); - c->b = (Uint8)(rgb); - pixel = indexc; - } else - pixel = rgb; - add_colorhash(colors, nextkey, cpp, pixel); - nextkey += cpp; - if (rgb == 0xffffffff) - SDL_SetColorKey(image, SDL_SRCCOLORKEY, pixel); - break; - } - } - - /* Read the pixels */ - pixels_len = w * cpp; - dst = image->pixels; - for (y = 0; y < h; y++) { - line = get_next_line(xpmlines, src, pixels_len); - if (indexed) { - /* optimization for some common cases */ - if (cpp == 1) - for (x = 0; x < w; x++) - dst[x] = (Uint8)QUICK_COLORHASH(colors, - line + x); - else - for (x = 0; x < w; x++) - dst[x] = (Uint8)get_colorhash(colors, - line + x * cpp, - cpp); - } else { - for (x = 0; x < w; x++) - ((Uint32*)dst)[x] = get_colorhash(colors, - line + x * cpp, - cpp); - } - dst += image->pitch; - } - -done: - if (error) { - SDL_FreeSurface(image); - image = NULL; - SDL_SetError(error); - } - free(keystrings); - free_colorhash(colors); - free(linebuf); - return(image); -} - -/* Load a XPM type image from an RWops datasource */ -#if 0 -SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) -{ - if ( !src ) { - /* The error message has been set in SDL_RWFromFile */ - return NULL; - } - return load_xpm(NULL, src); -} -#endif - -static inline SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) -{ - return load_xpm(xpm, NULL); -} - -#else /* not LOAD_XPM */ - -/* See if an image is contained in a data source */ -#if 0 -int IMG_isXPM(SDL_RWops *src) -{ - return(0); -} - -/* Load a XPM type image from an SDL datasource */ -SDL_Surface *IMG_LoadXPM_RW(SDL_RWops *src) -{ - return(NULL); -} -#endif - -static inline SDL_Surface *IMG_ReadXPMFromArray(const char **xpm) -{ - return NULL; -} -#endif /* not LOAD_XPM */ diff --git a/src/sdl12/MakeCYG.cfg b/src/sdl12/MakeCYG.cfg deleted file mode 100644 index b55d9dc50..000000000 --- a/src/sdl12/MakeCYG.cfg +++ /dev/null @@ -1,17 +0,0 @@ -# -# sdl12/makeCYG.cfg for SRB2/Cygwin -# - -# -#Cygwin, for debugging - - NOHW=1 - NOHS=1 - NOASM=1 - - OPTS+=-DLINUX - - i_system_o+=$(OBJDIR)/SRB2.res - - # name of the exefile - EXENAME?=lsdlsrb2.exe diff --git a/src/sdl12/MakeNIX.cfg b/src/sdl12/MakeNIX.cfg deleted file mode 100644 index 1278aaf06..000000000 --- a/src/sdl12/MakeNIX.cfg +++ /dev/null @@ -1,92 +0,0 @@ -# -# sdl12/makeNIX.cfg for SRB2/?nix -# - -#Valgrind support -ifdef VALGRIND -VALGRIND_PKGCONFIG?=valgrind -VALGRIND_CFLAGS?=$(shell $(PKG_CONFIG) $(VALGRIND_PKGCONFIG) --cflags) -VALGRIND_LDFLAGS?=$(shell $(PKG_CONFIG) $(VALGRIND_PKGCONFIG) --libs) -ZDEBUG=1 -LIBS+=$(VALGRIND_LDFLAGS) -ifdef GCC46 -WFLAGS+=-Wno-error=unused-but-set-variable -WFLAGS+=-Wno-unused-but-set-variable -endif -endif - -# -#here is GNU/Linux and other -# - - OPTS=-DUNIXCOMMON - - #LDFLAGS = -L/usr/local/lib - LIBS=-lm -ifdef LINUX - LIBS+=-lrt -ifdef NOTERMIOS - OPTS+=-DNOTERMIOS -endif -endif - -# -#here is Solaris -# -ifdef SOLARIS - NOIPX=1 - NOASM=1 - OPTS+=-DSOLARIS -DINADDR_NONE=INADDR_ANY -DBSD_COMP - OPTS+=-I/usr/local/include -I/opt/sfw/include - LDFLAGS+=-L/opt/sfw/lib - LIBS+=-lsocket -lnsl -endif - -# -#here is FreeBSD -# -ifdef FREEBSD - OPTS+=-DLINUX -DFREEBSD -I/usr/X11R6/include - SDL_CONFIG?=sdl11-config - LDFLAGS+=-L/usr/X11R6/lib - LIBS+=-lipx -lkvm -endif - -# -#here is GP2x (arm-gp2x-linux) -# -ifdef GP2X - PNG_CONFIG?=$(PREFIX)-libpng12-config -ifdef STATIC #need a better setting name - CFLAGS+=-I$(OPEN2X)/include -ifndef NOMIXER - LIBS+=-lvorbisidec -ifdef MIKMOD - LIBS+=-lmikmod -endif -ifdef SMPEGLIB - LIBS+=-lsmpeg - LD=$(CXX) -endif -endif - NONET=1 -endif -ifndef ARCHNAME -"error" -endif - NONX86=1 - NOHW=1 - NOHS=1 - NOMD5=1 - WFLAGS+=-O0 - OPTS+=-DGP2X -ffast-math -mcpu=arm920t - EXENAME?=SRB2GP2X.gpe -endif - -ifndef NOHW - OPTS+=-I/usr/X11R6/include - LDFLAGS+=-L/usr/X11R6/lib -endif - - # name of the exefile - EXENAME?=lsdlsrb2 diff --git a/src/sdl12/Makefile.cfg b/src/sdl12/Makefile.cfg deleted file mode 100644 index 8d9ebc35c..000000000 --- a/src/sdl12/Makefile.cfg +++ /dev/null @@ -1,163 +0,0 @@ -# -# sdl12/makefile.cfg for SRB2/SDL -# - -# -#SDL...., *looks at Alam*, THIS IS A MESS! -# - -ifdef UNIXCOMMON -include sdl12/MakeNIX.cfg -endif - -ifdef PANDORA -include sdl12/SRB2Pandora/Makefile.cfg -endif #ifdef PANDORA - -ifdef DC -include sdl12/SRB2DC/Makefile.cfg -endif #ifdef DC - -ifdef PS3N -include sdl12/SRB2PS3/Makefile.cfg -endif #ifdef PS3N - -ifdef PSP -include sdl12/SRB2PSP/Makefile.cfg -endif #ifdef PSP - -ifdef XBOX -include sdl12/SRB2XBOX/Makefile.cfg -endif #ifdef XBOX - -ifdef WINCE -include sdl12/SRB2CE/Makefile.cfg -endif #ifef WINCE - -ifdef CYGWIN32 -include sdl12/MakeCYG.cfg -endif #ifdef CYGWIN32 - -ifdef SDL_PKGCONFIG -SDL_CFLAGS?=$(shell $(PKG_CONFIG) $(SDL_PKGCONFIG) --cflags) -SDL_LDFLAGS?=$(shell $(PKG_CONFIG) $(SDL_PKGCONFIG) --libs) -else -ifdef PREFIX - SDL_CONFIG?=$(PREFIX)-sdl-config -else - SDL_CONFIG?=sdl-config -endif - -ifdef STATIC - SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags) - SDL_LDFLAGS?=$(shell $(SDL_CONFIG) --static-libs) -else - SDL_CFLAGS?=$(shell $(SDL_CONFIG) --cflags) - SDL_LDFLAGS?=$(shell $(SDL_CONFIG) --libs) -endif -endif - - - #use the x86 asm code -ifndef CYGWIN32 -ifndef NOASM - USEASM=1 -endif -endif - - OBJS+=$(OBJDIR)/i_video.o $(OBJDIR)/dosstr.o $(OBJDIR)/endtxt.o $(OBJDIR)/hwsym_sdl.o - - OPTS+=-DDIRECTFULLSCREEN -DHAVE_SDL - -ifndef NOHW - OBJS+=$(OBJDIR)/r_opengl.o $(OBJDIR)/ogl_sdl.o -endif - -ifndef NOHS -ifdef OPENAL - OBJS+=$(OBJDIR)/s_openal.o - OPTS+=-DSTATIC3DS - STATICHS=1 -else -ifdef FMOD - OBJS+=$(OBJDIR)/s_fmod.o - OPTS+=-DSTATIC3DS - STATICHS=1 -else -ifdef MINGW -ifdef DS3D - OBJS+=$(OBJDIR)/s_ds3d.o - OPTS+=-DSTATIC3DS - STATICHS=1 -endif -endif -endif -endif -endif - -ifdef FILTERS - OBJS+=$(OBJDIR)/filters.o $(OBJDIR)/hq2x.o $(OBJDIR)/lq2x.o - OPTS+=-DHAVE_FILTER -endif - -ifdef NOMIXER - i_sound_o=$(OBJDIR)/sdl_sound.o -else - i_sound_o=$(OBJDIR)/mixer_sound.o - OPTS+=-DHAVE_MIXER - SDL_LDFLAGS+=-lSDL_mixer -endif - -ifdef SDL_TTF - OPTS+=-DHAVE_TTF - SDL_LDFLAGS+=-lSDL_ttf -lfreetype -lz - OBJS+=$(OBJDIR)/i_ttf.o -endif - -#ifdef SDL_IMAGE -# OPTS+=-DHAVE_IMAGE -# SDL_LDFLAGS+=-lSDL_image -#endif - -ifdef SDL_NET - OPTS+=-DHAVE_SDLNET - SDL_LDFLAGS+=-lSDL_net -endif - -ifdef SDLMAIN - OPTS+=-DSDLMAIN -else -ifdef MINGW - SDL_CFLAGS+=-Umain - SDL_LDFLAGS+=-mconsole -endif -endif - -ifndef NOHW -ifdef OPENAL -ifdef MINGW - LIBS:=-lopenal32 $(LIBS) -else - LIBS:=-lopenal $(LIBS) -endif -else -ifdef MINGW -ifdef DS3D - LIBS:=-ldsound -luuid $(LIBS) -endif -endif -endif -endif - -# FIXME: DevkitPPC and ready-compiled SDL Wii require these things to be in a silly order -ifdef WII -include sdl12/SRB2WII/Makefile.cfg -endif #ifdef WII - -CFLAGS+=$(SDL_CFLAGS) -LIBS:=$(SDL_LDFLAGS) $(LIBS) -ifndef WII -ifdef STATIC - LIBS+=$(shell $(SDL_CONFIG) --static-libs) -endif -endif diff --git a/src/sdl12/SDL_icon.xpm b/src/sdl12/SDL_icon.xpm deleted file mode 100644 index cf72960df..000000000 --- a/src/sdl12/SDL_icon.xpm +++ /dev/null @@ -1,425 +0,0 @@ -/* XPM */ -static char * C:\Repo\srb2\src\sdl\SDL_icon_xpm[] = { -"32 32 390 2", -" c None", -". c #4F4F70", -"+ c #4D4D87", -"@ c #4D4D84", -"# c #4E4E6C", -"$ c #6C6C95", -"% c #5E5EB2", -"& c #6B6BE7", -"* c #7373F9", -"= c #7C7CFF", -"- c #6F70E7", -"; c #494BB2", -"> c #4F4FA3", -", c #6464D4", -"' c #7979F5", -") c #5F5FCA", -"! c #5D5D93", -"~ c #3A3A9F", -"{ c #6060AC", -"] c #777793", -"^ c #5C5CB3", -"/ c #7373EA", -"( c #7A7AFF", -"_ c #7575FF", -": c #7979FF", -"< c #6264DD", -"[ c #47478C", -"} c #564567", -"| c #4647D0", -"1 c #5C5CAE", -"2 c #5E5EFF", -"3 c #2929FF", -"4 c #1D1DFF", -"5 c #1919D1", -"6 c #4F4F90", -"7 c #1E1ECE", -"8 c #5858FF", -"9 c #6767A8", -"0 c #4949A0", -"a c #7070FB", -"b c #7D7DFF", -"c c #7777FF", -"d c #7373FF", -"e c #7272FF", -"f c #7878FF", -"g c #6465D8", -"h c #363886", -"i c #9F7655", -"j c #C89B5C", -"k c #1D1CB7", -"l c #3031B1", -"m c #1919F4", -"n c #1111FF", -"o c #1818FF", -"p c #1B1BFF", -"q c #1C1CFF", -"r c #2626B3", -"s c #1E1EC8", -"t c #1A1AE8", -"u c #24249F", -"v c #2F2FD2", -"w c #7676FF", -"x c #6869E2", -"y c #414290", -"z c #8C6751", -"A c #FCBA68", -"B c #E9BD7D", -"C c #201EB8", -"D c #090AB8", -"E c #1616EB", -"F c #1818FD", -"G c #1414EE", -"H c #1010E1", -"I c #0E0EE2", -"J c #0E0EF4", -"K c #0606B2", -"L c #7A7A89", -"M c #0C0C9A", -"N c #0A0AA7", -"O c #2424E4", -"P c #6669E6", -"Q c #4F4A8F", -"R c #BF853B", -"S c #FFD98D", -"T c #CDAB76", -"U c #1717C4", -"V c #0F10BA", -"W c #0909B6", -"X c #0505C3", -"Y c #0000B6", -"Z c #0000BE", -"` c #0000AD", -" . c #1D1D83", -".. c #63638E", -"+. c #090975", -"@. c #1414F3", -"#. c #5B5BFF", -"$. c #7B7BFF", -"%. c #7070FF", -"&. c #6E6EFF", -"*. c #7172F6", -"=. c #625DAF", -"-. c #BA9E6C", -";. c #887167", -">. c #090DF2", -",. c #1313BE", -"'. c #000085", -"). c #0000AC", -"!. c #0202AA", -"~. c #242488", -"{. c #1414C7", -"]. c #1717FF", -"^. c #5959FF", -"/. c #7F7FFF", -"(. c #7474FF", -"_. c #7171FF", -":. c #8686FF", -"<. c #7574FF", -"[. c #797CFF", -"}. c #5756B8", -"|. c #1C19A4", -"1. c #1617FF", -"2. c #1212BD", -"3. c #040485", -"4. c #0707A4", -"5. c #1B1B71", -"6. c #373797", -"7. c #1616FF", -"8. c #5050FF", -"9. c #8080FF", -"0. c #AAAAFF", -"a. c #AEAEF6", -"b. c #8A8AEF", -"c. c #6969FB", -"d. c #2728FF", -"e. c #1314FF", -"f. c #1919FF", -"g. c #1313E8", -"h. c #1F1FF4", -"i. c #5454FF", -"j. c #6D6DF0", -"k. c #6868B5", -"l. c #0B0BB8", -"m. c #1212C5", -"n. c #1616FC", -"o. c #1515FF", -"p. c #1212FF", -"q. c #2323FF", -"r. c #3636FF", -"s. c #4040FF", -"t. c #4343F9", -"u. c #5D5DB8", -"v. c #7F7F92", -"w. c #878793", -"x. c #4B4B94", -"y. c #0B0CE2", -"z. c #1313FF", -"A. c #4C4CFF", -"B. c #8282FF", -"C. c #7171ED", -"D. c #636394", -"E. c #575785", -"F. c #A9A99C", -"G. c #1414BC", -"H. c #1414FF", -"I. c #0707FD", -"J. c #2525AA", -"K. c #A8A8A4", -"L. c #EBEBE2", -"M. c #F9F9F2", -"N. c #E1E1CC", -"O. c #4D4D9F", -"P. c #0B0BF7", -"Q. c #2121FF", -"R. c #3232FF", -"S. c #5555FF", -"T. c #6161B4", -"U. c #B5B5B2", -"V. c #FFFFF8", -"W. c #4F4F9A", -"X. c #0B0BF5", -"Y. c #1616C5", -"Z. c #A8A8A1", -"`. c #FFFFFC", -" + c #FFFFFF", -".+ c #C0C0C4", -"++ c #1212D4", -"@+ c #4444FF", -"#+ c #6464FF", -"$+ c #8383FF", -"%+ c #6767C3", -"&+ c #E4E4E4", -"*+ c #9494AE", -"=+ c #0808DF", -"-+ c #0D0DF2", -";+ c #61619A", -">+ c #F1F1E0", -",+ c #E8E8DD", -"'+ c #2424BB", -")+ c #1010FF", -"!+ c #3434FF", -"~+ c #6161FF", -"{+ c #6969D2", -"]+ c #EFEFF0", -"^+ c #C2C2BA", -"/+ c #1010B6", -"(+ c #0909AC", -"_+ c #A4A49A", -":+ c #EAEADE", -"<+ c #2525B8", -"[+ c #2F2FFF", -"}+ c #3C3CB5", -"|+ c #EEEEEE", -"1+ c #BBBBAD", -"2+ c #0B0B56", -"3+ c #0B0BFC", -"4+ c #1212EF", -"5+ c #0C0C3E", -"6+ c #919187", -"7+ c #DEDED6", -"8+ c #1F1FC0", -"9+ c #1A1AFF", -"0+ c #1717FA", -"a+ c #1515F8", -"b+ c #1111FC", -"c+ c #494992", -"d+ c #999998", -"e+ c #3E3E3B", -"f+ c #3C3C99", -"g+ c #535397", -"h+ c #5A5A4D", -"i+ c #6F6F70", -"j+ c #BFBFC9", -"k+ c #1111D6", -"l+ c #1515F1", -"m+ c #0F0FE2", -"n+ c #0D0DD9", -"o+ c #0909CD", -"p+ c #0808C7", -"q+ c #0505C7", -"r+ c #0303CB", -"s+ c #0101C0", -"t+ c #0202AF", -"u+ c #0606AC", -"v+ c #121283", -"w+ c #BBBBBB", -"x+ c #BEBEBE", -"y+ c #2F2F2E", -"z+ c #C7C8BB", -"A+ c #D8DAD1", -"B+ c #272828", -"C+ c #929292", -"D+ c #8688C7", -"E+ c #0506F6", -"F+ c #1616F5", -"G+ c #0B0BD3", -"H+ c #0202B6", -"I+ c #0000AF", -"J+ c #0000B4", -"K+ c #0000BD", -"L+ c #0000BB", -"M+ c #00009E", -"N+ c #2C2C7E", -"O+ c #6A6A8B", -"P+ c #959595", -"Q+ c #F0F0F1", -"R+ c #E1E1E1", -"S+ c #8C8E90", -"T+ c #BEBEBF", -"U+ c #C9C7C5", -"V+ c #939699", -"W+ c #E7EAED", -"X+ c #CBCBC7", -"Y+ c #413B9B", -"Z+ c #0607DD", -"`+ c #0C0CE2", -" @ c #0303B9", -".@ c #0000A8", -"+@ c #181888", -"@@ c #6A6A6A", -"#@ c #626263", -"$@ c #4B4B4C", -"%@ c #3E3B36", -"&@ c #9B805C", -"*@ c #D9B07D", -"=@ c #C9AE89", -"-@ c #B9AF9E", -";@ c #C7C5C4", -">@ c #CBCCCF", -",@ c #C7C6C6", -"'@ c #AEA59A", -")@ c #B69974", -"!@ c #D8B87F", -"~@ c #9B8272", -"{@ c #0E0B9B", -"]@ c #0000B7", -"^@ c #0000B8", -"/@ c #000082", -"(@ c #00007A", -"_@ c #636379", -":@ c #62533E", -"<@ c #B59B6C", -"[@ c #DEB07B", -"}@ c #FECC90", -"|@ c #FFCE92", -"1@ c #FEC98C", -"2@ c #F1BD82", -"3@ c #D1A979", -"4@ c #BC9E73", -"5@ c #CCA777", -"6@ c #EAB980", -"7@ c #FFCD90", -"8@ c #FFD595", -"9@ c #FDD782", -"0@ c #413678", -"a@ c #0000AE", -"b@ c #000077", -"c@ c #010193", -"d@ c #0C0CE4", -"e@ c #38389E", -"f@ c #EEC585", -"g@ c #FFDA9D", -"h@ c #FFC992", -"i@ c #FFC88F", -"j@ c #FFC990", -"k@ c #FFCE93", -"l@ c #FFD094", -"m@ c #FFCC92", -"n@ c #C9A174", -"o@ c #EDBD88", -"p@ c #FAD287", -"q@ c #3A2F7F", -"r@ c #0000BA", -"s@ c #0000B0", -"t@ c #0101B2", -"u@ c #1111ED", -"v@ c #1919C1", -"w@ c #95887C", -"x@ c #DCAC6E", -"y@ c #FFD393", -"z@ c #FFCD94", -"A@ c #FFCA93", -"B@ c #FFC991", -"C@ c #FFC78E", -"D@ c #FFCB91", -"E@ c #E0B581", -"F@ c #BB9A6F", -"G@ c #FFDC97", -"H@ c #C1A173", -"I@ c #0E0B9A", -"J@ c #0000B5", -"K@ c #0101B6", -"L@ c #1010E0", -"M@ c #1616EC", -"N@ c #A68156", -"O@ c #E7AC6B", -"P@ c #FFC582", -"Q@ c #FFCF8F", -"R@ c #FFD195", -"S@ c #FFD296", -"T@ c #FFD396", -"U@ c #FFD193", -"V@ c #FFD28F", -"W@ c #D2A96B", -"X@ c #2F2482", -"Y@ c #0000C1", -"Z@ c #0000C0", -"`@ c #0000BF", -" # c #0101BF", -".# c #1212F0", -"+# c #767698", -"@# c #9C866E", -"## c #A9865D", -"$# c #C0915D", -"%# c #C89760", -"&# c #C29360", -"*# c #AD8A61", -"=# c #9D8971", -"-# c #7F7A7A", -";# c #70708F", -"># c #6F6F91", -",# c #575788", -"'# c #464687", -")# c #2F2F87", -"!# c #15158F", -"~# c #0101A8", -"{# c #1313FB", -"]# c #57579F", -"^# c #343487", -"/# c #434388", -" ", -" ", -" ", -" . + @ # ", -" $ % & * = - ; > , ' ) ! ", -" ~ { ] ^ / = ( _ : < [ } | 1 2 3 4 5 6 ", -" 7 8 9 0 a b c d e f g h i j k l m n o p q r ", -" s t u v _ f d d d w x y z A B C D E F G H I J K L ", -" M N O _ c e d d d _ P Q R S T U V W X Y Z ` ... ", -" +.@.#.$.d d d d %.&._ *.=.-.;.>.,.'.).!.~. ", -" {.].^./.(.d d _.$.:._ <.[.}.|.1.2.3.4.5. ", -" 6.7.7.4 8.e : w 9.0.a.b.c.2 d.e.f.g.h.i.j.k. ", -" l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.o o z.A.B./.b C.D. ", -" E.F.G.].o H.z.I.J.K.L.M.N.O.P.o o o Q.R.S._.b B.T. ", -" U.V.W.X.f.f.7.Y.Z.`. + + +.+++].o o o.n z.q.@+#+$+%+ ", -" &+ +*+=+].o -+;+>+ + + + +,+'+H.o o o o o H.)+o !+~+{+ ", -" ]+ +^+/+H.o.(+_+ + + + + +:+<+z.o o o o o o o 7.n H.[+}+ ", -" |+ +1+2+3+4+5+6+ + + + + +7+8+H.o o f.9+f.9+f.F 0+a+b+o.c+ ", -" &+ +d+e+f+g+h+i+ + + + + +j+k+].f.9+l+m+n+o+p+q+r+s+t+u+v+ ", -" w+ +x+y+z+A+B+C+ + + + + +D+E+9+F+G+H+I+J+K+L+M+N+O+ ", -" P+Q+R+S+T+U+V+W+ + + + +X+Y+Z+`+ @I+J+Z .@+@E. ", -" @@#@$@%@&@*@=@-@;@>@,@'@)@!@~@{@]@^@I+/@(@_@ ", -" :@<@[@}@|@1@2@3@4@5@6@7@8@9@0@L+a@b@c@d@e@ ", -" f@g@h@i@i@j@k@l@|@m@n@o@p@q@r@s@t@u@p v@ ", -" w@x@y@z@A@B@i@C@D@E@F@G@H@I@L+J@K@L@p M@ ", -" N@O@P@Q@R@S@T@U@V@W@X@Y@Z@Y@`@ #.#p +# ", -" @###$#%#&#*#=#-#;#>#,#'#)#!#~#{#]# ", -" ^#/# ", -" ", -" ", -" ", -" "}; diff --git a/src/sdl12/SDL_main/SDL_dummy_main.c b/src/sdl12/SDL_main/SDL_dummy_main.c deleted file mode 100644 index d8cfdd5bb..000000000 --- a/src/sdl12/SDL_main/SDL_dummy_main.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Include the SDL main definition header */ -#include "SDL_main.h" - -#ifdef main -#undef main -int main(int argc, char *argv[]) -{ - return(SDL_main(argc, argv)); -} -#else -/* Nothing to do on this platform */; -#endif diff --git a/src/sdl12/SDL_main/SDL_macosx_main.h b/src/sdl12/SDL_main/SDL_macosx_main.h deleted file mode 100644 index 4683df57a..000000000 --- a/src/sdl12/SDL_main/SDL_macosx_main.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import - -@interface SDLMain : NSObject -@end diff --git a/src/sdl12/SDL_main/SDL_macosx_main.m b/src/sdl12/SDL_main/SDL_macosx_main.m deleted file mode 100644 index 226afe13d..000000000 --- a/src/sdl12/SDL_main/SDL_macosx_main.m +++ /dev/null @@ -1,374 +0,0 @@ -/* SDLMain.m - main entry point for our Cocoa-ized SDL app - Initial Version: Darrell Walisser - Non-NIB-Code & other changes: Max Horn - - Feel free to customize this file to suit your needs -*/ - -#import "SDL.h" -#import "SDL_macosx_main.h" -#import /* for MAXPATHLEN */ -#import - -/* For some reaon, Apple removed setAppleMenu from the headers in 10.4, - but the method still is there and works. To avoid warnings, we declare - it ourselves here. */ -@interface NSApplication(SDL_Missing_Methods) -- (void)setAppleMenu:(NSMenu *)menu; -@end - -/* Use this flag to determine whether we use SDLMain.nib or not */ -#define SDL_USE_NIB_FILE 0 - -/* Use this flag to determine whether we use CPS (docking) or not */ -#define SDL_USE_CPS 1 -#if SDL_USE_CPS -/* Portions of CPS.h */ -typedef struct CPSProcessSerNum -{ - UInt32 lo; - UInt32 hi; -} CPSProcessSerNum; - -extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); -extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); -extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); - -#endif /* SDL_USE_CPS */ - -static int gArgc; -static char **gArgv; -static BOOL gFinderLaunch; - -static void addArgument(const char *value) -{ - if(!gArgc) - gArgv = (char **)malloc(sizeof(*gArgv)); - else - { - char **newgArgv = (char **)realloc(gArgv, sizeof(*gArgv) * (gArgc + 1)); - if (!newgArgv) - { - newgArgv = malloc(sizeof(*gArgv) * (gArgc + 1)); - memcpy(newgArgv, gArgv, sizeof(*gArgv) * gArgc); - free(gArgv); - } - gArgv = newgArgv; - } - gArgc++; - gArgv[gArgc - 1] = (char *)malloc(sizeof(char) * (strlen(value) + 1)); - strcpy(gArgv[gArgc - 1], value); -} - -static NSString *getApplicationName(void) -{ - NSDictionary *dict; - NSString *appName = NULL; - - /* Determine the application name */ - dict = ( NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; - - if (![appName length]) - appName = [[NSProcessInfo processInfo] processName]; - - return appName; -} - -#if SDL_USE_NIB_FILE -/* A helper category for NSString */ -@interface NSString (ReplaceSubString) -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; -@end -#endif - -@interface SDLApplication : NSApplication -@end - -@implementation SDLApplication -/* Invoked from the Quit menu item */ -- (void)terminate:(id)sender -{ -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) - (void)sender; -#endif - /* Post a SDL_QUIT event */ - SDL_Event event; - event.type = SDL_QUIT; - SDL_PushEvent(&event); -} -@end - -/* The main class of the application, the application's delegate */ -@implementation SDLMain - -/* Set the working directory to the .app's parent directory */ -- (void) setupWorkingDirectory:(BOOL)shouldChdir -{ - if (shouldChdir) - { - char parentdir[MAXPATHLEN]; - CFURLRef url = CFBundleCopyBundleURL(CFBundleGetMainBundle()); - CFURLRef url2 = CFURLCreateCopyDeletingLastPathComponent(0, url); - if (CFURLGetFileSystemRepresentation(url2, true, (UInt8 *)parentdir, MAXPATHLEN)) - { - assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ - } - CFRelease(url); - CFRelease(url2); - } - -} - -#if SDL_USE_NIB_FILE - -/* Fix menu to contain the real app name instead of "SDL App" */ -- (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName -{ - NSRange aRange; - NSEnumerator *enumerator; - NSMenuItem *menuItem; - - aRange = [[aMenu title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; - - enumerator = [[aMenu itemArray] objectEnumerator]; - while ((menuItem = [enumerator nextObject])) - { - aRange = [[menuItem title] rangeOfString:@"SDL App"]; - if (aRange.length != 0) - [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; - if ([menuItem hasSubmenu]) - [self fixMenu:[menuItem submenu] withAppName:appName]; - } - [ aMenu sizeToFit ]; -} - -#else - -static void setApplicationMenu(void) -{ - /* warning: this code is very odd */ - NSMenu *appleMenu; - NSMenuItem *menuItem; - NSString *title; - NSString *appName; - - appName = getApplicationName(); - appleMenu = [[NSMenu alloc] initWithTitle:@""]; - - /* Add menu items */ - title = [@"About " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Hide " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(hide:) keyEquivalent:@"h"]; - - menuItem = (NSMenuItem *)[appleMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; - [menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|NSCommandKeyMask)]; - - [appleMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; - - [appleMenu addItem:[NSMenuItem separatorItem]]; - - title = [@"Quit " stringByAppendingString:appName]; - [appleMenu addItemWithTitle:title action:@selector(terminate:) keyEquivalent:@"q"]; - - - /* Put menu into the menubar */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; - [menuItem setSubmenu:appleMenu]; - [[NSApp mainMenu] addItem:menuItem]; - - /* Tell the application object that this is now the application menu */ - [NSApp setAppleMenu:appleMenu]; - - /* Finally give up our references to the objects */ - [appleMenu release]; - [menuItem release]; -} - -/* Create a window menu */ -static void setupWindowMenu(void) -{ - NSMenu *windowMenu; - NSMenuItem *windowMenuItem; - NSMenuItem *menuItem; - - windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; - - /* "Minimize" item */ - menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; - [windowMenu addItem:menuItem]; - [menuItem release]; - - /* Put menu into the menubar */ - windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; - [windowMenuItem setSubmenu:windowMenu]; - [[NSApp mainMenu] addItem:windowMenuItem]; - - /* Tell the application object that this is now the window menu */ - [NSApp setWindowsMenu:windowMenu]; - - /* Finally give up our references to the objects */ - [windowMenu release]; - [windowMenuItem release]; -} - -/* Replacement for NSApplicationMain */ -static void CustomApplicationMain (int argc, char **argv) -{ -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) - (void)argc; - (void)argv; -#endif - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - SDLMain *sdlMain; - - /* Ensure the application object is initialised */ - [SDLApplication sharedApplication]; - -#if SDL_USE_CPS - { - CPSProcessSerNum PSN; - /* Tell the dock about us */ - if (!CPSGetCurrentProcess(&PSN)) - if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103)) - if (!CPSSetFrontProcess(&PSN)) - [SDLApplication sharedApplication]; - } -#endif /* SDL_USE_CPS */ - - /* Set up the menubar */ - [NSApp setMainMenu:[[NSMenu alloc] init]]; - setApplicationMenu(); - setupWindowMenu(); - - /* Create SDLMain and make it the app delegate */ - sdlMain = [[SDLMain alloc] init]; - [NSApp setDelegate:sdlMain]; - - /* Start the main event loop */ - [NSApp run]; - - [sdlMain release]; - [pool release]; -} - -#endif - -- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename -{ -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) - (void)theApplication; -#endif - addArgument("-iwad"); - addArgument([filename UTF8String]); - return YES; -} - -/* Called when the internal event loop has just started running */ -- (void) applicationDidFinishLaunching: (NSNotification *) note -{ -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) - (void)note; -#endif - int status; - - /* Set the working directory to the .app's parent directory */ - [self setupWorkingDirectory:gFinderLaunch]; - -#if SDL_USE_NIB_FILE - /* Set the main menu to contain the real app name instead of "SDL App" */ - [self fixMenu:[NSApp mainMenu] withAppName:getApplicationName()]; -#endif - - if (!getenv("SRB2WADDIR")) - setenv("SRB2WADDIR", [[[NSBundle mainBundle] resourcePath] UTF8String], 1); - - /* Hand off to main application code */ - status = SDL_main (gArgc, gArgv); - - /* We're done, thank you for playing */ - exit(status); -} -@end - - -@implementation NSString (ReplaceSubString) - -- (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString -{ - size_t bufferSize; - size_t selfLen = [self length]; - size_t aStringLen = [aString length]; - unichar *buffer; - NSRange localRange; - NSString *result; - - bufferSize = selfLen + aStringLen - aRange.length; - buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); - - /* Get first part into buffer */ - localRange.location = 0; - localRange.length = aRange.location; - [self getCharacters:buffer range:localRange]; - - /* Get middle part into buffer */ - localRange.location = 0; - localRange.length = aStringLen; - [aString getCharacters:(buffer+aRange.location) range:localRange]; - - /* Get last part into buffer */ - localRange.location = aRange.location + aRange.length; - localRange.length = selfLen - localRange.location; - [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; - - /* Build output string */ - result = [NSString stringWithCharacters:buffer length:bufferSize]; - - NSDeallocateMemoryPages(buffer, bufferSize); - - return result; -} - -@end - - - -#ifdef main -# undef main -#endif - - -/* Main entry point to executable - should *not* be SDL_main! */ -int main (int argc, char **argv) -{ - - /* Copy the arguments into a global variable */ - - /* This is passed if we are launched by double-clicking */ - if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { - gArgc = 1; - gFinderLaunch = YES; - } else { - gArgc = argc; - gFinderLaunch = NO; - } - gArgv = argv; - - /* Some additional arguments we always want to run with. */ - //addArgument("-opengl"); - -#if SDL_USE_NIB_FILE - [SDLApplication poseAsClass:[NSApplication class]]; - NSApplicationMain (argc, argv); -#else - CustomApplicationMain (argc, argv); -#endif - return 0; -} diff --git a/src/sdl12/SDL_main/SDL_openxdk_main.c b/src/sdl12/SDL_main/SDL_openxdk_main.c deleted file mode 100644 index 63db8da2d..000000000 --- a/src/sdl12/SDL_main/SDL_openxdk_main.c +++ /dev/null @@ -1,7 +0,0 @@ -/* Include the SDL main definition header */ -#include "SDL_main.h" - -void XBoxStartup() -{ - SDL_main(0, NULL); /// \todo ? -} diff --git a/src/sdl12/SDL_main/SDL_win32_main.c b/src/sdl12/SDL_main/SDL_win32_main.c deleted file mode 100644 index 46b20d0bd..000000000 --- a/src/sdl12/SDL_main/SDL_win32_main.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - SDL_main.c, placed in the public domain by Sam Lantinga 4/13/98 - - The WinMain function -- calls your program's main() function -*/ - -#include -#include -#include -#include -#define RPC_NO_WINDOWS_H -#include -#include /* For _alloca() */ - -#include - -#ifdef _WIN32_WCE -# define DIR_SEPERATOR TEXT("\\") -# define _tgetcwd(str,len) wcscpy(str,TEXT("")) -# define setbuf(f,b) -# define setvbuf(w,x,y,z) -# define _tremove(x) DeleteFile(x) -#else -# define DIR_SEPERATOR TEXT("/") -# include -#endif - -/* Include the SDL main definition header */ -#ifdef _MSC_VER -#pragma warning(disable : 4214 4244) -#endif -#include "SDL.h" -#include "SDL_main.h" -#ifdef _MSC_VER -#pragma warning(default : 4214 4244) -#endif -#include "../../win32/win_dbg.h" -#define USE_MESSAGEBOX - -#ifdef main -# ifndef _WIN32_WCE_EMULATION -# undef main -# endif /* _WIN32_WCE_EMULATION */ -#endif /* main */ - -/* The standard output files */ -//#ifdef _WIN32_WCE -//#define STDOUT_FILE TEXT("/Storage Card/SRB2DEMO/stdout.txt") -//#define STDERR_FILE TEXT("/Storage Card/SRB2DEMO/stderr.txt") -//#else -#define STDOUT_FILE TEXT("stdout.txt") -#define STDERR_FILE TEXT("stderr.txt") -//#endif - -#ifndef NO_STDIO_REDIRECT - static TCHAR stdoutPath[MAX_PATH]; - static TCHAR stderrPath[MAX_PATH]; -#endif - -#if defined(_WIN32_WCE) && _WIN32_WCE < 300 -/* seems to be undefined in Win CE although in online help */ -#define isspace(a) (((CHAR)a == ' ') || ((CHAR)a == '\t')) - -/* seems to be undefined in Win CE although in online help */ -char *strrchr(char *str, int c) -{ - char *p; - - /* Skip to the end of the string */ - p=str; - while (*p) - p++; - - /* Look for the given character */ - while ( (p >= str) && (*p != (CHAR)c) ) - p--; - - /* Return NULL if character not found */ - if ( p < str ) { - p = NULL; - } - return p; -} -#endif /* _WIN32_WCE < 300 */ - -/* Parse a command line buffer into arguments */ -static int ParseCommandLine(char *cmdline, char **argv) -{ - char *bufp; - int argc; - - argc = 0; - for ( bufp = cmdline; *bufp; ) { - /* Skip leading whitespace */ - while ( isspace(*bufp) ) { - ++bufp; - } - /* Skip over argument */ - if ( *bufp == '"' ) { - ++bufp; - if ( *bufp ) { - if ( argv ) { - argv[argc] = bufp; - } - ++argc; - } - /* Skip over word */ - while ( *bufp && (*bufp != '"') ) { - ++bufp; - } - } else { - if ( *bufp ) { - if ( argv ) { - argv[argc] = bufp; - } - ++argc; - } - /* Skip over word */ - while ( *bufp && ! isspace(*bufp) ) { - ++bufp; - } - } - if ( *bufp ) { - if ( argv ) { - *bufp = '\0'; - } - ++bufp; - } - } - if ( argv ) { - argv[argc] = NULL; - } - return(argc); -} - -/* Show an error message */ -static void ShowError(const char *title, const char *message) -{ -/* If USE_MESSAGEBOX is defined, you need to link with user32.lib */ -#ifdef USE_MESSAGEBOX - MessageBoxA(NULL, - message, - title, - MB_ICONEXCLAMATION|MB_OK); -#else - fprintf(stderr, "%s: %s\n", title, message); -#endif -} - -/* Pop up an out of memory message, returns to Windows */ -static BOOL OutOfMemory(void) -{ - ShowError("Fatal Error", "Out of memory - aborting"); - return FALSE; -} - -/* Remove the output files if there was no output written */ -static void __cdecl cleanup_output(void) -{ -#ifndef NO_STDIO_REDIRECT - FILE *file; - int empty; -#endif - - /* Flush the output in case anything is queued */ - fclose(stdout); - fclose(stderr); - -#ifndef NO_STDIO_REDIRECT - /* See if the files have any output in them */ - if ( stdoutPath[0] ) { - file = _tfopen(stdoutPath, TEXT("rb")); - if ( file ) { - empty = (fgetc(file) == EOF) ? 1 : 0; - fclose(file); - if ( empty ) { - _tremove(stdoutPath); - } - } - } - if ( stderrPath[0] ) { - file = _tfopen(stderrPath, TEXT("rb")); - if ( file ) { - empty = (fgetc(file) == EOF) ? 1 : 0; - fclose(file); - if ( empty ) { - _tremove(stderrPath); - } - } - } -#endif -} - -#if defined(_MSC_VER) && !defined(_WIN32_WCE) -/* The VC++ compiler needs main defined */ -#define console_main main -#endif - -/* This is where execution begins [console apps] */ -int console_main(int argc, char *argv[]) -{ - size_t n; - int st; - char *bufp, *appname; - - /* Get the class name from argv[0] */ - appname = argv[0]; - if ( (bufp=strrchr(argv[0], '\\')) != NULL ) { - appname = bufp+1; - } else - if ( (bufp=strrchr(argv[0], '/')) != NULL ) { - appname = bufp+1; - } - - if ( (bufp=strrchr(appname, '.')) == NULL ) - n = strlen(appname); - else - n = (bufp-appname); - - bufp = (char *)alloca(n+1); - if ( bufp == NULL ) { - return OutOfMemory(); - } - strncpy(bufp, appname, n); - bufp[n] = '\0'; - appname = bufp; - - /* Load SDL dynamic link library */ - if ( SDL_Init(SDL_INIT_NOPARACHUTE) < 0 ) { - ShowError("WinMain() error", SDL_GetError()); - return(FALSE); - } - atexit(cleanup_output); - atexit(SDL_Quit); - -#ifndef DISABLE_VIDEO -#if 0 - /* Create and register our class * - DJM: If we do this here, the user nevers gets a chance to - putenv(SDL_WINDOWID). This is already called later by - the (DIB|DX5)_CreateWindow function, so it should be - safe to comment it out here. - if ( SDL_RegisterApp(appname, CS_BYTEALIGNCLIENT, - GetModuleHandle(NULL)) < 0 ) { - ShowError("WinMain() error", SDL_GetError()); - exit(1); - }*/ -#else - /* Sam: - We still need to pass in the application handle so that - DirectInput will initialize properly when SDL_RegisterApp() - is called later in the video initialization. - */ - SDL_SetModuleHandle(GetModuleHandle(NULL)); -#endif /* 0 */ -#endif /* !DISABLE_VIDEO */ - - /* Run the application main() code */ - st = SDL_main(argc, argv); - - /* Exit cleanly, calling atexit() functions */ - //exit(0); - cleanup_output(); - SDL_Quit(); - - /* Hush little compiler, don't you cry... */ - return st; -} - -/* This is where execution begins [windowed apps] */ -#ifdef _WIN32_WCE -int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPWSTR szCmdLine, int sw) -#else -int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) -#endif -{ - HINSTANCE handle; - int Result = -1; - char **argv; - int argc; - LPSTR cmdline; -#ifdef _WIN32_WCE - size_t nLen; - LPTSTR bufp; -#else - LPSTR bufp; -#endif -#ifndef NO_STDIO_REDIRECT - FILE *newfp; -#endif - - /* Start up DDHELP.EXE before opening any files, so DDHELP doesn't - keep them open. This is a hack.. hopefully it will be fixed - someday. DDHELP.EXE starts up the first time DDRAW.DLL is loaded. - */ - hPrev = hInst = NULL; - sw = 0; - handle = LoadLibrary(TEXT("DDRAW.DLL")); - if ( handle != NULL ) { - FreeLibrary(handle); - } - -#ifndef NO_STDIO_REDIRECT - _tgetcwd( stdoutPath, sizeof( stdoutPath ) ); - _tcscat( stdoutPath, DIR_SEPERATOR STDOUT_FILE ); - - /* Redirect standard input and standard output */ - newfp = _tfreopen(stdoutPath, TEXT("w"), stdout); - -#ifndef _WIN32_WCE - if ( newfp == NULL ) { /* This happens on NT */ -#if !defined(stdout) - stdout = _tfopen(stdoutPath, TEXT("w")); -#else - newfp = _tfopen(stdoutPath, TEXT("w")); - if ( newfp ) { - *stdout = *newfp; - } -#endif - } -#endif /* _WIN32_WCE */ - - _tgetcwd( stderrPath, sizeof( stderrPath ) ); - _tcscat( stderrPath, DIR_SEPERATOR STDERR_FILE ); - - newfp = _tfreopen(stderrPath, TEXT("w"), stderr); -#ifndef _WIN32_WCE - if ( newfp == NULL ) { /* This happens on NT */ -#if !defined(stderr) - stderr = _tfopen(stderrPath, TEXT("w")); -#else - newfp = _tfopen(stderrPath, TEXT("w")); - if ( newfp ) { - *stderr = *newfp; - } -#endif - } -#endif /* _WIN32_WCE */ - - setvbuf(stdout, NULL, _IOLBF, BUFSIZ); /* Line buffered */ - setbuf(stderr, NULL); /* No buffering */ -#endif /* !NO_STDIO_REDIRECT */ - -#ifdef _WIN32_WCE - nLen = wcslen(szCmdLine)+128+1; - bufp = (wchar_t *)alloca(nLen*2); - wcscpy (bufp, TEXT("\"")); - GetModuleFileName(NULL, bufp+1, 128-3); - wcscpy (bufp+wcslen(bufp), TEXT("\" ")); - wcsncpy(bufp+wcslen(bufp), szCmdLine,nLen-wcslen(bufp)); - nLen = wcslen(bufp)+1; - cmdline = (char *)alloca(nLen); - if ( cmdline == NULL ) { - return OutOfMemory(); - } - WideCharToMultiByte(CP_ACP, 0, bufp, -1, cmdline, nLen, NULL, NULL); -#else - szCmdLine = NULL; - /* Grab the command line (use alloca() on Windows) */ - bufp = GetCommandLineA(); - cmdline = (LPSTR)alloca(strlen(bufp)+1); - if ( cmdline == NULL ) { - return OutOfMemory(); - } - strcpy(cmdline, bufp); -#endif - - /* Parse it into argv and argc */ - argc = ParseCommandLine(cmdline, NULL); - argv = (char **)alloca((argc+1)*(sizeof *argv)); - if ( argv == NULL ) { - return OutOfMemory(); - } - ParseCommandLine(cmdline, argv); - -#ifdef BUGTRAP - /* Try BugTrap. */ - if(InitBugTrap()) - Result = console_main(argc, argv); - else - { -#endif - - /* Run the main program (after a little SDL initialization) */ -#ifndef _WIN32_WCE - __try -#endif - { - Result = console_main(argc, argv); - } -#ifndef _WIN32_WCE - __except ( RecordExceptionInfo(GetExceptionInformation())) - { - SetUnhandledExceptionFilter(EXCEPTION_CONTINUE_SEARCH); //Do nothing here. - } -#endif - -#ifdef BUGTRAP - } /* BT failure clause. */ - - /* This is safe even if BT didn't start. */ - ShutdownBugTrap(); -#endif - - return Result; -} diff --git a/src/sdl12/SRB2CE/Makefile.cfg b/src/sdl12/SRB2CE/Makefile.cfg deleted file mode 100644 index 8d4ae3e48..000000000 --- a/src/sdl12/SRB2CE/Makefile.cfg +++ /dev/null @@ -1,12 +0,0 @@ -# -# Makefile.cfg for WinCE with GCC -# - -OPTS+=-D_WIN32_WCE -D_UNICODE -SDL_CFLAGS?= -SDL_LDFLAGS?= -NOHS=1 -NOHW=1 -NONET=1 -NOMIXER=1 -NOPNG=1 diff --git a/src/sdl12/SRB2CE/SRB2CE.zip b/src/sdl12/SRB2CE/SRB2CE.zip deleted file mode 100644 index 3ac8530dc..000000000 Binary files a/src/sdl12/SRB2CE/SRB2CE.zip and /dev/null differ diff --git a/src/sdl12/SRB2CE/cehelp.c b/src/sdl12/SRB2CE/cehelp.c deleted file mode 100644 index 13505cff7..000000000 --- a/src/sdl12/SRB2CE/cehelp.c +++ /dev/null @@ -1,446 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2004-2018 by Sonic Team Jr. -// -// 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: -// stub and replacement "ANSI" C functions for use under Windows CE -// -//----------------------------------------------------------------------------- - -#include "../../doomdef.h" -#include "cehelp.h" - -#define _SEC_IN_MINUTE 60 -#define _SEC_IN_HOUR 3600 -#define _SEC_IN_DAY 86400 - -static const int DAYS_IN_MONTH[12] = -{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; - -#define _DAYS_IN_MONTH(x) ((x == 1) ? days_in_feb : DAYS_IN_MONTH[x]) - -static const int _DAYS_BEFORE_MONTH[12] = -{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; - -#define _ISLEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || (((y)+1900) % 400) == 0)) -#define _DAYS_IN_YEAR(year) (_ISLEAP(year) ? 366 : 365) - -char *strerror(int ecode) -{ - static char buff[1024 + 1]; - DWORD dwMsgLen = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - ecode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), &buff[0], 1024, NULL); - return buff; -} - -int unlink( const char *filename ) -{ - return remove(filename); -} - -int remove( const char *path ) -{ - return DeleteFileA(path)-1; -} - -int rename( const char *oldname, const char *newname ) -{ - return MoveFileA(oldname, newname)!=0; -} - -static inline void STToTM(const SYSTEMTIME *st, struct tm *tm) -{ - if (!st || !tm) return; - tm->tm_sec = st->wSecond; - tm->tm_min = st->wMinute; - tm->tm_hour = st->wHour; - tm->tm_mday = st->wDay; - tm->tm_mon = st->wMonth - 1; - tm->tm_year = st->wYear - 1900; - tm->tm_wday = st->wDayOfWeek; - tm->tm_yday = 0; - tm->tm_isdst = 0; -} - -time_t time(time_t *T) -{ - time_t returntime; - SYSTEMTIME st; - struct tm stft; - GetSystemTime(&st); - STToTM(&st,&stft); - returntime = mktime(&stft); - if (T) *T = returntime; - return returntime; -} - -static inline UINT64 TTtoFT(const time_t wt, FILETIME *ft) -{ - UINT64 temptime = wt; // FILETIME: 1/(10^7) secs since January 1, 1601 - temptime *= 10000000; // time_t : 1 secs since January 1, 1970 - // 369 years * 365 days * 24 hours * 60 mins * 60 secs * 10 - // 123 leaps days * 24 hours * 60 mins * 60 secs * 10 - temptime += 116444736000000000; - if (ft) CopyMemory(ft,&temptime,sizeof (ULARGE_INTEGER)); - return temptime; -} - -static struct tm cehelptm; - -struct tm * localtime(const time_t *CLOCK) -{ - SYSTEMTIME st; - FILETIME stft; - UINT64 ftli = 0; - if (CLOCK) ftli = TTtoFT(*CLOCK, &stft); - if (ftli) - FileTimeToSystemTime(&stft,&st); - else - GetSystemTime(&st); - STToTM(&st,&cehelptm); - if (st.wYear >= 1970) - return &cehelptm; - else - return NULL; -} - -static void validate_structure (struct tm *tim_p) // from newlib -{ - div_t res; - int days_in_feb = 28; - - /* calculate time & date to account for out of range values */ - if (tim_p->tm_sec < 0 || tim_p->tm_sec > 59) - { - res = div (tim_p->tm_sec, 60); - tim_p->tm_min += res.quot; - if ((tim_p->tm_sec = res.rem) < 0) - { - tim_p->tm_sec += 60; - --tim_p->tm_min; - } - } - - if (tim_p->tm_min < 0 || tim_p->tm_min > 59) - { - res = div (tim_p->tm_min, 60); - tim_p->tm_hour += res.quot; - if ((tim_p->tm_min = res.rem) < 0) - { - tim_p->tm_min += 60; - --tim_p->tm_hour; - } - } - - if (tim_p->tm_hour < 0 || tim_p->tm_hour > 23) - { - res = div (tim_p->tm_hour, 24); - tim_p->tm_mday += res.quot; - if ((tim_p->tm_hour = res.rem) < 0) - { - tim_p->tm_hour += 24; - --tim_p->tm_mday; - } - } - - if (tim_p->tm_mon > 11) - { - res = div (tim_p->tm_mon, 12); - tim_p->tm_year += res.quot; - if ((tim_p->tm_mon = res.rem) < 0) - { - tim_p->tm_mon += 12; - --tim_p->tm_year; - } - } - - if (_DAYS_IN_YEAR (tim_p->tm_year) == 366) - days_in_feb = 29; - - if (tim_p->tm_mday <= 0) - { - while (tim_p->tm_mday <= 0) - { - if (--tim_p->tm_mon == -1) - { - tim_p->tm_year--; - tim_p->tm_mon = 11; - days_in_feb = - ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? - 29 : 28); - } - tim_p->tm_mday += _DAYS_IN_MONTH (tim_p->tm_mon); - } - } - else - { - while (tim_p->tm_mday > _DAYS_IN_MONTH (tim_p->tm_mon)) - { - tim_p->tm_mday -= _DAYS_IN_MONTH (tim_p->tm_mon); - if (++tim_p->tm_mon == 12) - { - tim_p->tm_year++; - tim_p->tm_mon = 0; - days_in_feb = - ((_DAYS_IN_YEAR (tim_p->tm_year) == 366) ? - 29 : 28); - } - } - } -} - -time_t mktime (struct tm *tim_p) // from newlib -{ - time_t tim = 0; - long days = 0; - int year; - - /* validate structure */ - validate_structure (tim_p); - - /* compute hours, minutes, seconds */ - tim += tim_p->tm_sec + (tim_p->tm_min * _SEC_IN_MINUTE) + - (tim_p->tm_hour * _SEC_IN_HOUR); - - /* compute days in year */ - days += tim_p->tm_mday - 1; - days += _DAYS_BEFORE_MONTH[tim_p->tm_mon]; - if (tim_p->tm_mon > 1 && _DAYS_IN_YEAR (tim_p->tm_year) == 366) - days++; - - /* compute day of the year */ - tim_p->tm_yday = days; - - if (tim_p->tm_year > 10000 - || tim_p->tm_year < -10000) - { - return (time_t) -1; - } - - /* compute days in other years */ - if (tim_p->tm_year > 70) - { - for (year = 70; year < tim_p->tm_year; year++) - days += _DAYS_IN_YEAR (year); - } - else if (tim_p->tm_year < 70) - { - for (year = 69; year > tim_p->tm_year; year--) - days -= _DAYS_IN_YEAR (year); - days -= _DAYS_IN_YEAR (year); - } - - /* compute day of the week */ - if ((tim_p->tm_wday = (days + 4) % 7) < 0) - tim_p->tm_wday += 7; - - /* compute total seconds */ - tim += (days * _SEC_IN_DAY); - - return tim; -} - -#undef WINAPI -#define WINAPI __stdcall //__delcspec(dllexport) - -#ifdef _MSC_VER -//#pragma warning(disable : 4273) -#endif - - -static __forceinline int STRtoWSTR(LPCSTR lpMultiByteStr, int cchMultiByte, - LPWSTR lpWideCharStr, int cchWideChar) -{ - return MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,lpMultiByteStr, - cchMultiByte,lpWideCharStr,cchWideChar); -} - -static __forceinline int WSTRtoSTR(LPCWSTR lpWideCharStr, int cchWideChar, - LPSTR lpMultiByteStr, int cbMultiByte) -{ - return WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK|WC_SEPCHARS, - lpWideCharStr,cchWideChar,lpMultiByteStr,cbMultiByte,NULL,NULL); -} - -DWORD WINAPI FormatMessageA( - DWORD dwFlags, - LPCVOID lpSource, - DWORD dwMessageId, - DWORD dwLanguageId, - LPSTR lpBuffer, - DWORD nSize, - va_list *Arguments) -{ - const int nSizeW = STRtoWSTR(lpBuffer,nSize,NULL,0); - int nSizeF = 0; - LPWSTR lpBufferW = alloca(sizeof (wchar_t)*nSizeW); - LPWSTR lpSourceW = NULL; - - if (!lpBufferW) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - ZeroMemory(lpBuffer,nSize); - return nSizeF; - } - - if (dwFlags & FORMAT_MESSAGE_FROM_STRING) - { - const int sLen = STRtoWSTR(lpSource, -1, NULL, 0); - lpSourceW = alloca(sizeof (wchar_t)*sLen); - - if (lpSourceW) - STRtoWSTR(lpSource, -1, lpSourceW, sLen); - else - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return nSizeF; - } - } - - if (lpSourceW) - nSizeF = FormatMessageW(dwFlags, lpSourceW, dwMessageId, dwLanguageId, - lpBufferW, nSizeW, Arguments); - else - nSizeF = FormatMessageW(dwFlags, lpSource, dwMessageId, dwLanguageId, - lpBufferW, nSizeW, Arguments); - - return WSTRtoSTR(lpBufferW, nSizeF, lpBuffer, nSize); -} - -BOOL WINAPI DeleteFileA( - LPCSTR lpFileName) -{ - const int sLen = STRtoWSTR(lpFileName, -1, NULL, 0); - LPWSTR lpFileNameW = alloca(sizeof (wchar_t)*sLen); - - if (lpFileNameW) - STRtoWSTR(lpFileName, -1, lpFileNameW, sLen); - else - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - return DeleteFileW(lpFileNameW); -} - -BOOL WINAPI MoveFileA( - LPCSTR lpExistingFileName, - LPCSTR lpNewFileName -) -{ - const int sLen1 = STRtoWSTR(lpExistingFileName, -1, NULL, 0); - LPWSTR lpExistingFileNameW = alloca(sizeof (wchar_t)*sLen1); - - const int sLen2 = STRtoWSTR(lpNewFileName, -1, NULL, 0); - LPWSTR lpNewFileNameW = alloca(sizeof (wchar_t)*sLen2); - - - if (!lpExistingFileNameW || !lpNewFileNameW) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - STRtoWSTR(lpExistingFileName, -1, lpExistingFileNameW, sLen1); - STRtoWSTR(lpNewFileName, -1, lpNewFileNameW, sLen2); - - return MoveFileW(lpExistingFileNameW, lpNewFileNameW); -} - - -HANDLE WINAPI CreateFileA( - LPCSTR lpFileName, - DWORD dwDesiredAccess, - DWORD dwShareMode, - LPSECURITY_ATTRIBUTES lpSecurityAttributes, - DWORD dwCreationDisposition, - DWORD dwFlagsAndAttributes, - HANDLE hTemplateFile) -{ - const int sLen = STRtoWSTR(lpFileName, -1, NULL, 0); - LPWSTR lpFileNameW = alloca(sizeof (wchar_t)*sLen); - - if (lpFileNameW) - STRtoWSTR(lpFileName, -1, lpFileNameW, sLen); - else - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return INVALID_HANDLE_VALUE; - } - - return CreateFileW(lpFileNameW, dwDesiredAccess, dwShareMode, - lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, - hTemplateFile); -} - -BOOL WINAPI CreateDirectoryA( - LPCSTR lpPathName, - LPSECURITY_ATTRIBUTES lpSecurityAttributes) -{ - const int sLen = STRtoWSTR(lpPathName, -1, NULL, 0); - LPWSTR lpPathNameW = alloca(sizeof (wchar_t)*sLen); - - if (lpPathNameW) - STRtoWSTR(lpPathName, -1, lpPathNameW, sLen); - else - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - return CreateDirectoryW(lpPathNameW, lpSecurityAttributes); -} - -int WINAPI MessageBoxA( - HWND hWnd , - LPCSTR lpText, - LPCSTR lpCaption, - UINT uType) -{ - const int sLen1 = STRtoWSTR(lpText, -1, NULL, 0); - LPWSTR lpTextW = alloca(sizeof (wchar_t)*sLen1); - - const int sLen2 = STRtoWSTR(lpCaption, -1, NULL, 0); - LPWSTR lpCaptionW = alloca(sizeof (wchar_t)*sLen2); - - - if (!lpTextW || !lpCaptionW) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return 0; - } - - STRtoWSTR(lpText, -1, lpTextW, sLen1); - STRtoWSTR(lpCaption, -1, lpCaptionW, sLen2); - - return MessageBoxW(hWnd, lpTextW, lpCaptionW, uType); -} - -VOID WINAPI OutputDebugStringA( - LPCSTR lpOutputString) -{ - const int sLen = STRtoWSTR(lpOutputString, -1, NULL, 0); - LPWSTR lpOutputStringW = alloca(sizeof (wchar_t)*sLen); - - if (lpOutputStringW) - STRtoWSTR(lpOutputString, -1, lpOutputStringW, sLen); - else - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - return; - } - - OutputDebugStringW(lpOutputStringW); -} diff --git a/src/sdl12/SRB2CE/cehelp.h b/src/sdl12/SRB2CE/cehelp.h deleted file mode 100644 index 3ed0d9dd4..000000000 --- a/src/sdl12/SRB2CE/cehelp.h +++ /dev/null @@ -1,63 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2004-2018 by Sonic Team Jr. -// -// 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: -// stub and replacement "ANSI" C functions for use under Windows CE -// -//----------------------------------------------------------------------------- - -#ifndef __I_WINCE__ -#define __I_WINCE__ - -#ifdef USEASMCE -#define USEASM // Remline if NASM doesn't work on x86 targets -#endif - -char *strerror(int ecode); -int access(const char *path, int amode); -int unlink( const char *filename ); -int remove( const char *path ); -int rename( const char *oldname, const char *newname ); -//CreateDirectoryEx( const char *currectpath, const char *path,SECURITY_ATTRIBUTES) - -#ifndef _TIME_T_DEFINED -typedef long time_t; /* time value */ -#define _TIME_T_DEFINED /* avoid multiple def's of time_t */ -#endif - -time_t time(time_t *T); - -#ifndef __GNUC__ -#ifndef _TM_DEFINED -struct tm { - int tm_sec; /* seconds after the minute - [0,59] */ - int tm_min; /* minutes after the hour - [0,59] */ - int tm_hour; /* hours since midnight - [0,23] */ - int tm_mday; /* day of the month - [1,31] */ - int tm_mon; /* months since January - [0,11] */ - int tm_year; /* years since 1900 */ - int tm_wday; /* days since Sunday - [0,6] */ - int tm_yday; /* days since January 1 - [0,365] */ - int tm_isdst; /* daylight savings time flag */ - }; -#define _TM_DEFINED -#endif - -struct tm * localtime(const time_t *CLOCK); - -time_t mktime (struct tm *tim_p); -#endif - -#endif diff --git a/src/sdl12/SRB2DC/.gitignore b/src/sdl12/SRB2DC/.gitignore deleted file mode 100644 index a966585d4..000000000 --- a/src/sdl12/SRB2DC/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/scramble diff --git a/src/sdl12/SRB2DC/IP.BIN b/src/sdl12/SRB2DC/IP.BIN deleted file mode 100644 index c3366213b..000000000 Binary files a/src/sdl12/SRB2DC/IP.BIN and /dev/null differ diff --git a/src/sdl12/SRB2DC/Makefile.cfg b/src/sdl12/SRB2DC/Makefile.cfg deleted file mode 100644 index 3edaf8a16..000000000 --- a/src/sdl12/SRB2DC/Makefile.cfg +++ /dev/null @@ -1,53 +0,0 @@ -# -# Makefile.cfg for SRB2/Dreamcast -# - -#include $(KOS_BASE)/Makefile.rules - -# -#hmmm, the Dreamcast -# - - HOSTCC:=$(CC) - CC=$(KOS_CC) - PREFIX=$(KOS_CC_BASE)/bin/$(KOS_CC_PREFIX) - OBJDUMP=$(PREFIX)-objdump - OBJCOPY=$(PREFIX)-objcopy - - #NOHW=1 #No working MiniGL right now - NOHS=1 #No HWSound right now -ifndef LWIP - NONET=1 #No LWIP -endif - #i_net_o=$(OBJDIR)/i_udp.o #use KOS's UDP - #NOMIXER=1 #Basic sound only - NOIPX=1 #No IPX network code - NOPNG=1 #No Screenshot - - OPTS=$(KOS_CFLAGS) -DUNIXCOMMON -DDC -ifndef NOHW - OPTS+=-DSTATIC_OPENGL -DMINI_GL_COMPATIBILITY -DKOS_GL_COMPATIBILITY -endif - SDL_CFLAGS?=-I$(KOS_BASE)/addons/include/SDL - SDL_LDFLAGS?=-lSDL - LDFLAGS=$(KOS_LDFLAGS) - LIBS:=$(KOS_LIBS) -lconio -lm -ifndef NOMIXER - LIBS:=-loggvorbisplay -lSDL $(LIBS) -endif - -ifdef LWIP - OPTS+=-I$(KOS_BASE)/../kos-ports/lwip/kos/include -I$(KOS_BASE)/../kos-ports/lwip/lwip/src/include/ipv4 -I$(KOS_BASE)/../kos-ports/lwip/lwip/src/include -DIPv4 - LIBS:=-llwip4 -lkosutils $(LIBS) - OPTS+=-DHAVE_LWIP -endif -ifndef NOHW - LIBS+=-lgl -endif - - i_system_o+=$(OBJDIR)/dchelp.o - i_main_o=$(KOS_START) $(OBJDIR)/i_main.o $(OBJEXTRA) - - # name of the exefile - EXENAME?=SRB2.elf - BINNAME?=SRB2.BIN diff --git a/src/sdl12/SRB2DC/SELFBOOT.BIN b/src/sdl12/SRB2DC/SELFBOOT.BIN deleted file mode 100644 index a87ee3869..000000000 Binary files a/src/sdl12/SRB2DC/SELFBOOT.BIN and /dev/null differ diff --git a/src/sdl12/SRB2DC/VMU.xbm b/src/sdl12/SRB2DC/VMU.xbm deleted file mode 100644 index 0d56985f3..000000000 --- a/src/sdl12/SRB2DC/VMU.xbm +++ /dev/null @@ -1,19 +0,0 @@ -#define VMU_width 48 -#define VMU_height 32 -static unsigned char VMU_bits[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, - 0x00, 0x00, 0x58, 0x75, 0x00, 0x00, 0x00, 0x00, 0xee, 0xaa, 0x00, 0x00, - 0x00, 0x86, 0x55, 0x55, 0x01, 0x00, 0x00, 0xda, 0xc8, 0xaf, 0x00, 0x00, - 0x00, 0x62, 0x55, 0x54, 0x00, 0x00, 0x00, 0x32, 0xa2, 0x6c, 0x00, 0x00, - 0x00, 0x5c, 0x55, 0xfd, 0x01, 0x00, 0x00, 0xac, 0x88, 0xaa, 0x02, 0x00, - 0x00, 0x54, 0x75, 0x55, 0x05, 0x00, 0x00, 0xac, 0xbf, 0xaa, 0x0a, 0x00, - 0x00, 0xd6, 0x61, 0x55, 0x15, 0x00, 0x00, 0xe9, 0xc0, 0xaa, 0x2a, 0x00, - 0x00, 0x39, 0x40, 0x55, 0x55, 0x00, 0x00, 0x6d, 0xc0, 0xaa, 0xbe, 0x00, - 0x00, 0x6d, 0x40, 0xd5, 0xc3, 0x00, 0x00, 0x6d, 0xc0, 0xea, 0x00, 0x00, - 0x00, 0x29, 0x60, 0xf5, 0x00, 0x00, 0x00, 0x26, 0xe0, 0xfa, 0x00, 0x00, - 0x00, 0x58, 0xb8, 0xbd, 0x00, 0x00, 0x00, 0x84, 0x07, 0xdf, 0x00, 0x00, - 0x00, 0x08, 0x20, 0xae, 0x00, 0x00, 0x00, 0x30, 0xc0, 0x5f, 0x01, 0x00, - 0x00, 0xc0, 0x3f, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/src/sdl12/SRB2DC/dchelp.c b/src/sdl12/SRB2DC/dchelp.c deleted file mode 100644 index 1468baa8b..000000000 --- a/src/sdl12/SRB2DC/dchelp.c +++ /dev/null @@ -1,134 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2006-2018 by Sonic Team Jr. -// -// 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: -// stub and replacement "ANSI" C functions for use on Dreamcast/KOS -// -//----------------------------------------------------------------------------- -#include -#include -#ifndef HAVE_LWIP -#include -#endif -#include "../../doomdef.h" -#include "dchelp.h" - -int access(const char *path, int amode) -{ - file_t handle = FILEHND_INVALID; - - if (amode == F_OK || amode == R_OK) - handle=fs_open(path,O_RDONLY); - else if (amode == (R_OK|W_OK)) - handle=fs_open(path,O_RDWR); - else if (amode == W_OK) - handle=fs_open(path,O_WRONLY); - - if (handle != FILEHND_INVALID) - { - fs_close(handle); - return 0; - } - - return -1; -} - -double hypot(double x, double y) -{ - double ax, yx, yx2, yx1; - if (abs(y) > abs(x)) // |y|>|x| - { - ax = abs(y); // |y| => ax - yx = (x/y); - } - else // |x|>|y| - { - ax = abs(x); // |x| => ax - yx = (x/y); - } - yx2 = yx*yx; // (x/y)^2 - yx1 = sqrt(1+yx2); // (1 + (x/y)^2)^1/2 - return ax*yx1; // |x|*((1 + (x/y)^2)^1/2) -} - -#if !(defined (NONET) || defined (NOMD5)) -#ifdef HAVE_LWIP - -#include - -static uint8 ip[4]; -static char *h_addr_listtmp[2] = {ip, NULL}; -static struct hostent hostenttmp = {NULL, NULL, 0, 1, h_addr_listtmp}; - -struct hostent *gethostbyname(const char *name) -{ - struct sockaddr_in dnssrv; - dnssrv.sin_family = AF_INET; - dnssrv.sin_port = htons(53); - dnssrv.sin_addr.s_addr = htonl(0x0a030202); ///< what? - if (lwip_gethostbyname(&dnssrv, name, ip) < 0) - return NULL; - else - return &hostenttmp; -} -#else - -struct hostent *gethostbyname(const char *name) -{ - (void)name; - return NULL; -} - -int ioctl(int s, long cmd, void *argp) -{ - return fs_ioctl(s, argp, cmd); //FIONBIO? -} - -int select(int maxfdp1, void *readset, void *writeset, void *exceptset, - void *timeout) -{ - (void)maxfdp1; - (void)readset; - (void)writeset; - (void)exceptset; - (void)timeout; - errno = EAFNOSUPPORT; - return -1; -} - -int getsockopt (int s, int level, int optname, void *optval, socklen_t *optlen) -{ - (void)s; - (void)level; //SOL_SOCKET - (void)optname; //SO_RCVBUF, SO_ERROR - (void)optval; - (void)optlen; - errno = EAFNOSUPPORT; - return -1; -} - -int setsockopt (int s, int level, int optname, void *optval, socklen_t optlen) -{ - (void)s; - (void)level; //SOL_SOCKET - (void)optname; //SO_REUSEADDR, SO_BROADCAST, SO_RCVBUF - (void)optval; - (void)optlen; - errno = EAFNOSUPPORT; - return -1; -} - -#endif -#endif diff --git a/src/sdl12/SRB2DC/dchelp.h b/src/sdl12/SRB2DC/dchelp.h deleted file mode 100644 index 3647f9c89..000000000 --- a/src/sdl12/SRB2DC/dchelp.h +++ /dev/null @@ -1,51 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2006-2018 by Sonic Team Jr. -// -// 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: -// stub and replacement "ANSI" C functions for use on Dreamcast/KOS -// -//----------------------------------------------------------------------------- - -#ifndef __I_DREAMCAST__ -#define __I_DREAMCAST__ - -struct hostent -{ - char *h_name; /* Official name of host. */ - char **h_aliases; /* Alias list. */ - int h_addrtype; /* Host address type. */ - int h_length; /* Length of address. */ - char **h_addr_list; /* List of addresses from name server. */ -#define h_addr h_addr_list[0] /* Address, for backward compatibility. */ -}; - -struct hostent *gethostbyname(const char *name); - -#ifndef HAVE_LWIP -#define INADDR_NONE ((uint32) 0xffffffff) -#define INADDR_LOOPBACK ((uint32) 0x7f000001) -#define SOCK_STREAM 1 -#define FIONBIO 0 -#define SOL_SOCKET 0 -#define SO_ERROR 0 -#define SO_REUSEADDR 0 -#define SO_BROADCAST 0 -#define SO_RCVBUF 0 -int ioctl(int s, long cmd, void *argp); -int select(int maxfdp1, void *readset, void *writeset, void *exceptset, void *timeout); -int getsockopt(int s, int level, int optname, void *optval, socklen_t *optlen); -int setsockopt(int s, int level, int optname, void *optval, socklen_t optlen); -#endif -#endif diff --git a/src/sdl12/SRB2DC/i_udp.c b/src/sdl12/SRB2DC/i_udp.c deleted file mode 100644 index cf7654c10..000000000 --- a/src/sdl12/SRB2DC/i_udp.c +++ /dev/null @@ -1,455 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// Copyright (C) 1993-1996 by id Software, Inc. -// Portions Copyright (C) 2005-2018 by Sonic Team Jr. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief KOS UDP network interface - -#include "../../doomdef.h" - -#include "../../i_system.h" -#include "../../d_event.h" -#include "../../d_net.h" -#include "../../m_argv.h" - -#include "../../doomstat.h" - -#include "../../i_net.h" - -#include "../../z_zone.h" - -#include "../../i_tcp.h" - -#include -//#include -#define NET_NONE 0x00000000 -#define NET_LOCAL 0x0100007F -#define NET_ANY 0xFFFFFFFF - -#define MAXBANS 20 - -typedef struct -{ - uint32 host; - uint16 port; -} IPaddress; - -static IPaddress clientaddress[MAXNETNODES+1]; -static boolean nodeconnected[MAXNETNODES+1]; - -static int mysocket = 0; -static boolean init_KOSUDP_driver = false; - -static size_t numbans = 0; -static IPaddress banned[MAXBANS]; -static boolean KOSUDP_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? - -static inline int net_udp_sendto(int sock, const uint8 *data, int size, uint16 rem_port, uint32 rem_addr) -{ - uint8 dst_ip[4] = {((uint8*)(&(rem_addr)))[0], - ((uint8*)(&(rem_addr)))[1], - ((uint8*)(&(rem_addr)))[2], - ((uint8*)(&(rem_addr)))[3]}; - return net_udp_send_raw(net_default_dev, clientaddress[0].port, rem_port, dst_ip, data, size); - (void)sock; -} - -static inline int net_udp_recvfrom(int sock, uint8 *buf, int size, uint16 *rem_port, uint32 *rem_addr) -{ - return net_udp_recv(sock, buf, size); - (void)rem_port; - (void)rem_addr; -} - -static const char *KOSUDP_AddrToStr(IPaddress* sk) -{ - static char s[22]; // 255.255.255.255:65535 - sprintf(s,"%d.%d.%d.%d:%d", - ((uint8*)(&(sk->host)))[3], - ((uint8*)(&(sk->host)))[2], - ((uint8*)(&(sk->host)))[1], - ((uint8*)(&(sk->host)))[0], - net_ntohs(sk->port)); - return s; -} - -static const char *KOSUDP_GetNodeAddress(int node) -{ - if (!nodeconnected[node]) - return NULL; - return KOSUDP_AddrToStr(&clientaddress[node]); -} - -static const char *KOSUDP_GetBanAddress(size_t ban) -{ - if (ban > numbans) - return NULL; - return KOSUDP_AddrToStr(&banned[ban]); -} - -static boolean KOSUDP_cmpaddr(IPaddress* a, IPaddress* b) -{ - return (a->host == b->host && (b->port == 0 || a->port == b->port)); -} - -static SINT8 getfreenode(void) -{ - SINT8 j; - - for (j = 0; j < MAXNETNODES; j++) - if (!nodeconnected[j]) - { - nodeconnected[j] = true; - return j; - } - return -1; -} - -static void KOSUDP_Get(void) -{ - int size; - size_t i; - SINT8 j; - IPaddress temp = {clientaddress[BROADCASTADDR].host,clientaddress[BROADCASTADDR].port}; - - size = net_udp_recvfrom(mysocket,(char *)&doomcom->data, MAXPACKETLENGTH, &temp.port, &temp.host); - if (size == 0) - { - doomcom->remotenode = -1; // no packet - return; - } - - // find remote node number - for (i = 0; i < MAXNETNODES; i++) - if (KOSUDP_cmpaddr(&temp, &(clientaddress[i]))) - { - doomcom->remotenode = (INT16)i; // good packet from a game player - doomcom->datalength = (INT16)size; - return; - } - - // not found - - // find a free slot - j = getfreenode(); - if (j > 0) - { - M_Memcpy(&clientaddress[j], &temp, sizeof (temp)); - DEBFILE(va("New node detected: node:%d address:%s\n", j, - KOSUDP_GetNodeAddress(j))); - doomcom->remotenode = (INT16)j; // good packet from a game player - doomcom->datalength = (INT16)size; - // check if it's a banned dude so we can send a refusal later - for (i = 0; i < numbans; i++) - if (KOSUDP_cmpaddr(&temp, &banned[i])) - { - KOSUDP_bannednode[j] = true; - DEBFILE("This dude has been banned\n"); - break; - } - if (i == numbans) - KOSUDP_bannednode[j] = false; - return; - } - - DEBFILE("New node detected: No more free slots\n"); - doomcom->remotenode = -1; // no packet -} - -#if 0 -static boolean KOSUDP_CanSend(void) -{ - return true; -} -#endif - -static void KOSUDP_Send(void) -{ - const IPaddress *nodeinfo; - - if (!doomcom->remotenode || !nodeconnected[doomcom->remotenode]) - return; - - nodeinfo = clientaddress + doomcom->remotenode; - - if (net_udp_sendto(mysocket, (char *)&doomcom->data, doomcom->datalength, nodeinfo->port, nodeinfo->host) == -1) - { - CONS_Printf("KOSUDP: error sending data\n"); - } -} - -static void KOSUDP_FreeNodenum(int numnode) -{ - // can't disconnect from self :) - if (!numnode) - return; - - DEBFILE(va("Free node %d (%s)\n", numnode, KOSUDP_GetNodeAddress(numnode))); - - nodeconnected[numnode] = false; - - memset(&clientaddress[numnode], 0, sizeof (IPaddress)); -} - -static int KOSUDP_Socket(void) -{ - int temp = 0; - uint16 portnum = 0; - const uint32 hostip = net_default_dev?net_ntohl(net_ipv4_address(net_default_dev->ip_addr)):NET_LOCAL; - //Hurdler: I'd like to put a server and a client on the same computer - //Logan: Me too - //BP: in fact for client we can use any free port we want i have read - // in some doc that connect in udp can do it for us... - //Alam: where? - if (M_CheckParm("-clientport")) - { - if (!M_IsNextParm()) - I_Error("syntax: -clientport "); - portnum = net_ntohs(atoi(M_GetNextParm())); - } - else - portnum = net_ntohs(sock_port); - - temp = net_udp_sock_open(portnum, hostip, portnum, NET_NONE); - if (temp) - { - int btemp = net_udp_sock_open(portnum, hostip, portnum, NET_ANY); - clientaddress[0].port = portnum; - clientaddress[0].host = NET_NONE; - if (btemp) - { - clientaddress[BROADCASTADDR].port = net_ntohs(sock_port); - clientaddress[BROADCASTADDR].host = NET_ANY; - } - else - { - CONS_Printf("KOSUDP: can't setup broadcast sock\n"); - net_udp_sock_close(temp); - return 0; - } - } - else - { - CONS_Printf("KOSUDP: can't setup main sock\n"); - return 0; - } - - doomcom->extratics = 1; // internet is very high ping - - return temp; -} - -static void I_ShutdownKOSUDPDriver(void) -{ - //net_shutdown(); - init_KOSUDP_driver = false; -} - -static void I_InitKOSUDPDriver(void) -{ - if (init_KOSUDP_driver) - I_ShutdownKOSUDPDriver(); - else - net_init(); - D_SetDoomcom(); - memset(&clientaddress,0,sizeof (clientaddress)); - init_KOSUDP_driver = true; -} - -static void KOSUDP_CloseSocket(void) -{ - if (mysocket) - net_udp_sock_close(mysocket); - mysocket = 0; -} - -static SINT8 KOSUDP_NetMakeNodewPort(const char *hostname, const char* port) -{ - SINT8 newnode; - uint16 portnum = net_ntohs(sock_port); - - if (port && !port[0]) - portnum = net_ntohs((UINT16)atoi(port)); - - newnode = getfreenode(); - if (newnode == -1) - return -1; - // find ip of the server - clientaddress[newnode].port = portnum; - clientaddress[newnode].host = inet_addr(hostname); - - if (clientaddress[newnode].host == NET_NONE) - { - free(hostname); - return -1; - } - return newnode; -} - -static boolean KOSUDP_OpenSocket(void) -{ - size_t i; - - memset(clientaddress, 0, sizeof (clientaddress)); - - for (i = 0; i < MAXNETNODES; i++) - nodeconnected[i] = false; - - //CONS_Printf("KOSUDP Code starting up\n"); - - nodeconnected[0] = true; // always connected to self - nodeconnected[BROADCASTADDR] = true; - I_NetSend = KOSUDP_Send; - I_NetGet = KOSUDP_Get; - I_NetCloseSocket = KOSUDP_CloseSocket; - I_NetFreeNodenum = KOSUDP_FreeNodenum; - I_NetMakeNodewPort = KOSUDP_NetMakeNodewPort; - - //I_NetCanSend = KOSUDP_CanSend; - - // build the socket but close it first - KOSUDP_CloseSocket(); - mysocket = KOSUDP_Socket(); - - if (mysocket) - { -#if 0 - // for select - myset = SDLNet_AllocSocketSet(1); - if (!myset) - { - CONS_Printf("SDL_Net: %s",SDLNet_GetError()); - return false; - } - if (SDLNet_UDP_AddSocket(myset,mysocket) == -1) - { - CONS_Printf("SDL_Net: %s",SDLNet_GetError()); - return false; - } -#endif - return true; - } - return false; -} - -static boolean KOSUDP_Ban(int node) -{ - if (numbans == MAXBANS) - return false; - - M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (IPaddress)); - banned[numbans].port = 0' - numbans++; - return true; -} - -static void KOSUDP_ClearBans(void) -{ - numbans = 0; -} - -// -// I_InitNetwork -// Only required for DOS, so this is more a dummy -// -boolean I_InitNetwork(void) -{ - char serverhostname[255]; - boolean ret = false; - //if (!M_CheckParm ("-kosnet")) - // return false; - // initilize the driver - I_InitKOSUDPDriver(); - I_AddExitFunc(I_ShutdownKOSUDPDriver); - if (!init_KOSUDP_driver) - return false; - - if (M_CheckParm("-udpport")) - { - if (M_IsNextParm()) - sock_port = (UINT16)atoi(M_GetNextParm()); - else - sock_port = 0; - } - - // parse network game options, - if (M_CheckParm("-server") || dedicated) - { - server = true; - - // If a number of clients (i.e. nodes) is specified, the server will wait for the clients - // to connect before starting. - // If no number is specified here, the server starts with 1 client, and others can join - // in-game. - // Since Boris has implemented join in-game, there is no actual need for specifying a - // particular number here. - // FIXME: for dedicated server, numnodes needs to be set to 0 upon start -/* if (M_IsNextParm()) - doomcom->numnodes = (INT16)atoi(M_GetNextParm()); - else */if (dedicated) - doomcom->numnodes = 0; - else - doomcom->numnodes = 1; - - if (doomcom->numnodes < 0) - doomcom->numnodes = 0; - if (doomcom->numnodes > MAXNETNODES) - doomcom->numnodes = MAXNETNODES; - - // server - servernode = 0; - // FIXME: - // ??? and now ? - // server on a big modem ??? 4*isdn - net_bandwidth = 16000; - hardware_MAXPACKETLENGTH = INETPACKETLENGTH; - - ret = true; - } - else if (M_CheckParm("-connect")) - { - if (M_IsNextParm()) - strcpy(serverhostname, M_GetNextParm()); - else - serverhostname[0] = 0; // assuming server in the LAN, use broadcast to detect it - - // server address only in ip - if (serverhostname[0]) - { - COM_BufAddText("connect \""); - COM_BufAddText(serverhostname); - COM_BufAddText("\"\n"); - - // probably modem - hardware_MAXPACKETLENGTH = INETPACKETLENGTH; - } - else - { - // so we're on a LAN - COM_BufAddText("connect any\n"); - - net_bandwidth = 800000; - hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; - } - } - - I_NetOpenSocket = KOSUDP_OpenSocket; - I_Ban = KOSUDP_Ban; - I_ClearBans = KOSUDP_ClearBans; - I_GetNodeAddress = KOSUDP_GetNodeAddress; - I_GetBanAddress = KOSUDP_GetBanAddress; - bannednode = KOSUDP_bannednode; - - return ret; -} diff --git a/src/sdl12/SRB2DC/scramble.c b/src/sdl12/SRB2DC/scramble.c deleted file mode 100644 index a3483b00d..000000000 --- a/src/sdl12/SRB2DC/scramble.c +++ /dev/null @@ -1,259 +0,0 @@ -#include -#include - -#define MAXCHUNK (2048*1024) - -static unsigned int seed; - -void my_srand(unsigned int n) -{ - seed = n & 0xffff; -} - -unsigned int my_rand() -{ - seed = (seed * 2109 + 9273) & 0x7fff; - return (seed + 0xc000) & 0xffff; -} - -void load(FILE *fh, unsigned char *ptr, unsigned long sz) -{ - if (fread(ptr, 1, sz, fh) != sz) - { - fprintf(stderr, "Read error!\n"); - exit(1); - } -} - -void load_chunk(FILE *fh, unsigned char *ptr, unsigned long sz) -{ - static int idx[MAXCHUNK/32]; - int i; - - /* Convert chunk size to number of slices */ - sz /= 32; - - /* Initialize index table with unity, - so that each slice gets loaded exactly once */ - for (i = 0; i < sz; i++) - idx[i] = i; - - for (i = sz-1; i >= 0; --i) - { - /* Select a replacement index */ - int x = (my_rand() * i) >> 16; - - /* Swap */ - int tmp = idx[i]; - idx[i] = idx[x]; - idx[x] = tmp; - - /* Load resulting slice */ - load(fh, ptr+32*idx[i], 32); - } -} - -void load_file(FILE *fh, unsigned char *ptr, unsigned long filesz) -{ - unsigned long chunksz; - - my_srand(filesz); - - /* Descramble 2 meg blocks for as long as possible, then - gradually reduce the window down to 32 bytes (1 slice) */ - for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1) - while (filesz >= chunksz) - { - load_chunk(fh, ptr, chunksz); - filesz -= chunksz; - ptr += chunksz; - } - - /* Load final incomplete slice */ - if (filesz) - load(fh, ptr, filesz); -} - -void read_file(char *filename, unsigned char **ptr, unsigned long *sz) -{ - FILE *fh = fopen(filename, "rb"); - if (fh == NULL) - { - fprintf(stderr, "Can't open \"%s\".\n", filename); - exit(1); - } - if (fseek(fh, 0, SEEK_END)<0) - { - fprintf(stderr, "Seek error.\n"); - exit(1); - } - *sz = ftell(fh); - *ptr = malloc(*sz); - if ( *ptr == NULL ) - { - fprintf(stderr, "Out of memory.\n"); - exit(1); - } - if (fseek(fh, 0, SEEK_SET)<0) - { - fprintf(stderr, "Seek error.\n"); - exit(1); - } - load_file(fh, *ptr, *sz); - fclose(fh); -} - -void save(FILE *fh, unsigned char *ptr, unsigned long sz) -{ - if (fwrite(ptr, 1, sz, fh) != sz) - { - fprintf(stderr, "Write error!\n"); - exit(1); - } -} - -void save_chunk(FILE *fh, unsigned char *ptr, unsigned long sz) -{ - static int idx[MAXCHUNK/32]; - int i; - - /* Convert chunk size to number of slices */ - sz /= 32; - - /* Initialize index table with unity, - so that each slice gets saved exactly once */ - for (i = 0; i < sz; i++) - idx[i] = i; - - for (i = sz-1; i >= 0; --i) - { - /* Select a replacement index */ - int x = (my_rand() * i) >> 16; - - /* Swap */ - int tmp = idx[i]; - idx[i] = idx[x]; - idx[x] = tmp; - - /* Save resulting slice */ - save(fh, ptr+32*idx[i], 32); - } -} - -void save_file(FILE *fh, unsigned char *ptr, unsigned long filesz) -{ - unsigned long chunksz; - - my_srand(filesz); - - /* Descramble 2 meg blocks for as long as possible, then - gradually reduce the window down to 32 bytes (1 slice) */ - for (chunksz = MAXCHUNK; chunksz >= 32; chunksz >>= 1) - while (filesz >= chunksz) - { - save_chunk(fh, ptr, chunksz); - filesz -= chunksz; - ptr += chunksz; - } - - /* Save final incomplete slice */ - if (filesz) - save(fh, ptr, filesz); -} - -void write_file(char *filename, unsigned char *ptr, unsigned long sz) -{ - FILE *fh = fopen(filename, "wb"); - if (fh == NULL) - { - fprintf(stderr, "Can't open \"%s\".\n", filename); - exit(1); - } - save_file(fh, ptr, sz); - fclose(fh); -} - -void descramble(char *src, char *dst) -{ - unsigned char *ptr = NULL; - unsigned long sz = 0; - FILE *fh; - - read_file(src, &ptr, &sz); - - fh = fopen(dst, "wb"); - if (fh == NULL) - { - fprintf(stderr, "Can't open \"%s\".\n", dst); - exit(1); - } - if ( fwrite(ptr, 1, sz, fh) != sz ) - { - fprintf(stderr, "Write error.\n"); - exit(1); - } - fclose(fh); - free(ptr); -} - -void scramble(char *src, char *dst) -{ - unsigned char *ptr = NULL; - unsigned long sz = 0; - FILE *fh; - - fh = fopen(src, "rb"); - if (fh == NULL) - { - fprintf(stderr, "Can't open \"%s\".\n", src); - exit(1); - } - if (fseek(fh, 0, SEEK_END)<0) - { - fprintf(stderr, "Seek error.\n"); - exit(1); - } - sz = ftell(fh); - ptr = malloc(sz); - if ( ptr == NULL ) - { - fprintf(stderr, "Out of memory.\n"); - exit(1); - } - if (fseek(fh, 0, SEEK_SET)<0) - { - fprintf(stderr, "Seek error.\n"); - exit(1); - } - if ( fread(ptr, 1, sz, fh) != sz ) - { - fprintf(stderr, "Read error.\n"); - exit(1); - } - fclose(fh); - - write_file(dst, ptr, sz); - - free(ptr); -} - -int main(int argc, char *argv[]) -{ - int opt = 0; - - if (argc > 1 && !strcmp(argv[1], "-d")) - opt ++; - - if (argc != 3+opt) - { - fprintf(stderr, "Usage: %s [-d] from to\n", argv[0]); - exit(1); - } - - if (opt) - descramble(argv[2], argv[3]); - else - scramble(argv[1], argv[2]); - - return 0; -} diff --git a/src/sdl12/SRB2PS3/ICON0.png b/src/sdl12/SRB2PS3/ICON0.png deleted file mode 100644 index 140230c1e..000000000 Binary files a/src/sdl12/SRB2PS3/ICON0.png and /dev/null differ diff --git a/src/sdl12/SRB2PS3/Makefile.cfg b/src/sdl12/SRB2PS3/Makefile.cfg deleted file mode 100644 index 80f8db7bc..000000000 --- a/src/sdl12/SRB2PS3/Makefile.cfg +++ /dev/null @@ -1,139 +0,0 @@ -# -# Makefile.cfg for SRB2 for the PlayStation 3 using PSL1GHT -# - -# Check if PS3DEV and PSL1GHT is set in the environment. If so, continue with compilation. -.SUFFIXES: - -ifeq ($(strip $(PS3DEV)),) -$(error "Please set PS3DEV in your environment. export PS3DEV=ps3dev-toolchain") -endif - -ifeq ($(strip $(PSL1GHT)),) -$(error "Please set PSL1GHT in your environment. export PSL1GHT=PSL1GHT") -endif - -# Set compiler flags - -# Disable same warning flags -WFLAGS+=-Wno-shadow -Wno-char-subscripts -Wno-format - -ifdef JAILBREAK -EXENAME?=SRB2PS3-jb.elf -PKGNAME?=SRB2PS3-jb.pkg -else -EXENAME?=SRB2PS3.elf -PKGNAME?=SRB2PS3.pkg -endif -DGBNAME?=$(EXENAME).debug - -SRB2PS3DIR=sdl12/SRB2PS3 -ICON0?=$(SRB2PS3DIR)/ICON0.png -SFOXML?=sfo.xml -SRB2TTF?=sdl12/srb2.ttf - -TITLE=Sonic Robo Blast 2 v2.0.6 -APPID=SRB2-PS3 -CONTENTID=UP0001-$(APPID)_00-0000000000000000 - -FSELF=$(PS3DEV)/bin/fself.py -MAKE_SELF_NPDRM=$(PS3DEV)/ps3publictools/make_self_npdrm -FINALIZE=$(PS3DEV)/ps3publictools/package_finalize -SFO=$(PS3DEV)/bin/sfo.py -PKG=$(PS3DEV)/bin/pkg.py -PS3LOADEXE=$(PS3DEV)/ps3tools/ps3load -SED=sed -MV=mv -XARGS=xargs -FOR=for -SHXARGS:=$(XARGS) -SHSED:=$(SED) -SPRXLINKER=$(PS3DEV)/bin/sprxlinker - -ifdef JAILBREAK -PKGDIR=$(BIN)/pkg-jb -else -PKGDIR=$(BIN)/pkg -endif -USRDIR=$(PKGDIR)/USRDIR -ETCDIR=$(USRDIR)/etc -WGET=wget -P $(ETCDIR) -c -nc - -ifndef ECHO - FSELF:=@$(FSELF) - MAKE_SELF_NPDRM:=@$(MAKE_SELF_NPDRM) - FINALIZE:=@$(FINALIZE) - SFO:=@$(SFO) - PKG:=@$(PKG) - PS3LOADEXE:=@$(PS3LOADEXE) - SED:=@$(SED) - MV:=@$(MV) - SPRXLINKER:=@$(SPRXLINKER) - XARGS:=@$(XARGS) - FOR:=@(FOR) -endif - -# SRB2PS3 needs SDL_ttf to display any console text -SDL_TTF=1 - -# newlib has no support for networking -#NONET=1 - -# use absolute paths because changing PATH variable breaks distcc -PREFIX := $(PS3DEV)/ppu/bin/$(PREFIX) - -# PS3DEV toolchain libdir and includedir -PS3DEV_INC := $(PS3DEV)/ppu/include -PS3DEV_LIB := $(PS3DEV)/ppu/lib - -# PSL1GHT libdir and includedir -PSL1GHT_INC := $(PSL1GHT)/ppu/include -PSL1GHT_LIB := $(PSL1GHT)/ppu/lib - -PS3PORTS := $(PS3DEV)/portlibs -PS3PORTS_BIN := $(PS3PORTS)/ppu/bin -PS3PORTS_INC := $(PS3PORTS)/ppu/include - -PNG_CONFIG := $(PS3PORTS_BIN)/libpng-config -# static compilation -PNG_STATIC=1 - -SDL_CONFIG := $(PS3PORTS_BIN)/sdl-config - -INCLUDE := -I$(PSL1GHT_INC) -I$(PS3DEV_INC) -I$(PS3PORTS_INC) - -OPTS+=-D_PS3 -DUNIXCOMMON -CFLAGS+= -g $(INCLUDE) -L$(PSL1GHT_LIB) -L$(PS3DEV_LIB) -L$(PS3DEV)/lib -CXXFLAGS+=$(CFLAGS) -LDFLAGS+= -B$(PSL1GHT_LIB) -B$(PS3DEV_LIB) -B$(PS3DEV)/lib -LIBS+=-lrsx -ifndef NONET -LIBS+=-lnet -lsysmodule -endif - -$(BIN)/$(PKGNAME): $(OBJS) $(BIN)/$(EXENAME) - @echo Linking $(PKGNAME)... - -$(MKDIR) $(ETCDIR) - $(CP) $(ICON0) $(PKGDIR) - $(CP) $(SRB2TTF) $(ETCDIR) -ifdef WITHDATA - $(FOR) datafile in $(shell echo $(D_FILES) | $(SHSED) 's/\.srb/\.wad/' | $(SHXARGS) -n 1 basename); do \ - $(WGET) http://alam.srb2.org/SRB2/2.0.6-Final/Resources/$$datafile; \ - done -endif - $(SPRXLINKER) $(BIN)/$(EXENAME) -ifdef JAILBREAK - $(SED) 's/@@PS3_SYSTEM_VER@@/3.41/' $(SRB2PS3DIR)/$(SFOXML) > $(BIN)/$(SFOXML) - $(FSELF) -n $(BIN)/$(EXENAME) $(USRDIR)/EBOOT.BIN -else - $(SED) 's/@@PS3_SYSTEM_VER@@/3.55/' $(SRB2PS3DIR)/$(SFOXML) > $(BIN)/$(SFOXML) - $(MAKE_SELF_NPDRM) $(BIN)/$(EXENAME) $(USRDIR)/EBOOT.BIN $(CONTENTID) -endif - $(SFO) --title "$(TITLE)" --appid "$(APPID)" -f $(BIN)/$(SFOXML) $(PKGDIR)/PARAM.SFO - $(PKG) --contentid $(CONTENTID) $(PKGDIR)/ $(BIN)/$(PKGNAME) -ifndef JAILBREAK - $(FINALIZE) $(BIN)/$(PKGNAME) -endif - -run: $(BIN)/$(EXENAME) - $(PS3LOADEXE) $(USRDIR)/EBOOT.BIN diff --git a/src/sdl12/SRB2PS3/sfo.xml b/src/sdl12/SRB2PS3/sfo.xml deleted file mode 100644 index d7719b540..000000000 --- a/src/sdl12/SRB2PS3/sfo.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - 02.06 - - - 0 - - - 1 - - - HG - - - This application was created with the official non-official SDK called PSL1GHT, for more information visit http://www.psl1ght.com/ . This is in no way associated with Sony Computer Entertainment Inc., please do not contact them for help, they will not be able to provide it. - - - 0 - - - 0@@PS3_SYSTEM_VER@@00 - - - 63 - - - 279 - - - Sonic Robo Blast 2 - - - SRB200000 - - - 02.06 - - diff --git a/src/sdl12/SRB2PSP/ICON0.png b/src/sdl12/SRB2PSP/ICON0.png deleted file mode 100644 index 140230c1e..000000000 Binary files a/src/sdl12/SRB2PSP/ICON0.png and /dev/null differ diff --git a/src/sdl12/SRB2PSP/Makefile.cfg b/src/sdl12/SRB2PSP/Makefile.cfg deleted file mode 100644 index 5e4c0ba2f..000000000 --- a/src/sdl12/SRB2PSP/Makefile.cfg +++ /dev/null @@ -1,126 +0,0 @@ -# -# Makefile.cfg for SRB2/PSP -# - -# -#hmmm, the PSP -# - - PSPSDK=$(shell psp-config -p) - PSPDEV=$(shell psp-config -d) - PSPPREFIX=$(shell psp-config -P) - STRIP=psp-strip - MKSFO?=mksfoex -d MEMSIZE=1 - #MKSFO=mksfo - PACK_PBP=pack-pbp - FIXUP=psp-fixup-imports - HOSTCC:=$(CC) - CC=$(PSPDEV)/bin/psp-gcc - OBJCOPY=psp-objcopy - OBJDUMP=psp-objdump -ifdef FIXEDPRX - PRXGEN=psp-prxgen -else - PRXGEN=$(OBJCOPY) -endif -ifndef PRXSIGN - SIGNER:=$(PSPDEV)/bin/$(OBJCOPY) -endif - -ifndef ECHO - MKSFO:=@$(MKSFO) - PACK_PBP:=@$(PACK_PBP) - FIXUP:=@$(FIXUP) - PRXGEN:=@$(PRXGEN) -endif - - PSP_EBOOT_TITLE=SRB2-PSP vME - PSP_EBOOT_SFO=$(BIN)/PARAM.SFO - PSP_EBOOT_ICON=sdl12/SRB2PSP/ICON0.png - PSP_EBOOT_ICON1=NULL - PSP_EBOOT_UNKPNG=NULL - PSP_EBOOT_PIC1=sdl12/SRB2PSP/PIC1.png - PSP_EBOOT_SND0=NULL - PSP_EBOOT_PSAR=NULL - - SIGNER?=sdl12/SRB2PSP/psp-prxsign/psp-prxsign - - SDL=1 - PREFIX=psp - NONX86=1 - #NOHW=1 - NOHS=1 - NOMD5=1 - NONET=1 #No TCPIP code - NOPNG=1 #No Screenshot - - OPTS=-I$(PSPPREFIX)/include -I$(PSPSDK)/include - OPTS+=-DUNIXCOMMON -DFORCESDLMAIN -G0 - WFLAGS+=-Wno-undef - WFLAGS+=-O1 - LIBS=-lm - SDL_CONFIG?=$(PSPPREFIX)/bin/sdl-config - #SDL_CFLAGS?=-I$(PSPDEV)/psp/include/SDL - #SDL_LDFLAGS?=-lSDLmain -lSDL -lglut -lGLU -lGL -lpspgu -lpspaudiolib -lpspaudio -lpsphprm -lpspvfpu -lpsprtc -ifndef NOMIXER - LIBS:=-liberty -lvorbisfile -lvorbis -logg -lSDL $(LIBS) -endif -ifndef NOHW - OPTS+=-DSTATIC_OPENGL -DMINI_GL_COMPATIBILITY - LIBS+=-lGLU -lGL -lm -endif - #PSPSDK_LIBS=-L$(PSPSDK)/lib -lpspdebug -lpspdisplay -lpspge -lpspctrl -lpspsdk - #LIBS+=$(PSPSDK_LIBS) -lc -lpspnet -lpspnet_inet -lpspnet_apctl -lpspnet_resolver -lpsputility -lpspuser -lpspkernel -ifdef FIXEDPRX - LDFLAGS := -specs=$(PSPSDK)/lib/prxspecs -Wl,-q,-T$(PSPSDK)/lib/linkfile.prx $(LDFLAGS) - LIBS+=$(PSPSDK)/lib/prxexports.o -endif - -ifeq ($(PSP_FW_VERSION),) -PSP_FW_VERSION=150 -endif - - CPPFLAGS:=-D_PSP_FW_VERSION=$(PSP_FW_VERSION) $(CPPFLAGS) - - - # name of the exefile - EXENAME?=SRB2PSP.elf - PRXNAME?=SRB2PSP.prx - DBGNAME?=SRB2PSP.debug - -post-build: $(BIN)/EBOOT.PBP - -kxploit: $(BIN)/$(EXENAME) $(PSP_EBOOT_SFO) - -$(MKDIR) "$(BIN)/kxploit/srb2" - @echo emitting kxploit/srb2/ - $(STRIP) $(BIN)/$(EXENAME) -o $(BIN)/kxploit/srb2/EBOOT.PBP - @echo emitting kxploit/srb2% - -$(MKDIR) "$(BIN)/kxploit/srb2%/" - $(PACK_PBP) "$(BIN)/kxploit/srb2%/EBOOT.PBP" $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ - $(PSP_EBOOT_ICON1) $(PSP_EBOOT_UNKPNG) $(PSP_EBOOT_PIC1) \ - $(PSP_EBOOT_SND0) NULL $(PSP_EBOOT_PSAR) - -sdl12/SRB2PSP/psp-prxsign/psp-prxsign: - -$(MAKE) -C sdl12/SRB2PSP/psp-prxsign CFLAGS=-pipe CC="$(HOSTCC)" - -fix-up: $(BIN)/$(EXENAME) - @echo Running psp-fixup-imports on $(EXENAME) - $(FIXUP) $(BIN)/$(EXENAME) - -$(BIN)/$(PRXNAME): $(BIN)/$(EXENAME) fix-up - @echo Building $(PRXNAME) out of $(EXENAME) - $(PRXGEN) $(BIN)/$(EXENAME) $@ - -$(BIN)/EBOOT.PBP: $(BIN)/$(PRXNAME) $(SIGNER) $(PSP_EBOOT_SFO) - @echo Signing and running pack-pbp to make PBP - $(SIGNER) $(BIN)/$(PRXNAME) $(BIN)/$(PRXNAME).sign - $(PACK_PBP) $@ $(PSP_EBOOT_SFO) $(PSP_EBOOT_ICON) \ - $(PSP_EBOOT_ICON1) $(PSP_EBOOT_UNKPNG) $(PSP_EBOOT_PIC1) \ - $(PSP_EBOOT_SND0) $(BIN)/$(PRXNAME).sign $(PSP_EBOOT_PSAR) - $(REMOVE) $(BIN)/$(PRXNAME).sign - -$(PSP_EBOOT_SFO): - -$(MKDIR) $(BIN) - $(MKSFO) '$(PSP_EBOOT_TITLE)' $@ - -#include $(PSPSDK)/lib/build.mak diff --git a/src/sdl12/SRB2PSP/PIC1.png b/src/sdl12/SRB2PSP/PIC1.png deleted file mode 100644 index 0722a96bc..000000000 Binary files a/src/sdl12/SRB2PSP/PIC1.png and /dev/null differ diff --git a/src/sdl12/SRB2PSP/psp-prxsign/.gitignore b/src/sdl12/SRB2PSP/psp-prxsign/.gitignore deleted file mode 100644 index 6a07f1a5a..000000000 --- a/src/sdl12/SRB2PSP/psp-prxsign/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/psp-prxsign -/psp-prxsign.exe diff --git a/src/sdl12/SRB2PSP/psp-prxsign/Makefile b/src/sdl12/SRB2PSP/psp-prxsign/Makefile deleted file mode 100644 index 4a9b7da0f..000000000 --- a/src/sdl12/SRB2PSP/psp-prxsign/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -EXE=psp-prxsign -SRC=main.c cmac.c -OBJ=$(SRC:.c=.o)# replaces the .c from SRC with .o - -OPENSSL_PKGCONFIG?=openssl -OPENSSL_CFLAGS?=$(shell pkg-config $(OPENSSL_PKGCONFIG) --cflags) -OPENSSL_LDFLAGS?=$(shell pkg-config $(OPENSSL_PKGCONFIG) --libs) - -CFLAGS+=$(OPENSSL_CFLAGS) -LDFLAGS+=$(OPENSSL_LDFLAGS) - -.PHONY : all # .PHONY ignores files named all - -all: $(EXE) # all is dependent on $(BIN) to be complete - - -$(EXE): $(OBJ) # $(EXE) is dependent on all of the files in $(OBJ) to exist - $(CC) $^ $(LDFLAGS) -o $@ - -.PHONY : clean # .PHONY ignores files named clean -clean: - -$(RM) $(OBJ) $(EXE) diff --git a/src/sdl12/SRB2PSP/psp-prxsign/cmac.c b/src/sdl12/SRB2PSP/psp-prxsign/cmac.c deleted file mode 100644 index f527f7a71..000000000 --- a/src/sdl12/SRB2PSP/psp-prxsign/cmac.c +++ /dev/null @@ -1,130 +0,0 @@ -#include "cmac.h" - -#define AES_128 0 -unsigned char const_Rb[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 -}; -unsigned char const_Zero[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -void xor_128(unsigned char *a, unsigned char *b, unsigned char *out) -{ - int i; - for (i=0;i<16; i++) - { - out[i] = a[i] ^ b[i]; - } -} - -/* AES-CMAC Generation Function */ - -static inline void leftshift_onebit(unsigned char *input,unsigned char *output) -{ - int i; - unsigned char overflow = 0; - - for ( i=15; i>=0; i-- ) - { - output[i] = input[i] << 1; - output[i] |= overflow; - overflow = (input[i] & 0x80)?1:0; - } -} - -void generate_subkey(unsigned char *key, unsigned char *K1, unsigned char *K2) -{ - unsigned char L[16]; - unsigned char Z[16]; - unsigned char tmp[16]; - int i; - - for ( i=0; i<16; i++ ) Z[i] = 0; - - AES_KEY aes; - AES_set_encrypt_key(key, 128, &aes); - - AES_encrypt(Z, L, &aes); - - if ( (L[0] & 0x80) == 0 ) /* If MSB(L) = 0, then K1 = L << 1 */ - { - leftshift_onebit(L,K1); - } else { /* Else K1 = ( L << 1 ) (+) Rb */ - leftshift_onebit(L,tmp); - xor_128(tmp,const_Rb,K1); - } - - if ( (K1[0] & 0x80) == 0 ) - { - leftshift_onebit(K1,K2); - } else { - leftshift_onebit(K1,tmp); - xor_128(tmp,const_Rb,K2); - } -} - -static inline void padding ( unsigned char *lastb, unsigned char *pad, int length ) -{ - int j; - - /* original last block */ - for ( j=0; j<16; j++ ) - { - if ( j < length ) - { - pad[j] = lastb[j]; - } else if ( j == length ) { - pad[j] = 0x80; - } else { - pad[j] = 0x00; - } - } -} - -void AES_CMAC ( unsigned char *key, unsigned char *input, int length, unsigned char *mac ) -{ - unsigned char X[16],Y[16], M_last[16], padded[16]; - unsigned char K1[16], K2[16]; - int n, i, flag; - generate_subkey(key,K1,K2); - - n = (length+15) / 16; /* n is number of rounds */ - - if ( n == 0 ) - { - n = 1; - flag = 0; - } else { - if ( (length%16) == 0 ) { /* last block is a complete block */ - flag = 1; - } else { /* last block is not complete block */ - flag = 0; - } - - } - - if ( flag ) { /* last block is complete block */ - xor_128(&input[16*(n-1)],K1,M_last); - } else { - padding(&input[16*(n-1)],padded,length%16); - xor_128(padded,K2,M_last); - } - AES_KEY aes; - AES_set_encrypt_key(key, 128, &aes); - - for ( i=0; i<16; i++ ) X[i] = 0; - for ( i=0; i -#include - -void xor_128(unsigned char *a, unsigned char *b, unsigned char *out); -void generate_subkey(unsigned char *key, unsigned char *K1, unsigned char *K2); -void AES_CMAC(unsigned char *key, unsigned char *input, int length, unsigned char *mac); - -#endif diff --git a/src/sdl12/SRB2PSP/psp-prxsign/kirk_header.h b/src/sdl12/SRB2PSP/psp-prxsign/kirk_header.h deleted file mode 100644 index 76c921ef0..000000000 --- a/src/sdl12/SRB2PSP/psp-prxsign/kirk_header.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __kirk_header__ -#define __kirk_header__ - -static unsigned int size_kirk_header = 272; -static unsigned char kirk_header[] __attribute__((aligned(16))) = { - 0x2a, 0x4f, 0x3c, 0x49, 0x8a, 0x73, 0x4e, 0xd1, 0xf4, 0x55, 0x93, 0x0b, 0x9b, 0x69, 0xdc, 0x65, - 0x73, 0x22, 0x69, 0xd3, 0x73, 0x96, 0x7a, 0x60, 0x66, 0x8c, 0x88, 0xcf, 0x2f, 0x83, 0x58, 0xbc, - 0xb2, 0x00, 0x0a, 0x11, 0x72, 0x43, 0xc5, 0xde, 0xef, 0xbb, 0x2c, 0xbf, 0x97, 0x79, 0x6b, 0x9c, - 0x10, 0x1e, 0x7c, 0x57, 0x0e, 0xdb, 0x1d, 0x61, 0x6e, 0xb5, 0xf9, 0x3d, 0x35, 0xe9, 0x5c, 0xd8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x33, 0x55, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x7e, 0x50, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x22, 0x74, 0x69, 0x66, 0x70, 0x73, - 0x70, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x33, 0x55, 0x00, 0x50, 0x34, 0x55, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x67, 0x3d, 0x00, 0x50, 0x55, 0x0a, 0x01, 0x10, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x6b, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4c, 0x6b, 0x3d, 0x00, 0xcc, 0xbb, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, -}; - -#endif diff --git a/src/sdl12/SRB2PSP/psp-prxsign/main.c b/src/sdl12/SRB2PSP/psp-prxsign/main.c deleted file mode 100644 index a970ae6c1..000000000 --- a/src/sdl12/SRB2PSP/psp-prxsign/main.c +++ /dev/null @@ -1,190 +0,0 @@ -#include -#include -#include -#include -#include -#include "cmac.h" -#include "kirk_header.h" -#include "psp_header.h" - -typedef unsigned char byte; - -typedef struct { - byte key[16]; - byte ckey[16]; - byte head_hash[16]; - byte data_hash[16]; - byte unused[32]; - int unk1; // 1 - int unk2; // 0 - int unk3[2]; - int datasize; - int dataoffset; - int unk4[6]; -} kirk1head_t; - -// secret kirk command 1 key -byte kirk_key[] = { - 0x98, 0xc9, 0x40, 0x97, 0x5c, 0x1d, 0x10, 0xe8, 0x7f, 0xe6, 0x0e, 0xa3, 0xfd, 0x03, 0xa8, 0xba -}; - -int main(int argc, char **argv) -{ - int i, relrem, size, fullsize, blocks, datasize; - size_t j; - kirk1head_t kirk; - byte iv[16]; - byte cmac[32]; - byte subk[32]; - byte psph[0x150]; - byte *datablob; - byte *filebuff; - FILE *f; - AES_KEY aesKey; - Elf32_Ehdr *ehdr; - Elf32_Shdr *shdr; - Elf32_Rel *relo; - - if(argc < 3) { - printf("Usage: %s unsigned.prx signed.prx\n", argv[0]); - return 1; - } - - // clean kirk header, use modified PRXdecrypter to get it - /*f = fopen(argv[1], "rb"); - if(!f) { - printf("failed to open %s\n", argv[1]); - return 1; - } - fread(&kirk, 1, sizeof(kirk1head_t), f); - fclose(f);*/ - //memcpy(&kirk, kirk_header, size_kirk_header); - memcpy(&kirk, kirk_header, sizeof(kirk1head_t)); - - datasize = kirk.datasize; - if(datasize % 16) datasize += 16 - (datasize % 16); - - // original ~PSP header - /*f = fopen(argv[2], "rb"); - if(!f) { - free(datablob); - printf("failed to open %s\n", argv[2]); - return 1; - } - fread(psph, 1, 0x150, f); - fclose(f);*/ - memcpy(&psph, psp_header, size_psp_header); - - // file to encrypt - f = fopen(argv[1], "rb"); - if(!f) { - printf("psp-prxsign: Unable to open PRX\n"); - return 1; - } - fseek(f, 0, SEEK_END); - size = ftell(f); - if(size > datasize - 16) { - fclose(f); - printf("psp-prxsign: PRX is too large\n"); - return 1; - } - printf("%s : %i\n", argv[1], size); - fseek(f, 0, SEEK_SET); - - fullsize = datasize + 0x30 + kirk.dataoffset; - - // datablob holds everything needed to calculate data HASH - datablob = malloc(fullsize); - if(!datablob) { - fclose(f); - printf("psp-prxsign: Failed to allocate memory for blob\n"); - return 1; - } - memset(datablob, 0, fullsize); - memcpy(datablob, &kirk.unk1, 0x30); - memcpy(datablob + 0x30, psph, kirk.dataoffset); - filebuff = datablob + 0x30 + kirk.dataoffset; - - int whocares = fread(filebuff, 1, size, f); - (void)whocares; - fclose(f); - - // remove relocations type 7 - relrem = 0; - ehdr = (void *)filebuff; - if(!memcmp(ehdr->e_ident, ELFMAG, 4) && ehdr->e_shnum) { - shdr = (void *)(filebuff + ehdr->e_shoff); - for(i = 0; i < ehdr->e_shnum; i++) { - if(shdr[i].sh_type == 0x700000A0) { - relo = (void *)(filebuff + shdr[i].sh_offset); - for(j = 0; j < shdr[i].sh_size / sizeof(Elf32_Rel); j++) { - if((relo[j].r_info & 0xFF) == 7) { - relo[j].r_info = 0; - relrem++; - } - } - } - } - } - //printf("%i relocations type 7 removed\ncalculating ...\n", relrem); - - // get AES/CMAC key - AES_set_decrypt_key(kirk_key, 128, &aesKey); - memset(iv, 0, 16); - AES_cbc_encrypt(kirk.key, kirk.key, 32, &aesKey, iv, AES_DECRYPT); - - // check header hash, optional - // if you take correct kirk header, hash is always correct -/* AES_CMAC(kirk.ckey, datablob, 0x30, cmac); - if(memcmp(cmac, kirk.head_hash, 16)) { - free(datablob); - printf("header hash invalid\n"); - return 1; - } -*/ - - // encrypt input file - AES_set_encrypt_key(kirk.key, 128, &aesKey); - memset(iv, 0, 16); - AES_cbc_encrypt(filebuff, filebuff, datasize, &aesKey, iv, AES_ENCRYPT); - - // make CMAC correct - generate_subkey(kirk.ckey, subk, subk + 16); - AES_set_encrypt_key(kirk.ckey, 128, &aesKey); - blocks = fullsize / 16; - memset(cmac, 0, 16); - for(i = 0; i < blocks - 1; i++) { - xor_128(cmac, &datablob[16 * i], cmac + 16); - AES_encrypt(cmac + 16, cmac, &aesKey); - } - - AES_set_decrypt_key(kirk.ckey, 128, &aesKey); - AES_decrypt(kirk.data_hash, iv, &aesKey); - xor_128(cmac, iv, iv); - xor_128(iv, subk, &datablob[16 * (blocks-1)]); - // check it, optional - // it works, this is only if you want to change something -/* AES_CMAC(kirk.ckey, datablob, fullsize, cmac); - if(memcmp(cmac, kirk.data_hash, 16)) { - fclose(f); - free(datablob); - printf("data hash calculation error\n"); - return 1; - } -*/ - f = fopen(argv[2], "wb"); - if(!f) { - free(datablob); - printf("psp-prxsign: Failed to write signed PRX\n"); - return 1; - } - //printf("saving ...\n"); - // save ~PSP header - fwrite(psph, 1, 0x150, f); - // save encrypted file - fwrite(filebuff, 1, fullsize - 0x30 - kirk.dataoffset, f); - fclose(f); - free(datablob); - //printf("everything done\n"); - return 0; -} diff --git a/src/sdl12/SRB2PSP/psp-prxsign/psp_header.h b/src/sdl12/SRB2PSP/psp-prxsign/psp_header.h deleted file mode 100644 index 7faef832c..000000000 --- a/src/sdl12/SRB2PSP/psp-prxsign/psp_header.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef __psp_header__ -#define __psp_header__ - -static unsigned int size_psp_header = 336; -static unsigned char psp_header[] __attribute__((aligned(16))) = { - 0x7e, 0x50, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x22, 0x74, 0x69, 0x66, 0x70, 0x73, - 0x70, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x33, 0x55, 0x00, 0x50, 0x34, 0x55, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x40, 0x67, 0x3d, 0x00, 0x50, 0x55, 0x0a, 0x01, 0x10, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x6b, 0x3d, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x4c, 0x6b, 0x3d, 0x00, 0xcc, 0xbb, 0x11, 0x01, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00, - 0x90, 0x82, 0x4c, 0x48, 0xa3, 0x53, 0xb2, 0x1b, 0x13, 0x95, 0x2f, 0xf1, 0x0b, 0x90, 0x9c, 0x11, - 0x61, 0x40, 0x20, 0x67, 0xf8, 0xdb, 0xfc, 0x95, 0x5c, 0xbe, 0x8c, 0x80, 0xf3, 0x92, 0x03, 0x01, - 0xb0, 0xbe, 0xf5, 0xf8, 0xa1, 0xaf, 0xaf, 0xa8, 0x38, 0x26, 0x63, 0x09, 0x26, 0x0e, 0xb7, 0xd5, - 0x00, 0x33, 0x55, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5c, 0x3e, 0x03, 0x22, 0xe5, 0x7d, 0xb9, 0xd1, 0x13, 0x67, 0x97, 0xa3, 0x5b, 0xd8, 0x77, 0x1f, - 0xf0, 0x05, 0xf3, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x4a, 0xd7, 0x37, - 0xc2, 0x8f, 0x15, 0x43, 0x33, 0x93, 0x4d, 0x5b, 0xc0, 0x6e, 0xe4, 0x00, 0xc6, 0x0a, 0x71, 0x11, - 0x98, 0xb6, 0xc3, 0xb7, 0x59, 0x66, 0x21, 0xa8, 0x65, 0xf6, 0x53, 0xa9, 0x7a, 0x48, 0x17, 0xb6, -}; - -#endif diff --git a/src/sdl12/SRB2Pandora/Makefile.cfg b/src/sdl12/SRB2Pandora/Makefile.cfg deleted file mode 100644 index 1f057a212..000000000 --- a/src/sdl12/SRB2Pandora/Makefile.cfg +++ /dev/null @@ -1,39 +0,0 @@ -# Quick Pandora target to make a compliant SRB2 PND file. - -PNDNAME=SRB2.pnd -PNDDIR=$(BIN)/pnd -ICON=sdl12/SRB2Pandora/icon.png -PXML=sdl12/SRB2Pandora/PXML.xml - -SED=sed -CAT=cat -CP=cp -XARGS=xargs -FOR=for -WGET=wget -P $(PNDDIR) -c -nc - -SHXARGS:=$(XARGS) -SHSED:=$(SED) - -ifndef ECHO - CP:=@$(CP) - CAT:=@$(CAT) - SED:=@$(SED) - XARGS:=@$(XARGS) - FOR:=@(FOR) -endif - -$(BIN)/$(PNDNAME): $(BIN)/$(EXENAME) - @echo Linking $(PNDNAME)... - $(MKDIR) $(PNDDIR) - $(CP) $(BIN)/$(EXENAME) $(PNDDIR) - $(CP) $(ICON) $(PNDDIR) - $(CP) $(PXML) $(PNDDIR) -ifdef WITHDATA - $(FOR) datafile in $(shell echo $(D_FILES) | $(SHSED) 's/\.srb/\.wad/' | $(SHXARGS) -n 1 basename); do \ - $(WGET) http://alam.srb2.org/SRB2/2.0.6-Final/Resources/$$datafile; \ - done -endif - $(MKISOFS) -l -r -o $@ $(PNDDIR) - $(CAT) $(PXML) >> $@ - $(REMOVE) -r $(PNDDIR) diff --git a/src/sdl12/SRB2Pandora/PXML.xml b/src/sdl12/SRB2Pandora/PXML.xml deleted file mode 100644 index 33a9587db..000000000 --- a/src/sdl12/SRB2Pandora/PXML.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - Sonic Robo Blast 2 - ソニック・ロボ・ブラスト・2 - A 3D Sonic fangame with a huge fanbase developing custom content, including characters, levels, and even large-scale modifications - - - - - - - - - - - diff --git a/src/sdl12/SRB2Pandora/icon.png b/src/sdl12/SRB2Pandora/icon.png deleted file mode 100644 index 63af73ac3..000000000 Binary files a/src/sdl12/SRB2Pandora/icon.png and /dev/null differ diff --git a/src/sdl12/SRB2WII/Makefile.cfg b/src/sdl12/SRB2WII/Makefile.cfg deleted file mode 100644 index 778d2c3d6..000000000 --- a/src/sdl12/SRB2WII/Makefile.cfg +++ /dev/null @@ -1,124 +0,0 @@ -# -# Makefile.cfg for SRB2Wii native using libogc -# - -# Check if DEVKITPPC is set in the environment. If so, continue with compilation. -.SUFFIXES: - -ifeq ($(strip $(DEVKITPPC)),) -$(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") -endif - -# Set compiler flags - -SRB2NAME?=srb2wii -EXENAME?=$(SRB2NAME).elf -DBGNAME?=$(SRB2NAME).elf.debug -DOLNAME?=$(SRB2NAME).dol - -ICONPNG?=sdl12/SRB2WII/icon.png -METAXML?=sdl12/SRB2WII/meta.xml - -APPDIR=apps/$(SRB2NAME) -ZIPNAME=$(SRB2NAME).zip - -ELF2DOL=$(DEVKITPPC)/bin/elf2dol -WIILOADEXE=$(DEVKITPPC)/bin/wiiload -ZIP=zip -r -9 -WGET=wget -P srb2wii -c -nc -SED=sed -XARGS=xargs -SHXARGS:=$(XARGS) -SHSED:=$(SED) -FOR=for - -ifndef ECHO - ELF2DOL:=@$(ELF2DOL) - WIILOADEXE:=@$(WIILOADEXE) - ZIP:=@$(ZIP) - SED:=@$(SED) - XARGS:=@$(XARGS) - FOR:=@$(FOR) -endif - -# Disable same warning flags -WFLAGS+=-Wno-shadow -Wno-char-subscripts -Wno-old-style-definition -Wno-unsuffixed-float-constants - -# newlib has no support for networking -NONET=1 - -# use pkgconfig for PKG -PNG_PKGCONFIG=libpng - -# use absolute paths because changing PATH variable breaks distcc -PREFIX := $(DEVKITPPC)/bin/$(PREFIX) - -# FIXME: DevkitPPC and ready-compiled SDL Wii require these things to be in a silly order -# libogc/DevkitPro required stuff -LIBOGC := $(DEVKITPRO)/libogc -LIBOGC_INC := $(LIBOGC)/include -LIBOGC_LIB := $(LIBOGC)/lib - -PORTLIBS := $(DEVKITPRO)/portlibs/ppc -PORTLIBS_INC := $(PORTLIBS)/include -PORTLIBS_LIB := $(PORTLIBS)/lib - -SDL_CPPFLAGS := -I$(LIBOGC_INC)/SDL -SDL_LIB := $(DEVKITPRO)/libogc/lib/wii -INCLUDE := -I$(LIBOGC_INC) $(SDL_CPPFLAGS) -I$(PORTLIBS_INC) - -PKG_CONFIG_PATH := $(PORTLIBS)/lib/pkgconfig -PKG_BROKEN_SWTICH := --static --define-variable=DEVKITPRO=$(DEVKITPRO) -PNG_PKGCONFIG := $(PKG_CONFIG_PATH)/libpng.pc $(PKG_BROKEN_SWTICH) -ZLIB_PKGCONFIG := $(PKG_CONFIG_PATH)/zlib.pc $(PKG_BROKEN_SWTICH) - -ZLIB_CFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --cflags) -ZLIB_LDFLAGS?=$(shell $(PKG_CONFIG) $(ZLIB_PKGCONFIG) --libs) - -ifdef RDB - LIBS+=-ldb - OPTS+=-DREMOTE_DEBUGGING=$(RDB) -endif - -LIBS+= -L$(SDL_LIB) -ifndef NOMIXER - LD=$(CXX) - LIBS+=-lSDL_mixer -lvorbisidec -lsmpeg -endif -LIBS+=-lSDL - -LIBS+=$(ZLIB_LDFLAGS) -lfat -lwiiuse -lbte -logc -lm -lwiikeyboard -L$(LIBOGC_LIB) - -MACHDEP = -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float -OPTS+=-DWII -D_WII -DUNIXCOMMON -CFLAGS+=-D__BIG_ENDIAN__ -g -O3 -fsigned-char $(MACHDEP) $(INCLUDE) -CXXFLAGS+=$(CFLAGS) -LDFLAGS+=-g $(MACHDEP) -Wl,-Map,$(notdir $@).map - -SDL_CONFIG=/bin/true -SDL_CFLAGS= -SDL_LDFLAGS= - -$(BIN)/$(DOLNAME): $(BIN)/$(EXENAME) - @echo Linking $(DOLNAME)... - $(ELF2DOL) $(BIN)/$(EXENAME) $(BIN)/$(DOLNAME) - @echo Creating /apps/$(SRB2NAME)... - $(MKDIR) $(APPDIR) - $(CP) $(BIN)/$(DOLNAME) $(APPDIR)/boot.dol - $(CP) $(ICONPNG) $(APPDIR) - $(CP) $(METAXML) $(APPDIR) -ifdef WITHDATA - $(MKDIR) srb2wii - $(FOR) datafile in $(shell echo $(D_FILES) | $(SHSED) -e 's/\.srb/\.wad/' -e 's/music.dta//' | $(SHXARGS) -n 1 basename); do \ - $(WGET) http://alam.srb2.org/SRB2/2.0.6-Final/Resources/$$datafile; \ - done - # downsampled music.dta specially for SRB2Wii - $(WGET) http://repos.srb2.org/srb2ports/music.dta - $(ZIP) $(BIN)/$(ZIPNAME) $(APPDIR) srb2wii -else - $(ZIP) $(BIN)/$(ZIPNAME) $(APPDIR) -endif - $(REMOVE) -r $(APPDIR) - -run: $(BIN)/$(EXENAME) - $(WIILOADEXE) $(BIN)/$(DBGNAME) diff --git a/src/sdl12/SRB2WII/icon.png b/src/sdl12/SRB2WII/icon.png deleted file mode 100644 index d22324bc6..000000000 Binary files a/src/sdl12/SRB2WII/icon.png and /dev/null differ diff --git a/src/sdl12/SRB2WII/meta.xml b/src/sdl12/SRB2WII/meta.xml deleted file mode 100644 index 843176d3a..000000000 --- a/src/sdl12/SRB2WII/meta.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - SRB2Wii - Callum - 2.0.6 - 20101207 - A 3D Sonic fangame - Sonic Robo Blast 2 is a 3D fangame by a small group called -Sonic Team Junior, using the Doom engine as a base. -The game has been worked on for almost 11 years so far, and -it is still being very much developed today, with a huge -fanbase developing custom content, including characters, -levels, and even large-scale modifications that play out -a brand new adventure. -Based on the Doom II engine, SRB2's system requirements -are very low, even the oldest computers can play it at a -decent speed. - diff --git a/src/sdl12/SRB2XBOX/Makefile.cfg b/src/sdl12/SRB2XBOX/Makefile.cfg deleted file mode 100644 index 56966d438..000000000 --- a/src/sdl12/SRB2XBOX/Makefile.cfg +++ /dev/null @@ -1,44 +0,0 @@ -# -# Makefile.cfg for SRB2/XBOX -# - -# -#hmmm, the XBOX -# - - NOHW=1 #No working OpenGL right now - NOHS=1 #No HWSound right now - NOASM=1 #No Fast code - NONET=1 #No network code - NOMD5=1 #No Slow MD5 - NOPNG=1 #No Screenshot - #SDLMAIN=1 #SDLMain! - -ifndef OPENXDK - OPENXDK=/usr/local/openxdk -endif - - CXBE=$(OPENXDK)/bin/cxbe - -ifdef ECHO - CXBE:=@$(CXBE) -endif - -ifndef NOHW - OPTS+=-DMINI_GL_COMPATIBILITY -endif - - BUILTLM=-fno-builtin - CFLAGS+=-D_XBOX -std=gnu99 -ffreestanding $(BUILTLM) -fno-exceptions - CFLAGS+=-I$(OPENXDK)/i386-pc-xbox/include -I$(OPENXDK)/include - OPTS+=-nostdlib -mno-cygwin -march=i386 - LDFLAGS+=-nostdlib -Wl,--file-alignment,0x20 -Wl,--section-alignment,0x20 -shared -Wl,--entry,_WinMainCRTStartup -Wl,--strip-all -L$(OPENXDK)/i386-pc-xbox/lib -L$(OPENXDK)/lib - LIBS=-lg -lc -lm - SDL_CFLAGS?=-I$(OPENXDK)/include/SDL - SDL_LDFLAGS?=-lSDL -lopenxdk -lhal -lc -lhal -lusb -lhal -lc -lxboxkrnl - - i_system_o+=$(OBJDIR)/xboxhelp.o - - # name of the exefile - EXENAME?=SRB2XBOX.EXE - BINNAME?=default.xbe diff --git a/src/sdl12/SRB2XBOX/xboxhelp.c b/src/sdl12/SRB2XBOX/xboxhelp.c deleted file mode 100644 index 05b6c5e68..000000000 --- a/src/sdl12/SRB2XBOX/xboxhelp.c +++ /dev/null @@ -1,91 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2004-2018 by Sonic Team Jr. -// -// 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: -// stub and replacement "ANSI" C functions for use under OpenXDK -// -//----------------------------------------------------------------------------- - -#include "../../doomdef.h" -#include "xboxhelp.h" -#ifdef __GNUC__ -#include -#else -#include -#endif - -char *getcwd(char *_buf, size_t _size ) -{ - (void)_buf; - (void)_size; - return _buf; -} - -#ifdef _MSC_VER -int mkdir(const char *path) -{ - (void)path; - return 0; -} -#elif 0 //__GNUC__? -int mkdir(const char *path, mode_t _mode) -{ - (void)path; - (void)_mode; - return 0; -} -#endif - -int chdir (const char *__path ) -{ - (void)__path; - return 0; -} - -time_t time(time_t *T) -{ - long returntime = 0; - (void)T; -/* - SYSTEMTIME st; - FILETIME stft; - INT64 ftli; - if (!T) return returntime; - GetSystemTime(&st); - SystemTimeToFileTime(&st,&stft); - CopyMemory(&ftli,&stft,sizeof (LARGE_INTEGER)); - returntime = (long)ftli; - *T = returntime; -*/ - return returntime; -} - -#ifdef _MSC_VER -#include -void __cdecl _RTC_Initialize(void) -{ -} -char *getenv(const char *__env) -{ - __env = NULL; - return NULL; -} - -int putenv(const char *__env) -{ - __env = NULL; - return 0; -} -#endif diff --git a/src/sdl12/SRB2XBOX/xboxhelp.h b/src/sdl12/SRB2XBOX/xboxhelp.h deleted file mode 100644 index 97ef0a3be..000000000 --- a/src/sdl12/SRB2XBOX/xboxhelp.h +++ /dev/null @@ -1,6 +0,0 @@ -#if defined (_MSC_VER) -int access(const char *path, int amode); -char *getcwd(char *_buf, size_t _size ); -int mkdir(const char *path); -int chdir (const char *__path ); -#endif diff --git a/src/sdl12/Srb2SDL.dsw b/src/sdl12/Srb2SDL.dsw deleted file mode 100644 index 4f8f7bdce..000000000 --- a/src/sdl12/Srb2SDL.dsw +++ /dev/null @@ -1,74 +0,0 @@ -Microsoft Developer Studio Workspace File, Format Version 6.00 -# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! - -############################################################################### - -Project: "Srb2SDL"=.\Srb2SDL.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libpng - End Project Dependency - Begin Project Dependency - Project_Dep_Name zlib - End Project Dependency -}}} - -############################################################################### - -Project: "libpng"="..\..\libs\libpng-src\projects\visualc6\libpng.dsp" - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name zlib - End Project Dependency -}}} - -############################################################################### - -Project: "s_openal"=..\hardware\s_openal\s_openal.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Project: "zlib"=..\..\libs\zlib\projects\visualc6\zlib.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ -}}} - -############################################################################### - -Global: - -Package=<5> -{{{ -}}} - -Package=<3> -{{{ -}}} - -############################################################################### - diff --git a/src/sdl12/dosstr.c b/src/sdl12/dosstr.c deleted file mode 100644 index f9bbee9b4..000000000 --- a/src/sdl12/dosstr.c +++ /dev/null @@ -1,38 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// This file is in the public domain. -// (Re)written by Graue in 2006. -// -//----------------------------------------------------------------------------- -/// \file -/// \brief String uppercasing/lowercasing functions for non-DOS non-Win32 -/// systems - -#include "../doomtype.h" - -#ifndef HAVE_DOSSTR_FUNCS - -#include - -int strupr(char *n) -{ - while (*n != '\0') - { - *n = toupper(*n); - n++; - } - return 1; -} - -int strlwr(char *n) -{ - while (*n != '\0') - { - *n = tolower(*n); - n++; - } - return 1; -} - -#endif diff --git a/src/sdl12/endtxt.c b/src/sdl12/endtxt.c deleted file mode 100644 index 1d7756b4d..000000000 --- a/src/sdl12/endtxt.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Function to write the SRB2 end message text - * - * Copyright (C) 1998 by Udo Munk - * - * This code is provided AS IS and there are no guarantees, none. - * Feel free to share and modify. - */ -//----------------------------------------------------------------------------- -/// \file -/// \brief Support to show ENDOOM text -/// -/// Loads the lump ENDOOM, set up the console to print -/// out the colors and text - -#include -#include - -// need this 19990118 by Kin -#include "../doomdef.h" -#include "../w_wad.h" -#include "../z_zone.h" -#include "endtxt.h" -/** \brief The ShowEndTxt function - - - Prints out the ENDOOM the way DOOM.EXE/DOOM2.EXE did for Win32 or Linux/GNU - - \return void - - -*/ - -void ShowEndTxt(void) -{ -#if !(defined (_WIN32_WCE) || defined (_XBOX) || defined (_arch_dreamcast)) - INT32 i; - UINT16 j, att = 0; - INT32 nlflag = 1; -#ifdef _WIN32 - HANDLE co = GetStdHandle(STD_OUTPUT_HANDLE); - DWORD mode, bytesWritten; - CONSOLE_SCREEN_BUFFER_INFO backupcon; - COORD resizewin = {80,-1}; - CHAR let = 0; -#endif - UINT16 *ptext; - void *data; - lumpnum_t endoomnum = W_GetNumForName("ENDOOM"); - //char *col; - - /* if the xterm has more then 80 columns we need to add nl's */ - /* doesn't work, COLUMNS is not in the environment at this time ??? - col = I_getenv("COLUMNS"); - if (col) { - if (atoi(col) > 80) - nlflag++; - } - */ - - /* get the lump with the text */ - data = ptext = W_CacheLumpNum(endoomnum, PU_CACHE); - -#ifdef _WIN32 - if (co == INVALID_HANDLE_VALUE || GetFileType(co) != FILE_TYPE_CHAR || !GetConsoleMode(co, &mode)) // test if it a good handle - { - Z_Free(data); - return; - } - - backupcon.wAttributes = FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE; // Just in case - GetConsoleScreenBufferInfo(co, &backupcon); //Store old state - resizewin.Y = backupcon.dwSize.Y; - if (backupcon.dwSize.X < resizewin.X) - SetConsoleScreenBufferSize(co, resizewin); - - for (i=1; i<=80*25; i++) // print 80x25 text and deal with the attributes too - { - j = (UINT16)(*ptext >> 8); // attribute first - let = (char)(*ptext & 0xff); // text second - if (j != att) // attribute changed? - { - att = j; // save current attribute - SetConsoleTextAttribute(co, j); //set fg and bg color for buffer - } - - WriteConsoleA(co, &let, 1, &bytesWritten, NULL); // now the text - - if (nlflag && !(i % 80) && backupcon.dwSize.X > resizewin.X) // do we need a nl? - { - att = backupcon.wAttributes; - SetConsoleTextAttribute(co, att); // all attributes off - WriteConsoleA(co, "\n", 1, &bytesWritten, NULL); // newline to console - } - ptext++; - } - SetConsoleTextAttribute(co, backupcon.wAttributes); // all attributes off -#else - /* print 80x25 text and deal with the attributes too */ - for (i=1; i<=80*25; i++) { - /* attribute first */ - /* attribute changed? */ - if ((j = *ptext >> 8) != att) { - /* save current attribute */ - att = j; - /* set new attribute, forground color first */ - printf("\033["); - switch (j & 0x0f) { - case 0: /* black */ - printf("30"); - break; - case 1: /* blue */ - printf("34"); - break; - case 2: /* green */ - printf("32"); - break; - case 3: /* cyan */ - printf("36"); - break; - case 4: /* red */ - printf("31"); - break; - case 5: /* magenta */ - printf("35"); - break; - case 6: /* brown */ - printf("33"); - break; - case 7: /* bright grey */ - printf("37"); - break; - case 8: /* dark grey */ - printf("1;30"); - break; - case 9: /* bright blue */ - printf("1;34"); - break; - case 10: /* bright green */ - printf("1;32"); - break; - case 11: /* bright cyan */ - printf("1;36"); - break; - case 12: /* bright red */ - printf("1;31"); - break; - case 13: /* bright magenta */ - printf("1;35"); - break; - case 14: /* yellow */ - printf("1;33"); - break; - case 15: /* white */ - printf("1;37"); - break; - } - printf("m"); - /* now background color */ - printf("\033["); - switch ((j >> 4) & 0x0f) { - case 0: /* black */ - printf("40"); - break; - case 1: /* blue */ - printf("44"); - break; - case 2: /* green */ - printf("42"); - break; - case 3: /* cyan */ - printf("46"); - break; - case 4: /* red */ - printf("41"); - break; - case 5: /* magenta */ - printf("45"); - break; - case 6: /* brown */ - printf("43"); - break; - case 7: /* bright grey */ - printf("47"); - break; - case 8: /* dark grey */ - printf("1;40"); - break; - case 9: /* bright blue */ - printf("1;44"); - break; - case 10: /* bright green */ - printf("1;42"); - break; - case 11: /* bright cyan */ - printf("1;46"); - break; - case 12: /* bright red */ - printf("1;41"); - break; - case 13: /* bright magenta */ - printf("1;45"); - break; - case 14: /* yellow */ - printf("1;43"); - break; - case 15: /* white */ - printf("1;47"); - break; - } - printf("m"); - } - - /* now the text */ - printf("%c",*ptext++ & 0xff); - - /* do we need a nl? */ - if (nlflag) - { - if (!(i % 80)) - { - printf("\033[0m"); - att = 0; - printf("\n"); - } - } - } - /* all attributes off */ - printf("\033[0m"); -#endif - if (nlflag) - printf("\n"); - - Z_Free(data); -#endif -} diff --git a/src/sdl12/endtxt.h b/src/sdl12/endtxt.h deleted file mode 100644 index 41f8e51ad..000000000 --- a/src/sdl12/endtxt.h +++ /dev/null @@ -1,24 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Support to show ENDOOM text - -#ifndef __ENDTXT__ -#define __ENDTXT__ - -void ShowEndTxt (void); - -#endif diff --git a/src/sdl12/filter/filters.c b/src/sdl12/filter/filters.c deleted file mode 100644 index 1b2346e8e..000000000 --- a/src/sdl12/filter/filters.c +++ /dev/null @@ -1,1000 +0,0 @@ -#include -#include "filters.h" - -//Alam_GBC: C file based on sms_sdl's filter.c - -/* 2X SAI Filter */ -static Uint32 colorMask = 0xF7DEF7DE; -static Uint32 lowPixelMask = 0x08210821; -static Uint32 qcolorMask = 0xE79CE79C; -static Uint32 qlowpixelMask = 0x18631863; -static Uint32 redblueMask = 0xF81F; -static Uint32 greenMask = 0x7E0; - -SDL_Surface *filter_2x(SDL_Surface *src, SDL_Rect *srcclp, filter_2 filter) -{ - return filter_2xe(src,srcclp,filter,0,0,0); -} - -SDL_Surface *filter_2xe(SDL_Surface *src, SDL_Rect *srcclp, filter_2 filter,Uint8 R, Uint8 G, Uint8 B) -{ - SDL_Surface *srcfilter = NULL; - SDL_Rect dstclp = {0,3,0,0}; - SDL_Surface *dstfilter = NULL; - Uint32 Fillcolor = 0; - if(!src || !filter) return NULL; // Need src and filter - if(srcclp) // size by clp - { - dstclp.w = srcclp->w; //clp's width - dstclp.h = srcclp->h; //clp's height - } - else // size by src - { - dstclp.w = (Uint16)src->w; //src's width - dstclp.h = (Uint16)src->h; //src's height - } - if(filter == hq2x32 || filter == lq2x32) // src 0888 surface - srcfilter = SDL_CreateRGBSurface(SDL_SWSURFACE,dstclp.w,dstclp.h+6,32,0x00FF0000,0x0000FF00,0x000000FF,0x00); - else // src 565 surface - srcfilter = SDL_CreateRGBSurface(SDL_SWSURFACE,dstclp.w,dstclp.h+6,16,0x0000F800,0x000007E0,0x0000001F,0x00); - if(!srcfilter) return NULL; //No Memory? - Fillcolor = SDL_MapRGB(srcfilter->format,R,G,B); //Choose color - SDL_FillRect(srcfilter,NULL,Fillcolor); //fill it - if(filter == filter_hq2x || filter == hq2x32 || filter == lq2x32) // dst 0888 surface - dstfilter = SDL_CreateRGBSurface(SDL_SWSURFACE,dstclp.w*2,dstclp.h*2,32,0x00FF0000,0x0000FF00,0x000000FF,0x00); - else // dst 565 surface - dstfilter = SDL_CreateRGBSurface(SDL_SWSURFACE,dstclp.w*2,dstclp.h*2,16,0x0000F800,0x000007E0,0x0000001F,0x00); - if(!dstfilter || SDL_BlitSurface(src,srcclp,srcfilter,&dstclp) == -1) // No dstfilter or Blit failed - { - SDL_FreeSurface(srcfilter); // Free memory - return NULL; //No Memory? - } - else // have dstfilter ready and srcfilter done - { - SDL_FillRect(dstfilter,NULL,Fillcolor); //fill it too - filter(FILTER(srcfilter,dstfilter)); //filtering - SDL_FreeSurface(srcfilter); //almost - } - return dstfilter; //done -} - - -int filter_init_2xsai(SDL_PixelFormat *BitFormat) -{ - if (!BitFormat || BitFormat->BytesPerPixel != 2 ||BitFormat->Amask != 0x0) - { - return 0; - } - else if (BitFormat->Rmask == 0xF800 && BitFormat->Gmask == 0x7E0 - && BitFormat->Bmask == 0x1F && BitFormat->BitsPerPixel == 16) //565 - { - colorMask = 0xF7DEF7DE; - lowPixelMask = 0x08210821; - qcolorMask = 0xE79CE79C; - qlowpixelMask = 0x18631863; - redblueMask = 0xF81F; - greenMask = 0x7E0; - } - else if (BitFormat->Rmask == 0x7C00 && BitFormat->Gmask == 0x3E0 - && BitFormat->Bmask == 0x1F && BitFormat->BitsPerPixel == 15) //555 - { - colorMask = 0x7BDE7BDE; - lowPixelMask = 0x04210421; - qcolorMask = 0x739C739C; - qlowpixelMask = 0x0C630C63; - redblueMask = 0x7C1F; - greenMask = 0x3E0; - } - else - { - return 0; - } -#ifdef MMX - if(BitFormat->Gmask == 0x7E0) Init_2xSaIMMX(565); - else Init_2xSaIMMX(555); -#endif - return 1; -} - - -FUNCINLINE static ATTRINLINE int GetResult1 (Uint32 A, Uint32 B, Uint32 C, Uint32 D, Uint32 E) -{ - int x = 0; - int y = 0; - int r = 0; - (void)E; - - if (A == C) - x += 1; - else if (B == C) - y += 1; - if (A == D) - x += 1; - else if (B == D) - y += 1; - if (x <= 1) - r += 1; - if (y <= 1) - r -= 1; - return r; -} - -FUNCINLINE static ATTRINLINE int GetResult2 (Uint32 A, Uint32 B, Uint32 C, Uint32 D, Uint32 E) -{ - int x = 0; - int y = 0; - int r = 0; - (void)E; - - if (A == C) - x += 1; - else if (B == C) - y += 1; - if (A == D) - x += 1; - else if (B == D) - y += 1; - if (x <= 1) - r -= 1; - if (y <= 1) - r += 1; - return r; -} - -FUNCINLINE static ATTRINLINE int GetResult (Uint32 A, Uint32 B, Uint32 C, Uint32 D) -{ - int x = 0; - int y = 0; - int r = 0; - - if (A == C) - x += 1; - else if (B == C) - y += 1; - if (A == D) - x += 1; - else if (B == D) - y += 1; - if (x <= 1) - r += 1; - if (y <= 1) - r -= 1; - return r; -} - -FUNCINLINE static ATTRINLINE Uint32 INTERPOLATE (Uint32 A, Uint32 B) -{ - if (A != B) - { - return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + - (A & B & lowPixelMask)); - } - else - return A; -} - -FUNCINLINE static ATTRINLINE Uint32 Q_INTERPOLATE (Uint32 A, Uint32 B, Uint32 C, Uint32 D) -{ - register Uint32 x = ((A & qcolorMask) >> 2) + - ((B & qcolorMask) >> 2) + - ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2); - register Uint32 y = (A & qlowpixelMask) + - (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask); - y = (y >> 2) & qlowpixelMask; - return x + y; -} - -#define BLUE_MASK565 0x001F001F -#define RED_MASK565 0xF800F800 -#define GREEN_MASK565 0x07E007E0 - -#define BLUE_MASK555 0x001F001F -#define RED_MASK555 0x7C007C00 -#define GREEN_MASK555 0x03E003E0 - -void filter_super2xsai(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - Uint16 *bP; - Uint8 *dP; - Uint32 inc_bP; - Uint32 Nextline = srcPitch >> 1; - - Uint32 finish; - inc_bP = 1; - - for (; height; height--) - { - bP = (Uint16 *) srcPtr; - dP = (Uint8 *) dstPtr; - - for (finish = width; finish; finish -= inc_bP) - { - Uint32 color4, color5, color6; - Uint32 color1, color2, color3; - Uint32 colorA0, colorA1, colorA2, colorA3, - colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; - Uint32 product1a, product1b, product2a, product2b; - -//--------------------------------------- B1 B2 -// 4 5 6 S2 -// 1 2 3 S1 -// A1 A2 - - colorB0 = *(bP - Nextline - 1); - colorB1 = *(bP - Nextline); - colorB2 = *(bP - Nextline + 1); - colorB3 = *(bP - Nextline + 2); - - color4 = *(bP - 1); - color5 = *(bP); - color6 = *(bP + 1); - colorS2 = *(bP + 2); - - color1 = *(bP + Nextline - 1); - color2 = *(bP + Nextline); - color3 = *(bP + Nextline + 1); - colorS1 = *(bP + Nextline + 2); - - colorA0 = *(bP + Nextline + Nextline - 1); - colorA1 = *(bP + Nextline + Nextline); - colorA2 = *(bP + Nextline + Nextline + 1); - colorA3 = *(bP + Nextline + Nextline + 2); - -//-------------------------------------- - if (color2 == color6 && color5 != color3) - { - product2b = product1b = color2; - } - else if (color5 == color3 && color2 != color6) - { - product2b = product1b = color5; - } - else if (color5 == color3 && color2 == color6) - { - register int r = 0; - - r += GetResult (color6, color5, color1, colorA1); - r += GetResult (color6, color5, color4, colorB1); - r += GetResult (color6, color5, colorA2, colorS1); - r += GetResult (color6, color5, colorB2, colorS2); - - if (r > 0) - product2b = product1b = color6; - else if (r < 0) - product2b = product1b = color5; - else - { - product2b = product1b = INTERPOLATE (color5, color6); - } - } - else - { - if (color6 == color3 && color3 == colorA1 - && color2 != colorA2 && color3 != colorA0) - product2b = - Q_INTERPOLATE (color3, color3, color3, color2); - else if (color5 == color2 && color2 == colorA2 - && colorA1 != color3 && color2 != colorA3) - product2b = - Q_INTERPOLATE (color2, color2, color2, color3); - else - product2b = INTERPOLATE (color2, color3); - - if (color6 == color3 && color6 == colorB1 - && color5 != colorB2 && color6 != colorB0) - product1b = - Q_INTERPOLATE (color6, color6, color6, color5); - else if (color5 == color2 && color5 == colorB2 - && colorB1 != color6 && color5 != colorB3) - product1b = - Q_INTERPOLATE (color6, color5, color5, color5); - else - product1b = INTERPOLATE (color5, color6); - } - - if (color5 == color3 && color2 != color6 && color4 == color5 - && color5 != colorA2) - product2a = INTERPOLATE (color2, color5); - else - if (color5 == color1 && color6 == color5 - && color4 != color2 && color5 != colorA0) - product2a = INTERPOLATE (color2, color5); - else - product2a = color2; - - if (color2 == color6 && color5 != color3 && color1 == color2 - && color2 != colorB2) - product1a = INTERPOLATE (color2, color5); - else - if (color4 == color2 && color3 == color2 - && color1 != color5 && color2 != colorB0) - product1a = INTERPOLATE (color2, color5); - else - product1a = color5; - -#ifdef LSB_FIRST - product1a = product1a | (product1b << 16); - product2a = product2a | (product2b << 16); -#else - product1a = (product1a << 16) | product1b; - product2a = (product2a << 16) | product2b; -#endif - *((Uint32 *) dP) = product1a; - *((Uint32 *) (dP + dstPitch)) = product2a; - - bP += inc_bP; - dP += sizeof (Uint32); - } // end of for ( finish= width etc..) - - srcPtr += srcPitch; - dstPtr += dstPitch * 2; - } // endof: for (; height; height--) -} - -void filter_supereagle(Uint8 *srcPtr, Uint32 srcPitch, /* Uint8 *deltaPtr, */ - Uint8 *dstPtr, Uint32 dstPitch, int width, int height) -{ - Uint8 *dP; - Uint16 *bP; - Uint32 inc_bP; - - - - Uint32 finish; - Uint32 Nextline = srcPitch >> 1; - - inc_bP = 1; - - for (; height ; height--) - { - bP = (Uint16 *) srcPtr; - dP = dstPtr; - for (finish = width; finish; finish -= inc_bP) - { - Uint32 color4, color5, color6; - Uint32 color1, color2, color3; - Uint32 colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; - Uint32 product1a, product1b, product2a, product2b; - colorB1 = *(bP - Nextline); - colorB2 = *(bP - Nextline + 1); - - color4 = *(bP - 1); - color5 = *(bP); - color6 = *(bP + 1); - colorS2 = *(bP + 2); - - color1 = *(bP + Nextline - 1); - color2 = *(bP + Nextline); - color3 = *(bP + Nextline + 1); - colorS1 = *(bP + Nextline + 2); - - colorA1 = *(bP + Nextline + Nextline); - colorA2 = *(bP + Nextline + Nextline + 1); - // -------------------------------------- - if (color2 == color6 && color5 != color3) - { - product1b = product2a = color2; - if ((color1 == color2) || (color6 == colorB2)) - { - product1a = INTERPOLATE (color2, color5); - product1a = INTERPOLATE (color2, product1a); -// product1a = color2; - } - else - { - product1a = INTERPOLATE (color5, color6); - } - - if ((color6 == colorS2) || (color2 == colorA1)) - { - product2b = INTERPOLATE (color2, color3); - product2b = INTERPOLATE (color2, product2b); -// product2b = color2; - } - else - { - product2b = INTERPOLATE (color2, color3); - } - } - else if (color5 == color3 && color2 != color6) - { - product2b = product1a = color5; - - if ((colorB1 == color5) || (color3 == colorS1)) - { - product1b = INTERPOLATE (color5, color6); - product1b = INTERPOLATE (color5, product1b); -// product1b = color5; - } - else - { - product1b = INTERPOLATE (color5, color6); - } - - if ((color3 == colorA2) || (color4 == color5)) - { - product2a = INTERPOLATE (color5, color2); - product2a = INTERPOLATE (color5, product2a); -// product2a = color5; - } - else - { - product2a = INTERPOLATE (color2, color3); - } - - } - else if (color5 == color3 && color2 == color6) - { - register int r = 0; - - r += GetResult (color6, color5, color1, colorA1); - r += GetResult (color6, color5, color4, colorB1); - r += GetResult (color6, color5, colorA2, colorS1); - r += GetResult (color6, color5, colorB2, colorS2); - - if (r > 0) - { - product1b = product2a = color2; - product1a = product2b = INTERPOLATE (color5, color6); - } - else if (r < 0) - { - product2b = product1a = color5; - product1b = product2a = INTERPOLATE (color5, color6); - } - else - { - product2b = product1a = color5; - product1b = product2a = color2; - } - } - else - { - product2b = product1a = INTERPOLATE (color2, color6); - product2b = - Q_INTERPOLATE (color3, color3, color3, product2b); - product1a = - Q_INTERPOLATE (color5, color5, color5, product1a); - - product2a = product1b = INTERPOLATE (color5, color3); - product2a = - Q_INTERPOLATE (color2, color2, color2, product2a); - product1b = - Q_INTERPOLATE (color6, color6, color6, product1b); - -// product1a = color5; -// product1b = color6; -// product2a = color2; -// product2b = color3; - } -#ifdef LSB_FIRST - product1a = product1a | (product1b << 16); - product2a = product2a | (product2b << 16); -#else - product1a = (product1a << 16) | product1b; - product2a = (product2a << 16) | product2b; -#endif - - *((Uint32 *) dP) = product1a; - *((Uint32 *) (dP + dstPitch)) = product2a; - - bP += inc_bP; - dP += sizeof (Uint32); - } // end of for ( finish= width etc..) - srcPtr += srcPitch; - dstPtr += dstPitch * 2; - } // endof: for (height; height; height--) -} - -void filter_2xsai (Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, int width, int height) -{ - Uint8 *dP; - Uint16 *bP; - Uint32 inc_bP; - - - Uint32 finish; - Uint32 Nextline = srcPitch >> 1; - inc_bP = 1; - - - for (; height; height--) - { - bP = (Uint16 *) srcPtr; - dP = dstPtr; - - for (finish = width; finish; finish -= inc_bP) - { - - register Uint32 colorA, colorB; - Uint32 colorC, colorD, - colorE, colorF, colorG, colorH, - colorI, colorJ, colorK, colorL, - - colorM, colorN, colorO, colorP; - Uint32 product, product1, product2; - -//--------------------------------------- -// Map of the pixels: I|E F|J -// G|A B|K -// H|C D|L -// M|N O|P - colorI = *(bP - Nextline - 1); - colorE = *(bP - Nextline); - colorF = *(bP - Nextline + 1); - colorJ = *(bP - Nextline + 2); - - colorG = *(bP - 1); - colorA = *(bP); - colorB = *(bP + 1); - colorK = *(bP + 2); - - colorH = *(bP + Nextline - 1); - colorC = *(bP + Nextline); - colorD = *(bP + Nextline + 1); - colorL = *(bP + Nextline + 2); - - colorM = *(bP + Nextline + Nextline - 1); - colorN = *(bP + Nextline + Nextline); - colorO = *(bP + Nextline + Nextline + 1); - colorP = *(bP + Nextline + Nextline + 2); - - if ((colorA == colorD) && (colorB != colorC)) - { - if (((colorA == colorE) && (colorB == colorL)) || - ((colorA == colorC) && (colorA == colorF) - && (colorB != colorE) && (colorB == colorJ))) - { - product = colorA; - } - else - { - product = INTERPOLATE (colorA, colorB); - } - - if (((colorA == colorG) && (colorC == colorO)) || - ((colorA == colorB) && (colorA == colorH) - && (colorG != colorC) && (colorC == colorM))) - { - product1 = colorA; - } - else - { - product1 = INTERPOLATE (colorA, colorC); - } - product2 = colorA; - } - else if ((colorB == colorC) && (colorA != colorD)) - { - if (((colorB == colorF) && (colorA == colorH)) || - ((colorB == colorE) && (colorB == colorD) - && (colorA != colorF) && (colorA == colorI))) - { - product = colorB; - } - else - { - product = INTERPOLATE (colorA, colorB); - } - - if (((colorC == colorH) && (colorA == colorF)) || - ((colorC == colorG) && (colorC == colorD) - && (colorA != colorH) && (colorA == colorI))) - { - product1 = colorC; - } - else - { - product1 = INTERPOLATE (colorA, colorC); - } - product2 = colorB; - } - else if ((colorA == colorD) && (colorB == colorC)) - { - if (colorA == colorB) - { - product = colorA; - product1 = colorA; - product2 = colorA; - } - else - { - register int r = 0; - - product1 = INTERPOLATE (colorA, colorC); - product = INTERPOLATE (colorA, colorB); - - r += - GetResult1 (colorA, colorB, colorG, colorE, - colorI); - r += - GetResult2 (colorB, colorA, colorK, colorF, - colorJ); - r += - GetResult2 (colorB, colorA, colorH, colorN, - colorM); - r += - GetResult1 (colorA, colorB, colorL, colorO, - colorP); - - if (r > 0) - product2 = colorA; - else if (r < 0) - product2 = colorB; - else - { - product2 = - Q_INTERPOLATE (colorA, colorB, colorC, - colorD); - } - } - } - else - { - product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); - - if ((colorA == colorC) && (colorA == colorF) - && (colorB != colorE) && (colorB == colorJ)) - { - product = colorA; - } - else - if ((colorB == colorE) && (colorB == colorD) - && (colorA != colorF) && (colorA == colorI)) - { - product = colorB; - } - else - { - product = INTERPOLATE (colorA, colorB); - } - - if ((colorA == colorB) && (colorA == colorH) - && (colorG != colorC) && (colorC == colorM)) - { - product1 = colorA; - } - else - if ((colorC == colorG) && (colorC == colorD) - && (colorA != colorH) && (colorA == colorI)) - { - product1 = colorC; - } - else - { - product1 = INTERPOLATE (colorA, colorC); - } - } -#ifdef LSB_FIRST - product = colorA | (product << 16); - product1 = product1 | (product2 << 16); -#else - product = (colorA << 16) | product; - product1 = (product1 << 16) | product2; -#endif - *((Uint32 *) dP) = product; - *((Uint32 *) (dP + dstPitch)) = product1; - - bP += inc_bP; - dP += sizeof (Uint32); - } // end of for ( finish= width etc..) - - srcPtr += srcPitch; - dstPtr += dstPitch * 2; - } // endof: for (height; height; height--) -} - -#if 0 -static inline Uint32 Bilinear(Uint32 A, Uint32 B, Uint32 x) -{ - unsigned long areaA, areaB; - unsigned long result; - - if (A == B) - return A; - - areaB = (x >> 11) & 0x1f; // reduce 16 bit fraction to 5 bits - areaA = 0x20 - areaB; - - A = (A & redblueMask) | ((A & greenMask) << 16); - B = (B & redblueMask) | ((B & greenMask) << 16); - - result = ((areaA * A) + (areaB * B)) >> 5; - - return (result & redblueMask) | ((result >> 16) & greenMask); - -} - -static inline Uint32 Bilinear4 (Uint32 A, Uint32 B, Uint32 C, Uint32 D, Uint32 x, - Uint32 y) -{ - unsigned long areaA, areaB, areaC, areaD; - unsigned long result, xy; - - x = (x >> 11) & 0x1f; - y = (y >> 11) & 0x1f; - xy = (x * y) >> 5; - - A = (A & redblueMask) | ((A & greenMask) << 16); - B = (B & redblueMask) | ((B & greenMask) << 16); - C = (C & redblueMask) | ((C & greenMask) << 16); - D = (D & redblueMask) | ((D & greenMask) << 16); - - areaA = 0x20 + xy - x - y; - areaB = x - xy; - areaC = y - xy; - areaD = xy; - - result = ((areaA * A) + (areaB * B) + (areaC * C) + (areaD * D)) >> 5; - - return (result & redblueMask) | ((result >> 16) & greenMask); -} -#endif - - -void filter_advmame2x(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - unsigned int nextlineSrc = srcPitch / sizeof(short); - short *p = (short *)srcPtr; - - unsigned int nextlineDst = dstPitch / sizeof(short); - short *q = (short *)dstPtr; - - while(height--) { - int i = 0, j = 0; - for(i = 0; i < width; ++i, j += 2) { - short B = *(p + i - nextlineSrc); - short D = *(p + i - 1); - short E = *(p + i); - short F = *(p + i + 1); - short H = *(p + i + nextlineSrc); - - *(q + j) = (short)(D == B && B != F && D != H ? D : E); - *(q + j + 1) = (short)(B == F && B != D && F != H ? F : E); - *(q + j + nextlineDst) = (short)(D == H && D != B && H != F ? D : E); - *(q + j + nextlineDst + 1) = (short)(H == F && D != H && B != F ? F : E); - } - p += nextlineSrc; - q += nextlineDst << 1; - } -} - - -void filter_tv2x(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - unsigned int nextlineSrc = srcPitch / sizeof(Uint16); - Uint16 *p = (Uint16 *)srcPtr; - - unsigned int nextlineDst = dstPitch / sizeof(Uint16); - Uint16 *q = (Uint16 *)dstPtr; - - while(height--) { - int i = 0, j = 0; - for(; i < width; ++i, j += 2) { - Uint16 p1 = *(p + i); - Uint32 pi; - - pi = (((p1 & redblueMask) * 7) >> 3) & redblueMask; - pi |= (((p1 & greenMask) * 7) >> 3) & greenMask; - - *(q + j) = (Uint16)p1; - *(q + j + 1) = (Uint16)p1; - *(q + j + nextlineDst) = (Uint16)pi; - *(q + j + nextlineDst + 1) = (Uint16)pi; - } - p += nextlineSrc; - q += nextlineDst << 1; - } -} - -void filter_normal2x(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - unsigned int nextlineSrc = srcPitch / sizeof(Uint16); - Uint16 *p = (Uint16 *)srcPtr; - - unsigned int nextlineDst = dstPitch / sizeof(Uint16); - Uint16 *q = (Uint16 *)dstPtr; - - while(height--) { - int i = 0, j = 0; - for(; i < width; ++i, j += 2) { - Uint16 color = *(p + i); - - *(q + j) = color; - *(q + j + 1) = color; - *(q + j + nextlineDst) = color; - *(q + j + nextlineDst + 1) = color; - } - p += nextlineSrc; - q += nextlineDst << 1; - } -} - -void filter_scan50(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - - unsigned int nextlineSrc = srcPitch / sizeof(Uint16); - Uint16 *p = (Uint16 *)srcPtr; - - unsigned int nextlineDst = dstPitch / sizeof(Uint16); - Uint16 *q = (Uint16 *)dstPtr; - - while(height--) { - int i = 0, j = 0; - for(; i < width; ++i, j += 2) { - Uint16 p1 = *(p + i); - Uint16 p2 = *(p + i + nextlineSrc); - // 0111 1011 1110 1111 == 0x7BEF - Uint16 pm = (Uint16)(((p1 + p2) >> 2) & 0x7BEF); - - *(q + j) = p1; - *(q + j + 1) = p1; - *(q + j + nextlineDst) = pm; - *(q + j + nextlineDst + 1) = pm; - - } - p += nextlineSrc; - q += nextlineDst << 1; - } -} - - -void filter_scan100(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - unsigned int nextlineSrc = srcPitch / sizeof(Uint16); - Uint16 *p = (Uint16 *)srcPtr; - - unsigned int nextlineDst = dstPitch / sizeof(Uint16); - Uint16 *q = (Uint16 *)dstPtr; - - while(height--) { - int i = 0, j = 0; - for(; i < width; ++i, j += 2) { - *(q + j) = *(q + j + 1) = *(p + i); - } - p += nextlineSrc; - q += nextlineDst << 1; - } -} - - -FUNCINLINE static ATTRINLINE Uint16 DOT_16(Uint16 c, int j, int i) { - static const Uint16 dotmatrix[16] = { - 0x01E0, 0x0007, 0x3800, 0x0000, - 0x39E7, 0x0000, 0x39E7, 0x0000, - 0x3800, 0x0000, 0x01E0, 0x0007, - 0x39E7, 0x0000, 0x39E7, 0x0000 - }; - return (Uint16)(c - ((c >> 2) & *(dotmatrix + ((j & 3) << 2) + (i & 3)))); -} - -void filter_dotmatrix(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - unsigned int nextlineSrc = srcPitch / sizeof(Uint16); - Uint16 *p = (Uint16 *)srcPtr; - - unsigned int nextlineDst = dstPitch / sizeof(Uint16); - Uint16 *q = (Uint16 *)dstPtr; - - int i, ii, j, jj; - for(j = 0, jj = 0; j < height; ++j, jj += 2) { - for(i = 0, ii = 0; i < width; ++i, ii += 2) { - Uint16 c = *(p + i); - *(q + ii) = DOT_16(c, jj, ii); - *(q + ii + 1) = DOT_16(c, jj, ii + 1); - *(q + ii + nextlineDst) = DOT_16(c, jj + 1, ii); - *(q + ii + nextlineDst + 1) = DOT_16(c, jj + 1, ii + 1); - } - p += nextlineSrc; - q += nextlineDst << 1; - } -} - - -void filter_bilinear(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - unsigned int nextlineSrc = srcPitch / sizeof(Uint16); - Uint16 *p = (Uint16 *)srcPtr; - unsigned int nextlineDst = dstPitch / sizeof(Uint16); - Uint16 *q = (Uint16 *)dstPtr; - - while(height--) { - int i, ii; - for(i = 0, ii = 0; i < width; ++i, ii += 2) { - Uint16 A = *(p + i); - Uint16 B = *(p + i + 1); - Uint16 C = *(p + i + nextlineSrc); - Uint16 D = *(p + i + nextlineSrc + 1); - *(q + ii) = A; - *(q + ii + 1) = (Uint16)INTERPOLATE(A, B); - *(q + ii + nextlineDst) = (Uint16)INTERPOLATE(A, C); - *(q + ii + nextlineDst + 1) = (Uint16)Q_INTERPOLATE(A, B, C, D); - } - p += nextlineSrc; - q += nextlineDst << 1; - } -} - - -// NEED_OPTIMIZE -static void MULT(Uint16 c, float* r, float* g, float* b, float alpha) { - *r += alpha * ((c & RED_MASK565 ) >> 11); - *g += alpha * ((c & GREEN_MASK565) >> 5); - *b += alpha * ((c & BLUE_MASK565 ) >> 0); -} - -static Uint16 MAKE_RGB565(float r, float g, float b) { - return (Uint16) - (((((Uint8)r) << 11) & RED_MASK565 ) | - ((((Uint8)g) << 5) & GREEN_MASK565) | - ((((Uint8)b) << 0) & BLUE_MASK565 )); -} - -FUNCINLINE static ATTRINLINE float CUBIC_WEIGHT(float x) { - // P(x) = { x, x>0 | 0, x<=0 } - // P(x + 2) ^ 3 - 4 * P(x + 1) ^ 3 + 6 * P(x) ^ 3 - 4 * P(x - 1) ^ 3 - double r = 0.; - if(x + 2 > 0) r += pow(x + 2, 3); - if(x + 1 > 0) r += -4 * pow(x + 1, 3); - if(x > 0) r += 6 * pow(x , 3); - if(x - 1 > 0) r += -4 * pow(x - 1, 3); - return (float)r / 6; -} - -void filter_bicubic(Uint8 *srcPtr, Uint32 srcPitch, - Uint8 *dstPtr, Uint32 dstPitch, - int width, int height) -{ - unsigned int nextlineSrc = srcPitch / sizeof(Uint16); - Uint16 *p = (Uint16 *)srcPtr; - unsigned int nextlineDst = dstPitch / sizeof(Uint16); - Uint16 *q = (Uint16 *)dstPtr; - int dx = width << 1, dy = height << 1; - float fsx = (float)width / dx; - float fsy = (float)height / dy; - float v = 0.0f; - int j = 0; - for(; j < dy; ++j) { - float u = 0.0f; - int iv = (int)v; - float decy = v - iv; - int i = 0; - for(; i < dx; ++i) { - int iu = (int)u; - float decx = u - iu; - float r, g, b; - int m; - r = g = b = 0.; - for(m = -1; m <= 2; ++m) { - float r1 = CUBIC_WEIGHT(decy - m); - int n; - for(n = -1; n <= 2; ++n) { - float r2 = CUBIC_WEIGHT(n - decx); - Uint16* pIn = p + (iu + n) + (iv + m) * nextlineSrc; - MULT(*pIn, &r, &g, &b, r1 * r2); - } - } - *(q + i) = MAKE_RGB565(r, g, b); - u += fsx; - } - q += nextlineDst; - v += fsy; - } -} diff --git a/src/sdl12/filter/filters.h b/src/sdl12/filter/filters.h deleted file mode 100644 index c4a84b4c9..000000000 --- a/src/sdl12/filter/filters.h +++ /dev/null @@ -1,212 +0,0 @@ -#ifndef __FILTERS_H__ -#define __FILTERS_H__ - -#ifdef _MSC_VER -#pragma warning(disable : 4514 4214 4244) -#endif - -#include "SDL.h" - -#ifdef _MSC_VER -#pragma warning(default : 4214 4244) -#endif - -typedef enum { - FILTER_2XSAI = 0, - FILTER_SUPER2XSAI, - FILTER_SUPEREAGLE, - FILTER_ADVMAME2X , - FILTER_TV2X , - FILTER_NORMAL2X , - FILTER_BILINEAR , - FILTER_DOTMATRIX , - FILTER_NUM , -} t_filter; - -typedef void (*filter_2)(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -SDL_Surface *filter_2x(SDL_Surface *src, SDL_Rect *srcclp, filter_2 filter); -SDL_Surface *filter_2xe(SDL_Surface *src, SDL_Rect *srcclp, filter_2 filter,Uint8 R, Uint8 G, Uint8 B); -//Alam_GBC: Header file based on sms_sdl's filter.h -//Note: need 3 lines at the bottom and top? - -//int filter_init_2xsai(SDL_PixelFormat *BitFormat); -#define FILTER(src,dst) (Uint8 *)(src->pixels)+src->pitch*3, (Uint32)src->pitch, (Uint8 *)dst->pixels, (Uint32)dst->pitch, src->w, src->h-6 -#define SDLFILTER(src,dst) (Uint8 *)src->pixels, (Uint32)src->pitch, (Uint8 *)dst->pixels, (Uint32)dst->pitch, src->w, src->h -int filter_init_2xsai(SDL_PixelFormat *BitFormat); //unless? -void filter_scan50(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_scan100(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); - -void filter_2xsai(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_super2xsai(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_supereagle(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_advmame2x(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_tv2x(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_normal2x(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_bilinear(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_dotmatrix(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void filter_bicubic(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void lq2x16(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void hq2x16(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); - -void filter_hq2x(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void lq2x32(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); -void hq2x32(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height); - -#ifdef FILTERS -typedef struct filter_s { filter_2 filter; int bpp; } filter_t; -#define NUMFILTERS 13 -static filter_t filtermode[NUMFILTERS+1] = { - {NULL , 0}, //None - {filter_normal2x , 16}, //2xNormal - {filter_advmame2x , 16}, //AdvMAME2x - {filter_tv2x , 16}, //TV2x - {filter_bilinear , 16}, //Bilinear - {filter_dotmatrix , 16}, //DotMatrix - {lq2x16 , 16}, //16LQ2x - {hq2x16 , 16}, //16HQ2x - {lq2x32 , 32}, //32LQ2x - {hq2x32 , 32}, //32HQ2x -// {filter_bicubic , 16}, //Slow Bicubic - // BAD - {filter_2xsai , 16}, //2xSAI - {filter_super2xsai, 16}, //Super2xSAI - {filter_supereagle, 16}, //SuperEagle -}; -CV_PossibleValue_t CV_Filters[] = {{ 0, "None"}, { 1, "2xNormal"}, - { 2, "AdvMAME2x"}, { 3, "TV2x"}, { 4, "Bilinear"} , { 5, "DotMatrix"}, - { 6, "16LQ2x"}, { 7, "16HQ2x"}, { 8, "32LQ2x"} , { 9, "32HQ2x"}, - {10, "2xSAI"}, {11, "Super2xSAI"}, {12, "SuperEagle"}, {0, NULL},}; -static void Filterchange(void); -consvar_t cv_filter = {"filter", "None", CV_CALL|CV_NOINIT, CV_Filters,Filterchange,0,NULL,NULL,0,0,NULL}; -static filter_2 blitfilter = NULL; -static SDL_Surface *preSurface = NULL; -static SDL_Surface *f2xSurface = NULL; - -static void Filterchange(void) -{ - if(blitfilter) // only filtering? - { - int i=0; - for(;i < NUMFILTERS; i++)//find old filter - { - if(filtermode[i].filter == blitfilter) //Found it - break; //Stop - } - if(i < NUMFILTERS && filtermode[i].bpp == filtermode[cv_filter.value].bpp) //Easy to swap? - blitfilter = filtermode[cv_filter.value].filter; // Swap with new filter - } -} - -FUNCINLINE static ATTRINLINE void FilterBlit(SDL_Surface *froSurface) -{ - if(froSurface && blitfilter && preSurface && f2xSurface) - { - SDL_Rect dstclp = {0,3,0,0}; - int lockedpre = 0, lockedf2x = 0, blitpre = 0; - blitpre = SDL_BlitSurface(froSurface,NULL,preSurface,&dstclp); - if(SDL_MUSTLOCK(preSurface)) lockedpre = SDL_LockSurface(preSurface); - if(SDL_MUSTLOCK(f2xSurface)) lockedf2x = SDL_LockSurface(f2xSurface); - if(lockedpre == 0 && preSurface->pixels && lockedf2x == 0 && f2xSurface->pixels && blitpre == 0) - { - blitfilter(FILTER(preSurface,f2xSurface)); - if(SDL_MUSTLOCK(preSurface)) SDL_UnlockSurface(preSurface); - if(SDL_MUSTLOCK(f2xSurface)) SDL_UnlockSurface(f2xSurface); - } - } - else - { - blitfilter = NULL; - if(preSurface) SDL_FreeSurface(preSurface); - preSurface = NULL; - if(f2xSurface) SDL_FreeSurface(f2xSurface); - f2xSurface = NULL; - } -} - -FUNCINLINE static ATTRINLINE int Setupf2x(int width, int height, int bpp) -{ - blitfilter = NULL; - if(preSurface) SDL_FreeSurface(preSurface); - preSurface = NULL; - if(f2xSurface) SDL_FreeSurface(f2xSurface); - f2xSurface = NULL; - if( !(width%2) && !(height%2) && width >= BASEVIDWIDTH*2 && height >= BASEVIDHEIGHT*2 && cv_filter.value - && cv_filter.value <= NUMFILTERS && filtermode[cv_filter.value].filter && filtermode[cv_filter.value].bpp) - { - int hwidth = width/2 + 6; - int heighth = height/2 + 6; - int hbpp = filtermode[cv_filter.value].bpp; - switch(hbpp) - { - case 8: - preSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,hwidth,heighth, 8,0x00000000,0x00000000,0x00000000,0x00); - f2xSurface = SDL_CreateRGBSurface(SDL_HWSURFACE, width,height , 8,0x00000000,0x00000000,0x00000000,0x00); - case 15: - preSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,hwidth,heighth,15,0x00007C00,0x000003E0,0x0000001F,0x00); - f2xSurface = SDL_CreateRGBSurface(SDL_HWSURFACE, width,height ,15,0x00007C00,0x000003E0,0x0000001F,0x00); - break; - case 16: - preSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,hwidth,heighth,16,0x0000F800,0x000007E0,0x0000001F,0x00); - f2xSurface = SDL_CreateRGBSurface(SDL_HWSURFACE, width,height ,16,0x0000F800,0x000007E0,0x0000001F,0x00); - break; - case 24: - preSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,hwidth,heighth,24,0x00FF0000,0x0000FF00,0x000000FF,0x00); - f2xSurface = SDL_CreateRGBSurface(SDL_HWSURFACE, width,height ,24,0x00FF0000,0x0000FF00,0x000000FF,0x00); - break; - case 32: - preSurface = SDL_CreateRGBSurface(SDL_SWSURFACE,hwidth,heighth,32,0x00FF0000,0x0000FF00,0x000000FF,0x00); - f2xSurface = SDL_CreateRGBSurface(SDL_HWSURFACE, width,height ,32,0x00FF0000,0x0000FF00,0x000000FF,0x00); - break; - default: - //I_Error("Filter help"); - break; - } - if(preSurface && f2xSurface) - { - blitfilter = filtermode[cv_filter.value].filter; - if(bpp < hbpp) bpp = hbpp; - } - else - { - if(preSurface) SDL_FreeSurface(preSurface); - preSurface = NULL; - if(f2xSurface) SDL_FreeSurface(f2xSurface); - f2xSurface = NULL; - } - } - return bpp; -} -#else - -#ifdef __GNUC__ // __attribute__ ((X)) -#if (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) -#define FUNCINLINE __attribute__((always_inline)) -#endif -#define FUNCNOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -#define inline __inline -#define ATTRNORETURN __declspec(noreturn) -#define ATTRINLINE __forceinline -#if _MSC_VER > 1200 -#define ATTRNOINLINE __declspec(noinline) -#endif -#endif - - - -#ifndef FUNCINLINE -#define FUNCINLINE -#endif -#ifndef FUNCNOINLINE -#define FUNCNOINLINE -#endif -#ifndef ATTRINLINE -#define ATTRINLINE inline -#endif -#ifndef ATTRNOINLINE -#define ATTRNOINLINE -#endif - -#endif - -#endif diff --git a/src/sdl12/filter/hq2x.c b/src/sdl12/filter/hq2x.c deleted file mode 100644 index acdbcb168..000000000 --- a/src/sdl12/filter/hq2x.c +++ /dev/null @@ -1,3125 +0,0 @@ -//hq2x filter demo program -//---------------------------------------------------------- -//Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) - -//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.1 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, write to the Free Software -//Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -#include "filters.h" -#include -#ifdef __GNUC__ -#include -#endif - - -#if (defined(__GNUC__) && defined(__i386__)) || (defined(_MSC_VER) && defined(_X86_)) -#define HQ2XASM -#endif - -#ifdef _MSC_VER -//#define HQ2XMMXASM -#endif - -static int LUT16to32[65536]; -static int RGBtoYUV[65536]; -#ifdef HQ2XMMXASM -#include "SDL_cpuinfo.h" -static SDL_bool hasMMX = 0; -const Sint64 reg_blank = 0; -const Sint64 const3 = 0x0000000300030003; -const Sint64 const5 = 0x0000000500050005; -const Sint64 const6 = 0x0000000600060006; -const Sint64 const14 = 0x0000000E000E000E; -const Sint64 tr3eshold = 0x0000000000300706; -#endif -static int YUV1, YUV2; -const int Ymask = 0x00FF0000; -const int Umask = 0x0000FF00; -const int Vmask = 0x000000FF; -const int trY = 0x00300000; -const int trU = 0x00000700; -const int trV = 0x00000006; - -FUNCINLINE static ATTRINLINE void Interp1(Uint8 * pc, int c1, int c2) -{ -#ifdef HQ2XASM - //*((int*)pc) = (c1*3+c2)/4; -#ifdef __GNUC__ - int c3 = c1; - __asm__("shl $2, %1; add %2, %1; sub %3, %1; shr $2, %1":"=d"(*((int*)pc)):"d"(c1),"r"(c2),"r"(c3):"memory"); -#else - __asm - { - mov eax, pc - mov edx, c1 - shl edx, 2 - add edx, c2 - sub edx, c1 - shr edx, 2 - mov [eax], edx - } -#endif -#else - *((int*)pc) = (c1*3+c2) >> 2; -#endif -} - -FUNCINLINE static ATTRINLINE void Interp2(Uint8 * pc, int c1, int c2, int c3) -{ -#ifdef HQ2XASM -// *((int*)pc) = (c1*2+c2+c3) >> 2; -#ifdef __GNUC__ - __asm__("shl $1, %1; add %2, %1; add %3, %1; shr $2, %1":"=d"(*((int*)pc)):"d"(c1),"r"(c2),"r"(c3):"memory"); -#else - __asm - { - mov eax, pc - mov edx, c1 - shl edx, 1 - add edx, c2 - add edx, c3 - shr edx, 2 - mov [eax], edx - } -#endif -#else - *((int*)pc) = (c1*2+c2+c3) >> 2; -#endif -} - -#if 0 -static inline void Interp5(Uint8 * pc, int c1, int c2) -{ -#ifdef HQ2XASM - //*((int*)pc) = (c1+c2)/2; -#ifdef __GNUC__ - __asm__("add %2, %1; shr $1, %1":"=d"(*((int*)pc)):"d"(c1),"r"(c2):"memory"); -#else - __asm - { - mov eax, pc - mov edx, c1 - add edx, c2 - shr edx, 1 - mov [eax], edx - } -#endif -#else - *((int*)pc) = (c1+c2) >> 1; -#endif -} -#endif - -FUNCINLINE static ATTRINLINE void Interp6(Uint8 * pc, int c1, int c2, int c3) -{ -#ifdef HQ2XMMXASM - //*((int*)pc) = (c1*5+c2*2+c3)/8; - if(hasMMX) -#ifdef __GNUC__ - __asm__("movd %1, %%mm1; movd %2, %%mm2, movd %3, %%mm3; punpcklbw $_reg_blank, %%mm1; punpcklbw $_reg_blank, %%mm2; punpcklbw $_reg_blank, %%mm3; pmullw $_const5, %%mm1; psllw $1, %%mm2; paddw %%mm3, %%mm1; paddw %%mm2, %%mm1; psrlw $3, %%mm1; packuswb $_reg_blank, %%mm1; movd %%mm1, %0" : "=r"(*((int*)pc)) : "r" (c1),"r" (c2),"r" (c3) : "memory"); -#else - __asm - { - mov eax, pc - movd mm1, c1 - movd mm2, c2 - movd mm3, c3 - punpcklbw mm1, reg_blank - punpcklbw mm2, reg_blank - punpcklbw mm3, reg_blank - pmullw mm1, const5 - psllw mm2, 1 - paddw mm1, mm3 - paddw mm1, mm2 - psrlw mm1, 3 - packuswb mm1, reg_blank - movd [eax], mm1 - } -#endif - else -#endif - *((int*)pc) = ((((c1 & 0x00FF00)*5 + (c2 & 0x00FF00)*2 + (c3 & 0x00FF00) ) & 0x0007F800) + - (((c1 & 0xFF00FF)*5 + (c2 & 0xFF00FF)*2 + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; -} - -FUNCINLINE static ATTRINLINE void Interp7(Uint8 * pc, int c1, int c2, int c3) -{ -#ifdef HQ2XMMXASM - //*((int*)pc) = (c1*6+c2+c3)/8; - if(hasMMX) -#ifdef __GNUC__ - __asm__("movd %1, %%mm1; movd %2, %%mm2, movd %3, %%mm3; punpcklbw $_reg_blank, %%mm1; punpcklbw $_reg_blank, %%mm2; punpcklbw $_reg_blank, %%mm3; pmull2 $_const6, %%mm1; padw %%mm3, %%mm2; paddw %%mm2, %%mm1; psrlw $3, %%mm1; packuswb $_reg_blank, %%mm1; movd %%mm1, %0 " : "=r" (*((int*)pc)): "r"(c1), "r"(c2), "r"(c3) : "memory"); -#else - __asm - { - mov eax, pc - movd mm1, c1 - movd mm2, c2 - movd mm3, c3 - punpcklbw mm1, reg_blank - punpcklbw mm2, reg_blank - punpcklbw mm3, reg_blank - pmullw mm1, const6 - paddw mm2, mm3 - paddw mm1, mm2 - psrlw mm1, 3 - packuswb mm1, reg_blank - movd [eax], mm1 - } -#endif - else -#endif - *((int*)pc) = ((((c1 & 0x00FF00)*6 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x0007F800) + - (((c1 & 0xFF00FF)*6 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3; -} - -FUNCINLINE static ATTRINLINE void Interp9(Uint8 * pc, int c1, int c2, int c3) -{ -#ifdef HQ2XMMXASM - //*((int*)pc) = (c1*2+(c2+c3)*3)/8; - if(hasMMX) -#ifdef __GNUC__ - __asm__("movd %1, %%mm1; movd %2, %%mm2, movd %3, %%mm3; punpcklbw $_reg_blank, %%mm1; punpcklbw $_reg_blank, %%mm2; punpcklbw $_reg_blank, %%mm3; psllw $1, %%mm1; paddw %%mm3, %%mm2; pmullw $_const3, %%mm2; padw %%mm2, %%mm1; psrlw $3, %%mm1; packuswb $_reg_blank, %%mm1; movd %%mm1, %0;" : "=r"(*((int*)pc)) : "r" (c1),"r" (c2),"r" (c3) : "memory"); -#else - __asm - { - mov eax, pc - movd mm1, c1 - movd mm2, c2 - movd mm3, c3 - punpcklbw mm1, reg_blank - punpcklbw mm2, reg_blank - punpcklbw mm3, reg_blank - psllw mm1, 1 - paddw mm2, mm3 - pmullw mm2, const3 - paddw mm1, mm2 - psrlw mm1, 3 - packuswb mm1, reg_blank - movd [eax], mm1 - } -#endif - else -#endif - *((int*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*3 ) & 0x0007F800) + - (((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*3 ) & 0x07F807F8)) >> 3; -} - -FUNCINLINE static ATTRINLINE void Interp10(Uint8 * pc, int c1, int c2, int c3) -{ -#ifdef HQ2XMMXASM - //*((int*)pc) = (c1*14+c2+c3)/16; - if(hasMMX) -#ifdef __GNUC__ - __asm__("movd %1, %%mm1; movd %2, %%mm2, movd %3, %%mm3; punpcklbw $_reg_blank, %%mm1; punpcklbw $_reg_blank, %%mm2; punpcklbw $_reg_blank, %%mm3; pmullw $_const14, %%mm1; paddw %%mm3, %%mm2; paddw %%mm2, %%mm1; psrlw $4, %%mm1; packuswb $_req_blank, %%mm1; movd %%mm1, %0;" : "=r"(*((int*)pc)) : "r" (c1),"r" (c2),"r" (c3) : "memory"); -#else - __asm - { - mov eax, pc - movd mm1, c1 - movd mm2, c2 - movd mm3, c3 - punpcklbw mm1, reg_blank - punpcklbw mm2, reg_blank - punpcklbw mm3, reg_blank - pmullw mm1, const14 - paddw mm2, mm3 - paddw mm1, mm2 - psrlw mm1, 4 - packuswb mm1, reg_blank - movd [eax], mm1 - } -#endif - else -#endif - *((int*)pc) = ((((c1 & 0x00FF00)*14 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x000FF000) + - (((c1 & 0xFF00FF)*14 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x0FF00FF0)) >> 4; -} -#define PIXEL00_0 *((int*)(pOut)) = c[5]; -#define PIXEL00_10 Interp1(pOut, c[5], c[1]); -#define PIXEL00_11 Interp1(pOut, c[5], c[4]); -#define PIXEL00_12 Interp1(pOut, c[5], c[2]); -#define PIXEL00_20 Interp2(pOut, c[5], c[4], c[2]); -#define PIXEL00_21 Interp2(pOut, c[5], c[1], c[2]); -#define PIXEL00_22 Interp2(pOut, c[5], c[1], c[4]); -#define PIXEL00_60 Interp6(pOut, c[5], c[2], c[4]); -#define PIXEL00_61 Interp6(pOut, c[5], c[4], c[2]); -#define PIXEL00_70 Interp7(pOut, c[5], c[4], c[2]); -#define PIXEL00_90 Interp9(pOut, c[5], c[4], c[2]); -#define PIXEL00_100 Interp10(pOut, c[5], c[4], c[2]); -#define PIXEL01_0 *((int*)(pOut+4)) = c[5]; -#define PIXEL01_10 Interp1(pOut+4, c[5], c[3]); -#define PIXEL01_11 Interp1(pOut+4, c[5], c[2]); -#define PIXEL01_12 Interp1(pOut+4, c[5], c[6]); -#define PIXEL01_20 Interp2(pOut+4, c[5], c[2], c[6]); -#define PIXEL01_21 Interp2(pOut+4, c[5], c[3], c[6]); -#define PIXEL01_22 Interp2(pOut+4, c[5], c[3], c[2]); -#define PIXEL01_60 Interp6(pOut+4, c[5], c[6], c[2]); -#define PIXEL01_61 Interp6(pOut+4, c[5], c[2], c[6]); -#define PIXEL01_70 Interp7(pOut+4, c[5], c[2], c[6]); -#define PIXEL01_90 Interp9(pOut+4, c[5], c[2], c[6]); -#define PIXEL01_100 Interp10(pOut+4, c[5], c[2], c[6]); -#define PIXEL10_0 *((int*)(pOut+BpL)) = c[5]; -#define PIXEL10_10 Interp1(pOut+BpL, c[5], c[7]); -#define PIXEL10_11 Interp1(pOut+BpL, c[5], c[8]); -#define PIXEL10_12 Interp1(pOut+BpL, c[5], c[4]); -#define PIXEL10_20 Interp2(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL10_21 Interp2(pOut+BpL, c[5], c[7], c[4]); -#define PIXEL10_22 Interp2(pOut+BpL, c[5], c[7], c[8]); -#define PIXEL10_60 Interp6(pOut+BpL, c[5], c[4], c[8]); -#define PIXEL10_61 Interp6(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL10_70 Interp7(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL10_90 Interp9(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL10_100 Interp10(pOut+BpL, c[5], c[8], c[4]); -#define PIXEL11_0 *((int*)(pOut+BpL+4)) = c[5]; -#define PIXEL11_10 Interp1(pOut+BpL+4, c[5], c[9]); -#define PIXEL11_11 Interp1(pOut+BpL+4, c[5], c[6]); -#define PIXEL11_12 Interp1(pOut+BpL+4, c[5], c[8]); -#define PIXEL11_20 Interp2(pOut+BpL+4, c[5], c[6], c[8]); -#define PIXEL11_21 Interp2(pOut+BpL+4, c[5], c[9], c[8]); -#define PIXEL11_22 Interp2(pOut+BpL+4, c[5], c[9], c[6]); -#define PIXEL11_60 Interp6(pOut+BpL+4, c[5], c[8], c[6]); -#define PIXEL11_61 Interp6(pOut+BpL+4, c[5], c[6], c[8]); -#define PIXEL11_70 Interp7(pOut+BpL+4, c[5], c[6], c[8]); -#define PIXEL11_90 Interp9(pOut+BpL+4, c[5], c[6], c[8]); -#define PIXEL11_100 Interp10(pOut+BpL+4, c[5], c[6], c[8]); - -#ifdef _MSC_VER -#pragma warning(disable: 4035) -#endif - -FUNCINLINE static ATTRINLINE int Diff(Uint32 w1, Uint32 w2) -{ -#ifdef HQ2XMMXASM - if(hasMMX) - { -#ifdef __GNUC__ - int diffresult = 0; - if(w1 != w2) - __asm__("movd %3+%1*4, %%mm1; movq %%mm1, %%mm5; movd %3+%2*4, %%mm2; psubusb %%mm2, %%mm1; psubusb %%mm5, %%mm2; por %%mm2, %%mm1; psubusb $_treshold, %%mm1; movd %%mm1, %0" : "=c" (diffresult):"d" (w1),"q" (w2),"c" (RGBtoYUV) : "memory"); - return diffresult; -#else - __asm - { - xor eax,eax - mov ebx,w1 - mov edx,w2 - cmp ebx,edx - je FIN - mov ecx,offset RGBtoYUV - movd mm1,[ecx + ebx*4] - movq mm5,mm1 - movd mm2,[ecx + edx*4] - psubusb mm1,mm2 - psubusb mm2,mm5 - por mm1,mm2 - psubusb mm1,treshold - movd eax,mm1 -FIN: - }// returns result in eax register -#endif - } - else -#endif - { - YUV1 = RGBtoYUV[w1]; - YUV2 = RGBtoYUV[w2]; - return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) || - ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || - ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ); - } -} - - -#ifdef _MSC_VER -#pragma warning(default: 4035) -#endif - - -static void hq2x_32( Uint8 * pIn, Uint8 * pOut, int Xres, int Yres, int BpL ) -{ - int i, j, k; - int prevline, nextline; - int w[10]; - int c[10]; - - // +----+----+----+ - // | | | | - // | w1 | w2 | w3 | - // +----+----+----+ - // | | | | - // | w4 | w5 | w6 | - // +----+----+----+ - // | | | | - // | w7 | w8 | w9 | - // +----+----+----+ - - for (j=0; j0) prevline = -Xres*2; else prevline = 0; - if (j0) - { - w[1] = *((Uint16*)(pIn + prevline - 2)); - w[4] = *((Uint16*)(pIn - 2)); - w[7] = *((Uint16*)(pIn + nextline - 2)); - } - else - { - w[1] = w[2]; - w[4] = w[5]; - w[7] = w[8]; - } - - if (i trY ) || - ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) || - ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) ) - pattern |= flag; - } - flag <<= 1; - } - } - - for (k=1; k<=9; k++) - c[k] = LUT16to32[w[k]]; - - switch (pattern) - { - case 0: - case 1: - case 4: - case 32: - case 128: - case 5: - case 132: - case 160: - case 33: - case 129: - case 36: - case 133: - case 164: - case 161: - case 37: - case 165: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_20 - PIXEL11_20 - break; - } - case 2: - case 34: - case 130: - case 162: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_20 - PIXEL11_20 - break; - } - case 16: - case 17: - case 48: - case 49: - { - PIXEL00_20 - PIXEL01_22 - PIXEL10_20 - PIXEL11_21 - break; - } - case 64: - case 65: - case 68: - case 69: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_21 - PIXEL11_22 - break; - } - case 8: - case 12: - case 136: - case 140: - { - PIXEL00_21 - PIXEL01_20 - PIXEL10_22 - PIXEL11_20 - break; - } - case 3: - case 35: - case 131: - case 163: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_20 - PIXEL11_20 - break; - } - case 6: - case 38: - case 134: - case 166: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - } - case 20: - case 21: - case 52: - case 53: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_21 - break; - } - case 144: - case 145: - case 176: - case 177: - { - PIXEL00_20 - PIXEL01_22 - PIXEL10_20 - PIXEL11_12 - break; - } - case 192: - case 193: - case 196: - case 197: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_21 - PIXEL11_11 - break; - } - case 96: - case 97: - case 100: - case 101: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_22 - break; - } - case 40: - case 44: - case 168: - case 172: - { - PIXEL00_21 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - } - case 9: - case 13: - case 137: - case 141: - { - PIXEL00_12 - PIXEL01_20 - PIXEL10_22 - PIXEL11_20 - break; - } - case 18: - case 50: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_20 - } - PIXEL10_20 - PIXEL11_21 - break; - } - case 80: - case 81: - { - PIXEL00_20 - PIXEL01_22 - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_20 - } - break; - } - case 72: - case 76: - { - PIXEL00_21 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 10: - case 138: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_22 - PIXEL11_20 - break; - } - case 66: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_21 - PIXEL11_22 - break; - } - case 24: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_22 - PIXEL11_21 - break; - } - case 7: - case 39: - case 135: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - } - case 148: - case 149: - case 180: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_12 - break; - } - case 224: - case 228: - case 225: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_11 - break; - } - case 41: - case 169: - case 45: - { - PIXEL00_12 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - } - case 22: - case 54: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_20 - PIXEL11_21 - break; - } - case 208: - case 209: - { - PIXEL00_20 - PIXEL01_22 - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 104: - case 108: - { - PIXEL00_21 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 11: - case 139: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_22 - PIXEL11_20 - break; - } - case 19: - case 51: - { - if (Diff(w[2], w[6])) - { - PIXEL00_11 - PIXEL01_10 - } - else - { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_20 - PIXEL11_21 - break; - } - case 146: - case 178: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - PIXEL11_12 - } - else - { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_20 - break; - } - case 84: - case 85: - { - PIXEL00_20 - if (Diff(w[6], w[8])) - { - PIXEL01_11 - PIXEL11_10 - } - else - { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_21 - break; - } - case 112: - case 113: - { - PIXEL00_20 - PIXEL01_22 - if (Diff(w[6], w[8])) - { - PIXEL10_12 - PIXEL11_10 - } - else - { - PIXEL10_61 - PIXEL11_90 - } - break; - } - case 200: - case 204: - { - PIXEL00_21 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - PIXEL11_11 - } - else - { - PIXEL10_90 - PIXEL11_60 - } - break; - } - case 73: - case 77: - { - if (Diff(w[8], w[4])) - { - PIXEL00_12 - PIXEL10_10 - } - else - { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_20 - PIXEL11_22 - break; - } - case 42: - case 170: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - PIXEL10_11 - } - else - { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_21 - PIXEL11_20 - break; - } - case 14: - case 142: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - PIXEL01_12 - } - else - { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_22 - PIXEL11_20 - break; - } - case 67: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_21 - PIXEL11_22 - break; - } - case 70: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_21 - PIXEL11_22 - break; - } - case 28: - { - PIXEL00_21 - PIXEL01_11 - PIXEL10_22 - PIXEL11_21 - break; - } - case 152: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_22 - PIXEL11_12 - break; - } - case 194: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_21 - PIXEL11_11 - break; - } - case 98: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_12 - PIXEL11_22 - break; - } - case 56: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_11 - PIXEL11_21 - break; - } - case 25: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_22 - PIXEL11_21 - break; - } - case 26: - case 31: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_21 - break; - } - case 82: - case 214: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 88: - case 248: - { - PIXEL00_21 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 74: - case 107: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 27: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_22 - PIXEL11_21 - break; - } - case 86: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_21 - PIXEL11_10 - break; - } - case 216: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 106: - { - PIXEL00_10 - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 30: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_21 - break; - } - case 210: - { - PIXEL00_22 - PIXEL01_10 - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 120: - { - PIXEL00_21 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 75: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_10 - PIXEL11_22 - break; - } - case 29: - { - PIXEL00_12 - PIXEL01_11 - PIXEL10_22 - PIXEL11_21 - break; - } - case 198: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_21 - PIXEL11_11 - break; - } - case 184: - { - PIXEL00_21 - PIXEL01_22 - PIXEL10_11 - PIXEL11_12 - break; - } - case 99: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_12 - PIXEL11_22 - break; - } - case 57: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_11 - PIXEL11_21 - break; - } - case 71: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_21 - PIXEL11_22 - break; - } - case 156: - { - PIXEL00_21 - PIXEL01_11 - PIXEL10_22 - PIXEL11_12 - break; - } - case 226: - { - PIXEL00_22 - PIXEL01_21 - PIXEL10_12 - PIXEL11_11 - break; - } - case 60: - { - PIXEL00_21 - PIXEL01_11 - PIXEL10_11 - PIXEL11_21 - break; - } - case 195: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_21 - PIXEL11_11 - break; - } - case 102: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_12 - PIXEL11_22 - break; - } - case 153: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_22 - PIXEL11_12 - break; - } - case 58: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_21 - break; - } - case 83: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 92: - { - PIXEL00_21 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 202: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_11 - break; - } - case 78: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_22 - break; - } - case 154: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_22 - PIXEL11_12 - break; - } - case 114: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 89: - { - PIXEL00_12 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 90: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 55: - case 23: - { - if (Diff(w[2], w[6])) - { - PIXEL00_11 - PIXEL01_0 - } - else - { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_20 - PIXEL11_21 - break; - } - case 182: - case 150: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - PIXEL11_12 - } - else - { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_20 - break; - } - case 213: - case 212: - { - PIXEL00_20 - if (Diff(w[6], w[8])) - { - PIXEL01_11 - PIXEL11_0 - } - else - { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_21 - break; - } - case 241: - case 240: - { - PIXEL00_20 - PIXEL01_22 - if (Diff(w[6], w[8])) - { - PIXEL10_12 - PIXEL11_0 - } - else - { - PIXEL10_61 - PIXEL11_90 - } - break; - } - case 236: - case 232: - { - PIXEL00_21 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - PIXEL11_11 - } - else - { - PIXEL10_90 - PIXEL11_60 - } - break; - } - case 109: - case 105: - { - if (Diff(w[8], w[4])) - { - PIXEL00_12 - PIXEL10_0 - } - else - { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_20 - PIXEL11_22 - break; - } - case 171: - case 43: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - PIXEL10_11 - } - else - { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_21 - PIXEL11_20 - break; - } - case 143: - case 15: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - PIXEL01_12 - } - else - { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_22 - PIXEL11_20 - break; - } - case 124: - { - PIXEL00_21 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 203: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - PIXEL10_10 - PIXEL11_11 - break; - } - case 62: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_11 - PIXEL11_21 - break; - } - case 211: - { - PIXEL00_11 - PIXEL01_10 - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 118: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_12 - PIXEL11_10 - break; - } - case 217: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 110: - { - PIXEL00_10 - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 155: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_22 - PIXEL11_12 - break; - } - case 188: - { - PIXEL00_21 - PIXEL01_11 - PIXEL10_11 - PIXEL11_12 - break; - } - case 185: - { - PIXEL00_12 - PIXEL01_22 - PIXEL10_11 - PIXEL11_12 - break; - } - case 61: - { - PIXEL00_12 - PIXEL01_11 - PIXEL10_11 - PIXEL11_21 - break; - } - case 157: - { - PIXEL00_12 - PIXEL01_11 - PIXEL10_22 - PIXEL11_12 - break; - } - case 103: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_12 - PIXEL11_22 - break; - } - case 227: - { - PIXEL00_11 - PIXEL01_21 - PIXEL10_12 - PIXEL11_11 - break; - } - case 230: - { - PIXEL00_22 - PIXEL01_12 - PIXEL10_12 - PIXEL11_11 - break; - } - case 199: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_21 - PIXEL11_11 - break; - } - case 220: - { - PIXEL00_21 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 158: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_22 - PIXEL11_12 - break; - } - case 234: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_11 - break; - } - case 242: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 59: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_21 - break; - } - case 121: - { - PIXEL00_12 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 87: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 79: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_22 - break; - } - case 122: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 94: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 218: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 91: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 229: - { - PIXEL00_20 - PIXEL01_20 - PIXEL10_12 - PIXEL11_11 - break; - } - case 167: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_20 - PIXEL11_20 - break; - } - case 173: - { - PIXEL00_12 - PIXEL01_20 - PIXEL10_11 - PIXEL11_20 - break; - } - case 181: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_20 - PIXEL11_12 - break; - } - case 186: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_11 - PIXEL11_12 - break; - } - case 115: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 93: - { - PIXEL00_12 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 206: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_11 - break; - } - case 205: - case 201: - { - PIXEL00_12 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_10 - } - else - { - PIXEL10_70 - } - PIXEL11_11 - break; - } - case 174: - case 46: - { - if (Diff(w[4], w[2])) - { - PIXEL00_10 - } - else - { - PIXEL00_70 - } - PIXEL01_12 - PIXEL10_11 - PIXEL11_20 - break; - } - case 179: - case 147: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_10 - } - else - { - PIXEL01_70 - } - PIXEL10_20 - PIXEL11_12 - break; - } - case 117: - case 116: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_10 - } - else - { - PIXEL11_70 - } - break; - } - case 189: - { - PIXEL00_12 - PIXEL01_11 - PIXEL10_11 - PIXEL11_12 - break; - } - case 231: - { - PIXEL00_11 - PIXEL01_12 - PIXEL10_12 - PIXEL11_11 - break; - } - case 126: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 219: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 125: - { - if (Diff(w[8], w[4])) - { - PIXEL00_12 - PIXEL10_0 - } - else - { - PIXEL00_61 - PIXEL10_90 - } - PIXEL01_11 - PIXEL11_10 - break; - } - case 221: - { - PIXEL00_12 - if (Diff(w[6], w[8])) - { - PIXEL01_11 - PIXEL11_0 - } - else - { - PIXEL01_60 - PIXEL11_90 - } - PIXEL10_10 - break; - } - case 207: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - PIXEL01_12 - } - else - { - PIXEL00_90 - PIXEL01_61 - } - PIXEL10_10 - PIXEL11_11 - break; - } - case 238: - { - PIXEL00_10 - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - PIXEL11_11 - } - else - { - PIXEL10_90 - PIXEL11_60 - } - break; - } - case 190: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - PIXEL11_12 - } - else - { - PIXEL01_90 - PIXEL11_61 - } - PIXEL10_11 - break; - } - case 187: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - PIXEL10_11 - } - else - { - PIXEL00_90 - PIXEL10_60 - } - PIXEL01_10 - PIXEL11_12 - break; - } - case 243: - { - PIXEL00_11 - PIXEL01_10 - if (Diff(w[6], w[8])) - { - PIXEL10_12 - PIXEL11_0 - } - else - { - PIXEL10_61 - PIXEL11_90 - } - break; - } - case 119: - { - if (Diff(w[2], w[6])) - { - PIXEL00_11 - PIXEL01_0 - } - else - { - PIXEL00_60 - PIXEL01_90 - } - PIXEL10_12 - PIXEL11_10 - break; - } - case 237: - case 233: - { - PIXEL00_12 - PIXEL01_20 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - PIXEL11_11 - break; - } - case 175: - case 47: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - PIXEL01_12 - PIXEL10_11 - PIXEL11_20 - break; - } - case 183: - case 151: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_20 - PIXEL11_12 - break; - } - case 245: - case 244: - { - PIXEL00_20 - PIXEL01_11 - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 250: - { - PIXEL00_10 - PIXEL01_10 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 123: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 95: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_10 - PIXEL11_10 - break; - } - case 222: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 252: - { - PIXEL00_21 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 249: - { - PIXEL00_12 - PIXEL01_22 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 235: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_21 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - PIXEL11_11 - break; - } - case 111: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_22 - break; - } - case 63: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_11 - PIXEL11_21 - break; - } - case 159: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_22 - PIXEL11_12 - break; - } - case 215: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_21 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 246: - { - PIXEL00_22 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 254: - { - PIXEL00_10 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 253: - { - PIXEL00_12 - PIXEL01_11 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 251: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - PIXEL01_10 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 239: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - PIXEL01_12 - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - PIXEL11_11 - break; - } - case 127: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_20 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_20 - } - PIXEL11_10 - break; - } - case 191: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_11 - PIXEL11_12 - break; - } - case 223: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_20 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_10 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_20 - } - break; - } - case 247: - { - PIXEL00_11 - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - PIXEL10_12 - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - case 255: - { - if (Diff(w[4], w[2])) - { - PIXEL00_0 - } - else - { - PIXEL00_100 - } - if (Diff(w[2], w[6])) - { - PIXEL01_0 - } - else - { - PIXEL01_100 - } - if (Diff(w[8], w[4])) - { - PIXEL10_0 - } - else - { - PIXEL10_100 - } - if (Diff(w[6], w[8])) - { - PIXEL11_0 - } - else - { - PIXEL11_100 - } - break; - } - } - pIn+=2; - pOut+=8; - } - pOut+=BpL; - } -} - -FUNCINLINE static ATTRINLINE void InitLUTs(void) -{ - int i, j, k, r, g, b, Y, u, v; - -#ifdef HQ2XMMXASM - hasMMX = SDL_HasMMX(); -#endif - - for (i=0; i<65536; i++) - LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3); - - for (i=0; i<32; i++) - for (j=0; j<64; j++) - for (k=0; k<32; k++) - { - r = i << 3; - g = j << 2; - b = k << 3; - Y = (r + g + b) >> 2; - u = 128 + ((r - b) >> 2); - v = 128 + ((-r + 2*g -b)>>3); - RGBtoYUV[ (i << 11) + (j << 5) + k ] = (Y<<16) + (u<<8) + v; - } -} - -void filter_hq2x(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, Uint32 dstPitch, int width, int height) -{ - static Uint8 doneLUT = 1; - (void)srcPitch; - if(doneLUT) InitLUTs(); - else doneLUT = 0; - hq2x_32( srcPtr, dstPtr, width, height, dstPitch ); -} diff --git a/src/sdl12/filter/hq2x.h b/src/sdl12/filter/hq2x.h deleted file mode 100644 index 49c0b2687..000000000 --- a/src/sdl12/filter/hq2x.h +++ /dev/null @@ -1,1824 +0,0 @@ -case 0 : -case 1 : -case 4 : -case 5 : -case 32 : -case 33 : -case 36 : -case 37 : -case 128 : -case 129 : -case 132 : -case 133 : -case 160 : -case 161 : -case 164 : -case 165 : -{ - P0 = I211(4, 1, 3); - P1 = I211(4, 1, 5); - P2 = I211(4, 3, 7); - P3 = I211(4, 5, 7); -} break; -case 2 : -case 34 : -case 130 : -case 162 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I211(4, 3, 7); - P3 = I211(4, 5, 7); -} break; -case 3 : -case 35 : -case 131 : -case 163 : -{ - P0 = I31(4, 3); - P1 = I31(4, 2); - P2 = I211(4, 3, 7); - P3 = I211(4, 5, 7); -} break; -case 6 : -case 38 : -case 134 : -case 166 : -{ - P0 = I31(4, 0); - P1 = I31(4, 5); - P2 = I211(4, 3, 7); - P3 = I211(4, 5, 7); -} break; -case 7 : -case 39 : -case 135 : -case 167 : -{ - P0 = I31(4, 3); - P1 = I31(4, 5); - P2 = I211(4, 3, 7); - P3 = I211(4, 5, 7); -} break; -case 8 : -case 12 : -case 136 : -case 140 : -{ - P0 = I31(4, 0); - P1 = I211(4, 1, 5); - P2 = I31(4, 6); - P3 = I211(4, 5, 7); -} break; -case 9 : -case 13 : -case 137 : -case 141 : -{ - P0 = I31(4, 1); - P1 = I211(4, 1, 5); - P2 = I31(4, 6); - P3 = I211(4, 5, 7); -} break; -case 10 : -case 138 : -{ - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I211(4, 5, 7); - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 11 : -case 139 : -{ - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I211(4, 5, 7); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 14 : -case 142 : -{ - P2 = I31(4, 6); - P3 = I211(4, 5, 7); - if (MUL) { - P0 = I31(4, 0); - P1 = I31(4, 5); - } else { - P0 = I332(1, 3, 4); - P1 = I521(4, 1, 5); - } -} break; -case 15 : -case 143 : -{ - P2 = I31(4, 6); - P3 = I211(4, 5, 7); - if (MUL) { - P0 = IC(4); - P1 = I31(4, 5); - } else { - P0 = I332(1, 3, 4); - P1 = I521(4, 1, 5); - } -} break; -case 16 : -case 17 : -case 48 : -case 49 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 2); - P2 = I211(4, 3, 7); - P3 = I31(4, 8); -} break; -case 18 : -case 50 : -{ - P0 = I31(4, 0); - P2 = I211(4, 3, 7); - P3 = I31(4, 8); - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 19 : -case 51 : -{ - P2 = I211(4, 3, 7); - P3 = I31(4, 8); - if (MUR) { - P0 = I31(4, 3); - P1 = I31(4, 2); - } else { - P0 = I521(4, 1, 3); - P1 = I332(1, 5, 4); - } -} break; -case 20 : -case 21 : -case 52 : -case 53 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 1); - P2 = I211(4, 3, 7); - P3 = I31(4, 8); -} break; -case 22 : -case 54 : -{ - P0 = I31(4, 0); - P2 = I211(4, 3, 7); - P3 = I31(4, 8); - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 23 : -case 55 : -{ - P2 = I211(4, 3, 7); - P3 = I31(4, 8); - if (MUR) { - P0 = I31(4, 3); - P1 = IC(4); - } else { - P0 = I521(4, 1, 3); - P1 = I332(1, 5, 4); - } -} break; -case 24 : -case 66 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 8); -} break; -case 25 : -{ - P0 = I31(4, 1); - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 8); -} break; -case 26 : -case 31 : -case 95 : -{ - P2 = I31(4, 6); - P3 = I31(4, 8); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 27 : -case 75 : -{ - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 8); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 28 : -{ - P0 = I31(4, 0); - P1 = I31(4, 1); - P2 = I31(4, 6); - P3 = I31(4, 8); -} break; -case 29 : -{ - P0 = I31(4, 1); - P1 = I31(4, 1); - P2 = I31(4, 6); - P3 = I31(4, 8); -} break; -case 30 : -case 86 : -{ - P0 = I31(4, 0); - P2 = I31(4, 6); - P3 = I31(4, 8); - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 40 : -case 44 : -case 168 : -case 172 : -{ - P0 = I31(4, 0); - P1 = I211(4, 1, 5); - P2 = I31(4, 7); - P3 = I211(4, 5, 7); -} break; -case 41 : -case 45 : -case 169 : -case 173 : -{ - P0 = I31(4, 1); - P1 = I211(4, 1, 5); - P2 = I31(4, 7); - P3 = I211(4, 5, 7); -} break; -case 42 : -case 170 : -{ - P1 = I31(4, 2); - P3 = I211(4, 5, 7); - if (MUL) { - P0 = I31(4, 0); - P2 = I31(4, 7); - } else { - P0 = I332(1, 3, 4); - P2 = I521(4, 3, 7); - } -} break; -case 43 : -case 171 : -{ - P1 = I31(4, 2); - P3 = I211(4, 5, 7); - if (MUL) { - P0 = IC(4); - P2 = I31(4, 7); - } else { - P0 = I332(1, 3, 4); - P2 = I521(4, 3, 7); - } -} break; -case 46 : -case 174 : -{ - P1 = I31(4, 5); - P2 = I31(4, 7); - P3 = I211(4, 5, 7); - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } -} break; -case 47 : -case 175 : -{ - P1 = I31(4, 5); - P2 = I31(4, 7); - P3 = I211(4, 5, 7); - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } -} break; -case 56 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I31(4, 7); - P3 = I31(4, 8); -} break; -case 57 : -{ - P0 = I31(4, 1); - P1 = I31(4, 2); - P2 = I31(4, 7); - P3 = I31(4, 8); -} break; -case 58 : -{ - P2 = I31(4, 7); - P3 = I31(4, 8); - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 59 : -{ - P2 = I31(4, 7); - P3 = I31(4, 8); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 60 : -{ - P0 = I31(4, 0); - P1 = I31(4, 1); - P2 = I31(4, 7); - P3 = I31(4, 8); -} break; -case 61 : -{ - P0 = I31(4, 1); - P1 = I31(4, 1); - P2 = I31(4, 7); - P3 = I31(4, 8); -} break; -case 62 : -{ - P0 = I31(4, 0); - P2 = I31(4, 7); - P3 = I31(4, 8); - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 63 : -{ - P2 = I31(4, 7); - P3 = I31(4, 8); - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 64 : -case 65 : -case 68 : -case 69 : -{ - P0 = I211(4, 1, 3); - P1 = I211(4, 1, 5); - P2 = I31(4, 6); - P3 = I31(4, 8); -} break; -case 67 : -{ - P0 = I31(4, 3); - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 8); -} break; -case 70 : -{ - P0 = I31(4, 0); - P1 = I31(4, 5); - P2 = I31(4, 6); - P3 = I31(4, 8); -} break; -case 71 : -{ - P0 = I31(4, 3); - P1 = I31(4, 5); - P2 = I31(4, 6); - P3 = I31(4, 8); -} break; -case 72 : -case 76 : -{ - P0 = I31(4, 0); - P1 = I211(4, 1, 5); - P3 = I31(4, 8); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I211(4, 3, 7); - } -} break; -case 73 : -case 77 : -{ - P1 = I211(4, 1, 5); - P3 = I31(4, 8); - if (MDL) { - P0 = I31(4, 1); - P2 = I31(4, 6); - } else { - P0 = I521(4, 3, 1); - P2 = I332(3, 7, 4); - } -} break; -case 74 : -case 107 : -case 123 : -{ - P1 = I31(4, 2); - P3 = I31(4, 8); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 78 : -{ - P1 = I31(4, 5); - P3 = I31(4, 8); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } -} break; -case 79 : -{ - P1 = I31(4, 5); - P3 = I31(4, 8); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 80 : -case 81 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 2); - P2 = I31(4, 6); - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I211(4, 5, 7); - } -} break; -case 82 : -case 214 : -case 222 : -{ - P0 = I31(4, 0); - P2 = I31(4, 6); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 83 : -{ - P0 = I31(4, 3); - P2 = I31(4, 6); - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 84 : -case 85 : -{ - P0 = I211(4, 1, 3); - P2 = I31(4, 6); - if (MDR) { - P1 = I31(4, 1); - P3 = I31(4, 8); - } else { - P1 = I521(4, 5, 1); - P3 = I332(5, 7, 4); - } -} break; -case 87 : -{ - P0 = I31(4, 3); - P2 = I31(4, 6); - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 88 : -case 248 : -case 250 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } -} break; -case 89 : -{ - P0 = I31(4, 1); - P1 = I31(4, 2); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } -} break; -case 90 : -{ - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 91 : -{ - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 92 : -{ - P0 = I31(4, 0); - P1 = I31(4, 1); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } -} break; -case 93 : -{ - P0 = I31(4, 1); - P1 = I31(4, 1); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } -} break; -case 94 : -{ - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 96 : -case 97 : -case 100 : -case 101 : -{ - P0 = I211(4, 1, 3); - P1 = I211(4, 1, 5); - P2 = I31(4, 3); - P3 = I31(4, 8); -} break; -case 98 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I31(4, 3); - P3 = I31(4, 8); -} break; -case 99 : -{ - P0 = I31(4, 3); - P1 = I31(4, 2); - P2 = I31(4, 3); - P3 = I31(4, 8); -} break; -case 102 : -{ - P0 = I31(4, 0); - P1 = I31(4, 5); - P2 = I31(4, 3); - P3 = I31(4, 8); -} break; -case 103 : -{ - P0 = I31(4, 3); - P1 = I31(4, 5); - P2 = I31(4, 3); - P3 = I31(4, 8); -} break; -case 104 : -case 108 : -{ - P0 = I31(4, 0); - P1 = I211(4, 1, 5); - P3 = I31(4, 8); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } -} break; -case 105 : -case 109 : -{ - P1 = I211(4, 1, 5); - P3 = I31(4, 8); - if (MDL) { - P0 = I31(4, 1); - P2 = IC(4); - } else { - P0 = I521(4, 3, 1); - P2 = I332(3, 7, 4); - } -} break; -case 106 : -case 120 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P3 = I31(4, 8); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } -} break; -case 110 : -{ - P0 = I31(4, 0); - P1 = I31(4, 5); - P3 = I31(4, 8); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } -} break; -case 111 : -{ - P1 = I31(4, 5); - P3 = I31(4, 8); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } -} break; -case 112 : -case 113 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 2); - if (MDR) { - P2 = I31(4, 3); - P3 = I31(4, 8); - } else { - P2 = I521(4, 7, 3); - P3 = I332(5, 7, 4); - } -} break; -case 114 : -{ - P0 = I31(4, 0); - P2 = I31(4, 3); - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 115 : -{ - P0 = I31(4, 3); - P2 = I31(4, 3); - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 116 : -case 117 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 1); - P2 = I31(4, 3); - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } -} break; -case 118 : -{ - P0 = I31(4, 0); - P2 = I31(4, 3); - P3 = I31(4, 8); - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 119 : -{ - P2 = I31(4, 3); - P3 = I31(4, 8); - if (MUR) { - P0 = I31(4, 3); - P1 = IC(4); - } else { - P0 = I521(4, 1, 3); - P1 = I332(1, 5, 4); - } -} break; -case 121 : -{ - P0 = I31(4, 1); - P1 = I31(4, 2); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } -} break; -case 122 : -{ - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MDR) { - P3 = I31(4, 8); - } else { - P3 = I611(4, 5, 7); - } - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 124 : -{ - P0 = I31(4, 0); - P1 = I31(4, 1); - P3 = I31(4, 8); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } -} break; -case 125 : -{ - P1 = I31(4, 1); - P3 = I31(4, 8); - if (MDL) { - P0 = I31(4, 1); - P2 = IC(4); - } else { - P0 = I521(4, 3, 1); - P2 = I332(3, 7, 4); - } -} break; -case 126 : -{ - P0 = I31(4, 0); - P3 = I31(4, 8); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 127 : -{ - P3 = I31(4, 8); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 144 : -case 145 : -case 176 : -case 177 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 2); - P2 = I211(4, 3, 7); - P3 = I31(4, 7); -} break; -case 146 : -case 178 : -{ - P0 = I31(4, 0); - P2 = I211(4, 3, 7); - if (MUR) { - P1 = I31(4, 2); - P3 = I31(4, 7); - } else { - P1 = I332(1, 5, 4); - P3 = I521(4, 5, 7); - } -} break; -case 147 : -case 179 : -{ - P0 = I31(4, 3); - P2 = I211(4, 3, 7); - P3 = I31(4, 7); - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 148 : -case 149 : -case 180 : -case 181 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 1); - P2 = I211(4, 3, 7); - P3 = I31(4, 7); -} break; -case 150 : -case 182 : -{ - P0 = I31(4, 0); - P2 = I211(4, 3, 7); - if (MUR) { - P1 = IC(4); - P3 = I31(4, 7); - } else { - P1 = I332(1, 5, 4); - P3 = I521(4, 5, 7); - } -} break; -case 151 : -case 183 : -{ - P0 = I31(4, 3); - P2 = I211(4, 3, 7); - P3 = I31(4, 7); - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 152 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 7); -} break; -case 153 : -{ - P0 = I31(4, 1); - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 7); -} break; -case 154 : -{ - P2 = I31(4, 6); - P3 = I31(4, 7); - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 155 : -{ - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 7); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 156 : -{ - P0 = I31(4, 0); - P1 = I31(4, 1); - P2 = I31(4, 6); - P3 = I31(4, 7); -} break; -case 157 : -{ - P0 = I31(4, 1); - P1 = I31(4, 1); - P2 = I31(4, 6); - P3 = I31(4, 7); -} break; -case 158 : -{ - P2 = I31(4, 6); - P3 = I31(4, 7); - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 159 : -{ - P2 = I31(4, 6); - P3 = I31(4, 7); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 184 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I31(4, 7); - P3 = I31(4, 7); -} break; -case 185 : -{ - P0 = I31(4, 1); - P1 = I31(4, 2); - P2 = I31(4, 7); - P3 = I31(4, 7); -} break; -case 186 : -{ - P2 = I31(4, 7); - P3 = I31(4, 7); - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 187 : -{ - P1 = I31(4, 2); - P3 = I31(4, 7); - if (MUL) { - P0 = IC(4); - P2 = I31(4, 7); - } else { - P0 = I332(1, 3, 4); - P2 = I521(4, 3, 7); - } -} break; -case 188 : -{ - P0 = I31(4, 0); - P1 = I31(4, 1); - P2 = I31(4, 7); - P3 = I31(4, 7); -} break; -case 189 : -{ - P0 = I31(4, 1); - P1 = I31(4, 1); - P2 = I31(4, 7); - P3 = I31(4, 7); -} break; -case 190 : -{ - P0 = I31(4, 0); - P2 = I31(4, 7); - if (MUR) { - P1 = IC(4); - P3 = I31(4, 7); - } else { - P1 = I332(1, 5, 4); - P3 = I521(4, 5, 7); - } -} break; -case 191 : -{ - P2 = I31(4, 7); - P3 = I31(4, 7); - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 192 : -case 193 : -case 196 : -case 197 : -{ - P0 = I211(4, 1, 3); - P1 = I211(4, 1, 5); - P2 = I31(4, 6); - P3 = I31(4, 5); -} break; -case 194 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 5); -} break; -case 195 : -{ - P0 = I31(4, 3); - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 5); -} break; -case 198 : -{ - P0 = I31(4, 0); - P1 = I31(4, 5); - P2 = I31(4, 6); - P3 = I31(4, 5); -} break; -case 199 : -{ - P0 = I31(4, 3); - P1 = I31(4, 5); - P2 = I31(4, 6); - P3 = I31(4, 5); -} break; -case 200 : -case 204 : -{ - P0 = I31(4, 0); - P1 = I211(4, 1, 5); - if (MDL) { - P2 = I31(4, 6); - P3 = I31(4, 5); - } else { - P2 = I332(3, 7, 4); - P3 = I521(4, 7, 5); - } -} break; -case 201 : -case 205 : -{ - P0 = I31(4, 1); - P1 = I211(4, 1, 5); - P3 = I31(4, 5); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } -} break; -case 202 : -{ - P1 = I31(4, 2); - P3 = I31(4, 5); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } -} break; -case 203 : -{ - P1 = I31(4, 2); - P2 = I31(4, 6); - P3 = I31(4, 5); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 206 : -{ - P1 = I31(4, 5); - P3 = I31(4, 5); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } -} break; -case 207 : -{ - P2 = I31(4, 6); - P3 = I31(4, 5); - if (MUL) { - P0 = IC(4); - P1 = I31(4, 5); - } else { - P0 = I332(1, 3, 4); - P1 = I521(4, 1, 5); - } -} break; -case 208 : -case 209 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 2); - P2 = I31(4, 6); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } -} break; -case 210 : -case 216 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I31(4, 6); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } -} break; -case 211 : -{ - P0 = I31(4, 3); - P1 = I31(4, 2); - P2 = I31(4, 6); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } -} break; -case 212 : -case 213 : -{ - P0 = I211(4, 1, 3); - P2 = I31(4, 6); - if (MDR) { - P1 = I31(4, 1); - P3 = IC(4); - } else { - P1 = I521(4, 5, 1); - P3 = I332(5, 7, 4); - } -} break; -case 215 : -{ - P0 = I31(4, 3); - P2 = I31(4, 6); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 217 : -{ - P0 = I31(4, 1); - P1 = I31(4, 2); - P2 = I31(4, 6); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } -} break; -case 218 : -{ - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 219 : -{ - P1 = I31(4, 2); - P2 = I31(4, 6); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 220 : -{ - P0 = I31(4, 0); - P1 = I31(4, 1); - if (MDL) { - P2 = I31(4, 6); - } else { - P2 = I611(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } -} break; -case 221 : -{ - P0 = I31(4, 1); - P2 = I31(4, 6); - if (MDR) { - P1 = I31(4, 1); - P3 = IC(4); - } else { - P1 = I521(4, 5, 1); - P3 = I332(5, 7, 4); - } -} break; -case 223 : -{ - P2 = I31(4, 6); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 224 : -case 225 : -case 228 : -case 229 : -{ - P0 = I211(4, 1, 3); - P1 = I211(4, 1, 5); - P2 = I31(4, 3); - P3 = I31(4, 5); -} break; -case 226 : -{ - P0 = I31(4, 0); - P1 = I31(4, 2); - P2 = I31(4, 3); - P3 = I31(4, 5); -} break; -case 227 : -{ - P0 = I31(4, 3); - P1 = I31(4, 2); - P2 = I31(4, 3); - P3 = I31(4, 5); -} break; -case 230 : -{ - P0 = I31(4, 0); - P1 = I31(4, 5); - P2 = I31(4, 3); - P3 = I31(4, 5); -} break; -case 231 : -{ - P0 = I31(4, 3); - P1 = I31(4, 5); - P2 = I31(4, 3); - P3 = I31(4, 5); -} break; -case 232 : -case 236 : -{ - P0 = I31(4, 0); - P1 = I211(4, 1, 5); - if (MDL) { - P2 = IC(4); - P3 = I31(4, 5); - } else { - P2 = I332(3, 7, 4); - P3 = I521(4, 7, 5); - } -} break; -case 233 : -case 237 : -{ - P0 = I31(4, 1); - P1 = I211(4, 1, 5); - P3 = I31(4, 5); - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } -} break; -case 234 : -{ - P1 = I31(4, 2); - P3 = I31(4, 5); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MUL) { - P0 = I31(4, 0); - } else { - P0 = I611(4, 1, 3); - } -} break; -case 235 : -{ - P1 = I31(4, 2); - P3 = I31(4, 5); - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 238 : -{ - P0 = I31(4, 0); - P1 = I31(4, 5); - if (MDL) { - P2 = IC(4); - P3 = I31(4, 5); - } else { - P2 = I332(3, 7, 4); - P3 = I521(4, 7, 5); - } -} break; -case 239 : -{ - P1 = I31(4, 5); - P3 = I31(4, 5); - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } -} break; -case 240 : -case 241 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 2); - if (MDR) { - P2 = I31(4, 3); - P3 = IC(4); - } else { - P2 = I521(4, 7, 3); - P3 = I332(5, 7, 4); - } -} break; -case 242 : -{ - P0 = I31(4, 0); - P2 = I31(4, 3); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } - if (MUR) { - P1 = I31(4, 2); - } else { - P1 = I611(4, 1, 5); - } -} break; -case 243 : -{ - P0 = I31(4, 3); - P1 = I31(4, 2); - if (MDR) { - P2 = I31(4, 3); - P3 = IC(4); - } else { - P2 = I521(4, 7, 3); - P3 = I332(5, 7, 4); - } -} break; -case 244 : -case 245 : -{ - P0 = I211(4, 1, 3); - P1 = I31(4, 1); - P2 = I31(4, 3); - if (MDR) { - P3 = IC(4); - } else { - P3 = I1411(4, 5, 7); - } -} break; -case 246 : -{ - P0 = I31(4, 0); - P2 = I31(4, 3); - if (MDR) { - P3 = IC(4); - } else { - P3 = I1411(4, 5, 7); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 247 : -{ - P0 = I31(4, 3); - P2 = I31(4, 3); - if (MDR) { - P3 = IC(4); - } else { - P3 = I1411(4, 5, 7); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 249 : -{ - P0 = I31(4, 1); - P1 = I31(4, 2); - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } -} break; -case 251 : -{ - P1 = I31(4, 2); - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 252 : -{ - P0 = I31(4, 0); - P1 = I31(4, 1); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I1411(4, 5, 7); - } -} break; -case 253 : -{ - P0 = I31(4, 1); - P1 = I31(4, 1); - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I1411(4, 5, 7); - } -} break; -case 254 : -{ - P0 = I31(4, 0); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I1411(4, 5, 7); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 255 : -{ - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I1411(4, 5, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; diff --git a/src/sdl12/filter/interp.h b/src/sdl12/filter/interp.h deleted file mode 100644 index e994387fb..000000000 --- a/src/sdl12/filter/interp.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * This file is part of the Advance project. - * - * Copyright (C) 2003 Andrea Mazzoleni - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * In addition, as a special exception, Andrea Mazzoleni - * gives permission to link the code of this program with - * the MAME library (or with modified versions of MAME that use the - * same license as MAME), and distribute linked combinations including - * the two. You must obey the GNU General Public License in all - * respects for all of the code used other than MAME. If you modify - * this file, you may extend this exception to your version of the - * file, but you are not obligated to do so. If you do not wish to - * do so, delete this exception statement from your version. - */ - -#ifndef __INTERP_H -#define __INTERP_H - -/***************************************************************************/ -/* Basic types */ - -/***************************************************************************/ -/* interpolation */ - -static Uint32 interp_mask[2] = {0xF81F,0x07E0}; -static Uint32 interp_bits_per_pixel = 16; - -#define INTERP_16_MASK_1(v) (v & interp_mask[0]) -#define INTERP_16_MASK_2(v) (v & interp_mask[1]) - -FUNCINLINE static ATTRINLINE Uint16 interp_16_521(Uint16 p1, Uint16 p2, Uint16 p3) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*2 + INTERP_16_MASK_1(p3)*1) / 8) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*2 + INTERP_16_MASK_2(p3)*1) / 8)); -} - -FUNCINLINE static ATTRINLINE Uint16 interp_16_332(Uint16 p1, Uint16 p2, Uint16 p3) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)*2) / 8) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)*2) / 8)); -} - -FUNCINLINE static ATTRINLINE Uint16 interp_16_611(Uint16 p1, Uint16 p2, Uint16 p3) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*6 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 8) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*6 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 8)); -} - -/* -FUNCINLINE static ATTRINLINE Uint16 interp_16_71(Uint16 p1, Uint16 p2) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*7 + INTERP_16_MASK_1(p2)) / 8) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*7 + INTERP_16_MASK_2(p2)) / 8)); -} -*/ - -FUNCINLINE static ATTRINLINE Uint16 interp_16_211(Uint16 p1, Uint16 p2, Uint16 p3) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*2 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 4) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*2 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 4)); -} - -/* -FUNCINLINE static ATTRINLINE Uint16 interp_16_772(Uint16 p1, Uint16 p2, Uint16 p3) -{ - return (Uint16)(INTERP_16_MASK_1(((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2))*7 + INTERP_16_MASK_1(p3)*2) / 16) - | INTERP_16_MASK_2(((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2))*7 + INTERP_16_MASK_2(p3)*2) / 16)); -} - -FUNCINLINE static ATTRINLINE Uint16 interp_16_11(Uint16 p1, Uint16 p2) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2)) / 2) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2)) / 2)); -} -*/ - -FUNCINLINE static ATTRINLINE Uint16 interp_16_31(Uint16 p1, Uint16 p2) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)) / 4) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)) / 4)); -} - -FUNCINLINE static ATTRINLINE Uint16 interp_16_1411(Uint16 p1, Uint16 p2, Uint16 p3) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*14 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 16) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*14 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 16)); -} - -/* -FUNCINLINE static ATTRINLINE Uint16 interp_16_431(Uint16 p1, Uint16 p2, Uint16 p3) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*4 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)) / 8) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*4 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)) / 8)); -} - -FUNCINLINE static ATTRINLINE Uint16 interp_16_53(Uint16 p1, Uint16 p2) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*3) / 8) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*3) / 8)); -} - -FUNCINLINE static ATTRINLINE Uint16 interp_16_151(Uint16 p1, Uint16 p2) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*15 + INTERP_16_MASK_1(p2)) / 16) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*15 + INTERP_16_MASK_2(p2)) / 16)); -} - -FUNCINLINE static ATTRINLINE Uint16 interp_16_97(Uint16 p1, Uint16 p2) -{ - return (Uint16)(INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*9 + INTERP_16_MASK_1(p2)*7) / 16) - | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*9 + INTERP_16_MASK_2(p2)*7) / 16)); -} -*/ - -#define INTERP_32_MASK_1(v) (v & 0xFF00FF) -#define INTERP_32_MASK_2(v) (v & 0x00FF00) - -FUNCINLINE static ATTRINLINE Uint32 interp_32_521(Uint32 p1, Uint32 p2, Uint32 p3) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*2 + INTERP_32_MASK_1(p3)*1) / 8) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*2 + INTERP_32_MASK_2(p3)*1) / 8); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_332(Uint32 p1, Uint32 p2, Uint32 p3) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)*2) / 8) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)*2) / 8); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_211(Uint32 p1, Uint32 p2, Uint32 p3) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*2 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 4) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*2 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 4); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_611(Uint32 p1, Uint32 p2, Uint32 p3) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*6 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 8) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*6 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 8); -} - -/* -FUNCINLINE static ATTRINLINE Uint32 interp_32_71(Uint32 p1, Uint32 p2) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*7 + INTERP_32_MASK_1(p2)) / 8) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*7 + INTERP_32_MASK_2(p2)) / 8); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_772(Uint32 p1, Uint32 p2, Uint32 p3) -{ - return INTERP_32_MASK_1(((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2))*7 + INTERP_32_MASK_1(p3)*2) / 16) - | INTERP_32_MASK_2(((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2))*7 + INTERP_32_MASK_2(p3)*2) / 16); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_11(Uint32 p1, Uint32 p2) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2)) / 2) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2)) / 2); -} -*/ - -FUNCINLINE static ATTRINLINE Uint32 interp_32_31(Uint32 p1, Uint32 p2) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)) / 4) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)) / 4); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_1411(Uint32 p1, Uint32 p2, Uint32 p3) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*14 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 16) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*14 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 16); -} - -/* -FUNCINLINE static ATTRINLINE Uint32 interp_32_431(Uint32 p1, Uint32 p2, Uint32 p3) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*4 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)) / 8) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*4 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)) / 8); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_53(Uint32 p1, Uint32 p2) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*3) / 8) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*3) / 8); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_151(Uint32 p1, Uint32 p2) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*15 + INTERP_32_MASK_1(p2)) / 16) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*15 + INTERP_32_MASK_2(p2)) / 16); -} - -FUNCINLINE static ATTRINLINE Uint32 interp_32_97(Uint32 p1, Uint32 p2) -{ - return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*9 + INTERP_32_MASK_1(p2)*7) / 16) - | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*9 + INTERP_32_MASK_2(p2)*7) / 16); -} -*/ - -/***************************************************************************/ -/* diff */ - -#define INTERP_Y_LIMIT (0x30*4) -#define INTERP_U_LIMIT (0x07*4) -#define INTERP_V_LIMIT (0x06*8) - -static int interp_16_diff(Uint16 p1, Uint16 p2) -{ - int r, g, b; - int y, u, v; - - if (p1 == p2) - return 0; - - if (interp_bits_per_pixel == 16) { - b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; - g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3; - r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8; - } else { - b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3; - g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2; - r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7; - } - - y = r + g + b; - u = r - b; - v = -r + 2*g - b; - - if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) - return 1; - - if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) - return 1; - - if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) - return 1; - - return 0; -} - -static int interp_32_diff(Uint32 p1, Uint32 p2) -{ - int r, g, b; - int y, u, v; - - if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8)) - return 0; - - b = (int)((p1 & 0xFF) - (p2 & 0xFF)); - g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8; - r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16; - - y = r + g + b; - u = r - b; - v = -r + 2*g - b; - - if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) - return 1; - - if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) - return 1; - - if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) - return 1; - - return 0; -} - -/* -static void interp_set(Uint32 bits_per_pixel) -{ - interp_bits_per_pixel = bits_per_pixel; - - switch (bits_per_pixel) { - case 15 : - interp_mask[0] = 0x7C1F; - interp_mask[1] = 0x03E0; - break; - case 16 : - interp_mask[0] = 0xF81F; - interp_mask[1] = 0x07E0; - break; - case 32 : - interp_mask[0] = 0xFF00FF; - interp_mask[1] = 0x00FF00; - break; - } -} -*/ - -#endif diff --git a/src/sdl12/filter/lq2x.c b/src/sdl12/filter/lq2x.c deleted file mode 100644 index 8d06fa8cc..000000000 --- a/src/sdl12/filter/lq2x.c +++ /dev/null @@ -1,564 +0,0 @@ -#include "filters.h" -#include "interp.h" - -static void hq2x_16_def(Uint16* dst0, Uint16* dst1, const Uint16* src0, const Uint16* src1, const Uint16* src2, Uint32 count) -{ - Uint32 i; - - for(i=0;i0) { - c[0] = src0[-1]; - c[3] = src1[-1]; - c[6] = src2[-1]; - } else { - c[0] = c[1]; - c[3] = c[4]; - c[6] = c[7]; - } - - if (i0) { - c[0] = src0[-1]; - c[3] = src1[-1]; - c[6] = src2[-1]; - } else { - c[0] = c[1]; - c[3] = c[4]; - c[6] = c[7]; - } - - if (i0) { - c[0] = src0[-1]; - c[3] = src1[-1]; - c[6] = src2[-1]; - } else { - c[0] = c[1]; - c[3] = c[4]; - c[6] = c[7]; - } - - if (i0) { - c[0] = src0[-1]; - c[3] = src1[-1]; - c[6] = src2[-1]; - } else { - c[0] = c[1]; - c[3] = c[4]; - c[6] = c[7]; - } - - if (i> 1); - - Uint16 *src0 = (Uint16 *)srcPtr; - Uint16 *src1 = src0 + (srcPitch >> 1); - Uint16 *src2 = src1 + (srcPitch >> 1); - int count = height-2; - - hq2x_16_def(dst0, dst1, src0, src0, src1, width); - - while(count) { - dst0 += dstPitch; - dst1 += dstPitch; - hq2x_16_def(dst0, dst1, src0, src1, src2, width); - src0 = src1; - src1 = src2; - src2 += srcPitch >> 1; - --count; - } - dst0 += dstPitch; - dst1 += dstPitch; - hq2x_16_def(dst0, dst1, src0, src1, src1, width); -} - -void hq2x32(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, - Uint32 dstPitch, int width, int height) -{ - Uint32 *dst0 = (Uint32 *)dstPtr; - Uint32 *dst1 = dst0 + (dstPitch >> 2); - - Uint32 *src0 = (Uint32 *)srcPtr; - Uint32 *src1 = src0 + (srcPitch >> 2); - Uint32 *src2 = src1 + (srcPitch >> 2); - int count = height-2; - - hq2x_32_def(dst0, dst1, src0, src0, src1, width); - - while(count) { - dst0 += dstPitch >> 1; - dst1 += dstPitch >> 1; - hq2x_32_def(dst0, dst1, src0, src1, src2, width); - src0 = src1; - src1 = src2; - src2 += srcPitch >> 2; - --count; - } - dst0 += dstPitch >> 1; - dst1 += dstPitch >> 1; - hq2x_32_def(dst0, dst1, src0, src1, src1, width); -} - -void lq2x16(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, - Uint32 dstPitch, int width, int height) -{ - Uint16 *dst0 = (Uint16 *)dstPtr; - Uint16 *dst1 = dst0 + (dstPitch >> 1); - - Uint16 *src0 = (Uint16 *)srcPtr; - Uint16 *src1 = src0 + (srcPitch >> 1); - Uint16 *src2 = src1 + (srcPitch >> 1); - int count = height-2; - - lq2x_16_def(dst0, dst1, src0, src0, src1, width); - - while(count) { - dst0 += dstPitch; - dst1 += dstPitch; - lq2x_16_def(dst0, dst1, src0, src1, src2, width); - src0 = src1; - src1 = src2; - src2 += srcPitch >> 1; - --count; - } - dst0 += dstPitch; - dst1 += dstPitch; - lq2x_16_def(dst0, dst1, src0, src1, src1, width); -} - -void lq2x32(Uint8 *srcPtr, Uint32 srcPitch, Uint8 *dstPtr, - Uint32 dstPitch, int width, int height) -{ - Uint32 *dst0 = (Uint32 *)dstPtr; - Uint32 *dst1 = dst0 + (dstPitch >> 2); - - Uint32 *src0 = (Uint32 *)srcPtr; - Uint32 *src1 = src0 + (srcPitch >> 2); - Uint32 *src2 = src1 + (srcPitch >> 2); - int count = height-2; - - lq2x_32_def(dst0, dst1, src0, src0, src1, width); - - while(count) { - dst0 += dstPitch >> 1; - dst1 += dstPitch >> 1; - lq2x_32_def(dst0, dst1, src0, src1, src2, width); - src0 = src1; - src1 = src2; - src2 += srcPitch >> 2; - --count; - } - dst0 += dstPitch >> 1; - dst1 += dstPitch >> 1; - lq2x_32_def(dst0, dst1, src0, src1, src1, width); -} - -/* -static inline void hq2x_init(Uint32 bits_per_pixel) -{ - interp_set(bits_per_pixel); -} -*/ diff --git a/src/sdl12/filter/lq2x.h b/src/sdl12/filter/lq2x.h deleted file mode 100644 index 094c2b5ae..000000000 --- a/src/sdl12/filter/lq2x.h +++ /dev/null @@ -1,1284 +0,0 @@ -case 0 : -case 2 : -case 4 : -case 6 : -case 8 : -case 12 : -case 16 : -case 20 : -case 24 : -case 28 : -case 32 : -case 34 : -case 36 : -case 38 : -case 40 : -case 44 : -case 48 : -case 52 : -case 56 : -case 60 : -case 64 : -case 66 : -case 68 : -case 70 : -case 96 : -case 98 : -case 100 : -case 102 : -case 128 : -case 130 : -case 132 : -case 134 : -case 136 : -case 140 : -case 144 : -case 148 : -case 152 : -case 156 : -case 160 : -case 162 : -case 164 : -case 166 : -case 168 : -case 172 : -case 176 : -case 180 : -case 184 : -case 188 : -case 192 : -case 194 : -case 196 : -case 198 : -case 224 : -case 226 : -case 228 : -case 230 : -{ - P0 = IC(0); - P1 = IC(0); - P2 = IC(0); - P3 = IC(0); -} break; -case 1 : -case 5 : -case 9 : -case 13 : -case 17 : -case 21 : -case 25 : -case 29 : -case 33 : -case 37 : -case 41 : -case 45 : -case 49 : -case 53 : -case 57 : -case 61 : -case 65 : -case 69 : -case 97 : -case 101 : -case 129 : -case 133 : -case 137 : -case 141 : -case 145 : -case 149 : -case 153 : -case 157 : -case 161 : -case 165 : -case 169 : -case 173 : -case 177 : -case 181 : -case 185 : -case 189 : -case 193 : -case 197 : -case 225 : -case 229 : -{ - P0 = IC(1); - P1 = IC(1); - P2 = IC(1); - P3 = IC(1); -} break; -case 3 : -case 35 : -case 67 : -case 99 : -case 131 : -case 163 : -case 195 : -case 227 : -{ - P0 = IC(2); - P1 = IC(2); - P2 = IC(2); - P3 = IC(2); -} break; -case 7 : -case 39 : -case 71 : -case 103 : -case 135 : -case 167 : -case 199 : -case 231 : -{ - P0 = IC(3); - P1 = IC(3); - P2 = IC(3); - P3 = IC(3); -} break; -case 10 : -case 138 : -{ - P1 = IC(0); - P2 = IC(0); - P3 = IC(0); - if (MUL) { - P0 = IC(0); - } else { - P0 = I211(0, 1, 3); - } -} break; -case 11 : -case 27 : -case 75 : -case 139 : -case 155 : -case 203 : -{ - P1 = IC(2); - P2 = IC(2); - P3 = IC(2); - if (MUL) { - P0 = IC(2); - } else { - P0 = I211(2, 1, 3); - } -} break; -case 14 : -case 142 : -{ - P2 = IC(0); - P3 = IC(0); - if (MUL) { - P0 = IC(0); - P1 = IC(0); - } else { - P0 = I332(1, 3, 0); - P1 = I31(0, 1); - } -} break; -case 15 : -case 143 : -case 207 : -{ - P2 = IC(4); - P3 = IC(4); - if (MUL) { - P0 = IC(4); - P1 = IC(4); - } else { - P0 = I332(1, 3, 4); - P1 = I31(4, 1); - } -} break; -case 18 : -case 22 : -case 30 : -case 50 : -case 54 : -case 62 : -case 86 : -case 118 : -{ - P0 = IC(0); - P2 = IC(0); - P3 = IC(0); - if (MUR) { - P1 = IC(0); - } else { - P1 = I211(0, 1, 5); - } -} break; -case 19 : -case 51 : -{ - P2 = IC(2); - P3 = IC(2); - if (MUR) { - P0 = IC(2); - P1 = IC(2); - } else { - P0 = I31(2, 1); - P1 = I332(1, 5, 2); - } -} break; -case 23 : -case 55 : -case 119 : -{ - P2 = IC(3); - P3 = IC(3); - if (MUR) { - P0 = IC(3); - P1 = IC(3); - } else { - P0 = I31(3, 1); - P1 = I332(1, 5, 3); - } -} break; -case 26 : -{ - P2 = IC(0); - P3 = IC(0); - if (MUL) { - P0 = IC(0); - } else { - P0 = I211(0, 1, 3); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I211(0, 1, 5); - } -} break; -case 31 : -case 95 : -{ - P2 = IC(4); - P3 = IC(4); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 42 : -case 170 : -{ - P1 = IC(0); - P3 = IC(0); - if (MUL) { - P0 = IC(0); - P2 = IC(0); - } else { - P0 = I332(1, 3, 0); - P2 = I31(0, 3); - } -} break; -case 43 : -case 171 : -case 187 : -{ - P1 = IC(2); - P3 = IC(2); - if (MUL) { - P0 = IC(2); - P2 = IC(2); - } else { - P0 = I332(1, 3, 2); - P2 = I31(2, 3); - } -} break; -case 46 : -case 174 : -{ - P1 = IC(0); - P2 = IC(0); - P3 = IC(0); - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } -} break; -case 47 : -case 175 : -{ - P1 = IC(4); - P2 = IC(4); - P3 = IC(4); - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } -} break; -case 58 : -case 154 : -case 186 : -{ - P2 = IC(0); - P3 = IC(0); - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I611(0, 1, 5); - } -} break; -case 59 : -{ - P2 = IC(2); - P3 = IC(2); - if (MUL) { - P0 = IC(2); - } else { - P0 = I211(2, 1, 3); - } - if (MUR) { - P1 = IC(2); - } else { - P1 = I611(2, 1, 5); - } -} break; -case 63 : -{ - P2 = IC(4); - P3 = IC(4); - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 72 : -case 76 : -case 104 : -case 106 : -case 108 : -case 110 : -case 120 : -case 124 : -{ - P0 = IC(0); - P1 = IC(0); - P3 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I211(0, 3, 7); - } -} break; -case 73 : -case 77 : -case 105 : -case 109 : -case 125 : -{ - P1 = IC(1); - P3 = IC(1); - if (MDL) { - P0 = IC(1); - P2 = IC(1); - } else { - P0 = I31(1, 3); - P2 = I332(3, 7, 1); - } -} break; -case 74 : -{ - P1 = IC(0); - P3 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I211(0, 3, 7); - } - if (MUL) { - P0 = IC(0); - } else { - P0 = I211(0, 1, 3); - } -} break; -case 78 : -case 202 : -case 206 : -{ - P1 = IC(0); - P3 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I611(0, 3, 7); - } - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } -} break; -case 79 : -{ - P1 = IC(4); - P3 = IC(4); - if (MDL) { - P2 = IC(4); - } else { - P2 = I611(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } -} break; -case 80 : -case 208 : -case 210 : -case 216 : -{ - P0 = IC(0); - P1 = IC(0); - P2 = IC(0); - if (MDR) { - P3 = IC(0); - } else { - P3 = I211(0, 5, 7); - } -} break; -case 81 : -case 209 : -case 217 : -{ - P0 = IC(1); - P1 = IC(1); - P2 = IC(1); - if (MDR) { - P3 = IC(1); - } else { - P3 = I211(1, 5, 7); - } -} break; -case 82 : -case 214 : -case 222 : -{ - P0 = IC(0); - P2 = IC(0); - if (MDR) { - P3 = IC(0); - } else { - P3 = I211(0, 5, 7); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I211(0, 1, 5); - } -} break; -case 83 : -case 115 : -{ - P0 = IC(2); - P2 = IC(2); - if (MDR) { - P3 = IC(2); - } else { - P3 = I611(2, 5, 7); - } - if (MUR) { - P1 = IC(2); - } else { - P1 = I611(2, 1, 5); - } -} break; -case 84 : -case 212 : -{ - P0 = IC(0); - P2 = IC(0); - if (MDR) { - P1 = IC(0); - P3 = IC(0); - } else { - P1 = I31(0, 5); - P3 = I332(5, 7, 0); - } -} break; -case 85 : -case 213 : -case 221 : -{ - P0 = IC(1); - P2 = IC(1); - if (MDR) { - P1 = IC(1); - P3 = IC(1); - } else { - P1 = I31(1, 5); - P3 = I332(5, 7, 1); - } -} break; -case 87 : -{ - P0 = IC(3); - P2 = IC(3); - if (MDR) { - P3 = IC(3); - } else { - P3 = I611(3, 5, 7); - } - if (MUR) { - P1 = IC(3); - } else { - P1 = I211(3, 1, 5); - } -} break; -case 88 : -case 248 : -case 250 : -{ - P0 = IC(0); - P1 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I211(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I211(0, 5, 7); - } -} break; -case 89 : -case 93 : -{ - P0 = IC(1); - P1 = IC(1); - if (MDL) { - P2 = IC(1); - } else { - P2 = I611(1, 3, 7); - } - if (MDR) { - P3 = IC(1); - } else { - P3 = I611(1, 5, 7); - } -} break; -case 90 : -{ - if (MDL) { - P2 = IC(0); - } else { - P2 = I611(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I611(0, 5, 7); - } - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I611(0, 1, 5); - } -} break; -case 91 : -{ - if (MDL) { - P2 = IC(2); - } else { - P2 = I611(2, 3, 7); - } - if (MDR) { - P3 = IC(2); - } else { - P3 = I611(2, 5, 7); - } - if (MUL) { - P0 = IC(2); - } else { - P0 = I211(2, 1, 3); - } - if (MUR) { - P1 = IC(2); - } else { - P1 = I611(2, 1, 5); - } -} break; -case 92 : -{ - P0 = IC(0); - P1 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I611(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I611(0, 5, 7); - } -} break; -case 94 : -{ - if (MDL) { - P2 = IC(0); - } else { - P2 = I611(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I611(0, 5, 7); - } - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I211(0, 1, 5); - } -} break; -case 107 : -case 123 : -{ - P1 = IC(2); - P3 = IC(2); - if (MDL) { - P2 = IC(2); - } else { - P2 = I211(2, 3, 7); - } - if (MUL) { - P0 = IC(2); - } else { - P0 = I211(2, 1, 3); - } -} break; -case 111 : -{ - P1 = IC(4); - P3 = IC(4); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } -} break; -case 112 : -case 240 : -{ - P0 = IC(0); - P1 = IC(0); - if (MDR) { - P2 = IC(0); - P3 = IC(0); - } else { - P2 = I31(0, 7); - P3 = I332(5, 7, 0); - } -} break; -case 113 : -case 241 : -{ - P0 = IC(1); - P1 = IC(1); - if (MDR) { - P2 = IC(1); - P3 = IC(1); - } else { - P2 = I31(1, 7); - P3 = I332(5, 7, 1); - } -} break; -case 114 : -{ - P0 = IC(0); - P2 = IC(0); - if (MDR) { - P3 = IC(0); - } else { - P3 = I611(0, 5, 7); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I611(0, 1, 5); - } -} break; -case 116 : -{ - P0 = IC(0); - P1 = IC(0); - P2 = IC(0); - if (MDR) { - P3 = IC(0); - } else { - P3 = I611(0, 5, 7); - } -} break; -case 117 : -{ - P0 = IC(1); - P1 = IC(1); - P2 = IC(1); - if (MDR) { - P3 = IC(1); - } else { - P3 = I611(1, 5, 7); - } -} break; -case 121 : -{ - P0 = IC(1); - P1 = IC(1); - if (MDL) { - P2 = IC(1); - } else { - P2 = I211(1, 3, 7); - } - if (MDR) { - P3 = IC(1); - } else { - P3 = I611(1, 5, 7); - } -} break; -case 122 : -{ - if (MDL) { - P2 = IC(0); - } else { - P2 = I211(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I611(0, 5, 7); - } - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I611(0, 1, 5); - } -} break; -case 126 : -{ - P0 = IC(0); - P3 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I211(0, 3, 7); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I211(0, 1, 5); - } -} break; -case 127 : -{ - P3 = IC(4); - if (MDL) { - P2 = IC(4); - } else { - P2 = I211(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I211(4, 1, 5); - } -} break; -case 146 : -case 150 : -case 178 : -case 182 : -case 190 : -{ - P0 = IC(0); - P2 = IC(0); - if (MUR) { - P1 = IC(0); - P3 = IC(0); - } else { - P1 = I332(1, 5, 0); - P3 = I31(0, 5); - } -} break; -case 147 : -case 179 : -{ - P0 = IC(2); - P2 = IC(2); - P3 = IC(2); - if (MUR) { - P1 = IC(2); - } else { - P1 = I611(2, 1, 5); - } -} break; -case 151 : -case 183 : -{ - P0 = IC(3); - P2 = IC(3); - P3 = IC(3); - if (MUR) { - P1 = IC(3); - } else { - P1 = I1411(3, 1, 5); - } -} break; -case 158 : -{ - P2 = IC(0); - P3 = IC(0); - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I211(0, 1, 5); - } -} break; -case 159 : -{ - P2 = IC(4); - P3 = IC(4); - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 191 : -{ - P2 = IC(4); - P3 = IC(4); - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 200 : -case 204 : -case 232 : -case 236 : -case 238 : -{ - P0 = IC(0); - P1 = IC(0); - if (MDL) { - P2 = IC(0); - P3 = IC(0); - } else { - P2 = I332(3, 7, 0); - P3 = I31(0, 7); - } -} break; -case 201 : -case 205 : -{ - P0 = IC(1); - P1 = IC(1); - P3 = IC(1); - if (MDL) { - P2 = IC(1); - } else { - P2 = I611(1, 3, 7); - } -} break; -case 211 : -{ - P0 = IC(2); - P1 = IC(2); - P2 = IC(2); - if (MDR) { - P3 = IC(2); - } else { - P3 = I211(2, 5, 7); - } -} break; -case 215 : -{ - P0 = IC(3); - P2 = IC(3); - if (MDR) { - P3 = IC(3); - } else { - P3 = I211(3, 5, 7); - } - if (MUR) { - P1 = IC(3); - } else { - P1 = I1411(3, 1, 5); - } -} break; -case 218 : -{ - if (MDL) { - P2 = IC(0); - } else { - P2 = I611(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I211(0, 5, 7); - } - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I611(0, 1, 5); - } -} break; -case 219 : -{ - P1 = IC(2); - P2 = IC(2); - if (MDR) { - P3 = IC(2); - } else { - P3 = I211(2, 5, 7); - } - if (MUL) { - P0 = IC(2); - } else { - P0 = I211(2, 1, 3); - } -} break; -case 220 : -{ - P0 = IC(0); - P1 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I611(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I211(0, 5, 7); - } -} break; -case 223 : -{ - P2 = IC(4); - if (MDR) { - P3 = IC(4); - } else { - P3 = I211(4, 5, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I211(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; -case 233 : -case 237 : -{ - P0 = IC(1); - P1 = IC(1); - P3 = IC(1); - if (MDL) { - P2 = IC(1); - } else { - P2 = I1411(1, 3, 7); - } -} break; -case 234 : -{ - P1 = IC(0); - P3 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I211(0, 3, 7); - } - if (MUL) { - P0 = IC(0); - } else { - P0 = I611(0, 1, 3); - } -} break; -case 235 : -{ - P1 = IC(2); - P3 = IC(2); - if (MDL) { - P2 = IC(2); - } else { - P2 = I1411(2, 3, 7); - } - if (MUL) { - P0 = IC(2); - } else { - P0 = I211(2, 1, 3); - } -} break; -case 239 : -{ - P1 = IC(4); - P3 = IC(4); - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } -} break; -case 242 : -{ - P0 = IC(0); - P2 = IC(0); - if (MDR) { - P3 = IC(0); - } else { - P3 = I211(0, 5, 7); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I611(0, 1, 5); - } -} break; -case 243 : -{ - P0 = IC(2); - P1 = IC(2); - if (MDR) { - P2 = IC(2); - P3 = IC(2); - } else { - P2 = I31(2, 7); - P3 = I332(5, 7, 2); - } -} break; -case 244 : -{ - P0 = IC(0); - P1 = IC(0); - P2 = IC(0); - if (MDR) { - P3 = IC(0); - } else { - P3 = I1411(0, 5, 7); - } -} break; -case 245 : -{ - P0 = IC(1); - P1 = IC(1); - P2 = IC(1); - if (MDR) { - P3 = IC(1); - } else { - P3 = I1411(1, 5, 7); - } -} break; -case 246 : -{ - P0 = IC(0); - P2 = IC(0); - if (MDR) { - P3 = IC(0); - } else { - P3 = I1411(0, 5, 7); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I211(0, 1, 5); - } -} break; -case 247 : -{ - P0 = IC(3); - P2 = IC(3); - if (MDR) { - P3 = IC(3); - } else { - P3 = I1411(3, 5, 7); - } - if (MUR) { - P1 = IC(3); - } else { - P1 = I1411(3, 1, 5); - } -} break; -case 249 : -{ - P0 = IC(1); - P1 = IC(1); - if (MDL) { - P2 = IC(1); - } else { - P2 = I1411(1, 3, 7); - } - if (MDR) { - P3 = IC(1); - } else { - P3 = I211(1, 5, 7); - } -} break; -case 251 : -{ - P1 = IC(2); - if (MDL) { - P2 = IC(2); - } else { - P2 = I1411(2, 3, 7); - } - if (MDR) { - P3 = IC(2); - } else { - P3 = I211(2, 5, 7); - } - if (MUL) { - P0 = IC(2); - } else { - P0 = I211(2, 1, 3); - } -} break; -case 252 : -{ - P0 = IC(0); - P1 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I211(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I1411(0, 5, 7); - } -} break; -case 253 : -{ - P0 = IC(1); - P1 = IC(1); - if (MDL) { - P2 = IC(1); - } else { - P2 = I1411(1, 3, 7); - } - if (MDR) { - P3 = IC(1); - } else { - P3 = I1411(1, 5, 7); - } -} break; -case 254 : -{ - P0 = IC(0); - if (MDL) { - P2 = IC(0); - } else { - P2 = I211(0, 3, 7); - } - if (MDR) { - P3 = IC(0); - } else { - P3 = I1411(0, 5, 7); - } - if (MUR) { - P1 = IC(0); - } else { - P1 = I211(0, 1, 5); - } -} break; -case 255 : -{ - if (MDL) { - P2 = IC(4); - } else { - P2 = I1411(4, 3, 7); - } - if (MDR) { - P3 = IC(4); - } else { - P3 = I1411(4, 5, 7); - } - if (MUL) { - P0 = IC(4); - } else { - P0 = I1411(4, 1, 3); - } - if (MUR) { - P1 = IC(4); - } else { - P1 = I1411(4, 1, 5); - } -} break; diff --git a/src/sdl12/filter/main.c b/src/sdl12/filter/main.c deleted file mode 100644 index 98ab1541c..000000000 --- a/src/sdl12/filter/main.c +++ /dev/null @@ -1,15 +0,0 @@ -#include "filters.h" - -int main(int argc, char *argv[]) -{ - SDL_Surface *src = NULL; - SDL_Surface *dst = NULL; - src = SDL_LoadBMP("src.bmp"); //load - if(!src) return -1; //check - dst = filter_2x(src, NULL, hq2x32); //prcoess - SDL_FreeSurface(src); //free - if(!dst) return 0; //error - SDL_SaveBMP(dst, "dst.bmp"); //save - SDL_FreeSurface(dst); //free - return 1; //good -} diff --git a/src/sdl12/hwsym_sdl.h b/src/sdl12/hwsym_sdl.h deleted file mode 100644 index 7297587bf..000000000 --- a/src/sdl12/hwsym_sdl.h +++ /dev/null @@ -1,23 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Tool for dynamic referencing of hardware rendering/3D sound functions - -void *hwSym(const char *funcName,void *handle); - -void *hwOpen(const char *hwfile); - -void hwClose(void *handle); diff --git a/src/sdl12/i_cdmus.c b/src/sdl12/i_cdmus.c deleted file mode 100644 index b3490592e..000000000 --- a/src/sdl12/i_cdmus.c +++ /dev/null @@ -1,588 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief cd music interface -/// - -#ifdef HAVE_SDL - -#if defined (DC) || defined (_WIN32_WCE) || defined(GP2X) || defined(_PS3) -#define NOSDLCD -#endif - -#include -#ifndef NOSDLCD - -#ifdef _MSC_VER -#pragma warning(disable : 4214 4244) -#endif - -#include "SDL.h" - -#ifdef _MSC_VER -#pragma warning(default : 4214 4244) -#endif - -#endif - -#include "../doomtype.h" -#include "../i_sound.h" -#include "../command.h" -#include "../m_argv.h" -#include "../s_sound.h" - -#define MAX_CD_TRACKS 256 - -#ifdef _XBOX -INT32 SDL_SYS_CDInit(void) -{ - return(0); -} - -void SDL_SYS_CDQuit(void) -{ - return; -} -#endif - -UINT8 cdaudio_started = 0; // for system startup/shutdown - -consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; - -#ifndef NOSDLCD -static SDL_bool cdValid = SDL_FALSE; -static SDL_bool cdPlaying = SDL_FALSE; -static SDL_bool wasPlaying = SDL_FALSE; -static SDL_bool cdEnabled = SDL_FALSE; -static SDL_bool playLooping = SDL_FALSE; -static Uint8 playTrack = 0; -static Uint8 maxTrack = MAX_CD_TRACKS-1; -static Uint8 cdRemap[MAX_CD_TRACKS]; -static INT32 cdvolume = -1; -static SDL_CD *cdrom = NULL; -static CDstatus cdStatus = CD_ERROR; - -/************************************************************************** - * - * function: CDAudio_GetAudioDiskInfo - * - * description: - * set number of tracks if CD is available - * - **************************************************************************/ -static INT32 CDAudio_GetAudioDiskInfo(void) -{ - cdValid = SDL_FALSE; - maxTrack = 0; - - if (!cdrom) - return 0;//Alam: Lies! - - cdStatus = SDL_CDStatus(cdrom); - - if (!CD_INDRIVE(cdStatus)) - { - CONS_Printf("%s", M_GetText("No CD in drive\n")); - return -1; - } - - if (cdStatus == CD_ERROR) - { - CONS_Printf(M_GetText("CD Error: %s\n"), SDL_GetError()); - return -1; - } - - cdValid = SDL_TRUE; - maxTrack = (Uint8)cdrom->numtracks; - - return 0; -} - - -/************************************************************************** - * - * function: I_EjectCD - * - * description: - * - * - **************************************************************************/ -static void I_EjectCD(void) -{ - if (!cdrom || !cdEnabled) - return; // no cd init'd - - I_StopCD(); - - if (SDL_CDEject(cdrom)) - CONS_Printf("%s", M_GetText("CD eject failed\n")); -} - -/************************************************************************** - * - * function: Command_Cd_f - * - * description: - * handles all CD commands from the console - * - **************************************************************************/ -static void Command_Cd_f (void) -{ - const char *command; - size_t ret, n; - - if (!cdaudio_started) - return; - - if (COM_Argc() < 2) - { - CONS_Printf ("%s", M_GetText("cd [on] [off] [remap] [reset] [select]\n" - " [open] [info] [play ] [resume]\n" - " [stop] [pause] [loop ]\n")); - return; - } - - command = COM_Argv (1); - - if (!strncmp(command, "on", 2)) - { - cdEnabled = SDL_TRUE; - return; - } - - if (!strncmp(command, "off", 3)) - { - I_StopCD(); - cdEnabled = SDL_FALSE; - return; - } - - if (!strncmp(command, "select", 6)) - { - INT32 newcddrive; - newcddrive = atoi(COM_Argv(2)); - command = SDL_CDName(newcddrive); - I_StopCD(); - cdEnabled = SDL_FALSE; - SDL_CDClose(cdrom); - cdrom = SDL_CDOpen(newcddrive); - if (cdrom) - { - cdEnabled = SDL_TRUE; - CONS_Printf(M_GetText("Opened CD-ROM drive %s\n"), command ? command : COM_Argv(2)); - } - else CONS_Printf(M_GetText("Couldn't open CD-ROM drive %s: %s\n"), command ? command : COM_Argv(2), SDL_GetError()); - return; - } - - if (!strncmp(command, "remap", 5)) - { - ret = COM_Argc() - 2; - if (ret <= 0) - { - for (n = 1; n < MAX_CD_TRACKS; n++) - { - if (cdRemap[n] != n) - CONS_Printf(" %s -> %u\n", sizeu1(n), cdRemap[n]); - } - return; - } - for (n = 1; n <= ret; n++) - cdRemap[n] = (Uint8)atoi(COM_Argv (n+1)); - return; - } - - if (!strncmp(command, "reset", 5)) - { - if (!cdrom) return; - cdEnabled = SDL_TRUE; - I_StopCD(); - for (n = 0; n < MAX_CD_TRACKS; n++) - cdRemap[n] = (Uint8)n; - CDAudio_GetAudioDiskInfo(); - return; - } - - if (!cdValid) - { - if (CDAudio_GetAudioDiskInfo()==-1 && !cdValid) - { - CONS_Printf("%s", M_GetText("No CD in drive\n")); - return; - } - } - - if (!strncmp(command, "open", 4)) - { - I_EjectCD(); - cdValid = SDL_FALSE; - return; - } - - if (!strncmp(command, "info", 4)) - { - CONS_Printf(M_GetText("%u tracks\n"), maxTrack); - if (cdPlaying) - CONS_Printf(M_GetText("Currently %s track %u\n"), playLooping ? M_GetText("looping") : M_GetText("playing"), playTrack); - else if (wasPlaying) - CONS_Printf(M_GetText("Paused %s track %u\n"), playLooping ? M_GetText("looping") : M_GetText("playing"), playTrack); - CONS_Printf(M_GetText("Volume is %d\n"), cdvolume); - return; - } - - if (!strncmp(command, "play", 4)) - { - I_PlayCD((UINT8)atoi(COM_Argv (2)), SDL_FALSE); - return; - } - - if (!strncmp(command, "loop", 4)) - { - I_PlayCD((UINT8)atoi(COM_Argv (2)), true); - return; - } - - if (!strncmp(command, "stop", 4)) - { - I_StopCD(); - return; - } - if (!strncmp(command, "pause", 5)) - { - I_PauseCD(); - return; - } - - if (!strncmp(command, "resume", 6)) - { - I_ResumeCD(); - return; - } - - CONS_Printf(M_GetText("Invalid CD command \"CD %s\"\n"), COM_Argv(1)); -} -#endif - -/************************************************************************** - * - * function: StopCD - * - * description: - * - * - **************************************************************************/ -void I_StopCD(void) -{ -#ifndef NOSDLCD - if (!cdrom || !cdEnabled) - return; - - if (!(cdPlaying || wasPlaying)) - return; - - if (SDL_CDStop(cdrom)) - I_OutputMsg("cdromstop failed\n"); - - wasPlaying = SDL_FALSE; - cdPlaying = SDL_FALSE; -#endif -} - -/************************************************************************** - * - * function: PauseCD - * - * description: - * - * - **************************************************************************/ -void I_PauseCD (void) -{ -#ifndef NOSDLCD - if (!cdrom || !cdEnabled) - return; - - if (!cdPlaying) - return; - - if (SDL_CDPause(cdrom)) - I_OutputMsg("cdrompause failed\n"); - - wasPlaying = cdPlaying; - cdPlaying = SDL_FALSE; -#endif -} - -/************************************************************************** - * - * function: ResumeCD - * - * description: - * - * - **************************************************************************/ -// continue after a pause -void I_ResumeCD (void) -{ -#ifndef NOSDLCD - if (!cdrom || !cdEnabled) - return; - - if (!cdValid) - return; - - if (!wasPlaying) - return; - - if (cd_volume.value == 0) - return; - - if (SDL_CDResume(cdrom)) - I_OutputMsg("cdromresume failed\n"); - - cdPlaying = SDL_TRUE; - wasPlaying = SDL_FALSE; -#endif -} - - -/************************************************************************** - * - * function: ShutdownCD - * - * description: - * - * - **************************************************************************/ -void I_ShutdownCD (void) -{ -#ifndef NOSDLCD - if (!cdaudio_started) - return; - - I_StopCD(); - - CONS_Printf("I_ShutdownCD: "); - SDL_CDClose(cdrom); - cdrom = NULL; - cdaudio_started = false; - CONS_Printf("%s", M_GetText("shut down\n")); - SDL_QuitSubSystem(SDL_INIT_CDROM); - cdEnabled = SDL_FALSE; -#endif -} - -/************************************************************************** - * - * function: InitCD - * - * description: - * Initialize the first CD drive SDL detects and add console command 'cd' - * - **************************************************************************/ -void I_InitCD (void) -{ -#ifndef NOSDLCD - INT32 i; - - // Has been checked in d_main.c, but doesn't hurt here - if (M_CheckParm ("-nocd")) - return; - - CONS_Printf("%s", M_GetText("I_InitCD: Init CD audio\n")); - - // Initialize SDL first - if (SDL_InitSubSystem(SDL_INIT_CDROM) < 0) - { - CONS_Printf(M_GetText("Couldn't initialize SDL CDROM: %s\n"), SDL_GetError()); - return; - } - - // Open drive - cdrom = SDL_CDOpen(0); - - if (!cdrom) - { - const char *cdName = SDL_CDName(0); - if (!cdName) - CONS_Printf(M_GetText("Couldn't open CD-ROM drive %s: %s\n"), "\b", SDL_GetError()); - else - CONS_Printf(M_GetText("Couldn't open CD-ROM drive %s: %s\n"), cdName, SDL_GetError()); - //return; - } - - for (i = 0; i < MAX_CD_TRACKS; i++) - cdRemap[i] = (Uint8)i; - - cdaudio_started = true; - if (cdrom) cdEnabled = SDL_TRUE; - - if (CDAudio_GetAudioDiskInfo()==-1) - { - CONS_Printf("%s", M_GetText("No CD in drive\n")); - cdValid = SDL_FALSE; - } - - COM_AddCommand ("cd", Command_Cd_f); - - CONS_Printf("%s", M_GetText("CD audio Initialized\n")); -#endif -} - - - -// -/************************************************************************** - * - * function: UpdateCD - * - * description: - * sets CD volume (may have changed) and initiates play evey 2 seconds - * in case the song has elapsed - * - **************************************************************************/ -void I_UpdateCD (void) -{ -#ifndef NOSDLCD - static Uint32 lastchk = 0; - - if (!cdEnabled || !cdrom) - return; - - I_SetVolumeCD(cd_volume.value); - - if (cdPlaying && lastchk < SDL_GetTicks()) - { - lastchk = SDL_GetTicks() + 2000; //two seconds between chks - - if (CDAudio_GetAudioDiskInfo()==-1) - { - cdPlaying = SDL_FALSE; - return; - } - - if (cdStatus != CD_PLAYING && cdStatus != CD_PAUSED) - { - cdPlaying = SDL_FALSE; - if (playLooping) - I_PlayCD(playTrack, true); - } - } -#endif -} - - - -/************************************************************************** - * - * function: PlayCD - * - * description: - * play the requested track and set the looping flag - * pauses the CD if volume is 0 - * - **************************************************************************/ - -void I_PlayCD (UINT8 track, UINT8 looping) -{ -#ifdef NOSDLCD - (void)track; - (void)looping; -#else - if (!cdrom || !cdEnabled) - return; - - if (!cdValid) - { - CDAudio_GetAudioDiskInfo(); - if (!cdValid) - return; - } - - track = cdRemap[track]; - - if (track < 1 || track > maxTrack) - { - CONS_Printf(M_GetText("Bad track number %u.\n"), track); - return; - } - - // don't try to play a non-audio track - if (cdrom->track[track].type == SDL_DATA_TRACK) - { - CONS_Printf(M_GetText("Track %u is not audio\n"), track); - return; - } - - if (cdPlaying) - { - if (playTrack == track) - return; - I_StopCD(); - } - - if (SDL_CDPlayTracks(cdrom, track, 0, 1, 0)) - { - CONS_Printf(M_GetText("Error playing track %d: %s\n"), track, SDL_GetError()); - return; - } - - playLooping = looping; - playTrack = (Uint8)track; - cdPlaying = SDL_TRUE; - - if (cd_volume.value == 0) - I_PauseCD(); -#endif -} - - -/************************************************************************** - * - * function: SetVolumeCD - * - * description: - * SDL does not support setting the CD volume - * use pause instead and toggle between full and no music - * - **************************************************************************/ - -boolean I_SetVolumeCD (INT32 volume) -{ -#ifdef NOSDLCD - (void)volume; -#else - if (volume != cdvolume) - { - if (volume > 0 && volume < 16) - { - CV_SetValue(&cd_volume, 31); - cdvolume = 31; - I_ResumeCD(); - } - else if (volume > 15 && volume < 31) - { - CV_SetValue(&cd_volume, 0); - cdvolume = 0; - I_PauseCD(); - } - } -#endif - return false; -} - -#endif diff --git a/src/sdl12/i_net.c b/src/sdl12/i_net.c deleted file mode 100644 index ee4a34c13..000000000 --- a/src/sdl12/i_net.c +++ /dev/null @@ -1,442 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief SDL network interface - -#include "../doomdef.h" - -#include "../i_system.h" -#include "../d_event.h" -#include "../d_net.h" -#include "../m_argv.h" - -#include "../doomstat.h" - -#include "../i_net.h" - -#include "../z_zone.h" - -#include "../i_tcp.h" - -#ifdef HAVE_SDL - -#ifdef HAVE_SDLNET - -#include "SDL_net.h" - -#define MAXBANS 20 - -static IPaddress clientaddress[MAXNETNODES+1]; -static IPaddress banned[MAXBANS]; - -static UDPpacket mypacket; -static UDPsocket mysocket = NULL; -static SDLNet_SocketSet myset = NULL; - -static size_t numbans = 0; -static boolean NET_bannednode[MAXNETNODES+1]; /// \note do we really need the +1? -static boolean init_SDLNet_driver = false; - -static const char *NET_AddrToStr(IPaddress* sk) -{ - static char s[22]; // 255.255.255.255:65535 - strcpy(s, SDLNet_ResolveIP(sk)); - if (sk->port != 0) strcat(s, va(":%d", sk->port)); - return s; -} - -static const char *NET_GetNodeAddress(INT32 node) -{ - if (!nodeconnected[node]) - return NULL; - return NET_AddrToStr(&clientaddress[node]); -} - -static const char *NET_GetBanAddress(size_t ban) -{ - if (ban > numbans) - return NULL; - return NET_AddrToStr(&banned[ban]); -} - -static boolean NET_cmpaddr(IPaddress* a, IPaddress* b) -{ - return (a->host == b->host && (b->port == 0 || a->port == b->port)); -} - -static boolean NET_CanGet(void) -{ - return myset?(SDLNet_CheckSockets(myset,0) == 1):false; -} - -static void NET_Get(void) -{ - INT32 mystatus; - INT32 newnode; - mypacket.len = MAXPACKETLENGTH; - if (!NET_CanGet()) - { - doomcom->remotenode = -1; // no packet - return; - } - mystatus = SDLNet_UDP_Recv(mysocket,&mypacket); - if (mystatus != -1) - { - if (mypacket.channel != -1) - { - doomcom->remotenode = mypacket.channel+1; // good packet from a game player - doomcom->datalength = mypacket.len; - return; - } - newnode = SDLNet_UDP_Bind(mysocket,-1,&mypacket.address); - if (newnode != -1) - { - size_t i; - newnode++; - M_Memcpy(&clientaddress[newnode], &mypacket.address, sizeof (IPaddress)); - DEBFILE(va("New node detected: node:%d address:%s\n", newnode, - NET_GetNodeAddress(newnode))); - doomcom->remotenode = newnode; // good packet from a game player - doomcom->datalength = mypacket.len; - for (i = 0; i < numbans; i++) - { - if (NET_cmpaddr(&mypacket.address, &banned[i])) - { - DEBFILE("This dude has been banned\n"); - NET_bannednode[newnode] = true; - break; - } - } - if (i == numbans) - NET_bannednode[newnode] = false; - return; - } - else - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - } - else if (mystatus == -1) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - } - - DEBFILE("New node detected: No more free slots\n"); - doomcom->remotenode = -1; // no packet -} - -#if 0 -static boolean NET_CanSend(void) -{ - return true; -} -#endif - -static void NET_Send(void) -{ - if (!doomcom->remotenode) - return; - mypacket.len = doomcom->datalength; - if (SDLNet_UDP_Send(mysocket,doomcom->remotenode-1,&mypacket) == 0) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - } -} - -static void NET_FreeNodenum(INT32 numnode) -{ - // can't disconnect from self :) - if (!numnode) - return; - - DEBFILE(va("Free node %d (%s)\n", numnode, NET_GetNodeAddress(numnode))); - - SDLNet_UDP_Unbind(mysocket,numnode-1); - - memset(&clientaddress[numnode], 0, sizeof (IPaddress)); -} - -static UDPsocket NET_Socket(void) -{ - UDPsocket temp = NULL; - Uint16 portnum = 0; - IPaddress tempip = {INADDR_BROADCAST,0}; - //Hurdler: I'd like to put a server and a client on the same computer - //Logan: Me too - //BP: in fact for client we can use any free port we want i have read - // in some doc that connect in udp can do it for us... - //Alam: where? - if (M_CheckParm("-clientport")) - { - if (!M_IsNextParm()) - I_Error("syntax: -clientport "); - portnum = atoi(M_GetNextParm()); - } - else - portnum = sock_port; - temp = SDLNet_UDP_Open(portnum); - if (!temp) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - return NULL; - } - if (SDLNet_UDP_Bind(temp,BROADCASTADDR-1,&tempip) == -1) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - SDLNet_UDP_Close(temp); - return NULL; - } - clientaddress[BROADCASTADDR].port = sock_port; - clientaddress[BROADCASTADDR].host = INADDR_BROADCAST; - - doomcom->extratics = 1; // internet is very high ping - - return temp; -} - -static void I_ShutdownSDLNetDriver(void) -{ - if (myset) SDLNet_FreeSocketSet(myset); - myset = NULL; - SDLNet_Quit(); - init_SDLNet_driver = false; -} - -static void I_InitSDLNetDriver(void) -{ - if (init_SDLNet_driver) - I_ShutdownSDLNetDriver(); - if (SDLNet_Init() == -1) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - return; // No good! - } - D_SetDoomcom(); - mypacket.data = doomcom->data; - init_SDLNet_driver = true; -} - -static void NET_CloseSocket(void) -{ - if (mysocket) - SDLNet_UDP_Close(mysocket); - mysocket = NULL; -} - -static SINT8 NET_NetMakeNodewPort(const char *hostname, const char *port) -{ - INT32 newnode; - UINT16 portnum = sock_port; - IPaddress hostnameIP; - - // retrieve portnum from address! - if (port && !port[0]) - portnum = atoi(port); - - if (SDLNet_ResolveHost(&hostnameIP,hostname,portnum) == -1) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - return -1; - } - newnode = SDLNet_UDP_Bind(mysocket,-1,&hostnameIP); - if (newnode == -1) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - return newnode; - } - newnode++; - M_Memcpy(&clientaddress[newnode],&hostnameIP,sizeof (IPaddress)); - return (SINT8)newnode; -} - - -static boolean NET_OpenSocket(void) -{ - memset(clientaddress, 0, sizeof (clientaddress)); - - //I_OutputMsg("SDL_Net Code starting up\n"); - - I_NetSend = NET_Send; - I_NetGet = NET_Get; - I_NetCloseSocket = NET_CloseSocket; - I_NetFreeNodenum = NET_FreeNodenum; - I_NetMakeNodewPort = NET_NetMakeNodewPort; - - //I_NetCanSend = NET_CanSend; - - // build the socket but close it first - NET_CloseSocket(); - mysocket = NET_Socket(); - - if (!mysocket) - return false; - - // for select - myset = SDLNet_AllocSocketSet(1); - if (!myset) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - return false; - } - if (SDLNet_UDP_AddSocket(myset,mysocket) == -1) - { - I_OutputMsg("SDL_Net: %s",SDLNet_GetError()); - return false; - } - return true; -} - -static boolean NET_Ban(INT32 node) -{ - if (numbans == MAXBANS) - return false; - - M_Memcpy(&banned[numbans], &clientaddress[node], sizeof (IPaddress)); - banned[numbans].port = 0; - numbans++; - return true; -} - -static boolean NET_SetBanAddress(const char *address, const char *mask) -{ - (void)mask; - if (bans == MAXBANS) - return false; - - if (SDLNet_ResolveHost(&banned[numbans], address, 0) == -1) - return false; - numbans++; - return true; -} - -static void NET_ClearBans(void) -{ - numbans = 0; -} -#endif - -// -// I_InitNetwork -// Only required for DOS, so this is more a dummy -// -boolean I_InitNetwork(void) -{ -#ifdef HAVE_SDLNET - char serverhostname[255]; - boolean ret = false; - SDL_version SDLcompiled; - const SDL_version *SDLlinked = SDLNet_Linked_Version(); - SDL_NET_VERSION(&SDLcompiled) - I_OutputMsg("Compiled for SDL_Net version: %d.%d.%d\n", - SDLcompiled.major, SDLcompiled.minor, SDLcompiled.patch); - I_OutputMsg("Linked with SDL_Net version: %d.%d.%d\n", - SDLlinked->major, SDLlinked->minor, SDLlinked->patch); - //if (!M_CheckParm ("-sdlnet")) - // return false; - // initilize the driver - I_InitSDLNetDriver(); - I_AddExitFunc(I_ShutdownSDLNetDriver); - if (!init_SDLNet_driver) - return false; - - if (M_CheckParm("-udpport")) - { - if (M_IsNextParm()) - sock_port = (UINT16)atoi(M_GetNextParm()); - else - sock_port = 0; - } - - // parse network game options, - if (M_CheckParm("-server") || dedicated) - { - server = true; - - // If a number of clients (i.e. nodes) is specified, the server will wait for the clients - // to connect before starting. - // If no number is specified here, the server starts with 1 client, and others can join - // in-game. - // Since Boris has implemented join in-game, there is no actual need for specifying a - // particular number here. - // FIXME: for dedicated server, numnodes needs to be set to 0 upon start -/* if (M_IsNextParm()) - doomcom->numnodes = (INT16)atoi(M_GetNextParm()); - else */if (dedicated) - doomcom->numnodes = 0; - else - doomcom->numnodes = 1; - - if (doomcom->numnodes < 0) - doomcom->numnodes = 0; - if (doomcom->numnodes > MAXNETNODES) - doomcom->numnodes = MAXNETNODES; - - // server - servernode = 0; - // FIXME: - // ??? and now ? - // server on a big modem ??? 4*isdn - net_bandwidth = 16000; - hardware_MAXPACKETLENGTH = INETPACKETLENGTH; - - ret = true; - } - else if (M_CheckParm("-connect")) - { - if (M_IsNextParm()) - strcpy(serverhostname, M_GetNextParm()); - else - serverhostname[0] = 0; // assuming server in the LAN, use broadcast to detect it - - // server address only in ip - if (serverhostname[0]) - { - COM_BufAddText("connect \""); - COM_BufAddText(serverhostname); - COM_BufAddText("\"\n"); - - // probably modem - hardware_MAXPACKETLENGTH = INETPACKETLENGTH; - } - else - { - // so we're on a LAN - COM_BufAddText("connect any\n"); - - net_bandwidth = 800000; - hardware_MAXPACKETLENGTH = MAXPACKETLENGTH; - } - } - - mypacket.maxlen = hardware_MAXPACKETLENGTH; - I_NetOpenSocket = NET_OpenSocket; - I_Ban = NET_Ban; - I_ClearBans = NET_ClearBans; - I_GetNodeAddress = NET_GetNodeAddress; - I_GetBenAddress = NET_GetBenAddress; - I_SetBanAddress = NET_SetBanAddress; - bannednode = NET_bannednode; - - return ret; -#else - if ( M_CheckParm ("-net") ) - { - I_Error("-net not supported, use -server and -connect\n" - "see docs for more\n"); - } - return false; -#endif -} -#endif diff --git a/src/sdl12/i_ttf.c b/src/sdl12/i_ttf.c deleted file mode 100644 index 770a81d98..000000000 --- a/src/sdl12/i_ttf.c +++ /dev/null @@ -1,340 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2011 by Callum Dickinson. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief SDL_ttf interface code. Necessary for platforms with no framebuffer console systems. - -#if defined(SDL) && defined(HAVE_TTF) -#include "SDL.h" -#include "SDL_ttf.h" -#include "../doomdef.h" -#include "../doomstat.h" -#include "../d_netfil.h" -#include "../filesrch.h" -#include "i_ttf.h" - -// Search directories to find aforementioned TTF file. -#ifdef _PS3 -#include -#define FONTSEARCHPATH1 "/dev_hdd0/game/SRB2-PS3_/USRDIR/etc" -#elif defined (__unix__) || defined(__APPLE__) || defined (UNIXCOMMON) -#define FONTSEARCHPATH1 "/usr/share/fonts" -#define FONTSEARCHPATH2 "/usr/local/share/fonts" -#define FONTSEARCHPATH3 "/usr/games/SRB2" -#define FONTSEARCHPATH4 "/usr/local/games/SRB2" -#define FONTSEARCHPATH5 "/usr/local/share/games/SRB2" -#else -#define FONTSEARCHPATH1 "." -#endif - -#define FONTHANDLE -1 - -// Renduring surfaces. -SDL_Surface *TTFSurface = NULL; -SDL_Surface *TTFRendSurface = NULL; -// Text box. -SDL_Rect TTFRect; -// Temporary storage for the new TTFRect, used to check for -// line wrapping. -SDL_Rect TTFRectCheck; -// Text rendering resolution. -videoResolution res; -// Text storage buffer, the contents get printed to the SDL surface. -char textbuffer[8192]; - -// look for default ttf file in given directory -static char *searchFont(const char *fontsearchDir) -{ - static char tempsw[256] = ""; - filestatus_t fstemp; - - strcpy(tempsw, FONTFILE); - fstemp = filesearch(tempsw, fontsearchDir, NULL, true, 20); - if (fstemp == FS_FOUND) - { - return tempsw; - } - return NULL; -} - -// Load TTF font from file. -INT32 I_TTFLoadFont(const char *file, UINT32 ptsize) -{ - TTF_Font *tmpfont = NULL; - float fontsize; - - // If a font is currently loaded, unload it. - if (currentfont) - { - TTF_CloseFont(currentfont); - } - - // Scale the specified font point size for the current resolution. - fontsize = (ptsize * 0.005f) * (res.width - res.height); - - tmpfont = TTF_OpenFont(file, fontsize); - - if (!tmpfont) - return FONTHANDLE; - - // set pointer for current font - currentfont = tmpfont; - - // set current font point size - currentfontpoint = ptsize; - - // get font properties, and set them - currentfontstyle = TTF_GetFontStyle(currentfont); - TTF_SetFontStyle(currentfont, currentfontstyle); - - // these functions only exist in SDL_ttf 2.0.10 onwards -#if SDL_TTF_VERSION_ATLEAST(2,0,10) - currentfontkerning = TTF_GetFontKerning(currentfont); - TTF_SetFontKerning(currentfont, currentfontkerning); - - currentfonthinting = TTF_GetFontHinting(currentfont); - TTF_SetFontHinting(currentfont, currentfonthinting); - - currentfontoutline = TTF_GetFontOutline(currentfont); - TTF_SetFontOutline(currentfont, currentfontoutline); -#endif - - return 0; -} - -static void I_TTFRendSurface(const char *textmsg, TTF_Font *font, TextQuality quality, SDL_Color fontfgcolor, SDL_Color fontbgcolor) -{ - // Print text in the buffer. - // SDL_ttf has three modes to draw text. - // Solid rendering is quick, but dirty. Use it if you need speed more than quality. - switch (quality) - { - case solid: - TTFRendSurface = TTF_RenderText_Solid(font, textmsg, fontfgcolor); - break; - // Shaded rendering adds a background to the rendered text. Because of this, I_TTFDrawText - // takes an extra color more than the other styles to be a background color. - // Shaded is supposedly as fast as solid rendering and about as good quality as blended. - case shaded: - TTFRendSurface = TTF_RenderText_Shaded(font, textmsg, fontfgcolor, fontbgcolor); - break; - // Blended rendering is the opposite of solid. Good quality, but slow. - case blended: - TTFRendSurface = TTF_RenderText_Blended(font, textmsg, fontfgcolor); - break; - } - - // Get SDL to update the main surface. - SDL_BlitSurface(TTFRendSurface, NULL, TTFSurface, &TTFRect); - SDL_Flip(TTFSurface); -} - -// Draw text to screen. It will accept four colour vales (red, green, blue and alpha) -// with foreground for draw modes Solid and Blended, and an extra four values for background -// colour with draw type Shaded. -void I_TTFDrawText(TTF_Font *font, TextQuality quality, INT32 fgR, INT32 fgG, INT32 fgB, INT32 fgA, INT32 bgR, INT32 bgG, INT32 bgB, INT32 bgA, const char *textmsg) -{ - // Temporary small buffer to store character to process. - // NULL pointer to prevc to kill warning - char c, prevc = 0x0; - // hack to allow TTF_SizeText to work properly. - char linebuffer[2]; - // Don't need h, but TTF_SizeText needs a height parameter - INT32 w, h; - - // Globally declare foreground and background text colours, - // text drawing mode and the font to draw. - SDL_Color fontfgcolor = {fgR, fgG, fgB, fgA}; - SDL_Color fontbgcolor = {bgR, bgG, bgB, bgA}; - - // Keep on processing until the null terminator in the text buffer is reached. - while (*textmsg != '\0') - { - // Copy pointer for current character into the temporary buffer. - c = *textmsg; - // If c is a newline, move to the next available line. - if (c == '\n') - { - TTFRectCheck.x = 0; - TTFRectCheck.y += (currentfontpoint + 1); - } - // Otherwise... - else - { - // If the previous character was a newline, actually move to the next line. - if (prevc == '\n') - { - if (textbuffer != NULL) - { - // Render cached text to the SDL surface. - I_TTFRendSurface(textbuffer, font, quality, fontfgcolor, fontbgcolor); - // Empty text buffer. - memset(textbuffer, '\0', 1); - } - TTFRect.x = TTFRectCheck.x; - TTFRect.y = TTFRectCheck.y; - } - // Copy the character to the text buffer. - sprintf(textbuffer, "%s%c", textbuffer, c); - // Hack to allow TTF_SizeText to work properly. - sprintf(linebuffer, "%c", c); - // If we have reached the end of the screen, move to the next available line. - TTF_SizeText(currentfont, linebuffer, &w, &h); - TTFRectCheck.x += w; - if (TTFRectCheck.x >= res.width) - { - // Render cached text to the SDL surface. - I_TTFRendSurface(textbuffer, font, quality, fontfgcolor, fontbgcolor); - // Empty text buffer. - memset(textbuffer, '\0', 1); - // Move to the next line. - TTFRectCheck.x = 0; - TTFRectCheck.y += (currentfontpoint + 1); - // Set stored co-ordinates for next line. - TTFRect.x = TTFRectCheck.x; - TTFRect.y = TTFRectCheck.y; - } - } - // Add 1 to the pointer reference for the character to process. - textmsg++; - // Copy contents of the now-old buffer to somewhere else, so it can be referenced in next loop. - prevc = c; - } - - // If the buffer was previously emptied by a line wrapping operation and - // no text came after that, don't print anything. Otherwise, print everything - // still in the buffer. - if (textbuffer != NULL) - { - // Render cached text to the SDL surface. - I_TTFRendSurface(textbuffer, font, quality, fontfgcolor, fontbgcolor); - // Empty text buffer. - memset(textbuffer, '\0', 1); - // Set stored co-ordinates for next line. - TTFRect.x = TTFRectCheck.x; - TTFRect.y = TTFRectCheck.y; - } -} - -// Initialise SDL_ttf. -void I_StartupTTF(UINT32 fontpointsize, Uint32 initflags, Uint32 vidmodeflags) -{ - char *fontpath = NULL; - INT32 fontstatus = -1; -#ifdef _PS3 - videoState state; - videoGetState(0, 0, &state); - videoGetResolution(state.displayMode.resolution, &res); - bitsperpixel = 24; -#else - res.width = 320; - res.height = 200; - bitsperpixel = 8; -#endif - - // what's the point of trying to display an error? - // SDL_ttf is not started, can't display anything to screen (presumably)... - if (SDL_InitSubSystem(initflags) < 0) - I_Error("Couldn't initialize SDL: %s\n", SDL_GetError()); - - TTFSurface = SDL_SetVideoMode(res.width, res.height, bitsperpixel, vidmodeflags); - if (!TTFSurface) - I_Error("Couldn't set SDL Video resolution: %s\n", SDL_GetError()); - - if (TTF_Init() < 0) - I_Error("Couldn't start SDL_ttf: %s\n", TTF_GetError()); - - // look for default font in many directories -#ifdef FONTSEARCHPATH1 - fontpath = searchFont(FONTSEARCHPATH1); - if (fontpath) fontstatus = I_TTFLoadFont(fontpath, fontpointsize); -#endif -#ifdef FONTSEARCHPATH2 - if (fontstatus < 0) - { - fontpath = searchFont(FONTSEARCHPATH2); - if (fontpath) fontstatus = I_TTFLoadFont(fontpath, fontpointsize); - } -#endif -#ifdef FONTSEARCHPATH3 - if (fontstatus < 0) - { - fontpath = searchFont(FONTSEARCHPATH3); - if (fontpath) fontstatus = I_TTFLoadFont(fontpath, fontpointsize); - } -#endif -#ifdef FONTSEARCHPATH4 - if (fontstatus < 0) - { - fontpath = searchFont(FONTSEARCHPATH4); - if (fontpath) fontstatus = I_TTFLoadFont(fontpath, fontpointsize); - } -#endif -#ifdef FONTSEARCHPATH5 - if (fontstatus < 0) - { - fontpath = searchFont(FONTSEARCHPATH5); - if (fontpath) fontstatus = I_TTFLoadFont(fontpath, fontpointsize); - } -#endif -#ifdef FONTSEARCHPATH6 - if (fontstatus < 0) - { - fontpath = searchFont(FONTSEARCHPATH6); - if (fontpath) fontstatus = I_TTFLoadFont(fontpath, fontpointsize); - } -#endif -#ifdef FONTSEARCHPATH7 - if (fontstatus < 0) - { - fontpath = searchFont(FONTSEARCHPATH7); - if (fontpath) fontstatus = I_TTFLoadFont(fontpath, fontpointsize); - } -#endif - // argh! no font file found! disable SDL_ttf code - if (fontstatus < 0) - { - I_ShutdownTTF(); - CONS_Printf("Unable to find default font files! Not loading SDL_ttf\n"); - } - else - { - // Get SDL_ttf compiled and linked version - SDL_version TTFcompiled; - const SDL_version *TTFlinked; - - SDL_TTF_VERSION(&TTFcompiled); - TTFlinked = TTF_Linked_Version(); - - // Display it on screen - CONS_Printf("Compiled for SDL_ttf version: %d.%d.%d\n", - TTFcompiled.major, TTFcompiled.minor, TTFcompiled.patch); - CONS_Printf("Linked with SDL_ttf version: %d.%d.%d\n", - TTFlinked->major, TTFlinked->minor, TTFlinked->patch); - } -} - -void I_ShutdownTTF(void) -{ - // close current font - TTF_CloseFont(currentfont); - // shutdown SDL_ttf - TTF_Quit(); - - // Free TTF rendering surfaces. - SDL_FreeSurface(TTFSurface); - SDL_FreeSurface(TTFRendSurface); -} -#endif diff --git a/src/sdl12/i_ttf.h b/src/sdl12/i_ttf.h deleted file mode 100644 index 929c8021c..000000000 --- a/src/sdl12/i_ttf.h +++ /dev/null @@ -1,88 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2011 by Callum Dickinson. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief SDL_ttf interface code. Necessary for platforms with SDL inits that need to run immediately. - -#ifndef __I_TTF__ -#define __I_TTF__ - -#include "../doomdef.h" -#include "SDL_ttf.h" - -// Default name for standard TTF file. -#define FONTFILE "srb2.ttf" -#define FONTPOINTSIZE 12 - -// Default font foreground colours -#define DEFAULTFONTFGR 255 -#define DEFAULTFONTFGG 255 -#define DEFAULTFONTFGB 255 -#define DEFAULTFONTFGA 255 - -// Default font background colours -#define DEFAULTFONTBGR 0 -#define DEFAULTFONTBGG 0 -#define DEFAULTFONTBGB 0 -#define DEFAULTFONTBGA 255 - -#ifndef SDL_TTF_COMPILEDVERSION -#define SDL_TTF_COMPILEDVERSION \ - SDL_VERSIONNUM(TTF_MAJOR_VERSION, TTF_MINOR_VERSION, TTF_PATCHLEVEL) -#endif - -#ifndef SDL_TTF_VERSION_ATLEAST -#define SDL_TTF_VERSION_ATLEAST(X, Y, Z) \ - (SDL_TTF_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) -#endif - -TTF_Font* currentfont; -int currentfontpoint; -int currentfontstyle; -#if SDL_TTF_VERSION_ATLEAST(2,0,10) -int currentfontkerning; -int currentfonthinting; -int currentfontoutline; -#endif - -#ifndef _PS3 -typedef struct -{ - UINT16 width; - UINT16 height; -} VideoResolution; -#endif -UINT8 bitsperpixel; - -typedef enum -{ - solid, - shaded, - blended -} TextQuality; - -// Load TTF font from file. -INT32 I_TTFLoadFont(const char *file, UINT32 ptsize); - -// Draw TTF text to screen. It will accept four colour vales (red, green, blue and alpha) -// with foreground for draw modes Solid and Blended, and an extra four values for background -// colour with draw type Shaded. -void I_TTFDrawText(TTF_Font *font, TextQuality quality, INT32 fgR, INT32 fgG, INT32 fgB, INT32 fgA, INT32 bgR, INT32 bgG, INT32 bgB, INT32 bgA, const char *textmsg); - -// Initialise SDL_ttf. -void I_StartupTTF(UINT32 fontpointsize, Uint32 initflags, Uint32 vidmodeflags); - -void I_ShutdownTTF(void); -#endif diff --git a/src/sdl12/macosx/English.lproj/InfoPlist.strings b/src/sdl12/macosx/English.lproj/InfoPlist.strings deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/sdl12/macosx/Info.plist b/src/sdl12/macosx/Info.plist deleted file mode 100644 index ae0ce24de..000000000 --- a/src/sdl12/macosx/Info.plist +++ /dev/null @@ -1,28 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIconFile - Srb2mac.icns - CFBundleIdentifier - com.yourcompany.Srb2mac - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - APPL - CFBundleSignature - ???? - CFBundleVersion - 1.0 - NSMainNibFile - SDLMain - NSPrincipalClass - NSApplication - - diff --git a/src/sdl12/macosx/mac_alert.c b/src/sdl12/macosx/mac_alert.c deleted file mode 100644 index 455e36509..000000000 --- a/src/sdl12/macosx/mac_alert.c +++ /dev/null @@ -1,45 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Graphical Alerts for MacOSX -/// -/// Shows alerts, since we can't just print these to the screen when -/// launched graphically on a mac. - -#ifdef __APPLE_CC__ - -#include "mac_alert.h" -#include - -int MacShowAlert(const char *title, const char *message, const char *button1, const char *button2, const char *button3) -{ - CFOptionFlags results; - - CFUserNotificationDisplayAlert(0, - kCFUserNotificationStopAlertLevel | kCFUserNotificationNoDefaultButtonFlag, - NULL, NULL, NULL, - CFStringCreateWithCString(NULL, title, kCFStringEncodingASCII), - CFStringCreateWithCString(NULL, message, kCFStringEncodingASCII), - button1 != NULL ? CFStringCreateWithCString(NULL, button1, kCFStringEncodingASCII) : NULL, - button2 != NULL ? CFStringCreateWithCString(NULL, button2, kCFStringEncodingASCII) : NULL, - button3 != NULL ? CFStringCreateWithCString(NULL, button3, kCFStringEncodingASCII) : NULL, - &results); - - return (int)results; -} - -#endif diff --git a/src/sdl12/macosx/mac_alert.h b/src/sdl12/macosx/mac_alert.h deleted file mode 100644 index 82a28d120..000000000 --- a/src/sdl12/macosx/mac_alert.h +++ /dev/null @@ -1,27 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1993-1996 by id Software, Inc. -// Portions Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Graphical Alerts for MacOSX -/// -/// Shows alerts, since we can't just print these to the screen when -/// launched graphically on a mac. - -#ifdef __APPLE_CC__ - -extern int MacShowAlert(const char *title, const char *message, const char *button1, const char *button2, const char *button3); - -#endif diff --git a/src/sdl12/mixer_sound.c b/src/sdl12/mixer_sound.c deleted file mode 100644 index dcae19b05..000000000 --- a/src/sdl12/mixer_sound.c +++ /dev/null @@ -1,832 +0,0 @@ -// SONIC ROBO BLAST 2 -//----------------------------------------------------------------------------- -// Copyright (C) 2008-2018 by Sonic Team Junior. -// -// This program is free software distributed under the -// terms of the GNU General Public License, version 2. -// See the 'LICENSE' file for more details. -//----------------------------------------------------------------------------- -/// \file -/// \brief SDL Mixer interface for sound - -#include "../doomdef.h" - -#if defined(HAVE_SDL) && defined(HAVE_MIXER) && SOUND==SOUND_MIXER - -#include "../sounds.h" -#include "../s_sound.h" -#include "../i_sound.h" -#include "../w_wad.h" -#include "../z_zone.h" -#include "../byteptr.h" - -#ifdef _MSC_VER -#pragma warning(disable : 4214 4244) -#endif -#include "SDL.h" -#ifdef _MSC_VER -#pragma warning(default : 4214 4244) -#endif - -#include "SDL_mixer.h" - -/* This is the version number macro for the current SDL_mixer version: */ -#ifndef SDL_MIXER_COMPILEDVERSION -#define SDL_MIXER_COMPILEDVERSION \ - SDL_VERSIONNUM(MIX_MAJOR_VERSION, MIX_MINOR_VERSION, MIX_PATCHLEVEL) -#endif - -/* This macro will evaluate to true if compiled with SDL_mixer at least X.Y.Z */ -#ifndef SDL_MIXER_VERSION_ATLEAST -#define SDL_MIXER_VERSION_ATLEAST(X, Y, Z) \ - (SDL_MIXER_COMPILEDVERSION >= SDL_VERSIONNUM(X, Y, Z)) -#endif - -#ifdef HAVE_LIBGME -#include "gme/gme.h" -#define GME_TREBLE 5.0 -#define GME_BASS 1.0 -#ifdef HAVE_PNG /// TODO: compile with zlib support without libpng - -#define HAVE_ZLIB - -#ifndef _MSC_VER -#ifndef _WII -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif -#endif -#endif - -#ifndef _LFS64_LARGEFILE -#define _LFS64_LARGEFILE -#endif - -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 0 -#endif - -#include "zlib.h" -#endif -#endif - -UINT8 sound_started = false; - -static boolean midimode; -static Mix_Music *music; -static UINT8 music_volume, midi_volume, sfx_volume; -static float loop_point; - -#ifdef HAVE_LIBGME -static Music_Emu *gme; -static INT32 current_track; -#endif - -void I_StartupSound(void) -{ - I_Assert(!sound_started); - sound_started = true; - - midimode = false; - music = NULL; - music_volume = midi_volume = sfx_volume = 0; - -#if SDL_MIXER_VERSION_ATLEAST(1,2,11) - Mix_Init(MIX_INIT_FLAC|MIX_INIT_MOD|MIX_INIT_MP3|MIX_INIT_OGG); -#endif - Mix_OpenAudio(44100, AUDIO_S16LSB, 2, 2048); - Mix_AllocateChannels(256); -} - -void I_ShutdownSound(void) -{ - I_Assert(sound_started); - sound_started = false; - - Mix_CloseAudio(); -#if SDL_MIXER_VERSION_ATLEAST(1,2,11) - Mix_Quit(); -#endif -#ifdef HAVE_LIBGME - if (gme) - gme_delete(gme); -#endif -} - -void I_UpdateSound(void) -{ -} - -// this is as fast as I can possibly make it. -// sorry. more asm needed. -static Mix_Chunk *ds2chunk(void *stream) -{ - UINT16 ver,freq; - UINT32 samples, i, newsamples; - UINT8 *sound; - - SINT8 *s; - INT16 *d; - INT16 o; - fixed_t step, frac; - - // lump header - ver = READUINT16(stream); // sound version format? - if (ver != 3) // It should be 3 if it's a doomsound... - return NULL; // onos! it's not a doomsound! - freq = READUINT16(stream); - samples = READUINT32(stream); - - // convert from signed 8bit ???hz to signed 16bit 44100hz. - switch(freq) - { - case 44100: - if (samples >= UINT32_MAX>>2) - return NULL; // would wrap, can't store. - newsamples = samples; - break; - case 22050: - if (samples >= UINT32_MAX>>3) - return NULL; // would wrap, can't store. - newsamples = samples<<1; - break; - case 11025: - if (samples >= UINT32_MAX>>4) - return NULL; // would wrap, can't store. - newsamples = samples<<2; - break; - default: - frac = (44100 << FRACBITS) / (UINT32)freq; - if (!(frac & 0xFFFF)) // other solid multiples (change if FRACBITS != 16) - newsamples = samples * (frac >> FRACBITS); - else // strange and unusual fractional frequency steps, plus anything higher than 44100hz. - newsamples = FixedMul(FixedDiv(samples, freq), 44100) + 1; // add 1 to counter truncation. - if (newsamples >= UINT32_MAX>>2) - return NULL; // would and/or did wrap, can't store. - break; - } - sound = Z_Malloc(newsamples<<2, PU_SOUND, NULL); // samples * frequency shift * bytes per sample * channels - - s = (SINT8 *)stream; - d = (INT16 *)sound; - - i = 0; - switch(freq) - { - case 44100: // already at the same rate? well that makes it simple. - while(i++ < samples) - { - o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits - *d++ = o; // left channel - *d++ = o; // right channel - } - break; - case 22050: // unwrap 2x - while(i++ < samples) - { - o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits - *d++ = o; // left channel - *d++ = o; // right channel - *d++ = o; // left channel - *d++ = o; // right channel - } - break; - case 11025: // unwrap 4x - while(i++ < samples) - { - o = ((INT16)(*s++)+0x80)<<8; // changed signedness and shift up to 16 bits - *d++ = o; // left channel - *d++ = o; // right channel - *d++ = o; // left channel - *d++ = o; // right channel - *d++ = o; // left channel - *d++ = o; // right channel - *d++ = o; // left channel - *d++ = o; // right channel - } - break; - default: // convert arbitrary hz to 44100. - step = 0; - frac = ((UINT32)freq << FRACBITS) / 44100; - while (i < samples) - { - o = (INT16)(*s+0x80)<<8; // changed signedness and shift up to 16 bits - while (step < FRACUNIT) // this is as fast as I can make it. - { - *d++ = o; // left channel - *d++ = o; // right channel - step += frac; - } - do { - i++; s++; - step -= FRACUNIT; - } while (step >= FRACUNIT); - } - break; - } - - // return Mixer Chunk. - return Mix_QuickLoad_RAW(sound, (UINT8*)d-sound); -} - -void *I_GetSfx(sfxinfo_t *sfx) -{ - void *lump; - Mix_Chunk *chunk; -#ifdef HAVE_LIBGME - Music_Emu *emu; - gme_info_t *info; -#endif - - if (sfx->lumpnum == LUMPERROR) - sfx->lumpnum = S_GetSfxLumpNum(sfx); - sfx->length = W_LumpLength(sfx->lumpnum); - - lump = W_CacheLumpNum(sfx->lumpnum, PU_SOUND); - - // convert from standard DoomSound format. - chunk = ds2chunk(lump); - if (chunk) - { - Z_Free(lump); - return chunk; - } - - // Not a doom sound? Try something else. -#ifdef HAVE_LIBGME - // VGZ format - if (((UINT8 *)lump)[0] == 0x1F - && ((UINT8 *)lump)[1] == 0x8B) - { -#ifdef HAVE_ZLIB - UINT8 *inflatedData; - size_t inflatedLen; - z_stream stream; - int zErr; // Somewhere to handle any error messages zlib tosses out - - memset(&stream, 0x00, sizeof (z_stream)); // Init zlib stream - // Begin the inflation process - inflatedLen = *(UINT32 *)lump + (sfx->length-4); // Last 4 bytes are the decompressed size, typically - inflatedData = (UINT8 *)Z_Malloc(inflatedLen, PU_SOUND, NULL); // Make room for the decompressed data - stream.total_in = stream.avail_in = sfx->length; - stream.total_out = stream.avail_out = inflatedLen; - stream.next_in = (UINT8 *)lump; - stream.next_out = inflatedData; - - zErr = inflateInit2(&stream, 32 + MAX_WBITS); - if (zErr == Z_OK) // We're good to go - { - zErr = inflate(&stream, Z_FINISH); - if (zErr == Z_STREAM_END) { - // Run GME on new data - if (!gme_open_data(inflatedData, inflatedLen, &emu, 44100)) - { - short *mem; - UINT32 len; - gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - - Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around - Z_Free(lump); // We're done with the uninflated lump now, too. - - gme_start_track(emu, 0); - gme_set_equalizer(emu, &eq); - gme_track_info(emu, &info, 0); - - len = (info->play_length * 441 / 10) << 2; - mem = Z_Malloc(len, PU_SOUND, NULL); - gme_play(emu, len >> 1, mem); - gme_delete(emu); - - return Mix_QuickLoad_RAW((Uint8 *)mem, len); - } - } - else - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg); - } - (void)inflateEnd(&stream); - } - else // Hold up, zlib's got a problem - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg); - } - Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up -#else - //CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n"); -#endif - } - // Try to read it as a GME sound - else if (!gme_open_data(lump, sfx->length, &emu, 44100)) - { - short *mem; - UINT32 len; - gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - - Z_Free(lump); - - gme_start_track(emu, 0); - gme_set_equalizer(emu, &eq); - gme_track_info(emu, &info, 0); - - len = (info->play_length * 441 / 10) << 2; - mem = Z_Malloc(len, PU_SOUND, NULL); - gme_play(emu, len >> 1, mem); - gme_delete(emu); - - return Mix_QuickLoad_RAW((Uint8 *)mem, len); - } -#endif - - // Try to load it as a WAVE or OGG using Mixer. - return Mix_LoadWAV_RW(SDL_RWFromMem(lump, sfx->length), 1); -} - -void I_FreeSfx(sfxinfo_t *sfx) -{ - if (sfx->data) - Mix_FreeChunk(sfx->data); - sfx->data = NULL; -} - -INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel) -{ - UINT8 volume = (((UINT16)vol + 1) * (UINT16)sfx_volume) / 62; // (256 * 31) / 62 == 127 - INT32 handle = Mix_PlayChannel(channel, S_sfx[id].data, 0); - Mix_Volume(handle, volume); - Mix_SetPanning(handle, min((UINT16)(0xff-sep)<<1, 0xff), min((UINT16)(sep)<<1, 0xff)); - (void)pitch; // Mixer can't handle pitch - (void)priority; // priority and channel management is handled by SRB2... - return handle; -} - -void I_StopSound(INT32 handle) -{ - Mix_HaltChannel(handle); -} - -boolean I_SoundIsPlaying(INT32 handle) -{ - return Mix_Playing(handle); -} - -void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch) -{ - UINT8 volume = (((UINT16)vol + 1) * (UINT16)sfx_volume) / 62; // (256 * 31) / 62 == 127 - Mix_Volume(handle, volume); - Mix_SetPanning(handle, min((UINT16)(0xff-sep)<<1, 0xff), min((UINT16)(sep)<<1, 0xff)); - (void)pitch; -} - -void I_SetSfxVolume(UINT8 volume) -{ - sfx_volume = volume; -} - -// -// Music -// - -// Music hooks -static void music_loop(void) -{ - Mix_PlayMusic(music, 0); - Mix_SetMusicPosition(loop_point); -} - -#ifdef HAVE_LIBGME -static void mix_gme(void *udata, Uint8 *stream, int len) -{ - int i; - short *p; - - (void)udata; - - // no gme? no music. - if (!gme || gme_track_ended(gme)) - return; - - // play gme into stream - gme_play(gme, len/2, (short *)stream); - - // apply volume to stream - for (i = 0, p = (short *)stream; i < len/2; i++, p++) - *p = ((INT32)*p) * music_volume / 31; -} -#endif - -void I_InitMusic(void) -{ -} - -void I_ShutdownMusic(void) -{ - I_ShutdownDigMusic(); - I_ShutdownMIDIMusic(); -} - -void I_PauseSong(INT32 handle) -{ - (void)handle; - Mix_PauseMusic(); -} - -void I_ResumeSong(INT32 handle) -{ - (void)handle; - Mix_ResumeMusic(); -} - -// -// Digital Music -// - -void I_InitDigMusic(void) -{ -#ifdef HAVE_LIBGME - gme = NULL; - current_track = -1; -#endif -} - -void I_ShutdownDigMusic(void) -{ - if (midimode) - return; -#ifdef HAVE_LIBGME - if (gme) - { - Mix_HookMusic(NULL, NULL); - gme_delete(gme); - gme = NULL; - } -#endif - if (!music) - return; - Mix_HookMusicFinished(NULL); - Mix_FreeMusic(music); - music = NULL; -} - -boolean I_StartDigSong(const char *musicname, boolean looping) -{ - char *data; - size_t len; - lumpnum_t lumpnum = W_CheckNumForName(va("O_%s",musicname)); - - I_Assert(!music); -#ifdef HAVE_LIBGME - I_Assert(!gme); -#endif - - if (lumpnum == LUMPERROR) - { - lumpnum = W_CheckNumForName(va("D_%s",musicname)); - if (lumpnum == LUMPERROR) - return false; - midimode = true; - } - else - midimode = false; - - data = (char *)W_CacheLumpNum(lumpnum, PU_MUSIC); - len = W_LumpLength(lumpnum); - -#ifdef HAVE_LIBGME - if ((UINT8)data[0] == 0x1F - && (UINT8)data[1] == 0x8B) - { -#ifdef HAVE_ZLIB - UINT8 *inflatedData; - size_t inflatedLen; - z_stream stream; - int zErr; // Somewhere to handle any error messages zlib tosses out - - memset(&stream, 0x00, sizeof (z_stream)); // Init zlib stream - // Begin the inflation process - inflatedLen = *(UINT32 *)(data + (len-4)); // Last 4 bytes are the decompressed size, typically - inflatedData = (UINT8 *)Z_Calloc(inflatedLen, PU_MUSIC, NULL); // Make room for the decompressed data - stream.total_in = stream.avail_in = len; - stream.total_out = stream.avail_out = inflatedLen; - stream.next_in = (UINT8 *)data; - stream.next_out = inflatedData; - - zErr = inflateInit2(&stream, 32 + MAX_WBITS); - if (zErr == Z_OK) // We're good to go - { - zErr = inflate(&stream, Z_FINISH); - if (zErr == Z_STREAM_END) { - // Run GME on new data - if (!gme_open_data(inflatedData, inflatedLen, &gme, 44100)) - { - gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - gme_start_track(gme, 0); - current_track = 0; - gme_set_equalizer(gme, &eq); - Mix_HookMusic(mix_gme, gme); - Z_Free(inflatedData); // GME supposedly makes a copy for itself, so we don't need this lying around - return true; - } - } - else - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflate: %s\n", errorType, stream.msg); - } - (void)inflateEnd(&stream); - } - else // Hold up, zlib's got a problem - { - const char *errorType; - switch (zErr) - { - case Z_ERRNO: - errorType = "Z_ERRNO"; break; - case Z_STREAM_ERROR: - errorType = "Z_STREAM_ERROR"; break; - case Z_DATA_ERROR: - errorType = "Z_DATA_ERROR"; break; - case Z_MEM_ERROR: - errorType = "Z_MEM_ERROR"; break; - case Z_BUF_ERROR: - errorType = "Z_BUF_ERROR"; break; - case Z_VERSION_ERROR: - errorType = "Z_VERSION_ERROR"; break; - default: - errorType = "unknown error"; - } - CONS_Alert(CONS_ERROR,"Encountered %s when running inflateInit: %s\n", errorType, stream.msg); - } - Z_Free(inflatedData); // GME didn't open jack, but don't let that stop us from freeing this up -#else - //CONS_Alert(CONS_ERROR,"Cannot decompress VGZ; no zlib support\n"); -#endif - } - else if (!gme_open_data(data, len, &gme, 44100)) - { - gme_equalizer_t eq = {GME_TREBLE, GME_BASS, 0,0,0,0,0,0,0,0}; - gme_start_track(gme, 0); - current_track = 0; - gme_set_equalizer(gme, &eq); - Mix_HookMusic(mix_gme, gme); - return true; - } -#endif - - music = Mix_LoadMUS_RW(SDL_RWFromMem(data, len)); - if (!music) - { - CONS_Alert(CONS_ERROR, "Mix_LoadMUS_RW: %s\n", Mix_GetError()); - return true; - } - - // Find the OGG loop point. - loop_point = 0.0f; - if (looping) - { - const char *key1 = "LOOP"; - const char *key2 = "POINT="; - const char *key3 = "MS="; - const UINT8 key1len = strlen(key1); - const UINT8 key2len = strlen(key2); - const UINT8 key3len = strlen(key3); - char *p = data; - while ((UINT32)(p - data) < len) - { - if (strncmp(p++, key1, key1len)) - continue; - p += key1len-1; // skip OOP (the L was skipped in strncmp) - if (!strncmp(p, key2, key2len)) // is it LOOPPOINT=? - { - p += key2len; // skip POINT= - loop_point = (float)((44.1L+atoi(p)) / 44100.0L); // LOOPPOINT works by sample count. - // because SDL_Mixer is USELESS and can't even tell us - // something simple like the frequency of the streaming music, - // we are unfortunately forced to assume that ALL MUSIC is 44100hz. - // This means a lot of tracks that are only 22050hz for a reasonable downloadable file size will loop VERY badly. - } - else if (!strncmp(p, key3, key3len)) // is it LOOPMS=? - { - p += key3len; // skip MS= - loop_point = atoi(p) / 1000.0L; // LOOPMS works by real time, as miliseconds. - // Everything that uses LOOPMS will work perfectly with SDL_Mixer. - } - // Neither?! Continue searching. - } - } - - if (Mix_PlayMusic(music, looping && loop_point == 0.0f ? -1 : 0) == -1) - { - CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); - return true; - } - if (midimode) - Mix_VolumeMusic((UINT32)midi_volume*128/31); - else - Mix_VolumeMusic((UINT32)music_volume*128/31); - - if (loop_point != 0.0f) - Mix_HookMusicFinished(music_loop); - return true; -} - -void I_StopDigSong(void) -{ - if (midimode) - return; -#ifdef HAVE_LIBGME - if (gme) - { - Mix_HookMusic(NULL, NULL); - gme_delete(gme); - gme = NULL; - current_track = -1; - return; - } -#endif - if (!music) - return; - Mix_HookMusicFinished(NULL); - Mix_FreeMusic(music); - music = NULL; -} - -void I_SetDigMusicVolume(UINT8 volume) -{ - music_volume = volume; - if (midimode || !music) - return; - Mix_VolumeMusic((UINT32)volume*128/31); -} - -boolean I_SetSongSpeed(float speed) -{ - if (speed > 250.0f) - speed = 250.0f; //limit speed up to 250x -#ifdef HAVE_LIBGME - if (gme) - { - SDL_LockAudio(); - gme_set_tempo(gme, speed); - SDL_UnlockAudio(); - return true; - } -#else - (void)speed; -#endif - return false; -} - -boolean I_SetSongTrack(int track) -{ -#ifdef HAVE_LIBGME - if (current_track == track) - return false; - - // If the specified track is within the number of tracks playing, then change it - if (gme) - { - SDL_LockAudio(); - if (track >= 0 - && track < gme_track_count(gme)) - { - gme_err_t gme_e = gme_start_track(gme, track); - if (gme_e != NULL) - { - CONS_Alert(CONS_ERROR, "GME error: %s\n", gme_e); - return false; - } - current_track = track; - SDL_UnlockAudio(); - return true; - } - SDL_UnlockAudio(); - return false; - } -#endif - (void)track; - return false; -} - -// -// MIDI Music -// - -void I_InitMIDIMusic(void) -{ -} - -void I_ShutdownMIDIMusic(void) -{ - if (!midimode || !music) - return; - Mix_FreeMusic(music); - music = NULL; -} - -void I_SetMIDIMusicVolume(UINT8 volume) -{ - midi_volume = volume; - if (!midimode || !music) - return; - Mix_VolumeMusic((UINT32)volume*128/31); -} - -INT32 I_RegisterSong(void *data, size_t len) -{ - music = Mix_LoadMUS_RW(SDL_RWFromMem(data, len)); - if (!music) - { - CONS_Alert(CONS_ERROR, "Mix_LoadMUS_RW: %s\n", Mix_GetError()); - return -1; - } - return 1337; -} - -boolean I_PlaySong(INT32 handle, boolean looping) -{ - (void)handle; - - midimode = true; - - if (Mix_PlayMusic(music, looping ? -1 : 0) == -1) - { - CONS_Alert(CONS_ERROR, "Mix_PlayMusic: %s\n", Mix_GetError()); - return false; - } - Mix_VolumeMusic((UINT32)music_volume*128/31); - return true; -} - -void I_StopSong(INT32 handle) -{ - if (!midimode || !music) - return; - - (void)handle; - Mix_HaltMusic(); -} - -void I_UnRegisterSong(INT32 handle) -{ - if (!midimode || !music) - return; - - (void)handle; - Mix_FreeMusic(music); - music = NULL; -} - -#endif diff --git a/src/sdl12/sdlmain.h b/src/sdl12/sdlmain.h deleted file mode 100644 index d08236bdd..000000000 --- a/src/sdl12/sdlmain.h +++ /dev/null @@ -1,65 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 2006-2018 by Sonic Team Jr. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief System specific interface stuff. - -#ifndef __sdlmain__ -#define __sdlmain__ - -extern SDL_bool consolevent; -extern SDL_bool framebuffer; - -/** \brief The JoyInfo_s struct - - info about joystick -*/ -typedef struct SDLJoyInfo_s -{ - /// Joystick handle - SDL_Joystick *dev; - /// number of old joystick - int oldjoy; - /// number of axies - int axises; - /// scale of axises - INT32 scale; - /// number of buttons - int buttons; - /// number of hats - int hats; - /// number of balls - int balls; - -} SDLJoyInfo_t; - -/** \brief SDL info about joystick 1 -*/ -extern SDLJoyInfo_t JoyInfo; - -/** \brief joystick axis deadzone -*/ -#define SDL_JDEADZONE 153 -#undef SDL_JDEADZONE - -/** \brief SDL inof about joystick 2 -*/ -extern SDLJoyInfo_t JoyInfo2; - -void I_GetConsoleEvents(void); - -void SDLforceUngrabMouse(void); - -#endif diff --git a/src/sdl12/srb2.ttf b/src/sdl12/srb2.ttf deleted file mode 100644 index 53f4c6a28..000000000 Binary files a/src/sdl12/srb2.ttf and /dev/null differ diff --git a/src/slope_anchors.c b/src/slope_anchors.c new file mode 100644 index 000000000..69dc504a6 --- /dev/null +++ b/src/slope_anchors.c @@ -0,0 +1,491 @@ +// SONIC ROBO BLAST 2 KART +//----------------------------------------------------------------------------- +// Copyright (C) 2020 by James R. +// +// This program is free software distributed under the +// terms of the GNU General Public License, version 2. +// See the 'LICENSE' file for more details. +//----------------------------------------------------------------------------- +/// \brief Charyb's vertex slope anchors. +/// This file is self contained to avoid a Big Large merge conflict. + +/* +FIXME +FIXME +FIXME +FIXME WHEN 2.2 MERGE IS OVER, REFACTOR A LOT OF THE CODE IN P_SLOPES.C AND +FIXME MAKE THIS NOT REDUNDANT. +FIXME +FIXME +FIXME +*/ + +struct anchor_list +{ + mapthing_t ** anchors; + const vertex_t ** points; + fixed_t * closeness; + size_t count; +}; + +struct anchor_list floor_anchors; +struct anchor_list ceiling_anchors; + +static void * new_list (size_t n) { + return Z_Malloc(n, PU_LEVEL, NULL); +} + +static void make_new_anchor_list (struct anchor_list * list) { + list->anchors = new_list(list->count * sizeof *list->anchors); + list->points = new_list(list->count * sizeof *list->points); + list->closeness = new_list(list->count * sizeof *list->closeness); +} + +static void allocate_anchors (void) { + size_t i; + + floor_anchors.count = 0; + ceiling_anchors.count = 0; + + for (i = 0; i < nummapthings; ++i) + { + switch (mapthings[i].type) + { + case FLOOR_SLOPE_THING: + floor_anchors.count++; + break; + + case CEILING_SLOPE_THING: + ceiling_anchors.count++; + break; + } + } + + make_new_anchor_list(&floor_anchors); + make_new_anchor_list(&ceiling_anchors); +} + +static void +compare_vertex_distance +( + const vertex_t ** nearest, + fixed_t * nearest_distance, + const fixed_t origin_x, + const fixed_t origin_y, + const vertex_t * v +){ + const fixed_t distance = abs(P_AproxDistance + ( + origin_x - v->x, + origin_y - v->y + )); + + if (distance < (*nearest_distance)) + { + (*nearest) = v; + (*nearest_distance) = distance; + } +} + +static const vertex_t * +nearest_point +( + fixed_t * closeness, + mapthing_t * a, + const sector_t * sector +){ + const fixed_t x = a->x << FRACBITS; + const fixed_t y = a->y << FRACBITS; + + const vertex_t * v = NULL;/* shut compiler up, should never be NULL */ + + size_t i; + + (*closeness) = INT32_MAX; + + for (i = 0; i < sector->linecount; ++i) + { + compare_vertex_distance(&v, closeness, x, y, sector->lines[i]->v1); + compare_vertex_distance(&v, closeness, x, y, sector->lines[i]->v2); + } + + return v; +} + +static INT16 +anchor_height +( + const mapthing_t * a, + const sector_t * s +){ + const fixed_t x = a->x << FRACBITS; + const fixed_t y = a->y << FRACBITS; + + if (a->options & MTF_OBJECTFLIP) + { + return ( P_GetSectorCeilingZAt(s, x, y) >> FRACBITS ) - a->z; + } + else + { + return ( P_GetSectorFloorZAt(s, x, y) >> FRACBITS ) + a->z; + } +} + +static void +set_anchor +( + struct anchor_list * list, + mapthing_t * a +){ + const subsector_t * sub = R_PointInSubsector + ( + a->x << FRACBITS, + a->y << FRACBITS + ); + + const vertex_t * v; + + fixed_t closeness; + + v = nearest_point(&closeness, a, sub->sector); + + a->x = ( v->x >> FRACBITS ); + a->y = ( v->y >> FRACBITS ); + + a->z = anchor_height(a, sub->sector); + + list->anchors [list->count] = a; + list->points [list->count] = v; + list->closeness[list->count] = closeness; + + list->count++; +} + +static void build_anchors (void) { + size_t i; + + floor_anchors.count = 0; + ceiling_anchors.count = 0; + + for (i = 0; i < nummapthings; ++i) + { + switch (mapthings[i].type) + { + case FLOOR_SLOPE_THING: + set_anchor(&floor_anchors, &mapthings[i]); + break; + + case CEILING_SLOPE_THING: + set_anchor(&ceiling_anchors, &mapthings[i]); + break; + } + } +} + +static void +get_anchor +( + mapthing_t ** anchors, + fixed_t distances[3], + const struct anchor_list * list, + const INT16 tag, + const vertex_t * v +){ + size_t i; + + int k; + + for (i = 0; i < list->count; ++i) + { + if (list->points[i] == v && list->anchors[i]->extrainfo == tag) + { + for (k = 0; k < 3; ++k) + { + if (list->closeness[i] < distances[k]) + { + if (k == 0) + { + distances[2] = distances[1]; + distances[1] = distances[0]; + + anchors [2] = anchors [1]; + anchors [1] = anchors [0]; + } + else if (k == 1) + { + distances[2] = distances[1]; + anchors [2] = anchors [1]; + } + + distances[k] = list->closeness[i]; + + anchors[k] = list->anchors[i]; + + break; + } + else if (list->anchors[i] == anchors[k]) + { + break; + } + } + } + } +} + +static void +get_sector_anchors +( + mapthing_t ** anchors, + fixed_t distances[3], + const struct anchor_list * list, + const INT16 tag, + const sector_t * sector +){ + size_t i; + + for (i = 0; i < sector->linecount; ++i) + { + get_anchor(anchors, distances, list, tag, sector->lines[i]->v1); + get_anchor(anchors, distances, list, tag, sector->lines[i]->v2); + } +} + +static mapthing_t ** +find_closest_anchors +( + const sector_t * sector, + const struct anchor_list * list, + const INT16 tag +){ + fixed_t distances[3] = { INT32_MAX, INT32_MAX, INT32_MAX }; + + mapthing_t ** anchors; + + int last = 0; + + size_t i; + + if (list->count < 3) + { + I_Error("At least three slope anchors are required to make a slope."); + } + + anchors = Z_Malloc(3 * sizeof *anchors, PU_LEVEL, NULL); + + if (sector->numattached > 0) + { + for (i = 0; i < sector->numattached; ++i) + { + get_sector_anchors + (anchors, distances, list, tag, §ors[sector->attached[i]]); + } + } + else + { + get_sector_anchors(anchors, distances, list, tag, sector); + } + + if (distances[2] < INT32_MAX) + { + return anchors; + } + + if (distances[1] < INT32_MAX) + last = 2; + else if (distances[0] < INT32_MAX) + last = 1; + else + last = 0; + + if (sector->numattached > 0) + { + CONS_Printf("\nSearched for anchors in sectors...\n\n"); + + for (i = 0; i < sector->numattached; ++i) + { + CONS_Printf("#%s\n", sizeu1 (sector->attached[i])); + } + + I_Error( + "(Control Sector #%s)" + " Slope requires anchors (with Parameter %d)" + " near 3 of its target sectors' vertices (%d found)" + + "\n\nCheck the log to see which sectors were searched.", + + sizeu1 (sector - sectors), + tag, + last + ); + } + else + { + I_Error( + "(Sector #%s)" + " Slope requires anchors (with Parameter %d)" + " near 3 of its vertices (%d found)", + + sizeu1 (sector - sectors), + tag, + last + ); + } +} + +static pslope_t * +new_vertex_slope +( + mapthing_t ** anchors, + const INT16 flags +){ + pslope_t * slope = Z_Calloc(sizeof (pslope_t), PU_LEVEL, NULL); + const vector3_t anchorVertices[3] = { + {anchors[0]->x << FRACBITS, anchors[0]->y << FRACBITS, anchors[0]->z << FRACBITS}, + {anchors[1]->x << FRACBITS, anchors[1]->y << FRACBITS, anchors[1]->z << FRACBITS}, + {anchors[2]->x << FRACBITS, anchors[2]->y << FRACBITS, anchors[2]->z << FRACBITS} + }; + + if (flags & ML_NETONLY) + { + slope->flags |= SL_NOPHYSICS; + } + + if (flags & ML_NONET) + { + slope->flags |= SL_DYNAMIC; + } + + P_ReconfigureViaVertexes(slope, anchorVertices[0], anchorVertices[1], anchorVertices[2]); + //slope->refpos = 5; + + // Add to the slope list + slope->next = slopelist; + slopelist = slope; + + slopecount++; + slope->id = slopecount; + + return slope; +} + +static mapthing_t ** +flip_slope +( + mapthing_t ** origin, + const sector_t * sector +){ + mapthing_t * copy = Z_Malloc(3 * sizeof (mapthing_t), PU_LEVEL, NULL); + mapthing_t ** anchors = Z_Malloc(3 * sizeof (mapthing_t *), PU_LEVEL, NULL); + + size_t i; + + for (i = 0; i < 3; ++i) + { + memcpy(©[i], origin[i], sizeof copy[i]); + + copy[i].options ^= MTF_OBJECTFLIP; + copy[i].z = anchor_height(©[i], sector); + + anchors[i] = ©[i]; + } + + return anchors; +} + +static void +slope_sector +( + pslope_t ** slope, + pslope_t ** alt, + sector_t * sector, + const INT16 flags, + const struct anchor_list * list, + const INT16 tag +){ + mapthing_t ** anchors = find_closest_anchors(sector, list, tag); + + if (anchors != NULL) + { + (*slope) = new_vertex_slope(anchors, flags); + + /* Effect 6 - invert slope to opposite side */ + if (flags & ML_EFFECT6) + { + (*alt) = new_vertex_slope(flip_slope(anchors, sector), flags); + } + + sector->hasslope = true; + } +} + +static void +make_anchored_slope +( + const line_t * line, + const int plane +){ + enum + { + FLOOR = 0x1, + CEILING = 0x2, + }; + + INT16 flags = line->flags; + + const int side = ( flags & ML_NOCLIMB ) != 0; + + sector_t * s; + + if (side == 0 || flags & ML_TWOSIDED) + { + s = sides[line->sidenum[side]].sector; + + if (plane == (FLOOR|CEILING)) + { + flags &= ~ML_EFFECT6; + } + + if (plane & FLOOR) + { + slope_sector + (&s->f_slope, &s->c_slope, s, flags, &floor_anchors, line->tag); + } + + if (plane & CEILING) + { + slope_sector + (&s->c_slope, &s->f_slope, s, flags, &ceiling_anchors, line->tag); + } + } +} + +static void P_BuildSlopeAnchorList (void) { + allocate_anchors(); + build_anchors(); +} + +static void P_SetupAnchoredSlopes (void) { + enum + { + FLOOR = 0x1, + CEILING = 0x2, + }; + + size_t i; + + for (i = 0; i < numlines; ++i) + { + if (lines[i].special == LT_SLOPE_ANCHORS_FLOOR) + { + make_anchored_slope(&lines[i], FLOOR); + } + else if (lines[i].special == LT_SLOPE_ANCHORS_CEILING) + { + make_anchored_slope(&lines[i], CEILING); + } + else if (lines[i].special == LT_SLOPE_ANCHORS) + { + make_anchored_slope(&lines[i], FLOOR|CEILING); + } + } +} diff --git a/src/sounds.c b/src/sounds.c index 5581ade45..d06e521d0 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,7 +15,7 @@ #include "i_sound.h" #include "sounds.h" #include "r_defs.h" -#include "r_things.h" +#include "r_skins.h" #include "z_zone.h" #include "w_wad.h" #include "lua_script.h" @@ -32,936 +32,1010 @@ sfxinfo_t S_sfx[NUMSFX] = various flags. See soundflags_t. *****/ // S_sfx[0] needs to be a dummy for odd reasons. (don't modify this comment) -// name, singularity, priority, pitch, volume, data, length, skinsound, usefulness, lumpnum - {"none" , false, 0, 0, -1, NULL, 0, -1, -1, LUMPERROR}, +// name, singularity, priority, pitch, volume, data, length, skinsound, usefulness, lumpnum, caption + {"none" , false, 0, 0, -1, NULL, 0, -1, -1, LUMPERROR, "///////////////////////////////"}, // maximum length + + // A HUMBLE REQUEST FROM YOUR FRIENDLY NEIGHBORHOOD toaster! + // + // If you see a caption that's just "" (shows the lumpname in-game), + // and you intend to use the sound associated with it in a mod, + // PLEASE give it a caption through SOC or Lua. + // + // If the first character of the caption is '/', no caption will be + // produced; only do this for "unimportant" sounds that aren't used + // to indicate gameplay. + // + // (to whomstever updates the sounds list wiki page for 2.2, please + // either copy this comment across, or make sure its desire is + // codified in the initial paragraph of the page.) + // + // Closed Captioning may be a niche feature, but it's an important one. + // Thank you! ^u^ // Skin Sounds - {"altdi1", false, 192, 16, -1, NULL, 0, SKSPLDET1, -1, LUMPERROR}, - {"altdi2", false, 192, 16, -1, NULL, 0, SKSPLDET2, -1, LUMPERROR}, - {"altdi3", false, 192, 16, -1, NULL, 0, SKSPLDET3, -1, LUMPERROR}, - {"altdi4", false, 192, 16, -1, NULL, 0, SKSPLDET4, -1, LUMPERROR}, - {"altow1", false, 192, 16, -1, NULL, 0, SKSPLPAN1, -1, LUMPERROR}, - {"altow2", false, 192, 16, -1, NULL, 0, SKSPLPAN2, -1, LUMPERROR}, - {"altow3", false, 192, 16, -1, NULL, 0, SKSPLPAN3, -1, LUMPERROR}, - {"altow4", false, 192, 16, -1, NULL, 0, SKSPLPAN4, -1, LUMPERROR}, - {"victr1", false, 64, 16, -1, NULL, 0, SKSPLVCT1, -1, LUMPERROR}, - {"victr2", false, 64, 16, -1, NULL, 0, SKSPLVCT2, -1, LUMPERROR}, - {"victr3", false, 64, 16, -1, NULL, 0, SKSPLVCT3, -1, LUMPERROR}, - {"victr4", false, 64, 16, -1, NULL, 0, SKSPLVCT4, -1, LUMPERROR}, - {"gasp" , false, 64, 0, -1, NULL, 0, SKSGASP, -1, LUMPERROR}, - {"jump" , false, 140, 0, -1, NULL, 0, SKSJUMP, -1, LUMPERROR}, - {"pudpud", false, 64, 0, -1, NULL, 0, SKSPUDPUD, -1, LUMPERROR}, - {"putput", false, 64, 0, -1, NULL, 0, SKSPUTPUT, -1, LUMPERROR}, // not as high a priority - {"spin" , false, 100, 0, -1, NULL, 0, SKSSPIN, -1, LUMPERROR}, - {"spndsh", false, 64, 1, -1, NULL, 0, SKSSPNDSH, -1, LUMPERROR}, - {"thok" , false, 96, 0, -1, NULL, 0, SKSTHOK, -1, LUMPERROR}, - {"zoom" , false, 120, 1, -1, NULL, 0, SKSZOOM, -1, LUMPERROR}, - {"skid", false, 64, 32, -1, NULL, 0, SKSSKID, -1, LUMPERROR}, + {"altdi1", false, 192, 16, -1, NULL, 0, SKSPLDET1, -1, LUMPERROR, "Dying"}, + {"altdi2", false, 192, 16, -1, NULL, 0, SKSPLDET2, -1, LUMPERROR, "Dying"}, + {"altdi3", false, 192, 16, -1, NULL, 0, SKSPLDET3, -1, LUMPERROR, "Dying"}, + {"altdi4", false, 192, 16, -1, NULL, 0, SKSPLDET4, -1, LUMPERROR, "Dying"}, + {"altow1", false, 192, 16, -1, NULL, 0, SKSPLPAN1, -1, LUMPERROR, "Ring loss"}, + {"altow2", false, 192, 16, -1, NULL, 0, SKSPLPAN2, -1, LUMPERROR, "Ring loss"}, + {"altow3", false, 192, 16, -1, NULL, 0, SKSPLPAN3, -1, LUMPERROR, "Ring loss"}, + {"altow4", false, 192, 16, -1, NULL, 0, SKSPLPAN4, -1, LUMPERROR, "Ring loss"}, + {"victr1", false, 64, 16, -1, NULL, 0, SKSPLVCT1, -1, LUMPERROR, "/"}, + {"victr2", false, 64, 16, -1, NULL, 0, SKSPLVCT2, -1, LUMPERROR, "/"}, + {"victr3", false, 64, 16, -1, NULL, 0, SKSPLVCT3, -1, LUMPERROR, "/"}, + {"victr4", false, 64, 16, -1, NULL, 0, SKSPLVCT4, -1, LUMPERROR, "/"}, + {"gasp" , false, 64, 0, -1, NULL, 0, SKSGASP, -1, LUMPERROR, "Bubble gasp"}, + {"jump" , false, 140, 0, -1, NULL, 0, SKSJUMP, -1, LUMPERROR, "Jump"}, + {"pudpud", false, 64, 0, -1, NULL, 0, SKSPUDPUD, -1, LUMPERROR, "Tired flight"}, + {"putput", false, 64, 0, -1, NULL, 0, SKSPUTPUT, -1, LUMPERROR, "Flight"}, // not as high a priority + {"spin" , false, 100, 0, -1, NULL, 0, SKSSPIN, -1, LUMPERROR, "Spin"}, + {"spndsh", false, 64, 1, -1, NULL, 0, SKSSPNDSH, -1, LUMPERROR, "Spindash"}, + {"thok" , false, 96, 0, -1, NULL, 0, SKSTHOK, -1, LUMPERROR, "Thok"}, + {"zoom" , false, 120, 1, -1, NULL, 0, SKSZOOM, -1, LUMPERROR, "Spin launch"}, + {"skid", false, 64, 32, -1, NULL, 0, SKSSKID, -1, LUMPERROR, "Skid"}, // Ambience/background objects/etc - {"ambint", true, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"ambint", true, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Obnoxious disco music"}, - {"alarm", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"buzz1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"buzz2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"buzz3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"buzz4", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"crumbl", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Platform Crumble Tails 03-16-2001 - {"fire", false, 8, 32, -1, NULL, 0, -1, -1, LUMPERROR}, - {"grind", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"laser", true, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mswing", false, 16, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"pstart", false, 100, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"pstop", false, 100, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"steam1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Tails 06-19-2001 - {"steam2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Tails 06-19-2001 - {"wbreak", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"alarm", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Alarm"}, + {"buzz1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric zap"}, + {"buzz2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric zap"}, + {"buzz3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wacky worksurface"}, + {"buzz4", true, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Buzz"}, + {"crumbl", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crumbling"}, // Platform Crumble Tails 03-16-2001 + {"fire", false, 8, 32, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"}, + {"grind", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic grinding"}, + {"laser", true, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Laser hum"}, + {"mswing", false, 16, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Swinging mace"}, + {"pstart", false, 100, 0, -1, NULL, 0, -1, -1, LUMPERROR, "/"}, + {"pstop", false, 100, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crusher stomp"}, + {"steam1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Steam jet"}, // Tails 06-19-2001 + {"steam2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Steam jet"}, // Tails 06-19-2001 + {"wbreak", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wood breaking"}, + {"ambmac", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Machinery"}, + {"spsmsh", true, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy impact"}, - {"rainin", true, 24, 4, -1, NULL, 0, -1, -1, LUMPERROR}, - {"litng1", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"litng2", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"litng3", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"litng4", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"athun1", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"athun2", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR}, + {"rainin", true, 24, 4, -1, NULL, 0, -1, -1, LUMPERROR, "Rain"}, + {"litng1", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning"}, + {"litng2", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning"}, + {"litng3", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning"}, + {"litng4", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning"}, + {"athun1", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder"}, + {"athun2", false, 16, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder"}, - {"amwtr1", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"amwtr2", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"amwtr3", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"amwtr4", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"amwtr5", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"amwtr6", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"amwtr7", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"amwtr8", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bubbl1", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bubbl2", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bubbl3", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bubbl4", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bubbl5", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"floush", false, 16, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"splash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"splish", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Splish Tails 12-08-2000 - {"wdrip1", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wdrip2", false, 8 , 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wdrip3", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wdrip4", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wdrip5", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wdrip6", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wdrip7", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wdrip8", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wslap", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Water Slap Tails 12-13-2000 + {"amwtr1", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"}, + {"amwtr2", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"}, + {"amwtr3", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"}, + {"amwtr4", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"}, + {"amwtr5", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"}, + {"amwtr6", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"}, + {"amwtr7", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"}, + {"amwtr8", false, 12, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stream"}, + {"bubbl1", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"}, + {"bubbl2", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"}, + {"bubbl3", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"}, + {"bubbl4", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"}, + {"bubbl5", false, 11, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"}, + {"floush", false, 16, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"}, + {"splash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Glub"}, // labeling sfx_splash as "glub" and sfx_splish as "splash" seems wrong but isn't + {"splish", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"}, // Splish Tails 12-08-2000 + {"wdrip1", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drip"}, + {"wdrip2", false, 8 , 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drip"}, + {"wdrip3", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drip"}, + {"wdrip4", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drip"}, + {"wdrip5", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drip"}, + {"wdrip6", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drip"}, + {"wdrip7", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drip"}, + {"wdrip8", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drip"}, + {"wslap", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"}, // Water Slap Tails 12-13-2000 - {"doora1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"doorb1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"doorc1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"doorc2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"doord1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"doord2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"eleva1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"eleva2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"eleva3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"elevb1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"elevb2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"elevb3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"doora1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding open"}, + {"doorb1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding open"}, + {"doorc1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wooden door opening"}, + {"doorc2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Slamming shut"}, + {"doord1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Creaking open"}, + {"doord2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Slamming shut"}, + {"eleva1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starting elevator"}, + {"eleva2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Moving elevator"}, + {"eleva3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stopping elevator"}, + {"elevb1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starting elevator"}, + {"elevb2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Moving elevator"}, + {"elevb3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Stopping elevator"}, - {"ambin2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"lavbub", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rocks1", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rocks2", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rocks3", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rocks4", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rumbam", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rumble", false, 64, 24, -1, NULL, 0, -1, -1, LUMPERROR}, + {"ambin2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Natural vibrations"}, + {"lavbub", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Bubbling lava"}, + {"rocks1", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Falling rocks"}, + {"rocks2", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Falling rocks"}, + {"rocks3", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Falling rocks"}, + {"rocks4", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Falling rocks"}, + {"rumbam", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, + {"rumble", false, 64, 24, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, // Game objects, etc - {"appear", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Boing! - {"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Boing! - {"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cgot" , true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Got Emerald! Tails 09-02-2001 - {"cybdth", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"deton", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"ding", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"dmpain", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"drown", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"fizzle", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"gbeep", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Grenade beep - {"ghit" , false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"gloop", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"gspray", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"gravch", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"itemup", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"jet", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"jshard", true, 167, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"lose" , false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"lvpass", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mindig", false, 8, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mixup", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"pogo" , false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"pop" , false, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rail1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rail2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"rlaunc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"shield", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"shldls", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"spdpad", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"spkdth", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"spring", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"statu1", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"statu2", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"strpst", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Starpost Sound Tails 07-04-2002 - {"supert", true, 127, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"telept", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"tink" , false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"token" , true, 224, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // SS token - {"trfire", true, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"trpowr", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"turhit", false, 40, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wdjump", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mswarp", false, 60, 16, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mspogo", false, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"appear", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Appearing platform"}, + {"bkpoof", false, 70, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon pow"}, + {"bnce1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, // Boing! + {"bnce2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Scatter"}, // Boing! + {"cannon", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"}, + {"cgot" , true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Emerald"}, // Got Emerald! Tails 09-02-2001 + {"cybdth", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Explosion"}, + {"deton", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Threatening beeping"}, + {"ding", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Ding"}, + {"dmpain", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Machine damage"}, + {"drown", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"}, + {"fizzle", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Electric fizzle"}, + {"gbeep", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Threatening beeping"}, // Grenade beep + {"wepfir", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing weapon"}, // defaults to thok + {"ghit" , false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Goop splash"}, + {"gloop", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"}, + {"gspray", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Goop sling"}, + {"gravch", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Recycler"}, + {"itemup", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, + {"jet", false, 8, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jet engine"}, + {"jshard", true, 167, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Life transfer"}, // placeholder repurpose; original string was "Got Shard" + {"lose" , false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Failure"}, + {"lvpass", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spinning signpost"}, + {"mindig", false, 8, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Tunnelling"}, + {"mixup", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Teleport"}, + {"monton", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Golden Monitor activated"}, + {"pogo" , false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical pogo"}, + {"pop" , false, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop"}, + {"rail1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing rail"}, + {"rail2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crashing rail"}, + {"rlaunc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing"}, + {"shield", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pity Shield"}, // generic GET! + {"wirlsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whirlwind Shield"}, // Whirlwind GET! + {"forcsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Force Shield"}, // Force GET! + {"frcssg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weak Force Shield"}, // Force GET...? (consider making a custom shield with this instead of a single-hit force shield!) + {"elemsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Elemental Shield"}, // Elemental GET! + {"armasg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Armageddon Shield"}, // Armaggeddon GET! + {"attrsg", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction Shield"}, // Attract GET! + {"shldls", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"}, // You LOSE! + {"spdpad", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Speedpad"}, + {"spkdth", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spiked"}, + {"spring", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spring"}, + {"statu1", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Pushing a statue"}, + {"statu2", true, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Pushing a statue"}, + {"strpst", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, + {"supert", true, 127, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Transformation"}, + {"telept", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dash"}, + {"tink" , false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Tink"}, + {"token" , true, 224, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Token"}, + {"trfire", true, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Laser fired"}, + {"trpowr", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, + {"turhit", false, 40, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Laser hit"}, + {"wdjump", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Whirlwind jump"}, + {"shrpsp", true, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spincushion"}, + {"shrpgo", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"}, + {"mswarp", false, 60, 16, -1, NULL, 0, -1, -1, LUMPERROR, "Spinning out"}, + {"mspogo", true, 60, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Breaking through"}, + {"boingf", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bouncing"}, + {"corkp", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork fired"}, + {"corkh", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cork hit"}, + {"alart", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Caught red handed!"}, + {"vwre", false, 200, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Clone fighter!"}, + {"bowl", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bowling"}, + {"chuchu", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Train horn"}, + {"sprong", false, 112, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power spring"}, + {"lvfal1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rumble"}, + {"pscree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "SCREE!"}, + {"iceb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ice crack"}, + {"shattr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shattering"}, + {"antiri", true, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Depletion"}, // Menu, interface - {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"dwnind", false, 212, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"emfind", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"flgcap", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"menu1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"oneup", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"ptally", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Point tally is identical to menu for now - {"radio", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"wepchg", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Weapon switch is identical to menu for now - {"wtrdng", true, 212, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // make sure you can hear the DING DING! Tails 03-08-2000 - {"zelda", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"chchng", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"}, + {"dwnind", false, 212, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Thinking about air"}, + {"emfind", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Radar beep"}, + {"flgcap", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flag captured"}, + {"menu1", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Menu beep"}, + {"oneup", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "One-up"}, + {"ptally", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Tally"}, // Point tally is identical to menu for now + {"radio", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Notification"}, + {"wepchg", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Weapon change"}, // Weapon switch is identical to menu for now + {"wtrdng", true, 212, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, // make sure you can hear the DING DING! Tails 03-08-2000 + {"zelda", false, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, + {"adderr", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Error"}, + {"notadd", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Reject"}, + {"addfil", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accept"}, // NiGHTS - {"ideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"xideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Xmas - {"nbmper", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"nxbump", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Xmas - {"ncitem", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"nxitem", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Xmas - {"ngdone", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"nxdone", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Xmas - {"drill1", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"drill2", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"ncspec", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Tails 12-15-2003 - {"nghurt", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"ngskid", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"hoop1", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"hoop2", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"hoop3", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"hidden", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"prloop", false, 104, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"timeup", true, 256, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"ideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"}, + {"xideya", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Success"}, // Xmas + {"nbmper", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, + {"nxbump", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, // Xmas + {"ncchip", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got chip"}, + {"ncitem", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got special"}, + {"nxitem", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got special"}, // Xmas + {"ngdone", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonus time start"}, + {"nxdone", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonus time start"}, // Xmas + {"drill1", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drill"}, + {"drill2", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drill"}, + {"ncspec", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power-up"}, // Tails 12-15-2003 + {"nghurt", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"}, + {"ngskid", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Force stop"}, + {"hoop1", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hoop"}, + {"hoop2", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hoop+"}, + {"hoop3", false, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hoop++"}, + {"hidden", false, 204, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, + {"prloop", false, 104, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Gust of wind"}, + {"timeup", true, 256, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous Countdown"}, + {"ngjump", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, + {"peww", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pew"}, + + // Halloween + {"lntsit", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cacolantern awake"}, + {"lntdie", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Cacolantern death"}, + {"pumpkn", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pumpkin smash"}, // idspispopd + {"ghosty", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Laughter"}, // Mario - {"koopfr" , true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario1", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario2", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario3", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario4", true, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario5", false, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario6", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario7", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario8", false, 48, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"mario9", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"marioa", true, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"thwomp", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR}, + {"koopfr" , true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Fire"}, + {"mario1", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hit"}, + {"mario2", false, 127, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bonk"}, + {"mario3", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power-up"}, + {"mario4", true, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got coin"}, + {"mario5", false, 78, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boot-stomp"}, + {"mario6", false, 60, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, + {"mario7", false, 32, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Fire"}, + {"mario8", false, 48, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"}, + {"mario9", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Emerging power-up"}, + {"marioa", true, 192, 0, -1, NULL, 0, -1, -1, LUMPERROR, "One-up"}, + {"thwomp", true, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Thwomp"}, // Black Eggman - {"bebomb", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bechrg", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"becrsh", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bedeen", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bedie1", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bedie2", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"beeyow", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"befall", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"befire", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"beflap", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"begoop", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"begrnd", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"behurt", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bejet1", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"belnch", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"beoutb", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"beragh", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"beshot", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bestep", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bestp2", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bewar1", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bewar2", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bewar3", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bewar4", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bexpld", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"bgxpld", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, + {"bebomb", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Big explosion"}, + {"bechrg", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, + {"becrsh", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Crash"}, + {"bedeen", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic crash"}, + {"bedie1", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Eggman crying"}, + {"bedie2", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Eggman crying"}, + {"beeyow", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Failing machinery"}, + {"befall", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic slam"}, + {"befire", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Firing goop"}, + {"beflap", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical jump"}, + {"begoop", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful shot"}, + {"begrnd", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic grinding"}, + {"behurt", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Eggman shocked"}, + {"bejet1", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Jetpack charge"}, + {"belnch", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical jump"}, + {"beoutb", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Failed shot"}, + {"beragh", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Eggman screaming"}, + {"beshot", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Firing missile"}, + {"bestep", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical stomp"}, + {"bestp2", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical stomp"}, + {"bewar1", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Eggman laughing"}, + {"bewar2", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Eggman laughing"}, + {"bewar3", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Eggman laughing"}, + {"bewar4", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Eggman laughing"}, + {"bexpld", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Explosion"}, + {"bgxpld", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Explosion"}, // Cybrakdemon - {"beelec", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"brakrl", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, - {"brakrx", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, + {"beelec", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Electricity"}, + {"brakrl", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Rocket launch"}, + {"brakrx", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Rocket explosion"}, // Sonic 1 sounds - {"s1a0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1a1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1a2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Monty Mole attach - {"s1a3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1a4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1a5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1a6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1a7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1a8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1a9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1aa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1ab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Monty Mole twitch - {"s1ac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Misc. obstacle destroyed - {"s1ad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1ae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1af", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Toggle all items - {"s1b5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1b9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1ba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Toggle item - {"s1bb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Thwomp drop - {"s1bc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1bd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Ballhog bounce - {"s1be", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1bf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Monokuma death - {"s1c2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1c9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Item hit w/ voices off - {"s1ca", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1cb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1cc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1cd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1ce", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s1cf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s1a0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Monty Mole attach + {"s1a3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1a9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1aa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Monty Mole twitch + {"s1ac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Misc. obstacle destroyed + {"s1ad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1af", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Toggle all items + {"s1b5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1b9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Toggle item + {"s1bb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Thwomp drop + {"s1bc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Ballhog bounce + {"s1be", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1bf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Monokuma death + {"s1c2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1c9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Item hit w/ voices off + {"s1ca", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1ce", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s1cf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Sonic 2 sounds - {"s220", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s221", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Lap sound - {"s222", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s223", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s224", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s225", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s226", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s227", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s228", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s229", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s22a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s22b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s22c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s22d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s22e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s22f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s230", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s231", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s232", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s233", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s234", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s235", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s236", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s237", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s238", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s239", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s23a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s23b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s23c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Drift boost - {"s23d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s23e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Title screen opening - {"s23f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s240", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s241", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s242", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s243", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s244", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s245", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s246", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s247", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s248", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s249", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s24a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s24b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s24c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s24d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s24e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s24f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s250", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s251", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s252", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s253", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // 1st place finish - {"s254", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s255", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s256", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s257", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s258", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s259", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Item clashing - {"s25a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s25b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s25c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s25d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Perfect start boost - {"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s263", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s264", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s265", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s266", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s267", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s268", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s269", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s26a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s26b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s26c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s26d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Missed checkpoint - {"s26e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s26f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s270", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s220", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s221", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Lap sound + {"s222", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s223", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s224", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s225", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s226", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s227", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s228", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s229", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s22f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s230", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s231", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s232", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s233", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s234", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s235", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s236", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s237", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s238", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s239", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Drift boost + {"s23d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s23e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Title screen opening + {"s23f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s240", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s241", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s242", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s243", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s244", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s245", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s246", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s247", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s248", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s249", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s24f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s250", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s251", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s252", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s253", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // 1st place finish + {"s254", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s255", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s256", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s257", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s258", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s259", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Item clashing + {"s25a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s25f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Perfect start boost + {"s260", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s261", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s262", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s263", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s264", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s265", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s266", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s267", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s268", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s269", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Missed checkpoint + {"s26e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s26f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s270", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // S3&K sounds - {"s3k33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k3a", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart item shield - {"s3k3b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k3c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Flame Shield spawned - {"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Bubble Shield spawned - {"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Thunder Shield spawned - {"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k43", false, 96, 48, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k44", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Bubble Shield reflect - {"s3k45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart AIZ dust - {"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart bump sound - {"s3k4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k4e", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart explosion - {"s3k4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k54", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // MetalSonic shot fire - {"s3k55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k5a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k5c", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Mine tick - {"s3k5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k64", false, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k65", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Blue Spheres - {"s3k66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart final lap - {"s3k69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k6a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart finish - {"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k6f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k70", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k74", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k75", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k76", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k77", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k7a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k7b", false, 96, 16, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart successful hit - {"s3k7c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k7d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k7e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k7f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k80", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k81", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k82", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k83", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Overcharged start boost - {"s3k84", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k85", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k86", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k87", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k88", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Jawz target - {"s3k8a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k8b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k8c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k8d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k8e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k8f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k92", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Hyudoro use - {"s3k93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k94", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k95", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k96", false, 128, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Orbinaut - {"s3k97", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k98", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k99", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k9a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k9b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k9c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k9d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k9e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3k9f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart drift spark gain - {"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart 3,2,1 - {"s3ka8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3ka9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kaa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart GO! - {"s3kae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kaf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kb9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbcs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbcl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbdl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbes", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbfs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kbfl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc0s", false, 192, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Jawz - {"s3kc0l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc1s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc2s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc2l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc4l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc8s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kc9l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcas", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart respawn - {"s3kcal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kccs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kccl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcdl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kces", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcfs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kcfl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd0s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd0l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd1s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd1l", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd2s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd2l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd4l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd8s", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // Sharp Spin (maybe use the long/L version?) - {"s3kd8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kd9l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kdas", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kdal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kdbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"s3kdbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"s3k2b", true, 120, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Emerald"}, // Got Emerald! + {"s3k33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // stereo in original game, identical to latter + {"s3k34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, // mono in original game, identical to previous + {"s3k35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Hurt"}, + {"s3k36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Skid"}, + {"s3k37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spiked"}, + {"s3k38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble gasp"}, + {"s3k39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"}, + {"s3k3a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shield"}, // Kart item shield + {"s3k3b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"}, + {"s3k3c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spin"}, + {"s3k3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop"}, + {"s3k3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame Shield"}, // Kart Flame Shield spawned + {"s3k3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble Shield"}, // Kart Bubble Shield spawned + {"s3k40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction blast"}, + {"s3k41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Thunder Shield"}, // Kart Thunder Shield spawned + {"s3k42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Twinspin"}, + {"s3k43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flame burst"}, + {"s3k44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble bounce"}, // Kart Bubble Shield reflect + {"s3k45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lightning zap"}, + {"s3k46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Transformation"}, + {"s3k47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising dust"}, // Kart AIZ dust + {"s3k48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pulse"}, + {"s3k49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"}, // Kart bump sound + {"s3k4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Grab"}, + {"s3k4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Splash"}, + {"s3k4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"}, + {"s3k4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing bullet"}, + {"s3k4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Big explosion"}, // Kart explosion + {"s3k4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"}, + {"s3k50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Siren"}, + {"s3k51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling"}, + {"s3k52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spike"}, + {"s3k53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, + {"s3k54", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Firing"}, // MetalSonic shot fire + {"s3k55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical movement"}, + {"s3k56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy landing"}, + {"s3k57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, + {"s3k58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical movement"}, + {"s3k59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crumbling"}, + {"s3k5a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, + {"s3k5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Menu beep"}, + {"s3k5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric spark"}, // Kart Mine tick + {"s3k5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Heavy hit"}, + {"s3k5e", false, 127, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Releasing charge"}, + {"s3k5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crusher stomp"}, + {"s3k60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accelerating"}, + {"s3k61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drilling"}, + {"s3k62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, + {"s3k63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, + {"s3k64", false, 64, 2, -1, NULL, 0, -1, -1, LUMPERROR, "Clatter"}, + {"s3k65", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got sphere"}, // Blue Spheres + {"s3k66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage end"}, + {"s3k67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing missile"}, + {"s3k68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Discovery"}, // Kart final lap + {"s3k69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Switch click"}, + {"s3k6a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Special stage clear"}, // Kart finish + {"s3k6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Punch"}, + {"s3k6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, + {"s3k6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3k6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Mechanical damage"}, + {"s3k6f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, + {"s3k70", true, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, + {"s3k71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Basic Shield"}, + {"s3k72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Movement"}, + {"s3k73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, + {"s3k74", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Gong"}, + {"s3k75", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising"}, + {"s3k76", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Click"}, + {"s3k77", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Balloon pop"}, + {"s3k78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnet"}, + {"s3k79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Electric charge"}, + {"s3k7a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising from lava"}, + {"s3k7b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Soft bounce"}, + {"s3k7c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnet"}, + {"s3k7d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3k7e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dust"}, + {"s3k7f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Freeze"}, + {"s3k80", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ice spike burst"}, + {"s3k81", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, + {"s3k82", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Burst"}, + {"s3k83", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Collapsing"}, + {"s3k84", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, + {"s3k85", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering down"}, + {"s3k86", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Alarm"}, + {"s3k87", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, + {"s3k88", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Metallic squeak"}, + {"s3k89", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Advanced tech"}, + {"s3k8a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Boing"}, + {"s3k8b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powerful hit"}, + {"s3k8c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Humming power"}, + {"s3k8d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "/"}, + {"s3k8e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Accelerating"}, + {"s3k8f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Opening"}, + {"s3k90", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Impact"}, + {"s3k91", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Closed"}, + {"s3k92", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ghost"}, + {"s3k93", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Gas release"}, + {"s3k94", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spike"}, + {"s3k95", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Lava burst"}, + {"s3k96", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Landing"}, + {"s3k97", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind"}, + {"s3k98", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling spike"}, + {"s3k99", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bounce"}, + {"s3k9a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Click"}, + {"s3k9b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Crusher stomp"}, + {"s3k9c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Super Emerald"}, + {"s3k9d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Targeting"}, + {"s3k9e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wham"}, + {"s3k9f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Transformation"}, + {"s3ka0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"}, + {"s3ka1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3ka2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Launch"}, + {"s3ka3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising charge"}, + {"s3ka4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Powering up"}, + {"s3ka5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3ka6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Attraction fizzle"}, + {"s3ka7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Countdown beep"}, + {"s3ka8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Energy"}, + {"s3ka9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, + {"s3kaa", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, + {"s3kab", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kab9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kaba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabe", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kabf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spindash"}, + {"s3kac", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Got Continue"}, + {"s3kad", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "GO!"}, + {"s3kae", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pinball flipper"}, + {"s3kaf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "To Special Stage"}, + {"s3kb0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Score"}, + {"s3kb1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spring"}, + {"s3kb2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Failure"}, + {"s3kb3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, + {"s3kb4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Explosion"}, + {"s3kb5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Clink"}, + {"s3kb6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spin launch"}, + {"s3kb7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Tumbler"}, + {"s3kb8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spinning signpost"}, + {"s3kb9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ring loss"}, + {"s3kba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flight"}, + {"s3kbb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Tired flight"}, + {"s3kbcs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3kbcl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // long version of previous + {"s3kbds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying fortress"}, + {"s3kbdl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying fortress"}, // ditto + {"s3kbes", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying"}, + {"s3kbel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flying"}, // ditto + {"s3kbfs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"}, + {"s3kbfl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"}, // ditto + {"s3kc0s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"}, + {"s3kc0l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turbine"}, // ditto + {"s3kc1s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Fan"}, + {"s3kc1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Fan"}, // ditto + {"s3kc2s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"}, + {"s3kc2l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Flamethrower"}, // ditto + {"s3kc3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Levitation"}, + {"s3kc3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Levitation"}, // ditto + {"s3kc4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"}, + {"s3kc4l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Firing laser"}, // ditto + {"s3kc5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"}, + {"s3kc5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Revving up"}, // ditto + {"s3kc6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, + {"s3kc6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Orbiting"}, // ditto + {"s3kc7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, + {"s3kc7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aiming"}, // ditto + {"s3kc8s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"}, + {"s3kc8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sliding"}, // ditto + {"s3kc9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Swinging"}, + {"s3kc9l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Swinging"}, // ditto + {"s3kcas", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Energy"}, + {"s3kcal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Energy"}, // ditto + {"s3kcbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, + {"s3kcbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, // ditto + {"s3kccs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bursting"}, + {"s3kccl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bursting"}, // ditto + {"s3kcds", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, + {"s3kcdl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ominous rumbling"}, // ditto + {"s3kces", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Wind tunnel"}, + {"s3kcel", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dust devil"}, // ditto + {"s3kcfs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3kcfl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto + {"s3kd0s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising"}, + {"s3kd0l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Rising"}, // ditto + {"s3kd1s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3kd1l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto + {"s3kd2s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Turning"}, + {"s3kd2l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Moving chain"}, // ditto + {"s3kd3s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Digging"}, + {"s3kd3l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Digging"}, // ditto + {"s3kd4s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"}, + {"s3kd4l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Engine"}, // ditto + {"s3kd5s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling lava"}, + {"s3kd5l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Falling lava"}, // ditto + {"s3kd6s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"s3kd6l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // ditto + {"s3kd7s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Movement"}, + {"s3kd7l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Movement"}, // ditto + {"s3kd8s", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, "Acceleration"}, // Sharp Spin (maybe use the long/L version?) + {"s3kd8l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Acceleration"}, // ditto + {"s3kd9s", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnetism"}, + {"s3kd9l", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Magnetism"}, // ditto + {"s3kdas", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Click"}, + {"s3kdal", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Click"}, // ditto + {"s3kdbs", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running on water"}, + {"s3kdbl", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Running on water"}, // ditto // 3D Blast sounds (the "missing" ones are direct copies of S3K's, no minor differences what-so-ever) - {"3db06", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Bumper stolen - {"3db09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"3db14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"3db16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"3db06", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Collection"}, + {"3db09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Peep"}, + {"3db14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Chirp"}, + {"3db16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Sonic CD sounds - {"cdfm00", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Undercharged start boost - {"cdfm01", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Sneaker boost - {"cdfm02", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm03", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm04", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm05", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm06", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm07", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm08", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm10", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm11", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm12", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm13", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm15", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm17", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Brake drift ambient - {"cdfm18", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm19", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // CD SS1 UFO death - {"cdfm20", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm21", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm22", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm23", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm24", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm25", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm26", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm27", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm28", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Eggman item landing - {"cdfm29", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm31", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm39", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Mine deployed - {"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm64", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm70", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Trail item dragging - {"cdfm71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // CD SS1 UFO hit - {"cdfm74", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm75", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm76", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm77", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdfm79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"cdpcm9", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // No damage taken + {"cdfm00", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Skid"}, + {"cdfm01", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm02", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Jump"}, + {"cdfm03", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Dying"}, + {"cdfm04", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ring loss"}, + {"cdfm05", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Sparkle"}, + {"cdfm06", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop"}, + {"cdfm07", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Shield"}, + {"cdfm08", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Spring"}, + {"cdfm09", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm10", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm11", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm12", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm13", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm14", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm15", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm16", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm17", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm18", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm19", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm20", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm21", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm22", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm23", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm24", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm25", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm26", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm27", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm28", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm29", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Bubble gasp"}, + {"cdfm30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Starpost"}, + {"cdfm31", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, + {"cdfm32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Drowning"}, + {"cdfm39", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"}, + {"cdfm41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Extra time"}, + {"cdfm45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm46", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Aquaphobia"}, + {"cdfm50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm51", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Warp"}, + {"cdfm57", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm59", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Speed boost"}, + {"cdfm63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm64", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm70", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm71", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm72", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm73", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm74", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm75", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm76", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm77", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm78", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdfm79", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdpcm0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Future."}, + {"cdpcm1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Past."}, + {"cdpcm2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "All right!"}, + {"cdpcm3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "I'm outta here..."}, + {"cdpcm4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Yes!"}, + {"cdpcm5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Yeah!"}, + {"cdpcm6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Giggles"}, + {"cdpcm7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Eep!"}, + {"cdpcm8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"cdpcm9", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Bumper"}, // Knuckles Chaotix sounds - {"kc2a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc2b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc2c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc2d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc2e", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Item box gotten - {"kc2f", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Spring pad - {"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc31", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // NO CONTEST explosion - {"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Voting roulette - {"kc3a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc3b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc3c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Unlock everything cheat - {"kc43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc46", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Shrink use - {"kc47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Vote picked - {"kc49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Voting beep - {"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR}, // NO CONTEST debris ambience - {"kc52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc57", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // SPB locked in - {"kc58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc59", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Shrink - {"kc5a", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Grow - {"kc5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc64", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // SPB ambient - {"kc65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"kc6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, + {"kc2a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2e", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc2f", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc31", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc37", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc38", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc39", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc3f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc40", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc41", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc42", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Confirm"}, + {"kc43", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc44", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc45", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc46", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc47", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc48", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Select"}, + {"kc49", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop-shot"}, + {"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"}, + {"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc52", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc53", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc54", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc55", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc56", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc57", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Sheer terror"}, + {"kc58", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc59", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Shrink"}, + {"kc5a", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, "Grow"}, + {"kc5b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc5f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc60", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc61", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc62", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc63", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc64", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Terrifying rumble"}, + {"kc65", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power down"}, + {"kc66", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc67", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc68", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc69", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Ascending"}, + {"kc6c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"kc6e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SRB2kart - {"slip", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Spinout - {"screec", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Tight turning screech - {"drift", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Drifting ambient - {"ruburn", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Rubber-burn turn ambient - {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Respawn Drop Dash - {"tossed", false, 192, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Item fired - {"itpick", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Pick up HUD drop - {"peel", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Edited S25A for banana landing - {"hogbom", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Ballhog explosions - {"zio3", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Thunder Shield use - {"kpogos", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Pogo Spring use - {"alarmi", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Invincibility alarm - {"alarmg", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Grow alarm - {"kinvnc", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Invincibility music - {"kgrow", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Grow music - {"itrol1", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Roulette spinning - {"itrol2", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"itrol3", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"itrol4", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"itrol5", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"itrol6", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"itrol7", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"itrol8", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, - {"itrolf", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Roulette end - {"itrolm", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Roulette end (mashed) - {"itrolk", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Roulette end (karma enhanced) - {"itrole", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Roulette end (Eggman) - {"vroom", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Kart Krew opening vroom - {"chaooo", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Chao audience cheer - {"yeeeah", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Voting picks you - {"noooo1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Voting picks hell (by chance) - {"noooo2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Voting picks hell (on purpose) - {"ruby1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Phantom Ruby charge up - {"ruby2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Phantom Ruby teleport - {"tcart", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Twinkle Cart - {"bfare", false, 128, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Pleasure Castle fanfare - {"merry", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Pleasure Castle merry-go-round ambient - {"bowlh", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Pleasure Castle pins - {"tppop", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Pleasure Castle bombs - {"hsdoor", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Red Barrage Area door - {"hstrn", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Red Barrage Area train - {"aspkb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Red Barrage Area spikeballs - {"wind1", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Midnight Channel monsters - {"fire2", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR}, - {"chain", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Mementos Reaper - {"mkuma", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Trigger Happy Havoc Monokuma - {"toada", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Arid Sands Toad scream - {"bhurry", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // v1.0.2 Battle overtime - {"bsnipe", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Banana sniping - {"sploss", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Down to yellow sparks - {"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // :shitsfree: - {"dbgsal", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR}, // Debug notification - {"cock", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR}, // Hammer cocks, bang bang + {"slip", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Spinout + {"screec", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Tight turning screech + {"drift", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Drifting ambient + {"ruburn", false, 48, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Rubber-burn turn ambient + {"ddash", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Respawn Drop Dash + {"tossed", false, 192, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Item fired + {"itpick", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pick up HUD drop + {"peel", false, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Edited S25A for banana landing + {"hogbom", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Ballhog explosions + {"zio3", false, 128, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Thunder Shield use + {"kpogos", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pogo Spring use + {"alarmi", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Invincibility alarm + {"alarmg", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Grow alarm + {"kinvnc", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Invincibility music + {"kgrow", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Grow music + {"itrol1", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Roulette spinning + {"itrol2", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"itrol3", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"itrol4", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"itrol5", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"itrol6", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"itrol7", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"itrol8", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"itrolf", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Roulette end + {"itrolm", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Roulette end (mashed) + {"itrolk", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Roulette end (karma enhanced) + {"itrole", true, 96, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Roulette end (Eggman) + {"vroom", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Kart Krew opening vroom + {"chaooo", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Chao audience cheer + {"yeeeah", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Voting picks you + {"noooo1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Voting picks hell (by chance) + {"noooo2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Voting picks hell (on purpose) + {"ruby1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Phantom Ruby charge up + {"ruby2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Phantom Ruby teleport + {"tcart", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Twinkle Cart + {"bfare", false, 128, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pleasure Castle fanfare + {"merry", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pleasure Castle merry-go-round ambient + {"bowlh", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pleasure Castle pins + {"tppop", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Pleasure Castle bombs + {"hsdoor", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Red Barrage Area door + {"hstrn", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Red Barrage Area train + {"aspkb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Red Barrage Area spikeballs + {"wind1", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Midnight Channel monsters + {"fire2", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"chain", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Mementos Reaper + {"mkuma", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Trigger Happy Havoc Monokuma + {"toada", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Arid Sands Toad scream + {"bhurry", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // v1.0.2 Battle overtime + {"bsnipe", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Banana sniping + {"sploss", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Down to yellow sparks + {"join", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player joined server + {"leave", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Player left server + {"requst", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Got a Discord join request + {"syfail", false, 96, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Funny sync failure + {"itfree", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // :shitsfree: + {"dbgsal", false, 255, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Debug notification + {"cock", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Hammer cocks, bang bang // SRB2Kart - Engine sounds // Engine class A - {"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krta12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krta00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krta12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Engine class B - {"krtb00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtb12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krtb00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtb12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Engine class C - {"krtc00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtc12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krtc00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtc12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Engine class D - {"krtd00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtd12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krtd00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtd12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Engine class E - {"krte00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krte12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krte00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krte12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Engine class F - {"krtf00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtf12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krtf00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtf12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Engine class G - {"krtg00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krtg12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krtg00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krtg12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Engine class H - {"krth00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krth12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krth00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krth12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // Engine class I - {"krti00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, - {"krti12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR}, + {"krti00", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti01", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti02", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti03", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti04", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti05", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti06", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti07", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti08", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti09", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti10", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti11", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, + {"krti12", false, 48, 65, -1, NULL, 0, -1, -1, LUMPERROR, ""}, // SRB2kart - Skin sounds - {"kwin", false, 64, 96, -1, NULL, 0, SKSKWIN, -1, LUMPERROR}, - {"klose", false, 64, 96, -1, NULL, 0, SKSKLOSE, -1, LUMPERROR}, - {"khurt1", false, 64, 96, -1, NULL, 0, SKSKPAN1, -1, LUMPERROR}, - {"khurt2", false, 64, 96, -1, NULL, 0, SKSKPAN2, -1, LUMPERROR}, - {"kattk1", false, 64, 96, -1, NULL, 0, SKSKATK1, -1, LUMPERROR}, - {"kattk2", false, 64, 96, -1, NULL, 0, SKSKATK2, -1, LUMPERROR}, - {"kbost1", false, 64, 96, -1, NULL, 0, SKSKBST1, -1, LUMPERROR}, - {"kbost2", false, 64, 96, -1, NULL, 0, SKSKBST2, -1, LUMPERROR}, - {"kslow", false, 64, 32, -1, NULL, 0, SKSKSLOW, -1, LUMPERROR}, - {"khitem", false, 128, 32, -1, NULL, 0, SKSKHITM, -1, LUMPERROR}, - {"kgloat", false, 64, 48, -1, NULL, 0, SKSKPOWR, -1, LUMPERROR}, + {"kwin", false, 64, 96, -1, NULL, 0, SKSKWIN, -1, LUMPERROR, ""}, + {"klose", false, 64, 96, -1, NULL, 0, SKSKLOSE, -1, LUMPERROR, ""}, + {"khurt1", false, 64, 96, -1, NULL, 0, SKSKPAN1, -1, LUMPERROR, ""}, + {"khurt2", false, 64, 96, -1, NULL, 0, SKSKPAN2, -1, LUMPERROR, ""}, + {"kattk1", false, 64, 96, -1, NULL, 0, SKSKATK1, -1, LUMPERROR, ""}, + {"kattk2", false, 64, 96, -1, NULL, 0, SKSKATK2, -1, LUMPERROR, ""}, + {"kbost1", false, 64, 96, -1, NULL, 0, SKSKBST1, -1, LUMPERROR, ""}, + {"kbost2", false, 64, 96, -1, NULL, 0, SKSKBST2, -1, LUMPERROR, ""}, + {"kslow", false, 64, 32, -1, NULL, 0, SKSKSLOW, -1, LUMPERROR, ""}, + {"khitem", false, 128, 32, -1, NULL, 0, SKSKHITM, -1, LUMPERROR, ""}, + {"kgloat", false, 64, 48, -1, NULL, 0, SKSKPOWR, -1, LUMPERROR, ""}, // skin sounds free slots to add sounds at run time (Boris HACK!!!) // initialized to NULL @@ -1001,38 +1075,50 @@ void S_InitRuntimeSounds (void) S_sfx[i].skinsound = -1; S_sfx[i].usefulness = -1; S_sfx[i].lumpnum = LUMPERROR; + //strlcpy(S_sfx[i].caption, "", 1); + S_sfx[i].caption[0] = '\0'; } } +sfxenum_t sfxfree = sfx_freeslot0; + // Add a new sound fx into a free sfx slot. // sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean skinsound) { - sfxenum_t i, slot; + sfxenum_t i; if (skinsound) - slot = sfx_skinsoundslot0; - else - slot = sfx_freeslot0; - - for (i = slot; i < NUMSFX; i++) { - if (!S_sfx[i].priority) + for (i = sfx_skinsoundslot0; i < NUMSFX; i++) { - strncpy(freeslotnames[i-sfx_freeslot0], name, 6); - S_sfx[i].singularity = singular; - S_sfx[i].priority = 60; - S_sfx[i].pitch = flags; - S_sfx[i].volume = -1; - S_sfx[i].lumpnum = LUMPERROR; - S_sfx[i].skinsound = -1; - S_sfx[i].usefulness = -1; - - /// \todo if precached load it here - S_sfx[i].data = NULL; - return i; + if (S_sfx[i].priority) + continue; + break; } } + else + i = sfxfree; + + if (i < NUMSFX) + { + strncpy(freeslotnames[i-sfx_freeslot0], name, 6); + S_sfx[i].singularity = singular; + S_sfx[i].priority = 60; + S_sfx[i].pitch = flags; + S_sfx[i].volume = -1; + S_sfx[i].lumpnum = LUMPERROR; + S_sfx[i].skinsound = -1; + S_sfx[i].usefulness = -1; + + /// \todo if precached load it here + S_sfx[i].data = NULL; + + if (!skinsound) + sfxfree++; + + return i; + } CONS_Alert(CONS_WARNING, M_GetText("No more free sound slots\n")); return 0; } diff --git a/src/sounds.h b/src/sounds.h index d9b303044..51155c7c3 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -98,6 +98,9 @@ struct sfxinfo_struct // lump number of sfx lumpnum_t lumpnum; + + // closed caption info/wiki table bait + char caption[32]; }; // the complete set of sound effects @@ -153,6 +156,8 @@ typedef enum sfx_steam1, sfx_steam2, sfx_wbreak, + sfx_ambmac, + sfx_spsmsh, sfx_rainin, sfx_litng1, @@ -224,6 +229,7 @@ typedef enum sfx_drown, sfx_fizzle, sfx_gbeep, + sfx_wepfir, sfx_ghit, sfx_gloop, sfx_gspray, @@ -235,12 +241,19 @@ typedef enum sfx_lvpass, sfx_mindig, sfx_mixup, + sfx_monton, sfx_pogo, sfx_pop, sfx_rail1, sfx_rail2, sfx_rlaunc, sfx_shield, + sfx_wirlsg, + sfx_forcsg, + sfx_frcssg, + sfx_elemsg, + sfx_armasg, + sfx_attrsg, sfx_shldls, sfx_spdpad, sfx_spkdth, @@ -256,8 +269,24 @@ typedef enum sfx_trpowr, sfx_turhit, sfx_wdjump, + sfx_shrpsp, + sfx_shrpgo, sfx_mswarp, sfx_mspogo, + sfx_boingf, + sfx_corkp, + sfx_corkh, + sfx_alart, + sfx_vwre, + sfx_bowl, + sfx_chuchu, + //sfx_bsnipe, + sfx_sprong, + sfx_lvfal1, + sfx_pscree, + sfx_iceb, + sfx_shattr, + sfx_antiri, // Menu, interface sfx_chchng, @@ -271,12 +300,16 @@ typedef enum sfx_wepchg, sfx_wtrdng, sfx_zelda, + sfx_adderr, + sfx_notadd, + sfx_addfil, // NiGHTS sfx_ideya, sfx_xideya, // Xmas sfx_nbmper, sfx_nxbump, // Xmas + sfx_ncchip, sfx_ncitem, sfx_nxitem, // Xmas sfx_ngdone, @@ -291,7 +324,15 @@ typedef enum sfx_hoop3, sfx_hidden, sfx_prloop, - sfx_timeup, // Was gonna be played when less than ten seconds are on the clock; uncomment uses of this to see it in-context + sfx_timeup, + sfx_ngjump, + sfx_peww, + + // Halloween + sfx_lntsit, + sfx_lntdie, + sfx_pumpkn, + sfx_ghosty, // Mario sfx_koopfr, @@ -474,6 +515,7 @@ typedef enum sfx_s270, // S3&K sounds + sfx_s3k2b, sfx_s3k33, sfx_s3k34, sfx_s3k35, @@ -595,6 +637,21 @@ typedef enum sfx_s3ka9, sfx_s3kaa, sfx_s3kab, + sfx_s3kab1, + sfx_s3kab2, + sfx_s3kab3, + sfx_s3kab4, + sfx_s3kab5, + sfx_s3kab6, + sfx_s3kab7, + sfx_s3kab8, + sfx_s3kab9, + sfx_s3kaba, + sfx_s3kabb, + sfx_s3kabc, + sfx_s3kabd, + sfx_s3kabe, + sfx_s3kabf, sfx_s3kac, sfx_s3kad, sfx_s3kae, @@ -895,6 +952,10 @@ typedef enum sfx_bhurry, sfx_bsnipe, sfx_sploss, + sfx_join, + sfx_leave, + sfx_requst, + sfx_syfail, sfx_itfree, sfx_dbgsal, sfx_cock, @@ -1056,6 +1117,7 @@ typedef enum void S_InitRuntimeSounds(void); sfxenum_t S_AddSoundFx(const char *name, boolean singular, INT32 flags, boolean skinsound); +extern sfxenum_t sfxfree; // sound test and slotting void S_RemoveSoundFx(sfxenum_t id); #endif diff --git a/src/st_stuff.c b/src/st_stuff.c index 5105172d2..a8e7d2434 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -23,12 +23,14 @@ #include "v_video.h" #include "z_zone.h" #include "hu_stuff.h" +#include "console.h" #include "s_sound.h" #include "i_system.h" #include "m_menu.h" #include "m_cheat.h" +#include "m_misc.h" // moviemode +#include "m_anigif.h" // cv_gif_downscale #include "p_setup.h" // NiGHTS grading -#include "k_hud.h" // SRB2kart //random index #include "m_random.h" @@ -40,9 +42,12 @@ #include "hardware/hw_main.h" #endif -#ifdef HAVE_BLUA #include "lua_hud.h" -#endif + +// SRB2Kart +#include "k_hud.h" // SRB2kart +#include "v_video.h" +#include "r_skins.h" // NUMFACES UINT16 objectsdrawn = 0; @@ -50,9 +55,7 @@ UINT16 objectsdrawn = 0; // STATUS BAR DATA // -patch_t *facerankprefix[MAXSKINS]; // ranking -patch_t *facewantprefix[MAXSKINS]; // wanted -patch_t *facemmapprefix[MAXSKINS]; // minimap +patch_t *faceprefix[MAXSKINS][NUMFACES]; // ------------------------------------------ // status bar overlay @@ -64,12 +67,14 @@ patch_t *sbotime; // Time logo patch_t *sbocolon; // Colon for time patch_t *sboperiod; // Period for time centiseconds patch_t *livesback; // Lives icon background +patch_t *stlivex; static patch_t *nrec_timer; // Timer for NiGHTS records static patch_t *sborings; -static patch_t *sboover; -static patch_t *timeover; -static patch_t *stlivex; -static patch_t *rrings; +static patch_t *slidgame; +static patch_t *slidtime; +static patch_t *slidover; +static patch_t *sboredrings; +static patch_t *sboredtime; static patch_t *getall; // Special Stage HUD static patch_t *timeup; // Special Stage HUD static patch_t *hunthoming[6]; @@ -78,14 +83,7 @@ static patch_t *race1; static patch_t *race2; static patch_t *race3; static patch_t *racego; -//static patch_t *ttlnum; static patch_t *nightslink; -static patch_t *count5; -static patch_t *count4; -static patch_t *count3; -static patch_t *count2; -static patch_t *count1; -static patch_t *count0; static patch_t *curweapon; static patch_t *normring; static patch_t *bouncering; @@ -101,18 +99,26 @@ static patch_t *ringshield; static patch_t *watershield; static patch_t *bombshield; static patch_t *pityshield; +static patch_t *pinkshield; +static patch_t *flameshield; +static patch_t *bubbleshield; +static patch_t *thundershield; static patch_t *invincibility; static patch_t *sneakers; static patch_t *gravboots; static patch_t *nonicon; +static patch_t *nonicon2; static patch_t *bluestat; static patch_t *byelstat; static patch_t *orngstat; static patch_t *redstat; static patch_t *yelstat; static patch_t *nbracket; +static patch_t *nring; static patch_t *nhud[12]; static patch_t *nsshud; +static patch_t *nbon[12]; +static patch_t *nssbon; static patch_t *narrow[9]; static patch_t *nredar[8]; // Red arrow static patch_t *drillbar; @@ -124,50 +130,47 @@ static patch_t *minus5sec; static patch_t *minicaps; static patch_t *gotrflag; static patch_t *gotbflag; +static patch_t *fnshico; // Midnight Channel: static patch_t *hud_tv1; static patch_t *hud_tv2; +#ifdef HAVE_DISCORDRPC +// Discord Rich Presence +static patch_t *envelope; +#endif + // SRB2kart hudinfo_t hudinfo[NUMHUDITEMS] = { - { 34, 176}, // HUD_LIVESNAME - { 16, 176}, // HUD_LIVESPIC - { 74, 184}, // HUD_LIVESNUM - { 38, 186}, // HUD_LIVESX + { 16, 176, V_SNAPTOLEFT|V_SNAPTOBOTTOM}, // HUD_LIVES - { 16, 42}, // HUD_RINGS - { 220, 10}, // HUD_RINGSSPLIT - { 112, 42}, // HUD_RINGSNUM - { 288, 10}, // HUD_RINGSNUMSPLIT + { 16, 42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGS + { 96, 42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGSNUM + { 120, 42, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_RINGSNUMTICS - { 16, 10}, // HUD_SCORE - { 128, 10}, // HUD_SCORENUM + { 16, 10, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_SCORE + { 120, 10, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_SCORENUM - { 17, 26}, // HUD_TIME - { 136, 10}, // HUD_TIMESPLIT - { 88, 26}, // HUD_MINUTES - { 188, 10}, // HUD_MINUTESSPLIT - { 88, 26}, // HUD_TIMECOLON - { 188, 10}, // HUD_TIMECOLONSPLIT - { 112, 26}, // HUD_SECONDS - { 212, 10}, // HUD_SECONDSSPLIT - { 112, 26}, // HUD_TIMETICCOLON - { 136, 26}, // HUD_TICS + { 16, 26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_TIME + { 72, 26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_MINUTES + { 72, 26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_TIMECOLON + { 96, 26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_SECONDS + { 96, 26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_TIMETICCOLON + { 120, 26, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_TICS - { 112, 56}, // HUD_SS_TOTALRINGS - { 288, 40}, // HUD_SS_TOTALRINGS_SPLIT + { 0, 56, V_SNAPTOLEFT|V_SNAPTOTOP}, // HUD_SS_TOTALRINGS - { 110, 93}, // HUD_GETRINGS - { 160, 93}, // HUD_GETRINGSNUM - { 124, 160}, // HUD_TIMELEFT - { 168, 176}, // HUD_TIMELEFTNUM - { 130, 93}, // HUD_TIMEUP - { 152, 168}, // HUD_HUNTPICS - { 152, 24}, // HUD_GRAVBOOTSICO - { 240, 160}, // HUD_LAP + { 110, 93, 0}, // HUD_GETRINGS + { 160, 93, 0}, // HUD_GETRINGSNUM + { 124, 160, 0}, // HUD_TIMELEFT + { 168, 176, 0}, // HUD_TIMELEFTNUM + { 130, 93, 0}, // HUD_TIMEUP + { 152, 168, 0}, // HUD_HUNTPICS + + { 288, 176, V_SNAPTORIGHT|V_SNAPTOBOTTOM}, // HUD_POWERUPS }; // @@ -176,34 +179,39 @@ hudinfo_t hudinfo[NUMHUDITEMS] = boolean ST_SameTeam(player_t *a, player_t *b) { - // Just pipe team messages to everyone in co-op or race. - if (!G_BattleGametype()) - return true; - // Spectator chat. if (a->spectator && b->spectator) + { return true; + } // Team chat. - if (G_GametypeHasTeams()) - return a->ctfteam == b->ctfteam; - - if (G_TagGametype()) - return ((a->pflags & PF_TAGIT) == (b->pflags & PF_TAGIT)); - - return false; + if (G_GametypeHasTeams() == true) + { + // You get team messages if you're on the same team. + return (a->ctfteam == b->ctfteam); + } + else + { + // Not that everyone's not on the same team, but team messages go to normal chat if everyone's not in the same team. + return true; + } } static boolean st_stopped = true; -void ST_Ticker(void) +void ST_Ticker(boolean run) { if (st_stopped) return; + + if (run) + ST_runTitleCard(); } // 0 is default, any others are special palettes. INT32 st_palette = 0; +INT32 st_translucency = 10; void ST_doPaletteStuff(void) { @@ -238,7 +246,7 @@ void ST_doPaletteStuff(void) void ST_UnloadGraphics(void) { - Z_FreeTags(PU_HUDGFX, PU_HUDGFX); + Z_FreeTag(PU_HUDGFX); } void ST_LoadGraphics(void) @@ -246,24 +254,30 @@ void ST_LoadGraphics(void) int i; // SRB2 border patch - st_borderpatchnum = W_GetNumForName("GFZFLR01"); - scr_borderpatch = W_CacheLumpNum(st_borderpatchnum, PU_HUDGFX); + // st_borderpatchnum = W_GetNumForName("GFZFLR01"); + // scr_borderpatch = W_CacheLumpNum(st_borderpatchnum, PU_HUDGFX); // the original Doom uses 'STF' as base name for all face graphics // Graue 04-08-2004: face/name graphics are now indexed by skins // but load them in R_AddSkins, that gets called // first anyway // cache the status bar overlay icons (fullscreen mode) - sborings = W_CachePatchName("SBORINGS", PU_HUDGFX); - sboscore = W_CachePatchName("SBOSCORE", PU_HUDGFX); - sboover = W_CachePatchName("SBOOVER", PU_HUDGFX); - timeover = W_CachePatchName("TIMEOVER", PU_HUDGFX); + + // Prefix "STT" is whitelisted (doesn't trigger ISGAMEMODIFIED), btw + sborings = W_CachePatchName("STTRINGS", PU_HUDGFX); + sboredrings = W_CachePatchName("STTRRING", PU_HUDGFX); + sboscore = W_CachePatchName("STTSCORE", PU_HUDGFX); + sbotime = W_CachePatchName("STTTIME", PU_HUDGFX); // Time logo + sboredtime = W_CachePatchName("STTRTIME", PU_HUDGFX); + sbocolon = W_CachePatchName("STTCOLON", PU_HUDGFX); // Colon for time + sboperiod = W_CachePatchName("STTPERIO", PU_HUDGFX); // Period for time centiseconds + + slidgame = W_CachePatchName("SLIDGAME", PU_HUDGFX); + slidtime = W_CachePatchName("SLIDTIME", PU_HUDGFX); + slidover = W_CachePatchName("SLIDOVER", PU_HUDGFX); + stlivex = W_CachePatchName("STLIVEX", PU_HUDGFX); livesback = W_CachePatchName("STLIVEBK", PU_HUDGFX); - rrings = W_CachePatchName("RRINGS", PU_HUDGFX); - sbotime = W_CachePatchName("SBOTIME", PU_HUDGFX); // Time logo - sbocolon = W_CachePatchName("SBOCOLON", PU_HUDGFX); // Colon for time - sboperiod = W_CachePatchName("SBOPERIO", PU_HUDGFX); // Period for time centiseconds nrec_timer = W_CachePatchName("NGRTIMER", PU_HUDGFX); // Timer for NiGHTS getall = W_CachePatchName("GETALL", PU_HUDGFX); // Special Stage HUD timeup = W_CachePatchName("TIMEUP", PU_HUDGFX); // Special Stage HUD @@ -272,12 +286,6 @@ void ST_LoadGraphics(void) race3 = W_CachePatchName("RACE3", PU_HUDGFX); racego = W_CachePatchName("RACEGO", PU_HUDGFX); nightslink = W_CachePatchName("NGHTLINK", PU_HUDGFX); - count5 = W_CachePatchName("DRWNF0", PU_HUDGFX); - count4 = W_CachePatchName("DRWNE0", PU_HUDGFX); - count3 = W_CachePatchName("DRWND0", PU_HUDGFX); - count2 = W_CachePatchName("DRWNC0", PU_HUDGFX); - count1 = W_CachePatchName("DRWNB0", PU_HUDGFX); - count0 = W_CachePatchName("DRWNA0", PU_HUDGFX); for (i = 0; i < 6; ++i) { @@ -294,15 +302,19 @@ void ST_LoadGraphics(void) scatterring = W_CachePatchName("SCATIND", PU_HUDGFX); grenadering = W_CachePatchName("GRENIND", PU_HUDGFX); railring = W_CachePatchName("RAILIND", PU_HUDGFX); - jumpshield = W_CachePatchName("WHTVB0", PU_HUDGFX); - forceshield = W_CachePatchName("BLTVB0", PU_HUDGFX); - ringshield = W_CachePatchName("YLTVB0", PU_HUDGFX); - watershield = W_CachePatchName("ELTVB0", PU_HUDGFX); - bombshield = W_CachePatchName("BKTVB0", PU_HUDGFX); - pityshield = W_CachePatchName("GRTVB0", PU_HUDGFX); - invincibility = W_CachePatchName("PINVB0", PU_HUDGFX); - sneakers = W_CachePatchName("SHTVB0", PU_HUDGFX); - gravboots = W_CachePatchName("GBTVB0", PU_HUDGFX); + jumpshield = W_CachePatchName("TVWWICON", PU_HUDGFX); + forceshield = W_CachePatchName("TVFOICON", PU_HUDGFX); + ringshield = W_CachePatchName("TVATICON", PU_HUDGFX); + watershield = W_CachePatchName("TVELICON", PU_HUDGFX); + bombshield = W_CachePatchName("TVARICON", PU_HUDGFX); + pityshield = W_CachePatchName("TVPIICON", PU_HUDGFX); + pinkshield = W_CachePatchName("TVPPICON", PU_HUDGFX); + flameshield = W_CachePatchName("TVFLICON", PU_HUDGFX); + bubbleshield = W_CachePatchName("TVBBICON", PU_HUDGFX); + thundershield = W_CachePatchName("TVZPICON", PU_HUDGFX); + invincibility = W_CachePatchName("TVIVICON", PU_HUDGFX); + sneakers = W_CachePatchName("TVSSICON", PU_HUDGFX); + gravboots = W_CachePatchName("TVGVICON", PU_HUDGFX); tagico = W_CachePatchName("TAGICO", PU_HUDGFX); rflagico = W_CachePatchName("RFLAGICO", PU_HUDGFX); @@ -311,7 +323,9 @@ void ST_LoadGraphics(void) bmatcico = W_CachePatchName("BMATCICO", PU_HUDGFX); gotrflag = W_CachePatchName("GOTRFLAG", PU_HUDGFX); gotbflag = W_CachePatchName("GOTBFLAG", PU_HUDGFX); + fnshico = W_CachePatchName("FNSHICO", PU_HUDGFX); nonicon = W_CachePatchName("NONICON", PU_HUDGFX); + nonicon2 = W_CachePatchName("NONICON2", PU_HUDGFX); // NiGHTS HUD things bluestat = W_CachePatchName("BLUESTAT", PU_HUDGFX); @@ -320,9 +334,14 @@ void ST_LoadGraphics(void) redstat = W_CachePatchName("REDSTAT", PU_HUDGFX); yelstat = W_CachePatchName("YELSTAT", PU_HUDGFX); nbracket = W_CachePatchName("NBRACKET", PU_HUDGFX); + nring = W_CachePatchName("NRNG1", PU_HUDGFX); for (i = 0; i < 12; ++i) + { nhud[i] = W_CachePatchName(va("NHUD%d", i+1), PU_HUDGFX); + nbon[i] = W_CachePatchName(va("NBON%d", i+1), PU_HUDGFX); + } nsshud = W_CachePatchName("NSSHUD", PU_HUDGFX); + nssbon = W_CachePatchName("NSSBON", PU_HUDGFX); minicaps = W_CachePatchName("MINICAPS", PU_HUDGFX); for (i = 0; i < 8; ++i) @@ -349,14 +368,36 @@ void ST_LoadGraphics(void) // Midnight Channel: hud_tv1 = W_CachePatchName("HUD_TV1", PU_HUDGFX); hud_tv2 = W_CachePatchName("HUD_TV2", PU_HUDGFX); + +#ifdef HAVE_DISCORDRPC + // Discord Rich Presence + envelope = W_CachePatchName("K_REQUES", PU_HUDGFX); +#endif } // made separate so that skins code can reload custom face graphics -void ST_LoadFaceGraphics(char *rankstr, char *wantstr, char *mmapstr, INT32 skinnum) +void ST_LoadFaceGraphics(INT32 skinnum) { - facerankprefix[skinnum] = W_CachePatchName(rankstr, PU_HUDGFX); - facewantprefix[skinnum] = W_CachePatchName(wantstr, PU_HUDGFX); - facemmapprefix[skinnum] = W_CachePatchName(mmapstr, PU_HUDGFX); +#define FACE_MAX (FACE_MINIMAP+1) + spritedef_t *sprdef = &skins[skinnum].sprites[SPR2_XTRA]; + spriteframe_t *sprframe; + UINT8 i = 0, maxer = min(sprdef->numframes, FACE_MAX); + while (i < maxer) + { + sprframe = &sprdef->spriteframes[i]; + faceprefix[skinnum][i] = W_CachePatchNum(sprframe->lumppat[0], PU_HUDGFX); + i++; + } + if (i < FACE_MAX) + { + patch_t *missing = W_CachePatchName("MISSING", PU_HUDGFX); + while (i < FACE_MAX) + { + faceprefix[skinnum][i] = missing; + i++; + } + } +#undef FACE_MAX } void ST_ReloadSkinFaceGraphics(void) @@ -364,7 +405,7 @@ void ST_ReloadSkinFaceGraphics(void) INT32 i; for (i = 0; i < numskins; i++) - ST_LoadFaceGraphics(skins[i].facerank, skins[i].facewant, skins[i].facemmap, i); + ST_LoadFaceGraphics(i); } static inline void ST_InitData(void) @@ -508,6 +549,7 @@ static INT32 SCR(INT32 r) // ========================================================================= // INTERNAL DRAWING // ========================================================================= +#define ST_DrawTopLeftOverlayPatch(x,y,p) V_DrawScaledPatch(SCX(hudinfo[h+!!r_splitscreen].x), SCY(hudinfo[h+!!r_splitscreen].y), V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANS, p) #define ST_DrawOverlayNum(x,y,n) V_DrawTallNum(x, y, V_NOSCALESTART|V_HUDTRANS, n) #define ST_DrawPaddedOverlayNum(x,y,n,d) V_DrawPaddedTallNum(x, y, V_NOSCALESTART|V_HUDTRANS, n, d) #define ST_DrawOverlayPatch(x,y,p) V_DrawScaledPatch(x, y, V_NOSCALESTART|V_HUDTRANS, p) @@ -519,39 +561,6 @@ static INT32 SCR(INT32 r) #define ST_DrawPadNumFromHudWS(h,n,q) V_DrawPaddedTallNum(SCX(hudinfo[h+!!r_splitscreen].x), SCY(hudinfo[h+!!r_splitscreen].y), V_NOSCALESTART|V_HUDTRANS, n, q) #define ST_DrawPatchFromHudWS(h,p) V_DrawScaledPatch(SCX(hudinfo[h+!!r_splitscreen].x), SCY(hudinfo[h+!!r_splitscreen].y), V_NOSCALESTART|V_HUDTRANS, p) -/* -// Draw a number, scaled, over the view, maybe with set translucency -// Always draw the number completely since it's overlay -// -// Supports different colors! woo! -static void ST_DrawNightsOverlayNum(INT32 x, INT32 y, INT32 a, - INT32 num, patch_t **numpat, skincolors_t colornum) -{ - INT32 w = SHORT(numpat[0]->width); - const UINT8 *colormap; - - // I want my V_SNAPTOx flags. :< -Red - //a &= V_ALPHAMASK; - - if (colornum == 0) - colormap = colormaps; - else // Uses the player colors. - colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE); - - I_Assert(num >= 0); // this function does not draw negative numbers - - // draw the number - do - { - x -= w; - V_DrawTranslucentMappedPatch(x, y, a, numpat[num % 10], colormap); - num /= 10; - } while (num); - - // Sorry chum, this function only draws UNSIGNED values! -} -*/ - // Devmode information static void ST_drawDebugInfo(void) { @@ -617,1281 +626,249 @@ static void ST_drawDebugInfo(void) V_DrawRightAlignedString(320, height, V_MONOSPACE, va("Heap used: %7sKB", sizeu1(Z_TagsUsage(0, INT32_MAX)>>10))); } -/* -static void ST_drawScore(void) +static patch_t *lt_patches[3]; +static INT32 lt_scroll = 0; +static INT32 lt_mom = 0; +static INT32 lt_zigzag = 0; + +tic_t lt_ticker = 0, lt_lasttic = 0; +tic_t lt_exitticker = 0, lt_endtime = 0; + +// +// Load the graphics for the title card. +// Don't let LJ see this +// +static void ST_cacheLevelTitle(void) { - // SCORE: - ST_DrawPatchFromHud(HUD_SCORE, sboscore); - if (objectplacing) - { - if (op_displayflags > UINT16_MAX) - ST_DrawOverlayPatch(SCX(hudinfo[HUD_SCORENUM].x-tallminus->width), SCY(hudinfo[HUD_SCORENUM].y), tallminus); - else - ST_DrawNumFromHud(HUD_SCORENUM, op_displayflags); - } - else - ST_DrawNumFromHud(HUD_SCORENUM, stplyr->score); + lt_patches[0] = (patch_t *)W_CachePatchName("LTACTBLU", PU_HUDGFX); + lt_patches[1] = (patch_t *)W_CachePatchName("LTZIGZAG", PU_HUDGFX); + lt_patches[2] = (patch_t *)W_CachePatchName("LTZZTEXT", PU_HUDGFX); } -*/ -/* -static void ST_drawTime(void) +// +// Start the title card. +// +void ST_startTitleCard(void) { - INT32 seconds, minutes, tictrn, tics; + // cache every HUD patch used + ST_cacheLevelTitle(); - // TIME: - ST_DrawPatchFromHudWS(HUD_TIME, sbotime); + // initialize HUD variables + lt_ticker = lt_exitticker = lt_lasttic = 0; + lt_endtime = 2*TICRATE + (10*NEWTICRATERATIO); + lt_scroll = BASEVIDWIDTH * FRACUNIT; + lt_zigzag = -((lt_patches[1])->width * FRACUNIT); + lt_mom = 0; +} - if (objectplacing) - { - tics = objectsdrawn; - seconds = objectsdrawn%100; - minutes = objectsdrawn/100; - tictrn = 0; - } +// +// What happens before drawing the title card. +// Which is just setting the HUD translucency. +// +void ST_preDrawTitleCard(void) +{ + if (!G_IsTitleCardAvailable()) + return; + + if (lt_ticker >= (lt_endtime + TICRATE)) + return; + + if (!lt_exitticker) + st_translucency = 0; else - { - tics = stplyr->realtime; - seconds = G_TicsToSeconds(tics); - minutes = G_TicsToMinutes(tics, true); - tictrn = G_TicsToCentiseconds(tics); - } + st_translucency = max(0, min((INT32)lt_exitticker-4, cv_translucenthud.value)); +} - if (cv_timetic.value == 1) // Tics only -- how simple is this? - ST_DrawNumFromHudWS(HUD_SECONDS, tics); - else - { - ST_DrawNumFromHudWS(HUD_MINUTES, minutes); // Minutes - ST_DrawPatchFromHudWS(HUD_TIMECOLON, sbocolon); // Colon - ST_DrawPadNumFromHudWS(HUD_SECONDS, seconds, 2); // Seconds +// +// Run the title card. +// Called from ST_Ticker. +// +void ST_runTitleCard(void) +{ + boolean run = !(paused || P_AutoPause()); - if (!splitscreen && (cv_timetic.value == 2 || modeattacking)) // there's not enough room for tics in splitscreen, don't even bother trying! + if (!G_IsTitleCardAvailable()) + return; + + if (lt_ticker >= (lt_endtime + TICRATE)) + return; + + if (run || (lt_ticker < PRELEVELTIME)) + { + // tick + lt_ticker++; + if (lt_ticker >= lt_endtime) + lt_exitticker++; + + // scroll to screen (level title) + if (!lt_exitticker) { - ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period - ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics + if (abs(lt_scroll) > FRACUNIT) + lt_scroll -= (lt_scroll>>2); + else + lt_scroll = 0; } + // scroll away from screen (level title) + else + { + lt_mom -= FRACUNIT*6; + lt_scroll += lt_mom; + } + + // scroll to screen (zigzag) + if (!lt_exitticker) + { + if (abs(lt_zigzag) > FRACUNIT) + lt_zigzag -= (lt_zigzag>>2); + else + lt_zigzag = 0; + } + // scroll away from screen (zigzag) + else + lt_zigzag += lt_mom; } } -*/ -/* -static inline void ST_drawRings(void) // SRB2kart - unused. -{ - INT32 ringnum = max(stplyr->health-1, 0); +// +// Draw the title card itself. +// - ST_DrawPatchFromHudWS(HUD_RINGS, ((stplyr->health <= 1 && leveltime/5 & 1) ? rrings : sborings)); - - if (objectplacing) - ringnum = op_currentdoomednum; - else if (!useNightsSS && G_IsSpecialStage(gamemap)) - { - INT32 i; - ringnum = 0; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].mo && players[i].mo->health > 1) - ringnum += players[i].mo->health - 1; - } - - ST_DrawNumFromHudWS(HUD_RINGSNUM, ringnum); -} -*/ - -/* -static void ST_drawLives(void) // SRB2kart - unused. -{ - const INT32 v_splitflag = V_SPLITSCREEN; - - if (!stplyr->skincolor) - return; // Just joined a server, skin isn't loaded yet! - - // face background - V_DrawSmallScaledPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, livesback); - - // face - if (stplyr->mo && stplyr->mo->color) - { - // skincolor face/super - UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->mo->color, GTC_CACHE); - patch_t *face = facerankprefix[stplyr->skin]; - if (stplyr->powers[pw_super] || stplyr->pflags & PF_NIGHTSMODE) - face = facewantprefix[stplyr->skin]; - V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,face, colormap); - } - else if (stplyr->skincolor) - { - // skincolor face - UINT8 *colormap = R_GetTranslationColormap(stplyr->skin, stplyr->skincolor, GTC_CACHE); - V_DrawSmallMappedPatch(hudinfo[HUD_LIVESPIC].x, hudinfo[HUD_LIVESPIC].y + (v_splitflag ? -12 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag,facerankprefix[stplyr->skin], colormap); - } - - // name - if (strlen(skins[stplyr->skin].hudname) > 8) - V_DrawThinString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), - V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); - else - V_DrawString(hudinfo[HUD_LIVESNAME].x, hudinfo[HUD_LIVESNAME].y + (v_splitflag ? -12 : 0), - V_HUDTRANS|V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_MONOSPACE|V_YELLOWMAP|v_splitflag, skins[stplyr->skin].hudname); - // x - V_DrawScaledPatch(hudinfo[HUD_LIVESX].x, hudinfo[HUD_LIVESX].y + (v_splitflag ? -4 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, stlivex); - // lives - V_DrawRightAlignedString(hudinfo[HUD_LIVESNUM].x, hudinfo[HUD_LIVESNUM].y + (v_splitflag ? -4 : 0), - V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS|v_splitflag, va("%d",stplyr->lives)); -} -*/ - -static void ST_drawLevelTitle(void) +void ST_drawTitleCard(void) { char *lvlttl = mapheaderinfo[gamemap-1]->lvlttl; char *subttl = mapheaderinfo[gamemap-1]->subttl; char *zonttl = mapheaderinfo[gamemap-1]->zonttl; // SRB2kart - char *actnum = mapheaderinfo[gamemap-1]->actnum; - INT32 lvlttlxpos; - INT32 ttlnumxpos; - INT32 zonexpos; - INT32 dupcalc = (vid.width/vid.dupx); - UINT8 gtc = G_GetGametypeColor(gametype); - INT32 sub = 0; - INT32 bary = (r_splitscreen) - ? BASEVIDHEIGHT/2 - : 163; - INT32 lvlw; + UINT8 actnum = mapheaderinfo[gamemap-1]->actnum; + INT32 lvlttlxpos, ttlnumxpos, zonexpos; + INT32 subttlxpos = BASEVIDWIDTH/2; + INT32 ttlscroll = FixedInt(lt_scroll); +#ifdef TITLEPATCHES + INT32 zzticker; + patch_t *actpat, *zigzag, *zztext; + UINT8 colornum; + const UINT8 *colormap; - if (timeinmap > 113) + if (players[g_localplayers[0]].skincolor) + colornum = players[g_localplayers[0]].skincolor; + else + colornum = cv_playercolor[0].value; + + colormap = R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE); +#endif + + if (!G_IsTitleCardAvailable()) return; - lvlw = V_LevelNameWidth(lvlttl); + if (!LUA_HudEnabled(hud_stagetitle)) + goto luahook; - if (actnum[0]) - lvlttlxpos = ((BASEVIDWIDTH/2) - (lvlw/2)) - V_LevelNameWidth(actnum); + if (lt_ticker >= (lt_endtime + TICRATE)) + goto luahook; + + if ((lt_ticker-lt_lasttic) > 1) + lt_ticker = lt_lasttic+1; + + ST_cacheLevelTitle(); + +#ifdef TITLEPATCHES + actpat = lt_patches[0]; + zigzag = lt_patches[1]; + zztext = lt_patches[2]; +#endif + + lvlttlxpos = ((BASEVIDWIDTH/2) - (V_LevelNameWidth(lvlttl)/2)); + + if (actnum > 0) + lvlttlxpos -= V_LevelNameWidth(va("%d", actnum)); + + zonexpos = ttlnumxpos = lvlttlxpos + V_LevelNameWidth(lvlttl); + if (zonttl[0]) + zonexpos -= V_LevelNameWidth(zonttl); // SRB2kart else - lvlttlxpos = ((BASEVIDWIDTH/2) - (lvlw/2)); + zonexpos -= V_LevelNameWidth(M_GetText("Zone")); - zonexpos = ttlnumxpos = lvlttlxpos + lvlw; - if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - { - if (zonttl[0]) - zonexpos -= V_LevelNameWidth(zonttl); // SRB2kart - else - zonexpos -= V_LevelNameWidth(M_GetText("ZONE")); - } + ttlnumxpos++; if (lvlttlxpos < 0) lvlttlxpos = 0; - if (timeinmap > 105) +#ifdef TITLEPATCHES + if (!splitscreen || (splitscreen && stplyr == &players[displayplayers[0]])) { - INT32 count = (113 - (INT32)(timeinmap)); - sub = dupcalc; - while (count-- > 0) - sub >>= 1; - sub = -sub; + zzticker = lt_ticker; + V_DrawMappedPatch(FixedInt(lt_zigzag), (-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap); + V_DrawMappedPatch(FixedInt(lt_zigzag), (zigzag->height-zzticker) % zigzag->height, V_SNAPTOTOP|V_SNAPTOLEFT, zigzag, colormap); + V_DrawMappedPatch(FixedInt(lt_zigzag), (-zigzag->height+zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap); + V_DrawMappedPatch(FixedInt(lt_zigzag), (zzticker) % zztext->height, V_SNAPTOTOP|V_SNAPTOLEFT, zztext, colormap); + } +#endif + + if (actnum) + { +#ifdef TITLEPATCHES + if (!splitscreen) + { + if (actnum > 9) // slightly offset the act diamond for two-digit act numbers + V_DrawMappedPatch(ttlnumxpos + (V_LevelNameWidth(va("%d", actnum))/4) + ttlscroll, 104 - ttlscroll, 0, actpat, colormap); + else + V_DrawMappedPatch(ttlnumxpos + ttlscroll, 104 - ttlscroll, 0, actpat, colormap); + } +#endif + V_DrawLevelTitle(ttlnumxpos + ttlscroll, 104, 0, va("%d", actnum)); } - { - dupcalc = (dupcalc - BASEVIDWIDTH)>>1; - V_DrawFill(sub - dupcalc, bary+9, ttlnumxpos+dupcalc + 1, 2, 31); - V_DrawDiag(sub + ttlnumxpos + 1, bary, 11, 31); - V_DrawFill(sub - dupcalc, bary, ttlnumxpos+dupcalc, 10, gtc); - V_DrawDiag(sub + ttlnumxpos, bary, 10, gtc); - - if (subttl[0]) - V_DrawRightAlignedString(sub + zonexpos - 8, bary+1, V_ALLOWLOWERCASE, subttl); - //else - //V_DrawRightAlignedString(sub + zonexpos - 8, bary+1, V_ALLOWLOWERCASE, va("%s Mode", gametype_cons_t[gametype].strvalue)); - } - - ttlnumxpos += sub; - lvlttlxpos += sub; - zonexpos += sub; - - V_DrawLevelTitle(lvlttlxpos, bary-18, 0, lvlttl); - - if (strlen(zonttl) > 0) - V_DrawLevelTitle(zonexpos, bary+6, 0, zonttl); + V_DrawLevelTitle(lvlttlxpos - ttlscroll, 80, 0, lvlttl); + if (zonttl[0]) + V_DrawLevelTitle(zonexpos + ttlscroll, 104, 0, zonttl); else if (!(mapheaderinfo[gamemap-1]->levelflags & LF_NOZONE)) - V_DrawLevelTitle(zonexpos, bary+6, 0, M_GetText("ZONE")); + V_DrawLevelTitle(zonexpos + ttlscroll, 104, 0, M_GetText("Zone")); + V_DrawCenteredString(subttlxpos - ttlscroll, 135, 0|V_ALLOWLOWERCASE, subttl); - if (actnum[0]) - V_DrawLevelTitle(ttlnumxpos+12, bary+6, 0, actnum); + lt_lasttic = lt_ticker; + +luahook: + LUAh_TitleCardHUD(stplyr); } -/* -static void ST_drawFirstPersonHUD(void) +// +// Drawer for G_PreLevelTitleCard. +// +void ST_preLevelTitleCardDrawer(void) { - player_t *player = stplyr; - patch_t *p = NULL; - UINT16 invulntime = 0; - - if (player->playerstate != PST_LIVE) - return; - - // Graue 06-18-2004: no V_NOSCALESTART, no SCX, no SCY, snap to right - if (player->powers[pw_shield] & SH_FORCE) - { - if ((player->powers[pw_shield] & 0xFF) > 0 || leveltime & 1) - p = forceshield; - } - else switch (player->powers[pw_shield] & SH_NOSTACK) - { - case SH_JUMP: p = jumpshield; break; - case SH_ELEMENTAL: p = watershield; break; - case SH_BOMB: p = bombshield; break; - case SH_ATTRACT: p = ringshield; break; - case SH_PITY: p = pityshield; break; - default: break; - } - - if (p) - { - if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24), V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); - else - V_DrawScaledPatch(304, 24, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); - } - - // pw_flashing just sets the icon to flash no matter what. - invulntime = player->powers[pw_flashing] ? 1 : player->powers[pw_invulnerability]; - if (invulntime > 3*TICRATE || (invulntime && leveltime & 1)) - { - if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 14, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, invincibility); - else - V_DrawScaledPatch(304, 24 + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, invincibility); - } - - if (player->powers[pw_sneakers] > 3*TICRATE || (player->powers[pw_sneakers] && leveltime & 1)) - { - if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 28, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, sneakers); - else - V_DrawScaledPatch(304, 24 + 56, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, sneakers); - } - - p = NULL; - - // Display the countdown drown numbers! - if ((player->powers[pw_underwater] <= 11*TICRATE + 1 - && player->powers[pw_underwater] >= 10*TICRATE + 1) - || (player->powers[pw_spacetime] <= 11*TICRATE + 1 - && player->powers[pw_spacetime] >= 10*TICRATE + 1)) - { - p = count5; - } - else if ((player->powers[pw_underwater] <= 9*TICRATE + 1 - && player->powers[pw_underwater] >= 8*TICRATE + 1) - || (player->powers[pw_spacetime] <= 9*TICRATE + 1 - && player->powers[pw_spacetime] >= 8*TICRATE + 1)) - { - p = count4; - } - else if ((player->powers[pw_underwater] <= 7*TICRATE + 1 - && player->powers[pw_underwater] >= 6*TICRATE + 1) - || (player->powers[pw_spacetime] <= 7*TICRATE + 1 - && player->powers[pw_spacetime] >= 6*TICRATE + 1)) - { - p = count3; - } - else if ((player->powers[pw_underwater] <= 5*TICRATE + 1 - && player->powers[pw_underwater] >= 4*TICRATE + 1) - || (player->powers[pw_spacetime] <= 5*TICRATE + 1 - && player->powers[pw_spacetime] >= 4*TICRATE + 1)) - { - p = count2; - } - else if ((player->powers[pw_underwater] <= 3*TICRATE + 1 - && player->powers[pw_underwater] >= 2*TICRATE + 1) - || (player->powers[pw_spacetime] <= 3*TICRATE + 1 - && player->powers[pw_spacetime] >= 2*TICRATE + 1)) - { - p = count1; - } - else if ((player->powers[pw_underwater] <= 1*TICRATE + 1 - && player->powers[pw_underwater] > 1) - || (player->powers[pw_spacetime] <= 1*TICRATE + 1 - && player->powers[pw_spacetime] > 1)) - { - p = count0; - } - - if (p) - V_DrawScaledPatch(SCX((BASEVIDWIDTH/2) - (SHORT(p->width)/2) + SHORT(p->leftoffset)), SCY(60 - SHORT(p->topoffset)), - V_NOSCALESTART|V_OFFSET|V_TRANSLUCENT, p); + V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, levelfadecol); + ST_drawWipeTitleCard(); + I_OsPolling(); + I_UpdateNoBlit(); } -*/ -/* -// [21:42] <+Rob> Beige - Lavender - Steel Blue - Peach - Orange - Purple - Silver - Yellow - Pink - Red - Blue - Green - Cyan - Gold -static skincolors_t linkColor[14] = -{SKINCOLOR_BEIGE, SKINCOLOR_LAVENDER, SKINCOLOR_STEEL, SKINCOLOR_PEACH, SKINCOLOR_ORANGE, - SKINCOLOR_PURPLE, SKINCOLOR_SILVER, SKINCOLOR_SUPER4, SKINCOLOR_PINK, SKINCOLOR_RED, - SKINCOLOR_BLUE, SKINCOLOR_GREEN, SKINCOLOR_CYAN, SKINCOLOR_GOLD}; - -static void ST_drawNightsRecords(void) +// +// Draw the title card while on a wipe. +// Also used in G_PreLevelTitleCard. +// +void ST_drawWipeTitleCard(void) { - INT32 aflag = 0; + UINT8 i; - if (!stplyr->texttimer) - return; - - if (stplyr->texttimer < TICRATE/2) - aflag = (9 - 9*stplyr->texttimer/(TICRATE/2)) << V_ALPHASHIFT; - - // A "Bonus Time Start" by any other name... - if (stplyr->textvar == 1) + for (i = 0; i <= r_splitscreen; i++) { - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(52), V_GREENMAP|aflag, M_GetText("GET TO THE GOAL!")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(60), aflag, M_GetText("SCORE MULTIPLIER START!")); - - if (stplyr->finishedtime) - { - V_DrawString(BASEVIDWIDTH/2 - 48, STRINGY(140), aflag, "TIME:"); - V_DrawString(BASEVIDWIDTH/2 - 48, STRINGY(148), aflag, "BONUS:"); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(140), V_ORANGEMAP|aflag, va("%d", (stplyr->startedtime - stplyr->finishedtime)/TICRATE)); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(148), V_ORANGEMAP|aflag, va("%d", (stplyr->finishedtime/TICRATE) * 100)); - } - } - - // Get n [more] Spheres - else if (stplyr->textvar <= 3 && stplyr->textvar >= 2) - { - if (!stplyr->capsule) - return; - - // Yes, this string is an abomination. - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(60), aflag, - va(M_GetText("\x80GET\x82 %d\x80 %s%s%s!"), stplyr->capsule->health, - (stplyr->textvar == 3) ? M_GetText("MORE ") : "", - (G_IsSpecialStage(gamemap)) ? "SPHERE" : "RING", - (stplyr->capsule->health > 1) ? "S" : "")); - } - - // End Bonus - else if (stplyr->textvar == 4) - { - V_DrawString(BASEVIDWIDTH/2 - 48, STRINGY(140), aflag, (G_IsSpecialStage(gamemap)) ? "ORBS:" : "RINGS:"); - V_DrawString(BASEVIDWIDTH/2 - 48, STRINGY(148), aflag, "BONUS:"); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(140), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings)); - V_DrawRightAlignedString(BASEVIDWIDTH/2 + 48, STRINGY(148), V_ORANGEMAP|aflag, va("%d", stplyr->finishedrings * 50)); - ST_DrawNightsOverlayNum(BASEVIDWIDTH/2 + 48, STRINGY(160), aflag, stplyr->lastmarescore, nightsnum, SKINCOLOR_STEEL); - - // If new record, say so! - if (!(netgame || multiplayer) && G_GetBestNightsScore(gamemap, stplyr->lastmare + 1) <= stplyr->lastmarescore) - { - if (stplyr->texttimer & 16) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(184), V_YELLOWMAP|aflag, "* NEW RECORD *"); - } - - if (P_HasGrades(gamemap, stplyr->lastmare + 1)) - { - if (aflag) - V_DrawTranslucentPatch(BASEVIDWIDTH/2 + 60, STRINGY(160), aflag, - ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]); - else - V_DrawScaledPatch(BASEVIDWIDTH/2 + 60, STRINGY(160), 0, - ngradeletters[P_GetGrade(stplyr->lastmarescore, gamemap, stplyr->lastmare)]); - } - } -} -*/ - -/* -static void ST_drawNiGHTSHUD(void) // SRB2kart - unused. -{ - INT32 origamount; - INT32 minlink = 1; - INT32 total_ringcount; - UINT8 nosshack = 0; - - // When debugging, show "0 Link". - if (cv_debug & DBG_NIGHTSBASIC) - minlink = 0; - - // Cheap hack: don't display when the score is showing (it popping up for a split second when exiting a map is intentional) - if (stplyr->texttimer && stplyr->textvar == 4) - minlink = INT32_MAX; - - if (G_IsSpecialStage(gamemap)) - { // Since special stages share score, time, rings, etc. - // disable splitscreen mode for its HUD. - if (stplyr != &players[displayplayers[0]]) - return; - nosshack = splitscreen; - splitscreen = 0; - } - - // Link drawing - if ( -#ifdef HAVE_BLUA - LUA_HudEnabled(hud_nightslink) && -#endif - stplyr->linkcount > minlink) - { - skincolors_t colornum = linkColor[((stplyr->linkcount-1) / 5) % (sizeof(linkColor) / sizeof(skincolors_t))]; - if (stplyr->powers[pw_nights_linkfreeze]) - colornum = SKINCOLOR_WHITE; - - if (stplyr->linktimer < 2*TICRATE/3) - { - INT32 linktrans = (9 - 9*stplyr->linktimer/(2*TICRATE/3)) << V_ALPHASHIFT; - - if (splitscreen) - { - ST_DrawNightsOverlayNum(256, STRINGY(152), SPLITFLAGS(V_SNAPTOBOTTOM)|V_SNAPTORIGHT|linktrans, (stplyr->linkcount-1), nightsnum, colornum); - V_DrawTranslucentMappedPatch(264, STRINGY(152), SPLITFLAGS(V_SNAPTOBOTTOM)|V_SNAPTORIGHT|linktrans, nightslink, - colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); - } - else - { - ST_DrawNightsOverlayNum(160, 160, V_SNAPTOBOTTOM|linktrans, (stplyr->linkcount-1), nightsnum, colornum); - V_DrawTranslucentMappedPatch(168, 160, V_SNAPTOBOTTOM|linktrans, nightslink, - colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); - } - } - else // normal, fullbright - { -#if 0 // Cool but silly number effect where the previous link number fades away - if (stplyr->linkcount > 2 && stplyr->linktimer > (2*TICRATE) - 9) - { - INT32 offs = 10 - (stplyr->linktimer - (2*TICRATE - 9)); - INT32 ghosttrans = offs << V_ALPHASHIFT; - ST_DrawNightsOverlayNum(160, STRINGY(160+offs), SPLITFLAGS(V_SNAPTOBOTTOM)|ghosttrans, (stplyr->linkcount-2), - nightsnum, colornum); - } -#endif - - if (splitscreen) - { - ST_DrawNightsOverlayNum(256, STRINGY(152), SPLITFLAGS(V_SNAPTOBOTTOM)|V_SNAPTORIGHT, (stplyr->linkcount-1), nightsnum, colornum); - V_DrawMappedPatch(264, STRINGY(152), SPLITFLAGS(V_SNAPTOBOTTOM)|V_SNAPTORIGHT, nightslink, - colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); - } - else - { - ST_DrawNightsOverlayNum(160, 160, V_SNAPTOBOTTOM, (stplyr->linkcount-1), nightsnum, colornum); - V_DrawMappedPatch(168, 160, V_SNAPTOBOTTOM, nightslink, - colornum == 0 ? colormaps : R_GetTranslationColormap(TC_DEFAULT, colornum, GTC_CACHE)); - } - } - - // Show remaining link time left in debug - if (cv_debug & DBG_NIGHTSBASIC) - V_DrawCenteredString(BASEVIDWIDTH/2, 180, V_SNAPTOBOTTOM, va("End in %d.%02d", stplyr->linktimer/TICRATE, G_TicsToCentiseconds(stplyr->linktimer))); - } - - // Drill meter - if ( -#ifdef HAVE_BLUA - LUA_HudEnabled(hud_nightsdrill) && -#endif - stplyr->pflags & PF_NIGHTSMODE) - { - INT32 locx, locy; - INT32 dfill; - UINT8 fillpatch; - - if (splitscreen || nosshack) - { - locx = 110; - locy = 188; - } - else - { - locx = 16; - locy = 180; - } - - // Use which patch? - if (stplyr->pflags & PF_DRILLING) - fillpatch = (stplyr->drillmeter & 1) + 1; - else - fillpatch = 0; - - if (splitscreen) - { // 11-5-14 Replaced the old hack with a slightly better hack. -Red - V_DrawScaledPatch(locx, STRINGY(locy)-3, SPLITFLAGS(V_SNAPTOBOTTOM)|V_HUDTRANS, drillbar); - for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), SPLITFLAGS(V_SNAPTOBOTTOM)|V_HUDTRANS, drillfill[fillpatch]); - } - else if (nosshack) - { // Even dirtier hack-of-a-hack to draw seperate drill meters in splitscreen special stages but nothing else. - splitscreen = nosshack; - V_DrawScaledPatch(locx, STRINGY(locy)-3, V_HUDTRANS, drillbar); - for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), V_HUDTRANS, drillfill[fillpatch]); - stplyr = &players[displayplayers[1]]; - if (stplyr->pflags & PF_DRILLING) - fillpatch = (stplyr->drillmeter & 1) + 1; - else - fillpatch = 0; - V_DrawScaledPatch(locx, STRINGY(locy-3), V_SNAPTOBOTTOM|V_HUDTRANS, drillbar); - for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(locx + 2 + dfill, STRINGY(locy + 3), V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]); - stplyr = &players[displayplayers[0]]; - splitscreen = 0; - } - else - { // Draw normally. <:3 - V_DrawScaledPatch(locx, locy, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillbar); - for (dfill = 0; dfill < stplyr->drillmeter/20 && dfill < 96; ++dfill) - V_DrawScaledPatch(locx + 2 + dfill, locy + 3, V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_HUDTRANS, drillfill[fillpatch]); - } - - // Display actual drill amount and bumper time - if (cv_debug & DBG_NIGHTSBASIC) - { - if (stplyr->bumpertime) - V_DrawString(SCX(locx), SCY(locy - 8), V_NOSCALESTART|V_REDMAP|V_MONOSPACE, va("BUMPER: 0.%02d", G_TicsToCentiseconds(stplyr->bumpertime))); - else - V_DrawString(SCX(locx), SCY(locy - 8), V_NOSCALESTART|V_MONOSPACE, va("Drill: %3d%%", (stplyr->drillmeter*100)/(96*20))); - } - } - - if (gametype == GT_RACE || gametype == GT_COMPETITION) - { - ST_drawScore(); - ST_drawTime(); - return; - } - - // Begin drawing brackets/chip display -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_nightsrings)) - { -#endif - ST_DrawOverlayPatch(SCX(16), SCY(8), nbracket); - if (G_IsSpecialStage(gamemap)) - ST_DrawOverlayPatch(SCX(24), SCY(8) + SCZ(8), nsshud); - else - ST_DrawOverlayPatch(SCX(24), SCY(8) + SCZ(8), nhud[(leveltime/2)%12]); - - if (G_IsSpecialStage(gamemap)) - { - INT32 i; - total_ringcount = 0; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE && players[i].health) - total_ringcount += players[i].health - 1; - } - else - total_ringcount = stplyr->health-1; - - if (stplyr->capsule) - { - INT32 amount; - const INT32 length = 88; - - origamount = stplyr->capsule->spawnpoint->angle; - I_Assert(origamount > 0); // should not happen now - - ST_DrawOverlayPatch(SCX(72), SCY(8), nbracket); - ST_DrawOverlayPatch(SCX(74), SCY(8) + SCZ(4), minicaps); - - if (stplyr->capsule->reactiontime != 0) - { - INT32 r; - const INT32 orblength = 20; - - for (r = 0; r < 5; r++) - { - ST_DrawOverlayPatch(SCX(230 - (7*r)), SCY(144), redstat); - ST_DrawOverlayPatch(SCX(188 - (7*r)), SCY(144), orngstat); - ST_DrawOverlayPatch(SCX(146 - (7*r)), SCY(144), yelstat); - ST_DrawOverlayPatch(SCX(104 - (7*r)), SCY(144), byelstat); - } - - amount = (origamount - stplyr->capsule->health); - amount = (amount * orblength)/origamount; - - if (amount > 0) - { - INT32 t; - - // Fill up the bar with blue orbs... in reverse! (yuck) - for (r = amount; r > 0; r--) - { - t = r; - - if (r > 15) ++t; - if (r > 10) ++t; - if (r > 5) ++t; - - ST_DrawOverlayPatch(SCX(69 + (7*t)), SCY(144), bluestat); - } - } - } - else - { - INT32 cfill; - - // Lil' white box! - V_DrawScaledPatch(15, STRINGY(8) + 34, V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulebar); - - amount = (origamount - stplyr->capsule->health); - amount = (amount * length)/origamount; - - for (cfill = 0; cfill < amount && cfill < 88; ++cfill) - V_DrawScaledPatch(15 + cfill + 1, STRINGY(8) + 35, V_SNAPTOLEFT|V_SNAPTOTOP|V_HUDTRANS, capsulefill); - } - - if (total_ringcount >= stplyr->capsule->health) - ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), nredar[leveltime%8]); - else - ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), narrow[(leveltime/2)%8]); - } - else - ST_DrawOverlayPatch(SCX(40), SCY(8) + SCZ(5), narrow[8]); - - if (total_ringcount >= 100) - ST_DrawOverlayNum((total_ringcount >= 1000) ? SCX(76) : SCX(72), SCY(8) + SCZ(11), total_ringcount); - else - ST_DrawOverlayNum(SCX(68), SCY(8) + SCZ(11), total_ringcount); -#ifdef HAVE_BLUA - } -#endif - - // Score - if (!stplyr->exiting -#ifdef HAVE_BLUA - && LUA_HudEnabled(hud_nightsscore) -#endif - ) - { - ST_DrawNightsOverlayNum(304, STRINGY(16), SPLITFLAGS(V_SNAPTOTOP)|V_SNAPTORIGHT, stplyr->marescore, nightsnum, SKINCOLOR_STEEL); - } - - if (!stplyr->exiting -#ifdef HAVE_BLUA - // TODO give this its own section for Lua - && LUA_HudEnabled(hud_nightsscore) -#endif - ) - { - if (modeattacking == ATTACKING_CAPSULES) - { - INT32 maretime = max(stplyr->realtime - stplyr->marebegunat, 0); - fixed_t cornerx = vid.width, cornery = vid.height-SCZ(20); - -#define ASSISHHUDFIX(n) (n*vid.dupx) - ST_DrawOverlayPatch(cornerx-ASSISHHUDFIX(22), cornery, W_CachePatchName("NGRTIMER", PU_HUDGFX)); - ST_DrawPaddedOverlayNum(cornerx-ASSISHHUDFIX(22), cornery, G_TicsToCentiseconds(maretime), 2); - ST_DrawOverlayPatch(cornerx-ASSISHHUDFIX(46), cornery, sboperiod); - if (maretime < 60*TICRATE) - ST_DrawOverlayNum(cornerx-ASSISHHUDFIX(46), cornery, G_TicsToSeconds(maretime)); - else - { - ST_DrawPaddedOverlayNum(cornerx-ASSISHHUDFIX(46), cornery, G_TicsToSeconds(maretime), 2); - ST_DrawOverlayPatch(cornerx-ASSISHHUDFIX(70), cornery, sbocolon); - ST_DrawOverlayNum(cornerx-ASSISHHUDFIX(70), cornery, G_TicsToMinutes(maretime, true)); - } - } -#undef ASSISHHUDFIX - } - - // Ideya time remaining - if (!stplyr->exiting && stplyr->nightstime > 0 -#ifdef HAVE_BLUA - && LUA_HudEnabled(hud_nightstime) -#endif - ) - { - INT32 realnightstime = stplyr->nightstime/TICRATE; - INT32 numbersize; - - if (G_IsSpecialStage(gamemap)) - { - tic_t lowest_time = stplyr->nightstime; - INT32 i; - for (i = 0; i < MAXPLAYERS; i++) - if (playeringame[i] && players[i].pflags & PF_NIGHTSMODE && players[i].nightstime < lowest_time) - lowest_time = players[i].nightstime; - realnightstime = lowest_time/TICRATE; - } - - if (stplyr->powers[pw_flashing] > TICRATE ) // was hit - { - UINT16 flashingLeft = stplyr->powers[pw_flashing]-(TICRATE); - if (flashingLeft < TICRATE/2) // Start fading out - { - UINT32 fadingFlag = (9 - 9*flashingLeft/(TICRATE/2)) << V_ALPHASHIFT; - V_DrawTranslucentPatch(SCX(160 - (minus5sec->width/2)), SCY(28), V_NOSCALESTART|fadingFlag, minus5sec); - } - else - V_DrawScaledPatch(SCX(160 - (minus5sec->width/2)), SCY(28), V_NOSCALESTART, minus5sec); - } - - if (realnightstime < 10) - numbersize = 16/2; - else if (realnightstime < 100) - numbersize = 32/2; - else - numbersize = 48/2; - - if (realnightstime < 10) - ST_DrawNightsOverlayNum(160 + numbersize, STRINGY(12), SPLITFLAGS(V_SNAPTOTOP), realnightstime, - nightsnum, SKINCOLOR_RED); - else - ST_DrawNightsOverlayNum(160 + numbersize, STRINGY(12), SPLITFLAGS(V_SNAPTOTOP), realnightstime, - nightsnum, SKINCOLOR_SUPER4); - - // Show exact time in debug - if (cv_debug & DBG_NIGHTSBASIC) - V_DrawString(160 + numbersize + 8, 24, V_SNAPTOTOP|((realnightstime < 10) ? V_REDMAP : V_YELLOWMAP), va("%02d", G_TicsToCentiseconds(stplyr->nightstime))); - } - - // Show pickup durations - if (cv_debug & DBG_NIGHTSBASIC) - { - UINT16 pwr; - - if (stplyr->powers[pw_nights_superloop]) - { - pwr = stplyr->powers[pw_nights_superloop]; - V_DrawSmallScaledPatch(SCX(110), SCY(44), V_NOSCALESTART, W_CachePatchName("NPRUA0",PU_CACHE)); - V_DrawThinString(SCX(106), SCY(52), V_NOSCALESTART|V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); - } - - if (stplyr->powers[pw_nights_helper]) - { - pwr = stplyr->powers[pw_nights_helper]; - V_DrawSmallScaledPatch(SCX(150), SCY(44), V_NOSCALESTART, W_CachePatchName("NPRUC0",PU_CACHE)); - V_DrawThinString(SCX(146), SCY(52), V_NOSCALESTART|V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); - } - - if (stplyr->powers[pw_nights_linkfreeze]) - { - pwr = stplyr->powers[pw_nights_linkfreeze]; - V_DrawSmallScaledPatch(SCX(190), SCY(44), V_NOSCALESTART, W_CachePatchName("NPRUE0",PU_CACHE)); - V_DrawThinString(SCX(186), SCY(52), V_NOSCALESTART|V_MONOSPACE, va("%2d.%02d", pwr/TICRATE, G_TicsToCentiseconds(pwr))); - } - } - - // Records/extra text -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_nightsrecords)) -#endif - ST_drawNightsRecords(); - - splitscreen = nosshack; -} -*/ - -/* -static void ST_drawWeaponRing(powertype_t weapon, INT32 rwflag, INT32 wepflag, INT32 xoffs, patch_t *pat) -{ - INT32 txtflags = 0, patflags = 0; - - if (stplyr->powers[weapon]) - { - if (stplyr->powers[weapon] >= rw_maximums[wepflag]) - txtflags |= V_YELLOWMAP; - - if (weapon == pw_infinityring - || (stplyr->ringweapons & rwflag && stplyr->health > 1)) - txtflags |= V_20TRANS; - else - { - txtflags |= V_TRANSLUCENT; - patflags = V_80TRANS; - } - - V_DrawScaledPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|patflags, pat); - - if (stplyr->powers[weapon] > 99) - V_DrawThinString(8 + xoffs + 1, STRINGY(162), V_SNAPTOLEFT|txtflags, va("%d", stplyr->powers[weapon])); - else - V_DrawString(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|txtflags, va("%d", stplyr->powers[weapon])); - - if (stplyr->currentweapon == wepflag) - V_DrawScaledPatch(6 + xoffs, STRINGY(162 - (splitscreen ? 4 : 2)), V_SNAPTOLEFT, curweapon); - } - else if (stplyr->ringweapons & rwflag) - V_DrawScaledPatch(8 + xoffs, STRINGY(162), V_SNAPTOLEFT|V_TRANSLUCENT, pat); -} -*/ - -/* -static void ST_drawMatchHUD(void) // SRB2kart - unused. -{ - INT32 offset = (BASEVIDWIDTH / 2) - (NUM_WEAPONS * 10); - - if (!G_BattleGametype()) - return; - - if (G_TagGametype() && !(stplyr->pflags & PF_TAGIT)) - return; - -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_weaponrings)) { -#endif - - if (stplyr->powers[pw_infinityring]) - ST_drawWeaponRing(pw_infinityring, 0, 0, offset, infinityring); - else if (stplyr->health > 1) - V_DrawScaledPatch(8 + offset, STRINGY(162), V_SNAPTOLEFT, normring); - else - V_DrawTranslucentPatch(8 + offset, STRINGY(162), V_SNAPTOLEFT|V_80TRANS, normring); - - if (!stplyr->currentweapon) - V_DrawScaledPatch(6 + offset, STRINGY(162 - (splitscreen ? 4 : 2)), V_SNAPTOLEFT, curweapon); - - offset += 20; - ST_drawWeaponRing(pw_automaticring, RW_AUTO, WEP_AUTO, offset, autoring); - offset += 20; - ST_drawWeaponRing(pw_bouncering, RW_BOUNCE, WEP_BOUNCE, offset, bouncering); - offset += 20; - ST_drawWeaponRing(pw_scatterring, RW_SCATTER, WEP_SCATTER, offset, scatterring); - offset += 20; - ST_drawWeaponRing(pw_grenadering, RW_GRENADE, WEP_GRENADE, offset, grenadering); - offset += 20; - ST_drawWeaponRing(pw_explosionring, RW_EXPLODE, WEP_EXPLODE, offset, explosionring); - offset += 20; - ST_drawWeaponRing(pw_railring, RW_RAIL, WEP_RAIL, offset, railring); - -#ifdef HAVE_BLUA - } - - if (LUA_HudEnabled(hud_powerstones)) { -#endif - - // Power Stones collected - offset = 136; // Used for Y now - - if (stplyr->powers[pw_emeralds] & EMERALD1) - V_DrawScaledPatch(28, STRINGY(offset), V_SNAPTOLEFT, tinyemeraldpics[0]); - - offset += 8; - - if (stplyr->powers[pw_emeralds] & EMERALD2) - V_DrawScaledPatch(40, STRINGY(offset), V_SNAPTOLEFT, tinyemeraldpics[1]); - - if (stplyr->powers[pw_emeralds] & EMERALD6) - V_DrawScaledPatch(16, STRINGY(offset), V_SNAPTOLEFT, tinyemeraldpics[5]); - - offset += 16; - - if (stplyr->powers[pw_emeralds] & EMERALD3) - V_DrawScaledPatch(40, STRINGY(offset), V_SNAPTOLEFT, tinyemeraldpics[2]); - - if (stplyr->powers[pw_emeralds] & EMERALD5) - V_DrawScaledPatch(16, STRINGY(offset), V_SNAPTOLEFT, tinyemeraldpics[4]); - - offset += 8; - - if (stplyr->powers[pw_emeralds] & EMERALD4) - V_DrawScaledPatch(28, STRINGY(offset), V_SNAPTOLEFT, tinyemeraldpics[3]); - - offset -= 16; - - if (stplyr->powers[pw_emeralds] & EMERALD7) - V_DrawScaledPatch(28, STRINGY(offset), V_SNAPTOLEFT, tinyemeraldpics[6]); - -#ifdef HAVE_BLUA - } -#endif -} -*/ - -/* -static inline void ST_drawRaceHUD(void) // SRB2kart - unused. -{ - if (leveltime > starttime-(3*TICRATE) && leveltime <= starttime-(2*TICRATE)) - V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race3->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race3); - else if (leveltime > starttime-(2*TICRATE) && leveltime <= starttime-TICRATE) - V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race2->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race2); - else if (leveltime > starttime-TICRATE && leveltime <= starttime) - V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(race1->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, race1); - else if (leveltime > starttime && leveltime <= starttime+TICRATE) - V_DrawScaledPatch(SCX((BASEVIDWIDTH - SHORT(racego->width))/2), (INT32)(SCY(BASEVIDHEIGHT/2)), V_NOSCALESTART, racego); - - if (circuitmap) - { - if (stplyr->exiting) - V_DrawString(hudinfo[HUD_LAP].x, STRINGY(hudinfo[HUD_LAP].y), V_YELLOWMAP, "FINISHED!"); - else - V_DrawString(hudinfo[HUD_LAP].x, STRINGY(hudinfo[HUD_LAP].y), 0, va("Lap: %u/%d", stplyr->laps, cv_numlaps.value)); - } -} -*/ - -/* -static void ST_drawTagHUD(void) // SRB2kart - unused. -{ - char pstime[33] = ""; - char pstext[33] = ""; - - // Figure out what we're going to print. - if (leveltime < hidetime * TICRATE) //during the hide time, the seeker and hiders have different messages on their HUD. - { - if (hidetime) - sprintf(pstime, "%d", (hidetime - leveltime/TICRATE)); //hide time is in seconds, not tics. - - if (stplyr->pflags & PF_TAGIT && !stplyr->spectator) - sprintf(pstext, "%s", M_GetText("WAITING FOR PLAYERS TO HIDE...")); - else - { - if (!stplyr->spectator) //spectators get a generic HUD message rather than a gametype specific one. - { - if (gametype == GT_HIDEANDSEEK) //hide and seek. - sprintf(pstext, "%s", M_GetText("HIDE BEFORE TIME RUNS OUT!")); - else //default - sprintf(pstext, "%s", M_GetText("FLEE BEFORE YOU ARE HUNTED!")); - } - else - sprintf(pstext, "%s", M_GetText("HIDE TIME REMAINING:")); - } - } - else - { - if (cv_timelimit.value && timelimitintics >= leveltime) - sprintf(pstime, "%d", (timelimitintics-leveltime)/TICRATE); - - if (stplyr->pflags & PF_TAGIT) - sprintf(pstext, "%s", M_GetText("YOU'RE IT!")); - else - { - if (cv_timelimit.value) - sprintf(pstext, "%s", M_GetText("TIME REMAINING:")); - else //Since having no hud message in tag is not characteristic: - sprintf(pstext, "%s", M_GetText("NO TIME LIMIT")); - } - } - - // Print the stuff. - if (pstext[0]) - { - if (splitscreen) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(168), 0, pstext); - else - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(184), 0, pstext); - } - if (pstime[0]) - { - if (splitscreen) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(184), 0, pstime); - else - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(192), 0, pstime); + stplyr = &players[displayplayers[i]]; + ST_preDrawTitleCard(); + ST_drawTitleCard(); } } -static void ST_drawCTFHUD(void) // SRB2kart - unused. -{ - INT32 i; - UINT16 whichflag = 0; - - // Draw the flags - V_DrawSmallScaledPatch(256, (splitscreen) ? STRINGY(160) : STRINGY(176), V_HUDTRANS, rflagico); - V_DrawSmallScaledPatch(288, (splitscreen) ? STRINGY(160) : STRINGY(176), V_HUDTRANS, bflagico); - - for (i = 0; i < MAXPLAYERS; i++) - { - if (players[i].gotflag & GF_REDFLAG) // Red flag isn't at base - V_DrawScaledPatch(256, (splitscreen) ? STRINGY(156) : STRINGY(174), V_HUDTRANS, nonicon); - else if (players[i].gotflag & GF_BLUEFLAG) // Blue flag isn't at base - V_DrawScaledPatch(288, (splitscreen) ? STRINGY(156) : STRINGY(174), V_HUDTRANS, nonicon); - - whichflag |= players[i].gotflag; - if ((whichflag & (GF_REDFLAG|GF_BLUEFLAG)) == (GF_REDFLAG|GF_BLUEFLAG)) - break; // both flags were found, let's stop early - } - - // YOU have a flag. Display a monitor-like icon for it. - if (stplyr->gotflag) - { - patch_t *p = (stplyr->gotflag & GF_REDFLAG) ? gotrflag : gotbflag; - - if (splitscreen) - V_DrawSmallScaledPatch(312, STRINGY(24) + 42, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); - else - V_DrawScaledPatch(304, 24 + 84, V_SNAPTORIGHT|V_SNAPTOTOP|V_HUDTRANS, p); - } - - // Display a countdown timer showing how much time left until the flag your team dropped returns to base. - { - char timeleft[33]; - if (redflag && redflag->fuse > 1) - { - sprintf(timeleft, "%u", (redflag->fuse / TICRATE)); - V_DrawCenteredString(268, STRINGY(184), V_YELLOWMAP|V_HUDTRANS, timeleft); - } - - if (blueflag && blueflag->fuse > 1) - { - sprintf(timeleft, "%u", (blueflag->fuse / TICRATE)); - V_DrawCenteredString(300, STRINGY(184), V_YELLOWMAP|V_HUDTRANS, timeleft); - } - } -} -*/ - -// Draws "Red Team", "Blue Team", or "Spectator" for team gametypes. -/* -static inline void ST_drawTeamName(void) // SRB2kart - unused. -{ - if (stplyr->ctfteam == 1) - V_DrawString(256, splitscreen ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "RED TEAM"); - else if (stplyr->ctfteam == 2) - V_DrawString(248, splitscreen ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "BLUE TEAM"); - else - V_DrawString(244, splitscreen ? STRINGY(184) : STRINGY(192), V_HUDTRANSHALF, "SPECTATOR"); -} -*/ - -/* -static void ST_drawSpecialStageHUD(void) // SRB2kart - unused. -{ - if (totalrings > 0) - ST_DrawNumFromHudWS(HUD_SS_TOTALRINGS, totalrings); - - if (leveltime < 5*TICRATE && totalrings > 0) - { - ST_DrawPatchFromHud(HUD_GETRINGS, getall); - ST_DrawNumFromHud(HUD_GETRINGSNUM, totalrings); - } - - if (sstimer) - { - V_DrawString(hudinfo[HUD_TIMELEFT].x, STRINGY(hudinfo[HUD_TIMELEFT].y), V_HUDTRANS, M_GetText("TIME LEFT")); - ST_DrawNumFromHud(HUD_TIMELEFTNUM, sstimer/TICRATE); - } - else - ST_DrawPatchFromHud(HUD_TIMEUP, timeup); -} -*/ - -/* -static INT32 ST_drawEmeraldHuntIcon(mobj_t *hunt, patch_t **patches, INT32 offset) -{ - INT32 interval, i; - UINT32 dist = ((UINT32)P_AproxDistance(P_AproxDistance(stplyr->mo->x - hunt->x, stplyr->mo->y - hunt->y), stplyr->mo->z - hunt->z))>>FRACBITS; - - if (dist < 128) - { - i = 5; - interval = 5; - } - else if (dist < 512) - { - i = 4; - interval = 10; - } - else if (dist < 1024) - { - i = 3; - interval = 20; - } - else if (dist < 2048) - { - i = 2; - interval = 30; - } - else if (dist < 3072) - { - i = 1; - interval = 35; - } - else - { - i = 0; - interval = 0; - } - - V_DrawScaledPatch(hudinfo[HUD_HUNTPICS].x+offset, STRINGY(hudinfo[HUD_HUNTPICS].y), V_HUDTRANS, patches[i]); - return interval; -} -*/ - -/* -// Separated a few things to stop the SOUND EFFECTS BLARING UGH SHUT UP AAAA -static void ST_doHuntIconsAndSound(void) // SRB2kart - unused. -{ - INT32 interval = 0, newinterval = 0; - - if (hunt1 && hunt1->health) - interval = ST_drawEmeraldHuntIcon(hunt1, hunthoming, -20); - - if (hunt2 && hunt2->health) - { - newinterval = ST_drawEmeraldHuntIcon(hunt2, hunthoming, 0); - if (newinterval && (!interval || newinterval < interval)) - interval = newinterval; - } - - if (hunt3 && hunt3->health) - { - newinterval = ST_drawEmeraldHuntIcon(hunt3, hunthoming, 20); - if (newinterval && (!interval || newinterval < interval)) - interval = newinterval; - } - - if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) - S_StartSound(NULL, sfx_emfind); -} - -static void ST_doItemFinderIconsAndSound(void) // SRB2kart - unused. -{ - INT32 emblems[16]; - thinker_t *th; - mobj_t *mo2; - - UINT8 stemblems = 0, stunfound = 0; - INT32 i; - INT32 interval = 0, newinterval = 0; - INT32 soffset; - - for (i = 0; i < numemblems; ++i) - { - if (emblemlocations[i].type > ET_SKIN || emblemlocations[i].level != gamemap) - continue; - - emblems[stemblems++] = i; - - if (!emblemlocations[i].collected) - ++stunfound; - - if (stemblems >= 16) - break; - } - // Found all/none exist? Don't waste our time - if (!stunfound) - return; - - // Scan thinkers to find emblem mobj with these ids - for (th = thinkercap.next; th != &thinkercap; th = th->next) - { - if (th->function.acp1 != (actionf_p1)P_MobjThinker) - continue; - mo2 = (mobj_t *)th; - - if (mo2->type == MT_EMBLEM) - { - if (!(mo2->flags & MF_SPECIAL)) - continue; - - for (i = 0; i < stemblems; ++i) - { - if (mo2->health == emblems[i]+1) - { - soffset = (i * 20) - ((stemblems-1) * 10); - - newinterval = ST_drawEmeraldHuntIcon(mo2, itemhoming, soffset); - if (newinterval && (!interval || newinterval < interval)) - interval = newinterval; - - break; - } - } - } - } - - if (!(P_AutoPause() || paused) && interval > 0 && leveltime && leveltime % interval == 0) - S_StartSound(NULL, sfx_emfind); -} -*/ - +// // Draw the status bar overlay, customisable: the user chooses which // kind of information to overlay // static void ST_overlayDrawer(void) { - //hu_showscores = auto hide score/time/rings when tab rankings are shown + // hu_showscores = auto hide score/time/rings when tab rankings are shown if (!(hu_showscores && (netgame || multiplayer))) - { K_drawKartHUD(); - /* SRB2kart doesn't need this stuff - if (maptol & TOL_NIGHTS) - ST_drawNiGHTSHUD(); - else - { -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_score)) -#endif - ST_drawScore(); -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_time)) -#endif - ST_drawTime(); -#ifdef HAVE_BLUA - if (LUA_HudEnabled(hud_rings)) -#endif - ST_drawRings(); - if (G_GametypeUsesLives() -#ifdef HAVE_BLUA - && LUA_HudEnabled(hud_lives) -#endif - ) - ST_drawLives(); - } - */ - } - - // GAME OVER pic - /*if (G_GametypeUsesLives() && stplyr->lives <= 0 && !(hu_showscores && (netgame || multiplayer))) - { - patch_t *p; - - if (racecountdown == 1) - p = timeover; - else - p = sboover; - - V_DrawScaledPatch((BASEVIDWIDTH - SHORT(p->width))/2, STRINGY(BASEVIDHEIGHT/2 - (SHORT(p->height)/2)), 0, p); - }*/ - if (!hu_showscores) // hide the following if TAB is held { - // Countdown timer for Race Mode - // ...moved to k_kart.c so we can take advantage of the LAPS_Y value - - /* SRB2kart doesn't need this stuff, I think - // If you are in overtime, put a big honkin' flashin' message on the screen. - if (G_BattleGametype() && cv_overtime.value - && (leveltime > (timelimitintics + TICRATE/2)) && cv_timelimit.value && (leveltime/TICRATE % 2 == 0)) - { - if (splitscreen) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(168), 0, M_GetText("OVERTIME!")); - else - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(184), 0, M_GetText("OVERTIME!")); - } - - // Draw Match-related stuff - //\note Match HUD is drawn no matter what gametype. - // ... just not if you're a spectator. - if (!stplyr->spectator) - ST_drawMatchHUD(); - - // Race HUD Stuff - if (gametype == GT_RACE || gametype == GT_COMPETITION) - ST_drawRaceHUD(); - // Tag HUD Stuff - else if (gametype == GT_TAG || gametype == GT_HIDEANDSEEK) - ST_drawTagHUD(); - // CTF HUD Stuff - else if (gametype == GT_CTF) - ST_drawCTFHUD(); - - // Team names for team gametypes - if (G_GametypeHasTeams()) - ST_drawTeamName(); - - // Special Stage HUD - if (!useNightsSS && G_IsSpecialStage(gamemap) && stplyr == &players[displayplayers[0]]) - ST_drawSpecialStageHUD(); - - // Emerald Hunt Indicators - if (cv_itemfinder.value && M_SecretUnlocked(SECRET_ITEMFINDER)) - ST_doItemFinderIconsAndSound(); - else - ST_doHuntIconsAndSound(); - - if (stplyr->powers[pw_gravityboots] > 3*TICRATE || (stplyr->powers[pw_gravityboots] && leveltime & 1)) - V_DrawScaledPatch(hudinfo[HUD_GRAVBOOTSICO].x, STRINGY(hudinfo[HUD_GRAVBOOTSICO].y), V_SNAPTORIGHT, gravboots); - */ - if (cv_showviewpointtext.value) { if (!(multiplayer && demo.playback)) @@ -1928,53 +905,14 @@ static void ST_overlayDrawer(void) } } } - - // This is where we draw all the fun cheese if you have the chasecam off! - /*if ((stplyr == &players[displayplayers[0]] && !camera[0].chase) - || ((splitscreen && stplyr == &players[displayplayers[1]]) && !camera[1].chase) - || ((splitscreen > 1 && stplyr == &players[displayplayers[2]]) && !camera[2].chase) - || ((splitscreen > 2 && stplyr == &players[displayplayers[3]]) && !camera[3].chase)) - { - ST_drawFirstPersonHUD(); - }*/ } -#ifdef HAVE_BLUA if (!(netgame || multiplayer) || !hu_showscores) LUAh_GameHUD(stplyr); -#endif - - // draw level title Tails - if (*mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer) && !mapreset) -#ifdef HAVE_BLUA - && LUA_HudEnabled(hud_stagetitle) -#endif - ) - ST_drawLevelTitle(); if (!hu_showscores && netgame && !mapreset) { - /*if (G_GametypeUsesLives() && stplyr->lives <= 0 && racecountdown != 1) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press Viewpoint Key to watch a player.")); - else if (gametype == GT_HIDEANDSEEK && - (!stplyr->spectator && !(stplyr->pflags & PF_TAGIT)) && (leveltime > hidetime * TICRATE)) - { - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(116), 0, M_GetText("You cannot move while hiding.")); - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), 0, M_GetText("Press Viewpoint Key to watch a player.")); - } - else if (!G_RaceGametype() && stplyr->playerstate == PST_DEAD && stplyr->lives) //Death overrides spectator text. - { - INT32 respawntime = cv_respawntime.value - stplyr->deadtimer/TICRATE; - if (respawntime > 0 && !stplyr->spectator) - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, va(M_GetText("Respawn in: %d second%s."), respawntime, respawntime == 1 ? "" : "s")); - else - V_DrawCenteredString(BASEVIDWIDTH/2, STRINGY(132), V_HUDTRANSHALF, M_GetText("Press Jump to respawn.")); - } - else*/ if (stplyr->spectator -#ifdef HAVE_BLUA - && LUA_HudEnabled(hud_textspectator) -#endif - ) + if (stplyr->spectator && LUA_HudEnabled(hud_textspectator)) { const char *itemtxt = M_GetText("Item - Join Game"); @@ -2019,15 +957,15 @@ static void ST_overlayDrawer(void) switch (demo.savemode) { case DSM_NOTSAVING: - V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Look Backward: Save replay"); + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|((gametyperules & GTR_BUMPERS) ? V_REDMAP : V_SKYMAP), "Look Backward: Save replay"); break; case DSM_WILLAUTOSAVE: - V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved. (Look Backward: Change title)"); + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|((gametyperules & GTR_BUMPERS) ? V_REDMAP : V_SKYMAP), "Replay will be saved. (Look Backward: Change title)"); break; case DSM_WILLSAVE: - V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|(G_BattleGametype() ? V_REDMAP : V_SKYMAP), "Replay will be saved."); + V_DrawRightAlignedThinString(BASEVIDWIDTH - 2, 2, V_HUDTRANS|V_SNAPTOTOP|V_SNAPTORIGHT|V_ALLOWLOWERCASE|((gametyperules & GTR_BUMPERS) ? V_REDMAP : V_SKYMAP), "Replay will be saved."); break; case DSM_TITLEENTRY: @@ -2081,22 +1019,52 @@ static void ST_MayonakaStatic(void) V_DrawFixedPatch(320<mo && !mapreset) + if (cv_seenames.value && cv_allowseenames.value && displayplayers[0] == consoleplayer && seenplayer && seenplayer->mo) { - if (cv_seenames.value == 1) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, player_names[seenplayer-players]); - else if (cv_seenames.value == 2) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, - va("%s%s", G_GametypeHasTeams() ? ((seenplayer->ctfteam == 1) ? "\x85" : "\x84") : "", player_names[seenplayer-players])); - else //if (cv_seenames.value == 3) - V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF, - va("%s%s", !G_BattleGametype() || (G_GametypeHasTeams() && players[consoleplayer].ctfteam == seenplayer->ctfteam) - ? "\x83" : "\x85", player_names[seenplayer-players])); + INT32 c = 0; + switch (cv_seenames.value) + { + case 1: // Colorless + break; + case 2: // Team + if (G_GametypeHasTeams()) + c = (seenplayer->ctfteam == 1) ? V_REDMAP : V_BLUEMAP; + break; + case 3: // Ally/Foe + default: + // Green = Ally, Red = Foe + if (G_GametypeHasTeams()) + c = (players[consoleplayer].ctfteam == seenplayer->ctfteam) ? V_GREENMAP : V_REDMAP; + else // Everyone is an ally, or everyone is a foe! + c = (G_RingSlingerGametype()) ? V_REDMAP : V_GREENMAP; + break; + } + + V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2 + 15, V_HUDTRANSHALF|c, player_names[seenplayer-players]); } #endif @@ -2117,8 +1085,17 @@ void ST_Drawer(void) #endif if (rendermode != render_none) ST_doPaletteStuff(); + st_translucency = cv_translucenthud.value; + + // Check for a valid level title + // If the HUD is enabled + // And, if Lua is running, if the HUD library has the stage title enabled + if ((stagetitle = (G_IsTitleCardAvailable() && *mapheaderinfo[gamemap-1]->lvlttl != '\0' && !(hu_showscores && (netgame || multiplayer))))) + ST_preDrawTitleCard(); + if (st_overlay) { + UINT8 i; // No deadview! for (i = 0; i <= r_splitscreen; i++) { @@ -2133,7 +1110,10 @@ void ST_Drawer(void) // Draw a fade on level opening if (timeinmap < 16) - V_DrawCustomFadeScreen(((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), 32-(timeinmap*2)); // Then gradually fade out from there + V_DrawCustomFadeScreen(((levelfadecol == 0) ? "FADEMAP1" : "FADEMAP0"), 31-(timeinmap*2)); // Then gradually fade out from there + + if (stagetitle) + ST_drawTitleCard(); ST_drawDebugInfo(); } diff --git a/src/st_stuff.h b/src/st_stuff.h index 3c8c2902f..d8e9b3b5e 100644 --- a/src/st_stuff.h +++ b/src/st_stuff.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,16 +19,24 @@ #include "d_player.h" #include "r_defs.h" +// SRB2Kart +#include "r_skins.h" // NUMFACES + // // STATUS BAR // // Called by main loop. -void ST_Ticker(void); +void ST_Ticker(boolean run); // Called when naming a replay. void ST_DrawDemoTitleEntry(void); +#ifdef HAVE_DISCORDRPC +// Called when you have Discord asks +void ST_AskToJoinEnvelope(void); +#endif + // Called by main loop. void ST_Drawer(void); @@ -45,14 +53,22 @@ void ST_UnloadGraphics(void); void ST_LoadGraphics(void); // face load graphics, called when skin changes -void ST_LoadFaceGraphics(char *rankstr, char *wantstr, char *mmapstr, INT32 playernum); +void ST_LoadFaceGraphics(INT32 playernum); void ST_ReloadSkinFaceGraphics(void); -#ifdef DELFILE -void ST_UnLoadFaceGraphics(INT32 skinnum); -#endif void ST_doPaletteStuff(void); +// title card +void ST_startTitleCard(void); +void ST_runTitleCard(void); +void ST_drawTitleCard(void); +void ST_preDrawTitleCard(void); +void ST_preLevelTitleCardDrawer(void); +void ST_drawWipeTitleCard(void); + +extern tic_t lt_ticker, lt_lasttic; +extern tic_t lt_exitticker, lt_endtime; + // return if player a is in the same team as player b boolean ST_SameTeam(player_t *a, player_t *b); @@ -62,6 +78,7 @@ boolean ST_SameTeam(player_t *a, player_t *b); extern boolean st_overlay; // sb overlay on or off when fullscreen extern INT32 st_palette; // 0 is default, any others are special palettes. +extern INT32 st_translucency; extern lumpnum_t st_borderpatchnum; // patches, also used in intermission @@ -69,47 +86,37 @@ extern patch_t *sboscore; extern patch_t *sbotime; extern patch_t *sbocolon; extern patch_t *sboperiod; -extern patch_t *facerankprefix[MAXSKINS]; // ranking -extern patch_t *facewantprefix[MAXSKINS]; // wanted -extern patch_t *facemmapprefix[MAXSKINS]; // minimap +extern patch_t *faceprefix[MAXSKINS][NUMFACES]; extern patch_t *livesback; +extern patch_t *stlivex; extern patch_t *ngradeletters[7]; /** HUD location information (don't move this comment) */ typedef struct { - INT32 x, y; + INT32 x, y, f; } hudinfo_t; typedef enum { - HUD_LIVESNAME, - HUD_LIVESPIC, - HUD_LIVESNUM, - HUD_LIVESX, + HUD_LIVES, HUD_RINGS, - HUD_RINGSSPLIT, HUD_RINGSNUM, - HUD_RINGSNUMSPLIT, + HUD_RINGSNUMTICS, HUD_SCORE, HUD_SCORENUM, HUD_TIME, - HUD_TIMESPLIT, HUD_MINUTES, - HUD_MINUTESSPLIT, HUD_TIMECOLON, - HUD_TIMECOLONSPLIT, HUD_SECONDS, - HUD_SECONDSSPLIT, HUD_TIMETICCOLON, HUD_TICS, HUD_SS_TOTALRINGS, - HUD_SS_TOTALRINGS_SPLIT, HUD_GETRINGS, HUD_GETRINGSNUM, @@ -117,8 +124,7 @@ typedef enum HUD_TIMELEFTNUM, HUD_TIMEUP, HUD_HUNTPICS, - HUD_GRAVBOOTSICO, - HUD_LAP, + HUD_POWERUPS, NUMHUDITEMS } hudnum_t; diff --git a/src/strcasestr.c b/src/strcasestr.c new file mode 100644 index 000000000..b266278ed --- /dev/null +++ b/src/strcasestr.c @@ -0,0 +1,111 @@ +/* +strcasestr -- case insensitive substring searching function. +*/ +/* +Copyright 2019-2020 James R. +All rights reserved. + +Redistribution and use in source forms, with or without modification, is +permitted provided that the following condition is met: + +1. Redistributions of source code must retain the above copyright notice, this + condition and the following disclaimer. + +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 OWNER 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. +*/ + +static inline int +trycmp (char **pp, char *cp, + const char *q, size_t qn) +{ + char *p; + p = (*pp); + if (strncasecmp(p, q, qn) == 0) + return 0; + (*pp) = strchr(&p[1], (*cp)); + return 1; +} + +static inline void +swapp (char ***ppap, char ***ppbp, char **cpap, char **cpbp) +{ + char **pp; + char *p; + + pp = *ppap; + *ppap = *ppbp; + *ppbp = pp; + + p = *cpap; + *cpap = *cpbp; + *cpbp = p; +} + +char * +strcasestr (const char *s, const char *q) +{ + size_t qn; + + char uc; + char lc; + + char *up; + char *lp; + + char **ppa; + char **ppb; + + char *cpa; + char *cpb; + + uc = toupper(*q); + lc = tolower(*q); + + up = strchr(s, uc); + lp = strchr(s, lc); + + if (!( (intptr_t)up|(intptr_t)lp )) + return 0; + + if (!lp || ( up && up < lp )) + { + ppa = &up; + ppb = &lp; + + cpa = &uc; + cpb = &lc; + } + else + { + ppa = &lp; + ppb = &up; + + cpa = &lc; + cpb = &uc; + } + + qn = strlen(q); + + for (;;) + { + if (trycmp(ppa, cpa, q, qn) == 0) + return (*ppa); + + if (!( (intptr_t)up|(intptr_t)lp )) + break; + + if (!(*ppa) || ( (*ppb) && (*ppb) < (*ppa) )) + swapp(&ppa, &ppb, &cpa, &cpb); + } + + return 0; +} diff --git a/src/string.c b/src/string.c index 2a03e8729..e430c5cc3 100644 --- a/src/string.c +++ b/src/string.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2018 by Sonic Team Junior. +// Copyright (C) 2006-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -50,3 +50,5 @@ size_t strlcpy(char *dst, const char *src, size_t siz) } #endif + +#include "strcasestr.c" diff --git a/src/tables.c b/src/tables.c index 7d5137075..70a1ecd0a 100644 --- a/src/tables.c +++ b/src/tables.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -72,7 +72,7 @@ static FUNCMATH angle_t AngleAdj(const fixed_t fa, const fixed_t wf, const angle_t adj = 0x77; const boolean fan = fa < 0; const fixed_t sl = FixedDiv(fa, wf*2); - const fixed_t lb = FixedRem(fa, wf*2); + const fixed_t lb = fa % (wf*2); const fixed_t lo = (wf*2)-lb; if (ra == 0) @@ -168,12 +168,10 @@ angle_t FixedAngle(fixed_t fa) } -#if !(defined _NDS) || !(defined NONET) #include "t_ftan.c" #include "t_fsin.c" fixed_t *finecosine = &finesine[FINEANGLES/4]; -#endif #include "t_tan2a.c" diff --git a/src/tables.h b/src/tables.h index 2c2f74e1d..e760a1e65 100644 --- a/src/tables.h +++ b/src/tables.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -25,7 +25,6 @@ #define ANGLETOFINESHIFT 19 // 0x100000000 to 0x2000 #define FINEANGLE_C(x) ((FixedAngle((x)*FRACUNIT)>>ANGLETOFINESHIFT) & FINEMASK) // ((x*(ANGLE_45/45))>>ANGLETOFINESHIFT) & FINEMASK -#if !(defined _NDS) || !(defined NONET) // Effective size is 10240. extern fixed_t finesine[5*FINEANGLES/4]; @@ -34,7 +33,6 @@ extern fixed_t *finecosine; // Effective size is 4096. extern fixed_t finetangent[FINEANGLES/2]; -#endif #define ANG1 0x00B60B61 //0.B6~ #define ANG2 0x016C16C1 //.6C1~ @@ -118,17 +116,9 @@ void FM_Rotate(matrix_t *dest, angle_t angle, fixed_t x, fixed_t y, fixed_t z); // The table values in tables.c are calculated with this many fractional bits. #define FINE_FRACBITS 16 -#if (defined _NDS) && (defined NONET) -// Use the NDS's trig functions. This would break netplay, so we only do -// it if NONET is defined. -#define FINESINE(n) ((fixed_t)sinLerp((INT16)(((INT32)(n))<<(ANGLETOFINESHIFT-17))) << (FRACBITS - 12)) -#define FINECOSINE(n) ((fixed_t)cosLerp((INT16)(((INT32)(n))<<(ANGLETOFINESHIFT-17))) << (FRACBITS - 12)) -#define FINETANGENT(n) ((fixed_t)tanLerp((INT16)(((INT32)(n)-(FINEANGLES>>2))<<(ANGLETOFINESHIFT-17))) << (FRACBITS - 12)) -#else // These macros should be used in case FRACBITS < FINE_FRACBITS. #define FINESINE(n) (finesine[n]>>(FINE_FRACBITS-FRACBITS)) #define FINECOSINE(n) (finecosine[n]>>(FINE_FRACBITS-FRACBITS)) #define FINETANGENT(n) (finetangent[n]>>(FINE_FRACBITS-FRACBITS)) -#endif #endif diff --git a/src/tmap.nas b/src/tmap.nas index c72c1890a..106f38e96 100644 --- a/src/tmap.nas +++ b/src/tmap.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DooM Legacy Team. -;; Copyright (C) 1999-2018 by Sonic Team Junior. +;; Copyright (C) 1999-2020 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/tmap.s b/src/tmap.s index babd4ec1a..3a4cf2e1a 100644 --- a/src/tmap.s +++ b/src/tmap.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -60,7 +60,7 @@ C(vidwidth): .long 0 //use this one out of the inner loops //so you don't need to patch everywhere... #ifdef USEASM -#if !defined( LINUX) && !defined( __OS2__) +#if !defined( LINUX) .text #endif .globl C(ASM_PatchRowBytes) @@ -616,7 +616,7 @@ vskydone: ystep: .long 0 xstep: .long 0 C(texwidth): .long 64 // texture width -#if !defined( LINUX) && !defined( __OS2__) +#if !defined( LINUX) .text #endif #ifdef LINUX @@ -1338,7 +1338,7 @@ wdone: .data advancetable: .long 0, 0 -#if !defined( LINUX) && !defined( __OS2__) +#if !defined( LINUX) .text #endif #ifdef LINUX diff --git a/src/tmap_asm.s b/src/tmap_asm.s index 99cb0b627..3cd0f87cc 100644 --- a/src/tmap_asm.s +++ b/src/tmap_asm.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/tmap_mmx.nas b/src/tmap_mmx.nas index c512de8e9..15b97499d 100644 --- a/src/tmap_mmx.nas +++ b/src/tmap_mmx.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DOSDOOM. -;; Copyright (C) 2010-2018 by Sonic Team Junior. +;; Copyright (C) 2010-2020 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/tmap_vc.nas b/src/tmap_vc.nas index e943d48d8..49eb21a6d 100644 --- a/src/tmap_vc.nas +++ b/src/tmap_vc.nas @@ -1,7 +1,7 @@ ;; SONIC ROBO BLAST 2 ;;----------------------------------------------------------------------------- ;; Copyright (C) 1998-2000 by DooM Legacy Team. -;; Copyright (C) 1999-2018 by Sonic Team Junior. +;; Copyright (C) 1999-2020 by Sonic Team Junior. ;; ;; This program is free software distributed under the ;; terms of the GNU General Public License, version 2. diff --git a/src/v_video.c b/src/v_video.c index 3771419d5..89020eae8 100644 --- a/src/v_video.c +++ b/src/v_video.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,8 +15,12 @@ #include "doomdef.h" #include "r_local.h" +#include "p_local.h" // stplyr +#include "g_game.h" // players #include "v_video.h" +#include "st_stuff.h" #include "hu_stuff.h" +#include "f_finale.h" #include "r_draw.h" #include "console.h" @@ -26,12 +30,13 @@ #include "m_random.h" #include "doomstat.h" -#include "k_hud.h" - #ifdef HWRENDER -#include "hardware/hw_main.h" +#include "hardware/hw_glob.h" #endif +// SRB2Kart +#include "k_hud.h" + // Each screen is [vid.width*vid.height]; UINT8 *screens[5]; // screens[0] = main display window @@ -40,72 +45,45 @@ UINT8 *screens[5]; // screens[3] = fade screen start // screens[4] = fade screen end, postimage tempoarary buffer -consvar_t cv_ticrate = {"showfps", "No", 0, CV_YesNo, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_ticrate = CVAR_INIT ("showfps", "No", 0, CV_YesNo, NULL); static void CV_palette_OnChange(void); static CV_PossibleValue_t gamma_cons_t[] = {{-15, "MIN"}, {5, "MAX"}, {0, NULL}}; -consvar_t cv_globalgamma = {"gamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_globalgamma = CVAR_INIT ("gamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange); static CV_PossibleValue_t saturation_cons_t[] = {{0, "MIN"}, {10, "MAX"}, {0, NULL}}; -consvar_t cv_globalsaturation = {"saturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_globalsaturation = CVAR_INIT ("saturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange); #define huecoloursteps 4 static CV_PossibleValue_t hue_cons_t[] = {{0, "MIN"}, {(huecoloursteps*6)-1, "MAX"}, {0, NULL}}; -consvar_t cv_rhue = {"rhue", "0", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_yhue = {"yhue", "4", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ghue = {"ghue", "8", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_chue = {"chue", "12", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_bhue = {"bhue", "16", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mhue = {"mhue", "20", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_rhue = CVAR_INIT ("rhue", "0", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange); +consvar_t cv_yhue = CVAR_INIT ("yhue", "4", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange); +consvar_t cv_ghue = CVAR_INIT ("ghue", "8", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange); +consvar_t cv_chue = CVAR_INIT ("chue", "12", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange); +consvar_t cv_bhue = CVAR_INIT ("bhue", "16", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange); +consvar_t cv_mhue = CVAR_INIT ("mhue", "20", CV_SAVE|CV_CALL, hue_cons_t, CV_palette_OnChange); -consvar_t cv_rgamma = {"rgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ygamma = {"ygamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ggamma = {"ggamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_cgamma = {"cgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_bgamma = {"bgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_mgamma = {"mgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_rgamma = CVAR_INIT ("rgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange); +consvar_t cv_ygamma = CVAR_INIT ("ygamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange); +consvar_t cv_ggamma = CVAR_INIT ("ggamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange); +consvar_t cv_cgamma = CVAR_INIT ("cgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange); +consvar_t cv_bgamma = CVAR_INIT ("bgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange); +consvar_t cv_mgamma = CVAR_INIT ("mgamma", "0", CV_SAVE|CV_CALL, gamma_cons_t, CV_palette_OnChange); -consvar_t cv_rsaturation = {"rsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_ysaturation = {"ysaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_gsaturation = {"gsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_csaturation = {"csaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_bsaturation = {"bsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_msaturation = {"msaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_rsaturation = CVAR_INIT ("rsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange); +consvar_t cv_ysaturation = CVAR_INIT ("ysaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange); +consvar_t cv_gsaturation = CVAR_INIT ("gsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange); +consvar_t cv_csaturation = CVAR_INIT ("csaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange); +consvar_t cv_bsaturation = CVAR_INIT ("bsaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange); +consvar_t cv_msaturation = CVAR_INIT ("msaturation", "10", CV_SAVE|CV_CALL, saturation_cons_t, CV_palette_OnChange); static CV_PossibleValue_t constextsize_cons_t[] = { {V_NOSCALEPATCH, "Small"}, {V_SMALLSCALEPATCH, "Medium"}, {V_MEDSCALEPATCH, "Large"}, {0, "Huge"}, {0, NULL}}; static void CV_constextsize_OnChange(void); -consvar_t cv_constextsize = {"con_textsize", "Medium", CV_SAVE|CV_CALL, constextsize_cons_t, CV_constextsize_OnChange, 0, NULL, NULL, 0, 0, NULL}; - -#ifdef HWRENDER -static void CV_Gammaxxx_ONChange(void); -// Saved hardware mode variables -// - You can change them in software, -// but they won't do anything. -static CV_PossibleValue_t grgamma_cons_t[] = {{1, "MIN"}, {255, "MAX"}, {0, NULL}}; -static CV_PossibleValue_t grfakecontrast_cons_t[] = {{0, "Standard"}, {1, "Smooth"}, {0, NULL}}; - -consvar_t cv_grshaders = {"gr_shaders", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfovchange = {"gr_fovchange", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grgammared = {"gr_gammared", "127", CV_SAVE|CV_CALL, grgamma_cons_t, - CV_Gammaxxx_ONChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grgammagreen = {"gr_gammagreen", "127", CV_SAVE|CV_CALL, grgamma_cons_t, - CV_Gammaxxx_ONChange, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grgammablue = {"gr_gammablue", "127", CV_SAVE|CV_CALL, grgamma_cons_t, - CV_Gammaxxx_ONChange, 0, NULL, NULL, 0, 0, NULL}; - -//static CV_PossibleValue_t CV_MD2[] = {{0, "Off"}, {1, "On"}, {2, "Old"}, {0, NULL}}; -// console variables in development -consvar_t cv_grmdls = {"gr_mdls", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfallbackplayermodel = {"gr_fallbackplayermodel", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; - -consvar_t cv_grshearing = {"gr_shearing", "Off", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grspritebillboarding = {"gr_spritebillboarding", "On", CV_SAVE, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -consvar_t cv_grfakecontrast = {"gr_fakecontrast", "Standard", CV_SAVE, grfakecontrast_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; -#endif +consvar_t cv_constextsize = CVAR_INIT ("con_textsize", "Medium", CV_SAVE|CV_CALL, constextsize_cons_t, CV_constextsize_OnChange); // local copy of the palette for V_GetColor() RGBA_t *pLocalPalette = NULL; @@ -119,6 +97,7 @@ toast 18/04/17 */ float Cubepal[2][2][2][3]; +boolean Cubeapply = false; // returns whether to apply cube, selectively avoiding expensive operations static boolean InitCube(void) @@ -303,14 +282,43 @@ static boolean InitCube(void) return true; } +#ifdef BACKWARDSCOMPATCORRECTION +/* +So it turns out that the way gamma was implemented previously, the default +colour profile of the game was messed up. Since this bad decision has been +around for a long time, and the intent is to keep the base game looking the +same, I'm not gonna be the one to remove this base modification. +toast 20/04/17 +... welp yes i am (27/07/19, see the ifdef around it) +*/ +const UINT8 correctiontable[256] = + {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, + 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}; +#endif + // keep a copy of the palette so that we can get the RGB value for a color index at any time. static void LoadPalette(const char *lumpname) { - boolean cube = InitCube(); lumpnum_t lumpnum = W_GetNumForName(lumpname); size_t i, palsize = W_LumpLength(lumpnum)/3; UINT8 *pal; + Cubeapply = InitCube(); + Z_Free(pLocalPalette); Z_Free(pMasterPalette); @@ -320,49 +328,61 @@ static void LoadPalette(const char *lumpname) pal = W_CacheLumpNum(lumpnum, PU_CACHE); for (i = 0; i < palsize; i++) { +#ifdef BACKWARDSCOMPATCORRECTION + pMasterPalette[i].s.red = pLocalPalette[i].s.red = correctiontable[*pal++]; + pMasterPalette[i].s.green = pLocalPalette[i].s.green = correctiontable[*pal++]; + pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = correctiontable[*pal++]; +#else pMasterPalette[i].s.red = pLocalPalette[i].s.red = *pal++; pMasterPalette[i].s.green = pLocalPalette[i].s.green = *pal++; pMasterPalette[i].s.blue = pLocalPalette[i].s.blue = *pal++; +#endif pMasterPalette[i].s.alpha = pLocalPalette[i].s.alpha = 0xFF; - // lerp of colour cubing! - if (cube) - { - float working[4][3]; - float linear; - UINT8 q; + // lerp of colour cubing! if you want, make it smoother yourself + if (Cubeapply) + V_CubeApply(&pLocalPalette[i].s.red, &pLocalPalette[i].s.green, &pLocalPalette[i].s.blue); + } +} - linear = (pLocalPalette[i].s.red/255.0); +void V_CubeApply(UINT8 *red, UINT8 *green, UINT8 *blue) +{ + float working[4][3]; + float linear; + UINT8 q; + + if (!Cubeapply) + return; + + linear = (*red/255.0); #define dolerp(e1, e2) ((1 - linear)*e1 + linear*e2) - for (q = 0; q < 3; q++) - { - working[0][q] = dolerp(Cubepal[0][0][0][q], Cubepal[1][0][0][q]); - working[1][q] = dolerp(Cubepal[0][1][0][q], Cubepal[1][1][0][q]); - working[2][q] = dolerp(Cubepal[0][0][1][q], Cubepal[1][0][1][q]); - working[3][q] = dolerp(Cubepal[0][1][1][q], Cubepal[1][1][1][q]); - } - linear = (pLocalPalette[i].s.green/255.0); - for (q = 0; q < 3; q++) - { - working[0][q] = dolerp(working[0][q], working[1][q]); - working[1][q] = dolerp(working[2][q], working[3][q]); - } - linear = (pLocalPalette[i].s.blue/255.0); - for (q = 0; q < 3; q++) - { - working[0][q] = 255*dolerp(working[0][q], working[1][q]); - if (working[0][q] > 255.0) - working[0][q] = 255.0; - else if (working[0][q] < 0.0) - working[0][q] = 0.0; - } + for (q = 0; q < 3; q++) + { + working[0][q] = dolerp(Cubepal[0][0][0][q], Cubepal[1][0][0][q]); + working[1][q] = dolerp(Cubepal[0][1][0][q], Cubepal[1][1][0][q]); + working[2][q] = dolerp(Cubepal[0][0][1][q], Cubepal[1][0][1][q]); + working[3][q] = dolerp(Cubepal[0][1][1][q], Cubepal[1][1][1][q]); + } + linear = (*green/255.0); + for (q = 0; q < 3; q++) + { + working[0][q] = dolerp(working[0][q], working[1][q]); + working[1][q] = dolerp(working[2][q], working[3][q]); + } + linear = (*blue/255.0); + for (q = 0; q < 3; q++) + { + working[0][q] = 255*dolerp(working[0][q], working[1][q]); + if (working[0][q] > 255.0) + working[0][q] = 255.0; + else if (working[0][q] < 0.0) + working[0][q] = 0.0; + } #undef dolerp - pLocalPalette[i].s.red = (UINT8)(working[0][0]); - pLocalPalette[i].s.green = (UINT8)(working[0][1]); - pLocalPalette[i].s.blue = (UINT8)(working[0][2]); - } - } + *red = (UINT8)(working[0][0]); + *green = (UINT8)(working[0][1]); + *blue = (UINT8)(working[0][2]); } const char *R_GetPalname(UINT16 num) @@ -399,7 +419,7 @@ void V_SetPalette(INT32 palettenum) LoadMapPalette(); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_SetPalette(&pLocalPalette[palettenum*256]); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) else @@ -413,7 +433,7 @@ void V_SetPaletteLump(const char *pal) { LoadPalette(pal); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_SetPalette(pLocalPalette); #if (defined (__unix__) && !defined (MSDOS)) || defined (UNIXCOMMON) || defined (HAVE_SDL) else @@ -433,16 +453,6 @@ static void CV_palette_OnChange(void) V_SetPalette(0); } -// change the palette directly to see the change -#ifdef HWRENDER -static void CV_Gammaxxx_ONChange(void) -{ - if (rendermode != render_soft && rendermode != render_none) - V_SetPalette(0); -} -#endif - - #if defined (__GNUC__) && defined (__i386__) && !defined (NOASM) && !defined (__APPLE__) && !defined (NORUSEASM) void VID_BlitLinearScreen_ASM(const UINT8 *srcptr, UINT8 *destptr, INT32 width, INT32 height, size_t srcrowbytes, size_t destrowbytes); @@ -504,12 +514,12 @@ static inline UINT8 transmappedpdraw(const UINT8 *dest, const UINT8 *source, fix } // Draws a patch scaled to arbitrary size. -void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, const UINT8 *colormap) +void V_DrawStretchyFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, fixed_t vscale, INT32 scrn, patch_t *patch, const UINT8 *colormap) { UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); UINT32 alphalevel = 0; - fixed_t col, ofs, colfrac, rowfrac, fdup; + fixed_t col, ofs, colfrac, rowfrac, fdup, vdup; INT32 dupx, dupy; const column_t *column; UINT8 *desttop, *dest, *deststart, *destend; @@ -524,7 +534,7 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t //if (rendermode != render_soft && !con_startup) // Why? if (rendermode == render_opengl) { - HWR_DrawFixedPatch((GLPatch_t *)patch, x, y, pscale, scrn, colormap); + HWR_DrawStretchyFixedPatch((GLPatch_t *)patch, x, y, pscale, vscale, scrn, colormap); return; } #endif @@ -535,19 +545,20 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) { if (alphalevel == 13) - alphalevel = hudminusalpha[hudtrans]; + alphalevel = hudminusalpha[st_translucency]; else if (alphalevel == 14) - alphalevel = 10 - hudtrans; - /*else if (alphalevel == 15) - alphalevel = hudplusalpha[hudtrans];*/ + alphalevel = 10 - st_translucency; + else if (alphalevel == 15) + alphalevel = hudplusalpha[st_translucency]; if (alphalevel >= 10) return; // invis - } - if (alphalevel) - { - v_translevel = transtables + ((alphalevel-1)<topoffset)<topoffset)<>FRACBITS) < column->length; ofs += rowfrac) { @@ -697,6 +710,10 @@ void V_DrawFixedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t // Draws a patch cropped and scaled to arbitrary size. void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_t *patch, fixed_t sx, fixed_t sy, fixed_t w, fixed_t h) { + UINT8 (*patchdrawfunc)(const UINT8*, const UINT8*, fixed_t); + UINT32 alphalevel = 0; + // boolean flip = false; + fixed_t col, ofs, colfrac, rowfrac, fdup; INT32 dupx, dupy; const column_t *column; @@ -707,6 +724,7 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ return; #ifdef HWRENDER + //if (rendermode != render_soft && !con_startup) // Not this again if (rendermode == render_opengl) { HWR_DrawCroppedPatch((GLPatch_t*)patch,x,y,pscale,scrn,sx,sy,w,h); @@ -714,6 +732,28 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ } #endif + patchdrawfunc = standardpdraw; + + v_translevel = NULL; + if ((alphalevel = ((scrn & V_ALPHAMASK) >> V_ALPHASHIFT))) + { + if (alphalevel == 13) + alphalevel = hudminusalpha[st_translucency]; + else if (alphalevel == 14) + alphalevel = 10 - st_translucency; + else if (alphalevel == 15) + alphalevel = hudplusalpha[st_translucency]; + + if (alphalevel >= 10) + return; // invis + + if (alphalevel) + { + v_translevel = transtables + ((alphalevel-1)<>= FRACBITS; // Center it if necessary - if (!(scrn & V_SCALEPATCHMASK)) - { - // if it's meant to cover the whole screen, black out the rest - // BAD, BAD, BAD, FUCK OFF, STOP, EW, AAAAAAA - // This does NOT account for transparent pixels - /*if (x == 0 && SHORT(patch->width) == BASEVIDWIDTH && y == 0 && SHORT(patch->height) == BASEVIDHEIGHT) - { - column = (const column_t *)((const UINT8 *)(patch) + LONG(patch->columnofs[0])); - source = (const UINT8 *)(column) + 3; - V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, (column->topdelta == 0xff ? 31 : source[0])); - }*/ - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (scrn & V_SNAPTORIGHT) - x += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(scrn & V_SNAPTOLEFT)) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (scrn & V_SNAPTOBOTTOM) - y += (vid.height - (BASEVIDHEIGHT * dupy)); - else if (!(scrn & V_SNAPTOTOP)) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; - } - } + // adjustxy desttop += (y*vid.width) + x; } - for (col = sx<>FRACBITS) < SHORT(patch->width) && (col>>FRACBITS) < w; col += colfrac, ++x, desttop++) + for (col = sx<>FRACBITS) < SHORT(patch->width) && ((col>>FRACBITS) - sx) < w; col += colfrac, ++x, desttop++) { INT32 topdelta, prevdelta = -1; if (x < 0) // don't draw off the left of the screen (WRAP PREVENTION) @@ -793,12 +805,18 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ prevdelta = topdelta; source = (const UINT8 *)(column) + 3; dest = desttop; - dest += FixedInt(FixedMul(topdelta< 0) + { + dest += FixedInt(FixedMul((topdelta-sy)<>FRACBITS) < column->length && (ofs>>FRACBITS) < h; ofs += rowfrac) + for (; dest < deststop && (ofs>>FRACBITS) < column->length && (((ofs>>FRACBITS) - sy) + topdelta) < h; ofs += rowfrac) { if (dest >= screens[scrn&V_PARAMMASK]) // don't draw off the top of the screen (CRASH PREVENTION) - *dest = source[ofs>>FRACBITS]; + *dest = patchdrawfunc(dest, source, ofs); dest += vid.width; } column = (const column_t *)((const UINT8 *)column + column->length + 4); @@ -810,19 +828,11 @@ void V_DrawCroppedPatch(fixed_t x, fixed_t y, fixed_t pscale, INT32 scrn, patch_ // V_DrawContinueIcon // Draw a mini player! If we can, that is. Otherwise we draw a star. // -void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT8 skincolor) +void V_DrawContinueIcon(INT32 x, INT32 y, INT32 flags, INT32 skinnum, UINT16 skincolor) { - if (skinnum < 0 || skinnum >= numskins || (skins[skinnum].flags & SF_HIRES)) - V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_CACHE)); // Draw a star - else - { // Find front angle of the first waiting frame of the character's actual sprites - spriteframe_t *sprframe = &skins[skinnum].spritedef.spriteframes[2 & FF_FRAMEMASK]; - patch_t *patch = W_CachePatchNum(sprframe->lumppat[0], PU_CACHE); - const UINT8 *colormap = R_GetTranslationColormap(skinnum, skincolor, GTC_CACHE); - - // No variant for translucency - V_DrawTinyMappedPatch(x, y, flags, patch, colormap); - } + (void)skinnum; + (void)skincolor; + V_DrawScaledPatch(x - 10, y - 14, flags, W_CachePatchName("CONTINS", PU_PATCH)); } // @@ -865,6 +875,7 @@ void V_DrawFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) return; #ifdef HWRENDER + //if (rendermode != render_soft && !con_startup) // Not this again if (rendermode == render_opengl) { HWR_DrawFill(x, y, w, h, c); @@ -929,7 +940,7 @@ static UINT32 V_GetHWConsBackColor(void) switch (cons_backcolor.value) { case 0: hwcolor = 0xffffff00; break; // White - case 1: hwcolor = 0x80808000; break; // Gray + case 1: hwcolor = 0x80808000; break; // Black case 2: hwcolor = 0xdeb88700; break; // Sepia case 3: hwcolor = 0x40201000; break; // Brown case 4: hwcolor = 0xfa807200; break; // Pink @@ -955,11 +966,14 @@ static UINT32 V_GetHWConsBackColor(void) #endif // THANK YOU MPC!!! +// and thanks toaster for cleaning it up. void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) { UINT8 *dest; - INT32 u, v; + const UINT8 *deststop; + INT32 u; + UINT8 *fadetable; UINT32 alphalevel = 0; if (rendermode == render_none) @@ -969,44 +983,34 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) if (rendermode == render_opengl) { UINT32 hwcolor = V_GetHWConsBackColor(); - HWR_DrawConsoleFill(x, y, w, h, hwcolor, c); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. + HWR_DrawConsoleFill(x, y, w, h, c, hwcolor); // we still use the regular color stuff but only for flags. actual draw color is "hwcolor" for this. return; } #endif + if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) + { + if (alphalevel == 13) + alphalevel = hudminusalpha[st_translucency]; + else if (alphalevel == 14) + alphalevel = 10 - st_translucency; + else if (alphalevel == 15) + alphalevel = hudplusalpha[st_translucency]; + + if (alphalevel >= 10) + return; // invis + } + if (!(c & V_NOSCALESTART)) { INT32 dupx = vid.dupx, dupy = vid.dupy; - if (x == 0 && y == 0 && w == BASEVIDWIDTH && h == BASEVIDHEIGHT) - { // Clear the entire screen, from dest to deststop. Yes, this really works. - memset(screens[0], (UINT8)(c&255), vid.width * vid.height * vid.bpp); - return; - } - x *= dupx; y *= dupy; w *= dupx; h *= dupy; - // Center it if necessary - if (vid.width != BASEVIDWIDTH * dupx) - { - // dupx adjustments pretend that screen width is BASEVIDWIDTH * dupx, - // so center this imaginary screen - if (c & V_SNAPTORIGHT) - x += (vid.width - (BASEVIDWIDTH * dupx)); - else if (!(c & V_SNAPTOLEFT)) - x += (vid.width - (BASEVIDWIDTH * dupx)) / 2; - } - if (vid.height != BASEVIDHEIGHT * dupy) - { - // same thing here - if (c & V_SNAPTOBOTTOM) - y += (vid.height - (BASEVIDHEIGHT * dupy)); - else if (!(c & V_SNAPTOTOP)) - y += (vid.height - (BASEVIDHEIGHT * dupy)) / 2; - } + // adjustxy } if (x >= vid.width || y >= vid.height) @@ -1028,37 +1032,33 @@ void V_DrawFillConsoleMap(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c) h = vid.height-y; dest = screens[0] + y*vid.width + x; - - if ((alphalevel = ((c & V_ALPHAMASK) >> V_ALPHASHIFT))) - { - if (alphalevel == 13) - alphalevel = hudminusalpha[cv_translucenthud.value]; - else if (alphalevel == 14) - alphalevel = 10 - cv_translucenthud.value; - else if (alphalevel == 15) - alphalevel = hudplusalpha[cv_translucenthud.value]; - - if (alphalevel >= 10) - return; // invis - } + deststop = screens[0] + vid.rowbytes * vid.height; c &= 255; - if (!alphalevel) { - for (v = 0; v < h; v++, dest += vid.width) { - for (u = 0; u < w; u++) { - dest[u] = consolebgmap[dest[u]]; + // Jimita (12-04-2018) + if (alphalevel) + { + fadetable = ((UINT8 *)transtables + ((alphalevel-1)<= 0) && dest < deststop; dest += vid.width) + { + u = 0; + while (u < w) + { + dest[u] = fadetable[consolebgmap[dest[u]]]; + u++; } } - } else { // mpc 12-04-2018 - const UINT8 *fadetable = ((UINT8 *)transtables + ((alphalevel-1)<y) ? y : x - w = clip(w,vid.width); - h = clip(h,vid.height); -#undef clip - for (v = 0; v < h; v++, dest += vid.width) { - for (u = 0; u < w; u++) { - dest[u] = fadetable[consolebgmap[dest[u]]]; + } + else + { + for (;(--h >= 0) && dest < deststop; dest += vid.width) + { + u = 0; + while (u < w) + { + dest[u] = consolebgmap[dest[u]]; + u++; } } } @@ -1145,6 +1145,83 @@ void V_DrawDiag(INT32 x, INT32 y, INT32 wh, INT32 c) } } +// +// If color is 0x00 to 0xFF, draw transtable (strength range 0-9). +// Else, use COLORMAP lump (strength range 0-31). +// c is not color, it is for flags only. transparency flags will be ignored. +// IF YOU ARE NOT CAREFUL, THIS CAN AND WILL CRASH! +// I have kept the safety checks for strength out of this function; +// I don't trust Lua users with it, so it doesn't matter. +// +void V_DrawFadeFill(INT32 x, INT32 y, INT32 w, INT32 h, INT32 c, UINT16 color, UINT8 strength) +{ + UINT8 *dest; + const UINT8 *deststop; + INT32 u; + UINT8 *fadetable; + + if (rendermode == render_none) + return; + +#ifdef HWRENDER + if (rendermode == render_opengl) + { + // ughhhhh please can someone else do this? thanks ~toast 25/7/19 in 38 degrees centigrade w/o AC + HWR_DrawFadeFill(x, y, w, h, c, color, strength); // toast two days later - left above comment in 'cause it's funny + return; + } +#endif + + if (!(c & V_NOSCALESTART)) + { + INT32 dupx = vid.dupx, dupy = vid.dupy; + + x *= dupx; + y *= dupy; + w *= dupx; + h *= dupy; + + // Center it if necessary + // adjustxy + } + + if (x >= vid.width || y >= vid.height) + return; // off the screen + if (x < 0) { + w += x; + x = 0; + } + if (y < 0) { + h += y; + y = 0; + } + + if (w <= 0 || h <= 0) + return; // zero width/height wouldn't draw anything + if (x + w > vid.width) + w = vid.width-x; + if (y + h > vid.height) + h = vid.height-y; + + dest = screens[0] + y*vid.width + x; + deststop = screens[0] + vid.rowbytes * vid.height; + + c &= 255; + + fadetable = ((color & 0xFF00) // Color is not palette index? + ? ((UINT8 *)colormaps + strength*256) // Do COLORMAP fade. + : ((UINT8 *)transtables + ((9-strength)<= 0) && dest < deststop; dest += vid.width) + { + u = 0; + while (u < w) + { + dest[u] = fadetable[dest[u]]; + u++; + } + } +} + // // Fills a box of pixels using a flat texture as a pattern, scaled to screen size. // @@ -1327,7 +1404,7 @@ void V_DrawVhsEffect(boolean rewind) void V_DrawFadeScreen(UINT16 color, UINT8 strength) { #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { HWR_FadeScreenMenuBack(color, strength); return; @@ -1419,6 +1496,7 @@ void V_DrawFadeConsBack(INT32 plines) *buf = consolebgmap[*buf]; } + // // Invert the entire screen, for Encore fades // @@ -1447,6 +1525,72 @@ void V_EncoreInvertScreen(void) } } +// Very similar to F_DrawFadeConsBack, except we draw from the middle(-ish) of the screen to the bottom. +void V_DrawPromptBack(INT32 boxheight, INT32 color) +{ + UINT8 *deststop, *buf; + + if (color >= 256 && color < 512) + { + if (boxheight < 0) + boxheight = -boxheight; + else // 4 lines of space plus gaps between and some leeway + boxheight = ((boxheight * 4) + (boxheight/2)*5); + V_DrawFill((BASEVIDWIDTH-(vid.width/vid.dupx))/2, BASEVIDHEIGHT-boxheight, (vid.width/vid.dupx),boxheight, (color-256)|V_SNAPTOBOTTOM); + return; + } + + boxheight *= vid.dupy; + + if (color == INT32_MAX) + color = cons_backcolor.value; + +#ifdef HWRENDER + if (rendermode == render_opengl) + { + UINT32 hwcolor; + switch (color) + { + case 0: hwcolor = 0xffffff00; break; // White + case 1: hwcolor = 0x00000000; break; // Black // Note this is different from V_DrawFadeConsBack + case 2: hwcolor = 0xdeb88700; break; // Sepia + case 3: hwcolor = 0x40201000; break; // Brown + case 4: hwcolor = 0xfa807200; break; // Pink + case 5: hwcolor = 0xff69b400; break; // Raspberry + case 6: hwcolor = 0xff000000; break; // Red + case 7: hwcolor = 0xffd68300; break; // Creamsicle + case 8: hwcolor = 0xff800000; break; // Orange + case 9: hwcolor = 0xdaa52000; break; // Gold + case 10: hwcolor = 0x80800000; break; // Yellow + case 11: hwcolor = 0x00ff0000; break; // Emerald + case 12: hwcolor = 0x00800000; break; // Green + case 13: hwcolor = 0x4080ff00; break; // Cyan + case 14: hwcolor = 0x4682b400; break; // Steel + case 15: hwcolor = 0x1e90ff00; break; // Periwinkle + case 16: hwcolor = 0x0000ff00; break; // Blue + case 17: hwcolor = 0xff00ff00; break; // Purple + case 18: hwcolor = 0xee82ee00; break; // Lavender + // Default green + default: hwcolor = 0x00800000; break; + } + HWR_DrawTutorialBack(hwcolor, boxheight); + return; + } +#endif + + CON_SetupBackColormapEx(color, true); + + // heavily simplified -- we don't need to know x or y position, + // just the start and stop positions + buf = deststop = screens[0] + vid.rowbytes * vid.height; + if (boxheight < 0) + buf += vid.rowbytes * boxheight; + else // 4 lines of space plus gaps between and some leeway + buf -= vid.rowbytes * ((boxheight * 4) + (boxheight/2)*5); + for (; buf < deststop; ++buf) + *buf = promptbgmap[*buf]; +} + // Gets string colormap, used for 0x80 color codes // UINT8 *V_GetStringColormap(INT32 colorflags) @@ -1579,7 +1723,7 @@ char *V_WordWrap(INT32 x, INT32 w, INT32 option, const char *string) for (i = 0; i < slen; ++i) { c = newstring[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09 continue; if (c == '\n') @@ -1921,6 +2065,12 @@ void V_DrawRightAlignedString(INT32 x, INT32 y, INT32 option, const char *string V_DrawString(x, y, option, string); } +void V_DrawCenteredSmallString(INT32 x, INT32 y, INT32 option, const char *string) +{ + x -= V_SmallStringWidth(string, option)/2; + V_DrawSmallString(x, y, option, string); +} + void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string) { x -= V_SmallStringWidth(string, option); @@ -1939,6 +2089,51 @@ void V_DrawRightAlignedThinString(INT32 x, INT32 y, INT32 option, const char *st V_DrawThinString(x, y, option, string); } +// Draws a number using the PING font thingy. +// TODO: Merge number drawing functions into one with "font name" selection. + +void V_DrawPingNum(INT32 x, INT32 y, INT32 flags, INT32 num, const UINT8 *colormap) +{ + INT32 w = SHORT(fontv[PINGNUM_FONT].font[0]->width); // this SHOULD always be 5 but I guess custom graphics exist. + + if (flags & V_NOSCALESTART) + w *= vid.dupx; + + if (num < 0) + num = -num; + + // draw the number + do + { + x -= (w-1); // Oni wanted their outline to intersect. + V_DrawFixedPatch(x<= CRED_FONTSIZE) + w += 16; + else + w += SHORT(fontv[CRED_FONT].font[c]->width); + } + + return w; +} + // Draws a tallnum. Replaces two functions in y_inter and st_stuff void V_DrawTallNum(INT32 x, INT32 y, INT32 flags, INT32 num) { @@ -1985,51 +2180,6 @@ void V_DrawPaddedTallNum(INT32 x, INT32 y, INT32 flags, INT32 num, INT32 digits) } while (--digits); } -// Draws a number using the PING font thingy. -// TODO: Merge number drawing functions into one with "font name" selection. - -void V_DrawPingNum(INT32 x, INT32 y, INT32 flags, INT32 num, const UINT8 *colormap) -{ - INT32 w = SHORT(fontv[PINGNUM_FONT].font[0]->width); // this SHOULD always be 5 but I guess custom graphics exist. - - if (flags & V_NOSCALESTART) - w *= vid.dupx; - - if (num < 0) - num = -num; - - // draw the number - do - { - x -= (w-1); // Oni wanted their outline to intersect. - V_DrawFixedPatch(x<= CRED_FONTSIZE) - w += 16; - else - w += SHORT(fontv[CRED_FONT].font[c]->width); - } - - return w; -} - // Find string width from lt_font chars // INT32 V_LevelNameWidth(const char *string) @@ -2039,7 +2189,9 @@ INT32 V_LevelNameWidth(const char *string) for (i = 0; i < strlen(string); i++) { - c = toupper(string[i]) - LT_FONTSTART; + if (string[i] & 0x80) + continue; + c = string[i] - LT_FONTSTART; if (c < 0 || c >= LT_FONTSIZE || !fontv[LT_FONT].font[c]) w += 12; else @@ -2058,7 +2210,7 @@ INT32 V_LevelNameHeight(const char *string) for (i = 0; i < strlen(string); i++) { - c = toupper(string[i]) - LT_FONTSTART; + c = string[i] - LT_FONTSTART; if (c < 0 || c >= LT_FONTSIZE || !fontv[LT_FONT].font[c]) continue; @@ -2095,7 +2247,7 @@ INT32 V_StringWidth(const char *string, INT32 option) for (i = 0; i < strlen(string); i++) { c = string[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09 continue; c = toupper(c) - HU_FONTSTART; @@ -2105,6 +2257,9 @@ INT32 V_StringWidth(const char *string, INT32 option) w += (charwidth ? charwidth : SHORT(fontv[HU_FONT].font[c]->width)); } + if (option & (V_NOSCALESTART|V_NOSCALEPATCH)) + w *= vid.dupx; + return w; } @@ -2134,7 +2289,7 @@ INT32 V_SmallStringWidth(const char *string, INT32 option) for (i = 0; i < strlen(string); i++) { c = string[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09 continue; c = toupper(c) - HU_FONTSTART; @@ -2175,7 +2330,7 @@ INT32 V_ThinStringWidth(const char *string, INT32 option) for (i = 0; i < strlen(string); i++) { c = string[i]; - if ((UINT8)c >= 0x80 && (UINT8)c <= 0x8F) //color parsing! -Inuyasha 2.16.09 + if ((UINT8)c & 0x80) //color parsing! -Inuyasha 2.16.09 continue; if (!lowercase || !fontv[TINY_FONT].font[c-HU_FONTSTART]) @@ -2196,6 +2351,15 @@ INT32 V_ThinStringWidth(const char *string, INT32 option) return w; } +// +// Find string width from tny_font chars, 0.5x scale +// +INT32 V_SmallThinStringWidth(const char *string, INT32 option) +{ + INT32 w = V_ThinStringWidth(string, option)<init || memcmp(lut->palette, palette, palsize)) { - for (r = 0; r < CLUTSIZE; r++) - for (g = 0; g < CLUTSIZE; g++) - for (b = 0; b < CLUTSIZE; b++) - colorlookup[r][g][b] = NearestPaletteColor(r << SHIFTCOLORBITS, g << SHIFTCOLORBITS, b << SHIFTCOLORBITS, palette); - clutinit = true; - lastpalette = palette; + INT32 i; + + lut->init = true; + memcpy(lut->palette, palette, palsize); + + for (i = 0; i < 0xFFFF; i++) + lut->table[i] = 0xFFFF; + + if (makecolors) + { + UINT8 r, g, b; + + for (r = 0; r < 0xFF; r++) + for (g = 0; g < 0xFF; g++) + for (b = 0; b < 0xFF; b++) + { + i = CLUTINDEX(r, g, b); + if (lut->table[i] == 0xFFFF) + lut->table[i] = NearestPaletteColor(r, g, b, palette); + } + } } } +UINT8 GetColorLUT(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b) +{ + INT32 i = CLUTINDEX(r, g, b); + if (lut->table[i] == 0xFFFF) + lut->table[i] = NearestPaletteColor(r, g, b, lut->palette); + return lut->table[i]; +} + +UINT8 GetColorLUTDirect(colorlookup_t *lut, UINT8 r, UINT8 g, UINT8 b) +{ + INT32 i = CLUTINDEX(r, g, b); + return lut->table[i]; +} + // V_Init // old software stuff, buffers are allocated at video mode setup // here we set the screens[x] pointers accordingly @@ -2436,7 +2622,7 @@ void V_Init(void) #ifdef DEBUG CONS_Debug(DBG_RENDER, "V_Init done:\n"); - for (i = 0; i < NUMSCREENS+1; i++) + for (i = 0; i < NUMSCREENS; i++) CONS_Debug(DBG_RENDER, " screens[%d] = %x\n", i, screens[i]); #endif } diff --git a/src/v_video.h b/src/v_video.h index 95b3f16fb..49ab33028 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -18,6 +18,9 @@ #include "doomtype.h" #include "r_defs.h" +// SRB2Kart +#include "hu_stuff.h" // fonts + // // VIDEO // @@ -27,24 +30,28 @@ extern UINT8 *screens[5]; -extern consvar_t cv_ticrate, cv_constextsize,\ -cv_globalgamma, cv_globalsaturation, \ -cv_rhue, cv_yhue, cv_ghue, cv_chue, cv_bhue, cv_mhue,\ -cv_rgamma, cv_ygamma, cv_ggamma, cv_cgamma, cv_bgamma, cv_mgamma, \ +extern consvar_t cv_ticrate, cv_constextsize, +cv_globalgamma, cv_globalsaturation, +cv_rhue, cv_yhue, cv_ghue, cv_chue, cv_bhue, cv_mhue, +cv_rgamma, cv_ygamma, cv_ggamma, cv_cgamma, cv_bgamma, cv_mgamma, cv_rsaturation, cv_ysaturation, cv_gsaturation, cv_csaturation, cv_bsaturation, cv_msaturation; // Allocates buffer screens, call before R_Init. void V_Init(void); // Color look-up table +#define CLUTINDEX(r, g, b) (((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3) -#define COLORBITS 6 -#define SHIFTCOLORBITS (8-COLORBITS) -#define CLUTSIZE (1<>1,option,HU_FONT,string) +void V_DrawCenteredSmallString(INT32 x, INT32 y, INT32 option, const char *string); void V_DrawRightAlignedSmallString(INT32 x, INT32 y, INT32 option, const char *string); // draw a string using the tny_font @@ -239,6 +260,7 @@ void V_DrawPingNum(INT32 x, INT32 y, INT32 flags, INT32 num, const UINT8 *colorm // Find string width from lt_font chars INT32 V_LevelNameWidth(const char *string); INT32 V_LevelNameHeight(const char *string); +INT16 V_LevelActNumWidth(UINT8 num); // act number width #define V_DrawCreditString( x,y,option,string ) \ V__DrawOneScaleString (x,y,FRACUNIT,option,CRED_FONT,string) @@ -250,6 +272,8 @@ INT32 V_StringWidth(const char *string, INT32 option); INT32 V_SmallStringWidth(const char *string, INT32 option); // Find string width from tny_font chars INT32 V_ThinStringWidth(const char *string, INT32 option); +// Find string width from tny_font chars, 0.5x scale +INT32 V_SmallThinStringWidth(const char *string, INT32 option); void V_DoPostProcessor(INT32 view, postimg_t type, INT32 param); diff --git a/src/version.h b/src/version.h new file mode 100644 index 000000000..e350082fc --- /dev/null +++ b/src/version.h @@ -0,0 +1,15 @@ +#define SRB2VERSION "2.0"/* this must be the first line, for cmake !! */ + +// The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/showgroups.php ). +// DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. +// "17" is the default mod ID for SRB2Kart. +#define MODID 17 + +// The Modification Version, starting from 1. Do not follow your version string for this, +// it's only for detection of the version the player is using so the MS can alert them of an update. +// Only set it higher, not lower, obviously. +// Note that we use this to help keep internal testing in check; this is why v2.0 is not version "2". +#define MODVERSION 6 + +// Define this as a prerelease version suffix +// #define BETAVERSION "Alpha" diff --git a/src/vid_copy.s b/src/vid_copy.s index 050a80999..eae435ea4 100644 --- a/src/vid_copy.s +++ b/src/vid_copy.s @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. diff --git a/src/w_wad.c b/src/w_wad.c index 7fd7ac125..6de3cae6a 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -11,6 +11,24 @@ /// \file w_wad.c /// \brief Handles WAD file header, directory, lump I/O +#ifdef HAVE_ZLIB +#ifndef _MSC_VER +#ifndef _LARGEFILE64_SOURCE +#define _LARGEFILE64_SOURCE +#endif +#endif + +#ifndef _LFS64_LARGEFILE +#define _LFS64_LARGEFILE +#endif + +#ifndef _FILE_OFFSET_BITS +#define _FILE_OFFSET_BITS 0 +#endif + +#include +#endif + #ifdef __GNUC__ #include #endif @@ -18,11 +36,7 @@ #define ZWAD #ifdef ZWAD -#ifdef _WIN32_WCE -#define AVOID_ERRNO -#else #include -#endif #include "lzf.h" #endif @@ -42,6 +56,9 @@ #include "dehacked.h" #include "d_clisrv.h" #include "r_defs.h" +#include "r_data.h" +#include "r_textures.h" +#include "r_picformats.h" #include "i_system.h" #include "md5.h" #include "lua_script.h" @@ -51,39 +68,18 @@ #include "m_misc.h" // M_MapNumber #ifdef HWRENDER -#include "r_data.h" #include "hardware/hw_main.h" #include "hardware/hw_glob.h" #endif -#ifdef PC_DOS -#include // for snprintf -int snprintf(char *str, size_t n, const char *fmt, ...); -//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); +#ifdef _DEBUG +#include "console.h" #endif #ifndef O_BINARY #define O_BINARY 0 #endif -#ifdef HAVE_ZLIB -#ifndef _MSC_VER -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif -#endif - -#ifndef _LFS64_LARGEFILE -#define _LFS64_LARGEFILE -#endif - -#ifndef _FILE_OFFSET_BITS -#define _FILE_OFFSET_BITS 0 -#endif - -#include "zlib.h" -#endif - typedef struct { @@ -96,7 +92,7 @@ typedef struct typedef struct lumpnum_cache_s { - char lumpname[8]; + char lumpname[32]; lumpnum_t lumpnum; } lumpnum_cache_t; @@ -118,12 +114,18 @@ void W_Shutdown(void) { while (numwadfiles--) { - fclose(wadfiles[numwadfiles]->handle); - Z_Free(wadfiles[numwadfiles]->filename); - while (wadfiles[numwadfiles]->numlumps--) - Z_Free(wadfiles[numwadfiles]->lumpinfo[wadfiles[numwadfiles]->numlumps].name2); - Z_Free(wadfiles[numwadfiles]->lumpinfo); - Z_Free(wadfiles[numwadfiles]); + wadfile_t *wad = wadfiles[numwadfiles]; + + fclose(wad->handle); + Z_Free(wad->filename); + while (wad->numlumps--) + { + Z_Free(wad->lumpinfo[wad->numlumps].longname); + Z_Free(wad->lumpinfo[wad->numlumps].fullname); + } + + Z_Free(wad->lumpinfo); + Z_Free(wad); } } @@ -150,9 +152,15 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) { FILE *handle; - strncpy(filenamebuf, *filename, MAX_WADPATH); - filenamebuf[MAX_WADPATH - 1] = '\0'; - *filename = filenamebuf; + // Officially, strncpy should not have overlapping buffers, since W_VerifyNMUSlumps is called after this, and it + // changes filename to point at filenamebuf, it would technically be doing that. I doubt any issue will occur since + // they point to the same location, but it's better to be safe and this is a simple change. + if (filenamebuf != *filename) + { + strncpy(filenamebuf, *filename, MAX_WADPATH); + filenamebuf[MAX_WADPATH - 1] = '\0'; + *filename = filenamebuf; + } // open wad file if ((handle = fopen(*filename, "rb")) == NULL) @@ -183,77 +191,81 @@ FILE *W_OpenWadFile(const char **filename, boolean useerrors) } // Look for all DEHACKED and Lua scripts inside a PK3 archive. -static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum) +static inline void W_LoadDehackedLumpsPK3(UINT16 wadnum, boolean mainfile) { UINT16 posStart, posEnd; -#ifdef HAVE_BLUA - posStart = W_CheckNumForFolderStartPK3("Lua/", wadnum, 0); + + posStart = W_CheckNumForFullNamePK3("Init.lua", wadnum, 0); if (posStart != INT16_MAX) { - posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart); - posStart++; - for (; posStart < posEnd; posStart++) - LUA_LoadLump(wadnum, posStart); + LUA_LoadLump(wadnum, posStart, true); + } + else + { + posStart = W_CheckNumForFolderStartPK3("Lua/", wadnum, 0); + if (posStart != INT16_MAX) + { + posEnd = W_CheckNumForFolderEndPK3("Lua/", wadnum, posStart); + for (; posStart < posEnd; posStart++) + LUA_LoadLump(wadnum, posStart, true); + } } -#endif posStart = W_CheckNumForFolderStartPK3("SOC/", wadnum, 0); if (posStart != INT16_MAX) { posEnd = W_CheckNumForFolderEndPK3("SOC/", wadnum, posStart); - posStart++; + for(; posStart < posEnd; posStart++) { lumpinfo_t *lump_p = &wadfiles[wadnum]->lumpinfo[posStart]; - size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name + size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name char *name = malloc(length + 1); - sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2); + sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname); name[length] = '\0'; CONS_Printf(M_GetText("Loading SOC from %s\n"), name); - DEH_LoadDehackedLumpPwad(wadnum, posStart); + DEH_LoadDehackedLumpPwad(wadnum, posStart, mainfile); free(name); } } } // search for all DEHACKED lump in all wads and load it -static inline void W_LoadDehackedLumps(UINT16 wadnum) +static inline void W_LoadDehackedLumps(UINT16 wadnum, boolean mainfile) { UINT16 lump; -#ifdef HAVE_BLUA // Find Lua scripts before SOCs to allow new A_Actions in SOC editing. { lumpinfo_t *lump_p = wadfiles[wadnum]->lumpinfo; for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++) if (memcmp(lump_p->name,"LUA_",4)==0) - LUA_LoadLump(wadnum, lump); + LUA_LoadLump(wadnum, lump, true); } -#endif { lumpinfo_t *lump_p = wadfiles[wadnum]->lumpinfo; for (lump = 0; lump < wadfiles[wadnum]->numlumps; lump++, lump_p++) if (memcmp(lump_p->name,"SOC_",4)==0) // Check for generic SOC lump { // shameless copy+paste of code from LUA_LoadLump - size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->name2); // length of file name, '|', and lump name + size_t length = strlen(wadfiles[wadnum]->filename) + 1 + strlen(lump_p->fullname); // length of file name, '|', and lump name char *name = malloc(length + 1); - sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->name2); + sprintf(name, "%s|%s", wadfiles[wadnum]->filename, lump_p->fullname); name[length] = '\0'; CONS_Printf(M_GetText("Loading SOC from %s\n"), name); - DEH_LoadDehackedLumpPwad(wadnum, lump); + DEH_LoadDehackedLumpPwad(wadnum, lump, mainfile); free(name); } else if (memcmp(lump_p->name,"MAINCFG",8)==0) // Check for MAINCFG { CONS_Printf(M_GetText("Loading main config from %s\n"), wadfiles[wadnum]->filename); - DEH_LoadDehackedLumpPwad(wadnum, lump); + DEH_LoadDehackedLumpPwad(wadnum, lump, mainfile); } else if (memcmp(lump_p->name,"OBJCTCFG",8)==0) // Check for OBJCTCFG { CONS_Printf(M_GetText("Loading object config from %s\n"), wadfiles[wadnum]->filename); - DEH_LoadDehackedLumpPwad(wadnum, lump); + DEH_LoadDehackedLumpPwad(wadnum, lump, mainfile); } } @@ -335,16 +347,22 @@ static restype_t ResourceFileDetect (const char* filename) static lumpinfo_t* ResGetLumpsStandalone (FILE* handle, UINT16* numlumps, const char* lumpname) { lumpinfo_t* lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); - lumpinfo = Z_Calloc(sizeof (*lumpinfo), PU_STATIC, NULL); lumpinfo->position = 0; fseek(handle, 0, SEEK_END); lumpinfo->size = ftell(handle); fseek(handle, 0, SEEK_SET); strcpy(lumpinfo->name, lumpname); + + // Allocate the lump's long name. + lumpinfo->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strcpy(lumpinfo->longname, lumpname); + lumpinfo->longname[8] = '\0'; + // Allocate the lump's full name. - lumpinfo->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); - strcpy(lumpinfo->name2, lumpname); - lumpinfo->name2[8] = '\0'; + lumpinfo->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strcpy(lumpinfo->fullname, lumpname); + lumpinfo->fullname[8] = '\0'; + *numlumps = 1; return lumpinfo; } @@ -431,10 +449,16 @@ static lumpinfo_t* ResGetLumpsWad (FILE* handle, UINT16* nlmp, const char* filen lump_p->compression = CM_NOCOMPRESSION; memset(lump_p->name, 0x00, 9); strncpy(lump_p->name, fileinfo->name, 8); + + // Allocate the lump's long name. + lump_p->longname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strncpy(lump_p->longname, fileinfo->name, 8); + lump_p->longname[8] = '\0'; + // Allocate the lump's full name. - lump_p->name2 = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); - strncpy(lump_p->name2, fileinfo->name, 8); - lump_p->name2[8] = '\0'; + lump_p->fullname = Z_Malloc(9 * sizeof(char), PU_STATIC, NULL); + strncpy(lump_p->fullname, fileinfo->name, 8); + lump_p->fullname[8] = '\0'; } free(fileinfov); *nlmp = numlumps; @@ -525,8 +549,8 @@ typedef struct zlentry_s static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) { zend_t zend; - zentry_t* zentries; - zentry_t* zentry; + zentry_t zentry; + zlentry_t zlentry; UINT16 numlumps = *nlmp; lumpinfo_t* lumpinfo; @@ -554,40 +578,36 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) numlumps = zend.entries; lump_p = lumpinfo = Z_Malloc(numlumps * sizeof (*lumpinfo), PU_STATIC, NULL); - zentry = zentries = malloc(numlumps * sizeof (*zentries)); fseek(handle, zend.cdiroffset, SEEK_SET); - for (i = 0; i < numlumps; i++, zentry++, lump_p++) + for (i = 0; i < numlumps; i++, lump_p++) { char* fullname; char* trimname; char* dotpos; - if (fread(zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t)) + if (fread(&zentry, 1, sizeof(zentry_t), handle) < sizeof(zentry_t)) { CONS_Alert(CONS_ERROR, "Failed to read central directory (%s)\n", M_FileError(handle)); Z_Free(lumpinfo); - free(zentry); return NULL; } - if (memcmp(zentry->signature, pat_central, 4)) + if (memcmp(zentry.signature, pat_central, 4)) { CONS_Alert(CONS_ERROR, "Central directory is corrupt\n"); Z_Free(lumpinfo); - free(zentry); return NULL; } - lump_p->position = zentry->offset + zentry->namelen + zentry->xtralen + sizeof(zlentry_t); - lump_p->disksize = zentry->compsize; - lump_p->size = zentry->size; + lump_p->position = zentry.offset; // NOT ACCURATE YET: we still need to read the local entry to find our true position + lump_p->disksize = zentry.compsize; + lump_p->size = zentry.size; - fullname = malloc(zentry->namelen + 1); - if (fgets(fullname, zentry->namelen + 1, handle) != fullname) + fullname = malloc(zentry.namelen + 1); + if (fgets(fullname, zentry.namelen + 1, handle) != fullname) { CONS_Alert(CONS_ERROR, "Unable to read lumpname (%s)\n", M_FileError(handle)); Z_Free(lumpinfo); - free(zentry); free(fullname); return NULL; } @@ -604,12 +624,15 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) memset(lump_p->name, '\0', 9); // Making sure they're initialized to 0. Is it necessary? strncpy(lump_p->name, trimname, min(8, dotpos - trimname)); - lump_p->name2 = Z_Calloc(zentry->namelen + 1, PU_STATIC, NULL); - strncpy(lump_p->name2, fullname, zentry->namelen); + lump_p->longname = Z_Calloc(dotpos - trimname + 1, PU_STATIC, NULL); + strlcpy(lump_p->longname, trimname, dotpos - trimname + 1); + + lump_p->fullname = Z_Calloc(zentry.namelen + 1, PU_STATIC, NULL); + strncpy(lump_p->fullname, fullname, zentry.namelen); free(fullname); - switch(zentry->compression) + switch(zentry.compression) { case 0: lump_p->compression = CM_NOCOMPRESSION; @@ -627,12 +650,49 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) lump_p->compression = CM_UNSUPPORTED; break; } + + // skip and ignore comments/extra fields + if (fseek(handle, zentry.xtralen + zentry.commlen, SEEK_CUR) != 0) + { + CONS_Alert(CONS_ERROR, "Central directory is corrupt\n"); + Z_Free(lumpinfo); + return NULL; + } + } + + // Adjust lump position values properly + for (i = 0, lump_p = lumpinfo; i < numlumps; i++, lump_p++) + { + // skip and ignore comments/extra fields + if ((fseek(handle, lump_p->position, SEEK_SET) != 0) || (fread(&zlentry, 1, sizeof(zlentry_t), handle) < sizeof(zlentry_t))) + { + CONS_Alert(CONS_ERROR, "Local headers for lump %s are corrupt\n", lump_p->fullname); + Z_Free(lumpinfo); + return NULL; + } + + lump_p->position += sizeof(zlentry_t) + zlentry.namelen + zlentry.xtralen; } *nlmp = numlumps; return lumpinfo; } +static UINT16 W_InitFileError (const char *filename, boolean exitworthy) +{ + if (exitworthy) + { +#ifdef _DEBUG + CONS_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); +#else + I_Error("A WAD file was not found or not valid.\nCheck the log to see which ones.\n"); +#endif + } + else + CONS_Printf(M_GetText("Errors occurred while loading %s; not added.\n"), filename); + return INT16_MAX; +} + // Allocate a wadfile, setup the lumpinfo (directory) and // lumpcache, add the wadfile to the current active wadfiles // @@ -644,14 +704,16 @@ static lumpinfo_t* ResGetLumpsZip (FILE* handle, UINT16* nlmp) // // Can now load dehacked files (.soc) // -UINT16 W_InitFile(const char *filename) +UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup) { FILE *handle; lumpinfo_t *lumpinfo = NULL; wadfile_t *wadfile; restype_t type; UINT16 numlumps = 0; +#ifndef NOMD5 size_t i; +#endif UINT8 md5sum[16]; boolean important; @@ -676,13 +738,13 @@ UINT16 W_InitFile(const char *filename) { CONS_Alert(CONS_ERROR, M_GetText("Maximum wad files reached\n")); refreshdirmenu |= REFRESHDIR_MAX; - return INT16_MAX; + return W_InitFileError(filename, startup); } // open wad file if ((handle = W_OpenWadFile(&filename, true)) == NULL) - return INT16_MAX; - + return W_InitFileError(filename, startup); + important = !W_VerifyNMUSlumps(filename); #ifndef NOMD5 @@ -700,7 +762,7 @@ UINT16 W_InitFile(const char *filename) CONS_Alert(CONS_ERROR, M_GetText("%s is already loaded\n"), filename); if (handle) fclose(handle); - return INT16_MAX; + return W_InitFileError(filename, false); } } #endif @@ -710,11 +772,9 @@ UINT16 W_InitFile(const char *filename) case RET_SOC: lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "OBJCTCFG"); break; -#ifdef HAVE_BLUA case RET_LUA: lumpinfo = ResGetLumpsStandalone(handle, &numlumps, "LUA_INIT"); break; -#endif case RET_PK3: lumpinfo = ResGetLumpsZip(handle, &numlumps); break; @@ -728,7 +788,7 @@ UINT16 W_InitFile(const char *filename) if (lumpinfo == NULL) { fclose(handle); - return INT16_MAX; + return W_InitFileError(filename, startup); } // @@ -736,6 +796,7 @@ UINT16 W_InitFile(const char *filename) // wadfile = Z_Malloc(sizeof (*wadfile), PU_STATIC, NULL); wadfile->filename = Z_StrDup(filename); + wadfile->type = type; wadfile->handle = handle; wadfile->numlumps = (UINT16)numlumps; wadfile->lumpinfo = lumpinfo; @@ -751,6 +812,7 @@ UINT16 W_InitFile(const char *filename) // set up caching // Z_Calloc(numlumps * sizeof (*wadfile->lumpcache), PU_STATIC, &wadfile->lumpcache); + Z_Calloc(numlumps * sizeof (*wadfile->patchcache), PU_STATIC, &wadfile->patchcache); #ifdef HWRENDER // allocates GLPatch info structures and store them in a tree @@ -765,28 +827,30 @@ UINT16 W_InitFile(const char *filename) numwadfiles++; // must come BEFORE W_LoadDehackedLumps, so any addfile called by COM_BufInsertText called by Lua doesn't overwrite what we just loaded #ifdef HWRENDER - if (rendermode == render_opengl) - HWR_LoadShaders(numwadfiles - 1, (wadfile->type == RET_PK3)); -#endif + // Read shaders from file + if (rendermode == render_opengl && (vid_opengl_state == 1)) + { + HWR_LoadCustomShadersFromFile(numwadfiles - 1, (type == RET_PK3)); + HWR_CompileShaders(); + } +#endif // HWRENDER // TODO: HACK ALERT - Load Lua & SOC stuff right here. I feel like this should be out of this place, but... Let's stick with this for now. switch (wadfile->type) { case RET_WAD: - W_LoadDehackedLumps(numwadfiles - 1); + W_LoadDehackedLumps(numwadfiles - 1, mainfile); break; case RET_PK3: - W_LoadDehackedLumpsPK3(numwadfiles - 1); + W_LoadDehackedLumpsPK3(numwadfiles - 1, mainfile); break; case RET_SOC: CONS_Printf(M_GetText("Loading SOC from %s\n"), wadfile->filename); - DEH_LoadDehackedLumpPwad(numwadfiles - 1, 0); + DEH_LoadDehackedLumpPwad(numwadfiles - 1, 0, mainfile); break; -#ifdef HAVE_BLUA case RET_LUA: - LUA_LoadLump(numwadfiles - 1, 0); + LUA_LoadLump(numwadfiles - 1, 0, true); break; -#endif default: break; } @@ -799,38 +863,6 @@ UINT16 W_InitFile(const char *filename) return wadfile->numlumps; } -#ifdef DELFILE -void W_UnloadWadFile(UINT16 num) -{ - INT32 i; - wadfile_t *delwad = wadfiles[num]; - lumpcache_t *lumpcache; - if (num == 0) - return; - CONS_Printf(M_GetText("Removing WAD %s...\n"), wadfiles[num]->filename); - - DEH_UnloadDehackedWad(num); - wadfiles[num] = NULL; - lumpcache = delwad->lumpcache; - numwadfiles--; -#ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) - HWR_FreeTextureCache(); - M_AATreeFree(delwad->hwrcache); -#endif - if (*lumpcache) - { - for (i = 0;i < delwad->numlumps;i++) - Z_ChangeTag(lumpcache[i], PU_PURGELEVEL); - } - Z_Free(lumpcache); - fclose(delwad->handle); - Z_Free(delwad->filename); - Z_Free(delwad); - CONS_Printf(M_GetText("Done unloading WAD.\n")); -} -#endif - /** Tries to load a series of files. * All files are wads unless they have an extension of ".soc" or ".lua". * @@ -839,8 +871,6 @@ void W_UnloadWadFile(UINT16 num) * backwards, so a later file overrides all earlier ones. * * \param filenames A null-terminated list of files to use. - * \return 1 if all files were loaded, 0 if at least one was missing or - * invalid. */ INT32 W_InitMultipleFiles(char **filenames, boolean addons) { @@ -853,7 +883,7 @@ INT32 W_InitMultipleFiles(char **filenames, boolean addons) G_SetGameModified(true, false); //CONS_Debug(DBG_SETUP, "Loading %s\n", *filenames); - rc &= (W_InitFile(*filenames) != INT16_MAX) ? 1 : 0; + rc &= (W_InitFile(*filenames, !addons, true) != INT16_MAX) ? 1 : 0; } if (!numwadfiles) @@ -893,21 +923,14 @@ const char *W_CheckNameForNum(lumpnum_t lumpnum) } // -// Same as the original, but checks in one pwad only. // wadid is a wad number // (Used for sprites loading) // // 'startlump' is the lump number to start the search // -UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) +UINT16 W_FindNextEmptyInPwad(UINT16 wad, UINT16 startlump) { UINT16 i; - static char uname[9]; - - memset(uname, 0x00, sizeof uname); - strncpy(uname, name, 8); - uname[8] = 0; - strupr(uname); if (!TestValidLump(wad,0)) return INT16_MAX; @@ -921,25 +944,109 @@ UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) { lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) - { - if (memcmp(lump_p->name,uname,8) == 0) + if (!lump_p->size) return i; - } } // not found. return INT16_MAX; } +// +// Same as the original, but checks in one pwad only. +// wadid is a wad number +// (Used for sprites loading) +// +// 'startlump' is the lump number to start the search +// +UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump) +{ + UINT16 i; + static char uname[8 + 1]; + + if (!TestValidLump(wad,0)) + return INT16_MAX; + + strlcpy(uname, name, sizeof uname); + strupr(uname); + + // + // scan forward + // start at 'startlump', useful parameter when there are multiple + // resources with the same name + // + if (startlump < wadfiles[wad]->numlumps) + { + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + if (!strncmp(lump_p->name, uname, sizeof(uname) - 1)) + return i; + } + + // not found. + return INT16_MAX; +} + +// +// Like W_CheckNumForNamePwad, but can find entries with long names +// +// Should be the only version, but that's not possible until we fix +// all the instances of non null-terminated strings in the codebase... +// +UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump) +{ + UINT16 i; + static char uname[256 + 1]; + + if (!TestValidLump(wad,0)) + return INT16_MAX; + + strlcpy(uname, name, sizeof uname); + strupr(uname); + + // + // scan forward + // start at 'startlump', useful parameter when there are multiple + // resources with the same name + // + if (startlump < wadfiles[wad]->numlumps) + { + lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) + if (!strcmp(lump_p->longname, uname)) + return i; + } + + // not found. + return INT16_MAX; +} + +UINT16 +W_CheckNumForMarkerStartPwad (const char *name, UINT16 wad, UINT16 startlump) +{ + UINT16 marker; + marker = W_CheckNumForNamePwad(name, wad, startlump); + if (marker != INT16_MAX) + marker++; // Do not count the first marker + return marker; +} + // Look for the first lump from a folder. UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump) { + size_t name_length; INT32 i; lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; + name_length = strlen(name); for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) { - if (strnicmp(name, lump_p->name2, strlen(name)) == 0) + if (strnicmp(name, lump_p->fullname, name_length) == 0) + { + /* SLADE is special and puts a single directory entry. Skip that. */ + if (strlen(lump_p->fullname) == name_length) + i++; break; + } } return i; } @@ -953,7 +1060,7 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) { - if (strnicmp(name, lump_p->name2, strlen(name))) + if (strnicmp(name, lump_p->fullname, strlen(name))) break; } return i; @@ -967,7 +1074,7 @@ UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump) lumpinfo_t *lump_p = wadfiles[wad]->lumpinfo + startlump; for (i = startlump; i < wadfiles[wad]->numlumps; i++, lump_p++) { - if (!strnicmp(name, lump_p->name2, strlen(name))) + if (!strnicmp(name, lump_p->fullname, strlen(name))) { return i; } @@ -985,11 +1092,15 @@ lumpnum_t W_CheckNumForName(const char *name) INT32 i; lumpnum_t check = INT16_MAX; + if (!*name) // some doofus gave us an empty string? + return LUMPERROR; + // Check the lumpnumcache first. Loop backwards so that we check // most recent entries first for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) { - if (strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0) + if (!lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname[8] + && strncmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name, 8) == 0) { lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); return lumpnumcache[lumpnumcacheindex].lumpnum; @@ -1009,6 +1120,7 @@ lumpnum_t W_CheckNumForName(const char *name) { // Update the cache. lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); + memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32); strncpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 8); lumpnumcache[lumpnumcacheindex].lumpnum = (i<<16)+check; @@ -1016,6 +1128,55 @@ lumpnum_t W_CheckNumForName(const char *name) } } +// +// Like W_CheckNumForName, but can find entries with long names +// +// Should be the only version, but that's not possible until we fix +// all the instances of non null-terminated strings in the codebase... +// +lumpnum_t W_CheckNumForLongName(const char *name) +{ + INT32 i; + lumpnum_t check = INT16_MAX; + + if (!*name) // some doofus gave us an empty string? + return LUMPERROR; + + // Check the lumpnumcache first. Loop backwards so that we check + // most recent entries first + for (i = lumpnumcacheindex + LUMPNUMCACHESIZE; i > lumpnumcacheindex; i--) + { + if (strcmp(lumpnumcache[i & (LUMPNUMCACHESIZE - 1)].lumpname, name) == 0) + { + lumpnumcacheindex = i & (LUMPNUMCACHESIZE - 1); + return lumpnumcache[lumpnumcacheindex].lumpnum; + } + } + + // scan wad files backwards so patch lump files take precedence + for (i = numwadfiles - 1; i >= 0; i--) + { + check = W_CheckNumForLongNamePwad(name,(UINT16)i,0); + if (check != INT16_MAX) + break; //found it + } + + if (check == INT16_MAX) return LUMPERROR; + else + { + if (strlen(name) < 32) + { + // Update the cache. + lumpnumcacheindex = (lumpnumcacheindex + 1) & (LUMPNUMCACHESIZE - 1); + memset(lumpnumcache[lumpnumcacheindex].lumpname, '\0', 32); + strlcpy(lumpnumcache[lumpnumcacheindex].lumpname, name, 32); + lumpnumcache[lumpnumcacheindex].lumpnum = (i << 16) + check; + } + + return (i << 16) + check; + } +} + // Look for valid map data through all added files in descendant order. // Get a map marker for WADs, and a standalone WAD file lump inside PK3s. // TODO: Make it search through cache first, maybe...? @@ -1039,7 +1200,7 @@ lumpnum_t W_CheckNumForMap(const char *name) else continue; // Now look for the specified map. - for (++lumpNum; lumpNum < end; lumpNum++) + for (; lumpNum < end; lumpNum++) if (!strnicmp(name, (wadfiles[i]->lumpinfo + lumpNum)->name, 8)) return (i<<16) + lumpNum; } @@ -1064,6 +1225,24 @@ lumpnum_t W_GetNumForName(const char *name) return i; } +// +// Like W_GetNumForName, but can find entries with long names +// +// Should be the only version, but that's not possible until we fix +// all the instances of non null-terminated strings in the codebase... +// +lumpnum_t W_GetNumForLongName(const char *name) +{ + lumpnum_t i; + + i = W_CheckNumForLongName(name); + + if (i == LUMPERROR) + I_Error("W_GetNumForLongName: %s not found!\n", name); + + return i; +} + // // W_CheckNumForNameInBlock // Checks only in blocks from blockstart lump to blockend lump @@ -1103,7 +1282,7 @@ UINT8 W_LumpExists(const char *name) { lumpinfo_t *lump_p = wadfiles[i]->lumpinfo; for (j = 0; j < wadfiles[i]->numlumps; ++j, ++lump_p) - if (fastcmp(lump_p->name,name)) + if (fastcmp(lump_p->longname, name)) return true; } return false; @@ -1134,7 +1313,7 @@ boolean W_IsLumpWad(lumpnum_t lumpnum) { if (wadfiles[WADFILENUM(lumpnum)]->type == RET_PK3) { - const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->name2; + const char *lumpfullName = (wadfiles[WADFILENUM(lumpnum)]->lumpinfo + LUMPNUM(lumpnum))->fullname; if (strlen(lumpfullName) < 4) return false; // can't possibly be a WAD can it? @@ -1144,11 +1323,27 @@ boolean W_IsLumpWad(lumpnum_t lumpnum) return false; // WADs should never be inside non-PK3s as far as SRB2 is concerned } +// +// W_IsLumpFolder +// Is the lump a folder? (in a PK3 obviously) +// +boolean W_IsLumpFolder(UINT16 wad, UINT16 lump) +{ + if (wadfiles[wad]->type == RET_PK3) + { + const char *name = wadfiles[wad]->lumpinfo[lump].fullname; + + return (name[strlen(name)-1] == '/'); // folders end in '/' + } + + return false; // non-PK3s don't have folders +} + #ifdef HAVE_ZLIB /* report a zlib or i/o error */ void zerr(int ret) { - CONS_Printf("zpipe: "); + CONS_Printf("zpipe: "); switch (ret) { case Z_ERRNO: if (ferror(stdin)) @@ -1171,23 +1366,6 @@ void zerr(int ret) } #endif -#define NO_PNG_LUMPS - -#ifdef NO_PNG_LUMPS -static void ErrorIfPNG(UINT8 *d, size_t s, char *f, char *l) -{ - if (s < 67) // http://garethrees.org/2007/11/14/pngcrush/ - return; - // Check for PNG file signature using memcmp - // As it may be faster on CPUs with slow unaligned memory access - // Ref: http://www.libpng.org/pub/png/spec/1.2/PNG-Rationale.html#R.PNG-file-signature - if (memcmp(&d[0], "\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", 8) == 0) - { - I_Error("W_Wad: Lump \"%s\" in file \"%s\" is a .PNG - please convert to either Doom or Flat (raw) image format.", l, f); - } -} -#endif - /** Reads bytes from the head of a lump. * Note: If the lump is compressed, the whole thing has to be read anyway. * @@ -1230,7 +1408,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si #ifdef NO_PNG_LUMPS { size_t bytesread = fread(dest, 1, size, handle); - ErrorIfPNG(dest, bytesread, wadfiles[wad]->filename, l->name2); + if (Picture_IsLumpPNG((UINT8 *)dest, bytesread)) + Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename); return bytesread; } #else @@ -1271,7 +1450,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si Z_Free(rawData); Z_Free(decData); #ifdef NO_PNG_LUMPS - ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->name2); + if (Picture_IsLumpPNG((UINT8 *)dest, size)) + Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename); #endif return size; #else @@ -1324,7 +1504,6 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si } else { - CONS_Printf("whopet\n"); size = 0; zerr(zErr); } @@ -1333,7 +1512,8 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si Z_Free(decData); #ifdef NO_PNG_LUMPS - ErrorIfPNG(dest, size, wadfiles[wad]->filename, l->name2); + if (Picture_IsLumpPNG((UINT8 *)dest, size)) + Picture_ThrowPNGError(l->fullname, wadfiles[wad]->filename); #endif return size; } @@ -1341,7 +1521,7 @@ size_t W_ReadLumpHeaderPwad(UINT16 wad, UINT16 lump, void *dest, size_t size, si default: I_Error("wad %d, lump %d: unsupported compression type!", wad, lump); } - return -1; + return 0; } size_t W_ReadLumpHeader(lumpnum_t lumpnum, void *dest, size_t size, size_t offset) @@ -1390,7 +1570,6 @@ void *W_CacheLumpNumPwad(UINT16 wad, UINT16 lump, INT32 tag) void *W_CacheLumpNum(lumpnum_t lumpnum, INT32 tag) { - return W_CacheLumpNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); } @@ -1448,6 +1627,38 @@ boolean W_IsLumpCached(lumpnum_t lumpnum, void *ptr) return W_IsLumpCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); } +// +// W_IsPatchCached +// +// If a patch is already cached return true, otherwise +// return false. +// +// no outside code uses the PWAD form, for now +static inline boolean W_IsPatchCachedPWAD(UINT16 wad, UINT16 lump, void *ptr) +{ + void *lcache; + + if (!TestValidLump(wad, lump)) + return false; + + lcache = wadfiles[wad]->patchcache[lump]; + + if (ptr) + { + if (ptr == lcache) + return true; + } + else if (lcache) + return true; + + return false; +} + +boolean W_IsPatchCached(lumpnum_t lumpnum, void *ptr) +{ + return W_IsPatchCachedPWAD(WADFILENUM(lumpnum),LUMPNUM(lumpnum), ptr); +} + // ========================================================================== // W_CacheLumpName // ========================================================================== @@ -1471,25 +1682,79 @@ void *W_CacheLumpName(const char *name, INT32 tag) // Cache a patch into heap memory, convert the patch format as necessary // -// Software-only compile cache the data without conversion -#ifdef HWRENDER -static inline void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) +void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) { - GLPatch_t *grPatch; - - if (rendermode == render_soft || rendermode == render_none) - return W_CacheLumpNumPwad(wad, lump, tag); + lumpcache_t *lumpcache = NULL; if (!TestValidLump(wad, lump)) return NULL; + lumpcache = wadfiles[wad]->patchcache; + + if (!lumpcache[lump]) + { + size_t len = W_LumpLengthPwad(wad, lump); + void *ptr, *lumpdata; +#ifndef NO_PNG_LUMPS + void *srcdata = NULL; +#endif + + ptr = Z_Malloc(len, tag, &lumpcache[lump]); + lumpdata = Z_Malloc(len, tag, NULL); + + // read the lump in full + W_ReadLumpHeaderPwad(wad, lump, lumpdata, 0, 0); + +#ifndef NO_PNG_LUMPS + // lump is a png so convert it + if (Picture_IsLumpPNG((UINT8 *)lumpdata, len)) + { + size_t newlen; + srcdata = Picture_PNGConvert((UINT8 *)lumpdata, PICFMT_PATCH, NULL, NULL, NULL, NULL, len, &newlen, 0); + ptr = Z_Realloc(ptr, newlen, tag, &lumpcache[lump]); + M_Memcpy(ptr, srcdata, newlen); + Z_Free(srcdata); + } + else // just copy it into the patch cache +#endif + M_Memcpy(ptr, lumpdata, len); + } + else + Z_ChangeTag(lumpcache[lump], tag); + + return lumpcache[lump]; +} + +void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag) +{ + return W_CacheSoftwarePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); +} + +void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) +{ +#ifdef HWRENDER + GLPatch_t *grPatch; +#endif + + if (!TestValidLump(wad, lump)) + return NULL; + +#ifdef HWRENDER + // Software-only compile cache the data without conversion + if (rendermode == render_soft || rendermode == render_none) +#endif + { + return W_CacheSoftwarePatchNumPwad(wad, lump, tag); + } +#ifdef HWRENDER + grPatch = HWR_GetCachedGLPatchPwad(wad, lump); - if (grPatch->mipmap->grInfo.data) + if (grPatch->mipmap->data) { if (tag == PU_CACHE) tag = PU_HWRCACHE; - Z_ChangeTag(grPatch->mipmap->grInfo.data, tag); + Z_ChangeTag(grPatch->mipmap->data, tag); } else { @@ -1506,6 +1771,7 @@ static inline void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag) // return GLPatch_t, which can be casted to (patch_t) with valid patch header info return (void *)grPatch; +#endif } void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) @@ -1513,14 +1779,12 @@ void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag) return W_CachePatchNumPwad(WADFILENUM(lumpnum),LUMPNUM(lumpnum),tag); } -#endif // HWRENDER - void W_UnlockCachedPatch(void *patch) { // The hardware code does its own memory management, as its patches // have different lifetimes from software's. #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) HWR_UnlockCachedPatch((GLPatch_t*)patch); else #endif @@ -1538,6 +1802,17 @@ void *W_CachePatchName(const char *name, INT32 tag) return W_CachePatchNum(num, tag); } +void *W_CachePatchLongName(const char *name, INT32 tag) +{ + lumpnum_t num; + + num = W_CheckNumForLongName(name); + + if (num == LUMPERROR) + return W_CachePatchNum(W_GetNumForLongName("MISSING"), tag); + return W_CachePatchNum(num, tag); +} + #ifndef NOMD5 /** @@ -1605,18 +1880,171 @@ void W_VerifyFileMD5(UINT16 wadfilenum, const char *matchmd5) #else I_Error #endif - (M_GetText("File is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); + (M_GetText("File is old, is corrupt or has been modified: %s (found md5: %s, wanted: %s)\n"), wadfiles[wadfilenum]->filename, actualmd5text, matchmd5); } #endif } +// Verify versions for different archive +// formats. checklist assumed to be valid. + +static int +W_VerifyName (const char *name, lumpchecklist_t *checklist, boolean status) +{ + size_t j; + for (j = 0; checklist[j].len && checklist[j].name; ++j) + { + if (( strncasecmp(name, checklist[j].name, + checklist[j].len) != false ) == status) + { + return true; + } + } + return false; +} + +static int +W_VerifyWAD (FILE *fp, lumpchecklist_t *checklist, boolean status) +{ + size_t i; + + // assume wad file + wadinfo_t header; + filelump_t lumpinfo; + + // read the header + if (fread(&header, 1, sizeof header, fp) == sizeof header + && header.numlumps < INT16_MAX + && strncmp(header.identification, "ZWAD", 4) + && strncmp(header.identification, "IWAD", 4) + && strncmp(header.identification, "PWAD", 4) + && strncmp(header.identification, "SDLL", 4)) + { + return true; + } + + header.numlumps = LONG(header.numlumps); + header.infotableofs = LONG(header.infotableofs); + + // let seek to the lumpinfo list + if (fseek(fp, header.infotableofs, SEEK_SET) == -1) + return true; + + for (i = 0; i < header.numlumps; i++) + { + // fill in lumpinfo for this wad file directory + if (fread(&lumpinfo, sizeof (lumpinfo), 1 , fp) != 1) + return true; + + lumpinfo.filepos = LONG(lumpinfo.filepos); + lumpinfo.size = LONG(lumpinfo.size); + + if (lumpinfo.size == 0) + continue; + + if (! W_VerifyName(lumpinfo.name, checklist, status)) + return false; + } + + return true; +} + +// List of blacklisted folders to use when checking the PK3 +static lumpchecklist_t folderblacklist[] = +{ + {"Lua/", 4}, + {"SOC/", 4}, + {"Sprites/", 8}, + {"Textures/", 9}, + {"Patches/", 8}, + {"Flats/", 6}, + {"Fades/", 6}, + {NULL, 0}, +}; + +static int +W_VerifyPK3 (FILE *fp, lumpchecklist_t *checklist, boolean status) +{ + zend_t zend; + zentry_t zentry; + + UINT16 numlumps; + size_t i; + + char pat_central[] = {0x50, 0x4b, 0x01, 0x02, 0x00}; + char pat_end[] = {0x50, 0x4b, 0x05, 0x06, 0x00}; + + char lumpname[9]; + + // Haha the ResGetLumpsZip function doesn't + // check for file errors, so neither will I. + + // Central directory bullshit + + fseek(fp, 0, SEEK_END); + if (!ResFindSignature(fp, pat_end, max(0, ftell(fp) - (22 + 65536)))) + return true; + + fseek(fp, -4, SEEK_CUR); + if (fread(&zend, 1, sizeof zend, fp) < sizeof zend) + return true; + + numlumps = zend.entries; + + fseek(fp, zend.cdiroffset, SEEK_SET); + for (i = 0; i < numlumps; i++) + { + char* fullname; + char* trimname; + char* dotpos; + + if (fread(&zentry, 1, sizeof(zentry_t), fp) < sizeof(zentry_t)) + return true; + if (memcmp(zentry.signature, pat_central, 4)) + return true; + + fullname = malloc(zentry.namelen + 1); + if (fgets(fullname, zentry.namelen + 1, fp) != fullname) + return true; + + // Strip away file address and extension for the 8char name. + if ((trimname = strrchr(fullname, '/')) != 0) + trimname++; + else + trimname = fullname; // Care taken for root files. + + if (*trimname) // Ignore directories, well kinda + { + if ((dotpos = strrchr(trimname, '.')) == 0) + dotpos = fullname + strlen(fullname); // Watch for files without extension. + + memset(lumpname, '\0', 9); // Making sure they're initialized to 0. Is it necessary? + strncpy(lumpname, trimname, min(8, dotpos - trimname)); + + if (! W_VerifyName(lumpname, checklist, status)) + return false; + + // Check for directories next, if it's blacklisted it will return false + if (W_VerifyName(fullname, folderblacklist, status)) + return false; + } + + free(fullname); + + // skip and ignore comments/extra fields + if (fseek(fp, zentry.xtralen + zentry.commlen, SEEK_CUR) != 0) + return true; + } + + return true; +} + // Note: This never opens lumps themselves and therefore doesn't have to // deal with compressed lumps. static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, boolean status) { FILE *handle; - size_t i, j; int goodfile = false; if (!checklist) @@ -1625,66 +2053,15 @@ static int W_VerifyFile(const char *filename, lumpchecklist_t *checklist, if ((handle = W_OpenWadFile(&filename, false)) == NULL) return -1; - // detect wad file by the absence of the other supported extensions - if (stricmp(&filename[strlen(filename) - 4], ".soc") -#ifdef HAVE_BLUA - && stricmp(&filename[strlen(filename) - 4], ".lua") -#endif - && stricmp(&filename[strlen(filename) - 4], ".pk3")) + if (stricmp(&filename[strlen(filename) - 4], ".pk3") == 0) + goodfile = W_VerifyPK3(handle, checklist, status); + else { - // assume wad file - wadinfo_t header; - filelump_t lumpinfo; - - // read the header - if (fread(&header, 1, sizeof header, handle) == sizeof header - && header.numlumps < INT16_MAX - && strncmp(header.identification, "ZWAD", 4) - && strncmp(header.identification, "IWAD", 4) - && strncmp(header.identification, "PWAD", 4) - && strncmp(header.identification, "SDLL", 4)) + // detect wad file by the absence of the other supported extensions + if (stricmp(&filename[strlen(filename) - 4], ".soc") + && stricmp(&filename[strlen(filename) - 4], ".lua")) { - fclose(handle); - return true; - } - - header.numlumps = LONG(header.numlumps); - header.infotableofs = LONG(header.infotableofs); - - // let seek to the lumpinfo list - if (fseek(handle, header.infotableofs, SEEK_SET) == -1) - { - fclose(handle); - return false; - } - - goodfile = true; - for (i = 0; i < header.numlumps; i++) - { - // fill in lumpinfo for this wad file directory - if (fread(&lumpinfo, sizeof (lumpinfo), 1 , handle) != 1) - { - fclose(handle); - return -1; - } - - lumpinfo.filepos = LONG(lumpinfo.filepos); - lumpinfo.size = LONG(lumpinfo.size); - - if (lumpinfo.size == 0) - continue; - - for (j = 0; j < NUMSPRITES; j++) - if (sprnames[j] && !strncmp(lumpinfo.name, sprnames[j], 4)) // Sprites - continue; - - goodfile = false; - for (j = 0; checklist[j].len && checklist[j].name && !goodfile; j++) - if ((strncmp(lumpinfo.name, checklist[j].name, checklist[j].len) != false) == status) - goodfile = true; - - if (!goodfile) - break; + goodfile = W_VerifyWAD(handle, checklist, status); } } fclose(handle); @@ -1707,7 +2084,6 @@ int W_VerifyNMUSlumps(const char *filename) { lumpchecklist_t NMUSlist[] = { - {"D_", 2}, // MIDI music {"O_", 2}, // Digital music {"DS", 2}, // Sound effects @@ -1722,8 +2098,7 @@ int W_VerifyNMUSlumps(const char *filename) {"TTL", 3}, // Act number changes {"STCFN", 5}, // Console font changes {"TNYFN", 5}, // Tiny console font changes - {"SBO", 3}, // Acceptable HUD changes (Score Time Rings) - {"RRINGS", 6}, // Rings HUD (not named as SBO) + {"STT", 3}, // Acceptable HUD changes (Score Time Rings) {"YB_", 3}, // Intermission graphics, goes with the above {"M_", 2}, // As does menu stuff {"MKFNT", 5}, // Kart font changes @@ -1738,3 +2113,101 @@ int W_VerifyNMUSlumps(const char *filename) }; return W_VerifyFile(filename, NMUSlist, false); } + +/** \brief Generates a virtual resource used for level data loading. + * + * \param lumpnum_t reference + * \return Virtual resource + * + */ +virtres_t* vres_GetMap(lumpnum_t lumpnum) +{ + UINT32 i; + virtres_t* vres = NULL; + virtlump_t* vlumps = NULL; + size_t numlumps = 0; + + if (W_IsLumpWad(lumpnum)) + { + // Remember that we're assuming that the WAD will have a specific set of lumps in a specific order. + UINT8 *wadData = W_CacheLumpNum(lumpnum, PU_LEVEL); + filelump_t *fileinfo = (filelump_t *)(wadData + ((wadinfo_t *)wadData)->infotableofs); + numlumps = ((wadinfo_t *)wadData)->numlumps; + vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); + + // Build the lumps. + for (i = 0; i < numlumps; i++) + { + vlumps[i].size = (size_t)(((filelump_t *)(fileinfo + i))->size); + // Play it safe with the name in this case. + memcpy(vlumps[i].name, (fileinfo + i)->name, 8); + vlumps[i].name[8] = '\0'; + vlumps[i].data = Z_Malloc(vlumps[i].size, PU_LEVEL, NULL); // This is memory inefficient, sorry about that. + memcpy(vlumps[i].data, wadData + (fileinfo + i)->filepos, vlumps[i].size); + } + + Z_Free(wadData); + } + else + { + // Count number of lumps until the end of resource OR up until next "MAPXX" lump. + lumpnum_t lumppos = lumpnum + 1; + for (i = LUMPNUM(lumppos); i < wadfiles[WADFILENUM(lumpnum)]->numlumps; i++, lumppos++, numlumps++) + if (memcmp(W_CheckNameForNum(lumppos), "MAP", 3) == 0) + break; + numlumps++; + + vlumps = Z_Malloc(sizeof(virtlump_t)*numlumps, PU_LEVEL, NULL); + for (i = 0; i < numlumps; i++, lumpnum++) + { + vlumps[i].size = W_LumpLength(lumpnum); + memcpy(vlumps[i].name, W_CheckNameForNum(lumpnum), 8); + vlumps[i].name[8] = '\0'; + vlumps[i].data = W_CacheLumpNum(lumpnum, PU_LEVEL); + } + } + vres = Z_Malloc(sizeof(virtres_t), PU_LEVEL, NULL); + vres->vlumps = vlumps; + vres->numlumps = numlumps; + + return vres; +} + +/** \brief Frees zone memory for a given virtual resource. + * + * \param Virtual resource + */ +void vres_Free(virtres_t* vres) +{ + while (vres->numlumps--) + Z_Free(vres->vlumps[vres->numlumps].data); + Z_Free(vres->vlumps); + Z_Free(vres); +} + +/** (Debug) Prints lumps from a virtual resource into console. + */ +/* +static void vres_Diag(const virtres_t* vres) +{ + UINT32 i; + for (i = 0; i < vres->numlumps; i++) + CONS_Printf("%s\n", vres->vlumps[i].name); +} +*/ + +/** \brief Finds a lump in a given virtual resource. + * + * \param Virtual resource + * \param Lump name to look for + * \return Virtual lump if found, NULL otherwise + * + */ +virtlump_t* vres_Find(const virtres_t* vres, const char* name) +{ + UINT32 i; + for (i = 0; i < vres->numlumps; i++) + if (fastcmp(name, vres->vlumps[i].name)) + return &vres->vlumps[i]; + return NULL; +} diff --git a/src/w_wad.h b/src/w_wad.h index ffe63e795..4797f4afd 100644 --- a/src/w_wad.h +++ b/src/w_wad.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -66,12 +66,32 @@ typedef struct { unsigned long position; // filelump_t filepos unsigned long disksize; // filelump_t size - char name[9]; // filelump_t name[] - char *name2; // Used by PK3s. Dynamically allocated name. - size_t size; // real (uncompressed) size + char name[9]; // filelump_t name[] e.g. "LongEntr" + char *longname; // e.g. "LongEntryName" + char *fullname; // e.g. "Folder/Subfolder/LongEntryName.extension" + size_t size; // real (uncompressed) size compmethod compression; // lump compression method } lumpinfo_t; +// ========================================================================= +// 'VIRTUAL' RESOURCES +// ========================================================================= + +typedef struct { + char name[9]; + UINT8* data; + size_t size; +} virtlump_t; + +typedef struct { + size_t numlumps; + virtlump_t* vlumps; +} virtres_t; + +virtres_t* vres_GetMap(lumpnum_t); +void vres_Free(virtres_t*); +virtlump_t* vres_Find(const virtres_t*, const char*); + // ========================================================================= // DYNAMIC WAD LOADING // ========================================================================= @@ -97,13 +117,13 @@ typedef enum restype RET_UNKNOWN, } restype_t; - typedef struct wadfile_s { char *filename; restype_t type; lumpinfo_t *lumpinfo; lumpcache_t *lumpcache; + lumpcache_t *patchcache; #ifdef HWRENDER aatree_t *hwrcache; // patches are cached in renderer's native format #endif @@ -111,7 +131,8 @@ typedef struct wadfile_s FILE *handle; UINT32 filesize; // for network UINT8 md5sum[16]; - boolean important; + + boolean important; // also network - !W_VerifyNMUSlumps } wadfile_t; #define WADFILENUM(lumpnum) (UINT16)((lumpnum)>>16) // wad flumpnum>>16) // wad file number in upper word @@ -127,19 +148,23 @@ void W_Shutdown(void); // Opens a WAD file. Returns the FILE * handle for the file, or NULL if not found or could not be opened FILE *W_OpenWadFile(const char **filename, boolean useerrors); // Load and add a wadfile to the active wad files, returns numbers of lumps, INT16_MAX on error -UINT16 W_InitFile(const char *filename); -#ifdef DELFILE -void W_UnloadWadFile(UINT16 num); -#endif +UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup); // W_InitMultipleFiles returns 1 if all is okay, 0 otherwise, // so that it stops with a message if a file was not found, but not if all is okay. +// W_InitMultipleFiles exits if a file was not found, but not if all is okay. INT32 W_InitMultipleFiles(char **filenames, boolean addons); const char *W_CheckNameForNumPwad(UINT16 wad, UINT16 lump); const char *W_CheckNameForNum(lumpnum_t lumpnum); +UINT16 W_FindNextEmptyInPwad(UINT16 wad, UINT16 startlump); // checks only in one pwad + UINT16 W_CheckNumForNamePwad(const char *name, UINT16 wad, UINT16 startlump); // checks only in one pwad +UINT16 W_CheckNumForLongNamePwad(const char *name, UINT16 wad, UINT16 startlump); + +/* Find the first lump after F_START for instance. */ +UINT16 W_CheckNumForMarkerStartPwad(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFullNamePK3(const char *name, UINT16 wad, UINT16 startlump); UINT16 W_CheckNumForFolderStartPK3(const char *name, UINT16 wad, UINT16 startlump); @@ -147,7 +172,9 @@ UINT16 W_CheckNumForFolderEndPK3(const char *name, UINT16 wad, UINT16 startlump) lumpnum_t W_CheckNumForMap(const char *name); lumpnum_t W_CheckNumForName(const char *name); +lumpnum_t W_CheckNumForLongName(const char *name); lumpnum_t W_GetNumForName(const char *name); // like W_CheckNumForName but I_Error on LUMPERROR +lumpnum_t W_GetNumForLongName(const char *name); lumpnum_t W_CheckNumForNameInBlock(const char *name, const char *blockstart, const char *blockend); UINT8 W_LumpExists(const char *name); // Lua uses this. @@ -155,6 +182,7 @@ size_t W_LumpLengthPwad(UINT16 wad, UINT16 lump); size_t W_LumpLength(lumpnum_t lumpnum); boolean W_IsLumpWad(lumpnum_t lumpnum); // for loading maps from WADs in PK3s +boolean W_IsLumpFolder(UINT16 wad, UINT16 lump); // for detecting folder "lumps" #ifdef HAVE_ZLIB void zerr(int ret); // zlib error checking @@ -170,17 +198,21 @@ void *W_CacheLumpNum(lumpnum_t lump, INT32 tag); void *W_CacheLumpNumForce(lumpnum_t lumpnum, INT32 tag); boolean W_IsLumpCached(lumpnum_t lump, void *ptr); +boolean W_IsPatchCached(lumpnum_t lump, void *ptr); void *W_CacheLumpName(const char *name, INT32 tag); void *W_CachePatchName(const char *name, INT32 tag); +void *W_CachePatchLongName(const char *name, INT32 tag); -#ifdef HWRENDER -//void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); // return a patch_t -void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); // return a patch_t -#else -//#define W_CachePatchNumPwad(wad, lump, tag) W_CacheLumpNumPwad(wad, lump, tag) -#define W_CachePatchNum(lumpnum, tag) W_CacheLumpNum(lumpnum, tag) -#endif +// Returns either a Software patch, or an OpenGL patch. +// Performs any necessary conversions from PNG images. +void *W_CachePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); +void *W_CachePatchNum(lumpnum_t lumpnum, INT32 tag); + +// Returns a Software patch. +// Performs any necessary conversions from PNG images. +void *W_CacheSoftwarePatchNumPwad(UINT16 wad, UINT16 lump, INT32 tag); +void *W_CacheSoftwarePatchNum(lumpnum_t lumpnum, INT32 tag); void W_UnlockCachedPatch(void *patch); diff --git a/src/win32/Makefile.cfg b/src/win32/Makefile.cfg index 583a3c79a..9acb65857 100644 --- a/src/win32/Makefile.cfg +++ b/src/win32/Makefile.cfg @@ -10,15 +10,35 @@ ifdef MINGW64 HAVE_LIBGME=1 LIBGME_CFLAGS=-I../libs/gme/include LIBGME_LDFLAGS=-L../libs/gme/win64 -lgme +ifdef HAVE_OPENMPT + LIBOPENMPT_CFLAGS?=-I../libs/libopenmpt/inc + LIBOPENMPT_LDFLAGS?=-L../libs/libopenmpt/lib/x86_64/mingw -lopenmpt +endif +ifndef NOMIXERX + HAVE_MIXERX=1 + SDL_CFLAGS?=-I../libs/SDL2/x86_64-w64-mingw32/include/SDL2 -I../libs/SDLMixerX/x86_64-w64-mingw32/include/SDL2 -Dmain=SDL_main + SDL_LDFLAGS?=-L../libs/SDL2/x86_64-w64-mingw32/lib -L../libs/SDLMixerX/x86_64-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows +else SDL_CFLAGS?=-I../libs/SDL2/x86_64-w64-mingw32/include/SDL2 -I../libs/SDL2_mixer/x86_64-w64-mingw32/include/SDL2 -Dmain=SDL_main SDL_LDFLAGS?=-L../libs/SDL2/x86_64-w64-mingw32/lib -L../libs/SDL2_mixer/x86_64-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows +endif else HAVE_LIBGME=1 LIBGME_CFLAGS=-I../libs/gme/include LIBGME_LDFLAGS=-L../libs/gme/win32 -lgme +ifdef HAVE_OPENMPT + LIBOPENMPT_CFLAGS?=-I../libs/libopenmpt/inc + LIBOPENMPT_LDFLAGS?=-L../libs/libopenmpt/lib/x86/mingw -lopenmpt +endif +ifndef NOMIXERX + HAVE_MIXERX=1 + SDL_CFLAGS?=-I../libs/SDL2/i686-w64-mingw32/include/SDL2 -I../libs/SDLMixerX/i686-w64-mingw32/include/SDL2 -Dmain=SDL_main + SDL_LDFLAGS?=-L../libs/SDL2/i686-w64-mingw32/lib -L../libs/SDLMixerX/i686-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows +else SDL_CFLAGS?=-I../libs/SDL2/i686-w64-mingw32/include/SDL2 -I../libs/SDL2_mixer/i686-w64-mingw32/include/SDL2 -Dmain=SDL_main SDL_LDFLAGS?=-L../libs/SDL2/i686-w64-mingw32/lib -L../libs/SDL2_mixer/i686-w64-mingw32/lib -lmingw32 -lSDL2main -lSDL2 -mwindows endif +endif ifndef NOASM USEASM=1 @@ -30,6 +50,10 @@ ifndef MINGW64 #miniupnc is broken with MINGW64 endif endif +ifndef NO_DISCORDRPC + HAVE_DISCORDRPC=1 +endif + OPTS=-DSTDC_HEADERS ifndef GCC44 @@ -56,6 +80,12 @@ else endif endif +ifndef MINGW64 + CPPFLAGS+=-I../libs/drmingw/include + LDFLAGS+=-L../libs/drmingw/lib/win32 + LIBS+=-lmgwhelp -lexchndl +endif + # name of the exefile ifdef SDL EXENAME?=srb2kart.exe @@ -142,4 +172,15 @@ ifdef MINGW64 else CURL_LDFLAGS+=-L../libs/curl/lib32 -lcurl endif #MINGW64 -endif \ No newline at end of file +endif + +ifdef HAVE_DISCORDRPC +ifdef MINGW64 + CPPFLAGS+=-I../libs/discord-rpc/win64-dynamic/include + LDFLAGS+=-L../libs/discord-rpc/win64-dynamic/lib +else + CPPFLAGS+=-I../libs/discord-rpc/win32-dynamic/include + LDFLAGS+=-L../libs/discord-rpc/win32-dynamic/lib +endif + LIBS+=-ldiscord-rpc +endif diff --git a/src/win32/Srb2win-vc10.vcxproj b/src/win32/Srb2win-vc10.vcxproj index 698efa09b..e0d4c4546 100644 --- a/src/win32/Srb2win-vc10.vcxproj +++ b/src/win32/Srb2win-vc10.vcxproj @@ -234,7 +234,6 @@ - @@ -296,11 +295,17 @@ true + + true + + + + @@ -395,7 +400,6 @@ - @@ -452,11 +456,14 @@ + + + diff --git a/src/win32/Srb2win-vc10.vcxproj.filters b/src/win32/Srb2win-vc10.vcxproj.filters index e5401d720..a84ae63ca 100644 --- a/src/win32/Srb2win-vc10.vcxproj.filters +++ b/src/win32/Srb2win-vc10.vcxproj.filters @@ -87,6 +87,27 @@ Win32app + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + Hw_Hardware @@ -345,6 +366,9 @@ R_Rend + + R_Rend + R_Rend @@ -433,6 +457,28 @@ + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + + R_Rend + + + R_Rend + @@ -456,6 +502,42 @@ Win32app + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + + + Hw_Hardware + Hw_Hardware @@ -804,6 +886,19 @@ O_Other + + Hw_Hardware + + + + R_Rend + + + R_Rend + + + R_Rend + diff --git a/src/win32/Srb2win-vc9.vcproj b/src/win32/Srb2win-vc9.vcproj index 2bf2d6631..710fea317 100644 --- a/src/win32/Srb2win-vc9.vcproj +++ b/src/win32/Srb2win-vc9.vcproj @@ -55,7 +55,7 @@ Optimization="0" OmitFramePointers="false" AdditionalIncludeDirectories=""$(ProjectDir)..\..\libs\libpng-src";"$(ProjectDir)..\..\libs\zlib"" - PreprocessorDefinitions="_DEBUG;_WINDOWS;USEASM;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" + PreprocessorDefinitions="_DEBUG;_WINDOWS;USEASM;HAVE_PNG;COMPVERSION;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" MinimalRebuild="true" RuntimeLibrary="1" EnableFunctionLevelLinking="true" @@ -153,7 +153,7 @@ Optimization="0" OmitFramePointers="false" AdditionalIncludeDirectories=""$(ProjectDir)..\..\libs\libpng-src";"$(ProjectDir)..\..\libs\zlib"" - PreprocessorDefinitions="_DEBUG;_WINDOWS;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" + PreprocessorDefinitions="_DEBUG;_WINDOWS;HAVE_PNG;COMPVERSION;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" MinimalRebuild="true" BasicRuntimeChecks="3" SmallerTypeCheck="true" @@ -256,7 +256,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" AdditionalIncludeDirectories=""$(ProjectDir)..\..\libs\libpng-src";"$(ProjectDir)..\..\libs\zlib"" - PreprocessorDefinitions="NDEBUG;_WINDOWS;USEASM;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" + PreprocessorDefinitions="NDEBUG;_WINDOWS;USEASM;HAVE_PNG;COMPVERSION;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -356,7 +356,7 @@ FavorSizeOrSpeed="1" OmitFramePointers="true" AdditionalIncludeDirectories=""$(ProjectDir)..\..\libs\libpng-src";"$(ProjectDir)..\..\libs\zlib"" - PreprocessorDefinitions="NDEBUG;_WINDOWS;HAVE_PNG;COMPVERSION;HAVE_BLUA;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" + PreprocessorDefinitions="NDEBUG;_WINDOWS;HAVE_PNG;COMPVERSION;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="true" @@ -2331,46 +2331,6 @@ RelativePath="..\hardware\hw_md2.h" > - - - - - - - - - - - - - - diff --git a/src/win32/Srb2win.dsp b/src/win32/Srb2win.dsp index c52873f7b..661f3eaf9 100644 --- a/src/win32/Srb2win.dsp +++ b/src/win32/Srb2win.dsp @@ -563,10 +563,6 @@ SOURCE=..\hardware\hw_md2.h # End Source File # Begin Source File -SOURCE=..\hardware\hw_trick.c -# End Source File -# Begin Source File - SOURCE=..\hardware\hws_data.h # End Source File # End Group diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index d7a26dc85..b3925c873 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -3,6 +3,7 @@ //Microsoft Developer Studio generated resource script. // #include "resource.h" +#include "winver.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// @@ -74,9 +75,11 @@ END // Version // +#include "../doomdef.h" // Needed for version string + VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,0,9,0 - PRODUCTVERSION 1,0,9,0 + FILEVERSION 2,0,0,0 + PRODUCTVERSION 2,0,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -91,17 +94,17 @@ BEGIN BEGIN BLOCK "04090000" BEGIN - VALUE "Comments", "Visit our web site at www.srb2.org for news and updates!\0" - VALUE "CompanyName", "Sonic Team Junior\0" - VALUE "FileDescription", "Sonic Robo Blast 2\0" - VALUE "FileVersion", "1, 09\0" - VALUE "InternalName", "srb2\0" - VALUE "LegalCopyright", "Copyright � 1998-2018 by Sonic Team Junior\0" - VALUE "LegalTrademarks", "Sonic the Hedgehog and related characters are trademarks of Sega.\0" - VALUE "OriginalFilename", "srb2win.exe\0" + VALUE "Comments", "Go go-karting with Dr. Eggman!\0" + VALUE "CompanyName", "Kart Krew\0" + VALUE "FileDescription", "SRB2Kart\0" + VALUE "FileVersion", VERSIONSTRING_RC + VALUE "InternalName", "srb2kart\0" + VALUE "LegalCopyright", "Copyright 2018-2020 by Kart Krew\0" + VALUE "LegalTrademarks", "Dr. Eggman and related characters are trademarks of Sega.\0" + VALUE "OriginalFilename", "srb2kart.exe\0" VALUE "PrivateBuild", "\0" - VALUE "ProductName", "Sonic Robo Blast 2\0" - VALUE "ProductVersion", "1, 09\0" + VALUE "ProductName", "SRB2Kart\0" + VALUE "ProductVersion", VERSIONSTRING_RC VALUE "SpecialBuild", "\0" END END diff --git a/src/win32/srb2win.exe.manifest b/src/win32/srb2win.exe.manifest new file mode 100644 index 000000000..d3b8355cb --- /dev/null +++ b/src/win32/srb2win.exe.manifest @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/win32/win_cd.c b/src/win32/win_cd.c index 2586b8440..324c24928 100644 --- a/src/win32/win_cd.c +++ b/src/win32/win_cd.c @@ -161,13 +161,13 @@ static BOOL wasPlaying; //static INT cdVolume = 0; // current cd volume (0-31) // 0-31 like Music & Sfx, though CD hardware volume is 0-255. -consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cd_volume = CVAR_INIT ("cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL); // allow Update for next/loop track // some crap cd drivers take up to // a second for a simple 'busy' check.. // (on those Update can be disabled) -consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cdUpdate = CVAR_INIT ("cd_update","1",CV_SAVE, NULL, NULL); #if (__GNUC__ > 6) #pragma GCC diagnostic push diff --git a/src/win32/win_dll.c b/src/win32/win_dll.c index 77ddc6e30..f492cd92d 100644 --- a/src/win32/win_dll.c +++ b/src/win32/win_dll.c @@ -81,6 +81,95 @@ static VOID UnloadDLL (HMODULE* pModule) } #endif +// ========================================================================== +// STANDARD 3D DRIVER DLL FOR DOOM LEGACY +// ========================================================================== + +// note : the 3D driver loading should be put somewhere else.. +#ifdef HWRENDER +static HMODULE hwdModule = NULL; + +static loadfunc_t hwdFuncTable[] = { +#ifdef _X86_ + {"Init@4", &hwdriver.pfnInit}, + {"Shutdown@0", &hwdriver.pfnShutdown}, + {"GetModeList@8", &hwdriver.pfnGetModeList}, + {"SetPalette@4", &hwdriver.pfnSetPalette}, + {"FinishUpdate@4", &hwdriver.pfnFinishUpdate}, + {"Draw2DLine@12", &hwdriver.pfnDraw2DLine}, + {"DrawPolygon@16", &hwdriver.pfnDrawPolygon}, + {"RenderSkyDome@4", &hwdriver.pfnRenderSkyDome}, + {"SetBlend@4", &hwdriver.pfnSetBlend}, + {"ClearBuffer@12", &hwdriver.pfnClearBuffer}, + {"SetTexture@4", &hwdriver.pfnSetTexture}, + {"UpdateTexture@4", &hwdriver.pfnUpdateTexture}, + {"ReadRect@24", &hwdriver.pfnReadRect}, + {"GClipRect@20", &hwdriver.pfnGClipRect}, + {"ClearMipMapCache@0", &hwdriver.pfnClearMipMapCache}, + {"SetSpecialState@8", &hwdriver.pfnSetSpecialState}, + {"DrawModel@16", &hwdriver.pfnDrawModel}, + {"SetTransform@4", &hwdriver.pfnSetTransform}, + {"GetTextureUsed@0", &hwdriver.pfnGetTextureUsed}, + {"GetRenderVersion@0", &hwdriver.pfnGetRenderVersion}, +#ifdef SHUFFLE + {"PostImgRedraw@4", &hwdriver.pfnPostImgRedraw}, +#endif + {"FlushScreenTextures@0",&hwdriver.pfnFlushScreenTextures}, + {"StartScreenWipe@0", &hwdriver.pfnStartScreenWipe}, + {"EndScreenWipe@0", &hwdriver.pfnEndScreenWipe}, + {"DoScreenWipe@0", &hwdriver.pfnDoScreenWipe}, + {"DrawIntermissionBG@0",&hwdriver.pfnDrawIntermissionBG}, + {"MakeScreenTexture@0", &hwdriver.pfnMakeScreenTexture}, + {"MakeScreenFinalTexture@0", &hwdriver.pfnMakeScreenFinalTexture}, + {"DrawScreenFinalTexture@8", &hwdriver.pfnDrawScreenFinalTexture}, +#else + {"Init", &hwdriver.pfnInit}, + {"Shutdown", &hwdriver.pfnShutdown}, + {"GetModeList", &hwdriver.pfnGetModeList}, + {"SetPalette", &hwdriver.pfnSetPalette}, + {"FinishUpdate", &hwdriver.pfnFinishUpdate}, + {"Draw2DLine", &hwdriver.pfnDraw2DLine}, + {"DrawPolygon", &hwdriver.pfnDrawPolygon}, + {"RenderSkyDome", &hwdriver.pfnRenderSkyDome}, + {"SetBlend", &hwdriver.pfnSetBlend}, + {"ClearBuffer", &hwdriver.pfnClearBuffer}, + {"SetTexture", &hwdriver.pfnSetTexture}, + {"UpdateTexture", &hwdriver.pfnUpdateTexture}, + {"ReadRect", &hwdriver.pfnReadRect}, + {"GClipRect", &hwdriver.pfnGClipRect}, + {"ClearMipMapCache", &hwdriver.pfnClearMipMapCache}, + {"SetSpecialState", &hwdriver.pfnSetSpecialState}, + {"DrawModel", &hwdriver.pfnDrawModel}, + {"SetTransform", &hwdriver.pfnSetTransform}, + {"GetTextureUsed", &hwdriver.pfnGetTextureUsed}, + {"GetRenderVersion", &hwdriver.pfnGetRenderVersion}, +#ifdef SHUFFLE + {"PostImgRedraw", &hwdriver.pfnPostImgRedraw}, +#endif + {"FlushScreenTextures", &hwdriver.pfnFlushScreenTextures}, + {"StartScreenWipe", &hwdriver.pfnStartScreenWipe}, + {"EndScreenWipe", &hwdriver.pfnEndScreenWipe}, + {"DoScreenWipe", &hwdriver.pfnDoScreenWipe}, + {"DrawIntermissionBG", &hwdriver.pfnDrawIntermissionBG}, + {"MakeScreenTexture", &hwdriver.pfnMakeScreenTexture}, + {"MakeScreenFinalTexture", &hwdriver.pfnMakeScreenFinalTexture}, + {"DrawScreenFinalTexture", &hwdriver.pfnDrawScreenFinalTexture}, +#endif + {NULL,NULL} +}; + +BOOL Init3DDriver (LPCSTR dllName) +{ + hwdModule = LoadDLL(dllName, hwdFuncTable); + return (hwdModule != NULL); +} + +VOID Shutdown3DDriver (VOID) +{ + UnloadDLL(&hwdModule); +} +#endif + #ifdef HW3SOUND static HMODULE hwsModule = NULL; diff --git a/src/win32/win_main.c b/src/win32/win_main.c index 55d71585b..54b489751 100644 --- a/src/win32/win_main.c +++ b/src/win32/win_main.c @@ -42,7 +42,7 @@ #include "fabdxlib.h" #include "win_main.h" #include "win_dbg.h" -#include "../i_sound.h" // midi pause/unpause +#include "../s_sound.h" // pause sound with handling #include "../g_input.h" // KEY_MOUSEWHEELxxx #include "../screen.h" // for BASEVID* @@ -110,9 +110,9 @@ static LRESULT CALLBACK MainWndproc(HWND hWnd, UINT message, WPARAM wParam, LPAR // pause music when alt-tab if (appActive && !paused) - I_ResumeSong(); + S_ResumeAudio(); else if (!paused) - I_PauseSong(); + S_PauseAudio(); { HANDLE ci = GetStdHandle(STD_INPUT_HANDLE); DWORD mode; @@ -643,37 +643,28 @@ int WINAPI WinMain (HINSTANCE hInstance, int nCmdShow) { int Result = -1; - -#if 0 - // Win95 and NT <4 don't have this, so link at runtime. - p_IsDebuggerPresent pfnIsDebuggerPresent = (p_IsDebuggerPresent)GetProcAddress(GetModuleHandleA("kernel32.dll"),"IsDebuggerPresent"); -#endif - UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); UNREFERENCED_PARAMETER(nCmdShow); -#if 0 -#ifdef BUGTRAP - // Try BugTrap first. - if((!pfnIsDebuggerPresent || !pfnIsDebuggerPresent()) && InitBugTrap()) - Result = HandledWinMain(hInstance); - else { -#endif - // Try Dr MinGW's exception handler. - if (!pfnIsDebuggerPresent || !pfnIsDebuggerPresent()) -#endif - LoadLibraryA("exchndl.dll"); - -#ifndef __MINGW32__ - prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo); -#endif - - Result = HandledWinMain(hInstance); +#if 0 + p_IsDebuggerPresent pfnIsDebuggerPresent = (p_IsDebuggerPresent)GetProcAddress(GetModuleHandleA("kernel32.dll"),"IsDebuggerPresent"); + if((!pfnIsDebuggerPresent || !pfnIsDebuggerPresent()) +#ifdef BUGTRAP + && !InitBugTrap() +#endif + ) +#endif + { + LoadLibraryA("exchndl.dll"); + } + } +#ifndef __MINGW32__ + prevExceptionFilter = SetUnhandledExceptionFilter(RecordExceptionInfo); +#endif + Result = HandledWinMain(hInstance); #ifdef BUGTRAP - } // BT failure clause. - // This is safe even if BT didn't start. ShutdownBugTrap(); #endif diff --git a/src/win32/win_snd.c b/src/win32/win_snd.c index f3e3bbed4..13f766728 100644 --- a/src/win32/win_snd.c +++ b/src/win32/win_snd.c @@ -842,6 +842,7 @@ boolean I_SetSongPosition(UINT32 position) // Dummy out; this works for some MIDI, but not others. // SDL does not support this for any MIDI. return false; + e = FMOD_Channel_SetPosition(music_channel, position, FMOD_TIMEUNIT_MS); if (e == FMOD_OK) return true; diff --git a/src/win32/win_sys.c b/src/win32/win_sys.c index b32ee617f..2609c3e31 100644 --- a/src/win32/win_sys.c +++ b/src/win32/win_sys.c @@ -54,6 +54,8 @@ #include "../screen.h" +#include "../m_menu.h" + // Wheel support for Win95/WinNT3.51 #include @@ -327,7 +329,7 @@ static inline VOID I_GetConsoleEvents(VOID) break; case VK_RETURN: entering_con_command = false; - // Fall through. + /* FALLTHRU */ default: ev.data1 = MapVirtualKey(input.Event.KeyEvent.wVirtualKeyCode,2); // convert in to char } @@ -465,6 +467,7 @@ static void signal_handler(int num) char sigdef[64]; D_QuitNetGame(); // Fix server freezes + CL_AbortDownloadResume(); I_ShutdownSystem(); switch (num) @@ -647,9 +650,11 @@ void I_Error(const char *error, ...) if (demo.recording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); D_QuitNetGame(); + CL_AbortDownloadResume(); + M_FreePlayerSetupColors(); // shutdown everything that was started I_ShutdownSystem(); @@ -733,7 +738,7 @@ void I_Quit(void) if (demo.recording) G_CheckDemoStatus(); if (metalrecording) - G_StopMetalRecording(); + G_StopMetalRecording(false); M_SaveConfig(NULL); // save game config, cvars.. #ifndef NONET @@ -745,6 +750,9 @@ void I_Quit(void) // or something else that will be finished by I_ShutdownSystem(), // so do it before. D_QuitNetGame(); + CL_AbortDownloadResume(); + + M_FreePlayerSetupColors(); // shutdown everything that was started I_ShutdownSystem(); @@ -1354,6 +1362,8 @@ getBufferedData: } } +void I_UpdateMouseGrab(void) {} + // =========================================================================================== // DIRECT INPUT JOYSTICK // =========================================================================================== @@ -3197,7 +3207,7 @@ INT32 I_GetKey(void) // ----------------- #define DI_KEYBOARD_BUFFERSIZE 32 // number of data elements in keyboard buffer -void I_StartupKeyboard(void) +static void I_StartupKeyboard(void) { DIPROPDWORD dip; @@ -3433,6 +3443,8 @@ INT32 I_StartupSystem(void) // some 'more global than globals' things to initialize here ? graphics_started = keyboard_started = sound_started = cdaudio_started = false; + I_StartupKeyboard(); + #ifdef NDEBUG #ifdef BUGTRAP @@ -3646,7 +3658,7 @@ const CPUInfoFlags *I_CPUInfo(void) } static void CPUAffinity_OnChange(void); -static consvar_t cv_cpuaffinity = {"cpuaffinity", "-1", CV_CALL, NULL, CPUAffinity_OnChange, 0, NULL, NULL, 0, 0, NULL}; +static consvar_t cv_cpuaffinity = CVAR_INIT ("cpuaffinity", "-1", CV_CALL, NULL, CPUAffinity_OnChange); typedef HANDLE (WINAPI *p_GetCurrentProcess) (VOID); static p_GetCurrentProcess pfnGetCurrentProcess = NULL; diff --git a/src/win32/win_vid.c b/src/win32/win_vid.c index ecdd01674..ca79dbe7d 100644 --- a/src/win32/win_vid.c +++ b/src/win32/win_vid.c @@ -45,11 +45,12 @@ rendermode_t rendermode = render_soft; static void OnTop_OnChange(void); // synchronize page flipping with screen refresh static CV_PossibleValue_t CV_NeverOnOff[] = {{-1, "Never"}, {0, "Off"}, {1, "On"}, {0, NULL}}; -consvar_t cv_vidwait = {"vid_wait", "Off", CV_SAVE, CV_OnOff, OnTop_OnChange, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_stretch = {"stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; -static consvar_t cv_ontop = {"ontop", "Never", 0, CV_NeverOnOff, NULL, 0, NULL, NULL, 0, 0, NULL}; +consvar_t cv_vidwait = CVAR_INIT ("vid_wait", "On", CV_SAVE, CV_OnOff, OnTop_OnChange); +static consvar_t cv_stretch = CVAR_INIT ("stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL); +static consvar_t cv_ontop = CVAR_INIT ("ontop", "Never", 0, CV_NeverOnOff, NULL); boolean highcolor; +int vid_opengl_state = 0; static BOOL bDIBMode; // means we are using DIB instead of DirectDraw surfaces static LPBITMAPINFO bmiMain = NULL; @@ -228,6 +229,8 @@ void I_StartupGraphics(void) if (!dedicated) graphics_started = true; } +void VID_StartupOpenGL(void){} + // ------------------ // I_ShutdownGraphics // Close the screen, restore previous video mode. @@ -295,10 +298,9 @@ static inline boolean I_SkipFrame(void) case GS_LEVEL: if (!paused) return false; - /* FALLTHRU */ -#ifndef CLIENT_LOADINGSCREEN + /* FALLTHRU */ + //case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible case GS_WAITINGPLAYERS: -#endif return skip; // Skip odd frames default: return false; @@ -335,6 +337,13 @@ void I_FinishUpdate(void) if (I_SkipFrame()) return; + if (marathonmode) + SCR_DisplayMarathonInfo(); + + // draw captions if enabled + if (cv_closedcaptioning.value) + SCR_ClosedCaptions(); + // display a graph of ticrate if (cv_ticrate.value) SCR_DisplayTicRate(); @@ -856,6 +865,12 @@ INT32 VID_SetMode(INT32 modenum) return 1; } +void VID_CheckRenderer(void) {} +void VID_CheckGLLoaded(rendermode_t oldrender) +{ + (void)oldrender; +} + // ======================================================================== // Free the video buffer of the last video mode, // allocate a new buffer for the video mode to set. diff --git a/src/win32ce/GameX.h b/src/win32ce/GameX.h deleted file mode 100644 index 241fdd5be..000000000 --- a/src/win32ce/GameX.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - - GameX - WindowsCE Game Library for High Performance. - - Copyright (C) 1999 Hayes C. Haugen, all rights reserved. - - */ - -/* - * Need better way for host app to keep track of direct vs blit - drawing. Right now GetFBAddress() is the way to do it. - - - */ - - -#pragma once -#include // For VK codes. - -// Defines - -// display property flags - -const unsigned long kfDPGrey = 0x0001; -const unsigned long kfDPGrey2Bit = 0x0002; -const unsigned long kfDPGrey4Bit = 0x0004; -const unsigned long kfDPColor = 0x0008; -const unsigned long kfDPColor8Bit = 0x0010; -const unsigned long kfDPColor16Bit = 0x0020; -const unsigned long kfDPColor24Bit = 0x0040; -const unsigned long kfDPColor32Bit = 0x0080; -const unsigned long kfDPFormatNormal = 0x0100; // fb start is upper left, inc goes across -const unsigned long kfDPFormatRot270 = 0x0200; // fb start is lower left, inc goes up - -// Machine property flags - -const unsigned long kfMPPSPC = 0x0001; // Palm Sized PC - 240 x 320 -const unsigned long kfMPPSPC1 = 0x0002; // 1st gen pspc -const unsigned long kfMPPSPC2 = 0x0004; // Wyverns -const unsigned long kfMPHPC = 0x0008; // Handheld PC -const unsigned long kfMPHPC1 = 0x0010; // HPC 1, 480 x 240 -const unsigned long kfMPHPC2 = 0x0020; // HPC 2, 640 x 240 -const unsigned long kfMPHPC3 = 0x0040; // HPC Pro, 640 x 240, big keys -const unsigned long kfMPPro = 0x0080; // -const unsigned long kfMPAutoPC = 0x0100; -const unsigned long kfMPHasKeyboard = 0x0200; -const unsigned long kfMPHasMouse = 0x0400; -const unsigned long kfMPHasRumble = 0x0800; -const unsigned long kfMPHasTouch = 0x1000; - -// Rotations - -const int kiRotate0 = 0; // no rotation -const int kiRotate90 = 1; // 90 degrees clockwise -const int kiRotate180 = 2; // 180 degrees clockwise (upside down, Rotate 0 flipped) -const int kiRotate270 = 3; // 270 degrees clockwise (Rotate 1 flipped) - -class GameX { -public: - HWND SetButtonNotificationWindow(HWND hWnd); - GameX(); - ~GameX(); - - bool OpenGraphics(); - bool OpenSound(); - bool OpenButtons(HWND hwndButtonNotify); // Window that will get button messages or NULL if you just want to use GetAsyncKeyState(); - bool CloseGraphics(); - bool CloseSound(); - bool CloseButtons(); - - bool IsColor(); - bool IsPSPC(); - bool IsHPC(); - bool IsHPCPro(); - bool HasMouse(); - bool HasKeyboard(); // better than inferring from hpc/pspc/etc. - bool HasRumble(); - bool HasTouch(); // for completeness. At least 1 doesn't. - - int IsForeground(); - bool Suspend(); // release buttons, don't draw, etc. - bool Resume(); // regrab buttons, etc. - - bool BeginDraw(); - bool EndDraw(); - bool FindFrameBuffer(); - void * GetFBAddress(); // simple way to get things that makes code - long GetFBModulo(); // more readable. - long GetFBBpp(); - bool GetScreenRect(RECT * prc); - unsigned long GetDisplayProperties(); - - bool GetButton(int VK); // buttons init themselves on first button call?? - unsigned short GetDefaultButtonID(long id, long rotate); // gets the best button for use as specified by need and rotation - bool ReleaseButton(int VK); - bool BeginDetectButtons(); // grabs all buttons so user can indicate a button in a config dialog - bool EndDetectButtons(); // releases all buttons (except GetButton() ones) - - bool Rumble(); - bool Backlight(bool fOn); -private: -// LRESULT CALLBACK TaskBarWndProc(HWND hWnd, UINT message, WPARAM uParam, LPARAM lParam); - -private: - int m_iMP; // index into amp table for current machine. - void * m_pvFrameBuffer; - long m_cbFBModulo; // count of bytes to next line - unsigned long m_ffMachineProperties; - unsigned long m_ffDisplayProperties; - int m_cBitsPP; - - long m_dwPrevMode; // for Begin/EndDraw() - bool m_fActive; // true if active (resume), false if inactive (suspend). - - HWND m_hwndTaskbar; // Taskbar is official cap, change TaskBar's -}; - - -/* - -kmtCasioE10 -kmtCasioE11 -kmtCasioE15 -kmtCasioE55 -kmtCasioE100 -kmtLGPhenomII - -stuff for memory size and presence/absence of CF - -// Rotations that make sense for this device or default rotation: - -Rotate0 // no rotation -Rotate1 // 90 degrees clockwise -Rotate2 // 180 degrees clockwise (upside down, Rotate 0 flipped) -Rotate3 // 270 degrees clockwise (Rotate 1 flipped) - -kmtAccessNone // no direct framebuffer access -kmtAccess1 // write to fixed address -kmtAccess2 // find framebuffer memory aperture in GWES.EXE memory space. - -OriginUpperLeft -OriginUpperRight -OriginLowerRight -OriginLowerLeft - -MappedHorizontal // increasing fb address goes across screen -MappedVertical // increasing fb address goes up/down screen (Compaq) - -A machine entry: -=========================================== - machine kmtCasioE10, - type kmtPSPC | kmtPSPC1, - displaytype kmtGrey | kmtGrey2Bit | kmtAccess1, - pvFrameBuffer 0xAA000000, - cbFBModulo 1024 // count of bytes to next line - cbppFB 2, // bits per pixel - cxDisp 240, - cyDisp 320, - format OriginUpperLeft, MappedHorizontal - - rotate0 // for rotate mode 0, these are the best keys - vkUp VK_UP - vkDown VK_DOWN - vkLeft 0xC1 - vkRight 0xC2 - vkA 0xC3 - vkB 0 - rotate1 - vkUp 0xC1 - vkDown 0xC2 - vkLeft VK_DOWN - ... - ...*/ - diff --git a/src/win32ce/SRB2CE.zip b/src/win32ce/SRB2CE.zip deleted file mode 100644 index 3ac8530dc..000000000 Binary files a/src/win32ce/SRB2CE.zip and /dev/null differ diff --git a/src/win32ce/afxres.h b/src/win32ce/afxres.h deleted file mode 100644 index 7f5245404..000000000 --- a/src/win32ce/afxres.h +++ /dev/null @@ -1,17 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief needed if mfc not installed (if I remember well) diff --git a/src/win32ce/gapi_c.cpp b/src/win32ce/gapi_c.cpp deleted file mode 100644 index 60c7adfa2..000000000 --- a/src/win32ce/gapi_c.cpp +++ /dev/null @@ -1,129 +0,0 @@ -#include -#include - -#define _USE_GAPI_ - - -#ifndef _USE_GAPI_ - #include "GameX.h" - -struct GXDisplayProperties -{ - DWORD cxWidth; - DWORD cyHeight; - long cbxPitch; - long cbyPitch; - long cBPP; - DWORD ffFormat; -}; - -#define kfPalette 0x10 // Pixel values are indexes into a palette -#define kfDirect565 0x80 // 5 red bits, 6 green bits and 5 blue bits per pixel - - - GameX* gx = new GameX; -#else - #include "gx.h" -#endif - -extern "C" -{ - #include "gapi_c.h" -} - -extern "C" int GXOPENDISPLAY(HWND hWnd, DWORD dwFlags) -{ - #ifndef _USE_GAPI_ - if(!gx) - return 0; - - //gx->OpenSound(); - if(!gx->OpenGraphics()) - { - delete gx; - gx = 0; - return 0; - } - - return TRUE; - - #else - return GXOpenDisplay(hWnd,dwFlags); - #endif -} - -extern "C" int GXCLOSEDISPLAY() -{ - #ifndef _USE_GAPI_ - gx->CloseGraphics(); - return TRUE; - #else - return GXCloseDisplay(); - #endif -} - -extern "C" void * GXBEGINDRAW() -{ - #ifndef _USE_GAPI_ - if(gx->BeginDraw()) - return gx->GetFBAddress(); - - return NULL; - #else - return GXBeginDraw(); - #endif -} - -extern "C" int GXENDDRAW() -{ - #ifndef _USE_GAPI_ - return gx->EndDraw(); - #else - return GXEndDraw(); - #endif - -} - -extern "C" struct GXDisplayProperties GXGETDISPLAYPROPERTIES() -{ - #ifndef _USE_GAPI_ - RECT r; - GXDisplayProperties gxdp; - - gxdp.cbyPitch = gx->GetFBModulo(); - gxdp.cBPP = gx->GetFBBpp(); - gxdp.cbxPitch = (gxdp.cBPP >> 3); - - gx->GetScreenRect(&r); - gxdp.cxWidth = (r.right - r.left); - gxdp.cyHeight = (r.bottom - r.top); - - if(gxdp.cBPP = 16) - gxdp.ffFormat = kfDirect565; - else if(gxdp.cBPP = 8) - gxdp.ffFormat = kfPalette; - - return gxdp; - - #else - return GXGetDisplayProperties(); - #endif -} - -extern "C" int GXSUSPEND() -{ - #ifndef _USE_GAPI_ - return gx->Suspend(); - #else - return GXSuspend(); - #endif -} - -extern "C" int GXRESUME() -{ - #ifndef _USE_GAPI_ - return gx->Resume(); - #else - return GXResume(); - #endif -} \ No newline at end of file diff --git a/src/win32ce/gapi_c.h b/src/win32ce/gapi_c.h deleted file mode 100644 index 40e7799ff..000000000 --- a/src/win32ce/gapi_c.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef GAPI_H -#define GAPI_H - -int GXOPENDISPLAY(HWND hWnd, DWORD dwFlags); -int GXCLOSEDISPLAY(); -void * GXBEGINDRAW(); -int GXENDDRAW(); -struct GXDisplayProperties GXGETDISPLAYPROPERTIES(); -int GXSUSPEND(); -int GXRESUME(); - -#endif \ No newline at end of file diff --git a/src/win32ce/gxgapilib.c b/src/win32ce/gxgapilib.c deleted file mode 100644 index 8ff57092d..000000000 --- a/src/win32ce/gxgapilib.c +++ /dev/null @@ -1,636 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -// -//----------------------------------------------------------------------------- -/// \file -/// \brief Zak Larue-Buckley's GX and GAPI library v1.0 - -#include "../doomdef.h" -//#define WIN32_LEAN_AND_MEAN -#define RPC_NO_WINDOWS_H -#include -#include -#include "../i_system.h" -#include "dx_error.h" - -#include "fabdxlib.h" - -#define NT4COMPAT //always defined, always compatible - - -// globals - -IDirectDraw2* DDr2 = NULL; -IDirectDrawSurface* ScreenReal = NULL; // DirectDraw primary surface -IDirectDrawSurface* ScreenVirtual = NULL; // DirectDraw back surface -IDirectDrawPalette* DDPalette = NULL; // The primary surface palette -static IDirectDrawClipper *windclip = NULL; // clipper for windowed mode - -BOOL bAppFullScreen; // true for fullscreen exclusive mode, - -int windowPosX = 0; // current position in windowed mode -int windowPosY = 0; - -int ScreenWidth; -int ScreenHeight; -BOOL ScreenLocked; // Screen surface is being locked -int ScreenPitch; // offset from one line to the next -LPBYTE ScreenPtr; // memory of the surface - - -// -// CreateNewSurface -// -static inline IDirectDrawSurface* CreateNewSurface(int dwWidth, - int dwHeight, - int dwSurfaceCaps) -{ - DDSURFACEDESC ddsd; - HRESULT hr; - LPDIRECTDRAWSURFACE psurf; - - ZeroMemory(&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH; - - ddsd.ddsCaps.dwCaps = dwSurfaceCaps; - - ddsd.dwHeight = dwHeight; - ddsd.dwWidth = dwWidth; - - hr = IDirectDraw2_CreateSurface (DDr2, &ddsd, &psurf, NULL); - - if (hr == DD_OK) - { - //DDCOLORKEY ddck; - IDirectDrawSurface_Restore(psurf); - - //hr = IDirectDrawSurface_GetColorKey(DDCKEY_SRCBLT, &ddck); - //psurf->SetColorKey(DDCKEY_SRCBLT, &ddck); - } - else - psurf = NULL; - - return psurf; -} - -// -// wow! from 320x200x8 up to 1600x1200x32 thanks Banshee! :) -// -static HRESULT WINAPI myEnumModesCallback (LPDDSURFACEDESC surf, LPVOID lpContext) -{ - APPENUMMODESCALLBACK pfnContext = lpContext; - - if (pfnContext) pfnContext(surf->dwWidth, - surf->dwHeight,surf->ddpfPixelFormat. -#ifdef DUMMYUNIONNAMEN - DUMMYUNIONNAMEN(1). -#endif - dwRGBBitCount - ); - - /*CONS_Printf ("%dx%dx%d bpp %d refresh\n", - surf->dwWidth, - surf->dwHeight, - surf->ddpfPixelFormat.dwRGBBitCount, - surf->dwRefreshRate);*/ - - return DDENUMRET_OK; -} - - -// -// Application call here to enumerate display modes -// -BOOL EnumDirectDrawDisplayModes (APPENUMMODESCALLBACK appFunc) -{ - LPVOID lpappFunc = appFunc; - - if (DDr2 == NULL) - return FALSE; - - // enumerate display modes - // Carl: DirectX 3.x apparently does not support VGA modes. Who cares. :) - // faB: removed DDEDM_REFRESHRATES, detects too many modes, plus we don't care of refresh rate. - if (bDX0300) - IDirectDraw2_EnumDisplayModes (DDr2, 0 /*| DDEDM_REFRESHRATES*/, - NULL, lpappFunc, myEnumModesCallback); - else - IDirectDraw2_EnumDisplayModes (DDr2, DDEDM_STANDARDVGAMODES /*| DDEDM_REFRESHRATES*/, - NULL, lpappFunc, myEnumModesCallback); - return TRUE; -} - - -// -// Create the DirectDraw object for later -// -BOOL CreateDirectDrawInstance (VOID) -{ - HRESULT hr; - IDirectDraw* DDr; - IDirectDraw** rp = &DDr; - IDirectDraw2** rp2 = &DDr2; - LPVOID *tp = (LPVOID *)rp2; - - // - // create an instance of DirectDraw object - // - if (FAILED(hr = DirectDrawCreate(NULL, rp, NULL))) - I_Error("DirectDrawCreate FAILED: %s", DXErrorToString(hr)); - - // change interface to IDirectDraw2 - if (FAILED(hr = IDirectDraw_QueryInterface (DDr, &IID_IDirectDraw2, tp))) - I_Error("Failed to query DirectDraw2 interface: %s", DXErrorToString(hr)); - - // release the interface we don't need - IDirectDraw_Release (DDr); - return TRUE; -} - - -// -// - returns true if DirectDraw was initialized properly -// -int InitDirectDrawe (HWND appWin, int width, int height, int bpp, int fullScr) -{ - DDSURFACEDESC ddsd; // DirectDraw surface description for allocating - DDSCAPS ddscaps; - HRESULT ddrval; - - DWORD dwStyle; - RECT rect; - - // enumerate directdraw devices - //if (FAILED(DirectDrawEnumerate (myEnumDDDevicesCallback, NULL))) - // I_Error("Error with DirectDrawEnumerate"); - - if (!DDr2) - CreateDirectDrawInstance(); - - // remember what screen mode we are in - bAppFullScreen = fullScr; - ScreenHeight = height; - ScreenWidth = width; - - if (bAppFullScreen) - { - // Change window attributes - dwStyle = WS_POPUP | WS_VISIBLE; - SetWindowLong (appWin, GWL_STYLE, dwStyle); - SetWindowPos(appWin, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE | - SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER); - - // Get exclusive mode - ddrval = IDirectDraw2_SetCooperativeLevel(DDr2, appWin, DDSCL_EXCLUSIVE | - DDSCL_FULLSCREEN | - DDSCL_ALLOWREBOOT); - if (ddrval != DD_OK) - I_Error("SetCooperativeLevel FAILED: %s\n", DXErrorToString(ddrval)); - - // Switch from windows desktop to fullscreen - -#ifdef NT4COMPAT - ddrval = IDirectDraw2_SetDisplayMode(DDr2, width, height, bpp, 0, 0); -#else - ddrval = IDirectDraw2_SetDisplayMode(DDr2, width, height, bpp, 0, DDSDM_STANDARDVGAMODE); -#endif - if (ddrval != DD_OK) - I_Error("SetDisplayMode FAILED: %s\n", DXErrorToString(ddrval)); - - // This is not really needed, except in certain cases. One case - // is while using MFC. When the desktop is initally at 16bpp, a mode - // switch to 8bpp somehow causes the MFC window to not fully initialize - // and a CreateSurface will fail with DDERR_NOEXCLUSIVEMODE. This will - // ensure that the window is initialized properly after a mode switch. - - ShowWindow(appWin, SW_SHOW); - - // Create the primary surface with 1 back buffer. Always zero the - // DDSURFACEDESC structure and set the dwSize member! - - ZeroMemory(&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; - - // for fullscreen we use page flipping, for windowed mode, we blit the hidden surface to - // the visible surface, in both cases we have a visible (or 'real') surface, and a hidden - // (or 'virtual', or 'backbuffer') surface. - ddsd.dwBackBufferCount = 1; - - ddrval = IDirectDraw2_CreateSurface(DDr2,&ddsd, &ScreenReal, NULL); - if (ddrval != DD_OK) - I_Error("CreateSurface Primary Screen FAILED"); - - // Get a pointer to the back buffer - - ddscaps.dwCaps = DDSCAPS_BACKBUFFER; - ddrval = IDirectDrawSurface_GetAttachedSurface(ScreenReal,&ddscaps, &ScreenVirtual); - if (ddrval != DD_OK) - I_Error("GetAttachedSurface FAILED"); - } - else - { - rect.top = 0; - rect.left = 0; - rect.bottom = height-1; - rect.right = width-1; - - // Change window attributes - - dwStyle = GetWindowStyle(appWin); - dwStyle &= ~WS_POPUP; - dwStyle |= WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION; - - SetWindowLong(appWin, GWL_STYLE, dwStyle); - - // Resize the window so that the client area is the requested width/height - - AdjustWindowRectEx(&rect, GetWindowStyle(appWin), GetMenu(appWin) != NULL, - GetWindowExStyle(appWin)); - - // Just in case the window was moved off the visible area of the - // screen. - - SetWindowPos(appWin, NULL, 0, 0, rect.right-rect.left, - rect.bottom-rect.top, SWP_NOMOVE | SWP_NOZORDER | - SWP_NOACTIVATE); - - SetWindowPos(appWin, HWND_NOTOPMOST, 0, 0, 0, 0, - SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); - - // Exclusive mode is normal since it's in windowed mode and needs - // to cooperate with GDI - - ddrval = IDirectDraw2_SetCooperativeLevel(DDr2,appWin, DDSCL_NORMAL); - if (ddrval != DD_OK) - I_Error("SetCooperativeLevel FAILED"); - - // Always zero the DDSURFACEDESC structure and set the dwSize member! - - ZeroMemory(&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - ddsd.dwFlags = DDSD_CAPS; - ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; - - // Create the primary surface - - ddrval = IDirectDraw2_CreateSurface(DDr2,&ddsd, &ScreenReal, NULL); - if (ddrval != DD_OK) - I_Error("CreateSurface Primary Screen FAILED"); - - // Create a back buffer for offscreen rendering, this will be used to - // blt to the primary - - ScreenVirtual = CreateNewSurface(width, height, DDSCAPS_OFFSCREENPLAIN | - DDSCAPS_SYSTEMMEMORY); - if (ScreenVirtual == NULL) - I_Error("CreateSurface Secondary Screen FAILED"); - - /// \todo get the desktop bit depth, and build a lookup table - /// for quick conversions of 8bit color indexes 0-255 to desktop colors - /// eg: 256 entries of equivalent of palette colors 0-255 in 15,16,24,32 bit format - /// when blit virtual to real, convert pixels through lookup table.. - - // Use a clipper object for clipping when in windowed mode - // (make sure our drawing doesn't affect other windows) - - ddrval = IDirectDraw2_CreateClipper (DDr2, 0, &windclip, 0); - if (ddrval != DD_OK) - I_Error("CreateClipper FAILED"); - - // Associate the clipper with the window. - ddrval = IDirectDrawClipper_SetHWnd (windclip,0, appWin); - if (ddrval != DD_OK) - I_Error("Clipper -> SetHWnd FAILED"); - - // Attach the clipper to the surface. - ddrval = IDirectDrawSurface_SetClipper (ScreenReal,windclip); - if (ddrval != DD_OK) - I_Error("PrimaryScreen -> SetClipperClipper FAILED"); - } - - return TRUE; -} - - -// -// Free all memory -// -VOID CloseDirectDraw (VOID) -{ - ReleaseChtuff(); - if (DDr2) - { - IDirectDraw2_Release(DDr2); - DDr2 = NULL; - } -} - - -// -// Release DirectDraw stuff before display mode change -// -VOID ReleaseChtuff (VOID) -{ - if (!DDr2) - return; - if (windclip) - { - IDirectDrawClipper_Release(windclip); - windclip = NULL; - } - if (DDPalette) - { - IDirectDrawPalette_Release(DDPalette); - DDPalette = NULL; - } - // If the app is fullscreen, the back buffer is attached to the - // primary. Releasing the primary buffer will also release any - // attached buffers, so explicitly releasing the back buffer is not - // necessary. - - if (!bAppFullScreen && ScreenVirtual) - { - IDirectDrawSurface_Release(ScreenVirtual); // release hidden surface - ScreenVirtual = NULL; - } - if (ScreenReal) - { - IDirectDrawSurface_Release(ScreenReal); // and attached backbuffers for bAppFullScreen mode - ScreenReal = NULL; - } -} - - -// -// Clear the surface to color -// -VOID ClearSurface(IDirectDrawSurface* surface, int color) -{ - DDBLTFX ddbltfx; - - // Use the blter to do a color fill to clear the back buffer - ddbltfx.dwSize = sizeof (ddbltfx); - ddbltfx. -#ifdef DUMMYUNIONNAMEN - DUMMYUNIONNAMEN(5). -#endif - dwFillColor = color; - IDirectDrawSurface_Blt(surface,NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx); - -} - -// -// Flip the real page with virtual page -// - in bAppFullScreen mode, do page flipping -// - in windowed mode, copy the hidden surface to the visible surface -// -// waitflip : if not 0, wait for page flip to end -BOOL ScreenFlip(int waitflip) -{ - HRESULT hr; - RECT rect; - - waitflip = 0; - if (bAppFullScreen) - { - //hr = IDirectDrawSurface_GetFlipStatus (ScreenReal, DDGFS_); - - // In full-screen exclusive mode, do a hardware flip. - hr = IDirectDrawSurface_Flip(ScreenReal, NULL, DDFLIP_WAIT); //return immediately - - // If the surface was lost, restore it. - if (hr == DDERR_SURFACELOST) - { - IDirectDrawSurface_Restore(ScreenReal); - - // The restore worked, so try the flip again. - hr = IDirectDrawSurface_Flip(ScreenReal, 0, DDFLIP_WAIT); - } - } - else - { - rect.left = windowPosX; - rect.top = windowPosY; - rect.right = windowPosX + ScreenWidth - 1; - rect.bottom = windowPosY + ScreenHeight - 1; - - // Copy the back buffer to front. - hr = IDirectDrawSurface_Blt(ScreenReal, &rect, ScreenVirtual, 0, DDBLT_WAIT, 0); - - if (hr != DD_OK) - { - // If the surfaces were lost, restore them. - if (IDirectDrawSurface_IsLost(ScreenReal) == DDERR_SURFACELOST) - IDirectDrawSurface_Restore(ScreenReal); - - if (IDirectDrawSurface_IsLost(ScreenVirtual) == DDERR_SURFACELOST) - IDirectDrawSurface_Restore(ScreenVirtual); - - // Retry the copy. - hr = IDirectDrawSurface_Blt(ScreenReal,&rect, ScreenVirtual, 0, DDBLT_WAIT, 0); - } - } - - if (hr != DD_OK) - I_Error("ScreenFlip() : couldn't Flip surfaces"); - - return FALSE; -} - -// -// Print a text to the surface -// -VOID TextPrint(int x, int y, LPCSTR message) -{ - HRESULT hr; - HDC hdc = NULL; - - // Get the device context handle. - hr = IDirectDrawSurface_GetDC(ScreenVirtual,&hdc); - if (hr != DD_OK) - return; - - // Write the message. - SetBkMode(hdc, TRANSPARENT); - SetTextColor(hdc, RGB(255, 255, 255)); - TextOutA(hdc, x, y, message, (int)strlen(message)); - - // Release the device context. - hr = IDirectDrawSurface_ReleaseDC(ScreenVirtual,hdc); -} - -// -// Lock surface before multiple drawings by hand, for speed -// -boolean LockScreen(VOID) -{ - DDSURFACEDESC ddsd; - HRESULT ddrval; - - ZeroMemory(&ddsd, sizeof (ddsd)); - ddsd.dwSize = sizeof (ddsd); - - // attempt to Lock the surface - ddrval = IDirectDrawSurface_Lock(ScreenVirtual, NULL, &ddsd, DDLOCK_WAIT, NULL); - - // Always, always check for errors with DirectX! - // If the surface was lost, restore it. - if (ddrval == DDERR_SURFACELOST) - { - ddrval = IDirectDrawSurface_Restore(ScreenReal); - - // now retry to get the lock - ddrval = IDirectDrawSurface_Lock(ScreenVirtual, NULL, &ddsd, DDLOCK_WAIT, NULL); - } - - if (ddrval == DD_OK) - { - ScreenLocked = TRUE; - ScreenPtr = (LPBYTE)ddsd.lpSurface; - ScreenPitch = ddsd. -#ifdef DUMMYUNIONNAMEN - DUMMYUNIONNAMEN(1). -#endif - lPitch; - } - else - { - ScreenLocked = FALSE; - ScreenPtr = NULL; - ScreenPitch = 0; - //I_Error("LockScreen() : couldn't restore the surface."); - return false; - } - return true; -} - -// -// Unlock surface -// -VOID UnlockScreen(VOID) -{ - if (DD_OK != IDirectDrawSurface_Unlock(ScreenVirtual,NULL)) - I_Error("Couldn't UnLock the renderer!"); - - ScreenLocked = FALSE; - ScreenPtr = NULL; - ScreenPitch = 0; -} - -// Blit virtual screen to real screen -//faB: note: testing 14/03/1999, see if it is faster than memcopy of virtual to -/* -static LPDIRECTDRAWSURFACE lpDDS = NULL; -VOID BlitScreen(VOID) -{ - HRESULT hr; - - if (!lpDDS) - I_Error("lpDDS NULL"); - - hr = IDirectDrawSurface_BltFast(ScreenVirtual, - 0, 0, // Upper left xy of destination - lpDDS, // Source surface - NULL, // Source rectangle = entire surface - DDBLTFAST_WAIT | DDBLTFAST_NOCOLORKEY); - if (FAILED(hr)) - I_Error("BltFast FAILED"); -} - -VOID MakeScreen(int width, int height, BYTE* lpSurface) -{ - HRESULT hr; - DDSURFACEDESC ddsd; - - // Initialize the surface description. - ZeroMemory (&ddsd, sizeof ddsd); - ZeroMemory (&ddsd.ddpfPixelFormat, sizeof (DDPIXELFORMAT)); - ddsd.dwSize = sizeof ddsd; - ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | //DDSD_LPSURFACE | - DDSD_PITCH | DDSD_PIXELFORMAT | DDSD_CAPS; - ddsd.dwWidth = width; - ddsd.dwHeight= height; - ddsd.lPitch = width; - ddsd.lpSurface = lpSurface; - ddsd.ddsCaps.dwCaps = DDSCAPS_SYSTEMMEMORY | DDSCAPS_OFFSCREENPLAIN; - - // Set up the pixel format for 8-bit - ddsd.ddpfPixelFormat.dwSize = sizeof (DDPIXELFORMAT); - ddsd.ddpfPixelFormat.dwFlags= DDPF_RGB | DDPF_PALETTEINDEXED8; - ddsd.ddpfPixelFormat.dwRGBBitCount = 8; - - // - ddsd.ddpfPixelFormat.dwRGBBitCount = (DWORD)DEPTH*8; - ddsd.ddpfPixelFormat.dwRBitMask = 0x00FF0000; - ddsd.ddpfPixelFormat.dwGBitMask = 0x0000FF00; - ddsd.ddpfPixelFormat.dwBBitMask = 0x000000FF; - - // Create the surface - hr = IDirectDraw2_CreateSurface(DDr2, &ddsd, &lpDDS, NULL); - if (FAILED(hr)) - I_Error("MakeScreen FAILED: %s",DDError(hr)); - //ddsd.lpSurface = lpSurface; -} -*/ - -// -// Create a palette object -// -VOID CreateDDPalette (PALETTEENTRY* colorTable) -{ - HRESULT ddrval; - ddrval = IDirectDraw2_CreatePalette(DDr2,DDPCAPS_8BIT|DDPCAPS_ALLOW256, colorTable, &DDPalette, NULL); - if (ddrval != DD_OK) - I_Error("couldn't CreatePalette"); -}; - - -// -// Free the palette object -// -VOID DestroyDDPalette (VOID) -{ - if (DDPalette) - { - IDirectDrawPalette_Release(DDPalette); - DDPalette = NULL; - } -} - -// -// Set a a full palette of 256 PALETTEENTRY entries -// -VOID SetDDPalette(PALETTEENTRY* pal) -{ - // create palette first time - if (DDPalette == NULL) - CreateDDPalette(pal); - else - IDirectDrawPalette_SetEntries(DDPalette, 0, 0, 256, pal); - // setting the same palette to the same surface again does not increase - // the reference count - IDirectDrawSurface_SetPalette(ScreenReal, DDPalette); -} - -// -// Wait for vsync, gross -// -VOID WaitVbl(VOID) -{ - IDirectDraw2_WaitForVerticalBlank(DDr2, DDWAITVB_BLOCKBEGIN, NULL); -} diff --git a/src/win32ce/gxgapilib.h b/src/win32ce/gxgapilib.h deleted file mode 100644 index 189cc15b8..000000000 --- a/src/win32ce/gxgapilib.h +++ /dev/null @@ -1,81 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Zak Larue-Buckley's GX and GAPI library v1.0 - -#ifndef _H_GXGAPILIB_ -#define _H_GXGAPILIB_ - -//#define WIN32_LEAN_AND_MEAN -#define RPC_NO_WINDOWS_H -#include -#ifdef __MINGW32__ -//#define NONAMELESSUNION -#endif -#ifdef _MSC_VER -#pragma warning(disable : 4201) -#endif -#include -#if (defined (DIRECTDRAW_VERSION) && (DIRECTDRAW_VERSION >= 0x0700)) -#undef DUMMYUNIONNAMEN -#endif -// format of function in app called with width,height -typedef BOOL (*APPENUMMODESCALLBACK)(int width, int height, int bpp); - - -// globals -extern IDirectDraw2* DDr2; -extern IDirectDrawSurface* ScreenReal; -extern IDirectDrawSurface* ScreenVirtual; -extern IDirectDrawPalette* DDPalette; - -extern BOOL bAppFullScreen; // main code might need this to know the current - // fullscreen or windowed state - -extern int windowPosX; // current position in windowed mode -extern int windowPosY; - -extern int ScreenWidth; -extern int ScreenHeight; -extern BOOL ScreenLocked; // Screen surface is being locked -extern int ScreenPitch; // offset from one line to the next -extern LPBYTE ScreenPtr; // memory of the surface - -extern BOOL bDX0300; - -BOOL EnumDirectDrawDisplayModes (APPENUMMODESCALLBACK appFunc); -BOOL CreateDirectDrawInstance (VOID); - -int InitDirectDrawe (HWND appWin, int width, int height, int bpp, int fullScr); -VOID CloseDirectDraw (VOID); - -VOID ReleaseChtuff (VOID); - -VOID ClearSurface (IDirectDrawSurface* surface, int color); -BOOL ScreenFlip (int wait); -VOID TextPrint (int x, int y, LPCSTR message); - -VOID CreateDDPalette (PALETTEENTRY* colorTable); -VOID DestroyDDPalette (VOID); -VOID SetDDPalette (PALETTEENTRY* pal); - -VOID WaitVbl (VOID); - -boolean LockScreen (VOID); -VOID UnlockScreen (VOID); - - -#endif /* _H_FABDXLIB_ */ diff --git a/src/win32ce/midstuff.h b/src/win32ce/midstuff.h deleted file mode 100644 index 08ee80add..000000000 --- a/src/win32ce/midstuff.h +++ /dev/null @@ -1,150 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief MIDI structures and definitions -/// used by the MSTREAM sample application in -/// converting a MID file to a MIDI stream for -/// playback using the midiStream API. -/// Inpired by DirectX5 SDK examples - -#ifndef __MIDSTUFF_H__ -#define __MIDSTUFF_H__ - -// MIDI file constants -// -#define MThd 0x6468544D // Start of file -#define MTrk 0x6B72544D // Start of track - -#define MIDI_SYSEX ((BYTE)0xF0) // SysEx begin -#define MIDI_SYSEXEND ((BYTE)0xF7) // SysEx begin -#define MIDI_META ((BYTE)0xFF) // Meta event begin -#define MIDI_META_TEMPO ((BYTE)0x51) // Tempo change -#define MIDI_META_EOT ((BYTE)0x2F) // End-of-track - -#define MIDI_NOTEOFF ((BYTE)0x80) // + note + velocity -#define MIDI_NOTEON ((BYTE)0x90) // + note + velocity -#define MIDI_POLYPRESS ((BYTE)0xA0) // + pressure (2 bytes) -#define MIDI_CTRLCHANGE ((BYTE)0xB0) // + ctrlr + value -#define MIDI_PRGMCHANGE ((BYTE)0xC0) // + new patch -#define MIDI_CHANPRESS ((BYTE)0xD0) // + pressure (1 byte) -#define MIDI_PITCHBEND ((BYTE)0xE0) // + pitch bend (2 bytes) - -#define NUM_CHANNELS 16 - -#define MIDICTRL_VOLUME ((BYTE)0x07) -#define MIDICTRL_VOLUME_LSB ((BYTE)0x27) -#define MIDICTRL_PAN ((BYTE)0x0A) - -#define MIDIEVENT_CHANNEL(dw) (dw & 0x0000000F) -#define MIDIEVENT_TYPE(dw) (dw & 0x000000F0) -#define MIDIEVENT_DATA1(dw) ((dw & 0x0000FF00) >> 8) -#define MIDIEVENT_VOLUME(dw) ((dw & 0x007F0000) >> 16) - -// Macros for swapping hi/lo-endian data -// -#define WORDSWAP(w) (((w) >> 8) | \ - (((w) << 8) & 0xFF00)) - -#define DWORDSWAP(dw) (((dw) >> 24) | \ - (((dw) >> 8) & 0x0000FF00) | \ - (((dw) << 8) & 0x00FF0000) | \ - (((dw) << 24) & 0xFF000000)) - -// In debug builds, TRACKERR will show us where the parser died -// -//#define TRACKERR(p,sz) ShowTrackError(p,sz); -#define TRACKERR(p,sz) - - -// Make a little distinction here so the various structure members are a bit -// more clearly labelled -- we have offsets and byte counts to keep track of -// that deal with both in-memory buffers and the file on disk - -#define FILEOFF DWORD - - -// These structures are stored in MIDI files; they need to be byte aligned. -// -#if defined(_MSC_VER) -#pragma pack(1) -#endif - -// Chunk header. dwTag is either MTrk or MThd. -// -typedef struct -{ - DWORD dwTag; // Type - DWORD dwChunkLength; // Length (hi-lo) -} ATTRPACK MIDICHUNK; - -// Contents of MThd chunk. -typedef struct -{ - WORD wFormat; // Format (hi-lo) - WORD wTrackCount; // # tracks (hi-lo) - WORD wTimeDivision; // Time division (hi-lo) -} ATTRPACK MIDIFILEHDR; - -#if defined(_MSC_VER) -#pragma pack() // End of need for byte-aligned structures -#endif - - -// Temporary event structure which stores event data until we're ready to -// dump it into a stream buffer -// -typedef struct -{ - DWORD tkEvent; // Absolute time of event - BYTE byShortData[4]; // Event type and parameters if channel msg - DWORD dwEventLength; // Length of data which follows if meta or sysex - LPBYTE pLongData; // -> Event data if applicable -} TEMPEVENT, *PTEMPEVENT; - -#define ITS_F_ENDOFTRK 0x00000001 - -// Description of a track open for read -// -typedef struct -{ - DWORD fdwTrack; // Track status - DWORD dwTrackLength; // Total bytes in track - DWORD dwLeftInBuffer; // Bytes left unread in track buffer - LPBYTE pTrackStart; // -> start of track data buffer - LPBYTE pTrackCurrent; // -> next byte to read in buffer - DWORD tkNextEventDue; // Absolute time of next event in track - BYTE byRunningStatus;// Running status from last channel msg - - FILEOFF foTrackStart; // Start of track -- used for walking the file - FILEOFF foNextReadStart;// File offset of next read from disk - DWORD dwLeftOnDisk; // Bytes left unread on disk -#ifdef DEBUG - DWORD nTrack; // # of this track for debugging -#endif -} INTRACKSTATE, *PINTRACKSTATE; - -// Description of the input MIDI file -// -typedef struct -{ - DWORD cbFileLength; // Total bytes in file - DWORD dwTimeDivision; // Original time division - DWORD dwFormat; // Original format - DWORD dwTrackCount; // Track count (specifies pitsTracks size) - INTRACKSTATE *pitsTracks; // -> array of tracks in this file -} INFILESTATE, *PINFILESTATE; - -#endif //__MIDSTUFF_H__ diff --git a/src/win32ce/resource.h b/src/win32ce/resource.h deleted file mode 100644 index a712f14d6..000000000 --- a/src/win32ce/resource.h +++ /dev/null @@ -1,18 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by Srb2win.rc -// -#define IDI_DLICON1 101 -#define IDC_DLCURSOR1 103 -#define IDI_ICON1 106 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 114 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1000 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/src/win32ce/win_cd.c b/src/win32ce/win_cd.c deleted file mode 100644 index 940f59ff2..000000000 --- a/src/win32ce/win_cd.c +++ /dev/null @@ -1,529 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief cd music interface (uses MCI). - -#include "../doomdef.h" -#include "win_main.h" -#include - -#include "../command.h" -#include "../doomtype.h" -#include "../i_sound.h" -#include "../i_system.h" - -#include "../s_sound.h" - -#define MAX_CD_TRACKS 255 - -typedef struct { - BOOL IsAudio; - DWORD Start, End; - DWORD Length; // minutes -} CDTrack; - -// ------- -// private -// ------- -static CDTrack m_nTracks[MAX_CD_TRACKS]; -static int m_nTracksCount; // up to MAX_CD_TRACKS -static MCI_STATUS_PARMS m_MCIStatus; -static MCI_OPEN_PARMS m_MCIOpen; - -// ------ -// protos -// ------ -static void Command_Cd_f (void); - - -// ------------------- -// MCIErrorMessageBox -// Retrieve error message corresponding to return value from -// mciSendCommand() or mciSenString() -// ------------------- -static VOID MCIErrorMessageBox (MCIERROR iErrorCode) -{ - char szErrorText[128]; - if (!mciGetErrorStringA (iErrorCode, szErrorText, sizeof (szErrorText))) - wsprintfA(szErrorText,"MCI CD Audio Unknow Error #%d\n", iErrorCode); - CONS_Printf (szErrorText); - /*MessageBox (GetActiveWindow(), szTemp+1, "LEGACY", - MB_OK | MB_ICONSTOP);*/ -} - - -// -------- -// CD_Reset -// -------- -static void CD_Reset (void) -{ - // no win32 equivalent - //faB: for DOS, some odd drivers like to be reset sometimes.. useless in MCI I guess -} - - -// ---------------- -// CD_ReadTrackInfo -// Read in number of tracks, and length of each track in minutes/seconds -// returns true if error -// ---------------- -static BOOL CD_ReadTrackInfo (void) -{ - int i; - int nTrackLength; - MCIERROR iErr; - - m_nTracksCount = 0; - - m_MCIStatus.dwItem = MCI_STATUS_NUMBER_OF_TRACKS; - iErr = mciSendCommand(m_MCIOpen.wDeviceID, MCI_STATUS, MCI_STATUS_ITEM|MCI_WAIT, (DWORD_PTR)&m_MCIStatus); - if (iErr) - { - MCIErrorMessageBox (iErr); - return FALSE; - } - m_nTracksCount = (int)m_MCIStatus.dwReturn; - if (m_nTracksCount > MAX_CD_TRACKS) - m_nTracksCount = MAX_CD_TRACKS; - - for (i = 0; i < m_nTracksCount; i++) - { - m_MCIStatus.dwTrack = (DWORD)(i+1); - m_MCIStatus.dwItem = MCI_STATUS_LENGTH; - iErr = mciSendCommand(m_MCIOpen.wDeviceID, MCI_STATUS, MCI_TRACK|MCI_STATUS_ITEM|MCI_WAIT, (DWORD_PTR)&m_MCIStatus); - if (iErr) - { - MCIErrorMessageBox (iErr); - return FALSE; - } - nTrackLength = (DWORD)(MCI_MSF_MINUTE(m_MCIStatus.dwReturn)*60 + MCI_MSF_SECOND(m_MCIStatus.dwReturn)); - m_nTracks[i].Length = nTrackLength; - - m_MCIStatus.dwItem = MCI_CDA_STATUS_TYPE_TRACK; - iErr = mciSendCommand(m_MCIOpen.wDeviceID, MCI_STATUS, MCI_TRACK|MCI_STATUS_ITEM|MCI_WAIT, (DWORD_PTR)&m_MCIStatus); - if (iErr) - { - MCIErrorMessageBox (iErr); - return FALSE; - } - m_nTracks[i].IsAudio = (m_MCIStatus.dwReturn == MCI_CDA_TRACK_AUDIO); - } - - return TRUE; -} - - -// ------------ -// CD_TotalTime -// returns total time for all audio tracks in seconds -// ------------ -static int CD_TotalTime (void) -{ - int nTotalLength = 0; - int nTrack; - for (nTrack = 0; nTrack < m_nTracksCount; nTrack++) - { - if (m_nTracks[nTrack].IsAudio) - nTotalLength = nTotalLength + m_nTracks[nTrack].Length; - } - return nTotalLength; -} - - -//====================================================================== -// CD AUDIO MUSIC SUBSYSTEM -//====================================================================== - -UINT8 cdaudio_started = 0; // for system startup/shutdown - -static boolean cdPlaying = false; -static int cdPlayTrack; // when cdPlaying is true -static boolean cdLooping = false; -static UINT8 cdRemap[MAX_CD_TRACKS]; -static boolean cdEnabled = true; // cd info available -static boolean cdValid; // true when last cd audio info was ok -static boolean wasPlaying; -//static int cdVolume = 0; // current cd volume (0-31) - -// 0-31 like Music & Sfx, though CD hardware volume is 0-255. -consvar_t cd_volume = {"cd_volume","18",CV_SAVE,soundvolume_cons_t, NULL, 0, NULL, NULL, 0, 0, NULL}; - -// allow Update for next/loop track -// some crap cd drivers take up to -// a second for a simple 'busy' check.. -// (on those Update can be disabled) -consvar_t cdUpdate = {"cd_update","1",CV_SAVE, NULL, NULL, 0, NULL, NULL, 0, 0, NULL}; - -// hour,minutes,seconds -static char *hms(int seconds) -{ - int hours, minutes; - static char s[9]; - - minutes = seconds / 60; - seconds %= 60; - hours = minutes / 60; - minutes %= 60; - if (hours > 0) - sprintf (s, "%d:%02d:%02d", hours, minutes, seconds); - else - sprintf (s, "%2d:%02d", minutes, seconds); - return s; -} - -static void Command_Cd_f (void) -{ - LPCSTR s; - int i,j; - - if (!cdaudio_started) - return; - - if (COM_Argc()<2) - { - CONS_Printf ("cd [on] [off] [remap] [reset] [open]\n" - " [info] [play ] [loop ]\n" - " [stop] [resume]\n"); - return; - } - - s = COM_Argv(1); - - // activate cd music - if (!strncmp(s,"on",2)) - { - cdEnabled = true; - return; - } - - // stop/deactivate cd music - if (!strncmp(s,"off",3)) - { - if (cdPlaying) - I_StopCD (); - cdEnabled = false; - return; - } - - // remap tracks - if (!strncmp(s,"remap",5)) - { - i = (int)COM_Argc() - 2; - if (i <= 0) - { - CONS_Printf ("CD tracks remapped in that order :\n"); - for (j = 1; j < MAX_CD_TRACKS; j++) - if (cdRemap[j] != j) - CONS_Printf (" %2d -> %2d\n", j, cdRemap[j]); - return; - } - for (j = 1; j <= i; j++) - cdRemap[j] = (UINT8)atoi (COM_Argv (j+1)); - return; - } - - // reset the CD driver, useful on some odd cd's - if (!strncmp(s,"reset",5)) - { - cdEnabled = true; - if (cdPlaying) - I_StopCD (); - for (i = 0; i < MAX_CD_TRACKS; i++) - cdRemap[i] = (UINT8)i; - CD_Reset(); - cdValid = CD_ReadTrackInfo(); - return; - } - - // any other command is not allowed until we could retrieve cd information - if (!cdValid) - { - CONS_Printf ("CD is not ready.\n"); - return; - } - - /* faB: not with MCI, didn't find it, useless anyway - if (!strncmp(s,"open",4)) - { - if (cdPlaying) - I_StopCD (); - bcd_open_door(); - cdValid = false; - return; - }*/ - - if (!strncmp(s,"info",4)) - { - if (!CD_ReadTrackInfo()) - { - cdValid = false; - return; - } - - cdValid = true; - - if (m_nTracksCount <= 0) - CONS_Printf ("No audio tracks\n"); - else - { - // display list of tracks - // highlight current playing track - for (i = 0; i < m_nTracksCount; i++) - { - CONS_Printf("%s%2d. %s %s\n", - cdPlaying && (cdPlayTrack == i) ? "\2 " : " ", - i+1, m_nTracks[i].IsAudio ? "audio" : "data ", - hms(m_nTracks[i].Length)); - } - CONS_Printf ("\2Total time : %s\n", hms(CD_TotalTime())); - } - if (cdPlaying) - { - CONS_Printf ("%s track : %d\n", cdLooping ? "looping" : "playing", - cdPlayTrack); - } - return; - } - - if (!strncmp(s,"play",4)) - { - I_PlayCD ((UINT8)atoi(COM_Argv (2)), false); - return; - } - - if (!strncmp(s,"stop",4)) - { - I_StopCD (); - return; - } - - if (!strncmp(s,"loop",4)) - { - I_PlayCD ((UINT8)atoi(COM_Argv (2)), true); - return; - } - - if (!strncmp(s,"resume",4)) - { - I_ResumeCD (); - return; - } - - CONS_Printf ("cd command '%s' unknown\n", s); -} - - -// ------------ -// I_ShutdownCD -// Shutdown CD Audio subsystem, release whatever was allocated -// ------------ -void I_ShutdownCD (void) -{ - MCIERROR iErr; - - if (!cdaudio_started) - return; - - CONS_Printf("I_ShutdownCD()\n"); - - I_StopCD(); - - // closes MCI CD - iErr = mciSendCommand(m_MCIOpen.wDeviceID, MCI_CLOSE, 0, 0); - if (iErr) - MCIErrorMessageBox (iErr); -} - - -// -------- -// I_InitCD -// Init CD Audio subsystem -// -------- -void I_InitCD (void) -{ - MCI_SET_PARMS mciSet; - MCIERROR iErr; - int i; - - // We don't have an open device yet - m_MCIOpen.wDeviceID = 0; - m_nTracksCount = 0; - - cdaudio_started = false; - - m_MCIOpen.lpstrDeviceType = (LPCTSTR)MCI_DEVTYPE_CD_AUDIO; - iErr = mciSendCommand(0, MCI_OPEN, MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID, (DWORD_PTR)&m_MCIOpen); - if (iErr) - { - MCIErrorMessageBox (iErr); - return; - } - - // Set the time format to track/minute/second/frame (TMSF). - mciSet.dwTimeFormat = MCI_FORMAT_TMSF; - iErr = mciSendCommand(m_MCIOpen.wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&mciSet); - if (iErr) - { - MCIErrorMessageBox (iErr); - mciSendCommand(m_MCIOpen.wDeviceID, MCI_CLOSE, 0, 0); - return; - } - - I_AddExitFunc (I_ShutdownCD); - cdaudio_started = true; - - CONS_Printf("I_InitCD: Init CD audio\n"); - - // last saved in config.cfg - i = cd_volume.value; - //I_SetVolumeCD (0); // initialize to 0 for some odd cd drivers - I_SetVolumeCD (i); // now set the last saved volume - - for (i = 0; i < MAX_CD_TRACKS; i++) - cdRemap[i] = (UINT8)i; - - if (!CD_ReadTrackInfo()) - { - CONS_Printf("\2I_InitCD: no CD in player.\n"); - cdEnabled = false; - cdValid = false; - } - else - { - cdEnabled = true; - cdValid = true; - } - - COM_AddCommand ("cd", Command_Cd_f); -} - - - -// loop/go to next track when track is finished (if cd_update var is true) -// update the volume when it has changed (from console/menu) -void I_UpdateCD (void) -{ - /// \todo check for cd change and restart music ? -} - - -// -void I_PlayCD (UINT8 nTrack, UINT8 bLooping) -{ - MCI_PLAY_PARMS mciPlay; - MCIERROR iErr; - - if (!cdaudio_started || !cdEnabled) - return; - - //faB: try again if it didn't work (just free the user of typing 'cd reset' command) - if (!cdValid) - cdValid = CD_ReadTrackInfo(); - if (!cdValid) - return; - - // tracks start at 0 in the code.. - nTrack--; - if (nTrack < 0 || nTrack >= m_nTracksCount) - nTrack = nTrack % m_nTracksCount; - - nTrack = cdRemap[nTrack]; - - if (cdPlaying) - { - if (cdPlayTrack == nTrack) - return; - I_StopCD (); - } - - cdPlayTrack = nTrack; - - if (!m_nTracks[nTrack].IsAudio) - { - //CONS_Printf ("\2CD Play: not an audio track\n"); // Tails 03-25-2001 - return; - } - - cdLooping = bLooping; - - //faB: stop MIDI music, MIDI music will restart if volume is upped later - cv_digmusicvolume.value = 0; - cv_midimusicvolume.value = 0; - I_StopSong (0); - - //faB: I don't use the notify message, I'm trying to minimize the delay - mciPlay.dwCallback = (DWORD_PTR)((size_t)hWndMain); - mciPlay.dwFrom = MCI_MAKE_TMSF(nTrack+1, 0, 0, 0); - iErr = mciSendCommand(m_MCIOpen.wDeviceID, MCI_PLAY, MCI_FROM|MCI_NOTIFY, (DWORD_PTR)&mciPlay); - if (iErr) - { - MCIErrorMessageBox (iErr); - cdValid = false; - cdPlaying = false; - return; - } - - cdPlaying = true; -} - - -// pause cd music -void I_StopCD (void) -{ - MCIERROR iErr; - - if (!cdaudio_started || !cdEnabled) - return; - - iErr = mciSendCommand(m_MCIOpen.wDeviceID, MCI_PAUSE, MCI_WAIT, 0); - if (iErr) - MCIErrorMessageBox (iErr); - else - { - wasPlaying = cdPlaying; - cdPlaying = false; - } -} - - -// continue after a pause -void I_ResumeCD (void) -{ - MCIERROR iErr; - - if (!cdaudio_started || !cdEnabled) - return; - - if (!cdValid) - return; - - if (!wasPlaying) - return; - - iErr = mciSendCommand(m_MCIOpen.wDeviceID, MCI_RESUME, MCI_WAIT, 0); - if (iErr) - MCIErrorMessageBox (iErr); - else - cdPlaying = true; -} - - -// volume : logical cd audio volume 0-31 (hardware is 0-255) -int I_SetVolumeCD (int volume) -{ - (void)volume; - return 1; -} diff --git a/src/win32ce/win_dbg.h b/src/win32ce/win_dbg.h deleted file mode 100644 index acee896e6..000000000 --- a/src/win32ce/win_dbg.h +++ /dev/null @@ -1,54 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief exception handler - -//#define WIN32_LEAN_AND_MEAN -#define RPC_NO_WINDOWS_H -#include - -// called in the exception filter of the __try block, writes all useful debugging information -// to a file, using only win32 functions in case the C runtime is in a bad state. -int __cdecl RecordExceptionInfo (PEXCEPTION_POINTERS data/*, LPCSTR Message, LPSTR lpCmdLine*/); - -#ifdef __MINGW32__ - -#include - -#ifndef TRYLEVEL_NONE - -#define NO_SEH_MINGW //Alam:? -FUNCINLINE static ATTRINLINE struct _EXCEPTION_POINTERS *GetExceptionInformation(VOID) -{ - LPVOID SEHINFO = NULL; - //__asm__("movl -20(%%ebp), %%eax": "=a"(SEHINFO)); - return SEHINFO; -} - -//Alam_GBC: use __try1(seh) -#ifndef __try -#define __try -#endif //__try - -//#undef NO_SEH_MINGW //Alam: win_dbg's code not working with MINGW -//Alam_GBC: use __except1 -#ifndef __except -#define __except(x) if (0) -#endif //__except - -#endif // !__TRYLEVEL_NONE - -#endif // __MINGW32__ diff --git a/src/win32ce/win_file.c b/src/win32ce/win_file.c deleted file mode 100644 index f9f621011..000000000 --- a/src/win32ce/win_file.c +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include "win_file.h" - - -int FileAccess(LPCTSTR FileName, DWORD mode) -{ - HANDLE hFile; - - hFile = CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - - if (hFile == INVALID_HANDLE_VALUE) - return -1; - else - { - FileClose(hFile); - return 0; - } -} - -HANDLE FileCreate(LPCTSTR FileName) -{ - HANDLE hFile; - - if (FileAccess( FileName, 0) == 0) - hFile = CreateFile( FileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - else - hFile = CreateFile( FileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); - - return hFile; -} - -void FileClose(HANDLE hFile) -{ - CloseHandle(hFile); -} - -DWORD FileLength(HANDLE hFile) -{ - return GetFileSize(hFile, NULL); -} - -HANDLE FileOpen(LPCTSTR FileName) -{ - HANDLE hFile; - - hFile = CreateFile( FileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - - return hFile; -} - -HANDLE FileAppend(LPCTSTR FileName) -{ - HANDLE hFile; - - hFile = CreateFile( FileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); - FileSeek(hFile, 0, FILE_END ); - - return hFile; -} - -DWORD FileRead(HANDLE hFile, LPVOID data, DWORD size) -{ - DWORD readin = 0; - - ReadFile(hFile, data, size, &readin, NULL); - - return readin; -} - -DWORD FileSeek(HANDLE hFile, LONG distance, DWORD method) -{ - DWORD position; - - position = SetFilePointer(hFile, distance, NULL, method); - - return position; -} - -DWORD FileWrite(HANDLE hFile, LPCVOID data, DWORD size) -{ - DWORD written = 0; - - WriteFile(hFile, data, size, &written, NULL); - - return written; -} - -//These functions are provided as CRT replacements. (missing from WinCE) - -int access(char* file,int type) -{ - FILE* file_access = 0; - - file_access = fopen(file,"rb"); - - if(file_access) - { - fclose(file_access); - return 0; - } - - return -1; -} - -unsigned int file_len(char* file) -{ - FILE* file_access; - unsigned int len = 0; - - file_access = fopen(file,"rb"); - - if(!file_access) - return 0; - - fseek(file_access,0,SEEK_END); - - len = ftell(file_access); - - fclose(file_access); - - return len; -} diff --git a/src/win32ce/win_file.h b/src/win32ce/win_file.h deleted file mode 100644 index d1dc5e9c7..000000000 --- a/src/win32ce/win_file.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef FILE_H -#define FILE_H - -// New File I/O functions - -int FileAccess(LPCTSTR, DWORD); -HANDLE FileAppend(LPCTSTR FileName); -void FileClose(HANDLE); -HANDLE FileCreate(LPCTSTR); -DWORD FileLength(HANDLE); -HANDLE FileOpen(LPCTSTR); -DWORD FileRead(HANDLE, LPCVOID, DWORD); -DWORD FileSeek(HANDLE hFile, LONG distance, DWORD method); -DWORD FileWrite(HANDLE, LPCVOID, DWORD); - -int access(char* file,int type); -unsigned int file_len(char* file); - -#endif \ No newline at end of file diff --git a/src/win32ce/win_main.h b/src/win32ce/win_main.h deleted file mode 100644 index fef25327d..000000000 --- a/src/win32ce/win_main.h +++ /dev/null @@ -1,55 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Win32 Sharing - -//#define WIN32_LEAN_AND_MEAN -#define RPC_NO_WINDOWS_H -#include -#include - -extern HINSTANCE myInstance; -extern HWND hWndMain; - -// debugging CONS_Printf to file -#ifdef LOGMESSAGES -extern HANDLE logstream; -#endif -extern int appActive; - -// the MIDI callback is another thread, and Midi volume is delayed here in window proc -VOID I_SetMidiChannelVolume(DWORD dwChannel, DWORD dwVolumePercent); -extern DWORD dwVolumePercent; - -VOID I_GetSysMouseEvents(int mouse_state); -extern unsigned int MSHWheelMessage; - -extern BOOL nodinput; -extern BOOL win9x; - -//faB: midi channel Volume set is delayed by the MIDI stream callback thread, see win_snd.c -#define WM_MSTREAM_UPDATEVOLUME (WM_USER + 101) - -// defined in win_sys.c -VOID I_BeginProfile(VOID); //for timing code -DWORD I_EndProfile(VOID); - -VOID I_GetLastErrorMsgBox(VOID); -VOID I_LoadingScreen (LPCSTR msg); - -void I_RestartSysMouse(void); -void I_DoStartupMouse(void); -BOOL I_SaveMemToFile(const void *pData, size_t iLength, const char *sFileName); diff --git a/src/win32ce/win_net.c b/src/win32ce/win_net.c deleted file mode 100644 index dac1bed53..000000000 --- a/src/win32ce/win_net.c +++ /dev/null @@ -1,39 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief Win32 network interface - -#include "../doomdef.h" -#include "../m_argv.h" -#include "../i_net.h" - -// -// NETWORKING -// - -// -// I_InitNetwork -// -boolean I_InitNetwork (void) -{ - if (M_CheckParm ("-net")) - { - I_Error("The Win32 version of SRB2 doesn't work with external drivers like ipxsetup, sersetup, or doomatic\n" - "Read the documentation about \"-server\" and \"-connect\" parameters or just use the launcher\n"); - } - - return false; -} diff --git a/src/win32ce/win_snd.c b/src/win32ce/win_snd.c deleted file mode 100644 index 14ce4add4..000000000 --- a/src/win32ce/win_snd.c +++ /dev/null @@ -1,2408 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright (C) 1998-2000 by DooM Legacy Team. -// -// 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. -//----------------------------------------------------------------------------- -/// \file -/// \brief interface level code for sound -/// -/// Uses the midiStream* Win32 functions to play MIDI data -/// with low latency and low processor overhead. -#include "../doomdef.h" - -#include "win_main.h" -#include -#define DIRECTSOUND_VERSION 0x0600 /* version 6.0 */ -#define DIRECTINPUT_VERSION 0x0700 -#define DXVERSION_NTCOMPATIBLE 0x0300 -#ifdef _MSC_VER -#pragma warning(disable : 4201) -#endif -#include - -#include "../command.h" -#include "../i_sound.h" -#include "../s_sound.h" -#include "../i_system.h" -#include "../m_argv.h" -#include "../w_wad.h" -#include "../z_zone.h" -#include "../doomstat.h" - -#include "dx_error.h" - -#include "mid2strm.h" - -#ifdef HW3SOUND -#include "../hardware/hw3dsdrv.h" -#include "../hardware/hw3sound.h" -#include "win_dll.h" -#endif - -#ifndef SURROUND -#define SURROUND // comment out this to disable the SurroundSound code -#endif - -#ifdef SURROUND -ATTRNOINLINE static FUNCNOINLINE void CopyAndInvertMemory(void *dest, void *src, int bytes); //Can't inline ASM that haves lables -#endif - -#define FMODSOUND // comment out this to disable MOD/IT/MP3/OGG music playback - -/////////////////////////////////////////////////////////// -#ifdef FMODSOUND -#ifdef __MINGW32__ -#include -#else -#include -#endif -#ifdef FSOUND_INIT_DONTLATENCYADJUST //Alam: why didn't I think about this before? :) -#define FSOUND_Stream_OpenFile(name,mode,length) FSOUND_Stream_Open(name,mode,0,length) -#else -#define FSOUND_INIT_DONTLATENCYADJUST 0 -#endif -#ifdef __MINGW32__ -#include -#else -#include /* optional */ -#endif -//#include -#endif -///////////////////////////////////////////////////////// - -//#define TESTCODE // remove this for release version - -/* briefly described here for convenience: -typedef struct { - WORD wFormatTag; // WAVE_FORMAT_PCM is the only format accepted for DirectSound: - // this tag indicates Pulse Code Modulation (PCM), an uncompressed format - // in which each samples represents the amplitude of the signal at the time - // of sampling. - WORD nChannels; // either one (mono) or two (stereo) - DWORD nSamplesPerSec; // the sampling rate, or frequency, in hertz. - // Typical values are 11,025, 22,050, and 44,100 - DWORD nAvgBytesPerSec; // nAvgBytesPerSec is the product of nBlockAlign and nSamplesPerSec - WORD nBlockAlign; // the number of bytes required for each complete sample, for PCM formats - // is equal to (wBitsPerSample * nChannels / 8). - WORD wBitsPerSample; // gives the size of each sample, generally 8 or 16 bits - WORD cbSize; // cbSize gives the size of any extra fields required to describe a - // specialized wave format. This member is always zero for PCM formats. -} WAVEFORMATEX; -*/ - -// Tails 11-21-2002 -#ifdef FMODSOUND -static FMUSIC_MODULE *mod = NULL; -static int fsoundchannel = -1; -static int fsoundfreq = 0; -static int fmodvol = 127; -static FSOUND_STREAM *fmus = NULL; -#endif - -// -------------------------------------------------------------------------- -// DirectSound stuff -// -------------------------------------------------------------------------- -static LPDIRECTSOUND DSnd = NULL; -static LPDIRECTSOUNDBUFFER DSndPrimary = NULL; ; - -// Stack sounds means sounds put on top of each other, since DirectSound can't play -// the same sound buffer at different locations at the same time, we need to dupli- -// cate existing buffers to play multiple instances of the same sound in the same -// time frame. A duplicate sound is freed when it is no more used. The priority that -// comes from the s_sound engine, is kept so that the lowest priority sounds are -// stopped to make place for the new sound, unless the new sound has a lower priority -// than all playing sounds, in which case the sound is not started. -#define MAXSTACKSOUNDS 32 // this is the absolute number of sounds that - // can play simultaneously, whatever the value - // of cv_numChannels -typedef struct { - LPDIRECTSOUNDBUFFER lpSndBuf; -#ifdef SURROUND - // judgecutor: - // Need for produce surround sound - LPDIRECTSOUNDBUFFER lpSurround; -#endif - int priority; - boolean duplicate; -} StackSound_t; -static StackSound_t StackSounds[MAXSTACKSOUNDS]; - -// -------------------------------------------------------------------------- -// Fill the DirectSoundBuffer with data from a sample, made separate so that -// sound data cna be reloaded if a sound buffer was lost. -// -------------------------------------------------------------------------- -static boolean CopySoundData (LPDIRECTSOUNDBUFFER dsbuffer, LPBYTE data, DWORD length) -{ - LPVOID lpvAudio1; // receives address of lock start - DWORD dwBytes1; // receives number of bytes locked - LPVOID lpvAudio2; // receives address of lock start - DWORD dwBytes2; // receives number of bytes locked - HRESULT hr; - - // Obtain memory address of write block. - hr = IDirectSoundBuffer_Lock (dsbuffer, 0, length, &lpvAudio1, &dwBytes1, &lpvAudio2, &dwBytes2, 0); - - // If DSERR_BUFFERLOST is returned, restore and retry lock. - if (hr == DSERR_BUFFERLOST) - { - hr = IDirectSoundBuffer_Restore (dsbuffer); - if (FAILED (hr)) - I_Error("Restore fail on %x, %s\n",dsbuffer,DXErrorToString(hr)); - hr = IDirectSoundBuffer_Lock (dsbuffer, 0, length, &lpvAudio1, &dwBytes1, &lpvAudio2, &dwBytes2, 0); - if (FAILED (hr)) - I_Error("Lock fail(2) on %x, %s\n",dsbuffer,DXErrorToString(hr)); - } - else - if (FAILED (hr)) - I_Error("Lock fail(1) on %x, %s\n",dsbuffer,DXErrorToString(hr)); - - // copy wave data into the buffer (note: dwBytes1 should equal to dsbdesc->dwBufferBytes ...) - CopyMemory (lpvAudio1, data, dwBytes1); - - if (dwBytes2 && lpvAudio2) - CopyMemory(lpvAudio2, data+dwBytes1, dwBytes2); - - // finally, unlock the buffer - hr = IDirectSoundBuffer_Unlock (dsbuffer, lpvAudio1, dwBytes1, lpvAudio2, dwBytes2); - - if (FAILED (hr)) - I_Error("Unlock fail on %x, %s\n",dsbuffer,DXErrorToString(hr)); - - return true; -} - -#ifdef SURROUND -// judgecutor: -// Hmmm... May be this function is not too good... -static void CopyAndInvertMemory(void *dest, void *src, int bytes) -{ -#ifdef __GNUC__ - __asm__("CAIM:;lodsb;neg %%al;stosb;loop CAIM;"::"c"(bytes),"D"(dest),"S"(src): "memory","cc"); -#else - _asm - { - push esi - push edi - push ecx - mov ecx,bytes - mov esi,src - mov edi,dest -a: - lodsb - neg al - stosb - loop a - pop ecx - pop edi - pop esi - } -#endif -} - -// judgecutor: -// Like normal CopySoundData but sound data will be inverted -static boolean CopyAndInvertSoundData(LPDIRECTSOUNDBUFFER dsbuffer, LPBYTE data, DWORD length) -{ - LPVOID lpvAudio1 = NULL; // receives address of lock start - DWORD dwBytes1 = 0; // receives number of bytes locked - LPVOID lpvAudio2 = NULL; - DWORD dwBytes2 = 0; - HRESULT hr; - - // Obtain memory address of write block. - hr = IDirectSoundBuffer_Lock (dsbuffer, 0, length, &lpvAudio1, &dwBytes1, &lpvAudio2, &dwBytes2, 0); - - // If DSERR_BUFFERLOST is returned, restore and retry lock. - if (hr == DSERR_BUFFERLOST) - { - hr = IDirectSoundBuffer_Restore (dsbuffer); - if (FAILED (hr)) - I_Error("CopyAndInvert: Restore fail on %x, %s\n",dsbuffer,DXErrorToString(hr)); - hr = IDirectSoundBuffer_Lock (dsbuffer, 0, length, &lpvAudio1, &dwBytes1, &lpvAudio2, &dwBytes2, 0); - if (FAILED (hr)) - I_Error("CopyAndInvert: Lock fail(2) on %x, %s\n",dsbuffer,DXErrorToString(hr)); - } else if (FAILED (hr)) - I_Error("CopyAndInvetrt: Lock fail(1) on %x, %s\n",dsbuffer,DXErrorToString(hr)); - - // copy wave data into the buffer (note: dwBytes1 should equal to dsbdesc->dwBufferBytes ...) - CopyAndInvertMemory (lpvAudio1, data, dwBytes1); - - if (dwBytes2 && lpvAudio2) - CopyAndInvertMemory(lpvAudio2, data+dwBytes1, dwBytes2); - - hr = IDirectSoundBuffer_Unlock (dsbuffer, lpvAudio1, dwBytes1, lpvAudio2, dwBytes2); - if (FAILED (hr)) - I_Error("CopyAndInvert: Unlock fail on %x, %s\n",dsbuffer,DXErrorToString(hr)); - - return false; -} -#endif - -static DWORD sound_buffer_flags = DSBCAPS_CTRLPAN | - DSBCAPS_CTRLVOLUME | - DSBCAPS_STICKYFOCUS | - //DSBCAPS_LOCSOFTWARE | - DSBCAPS_STATIC; - -// -------------------------------------------------------------------------- -// raw2DS : convert a raw sound data, returns a LPDIRECTSOUNDBUFFER -// -------------------------------------------------------------------------- -// dsdata points a 4 UINT16 header: -// +0 : value 3 what does it mean? -// +2 : sample rate, either 11025 or 22050. -// +4 : number of samples, each sample is a single byte since it's 8bit -// +6 : value 0 -// -#ifdef SURROUND -// judgecutor: -// We need an another function definition for supporting the surround sound -// Invert just cause to copy an inverted sound data -static LPDIRECTSOUNDBUFFER raw2DS(LPBYTE *dsdata, size_t len, UINT8 invert) -#else -static LPDIRECTSOUNDBUFFER raw2DS(LPBYTE *dsdata, size_t len) -#endif -{ - HRESULT hr; - WAVEFORMATEX wfm; - DSBUFFERDESC dsbdesc; - LPDIRECTSOUNDBUFFER dsbuffer; - - // initialise WAVEFORMATEX structure describing the wave format - ZeroMemory (&wfm, sizeof (WAVEFORMATEX)); - wfm.wFormatTag = WAVE_FORMAT_PCM; - wfm.nChannels = 1; - wfm.nSamplesPerSec = (dsdata[3]<<8)+dsdata[2]; //mostly 11025, but some at 22050. - wfm.wBitsPerSample = 8; - wfm.nBlockAlign = (WORD)(wfm.wBitsPerSample / 8 * wfm.nChannels); - wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign; - - // Set up DSBUFFERDESC structure. - ZeroMemory (&dsbdesc, sizeof (DSBUFFERDESC)); - dsbdesc.dwSize = sizeof (DSBUFFERDESC); -/* dsbdesc.dwFlags = DSBCAPS_CTRLPAN | - DSBCAPS_CTRLVOLUME | - DSBCAPS_STICKYFOCUS | - //DSBCAPS_LOCSOFTWARE | - DSBCAPS_STATIC - | DSBCAPS_CTRLFREQUENCY; // This one for pitching -*/ - dsbdesc.dwFlags = sound_buffer_flags; - dsbdesc.dwBufferBytes = len-8; - dsbdesc.lpwfxFormat = &wfm; // pointer to WAVEFORMATEX structure - - // Create the sound buffer - hr = IDirectSound_CreateSoundBuffer (DSnd, &dsbdesc, &dsbuffer, NULL); - - if (hr == DSERR_CONTROLUNAVAIL) - { - CONS_Printf("\tSoundBufferCreate error - a buffer control is not available.\n\tTrying to disable frequency control.\n"); - - sound_buffer_flags &= ~DSBCAPS_CTRLFREQUENCY; - dsbdesc.dwFlags = sound_buffer_flags; - - hr = IDirectSound_CreateSoundBuffer (DSnd, &dsbdesc, &dsbuffer, NULL); - } - - if (FAILED(hr)) - I_Error("CreateSoundBuffer() FAILED: %s\n", DXErrorToString(hr)); - -#ifdef SURROUND - if (invert) - // just invert a sound data for producing the surround sound - CopyAndInvertSoundData(dsbuffer, (LPBYTE)dsdata + 8, dsbdesc.dwBufferBytes); - else - // Do a normal operation -#endif - // fill the DirectSoundBuffer waveform data - CopySoundData (dsbuffer, (LPBYTE)dsdata + 8, dsbdesc.dwBufferBytes); - - return dsbuffer; -} - - -// -------------------------------------------------------------------------- -// This function loads the sound data from the WAD lump, for single sound. -// -------------------------------------------------------------------------- -void *I_GetSfx (sfxinfo_t * sfx) -{ - LPBYTE dssfx; - - if (sfx->lumpnum < 0) - sfx->lumpnum = S_GetSfxLumpNum (sfx); - -#ifdef HW3SOUND - if (hws_mode != HWS_DEFAULT_MODE) - return HW3S_GetSfx(sfx); -#endif - - sfx->length = W_LumpLength (sfx->lumpnum); - - // PU_CACHE because the data is copied to the DIRECTSOUNDBUFFER, the one here will not be used - dssfx = (LPBYTE) W_CacheLumpNum (sfx->lumpnum, PU_CACHE); - -#ifdef SURROUND - // Make a normal (not inverted) sound buffer - return (void *)raw2DS (dssfx, sfx->length, FALSE); -#else - // return the LPDIRECTSOUNDBUFFER, which will be stored in S_sfx[].data - return (void *)raw2DS (dssfx, sfx->length); -#endif -} - - -// -------------------------------------------------------------------------- -// Free all allocated resources for a single sound -// -------------------------------------------------------------------------- -void I_FreeSfx (sfxinfo_t *sfx) -{ - LPDIRECTSOUNDBUFFER dsbuffer; - - if (sfx->lumpnum < 0) - return; - -#ifdef HW3SOUND - if (hws_mode != HWS_DEFAULT_MODE) - { - HW3S_FreeSfx(sfx); - } - else -#endif - { - //CONS_Printf("I_FreeSfx(%d)\n", sfx->lumpnum); - - // free DIRECTSOUNDBUFFER - dsbuffer = (LPDIRECTSOUNDBUFFER) sfx->data; - if (dsbuffer) - { - size_t i; - for (i = 0; i < MAXSTACKSOUNDS; i++) - { - if (StackSounds[i].lpSndBuf == dsbuffer) - { - StackSounds[i].lpSndBuf = NULL; -#ifdef SURROUND - if (StackSounds[i].lpSurround) - { - IDirectSoundBuffer_Stop(StackSounds[i].lpSurround); - IDirectSoundBuffer_Release(StackSounds[i].lpSurround); - } - StackSounds[i].lpSurround = NULL; -#endif - } - } - IDirectSoundBuffer_Stop (dsbuffer); - IDirectSoundBuffer_Release (dsbuffer); - } - } - sfx->data = NULL; - sfx->lumpnum = -1; -} - - -// -------------------------------------------------------------------------- -// Set the global volume for sound effects -// -------------------------------------------------------------------------- -void I_SetSfxVolume(INT32 volume) -{ - int vol; - HRESULT hr; - - if (nosound || !sound_started) - return; - - // use the last quarter of volume range - if (volume) - vol = (volume * ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4)) / 31 + - (DSBVOLUME_MAX - ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4)); - else - vol = DSBVOLUME_MIN; // make sure 0 is silence - //CONS_Printf("setvolume to %d\n", vol); - hr = IDirectSoundBuffer_SetVolume (DSndPrimary, vol); - //if (FAILED(hr)) - // CONS_Printf("setvolumne failed\n"); -} - - -// -------------------------------------------------------------------------- -// Update the volume for a secondary buffer, make sure it was created with -// DSBCAPS_CTRLVOLUME -// -------------------------------------------------------------------------- -static void I_UpdateSoundVolume (LPDIRECTSOUNDBUFFER lpSnd, int volume) -{ - HRESULT hr; - volume = (volume * ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4)) / 256 + - (DSBVOLUME_MAX - ((DSBVOLUME_MAX-DSBVOLUME_MIN)/4)); - hr = IDirectSoundBuffer_SetVolume (lpSnd, volume); - //if (FAILED(hr)) - // CONS_Printf("\2SetVolume FAILED\n"); -} - - -// -------------------------------------------------------------------------- -// Update the panning for a secondary buffer, make sure it was created with -// DSBCAPS_CTRLPAN -// -------------------------------------------------------------------------- -#define DSBPAN_RANGE (DSBPAN_RIGHT-(DSBPAN_LEFT)) -#define SEP_RANGE 256 //Doom sounds pan range 0-255 (128 is centre) -static void I_UpdateSoundPanning (LPDIRECTSOUNDBUFFER lpSnd, int sep) -{ - HRESULT hr; - hr = IDirectSoundBuffer_SetPan (lpSnd, (sep * DSBPAN_RANGE)/SEP_RANGE - DSBPAN_RIGHT); - //if (FAILED(hr)) - // CONS_Printf("SetPan FAILED for sep %d pan %d\n", sep, (sep * DSBPAN_RANGE)/SEP_RANGE - DSBPAN_RIGHT); -} - -// search a free slot in the stack, free it if needed -static int GetFreeStackNum(int newpriority) -{ - int lowestpri = 256,lowestprihandle = 0; - int i; - // DirectSound can't play multiple instances of the same sound buffer - // unless they are duplicated, so if the sound buffer is in use, make a duplicate - for (i = 0; i < MAXSTACKSOUNDS; i++) - { - // find a free 'playing sound slot' to use - if (StackSounds[i].lpSndBuf == NULL) - { - //CONS_Printf("\t\tfound free slot %d\n", i); - return i; - } - else if (!I_SoundIsPlaying(i)) // check for sounds that finished playing, and can be freed - { - //CONS_Printf("\t\tfinished sound in slot %d\n", i); - //stop sound and free the 'slot' - I_StopSound (i); - // we can use this one since it's now freed - return i; - } - else if (StackSounds[i].priority < lowestpri) //remember lowest priority sound - { - lowestpri = StackSounds[i].priority; - lowestprihandle = i; - } - } - - // the maximum of sounds playing at the same time is reached, if we have at least - // one sound playing with a lower priority, stop it and replace it with the new one - - //CONS_Printf("\t\tall slots occupied..\n"); - if (newpriority >= lowestpri) - { - I_StopSound (lowestprihandle); - return lowestprihandle; - //CONS_Printf(" kicking out lowest priority slot: %d pri: %d, my priority: %d\n", - // handle, lowestpri, priority); - } - - return -1; -} - -#ifdef SURROUND -static LPDIRECTSOUNDBUFFER CreateInvertedSound(int id) -{ - lumpnnum_t lumpnum; - LBYPTE dsdata; - - lumpnum = S_sfx[id].lumpnum; - if (lumpnum < 0) - lumpnum = S_GetSfxLumpNum (&S_sfx[id]); - dsdata = W_CacheLumpNum (lumpnum, PU_CACHE); - return raw2DS(dsdata, S_sfx[id].length, TRUE); -} -#endif - -// Calculate internal pitch from Doom pitch -#if 0 -static float recalc_pitch(int doom_pitch) -{ - return doom_pitch < NORMAL_PITCH ? - (float)(doom_pitch + NORMAL_PITCH) / (NORMAL_PITCH * 2) - :(float)doom_pitch / (float)NORMAL_PITCH; -} -#endif - -// -------------------------------------------------------------------------- -// Start the given S_sfx[id] sound with given properties (panning, volume..) -// -------------------------------------------------------------------------- -INT32 I_StartSound (sfxenum_t id, - INT32 vol, - INT32 sep, - INT32 pitch, - INT32 priority, - INT32 channel) -{ - HRESULT hr; - LPDIRECTSOUNDBUFFER dsbuffer; - DWORD dwStatus; - int handle; - int i; - //DWORD freq; -#ifdef SURROUND - LPDIRECTSOUNDBUFFER dssurround; -#endif - (void)channel; - - if (nosound) - return -1; - - //CONS_Printf("I_StartSound:\n\t\tS_sfx[%d]\n", id); - handle = GetFreeStackNum(priority); - if (handle < 0) - return -1; - - //CONS_Printf("\t\tusing handle %d\n", handle); - - // if the original buffer is playing, duplicate it (DirectSound specific) - // else, use the original buffer - dsbuffer = (LPDIRECTSOUNDBUFFER) S_sfx[id].data; - IDirectSoundBuffer_GetStatus (dsbuffer, &dwStatus); - if (dwStatus & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING)) - { - //CONS_Printf("\t\toriginal sound S_sfx[%d] is playing, duplicating.. ", id); - hr = IDirectSound_DuplicateSoundBuffer(DSnd, (LPDIRECTSOUNDBUFFER) S_sfx[id].data, &dsbuffer); - if (FAILED(hr)) - { - //CONS_Printf("Cound't duplicate sound buffer\n"); - // re-use the original then.. - dsbuffer = (LPDIRECTSOUNDBUFFER) S_sfx[id].data; - // clean up stacksounds info - for (i = 0; i < MAXSTACKSOUNDS; i++) - if (handle != i && - StackSounds[i].lpSndBuf == dsbuffer) - { - StackSounds[i].lpSndBuf = NULL; - } - } - // stop the duplicate or the re-used original - IDirectSoundBuffer_Stop (dsbuffer); - } - - //judgecutor: Sound pitching -#if 0 - if (cv_rndsoundpitch.value) - { - // At first reset the buffer back to original frequency - hr = IDirectSoundBuffer_SetFrequency(dsbuffer, DSBFREQUENCY_ORIGINAL); - if (SUCCEEDED (hr)) - { - - IDirectSoundBuffer_GetFrequency(dsbuffer, &freq); - - // Now pitch it - freq *= recalc_pitch(pitch); - IDirectSoundBuffer_SetFrequency(dsbuffer, freq); - } - else - cv_rndsoundpitch = 0; - } -#else - pitch = 0; -#endif - // store information on the playing sound - StackSounds[handle].lpSndBuf = dsbuffer; - StackSounds[handle].priority = priority; - StackSounds[handle].duplicate = (dsbuffer != (LPDIRECTSOUNDBUFFER)S_sfx[id].data); - - //CONS_Printf("StackSounds[%d].lpSndBuf is %s\n", handle, StackSounds[handle].lpSndBuf == NULL ? "Null":"valid"); - //CONS_Printf("StackSounds[%d].priority is %d\n", handle, StackSounds[handle].priority); - //CONS_Printf("StackSounds[%d].duplicate is %s\n", handle, StackSounds[handle].duplicate ? "TRUE":"FALSE"); - - I_UpdateSoundVolume (dsbuffer, vol); - -#ifdef SURROUND - // Prepare the surround sound buffer - // Use a normal sound data for the left channel (with pan == 0) - // and an inverted sound data for the right channel (with pan == 255) - - dssurround = CreateInvertedSound(id); - - // Surround must be pitched too -#if 0 - if (cv_rndsoundpitch.value) - IDirectSoundBuffer_SetFrequency(dssurround, freq); -#endif - if (sep == -128) - { - I_UpdateSoundPanning(dssurround, 255); - I_UpdateSoundVolume(dssurround, vol); - I_UpdateSoundPanning(dsbuffer, 0); - IDirectSoundBuffer_SetCurrentPosition(dssurround, 0); - } - else - // Perform normal operation -#endif - - I_UpdateSoundPanning (dsbuffer, sep); - - IDirectSoundBuffer_SetCurrentPosition (dsbuffer, 0); - - hr = IDirectSoundBuffer_Play (dsbuffer, 0, 0, 0); - if (hr == DSERR_BUFFERLOST) - { - //CONS_Printf("buffer lost\n"); - // restores the buffer memory and all other settings for the buffer - hr = IDirectSoundBuffer_Restore (dsbuffer); - if (SUCCEEDED (hr)) - { - LPBYTE dsdata; - // reload sample data here - int lumpnum = S_sfx[id].lumpnum; - if (lumpnum < 0) - lumpnum = S_GetSfxLumpNum (&S_sfx[id]); - dsdata = W_CacheLumpNum (lumpnum, PU_CACHE); - - // Well... Data lenght must be -8!!! - CopySoundData (dsbuffer, dsdata + 8, S_sfx[id].length - 8); - - // play - hr = IDirectSoundBuffer_Play (dsbuffer, 0, 0, 0); - } - else - I_Error("I_StartSound : ->Restore FAILED, %s",DXErrorToString(hr)); - } - -#ifdef SURROUND - if (sep == -128) - { - hr = IDirectSoundBuffer_Play (dssurround, 0, 0, 0); - //CONS_Printf("Surround playback\n"); - if (hr == DSERR_BUFFERLOST) - { - // restores the buffer memory and all other settings for the surround buffer - hr = IDirectSoundBuffer_Restore (dssurround); - if (SUCCEEDED (hr)) - { - LPBYTE dsdata; - lumpnumt_t lumpnum = S_sfx[id].lumpnum; - - if (lumpnum < 0) - lumpnum = S_GetSfxLumpNum (&S_sfx[id]); - dsdata = W_CacheLumpNum (lumpnum, PU_CACHE); - CopyAndInvertSoundData (dssurround, (LPBYTE)dsdata + 8, S_sfx[id].length - 8); - - hr = IDirectSoundBuffer_Play (dssurround, 0, 0, 0); - } - else - I_Error("I_StartSound : ->Restore FAILED, %s",DXErrorToString(hr)); - } - } - StackSounds[handle].lpSurround = dssurround; -#endif - - // Returns a handle - return handle; -} - - -// -------------------------------------------------------------------------- -// Stop a sound if it is playing, -// free the corresponding 'playing sound slot' in StackSounds[] -// -------------------------------------------------------------------------- -void I_StopSound (INT32 handle) -{ - LPDIRECTSOUNDBUFFER dsbuffer; - HRESULT hr; - - if (nosound || handle < 0) - return; - - //CONS_Printf("I_StopSound (%d)\n", handle); - - dsbuffer = StackSounds[handle].lpSndBuf; - hr = IDirectSoundBuffer_Stop (dsbuffer); - - // free duplicates of original sound buffer (DirectSound hassles) - if (StackSounds[handle].duplicate) - { - //CONS_Printf("\t\trelease a duplicate..\n"); - IDirectSoundBuffer_Release (dsbuffer); - } - -#ifdef SURROUND - // Stop and release the surround sound buffer - dsbuffer = StackSounds[handle].lpSurround; - if (dsbuffer != NULL) - { - IDirectSoundBuffer_Stop(dsbuffer); - IDirectSoundBuffer_Release(dsbuffer); - } - StackSounds[handle].lpSurround = NULL; -#endif - - StackSounds[handle].lpSndBuf = NULL; -} - - -// -------------------------------------------------------------------------- -// Returns whether the sound is currently playing or not -// -------------------------------------------------------------------------- -INT32 I_SoundIsPlaying(INT32 handle) -{ - LPDIRECTSOUNDBUFFER dsbuffer; - DWORD dwStatus; - - if (nosound || handle == -1) - return FALSE; - - dsbuffer = StackSounds[handle].lpSndBuf; - if (dsbuffer) - { - IDirectSoundBuffer_GetStatus (dsbuffer, &dwStatus); - if (dwStatus & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING)) - return TRUE; - } - - return FALSE; -} - - -// -------------------------------------------------------------------------- -// Update properties of a sound currently playing -// -------------------------------------------------------------------------- -void I_UpdateSoundParams(INT32 handle, - INT32 vol, - INT32 sep, - INT32 pitch) -{ - LPDIRECTSOUNDBUFFER dsbuffer; -#ifdef SURROUND - LPDIRECTSOUNDBUFFER dssurround; - DWORD dwStatus; - DWORD pos; - boolean surround_inuse = FALSE; -#endif - - if (nosound) - return; - - pitch = 0; /// \todo pitch setup - dsbuffer = StackSounds[handle].lpSndBuf; - -#ifdef SURROUND - if (dsbuffer == NULL) - return; - - dssurround = StackSounds[handle].lpSurround; - if (dssurround) - { - IDirectSoundBuffer_GetStatus(dssurround, &dwStatus); - surround_inuse = (dwStatus & (DSBSTATUS_PLAYING | DSBSTATUS_LOOPING)); - } - // If pan changed to stereo... - if (sep != -128) - { - if (surround_inuse) - { - IDirectSoundBuffer_Stop(dssurround); - surround_inuse = FALSE; - } - } - else if (!surround_inuse) // Just update volumes and start the surround if need - { - I_UpdateSoundVolume(dssurround, vol); - I_UpdateSoundPanning(dsbuffer, 0); - IDirectSoundBuffer_GetCurrentPosition(dsbuffer, &pos, NULL); - IDirectSoundBuffer_SetCurrentPosition(dssurround, pos); - IDirectSoundBuffer_Play(dssurround, 0, 0, 0); - surround_inuse = TRUE; - } - else - I_UpdateSoundVolume(dssurround, vol); - I_UpdateSoundVolume(dsbuffer, vol); - - if (!surround_inuse) - I_UpdateSoundPanning(dsbuffer, sep); -#else - if (dsbuffer) - { - I_UpdateSoundVolume (dsbuffer, vol); - I_UpdateSoundPanning (dsbuffer, sep); - } -#endif -} - - -// -// Shutdown DirectSound -// -void I_ShutdownSound(void) -{ - int i; - - CONS_Printf("I_ShutdownSound()\n"); - -#ifdef HW3SOUND - if (hws_mode != HWS_DEFAULT_MODE) - { - HW3S_Shutdown(); - Shutdown3DSDriver(); - return; - } -#endif - // release any temporary 'duplicated' secondary buffers - for (i = 0; i < MAXSTACKSOUNDS; i++) - if (StackSounds[i].lpSndBuf) - // stops the sound and release it if it is a duplicate - I_StopSound (i); - - if (DSnd) - { - IDirectSound_Release(DSnd); - DSnd = NULL; - } -} - - -// ========================================================================== -// Startup DirectSound -// ========================================================================== -void I_StartupSound(void) -{ - HRESULT hr; - LPDIRECTSOUNDBUFFER lpDsb; - DSBUFFERDESC dsbdesc; - WAVEFORMATEX wfm; - int cooplevel; - int frequency; - -#ifdef HW3SOUND - const char *sdrv_name = NULL; - snddev_t snddev; -#endif - - sound_started = false; - - if (dedicated) - return; - - if (nosound) - return; - - // Secure and configure sound device first. - CONS_Printf("I_StartupSound: "); - - // frequency of primary buffer may be set at cmd-line - if (M_CheckParm ("-freq") && M_IsNextParm()) - { - frequency = atoi(M_GetNextParm()); - CONS_Printf(" requested frequency of %d hz\n", frequency); - CV_SetValue(&cv_samplerate,frequency); - } - else - frequency = cv_samplerate.value; - - // Set cooperative level - // Cooperative sound with other applications can be requested at cmd-line - if (M_CheckParm("-coopsound")) - cooplevel = DSSCL_PRIORITY; - else - cooplevel = DSSCL_EXCLUSIVE; - -#ifdef HW3SOUND - if (M_CheckParm("-ds3d")) - { - hws_mode = HWS_DS3D; - sdrv_name = "s_ds3d.dll"; - } -#if 1 - else if (M_CheckParm("-fmod3d")) - { - hws_mode = HWS_FMOD3D; - sdrv_name = "s_fmod.dll"; - } - else if (M_CheckParm("-sounddriver") && M_IsNextParm()) - { - hws_mode = HWS_OTHER; - sdrv_name = M_GetNextParm(); - } -#else - else if (M_CheckParm("-sounddriver") && M_IsNextParm()) - { - hws_mode = HWS_OTHER; - sdrv_name = M_GetNextParm(); - } - else if (!M_CheckParm("-nosd")) - { - hws_mode = HWS_FMOD3D; - sdrv_name = "s_fmod.dll"; - } -#endif - - // There must be further sound drivers (such as A3D and EAX)!!! - - if (hws_mode != HWS_DEFAULT_MODE && sdrv_name != NULL) - { - if (Init3DSDriver(sdrv_name)) - { - //nosound = true; - snddev.sample_rate = frequency; - snddev.bps = 16; - snddev.numsfxs = NUMSFX; - snddev.cooplevel = cooplevel; - snddev.hWnd = hWndMain; - if (HW3S_Init(I_Error, &snddev)) - { - CONS_Printf("Using external sound driver %s\n", sdrv_name); - I_AddExitFunc(I_ShutdownSound); - return; - } - // Falls back to default sound system - CONS_Printf("Not using external sound driver %s\n", sdrv_name); - HW3S_Shutdown(); - Shutdown3DSDriver(); - } - hws_mode = HWS_DEFAULT_MODE; - } -#endif - - // Create DirectSound, use the default sound device - hr = DirectSoundCreate(NULL, &DSnd, NULL); - if (FAILED(hr)) - { - CONS_Printf(" DirectSoundCreate FAILED\n" - " there is no sound device or the sound device is under\n" - " the control of another application\n"); - nosound = true; - return; - } - - // register exit code, now that we have at least DirectSound to close - I_AddExitFunc(I_ShutdownSound); - hr = IDirectSound_SetCooperativeLevel (DSnd, hWndMain, cooplevel); - if (FAILED(hr)) - { - CONS_Printf(" SetCooperativeLevel FAILED\n"); - nosound = true; - return; - } - - // Set up DSBUFFERDESC structure. - ZeroMemory (&dsbdesc, sizeof (DSBUFFERDESC)); - dsbdesc.dwSize = sizeof (DSBUFFERDESC); - dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER | - DSBCAPS_CTRLVOLUME; - dsbdesc.dwBufferBytes = 0; // Must be 0 for primary buffer - dsbdesc.lpwfxFormat = NULL; // Must be NULL for primary buffer - - // Set up structure for the desired format - ZeroMemory (&wfm, sizeof (WAVEFORMATEX)); - wfm.wFormatTag = WAVE_FORMAT_PCM; - wfm.nChannels = 2; //STEREO SOUND! - wfm.nSamplesPerSec = frequency; - wfm.wBitsPerSample = 16; - wfm.nBlockAlign = (WORD)(wfm.wBitsPerSample / 8 * wfm.nChannels); - wfm.nAvgBytesPerSec = wfm.nSamplesPerSec * wfm.nBlockAlign; - - // Gain access to the primary buffer - hr = IDirectSound_CreateSoundBuffer (DSnd, &dsbdesc, &lpDsb, NULL); - if (FAILED(hr)) - { - CONS_Printf("CreateSoundBuffer FAILED: %s (ErrNo %d)\n", DXErrorToString(hr), hr); - nosound = true; - return; - } - - // Set the primary buffer to the desired format, - // but only if we are allowed to do it - if (cooplevel >= DSSCL_PRIORITY) - { - if (SUCCEEDED (hr)) - { - // Set primary buffer to the desired format. If this fails, - // we'll just ignore and go with the default. - hr = IDirectSoundBuffer_SetFormat (lpDsb, &wfm); - if (FAILED(hr)) - CONS_Printf("I_StartupSound : couldn't set primary buffer format.\n"); - else - CV_SetValue(&cv_samplerate,wfm.nSamplesPerSec); - } - // move any on-board sound memory into a contiguous block - // to make the largest portion of free memory available. - - CONS_Printf(" Compacting onboard sound-memory..."); - hr = IDirectSound_Compact (DSnd); - CONS_Printf(" %s\n", SUCCEEDED(hr) ? "Done\n" : "Failed\n")); - } - - // set the primary buffer to play continuously, for performance - // "... this method will ensure that the primary buffer is playing even when no secondary - // buffers are playing; in that case, silence will be played. This can reduce processing - // overhead when sounds are started and stopped in sequence, because the primary buffer - // will be playing continuously rather than stopping and starting between secondary buffers." - hr = IDirectSoundBuffer_Play (lpDsb, 0, 0, DSBPLAY_LOOPING); - if (FAILED (hr)) - CONS_Printf(" Primary buffer continuous play FAILED\n"); - -#ifdef DEBUGSOUND - { - DSCAPS DSCaps; - DSCaps.dwSize = sizeof (DSCAPS); - hr = IDirectSound_GetCaps (DSnd, &DSCaps); - if (SUCCEEDED (hr)) - { - if (DSCaps.dwFlags & DSCAPS_CERTIFIED) - CONS_Printf("This driver has been certified by Microsoft\n"); - if (DSCaps.dwFlags & DSCAPS_EMULDRIVER) - CONS_Printf("No driver with DirectSound support installed (no hardware mixing)\n"); - if (DSCaps.dwFlags & DSCAPS_PRIMARY16BIT) - CONS_Printf("Supports 16-bit primary buffer\n"); - if (DSCaps.dwFlags & DSCAPS_PRIMARY8BIT) - CONS_Printf("Supports 8-bit primary buffer\n"); - if (DSCaps.dwFlags & DSCAPS_SECONDARY16BIT) - CONS_Printf("Supports 16-bit, hardware-mixed secondary buffers\n"); - if (DSCaps.dwFlags & DSCAPS_SECONDARY8BIT) - CONS_Printf("Supports 8-bit, hardware-mixed secondary buffers\n"); - - CONS_Printf("Maximum number of hardware buffers: %d\n", DSCaps.dwMaxHwMixingStaticBuffers); - CONS_Printf("Size of total hardware memory: %d\n", DSCaps.dwTotalHwMemBytes); - CONS_Printf("Size of free hardware memory= %d\n", DSCaps.dwFreeHwMemBytes); - CONS_Printf("Play Cpu Overhead (%% cpu cycles): %d\n", DSCaps.dwPlayCpuOverheadSwBuffers); - } - else - CONS_Printf(" couldn't get sound device caps.\n"); - } -#endif - - // save pointer to the primary DirectSound buffer for volume changes - DSndPrimary = lpDsb; - - ZeroMemory (StackSounds, sizeof (StackSounds)); - - CONS_Printf("sound initialised.\n"); - sound_started = true; -} - - -// ========================================================================== -// -// MUSIC API using MidiStream -// -// ========================================================================== - -#define SPECIAL_HANDLE_CLEANMIDI -1999 // tell I_StopSong() to do a full (slow) midiOutReset() on exit - -static BOOL bMusicStarted; - -static UINT uMIDIDeviceID, uCallbackStatus; -static HMIDISTRM hStream; -static HANDLE hBufferReturnEvent; // for synch between the callback thread and main program thread - // (we need to synch when we decide to stop/free stream buffers) - -static int nCurrentBuffer = 0, nEmptyBuffers; - -static BOOL bBuffersPrepared = FALSE; -static DWORD dwVolCache[MAX_MIDI_IN_TRACKS]; - DWORD dwVolumePercent; // accessed by win_main.c - - // this is accessed by mid2strm.c conversion code - BOOL bMidiLooped = FALSE; -static BOOL bMidiPlaying = FALSE; -static BOOL bMidiPaused = FALSE; -static CONVERTINFO ciStreamBuffers[NUM_STREAM_BUFFERS]; - -#define STATUS_KILLCALLBACK 100 // Signals that the callback should die -#define STATUS_CALLBACKDEAD 200 // Signals callback is done processing -#define STATUS_WAITINGFOREND 300 // Callback's waiting for buffers to play - -#define DEBUG_CALLBACK_TIMEOUT 2000 // Wait 2 seconds for callback - // faB: don't freeze the main code if we debug.. - -#define VOL_CACHE_INIT 127 // for dwVolCache[] - -static BOOL bMidiCanSetVolume; // midi caps - -static void Mid2StreamFreeBuffers(void); -static void CALLBACK MidiStreamCallback (HMIDIIN hMidi, UINT uMsg, DWORD dwInstance, - DWORD dwParam1, DWORD dwParam2); -static BOOL StreamBufferSetup(LPBYTE pMidiData, size_t iMidiSize); - -// ------------------- -// MidiErrorMessageBox -// Calls the midiOutGetErrorText() function and displays the text which -// corresponds to a midi subsystem error code. -// ------------------- -static void MidiErrorMessageBox(MMRESULT mmr) -{ - char szTemp[256] = ""; - - /*szTemp[0] = '\2'; //white text to stand out*/ - if((MMSYSERR_NOERROR == midiOutGetErrorTextA(mmr, szTemp/*+1*/, sizeof (szTemp))) && *szTemp) - CONS_Printf("%s\n",szTemp); - /*MessageBox (GetActiveWindow(), szTemp+1, "LEGACY", - MB_OK | MB_ICONSTOP);*/ - //wsprintf(szDebug, "Midi subsystem error: %s", szTemp); -} - - -// ---------------- -// I_InitAudioMixer -// ---------------- -#ifdef TESTCODE -void I_InitAudioMixer (void) -{ - UINT cMixerDevs = mixerGetNumDevs(); - CONS_Printf("%d mixer devices available\n", cMixerDevs); -} -#endif - -// ----------- -// I_InitDigMusic -// Startup Digital device for streaming output -// ----------- -void I_InitDigMusic(void) -{ - if (dedicated) - nodigimusic = true; - else - CONS_Printf("I_InitDigMusic()\n"); - -#ifdef FMODSOUND - if (!nodigimusic) - { - // Tails 11-21-2002 - if (FSOUND_GetVersion() < FMOD_VERSION) - { - //I_Error("FMOD Error : You are using the wrong DLL version!\nYou should be using FMOD %s\n", "FMOD_VERSION"); - CONS_Printf("FMOD Error : You are using the wrong DLL version!\nYou should be using FMOD %s\n", "FMOD_VERSION"); - nodigimusic = true; - } - - /* - INITIALIZE - */ -#if 1 - if (!FSOUND_SetHWND(hWndMain)) - { -// I_Error("FMOD(Init,FSOUND_SetHWND): %s\n", FMOD_ErrorString(FSOUND_GetError())); - //FSOUND_SetOutput(FSOUND_OUTPUT_DSOUND); - } - //else -#endif - - if (!FSOUND_Init(44100, 32, FSOUND_INIT_DONTLATENCYADJUST)) - { - //I_Error("FMOD(Init,FSOUND_Init): %s\n", FMOD_ErrorString(FSOUND_GetError())); - CONS_Printf("FMOD(Init,FSOUND_Init): %s\n", FMOD_ErrorString(FSOUND_GetError())); - nodigimusic = true; - } - else - I_AddExitFunc(I_ShutdownDigMusic); - } -#endif -} - -// ----------- -// I_InitMIDIMusic -// Startup Midi device for streaming output -// ----------- -void I_InitMIDIMusic(void) -{ - DWORD idx; - MMRESULT mmrRetVal; - UINT cMidiDevs; - MIDIOUTCAPS MidiOutCaps; - const char *szTechnology; - - bMusicStarted = false; - - if (dedicated) - nomidimusic = true; - else - CONS_Printf("I_InitMIDIMusic()\n"); - - if (nomidimusic) - return; - - // check out number of MIDI devices available - // - cMidiDevs = midiOutGetNumDevs(); - if (!cMidiDevs) - { - CONS_Printf("No MIDI devices available, music is disabled\n"); - nomidimusic = true; - return; - } -#ifdef DEBUGMIDISTREAM - else - { - CONS_Printf("%d MIDI devices available\n", cMidiDevs); - } -#endif - - if (M_CheckParm("-winmidi") && M_IsNextParm()) - uMIDIDeviceID = atoi(M_GetNextParm()); - else - uMIDIDeviceID = MIDI_MAPPER; - - // get MIDI device caps - // - if ((mmrRetVal = midiOutGetDevCaps (uMIDIDeviceID, &MidiOutCaps, sizeof (MIDIOUTCAPS))) != - MMSYSERR_NOERROR) - { - CONS_Printf("midiOutGetCaps FAILED : \n"); - MidiErrorMessageBox (mmrRetVal); - } - else - { - CONS_Printf("MIDI product name: %s\n", MidiOutCaps.szPname); - switch (MidiOutCaps.wTechnology) - { - case MOD_FMSYNTH: szTechnology = "FM Synth"; break; - case MOD_MAPPER: szTechnology = "Microsoft MIDI Mapper"; break; - case MOD_MIDIPORT: szTechnology = "MIDI hardware port"; break; - case MOD_SQSYNTH: szTechnology = "Square wave synthesizer"; break; - case MOD_SYNTH: szTechnology = "Synthesizer"; break; - default: szTechnology = "unknown"; break; - } - CONS_Printf("MIDI technology: %s\n", szTechnology); - CONS_Printf("MIDI caps:\n"); - if (MidiOutCaps.dwSupport & MIDICAPS_CACHE) - CONS_Printf("-Patch caching\n"); - if (MidiOutCaps.dwSupport & MIDICAPS_LRVOLUME) - CONS_Printf("-Separate left and right volume control\n"); - if (MidiOutCaps.dwSupport & MIDICAPS_STREAM) - CONS_Printf("-Direct support for midiStreamOut()\n"); - if (MidiOutCaps.dwSupport & MIDICAPS_VOLUME) - CONS_Printf("-Volume control\n"); - bMidiCanSetVolume = ((MidiOutCaps.dwSupport & MIDICAPS_VOLUME)!=0); - } - -#ifdef TESTCODE - I_InitAudioMixer (); -#endif - - // ---------------------------------------------------------------------- - // Midi2Stream initialization - // ---------------------------------------------------------------------- - - // create event for synch'ing the callback thread to main program thread - // when we will need it - hBufferReturnEvent = CreateEvent(NULL, FALSE, FALSE, - TEXT("SRB2 Midi Playback: Wait For Buffer Return")); - - if (!hBufferReturnEvent) - { - I_GetLastErrorMsgBox(); - nomidimusic = true; - return; - } - - if ((mmrRetVal = midiStreamOpen(&hStream, - &uMIDIDeviceID, - (DWORD)1, (DWORD_PTR)MidiStreamCallback/*NULL*/, - (DWORD)0, - CALLBACK_FUNCTION /*CALLBACK_NULL*/)) != MMSYSERR_NOERROR) - { - CONS_Printf("I_RegisterSong: midiStreamOpen FAILED\n"); - MidiErrorMessageBox(mmrRetVal); - nomidimusic = true; - return; - } - - // stream buffers are initially unallocated (set em NULL) - for (idx = 0; idx < NUM_STREAM_BUFFERS; idx++) - ZeroMemory (&ciStreamBuffers[idx].mhBuffer, sizeof (MIDIHDR)); - // ---------------------------------------------------------------------- - - // register exit code - I_AddExitFunc(I_ShutdownMIDIMusic); - - bMusicStarted = true; -} - -// --------------- -// I_InitMusic -// --------------- -void I_InitMusic(void) -{ - I_InitDigMusic(); - I_InitMIDIMusic(); -} - -// --------------- -// I_ShutdownDigMusic -// --------------- -void I_ShutdownDigMusic(void) -{ - CONS_Printf("I_ShutdownDigMusic: \n"); - -#ifdef FMODSOUND - if (!nodigimusic && FSOUND_GetError() != FMOD_ERR_UNINITIALIZED) - { - if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_CHANNEL_ALLOC && FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) - if (devparm) CONS_Printf("FMOD(Shutdown,Unknown): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (mod) - { - if (FMUSIC_IsPlaying(mod)) - if (!FMUSIC_StopSong(mod)) - if (devparm) CONS_Printf("FMOD(Shutdown,FMUSIC_StopSong): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (!FMUSIC_FreeSong(mod)) - if (devparm) CONS_Printf("FMOD(Shutdown,FMUSIC_FreeSong): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - if (fmus) - { - if (FSOUND_IsPlaying(fsoundchannel)) - if (!FSOUND_Stream_Stop(fmus)) - if (devparm) CONS_Printf("FMOD(Shutdown,FSOUND_Stream_Stop): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (!FSOUND_Stream_Close(fmus)) - if (devparm) CONS_Printf("FMOD(Shutdown,FSOUND_Stream_Close): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - FSOUND_Close(); - remove("fmod.tmp"); // Delete the temp file - //if (!FSOUND_StopSound(FSOUND_ALL)) - //if (FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) CONS_Printf("FMOD(Shutdown,FSOUND_StopSound): %s\n", FMOD_ErrorString(FSOUND_GetError())); - //FMUSIC_StopAllSongs(); - //if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) CONS_Printf("FMOD(Shutdown,FMUSIC_StopAllSongs): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } -#endif -} - -// --------------- -// I_ShutdownMIDIMusic -// --------------- -void I_ShutdownMIDIMusic(void) -{ - DWORD idx; - MMRESULT mmrRetVal; - HGLOBAL lp = NULL; - - CONS_Printf("I_ShutdownMIDIMusic: \n"); - - if (nomidimusic) - return; - - if (!bMusicStarted) - return; - - if (hStream) - { - I_StopSong (SPECIAL_HANDLE_CLEANMIDI); - } - - Mid2StreamConverterCleanup(); - Mid2StreamFreeBuffers(); - - // Free our stream buffers - for (idx = 0; idx < NUM_STREAM_BUFFERS; idx++) - { - if (ciStreamBuffers[idx].mhBuffer.lpData) - { - //GlobalFreePtr(ciStreamBuffers[idx].mhBuffer.lpData); - lp = GlobalPtrHandle(ciStreamBuffers[idx].mhBuffer.lpData); - GlobalUnlock(lp); - GlobalFree(lp); - ciStreamBuffers[idx].mhBuffer.lpData = NULL; - } - } - - if (hStream) - { - if ((mmrRetVal = midiStreamClose(hStream)) != MMSYSERR_NOERROR) - MidiErrorMessageBox(mmrRetVal); - hStream = NULL; - } - - CloseHandle(hBufferReturnEvent); - - bMusicStarted = false; -} - -// --------------- -// I_ShutdownMusic -// --------------- -void I_ShutdownMusic(void) -{ - if (!nodigimusic) - I_ShutdownDigMusic(); - - if (!nomidimusic) - I_ShutdownMIDIMusic(); -} - -// -------------------- -// SetAllChannelVolumes -// Given a percent in tenths of a percent, sets volume on all channels to -// reflect the new value. -// -------------------- -static void SetAllChannelVolumes(DWORD dwVolumePercent) -{ - DWORD dwEvent, dwStatus, dwVol, idx; - MMRESULT mmrRetVal; - - if (!bMidiPlaying) - return; - - for (idx = 0, dwStatus = MIDI_CTRLCHANGE; idx < MAX_MIDI_IN_TRACKS; idx++, dwStatus++) - { - dwVol = (dwVolCache[idx] * dwVolumePercent) / 1000; - //CONS_Printf("channel %d vol %d\n", idx, dwVol); - dwEvent = dwStatus | ((DWORD)MIDICTRL_VOLUME << 8) - | ((DWORD)dwVol << 16); - if ((mmrRetVal = midiOutShortMsg((HMIDIOUT)hStream, dwEvent)) - != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - return; - } - } -} - - -// ---------------- -// I_SetMusicVolume -// Set the midi output volume -// ---------------- -void I_SetMIDIMusicVolume(INT32 volume) -{ - MMRESULT mmrRetVal; - int iVolume; - - if (nomidimusic) - return; - - if (bMidiCanSetVolume) - { - // method A - // current volume is 0-31, we need 0-0xFFFF in each word (left/right channel) - iVolume = (volume << 11) | (volume << 27); - if ((mmrRetVal = midiOutSetVolume ((HMIDIOUT)(size_t)uMIDIDeviceID, iVolume)) != MMSYSERR_NOERROR) - { - CONS_Printf("I_SetMusicVolume: couldn't set volume\n"); - MidiErrorMessageBox(mmrRetVal); - } - } - else - { - // method B - dwVolumePercent = (volume * 1000) / 32; - SetAllChannelVolumes (dwVolumePercent); - } -} - -void I_SetDigMusicVolume(INT32 volume) -{ -#ifdef FMODSOUND - if (volume != -1) - fmodvol = (volume<<3)+(volume>>2); - if (!nodigimusic) - { - if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_CHANNEL_ALLOC && FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) - if (devparm) CONS_Printf("FMOD(Volume,Unknown): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (mod) - { - if (FMUSIC_GetType(mod) != FMUSIC_TYPE_NONE) - { - if (!FMUSIC_SetMasterVolume(mod, fmodvol) && devparm) - CONS_Printf("FMOD(Volume,FMUSIC_SetMasterVolume): %s\n", - FMOD_ErrorString(FSOUND_GetError())); - } - else if (devparm) - CONS_Printf("FMOD(Volume,FMUSIC_GetType): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - if (fmus) - { - if (!FSOUND_SetVolume(fsoundchannel, fmodvol)) - if (devparm) CONS_Printf("FMOD(Volume,FSOUND_SetVolume): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - } -#else - (void)volume; -#endif -} - - -// ---------- -// I_PlaySong -// Note: doesn't use the handle, would be useful to switch between mid's after -// some trigger (would do several RegisterSong, then PlaySong the chosen one) -// ---------- -boolean I_PlaySong(INT32 handle, INT32 bLooping) -{ - MMRESULT mmrRetVal; - - if (nomidimusic) - return false; - -#ifdef DEBUGMIDISTREAM - CONS_Printf("I_PlaySong: looping %d\n", bLooping); -#endif - - // unpause the song first if it was paused - if (bMidiPaused) - I_PauseSong(handle); - - // Clear the status of our callback so it will handle - // MOM_DONE callbacks once more - uCallbackStatus = 0; - bMidiPlaying = FALSE; - if ((mmrRetVal = midiStreamRestart(hStream)) != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - Mid2StreamConverterCleanup(); - Mid2StreamFreeBuffers(); - midiStreamClose(hStream); - //I_Error("I_PlaySong: midiStreamRestart error"); - midiStreamOpen(&hStream, &uMIDIDeviceID, (DWORD)1, - (DWORD_PTR)MidiStreamCallback/*NULL*/, - (DWORD)0, CALLBACK_FUNCTION /*CALLBACK_NULL*/); - } - else bMidiPlaying = TRUE; - bMidiLooped = bLooping; - return bMidiPlaying; -} - - -// ----------- -// I_PauseSong -// calls midiStreamPause() to pause the midi playback -// ----------- -void I_PauseSong (INT32 handle) -{ - (void)handle; -#ifdef FMODSOUND - if (!nodigimusic) - { - if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_CHANNEL_ALLOC && FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) - if (devparm) CONS_Printf("FMOD(Pause,Unknown): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (mod) - { - if (!FMUSIC_GetPaused(mod)) - if (!FMUSIC_SetPaused(mod, true)) - if (devparm) CONS_Printf("FMOD(Pause,FMUSIC_SetPaused): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - if (fmus) - { - if (!FSOUND_GetPaused(fsoundchannel)) - if (!FSOUND_SetPaused(fsoundchannel, true)) - if (devparm) CONS_Printf("FMOD(Pause,FSOUND_SetPaused): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - } -#endif - - if (nomidimusic) - return; - -#ifdef DEBUGMIDISTREAM - CONS_Printf("I_PauseSong: \n"); -#endif - - if (!bMidiPaused) - { - midiStreamPause(hStream); - bMidiPaused = true; - } -} - - -// ------------ -// I_ResumeSong -// un-pause the midi song with midiStreamRestart -// ------------ -void I_ResumeSong (INT32 handle) -{ - (void)handle; -#ifdef FMODSOUND - if (!nodigimusic) - { - if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_CHANNEL_ALLOC && FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) - if (devparm) CONS_Printf("FMOD(Resume,Unknown): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (mod != NULL) - { - if (FMUSIC_GetPaused(mod)) - if (!FMUSIC_SetPaused(mod, false)) - if (devparm) CONS_Printf("FMOD(Resume,FMUSIC_SetPaused): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - if (fmus != NULL) - { - if (FSOUND_GetPaused(fsoundchannel)) - if (!FSOUND_SetPaused(fsoundchannel, false)) - if (devparm) CONS_Printf("FMOD(Resume,FSOUND_SetPaused): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - } -#endif - - if (nomidimusic) - return; - -#ifdef DEBUGMIDISTREAM - CONS_Printf("I_ResumeSong: \n"); -#endif - - if (bMidiPaused) - { - midiStreamRestart(hStream); - bMidiPaused = false; - } -} - - -// ---------- -// I_StopSong -// ---------- -// faB: -1999 is a special handle here, it means we stop the midi when exiting -// Legacy, this will do a midiOutReset() for a more 'sure' midi off. -void I_StopSong(INT32 handle) -{ - MMRESULT mmrRetVal; - - if (nomidimusic) - return; - -#ifdef DEBUGMIDISTREAM - CONS_Printf("I_StopSong: \n"); -#endif - - if (bMidiPlaying || (uCallbackStatus != STATUS_CALLBACKDEAD)) - { - bMidiPlaying = bMidiPaused = FALSE; - if (uCallbackStatus != STATUS_CALLBACKDEAD && - uCallbackStatus != STATUS_WAITINGFOREND) - uCallbackStatus = STATUS_KILLCALLBACK; - - //CONS_Printf("a: %d\n",I_GetTime()); - if ((mmrRetVal = midiStreamStop(hStream)) != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - return; - } - - //faB: if we don't call midiOutReset() seems we have to stop the buffers - // ourselves (or it doesn't play anymore) - if (!bMidiPaused && (handle != SPECIAL_HANDLE_CLEANMIDI)) - { - midiStreamPause(hStream); - } - //CONS_Printf("b: %d\n",I_GetTime()); - else - //faB: this damn call takes 1 second and a half !!! still do it on exit - // to be sure everything midi is cleaned as much as possible - if (handle == SPECIAL_HANDLE_CLEANMIDI) - { - if ((mmrRetVal = midiOutReset((HMIDIOUT)hStream)) != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - return; - } - } - //CONS_Printf("c: %d\n",I_GetTime()); - - // Wait for the callback thread to release this thread, which it will do by - // calling SetEvent() once all buffers are returned to it - if ((devparm) - && (WaitForSingleObject(hBufferReturnEvent, DEBUG_CALLBACK_TIMEOUT) - == WAIT_TIMEOUT)) - { - // Note, this is a risky move because the callback may be genuinely busy, but - // when we're debugging, it's safer and faster than freezing the application, - // which leaves the MIDI device locked up and forces a system reset... - CONS_Printf("Timed out waiting for MIDI callback\n"); - uCallbackStatus = STATUS_CALLBACKDEAD; - } - //CONS_Printf("d: %d\n",I_GetTime()); - } - - if (uCallbackStatus == STATUS_CALLBACKDEAD) - { - uCallbackStatus = 0; - Mid2StreamConverterCleanup(); - Mid2StreamFreeBuffers(); - //faB: we could close the stream here and re-open later to avoid - // a little quirk in mmsystem (see DirectX6 mstream note) - midiStreamClose(hStream); - midiStreamOpen(&hStream, &uMIDIDeviceID, (DWORD)1, - (DWORD_PTR)MidiStreamCallback/*NULL*/, - (DWORD)0, CALLBACK_FUNCTION /*CALLBACK_NULL*/); - } -} - -void I_StopDigSong(void) -{ -#ifdef FMODSOUND - if (!nodigimusic) - { - if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_INVALID_PARAM && FSOUND_GetError() != FMOD_ERR_CHANNEL_ALLOC && FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) - if (devparm) CONS_Printf("FMOD(Stop,Unknown): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (mod) - { - if (FMUSIC_IsPlaying(mod)) - { - if (!FMUSIC_StopSong(mod)) - if (devparm) CONS_Printf("FMOD(Stop,FMUSIC_StopSong): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - } - if (fmus) - { - if (FSOUND_IsPlaying(fsoundchannel)) - { - if (!FSOUND_Stream_Stop(fmus)) - if (devparm) CONS_Printf("FMOD(Stop,FSOUND_Stream_Stop): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - } - //if (!FSOUND_StopSound(FSOUND_ALL)) - //if (FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) CONS_Printf("FMOD(Stop,FSOUND_StopSound): %s\n", FMOD_ErrorString(FSOUND_GetError())); - //FMUSIC_StopAllSongs(); - //if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) CONS_Printf("FMOD(Stop,FMUSIC_StopAllSongs): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } -#endif -} - -void I_UnRegisterSong(INT32 handle) -{ - handle = 0; - if (nomidimusic) - return; - - //faB: we might free here whatever is allocated per-music - // (but we don't cause I hate malloc's) - Mid2StreamConverterCleanup(); - -#ifdef DEBUGMIDISTREAM - CONS_Printf("I_UnregisterSong: \n"); -#endif -} - -int I_SetSongSpeed(unsigned int speed) -{ -#ifdef FMODSOUND - if (music_disabled || nodigimusic) - return 0; //there no music or FMOD is not loaded - - if((!fmus || !FSOUND_IsPlaying(fsoundchannel)) && (!mod || !FMUSIC_IsPlaying(mod))) - return 0; //there no FMOD music playing - - if (speed == 0) - return 1; //yes, we can set the speed - - if (fmus) - { - if (FSOUND_IsPlaying(fsoundchannel) - && !FSOUND_SetFrequency(fsoundchannel,(int)(((float)speed*(float)fsoundfreq)/100.0f))) - { - if (devparm) - CONS_Printf("FMOD(ChangeSpeed,FSOUND_SetFrequency): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - else - return 1; - } - else if (mod) - { - if (FMUSIC_IsPlaying(mod) - && !FMUSIC_SetMasterSpeed(mod,(float)speed/100.0f)) - { - if (devparm) - CONS_Printf("FMOD(ChangeSpeed,FMUSIC_SetMasterSpeed): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - else - return 1; - } -#else - (void)speed; -#endif - return 0; -} - -// Special FMOD support Tails 11-21-2002 -boolean I_StartDigSong(const char *musicname, INT32 looping) -{ -#ifdef FMODSOUND - char filename[9]; - void *data; - int lumpnum; - - if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_CHANNEL_ALLOC && - FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER && FSOUND_GetError() != FMOD_ERR_INVALID_PARAM) - if (devparm) CONS_Printf("FMOD(Start,Unknown): %s\n", FMOD_ErrorString(FSOUND_GetError())); - - if (fmus) - { - if (FSOUND_IsPlaying(fsoundchannel)) - if (!FSOUND_Stream_Stop(fmus)) - if (devparm) CONS_Printf("FMOD(Start,FSOUND_Stream_Stop): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (!FSOUND_Stream_Close(fmus)) - if (devparm) CONS_Printf("FMOD(Start,FSOUND_Stream_Close): %s\n", FMOD_ErrorString(FSOUND_GetError())); - fsoundchannel = -1; - fmus = NULL; - } - if (mod) - { - if (FMUSIC_IsPlaying(mod)) - if (!FMUSIC_StopSong(mod)) - if (devparm) CONS_Printf("FMOD(Start,FMUSIC_StopSong): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (!FMUSIC_FreeSong(mod)) - if (devparm) CONS_Printf("FMOD(Start,FMUSIC_FreeSong): %s\n", FMOD_ErrorString(FSOUND_GetError())); - mod = NULL; - } - //if (!FSOUND_StopSound(FSOUND_ALL)) - //if (FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) CONS_Printf("FMOD(Start,FSOUND_StopSound): %s\n", FMOD_ErrorString(FSOUND_GetError())); - //FMUSIC_StopAllSongs(); - //if (FSOUND_GetError() != FMOD_ERR_NONE && FSOUND_GetError() != FMOD_ERR_MEDIAPLAYER) CONS_Printf("FMOD(Start,FMUSIC_StopAllSongs): %s\n", FMOD_ErrorString(FSOUND_GetError())); - - // Create the filename we need - sprintf(filename, "o_%s", musicname); - - lumpnum = W_CheckNumForName(filename); - - if (lumpnum == -1) - { - // Graue 02-29-2004: don't worry about missing music, there might still be a MIDI - return false; // No music found. Oh well! - } - - data = W_CacheLumpName (filename, PU_CACHE); - - I_SaveMemToFile (data, W_LumpLength(lumpnum), "fmod.tmp"); - - Z_Free(data); - - mod = FMUSIC_LoadSong("fmod.tmp"); - - if (FSOUND_GetError() != FMOD_ERR_NONE) - { - if (FSOUND_GetError() != FMOD_ERR_FILE_FORMAT) - if (devparm) CONS_Printf("FMOD(Start,FMUSIC_LoadSong): %s\n", FMOD_ErrorString(FSOUND_GetError())); - - if (mod) - { - if (FMUSIC_IsPlaying(mod)) - if (!FMUSIC_StopSong(mod)) - if (devparm) CONS_Printf("FMOD(Start,FMUSIC_StopSong): %s\n", FMOD_ErrorString(FSOUND_GetError())); - if (!FMUSIC_FreeSong(mod)) - if (devparm) CONS_Printf("FMOD(Start,FMUSIC_FreeSong): %s\n", FMOD_ErrorString(FSOUND_GetError())); - mod = NULL; - } - } - - if (mod) - { - if (!FMUSIC_SetLooping(mod, (signed char)looping)) - { - if (devparm) CONS_Printf("FMOD(Start,FMUSIC_SetLooping): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } -// else if (FMUSIC_GetType(mod) == FMUSIC_TYPE_MOD || FMUSIC_GetType(mod) == FMUSIC_TYPE_S3M) -// { -// if (!FMUSIC_SetPanSeperation(mod, 0.85f)) /* 15% crossover */ -// CONS_Printf("FMOD(Start,FMUSIC_SetPanSeperation): %s\n", FMOD_ErrorString(FSOUND_GetError())); -// } - else if (!FMUSIC_SetPanSeperation(mod, 0.0f)) - { - if (devparm) CONS_Printf("FMOD(Start,FMUSIC_SetPanSeperation): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - } - else - { - fmus = FSOUND_Stream_OpenFile("fmod.tmp", ((looping) ? (FSOUND_LOOP_NORMAL) : (0)),0); - if (fmus == NULL) - { - if (devparm) CONS_Printf("FMOD(Start,FSOUND_Stream_Open): %s\n", FMOD_ErrorString(FSOUND_GetError())); - return false; - } - } - - // Scan the Ogg Vorbis file for the COMMENT= field for a custom loop point - if (fmus && looping) - { - int scan; - char *dataum; - char looplength[64]; - unsigned int loopstart = 0; - int newcount = 0; - const int freq = 44100; - int lumplength = W_LumpLength(lumpnum); - int length = FSOUND_Stream_GetLengthMs(fmus); - - if (length == 0) - { - if (devparm) CONS_Printf("FMOD(Start,FSOUND_Stream_GetLengthMs): %s\n", FMOD_ErrorString(FSOUND_GetError())); - } - else - { - //freq = FSOUND_GetFrequency(fsoundchannel); - - data = W_CacheLumpName (filename, PU_CACHE); - - dataum = (char *)data; - - for (scan = 0;scan < lumplength; scan++) - { - if (*dataum++ == 'C'){ - if (*dataum++ == 'O'){ - if (*dataum++ == 'M'){ - if (*dataum++ == 'M'){ - if (*dataum++ == 'E'){ - if (*dataum++ == 'N'){ - if (*dataum++ == 'T'){ - if (*dataum++ == '='){ - if (*dataum++ == 'L'){ - if (*dataum++ == 'O'){ - if (*dataum++ == 'O'){ - if (*dataum++ == 'P'){ - if (*dataum++ == 'P'){ - if (*dataum++ == 'O'){ - if (*dataum++ == 'I'){ - if (*dataum++ == 'N'){ - if (*dataum++ == 'T'){ - if (*dataum++ == '=') - { - - while (*dataum != 1 && newcount != 63) - { - looplength[newcount++] = *dataum++; - } - - looplength[newcount] = '\n'; - - loopstart = atoi(looplength); - } - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - else - dataum--;} - } - - Z_Free(data); - } - - if (loopstart > 0) - { - const unsigned int loopend = (unsigned int)((freq/1000.0f)*length-(freq/1000.0f)); - //const unsigned int loopend = (((freq/2)*length)/500)-8; - if (!FSOUND_Stream_SetLoopPoints(fmus, loopstart, loopend) && devparm) - CONS_Printf("FMOD(Start,FSOUND_Stream_SetLoopPoints): %s\n", - FMOD_ErrorString(FSOUND_GetError())); - } - } - - /* - PLAY SONG - */ - if (mod) - { - if (FMUSIC_PlaySong(mod)) - { - fsoundchannel = -1; - I_SetDigMusicVolume(-1); - return true; - } - else - { - if (devparm) - CONS_Printf("FMOD(Start,FMUSIC_PlaySong): %s\n", - FMOD_ErrorString(FSOUND_GetError())); - return false; - } - } - if (fmus) - { - fsoundchannel = FSOUND_Stream_PlayEx(FSOUND_FREE, fmus, NULL, TRUE); - - if (fsoundchannel == -1) - { - if (devparm) - CONS_Printf("FMOD(Start,FSOUND_Stream_PlayEx): %s\n", - FMOD_ErrorString(FSOUND_GetError())); - return false; - } - else if (!FSOUND_SetPaused(fsoundchannel, FALSE)) - { - if (devparm) - CONS_Printf("FMOD(Start,FSOUND_SetPaused): %s\n", - FMOD_ErrorString(FSOUND_GetError())); - return false; - } - - I_SetDigMusicVolume(-1); - fsoundfreq = FSOUND_GetFrequency(fsoundchannel); - return true; - } -#else - (void)musicname; - (void)looping; -#endif - return false; - -///////////////////////////////////////////////////////////////////////////////// -} - -// -------------- -// I_RegisterSong -// Prepare a song for playback -// - setup midi stream buffers, and activate the callback procedure -// which will continually fill the buffers with new data -// -------------- - -INT32 I_RegisterSong(void *data, int len) -{ - char *pMidiFileData = NULL; // MIDI music buffer to be played or NULL - - if (nomidimusic) - return 1; - if (!data || !len) - return 0; - -#ifdef DEBUGMIDISTREAM - CONS_Printf("I_RegisterSong: \n"); -#endif - // check for MID format file - if (!memcmp(data, "MThd", 4)) - pMidiFileData = data; - else - { - CONS_Printf("Music lump is not MID music format\n"); - return 0; - } - -#ifdef DEBUGMIDISTREAM - I_SaveMemToFile(pMidiFileData, len, "debug.mid"); -#endif - - // setup midi stream buffer - if (StreamBufferSetup((LPBYTE)pMidiFileData, len)) - { - Mid2StreamConverterCleanup(); - I_Error("I_RegisterSong: StreamBufferSetup FAILED"); - } - - return 1; -} - -// ----------------- -// StreamBufferSetup -// This function uses the filename stored in the global character array to -// open a MIDI file. Then it goes about converting at least the first part of -// that file into a midiStream buffer for playback. -// ----------------- - -// ----------------- -// StreamBufferSetup -// - returns TRUE if a problem occurs -// ----------------- -static BOOL StreamBufferSetup(LPBYTE pMidiData, size_t iMidiSize) -{ - MMRESULT mmrRetVal; - MIDIPROPTIMEDIV mptd; - BOOL bFoundEnd = FALSE; - int dwConvertFlag, nChkErr, idx; - -#ifdef DEBUGMIDISTREAM - if (hStream == NULL) - I_Error("StreamBufferSetup: hStream is NULL!"); -#endif - - // pause midi stream before manipulating the buffers - midiStreamPause(hStream); - - // allocate the stream buffers (only once) - for (idx = 0; idx < NUM_STREAM_BUFFERS; idx++) - { - ciStreamBuffers[idx].mhBuffer.dwBufferLength = OUT_BUFFER_SIZE; - if (!ciStreamBuffers[idx].mhBuffer.lpData) - { - ciStreamBuffers[idx].mhBuffer.lpData = GlobalAllocPtr(GHND, OUT_BUFFER_SIZE); - if (!ciStreamBuffers[idx].mhBuffer.lpData) - return FALSE; - } - } - - // returns TRUE in case of conversion error - if (Mid2StreamConverterInit(pMidiData, iMidiSize)) - return TRUE; - - // Initialize the volume cache array to some pre-defined value - for (idx = 0; idx < MAX_MIDI_IN_TRACKS; idx++) - dwVolCache[idx] = VOL_CACHE_INIT; - - mptd.cbStruct = sizeof (mptd); - mptd.dwTimeDiv = ifs.dwTimeDivision; - if ((mmrRetVal = midiStreamProperty(hStream, (LPBYTE)&mptd, MIDIPROP_SET|MIDIPROP_TIMEDIV)) - != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - return TRUE; - } - - nEmptyBuffers = 0; - dwConvertFlag = CONVERTF_RESET; - - for (nCurrentBuffer = 0; nCurrentBuffer < NUM_STREAM_BUFFERS; nCurrentBuffer++) - { - // Tell the converter to convert up to one entire buffer's length of output - // data. Also, set a flag so it knows to reset any saved state variables it - // may keep from call to call. - ciStreamBuffers[nCurrentBuffer].dwStartOffset = 0; - ciStreamBuffers[nCurrentBuffer].dwMaxLength = OUT_BUFFER_SIZE; - ciStreamBuffers[nCurrentBuffer].tkStart = 0; - ciStreamBuffers[nCurrentBuffer].bTimesUp = FALSE; - - if ((nChkErr = Mid2StreamConvertToBuffer(dwConvertFlag, &ciStreamBuffers[nCurrentBuffer])) - != CONVERTERR_NOERROR) - { - if (nChkErr == CONVERTERR_DONE) - bFoundEnd = TRUE; - else - { - CONS_Printf("StreamBufferSetup: initial conversion pass failed\n"); - return TRUE; - } - } - ciStreamBuffers[nCurrentBuffer].mhBuffer.dwBytesRecorded - = ciStreamBuffers[nCurrentBuffer].dwBytesRecorded; - - if (!bBuffersPrepared) - { - if ((mmrRetVal = midiOutPrepareHeader((HMIDIOUT)hStream, - &ciStreamBuffers[nCurrentBuffer].mhBuffer, sizeof (MIDIHDR))) != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - return TRUE; - } - } - if ((mmrRetVal = midiStreamOut(hStream, &ciStreamBuffers[nCurrentBuffer].mhBuffer, - sizeof (MIDIHDR))) != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - break; - } - dwConvertFlag = 0; - - if (bFoundEnd) - break; - } - - bBuffersPrepared = TRUE; - nCurrentBuffer = 0; - - // MIDI volume - dwVolumePercent = (cv_midimusicvolume.value * 1000) / 32; - if (hStream) - SetAllChannelVolumes(dwVolumePercent); - - return FALSE; -} - -// ---------------- -// SetChannelVolume -// Call here delayed by MIDI stream callback, to adapt the volume event of the -// midi stream to our own set volume percentage. -// ---------------- -void I_SetMidiChannelVolume(DWORD dwChannel, DWORD dwVolumePercent) -{ - DWORD dwEvent, dwVol; - MMRESULT mmrRetVal; - - if (!bMidiPlaying) - return; - - dwVol = (dwVolCache[dwChannel] * dwVolumePercent) / 1000; - dwEvent = MIDI_CTRLCHANGE|dwChannel|((DWORD)MIDICTRL_VOLUME << 8)|((DWORD)dwVol << 16); - if ((mmrRetVal = midiOutShortMsg((HMIDIOUT)hStream, dwEvent)) != MMSYSERR_NOERROR) - { -#ifdef DEBUGMIDISTREAM - MidiErrorMessageBox(mmrRetVal); -#endif - return; - } -} - -// ------------------ -// MidiStreamCallback -// This is the callback handler which continually refills MIDI data buffers -// as they're returned to us from the audio subsystem. -// ------------------ -static void CALLBACK MidiStreamCallback(HMIDIIN hMidi, UINT uMsg, DWORD dwInstance, - DWORD dwParam1, DWORD dwParam2) -{ - MMRESULT mmrRetVal; - int nChkErr; - MIDIEVENT* pme; - MIDIHDR* pmh; - - hMidi = NULL; - dwParam1 = dwParam2 = dwInstance = 0; - switch (uMsg) - { - case MOM_DONE: - // dwParam1 is LPMIDIHDR - if (uCallbackStatus == STATUS_CALLBACKDEAD) - return; - - nEmptyBuffers++; - - // we reached end of song, but we wait until all the buffers are returned - if (uCallbackStatus == STATUS_WAITINGFOREND) - { - if (nEmptyBuffers < NUM_STREAM_BUFFERS) - return; - else - { - // stop the song when end reached (was not looping) - uCallbackStatus = STATUS_CALLBACKDEAD; - SetEvent(hBufferReturnEvent); - I_StopSong(0); - return; - } - } - - // This flag is set whenever the callback is waiting for all buffers to come back. - if (uCallbackStatus == STATUS_KILLCALLBACK) - { - // Count NUM_STREAM_BUFFERS-1 being returned for the last time - if (nEmptyBuffers < NUM_STREAM_BUFFERS) - return; - // Then send a stop message when we get the last buffer back... - else - { - // Change the status to callback dead - uCallbackStatus = STATUS_CALLBACKDEAD; - SetEvent(hBufferReturnEvent); - return; - } - } - - dwProgressBytes += ciStreamBuffers[nCurrentBuffer].mhBuffer.dwBytesRecorded; - - // ------------------------------------------------- - // Fill an available buffer with audio data again... - // ------------------------------------------------- - - if (bMidiPlaying && nEmptyBuffers) - { - ciStreamBuffers[nCurrentBuffer].dwStartOffset = 0; - ciStreamBuffers[nCurrentBuffer].dwMaxLength = OUT_BUFFER_SIZE; - ciStreamBuffers[nCurrentBuffer].tkStart = 0; - ciStreamBuffers[nCurrentBuffer].dwBytesRecorded = 0; - ciStreamBuffers[nCurrentBuffer].bTimesUp = FALSE; - - if ((nChkErr = Mid2StreamConvertToBuffer(0, &ciStreamBuffers[nCurrentBuffer])) - != CONVERTERR_NOERROR) - { - if (nChkErr == CONVERTERR_DONE) - { - // Don't include this one in the count - uCallbackStatus = STATUS_WAITINGFOREND; - return; - } - else - { - // We're not in the main thread, so we can't call I_Error() now. - // Log the error message out, and post exit message. - CONS_Printf("MidiStreamCallback(): conversion pass failed!\n"); - PostMessage(hWndMain, WM_CLOSE, 0, 0); - return; - } - } - - ciStreamBuffers[nCurrentBuffer].mhBuffer.dwBytesRecorded - = ciStreamBuffers[nCurrentBuffer].dwBytesRecorded; - - if ((mmrRetVal = midiStreamOut(hStream, &ciStreamBuffers[nCurrentBuffer].mhBuffer, - sizeof (MIDIHDR))) != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - Mid2StreamConverterCleanup(); - return; - } - - nCurrentBuffer = (nCurrentBuffer + 1) % NUM_STREAM_BUFFERS; - nEmptyBuffers--; - } - - break; - case MOM_POSITIONCB: - pmh = (MIDIHDR*)(size_t)dwParam1; - pme = (MIDIEVENT*)(pmh->lpData + pmh->dwOffset); - if (MIDIEVENT_TYPE(pme->dwEvent) == MIDI_CTRLCHANGE) - { -#ifdef DEBUGMIDISTREAM - if (MIDIEVENT_DATA1(pme->dwEvent) == MIDICTRL_VOLUME_LSB) - { - CONS_Printf("Got an LSB volume event\n"); - PostMessage(hWndMain, WM_CLOSE, 0, 0); // can't I_Error() here - break; - } -#endif - // this is meant to respond to our own intention, from mid2strm.c - if (MIDIEVENT_DATA1(pme->dwEvent) != MIDICTRL_VOLUME) - break; - - // Mask off the channel number and cache the volume data byte - dwVolCache[MIDIEVENT_CHANNEL(pme->dwEvent)] = MIDIEVENT_VOLUME(pme->dwEvent); - // call SetChannelVolume() later to adjust MIDI volume control message to our - // own current volume level. - PostMessage(hWndMain, WM_MSTREAM_UPDATEVOLUME, - MIDIEVENT_CHANNEL(pme->dwEvent), 0L); - } - break; - default: - break; - } - - return; -} - -// --------------------- -// Mid2StreamFreeBuffers -// This function unprepares and frees all our buffers -- something we must -// do to work around a bug in MMYSYSTEM that prevents a device from playing -// back properly unless it is closed and reopened after each stop. -// --------------------- -static void Mid2StreamFreeBuffers(void) -{ - DWORD idx; - MMRESULT mmrRetVal; - - if (bBuffersPrepared) - { - for (idx = 0; idx < NUM_STREAM_BUFFERS; idx++) - { - if ((mmrRetVal = midiOutUnprepareHeader((HMIDIOUT)hStream, - &ciStreamBuffers[idx].mhBuffer, sizeof (MIDIHDR))) != MMSYSERR_NOERROR) - { - MidiErrorMessageBox(mmrRetVal); - } - } - bBuffersPrepared = FALSE; - } - - // Don't free the stream buffers here, but rather allocate them once at startup, - // and free them at shutdown. -} diff --git a/src/win32ce/wince_stuff.c b/src/win32ce/wince_stuff.c deleted file mode 100644 index eb02e8ae2..000000000 --- a/src/win32ce/wince_stuff.c +++ /dev/null @@ -1,135 +0,0 @@ -//It's 4am and im writing replacement string functions.... - -#include -#include -#include "wince_stuff.h" - -char* _strlwr( char *string ) -{ - int i; - - if(!string) - return NULL; - - for(i=0 ; i < strlen(string); i++) - { - if((*(string + i) >= 65) && (*(string + i) <= 90)) - *(string+i) = *(string+i) + 32; - } - - return string; -} - -int _strnicmp(const char *first,const char *last, size_t count ) -{ - int f, l; - - do - { - if ( ((f = (unsigned char)(*(first++))) >= 'A') && (f <= 'Z') ) - f -= 'A' - 'a'; - - if ( ((l = (unsigned char)(*(last++))) >= 'A') && (l <= 'Z') ) - l -= 'A' - 'a'; - - } while ( --count && f && (f == l) ); - - return ( f - l ); -} - - -int _stricmp( const char *dst, const char *src ) -{ - int f, l; - - do - { - if ( ((f = (unsigned char)(*(dst++))) >= 'A') && (f <= 'Z') ) - f -= 'A' - 'a'; - - if ( ((l = (unsigned char)(*(src++))) >= 'A') && (l <= 'Z') ) - l -= 'A' - 'a'; - - } while ( f && (f == l) ); - - return(f - l); -} - - -char* _strupr( char *string ) -{ - int i; - - if(!string) - return NULL; - - for(i=0 ; i < strlen(string); i++) - { - if((*(string + i) >= 97) && (*(string + i) <= 122)) - *(string + i) = *(string + i) - 32; - } - - return string; -} - - - - -int isprint( int c ) -{ - if(c <= 31) - return FALSE; - - return TRUE; -} - - - -char* _strdup (const char * string) -{ - char *memory = NULL; - - if (!string) - return(NULL); - - if (memory = malloc(strlen(string) + 1)) - return(strcpy(memory,string)); - - return(NULL); -} - - - -char* strrchr (const char * string,int ch) -{ - char *start = (char *)string; - - while (*string++) /* find end of string */ - ; - /* search towards front */ - while (--string != start && *string != (char)ch) - ; - - if (*string == (char)ch) /* char found ? */ - return( (char *)string ); - - return(NULL); -} - -char* GetMyCWD(void) -{ - TCHAR fn[MAX_PATH]; - char* my_cwd,*p; - - GetModuleFileName(NULL,fn,MAX_PATH); - - my_cwd = (char*)malloc(MAX_PATH*sizeof(char)); - - WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK | WC_DEFAULTCHAR | WC_SEPCHARS, fn, -1, my_cwd, MAX_PATH, NULL, NULL); - p = strrchr(my_cwd,'\\'); - - if(p) - *(p+1) = '\0'; - - return my_cwd; -} diff --git a/src/win32ce/wince_stuff.h b/src/win32ce/wince_stuff.h deleted file mode 100644 index 5eab74848..000000000 --- a/src/win32ce/wince_stuff.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef WINCE_STUFF_H -#define WINCE_STUFF_H - -/* -char* _strlwr(char *string); -int _strnicmp(const char *string1,const char *string2, size_t count ); -int _stricmp( const char *string1, const char *string2 ); -char* _strupr( char *string ); - -char *_strdup( const char *strSource ); -char *strrchr( const char *string, int c ); - -int isprint( int c ); -*/ -char* GetMyCWD(void); - -#endif \ No newline at end of file diff --git a/src/y_inter.c b/src/y_inter.c index c216497af..5f5bb5f05 100644 --- a/src/y_inter.c +++ b/src/y_inter.c @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2018 by Sonic Team Junior. +// Copyright (C) 2004-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -19,7 +19,7 @@ #include "i_video.h" #include "p_tick.h" #include "r_defs.h" -#include "r_things.h" +#include "r_skins.h" #include "s_sound.h" #include "st_stuff.h" #include "v_video.h" @@ -35,26 +35,21 @@ #include "p_local.h" #include "m_cond.h" // condition sets +#include "lua_hook.h" // IntermissionThinker hook + +#include "lua_hud.h" #include "m_random.h" // M_RandomKey -#include "g_input.h" // PLAYER1INPUTDOWN -#include "k_color.h" // colortranslations +#include "g_input.h" // PlayerInputDown #include "k_battle.h" #include "k_pwrlv.h" #include "console.h" // cons_menuhighlight -#include "lua_hook.h" // IntermissionThinker hook #include "k_grandprix.h" #ifdef HWRENDER #include "hardware/hw_main.h" #endif -#ifdef PC_DOS -#include // for snprintf -int snprintf(char *str, size_t n, const char *fmt, ...); -//int vsnprintf(char *str, size_t n, const char *fmt, va_list ap); -#endif - typedef struct { char patch[9]; @@ -62,67 +57,66 @@ typedef struct UINT8 display; } y_bonus_t; -typedef union +typedef struct { - /*struct - { - char passed1[21]; // KNUCKLES GOT / CRAWLA HONCHO - char passed2[16]; // THROUGH THE ACT / PASSED THE ACT - INT32 passedx1; - INT32 passedx2; + INT32 *character[MAXPLAYERS]; // Winner's character # + UINT16 *color[MAXPLAYERS]; // Winner's color # + SINT8 num[MAXPLAYERS]; // Winner's player # + char *name[MAXPLAYERS]; // Winner's name - y_bonus_t bonuses[4]; - patch_t *bonuspatches[4]; + UINT8 numplayers; // Number of players being displayed - SINT8 gotperfbonus; // Used for visitation flags. + char levelstring[64]; // holds levelnames up to 64 characters - UINT32 score, total; // fake score, total - UINT32 tics; // time + // SRB2kart + INT16 increase[MAXPLAYERS]; // how much did the score increase by? + UINT8 jitter[MAXPLAYERS]; // wiggle - patch_t *ttlnum; // act number being displayed - patch_t *ptotal; // TOTAL - UINT8 gotlife; // Number of extra lives obtained - } coop;*/ + UINT32 val[MAXPLAYERS]; // Gametype-specific value + UINT8 pos[MAXPLAYERS]; // player positions. used for ties - struct - { - UINT8 *color[MAXPLAYERS]; // Winner's color # - INT32 *character[MAXPLAYERS]; // Winner's character # - INT32 num[MAXPLAYERS]; // Winner's player # - char *name[MAXPLAYERS]; // Winner's name - INT32 numplayers; // Number of players being displayed - char levelstring[64]; // holds levelnames up to 64 characters - // SRB2kart - INT16 increase[MAXPLAYERS]; // how much did the score increase by? - UINT8 jitter[MAXPLAYERS]; // wiggle - UINT32 val[MAXPLAYERS]; // Gametype-specific value - UINT8 pos[MAXPLAYERS]; // player positions. used for ties - boolean rankingsmode; // rankings mode - boolean encore; // encore mode - } match; + boolean rankingsmode; // rankings mode + boolean encore; // encore mode } y_data; static y_data data; // graphics static patch_t *bgpatch = NULL; // INTERSCR -static patch_t *widebgpatch = NULL; // INTERSCW +static patch_t *widebgpatch = NULL; static patch_t *bgtile = NULL; // SPECTILE/SRB2BACK static patch_t *interpic = NULL; // custom picture defined in map header static boolean usetile; +static INT32 timer; + +typedef struct +{ + INT32 source_width, source_height; + INT32 source_bpp, source_rowbytes; + UINT8 *source_picture; + INT32 target_width, target_height; + INT32 target_bpp, target_rowbytes; + UINT8 *target_picture; +} y_buffer_t; + boolean usebuffer = false; static boolean useinterpic; static INT32 timer; static INT32 powertype = PWRLV_DISABLED; +static boolean safetorender = true; +static y_buffer_t *y_buffer; static INT32 intertic; static INT32 endtic = -1; static INT32 sorttic = -1; intertype_t intertype = int_none; +intertype_t intermissiontypes[NUMGAMETYPES]; static void Y_FollowIntermission(void); +static void Y_RescaleScreenBuffer(void); static void Y_UnloadData(void); +static void Y_CleanupData(void); // SRB2Kart: voting stuff // Level images @@ -173,32 +167,32 @@ static void Y_UnloadVoteData(void); // static void Y_CompareTime(INT32 i) { - UINT32 val = ((players[i].pflags & PF_TIMEOVER || players[i].realtime == UINT32_MAX) + UINT32 val = ((players[i].pflags & PF_GAMETYPEOVER || players[i].realtime == UINT32_MAX) ? (UINT32_MAX-1) : players[i].realtime); - if (!(val < data.match.val[data.match.numplayers])) + if (!(val < data.val[data.numplayers])) return; - data.match.val[data.match.numplayers] = val; - data.match.num[data.match.numplayers] = i; + data.val[data.numplayers] = val; + data.num[data.numplayers] = i; } static void Y_CompareScore(INT32 i) { - UINT32 val = ((players[i].pflags & PF_TIMEOVER) + UINT32 val = ((players[i].pflags & PF_GAMETYPEOVER) ? (UINT32_MAX-1) : players[i].marescore); - if (!(data.match.val[data.match.numplayers] == UINT32_MAX - || (!(players[i].pflags & PF_TIMEOVER) && val > data.match.val[data.match.numplayers]))) + if (!(data.val[data.numplayers] == UINT32_MAX + || (!(players[i].pflags & PF_GAMETYPEOVER) && val > data.val[data.numplayers]))) return; - data.match.val[data.match.numplayers] = val; - data.match.num[data.match.numplayers] = i; + data.val[data.numplayers] = val; + data.num[data.numplayers] = i; } static void Y_CompareRank(INT32 i) { - INT16 increase = ((data.match.increase[i] == INT16_MIN) ? 0 : data.match.increase[i]); + INT16 increase = ((data.increase[i] == INT16_MIN) ? 0 : data.increase[i]); UINT32 score = players[i].score; if (powertype != PWRLV_DISABLED) @@ -206,11 +200,11 @@ static void Y_CompareRank(INT32 i) score = clientpowerlevels[i][powertype]; } - if (!(data.match.val[data.match.numplayers] == UINT32_MAX || (score - increase) > data.match.val[data.match.numplayers])) + if (!(data.val[data.numplayers] == UINT32_MAX || (score - increase) > data.val[data.numplayers])) return; - data.match.val[data.match.numplayers] = (score - increase); - data.match.num[data.match.numplayers] = i; + data.val[data.numplayers] = (score - increase); + data.num[data.numplayers] = i; } static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) @@ -222,72 +216,72 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) // Initialize variables if (rankingsmode > 1) ; - else if ((data.match.rankingsmode = (boolean)rankingsmode)) + else if ((data.rankingsmode = (boolean)rankingsmode)) { - sprintf(data.match.levelstring, "* Total Rankings *"); - data.match.encore = false; + sprintf(data.levelstring, "* Total Rankings *"); + data.encore = false; } else { // set up the levelstring if (mapheaderinfo[prevmap]->levelflags & LF_NOZONE) { - if (mapheaderinfo[prevmap]->actnum[0]) - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "* %s %s *", + if (mapheaderinfo[prevmap]->actnum > 0) + snprintf(data.levelstring, + sizeof data.levelstring, + "* %s %d *", mapheaderinfo[prevmap]->lvlttl, mapheaderinfo[prevmap]->actnum); else - snprintf(data.match.levelstring, - sizeof data.match.levelstring, + snprintf(data.levelstring, + sizeof data.levelstring, "* %s *", mapheaderinfo[prevmap]->lvlttl); } else { const char *zonttl = (mapheaderinfo[prevmap]->zonttl[0] ? mapheaderinfo[prevmap]->zonttl : "ZONE"); - if (mapheaderinfo[prevmap]->actnum[0]) - snprintf(data.match.levelstring, - sizeof data.match.levelstring, - "* %s %s %s *", + if (mapheaderinfo[prevmap]->actnum > 0) + snprintf(data.levelstring, + sizeof data.levelstring, + "* %s %s %d *", mapheaderinfo[prevmap]->lvlttl, zonttl, mapheaderinfo[prevmap]->actnum); else - snprintf(data.match.levelstring, - sizeof data.match.levelstring, + snprintf(data.levelstring, + sizeof data.levelstring, "* %s %s *", mapheaderinfo[prevmap]->lvlttl, zonttl); } - data.match.levelstring[sizeof data.match.levelstring - 1] = '\0'; + data.levelstring[sizeof data.levelstring - 1] = '\0'; - data.match.encore = encoremode; + data.encore = encoremode; - memset(data.match.jitter, 0, sizeof (data.match.jitter)); + memset(data.jitter, 0, sizeof (data.jitter)); } for (i = 0; i < MAXPLAYERS; i++) { - data.match.val[i] = UINT32_MAX; + data.val[i] = UINT32_MAX; if (nospectategrief[i] != -1) numgriefers++; if (!playeringame[i] || players[i].spectator) { - data.match.increase[i] = INT16_MIN; + data.increase[i] = INT16_MIN; continue; } if (!rankingsmode) - data.match.increase[i] = INT16_MIN; + data.increase[i] = INT16_MIN; numplayersingame++; } - memset(data.match.color, 0, sizeof (data.match.color)); - memset(data.match.character, 0, sizeof (data.match.character)); + memset(data.color, 0, sizeof (data.color)); + memset(data.character, 0, sizeof (data.character)); memset(completed, 0, sizeof (completed)); - data.match.numplayers = 0; + data.numplayers = 0; for (j = 0; j < numplayersingame; j++) { @@ -299,48 +293,133 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32)) comparison(i); } - i = data.match.num[data.match.numplayers]; + i = data.num[data.numplayers]; completed[i] = true; - data.match.color[data.match.numplayers] = &players[i].skincolor; - data.match.character[data.match.numplayers] = &players[i].skin; - data.match.name[data.match.numplayers] = player_names[i]; + data.color[data.numplayers] = &players[i].skincolor; + data.character[data.numplayers] = &players[i].skin; + data.name[data.numplayers] = player_names[i]; - if (data.match.numplayers && (data.match.val[data.match.numplayers] == data.match.val[data.match.numplayers-1])) + if (data.numplayers && (data.val[data.numplayers] == data.val[data.numplayers-1])) { - data.match.pos[data.match.numplayers] = data.match.pos[data.match.numplayers-1]; + data.pos[data.numplayers] = data.pos[data.numplayers-1]; } else { - data.match.pos[data.match.numplayers] = data.match.numplayers+1; + data.pos[data.numplayers] = data.numplayers+1; } if ((powertype == PWRLV_DISABLED) && (!rankingsmode) - && !(players[i].pflags & PF_TIMEOVER) - && (data.match.pos[data.match.numplayers] < (numplayersingame + numgriefers))) + && !(players[i].pflags & PF_GAMETYPEOVER) + && (data.pos[data.numplayers] < (numplayersingame + numgriefers))) { // Online rank is handled further below in this file. - data.match.increase[i] = K_CalculateGPRankPoints(data.match.pos[data.match.numplayers], numplayersingame + numgriefers); - players[i].score += data.match.increase[i]; + data.increase[i] = K_CalculateGPRankPoints(data.pos[data.numplayers], numplayersingame + numgriefers); + players[i].score += data.increase[i]; } if (demo.recording && !rankingsmode) { G_WriteStanding( - data.match.pos[data.match.numplayers], - data.match.name[data.match.numplayers], - *data.match.character[data.match.numplayers], - *data.match.color[data.match.numplayers], - data.match.val[data.match.numplayers] + data.pos[data.numplayers], + data.name[data.numplayers], + *data.character[data.numplayers], + *data.color[data.numplayers], + data.val[data.numplayers] ); } - data.match.numplayers++; + data.numplayers++; } } +// +// Y_ConsiderScreenBuffer +// +// Can we copy the current screen to a buffer? +// +void Y_ConsiderScreenBuffer(void) +{ + if (gameaction != ga_completed) + return; + + if (y_buffer == NULL) + y_buffer = Z_Calloc(sizeof(y_buffer_t), PU_STATIC, NULL); + else + return; + + y_buffer->source_width = vid.width; + y_buffer->source_height = vid.height; + y_buffer->source_bpp = vid.bpp; + y_buffer->source_rowbytes = vid.rowbytes; + y_buffer->source_picture = ZZ_Alloc(y_buffer->source_width*vid.bpp * y_buffer->source_height); + VID_BlitLinearScreen(screens[1], y_buffer->source_picture, vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); + + // Make the rescaled screen buffer + Y_RescaleScreenBuffer(); +} + +// +// Y_RescaleScreenBuffer +// +// Write the rescaled source picture, to the destination picture that has the current screen's resolutions. +// +static void Y_RescaleScreenBuffer(void) +{ + INT32 sx, sy; // source + INT32 dx, dy; // dest + fixed_t scalefac, yscalefac; + fixed_t rowfrac, colfrac; + UINT8 *dest; + + // Who knows? + if (y_buffer == NULL) + return; + + if (y_buffer->target_picture) + Z_Free(y_buffer->target_picture); + + y_buffer->target_width = vid.width; + y_buffer->target_height = vid.height; + y_buffer->target_rowbytes = vid.rowbytes; + y_buffer->target_bpp = vid.bpp; + y_buffer->target_picture = ZZ_Alloc(y_buffer->target_width*vid.bpp * y_buffer->target_height); + dest = y_buffer->target_picture; + + scalefac = FixedDiv(y_buffer->target_width*FRACUNIT, y_buffer->source_width*FRACUNIT); + yscalefac = FixedDiv(y_buffer->target_height*FRACUNIT, y_buffer->source_height*FRACUNIT); + + rowfrac = FixedDiv(FRACUNIT, yscalefac); + colfrac = FixedDiv(FRACUNIT, scalefac); + + for (sy = 0, dy = 0; sy < (y_buffer->source_height << FRACBITS) && dy < y_buffer->target_height; sy += rowfrac, dy++) + for (sx = 0, dx = 0; sx < (y_buffer->source_width << FRACBITS) && dx < y_buffer->target_width; sx += colfrac, dx += y_buffer->target_bpp) + dest[(dy * y_buffer->target_rowbytes) + dx] = y_buffer->source_picture[((sy>>FRACBITS) * y_buffer->source_width) + (sx>>FRACBITS)]; +} + +// +// Y_CleanupScreenBuffer +// +// Free all related memory. +// +void Y_CleanupScreenBuffer(void) +{ + // Who knows? + if (y_buffer == NULL) + return; + + if (y_buffer->target_picture) + Z_Free(y_buffer->target_picture); + + if (y_buffer->source_picture) + Z_Free(y_buffer->source_picture); + + Z_Free(y_buffer); + y_buffer = NULL; +} + // // Y_IntermissionDrawer // @@ -354,32 +433,57 @@ void Y_IntermissionDrawer(void) if (intertype == int_none || rendermode == render_none) return; - if (!usebuffer) + // Lactozilla: Renderer switching + if (needpatchrecache) + { + Y_CleanupData(); + safetorender = false; + } + + if (!safetorender) V_DrawFill(0, 0, BASEVIDWIDTH, BASEVIDHEIGHT, 31); + if (!safetorender) + goto dontdrawbg; + if (useinterpic) V_DrawScaledPatch(0, 0, 0, interpic); else if (!usetile) { if (rendermode == render_soft && usebuffer) - VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); -#ifdef HWRENDER - else if(rendermode != render_soft && usebuffer) { - HWR_DrawIntermissionBG(); - } -#endif - else - { - if (widebgpatch && rendermode == render_soft && vid.width / vid.dupx == 400) - V_DrawScaledPatch(0, 0, V_SNAPTOLEFT, widebgpatch); + // no y_buffer + if (y_buffer == NULL) + VID_BlitLinearScreen(screens[1], screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); else - V_DrawScaledPatch(0, 0, 0, bgpatch); + { + // Maybe the resolution changed? + if ((y_buffer->target_width != vid.width) || (y_buffer->target_height != vid.height)) + Y_RescaleScreenBuffer(); + + // Blit the already-scaled screen buffer to the current screen + VID_BlitLinearScreen(y_buffer->target_picture, screens[0], vid.width*vid.bpp, vid.height, vid.width*vid.bpp, vid.rowbytes); + } + } +#ifdef HWRENDER + else if (rendermode != render_soft && usebuffer) + HWR_DrawIntermissionBG(); +#endif + else if (bgpatch) + { + fixed_t hs = vid.width * FRACUNIT / BASEVIDWIDTH; + fixed_t vs = vid.height * FRACUNIT / BASEVIDHEIGHT; + V_DrawStretchyFixedPatch(0, 0, hs, vs, V_NOSCALEPATCH, bgpatch, NULL); } } - else + else if (bgtile) V_DrawPatchFill(bgtile); +dontdrawbg: + LUAh_IntermissionHUD(); + if (!LUA_HudEnabled(hud_intermissiontally)) + goto skiptallydrawer; + if (usebuffer) // Fade everything out V_DrawFadeScreen(0xFF00, 22); @@ -400,61 +504,20 @@ void Y_IntermissionDrawer(void) if (count < 8) x -= ((count * vid.width) / (8 * vid.dupx)); else if (count == 8) - goto dotimer; + goto skiptallydrawer; else if (count < 16) x += (((16 - count) * vid.width) / (8 * vid.dupx)); } - // SRB2kart 290117 - compeltely replaced this block. - /*if (intertype == int_timeattack) - { - // draw time - ST_DrawPatchFromHud(HUD_TIME, sbotime); - if (cv_timetic.value) - ST_DrawNumFromHud(HUD_SECONDS, data.coop.tics); - else - { - INT32 seconds, minutes, tictrn; - - seconds = G_TicsToSeconds(data.coop.tics); - minutes = G_TicsToMinutes(data.coop.tics, true); - tictrn = G_TicsToCentiseconds(data.coop.tics); - - ST_DrawNumFromHud(HUD_MINUTES, minutes); // Minutes - ST_DrawPatchFromHud(HUD_TIMECOLON, sbocolon); // Colon - ST_DrawPadNumFromHud(HUD_SECONDS, seconds, 2); // Seconds - - // SRB2kart - pulled from old coop block, just in case we need it - // we should show centiseconds on the intermission screen too, if the conditions are right. - if (modeattacking || cv_timetic.value == 2) - { - ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period - ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics - } - - ST_DrawPatchFromHud(HUD_TIMETICCOLON, sboperiod); // Period - ST_DrawPadNumFromHud(HUD_TICS, tictrn, 2); // Tics - } - - // draw the "got through act" lines and act number - V_DrawLevelTitle(data.coop.passedx1, 49, 0, data.coop.passed1); - V_DrawLevelTitle(data.coop.passedx2, 49+V_LevelNameHeight(data.coop.passed2)+2, 0, data.coop.passed2); - - if (strlen(mapheaderinfo[prevmap]->actnum) > 0) - V_DrawScaledPatch(244, 57, 0, data.coop.ttlnum); - - //if (gottimebonus && endtic != -1) - // V_DrawCenteredString(BASEVIDWIDTH/2, 172, V_YELLOWMAP, "TIME BONUS UNLOCKED!"); - } - else*/ if (intertype == int_race || intertype == int_match) + if (intertype == int_race || intertype == int_battle) { #define NUMFORNEWCOLUMN 8 - INT32 y = 41, gutter = ((data.match.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2)); + INT32 y = 41, gutter = ((data.numplayers > NUMFORNEWCOLUMN) ? 0 : (BASEVIDWIDTH/2)); INT32 dupadjust = (vid.width/vid.dupx), duptweak = (dupadjust - BASEVIDWIDTH)/2; const char *timeheader; int y2; - if (data.match.rankingsmode) + if (data.rankingsmode) { if (powertype == PWRLV_DISABLED) { @@ -473,7 +536,7 @@ void Y_IntermissionDrawer(void) case int_race: timeheader = "TIME"; break; - case int_match: + case int_battle: if (battlecapsules) { timeheader = "TIME"; @@ -487,13 +550,13 @@ void Y_IntermissionDrawer(void) } // draw the level name - V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12, 0, data.match.levelstring); + V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12, 0, data.levelstring); V_DrawFill((x-3) - duptweak, 34, dupadjust-2, 1, 0); - if (data.match.encore) + if (data.encore) V_DrawCenteredString(-4 + x + BASEVIDWIDTH/2, 12-8, hilicol, "ENCORE MODE"); - if (data.match.numplayers > NUMFORNEWCOLUMN) + if (data.numplayers > NUMFORNEWCOLUMN) { V_DrawFill(x+156, 24, 1, 158, 0); V_DrawFill((x-3) - duptweak, 182, dupadjust-2, 1, 0); @@ -509,37 +572,37 @@ void Y_IntermissionDrawer(void) V_DrawRightAlignedString(x+(BASEVIDWIDTH/2)+152, 24, hilicol, timeheader); - for (i = 0; i < data.match.numplayers; i++) + for (i = 0; i < data.numplayers; i++) { - boolean dojitter = data.match.jitter[data.match.num[i]]; - data.match.jitter[data.match.num[i]] = 0; + boolean dojitter = data.jitter[data.num[i]]; + data.jitter[data.num[i]] = 0; - if (data.match.num[i] != MAXPLAYERS && playeringame[data.match.num[i]] && !players[data.match.num[i]].spectator) + if (data.num[i] != MAXPLAYERS && playeringame[data.num[i]] && !players[data.num[i]].spectator) { char strtime[MAXPLAYERNAME+1]; if (dojitter) y--; - V_DrawCenteredString(x+6, y, 0, va("%d", data.match.pos[i])); + V_DrawCenteredString(x+6, y, 0, va("%d", data.pos[i])); - if (data.match.color[i]) + if (data.color[i]) { - UINT8 *colormap = R_GetTranslationColormap(*data.match.character[i], *data.match.color[i], GTC_CACHE); - V_DrawMappedPatch(x+16, y-4, 0, facerankprefix[*data.match.character[i]], colormap); + UINT8 *colormap = R_GetTranslationColormap(*data.character[i], *data.color[i], GTC_CACHE); + V_DrawMappedPatch(x+16, y-4, 0, faceprefix[*data.character[i]][FACE_RANK], colormap); } - if (data.match.num[i] == whiteplayer) + if (data.num[i] == whiteplayer) { UINT8 cursorframe = (intertic / 4) % 8; V_DrawScaledPatch(x+16, y-4, 0, W_CachePatchName(va("K_CHILI%d", cursorframe+1), PU_CACHE)); } - STRBUFCPY(strtime, data.match.name[i]); + STRBUFCPY(strtime, data.name[i]); y2 = y; - if (netgame && playerconsole[data.match.num[i]] == 0 && server_lagless && !players[data.match.num[i]].bot) + if (netgame && playerconsole[data.num[i]] == 0 && server_lagless && !players[data.num[i]].bot) { static int alagles_timer = 0; patch_t *alagles; @@ -568,61 +631,61 @@ void Y_IntermissionDrawer(void) y2 += SHORT (alagles->height) + 1; } - if (data.match.numplayers > NUMFORNEWCOLUMN) - V_DrawThinString(x+36, y2-1, ((data.match.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); + if (data.numplayers > NUMFORNEWCOLUMN) + V_DrawThinString(x+36, y2-1, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE|V_6WIDTHSPACE, strtime); else - V_DrawString(x+36, y2, ((data.match.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime); + V_DrawString(x+36, y2, ((data.num[i] == whiteplayer) ? hilicol : 0)|V_ALLOWLOWERCASE, strtime); - if (data.match.rankingsmode) + if (data.rankingsmode) { - if (powertype != PWRLV_DISABLED && !clientpowerlevels[data.match.num[i]][powertype]) + if (powertype != PWRLV_DISABLED && !clientpowerlevels[data.num[i]][powertype]) { // No power level (splitscreen guests) STRBUFCPY(strtime, "----"); } else { - if (data.match.increase[data.match.num[i]] != INT16_MIN) + if (data.increase[data.num[i]] != INT16_MIN) { - snprintf(strtime, sizeof strtime, "(%d)", data.match.increase[data.match.num[i]]); + snprintf(strtime, sizeof strtime, "(%d)", data.increase[data.num[i]]); - if (data.match.numplayers > NUMFORNEWCOLUMN) + if (data.numplayers > NUMFORNEWCOLUMN) V_DrawRightAlignedThinString(x+133+gutter, y-1, V_6WIDTHSPACE, strtime); else V_DrawRightAlignedString(x+118+gutter, y, 0, strtime); } - snprintf(strtime, sizeof strtime, "%d", data.match.val[i]); + snprintf(strtime, sizeof strtime, "%d", data.val[i]); } - if (data.match.numplayers > NUMFORNEWCOLUMN) + if (data.numplayers > NUMFORNEWCOLUMN) V_DrawRightAlignedThinString(x+152+gutter, y-1, V_6WIDTHSPACE, strtime); else V_DrawRightAlignedString(x+152+gutter, y, 0, strtime); } else { - if (data.match.val[i] == (UINT32_MAX-1)) - V_DrawRightAlignedThinString(x+152+gutter, y-1, (data.match.numplayers > NUMFORNEWCOLUMN ? V_6WIDTHSPACE : 0), "NO CONTEST."); + if (data.val[i] == (UINT32_MAX-1)) + V_DrawRightAlignedThinString(x+152+gutter, y-1, (data.numplayers > NUMFORNEWCOLUMN ? V_6WIDTHSPACE : 0), "NO CONTEST."); else { - if (intertype == int_race || (intertype == int_match && battlecapsules)) + if (intertype == int_race || (intertype == int_battle && battlecapsules)) { - snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(data.match.val[i], true), - G_TicsToSeconds(data.match.val[i]), G_TicsToCentiseconds(data.match.val[i])); + snprintf(strtime, sizeof strtime, "%i'%02i\"%02i", G_TicsToMinutes(data.val[i], true), + G_TicsToSeconds(data.val[i]), G_TicsToCentiseconds(data.val[i])); strtime[sizeof strtime - 1] = '\0'; - if (data.match.numplayers > NUMFORNEWCOLUMN) + if (data.numplayers > NUMFORNEWCOLUMN) V_DrawRightAlignedThinString(x+152+gutter, y-1, V_6WIDTHSPACE, strtime); else V_DrawRightAlignedString(x+152+gutter, y, 0, strtime); } else { - if (data.match.numplayers > NUMFORNEWCOLUMN) - V_DrawRightAlignedThinString(x+152+gutter, y-1, V_6WIDTHSPACE, va("%i", data.match.val[i])); + if (data.numplayers > NUMFORNEWCOLUMN) + V_DrawRightAlignedThinString(x+152+gutter, y-1, V_6WIDTHSPACE, va("%i", data.val[i])); else - V_DrawRightAlignedString(x+152+gutter, y, 0, va("%i", data.match.val[i])); + V_DrawRightAlignedString(x+152+gutter, y, 0, va("%i", data.val[i])); } } } @@ -631,7 +694,7 @@ void Y_IntermissionDrawer(void) y++; } else - data.match.num[i] = MAXPLAYERS; // this should be the only field setting in this function + data.num[i] = MAXPLAYERS; // this should be the only field setting in this function y += 18; @@ -644,7 +707,10 @@ void Y_IntermissionDrawer(void) } } -dotimer: +skiptallydrawer: + if (!LUA_HudEnabled(hud_intermissionmessages)) + return; + if (timer && grandprixinfo.gp == false) { char *string; @@ -682,6 +748,7 @@ dotimer: //{ /*if (cv_scrambleonchange.value && cv_teamscramble.value) V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT/2, hilicol, M_GetText("Teams will be scrambled next round!"));*/ + if (speedscramble != -1 && speedscramble != gamespeed) V_DrawCenteredString(BASEVIDWIDTH/2, BASEVIDHEIGHT-24, hilicol|V_ALLOWLOWERCASE|V_SNAPTOBOTTOM, va(M_GetText("Next race will be %s Speed!"), kartspeed_cons_t[1+speedscramble].strvalue)); @@ -700,7 +767,7 @@ void Y_Ticker(void) if (demo.recording) { - if (demo.savemode == DSM_NOTSAVING && InputDown(gc_lookback, 1)) + if (demo.savemode == DSM_NOTSAVING && PlayerInputDown(1, gc_lookback)) demo.savemode = DSM_TITLEENTRY; if (demo.savemode == DSM_WILLSAVE || demo.savemode == DSM_WILLAUTOSAVE) @@ -711,9 +778,7 @@ void Y_Ticker(void) if (paused || P_AutoPause()) return; -#ifdef HAVE_BLUA LUAh_IntermissionThinker(); -#endif intertic++; @@ -733,7 +798,7 @@ void Y_Ticker(void) if (!--timer) { Y_EndIntermission(); - Y_FollowIntermission(); + G_AfterIntermission(); return; } } @@ -741,70 +806,70 @@ void Y_Ticker(void) else if (intertic == endtic) { Y_EndIntermission(); - Y_FollowIntermission(); + G_AfterIntermission(); return; } if (intertic < TICRATE || intertic & 1 || endtic != -1) return; - if (intertype == int_race || intertype == int_match) + if (intertype == int_race || intertype == int_battle) { if (!(multiplayer && demo.playback)) // Don't advance to rankings in replays { - if (!data.match.rankingsmode && (intertic >= sorttic + 8)) + if (!data.rankingsmode && (intertic >= sorttic + 8)) { Y_CalculateMatchData(1, Y_CompareRank); } - if (data.match.rankingsmode && intertic > sorttic+16+(2*TICRATE)) + if (data.rankingsmode && intertic > sorttic+16+(2*TICRATE)) { INT32 q=0,r=0; boolean kaching = true; - for (q = 0; q < data.match.numplayers; q++) + for (q = 0; q < data.numplayers; q++) { - if (data.match.num[q] == MAXPLAYERS - || !data.match.increase[data.match.num[q]] - || data.match.increase[data.match.num[q]] == INT16_MIN) + if (data.num[q] == MAXPLAYERS + || !data.increase[data.num[q]] + || data.increase[data.num[q]] == INT16_MIN) { continue; } r++; - data.match.jitter[data.match.num[q]] = 1; + data.jitter[data.num[q]] = 1; if (powertype != PWRLV_DISABLED) { // Power Levels - if (abs(data.match.increase[data.match.num[q]]) < 10) + if (abs(data.increase[data.num[q]]) < 10) { // Not a lot of point increase left, just set to 0 instantly - data.match.increase[data.match.num[q]] = 0; + data.increase[data.num[q]] = 0; } else { SINT8 remove = 0; // default (should not happen) - if (data.match.increase[data.match.num[q]] < 0) + if (data.increase[data.num[q]] < 0) remove = -10; - else if (data.match.increase[data.match.num[q]] > 0) + else if (data.increase[data.num[q]] > 0) remove = 10; // Remove 10 points at a time - data.match.increase[data.match.num[q]] -= remove; + data.increase[data.num[q]] -= remove; // Still not zero, no kaching yet - if (data.match.increase[data.match.num[q]] != 0) + if (data.increase[data.num[q]] != 0) kaching = false; } } else { // Basic bitch points - if (data.match.increase[data.match.num[q]]) + if (data.increase[data.num[q]]) { - if (--data.match.increase[data.match.num[q]]) + if (--data.increase[data.num[q]]) kaching = false; } } @@ -819,112 +884,11 @@ void Y_Ticker(void) endtic = intertic + 3*TICRATE; // 3 second pause after end of tally } } - else - endtic = intertic + 8*TICRATE; // 8 second pause after end of tally + else if (!(intertic & 1)) + S_StartSound(NULL, sfx_ptally); // tally sound effect } } -// -// Y_UpdateRecordReplays -// -// Update replay files/data, etc. for Record Attack -// See G_SetNightsRecords for NiGHTS Attack. -// -static void Y_UpdateRecordReplays(void) -{ - const size_t glen = strlen(srb2home)+1+strlen("media")+strlen("replay")+1+strlen(timeattackfolder)+1+strlen("MAPXX")+1; - char *gpath; - char lastdemo[256], bestdemo[256]; - UINT8 earnedEmblems; - - // Record new best time - if (!mainrecords[gamemap-1]) - G_AllocMainRecordData(gamemap-1); - - if (players[consoleplayer].pflags & PF_TIMEOVER) - { - players[consoleplayer].realtime = UINT32_MAX; - } - - if (((mainrecords[gamemap-1]->time == 0) || (players[consoleplayer].realtime < mainrecords[gamemap-1]->time)) - && (players[consoleplayer].realtime < UINT32_MAX)) // DNF - { - mainrecords[gamemap-1]->time = players[consoleplayer].realtime; - } - - if (modeattacking == ATTACKING_RECORD) - { - if ((mainrecords[gamemap-1]->lap == 0) || (bestlap < mainrecords[gamemap-1]->lap)) - mainrecords[gamemap-1]->lap = bestlap; - } - else - { - mainrecords[gamemap-1]->lap = 0; - } - - // Save demo! - bestdemo[255] = '\0'; - lastdemo[255] = '\0'; - G_SetDemoTime(players[consoleplayer].realtime, bestlap); - G_CheckDemoStatus(); - - gpath = va("%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s", - srb2home, timeattackfolder); - M_MkdirEach(gpath, M_PathParts(gpath) - 3, 0755); - - if ((gpath = malloc(glen)) == NULL) - I_Error("Out of memory for replay filepath\n"); - - sprintf(gpath,"%s"PATHSEP"media"PATHSEP"replay"PATHSEP"%s"PATHSEP"%s", srb2home, timeattackfolder, G_BuildMapName(gamemap)); - snprintf(lastdemo, 255, "%s-%s-last.lmp", gpath, cv_chooseskin.string); - - if (FIL_FileExists(lastdemo)) - { - UINT8 *buf; - size_t len = FIL_ReadFile(lastdemo, &buf); - - snprintf(bestdemo, 255, "%s-%s-time-best.lmp", gpath, cv_chooseskin.string); - if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & 1) - { // Better time, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD TIME!"), M_GetText("Saved replay as"), bestdemo); - } - - if (modeattacking == ATTACKING_RECORD) - { - snprintf(bestdemo, 255, "%s-%s-lap-best.lmp", gpath, cv_chooseskin.string); - if (!FIL_FileExists(bestdemo) || G_CmpDemoTime(bestdemo, lastdemo) & (1<<1)) - { // Better lap time, save this demo. - if (FIL_FileExists(bestdemo)) - remove(bestdemo); - FIL_WriteFile(bestdemo, buf, len); - CONS_Printf("\x83%s\x80 %s '%s'\n", M_GetText("NEW RECORD LAP!"), M_GetText("Saved replay as"), bestdemo); - } - } - - //CONS_Printf("%s '%s'\n", M_GetText("Saved replay as"), lastdemo); - - Z_Free(buf); - } - free(gpath); - - // Check emblems when level data is updated - if ((earnedEmblems = M_CheckLevelEmblems())) - CONS_Printf(M_GetText("\x82" "Earned %hu medal%s for Record Attack records.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : ""); - - if (M_UpdateUnlockablesAndExtraEmblems(false)) - S_StartSound(NULL, sfx_ncitem); - - // SRB2Kart - save here so you NEVER lose your earned times/medals. - G_SaveGameData(false); - - // Update timeattack menu's replay availability. - CV_AddValue(&cv_nextmap, 1); - CV_AddValue(&cv_nextmap, -1); -} - static void K_UpdatePowerLevels(void) { INT32 i, j; @@ -955,7 +919,7 @@ static void K_UpdatePowerLevels(void) UINT16 theirpower = PWRLVRECORD_DEF; INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV INT16 inc = 0; // Total pt increment - UINT8 ipnum = data.match.num[i]; + UINT8 ipnum = data.num[i]; UINT8 jpnum; CONS_Debug(DBG_GAMELOGIC, "Power Level Gain for player %d:\n", ipnum); @@ -970,14 +934,14 @@ static void K_UpdatePowerLevels(void) { boolean won = false; - jpnum = data.match.num[j]; + jpnum = data.num[j]; if (i == j || ipnum == jpnum) // Same person continue; CONS_Debug(DBG_GAMELOGIC, "Player %d VS Player %d:\n", ipnum, jpnum); - if (data.match.val[i] == data.match.val[j]) // Tie -- neither get any points for this match up. + if (data.val[i] == data.val[j]) // Tie -- neither get any points for this match up. { CONS_Debug(DBG_GAMELOGIC, "TIE, no change.\n"); continue; @@ -990,14 +954,14 @@ static void K_UpdatePowerLevels(void) CONS_Debug(DBG_GAMELOGIC, "Player %d's PWR.LV: %d\n", jpnum, theirpower); - if (G_RaceGametype()) + if ((gametyperules & GTR_CIRCUIT)) { - if (data.match.val[i] < data.match.val[j]) + if (data.val[i] < data.val[j]) won = true; } else { - if (data.match.val[i] > data.match.val[j]) + if (data.val[i] > data.val[j]) won = true; } @@ -1042,7 +1006,7 @@ static void K_UpdatePowerLevels(void) if (inc == 0) { - data.match.increase[ipnum] = INT16_MIN; + data.increase[ipnum] = INT16_MIN; CONS_Debug(DBG_GAMELOGIC, "Total Result: No increment, no change.\n"); continue; } @@ -1062,20 +1026,40 @@ static void K_UpdatePowerLevels(void) if (increment[i] == 0) continue; - data.match.increase[i] = increment[i]; - clientpowerlevels[i][powertype] += data.match.increase[i]; + data.increase[i] = increment[i]; + clientpowerlevels[i][powertype] += data.increase[i]; if (i == consoleplayer) { CONS_Debug(DBG_GAMELOGIC, "Player %d is you! Saving...\n", i); vspowerlevel[powertype] = clientpowerlevels[i][powertype]; - if (M_UpdateUnlockablesAndExtraEmblems(true)) + if (M_UpdateUnlockablesAndExtraEmblems()) S_StartSound(NULL, sfx_ncitem); - G_SaveGameData(true); + G_SaveGameData(); } } } +// +// Y_DetermineIntermissionType +// +// Determines the intermission type from the current gametype. +// +void Y_DetermineIntermissionType(void) +{ + // set to int_none initially + intertype = int_none; + + if (intermissiontypes[gametype] != int_none) + intertype = intermissiontypes[gametype]; + else if (modeattacking) + intertype = int_timeattack; + else if (gametype == GT_RACE) + intertype = int_race; + else if (gametype == GT_BATTLE) + intertype = int_battle; +} + // // Y_StartIntermission // @@ -1096,21 +1080,6 @@ void Y_StartIntermission(void) if (!multiplayer) { timer = 20*TICRATE; - - if (!majormods && !multiplayer && !demo.playback) // move this once we have a proper time attack screen - { - // Update visitation flags - mapvisited[gamemap-1] |= MV_BEATEN; - if (ALL7EMERALDS(emeralds)) - mapvisited[gamemap-1] |= MV_ALLEMERALDS; - /*if (ultimatemode) - mapvisited[gamemap-1] |= MV_ULTIMATE; - if (data.coop.gotperfbonus) - mapvisited[gamemap-1] |= MV_PERFECT;*/ - - if (modeattacking) - Y_UpdateRecordReplays(); - } } else { @@ -1126,14 +1095,12 @@ void Y_StartIntermission(void) timer = 1; } } + + if (intermissiontypes[gametype] != int_none) + intertype = intermissiontypes[gametype]; sorttic = max((timer/2) - 2*TICRATE, 2*TICRATE); // 8 second pause after match results - if (gametype == GT_MATCH) - intertype = int_match; - else //if (gametype == GT_RACE) - intertype = int_race; - // We couldn't display the intermission even if we wanted to. // But we still need to give the players their score bonuses, dummy. //if (dedicated) return; @@ -1144,7 +1111,7 @@ void Y_StartIntermission(void) switch (intertype) { - case int_match: + case int_battle: { // Calculate who won if (battlecapsules) @@ -1178,7 +1145,7 @@ void Y_StartIntermission(void) K_UpdatePowerLevels(); } - //if (intertype == int_race || intertype == int_match) + //if (intertype == int_race || intertype == int_battle) { //bgtile = W_CachePatchName("SRB2BACK", PU_STATIC); usetile = useinterpic = false; @@ -1213,6 +1180,7 @@ static void Y_FollowIntermission(void) } #define UNLOAD(x) Z_ChangeTag(x, PU_CACHE); x = NULL +#define CLEANUP(x) x = NULL; // // Y_UnloadData @@ -1229,34 +1197,15 @@ static void Y_UnloadData(void) UNLOAD(widebgpatch); UNLOAD(bgtile); UNLOAD(interpic); +} - /*switch (intertype) - { - case int_coop: - // unload the coop and single player patches - UNLOAD(data.coop.ttlnum); - UNLOAD(data.coop.bonuspatches[3]); - UNLOAD(data.coop.bonuspatches[2]); - UNLOAD(data.coop.bonuspatches[1]); - UNLOAD(data.coop.bonuspatches[0]); - UNLOAD(data.coop.ptotal); - break; - case int_spec: - // unload the special stage patches - //UNLOAD(data.spec.cemerald); - //UNLOAD(data.spec.nowsuper); - UNLOAD(data.spec.bonuspatch); - UNLOAD(data.spec.pscore); - UNLOAD(data.spec.pcontinues); - break; - case int_match: - case int_race: - default: - //without this default, - //int_none, int_tag, int_chaos, and int_classicrace - //are not handled - break; - }*/ +static void Y_CleanupData(void) +{ + // unload the background patches + CLEANUP(bgpatch); + CLEANUP(widebgpatch); + CLEANUP(bgtile); + CLEANUP(interpic); } // SRB2Kart: Voting! @@ -1378,7 +1327,7 @@ void Y_VoteDrawer(void) break; } - color = colortranslations[players[p].skincolor][7]; + color = skincolors[players[p].skincolor].ramp[7]; colormap = R_GetTranslationColormap(TC_DEFAULT, players[p].skincolor, GTC_CACHE); } @@ -1482,7 +1431,7 @@ void Y_VoteDrawer(void) if (players[i].skincolor) { UINT8 *colormap = R_GetTranslationColormap(players[i].skin, players[i].skincolor, GTC_CACHE); - V_DrawMappedPatch(x+24, y+9, V_SNAPTOLEFT, facerankprefix[players[i].skin], colormap); + V_DrawMappedPatch(x+24, y+9, V_SNAPTOLEFT, faceprefix[players[i].skin][FACE_RANK], colormap); } if (!splitscreen && i == consoleplayer) @@ -1508,7 +1457,7 @@ void Y_VoteDrawer(void) hilicol = cons_menuhighlight.value; else if (gametype == GT_RACE) hilicol = V_SKYMAP; - else //if (gametype == GT_MATCH) + else //if (gametype == GT_BATTLE) hilicol = V_REDMAP; V_DrawCenteredString(BASEVIDWIDTH/2, 188, hilicol, va("Vote ends in %d", tickdown)); @@ -1558,9 +1507,7 @@ void Y_VoteTicker(void) if (paused || P_AutoPause() || !voteclient.loaded) return; -#ifdef HAVE_BLUA LUAh_VoteThinker(); -#endif votetic++; @@ -1693,13 +1640,13 @@ void Y_VoteTicker(void) && !voteclient.playerinfo[i].delay && pickedvote == -1 && votes[p] == -1) { - if (InputDown(gc_aimforward, i+1) || JoyAxis(AXISAIM, i+1) < 0) + if (PlayerInputDown(i+1, gc_aimforward) || PlayerJoyAxis(i+1, AXISAIM) < 0) { voteclient.playerinfo[i].selection--; pressed = true; } - if ((InputDown(gc_aimbackward, i+1) || JoyAxis(AXISAIM, i+1) > 0) && !pressed) + if ((PlayerInputDown(i+1, gc_aimbackward) || PlayerJoyAxis(i+1, AXISAIM) > 0) && !pressed) { voteclient.playerinfo[i].selection++; pressed = true; @@ -1710,7 +1657,7 @@ void Y_VoteTicker(void) if (voteclient.playerinfo[i].selection > 3) voteclient.playerinfo[i].selection = 0; - if ((InputDown(gc_accelerate, i+1) || JoyAxis(AXISMOVE, i+1) > 0) && !pressed) + if ((PlayerInputDown(i+1, gc_accelerate) || PlayerJoyAxis(i+1, AXISMOVE) > 0) && !pressed) { D_ModifyClientVote(consoleplayer, voteclient.playerinfo[i].selection, i); pressed = true; @@ -1784,8 +1731,8 @@ void Y_StartVote(void) I_Error("voteendtic is dirty"); #endif - widebgpatch = W_CachePatchName(((gametype == GT_MATCH) ? "BATTLSCW" : "INTERSCW"), PU_STATIC); - bgpatch = W_CachePatchName(((gametype == GT_MATCH) ? "BATTLSCR" : "INTERSCR"), PU_STATIC); + widebgpatch = W_CachePatchName(((gametype == GT_BATTLE) ? "BATTLSCW" : "INTERSCW"), PU_STATIC); + bgpatch = W_CachePatchName(((gametype == GT_BATTLE) ? "BATTLSCR" : "INTERSCR"), PU_STATIC); cursor = W_CachePatchName("M_CURSOR", PU_STATIC); cursor1 = W_CachePatchName("P1CURSOR", PU_STATIC); cursor2 = W_CachePatchName("P2CURSOR", PU_STATIC); @@ -1830,10 +1777,10 @@ void Y_StartVote(void) // set up the levelstring if (mapheaderinfo[votelevels[i][0]]->levelflags & LF_NOZONE || !mapheaderinfo[votelevels[i][0]]->zonttl[0]) { - if (mapheaderinfo[votelevels[i][0]]->actnum[0]) + if (mapheaderinfo[votelevels[i][0]]->actnum > 0) snprintf(levelinfo[i].str, sizeof levelinfo[i].str, - "%s %s", + "%s %d", mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->actnum); else snprintf(levelinfo[i].str, @@ -1843,10 +1790,10 @@ void Y_StartVote(void) } else { - if (mapheaderinfo[votelevels[i][0]]->actnum[0]) + if (mapheaderinfo[votelevels[i][0]]->actnum > 0) snprintf(levelinfo[i].str, sizeof levelinfo[i].str, - "%s %s %s", + "%s %s %d", mapheaderinfo[votelevels[i][0]]->lvlttl, mapheaderinfo[votelevels[i][0]]->zonttl, mapheaderinfo[votelevels[i][0]]->actnum); else snprintf(levelinfo[i].str, diff --git a/src/y_inter.h b/src/y_inter.h index 6162dc282..74a622963 100644 --- a/src/y_inter.h +++ b/src/y_inter.h @@ -1,6 +1,6 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- -// Copyright (C) 2004-2018 by Sonic Team Junior. +// Copyright (C) 2004-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -13,9 +13,15 @@ extern boolean usebuffer; void Y_IntermissionDrawer(void); void Y_Ticker(void); + void Y_StartIntermission(void); void Y_EndIntermission(void); +void Y_ConsiderScreenBuffer(void); +void Y_CleanupScreenBuffer(void); + +void Y_DetermineIntermissionType(void); + void Y_VoteDrawer(void); void Y_VoteTicker(void); void Y_StartVote(void); @@ -25,15 +31,10 @@ void Y_SetupVoteFinish(SINT8 pick, SINT8 level); typedef enum { int_none, - int_timeattack, // Time Attack - int_match, // Match - int_teammatch, // Team Match -// int_tag, // Tag - int_ctf, // CTF - int_spec, // Special Stage - int_nights, // NiGHTS into Dreams - int_nightsspec, // NiGHTS special stage - int_race, // Race - int_classicrace, // Competition + int_race, // Race + int_battle, // Battle + int_timeattack, // Time Attack } intertype_t; + extern intertype_t intertype; +extern intertype_t intermissiontypes[NUMGAMETYPES]; diff --git a/src/z_zone.c b/src/z_zone.c index b87a13106..2c7384c3d 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2018 by Sonic Team Junior. +// Copyright (C) 2006-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,6 +27,7 @@ #include "doomdef.h" #include "doomstat.h" +#include "r_picformats.h" #include "i_system.h" // I_GetFreeMem #include "i_video.h" // rendermode #include "z_zone.h" @@ -82,6 +83,59 @@ typedef struct memblock_s struct memblock_s *next, *prev; } ATTRPACK memblock_t; +// both the head and tail of the zone memory block list +static memblock_t head; + +// +// Function prototypes +// +static void Command_Memfree_f(void); +#ifdef ZDEBUG +static void Command_Memdump_f(void); +#endif + +// -------------------------- +// Zone memory initialisation +// -------------------------- + +/** Initialises zone memory. + * Used at game startup. + * + * \sa I_GetFreeMem, Command_Memfree_f, Command_Memdump_f + */ +void Z_Init(void) +{ + UINT32 total, memfree; + + memset(&head, 0x00, sizeof(head)); + + head.next = head.prev = &head; + + memfree = I_GetFreeMem(&total)>>20; + CONS_Printf("System memory: %uMB - Free: %uMB\n", total>>20, memfree); + + // Note: This allocates memory. Watch out. + COM_AddCommand("memfree", Command_Memfree_f); + +#ifdef ZDEBUG + COM_AddCommand("memdump", Command_Memdump_f); +#endif +} + + +// ---------------------- +// Zone memory allocation +// ---------------------- + +/** Returns the corresponding memblock_t for a given memory block. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * \param func A string containing the name of the function that called this, + * to be printed if the function I_Errors + * \return A pointer to the memblock_t for the given memory. + * \sa Z_Free, Z_ReallocAlign + */ #ifdef ZDEBUG #define Ptr2Memblock(s, f) Ptr2Memblock2(s, f, __FILE__, __LINE__) static memblock_t *Ptr2Memblock2(void *ptr, const char* func, const char *file, INT32 line) @@ -131,32 +185,12 @@ static memblock_t *Ptr2Memblock(void *ptr, const char* func) } -static memblock_t head; - -static void Command_Memfree_f(void); -#ifdef ZDEBUG -static void Command_Memdump_f(void); -#endif - -void Z_Init(void) -{ - UINT32 total, memfree; - - memset(&head, 0x00, sizeof(head)); - - head.next = head.prev = &head; - - memfree = I_GetFreeMem(&total)>>20; - CONS_Printf("System memory: %uMB - Free: %uMB\n", total>>20, memfree); - - // Note: This allocates memory. Watch out. - COM_AddCommand("memfree", Command_Memfree_f); - -#ifdef ZDEBUG - COM_AddCommand("memdump", Command_Memdump_f); -#endif -} - +/** Frees allocated memory. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * \sa Z_FreeTags + */ #ifdef ZDEBUG void Z_Free2(void *ptr, const char *file, INT32 line) #else @@ -183,11 +217,9 @@ void Z_Free(void *ptr) CONS_Debug(DBG_MEMORY, "Z_Free at %s:%d\n", file, line); #endif -#ifdef HAVE_BLUA // anything that isn't by lua gets passed to lua just in case. if (block->tag != PU_LUA) LUA_InvalidateUserdata(ptr); -#endif // TODO: if zdebugging, make sure no other block has a user // that is about to be freed. @@ -198,15 +230,19 @@ void Z_Free(void *ptr) // Free the memory and get rid of the block. free(block->real); - block->prev->next = block->next; - block->next->prev = block->prev; - free(block); #ifdef VALGRIND_DESTROY_MEMPOOL VALGRIND_DESTROY_MEMPOOL(block); #endif + block->prev->next = block->next; + block->next->prev = block->prev; + free(block); } -// malloc() that doesn't accept failure. +/** malloc() that doesn't accept failure. + * + * \param size Amount of memory to be allocated, in bytes. + * \return A pointer to the allocated memory. + */ static void *xm(size_t size) { const size_t padedsize = size+sizeof (size_t); @@ -224,10 +260,6 @@ static void *xm(size_t size) if (p == NULL) { -#if defined (_NDS) | defined (_PSP) - // Temporary-ish debugging measure - Command_Memfree_f(); -#endif I_Error("Out of memory allocating %s bytes", sizeu1(size)); } } @@ -235,10 +267,18 @@ static void *xm(size_t size) return p; } -// Z_Malloc -// You can pass Z_Malloc() a NULL user if the tag is less than -// PU_PURGELEVEL. - +/** The Z_MallocAlign function. + * Allocates a block of memory, adds it to a linked list so we can keep track of it. + * + * \param size Amount of memory to be allocated, in bytes. + * \param tag Purge tag. + * \param user The address of a pointer to the memory to be allocated. + * When the memory is freed by Z_Free later, + * the pointer at this address will then be automatically set to NULL. + * \param alignbits The alignment of the memory to be allocated, in bits. Can be 0. + * \note You can pass Z_Malloc() a NULL user if the tag is less than PU_PURGELEVEL. + * \sa Z_CallocAlign, Z_ReallocAlign + */ #ifdef ZDEBUG void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) @@ -275,13 +315,9 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) // The mem header lives 'sizeof (memhdr_t)' bytes before given. hdr = (memhdr_t *)((UINT8 *)given - sizeof *hdr); -#ifdef VALGRIND_CREATE_MEMPOOL - VALGRIND_CREATE_MEMPOOL(block, padsize, Z_calloc); +#ifdef HAVE_VALGRIND Z_calloc = false; #endif -#ifdef VALGRIND_MEMPOOL_ALLOC - VALGRIND_MEMPOOL_ALLOC(block, hdr, size + sizeof *hdr); -#endif block->next = head.next; block->prev = &head; @@ -299,6 +335,13 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) block->size = blocksize; block->realsize = size; +#ifdef VALGRIND_CREATE_MEMPOOL + VALGRIND_CREATE_MEMPOOL(block, padsize, Z_calloc); +#endif +//#ifdef VALGRIND_MEMPOOL_ALLOC +// VALGRIND_MEMPOOL_ALLOC(block, hdr, size + sizeof *hdr); +//#endif + hdr->id = ZONEID; hdr->block = block; @@ -318,6 +361,19 @@ void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) return given; } +/** The Z_CallocAlign function. + * Allocates a block of memory, adds it to a linked list so we can keep track of it. + * Unlike Z_MallocAlign, this also initialises the bytes to zero. + * + * \param size Amount of memory to be allocated, in bytes. + * \param tag Purge tag. + * \param user The address of a pointer to the memory to be allocated. + * When the memory is freed by Z_Free later, + * the pointer at this address will then be automatically set to NULL. + * \param alignbits The alignment of the memory to be allocated, in bits. Can be 0. + * \note You can pass Z_Calloc() a NULL user if the tag is less than PU_PURGELEVEL. + * \sa Z_MallocAlign, Z_ReallocAlign + */ #ifdef ZDEBUG void *Z_Calloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) #else @@ -334,10 +390,26 @@ void *Z_CallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) #endif } +/** The Z_ReallocAlign function. + * Reallocates a block of memory with a new size. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * If NULL, this function instead acts as a wrapper for Z_CallocAlign. + * \param size New size of memory block, in bytes. + * If zero, then the memory is freed and NULL is returned. + * \param tag New purge tag. + * \param user The address of a pointer to the memory to be reallocated. + * This can be a different user to the one originally assigned to the memory block. + * \param alignbits The alignment of the memory to be allocated, in bits. Can be 0. + * \return A pointer to the reallocated memory. Can be NULL if memory was freed. + * \note You can pass Z_Realloc() a NULL user if the tag is less than PU_PURGELEVEL. + * \sa Z_MallocAlign, Z_CallocAlign + */ #ifdef ZDEBUG void *Z_Realloc2(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) #else -void *Z_ReallocAlign(void *ptr, size_t size,INT32 tag, void *user, INT32 alignbits) +void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits) #endif { void *rez; @@ -404,6 +476,11 @@ void *Z_ReallocAlign(void *ptr, size_t size,INT32 tag, void *user, INT32 alignb return rez; } +/** Frees all memory for a given set of tags. + * + * \param lowtag The lowest tag to consider. + * \param hightag The highest tag to consider. + */ void Z_FreeTags(INT32 lowtag, INT32 hightag) { memblock_t *block, *next; @@ -418,22 +495,51 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) } } -// -// Z_CheckMemCleanup -// -// TODO: Currently blocks >= PU_PURGELEVEL are freed every -// CLEANUPCOUNT. It might be better to keep track of -// the total size of all purgable memory and free it when the -// size exceeds some value. -// -// This was in Z_Malloc, but was freeing data at -// unsafe times. Now it is only called when it is safe -// to cleanup memory. +// ----------------- +// Utility functions +// ----------------- +// for renderer switching +boolean needpatchflush = false; +boolean needpatchrecache = false; + +// flush all patches from memory +void Z_FlushCachedPatches(void) +{ + CONS_Debug(DBG_RENDER, "Z_FlushCachedPatches()...\n"); + Z_FreeTag(PU_PATCH); + Z_FreeTag(PU_HUDGFX); + Z_FreeTag(PU_HWRPATCHINFO); + Z_FreeTag(PU_HWRMODELTEXTURE); + Z_FreeTag(PU_HWRCACHE); + Z_FreeTag(PU_HWRCACHE_UNLOCKED); + Z_FreeTag(PU_HWRPATCHINFO_UNLOCKED); + Z_FreeTag(PU_HWRMODELTEXTURE_UNLOCKED); +} + +void Z_PreparePatchFlush(void) +{ + CONS_Debug(DBG_RENDER, "Z_PreparePatchFlush()...\n"); +#ifdef ROTSPRITE + R_FreeAllRotSprite(); +#endif +} + +// starting value of nextcleanup #define CLEANUPCOUNT 2000 +// number of function calls left before next cleanup static INT32 nextcleanup = CLEANUPCOUNT; +/** This was in Z_Malloc, but was freeing data at + * unsafe times. Now it is only called when it is safe + * to cleanup memory. + * + * \todo Currently blocks >= PU_PURGELEVEL are freed every + * CLEANUPCOUNT. It might be better to keep track of + * the total size of all purgable memory and free it when the + * size exceeds some value. + */ void Z_CheckMemCleanup(void) { if (nextcleanup-- == 0) @@ -549,10 +655,21 @@ void Z_CheckHeap(INT32 i) } } +// ------------------------ +// Zone memory modification +// ------------------------ + +/** Changes a memory block's purge tag. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * \param tag The new tag. + * \sa Z_SetUser + */ #ifdef PARANOIA void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line) #else -void Z_ChangeTag2(void *ptr, INT32 tag) +void Z_ChangeTag(void *ptr, INT32 tag) #endif { memblock_t *block; @@ -594,98 +711,17 @@ void Z_ChangeTag2(void *ptr, INT32 tag) block->tag = tag; } -/** Calculates memory usage for a given set of tags. - * \param lowtag The lowest tag to consider. - * \param hightag The highest tag to consider. - * \return Number of bytes currently allocated in the heap for the - * given tags. - * \sa Z_TagUsage +/** Changes a memory block's user. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * \param newuser The new user for the memory block. + * \sa Z_ChangeTag */ -size_t Z_TagsUsage(INT32 lowtag, INT32 hightag) -{ - size_t cnt = 0; - memblock_t *rover; - - for (rover = head.next; rover != &head; rover = rover->next) - { - if (rover->tag < lowtag || rover->tag > hightag) - continue; - cnt += rover->size + sizeof *rover; - } - - return cnt; -} - -size_t Z_TagUsage(INT32 tagnum) -{ - return Z_TagsUsage(tagnum, tagnum); -} - -void Command_Memfree_f(void) -{ - UINT32 freebytes, totalbytes; - - Z_CheckHeap(-1); - CONS_Printf("\x82%s", M_GetText("Memory Info\n")); - CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TagsUsage(0, INT32_MAX)>>10)); - CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10)); - CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10)); - CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10)); - CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10)); - CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10)); - CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10)); - CONS_Printf(M_GetText("All purgable : %7s KB\n"), - sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10)); - -#ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) - { - CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); - CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); - CONS_Printf(M_GetText("HW Texture cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); - CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); - } -#endif - - CONS_Printf("\x82%s", M_GetText("System Memory Info\n")); - freebytes = I_GetFreeMem(&totalbytes); - CONS_Printf(M_GetText(" Total physical memory: %7u KB\n"), totalbytes>>10); - CONS_Printf(M_GetText("Available physical memory: %7u KB\n"), freebytes>>10); -} - -#ifdef ZDEBUG -static void Command_Memdump_f(void) -{ - memblock_t *block; - INT32 mintag = 0, maxtag = INT32_MAX; - INT32 i; - - if ((i = COM_CheckParm("-min"))) - mintag = atoi(COM_Argv(i + 1)); - - if ((i = COM_CheckParm("-max"))) - maxtag = atoi(COM_Argv(i + 1)); - - for (block = head.next; block != &head; block = block->next) - if (block->tag >= mintag && block->tag <= maxtag) - { - char *filename = strrchr(block->ownerfile, PATHSEP[0]); - CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size), sizeu2(block->realsize), filename ? filename + 1 : block->ownerfile, block->ownerline); - } -} -#endif - -// Creates a copy of a string. -char *Z_StrDup(const char *s) -{ - return strcpy(ZZ_Alloc(strlen(s) + 1), s); -} - - #ifdef PARANOIA void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line) #else -void Z_SetUser2(void *ptr, void **newuser) +void Z_SetUser(void *ptr, void **newuser) #endif { memblock_t *block; @@ -717,3 +753,107 @@ void Z_SetUser2(void *ptr, void **newuser) block->user = (void*)newuser; *newuser = ptr; } + +// ----------------- +// Zone memory usage +// ----------------- + +/** Calculates memory usage for a given set of tags. + * + * \param lowtag The lowest tag to consider. + * \param hightag The highest tag to consider. + * \return Number of bytes currently allocated in the heap for the + * given tags. + */ +size_t Z_TagsUsage(INT32 lowtag, INT32 hightag) +{ + size_t cnt = 0; + memblock_t *rover; + + for (rover = head.next; rover != &head; rover = rover->next) + { + if (rover->tag < lowtag || rover->tag > hightag) + continue; + cnt += rover->size + sizeof *rover; + } + + return cnt; +} + +// ----------------------- +// Miscellaneous functions +// ----------------------- + +/** The function called by the "memfree" console command. + * Prints the memory being used by each part of the game to the console. + */ +static void Command_Memfree_f(void) +{ + UINT32 freebytes, totalbytes; + + Z_CheckHeap(-1); + CONS_Printf("\x82%s", M_GetText("Memory Info\n")); + CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TotalUsage()>>10)); + CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10)); + CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10)); + CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10)); + CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10)); + CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10)); + CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10)); + CONS_Printf(M_GetText("All purgable : %7s KB\n"), + sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10)); + +#ifdef HWRENDER + if (rendermode == render_opengl) + { + CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); + CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); + CONS_Printf(M_GetText("HW Texture cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); + CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); + CONS_Printf(M_GetText("HW model textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRMODELTEXTURE)>>10)); + CONS_Printf(M_GetText("HW Texture used : %7d KB\n"), HWR_GetTextureUsed()>>10); + } +#endif + + CONS_Printf("\x82%s", M_GetText("System Memory Info\n")); + freebytes = I_GetFreeMem(&totalbytes); + CONS_Printf(M_GetText(" Total physical memory: %7u KB\n"), totalbytes>>10); + CONS_Printf(M_GetText("Available physical memory: %7u KB\n"), freebytes>>10); +} + +#ifdef ZDEBUG +/** The function called by the "memdump" console command. + * Prints zone memory debugging information (i.e. tag, size, location in code allocated). + * Can be all memory allocated in game, or between a set of tags (if -min/-max args used). + * This command is available only if ZDEBUG is enabled. + */ +static void Command_Memdump_f(void) +{ + memblock_t *block; + INT32 mintag = 0, maxtag = INT32_MAX; + INT32 i; + + if ((i = COM_CheckParm("-min"))) + mintag = atoi(COM_Argv(i + 1)); + + if ((i = COM_CheckParm("-max"))) + maxtag = atoi(COM_Argv(i + 1)); + + for (block = head.next; block != &head; block = block->next) + if (block->tag >= mintag && block->tag <= maxtag) + { + char *filename = strrchr(block->ownerfile, PATHSEP[0]); + CONS_Printf("[%3d] %s (%s) bytes @ %s:%d\n", block->tag, sizeu1(block->size), sizeu2(block->realsize), filename ? filename + 1 : block->ownerfile, block->ownerline); + } +} +#endif + +/** Creates a copy of a string. + * + * \param s The string to be copied. + * \return A copy of the string, allocated in zone memory. + */ +char *Z_StrDup(const char *s) +{ + return strcpy(ZZ_Alloc(strlen(s) + 1), s); +} diff --git a/src/z_zone.h b/src/z_zone.h index 1424a3782..dfb2f6c71 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2020 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -30,96 +30,124 @@ //#define ZDEBUG // -// ZONE MEMORY -// PU - purge tags. -// Tags < PU_LEVEL are not purged until freed explicitly. -#define PU_STATIC 1 // static entire execution time -#define PU_LUA 2 // static entire execution time -- used by lua so it doesn't get caught in loops forever +// Purge tags +// +// Now they are an enum! -- Monster Iestyn 15/02/18 +// +enum +{ + // Tags < PU_LEVEL are not purged until freed explicitly. + PU_STATIC = 1, // static entire execution time + PU_LUA = 2, // static entire execution time -- used by lua so it doesn't get caught in loops forever -#define PU_SOUND 11 // static while playing -#define PU_MUSIC 12 // static while playing -#define PU_HUDGFX 13 // static until WAD added + PU_SOUND = 11, // static while playing + PU_MUSIC = 12, // static while playing + PU_HUDGFX = 13, // static until WAD added + PU_PATCH = 14, // static until renderer change -#define PU_HWRPATCHINFO 21 // Hardware GLPatch_t struct for OpenGL texture cache -#define PU_HWRPATCHCOLMIPMAP 22 // Hardware GLMipmap_t struct colromap variation of patch + PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache + PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch + PU_HWRMODELTEXTURE = 23, // Hardware model texture -#define PU_HWRCACHE 48 // static until unlocked -#define PU_CACHE 49 // static until unlocked + PU_HWRCACHE = 48, // static until unlocked + PU_CACHE = 49, // static until unlocked -// Tags s.t. PU_LEVEL <= tag < PU_PURGELEVEL are purged at level start -#define PU_LEVEL 50 // static until level exited -#define PU_LEVSPEC 51 // a special thinker in a level -#define PU_HWRPLANE 52 + // Tags s.t. PU_LEVEL <= tag < PU_PURGELEVEL are purged at level start + PU_LEVEL = 50, // static until level exited + PU_LEVSPEC = 51, // a special thinker in a level + PU_HWRPLANE = 52, // if ZPLANALLOC is enabled in hw_bsp.c, this is used to alloc polygons for OpenGL -// Tags >= PU_PURGELEVEL are purgable whenever needed -#define PU_PURGELEVEL 100 -#define PU_CACHE_UNLOCKED 101 -#define PU_HWRCACHE_UNLOCKED 102 // 'second-level' cache for graphics - // stored in hardware format and downloaded as needed -#define PU_HWRPATCHINFO_UNLOCKED 103 + // Tags >= PU_PURGELEVEL are purgable whenever needed + PU_PURGELEVEL = 100, // Note: this is never actually used as a tag + PU_CACHE_UNLOCKED = 101, // Note: unused + PU_HWRCACHE_UNLOCKED = 102, // 'unlocked' PU_HWRCACHE memory: + // 'second-level' cache for graphics + // stored in hardware format and downloaded as needed + PU_HWRPATCHINFO_UNLOCKED = 103, // 'unlocked' PU_HWRPATCHINFO memory + PU_HWRMODELTEXTURE_UNLOCKED = 104, // 'unlocked' PU_HWRMODELTEXTURE memory +}; +// +// Zone memory initialisation +// void Z_Init(void); -void Z_FreeTags(INT32 lowtag, INT32 hightag); -void Z_CheckMemCleanup(void); -void Z_CheckHeap(INT32 i); -#ifdef PARANOIA -void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line); -#else -void Z_ChangeTag2(void *ptr, INT32 tag); -#endif -#ifdef PARANOIA -void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line); -#else -void Z_SetUser2(void *ptr, void **newuser); -#endif +// +// Zone memory allocation +// +// enable ZDEBUG to get the file + line the functions were called from +// for ZZ_Alloc, see doomdef.h +// +// Z_Free and alloc with alignment #ifdef ZDEBUG -#define Z_Free(p) Z_Free2(p, __FILE__, __LINE__) -void Z_Free2(void *ptr, const char *file, INT32 line); -#define Z_Malloc(s,t,u) Z_Malloc2(s, t, u, 0, __FILE__, __LINE__) -#define Z_MallocAlign(s,t,u,a) Z_Malloc2(s, t, u, a, __FILE__, __LINE__) -void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(1); -#define Z_Calloc(s,t,u) Z_Calloc2(s, t, u, 0, __FILE__, __LINE__) -#define Z_CallocAlign(s,t,u,a) Z_Calloc2(s, t, u, a, __FILE__, __LINE__) -void *Z_Calloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(1); -#define Z_Realloc(p,s,t,u) Z_Realloc2(p, s, t, u, 0, __FILE__, __LINE__) +#define Z_Free(p) Z_Free2(p, __FILE__, __LINE__) +#define Z_MallocAlign(s,t,u,a) Z_Malloc2(s, t, u, a, __FILE__, __LINE__) +#define Z_CallocAlign(s,t,u,a) Z_Calloc2(s, t, u, a, __FILE__, __LINE__) #define Z_ReallocAlign(p,s,t,u,a) Z_Realloc2(p,s, t, u, a, __FILE__, __LINE__) +void Z_Free2(void *ptr, const char *file, INT32 line); +void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(1); +void *Z_Calloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(1); void *Z_Realloc2(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) FUNCALLOC(2); #else void Z_Free(void *ptr); void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) FUNCALLOC(1); -#define Z_Malloc(s,t,u) Z_MallocAlign(s, t, u, 0) void *Z_CallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) FUNCALLOC(1); -#define Z_Calloc(s,t,u) Z_CallocAlign(s, t, u, 0) -void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits) FUNCALLOC(2) ; -#define Z_Realloc(p, s,t,u) Z_ReallocAlign(p, s, t, u, 0) +void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits) FUNCALLOC(2); #endif -size_t Z_TagUsage(INT32 tagnum); -size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); +// Alloc with no alignment +#define Z_Malloc(s,t,u) Z_MallocAlign(s, t, u, 0) +#define Z_Calloc(s,t,u) Z_CallocAlign(s, t, u, 0) +#define Z_Realloc(p,s,t,u) Z_ReallocAlign(p, s, t, u, 0) -char *Z_StrDup(const char *in); +// Free all memory by tag +// these don't give line numbers for ZDEBUG currently though +// (perhaps this should be changed in future?) +#define Z_FreeTag(tagnum) Z_FreeTags(tagnum, tagnum) +void Z_FreeTags(INT32 lowtag, INT32 hightag); -// This is used to get the local FILE : LINE info from CPP -// prior to really call the function in question. +// +// Utility functions +// +void Z_CheckMemCleanup(void); +void Z_CheckHeap(INT32 i); + +// +// Zone memory modification +// +// enable PARANOIA to get the file + line the functions were called from // #ifdef PARANOIA #define Z_ChangeTag(p,t) Z_ChangeTag2(p, t, __FILE__, __LINE__) +#define Z_SetUser(p,u) Z_SetUser2(p, u, __FILE__, __LINE__) +void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line); +void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line); #else -#define Z_ChangeTag(p,t) Z_ChangeTag2(p, t) +void Z_ChangeTag(void *ptr, INT32 tag); +void Z_SetUser(void *ptr, void **newuser); #endif -#ifdef PARANOIA -#define Z_SetUser(p,u) Z_SetUser2(p, u, __FILE__, __LINE__) -#else -#define Z_SetUser(p,u) Z_SetUser2(p, u) -#endif +// +// Zone memory usage +// +// Note: These give the memory used in bytes, +// shift down by 10 to convert to KB +// +#define Z_TagUsage(tagnum) Z_TagsUsage(tagnum, tagnum) +size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); +#define Z_TotalUsage() Z_TagsUsage(0, INT32_MAX) -#ifdef _NDS ///TODO: need a lock reference system -#define Z_Unlock(p) Z_ChangeTag(p, PU_CACHE_UNLOCKED) -#else -#define Z_Unlock(p) (void)p -#endif +// +// Miscellaneous functions +// +char *Z_StrDup(const char *in); +#define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed + +// For renderer switching +extern boolean needpatchflush; +extern boolean needpatchrecache; +void Z_FlushCachedPatches(void); +void Z_PreparePatchFlush(void); #endif diff --git a/tools/flatb/Makefile b/tools/flatb/Makefile new file mode 100644 index 000000000..2134973e6 --- /dev/null +++ b/tools/flatb/Makefile @@ -0,0 +1,9 @@ +.PHONY : all clean + +all : flatb + +flatb.exe : flatb.c + i686-w64-mingw32-gcc $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) $(LDLIBS) -o $@ $< + +clean : + $(RM) flatb flatb.exe diff --git a/tools/flatb/flatb.c b/tools/flatb/flatb.c new file mode 100644 index 000000000..edc089232 --- /dev/null +++ b/tools/flatb/flatb.c @@ -0,0 +1,566 @@ +#define HELP \ +"Usage: flatb WAD-file list-file" "\n"\ +"Replace flats and textures by name in a DOOM WAD." "\n"\ +"\n"\ +"list-file may have the following format:" "\n"\ +"\n"\ +"GFZFLR01 GFZFLR02" "\n"\ +"# Comment" "\n"\ +"GFZROCK GFZBLOCK" "\n"\ +"\n"\ +"The first name and second name may be delimited by any whitespace." "\n"\ +"\n"\ +"Copyright 2019 James R." "\n"\ +"All rights reserved." "\n" + +/* +Copyright 2019 James R. +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 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 OWNER 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. +*/ + +#include +#include +#include +#include +#include +#include + +#define cchar const char +#define cvoid const void + +#define LONG int32_t + +#define va_inline( __ap,__last, ... )\ +(\ + va_start (__ap,__last),\ + __VA_ARGS__,\ + va_end (__ap)\ +) + +#define DELIM "\t\n\r " + +typedef struct +{ + FILE * fp; + cchar * filename; +} +File; + +int (*le32)(cvoid *); + +void +Pexit (int c, cchar *s, ...) +{ + va_list ap; + va_inline (ap, s, + + vfprintf(stderr, s, ap) + + ); + exit(c); +} + +void +Prexit (cchar *pr, ...) +{ + va_list ap; + va_inline (ap, pr, + + vfprintf(stderr, pr, ap) + + ); + perror(""); + exit(-1); +} + +void +Fopen (File *f, cchar *filename, const char *mode) +{ + FILE *fp; + if (!( fp = fopen(filename, mode) )) + Prexit("%s", filename); + f->filename = filename; + f->fp = fp; +} + +void +Ferr (File *f) +{ + if (ferror(f->fp)) + Prexit("%s", f->filename); +} + +char * +Fgets (File *f, int b, char *p) +{ + if (!( p = fgets(p, b, f->fp) )) + Ferr(f); + return p; +} + +void +Fread (File *f, int b, void *p) +{ + if (fread(p, 1, b, f->fp) < b) + Ferr(f); +} + +void +Fwrite (File *f, int b, cvoid *s) +{ + if (fwrite(s, 1, b, f->fp) < b) + Ferr(f); +} + +void +Fseek (File *f, long o) +{ + if (fseek(f->fp, o, SEEK_SET) == -1) + Prexit("%s", f->filename); +} + +void * +Malloc (int b) +{ + void *p; + if (!( p = malloc(b) )) + Prexit("%d", b); + return p; +} + +void * +Calloc (int c, int b) +{ + void *p; + if (!( p = calloc(c, b) )) + Prexit("(%d)%d", c, b); + return p; +} + +void +Reallocp (void *pp, int b) +{ + void *p; + if (!( p = realloc((*(void **)pp), b) )) + Prexit("%d", b); + (*(void **)pp) = p; +} + +void +strucpy (char *p, cchar *s, int n) +{ + int c; + int i; + for (i = 0; i < n && ( c = s[i] ); ++i) + p[i] = toupper(c); +} + +int +e32 (cvoid *s) +{ + unsigned int c; + c = *(LONG *)s; + return ( + ( c >> 24 ) | + (( c >> 8 )& 0x00FF00 )| + (( c << 8 )& 0xFF0000 )| + ( c << 24 ) + ); +} + +int +n32 (cvoid *s) +{ + return *(LONG *)s; +} + +void +Ie () +{ + int c; + c = 1; + if (*(char *)&c == 1) + le32 = n32; + else + le32 = e32; +} + +File wad_file; +File list_file; + +int list_c; +char *** list_v; + +char * directory; +char * lump; +int lumpsize; + +char * sectors; +int sectors_c; + +char * sides; +int sides_c; + +int st_floors; +int st_ceilings; +int st_sectors; + +int st_sides; +int st_uppers; +int st_mids; +int st_lowers; + +/* this is horseshit */ +char * old; +char * new; +int did; + +void +Itable () +{ + char a[1024]; + + char ***ttt; + char ***ppp; + + char **pp; + + int c; + + while (Fgets(&list_file, sizeof a, a)) + { + c = a[0]; + if (!( + c == '\n' || + c == '#' + )) + { + list_c++; + } + } + + rewind(list_file.fp); + + list_v = Calloc(list_c, sizeof (char **)); + for ( + ttt = ( ppp = list_v ) + list_c; + ppp < ttt; + ++ppp + ) + { + (*ppp) = pp = Calloc(2, sizeof (char *)); + pp[0] = Malloc(9); + pp[1] = Malloc(9); + } +} + +void +Iwad () +{ + char buf[12]; + + char * t; + char * p; + int map; + + char *sector_p; + char * side_p; + + int n; + int h; + + Fread(&wad_file, 12, buf); + if ( + memcmp(buf, "IWAD", 4) != 0 && + memcmp(buf, "PWAD", 4) != 0 + ) + { + Pexit(-1,"%s: Not a WAD\n", wad_file.filename); + } + + Fseek(&wad_file, (*le32)(&buf[8])); + + n = (*le32)(&buf[4]) * 8; + h = n / 9; + n *= 2; + directory = Malloc(n); + /* minimum number of lumps for a map */ + sectors = Malloc(h); + sides = Malloc(h); + + Fread(&wad_file, n, directory); + + sector_p = sectors; + side_p = sides; + map = 3; + for (t = ( p = directory ) + n; p < t; p += 16) + { + /* looking for SECTORS? Hopefully order doesn't matter in real world. */ + /* also search for fucking SIDES MY SIDES AAAAAAAAAA */ + switch (map) + { + case 0: + case 2: + if (strncmp(&p[8], "SECTORS", 8) == 0) + { + /* copy file offset and size */ + memcpy(sector_p, p, 8); + sector_p += 8; + sectors_c++; + map |= 1; + } + case 1: + if (strncmp(&p[8], "SIDEDEFS", 8) == 0) + { + memcpy(side_p, p, 8); + side_p += 8; + sides_c++; + map |= 2; + } + } + if (map == 3) + { + /* MAP marker */ + if (p[13] == '\0' && strncmp(&p[8], "MAP", 3) == 0) + map = 0; + } + } +} + +void +Fuckyou (char *p, int f, int *st) +{ + if (strncmp(p, old, 8) == 0) + { + strncpy(p, new, 8); + (*st)++; + did |= f; + } +} + +void +Epic (char *p, char *t) +{ + char *top; + char *bot; + int i; + /* oh hi magic number! */ + for (; p < t; p += 26) + { + bot = &p [4]; + top = &p[12]; + did = 0; + for (i = 0; i < list_c; ++i) + { + old = list_v[i][0]; + new = list_v[i][1]; + switch (did) + { + case 0: + case 2: + Fuckyou(bot, 1, &st_floors); + case 1: + Fuckyou(top, 2, &st_ceilings); + } + if (did == 3) + break; + } + if (did) + st_sectors++; + } +} + +void +Epic2 (char *p, char *t) +{ + char *top; + char *mid; + char *bot; + int i; + for (; p < t; p += 30) + { + top = &p [4]; + bot = &p[12]; + mid = &p[20]; + did = 0; + for (i = 0; i < list_c; ++i) + { + old = list_v[i][0]; + new = list_v[i][1]; + switch (did) + { + case 0: + case 2: + case 4: + case 6: + Fuckyou(top, 1, &st_uppers); + case 1: + case 5: + Fuckyou(mid, 2, &st_mids); + case 3: + Fuckyou(bot, 4, &st_lowers); + } + if (did == 7) + break; + } + if (did) + st_sides++; + } +} + +void +Fuck (char *p, int c, void (*fn)(char *,char *)) +{ + char *t; + int offs; + int size; + for (t = p + c * 8; p < t; p += 8) + { + offs = (*le32)(p); + size = (*le32)(p + 4); + if (lumpsize < size) + { + Reallocp(&lump, size); + lumpsize = size; + } + Fseek(&wad_file, offs); + Fread(&wad_file, size, lump); + (*fn)(lump, lump + size); + Fseek(&wad_file, offs); + Fwrite(&wad_file, size, lump); + } +} + +void +Awad () +{ + Fuck (sectors, sectors_c, Epic); + Fuck (sides, sides_c, Epic2); +} + +void +Readtable () +{ + char a[1024]; + + int s; + char *old; + char *new; + + int c; + + s = 0; + + while (Fgets(&list_file, sizeof a, a)) + { + c = a[0]; + if (!( + c == '\n' || + c == '#' + )) + { + if ( + ( old = strtok(a, DELIM) ) && + ( new = strtok(0, DELIM) ) + ) + { + strucpy(list_v[s][0], old, 8); + strucpy(list_v[s][1], new, 8); + ++s; + } + } + } +} + +void +Cleanup () +{ + char ***ttt; + char ***ppp; + + char **pp; + + free(lump); + free(sides); + free(sectors); + free(directory); + + if (list_v) + { + for ( + ttt = ( ppp = list_v ) + list_c; + ppp < ttt && ( pp = (*ppp) ); + ++ppp + ) + { + free(pp[0]); + free(pp[1]); + free(pp); + } + free(list_v); + } +} + +int +main (int ac, char **av) +{ + int n; + + if (ac < 3) + Pexit(0,HELP); + + Fopen (& wad_file, av[1], "rb+"); + Fopen (&list_file, av[2], "r"); + + if (atexit(Cleanup) != 0) + Pexit(-1,"Failed to register cleanup function.\n"); + + Itable(); + Readtable(); + + Ie(); + + Iwad(); + Awad(); + + printf( + "%5d sectors changed.\n" + "%5d floors.\n" + "%5d ceilings.\n" + "\n" + "%5d sides.\n" + "%5d upper textures.\n" + "%5d mid textures.\n" + "%5d lower textures.\n", + + st_sectors, + + st_floors, + st_ceilings, + + st_sides, + + st_uppers, + st_mids, + st_lowers); + + return 0; +} diff --git a/tools/masterserver/.gitignore b/tools/masterserver/.gitignore index 9f45745a3..8ae879eec 100644 --- a/tools/masterserver/.gitignore +++ b/tools/masterserver/.gitignore @@ -1,4 +1,4 @@ /client /server -/server.log -/*.o +/*.log +/*.o \ No newline at end of file diff --git a/tools/masterserver/ipcs.h b/tools/masterserver/ipcs.h index b9dc52fdf..4e144f4a5 100644 --- a/tools/masterserver/ipcs.h +++ b/tools/masterserver/ipcs.h @@ -140,8 +140,8 @@ typedef struct char port[8]; char name[32]; INT32 room; - char key[32]; // Secret key for linking dedicated servers to accounts char version[8]; // format is: x.yy.z (like 1.30.2 or 1.31) + char key[32]; // Secret key for linking dedicated servers to accounts } ATTRPACK msg_server_t; typedef struct diff --git a/tools/masterserver/masterserver.sh b/tools/masterserver/masterserver.sh index 9b1adb128..fe4ba0071 100755 --- a/tools/masterserver/masterserver.sh +++ b/tools/masterserver/masterserver.sh @@ -5,9 +5,10 @@ # Get LSB functions . /lib/lsb/init-functions -. /etc/default/rcS +#. /etc/default/rcS -SRB2MS=/usr/local/bin/masterserver +#SRB2MS=/usr/local/bin/masterserver +SRB2MS=./server SRB2MS_PORT=28900 # Check that the package is still installed @@ -15,11 +16,9 @@ SRB2MS_PORT=28900 case "$1" in start) - log_begin_msg "Starting SRB2MS..." + log_begin_msg "Starting SRB2MS...\n" umask 002 - if start-stop-daemon --start \ - --exec $SRB2MS \ - -- $SRB2MS_PORT; then + if exec $SRB2MS $SRB2MS_PORT & then log_end_msg 0 else log_end_msg $? @@ -27,11 +26,11 @@ case "$1" in ;; stop) - log_begin_msg "Stopping SRB2MS..." - if start-stop-daemon --stop --exec $SRB2MS; then - log_end_msg 0 + log_begin_msg "Stopping SRB2MS...\n" + if killall $SRB2MS -q & then + log_end_msg 0 else - log_end_msg $? + log_end_msg $? fi ;; @@ -40,7 +39,7 @@ case "$1" in ;; *) - e cho "Usage: /etc/init.d/masterserver {start|stop|restart|force-reload}" + echo "Usage: $0 {start|stop|restart|force-reload}" exit 1 ;; esac diff --git a/tools/masterserver/server.cpp b/tools/masterserver/server.cpp index b7ed0d6b4..d00205301 100644 --- a/tools/masterserver/server.cpp +++ b/tools/masterserver/server.cpp @@ -86,7 +86,7 @@ typedef struct //============================================================================= -#define HOSTNAME "loopback" +#define HOSTNAME "localhost" #define USER "srb2_ms" #define PASSWORD "gLRDRb7WgLRDRb7W" #define DATABASE "srb2_ms" @@ -291,17 +291,17 @@ void MySQL_AddServer(const char *ip, const char *port, const char *name, const c char checkquery[500]; char updatequery[5000]; char queryp1[5000] = "INSERT INTO `ms_servers` (`name`,`ip`,`port`,`version`,`timestamp`,`room`,`key`) VALUES ('%s','%s','%s','%s','%ld','%d','%s')"; - char checkqueryp1[500] = "SELECT room_override FROM `ms_servers` WHERE `ip` = '%s'"; + char checkqueryp1[500] = "SELECT room_override FROM `ms_servers` WHERE `ip` = '%s' AND `port` = '%s'"; char updatequeryp1[5000]; if(firstadd) { logPrintf(logfile, "First add.\n"); - strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `delisted` = '0', `key` = '%s' WHERE `ip` = '%s'"); + strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `delisted` = '0', `key` = '%s' WHERE `ip` = '%s' AND `port` = '%s'"); } else { logPrintf(logfile, "Update ping.\n"); - strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `key` = '%s' WHERE `ip` = '%s' AND `delisted` = '0'"); + strcpy(updatequeryp1, "UPDATE `ms_servers` SET `name` = '%s', `port` = '%s', `version` = '%s', timestamp = '%ld', upnow = '1', `room` = '%d', `key` = '%s' WHERE `ip` = '%s' AND `port` = '%s' AND `delisted` = '0'"); } MySQL_Conn(false); mysql_real_escape_string(conn, escapedName, name, (unsigned long)strlen(name)); @@ -314,10 +314,10 @@ void MySQL_AddServer(const char *ip, const char *port, const char *name, const c logPrintf(errorfile, "IP %s tried to use the private room %d! THIS SHOULD NOT HAPPEN\n", ip, room); return; } - sprintf(checkquery, checkqueryp1, ip); + sprintf(checkquery, checkqueryp1, ip, port); time_t timestamp; timestamp = time (NULL); - logPrintf(logfile, "Checking for existing servers in table with the same IP...\n"); + logPrintf(logfile, "Checking for existing servers in table with the same IP and port...\n"); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", checkquery); if(mysql_query(conn, checkquery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); @@ -341,9 +341,9 @@ void MySQL_AddServer(const char *ip, const char *port, const char *name, const c if(atoi(row[0]) != 0) room = atoi(row[0]); mysql_free_result(res); - logPrintf(logfile, "Server's IP already exists, so let's just update it instead...\n"); + logPrintf(logfile, "Server's IP and port already exists, so let's just update it instead...\n"); logPrintf(logfile, "Updating Server Data for %s\n", ip); - sprintf(updatequery, updatequeryp1, escapedName, escapedPort, escapedVersion, timestamp, room, escapedKey, ip); + sprintf(updatequery, updatequeryp1, escapedName, escapedPort, escapedVersion, timestamp, room, escapedKey, ip, port); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", updatequery); if(mysql_query(conn, updatequery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); @@ -619,10 +619,10 @@ void MySQL_ListServServers(UINT32 id, UINT32 type, const char *ip) { void MySQL_RemoveServer(char *ip, char *port, char *name, char *version) { char escapedName[255]; char updatequery[5000]; - char updatequeryp1[5000] = "UPDATE `ms_servers` SET upnow = '0' WHERE `ip` = '%s' AND `permanent` = '0'"; + char updatequeryp1[5000] = "UPDATE `ms_servers` SET upnow = '0' WHERE `ip` = '%s' AND `port` = '%s' AND `permanent` = '0'"; MySQL_Conn(false); mysql_real_escape_string(conn, escapedName, name, (unsigned long)strlen(name)); - sprintf(updatequery, updatequeryp1, ip); + sprintf(updatequery, updatequeryp1, ip, port); logPrintf(mysqlfile, "Executing MySQL Query: %s\n", updatequery); if(mysql_query(conn, updatequery)) { logPrintf(errorfile, "MYSQL ERROR: %s\n", mysql_error(conn)); @@ -841,6 +841,10 @@ static void addServer(int id, char *buffer, bool firstadd) info->port[sizeof (info->port)-1] = '\0'; info->name[sizeof (info->name)-1] = '\0'; info->version[sizeof (info->version)-1] = '\0'; + + logPrintf(logfile, "addServer(): Version = \"%s\"\n", info->version); + logPrintf(logfile, "addServer(): Key = \"%s\"\n", info->key); + // retrieve the true ip of the server strcpy(info->ip, server_socket.getClientIP(id)); //strcpy(info->port, server_socket.getClientPort(id)); @@ -995,7 +999,7 @@ int main(int argc, char *argv[]) if (server_socket.listen(argv[1]) < 0) { - fprintf(stderr, "Error while initializing the server\n"); + fprintf(stderr, "Error while initializing the server; port being used! Try killing the other Master Server.\n"); exit(2); } diff --git a/tools/masterserver/structure.sql b/tools/masterserver/structure.sql index 3cc2cb15b..013c22383 100644 --- a/tools/masterserver/structure.sql +++ b/tools/masterserver/structure.sql @@ -13,8 +13,8 @@ SET time_zone = "+00:00"; -- Database: `srb2ms` -- -CREATE DATABASE IF NOT EXISTS `srb2ms` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; -USE `srb2ms`; +CREATE DATABASE IF NOT EXISTS `srb2_ms` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; +USE `srb2_ms`; -- -------------------------------------------------------- @@ -25,8 +25,8 @@ USE `srb2ms`; CREATE TABLE `ms_bans` ( `bid` int(11) DEFAULT NULL, - `ipstart` int(11) DEFAULT NULL, - `ipend` int(11) DEFAULT NULL, + `ipstart` int(10) unsigned DEFAULT NULL, + `ipend` int(10) unsigned DEFAULT NULL, `full_endtime` int(11) DEFAULT NULL, `permanent` tinyint(1) DEFAULT NULL, `hostonly` tinyint(1) DEFAULT NULL, @@ -63,19 +63,19 @@ INSERT INTO `ms_rooms` (`room_id`, `title`, `motd`, `visible`, `order`, `private -- CREATE TABLE `ms_servers` ( - `sid` int(11) NOT NULL, + `sid` int(11) primary key AUTO_INCREMENT, `name` text COLLATE utf8mb4_unicode_ci NOT NULL, `ip` text COLLATE utf8mb4_unicode_ci NOT NULL, - `port` int(11) NOT NULL, + `port` int(11) NOT NULL DEFAULT 5029, `version` text COLLATE utf8mb4_unicode_ci NOT NULL, - `timestamp` int(11) NOT NULL, - `room` int(11) NOT NULL, + `timestamp` int(11) NOT NULL DEFAULT 0, + `room` int(11) NOT NULL DEFAULT 0, `key` text COLLATE utf8mb4_unicode_ci NOT NULL, - `room_override` int(11) NOT NULL, - `upnow` tinyint(1) NOT NULL, - `permanent` tinyint(1) NOT NULL, - `delisted` tinyint(1) NOT NULL, - `sticky` int(11) NOT NULL + `room_override` int(11) NOT NULL DEFAULT 0, + `upnow` tinyint(1) NOT NULL DEFAULT 1, + `permanent` tinyint(1) NOT NULL DEFAULT 0, + `delisted` tinyint(1) NOT NULL DEFAULT 0, + `sticky` int(11) NOT NULL DEFAULT 0 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- -------------------------------------------------------- @@ -85,16 +85,20 @@ CREATE TABLE `ms_servers` ( -- CREATE TABLE `ms_versions` ( - `mod_id` int(11) NOT NULL, - `mod_version` int(11) NOT NULL + `mod_id` int(10) unsigned primary key AUTO_INCREMENT, + `mod_version` int(10) unsigned NOT NULL DEFAULT 1, + `mod_vstring` varchar(45) NOT NULL DEFAULT 'v1.0', + `mod_codebase` int(10) unsigned NOT NULL DEFAULT 205, + `mod_name` varchar(255) NOT NULL DEFAULT 'Default MOD Name', + `mod_url` text NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; -- -- Dumping data for table `ms_versions` -- -INSERT INTO `ms_versions` (`mod_id`, `mod_version`) VALUES -(12, 25); +INSERT INTO `ms_versions` (`mod_id`, `mod_version`, `mod_vstring`, `mod_codebase`, `mod_name`, `mod_url`) VALUES +(18, 42, 'v2.2.2', 205, 'SRB2 2.2', 'SRB2.org'); -- -------------------------------------------------------- @@ -114,4 +118,4 @@ COMMIT; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; \ No newline at end of file diff --git a/tools/musicdef-2.2.1/Makefile b/tools/musicdef-2.2.1/Makefile new file mode 100644 index 000000000..403d27b04 --- /dev/null +++ b/tools/musicdef-2.2.1/Makefile @@ -0,0 +1 @@ +musicdef-2.2.1: diff --git a/tools/musicdef-2.2.1/musicdef-2.2.1.c b/tools/musicdef-2.2.1/musicdef-2.2.1.c new file mode 100644 index 000000000..92a999da8 --- /dev/null +++ b/tools/musicdef-2.2.1/musicdef-2.2.1.c @@ -0,0 +1,76 @@ +/* +Copyright 2020 James R. +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 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 OWNER 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. +*/ + +#include +#include + +#ifdef _WIN32 +#define strcasecmp _stricmp +#else +#include +#endif + +int +main (int ac, char **av) +{ + char line[256]; + char buf[256]; + char *var; + char *val; + char *p; + int n; + (void)ac; + (void)av; + fputs( + "Copyright 2020 James R.\n" + "All rights reserved.\n" + "\n" + "Usage: musicdef-2.2.1 < old-MUSICDEF > new-MUSICDEF\n" + "\n" + ,stderr); + while (fgets(line, sizeof line, stdin)) + { + memcpy(buf, line, sizeof buf); + if (( var = strtok(buf, " =") )) + { + if (!( + strcasecmp(var, "USAGE") && + strcasecmp(var, "SOURCE") + )){ + if (( val = strtok(0, "") )) + { + for (p = val; ( p = strchr(p, '_') ); ) + { + n = strspn(p, "_"); + memset(p, ' ', n); + p += n; + } + printf("%s %s", var, val); + continue; + } + } + } + fputs(line, stdout); + } + return 0; +} diff --git a/windows-installer/staging/! SRB2KART INSTALL INSTRUCTIONS !.txt b/windows-installer/staging/! SRB2KART INSTALL INSTRUCTIONS !.txt deleted file mode 100644 index 91d055be6..000000000 --- a/windows-installer/staging/! SRB2KART INSTALL INSTRUCTIONS !.txt +++ /dev/null @@ -1,11 +0,0 @@ -SRB2Kart Install Instructions - -1. Move every file from the "new-install" folder to this main install folder. - -2. DELETE "staging.bat" and "staging.txt"! These can mess up your installation if run by accident! - -3. Optionally, create a folder in your user profile named "SRB2Kart". This is where your game data and addons may live. For example, - - C:\Users\[User]\SRB2Kart - -4. Run the game! Double-click srb2kart.exe -- or see if you have Start Menu icons under "SRB2Kart". \ No newline at end of file